@@ -968,42 +968,78 @@ impl cmp::PartialOrd for RouteGraphNode {
968
968
///
969
969
/// Used to construct a [`PathBuildingHop`] and to estimate [`EffectiveCapacity`].
970
970
#[ derive( Clone , Debug ) ]
971
- enum CandidateRouteHop < ' a > {
971
+ pub enum CandidateRouteHop < ' a > {
972
972
/// A hop from the payer, where the outbound liquidity is known.
973
973
FirstHop {
974
+ /// The channel details of the first hop.
975
+ /// `get_outbound_payment_scid` is assumed to always return Some(scid) - this assumption is checked in
976
+ /// `find_route` method.
974
977
details : & ' a ChannelDetails ,
978
+ /// The node id of the payer.
979
+ /// Can be accessed via `source` method.
980
+ node_id : NodeId
975
981
} ,
976
982
/// A hop found in the [`ReadOnlyNetworkGraph`], where the channel capacity may be unknown.
977
983
PublicHop {
984
+ /// The channel info of the hop.
978
985
info : DirectedChannelInfo < ' a > ,
986
+ /// The short_channel_id of the channel.
979
987
short_channel_id : u64 ,
988
+ /// The node id of the current hop in route.
989
+ source_node_id : NodeId ,
990
+ /// The node id of next hop in route.
991
+ target_node_id : NodeId ,
980
992
} ,
981
993
/// A hop to the payee found in the BOLT 11 payment invoice, though not necessarily a direct
982
994
/// channel.
983
995
PrivateHop {
996
+ /// Hint provides information about a private hop, needed while routing through a private
997
+ /// channel.
984
998
hint : & ' a RouteHintHop ,
999
+ /// The node id of the next hop in route.
1000
+ target_node_id : NodeId
985
1001
} ,
986
1002
/// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
987
1003
Blinded {
1004
+ /// Hint provides information about a blinded hop, needed while routing through a blinded
1005
+ /// channel.
1006
+ /// `BlindedPayInfo` provides information needed about the
1007
+ /// payment while routing through a blinded
1008
+ /// path.
1009
+ /// `BlindedPath` is the blinded path to the destination.
988
1010
hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
1011
+ /// The index of the hint in the original list of blinded hints.
1012
+ /// Provided to uniquely identify a hop as we are
1013
+ /// route building.
989
1014
hint_idx : usize ,
990
1015
} ,
991
1016
/// Similar to [`Self::Blinded`], but the path here has 1 blinded hop. `BlindedPayInfo` provided
992
1017
/// for 1-hop blinded paths is ignored because it is meant to apply to the hops *between* the
993
1018
/// introduction node and the destination. Useful for tracking that we need to include a blinded
994
1019
/// path at the end of our [`Route`].
995
1020
OneHopBlinded {
1021
+ /// Hint provides information about a single blinded hop, needed while routing through a blinded
1022
+ /// channel.
1023
+ /// `BlindedPayInfo` is ignored here.
1024
+ /// `BlindedPath` is the blinded path to the destination.
996
1025
hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
1026
+ /// The index of the hint in the original list of blinded hints.
1027
+ /// Provided to uniquely identify a hop as we are
1028
+ /// route building.
997
1029
hint_idx : usize ,
998
1030
} ,
999
1031
}
1000
1032
1001
1033
impl < ' a > CandidateRouteHop < ' a > {
1002
- fn short_channel_id ( & self ) -> Option < u64 > {
1034
+ /// Returns short_channel_id if known.
1035
+ /// For `FirstHop` we assume `get_outbound_payment_scid` is always set, this assumption is checked in
1036
+ /// `find_route` method.
1037
+ /// For `Blinded` and `OneHopBlinded` we return None because we don't know the channel id.
1038
+ pub fn short_channel_id ( & self ) -> Option < u64 > {
1003
1039
match self {
1004
- CandidateRouteHop :: FirstHop { details } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
1040
+ CandidateRouteHop :: FirstHop { details, .. } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
1005
1041
CandidateRouteHop :: PublicHop { short_channel_id, .. } => Some ( * short_channel_id) ,
1006
- CandidateRouteHop :: PrivateHop { hint } => Some ( hint. short_channel_id ) ,
1042
+ CandidateRouteHop :: PrivateHop { hint, .. } => Some ( hint. short_channel_id ) ,
1007
1043
CandidateRouteHop :: Blinded { .. } => None ,
1008
1044
CandidateRouteHop :: OneHopBlinded { .. } => None ,
1009
1045
}
@@ -1012,7 +1048,7 @@ impl<'a> CandidateRouteHop<'a> {
1012
1048
// NOTE: This may alloc memory so avoid calling it in a hot code path.
1013
1049
fn features ( & self ) -> ChannelFeatures {
1014
1050
match self {
1015
- CandidateRouteHop :: FirstHop { details } => details. counterparty . features . to_context ( ) ,
1051
+ CandidateRouteHop :: FirstHop { details, .. } => details. counterparty . features . to_context ( ) ,
1016
1052
CandidateRouteHop :: PublicHop { info, .. } => info. channel ( ) . features . clone ( ) ,
1017
1053
CandidateRouteHop :: PrivateHop { .. } => ChannelFeatures :: empty ( ) ,
1018
1054
CandidateRouteHop :: Blinded { .. } => ChannelFeatures :: empty ( ) ,
@@ -1024,17 +1060,17 @@ impl<'a> CandidateRouteHop<'a> {
1024
1060
match self {
1025
1061
CandidateRouteHop :: FirstHop { .. } => 0 ,
1026
1062
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . cltv_expiry_delta as u32 ,
1027
- CandidateRouteHop :: PrivateHop { hint } => hint. cltv_expiry_delta as u32 ,
1063
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. cltv_expiry_delta as u32 ,
1028
1064
CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . cltv_expiry_delta as u32 ,
1029
1065
CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
1030
1066
}
1031
1067
}
1032
1068
1033
1069
fn htlc_minimum_msat ( & self ) -> u64 {
1034
1070
match self {
1035
- CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_minimum_msat ,
1071
+ CandidateRouteHop :: FirstHop { details, .. } => details. next_outbound_htlc_minimum_msat ,
1036
1072
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . htlc_minimum_msat ,
1037
- CandidateRouteHop :: PrivateHop { hint } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
1073
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
1038
1074
CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . htlc_minimum_msat ,
1039
1075
CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
1040
1076
}
@@ -1046,7 +1082,7 @@ impl<'a> CandidateRouteHop<'a> {
1046
1082
base_msat : 0 , proportional_millionths : 0 ,
1047
1083
} ,
1048
1084
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . fees ,
1049
- CandidateRouteHop :: PrivateHop { hint } => hint. fees ,
1085
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. fees ,
1050
1086
CandidateRouteHop :: Blinded { hint, .. } => {
1051
1087
RoutingFees {
1052
1088
base_msat : hint. 0 . fee_base_msat ,
@@ -1060,13 +1096,13 @@ impl<'a> CandidateRouteHop<'a> {
1060
1096
1061
1097
fn effective_capacity ( & self ) -> EffectiveCapacity {
1062
1098
match self {
1063
- CandidateRouteHop :: FirstHop { details } => EffectiveCapacity :: ExactLiquidity {
1099
+ CandidateRouteHop :: FirstHop { details, .. } => EffectiveCapacity :: ExactLiquidity {
1064
1100
liquidity_msat : details. next_outbound_htlc_limit_msat ,
1065
1101
} ,
1066
1102
CandidateRouteHop :: PublicHop { info, .. } => info. effective_capacity ( ) ,
1067
- CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : Some ( max) , .. } } =>
1103
+ CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : Some ( max) , .. } , .. } =>
1068
1104
EffectiveCapacity :: HintMaxHTLC { amount_msat : * max } ,
1069
- CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } } =>
1105
+ CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } , .. } =>
1070
1106
EffectiveCapacity :: Infinite ,
1071
1107
CandidateRouteHop :: Blinded { hint, .. } =>
1072
1108
EffectiveCapacity :: HintMaxHTLC { amount_msat : hint. 0 . htlc_maximum_msat } ,
@@ -1089,6 +1125,26 @@ impl<'a> CandidateRouteHop<'a> {
1089
1125
_ => None ,
1090
1126
}
1091
1127
}
1128
+ /// Returns the source node id of this hop.
1129
+ pub fn source ( & self ) -> NodeId {
1130
+ match self {
1131
+ CandidateRouteHop :: FirstHop { node_id, .. } => * node_id,
1132
+ CandidateRouteHop :: PublicHop { info, .. } => info. channel . node_one . into ( ) ,
1133
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. src_node_id . into ( ) ,
1134
+ CandidateRouteHop :: Blinded { hint, .. } => hint. 1 . introduction_node_id . into ( ) ,
1135
+ CandidateRouteHop :: OneHopBlinded { hint, .. } => hint. 1 . introduction_node_id . into ( )
1136
+ }
1137
+ }
1138
+ /// Returns the target node id of this hop, if known.
1139
+ pub fn target ( & self ) -> Option < NodeId > {
1140
+ match self {
1141
+ CandidateRouteHop :: FirstHop { details, .. } => Some ( details. counterparty . node_id . into ( ) ) ,
1142
+ CandidateRouteHop :: PublicHop { info, .. } => Some ( info. channel . node_two . into ( ) ) ,
1143
+ CandidateRouteHop :: PrivateHop { target_node_id, .. } => Some ( * target_node_id) ,
1144
+ CandidateRouteHop :: Blinded { hint, .. } => Some ( hint. 1 . blinding_point . into ( ) ) ,
1145
+ CandidateRouteHop :: OneHopBlinded { hint, .. } => Some ( hint. 1 . blinding_point . into ( ) )
1146
+ }
1147
+ }
1092
1148
}
1093
1149
1094
1150
#[ derive( Clone , Copy , Eq , Hash , Ord , PartialOrd , PartialEq ) ]
@@ -1132,7 +1188,7 @@ fn iter_equal<I1: Iterator, I2: Iterator>(mut iter_a: I1, mut iter_b: I2)
1132
1188
/// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
1133
1189
/// These fee values are useful to choose hops as we traverse the graph "payee-to-payer".
1134
1190
#[ derive( Clone ) ]
1135
- struct PathBuildingHop < ' a > {
1191
+ pub struct PathBuildingHop < ' a > {
1136
1192
// Note that this should be dropped in favor of loading it from CandidateRouteHop, but doing so
1137
1193
// is a larger refactor and will require careful performance analysis.
1138
1194
node_id : NodeId ,
@@ -1950,7 +2006,7 @@ where L::Target: Logger {
1950
2006
if !skip_node {
1951
2007
if let Some ( first_channels) = first_hop_targets. get( & $node_id) {
1952
2008
for details in first_channels {
1953
- let candidate = CandidateRouteHop :: FirstHop { details } ;
2009
+ let candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
1954
2010
add_entry!( candidate, our_node_id, $node_id, $fee_to_target_msat,
1955
2011
$next_hops_value_contribution,
1956
2012
$next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
@@ -2005,7 +2061,7 @@ where L::Target: Logger {
2005
2061
// place where it could be added.
2006
2062
payee_node_id_opt. map ( |payee| first_hop_targets. get ( & payee) . map ( |first_channels| {
2007
2063
for details in first_channels {
2008
- let candidate = CandidateRouteHop :: FirstHop { details } ;
2064
+ let candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2009
2065
let added = add_entry ! ( candidate, our_node_id, payee, 0 , path_value_msat,
2010
2066
0 , 0u64 , 0 , 0 ) . is_some ( ) ;
2011
2067
log_trace ! ( logger, "{} direct route to payee via {}" ,
@@ -2052,7 +2108,7 @@ where L::Target: Logger {
2052
2108
sort_first_hop_channels ( first_channels, & used_liquidities, recommended_value_msat,
2053
2109
our_node_pubkey) ;
2054
2110
for details in first_channels {
2055
- let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
2111
+ let first_hop_candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2056
2112
let blinded_path_fee = match compute_fees ( path_contribution_msat, candidate. fees ( ) ) {
2057
2113
Some ( fee) => fee,
2058
2114
None => continue
@@ -2098,7 +2154,7 @@ where L::Target: Logger {
2098
2154
info,
2099
2155
short_channel_id : hop. short_channel_id ,
2100
2156
} )
2101
- . unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop } ) ;
2157
+ . unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop, target_node_id : target } ) ;
2102
2158
2103
2159
if let Some ( hop_used_msat) = add_entry ! ( candidate, source, target,
2104
2160
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
@@ -2138,7 +2194,7 @@ where L::Target: Logger {
2138
2194
sort_first_hop_channels ( first_channels, & used_liquidities,
2139
2195
recommended_value_msat, our_node_pubkey) ;
2140
2196
for details in first_channels {
2141
- let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
2197
+ let first_hop_candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2142
2198
add_entry ! ( first_hop_candidate, our_node_id, NodeId :: from_pubkey( & prev_hop_id) ,
2143
2199
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
2144
2200
aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat,
@@ -2179,7 +2235,7 @@ where L::Target: Logger {
2179
2235
sort_first_hop_channels ( first_channels, & used_liquidities,
2180
2236
recommended_value_msat, our_node_pubkey) ;
2181
2237
for details in first_channels {
2182
- let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
2238
+ let first_hop_candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2183
2239
add_entry ! ( first_hop_candidate, our_node_id,
2184
2240
NodeId :: from_pubkey( & hop. src_node_id) ,
2185
2241
aggregate_next_hops_fee_msat,
0 commit comments