mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 22:45:27 +01:00
developer: add --dev-force-bip32-seed to force a specific BIP32 seed.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
07adb7efd6
commit
d59e2b1b4b
7 changed files with 57 additions and 4 deletions
|
@ -10,6 +10,7 @@ hsmstatus_client_bad_request,,msg,len*u8
|
||||||
hsm_init,11
|
hsm_init,11
|
||||||
hsm_init,,bip32_key_version,struct bip32_key_version
|
hsm_init,,bip32_key_version,struct bip32_key_version
|
||||||
hsm_init,,dev_force_privkey,?struct privkey
|
hsm_init,,dev_force_privkey,?struct privkey
|
||||||
|
hsm_init,,dev_force_bip32_seed,?struct secret
|
||||||
|
|
||||||
#include <common/bip32.h>
|
#include <common/bip32.h>
|
||||||
hsm_init_reply,111
|
hsm_init_reply,111
|
||||||
|
|
|
20
hsmd/hsmd.c
20
hsmd/hsmd.c
|
@ -75,6 +75,8 @@ static struct bip32_key_version bip32_key_version;
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
/* If they specify --dev-force-privkey it ends up in here. */
|
/* If they specify --dev-force-privkey it ends up in here. */
|
||||||
static struct privkey *dev_force_privkey;
|
static struct privkey *dev_force_privkey;
|
||||||
|
/* If they specify --dev-force-bip32-seed it ends up in here. */
|
||||||
|
static struct secret *dev_force_bip32_seed;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*~ We keep track of clients, but there's not much to keep. */
|
/*~ We keep track of clients, but there's not much to keep. */
|
||||||
|
@ -403,6 +405,18 @@ static void populate_secretstuff(void)
|
||||||
bip32_key_version.bip32_privkey_version,
|
bip32_key_version.bip32_privkey_version,
|
||||||
0, &master_extkey) != WALLY_OK);
|
0, &master_extkey) != WALLY_OK);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
|
/* In DEVELOPER mode, we can override with --dev-force-bip32-seed */
|
||||||
|
if (dev_force_bip32_seed) {
|
||||||
|
if (bip32_key_from_seed(dev_force_bip32_seed->data,
|
||||||
|
sizeof(dev_force_bip32_seed->data),
|
||||||
|
bip32_key_version.bip32_privkey_version,
|
||||||
|
0, &master_extkey) != WALLY_OK)
|
||||||
|
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||||
|
"Can't derive bip32 master key");
|
||||||
|
}
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
/* BIP 32:
|
/* BIP 32:
|
||||||
*
|
*
|
||||||
* The default wallet layout
|
* The default wallet layout
|
||||||
|
@ -557,6 +571,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
|
||||||
struct node_id node_id;
|
struct node_id node_id;
|
||||||
struct pubkey key;
|
struct pubkey key;
|
||||||
struct privkey *privkey;
|
struct privkey *privkey;
|
||||||
|
struct secret *seed;
|
||||||
|
|
||||||
/* This must be lightningd. */
|
/* This must be lightningd. */
|
||||||
assert(is_lightningd(c));
|
assert(is_lightningd(c));
|
||||||
|
@ -565,11 +580,13 @@ static struct io_plan *init_hsm(struct io_conn *conn,
|
||||||
* definitions in hsm_client_wire.csv. The format of those files is
|
* definitions in hsm_client_wire.csv. The format of those files is
|
||||||
* an extension of the simple comma-separated format output by the
|
* an extension of the simple comma-separated format output by the
|
||||||
* BOLT tools/extract-formats.py tool. */
|
* BOLT tools/extract-formats.py tool. */
|
||||||
if (!fromwire_hsm_init(NULL, msg_in, &bip32_key_version, &privkey))
|
if (!fromwire_hsm_init(NULL, msg_in, &bip32_key_version,
|
||||||
|
&privkey, &seed))
|
||||||
return bad_req(conn, c, msg_in);
|
return bad_req(conn, c, msg_in);
|
||||||
|
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
dev_force_privkey = privkey;
|
dev_force_privkey = privkey;
|
||||||
|
dev_force_bip32_seed = seed;
|
||||||
#endif
|
#endif
|
||||||
maybe_create_new_hsm();
|
maybe_create_new_hsm();
|
||||||
load_hsm();
|
load_hsm();
|
||||||
|
@ -1622,6 +1639,7 @@ static struct io_plan *handle_memleak(struct io_conn *conn,
|
||||||
memleak_scan_region(memtable, status_conn, tal_bytelen(status_conn));
|
memleak_scan_region(memtable, status_conn, tal_bytelen(status_conn));
|
||||||
|
|
||||||
memleak_scan_region(memtable, dev_force_privkey, 0);
|
memleak_scan_region(memtable, dev_force_privkey, 0);
|
||||||
|
memleak_scan_region(memtable, dev_force_bip32_seed, 0);
|
||||||
|
|
||||||
found_leak = dump_memleak(memtable);
|
found_leak = dump_memleak(memtable);
|
||||||
reply = towire_hsm_dev_memleak_reply(NULL, found_leak);
|
reply = towire_hsm_dev_memleak_reply(NULL, found_leak);
|
||||||
|
|
|
@ -96,9 +96,10 @@ void hsm_init(struct lightningd *ld)
|
||||||
if (!wire_sync_write(ld->hsm_fd, towire_hsm_init(tmpctx,
|
if (!wire_sync_write(ld->hsm_fd, towire_hsm_init(tmpctx,
|
||||||
&ld->topology->bitcoind->chainparams->bip32_key_version,
|
&ld->topology->bitcoind->chainparams->bip32_key_version,
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
ld->dev_force_privkey
|
ld->dev_force_privkey,
|
||||||
|
ld->dev_force_bip32_seed
|
||||||
#else
|
#else
|
||||||
NULL
|
NULL, NULL
|
||||||
#endif
|
#endif
|
||||||
)))
|
)))
|
||||||
err(1, "Writing init msg to hsm");
|
err(1, "Writing init msg to hsm");
|
||||||
|
|
|
@ -119,6 +119,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
|
||||||
ld->dev_allow_localhost = false;
|
ld->dev_allow_localhost = false;
|
||||||
ld->dev_gossip_time = 0;
|
ld->dev_gossip_time = 0;
|
||||||
ld->dev_force_privkey = NULL;
|
ld->dev_force_privkey = NULL;
|
||||||
|
ld->dev_force_bip32_seed = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*~ These are CCAN lists: an embedded double-linked list. It's not
|
/*~ These are CCAN lists: an embedded double-linked list. It's not
|
||||||
|
|
|
@ -208,6 +208,9 @@ struct lightningd {
|
||||||
|
|
||||||
/* This is the forced private key for the node. */
|
/* This is the forced private key for the node. */
|
||||||
struct privkey *dev_force_privkey;
|
struct privkey *dev_force_privkey;
|
||||||
|
|
||||||
|
/* This is the forced bip32 seed for the node. */
|
||||||
|
struct secret *dev_force_bip32_seed;
|
||||||
#endif /* DEVELOPER */
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
/* tor support */
|
/* tor support */
|
||||||
|
|
|
@ -449,6 +449,17 @@ static char *opt_force_privkey(const char *optarg, struct lightningd *ld)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *opt_force_bip32_seed(const char *optarg, struct lightningd *ld)
|
||||||
|
{
|
||||||
|
tal_free(ld->dev_force_bip32_seed);
|
||||||
|
ld->dev_force_bip32_seed = tal(ld, struct secret);
|
||||||
|
if (!hex_decode(optarg, strlen(optarg),
|
||||||
|
ld->dev_force_bip32_seed,
|
||||||
|
sizeof(*ld->dev_force_bip32_seed)))
|
||||||
|
return tal_fmt(NULL, "Unable to parse secret '%s'", optarg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void dev_register_opts(struct lightningd *ld)
|
static void dev_register_opts(struct lightningd *ld)
|
||||||
{
|
{
|
||||||
opt_register_noarg("--dev-no-reconnect", opt_set_invbool,
|
opt_register_noarg("--dev-no-reconnect", opt_set_invbool,
|
||||||
|
@ -487,7 +498,9 @@ static void dev_register_opts(struct lightningd *ld)
|
||||||
"UNIX time to override gossipd to use.");
|
"UNIX time to override gossipd to use.");
|
||||||
opt_register_arg("--dev-force-privkey", opt_force_privkey, NULL, ld,
|
opt_register_arg("--dev-force-privkey", opt_force_privkey, NULL, ld,
|
||||||
"Force HSM to use this as node private key");
|
"Force HSM to use this as node private key");
|
||||||
}
|
opt_register_arg("--dev-force-bip32-seed", opt_force_bip32_seed, NULL, ld,
|
||||||
|
"Force HSM to use this as bip32 seed");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct config testnet_config = {
|
static const struct config testnet_config = {
|
||||||
|
|
|
@ -1262,6 +1262,22 @@ def test_bitcoind_fail_first(node_factory, bitcoind, executor):
|
||||||
f.result()
|
f.result()
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs --dev-force-bip32-seed")
|
||||||
|
def test_dev_force_bip32_seed(node_factory):
|
||||||
|
l1 = node_factory.get_node(options={'dev-force-bip32-seed': '0000000000000000000000000000000000000000000000000000000000000001'})
|
||||||
|
# First is m/0/0/1 ..
|
||||||
|
bech32 = l1.rpc.newaddr('bech32')['bech32']
|
||||||
|
assert bech32 == "bcrt1qsdzqt93xsyewdjvagndw9523m27e52er5ca7hm"
|
||||||
|
bech32 = l1.rpc.newaddr('bech32')['bech32']
|
||||||
|
assert bech32 == "bcrt1qlkt93775wmf33uacykc49v2j4tayn0yj25msjn"
|
||||||
|
bech32 = l1.rpc.newaddr('bech32')['bech32']
|
||||||
|
assert bech32 == "bcrt1q2ng546gs0ylfxrvwx0fauzcvhuz655en4kwe2c"
|
||||||
|
bech32 = l1.rpc.newaddr('bech32')['bech32']
|
||||||
|
assert bech32 == "bcrt1qrdpwrlrmrnvn535l5eldt64lxm8r2nwkv0ruxq"
|
||||||
|
bech32 = l1.rpc.newaddr('bech32')['bech32']
|
||||||
|
assert bech32 == "bcrt1q622lwmdzxxterumd746eu3d3t40pq53p62zhlz"
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs dev command")
|
@unittest.skipIf(not DEVELOPER, "needs dev command")
|
||||||
def test_dev_demux(node_factory):
|
def test_dev_demux(node_factory):
|
||||||
l1 = node_factory.get_node(may_fail=True, allow_broken_log=True)
|
l1 = node_factory.get_node(may_fail=True, allow_broken_log=True)
|
||||||
|
|
Loading…
Add table
Reference in a new issue