diff --git a/common/coin_mvt.c b/common/coin_mvt.c index 1d77e9b9b..c0ca08777 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -91,7 +91,8 @@ static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx, enum mvt_tag *tags TAKES, struct amount_msat amount, bool is_credit, - struct amount_sat output_val) + struct amount_sat output_val, + u32 out_count) { struct chain_coin_mvt *mvt = tal(ctx, struct chain_coin_mvt); @@ -118,7 +119,9 @@ static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx, mvt->debit = amount; mvt->credit = AMOUNT_MSAT(0); } + mvt->output_val = output_val; + mvt->output_count = out_count; return mvt; } @@ -143,7 +146,7 @@ static struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx, blockheight, tags, amt_msat, is_credit, /* All amounts that are sat are * on-chain output values */ - amt_sat); + amt_sat, 0); } struct chain_coin_mvt *new_onchaind_withdraw(const tal_t *ctx, @@ -178,13 +181,15 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, const struct bitcoin_outpoint *out, u32 blockheight, const struct amount_msat amount, - const struct amount_sat output_val) + const struct amount_sat output_val, + u32 output_count) { return new_chain_coin_mvt(ctx, NULL, txid, out, NULL, blockheight, take(new_tag_arr(NULL, CHANNEL_CLOSE)), amount, false, - output_val); + output_val, + output_count); } struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, @@ -200,7 +205,7 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, mvt = new_chain_coin_mvt(ctx, NULL, NULL, out, NULL, blockheight, take(new_tag_arr(NULL, CHANNEL_OPEN)), amount, - true, output_val); + true, output_val, 0); mvt->account_name = type_to_string(mvt, struct channel_id, chan_id); /* If we're the opener, add to the tag list */ @@ -252,7 +257,7 @@ struct chain_coin_mvt *new_coin_external_spend(const tal_t *ctx, return new_chain_coin_mvt(ctx, EXTERNAL, txid, outpoint, NULL, blockheight, take(new_tag_arr(NULL, tag)), - AMOUNT_MSAT(0), true, amount); + AMOUNT_MSAT(0), true, amount, 0); } struct chain_coin_mvt *new_coin_external_deposit(const tal_t *ctx, @@ -334,6 +339,7 @@ struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, mvt->output_val = tal(mvt, struct amount_sat); *mvt->output_val = chain_mvt->output_val; + mvt->output_count = chain_mvt->output_count; mvt->fees = NULL; mvt->timestamp = timestamp; @@ -366,6 +372,7 @@ struct coin_mvt *finalize_channel_mvt(const tal_t *ctx, mvt->credit = chan_mvt->credit; mvt->debit = chan_mvt->debit; mvt->output_val = NULL; + mvt->output_count = 0; mvt->fees = tal(mvt, struct amount_msat); *mvt->fees = chan_mvt->fees; mvt->timestamp = timestamp; @@ -413,6 +420,7 @@ void towire_chain_coin_mvt(u8 **pptr, const struct chain_coin_mvt *mvt) towire_amount_msat(pptr, mvt->credit); towire_amount_msat(pptr, mvt->debit); towire_amount_sat(pptr, mvt->output_val); + towire_u32(pptr, mvt->output_count); } void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_mvt *mvt) @@ -455,4 +463,5 @@ void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_m mvt->credit = fromwire_amount_msat(cursor, max); mvt->debit = fromwire_amount_msat(cursor, max); mvt->output_val = fromwire_amount_sat(cursor, max); + mvt->output_count = fromwire_u32(cursor, max); } diff --git a/common/coin_mvt.h b/common/coin_mvt.h index 350945c00..1f0aa9a58 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -87,6 +87,10 @@ struct chain_coin_mvt { /* When we pay to external accounts, it's useful * to track which internal account it originated from */ const char *originating_acct; + + /* Number of outputs in spending tx; used by the + * `channel_close` event */ + u32 output_count; }; /* differs depending on type!? */ @@ -123,6 +127,8 @@ struct coin_mvt { /* Value of the output. May be different than * our credit/debit amount, eg channel opens */ struct amount_sat *output_val; + /* Really only needed for channel closes */ + size_t output_count; /* Amount of fees collected/paid by channel mvt */ struct amount_msat *fees; @@ -170,7 +176,8 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, const struct bitcoin_outpoint *out, u32 blockheight, const struct amount_msat amount, - const struct amount_sat output_val) + const struct amount_sat output_val, + u32 output_count) NON_NULL_ARGS(2, 3); struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, diff --git a/doc/PLUGINS.md b/doc/PLUGINS.md index e8196ec72..cc6d1ac0f 100644 --- a/doc/PLUGINS.md +++ b/doc/PLUGINS.md @@ -710,6 +710,7 @@ i.e. only definitively resolved HTLCs or confirmed bitcoin transactions. "credit":"2000000000msat", "debit":"0msat", "output_value": "2000000000msat", // ('chain_mvt' only) + "output_count": 2, // ('chain_mvt' only, typically only channel closes) "fees": "382msat", // ('channel_mvt' only) "tags": ["deposit"], "blockheight":102, // (May be null) @@ -757,6 +758,9 @@ multiple times. `channel_mvt` only channel opens/closes the total output value will not necessarily correspond to the amount that's credited/debited. +`output_count` is the total outputs to expect for a channel close. Useful +for figuring out when every onchain output for a close has been resolved. + `fees` is an HTLC annotation for the amount of fees either paid or earned. For "invoice" tagged events, the fees are the total fees paid to send that payment. The end amount can be found by subtracting diff --git a/lightningd/notification.c b/lightningd/notification.c index 13f9154b9..c77fa24c4 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -480,6 +480,10 @@ static void coin_movement_notification_serialize(struct json_stream *stream, if (mvt->output_val) json_add_amount_sat_only(stream, "output_value", *mvt->output_val); + if (mvt->output_count > 0) + json_add_num(stream, "output_count", + mvt->output_count); + if (mvt->fees) json_add_amount_msat_only(stream, "fees", *mvt->fees); diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index ae8eb2a5b..1a7ee7499 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -3860,7 +3860,8 @@ int main(int argc, char *argv[]) send_coin_mvt(take(new_coin_channel_close(NULL, &tx->txid, &funding, tx_blockheight, our_msat, - funding_sats))); + funding_sats, + tal_count(tx->outputs)))); status_debug("Remote per-commit point: %s", type_to_string(tmpctx, struct pubkey, diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index e14a2202b..0d17accd7 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -119,7 +119,8 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *out UNNEEDED, u32 blockheight UNNEEDED, const struct amount_msat amount UNNEEDED, - const struct amount_sat output_val) + const struct amount_sat output_val UNNEEDED, + u32 output_count) { 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 23454c0aa..9e3be0904 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -142,7 +142,8 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx UNNEEDED, const struct bitcoin_outpoint *out UNNEEDED, u32 blockheight UNNEEDED, const struct amount_msat amount UNNEEDED, - const struct amount_sat output_val) + const struct amount_sat output_val UNNEEDED, + u32 output_count) { fprintf(stderr, "new_coin_channel_close called!\n"); abort(); } /* Generated stub for new_coin_external_deposit */