Skip to content

Commit faa6643

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 ee0cfc2 commit faa6643

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
@@ -84,7 +84,7 @@ struct payment {
8484
struct amount_msat maxfee;
8585
/* Maximum delay on the route we're ok with */
8686
u32 maxdelay;
87-
/* Maximum number of payment routes that can be pending. */
87+
/* If non-zero: maximum number of payment routes that can be pending. */
8888
u32 maxparts;
8989
/* Do we have to do it all in a single part? */
9090
bool disable_mpp;
@@ -178,7 +178,6 @@ static struct command_result *xpay_core(struct command *cmd,
178178
u32 retryfor,
179179
const struct amount_msat *partial,
180180
u32 maxdelay,
181-
u32 dev_maxparts,
182181
bool as_pay);
183182

184183
/* Wrapper for pending commands (ignores return) */
@@ -1316,6 +1315,16 @@ static struct command_result *getroutes_done_err(struct command *aux_cmd,
13161315
msg = json_strdup(tmpctx, buf, json_get_member(buf, error, "message"));
13171316
json_to_int(buf, json_get_member(buf, error, "code"), &code);
13181317

1318+
/* If we were restricting the number of parts, we remove that
1319+
* restriction and try again. */
1320+
if (payment->maxparts) {
1321+
payment_log(payment, LOG_INFORM,
1322+
"getroute failed with maxparts=%u, so retrying without that restriction",
1323+
payment->maxparts);
1324+
payment->maxparts = 0;
1325+
return getroutes_for(aux_cmd, payment, payment->amount_being_routed);
1326+
}
1327+
13191328
/* Simple case: failed immediately. */
13201329
if (payment->total_num_attempts == 0) {
13211330
payment_give_up(aux_cmd, payment, code, "Failed: %s", msg);
@@ -1377,7 +1386,6 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
13771386
struct out_req *req;
13781387
const struct pubkey *dst;
13791388
struct amount_msat maxfee;
1380-
size_t count_pending;
13811389

13821390
/* I would normally assert here, but we have reports of this happening... */
13831391
if (amount_msat_is_zero(deliver)) {
@@ -1460,9 +1468,11 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
14601468
json_add_amount_msat(req->js, "maxfee_msat", maxfee);
14611469
json_add_u32(req->js, "final_cltv", payment->final_cltv);
14621470
json_add_u32(req->js, "maxdelay", payment->maxdelay);
1463-
count_pending = count_current_attempts(payment);
1464-
assert(payment->maxparts > count_pending);
1465-
json_add_u32(req->js, "maxparts", payment->maxparts - count_pending);
1471+
if (payment->maxparts) {
1472+
size_t count_pending = count_current_attempts(payment);
1473+
assert(payment->maxparts > count_pending);
1474+
json_add_u32(req->js, "maxparts", payment->maxparts - count_pending);
1475+
}
14661476

14671477
return send_payment_req(aux_cmd, payment, req);
14681478
}
@@ -1773,7 +1783,7 @@ struct xpay_params {
17731783
struct amount_msat *msat, *maxfee, *partial;
17741784
const char **layers;
17751785
unsigned int retryfor;
1776-
u32 maxdelay, dev_maxparts;
1786+
u32 maxdelay;
17771787
const char *bip353;
17781788
};
17791789

@@ -1790,7 +1800,7 @@ invoice_fetched(struct command *cmd,
17901800
return xpay_core(cmd, take(to_canonical_invstr(NULL, take(inv))),
17911801
NULL, params->maxfee, params->layers,
17921802
params->retryfor, params->partial, params->maxdelay,
1793-
params->dev_maxparts, false);
1803+
false);
17941804
}
17951805

17961806
static struct command_result *
@@ -1851,7 +1861,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
18511861
struct amount_msat *msat, *maxfee, *partial;
18521862
const char *invstring;
18531863
const char **layers;
1854-
u32 *maxdelay, *maxparts;
1864+
u32 *maxdelay;
18551865
unsigned int *retryfor;
18561866
struct out_req *req;
18571867
struct xpay_params *xparams;
@@ -1864,14 +1874,9 @@ static struct command_result *json_xpay_params(struct command *cmd,
18641874
p_opt_def("retry_for", param_number, &retryfor, 60),
18651875
p_opt("partial_msat", param_msat, &partial),
18661876
p_opt_def("maxdelay", param_u32, &maxdelay, 2016),
1867-
p_opt_dev("dev_maxparts", param_u32, &maxparts, 100),
18681877
NULL))
18691878
return command_param_failed();
18701879

1871-
if (*maxparts == 0)
1872-
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
1873-
"maxparts cannot be zero");
1874-
18751880
/* Is this a one-shot vibe payment? Kids these days! */
18761881
if (!as_pay && bolt12_has_offer_prefix(invstring)) {
18771882
struct command_result *ret;
@@ -1890,7 +1895,6 @@ static struct command_result *json_xpay_params(struct command *cmd,
18901895
xparams->layers = layers;
18911896
xparams->retryfor = *retryfor;
18921897
xparams->maxdelay = *maxdelay;
1893-
xparams->dev_maxparts = *maxparts;
18941898
xparams->bip353 = NULL;
18951899

18961900
return do_fetchinvoice(cmd, invstring, xparams);
@@ -1905,7 +1909,6 @@ static struct command_result *json_xpay_params(struct command *cmd,
19051909
xparams->layers = layers;
19061910
xparams->retryfor = *retryfor;
19071911
xparams->maxdelay = *maxdelay;
1908-
xparams->dev_maxparts = *maxparts;
19091912
xparams->bip353 = invstring;
19101913

19111914
req = jsonrpc_request_start(cmd, "fetchbip353",
@@ -1916,7 +1919,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
19161919
}
19171920

19181921
return xpay_core(cmd, invstring,
1919-
msat, maxfee, layers, *retryfor, partial, *maxdelay, *maxparts,
1922+
msat, maxfee, layers, *retryfor, partial, *maxdelay,
19201923
as_pay);
19211924
}
19221925

@@ -1928,11 +1931,12 @@ static struct command_result *xpay_core(struct command *cmd,
19281931
u32 retryfor,
19291932
const struct amount_msat *partial,
19301933
u32 maxdelay,
1931-
u32 dev_maxparts,
19321934
bool as_pay)
19331935
{
19341936
struct payment *payment = tal(cmd, struct payment);
19351937
struct xpay *xpay = xpay_of(cmd->plugin);
1938+
struct gossmap *gossmap = get_gossmap(xpay);
1939+
struct node_id dstid;
19361940
u64 now, invexpiry;
19371941
struct out_req *req;
19381942
char *err;
@@ -1956,10 +1960,8 @@ static struct command_result *xpay_core(struct command *cmd,
19561960
else
19571961
payment->layers = NULL;
19581962
payment->maxdelay = maxdelay;
1959-
payment->maxparts = dev_maxparts;
19601963

19611964
if (bolt12_has_prefix(payment->invstring)) {
1962-
struct gossmap *gossmap = get_gossmap(xpay);
19631965
struct tlv_invoice *b12inv
19641966
= invoice_decode(tmpctx, payment->invstring,
19651967
strlen(payment->invstring),
@@ -2085,6 +2087,15 @@ static struct command_result *xpay_core(struct command *cmd,
20852087
} else
20862088
payment->maxfee = *maxfee;
20872089

2090+
/* If we are using an unannounced channel, we assume we can
2091+
* only do 6 HTLCs at a time. This is currently true for
2092+
* Phoenix, which is a large and significant node. */
2093+
node_id_from_pubkey(&dstid, &payment->destination);
2094+
if (!gossmap_find_node(gossmap, &dstid))
2095+
payment->maxparts = 6;
2096+
else
2097+
payment->maxparts = 0;
2098+
20882099
/* Now preapprove, then start payment. */
20892100
if (command_check_only(cmd)) {
20902101
req = jsonrpc_request_start(cmd, "check",

tests/test_xpay.py

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

10221022

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

0 commit comments

Comments
 (0)