Skip to content

Commit 3ccc5e2

Browse files
committed
[router] Avoid re-selecting the same path over and over again
If we walk the network graph and find a route that meets are payment amount and has a liquidiy limit far in excess of our payment amount, we may select the same path several times in the main path-gathering loop. Instead, if the path we selected was not limited by the available liquidity, we set the middle hop in the path's liquidity available to zero, disabling that channel in future path finding steps.
1 parent 9f6e324 commit 3ccc5e2

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

lightning/src/routing/router.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
893893
// on some channels we already passed (assuming dest->source direction). Here, we
894894
// recompute the fees again, so that if that's the case, we match the currently
895895
// underpaid htlc_minimum_msat with fees.
896-
payment_path.update_value_and_recompute_fees(value_contribution_msat);
896+
payment_path.update_value_and_recompute_fees(cmp::min(value_contribution_msat, final_value_msat));
897897

898898
// Since a path allows to transfer as much value as
899899
// the smallest channel it has ("bottleneck"), we should recompute
@@ -904,6 +904,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
904904
// might have been computed considering a larger value.
905905
// Remember that we used these channels so that we don't rely
906906
// on the same liquidity in future paths.
907+
let mut prevented_redundant_path_selection = false;
907908
for payment_hop in payment_path.hops.iter() {
908909
let channel_liquidity_available_msat = bookkeeped_channels_liquidity_available_msat.get_mut(&payment_hop.route_hop.short_channel_id).unwrap();
909910
let mut spent_on_hop_msat = value_contribution_msat;
@@ -914,8 +915,23 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
914915
// trying to avoid cases when a hop is not usable due to the fee situation.
915916
break 'path_construction;
916917
}
918+
if spent_on_hop_msat == *channel_liquidity_available_msat {
919+
// If this path used all of this channel's available liquidity, we know
920+
// this path will not be selected again in the next loop iteration.
921+
prevented_redundant_path_selection = true;
922+
}
917923
*channel_liquidity_available_msat -= spent_on_hop_msat;
918924
}
925+
if !prevented_redundant_path_selection {
926+
// If we weren't capped by hitting a liquidity limit on a channel in the path,
927+
// we'll probably end up picking the same path again on the next iteration.
928+
// Randomly decrease the available liquidity of a hop in the middle of the
929+
// path.
930+
let victim_liquidity = bookkeeped_channels_liquidity_available_msat.get_mut(
931+
&payment_path.hops[(payment_path.hops.len() - 1) / 2].route_hop.short_channel_id).unwrap();
932+
*victim_liquidity = 0;
933+
}
934+
919935
// Track the total amount all our collected paths allow to send so that we:
920936
// - know when to stop looking for more paths
921937
// - know which of the hops are useless considering how much more sats we need

0 commit comments

Comments
 (0)