@@ -576,6 +576,28 @@ pub struct ProbabilisticScoringFeeParameters {
576
576
/// [`base_penalty_msat`]: Self::base_penalty_msat
577
577
/// [`anti_probing_penalty_msat`]: Self::anti_probing_penalty_msat
578
578
pub considered_impossible_penalty_msat : u64 ,
579
+
580
+ /// In order to calculate most of the scores above, we must first convert a lower and upper
581
+ /// bound on the available liquidity in a channel into the probability that we think a payment
582
+ /// will succeed. That probability is derived from a Probability Density Function for where we
583
+ /// think the liquidity in a channel likely lies, given such bounds.
584
+ ///
585
+ /// If this flag is set, that PDF is simply a constant - we assume that the actual available
586
+ /// liquidity in a channel is just as likely to be at any point between our lower and upper
587
+ /// bounds.
588
+ ///
589
+ /// If this flag is *not* set, that PDF is `(x - 0.5*capacity) ^ 6`. That is, we use an
590
+ /// exponential curve which expects the liquidity of a channel to lie "at the edges". This
591
+ /// matches experimental results - most routing nodes do not aggressively rebalance their
592
+ /// channels and flows in the network are often unbalanced, leaving liquidity usually
593
+ /// unavailable.
594
+ ///
595
+ /// Thus, for the "best" routes, leave this flag `false`. However, the flag does imply a number
596
+ /// of floating-point multiplications in the hottest routing code, which may lead to routing
597
+ /// performance degradation on some machines.
598
+ ///
599
+ /// Default value: false
600
+ pub linear_success_probability : bool ,
579
601
}
580
602
581
603
impl Default for ProbabilisticScoringFeeParameters {
@@ -590,6 +612,7 @@ impl Default for ProbabilisticScoringFeeParameters {
590
612
considered_impossible_penalty_msat : 1_0000_0000_000 ,
591
613
historical_liquidity_penalty_multiplier_msat : 10_000 ,
592
614
historical_liquidity_penalty_amount_multiplier_msat : 64 ,
615
+ linear_success_probability : false ,
593
616
}
594
617
}
595
618
}
@@ -643,6 +666,7 @@ impl ProbabilisticScoringFeeParameters {
643
666
manual_node_penalties : HashMap :: new ( ) ,
644
667
anti_probing_penalty_msat : 0 ,
645
668
considered_impossible_penalty_msat : 0 ,
669
+ linear_success_probability : true ,
646
670
}
647
671
}
648
672
}
@@ -1008,14 +1032,42 @@ const BASE_AMOUNT_PENALTY_DIVISOR: u64 = 1 << 30;
1008
1032
/// seen an HTLC successfully complete over this channel.
1009
1033
fn success_probability (
1010
1034
min_liquidity_msat : u64 , amount_msat : u64 , max_liquidity_msat : u64 , capacity_msat : u64 ,
1011
- _params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
1035
+ params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
1012
1036
) -> ( u64 , u64 ) {
1013
1037
debug_assert ! ( min_liquidity_msat <= amount_msat) ;
1014
1038
debug_assert ! ( amount_msat < max_liquidity_msat) ;
1015
1039
debug_assert ! ( max_liquidity_msat <= capacity_msat) ;
1016
1040
1017
- let numerator = max_liquidity_msat - amount_msat;
1018
- let mut denominator = ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) ;
1041
+ let ( numerator, mut denominator) =
1042
+ if params. linear_success_probability {
1043
+ ( max_liquidity_msat - amount_msat,
1044
+ ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) )
1045
+ } else {
1046
+ let capacity = capacity_msat as f64 ;
1047
+ let min = ( min_liquidity_msat as f64 ) / capacity;
1048
+ let max = ( max_liquidity_msat as f64 ) / capacity;
1049
+ let amount = ( amount_msat as f64 ) / capacity;
1050
+
1051
+ // Assume the channel has a probability density function of (x - 0.5)^6 for values from 0 to 1
1052
+ // (where 1 is the channel's full capacity). The success probability given some liquidity
1053
+ // bounds is thus the integral under the curve from the minimum liquidity to the amount,
1054
+ // divided by the same integral from the minimum to the maximum liquidity bounds.
1055
+ //
1056
+ // For (x - 0.5)^7, this means simply subtracting the two bounds mius 0.5 to the 7th power.
1057
+ let max_pow = ( max - 0.5 ) . powi ( 7 ) ;
1058
+ let num = max_pow - ( amount - 0.5 ) . powi ( 7 ) ;
1059
+ let den = max_pow - ( min - 0.5 ) . powi ( 7 ) ;
1060
+
1061
+ // Because our numerator and denominator max out at 2^-6 we need to multiply them by
1062
+ // quite a large factor to get something useful (ideally in the 2^30 range).
1063
+ const ALMOST_TRILLION : f64 = 1024.0 * 1024.0 * 1024.0 * 32.0 ;
1064
+ let numerator = ( num * ALMOST_TRILLION ) as u64 + 1 ;
1065
+ let denominator = ( den * ALMOST_TRILLION ) as u64 + 1 ;
1066
+ debug_assert ! ( numerator <= 1 << 30 , "Got large numerator ({}) from float {}." , numerator, num) ;
1067
+ debug_assert ! ( denominator <= 1 << 30 , "Got large denominator ({}) from float {}." , denominator, den) ;
1068
+ ( numerator, denominator)
1069
+ } ;
1070
+
1019
1071
if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
1020
1072
denominator < u64:: max_value ( ) / 21
1021
1073
{
@@ -2970,47 +3022,47 @@ mod tests {
2970
3022
inflight_htlc_msat : 0 ,
2971
3023
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : 1_000 } ,
2972
3024
} ;
2973
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 6262 ) ;
3025
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 17757 ) ;
2974
3026
let usage = ChannelUsage {
2975
3027
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2976
3028
} ;
2977
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4634 ) ;
3029
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 11812 ) ;
2978
3030
let usage = ChannelUsage {
2979
3031
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2980
3032
} ;
2981
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4186 ) ;
3033
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 9264 ) ;
2982
3034
let usage = ChannelUsage {
2983
3035
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2984
3036
} ;
2985
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3909 ) ;
3037
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 7912 ) ;
2986
3038
let usage = ChannelUsage {
2987
3039
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2988
3040
} ;
2989
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3556 ) ;
3041
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 7157 ) ;
2990
3042
let usage = ChannelUsage {
2991
3043
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2992
3044
} ;
2993
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3533 ) ;
3045
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 6402 ) ;
2994
3046
let usage = ChannelUsage {
2995
3047
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
2996
3048
} ;
2997
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3172 ) ;
3049
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5931 ) ;
2998
3050
let usage = ChannelUsage {
2999
3051
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3000
3052
} ;
3001
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3211 ) ;
3053
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5931 ) ;
3002
3054
let usage = ChannelUsage {
3003
3055
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3004
3056
} ;
3005
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3243 ) ;
3057
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5679 ) ;
3006
3058
let usage = ChannelUsage {
3007
3059
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3008
3060
} ;
3009
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3297 ) ;
3061
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5459 ) ;
3010
3062
let usage = ChannelUsage {
3011
3063
effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
3012
3064
} ;
3013
- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3250 ) ;
3065
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5208 ) ;
3014
3066
}
3015
3067
3016
3068
#[ test]
0 commit comments