From 203ef2ed0b866bad3e62c40d7bc0d7f942698b88 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 23 Feb 2019 15:30:04 +1030 Subject: [PATCH] listsendpays: updated version of listpayments. New name is less confusing, and most people should be transitioning to listpays rather than this anyway. Signed-off-by: Rusty Russell --- CHANGELOG.md | 2 + doc/Makefile | 2 +- doc/lightning-listpays.7.txt | 2 +- ...istpayments.7 => lightning-listsendpays.7} | 12 +++--- ...nts.7.txt => lightning-listsendpays.7.txt} | 8 ++-- doc/lightning-pay.7 | 2 +- doc/lightning-pay.7.txt | 2 +- doc/lightning-sendpay.7 | 4 +- doc/lightning-sendpay.7.txt | 4 +- doc/lightning-waitsendpay.7 | 6 +-- doc/lightning-waitsendpay.7.txt | 2 +- lightningd/pay.c | 14 +++++-- plugins/pay.c | 8 ++-- tests/test_connection.py | 8 ++-- tests/test_pay.py | 40 +++++++++---------- 15 files changed, 63 insertions(+), 53 deletions(-) rename doc/{lightning-listpayments.7 => lightning-listsendpays.7} (89%) rename doc/{lightning-listpayments.7.txt => lightning-listsendpays.7.txt} (87%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b01141d6f..884c0452c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - JSON API: `listfunds` now displays addresses for all outputs owned by the wallet (#2387) - JSON API: `waitsendpay` and `sendpay` output field `label` as specified by `sendpay` call. - JSON API: `listpays` command for higher-level payment view than `listpayments`, especially important with multi-part-payments coming. +- JSON API: `listpayments` is now `listsendpays`. ### Changed @@ -56,6 +57,7 @@ provide appropriate suffixes for JSON input fields. - JSON API: `short_channel_id` fields in JSON commands with `:` separators (use `x` instead). - JSON API: `pay` `description` is deprecated, as is support for BOLT11 strings using `h`. - JSON API: `sendpay` parameter `description` and `waitsendpay` and `sendpay` output fields `description` (now `label`). +- JSON API: `listpayments` has been deprecated (you probably want `listpays`) ### Removed diff --git a/doc/Makefile b/doc/Makefile index bd771ce22..8f26c2572 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -20,9 +20,9 @@ MANPAGES := doc/lightning-cli.1 \ doc/lightning-listchannels.7 \ doc/lightning-listfunds.7 \ doc/lightning-listinvoices.7 \ - doc/lightning-listpayments.7 \ doc/lightning-listpays.7 \ doc/lightning-listpeers.7 \ + doc/lightning-listsendpays.7 \ doc/lightning-newaddr.7 \ doc/lightning-pay.7 \ doc/lightning-sendpay.7 \ diff --git a/doc/lightning-listpays.7.txt b/doc/lightning-listpays.7.txt index 7155c37c7..1da3fa929 100644 --- a/doc/lightning-listpays.7.txt +++ b/doc/lightning-listpays.7.txt @@ -42,7 +42,7 @@ Rusty Russell is mainly responsible. SEE ALSO -------- -lightning-pay(7), lightning-paystatus(7), lightning-listpayments(7). +lightning-pay(7), lightning-paystatus(7), lightning-listsendpays(7). RESOURCES --------- diff --git a/doc/lightning-listpayments.7 b/doc/lightning-listsendpays.7 similarity index 89% rename from doc/lightning-listpayments.7 rename to doc/lightning-listsendpays.7 index 4cf98b006..38f6e1cb2 100644 --- a/doc/lightning-listpayments.7 +++ b/doc/lightning-listsendpays.7 @@ -1,13 +1,13 @@ '\" t -.\" Title: lightning-listpayments +.\" Title: lightning-listsendpays .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 02/22/2019 +.\" Date: 02/23/2019 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-LISTPAYME" "7" "02/22/2019" "\ \&" "\ \&" +.TH "LIGHTNING\-LISTSENDP" "7" "02/23/2019" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,13 +28,13 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -lightning-listpayments \- Low\-level command for querying payment status +lightning-listsendpays \- Low\-level command for querying sendpay status .SH "SYNOPSIS" .sp -\fBlistpayments\fR [\fIbolt11\fR] [\fIpayment_hash\fR] +\fBlistsendpays\fR [\fIbolt11\fR] [\fIpayment_hash\fR] .SH "DESCRIPTION" .sp -The \fBlistpayments\fR RPC command gets the status of all \fIsendpay\fR commands (which is also used by the \fIpay\fR command), or with \fIbolt11\fR or \fIpayment_hash\fR limits results to that specific payment\&. You cannot specify both\&. +The \fBlistsendpays\fR RPC command gets the status of all \fIsendpay\fR commands (which is also used by the \fIpay\fR command), or with \fIbolt11\fR or \fIpayment_hash\fR limits results to that specific payment\&. You cannot specify both\&. .sp Note that in future there may be more than one concurrent \fIsendpay\fR command per \fIpay\fR, so this command should be used with caution\&. .SH "RETURN VALUE" diff --git a/doc/lightning-listpayments.7.txt b/doc/lightning-listsendpays.7.txt similarity index 87% rename from doc/lightning-listpayments.7.txt rename to doc/lightning-listsendpays.7.txt index 95167f46a..d547a8e4e 100644 --- a/doc/lightning-listpayments.7.txt +++ b/doc/lightning-listsendpays.7.txt @@ -1,19 +1,19 @@ -LIGHTNING-LISTPAYMENTS(7) +LIGHTNING-LISTSENDPAYS(7) ======================== :doctype: manpage NAME ---- -lightning-listpayments - Low-level command for querying payment status +lightning-listsendpays - Low-level command for querying sendpay status SYNOPSIS -------- -*listpayments* ['bolt11'] ['payment_hash'] +*listsendpays* ['bolt11'] ['payment_hash'] DESCRIPTION ----------- -The *listpayments* RPC command gets the status of all 'sendpay' +The *listsendpays* RPC command gets the status of all 'sendpay' commands (which is also used by the 'pay' command), or with 'bolt11' or 'payment_hash' limits results to that specific payment. You cannot specify both. diff --git a/doc/lightning-pay.7 b/doc/lightning-pay.7 index 0158e6a84..fff663639 100644 --- a/doc/lightning-pay.7 +++ b/doc/lightning-pay.7 @@ -36,7 +36,7 @@ lightning-pay \- Command for sending a payment to a BOLT11 invoice .sp The \fBpay\fR RPC command attempts to find a route to the given destination, and send the funds it asks for\&. If the \fIbolt11\fR does not contain an amount, \fImsatoshi\fR is required, otherwise if it is specified it must be \fInull\fR\&. \fImsatoshi\fR is in millisatoshi precision; it can be a whole number, or a whole number with suffix \fImsat\fR or \fIsat\fR, or a three decimal point number with suffix \fIsat\fR, or an 1 to 11 decimal point number suffixed by \fIbtc\fR\&. .sp -The \fIlabel\fR field is used to attach a label to payments, and is returned in lightning\-listpays(7) and lightning\-listpayments(7)\&. The \fIriskfactor\fR is described in detail in lightning\-getroute(7), and defaults to 10\&. The \fImaxfeepercent\fR limits the money paid in fees, and defaults to 0\&.5\&. The maxfeepercent\*(Aq is a percentage of the amount that is to be paid\&. The `exemptfee option can be used for tiny payments which would be dominated by the fee leveraged by forwarding nodes\&. Setting exemptfee allows the maxfeepercent check to be skipped on fees that are smaller than exemptfee (default: 5000 millisatoshi)\&. +The \fIlabel\fR field is used to attach a label to payments, and is returned in lightning\-listpays(7) and lightning\-listsendpays(7)\&. The \fIriskfactor\fR is described in detail in lightning\-getroute(7), and defaults to 10\&. The \fImaxfeepercent\fR limits the money paid in fees, and defaults to 0\&.5\&. The maxfeepercent\*(Aq is a percentage of the amount that is to be paid\&. The `exemptfee option can be used for tiny payments which would be dominated by the fee leveraged by forwarding nodes\&. Setting exemptfee allows the maxfeepercent check to be skipped on fees that are smaller than exemptfee (default: 5000 millisatoshi)\&. .sp The response will occur when the payment fails or succeeds\&. Once a payment has succeeded, calls to \fBpay\fR with the same \fIbolt11\fR will succeed immediately\&. .sp diff --git a/doc/lightning-pay.7.txt b/doc/lightning-pay.7.txt index 3d2b79db3..bc4476b06 100644 --- a/doc/lightning-pay.7.txt +++ b/doc/lightning-pay.7.txt @@ -22,7 +22,7 @@ point number with suffix 'sat', or an 1 to 11 decimal point number suffixed by 'btc'. The 'label' field is used to attach a label to payments, and is returned -in lightning-listpays(7) and lightning-listpayments(7). +in lightning-listpays(7) and lightning-listsendpays(7). The 'riskfactor' is described in detail in lightning-getroute(7), and defaults to 10. The 'maxfeepercent' limits the money paid in fees, and defaults to 0.5. diff --git a/doc/lightning-sendpay.7 b/doc/lightning-sendpay.7 index 3b1b9e1de..dd416b11f 100644 --- a/doc/lightning-sendpay.7 +++ b/doc/lightning-sendpay.7 @@ -40,14 +40,14 @@ Generally, a client would call lightning\-getroute(7) to resolve a route, then u .sp The response will occur when the payment is on its way to the destination\&. The \fBsendpay\fR RPC command does not wait for definite success or definite failure of the payment\&. Instead, use the \fBwaitsendpay\fR RPC command to poll or wait for definite success or definite failure\&. .sp -The \fIlabel\fR and \fIbolt11\fR parameters, if provided, will be returned in \fIwaitsendpay\fR and \fIlistpayments\fR results\&. +The \fIlabel\fR and \fIbolt11\fR parameters, if provided, will be returned in \fIwaitsendpay\fR and \fIlistsendpays\fR results\&. .sp The \fImsatoshi\fR amount, if provided, is the amount that will be recorded as the target payment value\&. If not specified, it will be the final amount to the destination\&. If specified, then the final amount at the destination must be from the specified \fImsatoshi\fR to twice the specified \fImsatoshi\fR, inclusive\&. This is intended to obscure payments by overpaying slightly at the destination; the actual target payment is what should be specified as the \fImsatoshi\fR argument\&. \fImsatoshi\fR is in millisatoshi precision; it can be a whole number, or a whole number ending in \fImsat\fR or \fIsat\fR, or a number with three decimal places ending in \fIsat\fR, or a number with 1 to 11 decimal places ending in \fIbtc\fR\&. .sp Once a payment has succeeded, calls to \fBsendpay\fR with the same \fIpayment_hash\fR but a different \fImsatoshi\fR or destination will fail; this prevents accidental multiple payments\&. Calls to \fBsendpay\fR with the same \fIpayment_hash\fR, \fImsatoshi\fR, and destination as a previous successful payment (even if a different route) will return immediately with success\&. .SH "RETURN VALUE" .sp -On success, an object similar to the output of \fBlistpayments\fR will be returned\&. This object will have a \fIstatus\fR field that is typically the string \fI"pending"\fR, but may be \fI"complete"\fR if the payment was already performed successfully\&. +On success, an object similar to the output of \fBlistsendpays\fR will be returned\&. This object will have a \fIstatus\fR field that is typically the string \fI"pending"\fR, but may be \fI"complete"\fR if the payment was already performed successfully\&. .sp On error, if the error occurred from a node other than the final destination, the route table will be updated so that lightning\-getroute(7) should return an alternate route (if any)\&. An error from the final destination implies the payment should not be retried\&. .sp diff --git a/doc/lightning-sendpay.7.txt b/doc/lightning-sendpay.7.txt index 72ec862c4..7835ca89a 100644 --- a/doc/lightning-sendpay.7.txt +++ b/doc/lightning-sendpay.7.txt @@ -28,7 +28,7 @@ Instead, use the *waitsendpay* RPC command to poll or wait for definite success or definite failure. The 'label' and 'bolt11' parameters, if provided, will be returned in -'waitsendpay' and 'listpayments' results. +'waitsendpay' and 'listsendpays' results. The 'msatoshi' amount, if provided, is the amount that will be recorded as the target payment value. @@ -54,7 +54,7 @@ immediately with success. RETURN VALUE ------------ -On success, an object similar to the output of *listpayments* will +On success, an object similar to the output of *listsendpays* will be returned. This object will have a 'status' field that is typically the string '"pending"', but may be '"complete"' if the payment was diff --git a/doc/lightning-waitsendpay.7 b/doc/lightning-waitsendpay.7 index f00e59f5f..951cb5a4e 100644 --- a/doc/lightning-waitsendpay.7 +++ b/doc/lightning-waitsendpay.7 @@ -2,12 +2,12 @@ .\" Title: lightning-waitsendpay .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 01/15/2019 +.\" Date: 02/23/2019 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-WAITSENDP" "7" "01/15/2019" "\ \&" "\ \&" +.TH "LIGHTNING\-WAITSENDP" "7" "02/23/2019" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -43,7 +43,7 @@ Indicating a \fItimeout\fR of 0 effectively makes this call a pollable query of If the payment completed with success, this command returns with success\&. Otherwise, if the payment completed with failure, this command returns an error\&. .SH "RETURN VALUE" .sp -On success, an object similar to the output of \fBlistpayments\fR will be returned\&. This object will have a \fIstatus\fR field that is the string \fI"complete"\fR\&. +On success, an object similar to the output of \fBlistsendpays\fR will be returned\&. This object will have a \fIstatus\fR field that is the string \fI"complete"\fR\&. .sp On error, if the error occurred from a node other than the final destination, the route table will be updated so that getroute(7) should return an alternate route (if any)\&. An error from the final destination implies the payment should not be retried\&. .sp diff --git a/doc/lightning-waitsendpay.7.txt b/doc/lightning-waitsendpay.7.txt index b41526cb6..0fa191c40 100644 --- a/doc/lightning-waitsendpay.7.txt +++ b/doc/lightning-waitsendpay.7.txt @@ -36,7 +36,7 @@ returns an error. RETURN VALUE ------------ -On success, an object similar to the output of *listpayments* will +On success, an object similar to the output of *listsendpays* will be returned. This object will have a 'status' field that is the string '"complete"'. diff --git a/lightningd/pay.c b/lightningd/pay.c index a3faafbb5..e35c3f4a6 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -927,7 +927,7 @@ static const struct json_command waitsendpay_command = { }; AUTODATA(json_command, &waitsendpay_command); -static struct command_result *json_listpayments(struct command *cmd, +static struct command_result *json_listsendpays(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, const jsmntok_t *params) @@ -980,7 +980,15 @@ static struct command_result *json_listpayments(struct command *cmd, static const struct json_command listpayments_command = { "listpayments", - json_listpayments, - "Show outgoing payments" + json_listsendpays, + "Show outgoing payments", + true /* deprecated, use new name */ }; AUTODATA(json_command, &listpayments_command); + +static const struct json_command listsendpays_command = { + "listsendpays", + json_listsendpays, + "Show sendpay, old and current, optionally limiting to {bolt11} or {payment_hash}." +}; +AUTODATA(json_command, &listsendpays_command); diff --git a/plugins/pay.c b/plugins/pay.c index e36653409..3799f249e 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1109,7 +1109,7 @@ static const jsmntok_t *copy_member(char **ret, return m; } -static struct command_result *listpayments_done(struct command *cmd, +static struct command_result *listsendpays_done(struct command *cmd, const char *buf, const jsmntok_t *result, char *b11str) @@ -1122,7 +1122,7 @@ static struct command_result *listpayments_done(struct command *cmd, arr = json_get_member(buf, result, "payments"); if (!arr || arr->type != JSMN_ARRAY) return command_fail(cmd, LIGHTNINGD, - "Unexpected non-array result from listpayments"); + "Unexpected non-array result from listsendpays"); ret = tal_fmt(cmd, "{ 'pays': ["); json_for_each_arr(i, t, arr) { @@ -1172,8 +1172,8 @@ static struct command_result *handle_listpays(struct command *cmd, paramstr = tal_fmt(tmpctx, "'bolt11' : '%s'", b11str); else paramstr = ""; - return send_outreq(cmd, "listpayments", - listpayments_done, forward_error, + return send_outreq(cmd, "listsendpays", + listsendpays_done, forward_error, cast_const(char *, b11str), "%s", paramstr); } diff --git a/tests/test_connection.py b/tests/test_connection.py index 2b49df4a9..61d5c5b1d 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1371,9 +1371,9 @@ def test_restart_multi_htlc_rexmit(node_factory, bitcoind, executor): del l1.daemon.opts['dev-disconnect'] l1.start() - # Payments will fail due to restart, but we can see results in listpayments. - print(l1.rpc.listpayments()) - wait_for(lambda: [p['status'] for p in l1.rpc.listpayments()['payments']] == ['complete', 'complete']) + # Payments will fail due to restart, but we can see results in listsendpays. + print(l1.rpc.listsendpays()) + wait_for(lambda: [p['status'] for p in l1.rpc.listsendpays()['payments']] == ['complete', 'complete']) @unittest.skipIf(not DEVELOPER, "needs dev-disconnect") @@ -1507,7 +1507,7 @@ def test_restart_many_payments(node_factory): # Wait for them to finish. for n in innodes: - wait_for(lambda: 'pending' not in [p['status'] for p in n.rpc.listpayments()['payments']]) + wait_for(lambda: 'pending' not in [p['status'] for p in n.rpc.listsendpays()['payments']]) @unittest.skipIf(not DEVELOPER, "need dev-disconnect") diff --git a/tests/test_pay.py b/tests/test_pay.py index 5cd804b89..4130d12e5 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -52,10 +52,10 @@ def test_pay(node_factory): l1.rpc.pay(inv2, random.randint(1000, 999999)) # Should see 6 completed payments - assert len(l1.rpc.listpayments()['payments']) == 6 + assert len(l1.rpc.listsendpays()['payments']) == 6 - # Test listpayments indexed by bolt11. - payments = l1.rpc.listpayments(inv)['payments'] + # Test listsendpays indexed by bolt11. + payments = l1.rpc.listsendpays(inv)['payments'] assert len(payments) == 1 and payments[0]['payment_preimage'] == preimage @@ -221,23 +221,23 @@ def test_pay_optional_args(node_factory): inv1 = l2.rpc.invoice(123000, 'test_pay', 'desc')['bolt11'] l1.rpc.pay(inv1, label='desc') - payment1 = l1.rpc.listpayments(inv1)['payments'] + payment1 = l1.rpc.listsendpays(inv1)['payments'] assert len(payment1) and payment1[0]['msatoshi'] == 123000 assert payment1[0]['label'] == 'desc' inv2 = l2.rpc.invoice(321000, 'test_pay2', 'description')['bolt11'] l1.rpc.pay(inv2, riskfactor=5.0) - payment2 = l1.rpc.listpayments(inv2)['payments'] + payment2 = l1.rpc.listsendpays(inv2)['payments'] assert len(payment2) == 1 and payment2[0]['msatoshi'] == 321000 anyinv = l2.rpc.invoice('any', 'any_pay', 'desc')['bolt11'] l1.rpc.pay(anyinv, label='desc', msatoshi='500') - payment3 = l1.rpc.listpayments(anyinv)['payments'] + payment3 = l1.rpc.listsendpays(anyinv)['payments'] assert len(payment3) == 1 and payment3[0]['msatoshi'] == 500 assert payment3[0]['label'] == 'desc' # Should see 3 completed transactions - assert len(l1.rpc.listpayments()['payments']) == 3 + assert len(l1.rpc.listsendpays()['payments']) == 3 @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") @@ -270,9 +270,9 @@ def test_payment_success_persistence(node_factory, bitcoind, executor): # Should reconnect, and sort the payment out. l1.start() - wait_for(lambda: l1.rpc.listpayments()['payments'][0]['status'] != 'pending') + wait_for(lambda: l1.rpc.listsendpays()['payments'][0]['status'] != 'pending') - payments = l1.rpc.listpayments()['payments'] + payments = l1.rpc.listsendpays()['payments'] invoices = l2.rpc.listinvoices('inv1')['invoices'] assert len(payments) == 1 and payments[0]['status'] == 'complete' assert len(invoices) == 1 and invoices[0]['status'] == 'paid' @@ -320,9 +320,9 @@ def test_payment_failed_persistence(node_factory, executor): # Should reconnect, and fail the payment l1.start() - wait_for(lambda: l1.rpc.listpayments()['payments'][0]['status'] != 'pending') + wait_for(lambda: l1.rpc.listsendpays()['payments'][0]['status'] != 'pending') - payments = l1.rpc.listpayments()['payments'] + payments = l1.rpc.listsendpays()['payments'] invoices = l2.rpc.listinvoices('inv1')['invoices'] assert len(invoices) == 1 and invoices[0]['status'] == 'expired' assert len(payments) == 1 and payments[0]['status'] == 'failed' @@ -350,8 +350,8 @@ def test_payment_duplicate_uncommitted(node_factory, executor): # Make sure that's started... l1.daemon.wait_for_log('dev_disconnect: =WIRE_UPDATE_ADD_HTLC-nocommit') - # We should see it in listpayments - payments = l1.rpc.listpayments()['payments'] + # We should see it in listsendpays + payments = l1.rpc.listsendpays()['payments'] assert len(payments) == 1 assert payments[0]['status'] == 'pending' and payments[0]['payment_hash'] == inv1['payment_hash'] @@ -473,19 +473,19 @@ def test_sendpay(node_factory): assert only_one(l2.rpc.listinvoices('testpayment3')['invoices'])['status'] == 'paid' assert only_one(l2.rpc.listinvoices('testpayment3')['invoices'])['msatoshi_received'] == amt * 2 - # Test listpayments - payments = l1.rpc.listpayments()['payments'] + # Test listsendpays + payments = l1.rpc.listsendpays()['payments'] assert len(payments) == 2 invoice2 = only_one(l2.rpc.listinvoices('testpayment2')['invoices']) - payments = l1.rpc.listpayments(payment_hash=invoice2['payment_hash'])['payments'] + payments = l1.rpc.listsendpays(payment_hash=invoice2['payment_hash'])['payments'] assert len(payments) == 1 assert payments[0]['status'] == 'complete' assert payments[0]['payment_preimage'] == preimage2 invoice3 = only_one(l2.rpc.listinvoices('testpayment3')['invoices']) - payments = l1.rpc.listpayments(payment_hash=invoice3['payment_hash'])['payments'] + payments = l1.rpc.listsendpays(payment_hash=invoice3['payment_hash'])['payments'] assert len(payments) == 1 assert payments[0]['status'] == 'complete' @@ -1163,9 +1163,9 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind): l4.restart() l3.rpc.connect(l4.info['id'], 'localhost', l4.port) - wait_for(lambda: only_one(l1.rpc.listpayments()['payments'])['status'] == 'failed') - wait_for(lambda: only_one(l2.rpc.listpayments()['payments'])['status'] == 'failed') - wait_for(lambda: only_one(l3.rpc.listpayments()['payments'])['status'] == 'failed') + wait_for(lambda: only_one(l1.rpc.listsendpays()['payments'])['status'] == 'failed') + wait_for(lambda: only_one(l2.rpc.listsendpays()['payments'])['status'] == 'failed') + wait_for(lambda: only_one(l3.rpc.listsendpays()['payments'])['status'] == 'failed') # Should all still be connected. assert only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected']