diff --git a/hsmd/hsm.c b/hsmd/hsm.c index e42f0fd89..ee22e51b3 100644 --- a/hsmd/hsm.c +++ b/hsmd/hsm.c @@ -277,6 +277,44 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn, return daemon_conn_read_next(conn, dc); } +/* FIXME: Ensure HSM never does this twice for same dbid! */ +static struct io_plan *handle_sign_commitment_tx(struct io_conn *conn, + struct daemon_conn *dc) +{ + struct pubkey peer_id, remote_funding_pubkey, local_funding_pubkey; + u64 dbid, 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_commitment_tx(tmpctx, dc->msg_in, + &peer_id, &dbid, + &tx, + &remote_funding_pubkey, + &funding_amount)) + master_badmsg(WIRE_HSM_SIGN_COMMITMENT_TX, dc->msg_in); + + get_channel_seed(&peer_id, 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_commitment_tx_reply(NULL, &sig))); + return daemon_conn_read_next(conn, dc); +} + static bool check_client_capabilities(struct client *client, enum hsm_client_wire_type t) { @@ -294,6 +332,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_SIGN_FUNDING: case WIRE_HSM_SIGN_WITHDRAWAL: case WIRE_HSM_SIGN_INVOICE: + case WIRE_HSM_SIGN_COMMITMENT_TX: return (client->capabilities & HSM_CAP_MASTER) != 0; /* These are messages sent by the HSM so we should never receive them */ @@ -307,6 +346,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_SIGN_INVOICE_REPLY: case WIRE_HSM_INIT_REPLY: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: + case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY: break; } return false; @@ -365,6 +405,9 @@ static struct io_plan *handle_client(struct io_conn *conn, sign_withdrawal_tx(dc, dc->msg_in); return daemon_conn_read_next(conn, dc); + case WIRE_HSM_SIGN_COMMITMENT_TX: + return handle_sign_commitment_tx(conn, dc); + case WIRE_HSM_ECDH_RESP: case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_CUPDATE_SIG_REPLY: @@ -375,6 +418,7 @@ static struct io_plan *handle_client(struct io_conn *conn, case WIRE_HSM_SIGN_INVOICE_REPLY: case WIRE_HSM_INIT_REPLY: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: + case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY: break; } diff --git a/hsmd/hsm_client_wire_csv b/hsmd/hsm_client_wire_csv index 4eba86875..4759e6cd6 100644 --- a/hsmd/hsm_client_wire_csv +++ b/hsmd/hsm_client_wire_csv @@ -23,6 +23,7 @@ hsm_client_hsmfd,,capabilities,u64 # No content, just an fd. hsm_client_hsmfd_reply,109 + # Return signature for a funding tx. #include # FIXME: This should also take their commit sig & details, to verify. @@ -90,3 +91,16 @@ hsm_cupdate_sig_req,,cu,culen*u8 hsm_cupdate_sig_reply,103 hsm_cupdate_sig_reply,,culen,u16 hsm_cupdate_sig_reply,,cu,culen*u8 + +# Master asks HSM to sign a commitment transaction. +hsm_sign_commitment_tx,5 +hsm_sign_commitment_tx,,peer_id,struct pubkey +hsm_sign_commitment_tx,,channel_dbid,u64 +hsm_sign_commitment_tx,,tx,struct bitcoin_tx +hsm_sign_commitment_tx,,remote_funding_key,struct pubkey +hsm_sign_commitment_tx,,funding_amount,u64 + +hsm_sign_commitment_tx_reply,105 +hsm_sign_commitment_tx_reply,,sig,secp256k1_ecdsa_signature + + diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 4460d8119..c99a08eb2 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -44,6 +44,7 @@ #include #include #include +#include struct close_command { /* Inside struct lightningd close_commands. */ @@ -197,24 +198,27 @@ u32 feerate_max(struct lightningd *ld) static void sign_last_tx(struct channel *channel) { - u8 *funding_wscript; - struct secrets secrets; + struct lightningd *ld = channel->peer->ld; secp256k1_ecdsa_signature sig; + u8 *msg; assert(!channel->last_tx->input[0].witness); - derive_basepoints(&channel->seed, NULL, NULL, &secrets, NULL); + msg = towire_hsm_sign_commitment_tx(tmpctx, + &channel->peer->id, + channel->dbid, + channel->last_tx, + &channel->channel_info + .remote_fundingkey, + channel->funding_satoshi); - funding_wscript = bitcoin_redeem_2of2(tmpctx, - &channel->local_funding_pubkey, - &channel->channel_info.remote_fundingkey); - /* Need input amount for signing */ - channel->last_tx->input[0].amount = tal_dup(channel->last_tx->input, u64, - &channel->funding_satoshi); - sign_tx_input(channel->last_tx, 0, NULL, funding_wscript, - &secrets.funding_privkey, - &channel->local_funding_pubkey, - &sig); + if (!wire_sync_write(ld->hsm_fd, take(msg))) + fatal("Could not write to HSM: %s", strerror(errno)); + + msg = wire_sync_read(tmpctx, ld->hsm_fd); + if (!fromwire_hsm_sign_commitment_tx_reply(msg, &sig)) + fatal("HSM gave bad sign_commitment_tx_reply %s", + tal_hex(tmpctx, msg)); channel->last_tx->input[0].witness = bitcoin_witness_2of2(channel->last_tx->input, @@ -226,7 +230,6 @@ static void sign_last_tx(struct channel *channel) static void remove_sig(struct bitcoin_tx *signed_tx) { - signed_tx->input[0].amount = tal_free(signed_tx->input[0].amount); signed_tx->input[0].witness = tal_free(signed_tx->input[0].witness); } diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index b500ab78a..797f08fc2 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -77,6 +77,9 @@ bool fromwire_gossip_getpeers_reply(const tal_t *ctx UNNEEDED, const void *p UNN /* Generated stub for fromwire_gossip_peer_connected */ bool fromwire_gossip_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED) { fprintf(stderr, "fromwire_gossip_peer_connected called!\n"); abort(); } +/* Generated stub for fromwire_hsm_sign_commitment_tx_reply */ +bool fromwire_hsm_sign_commitment_tx_reply(const void *p UNNEEDED, secp256k1_ecdsa_signature *sig UNNEEDED) +{ fprintf(stderr, "fromwire_hsm_sign_commitment_tx_reply called!\n"); abort(); } /* Generated stub for get_feerate */ u32 get_feerate(const struct chain_topology *topo UNNEEDED, enum feerate feerate UNNEEDED) { fprintf(stderr, "get_feerate called!\n"); abort(); } @@ -384,6 +387,9 @@ u8 *towire_gossipctl_peer_important(const tal_t *ctx UNNEEDED, const struct pubk /* Generated stub for towire_gossip_getpeers_request */ u8 *towire_gossip_getpeers_request(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED) { fprintf(stderr, "towire_gossip_getpeers_request called!\n"); abort(); } +/* Generated stub for towire_hsm_sign_commitment_tx */ +u8 *towire_hsm_sign_commitment_tx(const tal_t *ctx UNNEEDED, const struct pubkey *peer_id UNNEEDED, u64 channel_dbid UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const struct pubkey *remote_funding_key UNNEEDED, u64 funding_amount UNNEEDED) +{ fprintf(stderr, "towire_hsm_sign_commitment_tx called!\n"); abort(); } /* Generated stub for watch_txid */ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED, @@ -404,6 +410,12 @@ struct txowatch *watch_txo(const tal_t *ctx UNNEEDED, size_t input_num UNNEEDED, const struct block *block)) { fprintf(stderr, "watch_txo called!\n"); abort(); } +/* Generated stub for wire_sync_read */ +u8 *wire_sync_read(const tal_t *ctx UNNEEDED, int fd UNNEEDED) +{ fprintf(stderr, "wire_sync_read called!\n"); abort(); } +/* Generated stub for wire_sync_write */ +bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED) +{ fprintf(stderr, "wire_sync_write called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ #if DEVELOPER