Commit Graph

19938 Commits

Author SHA1 Message Date
f321x 36e9f185d2 regtest: make fw_fail_htlc less flaky
On master fw_fail_htlc is, especially on the CI, flaky.
We mine 100 blocks, then wait fixed 5 seconds, then check if bob has
failed back the htlcs to alice.
However if the test runs slowly (CI) 5 seconds can be too short
for bob to catch up to the new 100 mined blocks.
Instead we should just use the wait_until_htlcs_settled helper function
which polls Alice local_unsettled_sent with 30 sec timeout, allowing bob
to take a bit longer (or be faster) than 5 s.

```
.***** test_fw_fail_htlc ******
initializing alice
funding alice
a101c8c4c22043ff42029bcab2f0bf6ce5482a60d656294cbec3a4df557e2687
initializing bob
funding bob
d323d572c54817116d185c91f15e449550c651eb4ed76891d3011e0a8eb4ef9a
initializing carol
funding carol
bbf3503663876a4ae00f70c7e58ad49318e83d5cf99d6effe692e113d10910c2
mining 1 blocks
starting daemon (PID 5559)
/tmp/alice/regtest/wallets/default_wallet
true
starting daemon (PID 5577)
/tmp/bob/regtest/wallets/default_wallet
true
starting daemon (PID 5595)
/tmp/carol/regtest/wallets/default_wallet
true
alice and carol open channels with bob
mining 3 blocks
wait until alice sees channel open.
wait until alice sees channel open..
wait until alice sees channel open...
alice pays carol
Daemon stopped
mining 1 blocks
mining 150 blocks
wait until 99ad1d44b9054f5a85c2fb45e9a9b93eb13c785104ed0664be5cf866d79d38fc:2 is spent.
...
wait until 99ad1d44b9054f5a85c2fb45e9a9b93eb13c785104ed0664be5cf866d79d38fc:2 is spent............................
mining 1 blocks
mining 100 blocks
alice htlc was not failed
FDaemon stopped
```
2026-04-22 17:12:30 +02:00
ThomasV bca41d941d Merge pull request #10573 from f321x/qml_wallet_rename
qml: allow renaming wallets
2026-04-22 10:03:14 +02:00
ThomasV 294d21407a Merge pull request #10568 from SomberNight/202604_verifier_left_sibling_duplicates
verifier.py: fix CVE-2012-2459: reject left-sibling duplicates
2026-04-21 16:22:07 +02:00
ThomasV c189360120 Merge pull request #10590 from SomberNight/202604_test_lnpeer_flaky_hold_invoice_set
tests: lnpeer: fix flaky test "hold_invoice_set_doesnt_get_expired"
2026-04-21 13:30:21 +02:00
Felix 1bea23926f Merge pull request #10595 from f321x/update_ci_review_model
ci: bump code review ci claude version 4.6 -> 4.7
2026-04-21 13:27:30 +02:00
f321x 1ba31448a3 ci: bump code review ci claude version 4.6 -> 4.7
An improved Claude Opus version got released, this bumps the code review
CI to use it.
2026-04-21 13:24:02 +02:00
ghost43 b45d89e120 Merge pull request #10546 from f321x/bolt12_preparation_1
bolt12: preparation 1
2026-04-20 15:09:41 +00:00
SomberNight ca8bdba0c5 tests: lnpeer: fix flaky test "hold_invoice_set_doesnt_get_expired"
This test was flaky: the mpp_set resolution gets set to SETTLING several asyncio event loop iterations before the hold invoice callback "cb" gets called.
If the 0.1 sec polling triggers just in the middle of that interval, `assert cb_got_called` fails.

```
    async def check_mpp_state():
        async def wait_for_resolution():
            while True:
                await asyncio.sleep(0.1)
                if payment_key not in bob_w.received_mpp_htlcs:
                    continue
                if not bob_w.received_mpp_htlcs[payment_key].resolution == RecvMPPResolution.SETTLING:
                    continue
                return
        await util.wait_for2(wait_for_resolution(), timeout=2)
>       assert cb_got_called
E       assert False

tests/test_lnpeer.py:1898: AssertionError
```

see https://github.com/spesmilo/electrum/blob/16c8cb50e38c274cce8f9f66f28d8dd453f9f074/electrum/lnpeer.py#L3136-L3137

