@@ -332,11 +332,9 @@ struct RouteGraphNode {
332
332
impl cmp:: Ord for RouteGraphNode {
333
333
fn cmp ( & self , other : & RouteGraphNode ) -> cmp:: Ordering {
334
334
let other_score = cmp:: max ( other. lowest_fee_to_peer_through_node , other. path_htlc_minimum_msat )
335
- . checked_add ( other. path_penalty_msat )
336
- . unwrap_or_else ( || u64:: max_value ( ) ) ;
335
+ . saturating_add ( other. path_penalty_msat ) ;
337
336
let self_score = cmp:: max ( self . lowest_fee_to_peer_through_node , self . path_htlc_minimum_msat )
338
- . checked_add ( self . path_penalty_msat )
339
- . unwrap_or_else ( || u64:: max_value ( ) ) ;
337
+ . saturating_add ( self . path_penalty_msat ) ;
340
338
other_score. cmp ( & self_score) . then_with ( || other. node_id . cmp ( & self . node_id ) )
341
339
}
342
340
}
@@ -495,6 +493,13 @@ impl<'a> PaymentPath<'a> {
495
493
self . hops . last ( ) . unwrap ( ) . 0 . fee_msat
496
494
}
497
495
496
+ fn get_path_penalty_msat ( & self ) -> u64 {
497
+ if self . hops . len ( ) < 1 {
498
+ return u64:: max_value ( ) ;
499
+ }
500
+ self . hops . first ( ) . unwrap ( ) . 0 . path_penalty_msat
501
+ }
502
+
498
503
fn get_total_fee_paid_msat ( & self ) -> u64 {
499
504
if self . hops . len ( ) < 1 {
500
505
return 0 ;
@@ -645,7 +650,7 @@ where L::Target: Logger {
645
650
pub ( crate ) fn get_route < L : Deref , S : Score > (
646
651
our_node_pubkey : & PublicKey , payment_params : & PaymentParameters , network_graph : & ReadOnlyNetworkGraph ,
647
652
first_hops : Option < & [ & ChannelDetails ] > , final_value_msat : u64 , final_cltv_expiry_delta : u32 ,
648
- logger : L , scorer : & S , _random_seed_bytes : & [ u8 ; 32 ]
653
+ logger : L , scorer : & S , random_seed_bytes : & [ u8 ; 32 ]
649
654
) -> Result < Route , LightningError >
650
655
where L :: Target : Logger {
651
656
let payee_node_id = NodeId :: from_pubkey ( & payment_params. payee_pubkey ) ;
@@ -833,7 +838,7 @@ where L::Target: Logger {
833
838
. entry( short_channel_id)
834
839
. or_insert_with( || $candidate. effective_capacity( ) . as_msat( ) ) ;
835
840
836
- // It is tricky to substract $next_hops_fee_msat from available liquidity here.
841
+ // It is tricky to subtract $next_hops_fee_msat from available liquidity here.
837
842
// It may be misleading because we might later choose to reduce the value transferred
838
843
// over these channels, and the channel which was insufficient might become sufficient.
839
844
// Worst case: we drop a good channel here because it can't cover the high following
@@ -873,8 +878,7 @@ where L::Target: Logger {
873
878
. checked_sub( 2 * MEDIAN_HOP_CLTV_EXPIRY_DELTA )
874
879
. unwrap_or( payment_params. max_total_cltv_expiry_delta - final_cltv_expiry_delta) ;
875
880
let hop_total_cltv_delta = ( $next_hops_cltv_delta as u32 )
876
- . checked_add( $candidate. cltv_expiry_delta( ) )
877
- . unwrap_or( u32 :: max_value( ) ) ;
881
+ . saturating_add( $candidate. cltv_expiry_delta( ) ) ;
878
882
let doesnt_exceed_cltv_delta_limit = hop_total_cltv_delta <= max_total_cltv_expiry_delta;
879
883
880
884
let value_contribution_msat = cmp:: min( available_value_contribution_msat, $next_hops_value_contribution) ;
@@ -981,9 +985,9 @@ where L::Target: Logger {
981
985
}
982
986
}
983
987
984
- let path_penalty_msat = $next_hops_path_penalty_msat. checked_add (
985
- scorer. channel_penalty_msat( short_channel_id, amount_to_transfer_over_msat, * available_liquidity_msat ,
986
- & $src_node_id, & $dest_node_id) ) . unwrap_or_else ( || u64 :: max_value ( ) ) ;
988
+ let path_penalty_msat = $next_hops_path_penalty_msat. saturating_add (
989
+ scorer. channel_penalty_msat( short_channel_id, amount_to_transfer_over_msat,
990
+ * available_liquidity_msat , & $src_node_id, & $dest_node_id) ) ;
987
991
let new_graph_node = RouteGraphNode {
988
992
node_id: $src_node_id,
989
993
lowest_fee_to_peer_through_node: total_fee_msat,
@@ -1011,11 +1015,9 @@ where L::Target: Logger {
1011
1015
// the fees included in $next_hops_path_htlc_minimum_msat, but also
1012
1016
// can't use something that may decrease on future hops.
1013
1017
let old_cost = cmp:: max( old_entry. total_fee_msat, old_entry. path_htlc_minimum_msat)
1014
- . checked_add( old_entry. path_penalty_msat)
1015
- . unwrap_or_else( || u64 :: max_value( ) ) ;
1018
+ . saturating_add( old_entry. path_penalty_msat) ;
1016
1019
let new_cost = cmp:: max( total_fee_msat, path_htlc_minimum_msat)
1017
- . checked_add( path_penalty_msat)
1018
- . unwrap_or_else( || u64 :: max_value( ) ) ;
1020
+ . saturating_add( path_penalty_msat) ;
1019
1021
1020
1022
if !old_entry. was_processed && new_cost < old_cost {
1021
1023
targets. push( new_graph_node) ;
@@ -1199,12 +1201,10 @@ where L::Target: Logger {
1199
1201
. unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop } ) ;
1200
1202
let capacity_msat = candidate. effective_capacity ( ) . as_msat ( ) ;
1201
1203
aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat
1202
- . checked_add ( scorer. channel_penalty_msat ( hop. short_channel_id , final_value_msat, capacity_msat, & source, & target) )
1203
- . unwrap_or_else ( || u64:: max_value ( ) ) ;
1204
+ . saturating_add ( scorer. channel_penalty_msat ( hop. short_channel_id , final_value_msat, capacity_msat, & source, & target) ) ;
1204
1205
1205
1206
aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta
1206
- . checked_add ( hop. cltv_expiry_delta as u32 )
1207
- . unwrap_or_else ( || u32:: max_value ( ) ) ;
1207
+ . saturating_add ( hop. cltv_expiry_delta as u32 ) ;
1208
1208
1209
1209
if !add_entry ! ( candidate, source, target, aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta) {
1210
1210
// If this hop was not used then there is no use checking the preceding hops
@@ -1442,24 +1442,31 @@ where L::Target: Logger {
1442
1442
}
1443
1443
1444
1444
// Sort by total fees and take the best paths.
1445
- payment_paths. sort_by_key ( |path| path. get_total_fee_paid_msat ( ) ) ;
1445
+ payment_paths. sort_unstable_by_key ( |path| path. get_total_fee_paid_msat ( ) ) ;
1446
1446
if payment_paths. len ( ) > 50 {
1447
1447
payment_paths. truncate ( 50 ) ;
1448
1448
}
1449
1449
1450
1450
// Draw multiple sufficient routes by randomly combining the selected paths.
1451
1451
let mut drawn_routes = Vec :: new ( ) ;
1452
- for i in 0 ..payment_paths. len ( ) {
1452
+ let mut prng = ChaCha20 :: new ( random_seed_bytes, & [ 0u8 ; 12 ] ) ;
1453
+ let mut random_index_bytes = [ 0u8 ; :: core:: mem:: size_of :: < usize > ( ) ] ;
1454
+
1455
+ let num_permutations = payment_paths. len ( ) ;
1456
+ for _ in 0 ..num_permutations {
1453
1457
let mut cur_route = Vec :: < PaymentPath > :: new ( ) ;
1454
1458
let mut aggregate_route_value_msat = 0 ;
1455
1459
1456
1460
// Step (6).
1457
- // TODO: real random shuffle
1458
- // Currently just starts with i_th and goes up to i-1_th in a looped way.
1459
- let cur_payment_paths = [ & payment_paths[ i..] , & payment_paths[ ..i] ] . concat ( ) ;
1461
+ // Do a Fisher-Yates shuffle to create a random permutation of the payment paths
1462
+ for cur_index in ( 1 ..payment_paths. len ( ) ) . rev ( ) {
1463
+ prng. process_in_place ( & mut random_index_bytes) ;
1464
+ let random_index = usize:: from_be_bytes ( random_index_bytes) . wrapping_rem ( cur_index+1 ) ;
1465
+ payment_paths. swap ( cur_index, random_index) ;
1466
+ }
1460
1467
1461
1468
// Step (7).
1462
- for payment_path in cur_payment_paths {
1469
+ for payment_path in & payment_paths {
1463
1470
cur_route. push ( payment_path. clone ( ) ) ;
1464
1471
aggregate_route_value_msat += payment_path. get_value_msat ( ) ;
1465
1472
if aggregate_route_value_msat > final_value_msat {
@@ -1469,12 +1476,17 @@ where L::Target: Logger {
1469
1476
// also makes routing more reliable.
1470
1477
let mut overpaid_value_msat = aggregate_route_value_msat - final_value_msat;
1471
1478
1472
- // First, drop some expensive low-value paths entirely if possible.
1473
- // Sort by value so that we drop many really-low values first, since
1474
- // fewer paths is better: the payment is less likely to fail.
1475
- // TODO: this could also be optimized by also sorting by feerate_per_sat_routed,
1476
- // so that the sender pays less fees overall. And also htlc_minimum_msat.
1477
- cur_route. sort_by_key ( |path| path. get_value_msat ( ) ) ;
1479
+ // First, we drop some expensive low-value paths entirely if possible, since fewer
1480
+ // paths is better: the payment is less likely to fail. In order to do so, we sort
1481
+ // by value and fall back to total fees paid, i.e., in case of equal values values
1482
+ // we prefer lower cost paths.
1483
+ cur_route. sort_unstable_by ( |a, b| {
1484
+ a. get_value_msat ( ) . cmp ( & b. get_value_msat ( ) )
1485
+ // Reverse ordering for fees, so we drop higher-fee paths first
1486
+ . then_with ( || b. get_total_fee_paid_msat ( ) . saturating_add ( b. get_path_penalty_msat ( ) )
1487
+ . cmp ( & a. get_total_fee_paid_msat ( ) . saturating_add ( a. get_path_penalty_msat ( ) ) ) )
1488
+ } ) ;
1489
+
1478
1490
// We should make sure that at least 1 path left.
1479
1491
let mut paths_left = cur_route. len ( ) ;
1480
1492
cur_route. retain ( |path| {
@@ -1498,13 +1510,14 @@ where L::Target: Logger {
1498
1510
assert ! ( cur_route. len( ) > 0 ) ;
1499
1511
1500
1512
// Step (8).
1501
- // Now, substract the overpaid value from the most-expensive path.
1513
+ // Now, subtract the overpaid value from the most-expensive path.
1502
1514
// TODO: this could also be optimized by also sorting by feerate_per_sat_routed,
1503
1515
// so that the sender pays less fees overall. And also htlc_minimum_msat.
1504
- cur_route. sort_by_key ( |path| { path. hops . iter ( ) . map ( |hop| hop. 0 . candidate . fees ( ) . proportional_millionths as u64 ) . sum :: < u64 > ( ) } ) ;
1516
+ cur_route. sort_unstable_by_key ( |path| { path. hops . iter ( ) . map ( |hop| hop. 0 . candidate . fees ( ) . proportional_millionths as u64 ) . sum :: < u64 > ( ) } ) ;
1505
1517
let expensive_payment_path = cur_route. first_mut ( ) . unwrap ( ) ;
1506
- // We already dropped all the small channels above, meaning all the
1507
- // remaining channels are larger than remaining overpaid_value_msat.
1518
+
1519
+ // We already dropped all the small value paths above, meaning all the
1520
+ // remaining paths are larger than remaining overpaid_value_msat.
1508
1521
// Thus, this can't be negative.
1509
1522
let expensive_path_new_value_msat = expensive_payment_path. get_value_msat ( ) - overpaid_value_msat;
1510
1523
expensive_payment_path. update_value_and_recompute_fees ( expensive_path_new_value_msat) ;
@@ -1516,7 +1529,7 @@ where L::Target: Logger {
1516
1529
1517
1530
// Step (9).
1518
1531
// Select the best route by lowest total fee.
1519
- drawn_routes. sort_by_key ( |paths| paths. iter ( ) . map ( |path| path. get_total_fee_paid_msat ( ) ) . sum :: < u64 > ( ) ) ;
1532
+ drawn_routes. sort_unstable_by_key ( |paths| paths. iter ( ) . map ( |path| path. get_total_fee_paid_msat ( ) ) . sum :: < u64 > ( ) ) ;
1520
1533
let mut selected_paths = Vec :: < Vec < Result < RouteHop , LightningError > > > :: new ( ) ;
1521
1534
for payment_path in drawn_routes. first ( ) . unwrap ( ) {
1522
1535
let mut path = payment_path. hops . iter ( ) . map ( |( payment_hop, node_features) | {
0 commit comments