Commit Graph

20019 Commits

Author SHA1 Message Date
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
ghost43 35b44a1e64 Merge pull request #10552 from spesmilo/authorized_decorator
plugins: use decorator to early return if plugin not authorized
2026-03-26 18:13:43 +00:00
ThomasV 032dfcf107 plugins: use decorator to early return if plugin not authorized 2026-03-26 17:40:25 +01:00
f321x a4af5cf48a qt: ReceiveTab: fix flickering zeroconf message
The ReceiveTab gets updated regularly (e.g. when syncing headers).
Every time it updates we would first show the invoice and then the
zeroconf confirmation overlay. This caused the overly to appear
flickering when there are updates in higher frequency.

Also we need to keep state if the user has already confirmed the
zeroconf message for this request, otherwise the question
will re-appear each time the user clicked "Accept" and the
ReceiveTab updates again.
2026-03-26 17:39:06 +01:00
f321x a06c8bacc3 lnpeer: don't signal OPTION_ZEROCONF_OPT to untrusted peer
Only signal `OPTION_ZEROCONF_OPT` to peers if we either:
1. Have no trusted peer configured (assuming that we are LSP)
2. Have a trusted peer configured, and the peer we are connecting
   to is this trusted peer.

Otherwise peers that are LSPs but are not the clients trusted LSP
might try to open a channel to the client but it would get rejected.
2026-03-26 17:39:05 +01:00
f321x 85356e5544 lnwallet: make jit fees configurable, add mining fees
Make the just in time channel fees and channel size
configvars, as in practice not every provider would
use the same hardcoded fees or channel sizes.
Add the mining fees required for the funding transaction on top of the
opening fees to prevent opening channels at a loss in a higher
fee environment.
2026-03-26 17:39:03 +01:00
f321x a3f12506ce tests: add unittests for LNWallet just in time opening
Adds unittests for `LNWallet.open_channel_just_in_time()`,
`LNWallet._cleanup_failed_jit_channel()`,
`LNWallet.can_get_zeroconf_channel()` and
`LNWallet.receive_requires_jit_channel()`.
2026-03-26 17:39:01 +01:00
f321x 2eac67b4b8 open_channel_just_in_time: add cleanup and broadcast retry
Adds cleanup logic to `LNWallet.open_channel_just_in_time` so
that the channel provider removes unfunded channels again, e.g. if
the client didn't release the preimage or the provider failed
to broadcast the funding transaction.

Also adds more robust transaction broadcast logic so we retry to
broadcast if it failed and check against adb to see if any previous
broadcast was successful.
2026-03-26 17:38:59 +01:00
f321x f56e1cafac lnworker: stop setting static jit alias for jit channel
...so we can have multiple just in time channels with the same lsp.
We already save a remote scid alias in `on_channel_ready` which we
already have received after the new zeroconf channel is in open state.
So setting the alias to the static node id hash is counterproductive
because it doesn't allow to differentiate between channels.

Also extends the regtest (`just_in_time`) to do a second channel
opening, to cover this scenario. This doesn't add much runtime to
the test, so the cost seems reasonable.
2026-03-26 17:38:58 +01:00
f321x 2da9fbbf15 lnworker/config: check if zeroconf is enabled when forwarding
On LSP side we were only checking if ACCEPT_ZEROCONF_CHANNELS
is enabled while forwarding a non-trampoline htlc.
During trampoline forwarding the config was ignored.

The ACCEPT_* prefix implied this was only for accepting inbound
zeroconf channels, but it also controls whether we open them when
forwarding HTLCs.

Renames the config var to OPEN_ZEROCONF_CHANNELS
to clarify it enables zeroconf channel opens in both directions,
and add the missing check when forwarding trampoline HTLCs.
2026-03-26 17:38:56 +01:00
f321x 1f17574dfa lnchannel: fix update_unfunded_state, add unittest
Fixes AbstractChannel.update_unfunded_state to stop calling a
non-existent method (unwatch_channel).
Adds unittest to execute the zeroconf path of update_unfunded_state.
2026-03-26 17:38:54 +01:00
f321x 297aed99f0 lnpeer: check just-in-time channel opening fee
Check the just-in-time channel opening fee when receiving an incoming
channel opening.
2026-03-26 17:38:49 +01:00
ThomasV 9d50d78e39 Merge pull request #10541 from f321x/trampoline_feature_invoice
lnwallet: also signal trampoline support in invoice features if trampoline is disabled
2026-03-26 12:20:00 +01:00
f321x ac87eea02f test_lnwallet: unittest trampoline invoice_feature and r_tag
Add unittest that verifies we only include r_tags for trampoline nodes
if we signal trampoline support in the invoice_features and only signal
trampoline support if we use trampoline or have only open trampoline
channels.
2026-03-26 12:10:24 +01:00
f321x 609a274661 LNWallet: set trampoline invoice feature independently
Make the trampoline signaling in bolt11 invoices dependent upon all
unfrozen channels being with trampoline peers instead of the trampoline
config.
Stops automatically freezing non-trampoline channels for receiving if
trampoline is enabled.

