Skip to content

Commit d9e2704

Browse files
committed
Add source and target functions to CandidateRouteHop
- Make methods public and add docs
1 parent 04841ac commit d9e2704

File tree

2 files changed

+83
-22
lines changed

2 files changed

+83
-22
lines changed

lightning/src/routing/gossip.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,8 @@ impl Readable for ChannelInfo {
977977
/// source node to a target node.
978978
#[derive(Clone)]
979979
pub struct DirectedChannelInfo<'a> {
980-
channel: &'a ChannelInfo,
980+
/// Provides information about a channel between two nodes.
981+
pub channel: &'a ChannelInfo,
981982
direction: &'a ChannelUpdateInfo,
982983
htlc_maximum_msat: u64,
983984
effective_capacity: EffectiveCapacity,

lightning/src/routing/router.rs

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -994,42 +994,78 @@ impl cmp::PartialOrd for RouteGraphNode {
994994
///
995995
/// Used to construct a [`PathBuildingHop`] and to estimate [`EffectiveCapacity`].
996996
#[derive(Clone, Debug)]
997-
enum CandidateRouteHop<'a> {
997+
pub enum CandidateRouteHop<'a> {
998998
/// A hop from the payer, where the outbound liquidity is known.
999999
FirstHop {
1000+
/// The channel details of the first hop.
1001+
/// `get_outbound_payment_scid` is assumed to always return Some(scid) - this assumption is checked in
1002+
/// `find_route` method.
10001003
details: &'a ChannelDetails,
1004+
/// The node id of the payer.
1005+
/// Can be accessed via `source` method.
1006+
node_id: NodeId
10011007
},
10021008
/// A hop found in the [`ReadOnlyNetworkGraph`], where the channel capacity may be unknown.
10031009
PublicHop {
1010+
/// The channel info of the hop.
10041011
info: DirectedChannelInfo<'a>,
1012+
/// The short_channel_id of the channel.
10051013
short_channel_id: u64,
1014+
/// The node id of the current hop in route.
1015+
source_node_id: NodeId,
1016+
/// The node id of next hop in route.
1017+
target_node_id: NodeId,
10061018
},
10071019
/// A hop to the payee found in the BOLT 11 payment invoice, though not necessarily a direct
10081020
/// channel.
10091021
PrivateHop {
1022+
/// Hint provides information about a private hop, needed while routing through a private
1023+
/// channel.
10101024
hint: &'a RouteHintHop,
1025+
/// The node id of the next hop in route.
1026+
target_node_id: NodeId
10111027
},
10121028
/// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
10131029
Blinded {
1030+
/// Hint provides information about a blinded hop, needed while routing through a blinded
1031+
/// channel.
1032+
/// `BlindedPayInfo` provides information needed about the
1033+
/// payment while routing through a blinded
1034+
/// path.
1035+
/// `BlindedPath` is the blinded path to the destination.
10141036
hint: &'a (BlindedPayInfo, BlindedPath),
1037+
/// The index of the hint in the original list of blinded hints.
1038+
/// Provided to uniquely identify a hop as we are
1039+
/// route building.
10151040
hint_idx: usize,
10161041
},
10171042
/// Similar to [`Self::Blinded`], but the path here has 1 blinded hop. `BlindedPayInfo` provided
10181043
/// for 1-hop blinded paths is ignored because it is meant to apply to the hops *between* the
10191044
/// introduction node and the destination. Useful for tracking that we need to include a blinded
10201045
/// path at the end of our [`Route`].
10211046
OneHopBlinded {
1047+
/// Hint provides information about a single blinded hop, needed while routing through a blinded
1048+
/// channel.
1049+
/// `BlindedPayInfo` is ignored here.
1050+
/// `BlindedPath` is the blinded path to the destination.
10221051
hint: &'a (BlindedPayInfo, BlindedPath),
1052+
/// The index of the hint in the original list of blinded hints.
1053+
/// Provided to uniquely identify a hop as we are
1054+
/// route building.
10231055
hint_idx: usize,
10241056
},
10251057
}
10261058

10271059
impl<'a> CandidateRouteHop<'a> {
1028-
fn short_channel_id(&self) -> Option<u64> {
1060+
/// Returns short_channel_id if known.
1061+
/// For `FirstHop` we assume `get_outbound_payment_scid` is always set, this assumption is checked in
1062+
/// `find_route` method.
1063+
/// For `Blinded` and `OneHopBlinded` we return None because we don't know the channel id.
1064+
pub fn short_channel_id(&self) -> Option<u64> {
10291065
match self {
1030-
CandidateRouteHop::FirstHop { details } => Some(details.get_outbound_payment_scid().unwrap()),
1066+
CandidateRouteHop::FirstHop { details, .. } => Some(details.get_outbound_payment_scid().unwrap()),
10311067
CandidateRouteHop::PublicHop { short_channel_id, .. } => Some(*short_channel_id),
1032-
CandidateRouteHop::PrivateHop { hint } => Some(hint.short_channel_id),
1068+
CandidateRouteHop::PrivateHop { hint, .. } => Some(hint.short_channel_id),
10331069
CandidateRouteHop::Blinded { .. } => None,
10341070
CandidateRouteHop::OneHopBlinded { .. } => None,
10351071
}
@@ -1038,7 +1074,7 @@ impl<'a> CandidateRouteHop<'a> {
10381074
// NOTE: This may alloc memory so avoid calling it in a hot code path.
10391075
fn features(&self) -> ChannelFeatures {
10401076
match self {
1041-
CandidateRouteHop::FirstHop { details } => details.counterparty.features.to_context(),
1077+
CandidateRouteHop::FirstHop { details, .. } => details.counterparty.features.to_context(),
10421078
CandidateRouteHop::PublicHop { info, .. } => info.channel().features.clone(),
10431079
CandidateRouteHop::PrivateHop { .. } => ChannelFeatures::empty(),
10441080
CandidateRouteHop::Blinded { .. } => ChannelFeatures::empty(),
@@ -1050,17 +1086,17 @@ impl<'a> CandidateRouteHop<'a> {
10501086
match self {
10511087
CandidateRouteHop::FirstHop { .. } => 0,
10521088
CandidateRouteHop::PublicHop { info, .. } => info.direction().cltv_expiry_delta as u32,
1053-
CandidateRouteHop::PrivateHop { hint } => hint.cltv_expiry_delta as u32,
1089+
CandidateRouteHop::PrivateHop { hint, .. } => hint.cltv_expiry_delta as u32,
10541090
CandidateRouteHop::Blinded { hint, .. } => hint.0.cltv_expiry_delta as u32,
10551091
CandidateRouteHop::OneHopBlinded { .. } => 0,
10561092
}
10571093
}
10581094

10591095
fn htlc_minimum_msat(&self) -> u64 {
10601096
match self {
1061-
CandidateRouteHop::FirstHop { details } => details.next_outbound_htlc_minimum_msat,
1097+
CandidateRouteHop::FirstHop { details, .. } => details.next_outbound_htlc_minimum_msat,
10621098
CandidateRouteHop::PublicHop { info, .. } => info.direction().htlc_minimum_msat,
1063-
CandidateRouteHop::PrivateHop { hint } => hint.htlc_minimum_msat.unwrap_or(0),
1099+
CandidateRouteHop::PrivateHop { hint, .. } => hint.htlc_minimum_msat.unwrap_or(0),
10641100
CandidateRouteHop::Blinded { hint, .. } => hint.0.htlc_minimum_msat,
10651101
CandidateRouteHop::OneHopBlinded { .. } => 0,
10661102
}
@@ -1072,7 +1108,7 @@ impl<'a> CandidateRouteHop<'a> {
10721108
base_msat: 0, proportional_millionths: 0,
10731109
},
10741110
CandidateRouteHop::PublicHop { info, .. } => info.direction().fees,
1075-
CandidateRouteHop::PrivateHop { hint } => hint.fees,
1111+
CandidateRouteHop::PrivateHop { hint, .. } => hint.fees,
10761112
CandidateRouteHop::Blinded { hint, .. } => {
10771113
RoutingFees {
10781114
base_msat: hint.0.fee_base_msat,
@@ -1086,13 +1122,13 @@ impl<'a> CandidateRouteHop<'a> {
10861122

10871123
fn effective_capacity(&self) -> EffectiveCapacity {
10881124
match self {
1089-
CandidateRouteHop::FirstHop { details } => EffectiveCapacity::ExactLiquidity {
1125+
CandidateRouteHop::FirstHop { details, .. } => EffectiveCapacity::ExactLiquidity {
10901126
liquidity_msat: details.next_outbound_htlc_limit_msat,
10911127
},
10921128
CandidateRouteHop::PublicHop { info, .. } => info.effective_capacity(),
1093-
CandidateRouteHop::PrivateHop { hint: RouteHintHop { htlc_maximum_msat: Some(max), .. }} =>
1129+
CandidateRouteHop::PrivateHop { hint: RouteHintHop { htlc_maximum_msat: Some(max), .. }, ..} =>
10941130
EffectiveCapacity::HintMaxHTLC { amount_msat: *max },
1095-
CandidateRouteHop::PrivateHop { hint: RouteHintHop { htlc_maximum_msat: None, .. }} =>
1131+
CandidateRouteHop::PrivateHop { hint: RouteHintHop { htlc_maximum_msat: None, .. }, ..} =>
10961132
EffectiveCapacity::Infinite,
10971133
CandidateRouteHop::Blinded { hint, .. } =>
10981134
EffectiveCapacity::HintMaxHTLC { amount_msat: hint.0.htlc_maximum_msat },
@@ -1115,6 +1151,26 @@ impl<'a> CandidateRouteHop<'a> {
11151151
_ => None,
11161152
}
11171153
}
1154+
/// Returns the source node id of this hop.
1155+
pub fn source(&self) -> NodeId {
1156+
match self {
1157+
CandidateRouteHop::FirstHop { node_id, .. } => *node_id,
1158+
CandidateRouteHop::PublicHop { info, .. } => info.channel.node_one.into(),
1159+
CandidateRouteHop::PrivateHop { hint, .. } => hint.src_node_id.into(),
1160+
CandidateRouteHop::Blinded { hint, .. } => hint.1.introduction_node_id.into(),
1161+
CandidateRouteHop::OneHopBlinded { hint, .. } => hint.1.introduction_node_id.into()
1162+
}
1163+
}
1164+
/// Returns the target node id of this hop, if known.
1165+
pub fn target(&self) -> Option<NodeId> {
1166+
match self {
1167+
CandidateRouteHop::FirstHop { details, .. } => Some(details.counterparty.node_id.into()),
1168+
CandidateRouteHop::PublicHop { info, .. } => Some(info.channel.node_two.into()),
1169+
CandidateRouteHop::PrivateHop { target_node_id, .. } => Some(*target_node_id),
1170+
CandidateRouteHop::Blinded { hint, .. } => Some(hint.1.blinding_point.into()),
1171+
CandidateRouteHop::OneHopBlinded { hint, .. } => Some(hint.1.blinding_point.into())
1172+
}
1173+
}
11181174
}
11191175

11201176
#[derive(Clone, Copy, Eq, Hash, Ord, PartialOrd, PartialEq)]
@@ -1158,7 +1214,7 @@ fn iter_equal<I1: Iterator, I2: Iterator>(mut iter_a: I1, mut iter_b: I2)
11581214
/// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
11591215
/// These fee values are useful to choose hops as we traverse the graph "payee-to-payer".
11601216
#[derive(Clone)]
1161-
struct PathBuildingHop<'a> {
1217+
pub struct PathBuildingHop<'a> {
11621218
// Note that this should be dropped in favor of loading it from CandidateRouteHop, but doing so
11631219
// is a larger refactor and will require careful performance analysis.
11641220
node_id: NodeId,
@@ -2022,7 +2078,7 @@ where L::Target: Logger {
20222078
if !skip_node {
20232079
if let Some(first_channels) = first_hop_targets.get(&$node_id) {
20242080
for details in first_channels {
2025-
let candidate = CandidateRouteHop::FirstHop { details };
2081+
let candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id };
20262082
add_entry!(candidate, our_node_id, $node_id, $fee_to_target_msat,
20272083
$next_hops_value_contribution,
20282084
$next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
@@ -2046,6 +2102,8 @@ where L::Target: Logger {
20462102
let candidate = CandidateRouteHop::PublicHop {
20472103
info: directed_channel,
20482104
short_channel_id: *chan_id,
2105+
source_node_id: *source,
2106+
target_node_id: $node_id,
20492107
};
20502108
add_entry!(candidate, *source, $node_id,
20512109
$fee_to_target_msat,
@@ -2077,7 +2135,7 @@ where L::Target: Logger {
20772135
// place where it could be added.
20782136
payee_node_id_opt.map(|payee| first_hop_targets.get(&payee).map(|first_channels| {
20792137
for details in first_channels {
2080-
let candidate = CandidateRouteHop::FirstHop { details };
2138+
let candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id };
20812139
let added = add_entry!(candidate, our_node_id, payee, 0, path_value_msat,
20822140
0, 0u64, 0, 0).is_some();
20832141
log_trace!(logger, "{} direct route to payee via {}",
@@ -2124,7 +2182,7 @@ where L::Target: Logger {
21242182
sort_first_hop_channels(first_channels, &used_liquidities, recommended_value_msat,
21252183
our_node_pubkey);
21262184
for details in first_channels {
2127-
let first_hop_candidate = CandidateRouteHop::FirstHop { details };
2185+
let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id};
21282186
let blinded_path_fee = match compute_fees(path_contribution_msat, candidate.fees()) {
21292187
Some(fee) => fee,
21302188
None => continue
@@ -2180,8 +2238,10 @@ where L::Target: Logger {
21802238
.map(|(info, _)| CandidateRouteHop::PublicHop {
21812239
info,
21822240
short_channel_id: hop.short_channel_id,
2241+
source_node_id: source,
2242+
target_node_id: target,
21832243
})
2184-
.unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop });
2244+
.unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop, target_node_id: target });
21852245

21862246
if let Some(hop_used_msat) = add_entry!(candidate, source, target,
21872247
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
@@ -2221,8 +2281,8 @@ where L::Target: Logger {
22212281
sort_first_hop_channels(first_channels, &used_liquidities,
22222282
recommended_value_msat, our_node_pubkey);
22232283
for details in first_channels {
2224-
let first_hop_candidate = CandidateRouteHop::FirstHop { details };
2225-
add_entry!(first_hop_candidate, our_node_id, target,
2284+
let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id};
2285+
add_entry!(first_hop_candidate, our_node_id, NodeId::from_pubkey(&prev_hop_id),
22262286
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
22272287
aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat,
22282288
aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length);
@@ -2266,7 +2326,7 @@ where L::Target: Logger {
22662326
sort_first_hop_channels(first_channels, &used_liquidities,
22672327
recommended_value_msat, our_node_pubkey);
22682328
for details in first_channels {
2269-
let first_hop_candidate = CandidateRouteHop::FirstHop { details };
2329+
let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id};
22702330
add_entry!(first_hop_candidate, our_node_id,
22712331
NodeId::from_pubkey(&hop.src_node_id),
22722332
aggregate_next_hops_fee_msat,
@@ -2577,7 +2637,7 @@ where L::Target: Logger {
25772637
let maybe_announced_channel = if let CandidateRouteHop::PublicHop { .. } = hop.candidate {
25782638
// If we sourced the hop from the graph we're sure the target node is announced.
25792639
true
2580-
} else if let CandidateRouteHop::FirstHop { details } = hop.candidate {
2640+
} else if let CandidateRouteHop::FirstHop { details, .. } = hop.candidate {
25812641
// If this is a first hop we also know if it's announced.
25822642
details.is_public
25832643
} else {

0 commit comments

Comments
 (0)