@@ -331,6 +331,17 @@ pub struct ProbabilisticScoringParameters {
331
331
/// Default value: 500 msat
332
332
pub base_penalty_msat : u64 ,
333
333
334
+ /// A fixed penalty in msats to apply to each channel, multiplied by the payment amount.
335
+ ///
336
+ /// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e.,
337
+ /// fees plus penalty) for large payments. The penalty is computed as the product of this
338
+ /// multiplier and `2^30`ths of the payment amount.
339
+ ///
340
+ /// ie `amount_penalty_multiplier_msat * amount_msat / 2^30`
341
+ ///
342
+ /// Default value: 8,192 msat
343
+ pub base_penalty_amount_multiplier_msat : u64 ,
344
+
334
345
/// A multiplier used in conjunction with the negative `log10` of the channel's success
335
346
/// probability for a payment to determine the liquidity penalty.
336
347
///
@@ -505,6 +516,7 @@ impl ProbabilisticScoringParameters {
505
516
fn zero_penalty ( ) -> Self {
506
517
Self {
507
518
base_penalty_msat : 0 ,
519
+ base_penalty_amount_multiplier_msat : 0 ,
508
520
liquidity_penalty_multiplier_msat : 0 ,
509
521
liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
510
522
amount_penalty_multiplier_msat : 0 ,
@@ -526,6 +538,7 @@ impl Default for ProbabilisticScoringParameters {
526
538
fn default ( ) -> Self {
527
539
Self {
528
540
base_penalty_msat : 500 ,
541
+ base_penalty_amount_multiplier_msat : 8192 ,
529
542
liquidity_penalty_multiplier_msat : 40_000 ,
530
543
liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
531
544
amount_penalty_multiplier_msat : 256 ,
@@ -598,10 +611,11 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
598
611
599
612
/// The divisor used when computing the amount penalty.
600
613
const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
614
+ const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
601
615
602
616
impl < L : Deref < Target = u64 > , T : Time , U : Deref < Target = T > > DirectedChannelLiquidity < L , T , U > {
603
- /// Returns a penalty for routing the given HTLC `amount_msat` through the channel in this
604
- /// direction.
617
+ /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
618
+ /// this direction.
605
619
fn penalty_msat ( & self , amount_msat : u64 , params : & ProbabilisticScoringParameters ) -> u64 {
606
620
let max_liquidity_msat = self . max_liquidity_msat ( ) ;
607
621
let min_liquidity_msat = core:: cmp:: min ( self . min_liquidity_msat ( ) , max_liquidity_msat) ;
@@ -625,8 +639,8 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
625
639
if amount_msat - min_liquidity_msat < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
626
640
// If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
627
641
// don't bother trying to use the log approximation as it gets too noisy to be
628
- // particularly helpful, instead just round down to 0 and return the base penalty .
629
- params . base_penalty_msat
642
+ // particularly helpful, instead just round down to 0.
643
+ 0
630
644
} else {
631
645
let negative_log10_times_2048 =
632
646
approx:: negative_log10_times_2048 ( numerator, denominator) ;
@@ -651,9 +665,7 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
651
665
. saturating_mul ( params. amount_penalty_multiplier_msat )
652
666
. saturating_mul ( amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR ;
653
667
654
- params. base_penalty_msat
655
- . saturating_add ( liquidity_penalty_msat)
656
- . saturating_add ( amount_penalty_msat)
668
+ liquidity_penalty_msat. saturating_add ( amount_penalty_msat)
657
669
}
658
670
659
671
/// Returns the lower bound of the channel liquidity balance in this direction.
@@ -735,13 +747,17 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
735
747
return u64:: max_value ( ) ;
736
748
}
737
749
750
+ let base_penalty_msat = self . params . base_penalty_msat . saturating_add (
751
+ self . params . base_penalty_amount_multiplier_msat
752
+ . saturating_mul ( usage. amount_msat ) / BASE_AMOUNT_PENALTY_DIVISOR ) ;
753
+
738
754
let mut anti_probing_penalty_msat = 0 ;
739
755
match usage. effective_capacity {
740
756
EffectiveCapacity :: ExactLiquidity { liquidity_msat } => {
741
757
if usage. amount_msat > liquidity_msat {
742
758
return u64:: max_value ( ) ;
743
759
} else {
744
- return self . params . base_penalty_msat ;
760
+ return base_penalty_msat;
745
761
}
746
762
} ,
747
763
EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_maximum_msat) } => {
@@ -762,6 +778,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
762
778
. as_directed ( source, target, capacity_msat, liquidity_offset_half_life)
763
779
. penalty_msat ( amount_msat, & self . params )
764
780
. saturating_add ( anti_probing_penalty_msat)
781
+ . saturating_add ( base_penalty_msat)
765
782
}
766
783
767
784
fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
@@ -2024,47 +2041,47 @@ mod tests {
2024
2041
inflight_htlc_msat : 0 ,
2025
2042
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
2026
2043
} ;
2027
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 3613 ) ;
2044
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 4375 ) ;
2028
2045
let usage = ChannelUsage {
2029
2046
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2030
2047
} ;
2031
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1977 ) ;
2048
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2739 ) ;
2032
2049
let usage = ChannelUsage {
2033
2050
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2034
2051
} ;
2035
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1474 ) ;
2052
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2236 ) ;
2036
2053
let usage = ChannelUsage {
2037
2054
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2038
2055
} ;
2039
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1223 ) ;
2056
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1985 ) ;
2040
2057
let usage = ChannelUsage {
2041
2058
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2042
2059
} ;
2043
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 877 ) ;
2060
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1639 ) ;
2044
2061
let usage = ChannelUsage {
2045
2062
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2046
2063
} ;
2047
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 845 ) ;
2064
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1607 ) ;
2048
2065
let usage = ChannelUsage {
2049
2066
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2050
2067
} ;
2051
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2068
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2052
2069
let usage = ChannelUsage {
2053
2070
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2054
2071
} ;
2055
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2072
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2056
2073
let usage = ChannelUsage {
2057
2074
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2058
2075
} ;
2059
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2076
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2060
2077
let usage = ChannelUsage {
2061
2078
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2062
2079
} ;
2063
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2080
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2064
2081
let usage = ChannelUsage {
2065
2082
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2066
2083
} ;
2067
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2084
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2068
2085
}
2069
2086
2070
2087
#[ test]
@@ -2092,6 +2109,15 @@ mod tests {
2092
2109
} ;
2093
2110
let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2094
2111
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 ) ;
2112
+
2113
+ let params = ProbabilisticScoringParameters {
2114
+ base_penalty_msat : 500 , liquidity_penalty_multiplier_msat : 1_000 ,
2115
+ base_penalty_amount_multiplier_msat : ( 1 <<30 ) ,
2116
+ anti_probing_penalty_msat : 0 , ..Default :: default ( )
2117
+ } ;
2118
+
2119
+ let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2120
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 + 128 ) ;
2095
2121
}
2096
2122
2097
2123
#[ test]
0 commit comments