From 7b3a4799dbee2c8f2c66c6c9c7fb238707115124 Mon Sep 17 00:00:00 2001 From: niftynei Date: Tue, 6 Aug 2024 00:11:47 -0500 Subject: [PATCH] coin-moves: when a splice confirms, send a channel_closed event We weren't properly notifying that a channel output has been spent in the case of it being spent in a splice. This fixes the notification side of the equation, however there's still some issues remaining for the bookkeeper side (to come). Changelog-Fixed: We now send a `coin_movement` notification for splice confirmations of channel funding outpoint spends. --- common/coin_mvt.c | 19 +++++++++-- common/coin_mvt.h | 9 +++-- lightningd/channel_control.c | 49 ++++++++++++++++++++++++--- onchaind/onchaind.c | 5 +-- onchaind/test/run-grind_feerate-bug.c | 4 ++- onchaind/test/run-grind_feerate.c | 4 ++- plugins/bkpr/recorder.c | 1 + wallet/test/run-wallet.c | 2 +- 8 files changed, 77 insertions(+), 16 deletions(-) diff --git a/common/coin_mvt.c b/common/coin_mvt.c index 504f3b9fb..c28d71f62 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -40,6 +40,7 @@ static const char *mvt_tags[] = { "leased", "stealable", "channel_proposed", + "splice", }; const char *mvt_tag_str(enum mvt_tag tag) @@ -177,19 +178,31 @@ struct chain_coin_mvt *new_onchaind_deposit(const tal_t *ctx, } struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, + const struct channel_id *chan_id, const struct bitcoin_txid *txid, const struct bitcoin_outpoint *out, u32 blockheight, const struct amount_msat amount, const struct amount_sat output_val, - u32 output_count) + u32 output_count, + bool is_splice) { - return new_chain_coin_mvt(ctx, NULL, txid, + struct chain_coin_mvt *mvt; + enum mvt_tag *tags = new_tag_arr(NULL, CHANNEL_CLOSE); + + if (is_splice) + tal_arr_expand(&tags, SPLICE); + + mvt = new_chain_coin_mvt(ctx, NULL, txid, out, NULL, blockheight, - take(new_tag_arr(NULL, CHANNEL_CLOSE)), + take(tags), amount, false, output_val, output_count); + if (chan_id) + mvt->account_name = fmt_channel_id(mvt, chan_id); + + return mvt; } struct chain_coin_mvt *new_coin_channel_open_proposed(const tal_t *ctx, diff --git a/common/coin_mvt.h b/common/coin_mvt.h index d35340073..9b34c69a9 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -14,7 +14,7 @@ enum mvt_type { CHANNEL_MVT = 1, }; -#define NUM_MVT_TAGS (CHANNEL_PROPOSED + 1) +#define NUM_MVT_TAGS (SPLICE + 1) enum mvt_tag { DEPOSIT = 0, WITHDRAWAL = 1, @@ -40,6 +40,7 @@ enum mvt_tag { LEASED = 21, STEALABLE = 22, CHANNEL_PROPOSED = 23, + SPLICE = 24, }; struct channel_coin_mvt { @@ -181,13 +182,15 @@ struct chain_coin_mvt *new_onchaind_deposit(const tal_t *ctx, NON_NULL_ARGS(2); struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, + const struct channel_id *chan_id, const struct bitcoin_txid *txid, const struct bitcoin_outpoint *out, u32 blockheight, const struct amount_msat amount, const struct amount_sat output_val, - u32 output_count) - NON_NULL_ARGS(2, 3); + u32 output_count, + bool is_splice) + NON_NULL_ARGS(3, 4); struct chain_coin_mvt *new_coin_channel_open_proposed(const tal_t *ctx, const struct channel_id *chan_id, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index ad354de41..67f29ef3a 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -912,6 +912,27 @@ static void handle_update_inflight(struct lightningd *ld, wallet_inflight_save(ld->wallet, inflight); } +static void channel_record_splice(struct channel *channel, + struct amount_msat orig_our_msats, + struct amount_sat orig_funding_sats, + struct bitcoin_outpoint *funding, + u32 blockheight, struct bitcoin_txid *txid, const struct channel_inflight *inflight) +{ + struct chain_coin_mvt *mvt; + u32 output_count; + + output_count = inflight->funding_psbt->num_outputs; + mvt = new_coin_channel_close(tmpctx, &channel->cid, + txid, + funding, + blockheight, + orig_our_msats, + orig_funding_sats, + output_count, + /* is_splice = */true); + notify_chain_mvt(channel->peer->ld, mvt); +} + void channel_record_open(struct channel *channel, u32 blockheight, bool record_push) { struct chain_coin_mvt *mvt; @@ -1039,7 +1060,9 @@ bool channel_on_channel_ready(struct channel *channel, static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) { - struct amount_sat funding_sats; + struct amount_sat funding_sats, prev_funding_sats; + struct amount_msat prev_our_msats; + struct bitcoin_outpoint prev_funding_out; s64 splice_amnt; struct channel_inflight *inflight; struct bitcoin_txid locked_txid; @@ -1054,16 +1077,22 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) return; } - channel->our_msat.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ - channel->msat_to_us_min.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ - channel->msat_to_us_max.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ - inflight = channel_inflight_find(channel, &locked_txid); if(!inflight) channel_internal_error(channel, "Unable to load inflight for" " locked_txid %s", fmt_bitcoin_txid(tmpctx, &locked_txid)); + /* Stash prev funding data so we can log it after scid is updated + * (to get the blockheight) */ + prev_our_msats = channel->our_msat; + prev_funding_sats = channel->funding_sats; + prev_funding_out = channel->funding; + + channel->our_msat.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ + channel->msat_to_us_min.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ + channel->msat_to_us_max.millisatoshis += splice_amnt * 1000; /* Raw: splicing */ + wallet_htlcsigs_confirm_inflight(channel->peer->ld->wallet, channel, &inflight->funding->outpoint); @@ -1085,6 +1114,16 @@ static void handle_peer_splice_locked(struct channel *channel, const u8 *msg) /* That freed watchers in inflights: now watch funding tx */ channel_watch_funding(channel->peer->ld, channel); + /* Log that funding output has been spent */ + channel_record_splice(channel, + prev_our_msats, + prev_funding_sats, + &prev_funding_out, + channel->scid ? + short_channel_id_blocknum(*channel->scid) : 0, + &locked_txid, + inflight); + /* 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/onchaind/onchaind.c b/onchaind/onchaind.c index e9d61f37e..d721e61f0 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -3463,14 +3463,15 @@ int main(int argc, char *argv[]) FUNDING_OUTPUT, NULL, NULL, NULL); /* Record funding output spent */ - send_coin_mvt(take(new_coin_channel_close(NULL, &tx->txid, + send_coin_mvt(take(new_coin_channel_close(NULL, NULL, &tx->txid, &funding, tx_blockheight, our_msat, funding_sats, is_elements(chainparams) ? /* Minus 1, fee output */ tal_count(tx->outputs) - 1 : - tal_count(tx->outputs)))); + tal_count(tx->outputs), + /* is_splice? */ false))); status_debug("Remote per-commit point: %s", fmt_pubkey(tmpctx, &remote_per_commit_point)); diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index 8be39f6c9..30a31b0b8 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -103,12 +103,14 @@ void memleak_status_broken(void *unused UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "memleak_status_broken called!\n"); abort(); } /* Generated stub for new_coin_channel_close */ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED, + const struct channel_id *chan_id UNNEEDED, const struct bitcoin_txid *txid UNNEEDED, const struct bitcoin_outpoint *out UNNEEDED, u32 blockheight UNNEEDED, const struct amount_msat amount UNNEEDED, const struct amount_sat output_val UNNEEDED, - u32 output_count) + u32 output_count UNNEEDED, + bool is_splice) { fprintf(stderr, "new_coin_channel_close called!\n"); abort(); } /* Generated stub for new_coin_external_deposit */ diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index f39039926..bc10c960a 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -153,12 +153,14 @@ void memleak_status_broken(void *unused UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "memleak_status_broken called!\n"); abort(); } /* Generated stub for new_coin_channel_close */ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED, + const struct channel_id *chan_id UNNEEDED, const struct bitcoin_txid *txid UNNEEDED, const struct bitcoin_outpoint *out UNNEEDED, u32 blockheight UNNEEDED, const struct amount_msat amount UNNEEDED, const struct amount_sat output_val UNNEEDED, - u32 output_count) + u32 output_count UNNEEDED, + bool is_splice) { fprintf(stderr, "new_coin_channel_close called!\n"); abort(); } /* Generated stub for new_coin_external_deposit */ diff --git a/plugins/bkpr/recorder.c b/plugins/bkpr/recorder.c index 00f388fd8..e7dd9b4d3 100644 --- a/plugins/bkpr/recorder.c +++ b/plugins/bkpr/recorder.c @@ -1294,6 +1294,7 @@ void maybe_update_account(struct db *db, case TO_MINER: case LEASE_FEE: case STEALABLE: + case SPLICE: /* Ignored */ break; } diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index b6f0791a9..8d45c180e 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1002,7 +1002,7 @@ void topology_add_sync_waiter_(const tal_t *ctx UNNEEDED, u8 *towire_announcement_signatures(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, struct short_channel_id short_channel_id UNNEEDED, const secp256k1_ecdsa_signature *node_signature UNNEEDED, const secp256k1_ecdsa_signature *bitcoin_signature UNNEEDED) { fprintf(stderr, "towire_announcement_signatures called!\n"); abort(); } /* Generated stub for towire_channel_reestablish */ -u8 *towire_channel_reestablish(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u64 next_commitment_number UNNEEDED, u64 next_revocation_number UNNEEDED, const struct secret *your_last_per_commitment_secret UNNEEDED, const struct pubkey *my_current_per_commitment_point UNNEEDED, const struct tlv_channel_reestablish_tlvs *channel_reestablish UNNEEDED) +u8 *towire_channel_reestablish(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u64 next_commitment_number UNNEEDED, u64 next_revocation_number UNNEEDED, const struct secret *your_last_per_commitment_secret UNNEEDED, const struct pubkey *my_current_per_commitment_point UNNEEDED, const struct tlv_channel_reestablish_tlvs *tlvs UNNEEDED) { fprintf(stderr, "towire_channel_reestablish called!\n"); abort(); } /* Generated stub for towire_channeld_dev_memleak */ u8 *towire_channeld_dev_memleak(const tal_t *ctx UNNEEDED)