Skip to content

Commit 453ab4c

Browse files
committed
lightningd: add created_index and updated_index to listhtlcs.
Signed-off-by: Rusty Russell <[email protected]> Changelog-Added: JSON-RPC: `listhtlcs` has `created_index` and `updated_index` fields.
1 parent 1007056 commit 453ab4c

File tree

12 files changed

+123
-13
lines changed

12 files changed

+123
-13
lines changed

.msggen.json

+11-1
Original file line numberDiff line numberDiff line change
@@ -2560,12 +2560,14 @@
25602560
},
25612561
"ListhtlcsHtlcs": {
25622562
"ListHtlcs.htlcs[].amount_msat": 4,
2563+
"ListHtlcs.htlcs[].created_index": 8,
25632564
"ListHtlcs.htlcs[].direction": 5,
25642565
"ListHtlcs.htlcs[].expiry": 3,
25652566
"ListHtlcs.htlcs[].id": 2,
25662567
"ListHtlcs.htlcs[].payment_hash": 6,
25672568
"ListHtlcs.htlcs[].short_channel_id": 1,
2568-
"ListHtlcs.htlcs[].state": 7
2569+
"ListHtlcs.htlcs[].state": 7,
2570+
"ListHtlcs.htlcs[].updated_index": 9
25692571
},
25702572
"ListhtlcsRequest": {
25712573
"ListHtlcs.id": 1
@@ -9582,6 +9584,10 @@
95829584
"added": "pre-v0.10.1",
95839585
"deprecated": null
95849586
},
9587+
"ListHtlcs.htlcs[].created_index": {
9588+
"added": "v25.05",
9589+
"deprecated": null
9590+
},
95859591
"ListHtlcs.htlcs[].direction": {
95869592
"added": "pre-v0.10.1",
95879593
"deprecated": null
@@ -9606,6 +9612,10 @@
96069612
"added": "pre-v0.10.1",
96079613
"deprecated": null
96089614
},
9615+
"ListHtlcs.htlcs[].updated_index": {
9616+
"added": "v25.05",
9617+
"deprecated": null
9618+
},
96099619
"ListHtlcs.id": {
96109620
"added": "pre-v0.10.1",
96119621
"deprecated": null

cln-grpc/proto/node.proto

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-grpc/src/convert.rs

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-rpc/src/model.rs

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/msggen/msggen/schema.json

+15
Original file line numberDiff line numberDiff line change
@@ -21549,6 +21549,7 @@
2154921549
"type": "object",
2155021550
"additionalProperties": false,
2155121551
"required": [
21552+
"created_index",
2155221553
"short_channel_id",
2155321554
"id",
2155421555
"expiry",
@@ -21564,6 +21565,20 @@
2156421565
"The channel that contains/contained the HTLC."
2156521566
]
2156621567
},
21568+
"created_index": {
21569+
"added": "v25.05",
21570+
"type": "u64",
21571+
"description": [
21572+
"1-based index indicating order this htlc was created in."
21573+
]
21574+
},
21575+
"updated_index": {
21576+
"added": "v25.05",
21577+
"type": "u64",
21578+
"description": [
21579+
"1-based index indicating order this htlc was changed (only present if it has changed since creation)."
21580+
]
21581+
},
2156721582
"id": {
2156821583
"type": "u64",
2156921584
"description": [

contrib/pyln-testing/pyln/testing/grpc2py.py

+2
Original file line numberDiff line numberDiff line change
@@ -1715,10 +1715,12 @@ def listhtlcs_htlcs2py(m):
17151715
"direction": str(m.direction), # EnumField in generate_composite
17161716
"state": str(m.state), # EnumField in generate_composite
17171717
"amount_msat": amount2msat(m.amount_msat), # PrimitiveField in generate_composite
1718+
"created_index": m.created_index, # PrimitiveField in generate_composite
17181719
"expiry": m.expiry, # PrimitiveField in generate_composite
17191720
"id": m.id, # PrimitiveField in generate_composite
17201721
"payment_hash": hexlify(m.payment_hash), # PrimitiveField in generate_composite
17211722
"short_channel_id": m.short_channel_id, # PrimitiveField in generate_composite
1723+
"updated_index": m.updated_index, # PrimitiveField in generate_composite
17221724
})
17231725

17241726

