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>
2324#include <ccan/noerr/noerr.h>
2425#include <ccan/ptrint/ptrint.h>
2526#include <ccan/read_write_all/read_write_all.h>
27+ #include <ccan/str/hex/hex.h>
2628#include <ccan/take/take.h>
29+ #include <ccan/tal/grab_file/grab_file.h>
2730#include <ccan/tal/str/str.h>
2831#include <common/daemon_conn.h>
2932#include <common/derive_basepoints.h>
3033#include <common/hash_u5.h>
34+ #include <common/json.h>
35+ #include <common/json_helpers.h>
3136#include <common/key_derive.h>
3237#include <common/memleak.h>
3338#include <common/node_id.h>
@@ -391,6 +396,72 @@ static void workaround_init_bolt12(const struct secret *hsm_secret, struct pubke
391396 "Could derive bolt12 public key." );
392397}
393398
399+ static void persist_node_id (const struct node_id * node_id ,
400+ const struct ext_key * bip32 ,
401+ const struct pubkey32 * bolt12 )
402+ {
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+
422+ int fd = open ("NODE_ID" , O_WRONLY |O_TRUNC |O_CREAT , 0666 );
423+ assert (fd != -1 );
424+ write_all (fd , p , len );
425+ json_out_consume (jout , len );
426+ close (fd );
427+ }
428+
429+ static bool restore_node_id (struct node_id * node_id ,
430+ struct ext_key * bip32 ,
431+ struct pubkey32 * bolt12 )
432+ {
433+ if (access ("NODE_ID" , F_OK ) == -1 ) {
434+ // This is a cold start, we don't have this yet.
435+ return false;
436+ }
437+
438+ // This is a warmstart, initialize our node_id.
439+ 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+
462+ return true;
463+ }
464+
394465/*~ This is the response to lightningd's HSM_INIT request, which is the first
395466 * thing it sends. */
396467static struct io_plan * init_hsm (struct io_conn * conn ,
@@ -405,6 +476,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
405476 struct sha256 * force_channel_secrets_shaseed ;
406477 struct secret * hsm_encryption_key ;
407478 struct secret hsm_secret ;
479+ struct secret * use_hsm_secret ;
408480 bool coldstart ;
409481
410482 /* This must be lightningd. */
@@ -444,41 +516,51 @@ static struct io_plan *init_hsm(struct io_conn *conn,
444516 * will use */
445517 c -> chainparams = chainparams ;
446518
447- /* To support integration tests we honor any seed provided
448- * in the hsm_secret file (testnet only). Otherwise we
449- * generate a random seed.
450- */
451- if (!read_test_seed (& hsm_secret )) {
452- randombytes_buf (& hsm_secret , sizeof (hsm_secret ));
453- }
454-
455519 /* Is this a warm start (restart) or a cold start (first time)? */
456- coldstart = access ("WARM" , F_OK ) == -1 ;
457-
458- proxy_stat rv = proxy_init_hsm (& bip32_key_version , chainparams ,
459- coldstart , & hsm_secret ,
460- & node_id , & pubstuff .bip32 );
461- if (PROXY_PERMANENT (rv )) {
462- status_failed (STATUS_FAIL_INTERNAL_ERROR ,
463- "proxy_%s failed: %s" , __FUNCTION__ ,
464- proxy_last_message ());
465- }
466- else if (!PROXY_SUCCESS (rv )) {
467- status_unusual ("proxy_%s failed: %s" , __FUNCTION__ ,
468- proxy_last_message ());
469- return bad_req_fmt (conn , c , msg_in ,
470- "proxy_%s error: %s" , __FUNCTION__ ,
471- proxy_last_message ());
472- }
520+ if (restore_node_id (& node_id , & pubstuff .bip32 , & bolt12 )) {
521+ // This is a warm start.
522+ proxy_set_node_id (& node_id );
523+ } else {
524+ status_unusual ("cold start, initializing the remote signer" );
525+
526+ // This is a cold start, initialize the remote signer.
527+
528+ /* To support integration tests we honor any seed provided
529+ * in the hsm_secret file (testnet only). Otherwise we
530+ * generate a random seed.
531+ */
532+ if (read_test_seed (& hsm_secret )) {
533+ // We are running integration tests and the secret has been forced.
534+ use_hsm_secret = & hsm_secret ;
535+ } else {
536+ // We are not running integration tests, remote signer generates.
537+ use_hsm_secret = NULL ;
538+ }
539+
540+ coldstart = true; // this can go away in the API.
541+ proxy_stat rv = proxy_init_hsm (& bip32_key_version , chainparams ,
542+ coldstart , use_hsm_secret ,
543+ & node_id , & pubstuff .bip32 );
544+ if (PROXY_PERMANENT (rv )) {
545+ status_failed (STATUS_FAIL_INTERNAL_ERROR ,
546+ "proxy_%s failed: %s" , __FUNCTION__ ,
547+ proxy_last_message ());
548+ }
549+ else if (!PROXY_SUCCESS (rv )) {
550+ status_unusual ("proxy_%s failed: %s" , __FUNCTION__ ,
551+ proxy_last_message ());
552+ return bad_req_fmt (conn , c , msg_in ,
553+ "proxy_%s error: %s" , __FUNCTION__ ,
554+ proxy_last_message ());
555+ }
473556
474- /* Mark this node as already inited. */
475- int fd = open ("WARM" , O_WRONLY |O_TRUNC |O_CREAT , 0666 );
476- assert (fd != -1 );
477- close (fd );
478557
479- // TODO - add support for bolt12
480- workaround_init_bolt12 (& hsm_secret , & bolt12 );
558+ // TODO - add support for bolt12
559+ workaround_init_bolt12 (& hsm_secret , & bolt12 );
481560
561+ /* Mark this node as already inited. */
562+ persist_node_id (& node_id , & pubstuff .bip32 , & bolt12 );
563+ }
482564 /* Now we can consider ourselves initialized, and we won't get
483565 * upset if we get a non-init message. */
484566 initialized = true;
0 commit comments