lightningd: add override amt to invoice_check_payment

Adds `expected_msat_override` to the `invoice_check_payment` check. If
it's set, it will be used to override the invoice amount as the expected
amount of the payment check.

This enables us to charge a different amount for a payment than the
amount stated on the invoice.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
This commit is contained in:
Peter Neuroth
2025-11-06 12:49:23 +01:00
committed by Rusty Russell
parent 193f24a039
commit 572c4553a2
5 changed files with 14 additions and 6 deletions

View File

@@ -150,8 +150,8 @@ void htlc_set_add_(struct lightningd *ld,
* [Failure Messages](#failure-messages)
* - Note: "amount paid" specified there is the `total_msat` field.
*/
details = invoice_check_payment(tmpctx, ld, payment_hash,
total_msat, payment_secret, &err);
details = invoice_check_payment(tmpctx, ld, payment_hash, total_msat,
NULL, payment_secret, &err);
if (!details) {
log_debug(log, "payment failed: %s", err);
fail(arg, take(failmsg_incorrect_or_unknown(NULL, ld, msat)));

View File

@@ -332,6 +332,7 @@ invoice_check_payment(const tal_t *ctx,
struct lightningd *ld,
const struct sha256 *payment_hash,
const struct amount_msat msat,
const struct amount_msat *expected_msat_override,
const struct secret *payment_secret,
const char **err)
{
@@ -408,15 +409,19 @@ invoice_check_payment(const tal_t *ctx,
if (details->msat != NULL) {
struct amount_msat twice;
if (amount_msat_less(msat, *details->msat)) {
/* Override the expected amount. */
struct amount_msat expected_msat =
expected_msat_override ? *expected_msat_override : *details->msat;
if (amount_msat_less(msat, expected_msat)) {
*err = tal_fmt(ctx, "Attempt to pay %s with amount %s < %s",
fmt_sha256(tmpctx, &details->rhash),
fmt_amount_msat(tmpctx, msat),
fmt_amount_msat(tmpctx, *details->msat));
fmt_amount_msat(tmpctx, expected_msat));
return tal_free(details);
}
if (amount_msat_add(&twice, *details->msat, *details->msat)
if (amount_msat_add(&twice, expected_msat, expected_msat)
&& amount_msat_greater(msat, twice)) {
*err = tal_fmt(ctx, "Attempt to pay %s with amount %s > %s",
fmt_sha256(tmpctx, &details->rhash),

View File

@@ -50,6 +50,7 @@ struct invoice_details {
* @ld: lightningd
* @payment_hash: hash of preimage they want.
* @msat: amount they offer to pay.
* @expected_msat_override: if set: overrides the amount we expect to be payed.
* @payment_secret: they payment secret they sent, if any.
* @err: error string if it returns NULL.
*
@@ -59,6 +60,7 @@ const struct invoice_details *invoice_check_payment(const tal_t *ctx,
struct lightningd *ld,
const struct sha256 *payment_hash,
const struct amount_msat msat,
const struct amount_msat *expected_msat_override,
const struct secret *payment_secret,
const char **err);

View File

@@ -1482,7 +1482,7 @@ static struct command_result *self_payment(struct lightningd *ld,
local_invreq_id);
/* Now, resolve the invoice */
inv = invoice_check_payment(tmpctx, ld, rhash, msat, payment_secret, &err);
inv = invoice_check_payment(tmpctx, ld, rhash, msat, NULL, payment_secret, &err);
if (!inv) {
struct routing_failure *fail;
wallet_payment_set_status(ld->wallet, rhash, partid, groupid,

View File

@@ -391,6 +391,7 @@ const struct invoice_details *invoice_check_payment(const tal_t *ctx UNNEEDED,
struct lightningd *ld UNNEEDED,
const struct sha256 *payment_hash UNNEEDED,
const struct amount_msat msat UNNEEDED,
const struct amount_msat *expected_msat_override UNNEEDED,
const struct secret *payment_secret UNNEEDED,
const char **err UNNEEDED)
{ fprintf(stderr, "invoice_check_payment called!\n"); abort(); }