@@ -1004,6 +1004,17 @@ impl<'a> CandidateRouteHop<'a> {
1004
1004
EffectiveCapacity :: Infinite ,
1005
1005
}
1006
1006
}
1007
+ fn id ( & self , channel_direction : bool /* src_node_id < target_node_id */ ) -> CandidateHopId {
1008
+ CandidateHopId :: Clear ( ( self . short_channel_id ( ) , channel_direction) )
1009
+ }
1010
+ }
1011
+
1012
+ #[ derive( Eq , Hash , PartialEq ) ]
1013
+ enum CandidateHopId {
1014
+ /// Contains (scid, src_node_id < target_node_id)
1015
+ Clear ( ( u64 , bool ) ) ,
1016
+ /// Index of the blinded route hint in [`Payee::Blinded::route_hints`].
1017
+ Blinded ( usize ) ,
1007
1018
}
1008
1019
1009
1020
#[ inline]
@@ -1247,7 +1258,7 @@ impl fmt::Display for LoggedPayeePubkey {
1247
1258
1248
1259
#[ inline]
1249
1260
fn sort_first_hop_channels (
1250
- channels : & mut Vec < & ChannelDetails > , used_channel_liquidities : & HashMap < ( u64 , bool ) , u64 > ,
1261
+ channels : & mut Vec < & ChannelDetails > , used_liquidities : & HashMap < CandidateHopId , u64 > ,
1251
1262
recommended_value_msat : u64 , our_node_pubkey : & PublicKey
1252
1263
) {
1253
1264
// Sort the first_hops channels to the same node(s) in priority order of which channel we'd
@@ -1265,11 +1276,11 @@ fn sort_first_hop_channels(
1265
1276
// Available outbound balances factor in liquidity already reserved for previously found paths.
1266
1277
channels. sort_unstable_by ( |chan_a, chan_b| {
1267
1278
let chan_a_outbound_limit_msat = chan_a. next_outbound_htlc_limit_msat
1268
- . saturating_sub ( * used_channel_liquidities . get ( & ( chan_a. get_outbound_payment_scid ( ) . unwrap ( ) ,
1269
- our_node_pubkey < & chan_a. counterparty . node_id ) ) . unwrap_or ( & 0 ) ) ;
1279
+ . saturating_sub ( * used_liquidities . get ( & CandidateHopId :: Clear ( ( chan_a. get_outbound_payment_scid ( ) . unwrap ( ) ,
1280
+ our_node_pubkey < & chan_a. counterparty . node_id ) ) ) . unwrap_or ( & 0 ) ) ;
1270
1281
let chan_b_outbound_limit_msat = chan_b. next_outbound_htlc_limit_msat
1271
- . saturating_sub ( * used_channel_liquidities . get ( & ( chan_b. get_outbound_payment_scid ( ) . unwrap ( ) ,
1272
- our_node_pubkey < & chan_b. counterparty . node_id ) ) . unwrap_or ( & 0 ) ) ;
1282
+ . saturating_sub ( * used_liquidities . get ( & CandidateHopId :: Clear ( ( chan_b. get_outbound_payment_scid ( ) . unwrap ( ) ,
1283
+ our_node_pubkey < & chan_b. counterparty . node_id ) ) ) . unwrap_or ( & 0 ) ) ;
1273
1284
if chan_b_outbound_limit_msat < recommended_value_msat || chan_a_outbound_limit_msat < recommended_value_msat {
1274
1285
// Sort in descending order
1275
1286
chan_b_outbound_limit_msat. cmp ( & chan_a_outbound_limit_msat)
@@ -1513,19 +1524,20 @@ where L::Target: Logger {
1513
1524
// drop the requirement by setting this to 0.
1514
1525
let mut channel_saturation_pow_half = payment_params. max_channel_saturation_power_of_half ;
1515
1526
1516
- // Keep track of how much liquidity has been used in selected channels. Used to determine
1517
- // if the channel can be used by additional MPP paths or to inform path finding decisions. It is
1518
- // aware of direction *only* to ensure that the correct htlc_maximum_msat value is used. Hence,
1519
- // liquidity used in one direction will not offset any used in the opposite direction.
1520
- let mut used_channel_liquidities: HashMap < ( u64 , bool ) , u64 > =
1527
+ // Keep track of how much liquidity has been used in selected channels or blinded paths. Used to
1528
+ // determine if the channel can be used by additional MPP paths or to inform path finding
1529
+ // decisions. It is aware of direction *only* to ensure that the correct htlc_maximum_msat value
1530
+ // is used. Hence, liquidity used in one direction will not offset any used in the opposite
1531
+ // direction.
1532
+ let mut used_liquidities: HashMap < CandidateHopId , u64 > =
1521
1533
HashMap :: with_capacity ( network_nodes. len ( ) ) ;
1522
1534
1523
1535
// Keeping track of how much value we already collected across other paths. Helps to decide
1524
1536
// when we want to stop looking for new paths.
1525
1537
let mut already_collected_value_msat = 0 ;
1526
1538
1527
1539
for ( _, channels) in first_hop_targets. iter_mut ( ) {
1528
- sort_first_hop_channels ( channels, & used_channel_liquidities , recommended_value_msat,
1540
+ sort_first_hop_channels ( channels, & used_liquidities , recommended_value_msat,
1529
1541
our_node_pubkey) ;
1530
1542
}
1531
1543
@@ -1560,8 +1572,8 @@ where L::Target: Logger {
1560
1572
// if the amount being transferred over this path is lower.
1561
1573
// We do this for now, but this is a subject for removal.
1562
1574
if let Some ( mut available_value_contribution_msat) = htlc_maximum_msat. checked_sub( $next_hops_fee_msat) {
1563
- let used_liquidity_msat = used_channel_liquidities
1564
- . get( & ( short_channel_id , $src_node_id < $dest_node_id) )
1575
+ let used_liquidity_msat = used_liquidities
1576
+ . get( & $candidate . id ( $src_node_id < $dest_node_id) )
1565
1577
. map_or( 0 , |used_liquidity_msat| {
1566
1578
available_value_contribution_msat = available_value_contribution_msat
1567
1579
. saturating_sub( * used_liquidity_msat) ;
@@ -1832,7 +1844,7 @@ where L::Target: Logger {
1832
1844
1833
1845
// TODO: diversify by nodes (so that all paths aren't doomed if one node is offline).
1834
1846
' paths_collection: loop {
1835
- // For every new path, start from scratch, except for used_channel_liquidities , which
1847
+ // For every new path, start from scratch, except for used_liquidities , which
1836
1848
// helps to avoid reusing previously selected paths in future iterations.
1837
1849
targets. clear ( ) ;
1838
1850
dist. clear ( ) ;
@@ -1918,8 +1930,9 @@ where L::Target: Logger {
1918
1930
hop_used = false ;
1919
1931
}
1920
1932
1921
- let used_liquidity_msat = used_channel_liquidities
1922
- . get ( & ( hop. short_channel_id , source < target) ) . copied ( ) . unwrap_or ( 0 ) ;
1933
+ let used_liquidity_msat = used_liquidities
1934
+ . get ( & candidate. id ( source < target) ) . copied ( )
1935
+ . unwrap_or ( 0 ) ;
1923
1936
let channel_usage = ChannelUsage {
1924
1937
amount_msat : final_value_msat + aggregate_next_hops_fee_msat,
1925
1938
inflight_htlc_msat : used_liquidity_msat,
@@ -1939,7 +1952,7 @@ where L::Target: Logger {
1939
1952
1940
1953
// Searching for a direct channel between last checked hop and first_hop_targets
1941
1954
if let Some ( first_channels) = first_hop_targets. get_mut ( & NodeId :: from_pubkey ( & prev_hop_id) ) {
1942
- sort_first_hop_channels ( first_channels, & used_channel_liquidities ,
1955
+ sort_first_hop_channels ( first_channels, & used_liquidities ,
1943
1956
recommended_value_msat, our_node_pubkey) ;
1944
1957
for details in first_channels {
1945
1958
let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
@@ -1980,7 +1993,7 @@ where L::Target: Logger {
1980
1993
// always assumes that the third argument is a node to which we have a
1981
1994
// path.
1982
1995
if let Some ( first_channels) = first_hop_targets. get_mut ( & NodeId :: from_pubkey ( & hop. src_node_id ) ) {
1983
- sort_first_hop_channels ( first_channels, & used_channel_liquidities ,
1996
+ sort_first_hop_channels ( first_channels, & used_liquidities ,
1984
1997
recommended_value_msat, our_node_pubkey) ;
1985
1998
for details in first_channels {
1986
1999
let first_hop_candidate = CandidateRouteHop :: FirstHop { details } ;
@@ -2098,8 +2111,8 @@ where L::Target: Logger {
2098
2111
. chain ( payment_path. hops . iter ( ) . map ( |( hop, _) | & hop. node_id ) ) ;
2099
2112
for ( prev_hop, ( hop, _) ) in prev_hop_iter. zip ( payment_path. hops . iter ( ) ) {
2100
2113
let spent_on_hop_msat = value_contribution_msat + hop. next_hops_fee_msat ;
2101
- let used_liquidity_msat = used_channel_liquidities
2102
- . entry ( ( hop. candidate . short_channel_id ( ) , * prev_hop < hop. node_id ) )
2114
+ let used_liquidity_msat = used_liquidities
2115
+ . entry ( hop. candidate . id ( * prev_hop < hop. node_id ) )
2103
2116
. and_modify ( |used_liquidity_msat| * used_liquidity_msat += spent_on_hop_msat)
2104
2117
. or_insert ( spent_on_hop_msat) ;
2105
2118
let hop_capacity = hop. candidate . effective_capacity ( ) ;
@@ -2118,8 +2131,8 @@ where L::Target: Logger {
2118
2131
let victim_scid = payment_path. hops [ ( payment_path. hops . len ( ) ) / 2 ] . 0 . candidate . short_channel_id ( ) ;
2119
2132
let exhausted = u64:: max_value ( ) ;
2120
2133
log_trace ! ( logger, "Disabling channel {} for future path building iterations to avoid duplicates." , victim_scid) ;
2121
- * used_channel_liquidities . entry ( ( victim_scid, false ) ) . or_default ( ) = exhausted;
2122
- * used_channel_liquidities . entry ( ( victim_scid, true ) ) . or_default ( ) = exhausted;
2134
+ * used_liquidities . entry ( CandidateHopId :: Clear ( ( victim_scid, false ) ) ) . or_default ( ) = exhausted;
2135
+ * used_liquidities . entry ( CandidateHopId :: Clear ( ( victim_scid, true ) ) ) . or_default ( ) = exhausted;
2123
2136
}
2124
2137
2125
2138
// Track the total amount all our collected paths allow to send so that we know
0 commit comments