@@ -746,7 +746,7 @@ where L::Target: Logger, GL::Target: Logger {
746
746
pub ( crate ) fn get_route < L : Deref , S : Score > (
747
747
our_node_pubkey : & PublicKey , payment_params : & PaymentParameters , network_graph : & ReadOnlyNetworkGraph ,
748
748
first_hops : Option < & [ & ChannelDetails ] > , final_value_msat : u64 , final_cltv_expiry_delta : u32 ,
749
- logger : L , scorer : & S , random_seed_bytes : & [ u8 ; 32 ]
749
+ logger : L , scorer : & S , _random_seed_bytes : & [ u8 ; 32 ]
750
750
) -> Result < Route , LightningError >
751
751
where L :: Target : Logger {
752
752
let payee_node_id = NodeId :: from_pubkey ( & payment_params. payee_pubkey ) ;
@@ -788,11 +788,11 @@ where L::Target: Logger {
788
788
// 4. See if we managed to collect paths which aggregately are able to transfer target value
789
789
// (not recommended value).
790
790
// 5. If yes, proceed. If not, fail routing.
791
- // 6. Randomly combine paths into routes having enough to fulfill the payment. (TODO: knapsack)
792
- // 7. Of all the found paths, select only those with the lowest total fee .
793
- // 8. The last path in every selected route is likely to be more than we need .
794
- // Reduce its value-to-transfer and recompute fees.
795
- // 9. Choose the best route by the lowest total fee .
791
+ // 6. Select the paths which have the lowest cost (fee plus scorer penalty) per amount
792
+ // transferred up to the transfer target value .
793
+ // 7. Reduce the value of the last path until we are sending only the target value .
794
+ // 8. If our maximum channel saturation limit caused us to pick two identical paths, combine
795
+ // them so that we're not sending two HTLCs along the same path .
796
796
797
797
// As for the actual search algorithm,
798
798
// we do a payee-to-payer pseudo-Dijkstra's sorting by each node's distance from the payee
@@ -1643,96 +1643,57 @@ where L::Target: Logger {
1643
1643
return Err ( LightningError { err : "Failed to find a sufficient route to the given destination" . to_owned ( ) , action : ErrorAction :: IgnoreError } ) ;
1644
1644
}
1645
1645
1646
- // Sort by total fees and take the best paths.
1647
- payment_paths. sort_unstable_by_key ( |path| path. get_total_fee_paid_msat ( ) ) ;
1648
- if payment_paths. len ( ) > 50 {
1649
- payment_paths. truncate ( 50 ) ;
1650
- }
1646
+ // Step (6).
1647
+ let mut selected_route = payment_paths;
1651
1648
1652
- // Draw multiple sufficient routes by randomly combining the selected paths.
1653
- let mut drawn_routes = Vec :: new ( ) ;
1654
- let mut prng = ChaCha20 :: new ( random_seed_bytes, & [ 0u8 ; 12 ] ) ;
1655
- let mut random_index_bytes = [ 0u8 ; :: core:: mem:: size_of :: < usize > ( ) ] ;
1649
+ debug_assert_eq ! ( selected_route. iter( ) . map( |p| p. get_value_msat( ) ) . sum:: <u64 >( ) , already_collected_value_msat) ;
1650
+ let mut overpaid_value_msat = already_collected_value_msat - final_value_msat;
1656
1651
1657
- let num_permutations = payment_paths. len ( ) ;
1658
- for _ in 0 ..num_permutations {
1659
- let mut cur_route = Vec :: < PaymentPath > :: new ( ) ;
1660
- let mut aggregate_route_value_msat = 0 ;
1652
+ // First, sort by the cost-per-value of the path, selecting only the paths which
1653
+ // contribute the most per cost.
1654
+ // We sort backwards as we will remove from the front in `retain`, next.
1655
+ selected_route. sort_unstable_by ( |a, b|
1656
+ ( ( ( b. get_cost_msat ( ) as u128 ) << 64 ) / ( b. get_value_msat ( ) as u128 ) )
1657
+ . cmp ( & ( ( ( a. get_cost_msat ( ) as u128 ) << 64 ) / ( a. get_value_msat ( ) as u128 ) ) )
1658
+ ) ;
1661
1659
1662
- // Step (6).
1663
- // Do a Fisher-Yates shuffle to create a random permutation of the payment paths
1664
- for cur_index in ( 1 ..payment_paths. len ( ) ) . rev ( ) {
1665
- prng. process_in_place ( & mut random_index_bytes) ;
1666
- let random_index = usize:: from_be_bytes ( random_index_bytes) . wrapping_rem ( cur_index+1 ) ;
1667
- payment_paths. swap ( cur_index, random_index) ;
1660
+ // We should make sure that at least 1 path left.
1661
+ let mut paths_left = selected_route. len ( ) ;
1662
+ selected_route. retain ( |path| {
1663
+ if paths_left == 1 {
1664
+ return true
1665
+ }
1666
+ let mut keep = true ;
1667
+ let path_value_msat = path. get_value_msat ( ) ;
1668
+ if path_value_msat <= overpaid_value_msat {
1669
+ keep = false ;
1670
+ overpaid_value_msat -= path_value_msat;
1671
+ paths_left -= 1 ;
1668
1672
}
1673
+ keep
1674
+ } ) ;
1675
+ assert ! ( selected_route. len( ) > 0 ) ;
1669
1676
1677
+ if overpaid_value_msat != 0 {
1670
1678
// Step (7).
1671
- for payment_path in & payment_paths {
1672
- cur_route. push ( payment_path. clone ( ) ) ;
1673
- aggregate_route_value_msat += payment_path. get_value_msat ( ) ;
1674
- if aggregate_route_value_msat > final_value_msat {
1675
- // Last path likely overpaid. Substract it from the most expensive
1676
- // (in terms of proportional fee) path in this route and recompute fees.
1677
- // This might be not the most economically efficient way, but fewer paths
1678
- // also makes routing more reliable.
1679
- let mut overpaid_value_msat = aggregate_route_value_msat - final_value_msat;
1680
-
1681
- // First, we drop some expensive low-value paths entirely if possible, since fewer
1682
- // paths is better: the payment is less likely to fail. In order to do so, we sort
1683
- // by value and fall back to total fees paid, i.e., in case of equal values we
1684
- // prefer lower cost paths.
1685
- cur_route. sort_unstable_by ( |a, b| {
1686
- a. get_value_msat ( ) . cmp ( & b. get_value_msat ( ) )
1687
- // Reverse ordering for cost, so we drop higher-cost paths first
1688
- . then_with ( || b. get_cost_msat ( ) . cmp ( & a. get_cost_msat ( ) ) )
1689
- } ) ;
1690
-
1691
- // We should make sure that at least 1 path left.
1692
- let mut paths_left = cur_route. len ( ) ;
1693
- cur_route. retain ( |path| {
1694
- if paths_left == 1 {
1695
- return true
1696
- }
1697
- let mut keep = true ;
1698
- let path_value_msat = path. get_value_msat ( ) ;
1699
- if path_value_msat <= overpaid_value_msat {
1700
- keep = false ;
1701
- overpaid_value_msat -= path_value_msat;
1702
- paths_left -= 1 ;
1703
- }
1704
- keep
1705
- } ) ;
1706
-
1707
- if overpaid_value_msat == 0 {
1708
- break ;
1709
- }
1679
+ // Now, subtract the overpaid value from the most-expensive path.
1680
+ // TODO: this could also be optimized by also sorting by feerate_per_sat_routed,
1681
+ // so that the sender pays less fees overall. And also htlc_minimum_msat.
1682
+ selected_route. sort_unstable_by ( |a, b| {
1683
+ let a_f = a. hops . iter ( ) . map ( |hop| hop. 0 . candidate . fees ( ) . proportional_millionths as u64 ) . sum :: < u64 > ( ) ;
1684
+ let b_f = b. hops . iter ( ) . map ( |hop| hop. 0 . candidate . fees ( ) . proportional_millionths as u64 ) . sum :: < u64 > ( ) ;
1685
+ a_f. cmp ( & b_f) . then_with ( || b. get_cost_msat ( ) . cmp ( & a. get_cost_msat ( ) ) )
1686
+ } ) ;
1687
+ let expensive_payment_path = selected_route. first_mut ( ) . unwrap ( ) ;
1710
1688
1711
- assert ! ( cur_route. len( ) > 0 ) ;
1712
-
1713
- // Step (8).
1714
- // Now, subtract the overpaid value from the most-expensive path.
1715
- // TODO: this could also be optimized by also sorting by feerate_per_sat_routed,
1716
- // so that the sender pays less fees overall. And also htlc_minimum_msat.
1717
- cur_route. sort_unstable_by_key ( |path| { path. hops . iter ( ) . map ( |hop| hop. 0 . candidate . fees ( ) . proportional_millionths as u64 ) . sum :: < u64 > ( ) } ) ;
1718
- let expensive_payment_path = cur_route. first_mut ( ) . unwrap ( ) ;
1719
-
1720
- // We already dropped all the small value paths above, meaning all the
1721
- // remaining paths are larger than remaining overpaid_value_msat.
1722
- // Thus, this can't be negative.
1723
- let expensive_path_new_value_msat = expensive_payment_path. get_value_msat ( ) - overpaid_value_msat;
1724
- expensive_payment_path. update_value_and_recompute_fees ( expensive_path_new_value_msat) ;
1725
- break ;
1726
- }
1727
- }
1728
- drawn_routes. push ( cur_route) ;
1689
+ // We already dropped all the small value paths above, meaning all the
1690
+ // remaining paths are larger than remaining overpaid_value_msat.
1691
+ // Thus, this can't be negative.
1692
+ let expensive_path_new_value_msat = expensive_payment_path. get_value_msat ( ) - overpaid_value_msat;
1693
+ expensive_payment_path. update_value_and_recompute_fees ( expensive_path_new_value_msat) ;
1729
1694
}
1730
1695
1731
- // Step (9).
1732
- // Select the best route by lowest total cost.
1733
- drawn_routes. sort_unstable_by_key ( |paths| paths. iter ( ) . map ( |path| path. get_cost_msat ( ) ) . sum :: < u64 > ( ) ) ;
1734
- let selected_route = drawn_routes. first_mut ( ) . unwrap ( ) ;
1735
-
1696
+ // Step (8).
1736
1697
// Sort by the path itself and combine redundant paths.
1737
1698
// Note that we sort by SCIDs alone as its simpler but when combining we have to ensure we
1738
1699
// compare both SCIDs and NodeIds as individual nodes may use random aliases causing collisions
0 commit comments