From 7f406ea80d795da60af4ad367f09185fae824b55 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 10 Mar 2017 21:19:43 +1030 Subject: [PATCH] lightningd/hsm: convert to subd. Signed-off-by: Rusty Russell --- lightningd/hsm/Makefile | 23 +++------- lightningd/hsm/hsm.c | 70 ++++++++++++++++------------- lightningd/hsm/hsm_control_wire_csv | 32 ------------- lightningd/hsm/hsm_status_wire_csv | 12 ----- lightningd/hsm/hsm_wire.csv | 47 +++++++++++++++++++ lightningd/hsm_control.c | 54 +++++++++++----------- lightningd/lightningd.h | 2 +- lightningd/peer_control.c | 33 +++++++------- 8 files changed, 140 insertions(+), 133 deletions(-) delete mode 100644 lightningd/hsm/hsm_control_wire_csv delete mode 100644 lightningd/hsm/hsm_status_wire_csv create mode 100644 lightningd/hsm/hsm_wire.csv diff --git a/lightningd/hsm/Makefile b/lightningd/hsm/Makefile index f5ed9c0b9..c142a25ec 100644 --- a/lightningd/hsm/Makefile +++ b/lightningd/hsm/Makefile @@ -12,16 +12,13 @@ LIGHTNINGD_HSM_CLIENT_SRC := lightningd/hsm/client.c lightningd/hsm/gen_hsm_clie LIGHTNINGD_HSM_CLIENT_OBJS := $(LIGHTNINGD_HSM_CLIENT_SRC:.c=.o) # Control daemon uses this: -LIGHTNINGD_HSM_CONTROL_HEADERS := lightningd/hsm/gen_hsm_control_wire.h \ - lightningd/hsm/gen_hsm_status_wire.h -LIGHTNINGD_HSM_CONTROL_SRC := lightningd/hsm/gen_hsm_control_wire.c \ - lightningd/hsm/gen_hsm_status_wire.c +LIGHTNINGD_HSM_CONTROL_HEADERS := lightningd/hsm/gen_hsm_wire.h +LIGHTNINGD_HSM_CONTROL_SRC := lightningd/hsm/gen_hsm_wire.c LIGHTNINGD_HSM_CONTROL_OBJS := $(LIGHTNINGD_HSM_CONTROL_SRC:.c=.o) # lightningd/hsm needs these: LIGHTNINGD_HSM_HEADERS := lightningd/hsm/gen_hsm_client_wire.h \ - lightningd/hsm/gen_hsm_control_wire.h \ - lightningd/hsm/gen_hsm_status_wire.h + lightningd/hsm/gen_hsm_wire.h LIGHTNINGD_HSM_SRC := lightningd/hsm/hsm.c \ $(LIGHTNINGD_HSM_HEADERS:.h=.c) LIGHTNINGD_HSM_OBJS := $(LIGHTNINGD_HSM_SRC:.c=.o) @@ -50,17 +47,11 @@ lightningd/hsm/gen_hsm_client_wire.h: $(WIRE_GEN) lightningd/hsm/hsm_client_wire lightningd/hsm/gen_hsm_client_wire.c: $(WIRE_GEN) lightningd/hsm/hsm_client_wire_csv $(WIRE_GEN) ${@:.c=.h} hsm_client_wire_type< lightningd/hsm/hsm_client_wire_csv > $@ -lightningd/hsm/gen_hsm_control_wire.h: $(WIRE_GEN) lightningd/hsm/hsm_control_wire_csv - $(WIRE_GEN) --header $@ hsm_control_wire_type < lightningd/hsm/hsm_control_wire_csv > $@ +lightningd/hsm/gen_hsm_wire.h: $(WIRE_GEN) lightningd/hsm/hsm_wire.csv + $(WIRE_GEN) --header $@ hsm_wire_type < lightningd/hsm/hsm_wire.csv > $@ -lightningd/hsm/gen_hsm_control_wire.c: $(WIRE_GEN) lightningd/hsm/hsm_control_wire_csv - $(WIRE_GEN) ${@:.c=.h} hsm_control_wire_type < lightningd/hsm/hsm_control_wire_csv > $@ - -lightningd/hsm/gen_hsm_status_wire.h: $(WIRE_GEN) lightningd/hsm/hsm_status_wire_csv - $(WIRE_GEN) --header $@ hsm_status_wire_type < lightningd/hsm/hsm_status_wire_csv > $@ - -lightningd/hsm/gen_hsm_status_wire.c: $(WIRE_GEN) lightningd/hsm/hsm_status_wire_csv - $(WIRE_GEN) ${@:.c=.h} hsm_status_wire_type < lightningd/hsm/hsm_status_wire_csv > $@ +lightningd/hsm/gen_hsm_wire.c: $(WIRE_GEN) lightningd/hsm/hsm_wire.csv + $(WIRE_GEN) ${@:.c=.h} hsm_wire_type < lightningd/hsm/hsm_wire.csv > $@ check-source: $(LIGHTNINGD_HSM_ALLSRC_NOGEN:%=check-src-include-order/%) $(LIGHTNINGD_HSM_ALLHEADERS_NOGEN:%=check-hdr-include-order/%) check-source-bolt: $(LIGHTNINGD_HSM_SRC:%=bolt-check/%) $(LIGHTNINGD_HSM_HEADERS:%=bolt-check/%) diff --git a/lightningd/hsm/hsm.c b/lightningd/hsm/hsm.c index 3136aaa43..fdf88f110 100644 --- a/lightningd/hsm/hsm.c +++ b/lightningd/hsm/hsm.c @@ -18,8 +18,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -155,8 +154,8 @@ static u8 *init_response(struct conn_info *control) status_failed(WIRE_HSMSTATUS_KEY_FAILED, "Can't serialize bip32 public key"); - msg = towire_hsmctl_init_response(control, &node_id, &peer_seed, - serialized_extkey); + msg = towire_hsmctl_init_reply(control, &node_id, &peer_seed, + serialized_extkey); tal_free(serialized_extkey); return msg; } @@ -252,7 +251,7 @@ static void bitcoin_keypair(struct privkey *privkey, "BIP32 pubkey %u create failed", index); } -static u8 *create_new_hsm(struct conn_info *control) +static void create_new_hsm(struct conn_info *control) { int fd = open("hsm_secret", O_CREAT|O_EXCL|O_WRONLY, 0400); if (fd < 0) @@ -284,11 +283,9 @@ static u8 *create_new_hsm(struct conn_info *control) close(fd); populate_secretstuff(); - - return init_response(control); } -static u8 *load_hsm(struct conn_info *control) +static void load_hsm(struct conn_info *control) { int fd = open("hsm_secret", O_RDONLY); if (fd < 0) @@ -300,6 +297,19 @@ static u8 *load_hsm(struct conn_info *control) close(fd); populate_secretstuff(); +} + +static u8 *init_hsm(struct conn_info *control, const u8 *msg) +{ + bool new; + + if (!fromwire_hsmctl_init(msg, NULL, &new)) + status_failed(WIRE_HSMSTATUS_BAD_REQUEST, "hsmctl_init: %s", + tal_hex(msg, msg)); + if (new) + create_new_hsm(control); + else + load_hsm(control); return init_response(control); } @@ -349,7 +359,7 @@ static u8 *pass_hsmfd_ecdh(struct io_conn *conn, io_new_conn(control, fds[0], ecdh_client, c); *fd_to_pass = fds[1]; - return towire_hsmctl_hsmfd_fd_response(control); + return towire_hsmctl_hsmfd_ecdh_fd_reply(control); } /* Note that it's the main daemon that asks for the funding signature so it @@ -408,7 +418,7 @@ static u8 *sign_funding_tx(const tal_t *ctx, const u8 *data) &inprivkey, &inkey, &sig[i]); } - msg_out = towire_hsmctl_sign_funding_response(ctx, sig); + msg_out = towire_hsmctl_sign_funding_reply(ctx, sig); tal_free(tmpctx); return msg_out; } @@ -416,17 +426,14 @@ static u8 *sign_funding_tx(const tal_t *ctx, const u8 *data) static struct io_plan *control_received_req(struct io_conn *conn, struct conn_info *control) { - enum hsm_control_wire_type t = fromwire_peektype(control->in); + enum hsm_wire_type t = fromwire_peektype(control->in); status_trace("Control: type %s len %zu", - hsm_control_wire_type_name(t), tal_count(control->in)); + hsm_wire_type_name(t), tal_count(control->in)); switch (t) { - case WIRE_HSMCTL_INIT_NEW: - control->out = create_new_hsm(control); - goto send_out; - case WIRE_HSMCTL_INIT_LOAD: - control->out = load_hsm(control); + case WIRE_HSMCTL_INIT: + control->out = init_hsm(control, control->in); goto send_out; case WIRE_HSMCTL_HSMFD_ECDH: control->out = pass_hsmfd_ecdh(conn, control, control->in, @@ -436,9 +443,15 @@ static struct io_plan *control_received_req(struct io_conn *conn, control->out = sign_funding_tx(control, control->in); goto send_out; - case WIRE_HSMCTL_INIT_RESPONSE: - case WIRE_HSMCTL_HSMFD_FD_RESPONSE: - case WIRE_HSMCTL_SIGN_FUNDING_RESPONSE: + case WIRE_HSMCTL_INIT_REPLY: + case WIRE_HSMCTL_HSMFD_ECDH_FD_REPLY: + case WIRE_HSMCTL_SIGN_FUNDING_REPLY: + case WIRE_HSMSTATUS_INIT_FAILED: + case WIRE_HSMSTATUS_WRITEMSG_FAILED: + case WIRE_HSMSTATUS_BAD_REQUEST: + case WIRE_HSMSTATUS_FD_FAILED: + case WIRE_HSMSTATUS_KEY_FAILED: + case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: break; } @@ -458,16 +471,11 @@ static struct io_plan *control_init(struct io_conn *conn, return recv_req(conn, control); } -/* Exit when control fd closes. */ -static void control_finish(struct io_conn *conn, struct conn_info *control) -{ - io_break(control); -} - #ifndef TESTING int main(int argc, char *argv[]) { struct conn_info *control; + struct io_conn *conn; if (argc == 2 && streq(argv[1], "--version")) { printf("%s\n", version()); @@ -481,15 +489,13 @@ int main(int argc, char *argv[]) control = tal(NULL, struct conn_info); conn_info_init(control, control_received_req); - /* Stdout == status, stdin == requests */ - status_setup(STDOUT_FILENO); + status_setup(STDIN_FILENO); - io_set_finish(io_new_conn(control, STDIN_FILENO, control_init, control), - control_finish, control); + conn = io_new_conn(NULL, STDIN_FILENO, control_init, control); + /* When conn closes, everything is freed. */ + tal_steal(conn, control); io_loop(NULL, NULL); - - tal_free(control); return 0; } #endif diff --git a/lightningd/hsm/hsm_control_wire_csv b/lightningd/hsm/hsm_control_wire_csv deleted file mode 100644 index 4f5c159a9..000000000 --- a/lightningd/hsm/hsm_control_wire_csv +++ /dev/null @@ -1,32 +0,0 @@ -# These both respond with init_response -hsmctl_init_new,1 -hsmctl_init_load,2 - -hsmctl_init_response,100 -hsmctl_init_response,0,node_id,33 -hsmctl_init_response,33,peer_seed,32,struct privkey -hsmctl_init_response,65,bip32_len,2 -hsmctl_init_response,67,bip32_seed,bip32_len*1,u8 - -# ECDH returns an fd. -hsmctl_hsmfd_ecdh,3 -hsmctl_hsmfd_ecdh,0,unique_id,8 - -# Return signature for a funding tx. -#include -# FIXME: This should also take their commit sig & details, to verify. -hsmctl_sign_funding,4 -hsmctl_sign_funding,0,satoshi_out,8 -hsmctl_sign_funding,8,change_out,8 -hsmctl_sign_funding,16,change_keyindex,4 -hsmctl_sign_funding,20,our_pubkey,33 -hsmctl_sign_funding,52,their_pubkey,33 -hsmctl_sign_funding,85,num_inputs,2 -hsmctl_sign_funding,87,inputs,num_inputs*49,struct utxo - -hsmctl_sign_funding_response,104 -hsmctl_sign_funding_response,0,num_sigs,2 -hsmctl_sign_funding_response,0,sig,num_sigs*64,secp256k1_ecdsa_signature - -# No message, just an fd. -hsmctl_hsmfd_fd_response,103 diff --git a/lightningd/hsm/hsm_status_wire_csv b/lightningd/hsm/hsm_status_wire_csv deleted file mode 100644 index 9636af65f..000000000 --- a/lightningd/hsm/hsm_status_wire_csv +++ /dev/null @@ -1,12 +0,0 @@ -# These are fatal. -hsmstatus_init_failed,0x8000 -hsmstatus_writemsg_failed,0x8001 -hsmstatus_bad_request,0x8002 -hsmstatus_fd_failed,0x8003 -hsmstatus_key_failed,0x8004 - -# Clients should not give a bad request but not the HSM's decision to crash. -hsmstatus_client_bad_request,1 -hsmstatus_client_bad_request,0,unique-id,8 -hsmstatus_client_bad_request,8,len,2 -hsmstatus_client_bad_request,10,msg,len,u8 diff --git a/lightningd/hsm/hsm_wire.csv b/lightningd/hsm/hsm_wire.csv new file mode 100644 index 000000000..be25d8e6b --- /dev/null +++ b/lightningd/hsm/hsm_wire.csv @@ -0,0 +1,47 @@ +# These are fatal. +hsmstatus_init_failed,0x8000 +hsmstatus_writemsg_failed,0x8001 +hsmstatus_bad_request,0x8002 +hsmstatus_fd_failed,0x8003 +hsmstatus_key_failed,0x8004 + +# Clients should not give a bad request but not the HSM's decision to crash. +hsmstatus_client_bad_request,1000 +hsmstatus_client_bad_request,0,unique-id,8 +hsmstatus_client_bad_request,8,len,2 +hsmstatus_client_bad_request,10,msg,len,u8 + +# Start the HSM. +hsmctl_init,1 +hsmctl_init,0,new,1,bool + +hsmctl_init_reply,101 +hsmctl_init_reply,0,node_id,33 +hsmctl_init_reply,33,peer_seed,32,struct privkey +hsmctl_init_reply,65,bip32_len,2 +hsmctl_init_reply,67,bip32_seed,bip32_len*1,u8 + +# ECDH returns an fd. +hsmctl_hsmfd_ecdh,3 +hsmctl_hsmfd_ecdh,0,unique_id,8 + +# No contents, just an fd. +hsmctl_hsmfd_ecdh_fd_reply,103 + +# Return signature for a funding tx. +#include +# FIXME: This should also take their commit sig & details, to verify. +hsmctl_sign_funding,4 +hsmctl_sign_funding,0,satoshi_out,8 +hsmctl_sign_funding,8,change_out,8 +hsmctl_sign_funding,16,change_keyindex,4 +hsmctl_sign_funding,20,our_pubkey,33 +hsmctl_sign_funding,52,their_pubkey,33 +hsmctl_sign_funding,85,num_inputs,2 +hsmctl_sign_funding,87,inputs,num_inputs*49,struct utxo + +hsmctl_sign_funding_reply,104 +hsmctl_sign_funding_reply,0,num_sigs,2 +hsmctl_sign_funding_reply,0,sig,num_sigs*64,secp256k1_ecdsa_signature + + diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index a6e62dff9..6a3144859 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -1,25 +1,24 @@ #include "hsm_control.h" #include "lightningd.h" #include "peer_control.h" -#include "subdaemon.h" +#include "subd.h" #include #include #include #include #include -#include -#include +#include #include -static void hsm_init_done(struct subdaemon *hsm, const u8 *msg, +static bool hsm_init_done(struct subd *hsm, const u8 *msg, struct lightningd *ld) { u8 *serialized_extkey; - if (!fromwire_hsmctl_init_response(hsm, msg, NULL, &ld->dstate.id, - &ld->peer_seed, - &serialized_extkey)) - errx(1, "HSM did not give init response"); + if (!fromwire_hsmctl_init_reply(hsm, msg, NULL, &ld->dstate.id, + &ld->peer_seed, + &serialized_extkey)) + errx(1, "HSM did not give init reply"); log_info_struct(ld->log, "Our ID: %s", struct pubkey, &ld->dstate.id); ld->bip32_base = tal(ld, struct ext_key); @@ -28,9 +27,10 @@ static void hsm_init_done(struct subdaemon *hsm, const u8 *msg, errx(1, "HSM did not give unserializable BIP32 extkey"); io_break(ld->hsm); + return true; } -static void hsm_finished(struct subdaemon *hsm, int status) +static void hsm_finished(struct subd *hsm, int status) { if (WIFEXITED(status)) errx(1, "HSM failed (exit status %i), exiting.", @@ -38,10 +38,9 @@ static void hsm_finished(struct subdaemon *hsm, int status) errx(1, "HSM failed (signal %u), exiting.", WTERMSIG(status)); } -static enum subdaemon_status hsm_status(struct subdaemon *hsm, const u8 *msg, - int fd) +static enum subd_msg_ret hsm_msg(struct subd *hsm, const u8 *msg, int fd) { - enum hsm_status_wire_type t = fromwire_peektype(msg); + enum hsm_wire_type t = fromwire_peektype(msg); u8 *badmsg; struct peer *peer; u64 id; @@ -68,33 +67,38 @@ static enum subdaemon_status hsm_status(struct subdaemon *hsm, const u8 *msg, case WIRE_HSMSTATUS_BAD_REQUEST: case WIRE_HSMSTATUS_FD_FAILED: case WIRE_HSMSTATUS_KEY_FAILED: - break; + + /* HSM doesn't send these */ + case WIRE_HSMCTL_INIT: + case WIRE_HSMCTL_HSMFD_ECDH: + case WIRE_HSMCTL_SIGN_FUNDING: + + /* Replies should be paired to individual requests. */ + case WIRE_HSMCTL_INIT_REPLY: + case WIRE_HSMCTL_HSMFD_ECDH_FD_REPLY: + case WIRE_HSMCTL_SIGN_FUNDING_REPLY: + errx(1, "HSM gave invalid message %s", hsm_wire_type_name(t)); } - return STATUS_COMPLETE; + return SUBD_COMPLETE; } void hsm_init(struct lightningd *ld, bool newdir) { bool create; - ld->hsm = new_subdaemon(ld, ld, "lightningd_hsm", NULL, - hsm_status_wire_type_name, - hsm_control_wire_type_name, - hsm_status, hsm_finished, -1); + ld->hsm = new_subd(ld, ld, "lightningd_hsm", NULL, + hsm_wire_type_name, + hsm_msg, hsm_finished, -1); if (!ld->hsm) - err(1, "Could not subdaemon hsm"); + err(1, "Could not subd hsm"); if (newdir) create = true; else create = (access("hsm_secret", F_OK) != 0); - if (create) - subdaemon_req(ld->hsm, take(towire_hsmctl_init_new(ld->hsm)), - -1, NULL, hsm_init_done, ld); - else - subdaemon_req(ld->hsm, take(towire_hsmctl_init_load(ld->hsm)), - -1, NULL, hsm_init_done, ld); + subd_req(ld->hsm, take(towire_hsmctl_init(ld->hsm, create)), + -1, NULL, hsm_init_done, ld); if (io_loop(NULL, NULL) != ld->hsm) errx(1, "Unexpected io exit during HSM startup"); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 772686a95..15a261fb0 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -24,7 +24,7 @@ struct lightningd { struct log *log; /* Bearer of all my secrets. */ - struct subdaemon *hsm; + struct subd *hsm; /* Daemon looking after peers during init / before channel. */ struct subdaemon *gossip; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 963963ec0..f5bb58771 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1,5 +1,6 @@ #include "lightningd.h" #include "peer_control.h" +#include "subd.h" #include "subdaemon.h" #include #include @@ -22,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -156,12 +157,12 @@ err: tal_free(peer); } -static void peer_got_handshake_hsmfd(struct subdaemon *hsm, const u8 *msg, +static bool peer_got_handshake_hsmfd(struct subd *hsm, const u8 *msg, struct peer *peer) { const u8 *req; - if (!fromwire_hsmctl_hsmfd_fd_response(msg, NULL)) { + if (!fromwire_hsmctl_hsmfd_ecdh_fd_reply(msg, NULL)) { log_unusual(peer->ld->log, "Malformed hsmfd response: %s", tal_hex(peer, msg)); goto error; @@ -197,10 +198,11 @@ static void peer_got_handshake_hsmfd(struct subdaemon *hsm, const u8 *msg, * back on success */ subdaemon_req(peer->owner, take(req), -1, &peer->fd, handshake_succeeded, peer); - return; + return true; error: tal_free(peer); + return true; } /* FIXME: timeout handshake if taking too long? */ @@ -212,9 +214,9 @@ static struct io_plan *peer_in(struct io_conn *conn, struct lightningd *ld) return io_close(conn); /* Get HSM fd for this peer. */ - subdaemon_req(ld->hsm, - take(towire_hsmctl_hsmfd_ecdh(ld, peer->unique_id)), - -1, &peer->hsmfd, peer_got_handshake_hsmfd, peer); + subd_req(ld->hsm, + take(towire_hsmctl_hsmfd_ecdh(ld, peer->unique_id)), + -1, &peer->hsmfd, peer_got_handshake_hsmfd, peer); /* We don't need conn, we'll pass fd to handshaked. */ return io_close_taken_fd(conn); @@ -343,9 +345,9 @@ static struct io_plan *peer_out(struct io_conn *conn, peer->id = tal_dup(peer, struct pubkey, &jc->id); /* Get HSM fd for this peer. */ - subdaemon_req(ld->hsm, - take(towire_hsmctl_hsmfd_ecdh(ld, peer->unique_id)), - -1, &peer->hsmfd, peer_got_handshake_hsmfd, peer); + subd_req(ld->hsm, + take(towire_hsmctl_hsmfd_ecdh(ld, peer->unique_id)), + -1, &peer->hsmfd, peer_got_handshake_hsmfd, peer); /* We don't need conn, we'll pass fd to handshaked. */ return io_close_taken_fd(conn); @@ -555,15 +557,15 @@ static enum watch_result funding_depth_cb(struct peer *peer, return DELETE_WATCH; } -static void opening_got_hsm_funding_sig(struct subdaemon *hsm, const u8 *resp, +static bool opening_got_hsm_funding_sig(struct subd *hsm, const u8 *resp, struct funding_channel *fc) { secp256k1_ecdsa_signature *sigs; struct bitcoin_tx *tx = fc->funding_tx; size_t i; - if (!fromwire_hsmctl_sign_funding_response(fc, resp, NULL, &sigs)) - fatal("HSM gave bad sign_funding_response %s", + if (!fromwire_hsmctl_sign_funding_reply(fc, resp, NULL, &sigs)) + fatal("HSM gave bad sign_funding_reply %s", tal_hex(fc, resp)); if (tal_count(sigs) != tal_count(tx->input)) @@ -595,6 +597,7 @@ static void opening_got_hsm_funding_sig(struct subdaemon *hsm, const u8 *resp, watch_tx(fc->peer, fc->peer->ld->topology, fc->peer, tx, funding_depth_cb, NULL); tal_free(fc); + return true; } static enum subdaemon_status update_channel_status(struct subdaemon *sd, @@ -715,8 +718,8 @@ static void opening_release_tx(struct subdaemon *opening, const u8 *resp, &fc->remote_fundingkey, utxos); tal_free(utxos); - subdaemon_req(fc->peer->ld->hsm, take(msg), -1, NULL, - opening_got_hsm_funding_sig, fc); + subd_req(fc->peer->ld->hsm, take(msg), -1, NULL, + opening_got_hsm_funding_sig, fc); /* Start normal channel daemon. */ peer_start_channeld(fc->peer, true,