From d2d1a18d8199d9632772d652f65b2bc84f19125e Mon Sep 17 00:00:00 2001 From: Arya Date: Wed, 8 May 2024 13:14:54 -0400 Subject: [PATCH] add(consensus): Add `slow_start_{interval/shift}` fields to `testnet::Parameters` (#8477) * - Adds `slow_start_interval` field to `testnet::Parameters` - Moves SLOW_START_INTERVAL/SLOW_START_SHIFT constants to zebra-chain * Apply suggestions from code review Co-authored-by: Marek --------- Co-authored-by: Marek --- zebra-chain/src/parameters.rs | 1 + zebra-chain/src/parameters/constants.rs | 17 +++++ zebra-chain/src/parameters/network.rs | 8 --- zebra-chain/src/parameters/network/testnet.rs | 65 ++++++++++++++++++- zebra-consensus/src/block/check.rs | 4 +- zebra-consensus/src/block/subsidy/general.rs | 28 ++++---- zebra-consensus/src/block/tests.rs | 4 +- zebra-consensus/src/parameters/subsidy.rs | 12 ---- 8 files changed, 96 insertions(+), 43 deletions(-) create mode 100644 zebra-chain/src/parameters/constants.rs diff --git a/zebra-chain/src/parameters.rs b/zebra-chain/src/parameters.rs index 2974bd78cce..acae466fc6d 100644 --- a/zebra-chain/src/parameters.rs +++ b/zebra-chain/src/parameters.rs @@ -12,6 +12,7 @@ //! Typically, consensus parameters are accessed via a function that takes a //! `Network` and `block::Height`. +pub mod constants; mod genesis; mod network; mod network_upgrade; diff --git a/zebra-chain/src/parameters/constants.rs b/zebra-chain/src/parameters/constants.rs new file mode 100644 index 00000000000..cb988c36c4e --- /dev/null +++ b/zebra-chain/src/parameters/constants.rs @@ -0,0 +1,17 @@ +//! Definitions of Zebra chain constants, including: +//! - slow start interval, +//! - slow start shift + +use crate::block::Height; + +/// An initial period from Genesis to this Height where the block subsidy is gradually incremented. [What is slow-start mining][slow-mining] +/// +/// [slow-mining]: https://z.cash/support/faq/#what-is-slow-start-mining +pub const SLOW_START_INTERVAL: Height = Height(20_000); + +/// `SlowStartShift()` as described in [protocol specification §7.8][7.8] +/// +/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies +/// +/// This calculation is exact, because `SLOW_START_INTERVAL` is divisible by 2. +pub const SLOW_START_SHIFT: Height = Height(SLOW_START_INTERVAL.0 / 2); diff --git a/zebra-chain/src/parameters/network.rs b/zebra-chain/src/parameters/network.rs index f61bf71ef95..b9631e627e0 100644 --- a/zebra-chain/src/parameters/network.rs +++ b/zebra-chain/src/parameters/network.rs @@ -189,14 +189,6 @@ impl Network { } } - /// Returns true if proof-of-work validation should be disabled for this network - pub fn disable_pow(&self) -> bool { - if let Self::Testnet(params) = self { - params.disable_pow() - } else { - false - } - } /// Returns the [`NetworkKind`] for this network. pub fn kind(&self) -> NetworkKind { match self { diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index 9b562f0ac70..76e7bba2a42 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -6,8 +6,9 @@ use zcash_primitives::constants as zp_constants; use crate::{ block::{self, Height}, parameters::{ - network_upgrade::TESTNET_ACTIVATION_HEIGHTS, Network, NetworkUpgrade, - NETWORK_UPGRADES_IN_ORDER, + constants::{SLOW_START_INTERVAL, SLOW_START_SHIFT}, + network_upgrade::TESTNET_ACTIVATION_HEIGHTS, + Network, NetworkUpgrade, NETWORK_UPGRADES_IN_ORDER, }, }; @@ -76,6 +77,8 @@ pub struct ParametersBuilder { hrp_sapling_extended_full_viewing_key: String, /// Sapling payment address human-readable prefix for this network hrp_sapling_payment_address: String, + /// Slow start interval for this network + slow_start_interval: Height, /// A flag for disabling proof-of-work checks when Zebra is validating blocks disable_pow: bool, } @@ -98,6 +101,7 @@ impl Default for ParametersBuilder { genesis_hash: TESTNET_GENESIS_HASH .parse() .expect("hard-coded hash parses"), + slow_start_interval: SLOW_START_INTERVAL, disable_pow: false, } } @@ -237,6 +241,12 @@ impl ParametersBuilder { self } + /// Sets the slow start interval to be used in the [`Parameters`] being built. + pub fn with_slow_start_interval(mut self, slow_start_interval: Height) -> Self { + self.slow_start_interval = slow_start_interval; + self + } + /// Sets the `disable_pow` flag to be used in the [`Parameters`] being built. pub fn with_disable_pow(mut self, disable_pow: bool) -> Self { self.disable_pow = disable_pow; @@ -252,6 +262,7 @@ impl ParametersBuilder { hrp_sapling_extended_spending_key, hrp_sapling_extended_full_viewing_key, hrp_sapling_payment_address, + slow_start_interval, disable_pow, } = self; Parameters { @@ -261,6 +272,8 @@ impl ParametersBuilder { hrp_sapling_extended_spending_key, hrp_sapling_extended_full_viewing_key, hrp_sapling_payment_address, + slow_start_interval, + slow_start_shift: Height(slow_start_interval.0 / 2), disable_pow, } } @@ -290,6 +303,10 @@ pub struct Parameters { hrp_sapling_extended_full_viewing_key: String, /// Sapling payment address human-readable prefix for this network hrp_sapling_payment_address: String, + /// Slow start interval for this network + slow_start_interval: Height, + /// Slow start shift for this network, always half the slow start interval + slow_start_shift: Height, /// A flag for disabling proof-of-work checks when Zebra is validating blocks disable_pow: bool, } @@ -322,6 +339,7 @@ impl Parameters { ..Self::build() .with_genesis_hash(REGTEST_GENESIS_HASH) .with_disable_pow(true) + .with_slow_start_interval(Height::MIN) .with_sapling_hrps( zp_constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY, zp_constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, @@ -353,6 +371,8 @@ impl Parameters { hrp_sapling_extended_spending_key, hrp_sapling_extended_full_viewing_key, hrp_sapling_payment_address, + slow_start_interval, + slow_start_shift, disable_pow, } = Self::new_regtest(None); @@ -361,6 +381,8 @@ impl Parameters { && self.hrp_sapling_extended_spending_key == hrp_sapling_extended_spending_key && self.hrp_sapling_extended_full_viewing_key == hrp_sapling_extended_full_viewing_key && self.hrp_sapling_payment_address == hrp_sapling_payment_address + && self.slow_start_interval == slow_start_interval + && self.slow_start_shift == slow_start_shift && self.disable_pow == disable_pow } @@ -394,8 +416,47 @@ impl Parameters { &self.hrp_sapling_payment_address } + /// Returns slow start interval for this network + pub fn slow_start_interval(&self) -> Height { + self.slow_start_interval + } + + /// Returns slow start shift for this network + pub fn slow_start_shift(&self) -> Height { + self.slow_start_shift + } + /// Returns true if proof-of-work validation should be disabled for this network pub fn disable_pow(&self) -> bool { self.disable_pow } } + +impl Network { + /// Returns true if proof-of-work validation should be disabled for this network + pub fn disable_pow(&self) -> bool { + if let Self::Testnet(params) = self { + params.disable_pow() + } else { + false + } + } + + /// Returns slow start interval for this network + pub fn slow_start_interval(&self) -> Height { + if let Self::Testnet(params) = self { + params.slow_start_interval() + } else { + SLOW_START_INTERVAL + } + } + + /// Returns slow start shift for this network + pub fn slow_start_shift(&self) -> Height { + if let Self::Testnet(params) = self { + params.slow_start_shift() + } else { + SLOW_START_SHIFT + } + } +} diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index e40723f18c5..349d14bb611 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -15,7 +15,7 @@ use zebra_chain::{ }, }; -use crate::{error::*, parameters::SLOW_START_INTERVAL}; +use crate::error::*; use super::subsidy; @@ -162,7 +162,7 @@ pub fn subsidy_is_valid(block: &Block, network: &Network) -> Result<(), BlockErr let slow_start_interval = if network.disable_pow() { Height(0) } else { - SLOW_START_INTERVAL + network.slow_start_interval() }; if height < slow_start_interval { diff --git a/zebra-consensus/src/block/subsidy/general.rs b/zebra-consensus/src/block/subsidy/general.rs index ab3c1b1a0d2..d7013c84ed4 100644 --- a/zebra-consensus/src/block/subsidy/general.rs +++ b/zebra-consensus/src/block/subsidy/general.rs @@ -25,20 +25,13 @@ pub fn halving_divisor(height: Height, network: &Network) -> Option { .activation_height(network) .expect("blossom activation height should be available"); - // TODO: Add this as a field on `testnet::Parameters` instead of checking `disable_pow()`, this is 0 for Regtest in zcashd, - // see - let slow_start_shift = if network.disable_pow() { - Height(0) - } else { - SLOW_START_SHIFT - }; - - if height < slow_start_shift { - unreachable!( - "unsupported block height {height:?}: checkpoints should handle blocks below {slow_start_shift:?}", + if height < network.slow_start_shift() { + panic!( + "unsupported block height {height:?}: checkpoints should handle blocks below {:?}", + network.slow_start_shift() ) } else if height < blossom_height { - let pre_blossom_height = height - slow_start_shift; + let pre_blossom_height = height - network.slow_start_shift(); let halving_shift = pre_blossom_height / PRE_BLOSSOM_HALVING_INTERVAL; let halving_div = 1u64 @@ -51,7 +44,7 @@ pub fn halving_divisor(height: Height, network: &Network) -> Option { Some(halving_div) } else { - let pre_blossom_height = blossom_height - slow_start_shift; + let pre_blossom_height = blossom_height - network.slow_start_shift(); let scaled_pre_blossom_height = pre_blossom_height * HeightDiff::from(BLOSSOM_POW_TARGET_SPACING_RATIO); @@ -87,9 +80,10 @@ pub fn block_subsidy(height: Height, network: &Network) -> Result - if height < SLOW_START_INTERVAL && !network.disable_pow() { + if height < network.slow_start_interval() && !network.disable_pow() { unreachable!( - "unsupported block height {height:?}: callers should handle blocks below {SLOW_START_INTERVAL:?}", + "unsupported block height {height:?}: callers should handle blocks below {:?}", + network.slow_start_interval() ) } else if height < blossom_height { // this calculation is exact, because the halving divisor is 1 here @@ -145,7 +139,7 @@ mod test { assert_eq!( 1, - halving_divisor((SLOW_START_INTERVAL + 1).unwrap(), network).unwrap() + halving_divisor((network.slow_start_interval() + 1).unwrap(), network).unwrap() ); assert_eq!( 1, @@ -274,7 +268,7 @@ mod test { // https://z.cash/support/faq/#what-is-slow-start-mining assert_eq!( Amount::try_from(1_250_000_000), - block_subsidy((SLOW_START_INTERVAL + 1).unwrap(), network) + block_subsidy((network.slow_start_interval() + 1).unwrap(), network) ); assert_eq!( Amount::try_from(1_250_000_000), diff --git a/zebra-consensus/src/block/tests.rs b/zebra-consensus/src/block/tests.rs index 52c24a1f3e7..f5b93faa6a8 100644 --- a/zebra-consensus/src/block/tests.rs +++ b/zebra-consensus/src/block/tests.rs @@ -20,7 +20,7 @@ use zebra_chain::{ use zebra_script::CachedFfiTransaction; use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; -use crate::{parameters::SLOW_START_SHIFT, transaction}; +use crate::transaction; use super::*; @@ -470,7 +470,7 @@ fn miner_fees_validation_for_network(network: Network) -> Result<(), Report> { let block_iter = network.block_iter(); for (&height, block) in block_iter { - if Height(height) > SLOW_START_SHIFT { + if Height(height) > network.slow_start_shift() { let block = Block::zcash_deserialize(&block[..]).expect("block should deserialize"); // fake the miner fee to a big amount diff --git a/zebra-consensus/src/parameters/subsidy.rs b/zebra-consensus/src/parameters/subsidy.rs index 119442e9d71..268221c6669 100644 --- a/zebra-consensus/src/parameters/subsidy.rs +++ b/zebra-consensus/src/parameters/subsidy.rs @@ -10,18 +10,6 @@ use zebra_chain::{ parameters::{Network, NetworkKind, NetworkUpgrade}, }; -/// An initial period from Genesis to this Height where the block subsidy is gradually incremented. [What is slow-start mining][slow-mining] -/// -/// [slow-mining]: https://z.cash/support/faq/#what-is-slow-start-mining -pub const SLOW_START_INTERVAL: Height = Height(20_000); - -/// `SlowStartShift()` as described in [protocol specification §7.8][7.8] -/// -/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies -/// -/// This calculation is exact, because `SLOW_START_INTERVAL` is divisible by 2. -pub const SLOW_START_SHIFT: Height = Height(SLOW_START_INTERVAL.0 / 2); - /// The largest block subsidy, used before the first halving. /// /// We use `25 / 2` instead of `12.5`, so that we can calculate the correct value without using floating-point.