Skip to content

Commit b302d3b

Browse files
committed
xpay: add maxdelay parameter
Changelog-Added: Plugins: `xpay` now supports a `maxdelay` parameter for better `xpay-handle-pay` compatibility.
1 parent 98679aa commit b302d3b

File tree

12 files changed

+217
-93
lines changed

12 files changed

+217
-93
lines changed

.msggen.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,7 @@
17721772
"GetRoutes.final_cltv": 7,
17731773
"GetRoutes.finalcltv": 6,
17741774
"GetRoutes.layers[]": 4,
1775+
"GetRoutes.maxdelay": 8,
17751776
"GetRoutes.maxfee_msat": 5,
17761777
"GetRoutes.source": 1
17771778
},
@@ -3728,6 +3729,7 @@
37283729
"Xpay.amount_msat": 2,
37293730
"Xpay.invstring": 1,
37303731
"Xpay.layers[]": 4,
3732+
"Xpay.maxdelay": 7,
37313733
"Xpay.maxfee": 3,
37323734
"Xpay.partial_msat": 6,
37333735
"Xpay.retry_for": 5
@@ -7317,6 +7319,10 @@
73177319
"added": "v24.08",
73187320
"deprecated": null
73197321
},
7322+
"GetRoutes.maxdelay": {
7323+
"added": "v25.02",
7324+
"deprecated": null
7325+
},
73207326
"GetRoutes.maxfee_msat": {
73217327
"added": "v24.08",
73227328
"deprecated": null
@@ -12969,6 +12975,10 @@
1296912975
"added": "v24.11",
1297012976
"deprecated": null
1297112977
},
12978+
"Xpay.maxdelay": {
12979+
"added": "v25.02",
12980+
"deprecated": null
12981+
},
1297212982
"Xpay.maxfee": {
1297312983
"added": "v24.11",
1297412984
"deprecated": null

cln-grpc/proto/node.proto

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-grpc/src/convert.rs

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-rpc/src/model.rs

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/msggen/msggen/schema.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15827,6 +15827,14 @@
1582715827
"description": [
1582815828
"Number of blocks for the final node. We need to know this because no HTLC is allowed to have a CLTV delay more than 2016 blocks."
1582915829
]
15830+
},
15831+
"maxdelay": {
15832+
"type": "u32",
15833+
"added": "v25.02",
15834+
"description": [
15835+
"Maximum number of blocks of delay for the route. Cannot be bigger than 2016."
15836+
],
15837+
"default": "2016"
1583015838
}
1583115839
}
1583215840
},
@@ -36353,6 +36361,14 @@
3635336361
"description": [
3635436362
"Explicitly state that you are only paying some part of the invoice. Presumably someone else is paying the rest (otherwise the payment will time out at the recipient)."
3635536363
]
36364+
},
36365+
"maxdelay": {
36366+
"type": "u32",
36367+
"added": "v25.02",
36368+
"description": [
36369+
"A payment may be delayed for up to `maxdelay` blocks by another node; clients should be prepared for this worst case."
36370+
],
36371+
"default": "2016"
3635636372
}
3635736373
}
3635836374
},

contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Lines changed: 76 additions & 76 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/schemas/lightning-getroutes.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@
6565
"description": [
6666
"Number of blocks for the final node. We need to know this because no HTLC is allowed to have a CLTV delay more than 2016 blocks."
6767
]
68+
},
69+
"maxdelay": {
70+
"type": "u32",
71+
"added": "v25.02",
72+
"description": [
73+
"Maximum number of blocks of delay for the route. Cannot be bigger than 2016."
74+
],
75+
"default": "2016"
6876
}
6977
}
7078
},

doc/schemas/lightning-xpay.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@
5757
"description": [
5858
"Explicitly state that you are only paying some part of the invoice. Presumably someone else is paying the rest (otherwise the payment will time out at the recipient)."
5959
]
60+
},
61+
"maxdelay": {
62+
"type": "u32",
63+
"added": "v25.02",
64+
"description": [
65+
"A payment may be delayed for up to `maxdelay` blocks by another node; clients should be prepared for this worst case."
66+
],
67+
"default": "2016"
6068
}
6169
}
6270
},

