Skip to content

Commit 1102d80

Browse files
committed
askrene: add optional layers to reservations.
We have the issue of aliases: xpay uses scids like 0x0x0 for routehints and blinded paths, and then can apply reservations to them. But generally, reservations are *global*, so we need to differentiate. Changelog-Added: Plugins: `askrene-reserve` and `askrene-unreserve` can take an optional `layer` inside `path` elements. Signed-off-by: Rusty Russell <[email protected]>
1 parent da4edd2 commit 1102d80

File tree

15 files changed

+264
-158
lines changed

15 files changed

+264
-158
lines changed

.msggen.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@
781781
"Askrene-reservePath": {
782782
"AskRene-Reserve.path[].amount_msat": 3,
783783
"AskRene-Reserve.path[].direction": 2,
784+
"AskRene-Reserve.path[].layer": 5,
784785
"AskRene-Reserve.path[].short_channel_id": 1,
785786
"AskRene-Reserve.path[].short_channel_id_dir": 4
786787
},
@@ -790,6 +791,7 @@
790791
"Askrene-unreservePath": {
791792
"AskRene-Unreserve.path[].amount_msat": 3,
792793
"AskRene-Unreserve.path[].direction": 2,
794+
"AskRene-Unreserve.path[].layer": 5,
793795
"AskRene-Unreserve.path[].short_channel_id": 1,
794796
"AskRene-Unreserve.path[].short_channel_id_dir": 4
795797
},
@@ -4548,6 +4550,10 @@
45484550
"added": "v24.08",
45494551
"deprecated": null
45504552
},
4553+
"AskRene-Reserve.path[].layer": {
4554+
"added": "v25.12",
4555+
"deprecated": null
4556+
},
45514557
"AskRene-Reserve.path[].short_channel_id": {
45524558
"added": "v24.08",
45534559
"deprecated": null
@@ -4572,6 +4578,10 @@
45724578
"added": "v24.08",
45734579
"deprecated": null
45744580
},
4581+
"AskRene-Unreserve.path[].layer": {
4582+
"added": "v25.12",
4583+
"deprecated": null
4584+
},
45754585
"AskRene-Unreserve.path[].short_channel_id": {
45764586
"added": "v24.08",
45774587
"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: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@
11221122
"layer": {
11231123
"type": "string",
11241124
"description": [
1125-
"The name of the layer to apply this change to."
1125+
"The name of the layer to apply this change to. Also causes us to consider any reservations which are local to that layer (which is useful for fake channels where `layer` is set in an `askrene-reserve` `path` object)."
11261126
]
11271127
},
11281128
"short_channel_id_dir": {
@@ -1879,6 +1879,13 @@
18791879
"description": [
18801880
"The amount to send into this hop."
18811881
]
1882+
},
1883+
"layer": {
1884+
"added": "v25.12",
1885+
"type": "string",
1886+
"description": [
1887+
"The layer to restrict this reservation to. This is only useful for fake channels which are not uniquely identified by `short_channel_id_dir`, which would otherwise confuse multiple unrelated callers."
1888+
]
18821889
}
18831890
}
18841891
}
@@ -1980,6 +1987,13 @@
19801987
"description": [
19811988
"The amount to send into this hop."
19821989
]
1990+
},
1991+
"layer": {
1992+
"added": "v25.12",
1993+
"type": "string",
1994+
"description": [
1995+
"The layer to restrict this reservation to (useful for fake channels)."
1996+
]
19831997
}
19841998
}
19851999
}

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

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

doc/schemas/askrene-inform-channel.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"layer": {
2020
"type": "string",
2121
"description": [
22-
"The name of the layer to apply this change to."
22+
"The name of the layer to apply this change to. Also causes us to consider any reservations which are local to that layer (which is useful for fake channels where `layer` is set in an `askrene-reserve` `path` object)."
2323
]
2424
},
2525
"short_channel_id_dir": {

doc/schemas/askrene-reserve.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
"description": [
3737
"The amount to send into this hop."
3838
]
39+
},
40+
"layer": {
41+
"added": "v25.12",
42+
"type": "string",
43+
"description": [
44+
"The layer to restrict this reservation to. This is only useful for fake channels which are not uniquely identified by `short_channel_id_dir`, which would otherwise confuse multiple unrelated callers."
45+
]
3946
}
4047
}
4148
}

