Skip to content

Commit 5f98c39

Browse files
committed
Scale the success probability of channels without info down by 75%
If we are examining a channel for which we have no information at all, we traditionally assume the HTLC success probability is proportional to the channel's capacity. While this may be the case, it is not the case that a tiny payment over a huge channel is guaranteed to succeed, as we assume. Rather, the probability of such success is likely closer to 50% than 100%. Here we try to capture this by simply scaling the success probability for channels where we have no information down linearly. We pick 75% as the upper bound rather arbitrarily - while 50% may be more accurate, its possible it would lead to an over-reliance on channels which we have paid through in the past, which aren't necessarily always the best candidates. Note that we only do this scaling for the historical bucket tracker, as there we can be confident we've never seen a successful HTLC completion on the given channel. If we were to apply the same scaling to the simple liquidity bounds based scoring we'd penalize channels we've never tried over those we've only ever fails to pay over, which is obviously not a good outcome.
1 parent 7543890 commit 5f98c39

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

lightning/src/routing/scoring.rs

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,11 +1007,25 @@ const BASE_AMOUNT_PENALTY_DIVISOR: u64 = 1 << 30;
10071007
/// (recently) seen an HTLC successfully complete over this channel.
10081008
#[inline(always)]
10091009
fn success_probability(
1010-
amount_msat: u64, min_liquidity_msat: u64, max_liquidity_msat: u64, _capacity_msat: u64,
1011-
_params: &ProbabilisticScoringFeeParameters, _min_zero_implies_no_successes: bool,
1010+
amount_msat: u64, min_liquidity_msat: u64, max_liquidity_msat: u64, capacity_msat: u64,
1011+
_params: &ProbabilisticScoringFeeParameters, min_zero_implies_no_successes: bool,
10121012
) -> (u64, u64) {
1013+
debug_assert!(min_liquidity_msat <= amount_msat);
1014+
debug_assert!(amount_msat < max_liquidity_msat);
1015+
debug_assert!(max_liquidity_msat <= capacity_msat);
1016+
10131017
let numerator = max_liquidity_msat - amount_msat;
1014-
let denominator = (max_liquidity_msat - min_liquidity_msat).saturating_add(1);
1018+
let mut denominator = (max_liquidity_msat - min_liquidity_msat).saturating_add(1);
1019+
if min_zero_implies_no_successes && min_liquidity_msat == 0 &&
1020+
denominator < u64::max_value() / 21
1021+
{
1022+
// If we have no knowledge of the channel, scale probability down by ~75%
1023+
// Note that we prefer to increase the denominator rather than decrease the numerator as
1024+
// the denominator is more likely to be larger and thus provide greater precision. This is
1025+
// mostly an overoptimization but makes a large difference in tests.
1026+
denominator = denominator * 21 / 16
1027+
}
1028+
10151029
(numerator, denominator)
10161030
}
10171031

@@ -2956,47 +2970,47 @@ mod tests {
29562970
inflight_htlc_msat: 0,
29572971
effective_capacity: EffectiveCapacity::Total { capacity_msat: 950_000_000, htlc_maximum_msat: 1_000 },
29582972
};
2959-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 4375);
2973+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 6262);
29602974
let usage = ChannelUsage {
29612975
effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29622976
};
2963-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 2739);
2977+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 4634);
29642978
let usage = ChannelUsage {
29652979
effective_capacity: EffectiveCapacity::Total { capacity_msat: 2_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29662980
};
2967-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 2236);
2981+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 4186);
29682982
let usage = ChannelUsage {
29692983
effective_capacity: EffectiveCapacity::Total { capacity_msat: 3_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29702984
};
2971-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1983);
2985+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3909);
29722986
let usage = ChannelUsage {
29732987
effective_capacity: EffectiveCapacity::Total { capacity_msat: 4_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29742988
};
2975-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1637);
2989+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3556);
29762990
let usage = ChannelUsage {
29772991
effective_capacity: EffectiveCapacity::Total { capacity_msat: 5_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29782992
};
2979-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1606);
2993+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3533);
29802994
let usage = ChannelUsage {
29812995
effective_capacity: EffectiveCapacity::Total { capacity_msat: 6_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29822996
};
2983-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1331);
2997+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3172);
29842998
let usage = ChannelUsage {
29852999
effective_capacity: EffectiveCapacity::Total { capacity_msat: 7_450_000_000, htlc_maximum_msat: 1_000 }, ..usage
29863000
};
2987-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1387);
3001+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3211);
29883002
let usage = ChannelUsage {
29893003
effective_capacity: EffectiveCapacity::Total { capacity_msat: 7_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29903004
};
2991-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1379);
3005+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3243);
29923006
let usage = ChannelUsage {
29933007
effective_capacity: EffectiveCapacity::Total { capacity_msat: 8_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29943008
};
2995-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1363);
3009+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3297);
29963010
let usage = ChannelUsage {
29973011
effective_capacity: EffectiveCapacity::Total { capacity_msat: 9_950_000_000, htlc_maximum_msat: 1_000 }, ..usage
29983012
};
2999-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1355);
3013+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 3250);
30003014
}
30013015

