From 7e820f07e75214a4fdbb60b9a4a937c9508228be Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 20 Jun 2017 15:34:03 +0930 Subject: [PATCH] channeld: get commit indices from master. Note that this will change a little in following commits. Signed-off-by: Rusty Russell --- lightningd/channel/channel.c | 32 +++++--- lightningd/channel/channel_wire.csv | 11 ++- lightningd/peer_control.c | 22 +++++- lightningd/peer_control.h | 1 + lightningd/peer_htlcs.c | 117 +++++++++++++++++++++++++--- lightningd/peer_htlcs.h | 9 ++- 6 files changed, 163 insertions(+), 29 deletions(-) diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index 8709b9107..3f0fe88ab 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -530,8 +530,8 @@ static void send_commit(struct peer *peer) } status_trace("Telling master we're about to commit..."); - /* Tell master to save to database, then wait for reply. */ - msg = sending_commitsig_msg(tmpctx, peer->commit_index[REMOTE], + /* Tell master to save this next commit to database, then wait. */ + msg = sending_commitsig_msg(tmpctx, peer->commit_index[REMOTE] + 1, changed_htlcs); master_sync_reply(peer, take(msg), WIRE_CHANNEL_SENDING_COMMITSIG_REPLY, @@ -1214,19 +1214,23 @@ static void init_channel(struct peer *peer) { struct privkey seed; struct basepoints points[NUM_SIDES]; - u64 funding_satoshi, push_msat; + u64 funding_satoshi; u16 funding_txout; + u64 commits_sent, commits_received, revocations_received; u64 local_msatoshi; struct pubkey funding_pubkey[NUM_SIDES]; struct sha256_double funding_txid; bool am_funder, last_was_revoke; + enum htlc_state *hstates; struct changed_htlc *last_sent_commit; + struct added_htlc *htlcs; u8 *funding_signed; u8 *msg; msg = wire_sync_read(peer, REQ_FD); if (!fromwire_channel_init(msg, msg, NULL, &funding_txid, &funding_txout, + &funding_satoshi, &peer->conf[LOCAL], &peer->conf[REMOTE], &peer->their_commit_sig, &peer->pcs.cs, @@ -1238,7 +1242,7 @@ static void init_channel(struct peer *peer) &am_funder, &peer->fee_base, &peer->fee_per_satoshi, - &funding_satoshi, &push_msat, + &local_msatoshi, &seed, &peer->node_ids[LOCAL], &peer->node_ids[REMOTE], @@ -1246,10 +1250,23 @@ static void init_channel(struct peer *peer) &peer->cltv_delta, &last_was_revoke, &last_sent_commit, + &commits_sent, + &commits_received, + &revocations_received, + &peer->htlc_id, + &htlcs, + &hstates, &funding_signed)) status_failed(WIRE_CHANNEL_BAD_COMMAND, "Init: %s", tal_hex(msg, msg)); + /* First commit is used for opening. */ + assert(commits_sent > 0); + assert(commits_received > 0); + + peer->commit_index[LOCAL] = commits_sent - 1; + peer->commit_index[REMOTE] = commits_received - 1; + /* channel_id is set from funding txout */ derive_channel_id(&peer->channel_id, &funding_txid, funding_txout); @@ -1262,11 +1279,6 @@ static void init_channel(struct peer *peer) type_to_string(trc, struct pubkey, &peer->old_per_commit[LOCAL])); - if (am_funder) - local_msatoshi = funding_satoshi * 1000 - push_msat; - else - local_msatoshi = push_msat; - peer->channel = new_channel(peer, &funding_txid, funding_txout, funding_satoshi, local_msatoshi, @@ -1622,11 +1634,9 @@ int main(int argc, char *argv[]) daemon_conn_init(peer, &peer->master, REQ_FD, req_in, master_gone); status_setup_async(&peer->master); - peer->htlc_id = 0; peer->num_pings_outstanding = 0; timers_init(&peer->timers, time_mono()); peer->commit_timer = NULL; - peer->commit_index[LOCAL] = peer->commit_index[REMOTE] = 0; peer->have_sigs[LOCAL] = peer->have_sigs[REMOTE] = false; peer->handle_master_reply = NULL; peer->master_reply_type = 0; diff --git a/lightningd/channel/channel_wire.csv b/lightningd/channel/channel_wire.csv index 5a6906f88..60a4a5259 100644 --- a/lightningd/channel/channel_wire.csv +++ b/lightningd/channel/channel_wire.csv @@ -21,6 +21,7 @@ channel_normal_operation,1001 channel_init,1 channel_init,,funding_txid,struct sha256_double channel_init,,funding_txout,2 +channel_init,,funding_satoshi,8 channel_init,,our_config,struct channel_config channel_init,,their_config,struct channel_config channel_init,,first_commit_sig,secp256k1_ecdsa_signature @@ -33,8 +34,7 @@ channel_init,,their_per_commit_point,33 channel_init,,am_funder,bool channel_init,,fee_base,4 channel_init,,fee_proportional,4 -channel_init,,funding_satoshi,8 -channel_init,,push_msat,8 +channel_init,,local_msatoshi,8 channel_init,,seed,struct privkey channel_init,,local_node_id,struct pubkey channel_init,,remote_node_id,struct pubkey @@ -43,6 +43,13 @@ channel_init,,cltv_delta,u16 channel_init,,last_was_revoke,bool channel_init,,num_last_sent_commit,u16 channel_init,,last_sent_commit,num_last_sent_commit*struct changed_htlc +channel_init,,commits_sent,u64 +channel_init,,commits_received,u64 +channel_init,,revocations_received,u64 +channel_init,,next_htlc_id,u64 +channel_init,,num_htlcs,u16 +channel_init,,htlcs,num_htlcs*struct added_htlc +channel_init,,htlc_states,num_htlcs*enum htlc_state channel_init,,init_peer_pkt_len,u16 channel_init,,init_peer_pkt,init_peer_pkt_len*u8 diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 03bb28a1b..352e745c7 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -301,6 +301,7 @@ void add_peer(struct lightningd *ld, u64 unique_id, peer->last_sent_commit = NULL; peer->num_commits_sent = peer->num_commits_received = peer->num_revocations_received = 0; + peer->next_htlc_id = 0; shachain_init(&peer->their_shachain); idname = type_to_string(peer, struct pubkey, id); @@ -921,6 +922,8 @@ static bool peer_start_channeld_hsmfd(struct subd *hsm, const u8 *resp, { u8 *initmsg; const struct config *cfg = &peer->ld->dstate.config; + struct added_htlc *htlcs; + enum htlc_state *htlc_states; peer->owner = new_subd(peer->ld, peer->ld, "lightningd_channel", peer, @@ -940,9 +943,12 @@ static bool peer_start_channeld_hsmfd(struct subd *hsm, const u8 *resp, log_debug(peer->log, "Waiting for funding confirmations"); peer_set_condition(peer, GETTING_HSMFD, CHANNELD_AWAITING_LOCKIN); + peer_htlcs(resp, peer, &htlcs, &htlc_states); + initmsg = towire_channel_init(peer, peer->funding_txid, peer->funding_outnum, + peer->funding_satoshi, &peer->our_config, &peer->channel_info->their_config, &peer->channel_info->commit_sig, @@ -955,8 +961,7 @@ static bool peer_start_channeld_hsmfd(struct subd *hsm, const u8 *resp, peer->funder == LOCAL, cfg->fee_base, cfg->fee_per_satoshi, - peer->funding_satoshi, - peer->push_msat, + *peer->balance, peer->seed, &peer->ld->dstate.id, &peer->id, @@ -964,6 +969,11 @@ static bool peer_start_channeld_hsmfd(struct subd *hsm, const u8 *resp, cfg->deadline_blocks, peer->last_was_revoke, peer->last_sent_commit, + peer->num_commits_sent, + peer->num_commits_received, + peer->num_revocations_received, + peer->next_htlc_id, + htlcs, htlc_states, peer->funding_signed); /* Don't need this any more (we never re-transmit it) */ @@ -1071,7 +1081,9 @@ static bool opening_funder_finished(struct subd *opening, const u8 *resp, return false; } - if (!peer_save_commitsig(fc->peer, 0)) { + /* We should have sent and received the first commitsig */ + if (!peer_save_commitsig_received(fc->peer, 0) + || !peer_save_commitsig_sent(fc->peer, 0)) { peer_fail(fc->peer, "Saving commitsig failed"); return false; } @@ -1132,7 +1144,9 @@ static bool opening_fundee_finished(struct subd *opening, return false; } - if (!peer_save_commitsig(peer, 0)) + /* We should have sent and received the first commitsig */ + if (!peer_save_commitsig_received(peer, 0) + || !peer_save_commitsig_sent(peer, 0)) return false; log_debug(peer->log, "Watching funding tx %s", diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 5050fbd96..72133044a 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -66,6 +66,7 @@ struct peer { /* Tracking commitment transaction numbers. */ u64 num_commits_sent, num_commits_received, num_revocations_received; + u64 next_htlc_id; /* Funding txid and amounts (once known) */ struct sha256_double *funding_txid; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 02a49e3de..fdf2b59d2 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -313,6 +313,20 @@ static bool rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds, return true; } + /* BOLT #2: + * + * A sending node MUST set `id` to 0 for the first HTLC it offers, and + * increase the value by 1 for each successive offer. + */ + if (hout->key.id != hout->key.peer->next_htlc_id) { + log_broken(subd->log, "Bad offer_htlc_reply HTLC id %"PRIu64 + " expected %"PRIu64, + hout->key.id, hout->key.peer->next_htlc_id); + tal_free(hout); + return false; + } + hout->key.peer->next_htlc_id++; + /* Add it to lookup table now we know id. */ connect_htlc_out(&subd->ld->htlcs_out, hout); @@ -775,14 +789,6 @@ int peer_sending_commitsig(struct peer *peer, const u8 *msg) return -1; } - if (commitnum != peer->num_commits_sent) { - log_broken(peer->log, - "channel_sending_commitsig: expected commitnum %" - PRIu64" got %"PRIu64, - peer->num_commits_sent, commitnum); - return -1; - } - for (i = 0; i < tal_count(changed_htlcs); i++) { if (!changed_htlc(peer, changed_htlcs + i)) { log_broken(peer->log, @@ -791,7 +797,8 @@ int peer_sending_commitsig(struct peer *peer, const u8 *msg) } } - peer->num_commits_sent++; + if (!peer_save_commitsig_sent(peer, commitnum)) + return -1; /* Last was commit. */ peer->last_was_revoke = false; @@ -870,7 +877,7 @@ static bool peer_sending_revocation(struct peer *peer, } /* Also used for opening's initial commitsig */ -bool peer_save_commitsig(struct peer *peer, u64 commitnum) +bool peer_save_commitsig_received(struct peer *peer, u64 commitnum) { if (commitnum != peer->num_commits_received) { log_broken(peer->log, @@ -886,6 +893,23 @@ bool peer_save_commitsig(struct peer *peer, u64 commitnum) return true; } +/* Also used for opening's initial commitsig */ +bool peer_save_commitsig_sent(struct peer *peer, u64 commitnum) +{ + if (commitnum != peer->num_commits_sent) { + log_broken(peer->log, + "channel_sent_commitsig: expected commitnum %"PRIu64 + " got %"PRIu64, + peer->num_commits_sent, commitnum); + return false; + } + + peer->num_commits_sent++; + + /* FIXME: Save to database, with sig and HTLCs. */ + return true; +} + /* This also implies we're sending revocation */ int peer_got_commitsig(struct peer *peer, const u8 *msg) { @@ -949,7 +973,8 @@ int peer_got_commitsig(struct peer *peer, const u8 *msg) return -1; peer->channel_info->commit_sig = commit_sig; - peer_save_commitsig(peer, commitnum); + if (!peer_save_commitsig_received(peer, commitnum)) + return -1; /* Tell it we've committed, and to go ahead with revoke. */ msg = towire_channel_got_commitsig_reply(msg); @@ -1061,3 +1086,73 @@ int peer_got_revoke(struct peer *peer, const u8 *msg) return 0; } +static void *tal_arr_append_(void **p, size_t size) +{ + size_t n = tal_len(*p) / size; + tal_resize_(p, size, n+1, false); + return (char *)(*p) + n * size; +} +#define tal_arr_append(p) tal_arr_append_((void **)(p), sizeof(**(p))) + +static void add_htlc(struct added_htlc **htlcs, + enum htlc_state **htlc_states, + u64 id, + u64 amount_msat, + const struct sha256 *payment_hash, + u32 cltv_expiry, + const u8 onion_routing_packet[TOTAL_PACKET_SIZE], + enum htlc_state state) +{ + struct added_htlc *a; + enum htlc_state *h; + + a = tal_arr_append(htlcs); + h = tal_arr_append(htlc_states); + + a->id = id; + a->amount_msat = amount_msat; + a->payment_hash = *payment_hash; + a->cltv_expiry = cltv_expiry; + memcpy(a->onion_routing_packet, onion_routing_packet, + sizeof(a->onion_routing_packet)); + *h = state; +} + +/* FIXME: Load direct from db. */ +void peer_htlcs(const tal_t *ctx, + const struct peer *peer, + struct added_htlc **htlcs, + enum htlc_state **htlc_states) +{ + struct htlc_in_map_iter ini; + struct htlc_out_map_iter outi; + struct htlc_in *hin; + struct htlc_out *hout; + + *htlcs = tal_arr(ctx, struct added_htlc, 0); + *htlc_states = tal_arr(ctx, enum htlc_state, 0); + + for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini); + hin; + hin = htlc_in_map_next(&peer->ld->htlcs_in, &ini)) { + if (hin->key.peer != peer) + continue; + + add_htlc(htlcs, htlc_states, + hin->key.id, hin->msatoshi, &hin->payment_hash, + hin->cltv_expiry, hin->onion_routing_packet, + hin->hstate); + } + + for (hout = htlc_out_map_first(&peer->ld->htlcs_out, &outi); + hout; + hout = htlc_out_map_next(&peer->ld->htlcs_out, &outi)) { + if (hout->key.peer != peer) + continue; + + add_htlc(htlcs, htlc_states, + hout->key.id, hout->msatoshi, &hout->payment_hash, + hout->cltv_expiry, hout->onion_routing_packet, + hout->hstate); + } +} diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index b686c400a..f7200d94d 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -13,7 +13,14 @@ struct channel_info { struct pubkey their_per_commit_point; }; -bool peer_save_commitsig(struct peer *peer, u64 commitnum); +/* Get all HTLCs for a peer, to send in init message. */ +void peer_htlcs(const tal_t *ctx, + const struct peer *peer, + struct added_htlc **htlcs, + enum htlc_state **htlc_states); + +bool peer_save_commitsig_received(struct peer *peer, u64 commitnum); +bool peer_save_commitsig_sent(struct peer *peer, u64 commitnum); int peer_sending_commitsig(struct peer *peer, const u8 *msg); int peer_got_commitsig(struct peer *peer, const u8 *msg);