@@ -324,13 +324,30 @@ where L::Target: Logger {
324324///
325325/// Used to configure base, liquidity, and amount penalties, the sum of which comprises the channel
326326/// penalty (i.e., the amount in msats willing to be paid to avoid routing through the channel).
327+ ///
328+ /// The penalty applied to any channel by the [`ProbabilisticScorer`] is the sum of each of the
329+ /// parameters here.
327330#[ derive( Clone ) ]
328331pub struct ProbabilisticScoringParameters {
329332 /// A fixed penalty in msats to apply to each channel.
330333 ///
331334 /// Default value: 500 msat
332335 pub base_penalty_msat : u64 ,
333336
337+ /// A multiplier used with the payment amount to calculate a fixed penalty applied to each
338+ /// channel, in excess of the [`base_penalty_msat`].
339+ ///
340+ /// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e.,
341+ /// fees plus penalty) for large payments. The penalty is computed as the product of this
342+ /// multiplier and `2^30`ths of the payment amount.
343+ ///
344+ /// ie `base_penalty_amount_multiplier_msat * amount_msat / 2^30`
345+ ///
346+ /// Default value: 8,192 msat
347+ ///
348+ /// [`base_penalty_msat`]: Self::base_penalty_msat
349+ pub base_penalty_amount_multiplier_msat : u64 ,
350+
334351 /// A multiplier used in conjunction with the negative `log10` of the channel's success
335352 /// probability for a payment to determine the liquidity penalty.
336353 ///
@@ -369,7 +386,7 @@ pub struct ProbabilisticScoringParameters {
369386 /// multiplier and `2^20`ths of the payment amount, weighted by the negative `log10` of the
370387 /// success probability.
371388 ///
372- /// `-log10(success_probability) * amount_penalty_multiplier_msat * amount_msat / 2^20`
389+ /// `-log10(success_probability) * liquidity_penalty_amount_multiplier_msat * amount_msat / 2^20`
373390 ///
374391 /// In practice, this means for 0.1 success probability (`-log10(0.1) == 1`) each `2^20`th of
375392 /// the amount will result in a penalty of the multiplier. And, as the success probability
@@ -378,7 +395,7 @@ pub struct ProbabilisticScoringParameters {
378395 /// fall below `1`.
379396 ///
380397 /// Default value: 256 msat
381- pub amount_penalty_multiplier_msat : u64 ,
398+ pub liquidity_penalty_amount_multiplier_msat : u64 ,
382399
383400 /// Manual penalties used for the given nodes. Allows to set a particular penalty for a given
384401 /// node. Note that a manual penalty of `u64::max_value()` means the node would not ever be
@@ -399,7 +416,7 @@ pub struct ProbabilisticScoringParameters {
399416 /// current estimate of the channel's available liquidity.
400417 ///
401418 /// Note that in this case all other penalties, including the
402- /// [`liquidity_penalty_multiplier_msat`] and [`amount_penalty_multiplier_msat `]-based
419+ /// [`liquidity_penalty_multiplier_msat`] and [`liquidity_penalty_amount_multiplier_msat `]-based
403420 /// penalties, as well as the [`base_penalty_msat`] and the [`anti_probing_penalty_msat`], if
404421 /// applicable, are still included in the overall penalty.
405422 ///
@@ -409,7 +426,7 @@ pub struct ProbabilisticScoringParameters {
409426 /// Default value: 1_0000_0000_000 msat (1 Bitcoin)
410427 ///
411428 /// [`liquidity_penalty_multiplier_msat`]: Self::liquidity_penalty_multiplier_msat
412- /// [`amount_penalty_multiplier_msat `]: Self::amount_penalty_multiplier_msat
429+ /// [`liquidity_penalty_amount_multiplier_msat `]: Self::liquidity_penalty_amount_multiplier_msat
413430 /// [`base_penalty_msat`]: Self::base_penalty_msat
414431 /// [`anti_probing_penalty_msat`]: Self::anti_probing_penalty_msat
415432 pub considered_impossible_penalty_msat : u64 ,
@@ -536,9 +553,10 @@ impl ProbabilisticScoringParameters {
536553 fn zero_penalty ( ) -> Self {
537554 Self {
538555 base_penalty_msat : 0 ,
556+ base_penalty_amount_multiplier_msat : 0 ,
539557 liquidity_penalty_multiplier_msat : 0 ,
540558 liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
541- amount_penalty_multiplier_msat : 0 ,
559+ liquidity_penalty_amount_multiplier_msat : 0 ,
542560 manual_node_penalties : HashMap :: new ( ) ,
543561 anti_probing_penalty_msat : 0 ,
544562 considered_impossible_penalty_msat : 0 ,
@@ -558,9 +576,10 @@ impl Default for ProbabilisticScoringParameters {
558576 fn default ( ) -> Self {
559577 Self {
560578 base_penalty_msat : 500 ,
579+ base_penalty_amount_multiplier_msat : 8192 ,
561580 liquidity_penalty_multiplier_msat : 40_000 ,
562581 liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
563- amount_penalty_multiplier_msat : 256 ,
582+ liquidity_penalty_amount_multiplier_msat : 256 ,
564583 manual_node_penalties : HashMap :: new ( ) ,
565584 anti_probing_penalty_msat : 250 ,
566585 considered_impossible_penalty_msat : 1_0000_0000_000 ,
@@ -631,10 +650,11 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
631650
632651/// The divisor used when computing the amount penalty.
633652const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
653+ const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
634654
635655impl < 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.
656+ /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
657+ /// this direction.
638658 fn penalty_msat ( & self , amount_msat : u64 , params : & ProbabilisticScoringParameters ) -> u64 {
639659 let max_liquidity_msat = self . max_liquidity_msat ( ) ;
640660 let min_liquidity_msat = core:: cmp:: min ( self . min_liquidity_msat ( ) , max_liquidity_msat) ;
@@ -653,8 +673,8 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
653673 if amount_msat - min_liquidity_msat < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
654674 // If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
655675 // 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
676+ // particularly helpful, instead just round down to 0.
677+ 0
658678 } else {
659679 let negative_log10_times_2048 =
660680 approx:: negative_log10_times_2048 ( numerator, denominator) ;
@@ -663,7 +683,7 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
663683 }
664684 }
665685
666- /// Computes the liquidity and amount penalties and adds them to the base penalty.
686+ /// Computes the liquidity penalty from the penalty multipliers .
667687 #[ inline( always) ]
668688 fn combined_penalty_msat (
669689 & self , amount_msat : u64 , negative_log10_times_2048 : u64 ,
@@ -676,12 +696,10 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
676696 ( negative_log10_times_2048. saturating_mul ( multiplier_msat) / 2048 ) . min ( max_penalty_msat)
677697 } ;
678698 let amount_penalty_msat = negative_log10_times_2048
679- . saturating_mul ( params. amount_penalty_multiplier_msat )
699+ . saturating_mul ( params. liquidity_penalty_amount_multiplier_msat )
680700 . saturating_mul ( amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR ;
681701
682- params. base_penalty_msat
683- . saturating_add ( liquidity_penalty_msat)
684- . saturating_add ( amount_penalty_msat)
702+ liquidity_penalty_msat. saturating_add ( amount_penalty_msat)
685703 }
686704
687705 /// Returns the lower bound of the channel liquidity balance in this direction.
@@ -763,13 +781,17 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
763781 return * penalty;
764782 }
765783
784+ let base_penalty_msat = self . params . base_penalty_msat . saturating_add (
785+ self . params . base_penalty_amount_multiplier_msat
786+ . saturating_mul ( usage. amount_msat ) / BASE_AMOUNT_PENALTY_DIVISOR ) ;
787+
766788 let mut anti_probing_penalty_msat = 0 ;
767789 match usage. effective_capacity {
768790 EffectiveCapacity :: ExactLiquidity { liquidity_msat } => {
769791 if usage. amount_msat > liquidity_msat {
770792 return u64:: max_value ( ) ;
771793 } else {
772- return self . params . base_penalty_msat ;
794+ return base_penalty_msat;
773795 }
774796 } ,
775797 EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_maximum_msat) } => {
@@ -790,6 +812,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
790812 . as_directed ( source, target, capacity_msat, liquidity_offset_half_life)
791813 . penalty_msat ( amount_msat, & self . params )
792814 . saturating_add ( anti_probing_penalty_msat)
815+ . saturating_add ( base_penalty_msat)
793816 }
794817
795818 fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
@@ -2069,47 +2092,47 @@ mod tests {
20692092 inflight_htlc_msat : 0 ,
20702093 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
20712094 } ;
2072- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 3613 ) ;
2095+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 4375 ) ;
20732096 let usage = ChannelUsage {
20742097 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20752098 } ;
2076- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1977 ) ;
2099+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2739 ) ;
20772100 let usage = ChannelUsage {
20782101 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20792102 } ;
2080- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1474 ) ;
2103+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2236 ) ;
20812104 let usage = ChannelUsage {
20822105 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20832106 } ;
2084- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1223 ) ;
2107+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1985 ) ;
20852108 let usage = ChannelUsage {
20862109 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20872110 } ;
2088- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 877 ) ;
2111+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1639 ) ;
20892112 let usage = ChannelUsage {
20902113 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20912114 } ;
2092- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 845 ) ;
2115+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1607 ) ;
20932116 let usage = ChannelUsage {
20942117 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20952118 } ;
2096- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2119+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
20972120 let usage = ChannelUsage {
20982121 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
20992122 } ;
2100- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2123+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21012124 let usage = ChannelUsage {
21022125 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
21032126 } ;
2104- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2127+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21052128 let usage = ChannelUsage {
21062129 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
21072130 } ;
2108- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2131+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21092132 let usage = ChannelUsage {
21102133 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
21112134 } ;
2112- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2135+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
21132136 }
21142137
21152138 #[ test]
@@ -2137,6 +2160,15 @@ mod tests {
21372160 } ;
21382161 let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
21392162 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 ) ;
2163+
2164+ let params = ProbabilisticScoringParameters {
2165+ base_penalty_msat : 500 , liquidity_penalty_multiplier_msat : 1_000 ,
2166+ base_penalty_amount_multiplier_msat : ( 1 << 30 ) ,
2167+ anti_probing_penalty_msat : 0 , ..Default :: default ( )
2168+ } ;
2169+
2170+ let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2171+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 + 128 ) ;
21402172 }
21412173
21422174 #[ test]
@@ -2153,15 +2185,15 @@ mod tests {
21532185
21542186 let params = ProbabilisticScoringParameters {
21552187 liquidity_penalty_multiplier_msat : 1_000 ,
2156- amount_penalty_multiplier_msat : 0 ,
2188+ liquidity_penalty_amount_multiplier_msat : 0 ,
21572189 ..ProbabilisticScoringParameters :: zero_penalty ( )
21582190 } ;
21592191 let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
21602192 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 300 ) ;
21612193
21622194 let params = ProbabilisticScoringParameters {
21632195 liquidity_penalty_multiplier_msat : 1_000 ,
2164- amount_penalty_multiplier_msat : 256 ,
2196+ liquidity_penalty_amount_multiplier_msat : 256 ,
21652197 ..ProbabilisticScoringParameters :: zero_penalty ( )
21662198 } ;
21672199 let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
0 commit comments