Skip to content

Commit baa727e

Browse files
Abide by max path length param in router.
Also adds some testing by augmenting existing tests.
1 parent 7f7f375 commit baa727e

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

lightning/src/routing/router.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,7 @@ pub(crate) fn get_route<L: Deref, S: ScoreLookUp>(
18601860
where L::Target: Logger {
18611861

18621862
let payment_params = &route_params.payment_params;
1863+
let max_path_length = core::cmp::min(payment_params.max_path_length, MAX_PATH_LENGTH_ESTIMATE);
18631864
let final_value_msat = route_params.final_value_msat;
18641865
// If we're routing to a blinded recipient, we won't have their node id. Therefore, keep the
18651866
// unblinded payee id as an option. We also need a non-optional "payee id" for path construction,
@@ -2155,8 +2156,9 @@ where L::Target: Logger {
21552156
// Verify the liquidity offered by this channel complies to the minimal contribution.
21562157
let contributes_sufficient_value = available_value_contribution_msat >= minimal_value_contribution_msat;
21572158
// Do not consider candidate hops that would exceed the maximum path length.
2158-
let path_length_to_node = $next_hops_path_length + 1;
2159-
let exceeds_max_path_length = path_length_to_node > MAX_PATH_LENGTH_ESTIMATE;
2159+
let path_length_to_node = $next_hops_path_length
2160+
+ if $candidate.blinded_hint_idx().is_some() { 0 } else { 1 };
2161+
let exceeds_max_path_length = path_length_to_node > max_path_length;
21602162

21612163
// Do not consider candidates that exceed the maximum total cltv expiry limit.
21622164
// In order to already account for some of the privacy enhancing random CLTV
@@ -2610,9 +2612,8 @@ where L::Target: Logger {
26102612
};
26112613
let path_min = candidate.htlc_minimum_msat().saturating_add(
26122614
compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees()));
2613-
add_entry!(&first_hop_candidate, blinded_path_fee,
2614-
path_contribution_msat, path_min, 0_u64, candidate.cltv_expiry_delta(),
2615-
candidate.blinded_path().map_or(1, |bp| bp.blinded_hops.len() as u8));
2615+
add_entry!(&first_hop_candidate, blinded_path_fee, path_contribution_msat, path_min,
2616+
0_u64, candidate.cltv_expiry_delta(), 0);
26162617
}
26172618
}
26182619
}
@@ -3372,7 +3373,7 @@ mod tests {
33723373
fn simple_route_test() {
33733374
let (secp_ctx, network_graph, _, _, logger) = build_graph();
33743375
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
3375-
let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
3376+
let mut payment_params = PaymentParameters::from_node_id(nodes[2], 42);
33763377
let scorer = ln_test_utils::TestScorer::new();
33773378
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
33783379
let random_seed_bytes = keys_manager.get_secure_random_bytes();
@@ -3387,7 +3388,8 @@ mod tests {
33873388
assert_eq!(err, "Cannot send a payment of 0 msat");
33883389
} else { panic!(); }
33893390

3390-
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
3391+
payment_params.max_path_length = 2;
3392+
let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
33913393
let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
33923394
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
33933395
assert_eq!(route.paths[0].hops.len(), 2);
@@ -3405,6 +3407,10 @@ mod tests {
34053407
assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
34063408
assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
34073409
assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
3410+
3411+
route_params.payment_params.max_path_length = 1;
3412+
get_route(&our_id, &route_params, &network_graph.read_only(), None,
3413+
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
34083414
}
34093415

34103416
#[test]
@@ -3809,7 +3815,7 @@ mod tests {
38093815
});
38103816

38113817
// If all the channels require some features we don't understand, route should fail
3812-
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
3818+
let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
38133819
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
38143820
&route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
38153821
&Default::default(), &random_seed_bytes) {
@@ -3819,6 +3825,7 @@ mod tests {
38193825
// If we specify a channel to node7, that overrides our local channel view and that gets used
38203826
let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(),
38213827
InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
3828+
route_params.payment_params.max_path_length = 2;
38223829
let route = get_route(&our_id, &route_params, &network_graph.read_only(),
38233830
Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
38243831
&Default::default(), &random_seed_bytes).unwrap();
@@ -4065,8 +4072,9 @@ mod tests {
40654072
} else { panic!(); }
40664073
}
40674074

4068-
let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
4075+
let mut payment_params = PaymentParameters::from_node_id(nodes[6], 42)
40694076
.with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap();
4077+
payment_params.max_path_length = 5;
40704078
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
40714079
let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
40724080
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
@@ -4224,7 +4232,8 @@ mod tests {
42244232
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
42254233
let random_seed_bytes = keys_manager.get_secure_random_bytes();
42264234
// Test through channels 2, 3, 0xff00, 0xff01.
4227-
// Test shows that multiple hop hints are considered.
4235+
// Test shows that multi-hop route hints are considered and factored correctly into the
4236+
// max path length.
42284237

42294238
// Disabling channels 6 & 7 by flags=2
42304239
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
@@ -4252,7 +4261,8 @@ mod tests {
42524261
excess_data: Vec::new()
42534262
});
42544263

4255-
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4264+
let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4265+
route_params.payment_params.max_path_length = 4;
42564266
let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
42574267
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
42584268
assert_eq!(route.paths[0].hops.len(), 4);
@@ -4284,6 +4294,9 @@ mod tests {
42844294
assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
42854295
assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
42864296
assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
4297+
route_params.payment_params.max_path_length = 3;
4298+
get_route(&our_id, &route_params, &network_graph.read_only(), None,
4299+
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
42874300
}
42884301

42894302
#[test]

0 commit comments

Comments
 (0)