Skip to content

Commit 977ea33

Browse files
committed
Decay historical_estimated_channel_liquidity_* result to None
`historical_estimated_channel_liquidity_probabilities` previously decayed to `Some(([0; 8], [0; 8]))`. This was thought to be useful in that it allowed identification of cases where data was previously available but is now decayed away vs cases where data was never available. However, with the introduction of `historical_estimated_payment_success_probability` (which uses the existing scoring routines so will decay to `None`) this is unnecessarily confusing. Given data which has decayed to zero will also not be used anyway, there's little reason to keep the old behavior, and we now decay to `None`.
1 parent 03d34b3 commit 977ea33

File tree

1 file changed

+27
-20
lines changed

1 file changed

+27
-20
lines changed

lightning/src/routing/scoring.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
706706
let amt = directed_info.effective_capacity().as_msat();
707707
let dir_liq = liq.as_directed(source, target, 0, amt, self.decay_params);
708708

709-
let (min_buckets, max_buckets, _) = dir_liq.liquidity_history
709+
let (min_buckets, max_buckets, _, _) = dir_liq.liquidity_history
710710
.get_decayed_buckets(now, *dir_liq.last_updated,
711711
self.decay_params.historical_no_updates_half_life);
712712

@@ -788,7 +788,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
788788
/// in the top and bottom bucket, and roughly with similar (recent) frequency.
789789
///
790790
/// Because the datapoints are decayed slowly over time, values will eventually return to
791-
/// `Some(([0; 32], [0; 32]))`.
791+
/// `Some(([1; 32], [1; 32]))` and then to `None` once no datapoints remain.
792792
///
793793
/// In order to fetch a single success probability from the buckets provided here, as used in
794794
/// the scoring model, see [`Self::historical_estimated_payment_success_probability`].
@@ -802,9 +802,18 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ProbabilisticScorerU
802802
let amt = directed_info.effective_capacity().as_msat();
803803
let dir_liq = liq.as_directed(source, target, 0, amt, self.decay_params);
804804

805-
let (min_buckets, mut max_buckets, _) = dir_liq.liquidity_history
806-
.get_decayed_buckets(dir_liq.now, *dir_liq.last_updated,
807-
self.decay_params.historical_no_updates_half_life);
805+
let (min_buckets, mut max_buckets, valid_points, required_decays) =
806+
dir_liq.liquidity_history.get_decayed_buckets(
807+
dir_liq.now, *dir_liq.last_updated,
808+
self.decay_params.historical_no_updates_half_life
809+
);
810+
811+
// If the total valid points is smaller than 1.0 (i.e. 32 in our fixed-point
812+
// scheme), treat it as if we were fully decayed.
813+
if valid_points.checked_shr(required_decays).unwrap_or(0) < 32*32 {
814+
return None;
815+
}
816+
808817
// Note that the liquidity buckets are an offset from the edge, so we inverse
809818
// the max order to get the probabilities from zero.
810819
max_buckets.reverse();
@@ -1735,15 +1744,23 @@ mod bucketed_history {
17351744
impl<D: Deref<Target = HistoricalBucketRangeTracker>> HistoricalMinMaxBuckets<D> {
17361745
#[inline]
17371746
pub(super) fn get_decayed_buckets<T: Time>(&self, now: T, last_updated: T, half_life: Duration)
1738-
-> ([u16; 32], [u16; 32], u32) {
1747+
-> ([u16; 32], [u16; 32], u64, u32) {
17391748
let required_decays = now.duration_since(last_updated).as_secs()
17401749
.checked_div(half_life.as_secs())
17411750
.map_or(u32::max_value(), |decays| cmp::min(decays, u32::max_value() as u64) as u32);
1751+
1752+
let mut total_valid_points_tracked = 0;
1753+
for (min_idx, min_bucket) in self.min_liquidity_offset_history.buckets.iter().enumerate() {
1754+
for max_bucket in self.max_liquidity_offset_history.buckets.iter().take(32 - min_idx) {
1755+
total_valid_points_tracked += (*min_bucket as u64) * (*max_bucket as u64);
1756+
}
1757+
}
1758+
17421759
let mut min_buckets = *self.min_liquidity_offset_history;
17431760
min_buckets.time_decay_data(required_decays);
17441761
let mut max_buckets = *self.max_liquidity_offset_history;
17451762
max_buckets.time_decay_data(required_decays);
1746-
(min_buckets.buckets, max_buckets.buckets, required_decays)
1763+
(min_buckets.buckets, max_buckets.buckets, total_valid_points_tracked, required_decays)
17471764
}
17481765

17491766
#[inline]
@@ -1755,24 +1772,14 @@ mod bucketed_history {
17551772
// having a minimum above our maximum is an invalid state). For each combination,
17561773
// calculate the probability of success given our payment amount, then total the
17571774
// weighted average probability of success.
1758-
let mut total_valid_points_tracked = 0;
1759-
17601775
let payment_pos = amount_to_pos(amount_msat, capacity_msat);
17611776
if payment_pos >= POSITION_TICKS { return None; }
17621777

17631778
// Check if all our buckets are zero, once decayed and treat it as if we had no data. We
17641779
// don't actually use the decayed buckets, though, as that would lose precision.
1765-
let (decayed_min_buckets, decayed_max_buckets, required_decays) =
1766-
self.get_decayed_buckets(now, last_updated, half_life);
1767-
if decayed_min_buckets.iter().all(|v| *v == 0) || decayed_max_buckets.iter().all(|v| *v == 0) {
1768-
return None;
1769-
}
1780+
let (decayed_min_buckets, decayed_max_buckets, total_valid_points_tracked, required_decays)
1781+
= self.get_decayed_buckets(now, last_updated, half_life);
17701782

1771-
for (min_idx, min_bucket) in self.min_liquidity_offset_history.buckets.iter().enumerate() {
1772-
for max_bucket in self.max_liquidity_offset_history.buckets.iter().take(32 - min_idx) {
1773-
total_valid_points_tracked += (*min_bucket as u64) * (*max_bucket as u64);
1774-
}
1775-
}
17761783
// If the total valid points is smaller than 1.0 (i.e. 32 in our fixed-point scheme), treat
17771784
// it as if we were fully decayed.
17781785
if total_valid_points_tracked.checked_shr(required_decays).unwrap_or(0) < 32*32 {
@@ -3100,7 +3107,7 @@ mod tests {
31003107
// Once fully decayed we still have data, but its all-0s. In the future we may remove the
31013108
// data entirely instead.
31023109
assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target),
3103-
Some(([0; 32], [0; 32])));
3110+
None);
31043111
assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 1), None);
31053112

31063113
let mut usage = ChannelUsage {

0 commit comments

Comments
 (0)