Skip to content

Commit d1759e4

Browse files
committed
Handle first and last hops better
1 parent 14b44d1 commit d1759e4

File tree

1 file changed

+38
-40
lines changed

1 file changed

+38
-40
lines changed

lightning/src/routing/router.rs

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,11 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
273273
}
274274
}
275275

276+
// For every new iteration of path finding, we will avoid using those channels,
277+
// which had the lowest available amount in the previous iterations.
278+
// It would help to have a strong diverse set of paths.
279+
let mut channels_to_avoid = HashSet::new();
280+
276281
// We don't want multiple paths (as per MPP) share capacity of the same channels.
277282
// This map allows paths to be aware of the channel use by other paths in the same call.
278283
// This would help to make a better path finding decisions and not "overbook" channels.
@@ -283,8 +288,9 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
283288
// over the channel with id $chan_id with fees described in
284289
// $directional_info.
285290
( $chan_id: expr, $src_node_id: expr, $dest_node_id: expr, $directional_info: expr, $capacity_sats: expr, $chan_features: expr, $starting_fee_msat: expr ) => {
291+
286292
//TODO: Explore simply adding fee to hit htlc_minimum_msat
287-
if $starting_fee_msat as u64 + final_value_msat >= $directional_info.htlc_minimum_msat {
293+
if $starting_fee_msat as u64 + final_value_msat >= $directional_info.htlc_minimum_msat && !channels_to_avoid.contains(&$chan_id.clone()) {
288294
let proportional_fee_millions = ($starting_fee_msat + final_value_msat).checked_mul($directional_info.fees.proportional_millionths as u64);
289295
if let Some(new_fee) = proportional_fee_millions.and_then(|part| {
290296
($directional_info.fees.base_msat as u64).checked_add(part / 1000000) })
@@ -376,11 +382,6 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
376382
};
377383
}
378384

379-
// For every new iteration of path finding, we will avoid using those channels,
380-
// which had the lowest available amount in the previous iterations.
381-
// It would help to have a strong diverse set of paths.
382-
let mut channels_to_avoid = HashSet::new();
383-
384385
macro_rules! add_entries_to_cheapest_to_target_node {
385386
( $node: expr, $node_id: expr, $fee_to_target_msat: expr ) => {
386387
if first_hops.is_some() {
@@ -428,47 +429,44 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
428429
};
429430
}
430431

431-
// Add the payment receiver node as a target, so that the dest-to-source search algorithm knows what to start with.
432-
match network.get_nodes().get(target) {
433-
None => {},
434-
Some(node) => {
435-
add_entries_to_cheapest_to_target_node!(node, target, 0);
436-
},
437-
}
438-
439-
for hop in last_hops.iter() {
440-
if first_hops.is_none() || hop.src_node_id != *our_node_id { // first_hop overrules last_hops
441-
if network.get_nodes().get(&hop.src_node_id).is_some() {
442-
if first_hops.is_some() {
443-
if let Some(&(ref first_hop, ref features)) = first_hop_targets.get(&hop.src_node_id) {
444-
// Currently there are no channel-context features defined, so we are a
445-
// bit lazy here. In the future, we should pull them out via our
446-
// ChannelManager, but there's no reason to waste the space until we
447-
// need them.
448-
add_entry!(first_hop, *our_node_id , hop.src_node_id, dummy_directional_info, None::<u64>, features.to_context(), 0);
449-
}
450-
}
451-
// BOLT 11 doesn't allow inclusion of features for the last hop hints, which
452-
// really sucks, cause we're gonna need that eventually.
453-
add_entry!(hop.short_channel_id, hop.src_node_id, target, hop, None::<u64>, ChannelFeatures::empty(), 0);
454-
}
455-
}
456-
}
457-
458432
let mut payment_paths = Vec::new();
459433
let mut tries_left = 10;
460434
let mut found_amount_msat = 0;
461-
// For every MPP start with the same pre-filled data.
462-
let prefilled_targets = targets.clone();
463-
let prefilled_dist = dist.clone();
464435

465436
// TODO: currently pretending that always have blockchain/amount data for channel capacities.
466437
// Should handle None better.
467438
'paths_collection: loop {
468-
// For every new path, start from the same prefilled data, except channels_to_avoid and used_channels_with_amounts_msat,
469-
// which will improve the further iterations of path finding.
470-
targets = prefilled_targets.clone();
471-
dist = prefilled_dist.clone();
439+
// For every new path, start from scratch, except channels_to_avoid and used_channels_with_amounts_msat,
440+
// which will improve the further iterations of path finding. Also keep first_hop_targets.
441+
targets.clear();
442+
dist.clear();
443+
444+
// Add the payment receiver node as a target, so that the dest-to-source search algorithm knows what to start with.
445+
match network.get_nodes().get(target) {
446+
None => {},
447+
Some(node) => {
448+
add_entries_to_cheapest_to_target_node!(node, target, 0);
449+
},
450+
}
451+
452+
for hop in last_hops.iter() {
453+
if first_hops.is_none() || hop.src_node_id != *our_node_id { // first_hop overrules last_hops
454+
if network.get_nodes().get(&hop.src_node_id).is_some() {
455+
if first_hops.is_some() {
456+
if let Some(&(ref first_hop, ref features)) = first_hop_targets.get(&hop.src_node_id) {
457+
// Currently there are no channel-context features defined, so we are a
458+
// bit lazy here. In the future, we should pull them out via our
459+
// ChannelManager, but there's no reason to waste the space until we
460+
// need them.
461+
add_entry!(first_hop, *our_node_id , hop.src_node_id, dummy_directional_info, None::<u64>, features.to_context(), 0);
462+
}
463+
}
464+
// BOLT 11 doesn't allow inclusion of features for the last hop hints, which
465+
// really sucks, cause we're gonna need that eventually.
466+
add_entry!(hop.short_channel_id, hop.src_node_id, target, hop, None::<u64>, ChannelFeatures::empty(), 0);
467+
}
468+
}
469+
}
472470

473471
// At this point, targets are filled with the data from first and last hops communicated by the caller, and the payment receiver.
474472
'path_construction: while let Some(RouteGraphNode { pubkey, lowest_fee_to_node, .. }) = targets.pop() {

0 commit comments

Comments
 (0)