fixes https://github.com/spesmilo/electrum/issues/10589

-----

diff to reproduce the failure without present patch:
```
diff --git a/tests/test_lnpeer.py b/tests/test_lnpeer.py
index 8669931c24..e15973d68f 100644
--- a/tests/test_lnpeer.py
+++ b/tests/test_lnpeer.py
@@ -1885,6 +1885,7 @@ class TestPeerDirect(TestPeer):
             cb_got_called = False
             async def cb(_payment_hash):
                 self.logger.debug(f"hold invoice callback called. {bob_w.network.get_local_height()=}")
+                await asyncio.sleep(1)
                 nonlocal cb_got_called
                 cb_got_called = True
```
2026-04-19 15:23:33 +00:00
SomberNight 16c8cb50e3 lnchannel: (trivial) fix type hint of receive_fail_reasons 2026-04-18 17:16:57 +00:00
accumulator 3fbf597485 Merge pull request #10579 from f321x/qml_relay_list_padding
qml: add top padding to nostr relay url list
2026-04-14 18:18:05 +02:00
SomberNight 4a14feffd4 lnpeer: chan_reest: clarify my_current_per_commitment_point is ignored
`my_current_per_commitment_point` was only used prior to option_static_remotekey
2026-04-14 14:18:14 +00:00
f321x 24d93420fb qml: add top padding to nostr relay url list
The first relay url was close to the top of the ElTextArea and looked a
bit sliced. Adding some padding makes it look better.
2026-04-14 08:34:18 +02:00
SomberNight 016c8b5f4c bip21: add comment listing URI scheme handler registrations
It is sufficiently rare that we have to touch this stuff that I always have to re-discover where/how it is done. And it is impractical to grep for "bitcoin:" or "lightning:".

Putting this "master list" comment very close to the BITCOIN_BIP21_URI_SCHEME variable seems like a good spot - at least this is where I would look for it first.
2026-04-11 02:55:54 +00:00
ghost43 1235b4a6b9 Merge pull request #10572 from f321x/fix_coingecko
exchange rate: fix coingecko api
2026-04-08 09:46:42 +00:00
f321x 8a12874c8e qml: allow renaming wallets
Allows to rename a wallet file from the QML Wallet Details view.
This seems like a feature we should support as the use-case of a wallet can
change or maybe the user didn't think about a proper name when setting
up the wallet. Especially with lightning channels it is not possible to
restore from seed to change the name.

Fixes #4377
2026-04-08 10:45:59 +02:00
f321x 9827734ab6 exchange rate: fix coingecko api
The CoinGecko API failed as the Honduran Lempira currency returned
null as value, rendering the API unusable:
```
11.19 | I | exchange_rate.CoinGecko | getting fx quotes for EUR
11.41 | E | exchange_rate.CoinGecko | failed fx quotes: InvalidOperation([<class 'decimal.ConversionSyntax'>])
Traceback (most recent call last):
  File "/var/home/user/code/vibecoding_vm/electrum/electrum/exchange_rate.py", line 87, in update_safe
    self._quotes = await self.get_rates(ccy)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/home/user/code/vibecoding_vm/electrum/electrum/exchange_rate.py", line 449, in get_rates
    return dict([(ccy.upper(), to_decimal(d['value']))
                               ~~~~~~~~~~^^^^^^^^^^^^
  File "/var/home/user/code/vibecoding_vm/electrum/electrum/util.py", line 243, in to_decimal
    return Decimal(str(x))
decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
```

```
"hnl":{"name":"Honduran Lempira","unit":"L","value":null,"type":"fiat"}
```
2026-04-08 10:20:01 +02:00
ThomasV 3304d76920 Merge pull request #10571 from f321x/nwc_handle_null_params
plugin: nwc: handle 'params: null' in request
2026-04-07 13:37:53 +02:00
f321x fd230cf9d1 plugin: nwc: handle 'null' params in request
Some clients send 'params: null' instead of 'params: {}' or no
params key at all.
2026-04-07 09:52:13 +02:00
SomberNight 3d39074294 verifier.py: fix CVE-2012-2459: reject left-sibling duplicates
Due to how the txid-commitment merkle tree used in the block headers is constructed, we need an extra check to be able to validate the *position* of a txid in a block.

I think this is low severity for us.

See https://bitcointalk.org/?topic=102395 :

