Skip to content

Commit 8c5756b

Browse files
committed
Add direct hops to intros after all blinded paths in pathfinding
When we do pathfinding with blinded paths, we start each pathfinding iteration by inserting all the blinded paths into our nodes map as last-hops to the destination. As we do that, we check if any of the introduction points happen to be nodes we have direct chanels with, as we want to use the local info for such channels and support finding a path even if that channel is not publicly announced. However, as we iterate the blinded paths, we may find a second blinded path from the same introduction point which we prefer over the first. If this happens, we would already have added info from us over the local channel to that intro point and end up with calculations for the first hop to a blinded path that we no longer prefer. This is ultimately fixed here in two ways: (a) we process the first-hop channels to blinded path introduction points in a separate loop after we've processed all blinded paths, ensuring we only ever consider a channel to the blinded path we will ultimately prefer. (b) In the next commit, we add we add a new tracking bool in `PathBuildingHop` called `best_path_from_hop_selected` which we set when we process a channel backwards from a node, indicating that we've committed to the best path to the node and check when we add a new path to a node. This would have resulted in a much earlier debug-assertion in fuzzing or several tests.
1 parent bc529c3 commit 8c5756b

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

lightning/src/routing/router.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,6 +2929,7 @@ where L::Target: Logger {
29292929
introduction_node_id_cache.len(),
29302930
"introduction_node_id_cache was built by iterating the blinded_route_hints, so they should be the same len"
29312931
);
2932+
let mut blind_intros_added = hash_map_with_capacity(payment_params.payee.blinded_route_hints().len());
29322933
for (hint_idx, hint) in payment_params.payee.blinded_route_hints().iter().enumerate() {
29332934
// Only add the hops in this route to our candidate set if either
29342935
// we have a direct channel to the first hop or the first hop is
@@ -2943,12 +2944,21 @@ where L::Target: Logger {
29432944
} else {
29442945
CandidateRouteHop::Blinded(BlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx })
29452946
};
2946-
let mut path_contribution_msat = path_value_msat;
29472947
if let Some(hop_used_msat) = add_entry!(&candidate,
2948-
0, path_contribution_msat, 0, 0_u64, 0, 0)
2948+
0, path_value_msat, 0, 0_u64, 0, 0)
29492949
{
2950-
path_contribution_msat = hop_used_msat;
2950+
blind_intros_added.insert(source_node_id, (hop_used_msat, candidate));
29512951
} else { continue }
2952+
}
2953+
// If we added a blinded path from an introduction node to the destination, where the
2954+
// introduction node is one of our direct peers, we need to scan our `first_channels`
2955+
// to detect this. However, doing so immediately after calling `add_entry`, above, could
2956+
// result in incorrect behavior if we, in a later loop iteration, update the fee from the
2957+
// same introduction point to the destination (due to a different blinded path with the
2958+
// same introduction point having a lower score).
2959+
// Thus, we track the nodes that we added paths from in `blind_intros_added` and scan for
2960+
// introduction points we have a channel with after processing all blinded paths.
2961+
for (source_node_id, (path_contribution_msat, candidate)) in blind_intros_added {
29522962
if let Some((first_channels, peer_node_counter)) = first_hop_targets.get_mut(source_node_id) {
29532963
sort_first_hop_channels(
29542964
first_channels, &used_liquidities, recommended_value_msat, our_node_pubkey

0 commit comments

Comments
 (0)