doc/schemas/askrene-unreserve.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
"description": [
3737
"The amount to send into this hop."
3838
]
39+
},
40+
"layer": {
41+
"added": "v25.12",
42+
"type": "string",
43+
"description": [
44+
"The layer to restrict this reservation to (useful for fake channels)."
45+
]
3946
}
4047
}
4148
}

plugins/askrene/askrene.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,21 @@ static struct command_result *parse_reserve_hop(struct command *cmd,
147147
struct reserve_hop *rhop)
148148
{
149149
const char *err;
150+
const char *layername = NULL;
150151

151-
err = json_scan(tmpctx, buffer, tok, "{short_channel_id_dir:%,amount_msat:%}",
152+
err = json_scan(tmpctx, buffer, tok, "{short_channel_id_dir:%,amount_msat:%,layer?:%}",
152153
JSON_SCAN(json_to_short_channel_id_dir, &rhop->scidd),
153-
JSON_SCAN(json_to_msat, &rhop->amount));
154+
JSON_SCAN(json_to_msat, &rhop->amount),
155+
JSON_SCAN_TAL(tmpctx, json_strdup, &layername));
154156
if (err)
155157
return command_fail_badparam(cmd, name, buffer, tok, err);
158+
if (layername) {
159+
rhop->layer = find_layer(get_askrene(cmd->plugin), layername);
160+
if (!rhop->layer)
161+
return command_fail_badparam(cmd, name, buffer, tok, "Unknown layer");
162+
} else
163+
rhop->layer = NULL;
164+
156165
return NULL;
157166
}
158167

@@ -548,8 +557,8 @@ void get_constraints(const struct route_query *rq,
548557
*max = gossmap_chan_get_capacity(rq->gossmap, chan);
549558

550559
/* Finally, if any is in use, subtract that! */
551-
reserve_sub(rq->reserved, &scidd, min);
552-
reserve_sub(rq->reserved, &scidd, max);
560+
reserve_sub(rq->reserved, &scidd, rq->layers, min);
561+
reserve_sub(rq->reserved, &scidd, rq->layers, max);
553562
}
554563

555564
static struct command_result *do_getroutes(struct command *cmd,
@@ -916,9 +925,11 @@ static struct command_result *json_askrene_unreserve(struct command *cmd,
916925
for (size_t i = 0; i < tal_count(path); i++) {
917926
if (!reserve_remove(askrene->reserved, &path[i])) {
918927
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
919-
"Unknown reservation for %s",
928+
"Unknown reservation for %s%s%s",
920929
fmt_short_channel_id_dir(tmpctx,
921-
&path[i].scidd));
930+
&path[i].scidd),
931+
path[i].layer ? " on layer " : "",
932+
path[i].layer ? layer_name(path[i].layer) : "");
922933
}
923934
}
924935

@@ -933,14 +944,15 @@ static struct command_result *json_askrene_listreservations(struct command *cmd,
933944
struct askrene *askrene = get_askrene(cmd->plugin);
934945
struct json_stream *response;
935946

947+
/* FIXME: We could allow layer names here? */
936948
if (!param(cmd, buffer, params,
937949
NULL))
938950
return command_param_failed();
939951
plugin_log(cmd->plugin, LOG_TRACE, "%s called: %.*s", __func__,
940952
json_tok_full_len(params), json_tok_full(buffer, params));
941953

942954
response = jsonrpc_stream_success(cmd);
943-
json_add_reservations(response, askrene->reserved, "reservations");
955+
json_add_reservations(response, askrene->reserved, "reservations", NULL);
944956
return command_finished(cmd, response);
945957
}
946958

@@ -1065,7 +1077,7 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd,
10651077
case INFORM_CONSTRAINED:
10661078
/* It didn't pass, so minimal assumption is that reserve was all used
10671079
* then there we were one msat short. */
1068-
if (!reserve_accumulate(askrene->reserved, scidd, amount))
1080+
if (!reserve_accumulate(askrene->reserved, scidd, layer, amount))
10691081
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
10701082
"Amount overflow with reserves");
10711083
if (!amount_msat_deduct(amount, AMOUNT_MSAT(1)))

0 commit comments

Comments
 (0)