@@ -324,13 +324,30 @@ where L::Target: Logger {
324
324
///
325
325
/// Used to configure base, liquidity, and amount penalties, the sum of which comprises the channel
326
326
/// 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.
327
330
#[ derive( Clone ) ]
328
331
pub struct ProbabilisticScoringParameters {
329
332
/// A fixed penalty in msats to apply to each channel.
330
333
///
331
334
/// Default value: 500 msat
332
335
pub base_penalty_msat : u64 ,
333
336
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
+
334
351
/// A multiplier used in conjunction with the negative `log10` of the channel's success
335
352
/// probability for a payment to determine the liquidity penalty.
336
353
///
@@ -369,7 +386,7 @@ pub struct ProbabilisticScoringParameters {
369
386
/// multiplier and `2^20`ths of the payment amount, weighted by the negative `log10` of the
370
387
/// success probability.
371
388
///
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`
373
390
///
374
391
/// In practice, this means for 0.1 success probability (`-log10(0.1) == 1`) each `2^20`th of
375
392
/// the amount will result in a penalty of the multiplier. And, as the success probability
@@ -378,7 +395,7 @@ pub struct ProbabilisticScoringParameters {
378
395
/// fall below `1`.
379
396
///
380
397
/// Default value: 256 msat
381
- pub amount_penalty_multiplier_msat : u64 ,
398
+ pub liquidity_penalty_amount_multiplier_msat : u64 ,
382
399
383
400
/// Manual penalties used for the given nodes. Allows to set a particular penalty for a given
384
401
/// node. Note that a manual penalty of `u64::max_value()` means the node would not ever be
@@ -399,7 +416,7 @@ pub struct ProbabilisticScoringParameters {
399
416
/// current estimate of the channel's available liquidity.
400
417
///
401
418
/// 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
403
420
/// penalties, as well as the [`base_penalty_msat`] and the [`anti_probing_penalty_msat`], if
404
421
/// applicable, are still included in the overall penalty.
405
422
///
@@ -409,7 +426,7 @@ pub struct ProbabilisticScoringParameters {
409
426
/// Default value: 1_0000_0000_000 msat (1 Bitcoin)
410
427
///
411
428
/// [`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
413
430
/// [`base_penalty_msat`]: Self::base_penalty_msat
414
431
/// [`anti_probing_penalty_msat`]: Self::anti_probing_penalty_msat
415
432
pub considered_impossible_penalty_msat : u64 ,
@@ -536,9 +553,10 @@ impl ProbabilisticScoringParameters {
536
553
fn zero_penalty ( ) -> Self {
537
554
Self {
538
555
base_penalty_msat : 0 ,
556
+ base_penalty_amount_multiplier_msat : 0 ,
539
557
liquidity_penalty_multiplier_msat : 0 ,
540
558
liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
541
- amount_penalty_multiplier_msat : 0 ,
559
+ liquidity_penalty_amount_multiplier_msat : 0 ,
542
560
manual_node_penalties : HashMap :: new ( ) ,
543
561
anti_probing_penalty_msat : 0 ,
544
562
considered_impossible_penalty_msat : 0 ,
@@ -558,9 +576,10 @@ impl Default for ProbabilisticScoringParameters {
558
576
fn default ( ) -> Self {
559
577
Self {
560
578
base_penalty_msat : 500 ,
579
+ base_penalty_amount_multiplier_msat : 8192 ,
561
580
liquidity_penalty_multiplier_msat : 40_000 ,
562
581
liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
563
- amount_penalty_multiplier_msat : 256 ,
582
+ liquidity_penalty_amount_multiplier_msat : 256 ,
564
583
manual_node_penalties : HashMap :: new ( ) ,
565
584
anti_probing_penalty_msat : 250 ,
566
585
considered_impossible_penalty_msat : 1_0000_0000_000 ,
@@ -631,10 +650,11 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
631
650
632
651
/// The divisor used when computing the amount penalty.
633
652
const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
653
+ const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
634
654
635
655
impl < 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.
638
658
fn penalty_msat ( & self , amount_msat : u64 , params : & ProbabilisticScoringParameters ) -> u64 {
639
659
let max_liquidity_msat = self . max_liquidity_msat ( ) ;
640
660
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
653
673
if amount_msat - min_liquidity_msat < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
654
674
// If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
655
675
// 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
658
678
} else {
659
679
let negative_log10_times_2048 =
660
680
approx:: negative_log10_times_2048 ( numerator, denominator) ;
@@ -663,7 +683,7 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
663
683
}
664
684
}
665
685
666
- /// Computes the liquidity and amount penalties and adds them to the base penalty.
686
+ /// Computes the liquidity penalty from the penalty multipliers .
667
687
#[ inline( always) ]
668
688
fn combined_penalty_msat (
669
689
& 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
676
696
( negative_log10_times_2048. saturating_mul ( multiplier_msat) / 2048 ) . min ( max_penalty_msat)
677
697
} ;
678
698
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 )
680
700
. saturating_mul ( amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR ;
681
701
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)
685
703
}
686
704
687
705
/// 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
763
781
return * penalty;
764
782
}
765
783
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
+
766
788
let mut anti_probing_penalty_msat = 0 ;
767
789
match usage. effective_capacity {
768
790
EffectiveCapacity :: ExactLiquidity { liquidity_msat } => {
769
791
if usage. amount_msat > liquidity_msat {
770
792
return u64:: max_value ( ) ;
771
793
} else {
772
- return self . params . base_penalty_msat ;
794
+ return base_penalty_msat;
773
795
}
774
796
} ,
775
797
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
790
812
. as_directed ( source, target, capacity_msat, liquidity_offset_half_life)
791
813
. penalty_msat ( amount_msat, & self . params )
792
814
. saturating_add ( anti_probing_penalty_msat)
815
+ . saturating_add ( base_penalty_msat)
793
816
}
794
817
795
818
fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
@@ -2069,47 +2092,47 @@ mod tests {
2069
2092
inflight_htlc_msat : 0 ,
2070
2093
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
2071
2094
} ;
2072
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 3613 ) ;
2095
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 4375 ) ;
2073
2096
let usage = ChannelUsage {
2074
2097
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2075
2098
} ;
2076
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1977 ) ;
2099
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2739 ) ;
2077
2100
let usage = ChannelUsage {
2078
2101
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2079
2102
} ;
2080
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1474 ) ;
2103
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 2236 ) ;
2081
2104
let usage = ChannelUsage {
2082
2105
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2083
2106
} ;
2084
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1223 ) ;
2107
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1985 ) ;
2085
2108
let usage = ChannelUsage {
2086
2109
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2087
2110
} ;
2088
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 877 ) ;
2111
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1639 ) ;
2089
2112
let usage = ChannelUsage {
2090
2113
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2091
2114
} ;
2092
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 845 ) ;
2115
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1607 ) ;
2093
2116
let usage = ChannelUsage {
2094
2117
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2095
2118
} ;
2096
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2119
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2097
2120
let usage = ChannelUsage {
2098
2121
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2099
2122
} ;
2100
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2123
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2101
2124
let usage = ChannelUsage {
2102
2125
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2103
2126
} ;
2104
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2127
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2105
2128
let usage = ChannelUsage {
2106
2129
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2107
2130
} ;
2108
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2131
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2109
2132
let usage = ChannelUsage {
2110
2133
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2111
2134
} ;
2112
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2135
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1262 ) ;
2113
2136
}
2114
2137
2115
2138
#[ test]
@@ -2137,6 +2160,15 @@ mod tests {
2137
2160
} ;
2138
2161
let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2139
2162
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 ) ;
2140
2172
}
2141
2173
2142
2174
#[ test]
@@ -2153,15 +2185,15 @@ mod tests {
2153
2185
2154
2186
let params = ProbabilisticScoringParameters {
2155
2187
liquidity_penalty_multiplier_msat : 1_000 ,
2156
- amount_penalty_multiplier_msat : 0 ,
2188
+ liquidity_penalty_amount_multiplier_msat : 0 ,
2157
2189
..ProbabilisticScoringParameters :: zero_penalty ( )
2158
2190
} ;
2159
2191
let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2160
2192
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 300 ) ;
2161
2193
2162
2194
let params = ProbabilisticScoringParameters {
2163
2195
liquidity_penalty_multiplier_msat : 1_000 ,
2164
- amount_penalty_multiplier_msat : 256 ,
2196
+ liquidity_penalty_amount_multiplier_msat : 256 ,
2165
2197
..ProbabilisticScoringParameters :: zero_penalty ( )
2166
2198
} ;
2167
2199
let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
0 commit comments