@@ -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 ///
@@ -536,6 +547,7 @@ impl ProbabilisticScoringParameters {
536547 fn zero_penalty ( ) -> Self {
537548 Self {
538549 base_penalty_msat : 0 ,
550+ base_penalty_amount_multiplier_msat : 0 ,
539551 liquidity_penalty_multiplier_msat : 0 ,
540552 liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
541553 amount_penalty_multiplier_msat : 0 ,
@@ -558,6 +570,7 @@ impl Default for ProbabilisticScoringParameters {
558570 fn default ( ) -> Self {
559571 Self {
560572 base_penalty_msat : 500 ,
573+ base_penalty_amount_multiplier_msat : 8192 ,
561574 liquidity_penalty_multiplier_msat : 40_000 ,
562575 liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
563576 amount_penalty_multiplier_msat : 256 ,
@@ -631,10 +644,11 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
631644
632645/// The divisor used when computing the amount penalty.
633646const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
647+ const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
634648
635649impl < L : Deref < Target = u64 > , T : Time , U : Deref < Target = T > > DirectedChannelLiquidity < L , T , U > {
636- /// Returns a penalty for routing the given HTLC `amount_msat` through the channel in this
637- /// direction.
650+ /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
651+ /// this direction.
638652 fn penalty_msat ( & self , amount_msat : u64 , params : & ProbabilisticScoringParameters ) -> u64 {
639653 let max_liquidity_msat = self . max_liquidity_msat ( ) ;
640654 let min_liquidity_msat = core:: cmp:: min ( self . min_liquidity_msat ( ) , max_liquidity_msat) ;
@@ -653,8 +667,8 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
653667 if amount_msat - min_liquidity_msat < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
654668 // If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
655669 // don't bother trying to use the log approximation as it gets too noisy to be
656- // particularly helpful, instead just round down to 0 and return the base penalty .
657- params . base_penalty_msat
670+ // particularly helpful, instead just round down to 0.
671+ 0
658672 } else {
659673 let negative_log10_times_2048 =
660674 approx:: negative_log10_times_2048 ( numerator, denominator) ;
@@ -679,9 +693,7 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
679693 . saturating_mul ( params. amount_penalty_multiplier_msat )
680694 . saturating_mul ( amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR ;
681695
682- params. base_penalty_msat
683- . saturating_add ( liquidity_penalty_msat)
684- . saturating_add ( amount_penalty_msat)
696+ liquidity_penalty_msat. saturating_add ( amount_penalty_msat)
685697 }
686698
687699 /// Returns the lower bound of the channel liquidity balance in this direction.
@@ -763,13 +775,17 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
763775 return * penalty;
764776 }
765777
778+ let base_penalty_msat = self . params . base_penalty_msat . saturating_add (
779+ self . params . base_penalty_amount_multiplier_msat
780+ . saturating_mul ( usage. amount_msat ) / BASE_AMOUNT_PENALTY_DIVISOR ) ;
781+
766782 let mut anti_probing_penalty_msat = 0 ;
767783 match usage. effective_capacity {
768784 EffectiveCapacity :: ExactLiquidity { liquidity_msat } => {
769785 if usage. amount_msat > liquidity_msat {
770786 return u64:: max_value ( ) ;
771787 } else {
772- return self . params . base_penalty_msat ;
788+ return base_penalty_msat;
773789 }
774790 } ,
775791 EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_maximum_msat) } => {
@@ -790,6 +806,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
790806 . as_directed ( source, target, capacity_msat, liquidity_offset_half_life)
791807 . penalty_msat ( amount_msat, & self . params )
792808 . saturating_add ( anti_probing_penalty_msat)
809+ . saturating_add ( base_penalty_msat)
793810 }
794811
795812 fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
@@ -2069,47 +2086,47 @@ mod tests {
20692086 inflight_htlc_msat : 0 ,
20702087 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
20712088 } ;
2072- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 3613 ) ;
2089+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 4375 ) ;
20732090 let usage = ChannelUsage {
20742091 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20752092 } ;
2076- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1977 ) ;
2093+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2739 ) ;
20772094 let usage = ChannelUsage {
20782095 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20792096 } ;
2080- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1474 ) ;
2097+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2236 ) ;
20812098 let usage = ChannelUsage {
20822099 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20832100 } ;
2084- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1223 ) ;
2101+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1985 ) ;
20852102 let usage = ChannelUsage {
20862103 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20872104 } ;
2088- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 877 ) ;
2105+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1639 ) ;
20892106 let usage = ChannelUsage {
20902107 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20912108 } ;
2092- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 845 ) ;
2109+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1607 ) ;
20932110 let usage = ChannelUsage {
20942111 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20952112 } ;
2096- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2113+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20972114 let usage = ChannelUsage {
20982115 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20992116 } ;
2100- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2117+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21012118 let usage = ChannelUsage {
21022119 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
21032120 } ;
2104- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2121+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21052122 let usage = ChannelUsage {
21062123 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
21072124 } ;
2108- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2125+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21092126 let usage = ChannelUsage {
21102127 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
21112128 } ;
2112- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2129+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21132130 }
21142131
21152132 #[ test]
@@ -2137,6 +2154,15 @@ mod tests {
21372154 } ;
21382155 let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
21392156 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 ) ;
2157+
2158+ let params = ProbabilisticScoringParameters {
2159+ base_penalty_msat : 500 , liquidity_penalty_multiplier_msat : 1_000 ,
2160+ base_penalty_amount_multiplier_msat : ( 1 <<30 ) ,
2161+ anti_probing_penalty_msat : 0 , ..Default :: default ( )
2162+ } ;
2163+
2164+ let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2165+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 + 128 ) ;
21402166 }
21412167
21422168 #[ test]
0 commit comments