diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index af91c20f4..c8d57cfdd 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -542,6 +542,94 @@ static void handle_splice_confirmed_signed(struct lightningd *ld, send_splice_tx(channel, tx, cc, output_index); } +bool depthcb_update_scid(struct channel *channel, + const struct bitcoin_txid *txid) +{ + struct txlocator *loc; + struct lightningd *ld = channel->peer->ld; + struct short_channel_id scid; + + /* What scid is this giving us? */ + loc = wallet_transaction_locate(tmpctx, ld->wallet, txid); + if (!mk_short_channel_id(&scid, + loc->blkheight, loc->index, + channel->funding.n)) { + channel_fail_permanent(channel, + REASON_LOCAL, + "Invalid funding scid %u:%u:%u", + loc->blkheight, loc->index, + channel->funding.n); + return false; + } + + if (!channel->scid) { + wallet_annotate_txout(ld->wallet, &channel->funding, + TX_CHANNEL_FUNDING, channel->dbid); + channel->scid = tal_dup(channel, struct short_channel_id, &scid); + + /* If we have a zeroconf channel, i.e., no scid yet + * but have exchange `channel_ready` messages, then we + * need to fire a second time, in order to trigger the + * `coin_movement` event. This is a subset of the + * `lockin_complete` function called from + * AWAITING_LOCKIN->NORMAL otherwise. */ + if (channel->minimum_depth == 0) + lockin_has_completed(channel, false); + + wallet_channel_save(ld->wallet, channel); + } else if (!short_channel_id_eq(channel->scid, &scid)) { + /* We freaked out if required when original was + * removed, so just update now */ + log_info(channel->log, "Short channel id changed from %s->%s", + type_to_string(tmpctx, struct short_channel_id, channel->scid), + type_to_string(tmpctx, struct short_channel_id, &scid)); + *channel->scid = scid; + wallet_channel_save(ld->wallet, channel); + } + + return true; +} + +static enum watch_result splice_depth_cb(struct lightningd *ld, + const struct bitcoin_txid *txid, + const struct bitcoin_tx *tx, + unsigned int depth, + struct channel_inflight *inflight) +{ + /* Usually, we're here because we're awaiting a splice, but + * we could also mutual shutdown, or that weird splice_locked_memonly + * hack... */ + if (inflight->channel->state != CHANNELD_AWAITING_SPLICE) + return DELETE_WATCH; + + /* Reorged out? OK, we're not committed yet. */ + if (depth == 0) + return KEEP_WATCHING; + + if (!depthcb_update_scid(inflight->channel, txid)) + return DELETE_WATCH; + + if (inflight->channel->owner) { + subd_send_msg(inflight->channel->owner, + take(towire_channeld_funding_depth( + NULL, inflight->channel->scid, + inflight->channel->alias[LOCAL], + depth, true, txid))); + } + + /* channeld will tell us when splice is locked in: we'll clean + * this watch up then. */ + return KEEP_WATCHING; +} + +void watch_splice_inflight(struct lightningd *ld, + struct channel_inflight *inflight) +{ + watch_txid(inflight, ld->topology, + &inflight->funding->outpoint.txid, + splice_depth_cb, inflight); +} + static void handle_add_inflight(struct lightningd *ld, struct channel *channel, const u8 *msg) @@ -596,7 +684,7 @@ static void handle_add_inflight(struct lightningd *ld, &inflight->funding->outpoint.txid)); wallet_inflight_add(ld->wallet, inflight); - channel_watch_inflight(ld, channel, inflight); + watch_splice_inflight(ld, inflight); subd_send_msg(channel->owner, take(towire_channeld_got_inflight(NULL))); } @@ -830,6 +918,9 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) wallet_channel_clear_inflights(channel->peer->ld->wallet, channel); + /* That freed watchers in inflights: now watch funding tx */ + channel_watch_funding(channel->peer->ld, channel); + /* Put the successful inflight back in as a memory-only object. * peer_control's funding_spent function will pick this up and clean up * our inflight. diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index 1bdba2558..85ddf7069 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -53,4 +53,12 @@ void lockin_complete(struct channel *channel, /* Accessor for zeroconf to tell us we've actually got an scid */ void lockin_has_completed(struct channel *channel, bool record_push); + +/* Watch this incoming splice */ +void watch_splice_inflight(struct lightningd *ld, + struct channel_inflight *inflight); + +/* Update/set scid now this txid is mined. */ +bool depthcb_update_scid(struct channel *channel, + const struct bitcoin_txid *txid); #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_CONTROL_H */ diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 8e19c2671..ac582fef0 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -953,6 +953,68 @@ openchannel2_signed_deserialize(struct openchannel2_psbt_payload *payload, return true; } +static enum watch_result opening_depth_cb(struct lightningd *ld, + const struct bitcoin_txid *txid, + const struct bitcoin_tx *tx, + unsigned int depth, + struct channel_inflight *inflight) +{ + struct txlocator *loc; + struct short_channel_id scid; + + /* Usually, we're here because we're awaiting a lockin, but + * we could also mutual shutdown */ + if (inflight->channel->state != DUALOPEND_AWAITING_LOCKIN) + return DELETE_WATCH; + + /* Reorged out? OK, we're not committed yet. */ + if (depth == 0) + return KEEP_WATCHING; + + /* FIXME: Don't do this until we're actually locked in! */ + loc = wallet_transaction_locate(tmpctx, ld->wallet, txid); + if (!mk_short_channel_id(&scid, + loc->blkheight, loc->index, + inflight->funding->outpoint.n)) { + channel_fail_permanent(inflight->channel, + REASON_LOCAL, + "Invalid funding scid %u:%u:%u", + loc->blkheight, loc->index, + inflight->funding->outpoint.n); + return DELETE_WATCH; + } + + if (!inflight->channel->scid) { + wallet_annotate_txout(ld->wallet, &inflight->funding->outpoint, + TX_CHANNEL_FUNDING, inflight->channel->dbid); + inflight->channel->scid = tal_dup(inflight->channel, struct short_channel_id, &scid); + wallet_channel_save(ld->wallet, inflight->channel); + } else if (!short_channel_id_eq(inflight->channel->scid, &scid)) { + /* We freaked out if required when original was + * removed, so just update now */ + log_info(inflight->channel->log, "Short channel id changed from %s->%s", + type_to_string(tmpctx, struct short_channel_id, inflight->channel->scid), + type_to_string(tmpctx, struct short_channel_id, &scid)); + *inflight->channel->scid = scid; + wallet_channel_save(ld->wallet, inflight->channel); + } + + dualopend_tell_depth(inflight->channel, txid, depth); + + if (depth >= inflight->channel->minimum_depth) + update_channel_from_inflight(ld, inflight->channel, inflight); + + return KEEP_WATCHING; +} + +void watch_opening_inflight(struct lightningd *ld, + struct channel_inflight *inflight) +{ + watch_txid(inflight, ld->topology, + &inflight->funding->outpoint.txid, + opening_depth_cb, inflight); +} + static void openchannel2_sign_hook_cb(struct openchannel2_psbt_payload *payload STEALS) { @@ -1007,7 +1069,7 @@ openchannel2_sign_hook_cb(struct openchannel2_psbt_payload *payload STEALS) cast_const(struct wally_psbt *, payload->psbt)); wallet_inflight_save(payload->ld->wallet, inflight); - channel_watch_funding(payload->ld, channel); + watch_opening_inflight(payload->ld, inflight); msg = towire_dualopend_send_tx_sigs(NULL, inflight->funding_psbt); send_msg: @@ -1835,6 +1897,9 @@ static void handle_channel_locked(struct subd *dualopend, /* Empty out the inflights */ wallet_channel_clear_inflights(dualopend->ld->wallet, channel); + /* That freed watchers in inflights: now watch funding tx */ + channel_watch_funding(dualopend->ld, channel); + /* FIXME: LND sigs/update_fee msgs? */ peer_start_channeld(channel, peer_fd, NULL, false, NULL); return; @@ -2611,8 +2676,7 @@ json_openchannel_signed(struct command *cmd, /* Update the PSBT on disk */ wallet_inflight_save(cmd->ld->wallet, inflight); - /* Uses the channel->funding_txid, which we verified above */ - channel_watch_funding(cmd->ld, channel); + watch_opening_inflight(cmd->ld, inflight); /* Send our tx_sigs to the peer */ subd_send_msg(channel->owner, diff --git a/lightningd/dual_open_control.h b/lightningd/dual_open_control.h index 8bacce793..80a2d7ab1 100644 --- a/lightningd/dual_open_control.h +++ b/lightningd/dual_open_control.h @@ -18,6 +18,9 @@ void dualopend_tell_depth(struct channel *channel, const struct bitcoin_txid *txid, u32 depth); +void watch_opening_inflight(struct lightningd *ld, + struct channel_inflight *inflight); + /* Close connection to an unsaved channel */ void channel_unsaved_close_conn(struct channel *channel, const char *why); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index c80f9c8da..b987d953d 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -350,7 +350,6 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel, resolve_close_command(ld, channel, cooperative, tx); } - } void resend_closing_transactions(struct lightningd *ld) @@ -1883,9 +1882,6 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, unsigned int depth, struct channel *channel) { - struct short_channel_id scid; - struct txlocator *loc; - /* This is stub channel, we don't activate anything! */ if (is_stub_scid(channel->scid)) return DELETE_WATCH; @@ -1954,43 +1950,8 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, return KEEP_WATCHING; } - /* What scid is this giving us? */ - loc = wallet_transaction_locate(tmpctx, ld->wallet, txid); - if (!mk_short_channel_id(&scid, - loc->blkheight, loc->index, - channel->funding.n)) { - channel_fail_permanent(channel, - REASON_LOCAL, - "Invalid funding scid %u:%u:%u", - loc->blkheight, loc->index, - channel->funding.n); + if (!depthcb_update_scid(channel, txid)) return DELETE_WATCH; - } - - if (!channel->scid) { - wallet_annotate_txout(ld->wallet, &channel->funding, - TX_CHANNEL_FUNDING, channel->dbid); - channel->scid = tal_dup(channel, struct short_channel_id, &scid); - - /* If we have a zeroconf channel, i.e., no scid yet - * but have exchange `channel_ready` messages, then we - * need to fire a second time, in order to trigger the - * `coin_movement` event. This is a subset of the - * `lockin_complete` function called from - * AWAITING_LOCKIN->NORMAL otherwise. */ - if (channel->minimum_depth == 0) - lockin_has_completed(channel, false); - - wallet_channel_save(ld->wallet, channel); - } else if (!short_channel_id_eq(channel->scid, &scid)) { - /* We freaked out if required when original was - * removed, so just update now */ - log_info(channel->log, "Short channel id changed from %s->%s", - type_to_string(tmpctx, struct short_channel_id, channel->scid), - type_to_string(tmpctx, struct short_channel_id, &scid)); - *channel->scid = scid; - wallet_channel_save(ld->wallet, channel); - } /* Always tell owner about depth change */ subd_tell_depth(channel, txid, depth); @@ -2115,17 +2076,6 @@ void channel_watch_funding(struct lightningd *ld, struct channel *channel) channel_watch_wrong_funding(ld, channel); } -void channel_watch_inflight(struct lightningd *ld, - struct channel *channel, - struct channel_inflight *inflight) -{ - watch_txid(channel, ld->topology, - &inflight->funding->outpoint.txid, funding_depth_cb, channel); - watch_txo(channel, ld->topology, channel, - &inflight->funding->outpoint, - funding_spent); -} - static void json_add_peer(struct lightningd *ld, struct json_stream *response, struct peer *p, @@ -2381,21 +2331,39 @@ static void setup_peer(struct peer *peer, u32 delay) bool connect = false; list_for_each(&peer->channels, channel, list) { - if (channel_state_uncommitted(channel->state)) + switch (channel->state) { + case DUALOPEND_OPEN_INIT: + case DUALOPEND_OPEN_COMMITTED: + /* Nothing to watch */ continue; - /* Watching lockin may be unnecessary, but it's harmless. */ - channel_watch_funding(ld, channel); - /* Also watch any inflight txs */ - list_for_each(&channel->inflights, inflight, list) { - /* Don't double watch the txid that's also in - * channel->funding_txid */ - if (bitcoin_txid_eq(&channel->funding.txid, - &inflight->funding->outpoint.txid)) - continue; + /* Normal cases where we watch funding */ + case CHANNELD_AWAITING_LOCKIN: + case CHANNELD_NORMAL: + case CHANNELD_SHUTTING_DOWN: + case CLOSINGD_SIGEXCHANGE: + /* We still want to watch spend, to tell onchaind: */ + case CLOSINGD_COMPLETE: + case AWAITING_UNILATERAL: + case FUNDING_SPEND_SEEN: + case ONCHAIN: + case CLOSED: + channel_watch_funding(ld, channel); + break; - channel_watch_inflight(ld, channel, inflight); + /* We need to watch all inflights which may open channel */ + case DUALOPEND_AWAITING_LOCKIN: + list_for_each(&channel->inflights, inflight, list) + watch_opening_inflight(ld, inflight); + break; + + /* We need to watch all inflights which may splice */ + case CHANNELD_AWAITING_SPLICE: + list_for_each(&channel->inflights, inflight, list) + watch_splice_inflight(ld, inflight); + break; } + if (channel_state_wants_peercomms(channel->state)) connect = true; } diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index e92a20a75..32d5b2c5a 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -116,9 +116,7 @@ void update_channel_from_inflight(struct lightningd *ld, const struct channel_inflight *inflight); void channel_watch_funding(struct lightningd *ld, struct channel *channel); -void channel_watch_inflight(struct lightningd *ld, - struct channel *channel, - struct channel_inflight *inflight); + /* If this channel has a "wrong funding" shutdown, watch that too. */ void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 3c9fc3013..bc7c511ad 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -198,6 +198,10 @@ void db_commit_transaction(struct db *db UNNEEDED) /* Generated stub for delete_channel */ void delete_channel(struct channel *channel STEALS UNNEEDED) { fprintf(stderr, "delete_channel called!\n"); abort(); } +/* Generated stub for depthcb_update_scid */ +bool depthcb_update_scid(struct channel *channel UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "depthcb_update_scid called!\n"); abort(); } /* Generated stub for dev_disconnect_permanent */ bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED) { fprintf(stderr, "dev_disconnect_permanent called!\n"); abort(); } @@ -654,9 +658,6 @@ void kill_uncommitted_channel(struct uncommitted_channel *uc UNNEEDED, void lockin_complete(struct channel *channel UNNEEDED, enum channel_state expected_state UNNEEDED) { fprintf(stderr, "lockin_complete called!\n"); abort(); } -/* Generated stub for lockin_has_completed */ -void lockin_has_completed(struct channel *channel UNNEEDED, bool record_push UNNEEDED) -{ fprintf(stderr, "lockin_has_completed called!\n"); abort(); } /* Generated stub for log_ */ void log_(struct logger *logger UNNEEDED, enum log_level level UNNEEDED, const struct node_id *node_id UNNEEDED, @@ -952,11 +953,6 @@ void try_reconnect(const tal_t *ctx UNNEEDED, /* Generated stub for version */ const char *version(void) { fprintf(stderr, "version called!\n"); abort(); } -/* Generated stub for wallet_annotate_txout */ -void wallet_annotate_txout(struct wallet *w UNNEEDED, - const struct bitcoin_outpoint *outpoint UNNEEDED, - enum wallet_tx_type type UNNEEDED, u64 channel UNNEEDED) -{ fprintf(stderr, "wallet_annotate_txout called!\n"); abort(); } /* Generated stub for wallet_channel_save */ void wallet_channel_save(struct wallet *w UNNEEDED, struct channel *chan UNNEEDED) { fprintf(stderr, "wallet_channel_save called!\n"); abort(); } @@ -1005,10 +1001,14 @@ struct amount_msat wallet_total_forward_fees(struct wallet *w UNNEEDED) void wallet_transaction_add(struct wallet *w UNNEEDED, const struct wally_tx *tx UNNEEDED, const u32 blockheight UNNEEDED, const u32 txindex UNNEEDED) { fprintf(stderr, "wallet_transaction_add called!\n"); abort(); } -/* Generated stub for wallet_transaction_locate */ -struct txlocator *wallet_transaction_locate(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED, - const struct bitcoin_txid *txid UNNEEDED) -{ fprintf(stderr, "wallet_transaction_locate called!\n"); abort(); } +/* Generated stub for watch_opening_inflight */ +void watch_opening_inflight(struct lightningd *ld UNNEEDED, + struct channel_inflight *inflight UNNEEDED) +{ fprintf(stderr, "watch_opening_inflight called!\n"); abort(); } +/* Generated stub for watch_splice_inflight */ +void watch_splice_inflight(struct lightningd *ld UNNEEDED, + struct channel_inflight *inflight UNNEEDED) +{ fprintf(stderr, "watch_splice_inflight called!\n"); abort(); } /* Generated stub for watch_txid_ */ struct txwatch *watch_txid_(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index c6c58384f..d47886ddb 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -139,6 +139,10 @@ struct onionreply *create_onionreply(const tal_t *ctx UNNEEDED, const struct secret *shared_secret UNNEEDED, const u8 *failure_msg UNNEEDED) { fprintf(stderr, "create_onionreply called!\n"); abort(); } +/* Generated stub for depthcb_update_scid */ +bool depthcb_update_scid(struct channel *channel UNNEEDED, + const struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "depthcb_update_scid called!\n"); abort(); } /* Generated stub for derive_channel_id */ void derive_channel_id(struct channel_id *channel_id UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED) @@ -442,9 +446,6 @@ void kill_uncommitted_channel(struct uncommitted_channel *uc UNNEEDED, void lockin_complete(struct channel *channel UNNEEDED, enum channel_state expected_state UNNEEDED) { fprintf(stderr, "lockin_complete called!\n"); abort(); } -/* Generated stub for lockin_has_completed */ -void lockin_has_completed(struct channel *channel UNNEEDED, bool record_push UNNEEDED) -{ fprintf(stderr, "lockin_has_completed called!\n"); abort(); } /* Generated stub for logv */ void logv(struct logger *logger UNNEEDED, enum log_level level UNNEEDED, const struct node_id *node_id UNNEEDED, bool call_notifier UNNEEDED, const char *fmt UNNEEDED, va_list ap UNNEEDED) @@ -898,6 +899,14 @@ const char *wait_index_name(enum wait_index index UNNEEDED) /* Generated stub for wait_subsystem_name */ const char *wait_subsystem_name(enum wait_subsystem subsystem UNNEEDED) { fprintf(stderr, "wait_subsystem_name called!\n"); abort(); } +/* Generated stub for watch_opening_inflight */ +void watch_opening_inflight(struct lightningd *ld UNNEEDED, + struct channel_inflight *inflight UNNEEDED) +{ fprintf(stderr, "watch_opening_inflight called!\n"); abort(); } +/* Generated stub for watch_splice_inflight */ +void watch_splice_inflight(struct lightningd *ld UNNEEDED, + struct channel_inflight *inflight UNNEEDED) +{ fprintf(stderr, "watch_splice_inflight called!\n"); abort(); } /* Generated stub for watch_txid_ */ struct txwatch *watch_txid_(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED,