Skip to content

Commit 66794d0

Browse files
committed
Only persist the node_id, fetch the bip32 ext_pub and use fake bolt12 pubkey. (#25)
1 parent ed437c6 commit 66794d0

File tree

4 files changed

+108
-137
lines changed

4 files changed

+108
-137
lines changed

contrib/remote_hsmd/Makefile

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ PROTOS_PATH = contrib/remote_hsmd
3434
RMTHSMD_COMMON_OBJS := \
3535
hsmd/hsmd_wiregen.o \
3636
common/amount.o \
37-
common/base32.o \
3837
common/bigsize.o \
3938
common/bip32.o \
4039
common/channel_id.o \
@@ -43,9 +42,6 @@ RMTHSMD_COMMON_OBJS := \
4342
common/derive_basepoints.o \
4443
common/status_wiregen.o \
4544
common/hash_u5.o \
46-
common/json.o \
47-
common/json_helpers.o \
48-
common/json_stream.o \
4945
common/key_derive.o \
5046
common/memleak.o \
5147
common/msg_queue.o \
@@ -59,8 +55,7 @@ RMTHSMD_COMMON_OBJS := \
5955
common/type_to_string.o \
6056
common/utils.o \
6157
common/utxo.o \
62-
common/version.o \
63-
common/wireaddr.o
58+
common/version.o
6459

6560
# For checking
6661
LIGHTNINGD_RMTHSM_ALLSRC_NOGEN := $(filter-out contrib/remote_hsmd/remotesigner.%, $(LIGHTNINGD_RMTHSM_SRC) $(LIGHTNINGD_RMTHSM_SRC))

contrib/remote_hsmd/hsmd.c

Lines changed: 43 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,15 @@
2020
#include <ccan/intmap/intmap.h>
2121
#include <ccan/io/fdpass/fdpass.h>
2222
#include <ccan/io/io.h>
23-
#include <ccan/json_out/json_out.h>
2423
#include <ccan/noerr/noerr.h>
2524
#include <ccan/ptrint/ptrint.h>
2625
#include <ccan/read_write_all/read_write_all.h>
27-
#include <ccan/str/hex/hex.h>
2826
#include <ccan/take/take.h>
2927
#include <ccan/tal/grab_file/grab_file.h>
3028
#include <ccan/tal/str/str.h>
3129
#include <common/daemon_conn.h>
3230
#include <common/derive_basepoints.h>
3331
#include <common/hash_u5.h>
34-
#include <common/json.h>
35-
#include <common/json_helpers.h>
3632
#include <common/key_derive.h>
3733
#include <common/memleak.h>
3834
#include <common/node_id.h>
@@ -352,23 +348,29 @@ static bool read_test_seed(struct secret *hsm_secret)
352348
return true;
353349
}
354350

355-
// TODO - Add support for bolt12 to remote signer and remove this entire routine.
356-
static void workaround_init_bolt12(const struct secret *hsm_secret, struct pubkey32 *bolt12out)
351+
// TODO - Add support for bolt12 to remote signer and remove this
352+
// entire routine. This does not actually setup a usable BOLT12
353+
// context; it always uses an empty hsm_secret.
354+
static void bogus_bolt12_placeholder(struct pubkey32 *bolt12out)
357355
{
356+
struct secret bad_hsm_secret;
358357
u8 bip32_seed[BIP32_ENTROPY_LEN_256];
359358
u32 salt = 0;
360359
struct ext_key master_extkey, child_extkey;
361360
secp256k1_keypair bolt12;
362361

362+
// This needs to be computed on the remote server!
363+
memset(&bad_hsm_secret, 0, sizeof(bad_hsm_secret));
364+
363365
/* Fill in the BIP32 tree for bitcoin addresses. */
364366
/* In libwally-core, the version BIP32_VER_TEST_PRIVATE is for testnet/regtest,
365367
* and BIP32_VER_MAIN_PRIVATE is for mainnet. For litecoin, we also set it like
366368
* bitcoin else.*/
367369
do {
368370
hkdf_sha256(bip32_seed, sizeof(bip32_seed),
369371
&salt, sizeof(salt),
370-
hsm_secret,
371-
sizeof(*hsm_secret),
372+
&bad_hsm_secret,
373+
sizeof(bad_hsm_secret),
372374
"bip32 seed", strlen("bip32 seed"));
373375
salt++;
374376
} while (bip32_key_from_seed(bip32_seed, sizeof(bip32_seed),
@@ -396,69 +398,29 @@ static void workaround_init_bolt12(const struct secret *hsm_secret, struct pubke
396398
"Could derive bolt12 public key.");
397399
}
398400

399-
static void persist_node_id(const struct node_id *node_id,
400-
const struct ext_key *bip32,
401-
const struct pubkey32 *bolt12)
401+
static void persist_node_id(const struct node_id *node_id)
402402
{
403-
struct json_out *jout = json_out_new(tmpctx);
404-
json_out_start(jout, NULL, '{');
405-
406-
json_out_addstr(jout, "nodeid", type_to_string(jout, struct node_id, node_id));
407-
408-
char *xpub;
409-
tal_wally_start();
410-
int rv2 = bip32_key_to_base58(bip32, BIP32_FLAG_KEY_PUBLIC, &xpub);
411-
tal_wally_end(NULL);
412-
assert(rv2 == WALLY_OK);
413-
json_out_addstr(jout, "xpub", xpub);
414-
wally_free_string(xpub);
415-
416-
json_out_addstr(jout, "bolt12", type_to_string(jout, struct pubkey32, bolt12));
417-
418-
json_out_end(jout, '}');
419-
size_t len;
420-
const char *p = json_out_contents(jout, &len);
421-
403+
char *node_id_str = tal_fmt(tmpctx, "%s\n",
404+
type_to_string(tmpctx, struct node_id, node_id));
422405
int fd = open("NODE_ID", O_WRONLY|O_TRUNC|O_CREAT, 0666);
423406
assert(fd != -1);
424-
write_all(fd, p, len);
425-
json_out_consume(jout, len);
407+
write_all(fd, node_id_str, strlen(node_id_str));
426408
close(fd);
427409
}
428410

429-
static bool restore_node_id(struct node_id *node_id,
430-
struct ext_key *bip32,
431-
struct pubkey32 *bolt12)
411+
static bool restore_node_id(struct node_id *node_id)
432412
{
433413
if (access("NODE_ID", F_OK) == -1) {
434-
// This is a cold start, we don't have this yet.
414+
// This is a cold start, we don't have a node_id yet.
435415
return false;
436416
}
437417

438-
// This is a warmstart, initialize our node_id.
439418
char *buffer = grab_file(tmpctx, "NODE_ID");
440-
const jsmntok_t *toks = json_parse_simple(buffer, buffer, strlen(buffer));
441-
const jsmntok_t *nodeidtok = json_get_member(buffer, toks, "nodeid");
442-
const jsmntok_t *xpubtok = json_get_member(buffer, toks, "xpub");
443-
const jsmntok_t *bolt12tok = json_get_member(buffer, toks, "bolt12");
444-
assert(nodeidtok != NULL);
445-
assert(xpubtok != NULL);
446-
assert(bolt12tok != NULL);
447-
448-
if (!json_to_node_id(buffer, nodeidtok, node_id))
449-
abort();
450-
451-
buffer[xpubtok->end] = '\0'; // need to null-terminate xpub string
452-
if (bip32_key_from_base58(buffer + xpubtok->start, bip32) != WALLY_OK)
453-
abort();
454-
455-
u8 raw[32];
456-
if (!hex_decode(buffer + bolt12tok->start, bolt12tok->end - bolt12tok->start,
457-
raw, sizeof(raw)))
458-
abort();
459-
if (secp256k1_xonly_pubkey_parse(secp256k1_ctx, &bolt12->pubkey, raw) != 1)
460-
abort();
461-
419+
assert(buffer != NULL);
420+
size_t len = tal_bytelen(buffer) - 2;
421+
assert(buffer[len] == '\n');
422+
bool ok = node_id_from_hexstr(buffer, len, node_id);
423+
assert(ok);
462424
return true;
463425
}
464426

@@ -517,7 +479,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
517479
c->chainparams = chainparams;
518480

519481
/* Is this a warm start (restart) or a cold start (first time)? */
520-
if (restore_node_id(&node_id, &pubstuff.bip32, &bolt12)) {
482+
if (restore_node_id(&node_id)) {
521483
// This is a warm start.
522484
proxy_set_node_id(&node_id);
523485
} else {
@@ -540,7 +502,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
540502
coldstart = true; // this can go away in the API.
541503
proxy_stat rv = proxy_init_hsm(&bip32_key_version, chainparams,
542504
coldstart, use_hsm_secret,
543-
&node_id, &pubstuff.bip32);
505+
&node_id);
544506
if (PROXY_PERMANENT(rv)) {
545507
status_failed(STATUS_FAIL_INTERNAL_ERROR,
546508
"proxy_%s failed: %s", __FUNCTION__,
@@ -554,13 +516,28 @@ static struct io_plan *init_hsm(struct io_conn *conn,
554516
proxy_last_message());
555517
}
556518

557-
558-
// TODO - add support for bolt12
559-
workaround_init_bolt12(&hsm_secret, &bolt12);
560-
561519
/* Mark this node as already inited. */
562-
persist_node_id(&node_id, &pubstuff.bip32, &bolt12);
520+
persist_node_id(&node_id);
521+
}
522+
523+
// Fetch the bip32 ext_pub_key.
524+
proxy_stat rv = proxy_get_ext_pub_key(&pubstuff.bip32);
525+
if (PROXY_PERMANENT(rv)) {
526+
status_failed(STATUS_FAIL_INTERNAL_ERROR,
527+
"proxy_%s failed: %s", __FUNCTION__,
528+
proxy_last_message());
529+
}
530+
else if (!PROXY_SUCCESS(rv)) {
531+
status_unusual("proxy_%s failed: %s", __FUNCTION__,
532+
proxy_last_message());
533+
return bad_req_fmt(conn, c, msg_in,
534+
"proxy_%s error: %s", __FUNCTION__,
535+
proxy_last_message());
563536
}
537+
538+
// TODO - add support for bolt12
539+
bogus_bolt12_placeholder(&bolt12);
540+
564541
/* Now we can consider ourselves initialized, and we won't get
565542
* upset if we get a non-init message. */
566543
initialized = true;

contrib/remote_hsmd/proxy.cc

Lines changed: 61 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,7 @@ proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version,
335335
struct chainparams const *chainparams,
336336
bool coldstart,
337337
struct secret *hsm_secret,
338-
struct node_id *o_node_id,
339-
struct ext_key *o_ext_pubkey)
338+
struct node_id *o_node_id)
340339
{
341340
STATUS_DEBUG(
342341
"%s:%d %s { \"hsm_secret\":%s, \"coldstart\":%s }",
@@ -345,69 +344,68 @@ proxy_stat proxy_init_hsm(struct bip32_key_version *bip32_key_version,
345344
coldstart ? "true" : "false"
346345
);
347346

348-
/* First we make the Init call to create the Node. */
349-
{
350-
last_message = "";
351-
InitRequest req;
352-
353-
auto nc = req.mutable_node_config();
354-
nc->set_key_derivation_style(NodeConfig::NATIVE);
355-
356-
auto cp = req.mutable_chainparams();
357-
cp->set_network_name(chainparams->network_name);
358-
359-
req.set_coldstart(coldstart);
360-
361-
// If we are running integration tests the secret will be forced.
362-
if (hsm_secret != NULL)
363-
marshal_bip32seed(hsm_secret, req.mutable_hsm_secret());
364-
365-
ClientContext context;
366-
InitReply rsp;
367-
Status status = stub->Init(&context, req, &rsp);
368-
if (status.ok()) {
369-
unmarshal_node_id(rsp.node_id(), o_node_id);
370-
unmarshal_node_id(rsp.node_id(), &self_id);
371-
STATUS_DEBUG("%s:%d %s { \"node_id\":%s }",
372-
__FILE__, __LINE__, __FUNCTION__,
373-
dump_node_id(o_node_id).c_str());
374-
last_message = "success";
375-
// Fall-through to the next part. */
376-
} else {
377-
status_unusual("%s:%d %s: %s",
378-
__FILE__, __LINE__, __FUNCTION__,
379-
status.error_message().c_str());
380-
last_message = status.error_message();
381-
return map_status(status);
382-
}
347+
last_message = "";
348+
InitRequest req;
349+
350+
auto nc = req.mutable_node_config();
351+
nc->set_key_derivation_style(NodeConfig::NATIVE);
352+
353+
auto cp = req.mutable_chainparams();
354+
cp->set_network_name(chainparams->network_name);
355+
356+
req.set_coldstart(coldstart);
357+
358+
// If we are running integration tests the secret will be forced.
359+
if (hsm_secret != NULL)
360+
marshal_bip32seed(hsm_secret, req.mutable_hsm_secret());
361+
362+
ClientContext context;
363+
InitReply rsp;
364+
Status status = stub->Init(&context, req, &rsp);
365+
if (status.ok()) {
366+
unmarshal_node_id(rsp.node_id(), o_node_id);
367+
unmarshal_node_id(rsp.node_id(), &self_id);
368+
STATUS_DEBUG("%s:%d %s { \"node_id\":%s }",
369+
__FILE__, __LINE__, __FUNCTION__,
370+
dump_node_id(o_node_id).c_str());
371+
last_message = "success";
372+
return PROXY_OK;
373+
} else {
374+
status_unusual("%s:%d %s: %s",
375+
__FILE__, __LINE__, __FUNCTION__,
376+
status.error_message().c_str());
377+
last_message = status.error_message();
378+
return map_status(status);
383379
}
380+
}
384381

385-
/* Next we make the GetExtPubKey call to fetch the XPUB. */
386-
{
387-
last_message = "";
388-
GetExtPubKeyRequest req;
389-
390-
marshal_node_id(&self_id, req.mutable_node_id());
391-
392-
ClientContext context;
393-
GetExtPubKeyReply rsp;
394-
Status status = stub->GetExtPubKey(&context, req, &rsp);
395-
if (status.ok()) {
396-
unmarshal_ext_pubkey(rsp.xpub(), o_ext_pubkey);
397-
STATUS_DEBUG("%s:%d %s "
398-
"{ \"node_id\":%s, \"ext_pubkey\":%s }",
399-
__FILE__, __LINE__, __FUNCTION__,
400-
dump_node_id(&self_id).c_str(),
401-
dump_ext_pubkey(o_ext_pubkey).c_str());
402-
last_message = "success";
403-
return PROXY_OK;
404-
} else {
405-
status_unusual("%s:%d %s: %s",
406-
__FILE__, __LINE__, __FUNCTION__,
407-
status.error_message().c_str());
408-
last_message = status.error_message();
409-
return map_status(status);
410-
}
382+
proxy_stat proxy_get_ext_pub_key(struct ext_key *o_ext_pubkey)
383+
{
384+
// TODO
385+
STATUS_DEBUG("%s:%d %s", __FILE__, __LINE__, __FUNCTION__);
386+
387+
last_message = "";
388+
GetExtPubKeyRequest req;
389+
390+
marshal_node_id(&self_id, req.mutable_node_id());
391+
392+
ClientContext context;
393+
GetExtPubKeyReply rsp;
394+
Status status = stub->GetExtPubKey(&context, req, &rsp);
395+
if (status.ok()) {
396+
unmarshal_ext_pubkey(rsp.xpub(), o_ext_pubkey);
397+
STATUS_DEBUG("%s:%d %s "
398+
"{ \"ext_pubkey\":%s }",
399+
__FILE__, __LINE__, __FUNCTION__,
400+
dump_ext_pubkey(o_ext_pubkey).c_str());
401+
last_message = "success";
402+
return PROXY_OK;
403+
} else {
404+
status_unusual("%s:%d %s: %s",
405+
__FILE__, __LINE__, __FUNCTION__,
406+
status.error_message().c_str());
407+
last_message = status.error_message();
408+
return map_status(status);
411409
}
412410
}
413411

contrib/remote_hsmd/proxy.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ proxy_stat proxy_init_hsm(
4444
struct chainparams const *chainparams,
4545
bool coldstart,
4646
struct secret *hsm_secret,
47-
struct node_id *o_node_id,
48-
struct ext_key *o_ext_pub_key);
47+
struct node_id *o_node_id);
48+
49+
proxy_stat proxy_get_ext_pub_key(struct ext_key *o_ext_pub_key);
4950

5051
proxy_stat proxy_handle_ecdh(
5152
const struct pubkey *point,

0 commit comments

Comments
 (0)