@@ -225,6 +225,16 @@ 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 percent of a channel's total capacity which will be sent over a
230+ /// channel, as a power of 1/2. A higher value prefers to send the payment using more MPP parts
231+ /// whereas a lower value prefers to send larger MPP parts, potentially saturating channels.
232+ ///
233+ /// A value of 0 will allow payments up to and including a channel's total announced usable
234+ /// capacity, a value of one will only use up to half its capacity, two 1/4, etc.
235+ ///
236+ /// Default value: 1
237+ pub max_channel_saturation_power_of_half : u8 ,
228238}
229239
230240impl_writeable_tlv_based ! ( PaymentParameters , {
@@ -233,6 +243,7 @@ impl_writeable_tlv_based!(PaymentParameters, {
233243 ( 2 , features, option) ,
234244 ( 3 , max_path_count, ( default_value, DEFAULT_MAX_PATH_COUNT ) ) ,
235245 ( 4 , route_hints, vec_type) ,
246+ ( 5 , max_channel_saturation_power_of_half, ( default_value, 1 ) ) ,
236247 ( 6 , expiry_time, option) ,
237248} ) ;
238249
@@ -246,6 +257,11 @@ impl PaymentParameters {
246257 expiry_time : None ,
247258 max_total_cltv_expiry_delta : DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ,
248259 max_path_count : DEFAULT_MAX_PATH_COUNT ,
260+ #[ cfg( test) ] // Many tests were written prior to the introduction of this parameter, so
261+ // we leave it as 0 by default in tests, and change it for a few.
262+ max_channel_saturation_power_of_half : 0 ,
263+ #[ cfg( not( test) ) ]
264+ max_channel_saturation_power_of_half : 1 ,
249265 }
250266 }
251267
@@ -433,16 +449,6 @@ impl<'a> CandidateRouteHop<'a> {
433449 }
434450 }
435451
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-
446452 fn fees ( & self ) -> RoutingFees {
447453 match self {
448454 CandidateRouteHop :: FirstHop { .. } => RoutingFees {
@@ -464,6 +470,24 @@ impl<'a> CandidateRouteHop<'a> {
464470 }
465471}
466472
473+ #[ inline]
474+ fn max_htlc_from_capacity ( capacity : EffectiveCapacity , max_channel_saturation_power_of_half : u8 ) -> u64 {
475+ let saturation_shift: u32 = max_channel_saturation_power_of_half as u32 ;
476+ match capacity {
477+ EffectiveCapacity :: ExactLiquidity { liquidity_msat } => liquidity_msat,
478+ EffectiveCapacity :: Infinite => u64:: max_value ( ) ,
479+ EffectiveCapacity :: Unknown => EffectiveCapacity :: Unknown . as_msat ( ) ,
480+ EffectiveCapacity :: MaximumHTLC { amount_msat } =>
481+ amount_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) ,
482+ EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : None } =>
483+ capacity_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) ,
484+ EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_max) } =>
485+ cmp:: min (
486+ capacity_msat. checked_shr ( saturation_shift) . unwrap_or ( 0 ) ,
487+ htlc_max) ,
488+ }
489+ }
490+
467491/// It's useful to keep track of the hops associated with the fees required to use them,
468492/// so that we can choose cheaper paths (as per Dijkstra's algorithm).
469493/// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
@@ -934,7 +958,8 @@ where L::Target: Logger {
934958 // - for first and last hops early in get_route
935959 if $src_node_id != $dest_node_id {
936960 let short_channel_id = $candidate. short_channel_id( ) ;
937- let htlc_maximum_msat = $candidate. htlc_maximum_msat( ) ;
961+ let effective_capacity = $candidate. effective_capacity( ) ;
962+ let htlc_maximum_msat = max_htlc_from_capacity( effective_capacity, payment_params. max_channel_saturation_power_of_half) ;
938963
939964 // It is tricky to subtract $next_hops_fee_msat from available liquidity here.
940965 // It may be misleading because we might later choose to reduce the value transferred
@@ -1084,7 +1109,7 @@ where L::Target: Logger {
10841109 let channel_usage = ChannelUsage {
10851110 amount_msat: amount_to_transfer_over_msat,
10861111 inflight_htlc_msat: used_liquidity_msat,
1087- effective_capacity: $candidate . effective_capacity ( ) ,
1112+ effective_capacity,
10881113 } ;
10891114 let channel_penalty_msat = scorer. channel_penalty_msat(
10901115 short_channel_id, & $src_node_id, & $dest_node_id, channel_usage
@@ -1505,12 +1530,15 @@ where L::Target: Logger {
15051530 . entry ( ( hop. candidate . short_channel_id ( ) , * prev_hop < hop. node_id ) )
15061531 . and_modify ( |used_liquidity_msat| * used_liquidity_msat += spent_on_hop_msat)
15071532 . or_insert ( spent_on_hop_msat) ;
1508- if * used_liquidity_msat == hop. candidate . htlc_maximum_msat ( ) {
1533+ let hop_capacity = hop. candidate . effective_capacity ( ) ;
1534+ let hop_max_msat = max_htlc_from_capacity ( hop_capacity,
1535+ payment_params. max_channel_saturation_power_of_half ) ;
1536+ if * used_liquidity_msat == hop_max_msat {
15091537 // If this path used all of this channel's available liquidity, we know
15101538 // this path will not be selected again in the next loop iteration.
15111539 prevented_redundant_path_selection = true ;
15121540 }
1513- debug_assert ! ( * used_liquidity_msat <= hop . candidate . htlc_maximum_msat ( ) ) ;
1541+ debug_assert ! ( * used_liquidity_msat <= hop_max_msat ) ;
15141542 }
15151543 if !prevented_redundant_path_selection {
15161544 // If we weren't capped by hitting a liquidity limit on a channel in the path,
0 commit comments