@@ -978,42 +978,78 @@ impl cmp::PartialOrd for RouteGraphNode {
978
978
///
979
979
/// Used to construct a [`PathBuildingHop`] and to estimate [`EffectiveCapacity`].
980
980
#[ derive( Clone , Debug ) ]
981
- enum CandidateRouteHop < ' a > {
981
+ pub enum CandidateRouteHop < ' a > {
982
982
/// A hop from the payer, where the outbound liquidity is known.
983
983
FirstHop {
984
+ /// The channel details of the first hop.
985
+ /// `get_outbound_payment_scid` is assumed to always return Some(scid) - this assumption is checked in
986
+ /// `find_route` method.
984
987
details : & ' a ChannelDetails ,
988
+ /// The node id of the payer.
989
+ /// Can be accessed via `source` method.
990
+ node_id : NodeId
985
991
} ,
986
992
/// A hop found in the [`ReadOnlyNetworkGraph`], where the channel capacity may be unknown.
987
993
PublicHop {
994
+ /// The channel info of the hop.
988
995
info : DirectedChannelInfo < ' a > ,
996
+ /// The short_channel_id of the channel.
989
997
short_channel_id : u64 ,
998
+ /// The node id of the current hop in route.
999
+ source_node_id : NodeId ,
1000
+ /// The node id of next hop in route.
1001
+ target_node_id : NodeId ,
990
1002
} ,
991
1003
/// A hop to the payee found in the BOLT 11 payment invoice, though not necessarily a direct
992
1004
/// channel.
993
1005
PrivateHop {
1006
+ /// Hint provides information about a private hop, needed while routing through a private
1007
+ /// channel.
994
1008
hint : & ' a RouteHintHop ,
1009
+ /// The node id of the next hop in route.
1010
+ target_node_id : NodeId
995
1011
} ,
996
1012
/// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
997
1013
Blinded {
1014
+ /// Hint provides information about a blinded hop, needed while routing through a blinded
1015
+ /// channel.
1016
+ /// `BlindedPayInfo` provides information needed about the
1017
+ /// payment while routing through a blinded
1018
+ /// path.
1019
+ /// `BlindedPath` is the blinded path to the destination.
998
1020
hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
1021
+ /// The index of the hint in the original list of blinded hints.
1022
+ /// Provided to uniquely identify a hop as we are
1023
+ /// route building.
999
1024
hint_idx : usize ,
1000
1025
} ,
1001
1026
/// Similar to [`Self::Blinded`], but the path here has 1 blinded hop. `BlindedPayInfo` provided
1002
1027
/// for 1-hop blinded paths is ignored because it is meant to apply to the hops *between* the
1003
1028
/// introduction node and the destination. Useful for tracking that we need to include a blinded
1004
1029
/// path at the end of our [`Route`].
1005
1030
OneHopBlinded {
1031
+ /// Hint provides information about a single blinded hop, needed while routing through a blinded
1032
+ /// channel.
1033
+ /// `BlindedPayInfo` is ignored here.
1034
+ /// `BlindedPath` is the blinded path to the destination.
1006
1035
hint : & ' a ( BlindedPayInfo , BlindedPath ) ,
1036
+ /// The index of the hint in the original list of blinded hints.
1037
+ /// Provided to uniquely identify a hop as we are
1038
+ /// route building.
1007
1039
hint_idx : usize ,
1008
1040
} ,
1009
1041
}
1010
1042
1011
1043
impl < ' a > CandidateRouteHop < ' a > {
1012
- fn short_channel_id ( & self ) -> Option < u64 > {
1044
+ /// Returns short_channel_id if known.
1045
+ /// For `FirstHop` we assume `get_outbound_payment_scid` is always set, this assumption is checked in
1046
+ /// `find_route` method.
1047
+ /// For `Blinded` and `OneHopBlinded` we return None because we don't know the channel id.
1048
+ pub fn short_channel_id ( & self ) -> Option < u64 > {
1013
1049
match self {
1014
- CandidateRouteHop :: FirstHop { details } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
1050
+ CandidateRouteHop :: FirstHop { details, .. } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
1015
1051
CandidateRouteHop :: PublicHop { short_channel_id, .. } => Some ( * short_channel_id) ,
1016
- CandidateRouteHop :: PrivateHop { hint } => Some ( hint. short_channel_id ) ,
1052
+ CandidateRouteHop :: PrivateHop { hint, .. } => Some ( hint. short_channel_id ) ,
1017
1053
CandidateRouteHop :: Blinded { .. } => None ,
1018
1054
CandidateRouteHop :: OneHopBlinded { .. } => None ,
1019
1055
}
@@ -1022,7 +1058,7 @@ impl<'a> CandidateRouteHop<'a> {
1022
1058
// NOTE: This may alloc memory so avoid calling it in a hot code path.
1023
1059
fn features ( & self ) -> ChannelFeatures {
1024
1060
match self {
1025
- CandidateRouteHop :: FirstHop { details } => details. counterparty . features . to_context ( ) ,
1061
+ CandidateRouteHop :: FirstHop { details, .. } => details. counterparty . features . to_context ( ) ,
1026
1062
CandidateRouteHop :: PublicHop { info, .. } => info. channel ( ) . features . clone ( ) ,
1027
1063
CandidateRouteHop :: PrivateHop { .. } => ChannelFeatures :: empty ( ) ,
1028
1064
CandidateRouteHop :: Blinded { .. } => ChannelFeatures :: empty ( ) ,
@@ -1034,17 +1070,17 @@ impl<'a> CandidateRouteHop<'a> {
1034
1070
match self {
1035
1071
CandidateRouteHop :: FirstHop { .. } => 0 ,
1036
1072
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . cltv_expiry_delta as u32 ,
1037
- CandidateRouteHop :: PrivateHop { hint } => hint. cltv_expiry_delta as u32 ,
1073
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. cltv_expiry_delta as u32 ,
1038
1074
CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . cltv_expiry_delta as u32 ,
1039
1075
CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
1040
1076
}
1041
1077
}
1042
1078
1043
1079
fn htlc_minimum_msat ( & self ) -> u64 {
1044
1080
match self {
1045
- CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_minimum_msat ,
1081
+ CandidateRouteHop :: FirstHop { details, .. } => details. next_outbound_htlc_minimum_msat ,
1046
1082
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . htlc_minimum_msat ,
1047
- CandidateRouteHop :: PrivateHop { hint } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
1083
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. htlc_minimum_msat . unwrap_or ( 0 ) ,
1048
1084
CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . htlc_minimum_msat ,
1049
1085
CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
1050
1086
}
@@ -1056,7 +1092,7 @@ impl<'a> CandidateRouteHop<'a> {
1056
1092
base_msat : 0 , proportional_millionths : 0 ,
1057
1093
} ,
1058
1094
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . fees ,
1059
- CandidateRouteHop :: PrivateHop { hint } => hint. fees ,
1095
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. fees ,
1060
1096
CandidateRouteHop :: Blinded { hint, .. } => {
1061
1097
RoutingFees {
1062
1098
base_msat : hint. 0 . fee_base_msat ,
@@ -1070,13 +1106,13 @@ impl<'a> CandidateRouteHop<'a> {
1070
1106
1071
1107
fn effective_capacity ( & self ) -> EffectiveCapacity {
1072
1108
match self {
1073
- CandidateRouteHop :: FirstHop { details } => EffectiveCapacity :: ExactLiquidity {
1109
+ CandidateRouteHop :: FirstHop { details, .. } => EffectiveCapacity :: ExactLiquidity {
1074
1110
liquidity_msat : details. next_outbound_htlc_limit_msat ,
1075
1111
} ,
1076
1112
CandidateRouteHop :: PublicHop { info, .. } => info. effective_capacity ( ) ,
1077
- CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : Some ( max) , .. } } =>
1113
+ CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : Some ( max) , .. } , .. } =>
1078
1114
EffectiveCapacity :: HintMaxHTLC { amount_msat : * max } ,
1079
- CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } } =>
1115
+ CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } , .. } =>
1080
1116
EffectiveCapacity :: Infinite ,
1081
1117
CandidateRouteHop :: Blinded { hint, .. } =>
1082
1118
EffectiveCapacity :: HintMaxHTLC { amount_msat : hint. 0 . htlc_maximum_msat } ,
@@ -1099,6 +1135,26 @@ impl<'a> CandidateRouteHop<'a> {
1099
1135
_ => None ,
1100
1136
}
1101
1137
}
1138
+ /// Returns the source node id of this hop.
1139
+ pub fn source ( & self ) -> NodeId {
1140
+ match self {
1141
+ CandidateRouteHop :: FirstHop { node_id, .. } => * node_id,
1142
+ CandidateRouteHop :: PublicHop { info, .. } => info. channel . node_one . into ( ) ,
1143
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. src_node_id . into ( ) ,
1144
+ CandidateRouteHop :: Blinded { hint, .. } => hint. 1 . introduction_node_id . into ( ) ,
1145
+ CandidateRouteHop :: OneHopBlinded { hint, .. } => hint. 1 . introduction_node_id . into ( )
1146
+ }
1147
+ }
1148
+ /// Returns the target node id of this hop, if known.
1149
+ pub fn target ( & self ) -> Option < NodeId > {
1150
+ match self {
1151
+ CandidateRouteHop :: FirstHop { details, .. } => Some ( details. counterparty . node_id . into ( ) ) ,
1152
+ CandidateRouteHop :: PublicHop { info, .. } => Some ( info. channel . node_two . into ( ) ) ,
1153
+ CandidateRouteHop :: PrivateHop { target_node_id, .. } => Some ( * target_node_id) ,
1154
+ CandidateRouteHop :: Blinded { hint, .. } => Some ( hint. 1 . blinding_point . into ( ) ) ,
1155
+ CandidateRouteHop :: OneHopBlinded { hint, .. } => Some ( hint. 1 . blinding_point . into ( ) )
1156
+ }
1157
+ }
1102
1158
}
1103
1159
1104
1160
#[ derive( Clone , Copy , Eq , Hash , Ord , PartialOrd , PartialEq ) ]
@@ -1142,7 +1198,7 @@ fn iter_equal<I1: Iterator, I2: Iterator>(mut iter_a: I1, mut iter_b: I2)
1142
1198
/// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
1143
1199
/// These fee values are useful to choose hops as we traverse the graph "payee-to-payer".
1144
1200
#[ derive( Clone ) ]
1145
- struct PathBuildingHop < ' a > {
1201
+ pub struct PathBuildingHop < ' a > {
1146
1202
// Note that this should be dropped in favor of loading it from CandidateRouteHop, but doing so
1147
1203
// is a larger refactor and will require careful performance analysis.
1148
1204
node_id : NodeId ,
@@ -1960,7 +2016,7 @@ where L::Target: Logger {
1960
2016
if !skip_node {
1961
2017
if let Some ( first_channels) = first_hop_targets. get( & $node_id) {
1962
2018
for details in first_channels {
1963
- let candidate = CandidateRouteHop :: FirstHop { details } ;
2019
+ let candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
1964
2020
add_entry!( candidate, our_node_id, $node_id, $fee_to_target_msat,
1965
2021
$next_hops_value_contribution,
1966
2022
$next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
@@ -2015,7 +2071,7 @@ where L::Target: Logger {
2015
2071
// place where it could be added.
2016
2072
payee_node_id_opt. map ( |payee| first_hop_targets. get ( & payee) . map ( |first_channels| {
2017
2073
for details in first_channels {
2018
- let candidate = CandidateRouteHop :: FirstHop { details } ;
2074
+ let candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2019
2075
let added = add_entry ! ( candidate, our_node_id, payee, 0 , path_value_msat,
2020
2076
0 , 0u64 , 0 , 0 ) . is_some ( ) ;
2021
2077
log_trace ! ( logger, "{} direct route to payee via {}" ,
@@ -2062,7 +2118,7 @@ where L::Target: Logger {
2062
2118
sort_first_hop_channels ( first_channels, & used_liquidities, recommended_value_msat,
2063
2119
our_node_pubkey) ;
2064
2120
for details in first_channels {
2065
- let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
2121
+ let first_hop_candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2066
2122
let blinded_path_fee = match compute_fees ( path_contribution_msat, candidate. fees ( ) ) {
2067
2123
Some ( fee) => fee,
2068
2124
None => continue
@@ -2108,7 +2164,7 @@ where L::Target: Logger {
2108
2164
info,
2109
2165
short_channel_id : hop. short_channel_id ,
2110
2166
} )
2111
- . unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop } ) ;
2167
+ . unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop, target_node_id : target } ) ;
2112
2168
2113
2169
if let Some ( hop_used_msat) = add_entry ! ( candidate, source, target,
2114
2170
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
@@ -2148,7 +2204,7 @@ where L::Target: Logger {
2148
2204
sort_first_hop_channels ( first_channels, & used_liquidities,
2149
2205
recommended_value_msat, our_node_pubkey) ;
2150
2206
for details in first_channels {
2151
- let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
2207
+ let first_hop_candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2152
2208
add_entry ! ( first_hop_candidate, our_node_id, NodeId :: from_pubkey( & prev_hop_id) ,
2153
2209
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
2154
2210
aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat,
@@ -2189,7 +2245,7 @@ where L::Target: Logger {
2189
2245
sort_first_hop_channels ( first_channels, & used_liquidities,
2190
2246
recommended_value_msat, our_node_pubkey) ;
2191
2247
for details in first_channels {
2192
- let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
2248
+ let first_hop_candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2193
2249
add_entry ! ( first_hop_candidate, our_node_id,
2194
2250
NodeId :: from_pubkey( & hop. src_node_id) ,
2195
2251
aggregate_next_hops_fee_msat,
0 commit comments