@@ -994,42 +994,78 @@ impl cmp::PartialOrd for RouteGraphNode {
994
994
///
995
995
/// Used to construct a [`PathBuildingHop`] and to estimate [`EffectiveCapacity`].
996
996
#[ derive( Clone , Debug ) ]
997
- enum CandidateRouteHop < ' a > {
997
+ pub enum CandidateRouteHop < ' a > {
998
998
/// A hop from the payer, where the outbound liquidity is known.
999
999
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.
1000
1003
details : & ' a ChannelDetails ,
1004
+ /// The node id of the payer.
1005
+ /// Can be accessed via `source` method.
1006
+ node_id : NodeId
1001
1007
} ,
1002
1008
/// A hop found in the [`ReadOnlyNetworkGraph`], where the channel capacity may be unknown.
1003
1009
PublicHop {
1010
+ /// The channel info of the hop.
1004
1011
info : DirectedChannelInfo < ' a > ,
1012
+ /// The short_channel_id of the channel.
1005
1013
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 ,
1006
1018
} ,
1007
1019
/// A hop to the payee found in the BOLT 11 payment invoice, though not necessarily a direct
1008
1020
/// channel.
1009
1021
PrivateHop {
1022
+ /// Hint provides information about a private hop, needed while routing through a private
1023
+ /// channel.
1010
1024
hint : & ' a RouteHintHop ,
1025
+ /// The node id of the next hop in route.
1026
+ target_node_id : NodeId
1011
1027
} ,
1012
1028
/// The payee's identity is concealed behind blinded paths provided in a BOLT 12 invoice.
1013
1029
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.
1014
1036
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.
1015
1040
hint_idx : usize ,
1016
1041
} ,
1017
1042
/// Similar to [`Self::Blinded`], but the path here has 1 blinded hop. `BlindedPayInfo` provided
1018
1043
/// for 1-hop blinded paths is ignored because it is meant to apply to the hops *between* the
1019
1044
/// introduction node and the destination. Useful for tracking that we need to include a blinded
1020
1045
/// path at the end of our [`Route`].
1021
1046
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.
1022
1051
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.
1023
1055
hint_idx : usize ,
1024
1056
} ,
1025
1057
}
1026
1058
1027
1059
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 > {
1029
1065
match self {
1030
- CandidateRouteHop :: FirstHop { details } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
1066
+ CandidateRouteHop :: FirstHop { details, .. } => Some ( details. get_outbound_payment_scid ( ) . unwrap ( ) ) ,
1031
1067
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 ) ,
1033
1069
CandidateRouteHop :: Blinded { .. } => None ,
1034
1070
CandidateRouteHop :: OneHopBlinded { .. } => None ,
1035
1071
}
@@ -1038,7 +1074,7 @@ impl<'a> CandidateRouteHop<'a> {
1038
1074
// NOTE: This may alloc memory so avoid calling it in a hot code path.
1039
1075
fn features ( & self ) -> ChannelFeatures {
1040
1076
match self {
1041
- CandidateRouteHop :: FirstHop { details } => details. counterparty . features . to_context ( ) ,
1077
+ CandidateRouteHop :: FirstHop { details, .. } => details. counterparty . features . to_context ( ) ,
1042
1078
CandidateRouteHop :: PublicHop { info, .. } => info. channel ( ) . features . clone ( ) ,
1043
1079
CandidateRouteHop :: PrivateHop { .. } => ChannelFeatures :: empty ( ) ,
1044
1080
CandidateRouteHop :: Blinded { .. } => ChannelFeatures :: empty ( ) ,
@@ -1050,17 +1086,17 @@ impl<'a> CandidateRouteHop<'a> {
1050
1086
match self {
1051
1087
CandidateRouteHop :: FirstHop { .. } => 0 ,
1052
1088
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 ,
1054
1090
CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . cltv_expiry_delta as u32 ,
1055
1091
CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
1056
1092
}
1057
1093
}
1058
1094
1059
1095
fn htlc_minimum_msat ( & self ) -> u64 {
1060
1096
match self {
1061
- CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_minimum_msat ,
1097
+ CandidateRouteHop :: FirstHop { details, .. } => details. next_outbound_htlc_minimum_msat ,
1062
1098
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 ) ,
1064
1100
CandidateRouteHop :: Blinded { hint, .. } => hint. 0 . htlc_minimum_msat ,
1065
1101
CandidateRouteHop :: OneHopBlinded { .. } => 0 ,
1066
1102
}
@@ -1072,7 +1108,7 @@ impl<'a> CandidateRouteHop<'a> {
1072
1108
base_msat : 0 , proportional_millionths : 0 ,
1073
1109
} ,
1074
1110
CandidateRouteHop :: PublicHop { info, .. } => info. direction ( ) . fees ,
1075
- CandidateRouteHop :: PrivateHop { hint } => hint. fees ,
1111
+ CandidateRouteHop :: PrivateHop { hint, .. } => hint. fees ,
1076
1112
CandidateRouteHop :: Blinded { hint, .. } => {
1077
1113
RoutingFees {
1078
1114
base_msat : hint. 0 . fee_base_msat ,
@@ -1086,13 +1122,13 @@ impl<'a> CandidateRouteHop<'a> {
1086
1122
1087
1123
fn effective_capacity ( & self ) -> EffectiveCapacity {
1088
1124
match self {
1089
- CandidateRouteHop :: FirstHop { details } => EffectiveCapacity :: ExactLiquidity {
1125
+ CandidateRouteHop :: FirstHop { details, .. } => EffectiveCapacity :: ExactLiquidity {
1090
1126
liquidity_msat : details. next_outbound_htlc_limit_msat ,
1091
1127
} ,
1092
1128
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) , .. } , .. } =>
1094
1130
EffectiveCapacity :: HintMaxHTLC { amount_msat : * max } ,
1095
- CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } } =>
1131
+ CandidateRouteHop :: PrivateHop { hint : RouteHintHop { htlc_maximum_msat : None , .. } , .. } =>
1096
1132
EffectiveCapacity :: Infinite ,
1097
1133
CandidateRouteHop :: Blinded { hint, .. } =>
1098
1134
EffectiveCapacity :: HintMaxHTLC { amount_msat : hint. 0 . htlc_maximum_msat } ,
@@ -1115,6 +1151,26 @@ impl<'a> CandidateRouteHop<'a> {
1115
1151
_ => None ,
1116
1152
}
1117
1153
}
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
+ }
1118
1174
}
1119
1175
1120
1176
#[ 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)
1158
1214
/// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
1159
1215
/// These fee values are useful to choose hops as we traverse the graph "payee-to-payer".
1160
1216
#[ derive( Clone ) ]
1161
- struct PathBuildingHop < ' a > {
1217
+ pub struct PathBuildingHop < ' a > {
1162
1218
// Note that this should be dropped in favor of loading it from CandidateRouteHop, but doing so
1163
1219
// is a larger refactor and will require careful performance analysis.
1164
1220
node_id : NodeId ,
@@ -2022,7 +2078,7 @@ where L::Target: Logger {
2022
2078
if !skip_node {
2023
2079
if let Some ( first_channels) = first_hop_targets. get( & $node_id) {
2024
2080
for details in first_channels {
2025
- let candidate = CandidateRouteHop :: FirstHop { details } ;
2081
+ let candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2026
2082
add_entry!( candidate, our_node_id, $node_id, $fee_to_target_msat,
2027
2083
$next_hops_value_contribution,
2028
2084
$next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
@@ -2046,6 +2102,8 @@ where L::Target: Logger {
2046
2102
let candidate = CandidateRouteHop :: PublicHop {
2047
2103
info: directed_channel,
2048
2104
short_channel_id: * chan_id,
2105
+ source_node_id: * source,
2106
+ target_node_id: $node_id,
2049
2107
} ;
2050
2108
add_entry!( candidate, * source, $node_id,
2051
2109
$fee_to_target_msat,
@@ -2077,7 +2135,7 @@ where L::Target: Logger {
2077
2135
// place where it could be added.
2078
2136
payee_node_id_opt. map ( |payee| first_hop_targets. get ( & payee) . map ( |first_channels| {
2079
2137
for details in first_channels {
2080
- let candidate = CandidateRouteHop :: FirstHop { details } ;
2138
+ let candidate = CandidateRouteHop :: FirstHop { details, node_id : our_node_id } ;
2081
2139
let added = add_entry ! ( candidate, our_node_id, payee, 0 , path_value_msat,
2082
2140
0 , 0u64 , 0 , 0 ) . is_some ( ) ;
2083
2141
log_trace ! ( logger, "{} direct route to payee via {}" ,
@@ -2124,7 +2182,7 @@ where L::Target: Logger {
2124
2182
sort_first_hop_channels ( first_channels, & used_liquidities, recommended_value_msat,
2125
2183
our_node_pubkey) ;
2126
2184
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 } ;
2128
2186
let blinded_path_fee = match compute_fees ( path_contribution_msat, candidate. fees ( ) ) {
2129
2187
Some ( fee) => fee,
2130
2188
None => continue
@@ -2180,8 +2238,10 @@ where L::Target: Logger {
2180
2238
. map ( |( info, _) | CandidateRouteHop :: PublicHop {
2181
2239
info,
2182
2240
short_channel_id : hop. short_channel_id ,
2241
+ source_node_id : source,
2242
+ target_node_id : target,
2183
2243
} )
2184
- . unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop } ) ;
2244
+ . unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop, target_node_id : target } ) ;
2185
2245
2186
2246
if let Some ( hop_used_msat) = add_entry ! ( candidate, source, target,
2187
2247
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
@@ -2221,8 +2281,8 @@ where L::Target: Logger {
2221
2281
sort_first_hop_channels ( first_channels, & used_liquidities,
2222
2282
recommended_value_msat, our_node_pubkey) ;
2223
2283
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 ) ,
2226
2286
aggregate_next_hops_fee_msat, aggregate_path_contribution_msat,
2227
2287
aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat,
2228
2288
aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length) ;
@@ -2266,7 +2326,7 @@ where L::Target: Logger {
2266
2326
sort_first_hop_channels ( first_channels, & used_liquidities,
2267
2327
recommended_value_msat, our_node_pubkey) ;
2268
2328
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 } ;
2270
2330
add_entry ! ( first_hop_candidate, our_node_id,
2271
2331
NodeId :: from_pubkey( & hop. src_node_id) ,
2272
2332
aggregate_next_hops_fee_msat,
@@ -2577,7 +2637,7 @@ where L::Target: Logger {
2577
2637
let maybe_announced_channel = if let CandidateRouteHop :: PublicHop { .. } = hop. candidate {
2578
2638
// If we sourced the hop from the graph we're sure the target node is announced.
2579
2639
true
2580
- } else if let CandidateRouteHop :: FirstHop { details } = hop. candidate {
2640
+ } else if let CandidateRouteHop :: FirstHop { details, .. } = hop. candidate {
2581
2641
// If this is a first hop we also know if it's announced.
2582
2642
details. is_public
2583
2643
} else {
0 commit comments