Skip to content

Commit cccac43

Browse files
committed
xpay: restrict maxparts to 6 for non-public nodes, but remove it if we can't route.
This attempts to solve a problem we have with Phoenix clients: This payment has been split in two many parts by the sender: 31 parts vs max 6 parts allowed for on-the-fly funding. The problem is that we don't have any way in bolt11 or bolt12 to specify the maximum number of HTLCs. As a workaround, we start by restricting askrene to 6 parts if the node is not openly reachable, and if it struggles, we remove the restriction. This would work much better if askrene handled maxparts more completely! See-Also: #8331 Changelog-Fixed: `xpay` will not try to send too many HTLCs through unknown channels (6, as that is Phoenix's limit) unless it has no choice) Signed-off-by: Rusty Russell <[email protected]>
1 parent 7743075 commit cccac43

File tree

2 files changed

+31
-21
lines changed

2 files changed

+31
-21
lines changed

plugins/xpay/xpay.c

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct payment {
7878
struct amount_msat maxfee;
7979
/* Maximum delay on the route we're ok with */
8080
u32 maxdelay;
81-
/* Maximum number of payment routes that can be pending. */
81+
/* If non-zero: maximum number of payment routes that can be pending. */
8282
u32 maxparts;
8383
/* Do we have to do it all in a single part? */
8484
bool disable_mpp;
@@ -172,7 +172,6 @@ static struct command_result *xpay_core(struct command *cmd,
172172
u32 retryfor,
173173
const struct amount_msat *partial,
174174
u32 maxdelay,
175-
u32 dev_maxparts,
176175
bool as_pay);
177176

178177
/* Wrapper for pending commands (ignores return) */
@@ -1287,6 +1286,16 @@ static struct command_result *getroutes_done_err(struct command *aux_cmd,
12871286
msg = json_strdup(tmpctx, buf, json_get_member(buf, error, "message"));
12881287
json_to_int(buf, json_get_member(buf, error, "code"), &code);
12891288

1289+
/* If we were restricting the number of parts, we remove that
1290+
* restriction and try again. */
1291+
if (payment->maxparts) {
1292+
payment_log(payment, LOG_INFORM,
1293+
"getroute failed with maxparts=%u, so retrying without that restriction",
1294+
payment->maxparts);
1295+
payment->maxparts = 0;
1296+
return getroutes_for(aux_cmd, payment, payment->amount_being_routed);
1297+
}
1298+
12901299
/* Simple case: failed immediately. */
12911300
if (payment->total_num_attempts == 0) {
12921301
payment_give_up(aux_cmd, payment, code, "Failed: %s", msg);
@@ -1319,7 +1328,6 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
13191328
struct out_req *req;
13201329
const struct pubkey *dst;
13211330
struct amount_msat maxfee;
1322-
size_t count_pending;
13231331

13241332
/* I would normally assert here, but we have reports of this happening... */
13251333
if (amount_msat_is_zero(deliver)) {
@@ -1380,9 +1388,11 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
13801388
json_add_amount_msat(req->js, "maxfee_msat", maxfee);
13811389
json_add_u32(req->js, "final_cltv", payment->final_cltv);
13821390
json_add_u32(req->js, "maxdelay", payment->maxdelay);
1383-
count_pending = count_current_attempts(payment);
1384-
assert(payment->maxparts > count_pending);
1385-
json_add_u32(req->js, "maxparts", payment->maxparts - count_pending);
1391+
if (payment->maxparts) {
1392+
size_t count_pending = count_current_attempts(payment);
1393+
assert(payment->maxparts > count_pending);
1394+
json_add_u32(req->js, "maxparts", payment->maxparts - count_pending);
1395+
}
13861396

13871397
return send_payment_req(aux_cmd, payment, req);
13881398
}
@@ -1693,7 +1703,7 @@ struct xpay_params {
16931703
struct amount_msat *msat, *maxfee, *partial;
16941704
const char **layers;
16951705
unsigned int retryfor;
1696-
u32 maxdelay, dev_maxparts;
1706+
u32 maxdelay;
16971707
const char *bip353;
16981708
};
16991709

@@ -1710,7 +1720,7 @@ invoice_fetched(struct command *cmd,
17101720
return xpay_core(cmd, take(to_canonical_invstr(NULL, take(inv))),
17111721
NULL, params->maxfee, params->layers,
17121722
params->retryfor, params->partial, params->maxdelay,
1713-
params->dev_maxparts, false);
1723+
false);
17141724
}
17151725

17161726
static struct command_result *
@@ -1771,7 +1781,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
17711781
struct amount_msat *msat, *maxfee, *partial;
17721782
const char *invstring;
17731783
const char **layers;
1774-
u32 *maxdelay, *maxparts;
1784+
u32 *maxdelay;
17751785
unsigned int *retryfor;
17761786
struct out_req *req;
17771787
struct xpay_params *xparams;
@@ -1784,14 +1794,9 @@ static struct command_result *json_xpay_params(struct command *cmd,
17841794
p_opt_def("retry_for", param_number, &retryfor, 60),
17851795
p_opt("partial_msat", param_msat, &partial),
17861796
p_opt_def("maxdelay", param_u32, &maxdelay, 2016),
1787-
p_opt_dev("dev_maxparts", param_u32, &maxparts, 100),
17881797
NULL))
17891798
return command_param_failed();
17901799

1791-
if (*maxparts == 0)
1792-
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
1793-
"maxparts cannot be zero");
1794-
17951800
/* Is this a one-shot vibe payment? Kids these days! */
17961801
if (!as_pay && bolt12_has_offer_prefix(invstring)) {
17971802
struct command_result *ret;
@@ -1810,7 +1815,6 @@ static struct command_result *json_xpay_params(struct command *cmd,
18101815
xparams->layers = layers;
18111816
xparams->retryfor = *retryfor;
18121817
xparams->maxdelay = *maxdelay;
1813-
xparams->dev_maxparts = *maxparts;
18141818
xparams->bip353 = NULL;
18151819

18161820
return do_fetchinvoice(cmd, invstring, xparams);
@@ -1825,7 +1829,6 @@ static struct command_result *json_xpay_params(struct command *cmd,
18251829
xparams->layers = layers;
18261830
xparams->retryfor = *retryfor;
18271831
xparams->maxdelay = *maxdelay;
1828-
xparams->dev_maxparts = *maxparts;
18291832
xparams->bip353 = invstring;
18301833

18311834
req = jsonrpc_request_start(cmd, "fetchbip353",
@@ -1836,7 +1839,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
18361839
}
18371840

18381841
return xpay_core(cmd, invstring,
1839-
msat, maxfee, layers, *retryfor, partial, *maxdelay, *maxparts,
1842+
msat, maxfee, layers, *retryfor, partial, *maxdelay,
18401843
as_pay);
18411844
}
18421845

@@ -1848,11 +1851,12 @@ static struct command_result *xpay_core(struct command *cmd,
18481851
u32 retryfor,
18491852
const struct amount_msat *partial,
18501853
u32 maxdelay,
1851-
u32 dev_maxparts,
18521854
bool as_pay)
18531855
{
18541856
struct payment *payment = tal(cmd, struct payment);
18551857
struct xpay *xpay = xpay_of(cmd->plugin);
1858+
struct gossmap *gossmap = get_gossmap(xpay);
1859+
struct node_id dstid;
18561860
u64 now, invexpiry;
18571861
struct out_req *req;
18581862
char *err;
@@ -1875,10 +1879,8 @@ static struct command_result *xpay_core(struct command *cmd,
18751879
else
18761880
payment->layers = NULL;
18771881
payment->maxdelay = maxdelay;
1878-
payment->maxparts = dev_maxparts;
18791882

18801883
if (bolt12_has_prefix(payment->invstring)) {
1881-
struct gossmap *gossmap = get_gossmap(xpay);
18821884
struct tlv_invoice *b12inv
18831885
= invoice_decode(tmpctx, payment->invstring,
18841886
strlen(payment->invstring),
@@ -2004,6 +2006,15 @@ static struct command_result *xpay_core(struct command *cmd,
20042006
} else
20052007
payment->maxfee = *maxfee;
20062008

2009+
/* If we are using an unannounced channel, we assume we can
2010+
* only do 6 HTLCs at a time. This is currently true for
2011+
* Phoenix, which is a large and significant node. */
2012+
node_id_from_pubkey(&dstid, &payment->destination);
2013+
if (!gossmap_find_node(gossmap, &dstid))
2014+
payment->maxparts = 6;
2015+
else
2016+
payment->maxparts = 0;
2017+
20072018
/* Now preapprove, then start payment. */
20082019
if (command_check_only(cmd)) {
20092020
req = jsonrpc_request_start(cmd, "check",

tests/test_xpay.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,6 @@ def test_xpay_bip353(node_factory):
10131013
l2.rpc.xpay('[email protected]', 100)
10141014

10151015

1016-
@pytest.mark.xfail(strict=True)
10171016
def test_xpay_limited_max_accepted_htlcs(node_factory):
10181017
"""xpay should try to reduce flows to 6 if there is an unannounced channel, and only try more if that fails"""
10191018
CHANNEL_SIZE_SATS = 10**6

0 commit comments

Comments
 (0)