From 76a9f5b8c40d94669b4ad469d5054d7f1bca48db Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 11 Nov 2020 00:41:24 +1000 Subject: [PATCH] Refactor block target spacing into NetworkUpgrade methods And add a method for the minimum difficulty time gap threshold. --- zebra-chain/src/parameters/network_upgrade.rs | 60 +++++++++++++++++++ zebra-consensus/src/parameters/subsidy.rs | 14 ++--- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 3fc8e0916..d3db8f740 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -8,6 +8,8 @@ use crate::parameters::{Network, Network::*}; use std::collections::{BTreeMap, HashMap}; use std::ops::Bound::*; +use chrono::Duration; + /// A Zcash network upgrade. /// /// Network upgrades can change the Zcash network protocol or consensus rules in @@ -96,6 +98,23 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Canopy, ConsensusBranchId(0xe9ff75a6)), ]; +/// The target block spacing before Blossom. +const PRE_BLOSSOM_POW_TARGET_SPACING: i64 = 150; + +/// The target block spacing after Blossom activation. +const POST_BLOSSOM_POW_TARGET_SPACING: i64 = 75; + +/// The multiplier used to derive the testnet minimum difficulty block time gap +/// threshold. +/// +/// Based on https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network +const TESTNET_MINIMUM_DIFFICULTY_GAP_MULTIPLIER: i32 = 6; + +/// The start height for the testnet minimum difficulty consensus rule. +/// +/// Based on https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network +const TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT: block::Height = block::Height(299_188); + impl NetworkUpgrade { /// Returns a BTreeMap of activation heights and network upgrades for /// `network`. @@ -163,6 +182,47 @@ impl NetworkUpgrade { pub fn branch_id(&self) -> Option { NetworkUpgrade::branch_id_list().get(&self).cloned() } + + /// Returns the target block spacing for the network upgrade. + /// + /// Based on `PRE_BLOSSOM_POW_TARGET_SPACING` and + /// `POST_BLOSSOM_POW_TARGET_SPACING` from the Zcash specification. + pub fn target_spacing(&self) -> Duration { + let spacing_seconds = match self { + Genesis | BeforeOverwinter | Overwinter | Sapling => PRE_BLOSSOM_POW_TARGET_SPACING, + Blossom | Heartwood | Canopy => POST_BLOSSOM_POW_TARGET_SPACING, + }; + + Duration::seconds(spacing_seconds) + } + + /// Returns the target block spacing for `network` and `height`. + /// + /// See `target_spacing` for details. + pub fn target_spacing_for_height(network: Network, height: block::Height) -> Duration { + NetworkUpgrade::current(network, height).target_spacing() + } + + /// Returns the minimum difficulty block spacing for `network` and `height`. + /// Returns `None` if the testnet minimum difficulty consensus rule is not active. + /// + /// Based on https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network + /// + /// `zcashd` requires a gap that's strictly greater than 6 times the target + /// threshold, but ZIP-205 and ZIP-208 are ambiguous. See bug #1276. + pub fn minimum_difficulty_spacing_for_height( + network: Network, + height: block::Height, + ) -> Option { + match (network, height) { + (Network::Testnet, height) if height < TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT => None, + (Network::Mainnet, _) => None, + (Network::Testnet, _) => { + let network_upgrade = NetworkUpgrade::current(network, height); + Some(network_upgrade.target_spacing() * TESTNET_MINIMUM_DIFFICULTY_GAP_MULTIPLIER) + } + } + } } impl ConsensusBranchId { diff --git a/zebra-consensus/src/parameters/subsidy.rs b/zebra-consensus/src/parameters/subsidy.rs index 03894b311..fc5d00a01 100644 --- a/zebra-consensus/src/parameters/subsidy.rs +++ b/zebra-consensus/src/parameters/subsidy.rs @@ -1,7 +1,5 @@ //! Constants for Block Subsidy, Funding Streams, and Founders’ Reward -use std::time::Duration; - use zebra_chain::{amount::COIN, block::Height}; /// An initial period from Genesis to this Height where the block subsidy is gradually incremented. [What is slow-start mining][slow-mining] @@ -22,15 +20,11 @@ pub const SLOW_START_SHIFT: Height = Height(SLOW_START_INTERVAL.0 / 2); /// This calculation is exact, because COIN is divisible by 2, and the division is done last. pub const MAX_BLOCK_SUBSIDY: u64 = ((25 * COIN) / 2) as u64; -/// The blocktime before Blossom, used to calculate ratio. -pub const PRE_BLOSSOM_POW_TARGET_SPACING: Duration = Duration::from_secs(150); - -/// The blocktime after Blossom, used to calculate ratio. -pub const POST_BLOSSOM_POW_TARGET_SPACING: Duration = Duration::from_secs(75); - /// Used as a multiplier to get the new halving interval after Blossom. -pub const BLOSSOM_POW_TARGET_SPACING_RATIO: u64 = - PRE_BLOSSOM_POW_TARGET_SPACING.as_secs() / POST_BLOSSOM_POW_TARGET_SPACING.as_secs(); +/// +/// Calculated as `PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING` +/// in the Zcash specification. +pub const BLOSSOM_POW_TARGET_SPACING_RATIO: u64 = 2; /// Halving is at about every 4 years, before Blossom block time is 150 seconds. ///