From 3bef54b76411eacc21ac27db6dd60d658c29e26b Mon Sep 17 00:00:00 2001 From: Za Wilcox Date: Tue, 12 Mar 2024 15:41:44 -0600 Subject: [PATCH] change(consensus): Refactor production code for network consensus rules to `Network` methods (#8340) * begin refactor suggested as "step 2": https://github.com/ZcashFoundation/zebra/issues/7968#issue-2003245309 Squashed from multiple commits to enable partial rebase * break out more little traits * add activation implementation leveraging From for lrz::cons:: * for transfer of ownership I cannot return a type that's owned by the method * hrp_sapling_extended_full_viewing_key * complete implementation of interface of Parameters on Network reuse Parameters on zcash Network where possible * move doc-comments to trait declarations (from impls) * Simplify/complete Parameters impl for Network * Add checkpoint_list method, move documentation, etc * move last match network to inside network method * add back comment * use zcash_address for parameter types in zebra-chain * use inherent methods instead of big parameters passthrough * revert to implementation of From on zcash_primitives::..::Network vs &zcash_prim... * move match * add test to block maximum time rule * update changelog * finish porting target_difficutly_limit * remove obscelete code comment * revert non-functional change * finish migrating target_difficulty_limit, checkpoint_list * update changelog --------- Co-authored-by: Hazel OHearn --- CHANGELOG.md | 14 ++++ zebra-chain/Cargo.toml | 4 +- zebra-chain/src/parameters/genesis.rs | 16 +---- zebra-chain/src/parameters/network.rs | 31 ++++++++- .../src/parameters/network/tests/prop.rs | 17 ++++- zebra-chain/src/parameters/network_upgrade.rs | 34 ++++------ zebra-chain/src/parameters/tests.rs | 12 ++-- .../src/primitives/zcash_note_encryption.rs | 24 ++----- zebra-chain/src/transparent/address.rs | 68 +++++++------------ zebra-chain/src/work/difficulty.rs | 64 +++++++++-------- .../src/work/difficulty/tests/vectors.rs | 10 +-- zebra-consensus/src/block/check.rs | 9 ++- .../src/block/subsidy/funding_streams.rs | 23 +------ zebra-consensus/src/block/subsidy/general.rs | 12 +--- zebra-consensus/src/block/tests.rs | 4 +- zebra-consensus/src/checkpoint.rs | 4 +- zebra-consensus/src/checkpoint/list.rs | 68 ++++++++++++------- zebra-consensus/src/checkpoint/list/tests.rs | 8 +-- zebra-consensus/src/lib.rs | 7 +- zebra-consensus/src/parameters/subsidy.rs | 34 +++++++++- zebra-consensus/src/router.rs | 6 +- zebra-network/src/protocol/external/codec.rs | 4 +- zebra-network/src/protocol/external/types.rs | 10 +-- zebra-rpc/src/methods.rs | 2 +- .../src/methods/get_block_template_rpcs.rs | 8 +-- .../tests/snapshot/get_block_template_rpcs.rs | 4 +- zebra-rpc/src/methods/tests/vectors.rs | 4 +- zebra-state/src/service/check.rs | 4 +- zebra-state/src/service/check/difficulty.rs | 9 +-- zebrad/src/components/sync.rs | 4 +- zebrad/src/components/sync/progress.rs | 5 +- zebrad/tests/end_of_support.rs | 4 +- 32 files changed, 284 insertions(+), 243 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9a7b8c3..bddc43ed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to Zebra are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org). +## Unreleased + +### Added +- `zebra_chain::Network` methods: + - `b58_pubkey_address_prefix`, `b58_script_address_prefix`, `num_funding_streams` + +### Changed +- Functions that take a `zebra_chain::Network` as an argument have been moved to be methods of `Network`, including + - `zebra_chain::parameters`: + - `genesis::genesis_hash`, `NetworkUpgrade::activation_list`, `NetworkUpgrade::is_max_block_time_enforced`, + - `zebra_chain::work::difficulty::ExpandedDifficulty::target_difficutly_limit` + - `zebra_consensus::height_for_first_halving` + - `zebra_consensus::checkpoint::CheckpointList::new` (now `Network::checkpoint_list`) + ## [Zebra 1.6.0](https://github.com/ZcashFoundation/zebra/releases/tag/v1.6.0) - 2024-02-23 This release exposes the shielded scanning functionality through an initial diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 3e714ccd6..83c44b232 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -31,7 +31,6 @@ async-error = [ # Mining RPC support getblocktemplate-rpcs = [ - "zcash_address", ] # Experimental shielded scanning support @@ -132,8 +131,7 @@ serde_json = { version = "1.0.113", optional = true } # Production feature async-error and testing feature proptest-impl tokio = { version = "1.36.0", optional = true } -# Production feature getblocktemplate-rpcs -zcash_address = { version = "0.3.1", optional = true } +zcash_address = { version = "0.3.1" } # Experimental feature shielded-scan zcash_client_backend = { version = "0.10.0-rc.1", optional = true } diff --git a/zebra-chain/src/parameters/genesis.rs b/zebra-chain/src/parameters/genesis.rs index 41f2b7be8..04d1bad6e 100644 --- a/zebra-chain/src/parameters/genesis.rs +++ b/zebra-chain/src/parameters/genesis.rs @@ -1,21 +1,7 @@ //! Genesis consensus parameters for each Zcash network. -use crate::{block, parameters::Network}; - /// The previous block hash for the genesis block. /// /// All known networks use the Bitcoin `null` value for the parent of the /// genesis block. (In Bitcoin, `null` is `[0; 32]`.) -pub const GENESIS_PREVIOUS_BLOCK_HASH: block::Hash = block::Hash([0; 32]); - -/// Returns the hash for the genesis block in `network`. -pub fn genesis_hash(network: Network) -> block::Hash { - match network { - // zcash-cli getblockhash 0 - Network::Mainnet => "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", - // zcash-cli -testnet getblockhash 0 - Network::Testnet => "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", - } - .parse() - .expect("hard-coded hash parses") -} +pub const GENESIS_PREVIOUS_BLOCK_HASH: crate::block::Hash = crate::block::Hash([0; 32]); diff --git a/zebra-chain/src/parameters/network.rs b/zebra-chain/src/parameters/network.rs index 15a6d3924..634a44a19 100644 --- a/zebra-chain/src/parameters/network.rs +++ b/zebra-chain/src/parameters/network.rs @@ -5,7 +5,7 @@ use std::{fmt, str::FromStr}; use thiserror::Error; use crate::{ - block::{Height, HeightDiff}, + block::{self, Height, HeightDiff}, parameters::NetworkUpgrade::Canopy, }; @@ -63,6 +63,35 @@ pub enum Network { Testnet, } +use zcash_primitives::consensus::{Network as ZcashPrimitivesNetwork, Parameters as _}; +impl Network { + /// Returns the human-readable prefix for Base58Check-encoded transparent + /// pay-to-public-key-hash payment addresses for the network. + pub fn b58_pubkey_address_prefix(&self) -> [u8; 2] { + ::from(*self).b58_pubkey_address_prefix() + } + + /// Returns the human-readable prefix for Base58Check-encoded transparent pay-to-script-hash + /// payment addresses for the network. + pub fn b58_script_address_prefix(&self) -> [u8; 2] { + ::from(*self).b58_script_address_prefix() + } + /// Returns true if the maximum block time rule is active for `network` and `height`. + /// + /// Always returns true if `network` is the Mainnet. + /// If `network` is the Testnet, the `height` should be at least + /// TESTNET_MAX_TIME_START_HEIGHT to return true. + /// Returns false otherwise. + /// + /// Part of the consensus rules at + pub fn is_max_block_time_enforced(self, height: block::Height) -> bool { + match self { + Network::Mainnet => true, + Network::Testnet => height >= super::TESTNET_MAX_TIME_START_HEIGHT, + } + } +} + impl From for &'static str { fn from(network: Network) -> &'static str { match network { diff --git a/zebra-chain/src/parameters/network/tests/prop.rs b/zebra-chain/src/parameters/network/tests/prop.rs index 9e23e9e9f..605f97901 100644 --- a/zebra-chain/src/parameters/network/tests/prop.rs +++ b/zebra-chain/src/parameters/network/tests/prop.rs @@ -1,7 +1,10 @@ use proptest::prelude::*; use super::super::{Network, ZIP_212_GRACE_PERIOD_DURATION}; -use crate::parameters::NetworkUpgrade; +use crate::{ + block::Height, + parameters::{NetworkUpgrade, TESTNET_MAX_TIME_START_HEIGHT}, +}; proptest! { /// Check that the mandatory checkpoint is after the ZIP-212 grace period. @@ -23,4 +26,16 @@ proptest! { assert!(network.mandatory_checkpoint_height() >= grace_period_end_height); } + + #[test] + /// Asserts that the activation height is correct for the block + /// maximum time rule on Testnet is correct. + fn max_block_times_correct_enforcement(height in any::()) { + let _init_guard = zebra_test::init(); + + assert!(Network::Mainnet.is_max_block_time_enforced(height)); + assert_eq!(Network::Testnet.is_max_block_time_enforced(height), TESTNET_MAX_TIME_START_HEIGHT <= height); + + + } } diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 451d7fe3e..c26253081 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -229,7 +229,7 @@ const TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT: block::Height = block::Height(299 /// pub const TESTNET_MAX_TIME_START_HEIGHT: block::Height = block::Height(653_606); -impl NetworkUpgrade { +impl Network { /// Returns a map between activation heights and network upgrades for `network`, /// in ascending height order. /// @@ -241,7 +241,7 @@ impl NetworkUpgrade { /// When the environment variable TEST_FAKE_ACTIVATION_HEIGHTS is set /// and it's a test build, this returns a list of fake activation heights /// used by some tests. - pub fn activation_list(network: Network) -> BTreeMap { + pub fn activation_list(&self) -> BTreeMap { let (mainnet_heights, testnet_heights) = { #[cfg(not(feature = "zebra-test"))] { @@ -269,7 +269,7 @@ impl NetworkUpgrade { (MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS) } }; - match network { + match self { Mainnet => mainnet_heights, Testnet => testnet_heights, } @@ -277,10 +277,12 @@ impl NetworkUpgrade { .cloned() .collect() } - +} +impl NetworkUpgrade { /// Returns the current network upgrade for `network` and `height`. pub fn current(network: Network, height: block::Height) -> NetworkUpgrade { - NetworkUpgrade::activation_list(network) + network + .activation_list() .range(..=height) .map(|(_, nu)| *nu) .next_back() @@ -292,7 +294,8 @@ impl NetworkUpgrade { /// Returns None if the next upgrade has not been implemented in Zebra /// yet. pub fn next(network: Network, height: block::Height) -> Option { - NetworkUpgrade::activation_list(network) + network + .activation_list() .range((Excluded(height), Unbounded)) .map(|(_, nu)| *nu) .next() @@ -303,7 +306,8 @@ impl NetworkUpgrade { /// Returns None if this network upgrade is a future upgrade, and its /// activation height has not been set yet. pub fn activation_height(&self, network: Network) -> Option { - NetworkUpgrade::activation_list(network) + network + .activation_list() .iter() .filter(|(_, nu)| nu == &self) .map(|(height, _)| *height) @@ -316,7 +320,7 @@ impl NetworkUpgrade { /// Use [`NetworkUpgrade::activation_height`] to get the specific network /// upgrade. pub fn is_activation_height(network: Network, height: block::Height) -> bool { - NetworkUpgrade::activation_list(network).contains_key(&height) + network.activation_list().contains_key(&height) } /// Returns an unordered mapping between NetworkUpgrades and their ConsensusBranchIds. @@ -445,20 +449,6 @@ impl NetworkUpgrade { NetworkUpgrade::current(network, height).averaging_window_timespan() } - /// Returns true if the maximum block time rule is active for `network` and `height`. - /// - /// Always returns true if `network` is the Mainnet. - /// If `network` is the Testnet, the `height` should be at least - /// TESTNET_MAX_TIME_START_HEIGHT to return true. - /// Returns false otherwise. - /// - /// Part of the consensus rules at - pub fn is_max_block_time_enforced(network: Network, height: block::Height) -> bool { - match network { - Network::Mainnet => true, - Network::Testnet => height >= TESTNET_MAX_TIME_START_HEIGHT, - } - } /// Returns the NetworkUpgrade given an u32 as ConsensusBranchId pub fn from_branch_id(branch_id: u32) -> Option { CONSENSUS_BRANCH_IDS diff --git a/zebra-chain/src/parameters/tests.rs b/zebra-chain/src/parameters/tests.rs index 0525b540e..ac4e4ca69 100644 --- a/zebra-chain/src/parameters/tests.rs +++ b/zebra-chain/src/parameters/tests.rs @@ -14,14 +14,14 @@ use NetworkUpgrade::*; fn activation_bijective() { let _init_guard = zebra_test::init(); - let mainnet_activations = NetworkUpgrade::activation_list(Mainnet); + let mainnet_activations = Mainnet.activation_list(); let mainnet_heights: HashSet<&block::Height> = mainnet_activations.keys().collect(); assert_eq!(MAINNET_ACTIVATION_HEIGHTS.len(), mainnet_heights.len()); let mainnet_nus: HashSet<&NetworkUpgrade> = mainnet_activations.values().collect(); assert_eq!(MAINNET_ACTIVATION_HEIGHTS.len(), mainnet_nus.len()); - let testnet_activations = NetworkUpgrade::activation_list(Testnet); + let testnet_activations = Testnet.activation_list(); let testnet_heights: HashSet<&block::Height> = testnet_activations.keys().collect(); assert_eq!(TESTNET_ACTIVATION_HEIGHTS.len(), testnet_heights.len()); @@ -46,7 +46,7 @@ fn activation_extremes_testnet() { fn activation_extremes(network: Network) { // The first three upgrades are Genesis, BeforeOverwinter, and Overwinter assert_eq!( - NetworkUpgrade::activation_list(network).get(&block::Height(0)), + network.activation_list().get(&block::Height(0)), Some(&Genesis) ); assert_eq!(Genesis.activation_height(network), Some(block::Height(0))); @@ -62,7 +62,7 @@ fn activation_extremes(network: Network) { ); assert_eq!( - NetworkUpgrade::activation_list(network).get(&block::Height(1)), + network.activation_list().get(&block::Height(1)), Some(&BeforeOverwinter) ); assert_eq!( @@ -91,7 +91,7 @@ fn activation_extremes(network: Network) { // We assume that the last upgrade we know about continues forever // (even if we suspect that won't be true) assert_ne!( - NetworkUpgrade::activation_list(network).get(&block::Height::MAX), + network.activation_list().get(&block::Height::MAX), Some(&Genesis) ); assert!(!NetworkUpgrade::is_activation_height( @@ -121,7 +121,7 @@ fn activation_consistent_testnet() { /// Check that the `activation_height`, `is_activation_height`, /// `current`, and `next` functions are consistent for `network`. fn activation_consistent(network: Network) { - let activation_list = NetworkUpgrade::activation_list(network); + let activation_list = network.activation_list(); let network_upgrades: HashSet<&NetworkUpgrade> = activation_list.values().collect(); for &network_upgrade in network_upgrades { diff --git a/zebra-chain/src/primitives/zcash_note_encryption.rs b/zebra-chain/src/primitives/zcash_note_encryption.rs index 6f46af82d..0760c9f37 100644 --- a/zebra-chain/src/primitives/zcash_note_encryption.rs +++ b/zebra-chain/src/primitives/zcash_note_encryption.rs @@ -25,24 +25,12 @@ pub fn decrypts_successfully(transaction: &Transaction, network: Network, height if let Some(bundle) = alt_tx.sapling_bundle() { for output in bundle.shielded_outputs().iter() { - let recovery = match network { - Network::Mainnet => { - zcash_primitives::sapling::note_encryption::try_sapling_output_recovery( - &zcash_primitives::consensus::MAIN_NETWORK, - alt_height, - &null_sapling_ovk, - output, - ) - } - Network::Testnet => { - zcash_primitives::sapling::note_encryption::try_sapling_output_recovery( - &zcash_primitives::consensus::TEST_NETWORK, - alt_height, - &null_sapling_ovk, - output, - ) - } - }; + let recovery = zcash_primitives::sapling::note_encryption::try_sapling_output_recovery( + &::from(network), + alt_height, + &null_sapling_ovk, + output, + ); if recovery.is_none() { return false; } diff --git a/zebra-chain/src/transparent/address.rs b/zebra-chain/src/transparent/address.rs index 0faeb9216..5fb203baf 100644 --- a/zebra-chain/src/transparent/address.rs +++ b/zebra-chain/src/transparent/address.rs @@ -15,20 +15,6 @@ use crate::{ #[cfg(test)] use proptest::prelude::*; -/// Magic numbers used to identify what networks Transparent Addresses -/// are associated with. -mod magics { - pub mod p2sh { - pub const MAINNET: [u8; 2] = [0x1C, 0xBD]; - pub const TESTNET: [u8; 2] = [0x1C, 0xBA]; - } - - pub mod p2pkh { - pub const MAINNET: [u8; 2] = [0x1C, 0xB8]; - pub const TESTNET: [u8; 2] = [0x1D, 0x25]; - } -} - /// Transparent Zcash Addresses /// /// In Bitcoin a single byte is used for the version field identifying @@ -118,24 +104,14 @@ impl ZcashSerialize for Address { network, script_hash, } => { - // Dev network doesn't have a recommendation so we - // default to testnet bytes if it's not mainnet. - match *network { - Network::Mainnet => writer.write_all(&magics::p2sh::MAINNET[..])?, - _ => writer.write_all(&magics::p2sh::TESTNET[..])?, - } + writer.write_all(&network.b58_script_address_prefix())?; writer.write_all(script_hash)? } Address::PayToPublicKeyHash { network, pub_key_hash, } => { - // Dev network doesn't have a recommendation so we - // default to testnet bytes if it's not mainnet. - match *network { - Network::Mainnet => writer.write_all(&magics::p2pkh::MAINNET[..])?, - _ => writer.write_all(&magics::p2pkh::TESTNET[..])?, - } + writer.write_all(&network.b58_pubkey_address_prefix())?; writer.write_all(pub_key_hash)? } } @@ -153,22 +129,30 @@ impl ZcashDeserialize for Address { reader.read_exact(&mut hash_bytes)?; match version_bytes { - magics::p2sh::MAINNET => Ok(Address::PayToScriptHash { - network: Network::Mainnet, - script_hash: hash_bytes, - }), - magics::p2sh::TESTNET => Ok(Address::PayToScriptHash { - network: Network::Testnet, - script_hash: hash_bytes, - }), - magics::p2pkh::MAINNET => Ok(Address::PayToPublicKeyHash { - network: Network::Mainnet, - pub_key_hash: hash_bytes, - }), - magics::p2pkh::TESTNET => Ok(Address::PayToPublicKeyHash { - network: Network::Testnet, - pub_key_hash: hash_bytes, - }), + zcash_primitives::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX => { + Ok(Address::PayToScriptHash { + network: Network::Mainnet, + script_hash: hash_bytes, + }) + } + zcash_primitives::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX => { + Ok(Address::PayToScriptHash { + network: Network::Testnet, + script_hash: hash_bytes, + }) + } + zcash_primitives::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX => { + Ok(Address::PayToPublicKeyHash { + network: Network::Mainnet, + pub_key_hash: hash_bytes, + }) + } + zcash_primitives::constants::testnet::B58_PUBKEY_ADDRESS_PREFIX => { + Ok(Address::PayToPublicKeyHash { + network: Network::Testnet, + pub_key_hash: hash_bytes, + }) + } _ => Err(SerializationError::Parse("bad t-addr version/type")), } } diff --git a/zebra-chain/src/work/difficulty.rs b/zebra-chain/src/work/difficulty.rs index 472418806..9c5252c2b 100644 --- a/zebra-chain/src/work/difficulty.rs +++ b/zebra-chain/src/work/difficulty.rs @@ -384,32 +384,6 @@ impl ExpandedDifficulty { U256::from_little_endian(&hash.0).into() } - /// Returns the easiest target difficulty allowed on `network`. - /// - /// # Consensus - /// - /// See `PoWLimit` in the Zcash specification: - /// - pub fn target_difficulty_limit(network: Network) -> ExpandedDifficulty { - let limit: U256 = match network { - /* 2^243 - 1 */ - Network::Mainnet => (U256::one() << 243) - 1, - /* 2^251 - 1 */ - Network::Testnet => (U256::one() << 251) - 1, - }; - - // `zcashd` converts the PoWLimit into a compact representation before - // using it to perform difficulty filter checks. - // - // The Zcash specification converts to compact for the default difficulty - // filter, but not for testnet minimum difficulty blocks. (ZIP 205 and - // ZIP 208 don't specify this conversion either.) See #1277 for details. - ExpandedDifficulty(limit) - .to_compact() - .to_expanded() - .expect("difficulty limits are valid expanded values") - } - /// Calculate the CompactDifficulty for an expanded difficulty. /// /// # Consensus @@ -681,7 +655,8 @@ impl PartialCumulativeWork { pub fn difficulty_multiplier_for_display(&self, network: Network) -> f64 { // This calculation is similar to the `getdifficulty` RPC, see that code for details. - let pow_limit = ExpandedDifficulty::target_difficulty_limit(network) + let pow_limit = network + .target_difficulty_limit() .to_compact() .to_work() .expect("target difficult limit is valid work"); @@ -705,6 +680,41 @@ impl PartialCumulativeWork { } } +/// Network methods related to Difficulty +pub trait ParameterDifficulty { + /// Returns the easiest target difficulty allowed on `network`. + /// + /// # Consensus + /// + /// See `PoWLimit` in the Zcash specification: + /// + fn target_difficulty_limit(&self) -> ExpandedDifficulty; +} + +impl ParameterDifficulty for Network { + /// Returns the easiest target difficulty allowed on `network`. + /// See [`ParameterDifficulty::target_difficulty_limit`] + fn target_difficulty_limit(&self) -> ExpandedDifficulty { + let limit: U256 = match self { + /* 2^243 - 1 */ + Network::Mainnet => (U256::one() << 243) - 1, + /* 2^251 - 1 */ + Network::Testnet => (U256::one() << 251) - 1, + }; + + // `zcashd` converts the PoWLimit into a compact representation before + // using it to perform difficulty filter checks. + // + // The Zcash specification converts to compact for the default difficulty + // filter, but not for testnet minimum difficulty blocks. (ZIP 205 and + // ZIP 208 don't specify this conversion either.) See #1277 for details. + ExpandedDifficulty(limit) + .to_compact() + .to_expanded() + .expect("difficulty limits are valid expanded values") + } +} + impl From for PartialCumulativeWork { fn from(work: Work) -> Self { PartialCumulativeWork(work.0) diff --git a/zebra-chain/src/work/difficulty/tests/vectors.rs b/zebra-chain/src/work/difficulty/tests/vectors.rs index e8b190221..e18b15417 100644 --- a/zebra-chain/src/work/difficulty/tests/vectors.rs +++ b/zebra-chain/src/work/difficulty/tests/vectors.rs @@ -309,9 +309,9 @@ fn block_difficulty_for_network(network: Network) -> Result<(), Report> { /// SPANDOC: Check the PoWLimit for block {?height, ?network, ?threshold, ?hash} { // the consensus rule - assert!(threshold <= ExpandedDifficulty::target_difficulty_limit(network)); + assert!(threshold <= network.target_difficulty_limit()); // check that ordering is transitive, we checked `hash <= threshold` above - assert!(hash <= ExpandedDifficulty::target_difficulty_limit(network)); + assert!(hash <= network.target_difficulty_limit()); } /// SPANDOC: Check compact round-trip for block {?height, ?network} @@ -376,7 +376,7 @@ fn genesis_block_difficulty_for_network(network: Network) -> Result<(), Report> { assert_eq!( threshold, - ExpandedDifficulty::target_difficulty_limit(network), + network.target_difficulty_limit(), "genesis block difficulty thresholds must be equal to the PoWLimit" ); } @@ -477,12 +477,12 @@ fn check_testnet_minimum_difficulty_block(height: block::Height) -> Result<(), R /// SPANDOC: Check that the testnet minimum difficulty is the PoWLimit {?height, ?threshold, ?hash} { - assert_eq!(threshold, ExpandedDifficulty::target_difficulty_limit(Network::Testnet), + assert_eq!(threshold, Network::Testnet.target_difficulty_limit(), "testnet minimum difficulty thresholds should be equal to the PoWLimit. Hint: Blocks with large gaps are allowed to have the minimum difficulty, but it's not required."); // all blocks pass the minimum difficulty threshold, even if they aren't minimum // difficulty blocks, because it's the lowest permitted difficulty assert!( - hash <= ExpandedDifficulty::target_difficulty_limit(Network::Testnet), + hash <= Network::Testnet.target_difficulty_limit(), "testnet minimum difficulty hashes must be less than the PoWLimit" ); } diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index e539743a3..319fa5004 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -9,7 +9,10 @@ use zebra_chain::{ block::{Block, Hash, Header, Height}, parameters::{Network, NetworkUpgrade}, transaction, - work::{difficulty::ExpandedDifficulty, equihash}, + work::{ + difficulty::{ExpandedDifficulty, ParameterDifficulty as _}, + equihash, + }, }; use crate::{error::*, parameters::SLOW_START_INTERVAL}; @@ -78,13 +81,13 @@ pub fn difficulty_threshold_is_valid( // The PowLimit check is part of `Threshold()` in the spec, but it doesn't // actually depend on any previous blocks. - if difficulty_threshold > ExpandedDifficulty::target_difficulty_limit(network) { + if difficulty_threshold > network.target_difficulty_limit() { Err(BlockError::TargetDifficultyLimit( *height, *hash, difficulty_threshold, network, - ExpandedDifficulty::target_difficulty_limit(network), + network.target_difficulty_limit(), ))?; } diff --git a/zebra-consensus/src/block/subsidy/funding_streams.rs b/zebra-consensus/src/block/subsidy/funding_streams.rs index 977b14a56..22cfec729 100644 --- a/zebra-consensus/src/block/subsidy/funding_streams.rs +++ b/zebra-consensus/src/block/subsidy/funding_streams.rs @@ -48,22 +48,6 @@ pub fn funding_stream_values( Ok(results) } -/// Returns the minimum height after the first halving -/// as described in [protocol specification §7.10][7.10] -/// -/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams -pub fn height_for_first_halving(network: Network) -> Height { - // First halving on Mainnet is at Canopy - // while in Testnet is at block constant height of `1_116_000` - // https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams - match network { - Network::Mainnet => Canopy - .activation_height(network) - .expect("canopy activation height should be available"), - Network::Testnet => FIRST_HALVING_TESTNET, - } -} - /// Returns the address change period /// as described in [protocol specification §7.10][7.10] /// @@ -78,7 +62,7 @@ fn funding_stream_address_period(height: Height, network: Network) -> u32 { // // This is the same as `floor()`, because these numbers are all positive. - let height_after_first_halving = height - height_for_first_halving(network); + let height_after_first_halving = height - network.height_for_first_halving(); let address_period = (height_after_first_halving + POST_BLOSSOM_HALVING_INTERVAL) / FUNDING_STREAM_ADDRESS_CHANGE_INTERVAL; @@ -93,10 +77,7 @@ fn funding_stream_address_period(height: Height, network: Network) -> u32 { /// /// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams fn funding_stream_address_index(height: Height, network: Network) -> usize { - let num_addresses = match network { - Network::Mainnet => FUNDING_STREAMS_NUM_ADDRESSES_MAINNET, - Network::Testnet => FUNDING_STREAMS_NUM_ADDRESSES_TESTNET, - }; + let num_addresses = network.num_funding_streams(); let index = 1u32 .checked_add(funding_stream_address_period(height, network)) diff --git a/zebra-consensus/src/block/subsidy/general.rs b/zebra-consensus/src/block/subsidy/general.rs index 5be97f3a9..c906541e0 100644 --- a/zebra-consensus/src/block/subsidy/general.rs +++ b/zebra-consensus/src/block/subsidy/general.rs @@ -131,11 +131,7 @@ mod test { fn halving_for_network(network: Network) -> Result<(), Report> { let blossom_height = Blossom.activation_height(network).unwrap(); - let first_halving_height = match network { - Network::Mainnet => Canopy.activation_height(network).unwrap(), - // Based on "7.8 Calculation of Block Subsidy and Founders' Reward" - Network::Testnet => Height(1_116_000), - }; + let first_halving_height = network.height_for_first_halving(); assert_eq!( 1, @@ -261,11 +257,7 @@ mod test { fn block_subsidy_for_network(network: Network) -> Result<(), Report> { let blossom_height = Blossom.activation_height(network).unwrap(); - let first_halving_height = match network { - Network::Mainnet => Canopy.activation_height(network).unwrap(), - // Based on "7.8 Calculation of Block Subsidy and Founders' Reward" - Network::Testnet => Height(1_116_000), - }; + let first_halving_height = network.height_for_first_halving(); // After slow-start mining and before Blossom the block subsidy is 12.5 ZEC // https://z.cash/support/faq/#what-is-slow-start-mining diff --git a/zebra-consensus/src/block/tests.rs b/zebra-consensus/src/block/tests.rs index f074cf736..d72737893 100644 --- a/zebra-consensus/src/block/tests.rs +++ b/zebra-consensus/src/block/tests.rs @@ -19,7 +19,7 @@ use zebra_chain::{ parameters::{Network, NetworkUpgrade}, serialization::{ZcashDeserialize, ZcashDeserializeInto}, transaction::{arbitrary::transaction_to_fake_v5, LockTime, Transaction}, - work::difficulty::{ExpandedDifficulty, INVALID_COMPACT_DIFFICULTY}, + work::difficulty::{ParameterDifficulty as _, INVALID_COMPACT_DIFFICULTY}, }; use zebra_script::CachedFfiTransaction; use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; @@ -241,7 +241,7 @@ fn difficulty_validation_failure() -> Result<(), Report> { hash, difficulty_threshold, Network::Mainnet, - ExpandedDifficulty::target_difficulty_limit(Network::Mainnet), + Network::Mainnet.target_difficulty_limit(), ); assert_eq!(expected, result); diff --git a/zebra-consensus/src/checkpoint.rs b/zebra-consensus/src/checkpoint.rs index 6541c502f..e8605c1e3 100644 --- a/zebra-consensus/src/checkpoint.rs +++ b/zebra-consensus/src/checkpoint.rs @@ -42,7 +42,7 @@ use crate::{ TargetHeight::{self, *}, }, error::BlockError, - BoxError, + BoxError, ParameterCheckpoint as _, }; pub(crate) mod list; @@ -207,7 +207,7 @@ where initial_tip: Option<(block::Height, block::Hash)>, state_service: S, ) -> Self { - let checkpoint_list = CheckpointList::new(network); + let checkpoint_list = network.checkpoint_list(); let max_height = checkpoint_list.max_height(); tracing::info!( ?max_height, diff --git a/zebra-consensus/src/checkpoint/list.rs b/zebra-consensus/src/checkpoint/list.rs index a22ce888c..2b45e4365 100644 --- a/zebra-consensus/src/checkpoint/list.rs +++ b/zebra-consensus/src/checkpoint/list.rs @@ -17,7 +17,7 @@ use std::{ }; use zebra_chain::block; -use zebra_chain::parameters::{genesis_hash, Network}; +use zebra_chain::parameters::Network; /// The hard-coded checkpoints for mainnet, generated using the /// `zebra-checkpoints` tool. @@ -43,6 +43,47 @@ const MAINNET_CHECKPOINTS: &str = include_str!("main-checkpoints.txt"); /// information. const TESTNET_CHECKPOINTS: &str = include_str!("test-checkpoints.txt"); +/// Network methods related to checkpoints +pub trait ParameterCheckpoint { + /// Returns the hash for the genesis block in `network`. + fn genesis_hash(&self) -> zebra_chain::block::Hash; + /// Returns the hard-coded checkpoint list for `network`. + fn checkpoint_list(&self) -> CheckpointList; +} + +impl ParameterCheckpoint for Network { + fn genesis_hash(&self) -> zebra_chain::block::Hash { + match self { + // zcash-cli getblockhash 0 + Network::Mainnet => "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + // zcash-cli -testnet getblockhash 0 + Network::Testnet => "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + } + .parse() + .expect("hard-coded hash parses") + } + + fn checkpoint_list(&self) -> CheckpointList { + // parse calls CheckpointList::from_list + let checkpoint_list: CheckpointList = match self { + Network::Mainnet => MAINNET_CHECKPOINTS + .parse() + .expect("Hard-coded Mainnet checkpoint list parses and validates"), + Network::Testnet => TESTNET_CHECKPOINTS + .parse() + .expect("Hard-coded Testnet checkpoint list parses and validates"), + }; + + match checkpoint_list.hash(block::Height(0)) { + Some(hash) if hash == self.genesis_hash() => checkpoint_list, + Some(_) => { + panic!("The hard-coded genesis checkpoint does not match the network genesis hash") + } + None => unreachable!("Parser should have checked for a missing genesis checkpoint"), + } + } +} + /// A list of block height and hash checkpoints. /// /// Checkpoints should be chosen to avoid forks or chain reorganizations, @@ -81,27 +122,6 @@ impl FromStr for CheckpointList { } impl CheckpointList { - /// Returns the hard-coded checkpoint list for `network`. - pub fn new(network: Network) -> Self { - // parse calls CheckpointList::from_list - let checkpoint_list: CheckpointList = match network { - Network::Mainnet => MAINNET_CHECKPOINTS - .parse() - .expect("Hard-coded Mainnet checkpoint list parses and validates"), - Network::Testnet => TESTNET_CHECKPOINTS - .parse() - .expect("Hard-coded Testnet checkpoint list parses and validates"), - }; - - match checkpoint_list.hash(block::Height(0)) { - Some(hash) if hash == genesis_hash(network) => checkpoint_list, - Some(_) => { - panic!("The hard-coded genesis checkpoint does not match the network genesis hash") - } - None => unreachable!("Parser should have checked for a missing genesis checkpoint"), - } - } - /// Create a new checkpoint list for `network` from `checkpoint_list`. /// /// Assumes that the provided genesis checkpoint is correct. @@ -123,8 +143,8 @@ impl CheckpointList { // Check that the list starts with the correct genesis block match checkpoints.iter().next() { Some((block::Height(0), hash)) - if (hash == &genesis_hash(Network::Mainnet) - || hash == &genesis_hash(Network::Testnet)) => {} + if (hash == &Network::Mainnet.genesis_hash() + || hash == &Network::Testnet.genesis_hash()) => {} Some((block::Height(0), _)) => { Err("the genesis checkpoint does not match the Mainnet or Testnet genesis hash")? } diff --git a/zebra-consensus/src/checkpoint/list/tests.rs b/zebra-consensus/src/checkpoint/list/tests.rs index da07c6894..0588a365c 100644 --- a/zebra-consensus/src/checkpoint/list/tests.rs +++ b/zebra-consensus/src/checkpoint/list/tests.rs @@ -235,8 +235,8 @@ fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> { .parse() .expect("hard-coded Testnet checkpoint list should parse"); - let _ = CheckpointList::new(Mainnet); - let _ = CheckpointList::new(Testnet); + let _ = Mainnet.checkpoint_list(); + let _ = Testnet.checkpoint_list(); Ok(()) } @@ -257,7 +257,7 @@ fn checkpoint_list_hard_coded_mandatory(network: Network) -> Result<(), BoxError let mandatory_checkpoint = network.mandatory_checkpoint_height(); - let list = CheckpointList::new(network); + let list = network.checkpoint_list(); assert!( list.max_height() >= mandatory_checkpoint, @@ -292,7 +292,7 @@ fn checkpoint_list_hard_coded_max_gap(network: Network) -> Result<(), BoxError> HeightDiff::try_from(div_ceil(MAX_CHECKPOINT_BYTE_COUNT, MAX_BLOCK_BYTES)) .expect("constant fits in HeightDiff"); - let list = CheckpointList::new(network); + let list = network.checkpoint_list(); let mut heights = list.0.keys(); // Check that we start at the genesis height diff --git a/zebra-consensus/src/lib.rs b/zebra-consensus/src/lib.rs index 253c11d49..97fab5150 100644 --- a/zebra-consensus/src/lib.rs +++ b/zebra-consensus/src/lib.rs @@ -49,18 +49,19 @@ pub use block::{ subsidy::{ funding_streams::{ funding_stream_address, funding_stream_recipient_info, funding_stream_values, - height_for_first_halving, new_coinbase_script, + new_coinbase_script, }, general::miner_subsidy, }, Request, VerifyBlockError, MAX_BLOCK_SIGOPS, }; pub use checkpoint::{ - CheckpointList, VerifyCheckpointError, MAX_CHECKPOINT_BYTE_COUNT, MAX_CHECKPOINT_HEIGHT_GAP, + list::ParameterCheckpoint, CheckpointList, VerifyCheckpointError, MAX_CHECKPOINT_BYTE_COUNT, + MAX_CHECKPOINT_HEIGHT_GAP, }; pub use config::Config; pub use error::BlockError; -pub use parameters::FundingStreamReceiver; +pub use parameters::{FundingStreamReceiver, ParameterSubsidy}; pub use primitives::{ed25519, groth16, halo2, redjubjub, redpallas}; pub use router::RouterError; diff --git a/zebra-consensus/src/parameters/subsidy.rs b/zebra-consensus/src/parameters/subsidy.rs index ba8f910d8..50dd78d8b 100644 --- a/zebra-consensus/src/parameters/subsidy.rs +++ b/zebra-consensus/src/parameters/subsidy.rs @@ -7,7 +7,7 @@ use lazy_static::lazy_static; use zebra_chain::{ amount::COIN, block::{Height, HeightDiff}, - parameters::Network, + parameters::{Network, NetworkUpgrade}, }; /// An initial period from Genesis to this Height where the block subsidy is gradually incremented. [What is slow-start mining][slow-mining] @@ -198,6 +198,38 @@ pub const FUNDING_STREAM_ECC_ADDRESSES_MAINNET: [&str; FUNDING_STREAMS_NUM_ADDRE "t3XHAGxRP2FNfhAjxGjxbrQPYtQQjc3RCQD", ]; +/// Functionality specific to block subsidy-related consensus rules +pub trait ParameterSubsidy { + /// Number of addresses for each funding stream in the Network. + /// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams + fn num_funding_streams(&self) -> usize; + /// Returns the minimum height after the first halving + /// as described in [protocol specification §7.10][7.10] + /// + /// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams + fn height_for_first_halving(&self) -> Height; +} + +/// Network methods related to Block Subsidy and Funding Streams +impl ParameterSubsidy for Network { + fn num_funding_streams(&self) -> usize { + match self { + Network::Mainnet => FUNDING_STREAMS_NUM_ADDRESSES_MAINNET, + Network::Testnet => FUNDING_STREAMS_NUM_ADDRESSES_TESTNET, + } + } + fn height_for_first_halving(&self) -> Height { + // First halving on Mainnet is at Canopy + // while in Testnet is at block constant height of `1_116_000` + // https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams + match self { + Network::Mainnet => NetworkUpgrade::Canopy + .activation_height(*self) + .expect("canopy activation height should be available"), + Network::Testnet => FIRST_HALVING_TESTNET, + } + } +} /// List of addresses for the Zcash Foundation funding stream in the Mainnet. pub const FUNDING_STREAM_ZF_ADDRESSES_MAINNET: [&str; FUNDING_STREAMS_NUM_ADDRESSES_MAINNET] = ["t3dvVE3SQEi7kqNzwrfNePxZ1d4hUyztBA1"; FUNDING_STREAMS_NUM_ADDRESSES_MAINNET]; diff --git a/zebra-consensus/src/router.rs b/zebra-consensus/src/router.rs index 5c10e545b..ab99bbd41 100644 --- a/zebra-consensus/src/router.rs +++ b/zebra-consensus/src/router.rs @@ -36,7 +36,7 @@ use crate::{ block::{Request, SemanticBlockVerifier, VerifyBlockError}, checkpoint::{CheckpointList, CheckpointVerifier, VerifyCheckpointError}, error::TransactionError, - transaction, BoxError, Config, + transaction, BoxError, Config, ParameterCheckpoint as _, }; #[cfg(test)] @@ -263,7 +263,7 @@ where // > activation block hashes given in § 3.12 ‘Mainnet and Testnet’ on p. 20. // // - let full_checkpoints = CheckpointList::new(network); + let full_checkpoints = network.checkpoint_list(); let mut already_warned = false; for (height, checkpoint_hash) in full_checkpoints.iter() { @@ -363,7 +363,7 @@ where pub fn init_checkpoint_list(config: Config, network: Network) -> (CheckpointList, Height) { // TODO: Zebra parses the checkpoint list three times at startup. // Instead, cache the checkpoint list for each `network`. - let list = CheckpointList::new(network); + let list = network.checkpoint_list(); let max_checkpoint_height = if config.checkpoint_sync { list.max_height() diff --git a/zebra-network/src/protocol/external/codec.rs b/zebra-network/src/protocol/external/codec.rs index 88f54c6b2..d511b50f7 100644 --- a/zebra-network/src/protocol/external/codec.rs +++ b/zebra-network/src/protocol/external/codec.rs @@ -163,7 +163,7 @@ impl Encoder for Codec { let start_len = dst.len(); { let dst = &mut dst.writer(); - dst.write_all(&Magic::from(self.builder.network).0[..])?; + dst.write_all(&self.builder.network.magic_value().0[..])?; dst.write_all(command)?; dst.write_u32::(body_length as u32)?; @@ -389,7 +389,7 @@ impl Decoder for Codec { "read header from src buffer" ); - if magic != Magic::from(self.builder.network) { + if magic != self.builder.network.magic_value() { return Err(Parse("supplied magic did not meet expectations")); } if body_len > self.builder.max_len { diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 8cf65765b..049ba1fd7 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -23,11 +23,13 @@ impl fmt::Debug for Magic { f.debug_tuple("Magic").field(&hex::encode(self.0)).finish() } } - -impl From for Magic { +pub(crate) trait ParameterMagic { + fn magic_value(&self) -> Magic; +} +impl ParameterMagic for Network { /// Get the magic value associated to this `Network`. - fn from(network: Network) -> Self { - match network { + fn magic_value(&self) -> Magic { + match self { Network::Mainnet => magics::MAINNET, Network::Testnet => magics::TESTNET, } diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 9fc190a9a..6c2668a34 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -519,7 +519,7 @@ where // // Get the network upgrades in height order, like `zcashd`. let mut upgrades = IndexMap::new(); - for (activation_height, network_upgrade) in NetworkUpgrade::activation_list(network) { + for (activation_height, network_upgrade) in network.activation_list() { // Zebra defines network upgrades based on incompatible consensus rule changes, // but zcashd defines them based on ZIPs. // diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index 7d0550c05..57f27e228 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -20,10 +20,10 @@ use zebra_chain::{ transparent::{ self, EXTRA_ZEBRA_COINBASE_DATA, MAX_COINBASE_DATA_LEN, MAX_COINBASE_HEIGHT_DATA_LEN, }, - work::difficulty::{ExpandedDifficulty, U256}, + work::difficulty::{ParameterDifficulty as _, U256}, }; use zebra_consensus::{ - funding_stream_address, funding_stream_values, height_for_first_halving, miner_subsidy, + funding_stream_address, funding_stream_values, miner_subsidy, ParameterSubsidy as _, RouterError, }; use zebra_network::AddressBookPeers; @@ -1098,7 +1098,7 @@ where best_chain_tip_height(&latest_chain_tip)? }; - if height < height_for_first_halving(network) { + if height < network.height_for_first_halving() { return Err(Error { code: ErrorCode::ServerError(0), message: "Zebra does not support founders' reward subsidies, \ @@ -1197,7 +1197,7 @@ where // using this calculation.) // Get expanded difficulties (256 bits), these are the inverse of the work - let pow_limit: U256 = ExpandedDifficulty::target_difficulty_limit(network).into(); + let pow_limit: U256 = network.target_difficulty_limit().into(); let difficulty: U256 = chain_info .expected_difficulty .to_expanded() diff --git a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs index c7299565a..e93571bae 100644 --- a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs @@ -23,7 +23,7 @@ use zebra_chain::{ serialization::{DateTime32, ZcashDeserializeInto}, transaction::Transaction, transparent, - work::difficulty::{CompactDifficulty, ExpandedDifficulty}, + work::difficulty::{CompactDifficulty, ParameterDifficulty as _}, }; use zebra_network::{address_book_peers::MockAddressBookPeers, types::MetaAddr}; use zebra_node_services::mempool; @@ -115,7 +115,7 @@ pub async fn test_responses( let fake_max_time = DateTime32::from(1654008728); // Use a valid fractional difficulty for snapshots - let pow_limit = ExpandedDifficulty::target_difficulty_limit(network); + let pow_limit = network.target_difficulty_limit(); let fake_difficulty = pow_limit * 2 / 3; let fake_difficulty = CompactDifficulty::from(fake_difficulty); diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 0a9dcb9e1..03aa5b12c 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -1658,7 +1658,7 @@ async fn rpc_getdifficulty() { chain_sync_status::MockSyncStatus, chain_tip::mock::MockChainTip, serialization::DateTime32, - work::difficulty::{CompactDifficulty, ExpandedDifficulty, U256}, + work::difficulty::{CompactDifficulty, ExpandedDifficulty, ParameterDifficulty as _, U256}, }; use zebra_network::address_book_peers::MockAddressBookPeers; @@ -1742,7 +1742,7 @@ async fn rpc_getdifficulty() { assert_eq!(format!("{:.9}", get_difficulty.unwrap()), "0.000122072"); // Fake the ChainInfo response: difficulty limit - smallest valid difficulty - let pow_limit = ExpandedDifficulty::target_difficulty_limit(Mainnet); + let pow_limit = Mainnet.target_difficulty_limit(); let fake_difficulty = pow_limit.into(); let mut read_state2 = read_state.clone(); let mock_read_state_request_handler = async move { diff --git a/zebra-state/src/service/check.rs b/zebra-state/src/service/check.rs index c89f63956..0d3a941f2 100644 --- a/zebra-state/src/service/check.rs +++ b/zebra-state/src/service/check.rs @@ -277,9 +277,7 @@ fn difficulty_threshold_and_time_are_valid( // of that block plus 90*60 seconds. // // https://zips.z.cash/protocol/protocol.pdf#blockheader - if NetworkUpgrade::is_max_block_time_enforced(network, candidate_height) - && candidate_time > block_time_max - { + if network.is_max_block_time_enforced(candidate_height) && candidate_time > block_time_max { Err(ValidateContextError::TimeTooLate { candidate_time, block_time_max, diff --git a/zebra-state/src/service/check/difficulty.rs b/zebra-state/src/service/check/difficulty.rs index c81ad2d76..a5ec6179b 100644 --- a/zebra-state/src/service/check/difficulty.rs +++ b/zebra-state/src/service/check/difficulty.rs @@ -15,8 +15,8 @@ use zebra_chain::{ parameters::Network, parameters::NetworkUpgrade, parameters::POW_AVERAGING_WINDOW, - work::difficulty::ExpandedDifficulty, work::difficulty::{CompactDifficulty, U256}, + work::difficulty::{ExpandedDifficulty, ParameterDifficulty as _}, }; /// The median block span for time median calculations. @@ -188,7 +188,7 @@ impl AdjustedDifficulty { Network::Testnet, "invalid network: the minimum difficulty rule only applies on testnet" ); - ExpandedDifficulty::target_difficulty_limit(self.network).to_compact() + self.network.target_difficulty_limit().to_compact() } else { self.threshold_bits() } @@ -210,10 +210,7 @@ impl AdjustedDifficulty { let threshold = (self.mean_target_difficulty() / averaging_window_timespan.num_seconds()) * self.median_timespan_bounded().num_seconds(); - let threshold = min( - ExpandedDifficulty::target_difficulty_limit(self.network), - threshold, - ); + let threshold = min(self.network.target_difficulty_limit(), threshold); threshold.to_compact() } diff --git a/zebrad/src/components/sync.rs b/zebrad/src/components/sync.rs index 651dacc1f..cbfd5e7b6 100644 --- a/zebrad/src/components/sync.rs +++ b/zebrad/src/components/sync.rs @@ -21,8 +21,8 @@ use tower::{ use zebra_chain::{ block::{self, Height, HeightDiff}, chain_tip::ChainTip, - parameters::genesis_hash, }; +use zebra_consensus::ParameterCheckpoint as _; use zebra_network as zn; use zebra_state as zs; @@ -500,7 +500,7 @@ where )); let new_syncer = Self { - genesis_hash: genesis_hash(config.network.network), + genesis_hash: config.network.network.genesis_hash(), max_checkpoint_height, checkpoint_verify_concurrency_limit, full_verify_concurrency_limit, diff --git a/zebrad/src/components/sync/progress.rs b/zebrad/src/components/sync/progress.rs index 66acfb082..9fbf6517c 100644 --- a/zebrad/src/components/sync/progress.rs +++ b/zebrad/src/components/sync/progress.rs @@ -16,7 +16,7 @@ use zebra_chain::{ fmt::humantime_seconds, parameters::{Network, NetworkUpgrade, POST_BLOSSOM_POW_TARGET_SPACING}, }; -use zebra_consensus::CheckpointList; +use zebra_consensus::ParameterCheckpoint as _; use zebra_state::MAX_BLOCK_REORG_HEIGHT; use crate::components::sync::SyncStatus; @@ -82,7 +82,8 @@ pub async fn show_block_chain_progress( // The minimum height of the valid best chain, based on: // - the hard-coded checkpoint height, // - the minimum number of blocks after the highest checkpoint. - let after_checkpoint_height = CheckpointList::new(network) + let after_checkpoint_height = network + .checkpoint_list() .max_height() .add(min_after_checkpoint_blocks) .expect("hard-coded checkpoint height is far below Height::MAX"); diff --git a/zebrad/tests/end_of_support.rs b/zebrad/tests/end_of_support.rs index bbc6095f2..2a2a4afc3 100644 --- a/zebrad/tests/end_of_support.rs +++ b/zebrad/tests/end_of_support.rs @@ -5,7 +5,7 @@ use std::time::Duration; use color_eyre::eyre::Result; use zebra_chain::{block::Height, chain_tip::mock::MockChainTip, parameters::Network}; -use zebra_consensus::CheckpointList; +use zebra_consensus::ParameterCheckpoint as _; use zebrad::components::sync::end_of_support::{self, EOS_PANIC_AFTER, ESTIMATED_RELEASE_HEIGHT}; // Estimated blocks per day with the current 75 seconds block spacing. @@ -54,7 +54,7 @@ fn end_of_support_function() { #[tracing_test::traced_test] fn end_of_support_date() { // Get the list of checkpoints. - let list = CheckpointList::new(Network::Mainnet); + let list = Network::Mainnet.checkpoint_list(); // Get the last one we have and use it as tip. let higher_checkpoint = list.max_height();