lnworker/config: check if zeroconf is enabled when forwarding
What changed, and why it matters
This commit fixes a configuration check in Electrum's Lightning Network code. Previously, when forwarding payments through a trampoline node, the software ignored a setting meant to control whether it opens special 'zeroconf' channels. The patch makes the code check that setting consistently and renames it from 'accept' to 'open' to better reflect that it controls opening channels in both directions. This is a defensive fix to prevent unintended channel opens.
Review whether the assertion is the appropriate control mechanism or whether a graceful failure path is preferable. Verify that the renamed config variable is migrated or documented for users/operators who previously set `accept_zeroconf_channels`. Consider whether the missing check could have led to unintended zeroconf channel opens in deployed LSP nodes and assess operational impact.
Security signals we found
Missing authorization/access-control check added (config gating)
Renames misleading config variable to clarify dual-direction behavior
Adds assertion enforcing config check in previously unchecked code path
Lightning Network / payment forwarding code affected
Evidence from the diff
The patch renames the config variable ACCEPT_ZEROCONF_CHANNELS to OPEN_ZEROCONF_CHANNELS and adds an assertion assert self.config.OPEN_ZEROCONF_CHANNELS in the trampoline forwarding path (maybe_open_jit_channel or similar). It also updates can_get_zeroconf_channel() and JIT channel selection logic to use the renamed config and feature bits consistently. The change ensures zeroconf channel opens during trampoline HTLC forwarding respect the same configuration as non-trampoline forwarding.
Changed components
electrum/lnworker.pyelectrum/simple_config.pyelectrum/wallet.pytests/regtest.pyInspect captured patch +10 / −9
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
index b532e5a..8e39e78 100644
--- a/electrum/lnworker.py
+++ b/electrum/lnworker.py
@@ -1010,7 +1010,7 @@ class LNWallet(Logger):
features = LNWALLET_FEATURES
if self.config.ENABLE_ANCHOR_CHANNELS:
features |= LnFeatures.OPTION_ANCHORS_ZERO_FEE_HTLC_OPT
- if self.config.ACCEPT_ZEROCONF_CHANNELS:
+ if self.config.OPEN_ZEROCONF_CHANNELS:
features |= LnFeatures.OPTION_ZEROCONF_OPT
if self.config.EXPERIMENTAL_LN_FORWARD_PAYMENTS or self.config.EXPERIMENTAL_LN_FORWARD_TRAMPOLINE_PAYMENTS:
features |= LnFeatures.OPTION_ONION_MESSAGE_OPT
@@ -1485,6 +1485,7 @@ class LNWallet(Logger):
payment_hash: bytes,
next_onion: OnionPacket,
) -> str:
+ assert self.config.OPEN_ZEROCONF_CHANNELS
# if an exception is raised during negotiation, we raise an OnionRoutingFailure.
# this will cancel the incoming HTLC
@@ -3351,7 +3352,7 @@ class LNWallet(Logger):
return False
def can_get_zeroconf_channel(self) -> bool:
- if not self.config.ACCEPT_ZEROCONF_CHANNELS and self.config.ZEROCONF_TRUSTED_NODE:
+ if not self.config.OPEN_ZEROCONF_CHANNELS and self.config.ZEROCONF_TRUSTED_NODE:
# check if zeroconf is accepted and client has trusted zeroconf node configured
return False
try:
@@ -3998,7 +3999,7 @@ class LNWallet(Logger):
# do we have a connection to the node?
next_peer = self.lnpeermgr.get_peer_by_pubkey(outgoing_node_id)
- if next_peer and next_peer.accepts_zeroconf():
+ if next_peer and next_peer.accepts_zeroconf() and self.features.supports(LnFeatures.OPTION_ZEROCONF_OPT):
self.logger.info(f'JIT: found next_peer')
for next_chan in next_peer.channels.values():
if next_chan.can_pay(amt_to_forward):
diff --git a/electrum/simple_config.py b/electrum/simple_config.py
index f1bdf24..4918eb2 100644
--- a/electrum/simple_config.py
+++ b/electrum/simple_config.py
@@ -954,7 +954,7 @@ Warning: setting this to too low will result in lots of payment failures."""),
# anchor outputs channels
ENABLE_ANCHOR_CHANNELS = ConfigVar('enable_anchor_channels', default=True, type_=bool)
# zeroconf channels
- ACCEPT_ZEROCONF_CHANNELS = ConfigVar('accept_zeroconf_channels', default=False, type_=bool)
+ OPEN_ZEROCONF_CHANNELS = ConfigVar('open_zeroconf_channels', default=False, type_=bool)
ZEROCONF_TRUSTED_NODE = ConfigVar('zeroconf_trusted_node', default='', type_=str)
ZEROCONF_MIN_OPENING_FEE = ConfigVar('zeroconf_min_opening_fee', default=5000, type_=int)
LN_UTXO_RESERVE = ConfigVar(
diff --git a/electrum/wallet.py b/electrum/wallet.py
index 00f5c93..e0c1292 100644
--- a/electrum/wallet.py
+++ b/electrum/wallet.py
@@ -3458,7 +3458,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
zeroconf_nodeid = extract_nodeid(self.config.ZEROCONF_TRUSTED_NODE)[0]
except Exception:
zeroconf_nodeid = None
- can_get_zeroconf_channel = (self.lnworker and self.config.ACCEPT_ZEROCONF_CHANNELS
+ can_get_zeroconf_channel = (self.lnworker and self.config.OPEN_ZEROCONF_CHANNELS
and self.lnworker.lnpeermgr.get_peer_by_pubkey(zeroconf_nodeid) is not None)
status = self.get_invoice_status(req)
diff --git a/tests/regtest.py b/tests/regtest.py
index 6c0953e..ae18044 100644
--- a/tests/regtest.py
+++ b/tests/regtest.py
@@ -151,12 +151,12 @@ class TestLightningABC(TestLightning):
class TestLightningJIT(TestLightning):
agents = {
'alice': {
- 'accept_zeroconf_channels': 'true',
+ 'open_zeroconf_channels': 'true',
},
'bob': {
'lightning_listen': 'localhost:9735',
'lightning_forward_payments': 'true',
- 'accept_zeroconf_channels': 'true',
+ 'open_zeroconf_channels': 'true',
},
'carol': {
}
@@ -170,13 +170,13 @@ class TestLightningJITTrampoline(TestLightningJIT):
agents = {
'alice': {
'use_gossip': 'false',
- 'accept_zeroconf_channels': 'true',
+ 'open_zeroconf_channels': 'true',
},
'bob': {
'lightning_listen': 'localhost:9735',
'lightning_forward_payments': 'true',
'lightning_forward_trampoline_payments': 'true',
- 'accept_zeroconf_channels': 'true',
+ 'open_zeroconf_channels': 'true',
},
'carol': {
'use_gossip': 'false',
Why this scored 43/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.