Skip to content

Commit 1c0c656

Browse files
committed
make target optional
1 parent c4f7c3d commit 1c0c656

File tree

3 files changed

+226
-270
lines changed

3 files changed

+226
-270
lines changed

lightning/src/routing/gossip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ impl Readable for ChannelInfo {
980980
#[derive(Clone)]
981981
pub struct DirectedChannelInfo<'a> {
982982
/// Provides information about a channel between two nodes.
983-
pub channel: &'a ChannelInfo,
983+
channel: &'a ChannelInfo,
984984
direction: &'a ChannelUpdateInfo,
985985
htlc_maximum_msat: u64,
986986
effective_capacity: EffectiveCapacity,

lightning/src/routing/router.rs

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,11 @@ impl<'a, S: Deref> ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: Scor
131131
impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp {
132132
type ScoreParams = <S::Target as ScoreLookUp>::ScoreParams;
133133
fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 {
134-
let target = candidate.target();
135134
let short_channel_id = match candidate.short_channel_id() {
136135
Some(short_channel_id) => short_channel_id,
137136
None => return self.scorer.channel_penalty_msat(candidate, usage, score_params),
138137
};
138+
let target = candidate.target().unwrap();
139139
let source = candidate.source();
140140
if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat(
141141
&source, &target, short_channel_id
@@ -1036,7 +1036,7 @@ pub enum CandidateRouteHop<'a> {
10361036
/// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
10371037
Blinded {
10381038
/// Hint provides information about a blinded hop, needed while routing through a blinded
1039-
/// channel.
1039+
/// path.
10401040
/// `BlindedPayInfo` provides information needed about the
10411041
/// payment while routing through a blinded
10421042
/// path.
@@ -1046,10 +1046,6 @@ pub enum CandidateRouteHop<'a> {
10461046
/// Provided to uniquely identify a hop as we are
10471047
/// route building.
10481048
hint_idx: usize,
1049-
/// The node id of current hop in route.
1050-
///
1051-
/// This will always equal to `maybe_dummy_payee_node_id` in `find_route` method.
1052-
target_node_id: NodeId,
10531049
},
10541050
/// Similar to [`Self::Blinded`], but the path here has 1 blinded hop. `BlindedPayInfo` provided
10551051
/// for 1-hop blinded paths is ignored because it is meant to apply to the hops *between* the
@@ -1065,10 +1061,6 @@ pub enum CandidateRouteHop<'a> {
10651061
/// Provided to uniquely identify a hop as we are
10661062
/// route building.
10671063
hint_idx: usize,
1068-
/// The node id of current hop in route.
1069-
///
1070-
/// This will always equal to `maybe_dummy_payee_node_id` in `find_route` method.
1071-
target_node_id: NodeId,
10721064
},
10731065
}
10741066

@@ -1158,11 +1150,11 @@ impl<'a> CandidateRouteHop<'a> {
11581150
/// Returns the id of this hop.
11591151
/// For `Blinded` and `OneHopBlinded` we return `CandidateHopId::Blinded` because we don't know the channel id.
11601152
/// For any other option we return `CandidateHopId::Clear` because we know the channel id and the direction.
1161-
pub fn id(&self, channel_direction: bool /* src_node_id < target_node_id */) -> CandidateHopId {
1153+
pub fn id(&self, channel_direction: Option<bool> /* src_node_id < target_node_id */) -> CandidateHopId {
11621154
match self {
11631155
CandidateRouteHop::Blinded { hint_idx, .. } => CandidateHopId::Blinded(*hint_idx),
11641156
CandidateRouteHop::OneHopBlinded { hint_idx, .. } => CandidateHopId::Blinded(*hint_idx),
1165-
_ => CandidateHopId::Clear((self.short_channel_id().unwrap(), channel_direction)),
1157+
_ => CandidateHopId::Clear((self.short_channel_id().unwrap(), channel_direction.unwrap_or_else(|| self.source() < self.target().unwrap()))),
11661158
}
11671159
}
11681160
fn blinded_path(&self) -> Option<&'a BlindedPath> {
@@ -1194,14 +1186,14 @@ impl<'a> CandidateRouteHop<'a> {
11941186
///
11951187
/// Target node id refers to the current examined hop in route finding.
11961188
///
1197-
/// For `Blinded` and `OneHopBlinded` we return `maybe_dummy_payee_node_id` because we don't know the target.
1198-
pub fn target(&self) -> NodeId {
1189+
/// For `Blinded` and `OneHopBlinded` we return `None` because we don't know the target.
1190+
pub fn target(&self) -> Option<NodeId> {
11991191
match self {
1200-
CandidateRouteHop::FirstHop { details, .. } => details.counterparty.node_id.into(),
1201-
CandidateRouteHop::PublicHop { target_node_id, .. } => *target_node_id,
1202-
CandidateRouteHop::PrivateHop { target_node_id, .. } => *target_node_id,
1203-
CandidateRouteHop::Blinded { target_node_id, .. } => *target_node_id,
1204-
CandidateRouteHop::OneHopBlinded { target_node_id, .. } => *target_node_id,
1192+
CandidateRouteHop::FirstHop { details, .. } => Some(details.counterparty.node_id.into()),
1193+
CandidateRouteHop::PublicHop { target_node_id, .. } => Some(*target_node_id),
1194+
CandidateRouteHop::PrivateHop { target_node_id, .. } => Some(*target_node_id),
1195+
CandidateRouteHop::Blinded { .. } => None,
1196+
CandidateRouteHop::OneHopBlinded { .. } => None,
12051197
}
12061198
}
12071199
}
@@ -1815,7 +1807,7 @@ where L::Target: Logger {
18151807
// $next_hops_fee_msat represents the fees paid for using all the channels *after* this one,
18161808
// since that value has to be transferred over this channel.
18171809
// Returns the contribution amount of $candidate if the channel caused an update to `targets`.
1818-
( $candidate: expr, $src_node_id: expr, $dest_node_id: expr, $next_hops_fee_msat: expr,
1810+
( $candidate: expr, $next_hops_fee_msat: expr,
18191811
$next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
18201812
$next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => { {
18211813
// We "return" whether we updated the path at the end, and how much we can route via
@@ -1825,7 +1817,9 @@ where L::Target: Logger {
18251817
// practice these cases should be caught earlier:
18261818
// - for regular channels at channel announcement (TODO)
18271819
// - for first and last hops early in get_route
1828-
if $src_node_id != $dest_node_id {
1820+
let src_node_id = $candidate.source();
1821+
let dest_node_id = $candidate.target().unwrap_or(maybe_dummy_payee_node_id);
1822+
if src_node_id != dest_node_id {
18291823
let scid_opt = $candidate.short_channel_id();
18301824
let effective_capacity = $candidate.effective_capacity();
18311825
let htlc_maximum_msat = max_htlc_from_capacity(effective_capacity, channel_saturation_pow_half);
@@ -1839,7 +1833,7 @@ where L::Target: Logger {
18391833
// We do this for now, but this is a subject for removal.
18401834
if let Some(mut available_value_contribution_msat) = htlc_maximum_msat.checked_sub($next_hops_fee_msat) {
18411835
let used_liquidity_msat = used_liquidities
1842-
.get(&$candidate.id($src_node_id < $dest_node_id))
1836+
.get(&$candidate.id(None))
18431837
.map_or(0, |used_liquidity_msat| {
18441838
available_value_contribution_msat = available_value_contribution_msat
18451839
.saturating_sub(*used_liquidity_msat);
@@ -1934,7 +1928,7 @@ where L::Target: Logger {
19341928
);
19351929
let path_htlc_minimum_msat = compute_fees_saturating(curr_min, $candidate.fees())
19361930
.saturating_add(curr_min);
1937-
let hm_entry = dist.entry($src_node_id);
1931+
let hm_entry = dist.entry($candidate.source());
19381932
let old_entry = hm_entry.or_insert_with(|| {
19391933
// If there was previously no known way to access the source node
19401934
// (recall it goes payee-to-payer) of short_channel_id, first add a
@@ -1970,7 +1964,7 @@ where L::Target: Logger {
19701964

19711965
// Ignore hop_use_fee_msat for channel-from-us as we assume all channels-from-us
19721966
// will have the same effective-fee
1973-
if $src_node_id != our_node_id {
1967+
if src_node_id != our_node_id {
19741968
// Note that `u64::max_value` means we'll always fail the
19751969
// `old_entry.total_fee_msat > total_fee_msat` check below
19761970
hop_use_fee_msat = compute_fees_saturating(amount_to_transfer_over_msat, $candidate.fees());
@@ -1996,7 +1990,7 @@ where L::Target: Logger {
19961990
let path_penalty_msat = $next_hops_path_penalty_msat
19971991
.saturating_add(channel_penalty_msat);
19981992
let new_graph_node = RouteGraphNode {
1999-
node_id: $src_node_id,
1993+
node_id: src_node_id,
20001994
lowest_fee_to_node: total_fee_msat,
20011995
total_cltv_delta: hop_total_cltv_delta,
20021996
value_contribution_msat,
@@ -2112,7 +2106,7 @@ where L::Target: Logger {
21122106
if let Some(first_channels) = first_hop_targets.get(&$node_id) {
21132107
for details in first_channels {
21142108
let candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id };
2115-
add_entry!(&candidate, our_node_id, $node_id, $fee_to_target_msat,
2109+
add_entry!(&candidate, $fee_to_target_msat,
21162110
$next_hops_value_contribution,
21172111
$next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
21182112
$next_hops_cltv_delta, $next_hops_path_length);
@@ -2138,7 +2132,7 @@ where L::Target: Logger {
21382132
source_node_id: *source,
21392133
target_node_id: $node_id,
21402134
};
2141-
add_entry!(&candidate, *source, $node_id,
2135+
add_entry!(&candidate,
21422136
$fee_to_target_msat,
21432137
$next_hops_value_contribution,
21442138
$next_hops_path_htlc_minimum_msat,
@@ -2169,7 +2163,7 @@ where L::Target: Logger {
21692163
payee_node_id_opt.map(|payee| first_hop_targets.get(&payee).map(|first_channels| {
21702164
for details in first_channels {
21712165
let candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id };
2172-
let added = add_entry!(&candidate, our_node_id, payee, 0, path_value_msat,
2166+
let added = add_entry!(&candidate, 0, path_value_msat,
21732167
0, 0u64, 0, 0).is_some();
21742168
log_trace!(logger, "{} direct route to payee via {}",
21752169
if added { "Added" } else { "Skipped" }, LoggedCandidateHop(&candidate));
@@ -2203,10 +2197,10 @@ where L::Target: Logger {
22032197
network_nodes.get(&intro_node_id).is_some();
22042198
if !have_intro_node_in_graph || our_node_id == intro_node_id { continue }
22052199
let candidate = if hint.1.blinded_hops.len() == 1 {
2206-
CandidateRouteHop::OneHopBlinded { hint, hint_idx, target_node_id: maybe_dummy_payee_node_id }
2207-
} else { CandidateRouteHop::Blinded { hint, hint_idx, target_node_id: maybe_dummy_payee_node_id } };
2200+
CandidateRouteHop::OneHopBlinded { hint, hint_idx }
2201+
} else { CandidateRouteHop::Blinded { hint, hint_idx } };
22082202
let mut path_contribution_msat = path_value_msat;
2209-
if let Some(hop_used_msat) = add_entry!(&candidate, intro_node_id, maybe_dummy_payee_node_id,
2203+
if let Some(hop_used_msat) = add_entry!(&candidate,
22102204
0, path_contribution_msat, 0, 0_u64, 0, 0)
22112205
{
22122206
path_contribution_msat = hop_used_msat;
@@ -2222,7 +2216,7 @@ where L::Target: Logger {
22222216
};
22232217
let path_min = candidate.htlc_minimum_msat().saturating_add(
22242218
compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees()));
2225-
add_entry!(&first_hop_candidate, our_node_id, intro_node_id, blinded_path_fee,
2219+
add_entry!(&first_hop_candidate, blinded_path_fee,
22262220
path_contribution_msat, path_min, 0_u64, candidate.cltv_expiry_delta(),
22272221
candidate.blinded_path().map_or(1, |bp| bp.blinded_hops.len() as u8));
22282222
}
@@ -2276,7 +2270,7 @@ where L::Target: Logger {
22762270
})
22772271
.unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop, target_node_id: target });
22782272

2279-
if let Some(hop_used_msat) = add_entry!(&candidate, source, target,
2273+
if let Some(hop_used_msat) = add_entry!(&candidate,
22802274
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
22812275
aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat,
22822276
aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length)
@@ -2290,7 +2284,7 @@ where L::Target: Logger {
22902284
}
22912285

22922286
let used_liquidity_msat = used_liquidities
2293-
.get(&candidate.id(source < target)).copied()
2287+
.get(&candidate.id(None)).copied()
22942288
.unwrap_or(0);
22952289
let channel_usage = ChannelUsage {
22962290
amount_msat: final_value_msat + aggregate_next_hops_fee_msat,
@@ -2315,7 +2309,7 @@ where L::Target: Logger {
23152309
recommended_value_msat, our_node_pubkey);
23162310
for details in first_channels {
23172311
let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id};
2318-
add_entry!(&first_hop_candidate, our_node_id, NodeId::from_pubkey(&prev_hop_id),
2312+
add_entry!(&first_hop_candidate,
23192313
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
23202314
aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat,
23212315
aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length);
@@ -2360,8 +2354,7 @@ where L::Target: Logger {
23602354
recommended_value_msat, our_node_pubkey);
23612355
for details in first_channels {
23622356
let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id};
2363-
add_entry!(&first_hop_candidate, our_node_id,
2364-
NodeId::from_pubkey(&hop.src_node_id),
2357+
add_entry!(&first_hop_candidate,
23652358
aggregate_next_hops_fee_msat,
23662359
aggregate_path_contribution_msat,
23672360
aggregate_next_hops_path_htlc_minimum_msat,
@@ -2400,7 +2393,7 @@ where L::Target: Logger {
24002393

24012394
'path_walk: loop {
24022395
let mut features_set = false;
2403-
if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.candidate.target()) {
2396+
if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.candidate.target().unwrap_or(maybe_dummy_payee_node_id)) {
24042397
for details in first_channels {
24052398
if let Some(scid) = ordered_hops.last().unwrap().0.candidate.short_channel_id() {
24062399
if details.get_outbound_payment_scid().unwrap() == scid {
@@ -2412,7 +2405,7 @@ where L::Target: Logger {
24122405
}
24132406
}
24142407
if !features_set {
2415-
if let Some(node) = network_nodes.get(&ordered_hops.last().unwrap().0.candidate.target()) {
2408+
if let Some(node) = network_nodes.get(&ordered_hops.last().unwrap().0.candidate.target().unwrap_or(maybe_dummy_payee_node_id)) {
24162409
if let Some(node_info) = node.announcement_info.as_ref() {
24172410
ordered_hops.last_mut().unwrap().1 = node_info.features.clone();
24182411
} else {
@@ -2429,11 +2422,11 @@ where L::Target: Logger {
24292422
// save this path for the payment route. Also, update the liquidity
24302423
// remaining on the used hops, so that we take them into account
24312424
// while looking for more paths.
2432-
if ordered_hops.last().unwrap().0.candidate.target() == maybe_dummy_payee_node_id {
2425+
if ordered_hops.last().unwrap().0.candidate.target().unwrap_or(maybe_dummy_payee_node_id) == maybe_dummy_payee_node_id {
24332426
break 'path_walk;
24342427
}
24352428

2436-
new_entry = match dist.remove(&ordered_hops.last().unwrap().0.candidate.target()) {
2429+
new_entry = match dist.remove(&ordered_hops.last().unwrap().0.candidate.target().unwrap_or(maybe_dummy_payee_node_id)) {
24372430
Some(payment_hop) => payment_hop,
24382431
// We can't arrive at None because, if we ever add an entry to targets,
24392432
// we also fill in the entry in dist (see add_entry!).
@@ -2473,12 +2466,11 @@ where L::Target: Logger {
24732466
// on the same liquidity in future paths.
24742467
let mut prevented_redundant_path_selection = false;
24752468
let prev_hop_iter = core::iter::once(our_node_id)
2476-
.chain(payment_path.hops.iter().map(|(hop, _)| hop.candidate.target()));
2477-
for (prev_hop, (hop, _)) in prev_hop_iter.zip(payment_path.hops.iter()) {
2478-
let target = hop.candidate.target();
2469+
.chain(payment_path.hops.iter().map(|(hop, _)| hop.candidate.target().unwrap_or(maybe_dummy_payee_node_id)));
2470+
for (_, (hop, _)) in prev_hop_iter.zip(payment_path.hops.iter()) {
24792471
let spent_on_hop_msat = value_contribution_msat + hop.next_hops_fee_msat;
24802472
let used_liquidity_msat = used_liquidities
2481-
.entry(hop.candidate.id(prev_hop < target))
2473+
.entry(hop.candidate.id(None))
24822474
.and_modify(|used_liquidity_msat| *used_liquidity_msat += spent_on_hop_msat)
24832475
.or_insert(spent_on_hop_msat);
24842476
let hop_capacity = hop.candidate.effective_capacity();
@@ -2499,8 +2491,8 @@ where L::Target: Logger {
24992491
log_trace!(logger,
25002492
"Disabling route candidate {} for future path building iterations to avoid duplicates.",
25012493
LoggedCandidateHop(victim_candidate));
2502-
*used_liquidities.entry(victim_candidate.id(false)).or_default() = exhausted;
2503-
*used_liquidities.entry(victim_candidate.id(true)).or_default() = exhausted;
2494+
*used_liquidities.entry(victim_candidate.id(Some(false))).or_default() = exhausted;
2495+
*used_liquidities.entry(victim_candidate.id(Some(true))).or_default() = exhausted;
25042496
}
25052497

25062498
// Track the total amount all our collected paths allow to send so that we know
@@ -2646,15 +2638,15 @@ where L::Target: Logger {
26462638
selected_route.sort_unstable_by_key(|path| {
26472639
let mut key = [CandidateHopId::Clear((42, true)) ; MAX_PATH_LENGTH_ESTIMATE as usize];
26482640
debug_assert!(path.hops.len() <= key.len());
2649-
for (scid, key) in path.hops.iter() .map(|h| h.0.candidate.id(true)).zip(key.iter_mut()) {
2641+
for (scid, key) in path.hops.iter() .map(|h| h.0.candidate.id(Some(true))).zip(key.iter_mut()) {
26502642
*key = scid;
26512643
}
26522644
key
26532645
});
26542646
for idx in 0..(selected_route.len() - 1) {
26552647
if idx + 1 >= selected_route.len() { break; }
2656-
if iter_equal(selected_route[idx ].hops.iter().map(|h| (h.0.candidate.id(true), h.0.candidate.target())),
2657-
selected_route[idx + 1].hops.iter().map(|h| (h.0.candidate.id(true), h.0.candidate.target()))) {
2648+
if iter_equal(selected_route[idx ].hops.iter().map(|h| (h.0.candidate.id(Some(true)), h.0.candidate.target().unwrap_or(maybe_dummy_payee_node_id))),
2649+
selected_route[idx + 1].hops.iter().map(|h| (h.0.candidate.id(Some(true)), h.0.candidate.target().unwrap_or(maybe_dummy_payee_node_id)))) {
26582650
let new_value = selected_route[idx].get_value_msat() + selected_route[idx + 1].get_value_msat();
26592651
selected_route[idx].update_value_and_recompute_fees(new_value);
26602652
selected_route.remove(idx + 1);
@@ -2679,14 +2671,14 @@ where L::Target: Logger {
26792671
// there are announced channels between the endpoints. If so, the hop might be
26802672
// referring to any of the announced channels, as its `short_channel_id` might be
26812673
// an alias, in which case we don't take any chances here.
2682-
network_graph.node(&hop.candidate.target()).map_or(false, |hop_node|
2674+
network_graph.node(&hop.candidate.target().unwrap_or(maybe_dummy_payee_node_id)).map_or(false, |hop_node|
26832675
hop_node.channels.iter().any(|scid| network_graph.channel(*scid)
26842676
.map_or(false, |c| c.as_directed_from(&prev_hop_node_id).is_some()))
26852677
)
26862678
};
26872679

26882680
hops.push(RouteHop {
2689-
pubkey: PublicKey::from_slice(hop.candidate.target().as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &hop.candidate.target()), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
2681+
pubkey: PublicKey::from_slice(hop.candidate.target().unwrap_or(maybe_dummy_payee_node_id).as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &hop.candidate.target().unwrap_or(maybe_dummy_payee_node_id).as_slice()), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
26902682
node_features: node_features.clone(),
26912683
short_channel_id: hop.candidate.short_channel_id().unwrap(),
26922684
channel_features: hop.candidate.features(),
@@ -2695,7 +2687,7 @@ where L::Target: Logger {
26952687
maybe_announced_channel,
26962688
});
26972689

2698-
prev_hop_node_id = hop.candidate.target();
2690+
prev_hop_node_id = hop.candidate.target().unwrap_or(maybe_dummy_payee_node_id);
26992691
}
27002692
let mut final_cltv_delta = final_cltv_expiry_delta;
27012693
let blinded_tail = payment_path.hops.last().and_then(|(h, _)| {
@@ -2861,7 +2853,7 @@ fn build_route_from_hops_internal<L: Deref>(
28612853
fn channel_penalty_msat(&self, candidate: &CandidateRouteHop,
28622854
_usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64
28632855
{
2864-
let target = candidate.target();
2856+
let target = candidate.target().unwrap();
28652857
let source = candidate.source();
28662858
let mut cur_id = self.our_node_id;
28672859
for i in 0..self.hop_ids.len() {
@@ -6237,7 +6229,7 @@ mod tests {
62376229
impl ScoreLookUp for BadNodeScorer {
62386230
type ScoreParams = ();
62396231
fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
6240-
let target = candidate.target();
6232+
let target = candidate.target().unwrap();
62416233
if target == self.node_id { u64::max_value() } else { 0 }
62426234
}
62436235
}

0 commit comments

Comments
 (0)