From 60c9dedfc7389f88c502df8cf23b452270d07d65 Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 29 Jul 2020 10:48:47 +0200 Subject: [PATCH 1/2] listpays: fixed bolt11 null with keysend and update doc command listpays: make doc-all missed Changelog-Added: JSON-RPC: `listpays` can be used to query payments using the `payment_hash` Changelog-Added: JSON-RPC: `listpays` now includes the `payment_hash` --- doc/lightning-listpays.7 | 14 +++++++++----- doc/lightning-listpays.7.md | 13 ++++++++----- plugins/pay.c | 12 ++++++++++-- tests/test_pay.py | 24 ++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/doc/lightning-listpays.7 b/doc/lightning-listpays.7 index adff03ec3521..30573f34ec51 100644 --- a/doc/lightning-listpays.7 +++ b/doc/lightning-listpays.7 @@ -3,12 +3,12 @@ lightning-listpays - Command for querying payment status .SH SYNOPSIS -\fBlistpays\fR [bolt11] +\fBlistpays\fR [bolt11] [payment_hash] .SH DESCRIPTION The \fBlistpay\fR RPC command gets the status of all \fIpay\fR commands, or a -single one if \fIbolt11\fR is specified\. +single one if either \fIbolt11\fR or \fIpayment_hash\fR was specified\. .SH RETURN VALUE @@ -16,7 +16,11 @@ On success, an array of objects is returned\. Each object contains: \fIbolt11\fR -the \fIbolt11\fR argument given to \fIpay\fR (see below for exceptions)\. +the \fIbolt11\fR invoice if provided to \fBpay\fR\. + + + \fIpayment_hash\fR +the \fIpayment_hash\fR of the payment\. \fIstatus\fR @@ -24,11 +28,11 @@ one of \fIcomplete\fR, \fIfailed\fR or \fIpending\fR\. \fIpayment_preimage\fR -(if \fIstatus\fR is \fIcomplete\fR) proves payment was received\. +if \fIstatus\fR is \fIcomplete\fR\. \fIlabel\fR -optional \fIlabel\fR, if provided to \fIpay\fR\. +optional \fIlabel\fR, if provided to \fIpay\fR or \fIsendonion\fR\. \fIamount_sent_msat\fR diff --git a/doc/lightning-listpays.7.md b/doc/lightning-listpays.7.md index 1cb8d0e19b14..4620dfabfdc8 100644 --- a/doc/lightning-listpays.7.md +++ b/doc/lightning-listpays.7.md @@ -4,13 +4,13 @@ lightning-listpays -- Command for querying payment status SYNOPSIS -------- -**listpays** \[bolt11\] +**listpays** \[bolt11\] \[payment_hash\] DESCRIPTION ----------- The **listpay** RPC command gets the status of all *pay* commands, or a -single one if *bolt11* is specified. +single one if either *bolt11* or *payment_hash* was specified. RETURN VALUE ------------ @@ -18,16 +18,19 @@ RETURN VALUE On success, an array of objects is returned. Each object contains: *bolt11* -the *bolt11* argument given to *pay* (see below for exceptions). +the *bolt11* invoice if provided to `pay`. + + *payment_hash* +the *payment_hash* of the payment. *status* one of *complete*, *failed* or *pending*. *payment\_preimage* -(if *status* is *complete*) proves payment was received. +if *status* is *complete*. *label* -optional *label*, if provided to *pay*. +optional *label*, if provided to *pay* or *sendonion*. *amount\_sent\_msat* total amount sent, in "NNNmsat" format. diff --git a/plugins/pay.c b/plugins/pay.c index 883ddd693777..1d63d99a3214 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1736,7 +1736,10 @@ static void add_new_entry(struct json_stream *ret, const struct pay_mpp *pm) { json_object_start(ret, NULL); - json_add_string(ret, "bolt11", pm->b11); + if (pm->b11) + json_add_string(ret, "bolt11", pm->b11); + + json_add_sha256(ret, "payment_hash", pm->payment_hash); json_add_string(ret, "status", pm->status); json_add_u32(ret, "created_at", pm->timestamp); @@ -1854,11 +1857,13 @@ static struct command_result *json_listpays(struct command *cmd, const jsmntok_t *params) { const char *b11str; + struct sha256 *payment_hash; struct out_req *req; /* FIXME: would be nice to parse as a bolt11 so check worked in future */ if (!param(cmd, buf, params, p_opt("bolt11", param_string, &b11str), + p_opt("payment_hash", param_sha256, &payment_hash), NULL)) return command_param_failed(); @@ -1867,6 +1872,9 @@ static struct command_result *json_listpays(struct command *cmd, cast_const(char *, b11str)); if (b11str) json_add_string(req->js, "bolt11", b11str); + + if (payment_hash) + json_add_sha256(req->js, "payment_hash", payment_hash); return send_outreq(cmd->plugin, req); } @@ -2054,7 +2062,7 @@ static const struct plugin_command commands[] = { }, { "listpays", "payment", - "List result of payment {bolt11}, or all", + "List result of payment {bolt11} or {payment_hash}, or all", "Covers old payments (failed and succeeded) and current ones.", json_listpays }, diff --git a/tests/test_pay.py b/tests/test_pay.py index f864895f289d..08817fc93ea7 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -3240,3 +3240,27 @@ def test_mpp_presplit_routehint_conflict(node_factory, bitcoind): inv = l3.rpc.invoice(Millisatoshi(2 * 10000 * 1000), 'i', 'i', exposeprivatechannels=True)['bolt11'] l1.rpc.pay(inv) + + +def test_listpay_result_with_paymod(node_factory, bitcoind): + """ + The object of this test is to verify the correct behavior + of the RPC command listpay e with two different type of + payment, such as: keysend (without invoice) and pay (with invoice). + l1 -> keysend -> l2 + l2 -> pay invoice -> l3 + """ + + amount_sat = 10 ** 6 + + l1, l2, l3 = node_factory.line_graph(3) + + invl2 = l2.rpc.invoice(amount_sat * 2, "inv_l2", "inv_l2") + l1.rpc.pay(invl2['bolt11']) + + l2.rpc.keysend(l3.info['id'], amount_sat * 2, "keysend_l3") + + assert 'bolt11' in l1.rpc.listpays()['pays'][0] + assert 'payment_hash' in l2.rpc.listpays()['pays'][0] + assert 'payment_hash' in l1.rpc.listpays()['pays'][0] + assert 'bolt11' not in l2.rpc.listpays()['pays'][0] From 8783ae4ba1225cafdbedbb5cb3b0ecf32cfd761e Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Fri, 31 Jul 2020 17:19:22 +0200 Subject: [PATCH 2/2] listpays mod 1: add destination inside the response when bolt11 is null Changelog-Added: JSON-RPC: `listpays` now lists the `destination` if it was provided (e.g., via the `pay` plugin or `keysend` plugin) --- doc/lightning-sendonion.7 | 6 +++++- doc/lightning-sendonion.7.md | 5 ++++- lightningd/pay.c | 4 +++- plugins/libplugin-pay.c | 3 +++ plugins/pay.c | 15 ++++++++++++++- tests/test_pay.py | 4 +++- 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/doc/lightning-sendonion.7 b/doc/lightning-sendonion.7 index 260921fee390..56d63b1e1414 100644 --- a/doc/lightning-sendonion.7 +++ b/doc/lightning-sendonion.7 @@ -3,7 +3,8 @@ lightning-sendonion - Send a payment with a custom onion packet .SH SYNOPSIS -\fBsendonion\fR \fIonion\fR \fIfirst_hop\fR \fIpayment_hash\fR [\fIlabel\fR] [\fIshared_secrets\fR] [\fIpartid\fR] [\fIbolt11\fR] [\fImsatoshi\fR] +\fBsendonion\fR \fIonion\fR \fIfirst_hop\fR \fIpayment_hash\fR [\fIlabel\fR] [\fIshared_secrets\fR] [\fIpartid\fR] [\fIbolt11\fR] +[\fIdestination\fR] [\fImsatoshi\fR] .SH DESCRIPTION @@ -90,6 +91,9 @@ The \fIbolt11\fR parameter, if provided, will be returned in \fIwaitsendpay\fR and \fIlistsendpays\fR results\. +The \fIdestination\fR parameter, if provided, will be returned in \fBlistpays\fR result\. + + The \fImsatoshi\fR parameter is used to annotate the payment, and is returned by \fIwaitsendpay\fR and \fIlistsendpays\fR\. diff --git a/doc/lightning-sendonion.7.md b/doc/lightning-sendonion.7.md index cde69a1dbe19..0b4e18f423b2 100644 --- a/doc/lightning-sendonion.7.md +++ b/doc/lightning-sendonion.7.md @@ -4,7 +4,8 @@ lightning-sendonion -- Send a payment with a custom onion packet SYNOPSIS -------- -**sendonion** *onion* *first_hop* *payment_hash* \[*label*\] \[*shared_secrets*\] \[*partid*\] \[*bolt11*\] \[*msatoshi*\] +**sendonion** *onion* *first_hop* *payment_hash* \[*label*\] \[*shared_secrets*\] \[*partid*\] \[*bolt11*\] +\[*msatoshi*\] \[*destination*\] DESCRIPTION ----------- @@ -78,6 +79,8 @@ partial payments with the same *payment_hash*. The *bolt11* parameter, if provided, will be returned in *waitsendpay* and *listsendpays* results. +The *destination* parameter, if provided, will be returned in **listpays** result. + The *msatoshi* parameter is used to annotate the payment, and is returned by *waitsendpay* and *listsendpays*. diff --git a/lightningd/pay.c b/lightningd/pay.c index f9dc40f5715e..d6a013d51766 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -1178,6 +1178,7 @@ static struct command_result *json_sendonion(struct command *cmd, struct sha256 *payment_hash; struct lightningd *ld = cmd->ld; const char *label, *b11str; + struct node_id *destination; struct secret *path_secrets; struct amount_msat *msat; u64 *partid; @@ -1191,6 +1192,7 @@ static struct command_result *json_sendonion(struct command *cmd, p_opt_def("partid", param_u64, &partid, 0), p_opt("bolt11", param_string, &b11str), p_opt_def("msatoshi", param_msat, &msat, AMOUNT_MSAT(0)), + p_opt("destination", param_node_id, &destination), NULL)) return command_param_failed(); @@ -1204,7 +1206,7 @@ static struct command_result *json_sendonion(struct command *cmd, return send_payment_core(ld, cmd, payment_hash, *partid, first_hop, *msat, AMOUNT_MSAT(0), - label, b11str, &packet, NULL, NULL, NULL, + label, b11str, &packet, destination, NULL, NULL, path_secrets); } diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 5b6fe84b07b1..4521b9afaec2 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -1041,6 +1041,9 @@ static struct command_result *payment_createonion_success(struct command *cmd, if (p->bolt11) json_add_string(req->js, "bolt11", p->bolt11); + if (p->destination) + json_add_node_id(req->js, "destination", p->destination); + send_outreq(p->plugin, req); return command_still_pending(cmd); } diff --git a/plugins/pay.c b/plugins/pay.c index 1d63d99a3214..3832e8900aa1 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1669,6 +1669,9 @@ struct pay_mpp { /* Timestamp of the first part */ u32 timestamp; + + /* The destination of the payment, if specified. */ + struct node_id *destination; }; static const struct sha256 *pay_mpp_key(const struct pay_mpp *pm) @@ -1739,6 +1742,9 @@ static void add_new_entry(struct json_stream *ret, if (pm->b11) json_add_string(ret, "bolt11", pm->b11); + if (pm->destination) + json_add_node_id(ret, "destination", pm->destination); + json_add_sha256(ret, "payment_hash", pm->payment_hash); json_add_string(ret, "status", pm->status); json_add_u32(ret, "created_at", pm->timestamp); @@ -1785,13 +1791,15 @@ static struct command_result *listsendpays_done(struct command *cmd, ret = jsonrpc_stream_success(cmd); json_array_start(ret, "pays"); json_for_each_arr(i, t, arr) { - const jsmntok_t *status, *b11tok, *hashtok, *createdtok; + const jsmntok_t *status, *b11tok, *hashtok, *destinationtok, *createdtok; const char *b11 = b11str; struct sha256 payment_hash; + struct node_id destination; u32 created_at; b11tok = json_get_member(buf, t, "bolt11"); hashtok = json_get_member(buf, t, "payment_hash"); + destinationtok = json_get_member(buf, t, "destination"); createdtok = json_get_member(buf, t, "created_at"); assert(hashtok != NULL); assert(createdtok != NULL); @@ -1801,11 +1809,15 @@ static struct command_result *listsendpays_done(struct command *cmd, if (b11tok) b11 = json_strdup(cmd, buf, b11tok); + if (destinationtok) + json_to_node_id(buf, destinationtok, &destination); + pm = pay_map_get(&pay_map, &payment_hash); if (!pm) { pm = tal(cmd, struct pay_mpp); pm->payment_hash = tal_dup(pm, struct sha256, &payment_hash); pm->b11 = tal_steal(pm, b11); + pm->destination = tal_dup(pm,struct node_id, &destination); pm->label = json_get_member(buf, t, "label"); pm->preimage = NULL; pm->amount_sent = AMOUNT_MSAT(0); @@ -1875,6 +1887,7 @@ static struct command_result *json_listpays(struct command *cmd, if (payment_hash) json_add_sha256(req->js, "payment_hash", payment_hash); + return send_outreq(cmd->plugin, req); } diff --git a/tests/test_pay.py b/tests/test_pay.py index 08817fc93ea7..0b2c1865b479 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -3261,6 +3261,8 @@ def test_listpay_result_with_paymod(node_factory, bitcoind): l2.rpc.keysend(l3.info['id'], amount_sat * 2, "keysend_l3") assert 'bolt11' in l1.rpc.listpays()['pays'][0] + assert 'bolt11' not in l2.rpc.listpays()['pays'][0] assert 'payment_hash' in l2.rpc.listpays()['pays'][0] assert 'payment_hash' in l1.rpc.listpays()['pays'][0] - assert 'bolt11' not in l2.rpc.listpays()['pays'][0] + assert 'destination' in l1.rpc.listpays()['pays'][0] + assert 'destination' in l2.rpc.listpays()['pays'][0]