Skip to content

Commit

Permalink
hsmtool: makerune command.
Browse files Browse the repository at this point in the history
You still need to actually make a rune when lightningd starts, as
commando (for safety) won't work unless you actually generate a rune
(that it knows of!).

Signed-off-by: Rusty Russell <[email protected]>
Changelog-Added: hsmtool: `makerune` command to make a master rune for a node.
  • Loading branch information
rustyrussell authored and ShahanaFarooqui committed Apr 11, 2023
1 parent 441b38c commit 62d9ecb
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
5 changes: 5 additions & 0 deletions doc/lightning-hsmtool.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ We need the path to the hsm\_secret containing the wallet seed, and an optional
To generate descriptors using testnet master keys, you may specify *testnet* as
the last parameter. By default, mainnet-encoded keys are generated.

**makerune** *hsm\_secret*
Make a master rune for this node (with `uniqueid` 0)
This produces the same results as lightning-commando-rune(7) on a fresh node.
You will still need to create a rune once the node starts, if you want commando to work (as it is only activated once it has generated one).

BUGS
----

Expand Down
31 changes: 31 additions & 0 deletions tests/test_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -1667,3 +1667,34 @@ def test_upgradewallet(node_factory, bitcoind):
sync_blockheight(l1.bitcoin, [l1])
upgrade = l1.rpc.upgradewallet(feerate="urgent", reservedok=True)
assert upgrade['upgraded_outs'] == 0


def test_hsmtool_makerune(node_factory):
"""Test we can make a valid rune before the node really exists"""
l1 = node_factory.get_node(start=False)

# get_node() creates a secret, but in usual case we generate one.
hsm_path = os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "hsm_secret")
os.remove(hsm_path)

hsmtool = HsmTool(node_factory.directory, "generatehsm", hsm_path)
master_fd, slave_fd = os.openpty()
hsmtool.start(stdin=slave_fd)
hsmtool.wait_for_log(r"Select your language:")
write_all(master_fd, "0\n".encode("utf-8"))
hsmtool.wait_for_log(r"Introduce your BIP39 word list")
write_all(master_fd, "ritual idle hat sunny universe pluck key alpha wing "
"cake have wedding\n".encode("utf-8"))
hsmtool.wait_for_log(r"Enter your passphrase:")
write_all(master_fd, "This is actually not a passphrase\n".encode("utf-8"))
assert hsmtool.proc.wait(WAIT_TIMEOUT) == 0
hsmtool.is_in_log(r"New hsm_secret file created")

cmd_line = ["tools/hsmtool", "makerune", hsm_path]
out = subprocess.check_output(cmd_line).decode("utf8").split("\n")[0]

l1.start()

# We have to generate a rune now, for commando to even start processing!
rune = l1.rpc.commando_rune()['rune']
assert rune == out
35 changes: 35 additions & 0 deletions tools/hsmtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <ccan/err/err.h>
#include <ccan/noerr/noerr.h>
#include <ccan/read_write_all/read_write_all.h>
#include <ccan/rune/rune.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
#include <ccan/tal/str/str.h>
Expand Down Expand Up @@ -42,6 +43,7 @@ static void show_usage(const char *progname)
printf(" - generatehsm <path/to/new/hsm_secret>\n");
printf(" - checkhsm <path/to/new/hsm_secret>\n");
printf(" - dumponchaindescriptors <path/to/hsm_secret> [network]\n");
printf(" - makerune <path/to/hsm_secret>\n");
exit(0);
}

Expand Down Expand Up @@ -611,6 +613,33 @@ static int check_hsm(const char *hsm_secret_path)
return 0;
}

static int make_rune(const char *hsm_secret_path)
{
struct secret hsm_secret, derived_secret, rune_secret;
struct rune *master_rune, *rune;

/* Get hsm_secret */
get_hsm_secret(&hsm_secret, hsm_secret_path);

/* HSM derives a root secret for `makesecret` */
hkdf_sha256(&derived_secret, sizeof(struct secret), NULL, 0,
&hsm_secret, sizeof(hsm_secret),
"derived secrets", strlen("derived secrets"));

/* Commando derives secret using makesecret "commando" */
hkdf_sha256(&rune_secret, sizeof(struct secret), NULL, 0,
&derived_secret, sizeof(derived_secret),
"commando", strlen("commando"));

master_rune = rune_new(tmpctx,
rune_secret.data,
ARRAY_SIZE(rune_secret.data),
NULL);
rune = rune_derive_start(tmpctx, master_rune, "0");
printf("%s\n", rune_to_base64(tmpctx, rune));
return 0;
}

int main(int argc, char *argv[])
{
const char *method;
Expand Down Expand Up @@ -703,5 +732,11 @@ int main(int argc, char *argv[])
return check_hsm(argv[2]);
}

if (streq(method, "makerune")) {
if (argc < 3)
show_usage(argv[0]);
return make_rune(argv[2]);
}

show_usage(argv[0]);
}

0 comments on commit 62d9ecb

Please sign in to comment.