From 89f411ca79578b262a468f7a527e35761bfa0ec6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 30 Jun 2025 11:15:55 +0930 Subject: [PATCH] doc: be explicit (with tests!) on when we don't know amount_msat for listsendpays. Sangbida and I traced back through ancient history: when the pay plugin was introduced in 0.9.0 (2019!) it already used the amount_msat parameter (then called `msatoshi`), so this case effectively "never happens". But we added a test for it just in case. Signed-off-by: Rusty Russell --- contrib/msggen/msggen/schema.json | 4 ++-- doc/schemas/listpays.json | 2 +- doc/schemas/listsendpays.json | 2 +- tests/test_pay.py | 25 ++++++++++++++++--------- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json index 7f38f8e67..b2d8134b8 100644 --- a/contrib/msggen/msggen/schema.json +++ b/contrib/msggen/msggen/schema.json @@ -21942,7 +21942,7 @@ "amount_msat": { "type": "msat", "description": [ - "The amount of millisatoshi we intended to send to the destination." + "The amount of millisatoshi we intended to send to the destination. This can only be missing in the case of someone manually calling sendonion without the `amount_msat` parameter (which no plugin currently does)." ] }, "amount_sent_msat": { @@ -24449,7 +24449,7 @@ "amount_msat": { "type": "msat", "description": [ - "The amount delivered to destination (if known)." + "The amount delivered to destination (if known). This is not known in the case where sendonion(7) was used to manually initiate a payment without the `amount_msat` parameter." ] }, "destination": { diff --git a/doc/schemas/listpays.json b/doc/schemas/listpays.json index 806e73298..eaa78aa0b 100644 --- a/doc/schemas/listpays.json +++ b/doc/schemas/listpays.json @@ -192,7 +192,7 @@ "amount_msat": { "type": "msat", "description": [ - "The amount of millisatoshi we intended to send to the destination." + "The amount of millisatoshi we intended to send to the destination. This can only be missing in the case of someone manually calling sendonion without the `amount_msat` parameter (which no plugin currently does)." ] }, "amount_sent_msat": { diff --git a/doc/schemas/listsendpays.json b/doc/schemas/listsendpays.json index b40dbba5e..49d8ee5b4 100644 --- a/doc/schemas/listsendpays.json +++ b/doc/schemas/listsendpays.json @@ -144,7 +144,7 @@ "amount_msat": { "type": "msat", "description": [ - "The amount delivered to destination (if known)." + "The amount delivered to destination (if known). This is not known in the case where sendonion(7) was used to manually initiate a payment without the `amount_msat` parameter." ] }, "destination": { diff --git a/tests/test_pay.py b/tests/test_pay.py index f6531d85b..497cf2e12 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -2995,16 +2995,20 @@ def test_sendonion_rpc(node_factory): invs = l4.rpc.listinvoices(label="lbl")['invoices'] assert(len(invs) == 1 and invs[0]['status'] == 'paid') - pays = l1.rpc.listsendpays()['payments'] - assert(len(pays) == 1 and pays[0]['status'] == 'complete' - and pays[0]['payment_hash'] == inv['payment_hash']) + pay = only_one(l1.rpc.listsendpays()['payments']) + assert (pay['status'] == 'complete' + and pay['payment_hash'] == inv['payment_hash']) + + # listsendpays promised that amount would be missing if sendonion didn't + # specify + assert 'amount_msat' not in pay # And now for a failing payment, using a payment_hash that doesn't match an # invoice payment_hash = "00" * 32 onion = l1.rpc.createonion(hops=hops, assocdata=payment_hash) l1.rpc.sendonion(onion=onion['onion'], first_hop=first_hop, - payment_hash=payment_hash) + payment_hash=payment_hash, amount_msat=amt) try: l1.rpc.waitsendpay(payment_hash=payment_hash) @@ -3013,13 +3017,16 @@ def test_sendonion_rpc(node_factory): assert(e.error['code'] == 202) assert(e.error['message'] == "Malformed error reply") - pays = l1.rpc.listsendpays(payment_hash=payment_hash)['payments'] - assert(len(pays) == 1 and pays[0]['status'] == 'failed' - and pays[0]['payment_hash'] == payment_hash) - assert('erroronion' in pays[0]) + pay = only_one(l1.rpc.listsendpays(payment_hash=payment_hash)['payments']) + assert(pay['status'] == 'failed' + and pay['payment_hash'] == payment_hash) + assert 'erroronion' in pay + + # Since we told sendonion the destination amount, listsendpays will know: + assert pay['amount_msat'] == amt # Fail onion is msg + padding = 256 + 2*2 byte lengths + 32 byte HMAC - assert(len(pays[0]['erroronion']) == (256 + 32 + 2 + 2) * 2) + assert(len(pay['erroronion']) == (256 + 32 + 2 + 2) * 2) # Let's try that again, this time we give it the shared_secrets so it # should be able to decode the error.