@@ -576,6 +576,28 @@ pub struct ProbabilisticScoringFeeParameters {
576576 /// [`base_penalty_msat`]: Self::base_penalty_msat
577577 /// [`anti_probing_penalty_msat`]: Self::anti_probing_penalty_msat
578578 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 ,
579601}
580602
581603impl Default for ProbabilisticScoringFeeParameters {
@@ -590,6 +612,7 @@ impl Default for ProbabilisticScoringFeeParameters {
590612 considered_impossible_penalty_msat : 1_0000_0000_000 ,
591613 historical_liquidity_penalty_multiplier_msat : 10_000 ,
592614 historical_liquidity_penalty_amount_multiplier_msat : 64 ,
615+ linear_success_probability : false ,
593616 }
594617 }
595618}
@@ -643,6 +666,7 @@ impl ProbabilisticScoringFeeParameters {
643666 manual_node_penalties : HashMap :: new ( ) ,
644667 anti_probing_penalty_msat : 0 ,
645668 considered_impossible_penalty_msat : 0 ,
669+ linear_success_probability : true ,
646670 }
647671 }
648672}
@@ -1005,14 +1029,44 @@ const BASE_AMOUNT_PENALTY_DIVISOR: u64 = 1 << 30;
10051029#[ inline( always) ]
10061030fn success_probability (
10071031 amount_msat : u64 , min_liquidity_msat : u64 , max_liquidity_msat : u64 , capacity_msat : u64 ,
1008- _params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
1032+ params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
10091033) -> ( u64 , u64 ) {
10101034 debug_assert ! ( min_liquidity_msat <= amount_msat) ;
10111035 debug_assert ! ( amount_msat < max_liquidity_msat) ;
10121036 debug_assert ! ( max_liquidity_msat <= capacity_msat) ;
10131037
1014- let numerator = max_liquidity_msat - amount_msat;
1015- let mut denominator = ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) ;
1038+ let ( numerator, mut denominator) =
1039+ if params. linear_success_probability {
1040+ ( max_liquidity_msat - amount_msat,
1041+ ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) )
1042+ } else {
1043+ let capacity = capacity_msat as f64 ;
1044+ let min = ( min_liquidity_msat as f64 ) / capacity;
1045+ let max = ( max_liquidity_msat as f64 ) / capacity;
1046+ let amount = ( amount_msat as f64 ) / capacity;
1047+
1048+ // Assume the channel has a probability density function of (x - 0.5)^2 for values from
1049+ // 0 to 1 (where 1 is the channel's full capacity). The success probability given some
1050+ // liquidity bounds is thus the integral under the curve from the minimum liquidity to
1051+ // the amount, divided by the same integral from the minimum to the maximum liquidity
1052+ // bounds.
1053+ //
1054+ // Because the integral is simply a constant times (x - 0.5)^3, this means we simply
1055+ // subtract the two bounds mius 0.5 to the 3rd power.
1056+ let max_pow = ( max - 0.5 ) . powi ( 3 ) ;
1057+ let num = max_pow - ( amount - 0.5 ) . powi ( 3 ) ;
1058+ let den = max_pow - ( min - 0.5 ) . powi ( 3 ) ;
1059+
1060+ // Because our numerator and denominator max out at 2^-3 we need to multiply them by
1061+ // quite a large factor to get something useful (ideally in the 2^30 range).
1062+ const ALMOST_TRILLION : f64 = 1024.0 * 1024.0 * 1024.0 * 2.0 ;
1063+ let numerator = ( num * ALMOST_TRILLION ) as u64 + 1 ;
1064+ let denominator = ( den * ALMOST_TRILLION ) as u64 + 1 ;
1065+ debug_assert ! ( numerator <= 1 << 30 , "Got large numerator ({}) from float {}." , numerator, num) ;
1066+ debug_assert ! ( denominator <= 1 << 30 , "Got large denominator ({}) from float {}." , denominator, den) ;
1067+ ( numerator, denominator)
1068+ } ;
1069+
10161070 if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
10171071 denominator < u64:: max_value ( ) / 21
10181072 {
@@ -2960,47 +3014,47 @@ mod tests {
29603014 inflight_htlc_msat : 0 ,
29613015 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : 1_000 } ,
29623016 } ;
2963- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 6262 ) ;
3017+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 11497 ) ;
29643018 let usage = ChannelUsage {
29653019 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29663020 } ;
2967- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4634 ) ;
3021+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 7408 ) ;
29683022 let usage = ChannelUsage {
29693023 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29703024 } ;
2971- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4186 ) ;
3025+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 6151 ) ;
29723026 let usage = ChannelUsage {
29733027 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29743028 } ;
2975- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3909 ) ;
3029+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 5459 ) ;
29763030 let usage = ChannelUsage {
29773031 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29783032 } ;
2979- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3556 ) ;
3033+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4987 ) ;
29803034 let usage = ChannelUsage {
29813035 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29823036 } ;
2983- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3533 ) ;
3037+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4736 ) ;
29843038 let usage = ChannelUsage {
29853039 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29863040 } ;
2987- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3172 ) ;
3041+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4515 ) ;
29883042 let usage = ChannelUsage {
29893043 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29903044 } ;
2991- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3211 ) ;
3045+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4515 ) ;
29923046 let usage = ChannelUsage {
29933047 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29943048 } ;
2995- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3243 ) ;
3049+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4295 ) ;
29963050 let usage = ChannelUsage {
29973051 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29983052 } ;
2999- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3297 ) ;
3053+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4295 ) ;
30003054 let usage = ChannelUsage {
30013055 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30023056 } ;
3003- assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 3250 ) ;
3057+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 4044 ) ;
30043058 }
30053059
30063060 #[ test]
0 commit comments