@@ -893,7 +893,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
893893/// [`Self::historical_estimated_channel_liquidity_probabilities`] (but not those returned by 
894894/// [`Self::estimated_channel_liquidity_range`]). 
895895pub  fn  historical_estimated_payment_success_probability ( 
896- 		& self ,  scid :  u64 ,  target :  & NodeId ,  amount_msat :  u64 ) 
896+ 		& self ,  scid :  u64 ,  target :  & NodeId ,  amount_msat :  u64 ,   params :   & ProbabilisticScoringFeeParameters ) 
897897	-> Option < f64 >  { 
898898		let  graph = self . network_graph . read_only ( ) ; 
899899
@@ -905,7 +905,8 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
905905
906906					return  dir_liq. liquidity_history . calculate_success_probability_times_billion ( 
907907						dir_liq. now ,  * dir_liq. last_updated , 
908- 						self . decay_params . historical_no_updates_half_life ,  amount_msat,  capacity_msat
908+ 						self . decay_params . historical_no_updates_half_life ,  & params,  amount_msat, 
909+ 						capacity_msat
909910					) . map ( |p| p as  f64  / ( 1024  *  1024  *  1024 )  as  f64 ) ; 
910911				} 
911912			} 
@@ -997,6 +998,23 @@ const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
997998const  AMOUNT_PENALTY_DIVISOR :  u64  = 1  << 20 ; 
998999const  BASE_AMOUNT_PENALTY_DIVISOR :  u64  = 1  << 30 ; 
9991000
1001+ #[ inline( always) ]  
1002+ /// Given liquidity bounds, calculates the success probability (in the form of a numerator and 
1003+ /// denominator) of an HTLC. This is a key assumption in our scoring models. 
1004+ /// 
1005+ /// Must not return a numerator or denominator greater than 2^31 for arguments less than 2^31. 
1006+ 
1007+ /// min_zero_implies_no_successes signals that an `amount_msat` of 0 means we've not (recently) 
1008+ /// seen an HTLC successfully complete over this channel. 
1009+ fn  success_probability ( 
1010+ 	min_liquidity_msat :  u64 ,  amount_msat :  u64 ,  max_liquidity_msat :  u64 ,  _capacity_msat :  u64 , 
1011+ 	_params :  & ProbabilisticScoringFeeParameters ,  _min_zero_implies_no_successes :  bool , 
1012+ )  -> ( u64 ,  u64 )  { 
1013+ 	let  numerator = max_liquidity_msat - amount_msat; 
1014+ 	let  denominator = ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) ; 
1015+ 	( numerator,  denominator) 
1016+ } 
1017+ 
10001018impl < L :  Deref < Target  = u64 > ,  BRT :  Deref < Target  = HistoricalBucketRangeTracker > ,  T :  Time ,  U :  Deref < Target  = T > >  DirectedChannelLiquidity <  L ,  BRT ,  T ,  U >  { 
10011019	/// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in 
10021020/// this direction. 
@@ -1017,9 +1035,9 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
10171035					score_params. liquidity_penalty_amount_multiplier_msat ) 
10181036				. saturating_add ( score_params. considered_impossible_penalty_msat ) 
10191037		}  else  { 
1020- 			let  numerator =  ( max_liquidity_msat - amount_msat ) . saturating_add ( 1 ) ; 
1021- 			let  denominator =  ( max_liquidity_msat - min_liquidity_msat ) . saturating_add ( 1 ) ; 
1022- 			if  amount_msat  - min_liquidity_msat  < denominator / PRECISION_LOWER_BOUND_DENOMINATOR  { 
1038+ 			let  ( numerator,  denominator )  =  success_probability ( min_liquidity_msat , 
1039+ 				amount_msat ,   max_liquidity_msat,  available_capacity ,  score_params ,   false ) ; 
1040+ 			if  denominator  - numerator  < denominator / PRECISION_LOWER_BOUND_DENOMINATOR  { 
10231041				// If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64), 
10241042				// don't bother trying to use the log approximation as it gets too noisy to be 
10251043				// particularly helpful, instead just round down to 0. 
@@ -1046,7 +1064,8 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
10461064		   score_params. historical_liquidity_penalty_amount_multiplier_msat  != 0  { 
10471065			if  let  Some ( cumulative_success_prob_times_billion)  = self . liquidity_history 
10481066				. calculate_success_probability_times_billion ( self . now ,  * self . last_updated , 
1049- 					self . decay_params . historical_no_updates_half_life ,  amount_msat,  self . capacity_msat ) 
1067+ 					self . decay_params . historical_no_updates_half_life ,  score_params,  amount_msat, 
1068+ 					self . capacity_msat ) 
10501069			{ 
10511070				let  historical_negative_log10_times_2048 = approx:: negative_log10_times_2048 ( cumulative_success_prob_times_billion + 1 ,  1024  *  1024  *  1024 ) ; 
10521071				res = res. saturating_add ( Self :: combined_penalty_msat ( amount_msat, 
@@ -1056,9 +1075,8 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
10561075				// If we don't have any valid points (or, once decayed, we have less than a full 
10571076				// point), redo the non-historical calculation with no liquidity bounds tracked and 
10581077				// the historical penalty multipliers. 
1059- 				let  available_capacity = self . available_capacity ( ) ; 
1060- 				let  numerator = available_capacity. saturating_sub ( amount_msat) . saturating_add ( 1 ) ; 
1061- 				let  denominator = available_capacity. saturating_add ( 1 ) ; 
1078+ 				let  ( numerator,  denominator)  = success_probability ( 0 ,  amount_msat, 
1079+ 					available_capacity,  available_capacity,  score_params,  true ) ; 
10621080				let  negative_log10_times_2048 =
10631081					approx:: negative_log10_times_2048 ( numerator,  denominator) ; 
10641082				res = res. saturating_add ( Self :: combined_penalty_msat ( amount_msat,  negative_log10_times_2048, 
@@ -1851,8 +1869,9 @@ mod bucketed_history {
18511869
18521870		#[ inline]  
18531871		pub ( super )  fn  calculate_success_probability_times_billion < T :  Time > ( 
1854- 			& self ,  now :  T ,  last_updated :  T ,  half_life :  Duration ,  amount_msat :  u64 ,  capacity_msat :  u64 ) 
1855- 		-> Option < u64 >  { 
1872+ 			& self ,  now :  T ,  last_updated :  T ,  half_life :  Duration , 
1873+ 			params :  & ProbabilisticScoringFeeParameters ,  amount_msat :  u64 ,  capacity_msat :  u64 
1874+ 		)  -> Option < u64 >  { 
18561875			// If historical penalties are enabled, we try to calculate a probability of success 
18571876			// given our historical distribution of min- and max-liquidity bounds in a channel. 
18581877			// To do so, we walk the set of historical liquidity bucket (min, max) combinations 
@@ -1887,14 +1906,13 @@ mod bucketed_history {
18871906				} 
18881907				let  max_bucket_end_pos = BUCKET_START_POS [ 32  - highest_max_bucket_with_points]  - 1 ; 
18891908				if  payment_pos < max_bucket_end_pos { 
1909+ 					let  ( numerator,  denominator)  = success_probability ( 0 ,  payment_pos as  u64 , 
1910+ 						max_bucket_end_pos as  u64 ,  POSITION_TICKS  as  u64  - 1 ,  params,  true ) ; 
18901911					let  bucket_prob_times_billion =
18911912						( self . min_liquidity_offset_history . buckets [ 0 ]  as  u64 )  *  total_max_points
18921913							*  1024  *  1024  *  1024  / total_valid_points_tracked; 
18931914					cumulative_success_prob_times_billion += bucket_prob_times_billion * 
1894- 						( ( max_bucket_end_pos - payment_pos)  as  u64 )  /
1895- 						// Add an additional one in the divisor as the payment bucket has been 
1896- 						// rounded down. 
1897- 						( max_bucket_end_pos + 1 )  as  u64 ; 
1915+ 						numerator / denominator; 
18981916				} 
18991917			} 
19001918
@@ -1912,11 +1930,11 @@ mod bucketed_history {
19121930					}  else  if  payment_pos < min_bucket_start_pos { 
19131931						cumulative_success_prob_times_billion += bucket_prob_times_billion; 
19141932					}  else  { 
1933+ 						let  ( numerator,  denominator)  = success_probability ( 
1934+ 							min_bucket_start_pos as  u64 ,  payment_pos as  u64 , 
1935+ 							max_bucket_end_pos as  u64 ,  POSITION_TICKS  as  u64  - 1 ,  params,  true ) ; 
19151936						cumulative_success_prob_times_billion += bucket_prob_times_billion * 
1916- 							( ( max_bucket_end_pos - payment_pos)  as  u64 )  /
1917- 							// Add an additional one in the divisor as the payment bucket has been 
1918- 							// rounded down. 
1919- 							( ( max_bucket_end_pos - min_bucket_start_pos + 1 )  as  u64 ) ; 
1937+ 							numerator / denominator; 
19201938					} 
19211939				} 
19221940			} 
@@ -2919,7 +2937,7 @@ mod tests {
29192937		assert_eq ! ( scorer. channel_penalty_msat( 42 ,  & source,  & target,  usage,  & params) ,  300 ) ; 
29202938
29212939		SinceEpoch :: advance ( Duration :: from_secs ( 10 ) ) ; 
2922- 		assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 ,  & source,  & target,  usage,  & params) ,  365 ) ; 
2940+ 		assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 ,  & source,  & target,  usage,  & params) ,  370 ) ; 
29232941	} 
29242942
29252943	#[ test]  
@@ -3146,7 +3164,7 @@ mod tests {
31463164		assert_eq ! ( scorer. channel_penalty_msat( 42 ,  & source,  & target,  usage,  & params) ,  47 ) ; 
31473165		assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 ,  & target) , 
31483166			None ) ; 
3149- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  42 ) , 
3167+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  42 ,   & params ) , 
31503168			None ) ; 
31513169
31523170		scorer. payment_path_failed ( & payment_path_for_amount ( 1 ) ,  42 ) ; 
@@ -3157,9 +3175,9 @@ mod tests {
31573175		assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 ,  & target) , 
31583176			Some ( ( [ 32 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] , 
31593177				[ 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  32 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] ) ) ) ; 
3160- 		assert ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  1 ) 
3178+ 		assert ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  1 ,   & params ) 
31613179			. unwrap( )  > 0.35 ) ; 
3162- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  500 ) , 
3180+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  500 ,   & params ) , 
31633181			Some ( 0.0 ) ) ; 
31643182
31653183		// Even after we tell the scorer we definitely have enough available liquidity, it will 
@@ -3174,11 +3192,11 @@ mod tests {
31743192		// The exact success probability is a bit complicated and involves integer rounding, so we 
31753193		// simply check bounds here. 
31763194		let  five_hundred_prob =
3177- 			scorer. historical_estimated_payment_success_probability ( 42 ,  & target,  500 ) . unwrap ( ) ; 
3195+ 			scorer. historical_estimated_payment_success_probability ( 42 ,  & target,  500 ,   & params ) . unwrap ( ) ; 
31783196		assert ! ( five_hundred_prob > 0.66 ) ; 
31793197		assert ! ( five_hundred_prob < 0.68 ) ; 
31803198		let  one_prob =
3181- 			scorer. historical_estimated_payment_success_probability ( 42 ,  & target,  1 ) . unwrap ( ) ; 
3199+ 			scorer. historical_estimated_payment_success_probability ( 42 ,  & target,  1 ,   & params ) . unwrap ( ) ; 
31823200		assert ! ( one_prob < 1.0 ) ; 
31833201		assert ! ( one_prob > 0.95 ) ; 
31843202
@@ -3190,7 +3208,7 @@ mod tests {
31903208		// data entirely instead. 
31913209		assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 ,  & target) , 
31923210			None ) ; 
3193- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  1 ) ,  None ) ; 
3211+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  1 ,   & params ) ,  None ) ; 
31943212
31953213		let  mut  usage = ChannelUsage  { 
31963214			amount_msat :  100 , 
@@ -3354,7 +3372,7 @@ mod tests {
33543372		assert_eq ! ( scorer. channel_penalty_msat( 42 ,  & source,  & target,  usage,  & params) ,  0 ) ; 
33553373		assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 ,  & target) , 
33563374			None ) ; 
3357- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  42 ) , 
3375+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  42 ,   & params ) , 
33583376			None ) ; 
33593377
33603378		// Fail to pay once, and then check the buckets and penalty. 
@@ -3369,14 +3387,14 @@ mod tests {
33693387			Some ( ( [ 32 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] , 
33703388				[ 0 ,  32 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] ) ) ) ; 
33713389		// The success probability estimate itself should be zero. 
3372- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  amount_msat) , 
3390+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  amount_msat,   & params ) , 
33733391			Some ( 0.0 ) ) ; 
33743392
33753393		// Now test again with the amount in the bottom bucket. 
33763394		amount_msat /= 2 ; 
33773395		// The new amount is entirely within the only minimum bucket with score, so the probability 
33783396		// we assign is 1/2. 
3379- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  amount_msat) , 
3397+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  amount_msat,   & params ) , 
33803398			Some ( 0.5 ) ) ; 
33813399
33823400		// ...but once we see a failure, we consider the payment to be substantially less likely, 
@@ -3386,7 +3404,7 @@ mod tests {
33863404		assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 ,  & target) , 
33873405			Some ( ( [ 63 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] , 
33883406				[ 32 ,  31 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] ) ) ) ; 
3389- 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  amount_msat) , 
3407+ 		assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 ,  & target,  amount_msat,   & params ) , 
33903408			Some ( 0.0 ) ) ; 
33913409	} 
33923410} 
0 commit comments