Skip to content

Commit 67d7d4b

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 <rusty@rustcorp.com.au>
1 parent be6a6eb commit 67d7d4b

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

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

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

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

14681478
return send_payment_req(aux_cmd, payment, req);
14691479
}
@@ -1774,7 +1784,7 @@ struct xpay_params {
17741784
struct amount_msat *msat, *maxfee, *partial;
17751785
const char **layers;
17761786
unsigned int retryfor;
1777-
u32 maxdelay, dev_maxparts;
1787+
u32 maxdelay;
17781788
const char *bip353;
17791789
};
17801790

@@ -1791,7 +1801,7 @@ invoice_fetched(struct command *cmd,
17911801
return xpay_core(cmd, take(to_canonical_invstr(NULL, take(inv))),
17921802
NULL, params->maxfee, params->layers,
17931803
params->retryfor, params->partial, params->maxdelay,
1794-
params->dev_maxparts, false);
1804+
false);
17951805
}
17961806

17971807
static struct command_result *
@@ -1852,7 +1862,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
18521862
struct amount_msat *msat, *maxfee, *partial;
18531863
const char *invstring;
18541864
const char **layers;
1855-
u32 *maxdelay, *maxparts;
1865+
u32 *maxdelay;
18561866
unsigned int *retryfor;
18571867
struct out_req *req;
18581868
struct xpay_params *xparams;
@@ -1865,14 +1875,9 @@ static struct command_result *json_xpay_params(struct command *cmd,
18651875
p_opt_def("retry_for", param_number, &retryfor, 60),
18661876
p_opt("partial_msat", param_msat, &partial),
18671877
p_opt_def("maxdelay", param_u32, &maxdelay, 2016),
1868-
p_opt_dev("dev_maxparts", param_u32, &maxparts, 100),
18691878
NULL))
18701879
return command_param_failed();
18711880

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

18971901
return do_fetchinvoice(cmd, invstring, xparams);
@@ -1906,7 +1910,6 @@ static struct command_result *json_xpay_params(struct command *cmd,
19061910
xparams->layers = layers;
19071911
xparams->retryfor = *retryfor;
19081912
xparams->maxdelay = *maxdelay;
1909-
xparams->dev_maxparts = *maxparts;
19101913
xparams->bip353 = invstring;
19111914

19121915
req = jsonrpc_request_start(cmd, "fetchbip353",
@@ -1917,7 +1920,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
19171920
}
19181921

19191922
return xpay_core(cmd, invstring,
1920-
msat, maxfee, layers, *retryfor, partial, *maxdelay, *maxparts,
1923+
msat, maxfee, layers, *retryfor, partial, *maxdelay,
19211924
as_pay);
19221925
}
19231926

@@ -1929,11 +1932,12 @@ static struct command_result *xpay_core(struct command *cmd,
19291932
u32 retryfor,
19301933
const struct amount_msat *partial,
19311934
u32 maxdelay,
1932-
u32 dev_maxparts,
19331935
bool as_pay)
19341936
{
19351937
struct payment *payment = tal(cmd, struct payment);
19361938
struct xpay *xpay = xpay_of(cmd->plugin);
1939+
struct gossmap *gossmap = get_gossmap(xpay);
1940+
struct node_id dstid;
19371941
u64 now, invexpiry;
19381942
struct out_req *req;
19391943
char *err;
@@ -1957,10 +1961,8 @@ static struct command_result *xpay_core(struct command *cmd,
19571961
else
19581962
payment->layers = NULL;
19591963
payment->maxdelay = maxdelay;
1960-
payment->maxparts = dev_maxparts;
19611964

19621965
if (bolt12_has_prefix(payment->invstring)) {
1963-
struct gossmap *gossmap = get_gossmap(xpay);
19641966
struct tlv_invoice *b12inv
19651967
= invoice_decode(tmpctx, payment->invstring,
19661968
strlen(payment->invstring),
@@ -2086,6 +2088,15 @@ static struct command_result *xpay_core(struct command *cmd,
20862088
} else
20872089
payment->maxfee = *maxfee;
20882090

2091+
/* If we are using an unannounced channel, we assume we can
2092+
* only do 6 HTLCs at a time. This is currently true for
2093+
* Phoenix, which is a large and significant node. */
2094+
node_id_from_pubkey(&dstid, &payment->destination);
2095+
if (!gossmap_find_node(gossmap, &dstid))
2096+
payment->maxparts = 6;
2097+
else
2098+
payment->maxparts = 0;
2099+
20892100
/* Now preapprove, then start payment. */
20902101
if (command_check_only(cmd)) {
20912102
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('fake@fake.com', 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)