One effect of this change is that now we don't signal trampoline support
anymore in the invoice even if trampoline is enabled, if one of the
channels is with a non trampoline peer.
2026-03-26 12:10:22 +01:00
f321x 0265c70766 LNWallet: only include tramp r_tags if tramp feature
Only include r_tags for trampoline nodes in a bolt11 invoice
if its invoice_features signal trampoline support.
2026-03-26 12:10:19 +01:00
SomberNight 726d3995f4 qt gui: more defensive 'gui' RPC (i.e. URI) handling 2026-03-25 18:54:13 +00:00
SomberNight d951a3d2f4 in GUI mode, only start a limited minimal RPC server
To limit attack surface.

Context:
- both in daemon mode and in GUI mode, we start an RPC server
- the RPC server uses HTTP basic auth, with a random password that is saved in the config file
- read access to the config file implies access to the RPC server
- the traffic is unencrypted
- by default the server listens
  - on Windows, on localhost TCP
  - all other platform, via unix domain sockets
- if an attacker can listen to localhost TCP traffic, and there was traffic
  - they could see the plaintext RPC password and issue their own commands
  - e.g. if wireshark was already installed on the system, this might not require root access
- the "ping" and "gui" commands are used by everyday operations that affect most users:
  - "ping" is used when trying to launch a second instance of electrum, to contact the first instance and enforce "singleton" behaviour
  - "gui" is used for URI handling (`$ xdg-open bitcoin:asdasd`)
- many other sensitive commands, that operate on wallets, require *also* the wallet password
  - but note that wallet.unlock can be used by the user to bypass this and store the wallet password in memory (exposed in GUI)

I propose locking down the RPC server when running in GUI mode:
- we still start it, as it is used for "ping" and "gui" RPCs, however we disable all other RPCs
- we could opt-in enable it, using a config var, except that ofc would not help against an attacker that has filesystem write access to the config file
- so I think it's even safer to just "hardcode" disable it: however the functionality is useful for development
  - I propose we branch based on `constants.net.TESTNET`
  - an alternative we could branch on that is hard to fake is `is_git_clone` in run_electrum
2026-03-25 18:44:56 +00:00
ghost43 bd4439945a Merge pull request #10545 from SomberNight/202603_commands_getsockname
daemon: (trivial) CommandsServer.run: move tcp-specific line
2026-03-25 16:43:11 +00:00
SomberNight e08390a01d daemon: (trivial) CommandsServer.run: move tcp-specific line
this line would raise if site was a web.NamedPipeSite
2026-03-25 16:19:14 +00:00
ThomasV a76603ceef Merge pull request #10073 from f321x/fix_issue_10065
fix: remove negative fee assert from get_tx_fee_warning
2026-03-25 12:01:14 +01:00
f321x 06490657bc fix: remove negative fee assert from get_tx_fee_warning
rm the `assert fee >= 0, f"{fee=!r} must be non-negative satoshis"`
from `Abstract_Wallet.get_tx_fee_warning()` to prevent an exception when
users load a psbt with negative tx fee.
2026-03-25 11:55:03 +01:00
ThomasV 3012c367ad Qt: move LN fee slider to payment dialog. fixes #10516 2026-03-25 10:53:38 +01:00
ThomasV efb3e344d0 Merge pull request #10543 from f321x/qml_trustedcoin
qml: make 2fa secret copyable, open 2fa app for user
2026-03-25 08:36:32 +01:00
ThomasV 06e9f2b5e3 Merge pull request #10534 from SomberNight/202603_rpc_password_not_empty
daemon: forbid "setconfig" command to change rpcserver settings in-flight
2026-03-25 08:35:52 +01:00
SomberNight 0dcef9780b daemon: forbid "setconfig" command to change rpcserver settings in-flight
It is much easier to reason about the rpcserver if we don't allow changing its basic settings while it is already running. What does it mean to change the TCP port it is listening on ("rpcport") if it's already running? It is even problematic to change the rpcpassword: care needs to be taken to already update it for the current server.
(ref https://github.com/spesmilo/electrum/issues/6762)

This commit disallows changing all of the "rpc*" config variables if the daemon is already running.

---

Simultaneously, it also ensures rpc_password is always set and auth cannot be disabled.

Previously if there was a daemon running, and the user ran
`$ electrum setconfig rpcpassword ""` that would leave the RPC unauthenticated
for the current session. However next time the daemon restarted, get_rpc_credentials would see
the unset password and generate one.

I think this was the worst of both worlds:
- we did not really allow removing the rpc password, except for the current session, and
- perhaps unexpectedly, we would generate a new password on daemon restart

Instead now we explicitly make sure the RPC server can never get into a state where it does not have a password set.

Based on a report by `Zuzana Kotásková <36777@mail.vsfs.cz>`
2026-03-24 17:07:26 +00:00
f321x cb023e22e4 qml: 2fa: make 2fa setup qr code clickable
This will make the 2fa app open when the user clicks on the qr code,
much more convenient than manually copy pasting the secret.
2026-03-24 14:50:45 +01:00
f321x 37159e47a2 qml: 2fa: make it possible to copy 2fa secret
The 2fa secret is not selectable or copyable, this is very inconveniant
when setting up a new 2fa wallet as the user has to somehow manually
write the secret e.g. on a paper to then enter it again in their 2fa
app. This makes the secret string copyable by clicking on it.
2026-03-24 14:50:42 +01:00
ThomasV 3cf2c325d5 Merge pull request #10506 from accumulator/spend_from_coin_selection_refactor
qt: perform 'fully spend' action with coin selection, keep separate from coin control when doing action
2026-03-24 12:46:02 +01:00