coin_mvt: put timestamp into the struct.
What changed, and why it matters
This commit moves the timestamp for coin movement records from being generated at the moment of notification into the coin movement data structure itself. It is a straightforward internal refactoring to prepare for future list commands. There is no security issue here.
No security action required. Review as normal code change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch adds a u64 timestamp field to struct channel_coin_mvt and struct chain_coin_mvt, updates constructors and wire serialization/deserialization, and changes notification.c to emit the stored timestamp rather than calling time_now() at serialization time. The JSON output changes from json_add_u32 to json_add_u64 for the timestamp field. This is a preparatory refactor with no vulnerability introduced.
Changed components
common/coin_mvt.ccommon/coin_mvt.hlightningd/coin_mvts.clightningd/notification.cInspect captured patch +27 / −12
diff --git a/common/coin_mvt.c b/common/coin_mvt.c
index c0720dd5..98431b4f 100644
--- a/common/coin_mvt.c
+++ b/common/coin_mvt.c
@@ -4,6 +4,7 @@
#include <ccan/bitops/bitops.h>
#include <ccan/ccan/cast/cast.h>
#include <ccan/tal/str/str.h>
+#include <ccan/time/time.h>
#include <common/coin_mvt.h>
#include <common/node_id.h>
#include <wire/wire.h>
@@ -117,6 +118,7 @@ struct mvt_account_id *new_mvt_account_id(const tal_t *ctx,
struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
const struct channel *channel,
+ u64 timestamp,
const struct sha256 *payment_hash TAKES,
const u64 *part_id,
const u64 *group_id,
@@ -129,6 +131,7 @@ struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
assert(mvt_tags_valid(tags));
set_mvt_account_id(&mvt->account, channel, NULL);
+ mvt->timestamp = timestamp;
mvt->payment_hash = tal_dup_or_null(mvt, struct sha256, payment_hash);
if (!part_id) {
assert(!group_id);
@@ -160,6 +163,7 @@ struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx,
const struct channel *channel,
const char *account_name TAKES,
+ u64 timestamp,
const struct bitcoin_txid *tx_txid,
const struct bitcoin_outpoint *outpoint,
const struct sha256 *payment_hash TAKES,
@@ -174,6 +178,7 @@ static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx,
assert(mvt_tags_valid(tags));
set_mvt_account_id(&mvt->account, channel, account_name);
+ mvt->timestamp = timestamp;
mvt->tx_txid = tx_txid;
mvt->outpoint = outpoint;
mvt->originating_acct = NULL;
@@ -219,7 +224,8 @@ static struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx,
ok = amount_sat_to_msat(&amt_msat, amt_sat);
assert(ok);
- return new_chain_coin_mvt(ctx, channel, account_name, tx_txid,
+ return new_chain_coin_mvt(ctx, channel, account_name,
+ time_now().ts.tv_sec, tx_txid,
outpoint, payment_hash,
blockheight, tags, direction, amt_msat,
/* All amounts that are sat are
@@ -273,7 +279,8 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx,
else
tags = mk_mvt_tags(MVT_CHANNEL_CLOSE);
- mvt = new_chain_coin_mvt(ctx, channel, alt_account, txid,
+ mvt = new_chain_coin_mvt(ctx, channel, alt_account,
+ time_now().ts.tv_sec, txid,
out, NULL, blockheight,
tags,
COIN_DEBIT, amount,
@@ -301,7 +308,8 @@ struct chain_coin_mvt *new_coin_channel_open_proposed(const tal_t *ctx,
if (is_leased)
tag_set(&tags, MVT_LEASED);
- mvt = new_chain_coin_mvt(ctx, channel, NULL, NULL, out, NULL, 0,
+ mvt = new_chain_coin_mvt(ctx, channel, NULL, time_now().ts.tv_sec,
+ NULL, out, NULL, 0,
tags,
COIN_CREDIT, amount, output_val, 0);
mvt->peer_id = tal_dup(mvt, struct node_id, peer_id);
@@ -329,7 +337,8 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx,
if (is_leased)
tag_set(&tags, MVT_LEASED);
- mvt = new_chain_coin_mvt(ctx, channel, NULL, NULL, out, NULL, blockheight,
+ mvt = new_chain_coin_mvt(ctx, channel, NULL, time_now().ts.tv_sec,
+ NULL, out, NULL, blockheight,
tags,
COIN_CREDIT, amount,
output_val, 0);
@@ -374,7 +383,8 @@ struct chain_coin_mvt *new_coin_external_spend(const tal_t *ctx,
struct amount_sat amount,
struct mvt_tags tags)
{
- return new_chain_coin_mvt(ctx, NULL, EXTERNAL, txid,
+ return new_chain_coin_mvt(ctx, NULL, EXTERNAL,
+ time_now().ts.tv_sec, txid,
outpoint, NULL, blockheight,
tags,
COIN_CREDIT, AMOUNT_MSAT(0), amount, 0);
@@ -427,7 +437,7 @@ struct channel_coin_mvt *new_coin_channel_push(const tal_t *ctx,
struct amount_msat amount,
struct mvt_tags tags)
{
- return new_channel_coin_mvt(ctx, channel, NULL,
+ return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, NULL,
NULL, NULL, direction, amount,
tags,
AMOUNT_MSAT(0));
@@ -500,6 +510,7 @@ void towire_chain_coin_mvt(u8 **pptr, const struct chain_coin_mvt *mvt)
towire_node_id(pptr, mvt->peer_id);
} else
towire_bool(pptr, false);
+ towire_u64(pptr, mvt->timestamp);
}
void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_mvt *mvt)
@@ -540,6 +551,7 @@ void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_m
mvt->peer_id = tal_dup(mvt, struct node_id, &peer_id);
} else
mvt->peer_id = NULL;
+ mvt->timestamp = fromwire_u64(cursor, max);
}
struct mvt_tags mk_mvt_tags_(enum mvt_tag tag, ...)
diff --git a/common/coin_mvt.h b/common/coin_mvt.h
index 5f495f23..7f29b1b6 100644
--- a/common/coin_mvt.h
+++ b/common/coin_mvt.h
@@ -66,6 +66,7 @@ struct channel_coin_mvt {
/* only one or the other */
struct amount_msat credit;
struct amount_msat debit;
+ u64 timestamp;
/* identifier */
const struct sha256 *payment_hash;
@@ -85,6 +86,7 @@ struct chain_coin_mvt {
/* only one or the other */
struct amount_msat credit;
struct amount_msat debit;
+ u64 timestamp;
const struct bitcoin_txid *tx_txid;
const struct bitcoin_outpoint *outpoint;
@@ -138,6 +140,7 @@ struct mvt_account_id *new_mvt_account_id(const tal_t *ctx,
/* 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 *channel,
+ u64 timestamp,
const struct sha256 *payment_hash TAKES,
const u64 *part_id,
const u64 *group_id,
diff --git a/lightningd/coin_mvts.c b/lightningd/coin_mvts.c
index 68bf42d9..f122fc9b 100644
--- a/lightningd/coin_mvts.c
+++ b/lightningd/coin_mvts.c
@@ -10,7 +10,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hin(const tal_t *ctx,
const struct htlc_in *hin,
const struct channel *channel)
{
- return new_channel_coin_mvt(ctx, channel,
+ return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec,
&hin->payment_hash, NULL, NULL,
COIN_CREDIT, hin->msat,
mk_mvt_tags(MVT_INVOICE),
@@ -30,7 +30,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hin(const tal_t *ctx,
hin->payload->amt_to_forward))
return NULL;
- return new_channel_coin_mvt(ctx, channel,
+ return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec,
&hin->payment_hash, NULL, NULL,
COIN_CREDIT, hin->msat,
mk_mvt_tags(MVT_ROUTED),
@@ -41,7 +41,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hout(const tal_t *ctx,
const struct htlc_out *hout,
const struct channel *channel)
{
- return new_channel_coin_mvt(ctx, channel,
+ return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec,
&hout->payment_hash,
&hout->partid,
&hout->groupid,
@@ -54,7 +54,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx,
const struct htlc_out *hout,
const struct channel *channel)
{
- return new_channel_coin_mvt(ctx, channel,
+ return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec,
&hout->payment_hash, NULL, NULL,
COIN_DEBIT, hout->msat,
mk_mvt_tags(MVT_ROUTED),
diff --git a/lightningd/notification.c b/lightningd/notification.c
index e6722891..d01d28be 100644
--- a/lightningd/notification.c
+++ b/lightningd/notification.c
@@ -525,7 +525,7 @@ static void chain_movement_notification_serialize(struct json_stream *stream,
add_movement_tags(stream, ld, chain_mvt->tags, true);
json_add_u32(stream, "blockheight", chain_mvt->blockheight);
- json_add_u32(stream, "timestamp", time_now().ts.tv_sec);
+ json_add_u64(stream, "timestamp", chain_mvt->timestamp);
json_add_string(stream, "coin_type", chainparams->lightning_hrp);
}
@@ -551,7 +551,7 @@ static void channel_movement_notification_serialize(struct json_stream *stream,
add_movement_tags(stream, ld, chan_mvt->tags, extra_tags_field);
- json_add_u32(stream, "timestamp", time_now().ts.tv_sec);
+ json_add_u64(stream, "timestamp", chan_mvt->timestamp);
json_add_string(stream, "coin_type", chainparams->lightning_hrp);
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.