Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .msggen.json
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,7 @@
"Askrene-reservePath": {
"AskRene-Reserve.path[].amount_msat": 3,
"AskRene-Reserve.path[].direction": 2,
"AskRene-Reserve.path[].layer": 5,
"AskRene-Reserve.path[].short_channel_id": 1,
"AskRene-Reserve.path[].short_channel_id_dir": 4
},
Expand All @@ -761,6 +762,7 @@
"Askrene-unreservePath": {
"AskRene-Unreserve.path[].amount_msat": 3,
"AskRene-Unreserve.path[].direction": 2,
"AskRene-Unreserve.path[].layer": 5,
"AskRene-Unreserve.path[].short_channel_id": 1,
"AskRene-Unreserve.path[].short_channel_id_dir": 4
},
Expand Down Expand Up @@ -4412,6 +4414,10 @@
"added": "v24.08",
"deprecated": null
},
"AskRene-Reserve.path[].layer": {
"added": "v25.12",
"deprecated": null
},
"AskRene-Reserve.path[].short_channel_id": {
"added": "v24.08",
"deprecated": null
Expand All @@ -4436,6 +4442,10 @@
"added": "v24.08",
"deprecated": null
},
"AskRene-Unreserve.path[].layer": {
"added": "v25.12",
"deprecated": null
},
"AskRene-Unreserve.path[].short_channel_id": {
"added": "v24.08",
"deprecated": null
Expand Down
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
25.05
25.05.1
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [25.05.1] - 2025-11-10: "Satoshi's OP_RETURN Opinion II"

Fixes for xpay when used heavily.

### Fixed

- JSON-RPC: `xpay` clash with simultanous payments via routehints and blinded paths. ([#8685])
- Plugins: `askrene-reserve` and `askrene-unreserve` can take an optional `layer` inside `path` elements. ([#8685])
- Plugins: fix reservation code in askrene, which caused xpay to fail due to previous payments. ([#8670])

[#8685]: https://github.com/ElementsProject/lightning/pull/8685
[#8670]: https://github.com/ElementsProject/lightning/pull/8670
[25.05.1]: https://github.com/ElementsProject/lightning/releases/tag/v25.05.1


## [25.05] - 2025-06-16: "Satoshi's OP_RETURN Opinion"

This release named by Peter Neuroth (@nepet).
Expand Down
2 changes: 2 additions & 0 deletions cln-grpc/proto/node.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions cln-grpc/src/convert.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions cln-rpc/src/model.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion contrib/msggen/msggen/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@
"layer": {
"type": "string",
"description": [
"The name of the layer to apply this change to."
"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)."
]
},
"short_channel_id_dir": {
Expand Down Expand Up @@ -1553,6 +1553,13 @@
"description": [
"The amount to send into this hop."
]
},
"layer": {
"added": "v25.12",
"type": "string",
"description": [
"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."
]
}
}
}
Expand Down Expand Up @@ -1654,6 +1661,13 @@
"description": [
"The amount to send into this hop."
]
},
"layer": {
"added": "v25.12",
"type": "string",
"description": [
"The layer to restrict this reservation to (useful for fake channels)."
]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion contrib/pyln-client/pyln/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .gossmapstats import GossmapStats
from .version import NodeVersion

__version__ = "25.05"
__version__ = "25.05.1"

__all__ = [
"LightningRpc",
Expand Down
2 changes: 1 addition & 1 deletion contrib/pyln-client/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyln-client"
version = "25.05"
version = "25.05.1"
description = "Client library and plugin library for Core Lightning"
authors = ["Christian Decker <decker.christian@gmail.com>"]
license = "BSD-MIT"
Expand Down
270 changes: 135 additions & 135 deletions contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contrib/pyln-proto/pyln/proto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .onion import OnionPayload, TlvPayload, LegacyOnionPayload
from .wire import LightningConnection, LightningServerSocket

__version__ = "25.05"
__version__ = "25.05.1"

__all__ = [
"Invoice",
Expand Down
2 changes: 1 addition & 1 deletion contrib/pyln-proto/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyln-proto"
version = "25.05"
version = "25.05.1"
description = "This package implements some of the Lightning Network protocol in pure python. It is intended for protocol testing and some minor tooling only. It is not deemed secure enough to handle any amount of real funds (you have been warned!)."
authors = ["Christian Decker <decker.christian@gmail.com>"]
license = "BSD-MIT"
Expand Down
2 changes: 1 addition & 1 deletion contrib/pyln-testing/pyln/testing/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "25.05"
__version__ = "25.05.1"

__all__ = [
"__version__",
Expand Down
2 changes: 1 addition & 1 deletion contrib/pyln-testing/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyln-testing"
version = "25.05"
version = "25.05.1"
description = "Test your Core Lightning integration, plugins or whatever you want"
authors = ["Christian Decker <decker.christian@gmail.com>"]
license = "BSD-MIT"
Expand Down
2 changes: 1 addition & 1 deletion doc/schemas/askrene-inform-channel.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"layer": {
"type": "string",
"description": [
"The name of the layer to apply this change to."
"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)."
]
},
"short_channel_id_dir": {
Expand Down
7 changes: 7 additions & 0 deletions doc/schemas/askrene-reserve.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
"description": [
"The amount to send into this hop."
]
},
"layer": {
"added": "v25.12",
"type": "string",
"description": [
"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."
]
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions doc/schemas/askrene-unreserve.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
"description": [
"The amount to send into this hop."
]
},
"layer": {
"added": "v25.12",
"type": "string",
"description": [
"The layer to restrict this reservation to (useful for fake channels)."
]
}
}
}
Expand Down
28 changes: 20 additions & 8 deletions plugins/askrene/askrene.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,21 @@ static struct command_result *parse_reserve_hop(struct command *cmd,
struct reserve_hop *rhop)
{
const char *err;
const char *layername = NULL;

err = json_scan(tmpctx, buffer, tok, "{short_channel_id_dir:%,amount_msat:%}",
err = json_scan(tmpctx, buffer, tok, "{short_channel_id_dir:%,amount_msat:%,layer?:%}",
JSON_SCAN(json_to_short_channel_id_dir, &rhop->scidd),
JSON_SCAN(json_to_msat, &rhop->amount));
JSON_SCAN(json_to_msat, &rhop->amount),
JSON_SCAN_TAL(tmpctx, json_strdup, &layername));
if (err)
return command_fail_badparam(cmd, name, buffer, tok, err);
if (layername) {
rhop->layer = find_layer(get_askrene(cmd->plugin), layername);
if (!rhop->layer)
return command_fail_badparam(cmd, name, buffer, tok, "Unknown layer");
} else
rhop->layer = NULL;

return NULL;
}

Expand Down Expand Up @@ -629,8 +638,8 @@ void get_constraints(const struct route_query *rq,
*max = gossmap_chan_get_capacity(rq->gossmap, chan);

/* Finally, if any is in use, subtract that! */
reserve_sub(rq->reserved, &scidd, min);
reserve_sub(rq->reserved, &scidd, max);
reserve_sub(rq->reserved, &scidd, rq->layers, min);
reserve_sub(rq->reserved, &scidd, rq->layers, max);
}

struct getroutes_info {
Expand Down Expand Up @@ -887,9 +896,11 @@ static struct command_result *json_askrene_unreserve(struct command *cmd,
for (size_t i = 0; i < tal_count(path); i++) {
if (!reserve_remove(askrene->reserved, &path[i])) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown reservation for %s",
"Unknown reservation for %s%s%s",
fmt_short_channel_id_dir(tmpctx,
&path[i].scidd));
&path[i].scidd),
path[i].layer ? " on layer " : "",
path[i].layer ? layer_name(path[i].layer) : "");
}
}

Expand All @@ -904,14 +915,15 @@ static struct command_result *json_askrene_listreservations(struct command *cmd,
struct askrene *askrene = get_askrene(cmd->plugin);
struct json_stream *response;

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

response = jsonrpc_stream_success(cmd);
json_add_reservations(response, askrene->reserved, "reservations");
json_add_reservations(response, askrene->reserved, "reservations", NULL);
return command_finished(cmd, response);
}

Expand Down Expand Up @@ -1036,7 +1048,7 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd,
case INFORM_CONSTRAINED:
/* It didn't pass, so minimal assumption is that reserve was all used
* then there we were one msat short. */
if (!reserve_accumulate(askrene->reserved, scidd, amount))
if (!reserve_accumulate(askrene->reserved, scidd, layer, amount))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Amount overflow with reserves");
if (!amount_msat_sub(amount, *amount, AMOUNT_MSAT(1)))
Expand Down
2 changes: 1 addition & 1 deletion plugins/askrene/explain_failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static const char *why_max_constrained(const tal_t *ctx,
fmt_amount_msat(tmpctx, max));
}

reservations = fmt_reservations(tmpctx, rq->reserved, scidd);
reservations = fmt_reservations(tmpctx, rq->reserved, scidd, rq->layers);
if (reservations) {
if (!ret)
ret = tal_strdup(ctx, "");
Expand Down
5 changes: 4 additions & 1 deletion plugins/askrene/refine.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ static void add_reservation(struct reserve_hop **reservations,
}
rhop.scidd = *scidd;
rhop.amount = amt;
/* We don't have to restrict it to a layer, since it's transitory:
* nobody else will see this. */
rhop.layer = NULL;
reserve_add(askrene->reserved, &rhop, rq->cmd->id);

/* Set capacities entry to 0 so it get_constraints() looks in reserve. */
Expand Down Expand Up @@ -592,7 +595,7 @@ refine_with_fees_and_limits(const tal_t *ctx,
/* Total flowset probability is now easily calculated given reservations
* contains the total amounts through each channel (once we remove them) */
destroy_reservations(reservations, get_askrene(rq->plugin));
tal_add_destructor2(reservations, destroy_reservations, get_askrene(rq->plugin));
tal_del_destructor2(reservations, destroy_reservations, get_askrene(rq->plugin));

*flowset_probability = 1.0;
for (size_t i = 0; i < tal_count(reservations); i++) {
Expand Down
Loading
Loading