30023016
#[test]
@@ -3161,15 +3175,15 @@ mod tests {
31613175
};
31623176

31633177
// With no historical data the normal liquidity penalty calculation is used.
3164-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 47);
3178+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 168);
31653179
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
31663180
None);
31673181
assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, &params),
31683182
None);
31693183

31703184
scorer.payment_path_failed(&payment_path_for_amount(1), 42);
31713185
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 2048);
3172-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage_1, &params), 128);
3186+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage_1, &params), 249);
31733187
// The "it failed" increment is 32, where the probability should lie several buckets into
31743188
// the first octile.
31753189
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
@@ -3183,7 +3197,7 @@ mod tests {
31833197
// Even after we tell the scorer we definitely have enough available liquidity, it will
31843198
// still remember that there was some failure in the past, and assign a non-0 penalty.
31853199
scorer.payment_path_failed(&payment_path_for_amount(1000), 43);
3186-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 32);
3200+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 105);
31873201
// The first points should be decayed just slightly and the last bucket has a new point.
31883202
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
31893203
Some(([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, 32, 0, 0, 0, 0, 0],
@@ -3193,17 +3207,17 @@ mod tests {
31933207
// simply check bounds here.
31943208
let five_hundred_prob =
31953209
scorer.historical_estimated_payment_success_probability(42, &target, 500, &params).unwrap();
3196-
assert!(five_hundred_prob > 0.66);
3197-
assert!(five_hundred_prob < 0.68);
3210+
assert!(five_hundred_prob > 0.59);
3211+
assert!(five_hundred_prob < 0.60);
31983212
let one_prob =
31993213
scorer.historical_estimated_payment_success_probability(42, &target, 1, &params).unwrap();
3200-
assert!(one_prob < 1.0);
3201-
assert!(one_prob > 0.95);
3214+
assert!(one_prob < 0.85);
3215+
assert!(one_prob > 0.84);
32023216

32033217
// Advance the time forward 16 half-lives (which the docs claim will ensure all data is
32043218
// gone), and check that we're back to where we started.
32053219
SinceEpoch::advance(Duration::from_secs(10 * 16));
3206-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 47);
3220+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 168);
32073221
// Once fully decayed we still have data, but its all-0s. In the future we may remove the
32083222
// data entirely instead.
32093223
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
@@ -3367,9 +3381,9 @@ mod tests {
33673381
inflight_htlc_msat: 0,
33683382
effective_capacity: EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: capacity_msat },
33693383
};
3370-
// With no historical data the normal liquidity penalty calculation is used, which in this
3371-
// case is diminuitively low.
3372-
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 0);
3384+
// With no historical data the normal liquidity penalty calculation is used, which results
3385+
// in a success probability of ~75%.
3386+
assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, &params), 1269);
33733387
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
33743388
None);
33753389
assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, &params),

0 commit comments

Comments
 (0)