plugins/askrene/askrene.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ static const char *get_routes(const tal_t *ctx,
323323
struct amount_msat amount,
324324
struct amount_msat maxfee,
325325
u32 finalcltv,
326+
u32 maxdelay,
326327
const char **layers,
327328
struct gossmap_localmods *localmods,
328329
const struct layer *local_layer,
@@ -418,18 +419,11 @@ static const char *get_routes(const tal_t *ctx,
418419
}
419420

420421
/* Too much delay? */
421-
/* BOLT #4:
422-
* ## `max_htlc_cltv` Selection
423-
*
424-
* This ... value is defined as 2016 blocks, based on historical value
425-
* deployed by Lightning implementations.
426-
*/
427-
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
428-
while (finalcltv + flows_worst_delay(flows) > 2016) {
422+
while (finalcltv + flows_worst_delay(flows) > maxdelay) {
429423
delay_feefactor *= 2;
430424
rq_log(tmpctx, rq, LOG_UNUSUAL,
431425
"The worst flow delay is %"PRIu64" (> %i), retrying with delay_feefactor %f...",
432-
flows_worst_delay(flows), 2016 - finalcltv, delay_feefactor);
426+
flows_worst_delay(flows), maxdelay - finalcltv, delay_feefactor);
433427
flows = minflow(rq, rq, srcnode, dstnode, amount,
434428
mu, delay_feefactor);
435429
if (!flows || delay_feefactor > 10) {
@@ -487,7 +481,7 @@ static const char *get_routes(const tal_t *ctx,
487481
flows = new_flows;
488482
}
489483

490-
if (finalcltv + flows_worst_delay(flows) > 2016) {
484+
if (finalcltv + flows_worst_delay(flows) > maxdelay) {
491485
ret = rq_log(ctx, rq, LOG_UNUSUAL,
492486
"Could not find route without excessive cost or delays");
493487
goto fail;
@@ -601,7 +595,7 @@ struct getroutes_info {
601595
struct command *cmd;
602596
struct node_id *source, *dest;
603597
struct amount_msat *amount, *maxfee;
604-
u32 *finalcltv;
598+
u32 *finalcltv, *maxdelay;
605599
const char **layers;
606600
struct additional_cost_htable *additional_costs;
607601
/* Non-NULL if we are told to use "auto.localchans" */
@@ -621,7 +615,7 @@ static struct command_result *do_getroutes(struct command *cmd,
621615
err = get_routes(cmd, cmd,
622616
info->source, info->dest,
623617
*info->amount, *info->maxfee, *info->finalcltv,
624-
info->layers, localmods, info->local_layer,
618+
*info->maxdelay, info->layers, localmods, info->local_layer,
625619
&routes, &amounts, info->additional_costs, &probability);
626620
if (err)
627621
return command_fail(cmd, PAY_ROUTE_NOT_FOUND, "%s", err);
@@ -751,6 +745,14 @@ static struct command_result *json_getroutes(struct command *cmd,
751745
const char *buffer,
752746
const jsmntok_t *params)
753747
{
748+
/* BOLT #4:
749+
* ## `max_htlc_cltv` Selection
750+
*
751+
* This ... value is defined as 2016 blocks, based on
752+
* historical value deployed by Lightning implementations.
753+
*/
754+
/* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */
755+
const u32 maxdelay_allowed = 2016;
754756
struct getroutes_info *info = tal(cmd, struct getroutes_info);
755757

756758
if (!param(cmd, buffer, params,
@@ -760,9 +762,17 @@ static struct command_result *json_getroutes(struct command *cmd,
760762
p_req("layers", param_layer_names, &info->layers),
761763
p_req("maxfee_msat", param_msat, &info->maxfee),
762764
p_req("final_cltv", param_u32, &info->finalcltv),
765+
p_opt_def("maxdelay", param_u32, &info->maxdelay,
766+
maxdelay_allowed),
763767
NULL))
764768
return command_param_failed();
765769

770+
if (*info->maxdelay > maxdelay_allowed) {
771+
return command_fail(cmd, PAY_USER_ERROR,
772+
"maximum delay allowed is %d",
773+
maxdelay_allowed);
774+
}
775+
766776
info->cmd = cmd;
767777
info->additional_costs = tal(info, struct additional_cost_htable);
768778
additional_cost_htable_init(info->additional_costs);

plugins/xpay/xpay.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ struct payment {
7373
struct amount_msat full_amount;
7474
/* Maximum fee we're prepare to pay */
7575
struct amount_msat maxfee;
76+
/* Maximum delay on the route we're ok with */
77+
u32 *maxdelay;
7678
/* BOLT11 payment secret (NULL for BOLT12, it uses blinded paths) */
7779
const struct secret *payment_secret;
7880
/* BOLT11 payment metadata (NULL for BOLT12, it uses blinded paths) */
@@ -1186,6 +1188,7 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
11861188
json_array_end(req->js);
11871189
json_add_amount_msat(req->js, "maxfee_msat", maxfee);
11881190
json_add_u32(req->js, "final_cltv", payment->final_cltv);
1191+
json_add_u32(req->js, "maxdelay", *payment->maxdelay);
11891192

11901193
return send_payment_req(aux_cmd, payment, req);
11911194
}
@@ -1470,6 +1473,7 @@ static struct command_result *json_xpay_core(struct command *cmd,
14701473
p_opt("layers", param_string_array, &payment->layers),
14711474
p_opt_def("retry_for", param_number, &retryfor, 60),
14721475
p_opt("partial_msat", param_msat, &partial),
1476+
p_opt_def("maxdelay", param_u32, &payment->maxdelay, 2016),
14731477
NULL))
14741478
return command_param_failed();
14751479

@@ -1884,7 +1888,7 @@ static struct command_result *handle_rpc_command(struct command *cmd,
18841888
struct xpay *xpay = xpay_of(cmd->plugin);
18851889
const jsmntok_t *rpc_tok, *method_tok, *params_tok, *id_tok,
18861890
*bolt11 = NULL, *amount_msat = NULL,
1887-
*partial_msat = NULL, *retry_for = NULL;
1891+
*partial_msat = NULL, *retry_for = NULL, *maxdelay = NULL;
18881892
const char *maxfee = NULL;
18891893
struct json_stream *response;
18901894

@@ -1933,6 +1937,8 @@ static struct command_result *handle_rpc_command(struct command *cmd,
19331937
maxfeepercent = t + 1;
19341938
else if (json_tok_streq(buf, t, "exemptfee"))
19351939
exemptfee = t + 1;
1940+
else if (json_tok_streq(buf, t, "maxdelay"))
1941+
maxdelay = t + 1;
19361942
else {
19371943
plugin_log(cmd->plugin, LOG_INFORM,
19381944
"Not redirecting pay (unknown arg %.*s)",
@@ -1978,6 +1984,8 @@ static struct command_result *handle_rpc_command(struct command *cmd,
19781984
json_add_string(response, "maxfee", maxfee);
19791985
if (partial_msat)
19801986
json_add_tok(response, "partial_msat", partial_msat, buf);
1987+
if (maxdelay)
1988+
json_add_tok(response, "maxdelay", maxdelay, buf);
19811989
json_object_end(response);
19821990
json_object_end(response);
19831991
return command_finished(cmd, response);

0 commit comments

Comments
 (0)