> The Merkle hash implementation that Bitcoin uses to calculate the Merkle
> root in a block header is flawed in that one can easily construct multiple
> lists of hashes that map to the same Merkle root.
> For example, merkle_hash([a, b, c]) and merkle_hash([a, b, c, c]) yield
> the same result. This is because, at every iteration, the Merkle hash
> function pads its intermediate list of hashes with the last hash if the
> list is of odd length, in order to make it of even length.
>
> And so, the Merkle root function can be effectively preimaged by
> changing the input so that one of the intermediate lists is of even
> length with the last two elements equal (where originally it was
> of odd length with a last element equal to the earlier mentioned two).
> As was later noted, this extends to any input length that is
> not a power of two:
> merkle_hash([a, b, c, d, e, f]) == merkle_hash([a, b, c, d, e, f, e, f]).
> Note that to maintain the same root hash, the only flexibility that
> exists is duplication of elements.

Ported from https://github.com/Electron-Cash/Electron-Cash/commit/165146362b4cb0ad74770b36aca1f9acb2800195

Co-authored-by: bitcoincashautist <80100588+A60AB5450353F40E@users.noreply.github.com>
2026-04-03 02:22:01 +00:00
ThomasV 7a6a39d1aa add comments about xpub encryption 2026-04-02 14:46:50 +02:00
ghost43 2ea4874600 Merge pull request #10566 from f321x/release_script_apk
contrib: check for unsigned apk in release.sh
2026-04-02 12:44:31 +00:00
f321x 7adc833f21 contrib: check for unsigned apk in release.sh
release.sh expects signed apks. if a non-releasemanager uses
release.sh to build it will build the apks unsigned and then
rename them to the same name as the signed apks. However
if the apks have already been built separately and are still named
*-unsigned.apk it will not detect them and instead try to build them
again. Instead it should just rename them to *-release.apk as if built
directly through release.sh.
2026-04-02 13:49:32 +02:00
SomberNight e71616e673 update release notes for version 4.7.2 2026-04-01 15:50:28 +00:00
f321x 4254c9a051 onion_message: fix route construction to ip
Don't include first hop of the path,
this is the hop from us to the first node and we don't
need a payload for ourselves.

Also adds unittest checking this.
2026-04-01 09:07:36 +02:00
f321x 4134dc7b25 onion_message: split send_onion_message_to
Factor out code from `send_onion_message_to` into a separate
function `_create_route_to_introduction_point` to make it
easier to reason about it and more testable.
2026-04-01 09:07:36 +02:00
Sander van Grieken 2e0f263269 onion_message: iterate blinded paths for onion message requests 2026-04-01 09:07:36 +02:00
Sander van Grieken 9bcbbdd3eb move blinding_privkey from onion_message to lnonion 2026-04-01 09:07:36 +02:00
Sander van Grieken 3e3bffa4a2 onion_message: let caller specify considered channels for blinded paths.
This allows restricting blinded paths to channels that have sufficient receive
capacity for payment.

NOTE: this might have privacy issues, as this can be used to probe channel capacity.
Maybe randomize leeway?

@f321x: changed to use scid alias in create_blinded_path
2026-04-01 09:07:36 +02:00
f321x 2b6ad68145 tests: test_onion_message: mock LNWallet._add_peer
Mock LNWallet._add_peer so direct connection fallbacks don't
cause an exception.
2026-04-01 09:07:36 +02:00
Sander van Grieken 5c4fc2d713 onion_message: verify LNPeerAddr returned as hint in NoRouteFound 2026-04-01 09:07:36 +02:00
f321x 8d4affa293 test_onion_message: test get_blinded_paths_to_me
Add unittest to test the payment path of get_blinded_paths_to_me
2026-04-01 09:07:36 +02:00
Sander van Grieken b7a512845f onion_message: factor out get_blinded_paths_to_me from get_blinded_reply_paths.
the former also calculates payinfo information for payment scenarios.
include payment_relay struct for payment blinded_paths.
2026-04-01 09:07:36 +02:00
Sander van Grieken 65fb739584 segwit_addr: bech32 decode without checksum option 2026-04-01 09:07:36 +02:00
ghost43 09a09057f6 Merge pull request #10548 from SomberNight/202603_lockdown_rpcserver
in GUI mode, only start a limited minimal RPC server
2026-03-31 15:25:52 +00:00
ghost43 8942ceace8 Merge pull request #10558 from f321x/followup_10541
trampoline: prevent adding ourself on the route, fixes CI
2026-03-30 14:33:00 +00:00
ghost43 efcf1f056f Merge pull request #10547 from SomberNight/202603_umask
set restrictive unix umask application-wide by default
2026-03-27 18:27:51 +00:00
SomberNight 7755d97a76 set restrictive unix umask application-wide by default
- I noticed we were creating the RPC server unix domain socket with 0o775.
  Instead of hunting down each individual line we create files/dirs, we should
  just set a restrictive umask by default. We can still use chmod to relax this
  for individual files. -- but we should try to be secure by default
