@@ -491,13 +491,12 @@ pub struct ProbabilisticScoringFeeParameters {
491
491
/// Default value: 500 msat
492
492
pub base_penalty_msat : u64 ,
493
493
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`].
496
496
///
497
497
/// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e.,
498
498
/// 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.
501
500
///
502
501
/// ie `base_penalty_amount_multiplier_msat * amount_msat / 2^30`
503
502
///
@@ -524,14 +523,14 @@ pub struct ProbabilisticScoringFeeParameters {
524
523
/// [`liquidity_offset_half_life`]: ProbabilisticScoringDecayParameters::liquidity_offset_half_life
525
524
pub liquidity_penalty_multiplier_msat : u64 ,
526
525
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.
530
529
///
531
530
/// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e.,
532
531
/// 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.
535
534
///
536
535
/// `-log10(success_probability) * liquidity_penalty_amount_multiplier_msat * amount_msat / 2^20`
537
536
///
@@ -560,15 +559,14 @@ pub struct ProbabilisticScoringFeeParameters {
560
559
/// [`liquidity_penalty_multiplier_msat`]: Self::liquidity_penalty_multiplier_msat
561
560
pub historical_liquidity_penalty_multiplier_msat : u64 ,
562
561
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
566
565
/// penalty.
567
566
///
568
567
/// The purpose of the amount penalty is to avoid having fees dominate the channel cost for
569
568
/// 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.
572
570
///
573
571
/// This penalty is similar to [`liquidity_penalty_amount_multiplier_msat`], however, instead
574
572
/// 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) {
1076
1074
///
1077
1075
/// Must not return a numerator or denominator greater than 2^31 for arguments less than 2^31.
1078
1076
///
1077
+ /// `total_inflight_amount_msat` includes the amount of the HTLC and any HTLCs in flight over the
1078
+ /// channel.
1079
+ ///
1079
1080
/// min_zero_implies_no_successes signals that a `min_liquidity_msat` of 0 means we've not
1080
1081
/// (recently) seen an HTLC successfully complete over this channel.
1081
1082
#[ inline( always) ]
1082
1083
fn 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 ,
1085
1087
) -> ( 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) ;
1088
1090
debug_assert ! ( max_liquidity_msat <= capacity_msat) ;
1089
1091
1090
1092
let ( numerator, mut denominator) =
1091
1093
if params. linear_success_probability {
1092
- ( max_liquidity_msat - amount_msat ,
1094
+ ( max_liquidity_msat - total_inflight_amount_msat ,
1093
1095
( max_liquidity_msat - min_liquidity_msat) . saturating_add ( 1 ) )
1094
1096
} else {
1095
1097
let capacity = capacity_msat as f64 ;
1096
1098
let min = ( min_liquidity_msat as f64 ) / capacity;
1097
1099
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;
1099
1101
1100
1102
// Assume the channel has a probability density function of (x - 0.5)^2 for values from
1101
1103
// 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:
1138
1140
DirectedChannelLiquidity < L , HT , T > {
1139
1141
/// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in
1140
1142
/// 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) ;
1142
1148
let available_capacity = self . capacity_msat ;
1143
1149
let max_liquidity_msat = self . max_liquidity_msat ( ) ;
1144
1150
let min_liquidity_msat = core:: cmp:: min ( self . min_liquidity_msat ( ) , max_liquidity_msat) ;
1145
1151
1146
- let mut res = if amount_msat <= min_liquidity_msat {
1152
+ let mut res = if total_inflight_amount_msat <= min_liquidity_msat {
1147
1153
0
1148
- } else if amount_msat >= max_liquidity_msat {
1154
+ } else if total_inflight_amount_msat >= max_liquidity_msat {
1149
1155
// Equivalent to hitting the else clause below with the amount equal to the effective
1150
1156
// capacity and without any certainty on the liquidity upper bound, plus the
1151
1157
// impossibility penalty.
@@ -1155,8 +1161,10 @@ DirectedChannelLiquidity< L, HT, T> {
1155
1161
score_params. liquidity_penalty_amount_multiplier_msat )
1156
1162
. saturating_add ( score_params. considered_impossible_penalty_msat )
1157
1163
} 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
+ ) ;
1160
1168
if denominator - numerator < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
1161
1169
// If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
1162
1170
// don't bother trying to use the log approximation as it gets too noisy to be
@@ -1171,7 +1179,7 @@ DirectedChannelLiquidity< L, HT, T> {
1171
1179
}
1172
1180
} ;
1173
1181
1174
- if amount_msat >= available_capacity {
1182
+ if total_inflight_amount_msat >= available_capacity {
1175
1183
// We're trying to send more than the capacity, use a max penalty.
1176
1184
res = res. saturating_add ( Self :: combined_penalty_msat ( amount_msat,
1177
1185
NEGATIVE_LOG10_UPPER_BOUND * 2048 ,
@@ -1184,7 +1192,8 @@ DirectedChannelLiquidity< L, HT, T> {
1184
1192
score_params. historical_liquidity_penalty_amount_multiplier_msat != 0 {
1185
1193
if let Some ( cumulative_success_prob_times_billion) = self . liquidity_history
1186
1194
. calculate_success_probability_times_billion (
1187
- score_params, amount_msat, self . capacity_msat )
1195
+ score_params, total_inflight_amount_msat, self . capacity_msat
1196
+ )
1188
1197
{
1189
1198
let historical_negative_log10_times_2048 =
1190
1199
log_approx:: negative_log10_times_2048 ( cumulative_success_prob_times_billion + 1 , 1024 * 1024 * 1024 ) ;
@@ -1195,8 +1204,10 @@ DirectedChannelLiquidity< L, HT, T> {
1195
1204
// If we don't have any valid points (or, once decayed, we have less than a full
1196
1205
// point), redo the non-historical calculation with no liquidity bounds tracked and
1197
1206
// 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
+ ) ;
1200
1211
let negative_log10_times_2048 =
1201
1212
log_approx:: negative_log10_times_2048 ( numerator, denominator) ;
1202
1213
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
1353
1364
_ => { } ,
1354
1365
}
1355
1366
1356
- let amount_msat = usage. amount_msat . saturating_add ( usage. inflight_htlc_msat ) ;
1357
1367
let capacity_msat = usage. effective_capacity . as_msat ( ) ;
1358
1368
self . channel_liquidities
1359
1369
. get ( scid)
1360
1370
. unwrap_or ( & ChannelLiquidity :: new ( Duration :: ZERO ) )
1361
1371
. 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)
1363
1373
. saturating_add ( anti_probing_penalty_msat)
1364
1374
. saturating_add ( base_penalty_msat)
1365
1375
}
@@ -1773,7 +1783,7 @@ mod bucketed_history {
1773
1783
1774
1784
#[ inline]
1775
1785
pub ( super ) fn calculate_success_probability_times_billion (
1776
- & self , params : & ProbabilisticScoringFeeParameters , amount_msat : u64 ,
1786
+ & self , params : & ProbabilisticScoringFeeParameters , total_inflight_amount_msat : u64 ,
1777
1787
capacity_msat : u64
1778
1788
) -> Option < u64 > {
1779
1789
// If historical penalties are enabled, we try to calculate a probability of success
@@ -1783,7 +1793,7 @@ mod bucketed_history {
1783
1793
// state). For each pair, we calculate the probability as if the bucket's corresponding
1784
1794
// min- and max- liquidity bounds were our current liquidity bounds and then multiply
1785
1795
// 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) ;
1787
1797
if payment_pos >= POSITION_TICKS { return None ; }
1788
1798
1789
1799
let min_liquidity_offset_history_buckets =
@@ -3269,7 +3279,7 @@ mod tests {
3269
3279
short_channel_id : 42 ,
3270
3280
} ) ;
3271
3281
3272
- assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 2050 ) ;
3282
+ assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 2048 ) ;
3273
3283
3274
3284
let usage = ChannelUsage {
3275
3285
amount_msat : 1 ,
0 commit comments