lightningd: add ordering and pagination to listforwards.

Changelog-Added: JSON-RPC: `listforwards` new parameters `index`, `start` and `limit`.
This commit is contained in:
Rusty Russell 2023-10-28 13:42:11 +10:30
parent 1d8af90b56
commit f2162bf202
11 changed files with 285 additions and 129 deletions

View File

@ -92,6 +92,10 @@
"legacy": 0,
"tlv": 1
},
"ListforwardsIndex": {
"created": 0,
"updated": 1
},
"ListforwardsStatus": {
"failed": 3,
"local_failed": 2,
@ -940,7 +944,10 @@
},
"ListforwardsRequest": {
"ListForwards.in_channel": 2,
"ListForwards.index": 4,
"ListForwards.limit": 6,
"ListForwards.out_channel": 3,
"ListForwards.start": 5,
"ListForwards.status": 1
},
"ListforwardsResponse": {
@ -3624,10 +3631,22 @@
"added": "pre-v0.10.1",
"deprecated": false
},
"ListForwards.index": {
"added": "v23.11",
"deprecated": false
},
"ListForwards.limit": {
"added": "v23.11",
"deprecated": false
},
"ListForwards.out_channel": {
"added": "pre-v0.10.1",
"deprecated": false
},
"ListForwards.start": {
"added": "v23.11",
"deprecated": false
},
"ListForwards.status": {
"added": "pre-v0.10.1",
"deprecated": false

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1007,7 +1007,7 @@ class LightningRpc(UnixDomainSocketRpc):
}
return self.call("listdatastore", payload)
def listforwards(self, status=None, in_channel=None, out_channel=None):
def listforwards(self, status=None, in_channel=None, out_channel=None, index=None, start=None, limit=None):
"""List all forwarded payments and their information matching
forward {status}, {in_channel} and {out_channel}.
"""
@ -1015,6 +1015,9 @@ class LightningRpc(UnixDomainSocketRpc):
"status": status,
"in_channel": in_channel,
"out_channel": out_channel,
"index": index,
"start": start,
"limit": limit,
}
return self.call("listforwards", payload)

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@ lightning-listforwards -- Command showing all htlcs and their information
SYNOPSIS
--------
**listforwards** [*status*] [*in\_channel*] [*out\_channel*]
**listforwards** [*status*] [*in\_channel*] [*out\_channel*] [*index* [*start*] [*limit*]]
DESCRIPTION
-----------
@ -18,6 +18,12 @@ If *status* is specified, then only the forwards with the given status are retur
If *in\_channel* or *out\_channel* is specified, then only the matching forwards
on the given in/out channel are returned.
If neither *in\_channel* or *out\_channel* is specified,
`index` controls ordering, by `created` (default) or `updated`. If
`index` is specified, `start` may be specified to start from that
value, which is generally returned from lightning-wait(7), and `limit`
can be used to specify the maximum number of entries to return.
RETURN VALUE
------------

View File

@ -17,6 +17,25 @@
},
"out_channel": {
"type": "short_channel_id"
},
"index": {
"type": "string",
"added": "v23.11",
"enum": [
"created",
"updated"
],
"description": ""
},
"start": {
"type": "u64",
"added": "v23.11",
"description": ""
},
"limit": {
"type": "u32",
"added": "v23.11",
"description": ""
}
}
}

View File

@ -149,11 +149,14 @@ static void listforwardings_add_forwardings(struct json_stream *response,
struct wallet *wallet,
enum forward_status status,
const struct short_channel_id *chan_in,
const struct short_channel_id *chan_out)
const struct short_channel_id *chan_out,
const enum wait_index *listindex,
u64 liststart,
const u32 *listlimit)
{
const struct forwarding *forwardings;
forwardings = wallet_forwarded_payments_get(wallet, tmpctx, status, chan_in, chan_out);
forwardings = wallet_forwarded_payments_get(wallet, tmpctx, status, chan_in, chan_out, listindex, liststart, listlimit);
json_array_start(response, "forwards");
for (size_t i=0; i<tal_count(forwardings); i++) {
@ -190,17 +193,37 @@ static struct command_result *json_listforwards(struct command *cmd,
struct json_stream *response;
struct short_channel_id *chan_in, *chan_out;
enum forward_status *status;
enum wait_index *listindex;
u64 *liststart;
u32 *listlimit;
if (!param(cmd, buffer, params,
p_opt_def("status", param_forward_status, &status,
FORWARD_ANY),
p_opt("in_channel", param_short_channel_id, &chan_in),
p_opt("out_channel", param_short_channel_id, &chan_out),
p_opt("index", param_index, &listindex),
p_opt_def("start", param_u64, &liststart, 0),
p_opt("limit", param_u32, &listlimit),
NULL))
return command_param_failed();
if (*liststart != 0 && !listindex) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can only specify {start} with {index}");
}
if (listlimit && !listindex) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can only specify {limit} with {index}");
}
if ((chan_in || chan_out) && *liststart != 0) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Cannot use start with in_channel or out_channel");
}
response = json_stream_success(cmd);
listforwardings_add_forwardings(response, cmd->ld->wallet, *status, chan_in, chan_out);
listforwardings_add_forwardings(response, cmd->ld->wallet, *status, chan_in, chan_out, listindex, *liststart, listlimit);
return command_success(cmd, response);
}

