From 30abda2750f70e8f7690bb250befdcedbdb9b2e5 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 5 Jan 2021 18:55:01 +0100 Subject: [PATCH] jsonrpc: Allow filtering via bolt11 or payment_hash in listinvoices A user reported that it is sometimes cumbersome to search an invoice based on the payment hash or the bolt11 string in the full list, which may be required when we don't have the label available. This adds support for querying / filtering based on the `payment_hash` or `bolt11` string. Changelog-Added: JSON-RPC: `listinvoices` can now query for an invoice matching a `payment_hash` or a `bolt11` string, in addition to `label` --- lightningd/invoice.c | 61 ++++++++++++++++----- lightningd/test/run-invoice-select-inchan.c | 5 ++ 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 8ef0a91f9..89dbee7b2 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -1119,29 +1119,41 @@ AUTODATA(json_command, &invoice_command); static void json_add_invoices(struct json_stream *response, struct wallet *wallet, - const struct json_escape *label) + const struct json_escape *label, + const struct sha256 *payment_hash) { struct invoice_iterator it; const struct invoice_details *details; + struct invoice invoice; /* Don't iterate entire db if we're just after one. */ if (label) { - struct invoice invoice; if (wallet_invoice_find_by_label(wallet, &invoice, label)) { - details = wallet_invoice_details(response, wallet, invoice); + details = + wallet_invoice_details(response, wallet, invoice); json_object_start(response, NULL); json_add_invoice(response, details); json_object_end(response); } - return; - } + } else if (payment_hash != NULL) { + if (wallet_invoice_find_by_rhash(wallet, &invoice, + payment_hash)) { + json_object_start(response, NULL); + json_add_invoice( + response, + wallet_invoice_details(response, wallet, invoice)); + json_object_end(response); + } - memset(&it, 0, sizeof(it)); - while (wallet_invoice_iterate(wallet, &it)) { - details = wallet_invoice_iterator_deref(response, wallet, &it); - json_object_start(response, NULL); - json_add_invoice(response, details); - json_object_end(response); + } else { + memset(&it, 0, sizeof(it)); + while (wallet_invoice_iterate(wallet, &it)) { + details = wallet_invoice_iterator_deref(response, + wallet, &it); + json_object_start(response, NULL); + json_add_invoice(response, details); + json_object_end(response); + } } } @@ -1153,13 +1165,35 @@ static struct command_result *json_listinvoices(struct command *cmd, struct json_escape *label; struct json_stream *response; struct wallet *wallet = cmd->ld->wallet; + const char *invstring; + struct sha256 *payment_hash; + char *fail; + struct bolt11 *b11; + if (!param(cmd, buffer, params, p_opt("label", param_label, &label), + p_opt("invstring", param_string, &invstring), + p_opt("payment_hash", param_sha256, &payment_hash), NULL)) return command_param_failed(); + + if ((label && invstring) || (label && payment_hash) || + (invstring && payment_hash)) { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Can only specify one of" + " {label}, {invstring} or {payment_hash}"); + } + + /* Extract the payment_hash from the invoice. */ + if (invstring != NULL) { + b11 = bolt11_decode(cmd, invstring, cmd->ld->our_features, NULL, + NULL, &fail); + payment_hash = &b11->payment_hash; + } + response = json_stream_success(cmd); json_array_start(response, "invoices"); - json_add_invoices(response, wallet, label); + json_add_invoices(response, wallet, label, payment_hash); json_array_end(response); return command_success(cmd, response); } @@ -1168,7 +1202,8 @@ static const struct json_command listinvoices_command = { "listinvoices", "payment", json_listinvoices, - "Show invoice {label} (or all, if no {label})" + "Show invoice matching {label}, {invstring} or {payment_hash} (or all, if " + "no query parameter specified)" }; AUTODATA(json_command, &listinvoices_command); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index ffd20d57e..bbfe00597 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -463,6 +463,11 @@ struct command_result *param_number(struct command *cmd UNNEEDED, const char *na const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, unsigned int **num UNNEEDED) { fprintf(stderr, "param_number called!\n"); abort(); } +/* Generated stub for param_sha256 */ +struct command_result *param_sha256(struct command *cmd UNNEEDED, const char *name UNNEEDED, + const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, + struct sha256 **hash UNNEEDED) +{ fprintf(stderr, "param_sha256 called!\n"); abort(); } /* Generated stub for param_short_channel_id */ struct command_result *param_short_channel_id(struct command *cmd UNNEEDED, const char *name UNNEEDED,