diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index 56e5ef804..9cafbb764 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +73,10 @@ struct peer { struct daemon_conn gossip_client; struct daemon_conn master; + struct timers timers; + struct oneshot *commit_timer; + u32 commit_msec; + /* Announcement related information */ struct pubkey node_ids[NUM_SIDES]; struct short_channel_id short_channel_ids[NUM_SIDES]; @@ -254,6 +260,208 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg) "Bad peer_add_htlc: %u", add_err); } +static void send_commit(struct peer *peer) +{ + tal_t *tmpctx = tal_tmpctx(peer); + u8 *msg; + secp256k1_ecdsa_signature commit_sig, *htlc_sigs; + size_t i; + struct bitcoin_tx **txs; + const u8 **wscripts; + const struct htlc **htlc_map; + struct pubkey localkey; + struct privkey local_secretkey; + + /* Timer has expired. */ + peer->commit_timer = NULL; + + /* BOLT #2: + * + * A node MUST NOT send a `commitment_signed` message which does not + * include any updates. + */ + if (!channel_sent_commit(peer->channel)) { + tal_free(tmpctx); + return; + } + + if (!derive_simple_privkey(&peer->our_secrets.payment_basepoint_secret, + &peer->channel->basepoints[LOCAL].payment, + &peer->next_per_commit[REMOTE], + &local_secretkey)) + status_failed(WIRE_CHANNEL_CRYPTO_FAILED, + "Deriving local_secretkey"); + + if (!derive_simple_key(&peer->channel->basepoints[LOCAL].payment, + &peer->next_per_commit[REMOTE], + &localkey)) + status_failed(WIRE_CHANNEL_CRYPTO_FAILED, + "Deriving localkey"); + + txs = channel_txs(tmpctx, &htlc_map, &wscripts, peer->channel, + &peer->next_per_commit[REMOTE], REMOTE); + + sign_tx_input(txs[0], 0, NULL, + wscripts[0], + &peer->our_secrets.funding_privkey, + &peer->channel->funding_pubkey[LOCAL], + &commit_sig); + + status_trace("Creating commit_sig signature %s for tx %s wscript %s key %s", + type_to_string(trc, secp256k1_ecdsa_signature, + &commit_sig), + type_to_string(trc, struct bitcoin_tx, txs[0]), + tal_hex(trc, wscripts[0]), + type_to_string(trc, struct pubkey, + &peer->channel->funding_pubkey[LOCAL])); + + /* BOLT #2: + * + * A node MUST include one `htlc-signature` for every HTLC transaction + * corresponding to BIP69 lexicographic ordering of the commitment + * transaction. + */ + htlc_sigs = tal_arr(tmpctx, secp256k1_ecdsa_signature, + tal_count(txs) - 1); + + for (i = 0; i < tal_count(htlc_sigs); i++) { + sign_tx_input(txs[1 + i], 0, + NULL, + wscripts[1 + i], + &local_secretkey, &localkey, + &htlc_sigs[i]); + status_trace("Creating HTLC signature %s for tx %s wscript %s key %s", + type_to_string(trc, secp256k1_ecdsa_signature, + &htlc_sigs[i]), + type_to_string(trc, struct bitcoin_tx, txs[1+i]), + tal_hex(trc, wscripts[1+i]), + type_to_string(trc, struct pubkey, &localkey)); + assert(check_tx_sig(txs[1+i], 0, NULL, wscripts[1+i], + &localkey, &htlc_sigs[i])); + } + status_trace("Sending commit_sig with %zu htlc sigs", + tal_count(htlc_sigs)); + msg = towire_commitment_signed(tmpctx, &peer->channel_id, + &commit_sig, htlc_sigs); + msg_enqueue(&peer->peer_out, take(msg)); + tal_free(tmpctx); +} + +static void start_commit_timer(struct peer *peer) +{ + /* Already armed? */ + if (peer->commit_timer) + return; + + peer->commit_timer = new_reltimer(&peer->timers, peer, + time_from_msec(peer->commit_msec), + send_commit, peer); +} + +static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) +{ + tal_t *tmpctx = tal_tmpctx(peer); + struct channel_id channel_id; + secp256k1_ecdsa_signature commit_sig, *htlc_sigs; + struct pubkey remotekey; + struct bitcoin_tx **txs; + const struct htlc **htlc_map; + const u8 **wscripts; + size_t i; + + if (!channel_rcvd_commit(peer->channel)) { + /* BOLT #2: + * + * A node MUST NOT send a `commitment_signed` message which + * does not include any updates. + */ + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + WIRE_CHANNEL_PEER_BAD_MESSAGE, + "commit_sig with no changes"); + } + + if (!fromwire_commitment_signed(tmpctx, msg, NULL, + &channel_id, &commit_sig, &htlc_sigs)) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + WIRE_CHANNEL_PEER_BAD_MESSAGE, + "Bad commit_sig %s", tal_hex(msg, msg)); + + txs = channel_txs(tmpctx, &htlc_map, &wscripts, peer->channel, + &peer->next_per_commit[LOCAL], LOCAL); + + if (!derive_simple_key(&peer->channel->basepoints[REMOTE].payment, + &peer->next_per_commit[LOCAL], + &remotekey)) + status_failed(WIRE_CHANNEL_CRYPTO_FAILED, + "Deriving remotekey"); + + /* BOLT #2: + * + * A receiving node MUST fail the channel if `signature` is not valid + * for its local commitment transaction once all pending updates are + * applied. + */ + if (!check_tx_sig(txs[0], 0, NULL, wscripts[0], + &peer->channel->funding_pubkey[REMOTE], &commit_sig)) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + WIRE_CHANNEL_PEER_BAD_MESSAGE, + "Bad commit_sig signature %s for tx %s wscript %s key %s", + type_to_string(msg, secp256k1_ecdsa_signature, + &commit_sig), + type_to_string(msg, struct bitcoin_tx, txs[0]), + tal_hex(msg, wscripts[0]), + type_to_string(msg, struct pubkey, + &peer->channel->funding_pubkey + [REMOTE])); + + /* BOLT #2: + * + * A receiving node MUST fail the channel if `num-htlcs` is not equal + * to the number of HTLC outputs in the local commitment transaction + * once all pending updates are applied. + */ + if (tal_count(htlc_sigs) != tal_count(txs) - 1) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + WIRE_CHANNEL_PEER_BAD_MESSAGE, + "Expected %zu htlc sigs, not %zu", + tal_count(txs) - 1, tal_count(htlc_sigs)); + + /* BOLT #2: + * + * A receiving node MUST fail + * the channel if any `htlc-signature` is not valid for the + * corresponding HTLC transaction. + */ + for (i = 0; i < tal_count(htlc_sigs); i++) { + if (!check_tx_sig(txs[1+i], 0, NULL, wscripts[1+i], + &remotekey, &htlc_sigs[i])) + peer_failed(io_conn_fd(peer->peer_conn), + &peer->pcs.cs, + &peer->channel_id, + WIRE_CHANNEL_PEER_BAD_MESSAGE, + "Bad commit_sig signature %s for htlc %s wscript %s key %s", + type_to_string(msg, secp256k1_ecdsa_signature, &htlc_sigs[i]), + type_to_string(msg, struct bitcoin_tx, txs[1+i]), + tal_hex(msg, wscripts[1+i]), + type_to_string(msg, struct pubkey, &remotekey)); + } + + status_trace("Received commit_sig with %zu htlc sigs", + tal_count(htlc_sigs)); + + /* This may have triggered changes, so restart timer. */ + start_commit_timer(peer); + tal_free(tmpctx); +} + static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) { enum wire_type type = fromwire_peektype(msg); @@ -287,11 +495,12 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) /* Forward to gossip daemon */ daemon_conn_send(&peer->gossip_client, msg); goto done; - case WIRE_UPDATE_ADD_HTLC: handle_peer_add_htlc(peer, msg); goto done; - + case WIRE_COMMITMENT_SIGNED: + handle_peer_commit_sig(peer, msg); + goto done; case WIRE_INIT: case WIRE_ERROR: case WIRE_OPEN_CHANNEL: @@ -305,7 +514,6 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) case WIRE_UPDATE_FULFILL_HTLC: case WIRE_UPDATE_FAIL_HTLC: case WIRE_UPDATE_FAIL_MALFORMED_HTLC: - case WIRE_COMMITMENT_SIGNED: case WIRE_REVOKE_AND_ACK: case WIRE_UPDATE_FEE: peer_failed(io_conn_fd(peer->peer_conn), @@ -368,7 +576,8 @@ static void init_channel(struct peer *peer, const u8 *msg) &feerate, &funding_satoshi, &push_msat, &seed, &peer->node_ids[LOCAL], - &peer->node_ids[REMOTE])) + &peer->node_ids[REMOTE], + &peer->commit_msec)) status_failed(WIRE_CHANNEL_BAD_COMMAND, "%s", tal_hex(msg, msg)); @@ -419,11 +628,6 @@ static void handle_funding_announce_depth(struct peer *peer, const u8 *msg) send_announcement_signatures(peer); } -static void start_commit_timer(struct peer *peer) -{ - /* FIXME! */ -} - static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) { u8 *msg; @@ -589,6 +793,7 @@ static struct io_plan *req_in(struct io_conn *conn, struct daemon_conn *master) case WIRE_CHANNEL_BAD_COMMAND: case WIRE_CHANNEL_HSM_FAILED: + case WIRE_CHANNEL_CRYPTO_FAILED: case WIRE_CHANNEL_PEER_WRITE_FAILED: case WIRE_CHANNEL_PEER_READ_FAILED: case WIRE_CHANNEL_RECEIVED_FUNDING_LOCKED: @@ -629,6 +834,8 @@ int main(int argc, char *argv[]) daemon_conn_init(peer, &peer->master, REQ_FD, req_in); peer->channel = NULL; peer->htlc_id = 0; + timers_init(&peer->timers, time_mono()); + peer->commit_timer = NULL; status_setup_async(&peer->master); msg_queue_init(&peer->peer_out, peer); @@ -639,8 +846,15 @@ int main(int argc, char *argv[]) init_peer_crypto_state(peer, &peer->pcs); peer->funding_locked[LOCAL] = peer->funding_locked[REMOTE] = false; - /* We don't expect to exit here. */ - io_loop(NULL, NULL); + for (;;) { + struct timer *expired = NULL; + io_loop(&peer->timers, &expired); + + if (!expired) + break; + timer_expired(peer, expired); + } + tal_free(peer); return 0; } diff --git a/lightningd/channel/channel_wire.csv b/lightningd/channel/channel_wire.csv index 12e31c827..ba619b9e5 100644 --- a/lightningd/channel/channel_wire.csv +++ b/lightningd/channel/channel_wire.csv @@ -2,6 +2,7 @@ channel_bad_command,0x8000 # Also shouldn't happen channel_hsm_failed,0x8001 +channel_crypto_failed,0x8002 # These are due to peer. channel_peer_write_failed,0x8010 @@ -37,6 +38,7 @@ channel_init,488,push_msat,8 channel_init,496,seed,struct privkey channel_init,529,local_node_id,struct pubkey channel_init,562,remote_node_id,struct pubkey +channel_init,595,commit_msec,4 # Tx is deep enough, go! channel_funding_locked,2 diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 40878da76..01da2e210 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -640,6 +640,7 @@ static size_t update_channel_status(struct subd *sd, /* We never see fatal ones. */ case WIRE_CHANNEL_BAD_COMMAND: case WIRE_CHANNEL_HSM_FAILED: + case WIRE_CHANNEL_CRYPTO_FAILED: case WIRE_CHANNEL_PEER_WRITE_FAILED: case WIRE_CHANNEL_PEER_READ_FAILED: case WIRE_CHANNEL_PEER_BAD_MESSAGE: @@ -704,7 +705,9 @@ static void peer_start_channeld(struct peer *peer, bool am_funder, peer->push_msat, peer->seed, &peer->ld->dstate.id, - peer->id); + peer->id, + time_to_msec(peer->ld->dstate.config + .commit_time)); /* We don't expect a response: we are triggered by funding_depth_cb. */ subd_send_msg(peer->owner, take(msg));