doc/schemas/listhtlcs.json

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"type": "object",
3434
"additionalProperties": false,
3535
"required": [
36+
"created_index",
3637
"short_channel_id",
3738
"id",
3839
"expiry",
@@ -48,6 +49,20 @@
4849
"The channel that contains/contained the HTLC."
4950
]
5051
},
52+
"created_index": {
53+
"added": "v25.05",
54+
"type": "u64",
55+
"description": [
56+
"1-based index indicating order this htlc was created in."
57+
]
58+
},
59+
"updated_index": {
60+
"added": "v25.05",
61+
"type": "u64",
62+
"description": [
63+
"1-based index indicating order this htlc was changed (only present if it has changed since creation)."
64+
]
65+
},
5166
"id": {
5267
"type": "u64",
5368
"description": [

lightningd/peer_htlcs.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -3106,7 +3106,7 @@ static struct command_result *json_listhtlcs(struct command *cmd,
31063106
struct channel *chan;
31073107
struct wallet_htlc_iter *i;
31083108
struct short_channel_id scid;
3109-
u64 htlc_id;
3109+
u64 htlc_id, created_index, updated_index;
31103110
int cltv_expiry;
31113111
enum side owner;
31123112
struct amount_msat msat;
@@ -3122,12 +3122,17 @@ static struct command_result *json_listhtlcs(struct command *cmd,
31223122
json_array_start(response, "htlcs");
31233123
for (i = wallet_htlcs_first(cmd, cmd->ld->wallet, chan,
31243124
&scid, &htlc_id, &cltv_expiry, &owner, &msat,
3125-
&payment_hash, &hstate);
3125+
&payment_hash, &hstate,
3126+
&created_index, &updated_index);
31263127
i;
31273128
i = wallet_htlcs_next(cmd->ld->wallet, i,
31283129
&scid, &htlc_id, &cltv_expiry, &owner, &msat,
3129-
&payment_hash, &hstate)) {
3130+
&payment_hash, &hstate,
3131+
&created_index, &updated_index)) {
31303132
json_object_start(response, NULL);
3133+
json_add_u64(response, "created_index", created_index);
3134+
if (updated_index != 0)
3135+
json_add_u64(response, "updated_index", updated_index);
31313136
json_add_short_channel_id(response, "short_channel_id", scid);
31323137
json_add_u64(response, "id", htlc_id);
31333138
json_add_u32(response, "expiry", cltv_expiry);

tests/test_connection.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -4342,27 +4342,35 @@ def test_multichan(node_factory, executor, bitcoind):
43424342
assert l1htlcs == l1.rpc.listhtlcs(scid12)['htlcs']
43434343
assert l1htlcs == [{"short_channel_id": scid12,
43444344
"id": 0,
4345+
"created_index": 1,
4346+
"updated_index": 9,
43454347
"expiry": 117,
43464348
"direction": "out",
43474349
"amount_msat": Millisatoshi(100001001),
43484350
"payment_hash": inv1['payment_hash'],
43494351
"state": "RCVD_REMOVE_ACK_REVOCATION"},
43504352
{"short_channel_id": scid12,
43514353
"id": 1,
4354+
"created_index": 2,
4355+
"updated_index": 18,
43524356
"expiry": 117,
43534357
"direction": "out",
43544358
"amount_msat": Millisatoshi(100001001),
43554359
"payment_hash": inv2['payment_hash'],
43564360
"state": "RCVD_REMOVE_ACK_REVOCATION"},
43574361
{"short_channel_id": scid12,
43584362
"id": 2,
4363+
"created_index": 3,
4364+
"updated_index": 27,
43594365
"expiry": 135,
43604366
"direction": "out",
43614367
"amount_msat": Millisatoshi(100001001),
43624368
"payment_hash": inv3['payment_hash'],
43634369
"state": "RCVD_REMOVE_ACK_REVOCATION"},
43644370
{"short_channel_id": scid12,
43654371
"id": 3,
4372+
"created_index": 4,
4373+
"updated_index": 36,
43664374
"expiry": 135,
43674375
"direction": "out",
43684376
"amount_msat": Millisatoshi(100001001),
@@ -4373,7 +4381,16 @@ def test_multichan(node_factory, executor, bitcoind):
43734381
for h in l1htlcs:
43744382
h['direction'] = 'in'
43754383
h['state'] = 'SENT_REMOVE_ACK_REVOCATION'
4376-
assert l2.rpc.listhtlcs(scid12)['htlcs'] == l1htlcs
4384+
# These won't match!
4385+
del h['created_index']
4386+
del h['updated_index']
4387+
4388+
l2htlcs = l2.rpc.listhtlcs(scid12)['htlcs']
4389+
for h in l2htlcs:
4390+
del h['created_index']
4391+
del h['updated_index']
4392+
4393+
assert l2htlcs == l1htlcs
43774394

43784395

43794396
def test_mutual_reconnect_race(node_factory, executor, bitcoind):

tests/test_misc.py

+26-3
Original file line numberDiff line numberDiff line change
@@ -3293,13 +3293,18 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
32933293
assert [h['direction'] for h in c1htlcs] == ['out'] * 3
32943294
assert [h['state'] for h in c1htlcs] == ['RCVD_REMOVE_ACK_REVOCATION'] * 3
32953295

3296-
# These should be a mirror!
3296+
# These should be a mirror! (Except indexes)
32973297
c2c1htlcs = l2.rpc.listhtlcs(c12)['htlcs']
32983298
for h in c2c1htlcs:
32993299
assert h['state'] == 'SENT_REMOVE_ACK_REVOCATION'
33003300
assert h['direction'] == 'in'
33013301
h['state'] = 'RCVD_REMOVE_ACK_REVOCATION'
33023302
h['direction'] = 'out'
3303+
del h['created_index']
3304+
del h['updated_index']
3305+
for h in c1htlcs:
3306+
del h['created_index']
3307+
del h['updated_index']
33033308
assert c2c1htlcs == c1htlcs
33043309

33053310
# One channel at a time should result in all htlcs.
@@ -3311,11 +3316,29 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
33113316
for h in allhtlcs:
33123317
assert h in parthtlcs
33133318

3314-
# Now, close and forget.
3319+
# Now, close and forget (first mine c23 close)
3320+
bitcoind.generate_block(1, wait_for_mempool=1)
33153321
l2.rpc.close(c24)
3322+
bitcoind.generate_block(1, wait_for_mempool=1)
33163323
l2.rpc.close(c12)
3324+
# Not actually deleted yet.
3325+
assert l2.rpc.wait('htlcs', 'deleted', 0)['deleted'] == 0
3326+
3327+
# 99 blocks is not enough for them to be deleted.
3328+
bitcoind.generate_block(97)
3329+
assert l2.rpc.wait('htlcs', 'deleted', 0)['deleted'] == 0
3330+
3331+
# This will forget c23
3332+
bitcoind.generate_block(1)
3333+
assert l2.rpc.wait('htlcs', 'deleted', 1)['deleted'] == 1
3334+
3335+
# This will forget c24
3336+
bitcoind.generate_block(1)
3337+
assert l2.rpc.wait('htlcs', 'deleted', 2)['deleted'] == 2
33173338

3318-
bitcoind.generate_block(100, wait_for_mempool=3)
3339+
# This will forget c12
3340+
bitcoind.generate_block(1)
3341+
assert l2.rpc.wait('htlcs', 'deleted', 3)['deleted'] == 5
33193342

33203343
# Once channels are gone, htlcs are gone.
33213344
for n in (l1, l2, l3, l4):

wallet/wallet.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -6201,7 +6201,9 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
62016201
enum side *owner,
62026202
struct amount_msat *msat,
62036203
struct sha256 *payment_hash,
6204-
enum htlc_state *hstate)
6204+
enum htlc_state *hstate,
6205+
u64 *created_index,
6206+
u64 *updated_index)
62056207
{
62066208
struct wallet_htlc_iter *i = tal(ctx, struct wallet_htlc_iter);
62076209

@@ -6217,6 +6219,8 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
62176219
", h.msatoshi"
62186220
", h.payment_hash"
62196221
", h.hstate"
6222+
", h.id"
6223+
", h.updated_index"
62206224
" FROM channel_htlcs h"
62216225
" WHERE channel_id = ?"
62226226
" ORDER BY id ASC"));
@@ -6232,6 +6236,8 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
62326236
", h.msatoshi"
62336237
", h.payment_hash"
62346238
", h.hstate"
6239+
", h.id"
6240+
", h.updated_index"
62356241
" FROM channel_htlcs h"
62366242
" JOIN channels ON channels.id = h.channel_id"
62376243
" ORDER BY h.id ASC"));
@@ -6242,7 +6248,8 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
62426248

