Skip to content

Commit 08aaa2e

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 8c9e3a3 commit 08aaa2e

File tree

6 files changed

+87
-12
lines changed

6 files changed

+87
-12
lines changed

doc/schemas/lightning-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
@@ -3142,7 +3142,7 @@ static struct command_result *json_listhtlcs(struct command *cmd,
31423142
struct channel *chan;
31433143
struct wallet_htlc_iter *i;
31443144
struct short_channel_id scid;
3145-
u64 htlc_id;
3145+
u64 htlc_id, created_index, updated_index;
31463146
int cltv_expiry;
31473147
enum side owner;
31483148
struct amount_msat msat;
@@ -3158,12 +3158,17 @@ static struct command_result *json_listhtlcs(struct command *cmd,
31583158
json_array_start(response, "htlcs");
31593159
for (i = wallet_htlcs_first(cmd, cmd->ld->wallet, chan,
31603160
&scid, &htlc_id, &cltv_expiry, &owner, &msat,
3161-
&payment_hash, &hstate);
3161+
&payment_hash, &hstate,
3162+
&created_index, &updated_index);
31623163
i;
31633164
i = wallet_htlcs_next(cmd->ld->wallet, i,
31643165
&scid, &htlc_id, &cltv_expiry, &owner, &msat,
3165-
&payment_hash, &hstate)) {
3166+
&payment_hash, &hstate,
3167+
&created_index, &updated_index)) {
31663168
json_object_start(response, NULL);
3169+
json_add_u64(response, "created_index", created_index);
3170+
if (updated_index != 0)
3171+
json_add_u64(response, "updated_index", updated_index);
31673172
json_add_short_channel_id(response, "short_channel_id", scid);
31683173
json_add_u64(response, "id", htlc_id);
31693174
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
@@ -3291,13 +3291,18 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
32913291
assert [h['direction'] for h in c1htlcs] == ['out'] * 3
32923292
assert [h['state'] for h in c1htlcs] == ['RCVD_REMOVE_ACK_REVOCATION'] * 3
32933293

3294-
# These should be a mirror!
3294+
# These should be a mirror! (Except indexes)
32953295
c2c1htlcs = l2.rpc.listhtlcs(c12)['htlcs']
32963296
for h in c2c1htlcs:
32973297
assert h['state'] == 'SENT_REMOVE_ACK_REVOCATION'
32983298
assert h['direction'] == 'in'
32993299
h['state'] = 'RCVD_REMOVE_ACK_REVOCATION'
33003300
h['direction'] = 'out'
3301+
del h['created_index']
3302+
del h['updated_index']
3303+
for h in c1htlcs:
3304+
del h['created_index']
3305+
del h['updated_index']
33013306
assert c2c1htlcs == c1htlcs
33023307

33033308
# One channel at a time should result in all htlcs.
@@ -3309,11 +3314,29 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
33093314
for h in allhtlcs:
33103315
assert h in parthtlcs
33113316

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

3316-
bitcoind.generate_block(100, wait_for_mempool=3)
3337+
# This will forget c12
3338+
bitcoind.generate_block(1)
3339+
assert l2.rpc.wait('htlcs', 'deleted', 3)['deleted'] == 5
33173340

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

wallet/wallet.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -6180,7 +6180,9 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
61806180
enum side *owner,
61816181
struct amount_msat *msat,
61826182
struct sha256 *payment_hash,
6183-
enum htlc_state *hstate)
6183+
enum htlc_state *hstate,
6184+
u64 *created_index,
6185+
u64 *updated_index)
61846186
{
61856187
struct wallet_htlc_iter *i = tal(ctx, struct wallet_htlc_iter);
61866188

@@ -6196,6 +6198,8 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
61966198
", h.msatoshi"
61976199
", h.payment_hash"
61986200
", h.hstate"
6201+
", h.id"
6202+
", h.updated_index"
61996203
" FROM channel_htlcs h"
62006204
" WHERE channel_id = ?"
62016205
" ORDER BY id ASC"));
@@ -6211,6 +6215,8 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
62116215
", h.msatoshi"
62126216
", h.payment_hash"
62136217
", h.hstate"
6218+
", h.id"
6219+
", h.updated_index"
62146220
" FROM channel_htlcs h"
62156221
" JOIN channels ON channels.id = h.channel_id"
62166222
" ORDER BY h.id ASC"));
@@ -6221,7 +6227,8 @@ struct wallet_htlc_iter *wallet_htlcs_first(const tal_t *ctx,
62216227

62226228
return wallet_htlcs_next(w, i,
62236229
scid, htlc_id, cltv_expiry, owner, msat,
6224-
payment_hash, hstate);
6230+
payment_hash, hstate,
6231+
created_index, updated_index);
62256232
}
62266233

62276234
struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
@@ -6232,7 +6239,9 @@ struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
62326239
enum side *owner,
62336240
struct amount_msat *msat,
62346241
struct sha256 *payment_hash,
6235-
enum htlc_state *hstate)
6242+
enum htlc_state *hstate,
6243+
u64 *created_index,
6244+
u64 *updated_index)
62366245
{
62376246
if (!db_step(iter->stmt))
62386247
return tal_free(iter);
@@ -6256,6 +6265,8 @@ struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
62566265
db_col_sha256(iter->stmt, "h.payment_hash", payment_hash);
62576266
*cltv_expiry = db_col_int(iter->stmt, "h.cltv_expiry");
62586267
*hstate = db_col_int(iter->stmt, "h.hstate");
6268+
*created_index = db_col_u64(iter->stmt, "h.id");
6269+
*updated_index = db_col_u64(iter->stmt, "h.updated_index");
62596270
return iter;
62606271
}
62616272

wallet/wallet.h

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

16951697
/**
16961698
* Iterate through the htlcs table.
@@ -1708,7 +1710,9 @@ struct wallet_htlc_iter *wallet_htlcs_next(struct wallet *w,
17081710
enum side *owner,
17091711
struct amount_msat *msat,
17101712
struct sha256 *payment_hash,
1711-
enum htlc_state *hstate);
1713+
enum htlc_state *hstate,
1714+
u64 *created_index,
1715+
u64 *updated_index);
17121716

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

0 commit comments

Comments
 (0)