From 6e703ad97789b235323b75e5b7eabe116fde22c3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 17 Jan 2018 06:14:32 +1030 Subject: [PATCH] JSONRPC: listpayments can list just a specific bolt11 or payment_hash. Signed-off-by: Rusty Russell --- lightningd/pay.c | 47 +++++++++++++++++++++++++++++++++++++--- tests/test_lightningd.py | 37 +++++++++++++++++++++---------- wallet/wallet.c | 31 +++++++++++++++++++------- wallet/wallet.h | 5 ++++- 4 files changed, 97 insertions(+), 23 deletions(-) diff --git a/lightningd/pay.c b/lightningd/pay.c index d61fbe7a6..764b40b6f 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -441,8 +441,49 @@ static void json_listpayments(struct command *cmd, const char *buffer, { const struct wallet_payment **payments; struct json_result *response = new_json_result(cmd); + jsmntok_t *bolt11tok, *rhashtok; + struct sha256 *rhash = NULL; - payments = wallet_payment_list(cmd, cmd->ld->wallet); + if (!json_get_params(buffer, params, + "?bolt11", &bolt11tok, + "?payment_hash", &rhashtok, + NULL)) { + command_fail(cmd, "Invalid parameters"); + return; + } + + if (bolt11tok) { + struct bolt11 *b11; + char *b11str, *fail; + + if (rhashtok) { + command_fail(cmd, "Can only specify one of" + " {bolt11} or {payment_hash}"); + return; + } + + b11str = tal_strndup(cmd, buffer + bolt11tok->start, + bolt11tok->end - bolt11tok->start); + + b11 = bolt11_decode(cmd, b11str, NULL, &fail); + if (!b11) { + command_fail(cmd, "Invalid bolt11: %s", fail); + return; + } + rhash = &b11->payment_hash; + } else if (rhashtok) { + rhash = tal(cmd, struct sha256); + if (!hex_decode(buffer + rhashtok->start, + rhashtok->end - rhashtok->start, + rhash, sizeof(*rhash))) { + command_fail(cmd, "'%.*s' is not a valid sha256 hash", + (int)(rhashtok->end - rhashtok->start), + buffer + rhashtok->start); + return; + } + } + + payments = wallet_payment_list(cmd, cmd->ld->wallet, rhash); json_array_start(response, NULL); for (int i=0; idb, - "SELECT id, status, destination, " - "msatoshi, payment_hash, timestamp, payment_preimage, " - "path_secrets " - "FROM payments;"); + if (payment_hash) { + stmt = db_prepare( + wallet->db, + "SELECT id, status, destination, " + "msatoshi, payment_hash, timestamp, payment_preimage, " + "path_secrets " + "FROM payments " + "WHERE payment_hash = ?;"); + sqlite3_bind_sha256(stmt, 1, payment_hash); + } else { + stmt = db_prepare( + wallet->db, + "SELECT id, status, destination, " + "msatoshi, payment_hash, timestamp, payment_preimage, " + "path_secrets " + "FROM payments;"); + } for (i = 0; sqlite3_step(stmt) == SQLITE_ROW; i++) { tal_resize(&payments, i+1); @@ -1456,6 +1469,8 @@ const struct wallet_payment **wallet_payment_list(const tal_t *ctx, /* Now attach payments not yet in db. */ list_for_each(&wallet->unstored_payments, p, list) { + if (payment_hash && !structeq(&p->payment_hash, payment_hash)) + continue; tal_resize(&payments, i+1); payments[i++] = p; } diff --git a/wallet/wallet.h b/wallet/wallet.h index 6221a9703..0f26a468c 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -592,8 +592,11 @@ struct secret *wallet_payment_get_secrets(const tal_t *ctx, /** * wallet_payment_list - Retrieve a list of payments + * + * payment_hash: optional filter for only this payment hash. */ const struct wallet_payment **wallet_payment_list(const tal_t *ctx, - struct wallet *wallet); + struct wallet *wallet, + const struct sha256 *payment_hash); #endif /* WALLET_WALLET_H */