What changed, and why it matters
This commit simply marks the 'renepay' and 'renepaystatus' commands as deprecated. It adds warning text to documentation, lists the commands in the deprecated-features guide, and updates tests to explicitly allow deprecated APIs so they keep passing. There is no security fix or vulnerability here.
No security action required. Users relying on renepay/renepaystatus should plan migration to xpay, askrene, listpays, or listsendpays before v27.03.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change deprecates the renepay plugin’s RPC commands (renepay and renepaystatus) with removal scheduled for v27.03. It updates JSON schemas and the deprecated-features table, and adds deprecation version metadata in plugins/renepay/main.c. Test cases are adjusted to pass allow-deprecated-apis=True so the existing test suite continues to exercise the deprecated commands. No code behavior is altered beyond deprecation signaling.
Changed components
plugins/renepay/main.cdoc/schemas/renepay.jsondoc/schemas/renepaystatus.jsondoc/developers-guide/deprecated-features.mdcontrib/msggen/msggen/schema.jsontests/test_renepay.pyInspect captured patch +56 / −38
diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json
index d65eaba7..8f7c24fb 100644
--- a/contrib/msggen/msggen/schema.json
+++ b/contrib/msggen/msggen/schema.json
@@ -31793,6 +31793,8 @@
"title": "Command for sending a payment to a BOLT11 invoice",
"added": "v23.08",
"description": [
+ "WARNING: Deprecated, scheduled for removal in v27.03",
+ "",
"**renepay** is a new payment plugin based on Pickhardt-Richter optimization method for Multi-Path-Payments. This implementation has not been thoroughly tested and it should be used with caution.",
"",
"The response will occur when the payment fails or succeeds. Once a payment has succeeded, calls to **renepay** with the same *invstring* will not lead to a new payment attempt, but instead it will succeed immediately.",
@@ -32055,6 +32057,8 @@
"title": "Command for quering the status of previous renepay attempts",
"added": "v23.08",
"description": [
+ "WARNING: Deprecated, scheduled for removal in v27.03",
+ "",
"The **renepaystatus** RPC command queries the payment plugin **renepay** for the status of previous payment attempts.",
"",
"This command always succeeds."
diff --git a/doc/developers-guide/deprecated-features.md b/doc/developers-guide/deprecated-features.md
index e20885f0..e536c10c 100644
--- a/doc/developers-guide/deprecated-features.md
+++ b/doc/developers-guide/deprecated-features.md
@@ -31,6 +31,8 @@ privacy:
| paystatus | Command | v26.06 | v27.03 | Uses internal pay structures, doesn't work with xpay, doesn't work across restarts. |
| getroute | Command | v26.06 | v27.03 | Less flexible than `getroutes` which takes an actual fee budget and can do multiple paths at once. |
| keysend | Command | v26.06 | v27.03 | Replaced by more powerful `xkeysend`. |
+| renepay | Command | v26.06 | v27.03 | Use `xpay` instead. |
+| renepaystatus | Command | v26.06 | v27.03 | Use `xpay` notifications and `listpays` or `listsendpays` instead. |
Inevitably there are features which need to change: either to be generalized, or removed when they can no longer be supported.
diff --git a/doc/schemas/renepay.json b/doc/schemas/renepay.json
index 8169c387..32a7d44b 100644
--- a/doc/schemas/renepay.json
+++ b/doc/schemas/renepay.json
@@ -5,6 +5,8 @@
"title": "Command for sending a payment to a BOLT11 invoice",
"added": "v23.08",
"description": [
+ "WARNING: Deprecated, scheduled for removal in v27.03",
+ "",
"**renepay** is a new payment plugin based on Pickhardt-Richter optimization method for Multi-Path-Payments. This implementation has not been thoroughly tested and it should be used with caution.",
"",
"The response will occur when the payment fails or succeeds. Once a payment has succeeded, calls to **renepay** with the same *invstring* will not lead to a new payment attempt, but instead it will succeed immediately.",
diff --git a/doc/schemas/renepaystatus.json b/doc/schemas/renepaystatus.json
index 7bfe4774..e50928a9 100644
--- a/doc/schemas/renepaystatus.json
+++ b/doc/schemas/renepaystatus.json
@@ -5,6 +5,8 @@
"title": "Command for quering the status of previous renepay attempts",
"added": "v23.08",
"description": [
+ "WARNING: Deprecated, scheduled for removal in v27.03",
+ "",
"The **renepaystatus** RPC command queries the payment plugin **renepay** for the status of previous payment attempts.",
"",
"This command always succeeds."
diff --git a/plugins/renepay/main.c b/plugins/renepay/main.c
index 8c2d72e0..71276041 100644
--- a/plugins/renepay/main.c
+++ b/plugins/renepay/main.c
@@ -445,11 +445,13 @@ static struct command_result *json_renepay(struct command *cmd, const char *buf,
static const struct plugin_command commands[] = {
{
"renepaystatus",
- json_renepaystatus
+ json_renepaystatus,
+ "v26.06", "v27.03",
},
{
"renepay",
- json_renepay
+ json_renepay,
+ "v26.06", "v27.03",
},
};
diff --git a/tests/test_renepay.py b/tests/test_renepay.py
index c30bde01..3d1c1da3 100644
--- a/tests/test_renepay.py
+++ b/tests/test_renepay.py
@@ -19,7 +19,7 @@ import unittest
def test_simple(node_factory):
"""Testing simply paying a peer."""
- l1, l2 = node_factory.line_graph(2)
+ l1, l2 = node_factory.line_graph(2, opts={'allow-deprecated-apis': True})
inv = l2.rpc.invoice(123000, "test_renepay", "description")["bolt11"]
details = l1.rpc.call("renepay", {"invstring": inv})
assert details["status"] == "complete"
@@ -33,7 +33,7 @@ def test_direction_matters(node_factory):
3,
wait_for_announce=True,
opts=[
- {},
+ {'allow-deprecated-apis': True},
{"fee-base": 2000, "fee-per-satoshi": 20, "cltv-delta": 20},
{"fee-base": 3000, "fee-per-satoshi": 30, "cltv-delta": 30},
],
@@ -53,7 +53,8 @@ def test_shadow_routing(node_factory):
"""
# We need l3 for random walk
l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True,
- opts={'dev-allow-localhost': None})
+ opts={'allow-deprecated-apis': True,
+ 'dev-allow-localhost': None})
amount = 10000
total_amount = 0
@@ -77,7 +78,7 @@ def test_mpp(node_factory):
Try paying 1.2M sats from 1 to 6.
"""
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'dev-allow-localhost': None},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'dev-allow-localhost': None, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(6, opts=opts * 6)
node_factory.join_nodes(
@@ -97,7 +98,7 @@ def test_mpp(node_factory):
def test_errors(node_factory, bitcoind):
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(6, opts=opts * 6)
send_amount = Millisatoshi("21sat")
@@ -147,7 +148,7 @@ def test_errors(node_factory, bitcoind):
@pytest.mark.openchannel("v1")
@pytest.mark.openchannel("v2")
def test_pay(node_factory):
- l1, l2 = node_factory.line_graph(2)
+ l1, l2 = node_factory.line_graph(2, opts={'allow-deprecated-apis': True})
inv = l2.rpc.invoice(123000, "test_pay", "description")["bolt11"]
before = int(time.time())
@@ -230,7 +231,7 @@ def test_amounts(node_factory):
"""
Check that the amount received matches the amount requested in the invoice.
"""
- l1, l2 = node_factory.line_graph(2)
+ l1, l2 = node_factory.line_graph(2, opts={'allow-deprecated-apis': True})
inv = l2.rpc.invoice(Millisatoshi(123456), "test_pay_amounts", "description")[
"bolt11"
]
@@ -257,7 +258,7 @@ def test_limits(node_factory):
- probability of success is too low.
"""
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 100},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 100, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(6, opts=opts * 6)
node_factory.join_nodes(
@@ -365,7 +366,7 @@ def test_hardmpp(node_factory):
we build the network capacities.
"""
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(6, opts=opts * 6)
start_channels(
@@ -409,7 +410,7 @@ def test_hardmpp(node_factory):
@pytest.mark.flaky(reruns=2)
def test_self_pay(node_factory):
- l1, l2 = node_factory.line_graph(2, wait_for_announce=True)
+ l1, l2 = node_factory.line_graph(2, wait_for_announce=True, opts={'allow-deprecated-apis': True})
inv = l1.rpc.invoice(10000, "test", "test")["bolt11"]
l1.rpc.call("renepay", {"invstring": inv})
@@ -443,6 +444,7 @@ def test_fee_allocation(node_factory):
"fee-base": 1000,
"fee-per-satoshi": 30000,
"plugin": os.path.join(os.getcwd(), "tests/plugins/no_fail.py"),
+ 'allow-deprecated-apis': True,
},
]
l1, l2, l3, l4 = node_factory.get_nodes(4, opts=opts * 4)
@@ -468,22 +470,24 @@ def test_htlc_max(node_factory):
3----5----6
"""
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
{
"disable-mpp": None,
"fee-base": 0,
"fee-per-satoshi": 0,
"htlc-maximum-msat": 500000000,
+ 'allow-deprecated-apis': True,
},
{
"disable-mpp": None,
"fee-base": 0,
"fee-per-satoshi": 0,
"htlc-maximum-msat": 500000000,
+ 'allow-deprecated-apis': True,
},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(6, opts=opts)
start_channels(
@@ -511,7 +515,7 @@ def test_previous_sendpays(node_factory, bitcoind):
Check that renepay can complete a payment that already started
"""
opts = [
- {"disable-mpp": None, "fee-base": 1000, "fee-per-satoshi": 1000},
+ {"disable-mpp": None, "fee-base": 1000, "fee-per-satoshi": 1000, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4 = node_factory.line_graph(4, wait_for_announce=True, opts=opts * 4)
@@ -605,12 +609,12 @@ def test_fees(node_factory):
"""
# made up some random fees for every node
opts = [
- {"disable-mpp": None, "fee-base": 1000, "fee-per-satoshi": 100},
- {"disable-mpp": None, "fee-base": 2222, "fee-per-satoshi": 203},
- {"disable-mpp": None, "fee-base": 3333, "fee-per-satoshi": 300},
- {"disable-mpp": None, "fee-base": 2012, "fee-per-satoshi": 200},
- {"disable-mpp": None, "fee-base": 1010, "fee-per-satoshi": 100},
- {"disable-mpp": None, "fee-base": 1050, "fee-per-satoshi": 100},
+ {"disable-mpp": None, "fee-base": 1000, "fee-per-satoshi": 100, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 2222, "fee-per-satoshi": 203, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 3333, "fee-per-satoshi": 300, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 2012, "fee-per-satoshi": 200, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 1010, "fee-per-satoshi": 100, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 1050, "fee-per-satoshi": 100, 'allow-deprecated-apis': True},
]
nodes = node_factory.line_graph(len(opts), wait_for_announce=True, opts=opts)
source = nodes[0]
@@ -637,7 +641,7 @@ def test_fees(node_factory):
def test_local_htlcmax0(node_factory):
"""Testing a simple pay route when local channels have htlcmax=0."""
- l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True)
+ l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, opts={'allow-deprecated-apis': True})
l1.rpc.setchannel(l2.info["id"], htlcmax=0)
inv = l3.rpc.invoice(123000, "test_renepay", "description")["bolt11"]
details = l1.rpc.call("renepay", {"invstring": inv})
@@ -655,22 +659,24 @@ def test_htlcmax0(node_factory):
Tests the plugin when some routes have htlc_max=0.
"""
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
{
"disable-mpp": None,
"fee-base": 0,
"fee-per-satoshi": 0,
"htlc-maximum-msat": 0,
+ 'allow-deprecated-apis': True,
},
{
"disable-mpp": None,
"fee-base": 0,
"fee-per-satoshi": 0,
"htlc-maximum-msat": 800000000,
+ 'allow-deprecated-apis': True,
},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(6, opts=opts)
start_channels(
@@ -693,7 +699,7 @@ def test_htlcmax0(node_factory):
def test_concurrency(node_factory):
- l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, opts=[{}, {}, {}])
+ l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, opts={'allow-deprecated-apis': True})
inv = l3.rpc.invoice("1000sat", "test_renepay", "description")["bolt11"]
p1 = subprocess.Popen(
[
@@ -735,10 +741,10 @@ def test_privatechan(node_factory, bitcoind):
Tests if a payment can get through a private channel.
"""
opts = [
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 100},
- {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 100, 'allow-deprecated-apis': True},
+ {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 0, 'allow-deprecated-apis': True},
]
l1, l2, l3, l4 = node_factory.get_nodes(4, opts=opts)
@@ -771,7 +777,7 @@ def test_privatechan(node_factory, bitcoind):
@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', "broken for some reason")
def test_hardmpp2(node_factory, bitcoind):
"""Credits to @daywalker90 for this test case."""
- opts = {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 10}
+ opts = {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 10, 'allow-deprecated-apis': True}
l1, l2, l3 = node_factory.get_nodes(3, opts=opts)
start_channels(
[
@@ -797,7 +803,7 @@ def test_hardmpp2(node_factory, bitcoind):
def test_description(node_factory):
"""Test the processing of the payment description interface."""
- l1, l2 = node_factory.line_graph(2)
+ l1, l2 = node_factory.line_graph(2, opts={'allow-deprecated-apis': True})
# do not provide description in the command line, all payments should be
# fine
@@ -840,7 +846,7 @@ def test_description(node_factory):
def test_offers(node_factory):
l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True,
- opts={'dev-allow-localhost': None})
+ opts={'dev-allow-localhost': None, 'allow-deprecated-apis': True})
offer = l3.rpc.offer("1000sat", "test_renepay_offers")['bolt12']
invoice = l1.rpc.fetchinvoice(offer)['invoice']
response = l1.rpc.call("renepay", {"invstring": invoice})
@@ -849,14 +855,14 @@ def test_offers(node_factory):
def test_offer_selfpay(node_factory):
"""We can fetch an pay our own offer"""
- l1 = node_factory.get_node()
+ l1 = node_factory.get_node(options={'allow-deprecated-apis': True})
offer = l1.rpc.offer(amount="2msat", description="test_offer_path_self")["bolt12"]
inv = l1.rpc.fetchinvoice(offer)["invoice"]
l1.rpc.call("renepay", {"invstring": inv})
def test_unannounced(node_factory):
- l1, l2 = node_factory.line_graph(2, announce_channels=False)
+ l1, l2 = node_factory.line_graph(2, announce_channels=False, opts={'allow-deprecated-apis': True})
# BOLT-11 direct peer
b11 = l2.rpc.invoice(
"100sat", "test_renepay_unannounced", "test_renepay_unannounced"
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.