62436249
return wallet_htlcs_next(w, i,
62446250
scid, htlc_id, cltv_expiry, owner, msat,
6245-
payment_hash, hstate);
6251+
payment_hash, hstate,
6252+
created_index, updated_index);
62466253
}
62476254

62486255
struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
@@ -6253,7 +6260,9 @@ struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
62536260
enum side *owner,
62546261
struct amount_msat *msat,
62556262
struct sha256 *payment_hash,
6256-
enum htlc_state *hstate)
6263+
enum htlc_state *hstate,
6264+
u64 *created_index,
6265+
u64 *updated_index)
62576266
{
62586267
if (!db_step(iter->stmt))
62596268
return tal_free(iter);
@@ -6277,6 +6286,8 @@ struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
62776286
db_col_sha256(iter->stmt, "h.payment_hash", payment_hash);
62786287
*cltv_expiry = db_col_int(iter->stmt, "h.cltv_expiry");
62796288
*hstate = db_col_int(iter->stmt, "h.hstate");
6289+
*created_index = db_col_u64(iter->stmt, "h.id");
6290+
*updated_index = db_col_u64(iter->stmt, "h.updated_index");
62806291
return iter;
62816292
}
62826293

wallet/wallet.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,9 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
16911691
enum side *owner,
16921692
struct amount_msat *msat,
16931693
struct sha256 *payment_hash,
1694-
enum htlc_state *hstate);
1694+
enum htlc_state *hstate,
1695+
u64 *created_index,
1696+
u64 *updated_index);
16951697

16961698
/**
16971699
* Iterate through the htlcs table.
@@ -1709,7 +1711,9 @@ struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
17091711
enum side *owner,
17101712
struct amount_msat *msat,
17111713
struct sha256 *payment_hash,
1712-
enum htlc_state *hstate);
1714+
enum htlc_state *hstate,
1715+
u64 *created_index,
1716+
u64 *updated_index);
17131717

17141718
/* Make a PSBT from these utxos, or enhance @base if non-NULL. */
17151719
struct wally_psbt *psbt_using_utxos(const tal_t *ctx,

0 commit comments

Comments
 (0)