@@ -2043,9 +2043,10 @@ impl<'a> PaymentPath<'a> {
20432043 // that it the value being transferred has decreased while we were doing path finding, leading
20442044 // to the fees being paid not lining up with the actual limits.
20452045 //
2046- // Note that this function is not aware of the available_liquidity limit, and thus does not
2047- // support increasing the value being transferred beyond what was selected during the initial
2048- // routing passes.
2046+ // This function may also be used to increase the value being transferred in the case that
2047+ // overestimating later hops' fees caused us to underutilize earlier hops' capacity.
2048+ //
2049+ // Note that this function is not aware of the available_liquidity limit of any hops.
20492050 //
20502051 // Returns the amount that this path contributes to the total payment value, which may be greater
20512052 // than `value_msat` if we had to overpay to meet the final node's `htlc_minimum_msat`.
@@ -2110,15 +2111,56 @@ impl<'a> PaymentPath<'a> {
21102111 cur_hop. hop_use_fee_msat = new_fee;
21112112 total_fee_paid_msat += new_fee;
21122113 } else {
2113- // It should not be possible because this function is called only to reduce the
2114- // value. In that case, compute_fee was already called with the same fees for
2115- // larger amount and there was no overflow.
2114+ // It should not be possible because this function is only called either to reduce the
2115+ // value or with a larger amount that was already checked for overflow in
2116+ // `compute_max_final_value_contribution`. In the former case, compute_fee was already
2117+ // called with the same fees for larger amount and there was no overflow.
21162118 unreachable ! ( ) ;
21172119 }
21182120 }
21192121 }
21202122 value_msat + extra_contribution_msat
21212123 }
2124+
2125+ // Returns the maximum contribution that this path can make to the final value of the payment. May
2126+ // be slightly lower than the actual max due to rounding errors when aggregating fees along the
2127+ // path.
2128+ fn compute_max_final_value_contribution (
2129+ & self , used_liquidities : & HashMap < CandidateHopId , u64 > , channel_saturation_pow_half : u8
2130+ ) -> u64 {
2131+ let mut max_path_contribution = u64:: MAX ;
2132+ for ( idx, ( hop, _) ) in self . hops . iter ( ) . enumerate ( ) {
2133+ let hop_effective_capacity_msat = hop. candidate . effective_capacity ( ) ;
2134+ let hop_max_msat = max_htlc_from_capacity (
2135+ hop_effective_capacity_msat, channel_saturation_pow_half
2136+ ) . saturating_sub ( * used_liquidities. get ( & hop. candidate . id ( ) ) . unwrap_or ( & 0_u64 ) ) ;
2137+
2138+ let next_hops_feerates_iter = self . hops
2139+ . iter ( )
2140+ . skip ( idx + 1 )
2141+ . map ( |( hop, _) | hop. candidate . fees ( ) ) ;
2142+
2143+ // Aggregate the fees of the hops that come after this one, and use those fees to compute the
2144+ // maximum amount that this hop can contribute to the final value received by the payee.
2145+ let ( next_hops_aggregated_base, next_hops_aggregated_prop) =
2146+ crate :: blinded_path:: payment:: compute_aggregated_base_prop_fee ( next_hops_feerates_iter) . unwrap ( ) ;
2147+
2148+ // ceil(((hop_max_msat - agg_base) * 1_000_000) / (1_000_000 + agg_prop))
2149+ let hop_max_final_value_contribution = ( hop_max_msat as u128 )
2150+ . checked_sub ( next_hops_aggregated_base as u128 )
2151+ . and_then ( |f| f. checked_mul ( 1_000_000 ) )
2152+ . and_then ( |f| f. checked_add ( 1_000_000 - 1 ) )
2153+ . and_then ( |f| f. checked_add ( next_hops_aggregated_prop as u128 ) )
2154+ . map ( |f| f / ( ( next_hops_aggregated_prop as u128 ) . saturating_add ( 1_000_000 ) ) ) ;
2155+
2156+ if let Some ( hop_contribution) = hop_max_final_value_contribution {
2157+ let hop_contribution: u64 = hop_contribution. try_into ( ) . unwrap_or ( u64:: MAX ) ;
2158+ max_path_contribution = core:: cmp:: min ( hop_contribution, max_path_contribution) ;
2159+ } else { debug_assert ! ( false ) ; }
2160+ }
2161+
2162+ max_path_contribution
2163+ }
21222164}
21232165
21242166#[ inline( always) ]
@@ -3269,7 +3311,10 @@ where L::Target: Logger {
32693311 // recompute the fees again, so that if that's the case, we match the currently
32703312 // underpaid htlc_minimum_msat with fees.
32713313 debug_assert_eq ! ( payment_path. get_value_msat( ) , value_contribution_msat) ;
3272- let desired_value_contribution = cmp:: min ( value_contribution_msat, final_value_msat) ;
3314+ let max_path_contribution_msat = payment_path. compute_max_final_value_contribution (
3315+ & used_liquidities, channel_saturation_pow_half
3316+ ) ;
3317+ let desired_value_contribution = cmp:: min ( max_path_contribution_msat, final_value_msat) ;
32733318 value_contribution_msat = payment_path. update_value_and_recompute_fees ( desired_value_contribution) ;
32743319
32753320 // Since a path allows to transfer as much value as
@@ -3281,7 +3326,6 @@ where L::Target: Logger {
32813326 // might have been computed considering a larger value.
32823327 // Remember that we used these channels so that we don't rely
32833328 // on the same liquidity in future paths.
3284- let mut prevented_redundant_path_selection = false ;
32853329 for ( hop, _) in payment_path. hops . iter ( ) {
32863330 let spent_on_hop_msat = value_contribution_msat + hop. next_hops_fee_msat ;
32873331 let used_liquidity_msat = used_liquidities
@@ -3290,14 +3334,9 @@ where L::Target: Logger {
32903334 . or_insert ( spent_on_hop_msat) ;
32913335 let hop_capacity = hop. candidate . effective_capacity ( ) ;
32923336 let hop_max_msat = max_htlc_from_capacity ( hop_capacity, channel_saturation_pow_half) ;
3293- if * used_liquidity_msat == hop_max_msat {
3294- // If this path used all of this channel's available liquidity, we know
3295- // this path will not be selected again in the next loop iteration.
3296- prevented_redundant_path_selection = true ;
3297- }
32983337 debug_assert ! ( * used_liquidity_msat <= hop_max_msat) ;
32993338 }
3300- if !prevented_redundant_path_selection {
3339+ if max_path_contribution_msat > value_contribution_msat {
33013340 // If we weren't capped by hitting a liquidity limit on a channel in the path,
33023341 // we'll probably end up picking the same path again on the next iteration.
33033342 // Decrease the available liquidity of a hop in the middle of the path.
0 commit comments