From 02bfa4136f9073293a60500123c5bf83440e7f20 Mon Sep 17 00:00:00 2001 From: Sangbida Chaudhuri <101164840+sangbida@users.noreply.github.com> Date: Tue, 20 Jan 2026 19:34:42 +1030 Subject: [PATCH] pyln-testing: add old_hsmsecret param to get_node. This defaults to false for now: this breaks a lot of tests (since node ids change!) once we switch to true. --- contrib/pyln-testing/pyln/testing/utils.py | 33 ++++++++++++++++++++-- pyproject.toml | 1 + uv.lock | 11 ++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 732bd7b49..2159ef87b 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -17,6 +17,7 @@ import json import logging import lzma import math +import mnemonic import os import random import re @@ -664,6 +665,14 @@ class ElementsD(BitcoinD): return info['unconfidential'] +def mnemonic_from_seed(seed): + m = mnemonic.Mnemonic('english') + mnem = m.to_mnemonic(seed) + if not m.check(mnem): + raise RuntimeError("Generated mnemonic failed BIP39 validation (unexpected).") + return mnem + + class LightningD(TailableProc): def __init__( self, @@ -673,6 +682,7 @@ class LightningD(TailableProc): random_hsm=False, node_id=0, executable=None, + old_hsmsecret=None, ): # We handle our own version of verbose, below. TailableProc.__init__(self, lightning_dir, verbose=False) @@ -714,11 +724,27 @@ class LightningD(TailableProc): if not os.path.exists(os.path.join(lightning_dir, TEST_NETWORK)): os.makedirs(os.path.join(lightning_dir, TEST_NETWORK)) - # Last 32-bytes of final part of dir -> seed. - seed = (bytes(re.search('([^/]+)/*$', lightning_dir).group(1), encoding='utf-8') + bytes(32))[:32] + # Default: use old-timey hsm_secret. + if old_hsmsecret is None: + old_hsmsecret = True + + # BIP 39 secrets were only added in v25.12. + if old_hsmsecret is True: + assert self.cln_version >= "v25.12" + if not random_hsm: + # Last 32-bytes of final part of dir -> seed. + seed = (bytes(re.search('([^/]+)/*$', lightning_dir).group(1), encoding='utf-8') + bytes(32))[:32] + # Modern style is 32 zeroes then a 12-word mnemonic phrase. + if not old_hsmsecret: + # Use first 16 bytes (128 bits) for 12-word mnemonic + entropy_128 = seed[:16] + mnemonic_phrase = mnemonic_from_seed(entropy_128) + seed = bytes(32) + bytes(mnemonic_phrase, encoding='utf-8') + with open(os.path.join(lightning_dir, TEST_NETWORK, 'hsm_secret'), 'wb') as f: f.write(seed) + self.opts['dev-fast-gossip'] = None self.opts['dev-bitcoind-poll'] = 1 self.prefix = 'lightningd-%d' % (node_id) @@ -851,6 +877,7 @@ class LightningNode(object): valgrind_plugins=True, executable=None, bad_notifications=False, + old_hsmsecret=None, **kwargs): self.bitcoin = bitcoind self.executor = executor @@ -875,6 +902,7 @@ class LightningNode(object): lightning_dir, bitcoindproxy=bitcoind.get_proxy(), port=port, random_hsm=random_hsm, node_id=node_id, executable=executable, + old_hsmsecret=old_hsmsecret, ) self.cln_version = self.daemon.cln_version @@ -1689,6 +1717,7 @@ class NodeFactory(object): 'allow_bad_gossip', 'start', 'gossip_store_file', + 'old_hsmsecret', ] node_opts = {k: v for k, v in opts.items() if k in node_opt_keys} cli_opts = {k: v for k, v in opts.items() if k not in node_opt_keys} diff --git a/pyproject.toml b/pyproject.toml index b86ffef59..76335c2e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ dependencies = [ "pytest-rerunfailures>=16.0.1", "pyln-testing", "pyln-proto", + "mnemonic>=0.21", ] package-mode = false [dependency-groups] diff --git a/uv.lock b/uv.lock index 9373dedf7..0c75e49f7 100644 --- a/uv.lock +++ b/uv.lock @@ -460,6 +460,7 @@ dependencies = [ { name = "grpcio" }, { name = "grpcio-tools" }, { name = "mako" }, + { name = "mnemonic" }, { name = "protobuf" }, { name = "pyln-client" }, { name = "pyln-grpc-proto" }, @@ -501,6 +502,7 @@ requires-dist = [ { name = "grpcio", specifier = "==1.75.1" }, { name = "grpcio-tools", specifier = "==1.75.1" }, { name = "mako", specifier = ">=1.1.6" }, + { name = "mnemonic", specifier = ">=0.21" }, { name = "protobuf", specifier = "==6.32.1" }, { name = "pyln-client", editable = "contrib/pyln-client" }, { name = "pyln-grpc-proto", editable = "contrib/pyln-grpc-proto" }, @@ -1264,6 +1266,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, ] +[[package]] +name = "mnemonic" +version = "0.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/77/e6232ed59fbd7b90208bb8d4f89ed5aabcf30a524bc2fb8f0dafbe8e7df9/mnemonic-0.21.tar.gz", hash = "sha256:1fe496356820984f45559b1540c80ff10de448368929b9c60a2b55744cc88acf", size = 152462, upload-time = "2024-01-05T10:46:14.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/48/5abb16ce7f9d97b728e6b97c704ceaa614362e0847651f379ed0511942a0/mnemonic-0.21-py3-none-any.whl", hash = "sha256:72dc9de16ec5ef47287237b9b6943da11647a03fe7cf1f139fc3d7c4a7439288", size = 92701, upload-time = "2024-01-05T10:46:12.703Z" }, +] + [[package]] name = "more-itertools" version = "10.8.0"