@@ -491,13 +491,12 @@ pub struct ProbabilisticScoringFeeParameters {
491491 /// Default value: 500 msat
492492 pub base_penalty_msat : u64 ,
493493
494- /// A multiplier used with the total amount flowing over a channel to calculate a fixed penalty
495- /// applied to each channel, in excess of the [`base_penalty_msat`].
494+ /// A multiplier used with the payment amount to calculate a fixed penalty applied to each
495+ /// channel, in excess of the [`base_penalty_msat`].
496496 ///
497497 /// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e.,
498498 /// fees plus penalty) for large payments. The penalty is computed as the product of this
499- /// multiplier and `2^30`ths of the total amount flowing over a channel (i.e. the payment
500- /// amount plus the amount of any other HTLCs flowing we sent over the same channel).
499+ /// multiplier and `2^30`ths of the payment amount.
501500 ///
502501 /// ie `base_penalty_amount_multiplier_msat * amount_msat / 2^30`
503502 ///
@@ -524,14 +523,14 @@ pub struct ProbabilisticScoringFeeParameters {
524523 /// [`liquidity_offset_half_life`]: ProbabilisticScoringDecayParameters::liquidity_offset_half_life
525524 pub liquidity_penalty_multiplier_msat : u64 ,
526525
527- /// A multiplier used in conjunction with the total amount flowing over a channel and the
528- /// negative `log10` of the channel's success probability for the payment , as determined by our
529- /// latest estimates of the channel's liquidity, to determine the amount penalty.
526+ /// A multiplier used in conjunction with the payment amount and the negative `log10` of the
527+ /// channel's success probability for the total amount flowing over a channel , as determined by
528+ /// our latest estimates of the channel's liquidity, to determine the amount penalty.
530529 ///
531530 /// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e.,
532531 /// fees plus penalty) for large payments. The penalty is computed as the product of this
533- /// multiplier and `2^20`ths of the amount flowing over this channel , weighted by the negative
534- /// `log10` of the success probability.
532+ /// multiplier and `2^20`ths of the payment amount , weighted by the negative `log10` of the
533+ /// success probability.
535534 ///
536535 /// `-log10(success_probability) * liquidity_penalty_amount_multiplier_msat * amount_msat / 2^20`
537536 ///
@@ -560,15 +559,14 @@ pub struct ProbabilisticScoringFeeParameters {
560559 /// [`liquidity_penalty_multiplier_msat`]: Self::liquidity_penalty_multiplier_msat
561560 pub historical_liquidity_penalty_multiplier_msat : u64 ,
562561
563- /// A multiplier used in conjunction with the total amount flowing over a channel and the
564- /// negative `log10` of the channel's success probability for the payment , as determined based
565- /// on the history of our estimates of the channel's available liquidity, to determine a
562+ /// A multiplier used in conjunction with the payment amount and the negative `log10` of the
563+ /// channel's success probability for the total amount flowing over a channel , as determined
564+ /// based on the history of our estimates of the channel's available liquidity, to determine a
566565 /// penalty.
567566 ///
568567 /// The purpose of the amount penalty is to avoid having fees dominate the channel cost for
569568 /// large payments. The penalty is computed as the product of this multiplier and `2^20`ths
570- /// of the amount flowing over this channel, weighted by the negative `log10` of the success
571- /// probability.
569+ /// of the payment amount, weighted by the negative `log10` of the success probability.
572570 ///
573571 /// This penalty is similar to [`liquidity_penalty_amount_multiplier_msat`], however, instead
574572 /// of using only our latest estimate for the current liquidity available in the channel, it
@@ -1076,26 +1074,30 @@ fn three_f64_pow_3(a: f64, b: f64, c: f64) -> (f64, f64, f64) {
10761074///
10771075/// Must not return a numerator or denominator greater than 2^31 for arguments less than 2^31.
10781076///
1077+ /// `total_inflight_amount_msat` includes the amount of the HTLC and any HTLCs in flight over the
1078+ /// channel.
1079+ ///
10791080/// min_zero_implies_no_successes signals that a `min_liquidity_msat` of 0 means we've not
10801081/// (recently) seen an HTLC successfully complete over this channel.
10811082#[ inline( always) ]
10821083fn success_probability (
1083- amount_msat : u64 , min_liquidity_msat : u64 , max_liquidity_msat : u64 , capacity_msat : u64 ,
1084- params : & ProbabilisticScoringFeeParameters , min_zero_implies_no_successes : bool ,
1084+ total_inflight_amount_msat : u64 , min_liquidity_msat : u64 , max_liquidity_msat : u64 ,
1085+ capacity_msat : u64 , params : & ProbabilisticScoringFeeParameters ,
1086+ min_zero_implies_no_successes : bool ,
10851087) -> ( u64 , u64 ) {
1086- debug_assert ! ( min_liquidity_msat <= amount_msat ) ;
1087- debug_assert ! ( amount_msat < max_liquidity_msat) ;
1088+ debug_assert ! ( min_liquidity_msat <= total_inflight_amount_msat ) ;
1089+ debug_assert ! ( total_inflight_amount_msat < max_liquidity_msat) ;
10881090 debug_assert ! ( max_liquidity_msat <= capacity_msat) ;
10891091
10901092 let ( numerator, mut denominator) =
10911093 if params. linear_success_probability {
1092- ( max_liquidity_msat - amount_msat ,
1094+ ( max_liquidity_msat - total_inflight_amount_msat ,
10931095 ( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) )
10941096 } else {
10951097 let capacity = capacity_msat as f64 ;
10961098 let min = ( min_liquidity_msat as f64 ) / capacity;
10971099 let max = ( max_liquidity_msat as f64 ) / capacity;
1098- let amount = ( amount_msat as f64 ) / capacity;
1100+ let amount = ( total_inflight_amount_msat as f64 ) / capacity;
10991101
11001102 // Assume the channel has a probability density function of (x - 0.5)^2 for values from
11011103 // 0 to 1 (where 1 is the channel's full capacity). The success probability given some
@@ -1138,14 +1140,18 @@ impl<L: Deref<Target = u64>, HT: Deref<Target = HistoricalLiquidityTracker>, T:
11381140DirectedChannelLiquidity < L , HT , T > {
11391141 /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
11401142 /// this direction.
1141- fn penalty_msat ( & self , amount_msat : u64 , score_params : & ProbabilisticScoringFeeParameters ) -> u64 {
1143+ fn penalty_msat (
1144+ & self , amount_msat : u64 , inflight_htlc_msat : u64 ,
1145+ score_params : & ProbabilisticScoringFeeParameters ,
1146+ ) -> u64 {
1147+ let total_inflight_amount_msat = amount_msat. saturating_add ( inflight_htlc_msat) ;
11421148 let available_capacity = self . capacity_msat ;
11431149 let max_liquidity_msat = self . max_liquidity_msat ( ) ;
11441150 let min_liquidity_msat = core:: cmp:: min ( self . min_liquidity_msat ( ) , max_liquidity_msat) ;
11451151
1146- let mut res = if amount_msat <= min_liquidity_msat {
1152+ let mut res = if total_inflight_amount_msat <= min_liquidity_msat {
11471153 0
1148- } else if amount_msat >= max_liquidity_msat {
1154+ } else if total_inflight_amount_msat >= max_liquidity_msat {
11491155 // Equivalent to hitting the else clause below with the amount equal to the effective
11501156 // capacity and without any certainty on the liquidity upper bound, plus the
11511157 // impossibility penalty.
@@ -1155,8 +1161,10 @@ DirectedChannelLiquidity< L, HT, T> {
11551161 score_params. liquidity_penalty_amount_multiplier_msat )
11561162 . saturating_add ( score_params. considered_impossible_penalty_msat )
11571163 } else {
1158- let ( numerator, denominator) = success_probability ( amount_msat,
1159- min_liquidity_msat, max_liquidity_msat, available_capacity, score_params, false ) ;
1164+ let ( numerator, denominator) = success_probability (
1165+ total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat,
1166+ available_capacity, score_params, false ,
1167+ ) ;
11601168 if denominator - numerator < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
11611169 // If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
11621170 // don't bother trying to use the log approximation as it gets too noisy to be
@@ -1171,7 +1179,7 @@ DirectedChannelLiquidity< L, HT, T> {
11711179 }
11721180 } ;
11731181
1174- if amount_msat >= available_capacity {
1182+ if total_inflight_amount_msat >= available_capacity {
11751183 // We're trying to send more than the capacity, use a max penalty.
11761184 res = res. saturating_add ( Self :: combined_penalty_msat ( amount_msat,
11771185 NEGATIVE_LOG10_UPPER_BOUND * 2048 ,
@@ -1184,7 +1192,8 @@ DirectedChannelLiquidity< L, HT, T> {
11841192 score_params. historical_liquidity_penalty_amount_multiplier_msat != 0 {
11851193 if let Some ( cumulative_success_prob_times_billion) = self . liquidity_history
11861194 . calculate_success_probability_times_billion (
1187- score_params, amount_msat, self . capacity_msat )
1195+ score_params, total_inflight_amount_msat, self . capacity_msat
1196+ )
11881197 {
11891198 let historical_negative_log10_times_2048 =
11901199 log_approx:: negative_log10_times_2048 ( cumulative_success_prob_times_billion + 1 , 1024 * 1024 * 1024 ) ;
@@ -1195,8 +1204,10 @@ DirectedChannelLiquidity< L, HT, T> {
11951204 // If we don't have any valid points (or, once decayed, we have less than a full
11961205 // point), redo the non-historical calculation with no liquidity bounds tracked and
11971206 // the historical penalty multipliers.
1198- let ( numerator, denominator) = success_probability ( amount_msat, 0 ,
1199- available_capacity, available_capacity, score_params, true ) ;
1207+ let ( numerator, denominator) = success_probability (
1208+ total_inflight_amount_msat, 0 , available_capacity, available_capacity,
1209+ score_params, true ,
1210+ ) ;
12001211 let negative_log10_times_2048 =
12011212 log_approx:: negative_log10_times_2048 ( numerator, denominator) ;
12021213 res = res. saturating_add ( Self :: combined_penalty_msat ( amount_msat, negative_log10_times_2048,
@@ -1353,13 +1364,12 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreLookUp for Probabilistic
13531364 _ => { } ,
13541365 }
13551366
1356- let amount_msat = usage. amount_msat . saturating_add ( usage. inflight_htlc_msat ) ;
13571367 let capacity_msat = usage. effective_capacity . as_msat ( ) ;
13581368 self . channel_liquidities
13591369 . get ( scid)
13601370 . unwrap_or ( & ChannelLiquidity :: new ( Duration :: ZERO ) )
13611371 . as_directed ( & source, & target, capacity_msat)
1362- . penalty_msat ( amount_msat, score_params)
1372+ . penalty_msat ( usage . amount_msat , usage . inflight_htlc_msat , score_params)
13631373 . saturating_add ( anti_probing_penalty_msat)
13641374 . saturating_add ( base_penalty_msat)
13651375 }
@@ -1773,7 +1783,7 @@ mod bucketed_history {
17731783
17741784 #[ inline]
17751785 pub ( super ) fn calculate_success_probability_times_billion (
1776- & self , params : & ProbabilisticScoringFeeParameters , amount_msat : u64 ,
1786+ & self , params : & ProbabilisticScoringFeeParameters , total_inflight_amount_msat : u64 ,
17771787 capacity_msat : u64
17781788 ) -> Option < u64 > {
17791789 // If historical penalties are enabled, we try to calculate a probability of success
@@ -1783,7 +1793,7 @@ mod bucketed_history {
17831793 // state). For each pair, we calculate the probability as if the bucket's corresponding
17841794 // min- and max- liquidity bounds were our current liquidity bounds and then multiply
17851795 // that probability by the weight of the selected buckets.
1786- let payment_pos = amount_to_pos ( amount_msat , capacity_msat) ;
1796+ let payment_pos = amount_to_pos ( total_inflight_amount_msat , capacity_msat) ;
17871797 if payment_pos >= POSITION_TICKS { return None ; }
17881798
17891799 let min_liquidity_offset_history_buckets =
@@ -3269,7 +3279,7 @@ mod tests {
32693279 short_channel_id : 42 ,
32703280 } ) ;
32713281
3272- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 2050 ) ;
3282+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 2048 ) ;
32733283
32743284 let usage = ChannelUsage {
32753285 amount_msat : 1 ,
0 commit comments