- for payment_path in &payment_paths {
- cur_route.push(payment_path.clone());
- aggregate_route_value_msat += payment_path.get_value_msat();
- if aggregate_route_value_msat > final_value_msat {
- // Last path likely overpaid. Substract it from the most expensive
- // (in terms of proportional fee) path in this route and recompute fees.
- // This might be not the most economically efficient way, but fewer paths
- // also makes routing more reliable.
- let mut overpaid_value_msat = aggregate_route_value_msat - final_value_msat;
-
- // First, we drop some expensive low-value paths entirely if possible, since fewer
- // paths is better: the payment is less likely to fail. In order to do so, we sort
- // by value and fall back to total fees paid, i.e., in case of equal values we
- // prefer lower cost paths.
- cur_route.sort_unstable_by(|a, b| {
- a.get_value_msat().cmp(&b.get_value_msat())
- // Reverse ordering for cost, so we drop higher-cost paths first
- .then_with(|| b.get_cost_msat().cmp(&a.get_cost_msat()))
- });
-
- // We should make sure that at least 1 path left.
- let mut paths_left = cur_route.len();
- cur_route.retain(|path| {
- if paths_left == 1 {
- return true
- }
- let mut keep = true;
- let path_value_msat = path.get_value_msat();
- if path_value_msat <= overpaid_value_msat {
- keep = false;
- overpaid_value_msat -= path_value_msat;
- paths_left -= 1;
- }
- keep
- });
-
- if overpaid_value_msat == 0 {
- break;
- }
+ // Now, subtract the remaining overpaid value from the most-expensive path.
+ // TODO: this could also be optimized by also sorting by feerate_per_sat_routed,
+ // so that the sender pays less fees overall. And also htlc_minimum_msat.
+ selected_route.sort_unstable_by(|a, b| {
+ let a_f = a.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::<u64>();
+ let b_f = b.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::<u64>();
+ a_f.cmp(&b_f).then_with(|| b.get_cost_msat().cmp(&a.get_cost_msat()))
+ });
+ let expensive_payment_path = selected_route.first_mut().unwrap();