Skip to content

Commit b1fd8e1

Browse files
TheBlueMattadi2011
authored andcommitted
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 b3982c2 commit b1fd8e1

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
@@ -2969,6 +2969,7 @@ where L::Target: Logger {
29692969
introduction_node_id_cache.len(),
29702970
"introduction_node_id_cache was built by iterating the blinded_route_hints, so they should be the same len"
29712971
);
2972+
let mut blind_intros_added = hash_map_with_capacity(payment_params.payee.blinded_route_hints().len());
29722973
for (hint_idx, hint) in payment_params.payee.blinded_route_hints().iter().enumerate() {
29732974
// Only add the hops in this route to our candidate set if either
29742975
// we have a direct channel to the first hop or the first hop is
@@ -2983,12 +2984,21 @@ where L::Target: Logger {
29832984
} else {
29842985
CandidateRouteHop::Blinded(BlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx })
29852986
};
2986-
let mut path_contribution_msat = path_value_msat;
29872987
if let Some(hop_used_msat) = add_entry!(&candidate,
2988-
0, path_contribution_msat, 0, 0_u64, 0, 0)
2988+
0, path_value_msat, 0, 0_u64, 0, 0)
29892989
{
2990-
path_contribution_msat = hop_used_msat;
2990+
blind_intros_added.insert(source_node_id, (hop_used_msat, candidate));
29912991
} else { continue }
2992+
}
2993+
// If we added a blinded path from an introduction node to the destination, where the
2994+
// introduction node is one of our direct peers, we need to scan our `first_channels`
2995+
// to detect this. However, doing so immediately after calling `add_entry`, above, could
2996+
// result in incorrect behavior if we, in a later loop iteration, update the fee from the
2997+
// same introduction point to the destination (due to a different blinded path with the
2998+
// same introduction point having a lower score).
2999+
// Thus, we track the nodes that we added paths from in `blind_intros_added` and scan for
3000+
// introduction points we have a channel with after processing all blinded paths.
3001+
for (source_node_id, (path_contribution_msat, candidate)) in blind_intros_added {
29923002
if let Some((first_channels, peer_node_counter)) = first_hop_targets.get_mut(source_node_id) {
29933003
sort_first_hop_channels(
29943004
first_channels, &used_liquidities, recommended_value_msat, our_node_pubkey

0 commit comments

Comments
 (0)