Skip to content

Commit

Permalink
injectpaymentionion: allow specification of actual amount which reach…
Browse files Browse the repository at this point in the history
…es destination.

This appears in listsendpays / listpays, and is useful information (if we know!).

This doesn't fix old payments, but means that xpay can use this for new payments.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Dec 17, 2024
1 parent 6311a54 commit cf0bd39
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 52 deletions.
5 changes: 5 additions & 0 deletions .msggen.json
Original file line number Diff line number Diff line change
Expand Up @@ -1809,6 +1809,7 @@
"InjectpaymentonionRequest": {
"InjectPaymentOnion.amount_msat": 3,
"InjectPaymentOnion.cltv_expiry": 4,
"InjectPaymentOnion.destination_msat": 10,
"InjectPaymentOnion.groupid": 6,
"InjectPaymentOnion.invstring": 8,
"InjectPaymentOnion.label": 7,
Expand Down Expand Up @@ -7548,6 +7549,10 @@
"added": "v24.11",
"deprecated": null
},
"InjectPaymentOnion.destination_msat": {
"added": "v24.11.1",
"deprecated": null
},
"InjectPaymentOnion.groupid": {
"added": "v24.11",
"deprecated": null
Expand Down
1 change: 1 addition & 0 deletions cln-grpc/proto/node.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cln-grpc/src/convert.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cln-rpc/src/model.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion contrib/msggen/msggen/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16175,7 +16175,7 @@
"amount_msat": {
"type": "msat",
"description": [
"The amount for the first HTLC in millisatoshis. This is also the amount which will be forwarded to the first peer (if any) as we do not charge fees on our own payments."
"The amount for the first HTLC in millisatoshis. This is also the amount which will be forwarded to the first peer (if any) as we do not charge fees on our own payments. Note: this is shown in listsendpays as `amount_sent_msat`."
]
},
"cltv_expiry": {
Expand Down Expand Up @@ -16213,6 +16213,13 @@
"description": [
"`localinvreqid` is used by offers to link a payment attempt to a local `invoice_request` offer created by lightningd-invoicerequest(7)."
]
},
"destination_msat": {
"type": "msat",
"added": "v24.11.1",
"description": [
"Amount that is actually delivered to the destination (i.e. `amount_msat` minus fees), for showing in listsendpays (confusingly, as `amount_msat`)."
]
}
}
},
Expand Down
72 changes: 36 additions & 36 deletions contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion doc/schemas/lightning-injectpaymentonion.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"amount_msat": {
"type": "msat",
"description": [
"The amount for the first HTLC in millisatoshis. This is also the amount which will be forwarded to the first peer (if any) as we do not charge fees on our own payments."
"The amount for the first HTLC in millisatoshis. This is also the amount which will be forwarded to the first peer (if any) as we do not charge fees on our own payments. Note: this is shown in listsendpays as `amount_sent_msat`."
]
},
"cltv_expiry": {
Expand Down Expand Up @@ -71,6 +71,13 @@
"description": [
"`localinvreqid` is used by offers to link a payment attempt to a local `invoice_request` offer created by lightningd-invoicerequest(7)."
]
},
"destination_msat": {
"type": "msat",
"added": "v24.11.1",
"description": [
"Amount that is actually delivered to the destination (i.e. `amount_msat` minus fees), for showing in listsendpays (confusingly, as `amount_msat`)."
]
}
}
},
Expand Down
25 changes: 12 additions & 13 deletions lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@ static struct command_result *param_u64_nonzero(struct command *cmd,
static void register_payment_and_waiter(struct command *cmd,
const struct sha256 *payment_hash,
u64 partid, u64 groupid,
struct amount_msat msat,
struct amount_msat destination_msat,
struct amount_msat msat_sent,
struct amount_msat total_msat,
const char *label,
Expand All @@ -1799,7 +1799,7 @@ static void register_payment_and_waiter(struct command *cmd,
groupid,
PAYMENT_PENDING,
NULL,
msat,
destination_msat,
msat_sent,
total_msat,
NULL,
Expand Down Expand Up @@ -1829,7 +1829,7 @@ static struct command_result *json_injectpaymentonion(struct command *cmd,
struct lightningd *ld = cmd->ld;
const char *label, *invstring;
struct pubkey *blinding, *next_path_key;
struct amount_msat *msat;
struct amount_msat *destination_msat, *msat;
u32 *cltv;
u64 *partid, *groupid;
struct sha256 *local_invreq_id;
Expand Down Expand Up @@ -1857,12 +1857,13 @@ static struct command_result *json_injectpaymentonion(struct command *cmd,
p_opt("label", param_escaped_string, &label),
p_opt("invstring", param_invstring, &invstring),
p_opt("localinvreqid", param_sha256, &local_invreq_id),
p_opt_def("destination_msat", param_msat, &destination_msat, AMOUNT_MSAT(0)),
NULL))
return command_param_failed();

/* Safety check: reconcile this with previous attempts, check
* partid/groupid uniqueness: we don't know amount or total. */
ret = check_progress(cmd->ld, cmd, payment_hash, AMOUNT_MSAT(0),
* partid/groupid uniqueness: we don't know total. */
ret = check_progress(cmd->ld, cmd, payment_hash, *destination_msat,
AMOUNT_MSAT(0),
*partid, *groupid, NULL, &prev_payment);
if (ret)
Expand Down Expand Up @@ -1938,13 +1939,10 @@ static struct command_result *json_injectpaymentonion(struct command *cmd,
selfpay->groupid = *groupid;
selfpay->payment_hash = *payment_hash;

/* We actually *do* know msat delivered and total msat, but
* then check_progress will complain on the next part, because
* we don't know it then, so leave them 0 */
register_payment_and_waiter(cmd,
payment_hash,
*partid, *groupid,
AMOUNT_MSAT(0), *msat, AMOUNT_MSAT(0),
*destination_msat, *msat, AMOUNT_MSAT(0),
label, invstring, local_invreq_id,
&shared_secret);

Expand Down Expand Up @@ -2058,14 +2056,15 @@ static struct command_result *json_injectpaymentonion(struct command *cmd,
register_payment_and_waiter(cmd,
payment_hash,
*partid, *groupid,
AMOUNT_MSAT(0), *msat, AMOUNT_MSAT(0),
*destination_msat, *msat, AMOUNT_MSAT(0),
label, invstring, local_invreq_id,
&shared_secret);

/* If unknown, we set this equal (so accounting logs 0 fees) */
if (amount_msat_eq(*destination_msat, AMOUNT_MSAT(0)))
*destination_msat = *msat;
failmsg = send_htlc_out(tmpctx, next, *msat,
/* We set final_msat to the same, so fees == 0
* (in fact, we don't know!) */
*cltv, *msat,
*cltv, *destination_msat,
payment_hash,
next_path_key, *partid, *groupid,
serialize_onionpacket(tmpctx, rs->next),
Expand Down
6 changes: 5 additions & 1 deletion tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -6114,6 +6114,7 @@ def test_injectpaymentonion_simple(node_factory, executor):
assert lsp['partid'] == 1
assert lsp['payment_hash'] == inv1['payment_hash']
assert lsp['status'] == 'complete'
assert 'amount_msat' not in lsp

# We FAIL on reattempt
with pytest.raises(RpcError, match="Already paid this invoice") as err:
Expand Down Expand Up @@ -6175,6 +6176,7 @@ def test_injectpaymentonion_mpp(node_factory, executor):
assert lsp['partid'] == 1 or lsp['partid'] == 2
assert lsp['payment_hash'] == inv2['payment_hash']
assert lsp['status'] == 'complete'
assert 'amount_msat' not in lsp
assert len(lsps) == 2


Expand All @@ -6198,14 +6200,16 @@ def test_injectpaymentonion_3hop(node_factory, executor):
amount_msat=1001,
cltv_expiry=blockheight + 18 + 6 + 6,
partid=1,
groupid=0)
groupid=0,
destination_msat=1000)
assert sha256(bytes.fromhex(ret['payment_preimage'])).hexdigest() == inv3['payment_hash']
assert only_one(l3.rpc.listinvoices("test_injectpaymentonion3")['invoices'])['status'] == 'paid'
lsp = only_one(l1.rpc.listsendpays(inv3['bolt11'])['payments'])
assert lsp['groupid'] == 0
assert lsp['partid'] == 1
assert lsp['payment_hash'] == inv3['payment_hash']
assert lsp['status'] == 'complete'
assert lsp['amount_msat'] == 1000


def test_injectpaymentonion_selfpay(node_factory, executor):
Expand Down

0 comments on commit cf0bd39

Please sign in to comment.