Skip to content

Commit ab68de5

Browse files
Update CandidateRouteHop::short_channel_id to be optional
1 parent be59d01 commit ab68de5

File tree

1 file changed

+51
-33
lines changed

1 file changed

+51
-33
lines changed

lightning/src/routing/router.rs

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -946,11 +946,11 @@ enum CandidateRouteHop<'a> {
946946
}
947947

948948
impl<'a> CandidateRouteHop<'a> {
949-
fn short_channel_id(&self) -> u64 {
949+
fn short_channel_id(&self) -> Option<u64> {
950950
match self {
951-
CandidateRouteHop::FirstHop { details } => details.get_outbound_payment_scid().unwrap(),
952-
CandidateRouteHop::PublicHop { short_channel_id, .. } => *short_channel_id,
953-
CandidateRouteHop::PrivateHop { hint } => hint.short_channel_id,
951+
CandidateRouteHop::FirstHop { details } => Some(details.get_outbound_payment_scid().unwrap()),
952+
CandidateRouteHop::PublicHop { short_channel_id, .. } => Some(*short_channel_id),
953+
CandidateRouteHop::PrivateHop { hint } => Some(hint.short_channel_id),
954954
}
955955
}
956956

@@ -1002,7 +1002,9 @@ impl<'a> CandidateRouteHop<'a> {
10021002
}
10031003
}
10041004
fn id(&self, channel_direction: bool /* src_node_id < target_node_id */) -> CandidateHopId {
1005-
CandidateHopId::Clear((self.short_channel_id(), channel_direction))
1005+
match self {
1006+
_ => CandidateHopId::Clear((self.short_channel_id().unwrap(), channel_direction)),
1007+
}
10061008
}
10071009
}
10081010

@@ -1253,6 +1255,18 @@ impl fmt::Display for LoggedPayeePubkey {
12531255
}
12541256
}
12551257