- note: bitcoin core does the same
    https://github.com/bitcoin/bitcoin/blame/2fe76ed8324af44c985b96455a05c3e8bec0a03e/src/common/system.cpp#L92
- the umask is set in run_electrum as opposed to __init__.py so that we don't side-effect use-cases where electrum is imported as a library
2026-03-27 18:20:55 +00:00
SomberNight 9d204abfae daemon: set restrictive permission on RPC-server unix domain socket
0600 instead of 0775.
2026-03-27 18:20:52 +00:00
SomberNight 85ea6af5b1 ci: llm sec review: tweak trigger types
looks like if there is an overlap between automatic and manual, manual wins
2026-03-27 18:17:49 +00:00
ghost43 a8cd2715c8 Merge pull request #10553 from f321x/code_review
ci: add claude code pr security review
2026-03-27 17:58:11 +00:00
f321x 88f9c49a60 ci: add claude code code review
Adds a CI step to the Cirrus CI which will run claude code on the diff
of a Pull Request and fail if it finds critical security vulnerabilities
or serious code issues. Optinally it can be given a GitHub api key to
create a comment in the pull request.
2026-03-27 18:29:07 +01:00
f321x 11f0a68c96 trampoline: prevent adding ourself on the route
Followup #10541.
Fixes tests.regtest.TestLightningSwapserver.test_swapserver_forceclose.

In the regtest bob would now signal trampoline support due to #10541 and
include Alice into the invoice trampoline as he is connected to Alice.
Alice would then try to add herself onto the trampoline route, causing
the payment to fail.
2026-03-27 18:05:00 +01:00
SomberNight d33212656f crypto.py: replace sys.exit with ImportError
not nice to call sys.exit from inside the library
(run_electrum can do it, but the library probably should not)
2026-03-27 15:30:34 +00:00
ThomasV eb6a796de0 Merge pull request #10555 from f321x/nwc_handle_missing_params
plugin: nwc: handle missing params dict in request
2026-03-27 15:58:36 +01:00
ThomasV efbe1907d7 Merge pull request #10556 from f321x/settings_dialog_guard_network
qt: SettingsDialog: guard self.network access
2026-03-27 15:54:36 +01:00
f321x 1aad09a61d qt: SettingsDialog: guard self.network access
Check if self.network before trying to access it. This would trigger an
exception when toggling the trampoline checkbox in offline mode:
```
 29.13 | E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "/home/user/Documents/electrum/electrum/gui/qt/settings_dialog.py", line 133, in on_trampoline_checked
    self.network.run_from_another_thread(
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'run_from_another_thread'
 31.00 | E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "/home/user/Documents/electrum/electrum/gui/qt/settings_dialog.py", line 131, in on_trampoline_checked
    self.network.start_gossip()
    ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'start_gossip'
```
2026-03-27 15:40:22 +01:00
f321x b9a24ae1cf plugin: nwc: handle missing params dict in request
Even though the NIP-47 specification kind of defines that requests should
always pass a params dict in their request i witnessed way too often
that clients don't include it in some requests where it is technically
not neccessary and we fail on it.
Handling this gracefully improves compatibility without obvious
downsides.
2026-03-27 15:05:15 +01:00
SomberNight 7afec53828 follow-up prev 2026-03-27 13:15:07 +00:00
ThomasV 316e2b8c76 Merge pull request #10554 from SomberNight/202603_plugin_fix_type_hints
plugin.py: fix some type hints
2026-03-27 08:41:06 +01:00
SomberNight a508519017 plugin.py: fix some type hints 2026-03-26 18:56:02 +00:00