xpay: avoid MPP if invoice does not allow it.

This is deeply annoying, and we may have to support this properly
(using a separate algorithm entirely) if other implementations don't
fix their crap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Plugins: xpay: suppress multi-part payment if invoice doesn't allow it (please, fix your nodes!)
This commit is contained in:
Rusty Russell
2025-02-14 15:22:48 +10:30
parent 461eb2eddb
commit 4ed709f9ec
2 changed files with 11 additions and 1 deletions

View File

@@ -76,6 +76,8 @@ struct payment {
struct amount_msat maxfee;
/* Maximum delay on the route we're ok with */
u32 *maxdelay;
/* Do we have to do it all in a single part? */
bool disable_mpp;
/* BOLT11 payment secret (NULL for BOLT12, it uses blinded paths) */
const struct secret *payment_secret;
/* BOLT11 payment metadata (NULL for BOLT12, it uses blinded paths) */
@@ -1192,6 +1194,8 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
/* Add user-specified layers */
for (size_t i = 0; i < tal_count(payment->layers); i++)
json_add_string(req->js, NULL, payment->layers[i]);
if (payment->disable_mpp)
json_add_string(req->js, NULL, "auto.no_mpp_support");
json_array_end(req->js);
json_add_amount_msat(req->js, "maxfee_msat", maxfee);
json_add_u32(req->js, "final_cltv", payment->final_cltv);
@@ -1457,6 +1461,11 @@ preapproveinvoice_succeed(struct command *cmd,
payment->unique_id = xpay->counter++;
payment->private_layer = tal_fmt(payment,
"xpay-%"PRIu64, payment->unique_id);
/* Now unique_id is set, we can log this message */
if (payment->disable_mpp)
payment_log(payment, LOG_INFORM, "No MPP support: this is going to be hard to pay");
return populate_private_layer(cmd, payment);
}
@@ -1551,6 +1560,7 @@ static struct command_result *json_xpay_core(struct command *cmd,
if (payment->payinfos[i]->cltv_expiry_delta > payment->final_cltv)
payment->final_cltv = payment->payinfos[i]->cltv_expiry_delta;
}
payment->disable_mpp = false;
} else {
struct bolt11 *b11
= bolt11_decode(tmpctx, payment->invstring,
@@ -1586,6 +1596,7 @@ static struct command_result *json_xpay_core(struct command *cmd,
else
payment->full_amount = *msat;
payment->disable_mpp = !feature_offered(b11->features, OPT_BASIC_MPP);
if (amount_msat_is_zero(payment->full_amount))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Cannot pay bolt11 invoice with zero amount");

View File

@@ -621,7 +621,6 @@ def test_xpay_zeroconf(node_factory):
l1.rpc.xpay(b12)
@pytest.mark.xfail(strict=True)
def test_xpay_no_mpp(node_factory, chainparams):
"""Suppress mpp, resulting in a single payment part"""
l1, l2, l3, l4 = node_factory.get_nodes(4)