@@ -225,6 +225,17 @@ pub struct PaymentParameters {
225225 /// The maximum number of paths that may be used by (MPP) payments.
226226 /// Defaults to [`DEFAULT_MAX_PATH_COUNT`].
227227 pub max_path_count : u8 ,
228+
229+ /// Selects the maximum share of a channel's total capacity which will be sent over a channel,
230+ /// as a power of 1/2. A higher value prefers to send the payment using more MPP parts whereas
231+ /// a lower value prefers to send larger MPP parts, potentially saturating channels and
232+ /// increasing failure probability for those paths.
233+ ///
234+ /// A value of 0 will allow payments up to and including a channel's total announced usable
235+ /// capacity, a value of one will only use up to half its capacity, two 1/4, etc.
236+ ///
237+ /// Default value: 1
238+ pub max_channel_saturation_power_of_half : u8 ,
228239}
229240
230241impl_writeable_tlv_based ! ( PaymentParameters , {
@@ -233,6 +244,7 @@ impl_writeable_tlv_based!(PaymentParameters, {
233244 ( 2 , features, option) ,
234245 ( 3 , max_path_count, ( default_value, DEFAULT_MAX_PATH_COUNT ) ) ,
235246 ( 4 , route_hints, vec_type) ,
247+ ( 5 , max_channel_saturation_power_of_half, ( default_value, 1 ) ) ,
236248 ( 6 , expiry_time, option) ,
237249} ) ;
238250
@@ -246,6 +258,11 @@ impl PaymentParameters {
246258 expiry_time : None ,
247259 max_total_cltv_expiry_delta : DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ,
248260 max_path_count : DEFAULT_MAX_PATH_COUNT ,
261+ #[ cfg( test) ] // Many tests were written prior to the introduction of this parameter, so
262+ // we leave it as 0 by default in tests, and change it for a few.
263+ max_channel_saturation_power_of_half : 0 ,
264+ #[ cfg( not( test) ) ]
265+ max_channel_saturation_power_of_half : 1 ,
249266 }
250267 }
251268
@@ -433,16 +450,6 @@ impl<'a> CandidateRouteHop<'a> {
433450 }
434451 }
435452
436- fn htlc_maximum_msat ( & self ) -> u64 {
437- match self {
438- CandidateRouteHop :: FirstHop { details } => details. next_outbound_htlc_limit_msat ,
439- CandidateRouteHop :: PublicHop { info, .. } => info. htlc_maximum_msat ( ) ,
440- CandidateRouteHop :: PrivateHop { hint } => {
441- hint. htlc_maximum_msat . unwrap_or ( u64:: max_value ( ) )
442- } ,
443- }
444- }
445-
446453 fn fees ( & self ) -> RoutingFees {
447454 match self {
448455 CandidateRouteHop :: FirstHop { .. } => RoutingFees {
@@ -464,6 +471,22 @@ impl<'a> CandidateRouteHop<'a> {
464471 }
465472}
466473
474+ #[ inline]
475+ fn max_htlc_from_capacity ( capacity : EffectiveCapacity , max_channel_saturation_power_of_half : u8 ) -> u64 {
476+ let saturation_shift: u32 = max_channel_saturation_power_of_half as u32 ;
477+ match capacity {
478+ EffectiveCapacity :: ExactLiquidity { liquidity_msat } => liquidity_msat,
479+ EffectiveCapacity :: Infinite => u64:: max_value ( ) ,
480+ EffectiveCapacity :: Unknown => EffectiveCapacity :: Unknown . as_msat ( ) ,
481+ EffectiveCapacity :: MaximumHTLC { amount_msat } =>
482+ amount_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) ,
483+ EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : None } =>
484+ capacity_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) ,
485+ EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_max) } =>
486+ cmp:: min ( capacity_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) , htlc_max) ,
487+ }
488+ }
489+
467490/// It's useful to keep track of the hops associated with the fees required to use them,
468491/// so that we can choose cheaper paths (as per Dijkstra's algorithm).
469492/// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
@@ -934,7 +957,8 @@ where L::Target: Logger {
934957 // - for first and last hops early in get_route
935958 if $src_node_id != $dest_node_id {
936959 let short_channel_id = $candidate. short_channel_id( ) ;
937- let htlc_maximum_msat = $candidate. htlc_maximum_msat( ) ;
960+ let effective_capacity = $candidate. effective_capacity( ) ;
961+ let htlc_maximum_msat = max_htlc_from_capacity( effective_capacity, payment_params. max_channel_saturation_power_of_half) ;
938962
939963 // It is tricky to subtract $next_hops_fee_msat from available liquidity here.
940964 // It may be misleading because we might later choose to reduce the value transferred
@@ -1084,7 +1108,7 @@ where L::Target: Logger {
10841108 let channel_usage = ChannelUsage {
10851109 amount_msat: amount_to_transfer_over_msat,
10861110 inflight_htlc_msat: used_liquidity_msat,
1087- effective_capacity: $candidate . effective_capacity ( ) ,
1111+ effective_capacity,
10881112 } ;
10891113 let channel_penalty_msat = scorer. channel_penalty_msat(
10901114 short_channel_id, & $src_node_id, & $dest_node_id, channel_usage
@@ -1505,12 +1529,15 @@ where L::Target: Logger {
15051529 . entry ( ( hop. candidate . short_channel_id ( ) , * prev_hop < hop. node_id ) )
15061530 . and_modify ( |used_liquidity_msat| * used_liquidity_msat += spent_on_hop_msat)
15071531 . or_insert ( spent_on_hop_msat) ;
1508- if * used_liquidity_msat == hop. candidate . htlc_maximum_msat ( ) {
1532+ let hop_capacity = hop. candidate . effective_capacity ( ) ;
1533+ let hop_max_msat = max_htlc_from_capacity ( hop_capacity,
1534+ payment_params. max_channel_saturation_power_of_half ) ;
1535+ if * used_liquidity_msat == hop_max_msat {
15091536 // If this path used all of this channel's available liquidity, we know
15101537 // this path will not be selected again in the next loop iteration.
15111538 prevented_redundant_path_selection = true ;
15121539 }
1513- debug_assert ! ( * used_liquidity_msat <= hop . candidate . htlc_maximum_msat ( ) ) ;
1540+ debug_assert ! ( * used_liquidity_msat <= hop_max_msat ) ;
15141541 }
15151542 if !prevented_redundant_path_selection {
15161543 // If we weren't capped by hitting a liquidity limit on a channel in the path,
0 commit comments