@@ -331,6 +331,17 @@ pub struct ProbabilisticScoringParameters {
331331 /// Default value: 500 msat
332332 pub base_penalty_msat : u64 ,
333333
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+
334345 /// A multiplier used in conjunction with the negative `log10` of the channel's success
335346 /// probability for a payment to determine the liquidity penalty.
336347 ///
@@ -517,6 +528,7 @@ impl ProbabilisticScoringParameters {
517528 fn zero_penalty ( ) -> Self {
518529 Self {
519530 base_penalty_msat : 0 ,
531+ base_penalty_amount_multiplier_msat : 0 ,
520532 liquidity_penalty_multiplier_msat : 0 ,
521533 liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
522534 amount_penalty_multiplier_msat : 0 ,
@@ -538,6 +550,7 @@ impl Default for ProbabilisticScoringParameters {
538550 fn default ( ) -> Self {
539551 Self {
540552 base_penalty_msat : 500 ,
553+ base_penalty_amount_multiplier_msat : 8192 ,
541554 liquidity_penalty_multiplier_msat : 40_000 ,
542555 liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
543556 amount_penalty_multiplier_msat : 256 ,
@@ -610,10 +623,11 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
610623
611624/// The divisor used when computing the amount penalty.
612625const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
626+ const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
613627
614628impl < L : Deref < Target = u64 > , T : Time , U : Deref < Target = T > > DirectedChannelLiquidity < L , T , U > {
615- /// Returns a penalty for routing the given HTLC `amount_msat` through the channel in this
616- /// direction.
629+ /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
630+ /// this direction.
617631 fn penalty_msat ( & self , amount_msat : u64 , params : & ProbabilisticScoringParameters ) -> u64 {
618632 let max_liquidity_msat = self . max_liquidity_msat ( ) ;
619633 let min_liquidity_msat = core:: cmp:: min ( self . min_liquidity_msat ( ) , max_liquidity_msat) ;
@@ -637,8 +651,8 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
637651 if amount_msat - min_liquidity_msat < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
638652 // If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
639653 // don't bother trying to use the log approximation as it gets too noisy to be
640- // particularly helpful, instead just round down to 0 and return the base penalty .
641- params . base_penalty_msat
654+ // particularly helpful, instead just round down to 0.
655+ 0
642656 } else {
643657 let negative_log10_times_2048 =
644658 approx:: negative_log10_times_2048 ( numerator, denominator) ;
@@ -663,9 +677,7 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
663677 . saturating_mul ( params. amount_penalty_multiplier_msat )
664678 . saturating_mul ( amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR ;
665679
666- params. base_penalty_msat
667- . saturating_add ( liquidity_penalty_msat)
668- . saturating_add ( amount_penalty_msat)
680+ liquidity_penalty_msat. saturating_add ( amount_penalty_msat)
669681 }
670682
671683 /// Returns the lower bound of the channel liquidity balance in this direction.
@@ -747,13 +759,17 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
747759 return * penalty;
748760 }
749761
762+ let base_penalty_msat = self . params . base_penalty_msat . saturating_add (
763+ self . params . base_penalty_amount_multiplier_msat
764+ . saturating_mul ( usage. amount_msat ) / BASE_AMOUNT_PENALTY_DIVISOR ) ;
765+
750766 let mut anti_probing_penalty_msat = 0 ;
751767 match usage. effective_capacity {
752768 EffectiveCapacity :: ExactLiquidity { liquidity_msat } => {
753769 if usage. amount_msat > liquidity_msat {
754770 return u64:: max_value ( ) ;
755771 } else {
756- return self . params . base_penalty_msat ;
772+ return base_penalty_msat;
757773 }
758774 } ,
759775 EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_maximum_msat) } => {
@@ -774,6 +790,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
774790 . as_directed ( source, target, capacity_msat, liquidity_offset_half_life)
775791 . penalty_msat ( amount_msat, & self . params )
776792 . saturating_add ( anti_probing_penalty_msat)
793+ . saturating_add ( base_penalty_msat)
777794 }
778795
779796 fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
@@ -2048,47 +2065,47 @@ mod tests {
20482065 inflight_htlc_msat : 0 ,
20492066 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
20502067 } ;
2051- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 3613 ) ;
2068+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 4375 ) ;
20522069 let usage = ChannelUsage {
20532070 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20542071 } ;
2055- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1977 ) ;
2072+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2739 ) ;
20562073 let usage = ChannelUsage {
20572074 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20582075 } ;
2059- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1474 ) ;
2076+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2236 ) ;
20602077 let usage = ChannelUsage {
20612078 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20622079 } ;
2063- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1223 ) ;
2080+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1985 ) ;
20642081 let usage = ChannelUsage {
20652082 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20662083 } ;
2067- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 877 ) ;
2084+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1639 ) ;
20682085 let usage = ChannelUsage {
20692086 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20702087 } ;
2071- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 845 ) ;
2088+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1607 ) ;
20722089 let usage = ChannelUsage {
20732090 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20742091 } ;
2075- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2092+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20762093 let usage = ChannelUsage {
20772094 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20782095 } ;
2079- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2096+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20802097 let usage = ChannelUsage {
20812098 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20822099 } ;
2083- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2100+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20842101 let usage = ChannelUsage {
20852102 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20862103 } ;
2087- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2104+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20882105 let usage = ChannelUsage {
20892106 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20902107 } ;
2091- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2108+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20922109 }
20932110
20942111 #[ test]
@@ -2116,6 +2133,15 @@ mod tests {
21162133 } ;
21172134 let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
21182135 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 ) ;
2136+
2137+ let params = ProbabilisticScoringParameters {
2138+ base_penalty_msat : 500 , liquidity_penalty_multiplier_msat : 1_000 ,
2139+ base_penalty_amount_multiplier_msat : ( 1 <<30 ) ,
2140+ anti_probing_penalty_msat : 0 , ..Default :: default ( )
2141+ } ;
2142+
2143+ let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2144+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 + 128 ) ;
21192145 }
21202146
21212147 #[ test]
0 commit comments