Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions contrib/pyln-testing/pyln/testing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import logging
import lzma
import math
import mnemonic
import os
import random
import re
Expand Down Expand Up @@ -664,6 +665,14 @@ def getnewaddress(self):
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,
Expand All @@ -673,6 +682,7 @@ def __init__(
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)
Expand Down Expand Up @@ -714,11 +724,24 @@ def __init__(
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 newfangled hsm_secret, except old versions.
if old_hsmsecret is None:
# BIP 39 secrets were only added in v25.12.
old_hsmsecret = (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)
Expand Down Expand Up @@ -851,6 +874,7 @@ def __init__(self, node_id, lightning_dir, bitcoind, executor, may_fail=False,
valgrind_plugins=True,
executable=None,
bad_notifications=False,
old_hsmsecret=None,
**kwargs):
self.bitcoin = bitcoind
self.executor = executor
Expand All @@ -875,6 +899,7 @@ def __init__(self, node_id, lightning_dir, bitcoind, executor, may_fail=False,
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

Expand Down Expand Up @@ -1689,6 +1714,7 @@ def split_options(self, opts):
'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}
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies = [
"pytest-rerunfailures>=16.0.1",
"pyln-testing",
"pyln-proto",
"mnemonic>=0.21",
]
package-mode = false
[dependency-groups]
Expand Down
6 changes: 3 additions & 3 deletions tests/autogenerate-rpc-examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -1822,13 +1822,13 @@ def generate_backup_recovery_examples(node_factory, l4, l5, l6):

# Recover
def get_hsm_secret(n):
"""Returns codex32 and hex"""
"""Returns recoverstring and hex"""
try:
hsmfile = os.path.join(n.daemon.lightning_dir, TEST_NETWORK, "hsm_secret")
codex32 = subprocess.check_output(["tools/lightning-hsmtool", "getcodexsecret", hsmfile, "leet"]).decode('utf-8').strip()
recover = subprocess.check_output(["tools/lightning-hsmtool", "getsecret", hsmfile, "leet"]).decode('utf-8').strip()
with open(hsmfile, "rb") as f:
hexhsm = f.read().hex()
return codex32, hexhsm
return recover, hexhsm
except Exception as e:
logger.error(f'Error in getting hsm secret: {e}')
raise
Expand Down
17 changes: 6 additions & 11 deletions tests/plugins/channeld_fakenet.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
#include <ccan/htable/htable_type.h>
#include <ccan/mem/mem.h>
#include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h>
#include <channeld/channeld_wiregen.h>
#include <channeld/full_channel.h>
Expand Down Expand Up @@ -257,19 +258,13 @@ static u8 *get_next_onion(const tal_t *ctx, const struct route_step *rs)
static struct node *make_peer_node(const tal_t *ctx)
{
struct node *n = tal(ctx, struct node);
u32 salt = 0;
struct secret hsm_secret;
struct pubkey pubkey;

memset(&hsm_secret, 0, sizeof(hsm_secret));
snprintf((char *)&hsm_secret, sizeof(hsm_secret),
"lightning-2");

/* This maps hsm_secret -> node privkey */
hkdf_sha256(&n->p, sizeof(n->p),
&salt, sizeof(salt),
&hsm_secret, sizeof(hsm_secret),
"nodeid", 6);
/* l2's secret key */
if (!hex_decode("0c633a7c17c701a0980158f5483035e01fa8bd091b47fadf2e86e589a9f93fca",
strlen("0c633a7c17c701a0980158f5483035e01fa8bd091b47fadf2e86e589a9f93fca"),
&n->p, sizeof(n->p)))
abort();
pubkey_from_privkey(&n->p, &pubkey);
node_id_from_pubkey(&n->id, &pubkey);
n->name = tal_fmt(n, "lightningd-2");
Expand Down
Loading
Loading