diff --git a/hsmd/capabilities.h b/hsmd/capabilities.h index aebd607be..565356b40 100644 --- a/hsmd/capabilities.h +++ b/hsmd/capabilities.h @@ -5,6 +5,7 @@ #define HSM_CAP_SIGN_GOSSIP 2 #define HSM_CAP_SIGN_ONCHAIN_TX 4 #define HSM_CAP_COMMITMENT_POINT 8 +#define HSM_CAP_SIGN_REMOTE_TX 16 #define HSM_CAP_MASTER 1024 #endif /* LIGHTNING_HSMD_CAPABILITIES_H */ diff --git a/hsmd/hsm.c b/hsmd/hsm.c index d3a53a87b..214c5b8cd 100644 --- a/hsmd/hsm.c +++ b/hsmd/hsm.c @@ -337,6 +337,43 @@ static PRINTF_FMT(3,4) return io_close(conn); } +/* FIXME: make sure it meets some criteria? */ +static struct io_plan *handle_sign_remote_commitment_tx(struct io_conn *conn, + struct client *c) +{ + struct daemon_conn *dc = &c->dc; + struct pubkey remote_funding_pubkey, local_funding_pubkey; + u64 funding_amount; + struct secret channel_seed; + struct bitcoin_tx *tx; + secp256k1_ecdsa_signature sig; + struct secrets secrets; + const u8 *funding_wscript; + + if (!fromwire_hsm_sign_remote_commitment_tx(tmpctx, dc->msg_in, + &tx, + &remote_funding_pubkey, + &funding_amount)) + master_badmsg(WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX, dc->msg_in); + + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_basepoints(&channel_seed, + &local_funding_pubkey, NULL, &secrets, NULL); + + funding_wscript = bitcoin_redeem_2of2(tmpctx, + &local_funding_pubkey, + &remote_funding_pubkey); + /* Need input amount for signing */ + tx->input[0].amount = tal_dup(tx->input, u64, &funding_amount); + sign_tx_input(tx, 0, NULL, funding_wscript, + &secrets.funding_privkey, + &local_funding_pubkey, + &sig); + + daemon_conn_send(dc, take(towire_hsm_sign_tx_reply(NULL, &sig))); + return daemon_conn_read_next(conn, dc); +} + /* FIXME: Derive output address for this client, and check it here! */ static struct io_plan *handle_sign_to_us_tx(struct io_conn *conn, struct client *c, @@ -587,6 +624,65 @@ fail: return io_close(conn); } +static struct io_plan *handle_sign_remote_htlc_tx(struct io_conn *conn, + struct client *c) +{ + struct daemon_conn *dc = &c->dc; + struct secret channel_seed; + struct bitcoin_tx *tx; + secp256k1_ecdsa_signature sig; + struct secrets secrets; + struct basepoints basepoints; + struct pubkey remote_per_commit_point; + u64 amount; + u8 *wscript; + struct privkey htlc_privkey; + struct pubkey htlc_pubkey; + + if (!fromwire_hsm_sign_remote_htlc_tx(tmpctx, dc->msg_in, + &tx, &wscript, &amount, + &remote_per_commit_point)) { + status_broken("bad hsm_sign_remote_htlc_tx for client %s", + type_to_string(tmpctx, struct pubkey, &c->id)); + goto fail; + } + + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL); + + if (!derive_simple_privkey(&secrets.htlc_basepoint_secret, + &basepoints.htlc, + &remote_per_commit_point, + &htlc_privkey)) { + status_broken("Failed deriving htlc privkey for client %s", + type_to_string(tmpctx, struct pubkey, &c->id)); + goto fail; + } + + if (!derive_simple_key(&basepoints.htlc, + &remote_per_commit_point, + &htlc_pubkey)) { + status_broken("Failed deriving htlc pubkey for client %s", + type_to_string(tmpctx, struct pubkey, &c->id)); + goto fail; + } + + /* Need input amount for signing */ + tx->input[0].amount = tal_dup(tx->input, u64, &amount); + sign_tx_input(tx, 0, NULL, wscript, &htlc_privkey, &htlc_pubkey, + &sig); + + daemon_conn_send(dc, take(towire_hsm_sign_tx_reply(NULL, &sig))); + return daemon_conn_read_next(conn, dc); + +fail: + daemon_conn_send(c->master, + take(towire_hsmstatus_client_bad_request(NULL, + &c->id, + c->dc.msg_in))); + return io_close(conn); +} + static bool check_client_capabilities(struct client *client, enum hsm_client_wire_type t) { @@ -608,6 +704,10 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_GET_PER_COMMITMENT_POINT: return (client->capabilities & HSM_CAP_COMMITMENT_POINT) != 0; + case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX: + case WIRE_HSM_SIGN_REMOTE_HTLC_TX: + return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0; + case WIRE_HSM_INIT: case WIRE_HSM_CLIENT_HSMFD: case WIRE_HSM_SIGN_FUNDING: @@ -706,6 +806,12 @@ static struct io_plan *handle_client(struct io_conn *conn, case WIRE_HSM_GET_PER_COMMITMENT_POINT: return handle_get_per_commitment_point(conn, c); + case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX: + return handle_sign_remote_commitment_tx(conn, c); + + case WIRE_HSM_SIGN_REMOTE_HTLC_TX: + return handle_sign_remote_htlc_tx(conn, c); + case WIRE_HSM_ECDH_RESP: case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_CUPDATE_SIG_REPLY: diff --git a/hsmd/hsm_client_wire_csv b/hsmd/hsm_client_wire_csv index 5a0350f7e..1de135a12 100644 --- a/hsmd/hsm_client_wire_csv +++ b/hsmd/hsm_client_wire_csv @@ -135,7 +135,21 @@ hsm_sign_local_htlc_tx,,wscript_len,u16 hsm_sign_local_htlc_tx,,wscript,wscript_len*u8 hsm_sign_local_htlc_tx,,input_amount,u64 -# Reply for all the above requests from onchaind. +# Openingd/channeld asks HSM to sign the other sides' commitment tx. +hsm_sign_remote_commitment_tx,19 +hsm_sign_remote_commitment_tx,,tx,struct bitcoin_tx +hsm_sign_remote_commitment_tx,,remote_funding_key,struct pubkey +hsm_sign_remote_commitment_tx,,funding_amount,u64 + +# channeld asks HSM to sign remote HTLC tx. +hsm_sign_remote_htlc_tx,20 +hsm_sign_remote_htlc_tx,,tx,struct bitcoin_tx +hsm_sign_remote_htlc_tx,,len,u16 +hsm_sign_remote_htlc_tx,,wscript,len*u8 +hsm_sign_remote_htlc_tx,,amounts_satoshi,u64 +hsm_sign_remote_htlc_tx,,remote_per_commit_point,struct pubkey + +# Reply for all the above requests. hsm_sign_tx_reply,112 hsm_sign_tx_reply,,sig,secp256k1_ecdsa_signature @@ -146,4 +160,3 @@ hsm_get_per_commitment_point,,n,u64 hsm_get_per_commitment_point_reply,118 hsm_get_per_commitment_point_reply,,per_commitment_point,struct pubkey hsm_get_per_commitment_point_reply,,old_commitment_secret,?struct secret -