getroutes: deprecate old vaguely named fields.
What changed, and why it matters
This commit is a routine API cleanup, not a security fix. It renames three fields in the getroutes JSON-RPC response to clearer names and marks the old names as deprecated. The old fields are still emitted for backward compatibility unless a user opts into strict deprecation handling. There is no vulnerability being patched here.
No security action required. Developers using getroutes should plan to migrate from next_node_id, amount_msat, and delay to node_id_out, amount_in_msat, and cltv_in before the deprecated fields are removed in v27.06.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change deprecates the getroutes route path fields next_node_id, amount_msat, and delay in favor of node_id_out, amount_in_msat, and cltv_in respectively. It updates schemas, generated RPC models, documentation, internal consumers (xpay), and tests. The askrene plugin now conditionally includes the old fields based on notification_deprecated_out_ok(), preserving backward compatibility. No memory safety, cryptographic, or authorization issues are present in the diff.
Changed components
plugins/askreneplugins/xpaycln-rpccln-grpcdoc/schemas/getroutes.jsondoc/developers-guide/deprecated-features.mdInspect captured patch +269 / −174
diff --git a/.msggen.json b/.msggen.json
index e601c775..b5189763 100644
--- a/.msggen.json
+++ b/.msggen.json
@@ -8543,7 +8543,7 @@
},
"GetRoutes.routes[].path[].amount_msat": {
"added": "v24.08",
- "deprecated": null
+ "deprecated": "v26.06"
},
"GetRoutes.routes[].path[].amount_out_msat": {
"added": "v26.06",
@@ -8559,7 +8559,7 @@
},
"GetRoutes.routes[].path[].delay": {
"added": "v24.08",
- "deprecated": null
+ "deprecated": "v26.06"
},
"GetRoutes.routes[].path[].direction": {
"added": "v24.08",
@@ -8567,7 +8567,7 @@
},
"GetRoutes.routes[].path[].next_node_id": {
"added": "v24.08",
- "deprecated": null
+ "deprecated": "v26.06"
},
"GetRoutes.routes[].path[].node_id_in": {
"added": "v26.06",
diff --git a/cln-grpc/src/convert.rs b/cln-grpc/src/convert.rs
index c9e13aab..676d2fa9 100644
--- a/cln-grpc/src/convert.rs
+++ b/cln-grpc/src/convert.rs
@@ -4336,16 +4336,19 @@ impl From<responses::AskreneageResponse> for pb::AskreneageResponse {
}
}
-#[allow(unused_variables)]
+#[allow(unused_variables,deprecated)]
impl From<responses::GetroutesRoutesPath> for pb::GetroutesRoutesPath {
fn from(c: responses::GetroutesRoutesPath) -> Self {
Self {
amount_in_msat: c.amount_in_msat.map(|f| f.into()), // Rule #2 for type msat?
+ #[allow(deprecated)]
amount_msat: c.amount_msat.map(|f| f.into()), // Rule #2 for type msat?
amount_out_msat: c.amount_out_msat.map(|f| f.into()), // Rule #2 for type msat?
cltv_in: c.cltv_in, // Rule #2 for type u32?
cltv_out: c.cltv_out, // Rule #2 for type u32?
+ #[allow(deprecated)]
delay: c.delay, // Rule #2 for type u32?
+ #[allow(deprecated)]
next_node_id: c.next_node_id.map(|v| v.serialize().to_vec()), // Rule #2 for type pubkey?
node_id_in: c.node_id_in.map(|v| v.serialize().to_vec()), // Rule #2 for type pubkey?
node_id_out: c.node_id_out.map(|v| v.serialize().to_vec()), // Rule #2 for type pubkey?
diff --git a/cln-rpc/src/model.rs b/cln-rpc/src/model.rs
index 8a499f2b..1bd0e4eb 100644
--- a/cln-rpc/src/model.rs
+++ b/cln-rpc/src/model.rs
@@ -12206,10 +12206,17 @@ pub mod responses {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GetroutesRoutesPath {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub amount_in_msat: Option<Amount>,
+ #[deprecated]
#[serde(skip_serializing_if = "Option::is_none")]
pub amount_msat: Option<Amount>,
+ #[deprecated]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub delay: Option<u32>,
+ #[deprecated]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub next_node_id: Option<PublicKey>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub amount_in_msat: Option<Amount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub amount_out_msat: Option<Amount>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -12217,10 +12224,6 @@ pub mod responses {
#[serde(skip_serializing_if = "Option::is_none")]
pub cltv_out: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
- pub delay: Option<u32>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub next_node_id: Option<PublicKey>,
- #[serde(skip_serializing_if = "Option::is_none")]
pub node_id_in: Option<PublicKey>,
#[serde(skip_serializing_if = "Option::is_none")]
pub node_id_out: Option<PublicKey>,
diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json
index 25372a93..98837f02 100644
--- a/contrib/msggen/msggen/schema.json
+++ b/contrib/msggen/msggen/schema.json
@@ -16763,18 +16763,30 @@
"type": "msat",
"description": [
"The amount to send into this hop."
+ ],
+ "deprecated": [
+ "v26.06",
+ "v27.06"
]
},
"next_node_id": {
"type": "pubkey",
"description": [
"The peer id at the end of this hop."
+ ],
+ "deprecated": [
+ "v26.06",
+ "v27.06"
]
},
"delay": {
"type": "u32",
"description": [
"The total CLTV expected by the node at the start of this hop."
+ ],
+ "deprecated": [
+ "v26.06",
+ "v27.06"
]
}
}
diff --git a/doc/developers-guide/deprecated-features.md b/doc/developers-guide/deprecated-features.md
index f66f8dfb..b6214c27 100644
--- a/doc/developers-guide/deprecated-features.md
+++ b/doc/developers-guide/deprecated-features.md
@@ -24,6 +24,9 @@ privacy:
| hsmtool.getcodexsecret | Command | v25.12.1 | v26.12 | Doesn't work on nodes using mnemonic secrets (v25.12 or later). Use `getsecret` instead. |
| experimental_splicing | Config | v26.04 | v27.04 | Splicing is now enabled by default |
| getroutes.layers.auto.no_mpp_support | Parameter | v26.06 | v27.03 | Use `maxparts=1` instead (since v25.09) |
+| getroutes.next_node_id | Field | v26.06 | v27.06 | Use `node_id_out` instead (since v26.06) |
+| getroutes.amount_msat | Field | v26.06 | v27.06 | Use `amount_in_msat` instead (since v26.06) |
+| getroutes.delay | Field | v26.06 | v27.06 | Use `cltv_in` instead (since v26.06) |
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/getroutes.json b/doc/schemas/getroutes.json
index 43f676e1..d6b22256 100644
--- a/doc/schemas/getroutes.json
+++ b/doc/schemas/getroutes.json
@@ -197,18 +197,30 @@
"type": "msat",
"description": [
"The amount to send into this hop."
+ ],
+ "deprecated": [
+ "v26.06",
+ "v27.06"
]
},
"next_node_id": {
"type": "pubkey",
"description": [
"The peer id at the end of this hop."
+ ],
+ "deprecated": [
+ "v26.06",
+ "v27.06"
]
},
"delay": {
"type": "u32",
"description": [
"The total CLTV expected by the node at the start of this hop."
+ ],
+ "deprecated": [
+ "v26.06",
+ "v27.06"
]
}
}
diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c
index b51ecb79..27b4f545 100644
--- a/plugins/askrene/askrene.c
+++ b/plugins/askrene/askrene.c
@@ -555,6 +555,7 @@ static struct command_result *do_getroutes(struct command *cmd,
const struct layer **layers;
s8 *biases;
fp16_t *capacities;
+ bool include_next_node_id, include_amount_msat, include_delay;
/* update the gossmap */
if (gossmap_refresh(askrene->gossmap)) {
@@ -655,6 +656,19 @@ static struct command_result *do_getroutes(struct command *cmd,
include_fees = have_layer(info->layers, "auto.include_fees");
+ /* Figure out what deprecated fields to include */
+ include_next_node_id = notification_deprecated_out_ok(askrene->plugin,
+ "getroutes",
+ "next_node_id",
+ "v26.06", "v27.06");
+ include_amount_msat = notification_deprecated_out_ok(askrene->plugin,
+ "getroutes",
+ "amount_msat",
+ "v26.06", "v27.06");
+ include_delay = notification_deprecated_out_ok(askrene->plugin,
+ "getroutes",
+ "delay",
+ "v26.06", "v27.06");
child = tal(cmd, struct router_child);
child->start = time_mono();
deadline = timemono_add(child->start,
@@ -704,7 +718,11 @@ static struct command_result *do_getroutes(struct command *cmd,
deadline, srcnode, dstnode, info->amount,
info->maxfee, info->finalcltv, info->maxdelay, info->maxparts,
include_fees,
- cmd->id, cmd->filter, replyfds[1]);
+ cmd->id, cmd->filter,
+ include_next_node_id,
+ include_amount_msat,
+ include_delay,
+ replyfds[1]);
abort();
}
diff --git a/plugins/askrene/child/child.c b/plugins/askrene/child/child.c
index c3207ae6..72aecd68 100644
--- a/plugins/askrene/child/child.c
+++ b/plugins/askrene/child/child.c
@@ -141,7 +141,10 @@ static struct route **convert_flows_to_routes(const tal_t *ctx,
static void json_add_getroutes(struct json_stream *js,
struct route **routes,
- double probability)
+ double probability,
+ bool include_next_node_id,
+ bool include_amount_msat,
+ bool include_delay)
{
json_add_u64(js, "probability_ppm", (u64)(probability * 1000000));
json_array_start(js, "routes");
@@ -165,9 +168,12 @@ static void json_add_getroutes(struct json_stream *js,
json_add_u32(js, "cltv_in", hop->cltv_value_in);
json_add_u32(js, "cltv_out", hop->cltv_value_out);
- json_add_node_id(js, "next_node_id", &hop->node_out);
- json_add_amount_msat(js, "amount_msat", hop->amount_in);
- json_add_u32(js, "delay", hop->cltv_value_in);
+ if (include_next_node_id)
+ json_add_node_id(js, "next_node_id", &hop->node_out);
+ if (include_amount_msat)
+ json_add_amount_msat(js, "amount_msat", hop->amount_in);
+ if (include_delay)
+ json_add_u32(js, "delay", hop->cltv_value_in);
json_object_end(js);
}
json_array_end(js);
@@ -217,6 +223,9 @@ void run_child(const struct gossmap *gossmap,
bool include_fees,
const char *cmd_id,
struct json_filter *cmd_filter,
+ bool include_next_node_id,
+ bool include_amount_msat,
+ bool include_delay,
int replyfd)
{
double probability;
@@ -264,7 +273,10 @@ void run_child(const struct gossmap *gossmap,
json_object_start(js, "result");
if (cmd_filter)
json_stream_attach_filter(js, cmd_filter);
- json_add_getroutes(js, routes, probability);
+ json_add_getroutes(js, routes, probability,
+ include_next_node_id,
+ include_amount_msat,
+ include_delay);
/* Detach filter before it complains about closing object it never saw */
if (cmd_filter) {
diff --git a/plugins/askrene/child/child.h b/plugins/askrene/child/child.h
index b050cff0..5cb6688e 100644
--- a/plugins/askrene/child/child.h
+++ b/plugins/askrene/child/child.h
@@ -31,6 +31,9 @@ void run_child(const struct gossmap *gossmap,
bool include_fees,
const char *cmd_id,
struct json_filter *cmd_filter,
+ bool include_next_node_id,
+ bool include_amount_msat,
+ bool include_delay,
int reply_fd) NORETURN;
#endif /* LIGHTNING_PLUGINS_ASKRENE_CHILD_CHILD_H */
diff --git a/plugins/xpay/xpay.c b/plugins/xpay/xpay.c
index 0f082e25..aa7b4efd 100644
--- a/plugins/xpay/xpay.c
+++ b/plugins/xpay/xpay.c
@@ -1594,25 +1594,23 @@ static struct command_result *getroutes_done(struct command *aux_cmd,
struct hop *hop = &hops[j];
err = json_scan(tmpctx, buf, hoptok,
"{short_channel_id_dir:%"
- ",amount_msat:%"
- ",next_node_id:%"
- ",delay:%}",
+ ",amount_in_msat:%"
+ ",amount_out_msat:%"
+ ",node_id_out:%"
+ ",cltv_in:%"
+ ",cltv_out:%}",
JSON_SCAN(json_to_short_channel_id_dir,
&hop->scidd),
JSON_SCAN(json_to_msat, &hop->amount_in),
+ JSON_SCAN(json_to_msat, &hop->amount_out),
JSON_SCAN(json_to_pubkey, &hop->next_node),
- JSON_SCAN(json_to_u32, &hop->cltv_value_in));
+ JSON_SCAN(json_to_u32, &hop->cltv_value_in),
+ JSON_SCAN(json_to_u32, &hop->cltv_value_out));
if (err)
plugin_err(aux_cmd->plugin, "Malformed routes: %s",
err);
hop->fake_channel = !gossmap_find_chan(gossmap, &hop->scidd.scid);
- if (j > 0) {
- hops[j-1].amount_out = hop->amount_in;
- hops[j-1].cltv_value_out = hop->cltv_value_in;
- }
}
- hops[j-1].amount_out = delivers;
- hops[j-1].cltv_value_out = payment->final_cltv;
if (payment->use_shadow)
add_cltv_shadow(payment, gossmap, hops);
diff --git a/tests/test_askrene.py b/tests/test_askrene.py
index 8c87d068..2dcb216b 100644
--- a/tests/test_askrene.py
+++ b/tests/test_askrene.py
@@ -539,8 +539,8 @@ def test_node_bias_routes(node_factory):
)
assert len(r["routes"]) == 1
assert len(r["routes"][0]["path"]) == 3
- assert r["routes"][0]["path"][0]["next_node_id"] == nodemap[2]
- assert r["routes"][0]["path"][2]["next_node_id"] == nodemap[1]
+ assert r["routes"][0]["path"][0]["node_id_out"] == nodemap[2]
+ assert r["routes"][0]["path"][2]["node_id_out"] == nodemap[1]
# by using the layer that penalizes node 2, we end up routing through node 3
r = l1.rpc.getroutes(
@@ -553,8 +553,8 @@ def test_node_bias_routes(node_factory):
)
assert len(r["routes"]) == 1
assert len(r["routes"][0]["path"]) == 2
- assert r["routes"][0]["path"][0]["next_node_id"] == nodemap[3]
- assert r["routes"][0]["path"][1]["next_node_id"] == nodemap[1]
+ assert r["routes"][0]["path"][0]["node_id_out"] == nodemap[3]
+ assert r["routes"][0]["path"][1]["node_id_out"] == nodemap[1]
def test_layer_persistence(node_factory):
@@ -746,9 +746,12 @@ def test_getroutes(node_factory):
'final_cltv': 99,
'amount_msat': 1000,
'path': [{'short_channel_id_dir': f'0x1x0/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 1010,
- 'delay': 99 + 6}]}]}
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 1010,
+ 'amount_out_msat': 1000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99}]}]}
# Two hop, still easy.
dir13 = direction(nodemap[1], nodemap[3])
assert l1.rpc.getroutes(source=nodemap[0],
@@ -761,13 +764,19 @@ def test_getroutes(node_factory):
'final_cltv': 99,
'amount_msat': 100000,
'path': [{'short_channel_id_dir': f'0x1x0/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 103020,
- 'delay': 99 + 6 + 6},
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 103020,
+ 'amount_out_msat': 102000,
+ 'cltv_in': 99 + 6 + 6,
+ 'cltv_out': 99 + 6},
{'short_channel_id_dir': f'3x3x2/{dir13}',
- 'next_node_id': nodemap[3],
- 'amount_msat': 102000,
- 'delay': 99 + 6}
+ 'node_id_in': nodemap[1],
+ 'node_id_out': nodemap[3],
+ 'amount_in_msat': 102000,
+ 'amount_out_msat': 100000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99}
]}]}
# Too expensive
@@ -806,9 +815,12 @@ def test_getroutes(node_factory):
'final_cltv': 99,
'amount_msat': 1000000,
'path': [{'short_channel_id_dir': f'3x2x3/{dir02}',
- 'next_node_id': nodemap[2],
- 'amount_msat': 1000001,
- 'delay': 99 + 6}]}]}
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[2],
+ 'amount_in_msat': 1000001,
+ 'amount_out_msat': 1000000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99}]}]}
# For 10000 sats, we will split.
check_getroute_paths(l1,
@@ -816,13 +828,19 @@ def test_getroutes(node_factory):
nodemap[2],
10000000,
[[{'short_channel_id_dir': f'1x2x1/{dir02}',
- 'next_node_id': nodemap[2],
- 'amount_msat': 4500004,
- 'delay': 99 + 6}],
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[2],
+ 'amount_in_msat': 4500004,
+ 'amount_out_msat': 4500000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99}],
[{'short_channel_id_dir': f'3x2x3/{dir02}',
- 'next_node_id': nodemap[2],
- 'amount_msat': 5500005,
- 'delay': 99 + 6}]])
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[2],
+ 'amount_in_msat': 5500005,
+ 'amount_out_msat': 5500000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99}]])
def test_getroutes_single_path(node_factory):
@@ -861,9 +879,9 @@ def test_getroutes_single_path(node_factory):
[
{
"short_channel_id_dir": "3x2x2/1",
- "next_node_id": nodemap[2],
- "amount_msat": 10000010,
- "delay": 99 + 6,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 10000010,
+ "cltv_in": 99 + 6,
}
]
],
@@ -894,15 +912,15 @@ def test_getroutes_single_path(node_factory):
[
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 10000020,
- "delay": 99 + 6 + 6,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 10000020,
+ "cltv_in": 99 + 6 + 6,
},
{
"short_channel_id_dir": "3x2x2/1",
- "next_node_id": nodemap[2],
- "amount_msat": 10000010,
- "delay": 99 + 6,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 10000010,
+ "cltv_in": 99 + 6,
},
]
],
@@ -979,9 +997,12 @@ def test_getroutes_auto_sourcefree(node_factory):
'final_cltv': 99,
'amount_msat': 1000,
'path': [{'short_channel_id_dir': f'0x1x0/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 1010,
- 'delay': 105}]}]}
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 1010,
+ 'amount_out_msat': 1000,
+ 'cltv_in': 105,
+ 'cltv_out': 99}]}]}
# Start easy
assert l1.rpc.getroutes(source=nodemap[0],
@@ -994,9 +1015,12 @@ def test_getroutes_auto_sourcefree(node_factory):
'final_cltv': 99,
'amount_msat': 1000,
'path': [{'short_channel_id_dir': f'0x1x0/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 1000,
- 'delay': 99}]}]}
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 1000,
+ 'amount_out_msat': 1000,
+ 'cltv_in': 99,
+ 'cltv_out': 99}]}]}
# Two hop, still easy.
dir13 = direction(nodemap[1], nodemap[3])
assert l1.rpc.getroutes(source=nodemap[0],
@@ -1009,13 +1033,19 @@ def test_getroutes_auto_sourcefree(node_factory):
'final_cltv': 99,
'amount_msat': 100000,
'path': [{'short_channel_id_dir': f'0x1x0/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 102000,
- 'delay': 99 + 6},
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 102000,
+ 'amount_out_msat': 102000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99 + 6},
{'short_channel_id_dir': f'3x3x2/{dir13}',
- 'next_node_id': nodemap[3],
- 'amount_msat': 102000,
- 'delay': 99 + 6}
+ 'node_id_in': nodemap[1],
+ 'node_id_out': nodemap[3],
+ 'amount_in_msat': 102000,
+ 'amount_out_msat': 100000,
+ 'cltv_in': 99 + 6,
+ 'cltv_out': 99}
]}]}
# Too expensive
@@ -1062,9 +1092,12 @@ def test_getroutes_maxdelay(node_factory):
'final_cltv': 99,
'amount_msat': 1000,
'path': [{'short_channel_id_dir': f'0x1x0/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 1010,
- 'delay': 179}]}]}
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 1010,
+ 'amount_out_msat': 1000,
+ 'cltv_in': 179,
+ 'cltv_out': 99}]}]}
# But use the channel with lower delay when needed
assert l1.rpc.getroutes(source=nodemap[0],
@@ -1078,9 +1111,12 @@ def test_getroutes_maxdelay(node_factory):
'final_cltv': 99,
'amount_msat': 1000,
'path': [{'short_channel_id_dir': f'1x1x1/{dir01}',
- 'next_node_id': nodemap[1],
- 'amount_msat': 1020,
- 'delay': 139}]}]}
+ 'node_id_in': nodemap[0],
+ 'node_id_out': nodemap[1],
+ 'amount_in_msat': 1020,
+ 'amount_out_msat': 1000,
+ 'cltv_in': 139,
+ 'cltv_out': 99}]}]}
# Excessive maxdelay parameter
with pytest.raises(RpcError, match="maximum delay allowed is 2016"):
@@ -1126,9 +1162,9 @@ def test_getroutes_auto_localchans(node_factory):
100000,
maxfee_msat=100000,
layers=['auto.localchans'],
- paths=[[{'short_channel_id_dir': scid21dir, 'amount_msat': 102012, 'delay': 99 + 6 + 6 + 6},
- {'short_channel_id_dir': f'0x1x0/{dir01}', 'amount_msat': 102010, 'delay': 99 + 6 + 6},
- {'short_channel_id_dir': f'2x2x1/{dir12}', 'amount_msat': 101000, 'delay': 99 + 6}]])
+ paths=[[{'short_channel_id_dir': scid21dir, 'amount_in_msat': 102012, 'cltv_in': 99 + 6 + 6 + 6},
+ {'short_channel_id_dir': f'0x1x0/{dir01}', 'amount_in_msat': 102010, 'cltv_in': 99 + 6 + 6},
+ {'short_channel_id_dir': f'2x2x1/{dir12}', 'amount_in_msat': 101000, 'cltv_in': 99 + 6}]])
# This should get self-discount correct
check_getroute_paths(l2,
@@ -1137,9 +1173,9 @@ def test_getroutes_auto_localchans(node_factory):
100000,
maxfee_msat=100000,
layers=['auto.localchans', 'auto.sourcefree'],
- paths=[[{'short_channel_id_dir': scid21dir, 'amount_msat': 102010, 'delay': 99 + 6 + 6},
- {'short_channel_id_dir': f'0x1x0/{dir01}', 'amount_msat': 102010, 'delay': 99 + 6 + 6},
- {'short_channel_id_dir': f'2x2x1/{dir12}', 'amount_msat': 101000, 'delay': 99 + 6}]])
+ paths=[[{'short_channel_id_dir': scid21dir, 'amount_in_msat': 102010, 'cltv_in': 99 + 6 + 6},
+ {'short_channel_id_dir': f'0x1x0/{dir01}', 'amount_in_msat': 102010, 'cltv_in': 99 + 6 + 6},
+ {'short_channel_id_dir': f'2x2x1/{dir12}', 'amount_in_msat': 101000, 'cltv_in': 99 + 6}]])
def test_fees_dont_exceed_constraints(node_factory):
@@ -1170,7 +1206,7 @@ def test_fees_dont_exceed_constraints(node_factory):
assert len(routes) == 2
for hop in routes[0]['path'] + routes[1]['path']:
if hop['short_channel_id_dir'] == f"{chan['short_channel_id']}/{chan['direction']}":
- amount = hop['amount_msat']
+ amount = hop['amount_in_msat']
assert amount <= max_msat
@@ -1205,7 +1241,7 @@ def test_sourcefree_on_mods(node_factory, bitcoind):
final_cltv=99)['routes']
# Expect no fee.
check_route_as_expected(routes, [[{'short_channel_id_dir': f'0x3x3/{dir03}',
- 'amount_msat': 1000000, 'delay': 99}]])
+ 'amount_in_msat': 1000000, 'cltv_in': 99}]])
# NOT if we specify layers in the other order!
routes = l1.rpc.getroutes(source=nodemap[0],
@@ -1216,7 +1252,7 @@ def test_sourcefree_on_mods(node_factory, bitcoind):
final_cltv=99)['routes']
# Expect no fee.
check_route_as_expected(routes, [[{'short_channel_id_dir': f'0x3x3/{dir03}',
- 'amount_msat': 1003000, 'delay': 117}]])
+ 'amount_in_msat': 1003000, 'cltv_in': 117}]])
def test_live_spendable(node_factory, bitcoind):
@@ -1258,7 +1294,7 @@ def test_live_spendable(node_factory, bitcoind):
num_htlcs = {}
for r in routes["routes"]:
key = r["path"][0]["short_channel_id_dir"]
- path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_msat"]
+ path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_in_msat"]
num_htlcs[key] = num_htlcs.get(key, 0) + 1
# Take into account 645000msat (3750 feerate x 172 weight) per-HTLC reduction in capacity.
@@ -1336,7 +1372,7 @@ def test_limits_fake_gossmap(node_factory, bitcoind):
path_total = {}
for r in routes["routes"]:
key = r["path"][0]["short_channel_id_dir"]
- path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_msat"]
+ path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_in_msat"]
exceeded = {}
for scidd in spendable.keys():
@@ -1384,8 +1420,8 @@ def test_max_htlc(node_factory, bitcoind):
dir01 = direction(nodemap[0], nodemap[1])
check_route_as_expected(routes['routes'],
- [[{'short_channel_id_dir': f'0x1x0/{dir01}', 'amount_msat': 1_000_001, 'delay': 10 + 6}],
- [{'short_channel_id_dir': f'1x1x1/{dir01}', 'amount_msat': 19_000_019, 'delay': 10 + 6}]])
+ [[{'short_channel_id_dir': f'0x1x0/{dir01}', 'amount_in_msat': 1_000_001, 'cltv_in': 10 + 6}],
+ [{'short_channel_id_dir': f'1x1x1/{dir01}', 'amount_in_msat': 19_000_019, 'cltv_in': 10 + 6}]])
# If we can't use channel 2, we fail.
l1.rpc.askrene_create_layer('removechan2')
@@ -1419,7 +1455,7 @@ def test_min_htlc(node_factory, bitcoind):
dir01 = direction(nodemap[0], nodemap[1])
check_route_as_expected(routes['routes'],
- [[{'short_channel_id_dir': f'1x1x1/{dir01}', 'amount_msat': 1_000, 'delay': 10 + 6}]])
+ [[{'short_channel_id_dir': f'1x1x1/{dir01}', 'amount_in_msat': 1_000, 'cltv_in': 10 + 6}]])
def test_min_htlc_after_excess(node_factory, bitcoind):
@@ -1512,7 +1548,7 @@ def test_real_data(node_factory, bitcoind, executor):
futs = {}
for n, prev in prevs.items():
# Record fees
- fees[n].append(sum([r['path'][0]['amount_msat'] for r in prev['routes']]) - AMOUNT)
+ fees[n].append(sum([r['path'][0]['amount_in_msat'] for r in prev['routes']]) - AMOUNT)
# Now stress it, by asking it to spend 1msat less!
futs[n] = executor.submit(l1.rpc.getroutes,
source=l1.info['id'],
@@ -1530,7 +1566,7 @@ def test_real_data(node_factory, bitcoind, executor):
del prevs[n]
continue
- fee = sum([r['path'][0]['amount_msat'] for r in routes['routes']]) - AMOUNT
+ fee = sum([r['path'][0]['amount_in_msat'] for r in routes['routes']]) - AMOUNT
# Should get less expensive
assert fee < fees[n][-1]
@@ -1632,7 +1668,7 @@ def test_real_biases(node_factory, bitcoind, executor):
for r in routes:
for p in r['path']:
if p['short_channel_id_dir'] == chan:
- total += p['amount_msat']
+ total += p['amount_in_msat']
return total
amount_before = amount_through_chan(chan, route['routes'])
@@ -1726,19 +1762,14 @@ def test_askrene_fake_channeld(node_factory, bitcoind):
hash_hex = sha256(bytes.fromhex(preimage_hex)).hexdigest()
paths = {}
- # Sendpay wants a different format, so we convert.
+ # FIXME: Sendpay wants a different format, so we convert.
for i, r in enumerate(routes['routes']):
- paths[i] = [{'id': h['next_node_id'],
+ paths[i] = [{'id': h['node_id_out'],
'channel': h['short_channel_id_dir'].split('/')[0],
- 'direction': int(h['short_channel_id_dir'].split('/')[1])}
+ 'direction': int(h['short_channel_id_dir'].split('/')[1]),
+ 'delay': h['cltv_out'],
+ 'amount_msat': h['amount_out_msat']}
for h in r['path']]
-
- # delay and amount_msat for sendpay are amounts at *end* of hop, not start!
- with_end = r['path'] + [{'amount_msat': r['amount_msat'], 'delay': r['final_cltv']}]
- for n, h in enumerate(paths[i]):
- h['delay'] = with_end[n + 1]['delay']
- h['amount_msat'] = with_end[n + 1]['amount_msat']
-
l1.rpc.sendpay(paths[i], hash_hex,
amount_msat=AMOUNT,
payment_secret='00' * 32,
@@ -2248,9 +2279,9 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1011,
- "delay": 99 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1011,
+ "cltv_in": 99 + 5,
}
],
}
@@ -2269,15 +2300,15 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1033,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1033,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 1022,
- "delay": 99 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 1022,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2296,21 +2327,21 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1066,
- "delay": 99 + 5 + 5 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1066,
+ "cltv_in": 99 + 5 + 5 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 1055,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 1055,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "4x3x2/0",
- "next_node_id": nodemap[3],
- "amount_msat": 1033,
- "delay": 99 + 5,
+ "node_id_out": nodemap[3],
+ "amount_in_msat": 1033,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2331,9 +2362,9 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5,
}
],
}
@@ -2352,15 +2383,15 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 990,
- "delay": 99 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 990,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2379,21 +2410,21 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99 + 5 + 5 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5 + 5 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 990,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 990,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "4x3x2/0",
- "next_node_id": nodemap[3],
- "amount_msat": 969,
- "delay": 99 + 5,
+ "node_id_out": nodemap[3],
+ "amount_in_msat": 969,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2413,9 +2444,9 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99,
}
],
}
@@ -2434,15 +2465,15 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1022,
- "delay": 99 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1022,
+ "cltv_in": 99 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 1022,
- "delay": 99 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 1022,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2461,21 +2492,21 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1055,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1055,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 1055,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 1055,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "4x3x2/0",
- "next_node_id": nodemap[3],
- "amount_msat": 1033,
- "delay": 99 + 5,
+ "node_id_out": nodemap[3],
+ "amount_in_msat": 1033,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2495,9 +2526,9 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99,
}
],
}
@@ -2516,15 +2547,15 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 1000,
- "delay": 99 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5,
},
],
}
@@ -2543,21 +2574,21 @@ def test_includefees(node_factory):
"path": [
{
"short_channel_id_dir": "0x1x0/1",
- "next_node_id": nodemap[1],
- "amount_msat": 1000,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[1],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "2x2x1/1",
- "next_node_id": nodemap[2],
- "amount_msat": 1000,
- "delay": 99 + 5 + 5,
+ "node_id_out": nodemap[2],
+ "amount_in_msat": 1000,
+ "cltv_in": 99 + 5 + 5,
},
{
"short_channel_id_dir": "4x3x2/0",
- "next_node_id": nodemap[3],
- "amount_msat": 979,
- "delay": 99 + 5,
+ "node_id_out": nodemap[3],
+ "amount_in_msat": 979,
+ "cltv_in": 99 + 5,
},
],
}
Why this scored 21/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.