View File

@ -4832,7 +4832,10 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
const tal_t *ctx,
enum forward_status status,
const struct short_channel_id *chan_in,
const struct short_channel_id *chan_out)
const struct short_channel_id *chan_out,
const enum wait_index *listindex,
u64 liststart,
const u32 *listlimit)
{
struct forwarding *results = tal_arr(ctx, struct forwarding, 0);
size_t count = 0;
@ -4841,57 +4844,135 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
// placeholder for any parameter, the value doesn't matter because it's discarded by sql
const int any = -1;
stmt = db_prepare_v2(
w->db,
SQL("SELECT"
" state"
", in_msatoshi"
", out_msatoshi"
", in_channel_scid"
", out_channel_scid"
", in_htlc_id"
", out_htlc_id"
", received_time"
", resolved_time"
", failcode "
", forward_style "
", rowid "
", updated_index "
"FROM forwards "
"WHERE (1 = ? OR state = ?) AND "
"(1 = ? OR in_channel_scid = ?) AND "
"(1 = ? OR out_channel_scid = ?)"));
/* We don't support start/limits with this */
if (chan_in || chan_out) {
stmt = db_prepare_v2(
w->db,
SQL("SELECT"
" state"
", in_msatoshi"
", out_msatoshi"
", in_channel_scid"
", out_channel_scid"
", in_htlc_id"
", out_htlc_id"
", received_time"
", resolved_time"
", failcode "
", forward_style "
", rowid "
", updated_index "
"FROM forwards "
"WHERE (1 = ? OR state = ?) AND "
"(1 = ? OR in_channel_scid = ?) AND "
"(1 = ? OR out_channel_scid = ?)"));
if (status == FORWARD_ANY) {
// any status
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
if (status == FORWARD_ANY) {
// any status
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
} else {
// specific forward status
db_bind_int(stmt, 0);
db_bind_int(stmt, status);
}
if (chan_in) {
// specific in_channel
db_bind_int(stmt, 0);
db_bind_short_channel_id(stmt, chan_in);
} else {
// any in_channel
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
}
if (chan_out) {
// specific out_channel
db_bind_int(stmt, 0);
db_bind_short_channel_id(stmt, chan_out);
} else {
// any out_channel
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
}
} else if (listindex && *listindex == WAIT_INDEX_UPDATED) {
stmt = db_prepare_v2(
w->db,
SQL("SELECT"
" state"
", in_msatoshi"
", out_msatoshi"
", in_channel_scid"
", out_channel_scid"
", in_htlc_id"
", out_htlc_id"
", received_time"
", resolved_time"
", failcode "
", forward_style "
", rowid "
", updated_index "
"FROM forwards "
" WHERE"
" (1 = ? OR state = ?)"
" AND"
" updated_index >= ?"
" ORDER BY updated_index"
" LIMIT ?;"));
if (status == FORWARD_ANY) {
// any status
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
} else {
// specific forward status
db_bind_int(stmt, 0);
db_bind_int(stmt, status);
}
db_bind_u64(stmt, liststart);
if (listlimit)
db_bind_int(stmt, *listlimit);
else
db_bind_int(stmt, INT_MAX);
} else {
// specific forward status
db_bind_int(stmt, 0);
db_bind_int(stmt, status);
stmt = db_prepare_v2(
w->db,
SQL("SELECT"
" state"
", in_msatoshi"
", out_msatoshi"
", in_channel_scid"
", out_channel_scid"
", in_htlc_id"
", out_htlc_id"
", received_time"
", resolved_time"
", failcode "
", forward_style "
", rowid "
", updated_index "
"FROM forwards "
" WHERE"
" (1 = ? OR state = ?)"
" AND"
" rowid >= ?"
" ORDER BY rowid"
" LIMIT ?;"));
if (status == FORWARD_ANY) {
// any status
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
} else {
// specific forward status
db_bind_int(stmt, 0);
db_bind_int(stmt, status);
}
db_bind_u64(stmt, liststart);
if (listlimit)
db_bind_int(stmt, *listlimit);
else
db_bind_int(stmt, INT_MAX);
}
if (chan_in) {
// specific in_channel
db_bind_int(stmt, 0);
db_bind_short_channel_id(stmt, chan_in);
} else {
// any in_channel
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
}
if (chan_out) {
// specific out_channel
db_bind_int(stmt, 0);
db_bind_short_channel_id(stmt, chan_out);
} else {
// any out_channel
db_bind_int(stmt, 1);
db_bind_int(stmt, any);
}
db_query_prepared(stmt);
for (count=0; db_step(stmt); count++) {

View File

@ -1208,7 +1208,10 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
const tal_t *ctx,
enum forward_status state,
const struct short_channel_id *chan_in,
const struct short_channel_id *chan_out);
const struct short_channel_id *chan_out,
const enum wait_index *listindex,
u64 liststart,
const u32 *listlimit);
/**
* Delete a particular forward entry