From 537eeab20872e4e3cbc2e5ed8d5352e663d15d6e Mon Sep 17 00:00:00 2001 From: niftynei Date: Thu, 10 Sep 2020 14:41:42 -0500 Subject: [PATCH] df-open: add a 'open_commands' list to stash pending opens around in `openchannel_signed` commands hang out across the openingd/channeld boundary -- we don't return until we've successfully broadcast the transaction (or timed out waiting for them to send a tx_sigs back). --- lightningd/lightningd.c | 1 + lightningd/lightningd.h | 2 ++ lightningd/peer_control.c | 73 +++++++++++++++++++++++++++++++++++++++ lightningd/peer_control.h | 11 ++++++ 4 files changed, 87 insertions(+) diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 4ddca8b57..6c2e37e2e 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -195,6 +195,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx) list_head_init(&ld->waitsendpay_commands); list_head_init(&ld->sendpay_commands); list_head_init(&ld->close_commands); + list_head_init(&ld->open_commands); list_head_init(&ld->ping_commands); list_head_init(&ld->waitblockheight_commands); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 0ce16ccff..ef954237b 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -178,6 +178,8 @@ struct lightningd { struct list_head sendpay_commands; /* Outstanding close commands. */ struct list_head close_commands; + /* Outstanding openchannel_signed commands. */ + struct list_head open_commands; /* Outstanding ping commands. */ struct list_head ping_commands; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 118ab21b1..19cd91ea1 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -74,6 +74,17 @@ struct close_command { bool force; }; +struct open_command { + /* Inside struct lightningd open_commands. */ + struct list_node list; + /* Command structure. This is the parent of the open command. */ + struct command *cmd; + /* Channel being opened. */ + struct channel *channel; + /* PSBT in flight */ + struct wally_psbt *psbt; +}; + static void destroy_peer(struct peer *peer) { list_del_from(&peer->ld->peers, &peer->list); @@ -324,6 +335,68 @@ register_close_command(struct lightningd *ld, &close_command_timeout, cc); } +/* Destroy the open command structure in reaction to the + * channel being destroyed. */ +static void +destroy_open_command_on_channel_destroy(struct channel *_ UNUSED, + struct open_command *oc) +{ + /* The oc has the command as parent, so resolving the + * command destroys the oc and triggers destroy_open_command. + * Clear the oc->channel first so that we will not try to + * remove a destructor. */ + oc->channel = NULL; + was_pending(command_fail(oc->cmd, LIGHTNINGD, + "Channel forgotten before open concluded.")); +} + +/* Destroy the open command structure. */ +static void +destroy_open_command(struct open_command *oc) +{ + list_del(&oc->list); + /* If destroy_close_command_on_channel_destroy was + * triggered beforehand, it will have cleared + * the channel field, preventing us from removing it + * from an already-destroyed channel. */ + if (!oc->channel) + return; + tal_del_destructor2(oc->channel, + &destroy_open_command_on_channel_destroy, + oc); +} + +struct open_command *find_open_command(struct lightningd *ld, + struct channel *channel) +{ + struct open_command *oc, *n; + + list_for_each_safe (&ld->open_commands, oc, n, list) { + if (oc->channel != channel) + continue; + return oc; + } + + return NULL; +} + +void register_open_command(struct lightningd *ld, + struct command *cmd, + struct channel *channel) +{ + struct open_command *oc; + assert(channel); + + oc = tal(cmd, struct open_command); + list_add_tail(&ld->open_commands, &oc->list); + oc->cmd = cmd; + oc->channel = channel; + tal_add_destructor(oc, &destroy_open_command); + tal_add_destructor2(channel, + &destroy_open_command_on_channel_destroy, + oc); +} + static bool invalid_last_tx(const struct bitcoin_tx *tx) { /* This problem goes back further, but was discovered just before the diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index d6b107698..10619a6de 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -16,6 +16,7 @@ #include struct per_peer_state; +struct wally_psbt; struct peer { /* Inside ld->peers. */ @@ -89,6 +90,16 @@ void channel_watch_funding(struct lightningd *ld, struct channel *channel); struct amount_msat channel_amount_receivable(const struct channel *channel); +/* Find the open command that was registered for this channel */ +struct open_command *find_open_command(struct lightningd *ld, + struct channel *channel); + +/* Save an `openchannel_signed` command */ +void register_open_command(struct lightningd *ld, + struct command *cmd, + struct channel *channel); + + /* Pull peers, channels and HTLCs from db, and wire them up. * Returns any HTLCs we have to resubmit via htlcs_resubmit. */ struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld);