From e07b0bc8dab8ebe014e4e57c7c67862638d69462 Mon Sep 17 00:00:00 2001 From: teor Date: Thu, 19 Nov 2020 10:56:05 +1000 Subject: [PATCH] Implement median_time And enough stubs to run it on real data. --- zebra-state/src/service/check/difficulty.rs | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/zebra-state/src/service/check/difficulty.rs b/zebra-state/src/service/check/difficulty.rs index c429cc6f..a35c5c7a 100644 --- a/zebra-state/src/service/check/difficulty.rs +++ b/zebra-state/src/service/check/difficulty.rs @@ -151,6 +151,7 @@ impl AdjustedDifficulty { /// Testnet minimum difficulty adjustment.) fn threshold_bits(&self) -> CompactDifficulty { let mean_target = self.mean_target_difficulty(); + let _median_timespan = self.median_timespan_bounded(); // TODO: calculate the actual value mean_target.to_compact() @@ -187,4 +188,36 @@ impl AdjustedDifficulty { (total / divisor).into() } + + /// Calculate the median timespan. The median timespan is the difference of + /// medians of the timespan times, which are the `time`s from the previous + /// `PoWAveragingWindow + PoWMedianBlockSpan` (28) blocks in the relevant chain. + /// + /// Uses the candidate block's `height' and `network` to calculate the + /// `AveragingWindowTimespan` for that block. + /// + /// The median timespan is damped by the `PoWDampingFactor`, and bounded by + /// `PoWMaxAdjustDown` and `PoWMaxAdjustUp`. + /// + /// Implements `ActualTimespanBounded` from the Zcash specification. + /// + /// Note: This calculation only uses `PoWMedianBlockSpan` (11) times at the + /// start and end of the timespan times. timespan times `[11..=16]` are ignored. + fn median_timespan_bounded(&self) -> DateTime { + let newer_times: [DateTime; POW_MEDIAN_BLOCK_SPAN] = self.relevant_times + [0..POW_MEDIAN_BLOCK_SPAN] + .try_into() + .expect("relevant times is the correct length"); + // TODO: do the actual calculation + AdjustedDifficulty::median_time(newer_times) + } + + /// Calculate the median of the `median_block_span_times`: the `time`s from a + /// slice of `PoWMedianBlockSpan` (11) blocks in the relevant chain. + /// + /// Implements `MedianTime` from the Zcash specification. + fn median_time(mut median_block_span_times: [DateTime; 11]) -> DateTime { + median_block_span_times.sort_unstable(); + median_block_span_times[POW_MEDIAN_BLOCK_SPAN / 2] + } }