@@ -225,6 +225,16 @@ pub struct PaymentParameters {
225
225
/// The maximum number of paths that may be used by (MPP) payments.
226
226
/// Defaults to [`DEFAULT_MAX_PATH_COUNT`].
227
227
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 ,
228
238
}
229
239
230
240
impl_writeable_tlv_based ! ( PaymentParameters , {
@@ -233,6 +243,7 @@ impl_writeable_tlv_based!(PaymentParameters, {
233
243
( 2 , features, option) ,
234
244
( 3 , max_path_count, ( default_value, DEFAULT_MAX_PATH_COUNT ) ) ,
235
245
( 4 , route_hints, vec_type) ,
246
+ ( 5 , max_channel_saturation_power_of_half, ( default_value, 1 ) ) ,
236
247
( 6 , expiry_time, option) ,
237
248
} ) ;
238
249
@@ -246,6 +257,11 @@ impl PaymentParameters {
246
257
expiry_time : None ,
247
258
max_total_cltv_expiry_delta : DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ,
248
259
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 ,
249
265
}
250
266
}
251
267
@@ -433,16 +449,6 @@ impl<'a> CandidateRouteHop<'a> {
433
449
}
434
450
}
435
451
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
-
446
452
fn fees ( & self ) -> RoutingFees {
447
453
match self {
448
454
CandidateRouteHop :: FirstHop { .. } => RoutingFees {
@@ -464,6 +470,24 @@ impl<'a> CandidateRouteHop<'a> {
464
470
}
465
471
}
466
472
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
+
467
491
/// It's useful to keep track of the hops associated with the fees required to use them,
468
492
/// so that we can choose cheaper paths (as per Dijkstra's algorithm).
469
493
/// 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 {
934
958
// - for first and last hops early in get_route
935
959
if $src_node_id != $dest_node_id {
936
960
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) ;
938
963
939
964
// It is tricky to subtract $next_hops_fee_msat from available liquidity here.
940
965
// It may be misleading because we might later choose to reduce the value transferred
@@ -1084,7 +1109,7 @@ where L::Target: Logger {
1084
1109
let channel_usage = ChannelUsage {
1085
1110
amount_msat: amount_to_transfer_over_msat,
1086
1111
inflight_htlc_msat: used_liquidity_msat,
1087
- effective_capacity: $candidate . effective_capacity ( ) ,
1112
+ effective_capacity,
1088
1113
} ;
1089
1114
let channel_penalty_msat = scorer. channel_penalty_msat(
1090
1115
short_channel_id, & $src_node_id, & $dest_node_id, channel_usage
@@ -1505,12 +1530,15 @@ where L::Target: Logger {
1505
1530
. entry ( ( hop. candidate . short_channel_id ( ) , * prev_hop < hop. node_id ) )
1506
1531
. and_modify ( |used_liquidity_msat| * used_liquidity_msat += spent_on_hop_msat)
1507
1532
. 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 {
1509
1537
// If this path used all of this channel's available liquidity, we know
1510
1538
// this path will not be selected again in the next loop iteration.
1511
1539
prevented_redundant_path_selection = true ;
1512
1540
}
1513
- debug_assert ! ( * used_liquidity_msat <= hop . candidate . htlc_maximum_msat ( ) ) ;
1541
+ debug_assert ! ( * used_liquidity_msat <= hop_max_msat ) ;
1514
1542
}
1515
1543
if !prevented_redundant_path_selection {
1516
1544
// If we weren't capped by hitting a liquidity limit on a channel in the path,
0 commit comments