From 9984c34f14ede94cb40c159874fbe1eda3a5c772 Mon Sep 17 00:00:00 2001 From: niftynei Date: Thu, 10 Dec 2020 14:25:54 -0600 Subject: [PATCH] df: handle locked in etc in dualopend --- lightningd/channel_control.c | 1 - lightningd/dual_open_control.c | 54 +++++++++++++++++++++++---- openingd/dualopend.c | 68 +++++++++++++++++++++------------- openingd/dualopend_wire.csv | 8 +++- openingd/dualopend_wiregen.c | 54 ++++++++++++++++++++++++--- openingd/dualopend_wiregen.h | 20 ++++++++-- 6 files changed, 163 insertions(+), 42 deletions(-) diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 5085f3c82..e871ef7d4 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -643,7 +643,6 @@ bool channel_tell_depth(struct lightningd *ld, #if EXPERIMENTAL_FEATURES dualopen_tell_depth(channel->owner, channel, depth); - // FIXME: lockin complete? return true; #endif /* EXPERIMENTAL_FEATURES */ } else if (channel->state != CHANNELD_AWAITING_LOCKIN diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 83a1f651c..a8fcbe2e0 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1245,16 +1245,36 @@ static void handle_peer_tx_sigs_sent(struct subd *dualopend, } } +static void handle_peer_locked(struct subd *dualopend, const u8 *msg) +{ + struct pubkey remote_per_commit; + struct channel *channel; + + assert(dualopend->ctype == CHANNEL); + channel = dualopend->channel; + + if (!fromwire_dualopend_peer_locked(msg, &remote_per_commit)) + channel_internal_error(channel, + "bad WIRE_DUALOPEND_PEER_LOCKED %s", + tal_hex(msg, msg)); + + /* Updates channel with the next per-commit point etc */ + if (!channel_on_funding_locked(channel, &remote_per_commit)) + channel_internal_error(channel, + "Got funding_locked twice"); + + /* Remember that we got the lock-in */ + wallet_channel_save(dualopend->ld->wallet, channel); +} + static void handle_channel_locked(struct subd *dualopend, const int *fds, const u8 *msg) { struct channel *channel = dualopend->channel; - struct pubkey remote_per_commit; struct per_peer_state *pps; - if (!fromwire_dualopend_channel_locked(tmpctx, msg, &pps, - &remote_per_commit)) { + if (!fromwire_dualopend_channel_locked(tmpctx, msg, &pps)) { log_broken(dualopend->log, "bad WIRE_DUALOPEND_CHANNEL_LOCKED %s", tal_hex(msg, msg)); @@ -1265,10 +1285,6 @@ static void handle_channel_locked(struct subd *dualopend, } per_peer_state_set_fds_arr(pps, fds); - /* Updates channel with the next per-commit point etc */ - if (!channel_on_funding_locked(channel, &remote_per_commit)) - goto cleanup; - assert(channel->scid); assert(channel->remote_funding_locked); @@ -1737,6 +1753,24 @@ static struct command_result *json_openchannel_init(struct command *cmd, return command_still_pending(cmd); } +static void +channel_fail_fallen_behind(struct subd* dualopend, const u8 *msg) +{ + struct channel *channel; + + assert(dualopend->ctype == CHANNEL); + channel = dualopend->channel; + + if (!fromwire_dualopend_fail_fallen_behind(msg)) { + channel_internal_error(channel, + "bad dualopen_fail_fallen_behind %s", + tal_hex(tmpctx, msg)); + return; + } + + channel_fallen_behind(channel, msg); +} + static unsigned int dual_opend_msg(struct subd *dualopend, const u8 *msg, const int *fds) { @@ -1783,6 +1817,9 @@ static unsigned int dual_opend_msg(struct subd *dualopend, case WIRE_DUALOPEND_TX_SIGS_SENT: handle_peer_tx_sigs_sent(dualopend, fds, msg); return 0; + case WIRE_DUALOPEND_PEER_LOCKED: + handle_peer_locked(dualopend, msg); + return 0; case WIRE_DUALOPEND_CHANNEL_LOCKED: if (tal_count(fds) != 3) return 3; @@ -1796,6 +1833,9 @@ static unsigned int dual_opend_msg(struct subd *dualopend, return 3; handle_channel_closed(dualopend, fds, msg); return 0; + case WIRE_DUALOPEND_FAIL_FALLEN_BEHIND: + channel_fail_fallen_behind(dualopend, msg); + return 0; case WIRE_DUALOPEND_FAILED: open_failed(dualopend, msg); return 0; diff --git a/openingd/dualopend.c b/openingd/dualopend.c index ff3463a39..d678d8106 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -154,9 +154,6 @@ struct state { /* PSBT of the funding tx */ struct wally_psbt *psbt; - /* Peer sends this to us in the funding_locked msg */ - struct pubkey remote_per_commit; - /* Are we shutting down? */ bool shutdown_sent[NUM_SIDES]; @@ -781,16 +778,15 @@ static void handle_tx_sigs(struct state *state, const u8 *msg) return; } - if (state->funding_locked[REMOTE]) + /* On reconnect, we expect them to resend tx_sigs if they haven't + * gotten our funding_locked yet */ + if (state->funding_locked[REMOTE] && !state->reconnected) peer_failed(state->pps, &state->channel_id, "tx_signatures sent after funding_locked %s", tal_hex(msg, msg)); - /* This check only works if they've got inputs we need sigs for. - * In the case where they send duplicate tx_sigs but have no - * sigs, we'll end up re-notifying */ - if (tal_count(ws) && psbt_side_finalized(state->psbt, their_role)) { + if (state->remote_funding_sigs_rcvd) { status_info("Got duplicate WIRE_TX_SIGNATURES, " "already have their sigs. Ignoring"); return; @@ -823,6 +819,7 @@ static void handle_tx_sigs(struct state *state, const u8 *msg) psbt_finalize_input(state->psbt, in, elem); } + state->remote_funding_sigs_rcvd = true; /* Send to the controller, who will broadcast the funding_tx * as soon as we've got our sigs */ wire_sync_write(REQ_FD, @@ -2249,9 +2246,9 @@ static void opener_start(struct state *state, u8 *msg) static u8 *handle_funding_locked(struct state *state, u8 *msg) { struct channel_id cid; + struct pubkey remote_per_commit; - if (!fromwire_funding_locked(msg, &cid, - &state->remote_per_commit)) + if (!fromwire_funding_locked(msg, &cid, &remote_per_commit)) peer_failed(state->pps, &state->channel_id, "Bad funding_locked %s", tal_hex(msg, msg)); @@ -2263,11 +2260,24 @@ static u8 *handle_funding_locked(struct state *state, u8 *msg) &state->channel_id), type_to_string(msg, struct channel_id, &cid)); + /* If we haven't gotten their tx_sigs yet, this is a protocol error */ + if (!state->remote_funding_sigs_rcvd) { + peer_failed(state->pps, + &state->channel_id, + "funding_locked sent before tx_signatures %s", + tal_hex(msg, msg)); + } + state->funding_locked[REMOTE] = true; billboard_update(state); + + /* We save when the peer locks, so we do the right + * thing on reconnects */ + msg = towire_dualopend_peer_locked(NULL, &remote_per_commit); + wire_sync_write(REQ_FD, take(msg)); + if (state->funding_locked[LOCAL]) - return towire_dualopend_channel_locked(state, state->pps, - &state->remote_per_commit); + return towire_dualopend_channel_locked(state, state->pps); return NULL; } @@ -2288,10 +2298,26 @@ static void hsm_per_commitment_point(u64 index, struct pubkey *point) tal_hex(tmpctx, msg)); } +static void send_funding_locked(struct state *state) +{ + u8 *msg; + struct pubkey next_local_per_commit; + + /* Figure out the next local commit */ + hsm_per_commitment_point(1, &next_local_per_commit); + + msg = towire_funding_locked(NULL, + &state->channel_id, + &next_local_per_commit); + sync_crypto_write(state->pps, take(msg)); + + state->funding_locked[LOCAL] = true; + billboard_update(state); +} + static u8 *handle_funding_depth(struct state *state, u8 *msg) { u32 depth; - struct pubkey next_local_per_commit; if (!fromwire_dualopend_depth_reached(msg, &depth)) master_badmsg(WIRE_DUALOPEND_DEPTH_REACHED, msg); @@ -2303,20 +2329,10 @@ static u8 *handle_funding_depth(struct state *state, u8 *msg) /* We check this before we arrive here, but for sanity */ assert(state->minimum_depth <= depth); - /* Figure out the next local commit */ - hsm_per_commitment_point(1, &next_local_per_commit); - - msg = towire_funding_locked(NULL, - &state->channel_id, - &next_local_per_commit); - sync_crypto_write(state->pps, take(msg)); - - state->funding_locked[LOCAL] = true; - billboard_update(state); + send_funding_locked(state); if (state->funding_locked[REMOTE]) return towire_dualopend_channel_locked(state, - state->pps, - &state->remote_per_commit); + state->pps); return NULL; } @@ -2399,9 +2415,11 @@ static u8 *handle_master_in(struct state *state) case WIRE_DUALOPEND_COMMIT_RCVD: case WIRE_DUALOPEND_FUNDING_SIGS: case WIRE_DUALOPEND_TX_SIGS_SENT: + case WIRE_DUALOPEND_PEER_LOCKED: case WIRE_DUALOPEND_CHANNEL_LOCKED: case WIRE_DUALOPEND_GOT_SHUTDOWN: case WIRE_DUALOPEND_SHUTDOWN_COMPLETE: + case WIRE_DUALOPEND_FAIL_FALLEN_BEHIND: case WIRE_DUALOPEND_FAILED: break; } diff --git a/openingd/dualopend_wire.csv b/openingd/dualopend_wire.csv index 757ec0053..b5e282435 100644 --- a/openingd/dualopend_wire.csv +++ b/openingd/dualopend_wire.csv @@ -163,10 +163,13 @@ msgdata,dualopend_send_tx_sigs,signed_psbt,wally_psbt, # dualopend->master tx sigs transmitted to peer msgtype,dualopend_tx_sigs_sent,7012 +# dualopend->peer peer locked channel +msgtype,dualopend_peer_locked,7018 +msgdata,dualopend_peer_locked,remote_per_commit,pubkey, + # dualopend->master this channel has been locked msgtype,dualopend_channel_locked,7019 msgdata,dualopend_channel_locked,pps,per_peer_state, -msgdata,dualopend_channel_locked,remote_per_commit,pubkey, # master->dualopend funding reached depth; tell peer msgtype,dualopend_depth_reached,7020 @@ -182,6 +185,9 @@ msgtype,dualopend_got_shutdown,7024 msgdata,dualopend_got_shutdown,scriptpubkey_len,u16, msgdata,dualopend_got_shutdown,scriptpubkey,u8,scriptpubkey_len +# Peer presented proof it was from the future. +msgtype,dualopend_fail_fallen_behind,1028 + # Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd. msgtype,dualopend_shutdown_complete,7025 msgdata,dualopend_shutdown_complete,per_peer_state,per_peer_state, diff --git a/openingd/dualopend_wiregen.c b/openingd/dualopend_wiregen.c index 72a51bf81..cfe9572a3 100644 --- a/openingd/dualopend_wiregen.c +++ b/openingd/dualopend_wiregen.c @@ -33,10 +33,12 @@ const char *dualopend_wire_name(int e) case WIRE_DUALOPEND_FUNDING_SIGS: return "WIRE_DUALOPEND_FUNDING_SIGS"; case WIRE_DUALOPEND_SEND_TX_SIGS: return "WIRE_DUALOPEND_SEND_TX_SIGS"; case WIRE_DUALOPEND_TX_SIGS_SENT: return "WIRE_DUALOPEND_TX_SIGS_SENT"; + case WIRE_DUALOPEND_PEER_LOCKED: return "WIRE_DUALOPEND_PEER_LOCKED"; case WIRE_DUALOPEND_CHANNEL_LOCKED: return "WIRE_DUALOPEND_CHANNEL_LOCKED"; case WIRE_DUALOPEND_DEPTH_REACHED: return "WIRE_DUALOPEND_DEPTH_REACHED"; case WIRE_DUALOPEND_SEND_SHUTDOWN: return "WIRE_DUALOPEND_SEND_SHUTDOWN"; case WIRE_DUALOPEND_GOT_SHUTDOWN: return "WIRE_DUALOPEND_GOT_SHUTDOWN"; + case WIRE_DUALOPEND_FAIL_FALLEN_BEHIND: return "WIRE_DUALOPEND_FAIL_FALLEN_BEHIND"; case WIRE_DUALOPEND_SHUTDOWN_COMPLETE: return "WIRE_DUALOPEND_SHUTDOWN_COMPLETE"; case WIRE_DUALOPEND_DEV_MEMLEAK: return "WIRE_DUALOPEND_DEV_MEMLEAK"; case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY: return "WIRE_DUALOPEND_DEV_MEMLEAK_REPLY"; @@ -62,10 +64,12 @@ bool dualopend_wire_is_defined(u16 type) case WIRE_DUALOPEND_FUNDING_SIGS:; case WIRE_DUALOPEND_SEND_TX_SIGS:; case WIRE_DUALOPEND_TX_SIGS_SENT:; + case WIRE_DUALOPEND_PEER_LOCKED:; case WIRE_DUALOPEND_CHANNEL_LOCKED:; case WIRE_DUALOPEND_DEPTH_REACHED:; case WIRE_DUALOPEND_SEND_SHUTDOWN:; case WIRE_DUALOPEND_GOT_SHUTDOWN:; + case WIRE_DUALOPEND_FAIL_FALLEN_BEHIND:; case WIRE_DUALOPEND_SHUTDOWN_COMPLETE:; case WIRE_DUALOPEND_DEV_MEMLEAK:; case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY:; @@ -626,19 +630,40 @@ bool fromwire_dualopend_tx_sigs_sent(const void *p) return cursor != NULL; } +/* WIRE: DUALOPEND_PEER_LOCKED */ +/* dualopend->peer peer locked channel */ +u8 *towire_dualopend_peer_locked(const tal_t *ctx, const struct pubkey *remote_per_commit) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUALOPEND_PEER_LOCKED); + towire_pubkey(&p, remote_per_commit); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dualopend_peer_locked(const void *p, struct pubkey *remote_per_commit) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_PEER_LOCKED) + return false; + fromwire_pubkey(&cursor, &plen, remote_per_commit); + return cursor != NULL; +} + /* WIRE: DUALOPEND_CHANNEL_LOCKED */ /* dualopend->master this channel has been locked */ -u8 *towire_dualopend_channel_locked(const tal_t *ctx, const struct per_peer_state *pps, const struct pubkey *remote_per_commit) +u8 *towire_dualopend_channel_locked(const tal_t *ctx, const struct per_peer_state *pps) { u8 *p = tal_arr(ctx, u8, 0); towire_u16(&p, WIRE_DUALOPEND_CHANNEL_LOCKED); towire_per_peer_state(&p, pps); - towire_pubkey(&p, remote_per_commit); return memcheck(p, tal_count(p)); } -bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct per_peer_state **pps, struct pubkey *remote_per_commit) +bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct per_peer_state **pps) { const u8 *cursor = p; size_t plen = tal_count(p); @@ -646,7 +671,6 @@ bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct p if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_CHANNEL_LOCKED) return false; *pps = fromwire_per_peer_state(ctx, &cursor, &plen); - fromwire_pubkey(&cursor, &plen, remote_per_commit); return cursor != NULL; } @@ -730,6 +754,26 @@ bool fromwire_dualopend_got_shutdown(const tal_t *ctx, const void *p, u8 **scrip return cursor != NULL; } +/* WIRE: DUALOPEND_FAIL_FALLEN_BEHIND */ +/* Peer presented proof it was from the future. */ +u8 *towire_dualopend_fail_fallen_behind(const tal_t *ctx) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUALOPEND_FAIL_FALLEN_BEHIND); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dualopend_fail_fallen_behind(const void *p) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_FAIL_FALLEN_BEHIND) + return false; + return cursor != NULL; +} + /* WIRE: DUALOPEND_SHUTDOWN_COMPLETE */ /* Shutdown is complete */ u8 *towire_dualopend_shutdown_complete(const tal_t *ctx, const struct per_peer_state *per_peer_state) @@ -792,4 +836,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak) *leak = fromwire_bool(&cursor, &plen); return cursor != NULL; } -// SHA256STAMP:02f28abef3ab5503d52f776543a85f6d5682637a8e9f8494beae16ff44896442 +// SHA256STAMP:4410d5ca881f7d981e8eebf77c0acf69f5a5113eaec626251d51f21d8f16a649 diff --git a/openingd/dualopend_wiregen.h b/openingd/dualopend_wiregen.h index d1c3227fe..43b2fd72c 100644 --- a/openingd/dualopend_wiregen.h +++ b/openingd/dualopend_wiregen.h @@ -46,6 +46,8 @@ enum dualopend_wire { WIRE_DUALOPEND_SEND_TX_SIGS = 7011, /* dualopend->master tx sigs transmitted to peer */ WIRE_DUALOPEND_TX_SIGS_SENT = 7012, + /* dualopend->peer peer locked channel */ + WIRE_DUALOPEND_PEER_LOCKED = 7018, /* dualopend->master this channel has been locked */ WIRE_DUALOPEND_CHANNEL_LOCKED = 7019, /* master->dualopend funding reached depth; tell peer */ @@ -54,6 +56,8 @@ enum dualopend_wire { WIRE_DUALOPEND_SEND_SHUTDOWN = 7023, /* Peer told us that channel is shutting down */ WIRE_DUALOPEND_GOT_SHUTDOWN = 7024, + /* Peer presented proof it was from the future. */ + WIRE_DUALOPEND_FAIL_FALLEN_BEHIND = 1028, /* Shutdown is complete */ WIRE_DUALOPEND_SHUTDOWN_COMPLETE = 7025, /* master -> dualopend: do you have a memleak? */ @@ -138,10 +142,15 @@ bool fromwire_dualopend_send_tx_sigs(const tal_t *ctx, const void *p, struct wal u8 *towire_dualopend_tx_sigs_sent(const tal_t *ctx); bool fromwire_dualopend_tx_sigs_sent(const void *p); +/* WIRE: DUALOPEND_PEER_LOCKED */ +/* dualopend->peer peer locked channel */ +u8 *towire_dualopend_peer_locked(const tal_t *ctx, const struct pubkey *remote_per_commit); +bool fromwire_dualopend_peer_locked(const void *p, struct pubkey *remote_per_commit); + /* WIRE: DUALOPEND_CHANNEL_LOCKED */ /* dualopend->master this channel has been locked */ -u8 *towire_dualopend_channel_locked(const tal_t *ctx, const struct per_peer_state *pps, const struct pubkey *remote_per_commit); -bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct per_peer_state **pps, struct pubkey *remote_per_commit); +u8 *towire_dualopend_channel_locked(const tal_t *ctx, const struct per_peer_state *pps); +bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct per_peer_state **pps); /* WIRE: DUALOPEND_DEPTH_REACHED */ /* master->dualopend funding reached depth; tell peer */ @@ -158,6 +167,11 @@ bool fromwire_dualopend_send_shutdown(const tal_t *ctx, const void *p, u8 **shut u8 *towire_dualopend_got_shutdown(const tal_t *ctx, const u8 *scriptpubkey); bool fromwire_dualopend_got_shutdown(const tal_t *ctx, const void *p, u8 **scriptpubkey); +/* WIRE: DUALOPEND_FAIL_FALLEN_BEHIND */ +/* Peer presented proof it was from the future. */ +u8 *towire_dualopend_fail_fallen_behind(const tal_t *ctx); +bool fromwire_dualopend_fail_fallen_behind(const void *p); + /* WIRE: DUALOPEND_SHUTDOWN_COMPLETE */ /* Shutdown is complete */ u8 *towire_dualopend_shutdown_complete(const tal_t *ctx, const struct per_peer_state *per_peer_state); @@ -174,4 +188,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak); #endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */ -// SHA256STAMP:02f28abef3ab5503d52f776543a85f6d5682637a8e9f8494beae16ff44896442 +// SHA256STAMP:4410d5ca881f7d981e8eebf77c0acf69f5a5113eaec626251d51f21d8f16a649