@@ -580,6 +580,28 @@ pub struct ProbabilisticScoringFeeParameters {
580
580
/// [`base_penalty_msat`]: Self::base_penalty_msat
581
581
/// [`anti_probing_penalty_msat`]: Self::anti_probing_penalty_msat
582
582
pub considered_impossible_penalty_msat : u64 ,
583
+
584
+ /// In order to calculate most of the scores above, we must first convert a lower and upper
585
+ /// bound on the available liquidity in a channel into the probability that we think a payment
586
+ /// will succeed. That probability is derived from a Probability Density Function for where we
587
+ /// think the liquidity in a channel likely lies, given such bounds.
588
+ ///
589
+ /// If this flag is set, that PDF is simply a constant - we assume that the actual available
590
+ /// liquidity in a channel is just as likely to be at any point between our lower and upper
591
+ /// bounds.
592
+ ///
593
+ /// If this flag is *not* set, that PDF is `(x - 0.5*capacity) ^ 2`. That is, we use an
594
+ /// exponential curve which expects the liquidity of a channel to lie "at the edges". This
595
+ /// matches experimental results - most routing nodes do not aggressively rebalance their
596
+ /// channels and flows in the network are often unbalanced, leaving liquidity usually
597
+ /// unavailable.
598
+ ///
599
+ /// Thus, for the "best" routes, leave this flag `false`. However, the flag does imply a number
600
+ /// of floating-point multiplications in the hottest routing code, which may lead to routing
601
+ /// performance degradation on some machines.
602
+ ///
603
+ /// Default value: false
604
+ pub linear_success_probability : bool ,
583
605
}
584
606
585
607
impl Default for ProbabilisticScoringFeeParameters {
@@ -594,6 +616,7 @@ impl Default for ProbabilisticScoringFeeParameters {
594
616
considered_impossible_penalty_msat : 1_0000_0000_000 ,
595
617
historical_liquidity_penalty_multiplier_msat : 10_000 ,
596
618
historical_liquidity_penalty_amount_multiplier_msat : 64 ,
619
+ linear_success_probability : false ,
597
620
}
598
621
}
599
622
}
@@ -647,6 +670,7 @@ impl ProbabilisticScoringFeeParameters {
647
670
manual_node_penalties : HashMap :: new ( ) ,
648
671
anti_probing_penalty_msat : 0 ,
649
672
considered_impossible_penalty_msat : 0 ,
673
+ linear_success_probability : true ,
650
674
}
651
675
}
652
676
}
@@ -999,6 +1023,12 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
999
1023
const AMOUNT_PENALTY_DIVISOR : u64 = 1 << 20 ;
1000
1024
const BASE_AMOUNT_PENALTY_DIVISOR : u64 = 1 << 30 ;
1001
1025
1026
+ /// Raises three `f64`s to the 3rd power, without `powi` because it requires `std` (dunno why).
1027
+ #[ inline( always) ]
1028
+ fn three_f64_pow_3 ( a : f64 , b : f64 , c : f64 ) -> ( f64 , f64 , f64 ) {
1029
+ ( a * a * a, b * b * b, c * c * c)
1030
+ }
1031
+
1002
1032
/// Given liquidity bounds, calculates the success probability (in the form of a numerator and
1003
1033
/// denominator) of an HTLC. This is a key assumption in our scoring models.
1004
1034
///
@@ -1009,14 +1039,46 @@ const BASE_AMOUNT_PENALTY_DIVISOR: u64 = 1 << 30;
1009
1039
#[ inline( always) ]
1010
1040
fn success_probability (
1011
1041
amount_msat : u64 , min_liquidity_msat : u64 , max_liquidity_msat : u64 , capacity_msat : u64 ,
1012
- _params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
1042
+ params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
1013
1043
) -> ( u64 , u64 ) {
1014
1044
debug_assert ! ( min_liquidity_msat <= amount_msat) ;
1015
1045
debug_assert ! ( amount_msat < max_liquidity_msat) ;
1016
1046
debug_assert ! ( max_liquidity_msat <= capacity_msat) ;
1017
1047
1018
- let numerator = max_liquidity_msat - amount_msat;
1019
- let mut denominator = ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) ;
1048
+ let ( numerator, mut denominator) =
1049
+ if params. linear_success_probability {
1050
+ ( max_liquidity_msat - amount_msat,
1051
+ ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) )
1052
+ } else {
1053
+ let capacity = capacity_msat as f64 ;
1054
+ let min = ( min_liquidity_msat as f64 ) / capacity;
1055
+ let max = ( max_liquidity_msat as f64 ) / capacity;
1056
+ let amount = ( amount_msat as f64 ) / capacity;
1057
+
1058
+ // Assume the channel has a probability density function of (x - 0.5)^2 for values from
1059
+ // 0 to 1 (where 1 is the channel's full capacity). The success probability given some
1060
+ // liquidity bounds is thus the integral under the curve from the amount to maximum
1061
+ // estimated liquidity, divided by the same integral from the minimum to the maximum
1062
+ // estimated liquidity bounds.
1063
+ //
1064
+ // Because the integral from x to y is simply (y - 0.5)^3 - (x - 0.5)^3, we can
1065
+ // calculate the cumulative density function between the min/max bounds trivially. Note
1066
+ // that we don't bother to normalize the CDF to total to 1, as it will come out in the
1067
+ // division of num / den.
1068
+ let ( max_pow, amt_pow, min_pow) = three_f64_pow_3 ( max - 0.5 , amount - 0.5 , min - 0.5 ) ;
1069
+ let num = max_pow - amt_pow;
1070
+ let den = max_pow - min_pow;
1071
+
1072
+ // Because our numerator and denominator max out at 0.5^3 we need to multiply them by
1073
+ // quite a large factor to get something useful (ideally in the 2^30 range).
1074
+ const BILLIONISH : f64 = 1024.0 * 1024.0 * 1024.0 ;
1075
+ let numerator = ( num * BILLIONISH ) as u64 + 1 ;
1076
+ let denominator = ( den * BILLIONISH ) as u64 + 1 ;
1077
+ debug_assert ! ( numerator <= 1 << 30 , "Got large numerator ({}) from float {}." , numerator, num) ;
1078
+ debug_assert ! ( denominator <= 1 << 30 , "Got large denominator ({}) from float {}." , denominator, den) ;
1079
+ ( numerator, denominator)
1080
+ } ;
1081
+
1020
1082
if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
1021
1083
denominator < u64:: max_value ( ) / 21
1022
1084
{
@@ -2964,47 +3026,47 @@ mod tests {
2964
3026
inflight_htlc_msat : 0 ,
2965
3027
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : 1_000 } ,
2966
3028
} ;
2967
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 6262 ) ;
3029
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 11497 ) ;
2968
3030
let usage = ChannelUsage {
2969
3031
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2970
3032
} ;
2971
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4634 ) ;
3033
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 7408 ) ;
2972
3034
let usage = ChannelUsage {
2973
3035
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2974
3036
} ;
2975
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4186 ) ;
3037
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 6151 ) ;
2976
3038
let usage = ChannelUsage {
2977
3039
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2978
3040
} ;
2979
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3909 ) ;
3041
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5427 ) ;
2980
3042
let usage = ChannelUsage {
2981
3043
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2982
3044
} ;
2983
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3556 ) ;
3045
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4955 ) ;
2984
3046
let usage = ChannelUsage {
2985
3047
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2986
3048
} ;
2987
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3533 ) ;
3049
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4736 ) ;
2988
3050
let usage = ChannelUsage {
2989
3051
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2990
3052
} ;
2991
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3172 ) ;
3053
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4484 ) ;
2992
3054
let usage = ChannelUsage {
2993
3055
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2994
3056
} ;
2995
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3211 ) ;
3057
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4484 ) ;
2996
3058
let usage = ChannelUsage {
2997
3059
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2998
3060
} ;
2999
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3243 ) ;
3061
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4263 ) ;
3000
3062
let usage = ChannelUsage {
3001
3063
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3002
3064
} ;
3003
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3297 ) ;
3065
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4263 ) ;
3004
3066
let usage = ChannelUsage {
3005
3067
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3006
3068
} ;
3007
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3250 ) ;
3069
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4044 ) ;
3008
3070
}
3009
3071
3010
3072
#[ test]
0 commit comments