From 396d209638ad77b82da3bb83a4a2142113da552f Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 28 Jul 2020 09:39:00 +1000 Subject: [PATCH] feature: Add the MinimumDifficulty consensus parameter --- zebra-consensus/src/parameters.rs | 2 + .../src/parameters/minimum_difficulty.rs | 39 ++++++++++++++++++ zebra-consensus/src/parameters/tests.rs | 41 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 zebra-consensus/src/parameters/minimum_difficulty.rs diff --git a/zebra-consensus/src/parameters.rs b/zebra-consensus/src/parameters.rs index 141fbf95..7cc79210 100644 --- a/zebra-consensus/src/parameters.rs +++ b/zebra-consensus/src/parameters.rs @@ -10,9 +10,11 @@ //! `Network` and `BlockHeight`. pub mod genesis; +pub mod minimum_difficulty; pub mod network_upgrade; pub use genesis::*; +pub use minimum_difficulty::*; pub use network_upgrade::*; #[cfg(test)] diff --git a/zebra-consensus/src/parameters/minimum_difficulty.rs b/zebra-consensus/src/parameters/minimum_difficulty.rs new file mode 100644 index 00000000..b0aa79d0 --- /dev/null +++ b/zebra-consensus/src/parameters/minimum_difficulty.rs @@ -0,0 +1,39 @@ +//! The minimum difficulty block rule for Zcash. + +use zebra_chain::types::BlockHeight; +use zebra_chain::{Network, Network::*}; + +/// The testnet block height when minimum difficulty blocks start being +/// accepted. +pub(crate) const TESTNET_MINIMUM_DIFFICULTY_HEIGHT: BlockHeight = BlockHeight(299_188); + +/// The Zcash Testnet consensus rules were changed to allow +/// minimum-difficulty blocks, shortly after Testnet Sapling activation. +/// See ZIP-205 and ZIP-208 for details. +/// +/// This change represents a hard-fork on Testnet, but it doesn't appear on +/// Mainnet, so we handle it as an independent consensus rule change. +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub enum MinimumDifficulty { + /// Minimum difficulty blocks are rejected. + /// + /// Always returned for Mainnet blocks. + Rejected, + /// Minimum difficulty blocks are allowed. + /// + /// Only allowed for Testnet blocks. + AllowedOnTestnet, +} + +impl MinimumDifficulty { + /// Returns the current minimum difficulty rule for `network` and `height`. + pub fn current(network: Network, height: BlockHeight) -> MinimumDifficulty { + use MinimumDifficulty::*; + + match network { + Mainnet => Rejected, + Testnet if (height >= TESTNET_MINIMUM_DIFFICULTY_HEIGHT) => AllowedOnTestnet, + Testnet => Rejected, + } + } +} diff --git a/zebra-consensus/src/parameters/tests.rs b/zebra-consensus/src/parameters/tests.rs index b2e0b7d4..5879cc71 100644 --- a/zebra-consensus/src/parameters/tests.rs +++ b/zebra-consensus/src/parameters/tests.rs @@ -183,3 +183,44 @@ fn branch_id_consistent(network: Network) { } } } + +#[test] +fn minimum_difficulty_mainnet() { + minimum_difficulty(Mainnet) +} + +#[test] +fn minimum_difficulty_testnet() { + minimum_difficulty(Testnet) +} + +/// Test MinimumDifficulty +fn minimum_difficulty(network: Network) { + use MinimumDifficulty::*; + + let allowed_if_testnet = match network { + Mainnet => Rejected, + Testnet => AllowedOnTestnet, + }; + + assert_eq!( + MinimumDifficulty::current(network, BlockHeight(0)), + Rejected + ); + assert_eq!( + MinimumDifficulty::current(network, BlockHeight(299_187)), + Rejected + ); + assert_eq!( + MinimumDifficulty::current(network, BlockHeight(299_188)), + allowed_if_testnet + ); + assert_eq!( + MinimumDifficulty::current(network, BlockHeight(299_189)), + allowed_if_testnet + ); + assert_eq!( + MinimumDifficulty::current(network, BlockHeight::MAX), + allowed_if_testnet + ); +}