1258+
struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>);
1259+
impl<'a> fmt::Display for LoggedCandidateHop<'a> {
1260+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1261+
match self.0 {
1262+
_ => {
1263+
"SCID ".fmt(f)?;
1264+
self.0.short_channel_id().unwrap().fmt(f)
1265+
},
1266+
}
1267+
}
1268+
}
1269+
12561270
#[inline]
12571271
fn sort_first_hop_channels(
12581272
channels: &mut Vec<&ChannelDetails>, used_liquidities: &HashMap<CandidateHopId, u64>,
@@ -1557,7 +1571,7 @@ where L::Target: Logger {
15571571
// - for regular channels at channel announcement (TODO)
15581572
// - for first and last hops early in get_route
15591573
if $src_node_id != $dest_node_id {
1560-
let short_channel_id = $candidate.short_channel_id();
1574+
let scid_opt = $candidate.short_channel_id();
15611575
let effective_capacity = $candidate.effective_capacity();
15621576
let htlc_maximum_msat = max_htlc_from_capacity(effective_capacity, channel_saturation_pow_half);
15631577

@@ -1612,8 +1626,8 @@ where L::Target: Logger {
16121626
(amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat &&
16131627
recommended_value_msat > $next_hops_path_htlc_minimum_msat));
16141628

1615-
let payment_failed_on_this_channel =
1616-
payment_params.previously_failed_channels.contains(&short_channel_id);
1629+
let payment_failed_on_this_channel = scid_opt.map_or(false,
1630+
|scid| payment_params.previously_failed_channels.contains(&scid));
16171631

16181632
// If HTLC minimum is larger than the amount we're going to transfer, we shouldn't
16191633
// bother considering this channel. If retrying with recommended_value_msat may
@@ -1682,9 +1696,9 @@ where L::Target: Logger {
16821696
inflight_htlc_msat: used_liquidity_msat,
16831697
effective_capacity,
16841698
};
1685-
let channel_penalty_msat = scorer.channel_penalty_msat(
1686-
short_channel_id, &$src_node_id, &$dest_node_id, channel_usage, score_params
1687-
);
1699+
let channel_penalty_msat = scid_opt.map_or(0,
1700+
|scid| scorer.channel_penalty_msat(scid, &$src_node_id, &$dest_node_id,
1701+
channel_usage, score_params));
16881702
let path_penalty_msat = $next_hops_path_penalty_msat
16891703
.saturating_add(channel_penalty_msat);
16901704
let new_graph_node = RouteGraphNode {
@@ -1854,8 +1868,8 @@ where L::Target: Logger {
18541868
let candidate = CandidateRouteHop::FirstHop { details };
18551869
let added = add_entry!(candidate, our_node_id, payee, 0, path_value_msat,
18561870
0, 0u64, 0, 0).is_some();
1857-
log_trace!(logger, "{} direct route to payee via SCID {}",
1858-
if added { "Added" } else { "Skipped" }, candidate.short_channel_id());
1871+
log_trace!(logger, "{} direct route to payee via {}",
1872+
if added { "Added" } else { "Skipped" }, LoggedCandidateHop(&candidate));
18591873
}
18601874
}));
18611875

@@ -2036,10 +2050,12 @@ where L::Target: Logger {
20362050
let mut features_set = false;
20372051
if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.node_id) {
20382052
for details in first_channels {
2039-
if details.get_outbound_payment_scid().unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
2040-
ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
2041-
features_set = true;
2042-
break;
2053+
if let Some(scid) = ordered_hops.last().unwrap().0.candidate.short_channel_id() {
2054+
if details.get_outbound_payment_scid().unwrap() == scid {
2055+
ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
2056+
features_set = true;
2057+
break;
2058+
}
20432059
}
20442060
}
20452061
}
@@ -2125,11 +2141,12 @@ where L::Target: Logger {
21252141
// If we weren't capped by hitting a liquidity limit on a channel in the path,
21262142
// we'll probably end up picking the same path again on the next iteration.
21272143
// Decrease the available liquidity of a hop in the middle of the path.
2128-
let victim_scid = payment_path.hops[(payment_path.hops.len()) / 2].0.candidate.short_channel_id();
2144+
let victim_candidate = &payment_path.hops[(payment_path.hops.len()) / 2].0.candidate;
21292145
let exhausted = u64::max_value();
2130-
log_trace!(logger, "Disabling channel {} for future path building iterations to avoid duplicates.", victim_scid);
2131-
*used_liquidities.entry(CandidateHopId::Clear((victim_scid, false))).or_default() = exhausted;
2132-
*used_liquidities.entry(CandidateHopId::Clear((victim_scid, true))).or_default() = exhausted;
2146+
log_trace!(logger, "Disabling route candidate {} for future path building iterations to
2147+
avoid duplicates.", LoggedCandidateHop(victim_candidate));
2148+
*used_liquidities.entry(victim_candidate.id(false)).or_default() = exhausted;
2149+
*used_liquidities.entry(victim_candidate.id(true)).or_default() = exhausted;
21332150
}
21342151

21352152
// Track the total amount all our collected paths allow to send so that we know
@@ -2259,9 +2276,9 @@ where L::Target: Logger {
22592276
selected_route.sort_unstable_by_key(|path| {
22602277
let mut key = [0u64; MAX_PATH_LENGTH_ESTIMATE as usize];
22612278
debug_assert!(path.hops.len() <= key.len());
2262-
for (scid, key) in path.hops.iter().map(|h| h.0.candidate.short_channel_id()).zip(key.iter_mut()) {
2263-
*key = scid;
2264-
}
2279+
for (scid, key) in path.hops.iter().filter(|h| h.0.candidate.short_channel_id().is_some())
2280+
.map(|h| h.0.candidate.short_channel_id().unwrap()).zip(key.iter_mut())
2281+
{ *key = scid; }
22652282
key
22662283
});
22672284
for idx in 0..(selected_route.len() - 1) {
@@ -2276,15 +2293,16 @@ where L::Target: Logger {
22762293

22772294
let mut selected_paths = Vec::<Vec<Result<RouteHop, LightningError>>>::new();
22782295
for payment_path in selected_route {
2279-
let mut path = payment_path.hops.iter().map(|(payment_hop, node_features)| {
2280-
Ok(RouteHop {
2281-
pubkey: PublicKey::from_slice(payment_hop.node_id.as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &payment_hop.node_id), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
2282-
node_features: node_features.clone(),
2283-
short_channel_id: payment_hop.candidate.short_channel_id(),
2284-
channel_features: payment_hop.candidate.features(),
2285-
fee_msat: payment_hop.fee_msat,
2286-
cltv_expiry_delta: payment_hop.candidate.cltv_expiry_delta(),
2287-
})
2296+
let mut path = payment_path.hops.iter().filter(|(h, _)| h.candidate.short_channel_id().is_some())
2297+
.map(|(payment_hop, node_features)| {
2298+
Ok(RouteHop {
2299+
pubkey: PublicKey::from_slice(payment_hop.node_id.as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &payment_hop.node_id), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
2300+
node_features: node_features.clone(),
2301+
short_channel_id: payment_hop.candidate.short_channel_id().unwrap(),
2302+
channel_features: payment_hop.candidate.features(),
2303+
fee_msat: payment_hop.fee_msat,
2304+
cltv_expiry_delta: payment_hop.candidate.cltv_expiry_delta(),
2305+
})
22882306
}).collect::<Vec<_>>();
22892307
// Propagate the cltv_expiry_delta one hop backwards since the delta from the current hop is
22902308
// applicable for the previous hop.

0 commit comments

Comments
 (0)