What changed, and why it matters
This commit adds a small helper method that converts Lightning Network feature flags into a compact byte format used in modern Lightning protocol messages. It is a routine, additive code change with no security relevance visible in the commit or supplied references.
No security action required; review as normal feature/serialization code.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces LnFeatures.to_tlv_bytes(), which serializes an IntFlag-based feature set to minimal big-endian bytes: empty for zero, otherwise stripped of leading zeros and padded to an even hex digit count. Unit tests cover single-bit, multi-bit, combined, and zero cases. There is no change to parsing, validation, cryptography, or network handling.
Changed components
electrum/lnutil.pytests/test_lnutil.pyInspect captured patch +19 / −0
diff --git a/electrum/lnutil.py b/electrum/lnutil.py
index 9ce985c..e725092 100644
--- a/electrum/lnutil.py
+++ b/electrum/lnutil.py
@@ -1614,6 +1614,14 @@ class LnFeatures(IntFlag):
r.append(feature_name or f"bit_{flag}")
return r
+ def to_tlv_bytes(self) -> bytes:
+ if int(self) == 0:
+ return b''
+ a = hex(int(self))[2:]
+ b = (len(a) % 2) * '0' + a
+ d = bytes.fromhex(b)
+ return d
+
def _for_context(self, context: 'LnFeatureContexts') -> 'LnFeatures':
features = LnFeatures(0)
for flag in list_enabled_ln_feature_bits(self):
diff --git a/tests/test_lnutil.py b/tests/test_lnutil.py
index 8ff9142..5df8755 100644
--- a/tests/test_lnutil.py
+++ b/tests/test_lnutil.py
@@ -1095,6 +1095,17 @@ class TestLNUtil(ElectrumTestCase):
ctype = ChannelType.OPTION_STATIC_REMOTEKEY | ChannelType.OPTION_ANCHORS
self.assertTrue(ctype.complies_with_features(pfeatures))
+ def test_to_tlv_bytes(self):
+ features = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ
+ self.assertEqual(features.to_tlv_bytes(), bfh('01'))
+ features = LnFeatures.OPTION_ROUTE_BLINDING_OPT
+ self.assertEqual(features.to_tlv_bytes(), bfh('02000000'))
+ features = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ |\
+ LnFeatures.OPTION_ROUTE_BLINDING_OPT |\
+ LnFeatures.BASIC_MPP_OPT
+ self.assertEqual(features.to_tlv_bytes(), bfh('02020001'))
+ self.assertEqual(LnFeatures(0).to_tlv_bytes(), b'')
+
@as_testnet
async def test_decode_imported_channel_backup_v0(self):
encrypted_cb = "channel_backup:Adn87xcGIs9H2kfp4VpsOaNKWCHX08wBoqq37l1cLYKGlJamTeoaLEwpJA81l1BXF3GP/mRxqkY+whZG9l51G8izIY/kmMSvnh0DOiZEdwaaT/1/MwEHfsEomruFqs+iW24SFJPHbMM7f80bDtIxcLfZkKmgcKBAOlcqtq+dL3U3yH74S8BDDe2L4snaxxpCjF0JjDMBx1UR/28D+QlIi+lbvv1JMaCGXf+AF1+3jLQf8+lVI+rvFdyArws6Ocsvjf+ANQeSGUwW6Nb2xICQcMRgr1DO7bO4pgGu408eYRr2v3ayJBVtnKwSwd49gF5SDSjTDAO4CCM0uj9H5RxyzH7fqotkd9J80MBr84RiBXAeXKz+Ap8608/FVqgQ9BOcn6LhuAQdE5zXpmbQyw5jUGkPvHuseR+rzthzncy01odUceqTNg=="
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.