Skip to content

Commit 6f73a5c

Browse files
committed
Make the historical bucket data private to bucketed_history
In a comming commit we'll cache some additional data in the historical bucket tracker. In order to do so, here we isolate the buckets themselves into the `bucketed_history` module, reducing the possibility of accidentally updating them directly without updating caches.
1 parent 8179da7 commit 6f73a5c

File tree

1 file changed

+58
-27
lines changed

1 file changed

+58
-27
lines changed

lightning/src/routing/scoring.rs

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,8 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
841841
let amt = directed_info.effective_capacity().as_msat();
842842
let dir_liq = liq.as_directed(source, target, amt);
843843

844-
let min_buckets = &dir_liq.liquidity_history.min_liquidity_offset_history.buckets;
845-
let max_buckets = &dir_liq.liquidity_history.max_liquidity_offset_history.buckets;
844+
let min_buckets = &dir_liq.liquidity_history.min_liquidity_offset_history_buckets();
845+
let max_buckets = &dir_liq.liquidity_history.max_liquidity_offset_history_buckets();
846846

847847
log_debug!(self.logger, core::concat!(
848848
"Liquidity from {} to {} via {} is in the range ({}, {}).\n",
@@ -935,8 +935,8 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
935935
let amt = directed_info.effective_capacity().as_msat();
936936
let dir_liq = liq.as_directed(source, target, amt);
937937

938-
let min_buckets = dir_liq.liquidity_history.min_liquidity_offset_history.buckets;
939-
let mut max_buckets = dir_liq.liquidity_history.max_liquidity_offset_history.buckets;
938+
let min_buckets = *dir_liq.liquidity_history.min_liquidity_offset_history_buckets();
939+
let mut max_buckets = *dir_liq.liquidity_history.max_liquidity_offset_history_buckets();
940940

941941
// Note that the liquidity buckets are an offset from the edge, so we inverse
942942
// the max order to get the probabilities from zero.
@@ -1281,11 +1281,10 @@ DirectedChannelLiquidity<L, BRT, T> {
12811281
/// state"), we allow the caller to set an offset applied to our liquidity bounds which
12821282
/// represents the amount of the successful payment we just made.
12831283
fn update_history_buckets(&mut self, bucket_offset_msat: u64, duration_since_epoch: Duration) {
1284-
self.liquidity_history.min_liquidity_offset_history.track_datapoint(
1285-
*self.min_liquidity_offset_msat + bucket_offset_msat, self.capacity_msat
1286-
);
1287-
self.liquidity_history.max_liquidity_offset_history.track_datapoint(
1288-
self.max_liquidity_offset_msat.saturating_sub(bucket_offset_msat), self.capacity_msat
1284+
self.liquidity_history.track_datapoint(
1285+
*self.min_liquidity_offset_msat + bucket_offset_msat,
1286+
self.max_liquidity_offset_msat.saturating_sub(bucket_offset_msat),
1287+
self.capacity_msat,
12891288
);
12901289
*self.offset_history_last_updated = duration_since_epoch;
12911290
}
@@ -1451,19 +1450,12 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreUpdate for Probabilistic
14511450
if elapsed_time > decay_params.historical_no_updates_half_life {
14521451
let half_life = decay_params.historical_no_updates_half_life.as_secs_f64();
14531452
if half_life != 0.0 {
1454-
let divisor = powf64(2048.0, elapsed_time.as_secs_f64() / half_life) as u64;
1455-
for bucket in liquidity.liquidity_history.min_liquidity_offset_history.buckets.iter_mut() {
1456-
*bucket = ((*bucket as u64) * 1024 / divisor) as u16;
1457-
}
1458-
for bucket in liquidity.liquidity_history.max_liquidity_offset_history.buckets.iter_mut() {
1459-
*bucket = ((*bucket as u64) * 1024 / divisor) as u16;
1460-
}
1453+
liquidity.liquidity_history.decay_buckets(elapsed_time.as_secs_f64() / half_life);
14611454
liquidity.offset_history_last_updated = duration_since_epoch;
14621455
}
14631456
}
14641457
liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 ||
1465-
liquidity.liquidity_history.min_liquidity_offset_history.buckets != [0; 32] ||
1466-
liquidity.liquidity_history.max_liquidity_offset_history.buckets != [0; 32]
1458+
liquidity.liquidity_history.has_datapoints()
14671459
});
14681460
}
14691461
}
@@ -1593,7 +1585,7 @@ mod bucketed_history {
15931585
/// in each of 32 buckets.
15941586
#[derive(Clone, Copy)]
15951587
pub(super) struct HistoricalBucketRangeTracker {
1596-
pub(super) buckets: [u16; 32],
1588+
buckets: [u16; 32],
15971589
}
15981590

15991591
/// Buckets are stored in fixed point numbers with a 5 bit fractional part. Thus, the value
@@ -1602,7 +1594,7 @@ mod bucketed_history {
16021594

16031595
impl HistoricalBucketRangeTracker {
16041596
pub(super) fn new() -> Self { Self { buckets: [0; 32] } }
1605-
pub(super) fn track_datapoint(&mut self, liquidity_offset_msat: u64, capacity_msat: u64) {
1597+
fn track_datapoint(&mut self, liquidity_offset_msat: u64, capacity_msat: u64) {
16061598
// We have 32 leaky buckets for min and max liquidity. Each bucket tracks the amount of time
16071599
// we spend in each bucket as a 16-bit fixed-point number with a 5 bit fractional part.
16081600
//
@@ -1638,11 +1630,10 @@ mod bucketed_history {
16381630
impl_writeable_tlv_based!(HistoricalBucketRangeTracker, { (0, buckets, required) });
16391631
impl_writeable_tlv_based!(LegacyHistoricalBucketRangeTracker, { (0, buckets, required) });
16401632

1641-
16421633
#[derive(Clone, Copy)]
16431634
pub(super) struct HistoricalLiquidityTracker {
1644-
pub(super) min_liquidity_offset_history: HistoricalBucketRangeTracker,
1645-
pub(super) max_liquidity_offset_history: HistoricalBucketRangeTracker,
1635+
min_liquidity_offset_history: HistoricalBucketRangeTracker,
1636+
max_liquidity_offset_history: HistoricalBucketRangeTracker,
16461637
}
16471638

16481639
impl HistoricalLiquidityTracker {
@@ -1663,6 +1654,29 @@ mod bucketed_history {
16631654
}
16641655
}
16651656

1657+
pub(super) fn has_datapoints(&self) -> bool {
1658+
self.min_liquidity_offset_history.buckets != [0; 32] ||
1659+
self.max_liquidity_offset_history.buckets != [0; 32]
1660+
}
1661+
1662+
pub(super) fn decay_buckets(&mut self, half_lives: f64) {
1663+
let divisor = powf64(2048.0, half_lives) as u64;
1664+
for bucket in self.min_liquidity_offset_history.buckets.iter_mut() {
1665+
*bucket = ((*bucket as u64) * 1024 / divisor) as u16;
1666+
}
1667+
for bucket in self.max_liquidity_offset_history.buckets.iter_mut() {
1668+
*bucket = ((*bucket as u64) * 1024 / divisor) as u16;
1669+
}
1670+
}
1671+
1672+
pub(super) fn writeable_min_offset_history(&self) -> &HistoricalBucketRangeTracker {
1673+
&self.min_liquidity_offset_history
1674+
}
1675+
1676+
pub(super) fn writeable_max_offset_history(&self) -> &HistoricalBucketRangeTracker {
1677+
&self.max_liquidity_offset_history
1678+
}
1679+
16661680
pub(super) fn as_directed<'a>(&'a self, source_less_than_target: bool)
16671681
-> HistoricalMinMaxBuckets<&'a HistoricalBucketRangeTracker> {
16681682
let (min_liquidity_offset_history, max_liquidity_offset_history) =
@@ -1691,13 +1705,30 @@ mod bucketed_history {
16911705
pub(super) struct HistoricalMinMaxBuckets<D: Deref<Target = HistoricalBucketRangeTracker>> {
16921706
/// Buckets tracking where and how often we've seen the minimum liquidity bound for a
16931707
/// channel.
1694-
pub(super) min_liquidity_offset_history: D,
1708+
min_liquidity_offset_history: D,
16951709
/// Buckets tracking where and how often we've seen the maximum liquidity bound for a
16961710
/// channel.
1697-
pub(super) max_liquidity_offset_history: D,
1711+
max_liquidity_offset_history: D,
1712+
}
1713+
1714+
impl<D: DerefMut<Target = HistoricalBucketRangeTracker>> HistoricalMinMaxBuckets<D> {
1715+
pub(super) fn track_datapoint(
1716+
&mut self, min_offset_msat: u64, max_offset_msat: u64, capacity_msat: u64,
1717+
) {
1718+
self.min_liquidity_offset_history.track_datapoint(min_offset_msat, capacity_msat);
1719+
self.max_liquidity_offset_history.track_datapoint(max_offset_msat, capacity_msat);
1720+
}
16981721
}
16991722

17001723
impl<D: Deref<Target = HistoricalBucketRangeTracker>> HistoricalMinMaxBuckets<D> {
1724+
pub(super) fn min_liquidity_offset_history_buckets(&self) -> &[u16; 32] {
1725+
&self.min_liquidity_offset_history.buckets
1726+
}
1727+
1728+
pub(super) fn max_liquidity_offset_history_buckets(&self) -> &[u16; 32] {
1729+
&self.max_liquidity_offset_history.buckets
1730+
}
1731+
17011732
#[inline]
17021733
pub(super) fn calculate_success_probability_times_billion(
17031734
&self, params: &ProbabilisticScoringFeeParameters, amount_msat: u64,
@@ -1824,8 +1855,8 @@ impl Writeable for ChannelLiquidity {
18241855
(2, self.max_liquidity_offset_msat, required),
18251856
// 3 was the max_liquidity_offset_history in octile form
18261857
(4, self.last_updated, required),
1827-
(5, self.liquidity_history.min_liquidity_offset_history, required),
1828-
(7, self.liquidity_history.max_liquidity_offset_history, required),
1858+
(5, self.liquidity_history.writeable_min_offset_history(), required),
1859+
(7, self.liquidity_history.writeable_max_offset_history(), required),
18291860
(9, self.offset_history_last_updated, required),
18301861
});
18311862
Ok(())

0 commit comments

Comments
 (0)