@@ -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
@@ -3290,9 +3335,15 @@ where L::Target: Logger {
32903335 . or_insert ( spent_on_hop_msat) ;
32913336 let hop_capacity = hop. candidate . effective_capacity ( ) ;
32923337 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.
3338+
3339+ // If this path used all of this channel's available liquidity, we know this path will not
3340+ // be selected again in the next loop iteration.
3341+ //
3342+ // Allow the used amount to be slightly below the max when deciding whether a channel is
3343+ // fully utilized, to account for rounding errors in
3344+ // `PaymentPath::compute_max_final_value_contribution`.
3345+ let maxed_out_hop_liquidity_range = hop_max_msat. saturating_sub ( 1000 ) ..( hop_max_msat. saturating_add ( 1 ) ) ;
3346+ if maxed_out_hop_liquidity_range. contains ( used_liquidity_msat) {
32963347 prevented_redundant_path_selection = true ;
32973348 }
32983349 debug_assert ! ( * used_liquidity_msat <= hop_max_msat) ;
0 commit comments