LnFeatures: rename OPTION_ANCHORS_ZERO_FEE_HTLC to OPTION_ANCHORS
What changed, and why it matters
This commit is a simple renaming of a Lightning Network feature flag to match a recent change in the official protocol specifications (BOLTS). It replaces the old name 'OPTION_ANCHORS_ZERO_FEE_HTLC' with the shorter name 'OPTION_ANCHORS' everywhere it appears. The numeric bit positions and behavior are unchanged, so this is a non-functional code cleanup with no security relevance.
No security action needed. Treat as a routine protocol-spec alignment refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch renames LnFeatures.OPTION_ANCHORS_ZERO_FEE_HTLC_REQ/OPT to OPTION_ANCHORS_REQ/OPT and ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX to OPTION_ANCHORS. All references in lnchannel.py, lnpeer.py, lnutil.py, lnworker.py, and tests/test_lnchannel.py are updated. The bit values (1<<22 and 1<<23), feature contexts, direct dependencies, and LN_FEATURES_IMPLEMENTED mask remain identical. No logic changes.
Changed components
electrum/lnutil.pyelectrum/lnchannel.pyelectrum/lnpeer.pyelectrum/lnworker.pytests/test_lnchannel.pyInspect captured patch +17 / −17
diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
index b8df0b7..49878de 100644
--- a/electrum/lnchannel.py
+++ b/electrum/lnchannel.py
@@ -1029,7 +1029,7 @@ class Channel(AbstractChannel):
def has_anchors(self) -> bool:
channel_type = ChannelType(self.storage.get('channel_type'))
- return bool(channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX)
+ return bool(channel_type & ChannelType.OPTION_ANCHORS)
def get_wallet_addresses_channel_might_want_reserved(self) -> Sequence[str]:
assert self.is_static_remotekey_enabled()
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
index f0652c3..db79ed8 100644
--- a/electrum/lnpeer.py
+++ b/electrum/lnpeer.py
@@ -918,7 +918,7 @@ class Peer(Logger, EventListener):
return self.features.supports(LnFeatures.OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT)
def use_anchors(self) -> bool:
- return self.features.supports(LnFeatures.OPTION_ANCHORS_ZERO_FEE_HTLC_OPT)
+ return self.features.supports(LnFeatures.OPTION_ANCHORS_OPT)
def upfront_shutdown_script_from_payload(self, payload, msg_identifier: str) -> Optional[bytes]:
if msg_identifier not in ['accept', 'open']:
@@ -998,7 +998,7 @@ class Peer(Logger, EventListener):
assert self.their_features.supports(LnFeatures.OPTION_STATIC_REMOTEKEY_OPT)
our_channel_type = ChannelType(ChannelType.OPTION_STATIC_REMOTEKEY)
if self.use_anchors():
- our_channel_type |= ChannelType(ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX)
+ our_channel_type |= ChannelType(ChannelType.OPTION_ANCHORS)
if zeroconf:
our_channel_type |= ChannelType(ChannelType.OPTION_ZEROCONF)
# We do not set the option_scid_alias bit in channel_type because LND rejects it.
@@ -1010,7 +1010,7 @@ class Peer(Logger, EventListener):
'type': our_channel_type.to_bytes_minimal()
}
- if our_channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX:
+ if our_channel_type & ChannelType.OPTION_ANCHORS:
multisig_funding_keypair = lnutil.derive_multisig_funding_key_if_we_opened(
funding_root_secret=self.lnworker.funding_root_keypair.privkey,
remote_node_id_or_prefix=self.pubkey,
@@ -1275,7 +1275,7 @@ class Peer(Logger, EventListener):
raise Exception(f"{channel_opening_fee_sat=} exceeding fee limit, rejecting channel ({funding_sat=})")
self.logger.info(f"just-in-time channel: {channel_opening_fee_sat=}")
- if channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX:
+ if channel_type & ChannelType.OPTION_ANCHORS:
multisig_funding_keypair = lnutil.derive_multisig_funding_key_if_they_opened(
funding_root_secret=self.lnworker.funding_root_keypair.privkey,
remote_node_id_or_prefix=self.pubkey,
diff --git a/electrum/lnutil.py b/electrum/lnutil.py
index 9512721..b49e5bc 100644
--- a/electrum/lnutil.py
+++ b/electrum/lnutil.py
@@ -172,7 +172,7 @@ class ChannelConfig(StoredObject):
peer_features: 'LnFeatures',
channel_type: 'ChannelType',
) -> None:
- has_anchors = bool(channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX)
+ has_anchors = bool(channel_type & ChannelType.OPTION_ANCHORS)
# first we validate the configs separately
local_config.validate_params(funding_sat=funding_sat, config=config, peer_features=peer_features)
remote_config.validate_params(funding_sat=funding_sat, config=config, peer_features=peer_features)
@@ -1470,11 +1470,11 @@ class LnFeatures(IntFlag):
_ln_feature_contexts[OPTION_SUPPORT_LARGE_CHANNEL_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
_ln_feature_contexts[OPTION_SUPPORT_LARGE_CHANNEL_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
- OPTION_ANCHORS_ZERO_FEE_HTLC_REQ = 1 << 22
- OPTION_ANCHORS_ZERO_FEE_HTLC_OPT = 1 << 23
- _ln_feature_direct_dependencies[OPTION_ANCHORS_ZERO_FEE_HTLC_OPT] = {OPTION_STATIC_REMOTEKEY_OPT}
- _ln_feature_contexts[OPTION_ANCHORS_ZERO_FEE_HTLC_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
- _ln_feature_contexts[OPTION_ANCHORS_ZERO_FEE_HTLC_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
+ OPTION_ANCHORS_REQ = 1 << 22
+ OPTION_ANCHORS_OPT = 1 << 23
+ _ln_feature_direct_dependencies[OPTION_ANCHORS_OPT] = {OPTION_STATIC_REMOTEKEY_OPT}
+ _ln_feature_contexts[OPTION_ANCHORS_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
+ _ln_feature_contexts[OPTION_ANCHORS_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
# Temporary number.
OPTION_TRAMPOLINE_ROUTING_REQ_ECLAIR = 1 << 148
@@ -1618,7 +1618,7 @@ class LnFeatures(IntFlag):
class ChannelType(IntFlag):
OPTION_LEGACY_CHANNEL = 0
OPTION_STATIC_REMOTEKEY = 1 << 12
- OPTION_ANCHORS_ZERO_FEE_HTLC_TX = 1 << 22
+ OPTION_ANCHORS = 1 << 22
OPTION_SCID_ALIAS = 1 << 46
OPTION_ZEROCONF = 1 << 50
@@ -1641,7 +1641,7 @@ class ChannelType(IntFlag):
basic_type = self & ~(ChannelType.OPTION_SCID_ALIAS | ChannelType.OPTION_ZEROCONF)
if basic_type not in [
ChannelType.OPTION_STATIC_REMOTEKEY,
- ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX | ChannelType.OPTION_STATIC_REMOTEKEY
+ ChannelType.OPTION_ANCHORS | ChannelType.OPTION_STATIC_REMOTEKEY
]:
raise ValueError("Channel type is not a valid flag combination.")
@@ -1684,7 +1684,7 @@ LN_FEATURES_IMPLEMENTED = (
| LnFeatures.OPTION_SHUTDOWN_ANYSEGWIT_OPT | LnFeatures.OPTION_SHUTDOWN_ANYSEGWIT_REQ
| LnFeatures.OPTION_CHANNEL_TYPE_OPT | LnFeatures.OPTION_CHANNEL_TYPE_REQ
| LnFeatures.OPTION_SCID_ALIAS_OPT | LnFeatures.OPTION_SCID_ALIAS_REQ
- | LnFeatures.OPTION_ANCHORS_ZERO_FEE_HTLC_OPT | LnFeatures.OPTION_ANCHORS_ZERO_FEE_HTLC_REQ
+ | LnFeatures.OPTION_ANCHORS_OPT | LnFeatures.OPTION_ANCHORS_REQ
)
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
index 77484f6..7cb80d7 100644
--- a/electrum/lnworker.py
+++ b/electrum/lnworker.py
@@ -1015,7 +1015,7 @@ class LNWallet(Logger):
if features is None:
features = LNWALLET_FEATURES
if self.config.ENABLE_ANCHOR_CHANNELS:
- features |= LnFeatures.OPTION_ANCHORS_ZERO_FEE_HTLC_OPT
+ features |= LnFeatures.OPTION_ANCHORS_OPT
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:
@@ -1692,7 +1692,7 @@ class LNWallet(Logger):
upfront_shutdown_script = b''
assert channel_type is not None
- if channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX: # anchors
+ if channel_type & ChannelType.OPTION_ANCHORS: # anchors
static_payment_key = self.static_payment_key
static_remotekey = None
else: # static_remotekey
diff --git a/tests/test_lnchannel.py b/tests/test_lnchannel.py
index e3a89f0..932aabb 100644
--- a/tests/test_lnchannel.py
+++ b/tests/test_lnchannel.py
@@ -156,7 +156,7 @@ def create_test_channels(
peer_features = alice_lnwallet.features | LnFeatures.OPTION_SUPPORT_LARGE_CHANNEL_OPT
channel_type = ChannelType.OPTION_STATIC_REMOTEKEY
if anchor_outputs:
- channel_type |= ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX
+ channel_type |= ChannelType.OPTION_ANCHORS
# create alice's local config
alice_lconfig = alice_lnwallet.make_local_config_for_new_channel(
funding_sat=funding_sat,
Why this scored 15/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.