@@ -993,6 +993,17 @@ impl<'a> CandidateRouteHop<'a> {
993
993
EffectiveCapacity :: Infinite ,
994
994
}
995
995
}
996
+ fn id ( & self , channel_direction : bool /* src_node_id < target_node_id */ ) -> CandidateHopId {
997
+ CandidateHopId :: Clear ( ( self . short_channel_id ( ) , channel_direction) )
998
+ }
999
+ }
1000
+
1001
+ #[ derive( Eq , Hash , PartialEq ) ]
1002
+ enum CandidateHopId {
1003
+ /// Contains (scid, src_node_id < target_node_id)
1004
+ Clear ( ( u64 , bool ) ) ,
1005
+ /// Index of the blinded route hint in [`Payee::Blinded::route_hints`].
1006
+ Blinded ( usize ) ,
996
1007
}
997
1008
998
1009
#[ inline]
@@ -1236,7 +1247,7 @@ impl fmt::Display for LoggedPayeePubkey {
1236
1247
1237
1248
#[ inline]
1238
1249
fn sort_first_hop_channels (
1239
- channels : & mut Vec < & ChannelDetails > , used_channel_liquidities : & HashMap < ( u64 , bool ) , u64 > ,
1250
+ channels : & mut Vec < & ChannelDetails > , used_liquidities : & HashMap < CandidateHopId , u64 > ,
1240
1251
recommended_value_msat : u64 , our_node_pubkey : & PublicKey
1241
1252
) {
1242
1253
// Sort the first_hops channels to the same node(s) in priority order of which channel we'd
@@ -1254,11 +1265,11 @@ fn sort_first_hop_channels(
1254
1265
// Available outbound balances factor in liquidity already reserved for previously found paths.
1255
1266
channels. sort_unstable_by ( |chan_a, chan_b| {
1256
1267
let chan_a_outbound_limit_msat = chan_a. next_outbound_htlc_limit_msat
1257
- . saturating_sub ( * used_channel_liquidities . get ( & ( chan_a. get_outbound_payment_scid ( ) . unwrap ( ) ,
1258
- our_node_pubkey < & chan_a. counterparty . node_id ) ) . unwrap_or ( & 0 ) ) ;
1268
+ . saturating_sub ( * used_liquidities . get ( & CandidateHopId :: Clear ( ( chan_a. get_outbound_payment_scid ( ) . unwrap ( ) ,
1269
+ our_node_pubkey < & chan_a. counterparty . node_id ) ) ) . unwrap_or ( & 0 ) ) ;
1259
1270
let chan_b_outbound_limit_msat = chan_b. next_outbound_htlc_limit_msat
1260
- . saturating_sub ( * used_channel_liquidities . get ( & ( chan_b. get_outbound_payment_scid ( ) . unwrap ( ) ,
1261
- our_node_pubkey < & chan_b. counterparty . node_id ) ) . unwrap_or ( & 0 ) ) ;
1271
+ . saturating_sub ( * used_liquidities . get ( & CandidateHopId :: Clear ( ( chan_b. get_outbound_payment_scid ( ) . unwrap ( ) ,
1272
+ our_node_pubkey < & chan_b. counterparty . node_id ) ) ) . unwrap_or ( & 0 ) ) ;
1262
1273
if chan_b_outbound_limit_msat < recommended_value_msat || chan_a_outbound_limit_msat < recommended_value_msat {
1263
1274
// Sort in descending order
1264
1275
chan_b_outbound_limit_msat. cmp ( & chan_a_outbound_limit_msat)
@@ -1502,19 +1513,20 @@ where L::Target: Logger {
1502
1513
// drop the requirement by setting this to 0.
1503
1514
let mut channel_saturation_pow_half = payment_params. max_channel_saturation_power_of_half ;
1504
1515
1505
- // Keep track of how much liquidity has been used in selected channels. Used to determine
1506
- // if the channel can be used by additional MPP paths or to inform path finding decisions. It is
1507
- // aware of direction *only* to ensure that the correct htlc_maximum_msat value is used. Hence,
1508
- // liquidity used in one direction will not offset any used in the opposite direction.
1509
- let mut used_channel_liquidities: HashMap < ( u64 , bool ) , u64 > =
1516
+ // Keep track of how much liquidity has been used in selected channels or blinded paths. Used to
1517
+ // determine if the channel can be used by additional MPP paths or to inform path finding
1518
+ // decisions. It is aware of direction *only* to ensure that the correct htlc_maximum_msat value
1519
+ // is used. Hence, liquidity used in one direction will not offset any used in the opposite
1520
+ // direction.
1521
+ let mut used_liquidities: HashMap < CandidateHopId , u64 > =
1510
1522
HashMap :: with_capacity ( network_nodes. len ( ) ) ;
1511
1523
1512
1524
// Keeping track of how much value we already collected across other paths. Helps to decide
1513
1525
// when we want to stop looking for new paths.
1514
1526
let mut already_collected_value_msat = 0 ;
1515
1527
1516
1528
for ( _, channels) in first_hop_targets. iter_mut ( ) {
1517
- sort_first_hop_channels ( channels, & used_channel_liquidities , recommended_value_msat,
1529
+ sort_first_hop_channels ( channels, & used_liquidities , recommended_value_msat,
1518
1530
our_node_pubkey) ;
1519
1531
}
1520
1532
@@ -1549,8 +1561,8 @@ where L::Target: Logger {
1549
1561
// if the amount being transferred over this path is lower.
1550
1562
// We do this for now, but this is a subject for removal.
1551
1563
if let Some ( mut available_value_contribution_msat) = htlc_maximum_msat. checked_sub( $next_hops_fee_msat) {
1552
- let used_liquidity_msat = used_channel_liquidities
1553
- . get( & ( short_channel_id , $src_node_id < $dest_node_id) )
1564
+ let used_liquidity_msat = used_liquidities
1565
+ . get( & $candidate . id ( $src_node_id < $dest_node_id) )
1554
1566
. map_or( 0 , |used_liquidity_msat| {
1555
1567
available_value_contribution_msat = available_value_contribution_msat
1556
1568
. saturating_sub( * used_liquidity_msat) ;
@@ -1821,7 +1833,7 @@ where L::Target: Logger {
1821
1833
1822
1834
// TODO: diversify by nodes (so that all paths aren't doomed if one node is offline).
1823
1835
' paths_collection: loop {
1824
- // For every new path, start from scratch, except for used_channel_liquidities , which
1836
+ // For every new path, start from scratch, except for used_liquidities , which
1825
1837
// helps to avoid reusing previously selected paths in future iterations.
1826
1838
targets. clear ( ) ;
1827
1839
dist. clear ( ) ;
@@ -1907,8 +1919,9 @@ where L::Target: Logger {
1907
1919
hop_used = false ;
1908
1920
}
1909
1921
1910
- let used_liquidity_msat = used_channel_liquidities
1911
- . get ( & ( hop. short_channel_id , source < target) ) . copied ( ) . unwrap_or ( 0 ) ;
1922
+ let used_liquidity_msat = used_liquidities
1923
+ . get ( & candidate. id ( source < target) ) . copied ( )
1924
+ . unwrap_or ( 0 ) ;
1912
1925
let channel_usage = ChannelUsage {
1913
1926
amount_msat : final_value_msat + aggregate_next_hops_fee_msat,
1914
1927
inflight_htlc_msat : used_liquidity_msat,
@@ -1928,7 +1941,7 @@ where L::Target: Logger {
1928
1941
1929
1942
// Searching for a direct channel between last checked hop and first_hop_targets
1930
1943
if let Some ( first_channels) = first_hop_targets. get_mut ( & NodeId :: from_pubkey ( & prev_hop_id) ) {
1931
- sort_first_hop_channels ( first_channels, & used_channel_liquidities ,
1944
+ sort_first_hop_channels ( first_channels, & used_liquidities ,
1932
1945
recommended_value_msat, our_node_pubkey) ;
1933
1946
for details in first_channels {
1934
1947
let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
@@ -1969,7 +1982,7 @@ where L::Target: Logger {
1969
1982
// always assumes that the third argument is a node to which we have a
1970
1983
// path.
1971
1984
if let Some ( first_channels) = first_hop_targets. get_mut ( & NodeId :: from_pubkey ( & hop. src_node_id ) ) {
1972
- sort_first_hop_channels ( first_channels, & used_channel_liquidities ,
1985
+ sort_first_hop_channels ( first_channels, & used_liquidities ,
1973
1986
recommended_value_msat, our_node_pubkey) ;
1974
1987
for details in first_channels {
1975
1988
let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
@@ -2087,8 +2100,8 @@ where L::Target: Logger {
2087
2100
. chain ( payment_path. hops . iter ( ) . map ( |( hop, _) | & hop. node_id ) ) ;
2088
2101
for ( prev_hop, ( hop, _) ) in prev_hop_iter. zip ( payment_path. hops . iter ( ) ) {
2089
2102
let spent_on_hop_msat = value_contribution_msat + hop. next_hops_fee_msat ;
2090
- let used_liquidity_msat = used_channel_liquidities
2091
- . entry ( ( hop. candidate . short_channel_id ( ) , * prev_hop < hop. node_id ) )
2103
+ let used_liquidity_msat = used_liquidities
2104
+ . entry ( hop. candidate . id ( * prev_hop < hop. node_id ) )
2092
2105
. and_modify ( |used_liquidity_msat| * used_liquidity_msat += spent_on_hop_msat)
2093
2106
. or_insert ( spent_on_hop_msat) ;
2094
2107
let hop_capacity = hop. candidate . effective_capacity ( ) ;
@@ -2107,8 +2120,8 @@ where L::Target: Logger {
2107
2120
let victim_scid = payment_path. hops [ ( payment_path. hops . len ( ) ) / 2 ] . 0 . candidate . short_channel_id ( ) ;
2108
2121
let exhausted = u64:: max_value ( ) ;
2109
2122
log_trace ! ( logger, "Disabling channel {} for future path building iterations to avoid duplicates." , victim_scid) ;
2110
- * used_channel_liquidities . entry ( ( victim_scid, false ) ) . or_default ( ) = exhausted;
2111
- * used_channel_liquidities . entry ( ( victim_scid, true ) ) . or_default ( ) = exhausted;
2123
+ * used_liquidities . entry ( CandidateHopId :: Clear ( ( victim_scid, false ) ) ) . or_default ( ) = exhausted;
2124
+ * used_liquidities . entry ( CandidateHopId :: Clear ( ( victim_scid, true ) ) ) . or_default ( ) = exhausted;
2112
2125
}
2113
2126
2114
2127
// Track the total amount all our collected paths allow to send so that we know
0 commit comments