From bc5e54d153a87d3e400d494ae9a9b0a6af22c3e3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 14 Aug 2025 10:57:53 +0930 Subject: [PATCH] common: coin movements for payments need group id as well as part id. The part id is *only* unique within a group. The payment_hash / partid / groupid tuple is unique. Signed-off-by: Rusty Russell Changelog-Added: Plugins: `coin_movement` notification with `part_id` field now always has `group_id` field. --- common/coin_mvt.c | 15 ++++++++++++--- common/coin_mvt.h | 17 +++++++++++++---- .../plugin-development/event-notifications.md | 3 ++- lightningd/coin_mvts.c | 10 ++++++---- lightningd/notification.c | 6 ++++-- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/common/coin_mvt.c b/common/coin_mvt.c index d0d6d500d..d1f973222 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -51,7 +51,8 @@ enum mvt_tag *new_tag_arr(const tal_t *ctx, enum mvt_tag tag) struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, const struct channel_id *cid, const struct sha256 *payment_hash TAKES, - const u64 *part_id TAKES, + const u64 *part_id, + const u64 *group_id, struct amount_msat amount, const enum mvt_tag *tags TAKES, bool is_credit, @@ -61,7 +62,15 @@ struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, mvt->chan_id = *cid; mvt->payment_hash = tal_dup_or_null(mvt, struct sha256, payment_hash); - mvt->part_id = tal_dup_or_null(mvt, u64, part_id); + if (!part_id) { + assert(!group_id); + mvt->part_and_group = NULL; + } else { + mvt->part_and_group = tal(mvt, struct channel_coin_mvt_id); + mvt->part_and_group->part_id = *part_id; + mvt->part_and_group->group_id = *group_id; + } + mvt->tags = tal_dup_talarr(mvt, enum mvt_tag, tags); if (is_credit) { @@ -380,7 +389,7 @@ struct channel_coin_mvt *new_coin_channel_push(const tal_t *ctx, bool is_credit) { return new_channel_coin_mvt(ctx, cid, NULL, - NULL, amount, + NULL, NULL, amount, take(new_tag_arr(NULL, tag)), is_credit, AMOUNT_MSAT(0)); } diff --git a/common/coin_mvt.h b/common/coin_mvt.h index 664b3ac92..474a96781 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -37,6 +37,13 @@ enum mvt_tag { SPLICE = 23, }; +struct channel_coin_mvt_id { + /* multi-part payments may share a payment hash, + * so we should also record part-id and group-id for them */ + u64 part_id; + u64 group_id; +}; + struct channel_coin_mvt { /* account_id */ struct channel_id chan_id; @@ -44,9 +51,9 @@ struct channel_coin_mvt { /* identifier */ struct sha256 *payment_hash; - /* mutli-part payments may share a payment hash, - * so we should also record a 'part-id' for them */ - u64 *part_id; + /* multi-part payments may share a payment hash, + * so we should also record part-id and group-id for them */ + struct channel_coin_mvt_id *part_and_group; /* label / tag array */ enum mvt_tag *tags; @@ -96,10 +103,12 @@ struct chain_coin_mvt { enum mvt_tag *new_tag_arr(const tal_t *ctx, enum mvt_tag tag); +/* Either part_id and group_id both NULL, or neither are */ struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, const struct channel_id *cid, const struct sha256 *payment_hash TAKES, - const u64 *part_id TAKES, + const u64 *part_id, + const u64 *group_id, struct amount_msat amount, const enum mvt_tag *tags TAKES, bool is_credit, diff --git a/doc/developers-guide/plugin-development/event-notifications.md b/doc/developers-guide/plugin-development/event-notifications.md index bc649c980..37d69a771 100644 --- a/doc/developers-guide/plugin-development/event-notifications.md +++ b/doc/developers-guide/plugin-development/event-notifications.md @@ -333,6 +333,7 @@ A notification for topic `coin_movement` is sent to record the movement of coins "vout":1, // (`chain_mvt` only) "payment_hash": "xxx", // (either type, optional on both) "part_id": 0, // (`channel_mvt` only, optional) + "group_id": 0, // (`channel_mvt` only, optional) "credit_msat":2000000000, "debit_msat":0, "output_msat": 2000000000, // ('chain_mvt' only) @@ -364,7 +365,7 @@ _Only_ tagged on external events (deposits/withdrawals to an external party). `payment_hash` is the hash of the preimage used to move this payment. Only present for HTLC mediated moves (both `chain_mvt` and `channel_mvt`) A `chain_mvt` will have a `payment_hash` iff it's recording an htlc that was fulfilled onchain. -`part_id` is an identifier for parts of a multi-part payment. useful for aggregating payments for an invoice or to indicate why a payment hash appears multiple times. `channel_mvt` only +`part_id` and `group_id` are identifiers for parts of a multi-part payment. useful for aggregating payments for an invoice or to indicate why a payment hash appears multiple times. `channel_mvt` only `credit` and `debit` are millisatoshi denominated amounts of the fund movement. A 'credit' is funds deposited into an account; a `debit` is funds withdrawn. diff --git a/lightningd/coin_mvts.c b/lightningd/coin_mvts.c index 5ac2ef98f..80cd0b228 100644 --- a/lightningd/coin_mvts.c +++ b/lightningd/coin_mvts.c @@ -11,7 +11,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hin(const tal_t *ctx, const struct channel *channel) { return new_channel_coin_mvt(ctx, &channel->cid, - &hin->payment_hash, NULL, + &hin->payment_hash, NULL, NULL, hin->msat, new_tag_arr(ctx, INVOICE), true, AMOUNT_MSAT(0)); } @@ -30,7 +30,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hin(const tal_t *ctx, return NULL; return new_channel_coin_mvt(ctx, &channel->cid, - &hin->payment_hash, NULL, + &hin->payment_hash, NULL, NULL, hin->msat, new_tag_arr(ctx, ROUTED), true, fees_collected); } @@ -40,7 +40,9 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hout(const tal_t *ctx, const struct channel *channel) { return new_channel_coin_mvt(ctx, &channel->cid, - &hout->payment_hash, &hout->partid, + &hout->payment_hash, + &hout->partid, + &hout->groupid, hout->msat, new_tag_arr(ctx, INVOICE), false, hout->fees); } @@ -50,7 +52,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx, const struct channel *channel) { return new_channel_coin_mvt(ctx, &channel->cid, - &hout->payment_hash, NULL, + &hout->payment_hash, NULL, NULL, hout->msat, new_tag_arr(ctx, ROUTED), false, hout->fees); diff --git a/lightningd/notification.c b/lightningd/notification.c index cb60dabd2..6368ec274 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -505,8 +505,10 @@ static void channel_movement_notification_serialize(struct json_stream *stream, /* push funding / leases don't have a payment_hash */ if (chan_mvt->payment_hash) json_add_sha256(stream, "payment_hash", chan_mvt->payment_hash); - if (chan_mvt->part_id) - json_add_u64(stream, "part_id", *chan_mvt->part_id); + if (chan_mvt->part_and_group) { + json_add_u64(stream, "part_id", chan_mvt->part_and_group->part_id); + json_add_u64(stream, "group_id", chan_mvt->part_and_group->group_id); + } json_add_amount_msat(stream, "credit_msat", chan_mvt->credit); json_add_amount_msat(stream, "debit_msat", chan_mvt->debit); json_add_amount_msat(stream, "fees_msat", chan_mvt->fees);