Split out a median_timespan function

This commit is contained in:
teor 2020-11-19 12:00:10 +10:00
parent 054d6f0525
commit f0a49d64bf
1 changed files with 30 additions and 19 deletions

View File

@ -201,9 +201,10 @@ impl AdjustedDifficulty {
(total / divisor).into() (total / divisor).into()
} }
/// Calculate the median timespan. The median timespan is the difference of /// Calculate the bounded median timespan. The median timespan is the
/// medians of the timespan times, which are the `time`s from the previous /// difference of medians of the timespan times, which are the `time`s from
/// `PoWAveragingWindow + PoWMedianBlockSpan` (28) blocks in the relevant chain. /// the previous `PoWAveragingWindow + PoWMedianBlockSpan` (28) blocks in the
/// relevant chain.
/// ///
/// Uses the candidate block's `height' and `network` to calculate the /// Uses the candidate block's `height' and `network` to calculate the
/// `AveragingWindowTimespan` for that block. /// `AveragingWindowTimespan` for that block.
@ -216,27 +217,13 @@ impl AdjustedDifficulty {
/// Note: This calculation only uses `PoWMedianBlockSpan` (11) times at the /// Note: This calculation only uses `PoWMedianBlockSpan` (11) times at the
/// start and end of the timespan times. timespan times `[11..=16]` are ignored. /// start and end of the timespan times. timespan times `[11..=16]` are ignored.
fn median_timespan_bounded(&self) -> Duration { fn median_timespan_bounded(&self) -> Duration {
let newer_times: [DateTime<Utc>; POW_MEDIAN_BLOCK_SPAN] = self.relevant_times
[0..POW_MEDIAN_BLOCK_SPAN]
.try_into()
.expect("relevant times is the correct length");
let newer_median = AdjustedDifficulty::median_time(newer_times);
let older_times: [DateTime<Utc>; POW_MEDIAN_BLOCK_SPAN] = self.relevant_times
[POW_AVERAGING_WINDOW..]
.try_into()
.expect("relevant times is the correct length");
let older_median = AdjustedDifficulty::median_time(older_times);
// `ActualTimespan` in the Zcash specification
let median_timespan = newer_median - older_median;
let averaging_window_timespan = NetworkUpgrade::averaging_window_timespan_for_height( let averaging_window_timespan = NetworkUpgrade::averaging_window_timespan_for_height(
self.network, self.network,
self.candidate_height, self.candidate_height,
); );
// This value is exact, but we need to truncate its nanoseconds component // This value is exact, but we need to truncate its nanoseconds component
let damped_variance = (median_timespan - averaging_window_timespan) / POW_DAMPING_FACTOR; let damped_variance =
(self.median_timespan() - averaging_window_timespan) / POW_DAMPING_FACTOR;
// num_seconds truncates negative values towards zero, matching the Zcash specification // num_seconds truncates negative values towards zero, matching the Zcash specification
let damped_variance = Duration::seconds(damped_variance.num_seconds()); let damped_variance = Duration::seconds(damped_variance.num_seconds());
@ -256,6 +243,30 @@ impl AdjustedDifficulty {
) )
} }
/// 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.
///
/// Implements `ActualTimespan` from the Zcash specification.
///
/// See `median_timespan_bounded` for details.
fn median_timespan(&self) -> Duration {
let newer_times: [DateTime<Utc>; POW_MEDIAN_BLOCK_SPAN] = self.relevant_times
[0..POW_MEDIAN_BLOCK_SPAN]
.try_into()
.expect("relevant times is the correct length");
let newer_median = AdjustedDifficulty::median_time(newer_times);
let older_times: [DateTime<Utc>; POW_MEDIAN_BLOCK_SPAN] = self.relevant_times
[POW_AVERAGING_WINDOW..]
.try_into()
.expect("relevant times is the correct length");
let older_median = AdjustedDifficulty::median_time(older_times);
// `ActualTimespan` in the Zcash specification
newer_median - older_median
}
/// Calculate the median of the `median_block_span_times`: the `time`s from a /// Calculate the median of the `median_block_span_times`: the `time`s from a
/// slice of `PoWMedianBlockSpan` (11) blocks in the relevant chain. /// slice of `PoWMedianBlockSpan` (11) blocks in the relevant chain.
/// ///