@@ -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}
@@ -1008,14 +1032,42 @@ const BASE_AMOUNT_PENALTY_DIVISOR: u64 = 1 << 30;
10081032/// seen an HTLC successfully complete over this channel.
10091033fn success_probability (
10101034 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 ,
10121036) -> ( u64 , u64 ) {
10131037 debug_assert ! ( min_liquidity_msat <= amount_msat) ;
10141038 debug_assert ! ( amount_msat < max_liquidity_msat) ;
10151039 debug_assert ! ( max_liquidity_msat <= capacity_msat) ;
10161040
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+
10191071 if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
10201072 denominator < u64:: max_value ( ) / 21
10211073 {
@@ -2970,47 +3022,47 @@ mod tests {
29703022 inflight_htlc_msat : 0 ,
29713023 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : 1_000 } ,
29723024 } ;
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 ) ;
29743026 let usage = ChannelUsage {
29753027 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29763028 } ;
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 ) ;
29783030 let usage = ChannelUsage {
29793031 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29803032 } ;
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 ) ;
29823034 let usage = ChannelUsage {
29833035 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29843036 } ;
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 ) ;
29863038 let usage = ChannelUsage {
29873039 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29883040 } ;
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 ) ;
29903042 let usage = ChannelUsage {
29913043 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29923044 } ;
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 ) ;
29943046 let usage = ChannelUsage {
29953047 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
29963048 } ;
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 ) ;
29983050 let usage = ChannelUsage {
29993051 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30003052 } ;
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 ) ;
30023054 let usage = ChannelUsage {
30033055 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30043056 } ;
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 ) ;
30063058 let usage = ChannelUsage {
30073059 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30083060 } ;
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 ) ;
30103062 let usage = ChannelUsage {
30113063 effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : 1_000 } , ..usage
30123064 } ;
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 ) ;
30143066 }
30153067
30163068 #[ test]
0 commit comments