- Feature Name: contextual_difficulty_validation
- Start Date: 2020-11-02
- Design PR: [ZcashFoundation/zebra#0000](https://github.com/ZcashFoundation/zebra/pull/0000)
- Zebra Issue: [ZcashFoundation/zebra#1036](https://github.com/ZcashFoundation/zebra/issues/1036)

# Summary
[summary]: #summary

Zcash nodes use a Proof of Work algorithm to reach consensus on the best chain.
Valid blocks must reach a difficulty threshold, which is adjusted after every
block. The difficulty adjustment calculations depend on the difficulties and
times of recent blocks. So Zebra performs contextual validation [RFC2] of
difficulty adjustments as part of committing blocks to the state.

[RFC2]: ./0002-parallel-verification.md

# Motivation
[motivation]: #motivation

The Zcash block difficulty adjustment is one of the core Zcash consensus rules.
Zebra must implement this consensus rule to make sure that its cached chain
state is consistent with the consensus of Zcash nodes.

Difficulty adjustment is also a significant part of Zcash's security guarantees.
It ensures that the network continues to resist takeover attacks, even as the
number of Zcash miners grows.

Difficulty adjustment also ensures that blocks are regularly spaced, which
allows users to create and finalise transactions with short, consistent delays.
These predictable delays contribute to Zcash's usability.

# Definitions
[definitions]: #definitions

Difficulty:
* **hash difficulty**: An arbitrary ranking of blocks, based on their hashes.
  Defined as the hash of the block, interpreted as a big-endian 256-bit number.
  Numerically smaller difficulties are harder to generate.

* **difficulty threshold**: The easiest valid hash difficulty for a block.
  Numerically lower thresholds are harder to satisfy.

* **difficulty filter**: A block passes the difficulty filter if the hash
  difficulty is less than or equal to the difficulty threshold (based on the
  block's difficulty field).

* **block work**: The approximate amount of work required for a miner to generate
  a block hash that passes the difficulty filter. The number of block header
  attempts and the mining time are proportional to the work value. Numerically
  higher work values represent longer processing times.

* **averaging window**: The 17 most recent blocks in the relevant chain.

* **median block span**: The 11 most recent blocks from a chosen tip, typically
  the relevant tip.

* **target spacing**: 150 seconds per block before Blossom activation, 75 seconds
  per block from Blossom activation onwards.

* **adjusted difficulty**: After each block is mined, the difficulty threshold of
  the next block is adjusted, to keep the block gap close to the target spacing.

* **mean target difficulty**: The arithmetic mean of the difficulty thresholds
  of the blocks in the averaging window.

* **median timespan**: The average number of seconds taken to generate the blocks
  in the averaging window. Calculated using the difference of median block spans
  in and after the averaging window, then damped and bounded.

* **target timespan**: The target spacing for an averaging window's worth of
  blocks.

Consensus:
* **consensus rule:** A protocol rule which all nodes must apply consistently,
                      so they can converge on the same chain fork.

* **structural/semantic/contextual verification**: as defined in [RFC2].

State:
* **block chain**: A sequence of valid blocks linked by inclusion of the
  previous block hash in the subsequent block. Chains are rooted at the
  genesis block and extend to a tip.

* **relevant chain**: The relevant chain for a block starts at the previous
  block, and extends back to genesis.

* **relevant tip**: The tip of the relevant chain.

* **non-finalized state**: State data corresponding to blocks above the reorg
  limit. This data can change in the event of a chain reorg.

* **finalized state**: State data corresponding to blocks below the reorg
  limit. This data cannot change in the event of a chain reorg.

* **non-finalized tips**: The highest blocks in each non-finalized chain. These
  tips might be at different heights.

* **finalized tip**: The highest block in the finalized state. The tip of the best
  chain is usually 100 blocks (the reorg limit) above the finalized tip. But it can
  be lower during the initial sync, and after a chain reorganization, if the new
  best chain is at a lower height.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

Zcash's difficulty consensus rules are similar to Bitcoin.

Each block contains a **difficulty threshold** in its header. The hash of the
block header must be less than this **difficulty threshold**. (When interpreted
as a 256-bit integer in big-endian byte order.) This context-free semantic
verification check is performed by the `BlockVerifier`.

After each block, the difficulty threshold is adjusted so that the block gap is
close to the target spacing. On average, harder blocks take longer to mine, and
easier blocks take less time.

The **adjusted difficulty** for the next block is calculated using the difficulty
thresholds and times of recent blocks. Zcash uses the most recent 28 blocks in
the **relevant chain** in its difficulty adjustment calculations.

The difficulty adjustment calculations adjust the **mean target difficulty**,
based on the difference between the **median timespan** and the
**target timespan**. If the median timespan is less than the target timespan, the
next block is harder to mine.

The `StateService` calculates the adjusted difficulty using the context from the
**relevant chain**. The difficulty contextual verification check ensures that the
**difficulty threshold** of the next block is equal to the **adjusted difficulty**
for its relevant chain.

## State service interface changes
[state-service-interface]: #state-service-interface

Contextual validation accesses recent blocks. So we modify the internal state
service interface to provide an abstraction for accessing recent blocks.

### The relevant chain
[relevant-chain]: #relevant-chain

The relevant chain consists of the ancestors of a block, starting with its
parent block, and extending back to the genesis block.

In Zebra, recent blocks are part of the non-finalized state, which can contain
multiple chains. Past the reorganization limit, Zebra commits a single chain to
the finalized state.

The relevant chain can start at any block in the non-finalized state, or at the
finalized tip. See [RFC5] for details.

[RFC5]: ./0005-state-updates.md

## Contextual validation design
[contextual-validation-design]: #contextual-validation-design

Contextual validation is performed synchronously by the state service, as soon
as the state has:
* received the semantically valid next block (via `CommitBlock`), and
* committed the previous block.

The difficulty adjustment check calculates the correct adjusted difficulty
threshold value for a candidate block, and ensures that the block's
`difficulty_threshold` field is equal to that value.

This check is implemented as follows:

### Difficulty adjustment
[difficulty-adjustment]: #difficulty-adjustment

The block difficulty threshold is adjusted by scaling the mean target difficulty
by the median timespan.

On Testnet, if a long time has elapsed since the previous block, the difficulty
adjustment is modified to allow minimum-difficulty blocks.

#### Mean target difficulty
[mean-target-difficulty]: #mean-target-difficulty

The mean target difficulty is the arithmetic mean of the difficulty
thresholds of the `PoWAveragingWindow` (17) most recent blocks in the relevant
chain.

Zcash uses block difficulty thresholds in its difficulty adjustment calculations.
(Block hashes are not used for difficulty adjustment.)

#### Median timespan
[median-timespan]: #median-timespan

The average number of seconds taken to generate the 17 blocks in the averaging
window.

The median timespan is calculated by taking the difference of the median times
for:
* the relevant tip: the `PoWMedianBlockSpan` (11) most recent blocks, and
* the 11 blocks after the 17-block `PoWAveragingWindow`: that is, blocks 18-28
  behind the relevant tip.

The median timespan is damped by the `PoWDampingFactor`, and bounded by
`PoWMaxAdjustDown` and `PoWMaxAdjustUp`.

#### Test network minimum difficulty blocks
[test-net-min-difficulty]: #test-net-min-difficulty

If there is a large gap after a Testnet block, the next block becomes a minimum
difficulty block. Testnet minimum difficulty blocks have their
`difficulty_threshold` set to the minimum difficulty for Testnet.

#### Block difficulty threshold
[block-difficulty-threshold]: #block-difficulty-threshold

The block difficulty threshold for the next block is calculated by scaling the
mean target difficulty by the ratio between the median timespan and the averaging
window timespan.

The result of this calculation is limited by `ToCompact(PoWLimit(network))`, a
per-network minimum block difficulty. This minimum difficulty is also used when
a Testnet block's time gap exceeds the minimum difficulty gap.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

## Contextual validation
[contextual-validation]: #contextual-validation

Contextual validation is implemented in
`StateService::check_contextual_validity`, which calls a separate function for
each contextual validity check.

In Zebra, contextual validation starts after Canopy activation, so we can assume
that the relevant chain contains at least 28 blocks on Mainnet and Testnet. (And
panic if this assumption does not hold at runtime.)

## Fundamental data types
[fundamental-data-types]: #fundamental-data-types

Zebra is free to implement its difficulty calculations in any way that produces
equivalent results to `zcashd` and the Zcash specification.

### Difficulty

In Zcash block headers, difficulty thresholds are stored as a "compact" `nBits`
value, which uses a custom 32-bit floating-point encoding. Zebra calls this type
`CompactDifficulty`.

In Zcash, difficulty threshold calculations are performed using unsigned 256-bit
integers. Rust has no standard `u256` type, but there are a number of crates
available which implement the required operations on 256-bit integers. Zebra
abstracts over the chosen `u256` implementation using its `ExpandedDifficulty`
type.

### Time

In Zcash, time values are unsigned 32-bit integers. But the difficulty adjustment
calculations include time subtractions which could overflow an unsigned type, so
they are performed using signed 64-bit integers in `zcashd`.

Zebra parses the `header.time` field into a `DateTime<Utc>`. Conveniently, the
`chrono::DateTime<_>::timestamp()` function returns `i64` values. So Zebra can do
its signed time calculations using `i64` values internally.

Note: `i32` is an unsuitable type for signed time calculations. It is
theoretically possible for the time gap between blocks to be larger than
`i32::MAX`, because those times are provided by miners. Even if the median time
gap is that large, the bounds and minimum difficulty in Zcash's difficulty
adjustment algorithm will preserve a reasonable difficulty threshold. So Zebra
must support this edge case.

### Consensus-Critical Operations

The order of operations and overflow semantics for 256-bit integers can be
consensus-critical.

For example:
  - dividing before multiplying discards lower-order bits, but
  - multiplying before dividing can cause overflow.

Zebra's implementation should try to match zcashd's order of operations and
overflow handling as closely as possible.

## Difficulty adjustment check
[difficulty-adjustment-check]: #difficulty-adjustment-check

The difficulty adjustment check calculates the correct difficulty threshold
value for a candidate block, and ensures that the block's
`difficulty_threshold` field is equal to that value.

### Context data type
[context-data-type]: #context-data-type

The difficulty adjustment functions use a context consisting of the difficulties
and times from the previous 28 blocks in the relevant chain.

These functions also use the candidate block's `height` and `network`.

To make these functions more ergonomic, we create a `AdjustedDifficulty`
type, and implement the difficulty adjustment calculations as methods on that
type.

```rust
/// The averaging window for difficulty threshold arithmetic mean calculations.                               
///                                                                                                           
/// `PoWAveragingWindow` in the Zcash specification.                                                          
pub const POW_AVERAGING_WINDOW: usize = 17;

/// The median block span for time median calculations.                                                       
///                                                                                                           
/// `PoWMedianBlockSpan` in the Zcash specification.                                                          
pub const POW_MEDIAN_BLOCK_SPAN: usize = 11;

/// Contains the context needed to calculate the adjusted difficulty for a block. 
struct AdjustedDifficulty {
    candidate_time: DateTime<Utc>,
    candidate_height: block::Height,
    network: Network,
    relevant_difficulty_thresholds: [CompactDifficulty; POW_AVERAGING_WINDOW + POW_MEDIAN_BLOCK_SPAN],
    relevant_times: [DateTime<Utc>; POW_AVERAGING_WINDOW + POW_MEDIAN_BLOCK_SPAN],
}
```

We implement some initialiser methods on `AdjustedDifficulty` for convenience.
We might want to validate downloaded headers in future, so we include a
`new_from_header` initialiser.

```rust
/// Initialise and return a new `AdjustedDifficulty` using a `candidate_block`,
/// `network`, and a `context`.
///
/// The `context` contains the previous
/// `PoWAveragingWindow + PoWMedianBlockSpan` (28) `difficulty_threshold`s and
/// `time`s from the relevant chain for `candidate_block`, in reverse height
/// order, starting with the previous block.
///
/// Note that the `time`s might not be in reverse chronological order, because
/// block times are supplied by miners.
///
/// Panics:
/// If the `context` contains fewer than 28 items.
pub fn new_from_block<C>(candidate_block: &Block,
                         network: Network,
                         context: C)
                         -> AdjustedDifficulty
    where
        C: IntoIterator<Item = (CompactDifficulty, DateTime<Utc>)>,
    { ... }

/// Initialise and return a new `AdjustedDifficulty` using a
/// `candidate_header`, `previous_block_height`, `network`, and a `context`.
///
/// Designed for use when validating block headers, where the full block has not
/// been downloaded yet.
///
/// See `new_from_block` for detailed information about the `context`.
///
/// Panics:
/// If the context contains fewer than 28 items.
pub fn new_from_header<C>(candidate_header: &block::Header,
                          previous_block_height: block::Height,
                          network: Network,
                          context: C)
                          -> AdjustedDifficulty
    where
        C: IntoIterator<Item = (CompactDifficulty, DateTime<Utc>)>,
    { ... }
```

#### Memory usage note

Copying `CompactDifficulty` values into the `AdjustedDifficulty` struct uses
less memory than borrowing those values. `CompactDifficulty` values are 32 bits,
but pointers are 64-bit on most modern machines. (And since they all come from
different blocks, we need a pointer to each individual value.)

Borrowing `DateTime<Utc>` values might use slightly less memory than copying
them - but that depends on the exact way that Rust stores associated types
derived from a generic argument.

In any case, the overall size of each `AdjustedDifficulty` is only a few
hundred bytes. If it turns up in profiles, we can look at borrowing the block
header data.

### Difficulty adjustment check implementation
[difficulty-adjustment-check-implementation]: #difficulty-adjustment-check-implementation

The difficulty adjustment check ensures that the
`candidate_difficulty_threshold` is equal to the `difficulty_threshold` value
calculated using `AdjustedDifficulty::adjusted_difficulty_threshold`.

We implement this function:
```rust
/// Validate the `difficulty_threshold` from a candidate block's header, based
/// on an `expected_difficulty` for that block.
///
/// Uses `expected_difficulty` to calculate the expected `ToCompact(Threshold())`
/// value, then compares that value to the `difficulty_threshold`. Returns
/// `Ok(())` if the values are equal.
pub fn difficulty_threshold_is_valid(difficulty_threshold: CompactDifficulty,
                                     expected_difficulty: AdjustedDifficulty)
                                     -> Result<(), ValidateContextError> { ... }
```

[Issue 1166]: https://github.com/ZcashFoundation/zebra/issues/1166

### Mean target difficulty calculation
[mean-target-difficulty-calculation]: #mean-target-difficulty-calculation

The mean target difficulty is the arithmetic mean of the difficulty
thresholds of the `PoWAveragingWindow` (17) most recent blocks in the relevant
chain.

We implement this method on `AdjustedDifficulty`:
```rust
/// Calculate the arithmetic mean of the averaging window thresholds: the
/// expanded `difficulty_threshold`s from the previous `PoWAveragingWindow` (17)
/// blocks in the relevant chain.
///
/// Implements `MeanTarget` from the Zcash specification.
fn mean_target_difficulty(&self) -> ExpandedDifficulty { ... }
```

#### Implementation notes

Since the `PoWLimit`s are `2^251 − 1` for Testnet, and `2^243 − 1` for Mainnet,
the sum of these difficulty thresholds will be less than or equal to
`(2^251 − 1)*17 = 2^255 + 2^251 - 17`. Therefore, this calculation can not
overflow a `u256` value. So the function is infalliable.

In Zebra, contextual validation starts after Canopy activation, so we can assume
that the relevant chain contains at least 17 blocks. Therefore, the `PoWLimit`
case of `MeanTarget()` in the Zcash specification is unreachable.

### Median timespan calculation
[median-timespan-calculation]: #median-timespan-calculation

The median timespan is the difference of the median times for:
* the relevant tip: the `PoWMedianBlockSpan` (11) most recent blocks, and
* the 11 blocks after the 17-block `PoWAveragingWindow`: that is, blocks 18-28
  behind the relevant tip.

(The median timespan is known as the `ActualTimespan` in the Zcash specification,
but this terminology is confusing, because it is a difference of medians, rather
than any "actual" elapsed time.)

Zebra implements the median timespan using the following methods on
`AdjustedDifficulty`:
```rust
/// Calculate the bounded 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) -> Duration { ... }

/// 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 { ... }

/// 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<Utc>; POW_MEDIAN_BLOCK_SPAN])
               -> DateTime<Utc> { ... }
```

Zebra implements the `AveragingWindowTimespan` using the following methods on
`NetworkUpgrade`:
```rust
impl NetworkUpgrade {
    /// Returns the `AveragingWindowTimespan` for the network upgrade.
    pub fn averaging_window_timespan(&self) -> Duration { ... }

    /// Returns the `AveragingWindowTimespan` for `network` and `height`.
    pub fn averaging_window_timespan_for_height(network: Network,
                                                height: block::Height)
                                                -> Duration { ... }
}
```

#### Implementation notes

In Zebra, contextual validation starts after Canopy activation, so we can assume
that the relevant chain contains at least 28 blocks. Therefore:
* `max(0, height − PoWMedianBlockSpan)` in the `MedianTime()` calculation
   simplifies to `height − PoWMedianBlockSpan`, and
* there is always an odd number of blocks in `MedianTime()`, so the median is
  always the exact middle of the sequence.

Therefore, the function is infalliable.

### Test network minimum difficulty calculation
[test-net-min-difficulty-calculation]: #test-net-min-difficulty-calculation

A block is a Testnet minimum difficulty block if:
* the block is a Testnet block,
* the block's height is 299188 or greater, and
* the time gap from the previous block is greater than the Testnet minimum
  difficulty gap, which is 6 times the target spacing for the block's height.
  (The target spacing was halved from the Blossom network upgrade onwards.)

The difficulty adjustment is modified for Testnet minimum difficulty blocks as
follows:
* the difficulty threshold in the block header is set to the Testnet minimum
  difficulty threshold, `ToCompact(PoWLimit(network))`.

Since the new difficulty changes the block header, Testnet blocks can only
satisfy one of the alternate difficulty adjustment rules:
* if the time gap is less than or equal to the Testnet minimum difficulty gap:
  the difficulty threshold is calculated using the default difficulty adjustment
  rule,
* if the time gap is greater than the Testnet minimum difficulty gap:
  the difficulty threshold is the Testnet minimum difficulty threshold.

See [ZIP-208] for details.

Note: some older versions of ZIPs 205 and 208 incorrectly said that:
* the time gap threshold uses an "at least" check (it is strictly greater than),
* the minimum difficulty threshold value was `PoWLimit`
  (it is `ToCompact(PoWLimit)`),
* the `difficulty_threshold` (`nBits`) field is not modified in Testnet minimum
  difficulty blocks (the field is modified), and
* the Testnet minimum difficulty value is not used to calculate future difficulty
  adjustments (the modified value is used in future adjustments).

ZIP 205 and 208 were fixed on 14 November 2020, see [ZIP PR 417] and
[ZIP commit 806076c] for details.

[ZIP-208]: https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network
[ZIP PR 417]: https://github.com/zcash/zips/pull/417
[ZIP commit 806076c]: https://github.com/zcash/zips/commit/806076c48c9834fd9941b940a32310d737975a3a

#### Test network minimum difficulty implementation
[test-net-min-difficulty-implementation]: #test-net-min-difficulty-implementation

The Testnet minimum difficulty calculation uses the existing
`NetworkUpgrade::minimum_difficulty_spacing_for_height` function to calculate the
minimum difficulty gap.

We implement this method on `NetworkUpgrade`:
```rust
/// Returns true if the gap between `block_time` and `previous_block_time` is                             
/// greater than the Testnet minimum difficulty time gap. This time gap                                   
/// depends on the `network` and `block_height`.                                                          
///                                                                                                       
/// Returns false on Mainnet, when `block_height` is less than the minimum                                
/// difficulty start height, and when the time gap is too small.                                          
///                                                                                                       
/// `block_time` can be less than, equal to, or greater than                                              
/// `previous_block_time`, because block times are provided by miners.                                    
///                                                                                                       
/// Implements the Testnet minimum difficulty adjustment from ZIPs 205 and 208.                           
///                                                                                                       
/// Spec Note: Some parts of ZIPs 205 and 208 previously specified an incorrect                           
/// check for the time gap. This function implements the correct "greater than"                           
/// check.                                                                                                
pub fn is_testnet_min_difficulty_block(
    network: Network,
    block_height: block::Height,
    block_time: DateTime<Utc>,
    previous_block_time: DateTime<Utc>,
) -> bool { ... }
```

#### Implementation notes

In Zcash, the Testnet minimum difficulty rule starts at block 299188, and in
Zebra, contextual validation starts after Canopy activation. So we can assume
that there is always a previous block.

Therefore, this function is infalliable.

### Block difficulty threshold calculation
[block-difficulty-threshold-calculation]: #block-difficulty-threshold-calculation

The block difficulty threshold for the next block is calculated by scaling the
mean target difficulty by the ratio between the median timespan and the averaging
window timespan.

The result of the scaled threshold calculation is limited by
`ToCompact(PoWLimit(network))`, a per-network minimum block difficulty. This
minimum difficulty is also used when a Testnet block's time gap exceeds the
minimum difficulty gap. We use the existing
`ExpandedDifficulty::target_difficulty_limit` function to calculate the value of
`ToCompact(PoWLimit(network))`.

In Zebra, contextual validation starts after Canopy activation, so the genesis
case of `Threshold()` in the Zcash specification is unreachable.

#### Block difficulty threshold implementation
[block-difficulty-threshold-implementation]: #block-difficulty-threshold-implementation

We implement these methods on `AdjustedDifficulty`:
```rust
/// Calculate the expected `difficulty_threshold` for a candidate block, based
/// on the `candidate_time`, `candidate_height`, `network`, and the
/// `difficulty_threshold`s and `time`s from the previous
/// `PoWAveragingWindow + PoWMedianBlockSpan` (28) blocks in the relevant chain.
///
/// Implements `ThresholdBits` from the Zcash specification, and the Testnet
/// minimum difficulty adjustment from ZIPs 205 and 208.
pub fn expected_difficulty_threshold(&self) -> CompactDifficulty { ... }

/// Calculate the `difficulty_threshold` for a candidate block, based on the
/// `candidate_height`, `network`, and the relevant `difficulty_threshold`s and
/// `time`s.
///
/// See `expected_difficulty_threshold` for details.
///
/// Implements `ThresholdBits` from the Zcash specification. (Which excludes the
/// Testnet minimum difficulty adjustment.)
fn threshold_bits(&self) -> CompactDifficulty { ... }
```

#### Implementation notes

Since:
* the `PoWLimit`s are `2^251 − 1` for Testnet, and `2^243 − 1` for Mainnet,
* the `ActualTimespanBounded` can be at most `MaxActualTimespan`, which is
  `floor(PoWAveragingWindow * PoWTargetSpacing * (1 + PoWMaxAdjustDown))` or
  `floor(17 * 150 * (1 + 32/100)) =  3366`,
* `AveragingWindowTimespan` is at most `17 * 150 = 2250`, and
* `MeanTarget` is at most `PoWLimit`, ...

The maximum scaled value inside the `Threshold()` calculation is:
* `floor(PoWLimit / 2250) * 3366`, which equals
* `floor((2^251 − 1) / 2250) * 3366`, which equals
* `(2^251 − 1) * 132/100`,
* which is less than `2^252`.

Therefore, this calculation can not overflow a `u256` value. (And even if it did
overflow, it would be constrained to a valid value by the `PoWLimit` minimum.)

Note that the multiplication by `ActualTimespanBounded` must happen after the
division by `AveragingWindowTimespan`. Performing the multiplication first
could overflow.

If implemented in this way, the function is infalliable.

`zcashd` truncates the `MeanTarget` after the mean calculation, and
after dividing by `AveragingWindowTimespan`. But as long as there is no overflow,
this is [equivalent to the single truncation of the final result] in the Zcash
specification. However, Zebra should follow the order of operations in `zcashd`,
and use repeated divisions, because that can't overflow. See the relevant
[comment in the zcashd souce code].

[equivalent to the single truncation of the final result]: https://math.stackexchange.com/questions/147771/rewriting-repeated-integer-division-with-multiplication
[comment in the zcashd souce code]: https://github.com/zcash/zcash/pull/4860/files

## Module Structure
[module-structure]: #module-structure

The structs and functions in this RFC are implemented in a new
`zebra_state::service::check::difficulty` module.

This module has two entry points:
* `DifficultyAdjustment::new_from_block`
* `difficulty_threshold_is_valid`

These entry points are both called from
`StateService::check_contextual_validity`.

## Test Plan
[test-plan]: #test-plan

Explain how the feature will be tested, including:
- [ ] tests for consensus-critical functionality
- [ ] existing test vectors, if available
- [ ] Zcash blockchain block test vectors (specify the network upgrade, feature, or block height and network)
- [ ] property testing or fuzzing

The tests should cover:
- [ ] positive cases: make sure the feature accepts valid inputs
    - using block test vectors for each network upgrade provides some coverage of valid inputs
- [ ] negative cases: make sure the feature rejects invalid inputs
    - make sure there is a test case for each error condition in the code
    - if there are lots of potential errors, prioritise:
        - consensus-critical errors
        - security-critical errors, and
        - likely errors
- [ ] edge cases: make sure that boundary conditions are correctly handled

# Drawbacks
[drawbacks]: #drawbacks

Why should we *not* do this?

## Alternate consensus parameters
[alternate-consensus-parameters]: #alternate-consensus-parameters

Any alternate consensus parameters or `regtest` mode would have to respect the constraints set by this design.

In particular:
  * the `PoWLimit` must be less than or equal to
    `(2^256 - 1) / PoWAveragingWindow` (approximately `2^251`) to avoid overflow,
  * the `PoWAveragingWindow` and `PoWMedianBlockSpan` are fixed by function argument types
    (at least until Rust gets stable const generics), and
  * the design eliminates a significant number of edge cases by assuming that difficulty adjustments aren't
    validated for the first `PoWAveragingWindow + PoWMedianBlockSpan` (28) blocks in the chain.

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

## Is this design a good basis for later designs or implementations?
[good-basis]: #good-basis

The design includes specific methods for a future header-only validation design.

## What other designs have been considered and what is the rationale for not choosing them?
[alternate-designs]: #alternate-designs

A previous version of the RFC did not have the `AdjustedDifficulty` struct and
methods. That design was easy to misuse, because each function had a complicated
argument list.

## What is the impact of not doing this?
[no-action]: #no-action

Zebra could accept invalid, low-difficulty blocks from arbitrary miners. That
would be a security issue.

# Prior art
[prior-art]: #prior-art

* `zcashd`
* the Zcash specification
* Bitcoin

# Unresolved questions
[unresolved-questions]: #unresolved-questions

- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
  - Guide-level examples
  - Reference-level examples
  - Corner case examples
  - Testing

- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?
  - Monitoring and maintainence

# Future possibilities
[future-possibilities]: #future-possibilities

## Re-using the relevant chain API in other contextual checks
[relevant-chain-api-reuse]: #relevant-chain-api-reuse

The relevant chain iterator can be re-used to implement other contextual
validation checks.

For example, responding to peer requests for block locators, which means
implementing relevant chain hash queries as a `StateService` request

## Header-only difficulty adjustment validation
[header-only-validation]: #header-only-validation

Implementing header-only difficulty adjustment validation as a `StateService` request.

## Caching difficulty calculations
[caching-calculations]: #caching-calculations

Difficulty calculations use `u256` could be a bit expensive, particularly if we
get a flood of low-difficulty blocks. To reduce the impact of this kind of DoS,
we could cache the value returned by `threshold_bits` for each block in the
non-finalized state, and for the finalized tip. This value could be used to
quickly calculate the difficulties for any child blocks of these blocks.

There's no need to persist this cache, or pre-fill it. (Minimum-difficulty
Testnet blocks don't call `threshold_bits`, and some side-chain blocks will
never have a next block.)

This caching is only worth implementing if these calculations show up in `zebrad`
profiles.
