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