diff --git a/zebra-chain/src/lib.rs b/zebra-chain/src/lib.rs index 62bd310b..eef6fdc4 100644 --- a/zebra-chain/src/lib.rs +++ b/zebra-chain/src/lib.rs @@ -22,6 +22,7 @@ pub mod keys; pub mod note_commitment_tree; pub mod notes; pub mod nullifier; +pub mod parameters; pub mod proofs; pub mod serialization; pub mod transaction; @@ -31,6 +32,8 @@ pub mod utils; pub use ed25519_zebra; pub use redjubjub; +pub use parameters::NetworkUpgrade; + #[cfg(test)] use proptest_derive::Arbitrary; diff --git a/zebra-chain/src/parameters.rs b/zebra-chain/src/parameters.rs new file mode 100644 index 00000000..4b3a13a6 --- /dev/null +++ b/zebra-chain/src/parameters.rs @@ -0,0 +1,20 @@ +//! The consensus parameters for each Zcash network. +//! +//! This module contains the consensus parameters which are required for +//! parsing. +//! +//! Some consensus parameters change based on network upgrades. Each network +//! upgrade happens at a particular block height. Some parameters have a value +//! (or function) before the upgrade height, at the upgrade height, and after +//! the upgrade height. (For example, the value of the reserved field in the +//! block header during the Heartwood upgrade.) +//! +//! Typically, consensus parameters are accessed via a function that takes a +//! `Network` and `BlockHeight`. + +pub mod network_upgrade; + +pub use network_upgrade::*; + +#[cfg(test)] +mod tests; diff --git a/zebra-consensus/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs similarity index 98% rename from zebra-consensus/src/parameters/network_upgrade.rs rename to zebra-chain/src/parameters/network_upgrade.rs index b9e7ff60..ed04b487 100644 --- a/zebra-consensus/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -2,12 +2,12 @@ use NetworkUpgrade::*; +use crate::types::BlockHeight; +use crate::{Network, Network::*}; + use std::collections::{BTreeMap, HashMap}; use std::ops::Bound::*; -use zebra_chain::types::BlockHeight; -use zebra_chain::{Network, Network::*}; - /// A Zcash network upgrade. /// /// Network upgrades can change the Zcash network protocol or consensus rules in diff --git a/zebra-chain/src/parameters/tests.rs b/zebra-chain/src/parameters/tests.rs new file mode 100644 index 00000000..ad737b70 --- /dev/null +++ b/zebra-chain/src/parameters/tests.rs @@ -0,0 +1,185 @@ +//! Consensus parameter tests for Zebra. + +use super::*; +use NetworkUpgrade::*; + +use crate::types::BlockHeight; +use crate::{Network, Network::*}; + +use std::collections::HashSet; + +/// Check that the activation heights and network upgrades are unique. +#[test] +fn activation_bijective() { + let mainnet_activations = NetworkUpgrade::activation_list(Mainnet); + let mainnet_heights: HashSet<&BlockHeight> = 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_heights: HashSet<&BlockHeight> = testnet_activations.keys().collect(); + assert_eq!(TESTNET_ACTIVATION_HEIGHTS.len(), testnet_heights.len()); + + let testnet_nus: HashSet<&NetworkUpgrade> = testnet_activations.values().collect(); + assert_eq!(TESTNET_ACTIVATION_HEIGHTS.len(), testnet_nus.len()); +} + +#[test] +fn activation_extremes_mainnet() { + activation_extremes(Mainnet) +} + +#[test] +fn activation_extremes_testnet() { + activation_extremes(Testnet) +} + +/// Test the activation_list, activation_height, current, and next functions +/// for `network` with extreme values. +fn activation_extremes(network: Network) { + // The first three upgrades are Genesis, BeforeOverwinter, and Overwinter + assert_eq!( + NetworkUpgrade::activation_list(network).get(&BlockHeight(0)), + Some(&Genesis) + ); + assert_eq!(Genesis.activation_height(network), Some(BlockHeight(0))); + assert_eq!(NetworkUpgrade::current(network, BlockHeight(0)), Genesis); + assert_eq!( + NetworkUpgrade::next(network, BlockHeight(0)), + Some(BeforeOverwinter) + ); + + assert_eq!( + NetworkUpgrade::activation_list(network).get(&BlockHeight(1)), + Some(&BeforeOverwinter) + ); + assert_eq!( + BeforeOverwinter.activation_height(network), + Some(BlockHeight(1)) + ); + assert_eq!( + NetworkUpgrade::current(network, BlockHeight(1)), + BeforeOverwinter + ); + assert_eq!( + NetworkUpgrade::next(network, BlockHeight(1)), + Some(Overwinter) + ); + + // 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(&BlockHeight::MAX), + Some(&Genesis) + ); + assert_ne!(NetworkUpgrade::current(network, BlockHeight::MAX), Genesis); + assert_eq!(NetworkUpgrade::next(network, BlockHeight::MAX), None); +} + +#[test] +fn activation_consistent_mainnet() { + activation_consistent(Mainnet) +} + +#[test] +fn activation_consistent_testnet() { + activation_consistent(Testnet) +} + +/// Check that the activation_height, current, and next functions are consistent +/// for `network`. +fn activation_consistent(network: Network) { + let activation_list = NetworkUpgrade::activation_list(network); + let network_upgrades: HashSet<&NetworkUpgrade> = activation_list.values().collect(); + + for &network_upgrade in network_upgrades { + let height = network_upgrade + .activation_height(network) + .expect("activations must have a height"); + assert_eq!(NetworkUpgrade::current(network, height), network_upgrade); + // Network upgrades don't repeat + assert_ne!(NetworkUpgrade::next(network, height), Some(network_upgrade)); + assert_ne!( + NetworkUpgrade::next(network, BlockHeight(height.0 + 1)), + Some(network_upgrade) + ); + assert_ne!( + NetworkUpgrade::next(network, BlockHeight::MAX), + Some(network_upgrade) + ); + } +} + +/// Check that the network upgrades and branch ids are unique. +#[test] +fn branch_id_bijective() { + let branch_id_list = NetworkUpgrade::branch_id_list(); + let nus: HashSet<&NetworkUpgrade> = branch_id_list.keys().collect(); + assert_eq!(CONSENSUS_BRANCH_IDS.len(), nus.len()); + + let branch_ids: HashSet<&ConsensusBranchId> = branch_id_list.values().collect(); + assert_eq!(CONSENSUS_BRANCH_IDS.len(), branch_ids.len()); +} + +#[test] +fn branch_id_extremes_mainnet() { + branch_id_extremes(Mainnet) +} + +#[test] +fn branch_id_extremes_testnet() { + branch_id_extremes(Testnet) +} + +/// Test the branch_id_list, branch_id, and current functions for `network` with +/// extreme values. +fn branch_id_extremes(network: Network) { + // Branch ids were introduced in Overwinter + assert_eq!( + NetworkUpgrade::branch_id_list().get(&BeforeOverwinter), + None + ); + assert_eq!(ConsensusBranchId::current(network, BlockHeight(0)), None); + assert_eq!( + NetworkUpgrade::branch_id_list().get(&Overwinter).cloned(), + Overwinter.branch_id() + ); + + // We assume that the last upgrade we know about continues forever + // (even if we suspect that won't be true) + assert_ne!( + NetworkUpgrade::branch_id_list().get(&NetworkUpgrade::current(network, BlockHeight::MAX)), + None + ); + assert_ne!(ConsensusBranchId::current(network, BlockHeight::MAX), None); +} + +#[test] +fn branch_id_consistent_mainnet() { + branch_id_consistent(Mainnet) +} + +#[test] +fn branch_id_consistent_testnet() { + branch_id_consistent(Testnet) +} + +/// Check that the branch_id and current functions are consistent for `network`. +fn branch_id_consistent(network: Network) { + let branch_id_list = NetworkUpgrade::branch_id_list(); + let network_upgrades: HashSet<&NetworkUpgrade> = branch_id_list.keys().collect(); + + for &network_upgrade in network_upgrades { + let height = network_upgrade.activation_height(network); + + // Skip network upgrades that don't have activation heights yet + if let Some(height) = height { + assert_eq!( + ConsensusBranchId::current(network, height), + network_upgrade.branch_id() + ); + } + } +} diff --git a/zebra-consensus/src/chain.rs b/zebra-consensus/src/chain.rs index 65188924..0eda619d 100644 --- a/zebra-consensus/src/chain.rs +++ b/zebra-consensus/src/chain.rs @@ -15,7 +15,6 @@ mod tests; use crate::checkpoint::{CheckpointList, CheckpointVerifier}; -use crate::parameters::NetworkUpgrade::Sapling; use futures_util::FutureExt; use std::{ @@ -30,7 +29,7 @@ use tracing_futures::Instrument; use zebra_chain::block::{Block, BlockHeaderHash}; use zebra_chain::types::BlockHeight; -use zebra_chain::Network; +use zebra_chain::{Network, NetworkUpgrade::Sapling}; /// The maximum expected gap between blocks. /// diff --git a/zebra-consensus/src/checkpoint/list/tests.rs b/zebra-consensus/src/checkpoint/list/tests.rs index 0d5daea0..72104d7c 100644 --- a/zebra-consensus/src/checkpoint/list/tests.rs +++ b/zebra-consensus/src/checkpoint/list/tests.rs @@ -2,11 +2,10 @@ use super::*; -use crate::parameters::NetworkUpgrade::Sapling; - use std::sync::Arc; use zebra_chain::{block::Block, serialization::ZcashDeserialize}; +use zebra_chain::{Network, NetworkUpgrade::Sapling}; /// Make a checkpoint list containing only the genesis block #[test] diff --git a/zebra-consensus/src/parameters.rs b/zebra-consensus/src/parameters.rs index 7cc79210..90df264c 100644 --- a/zebra-consensus/src/parameters.rs +++ b/zebra-consensus/src/parameters.rs @@ -1,5 +1,8 @@ //! The consensus parameters for each Zcash network. //! +//! This module contains the consensus parameters which are required for +//! verification. +//! //! Some consensus parameters change based on network upgrades. Each network //! upgrade happens at a particular block height. Some parameters have a value //! (or function) before the upgrade height, at the upgrade height, and after @@ -11,11 +14,9 @@ pub mod genesis; pub mod minimum_difficulty; -pub mod network_upgrade; pub use genesis::*; pub use minimum_difficulty::*; -pub use network_upgrade::*; #[cfg(test)] mod tests; diff --git a/zebra-consensus/src/parameters/tests.rs b/zebra-consensus/src/parameters/tests.rs index 5879cc71..b35e1895 100644 --- a/zebra-consensus/src/parameters/tests.rs +++ b/zebra-consensus/src/parameters/tests.rs @@ -1,189 +1,10 @@ //! Consensus parameter tests for Zebra. use super::*; -use NetworkUpgrade::*; - -use std::collections::HashSet; use zebra_chain::types::BlockHeight; use zebra_chain::{Network, Network::*}; -/// Check that the activation heights and network upgrades are unique. -#[test] -fn activation_bijective() { - let mainnet_activations = NetworkUpgrade::activation_list(Mainnet); - let mainnet_heights: HashSet<&BlockHeight> = 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_heights: HashSet<&BlockHeight> = testnet_activations.keys().collect(); - assert_eq!(TESTNET_ACTIVATION_HEIGHTS.len(), testnet_heights.len()); - - let testnet_nus: HashSet<&NetworkUpgrade> = testnet_activations.values().collect(); - assert_eq!(TESTNET_ACTIVATION_HEIGHTS.len(), testnet_nus.len()); -} - -#[test] -fn activation_extremes_mainnet() { - activation_extremes(Mainnet) -} - -#[test] -fn activation_extremes_testnet() { - activation_extremes(Testnet) -} - -/// Test the activation_list, activation_height, current, and next functions -/// for `network` with extreme values. -fn activation_extremes(network: Network) { - // The first three upgrades are Genesis, BeforeOverwinter, and Overwinter - assert_eq!( - NetworkUpgrade::activation_list(network).get(&BlockHeight(0)), - Some(&Genesis) - ); - assert_eq!(Genesis.activation_height(network), Some(BlockHeight(0))); - assert_eq!(NetworkUpgrade::current(network, BlockHeight(0)), Genesis); - assert_eq!( - NetworkUpgrade::next(network, BlockHeight(0)), - Some(BeforeOverwinter) - ); - - assert_eq!( - NetworkUpgrade::activation_list(network).get(&BlockHeight(1)), - Some(&BeforeOverwinter) - ); - assert_eq!( - BeforeOverwinter.activation_height(network), - Some(BlockHeight(1)) - ); - assert_eq!( - NetworkUpgrade::current(network, BlockHeight(1)), - BeforeOverwinter - ); - assert_eq!( - NetworkUpgrade::next(network, BlockHeight(1)), - Some(Overwinter) - ); - - // 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(&BlockHeight::MAX), - Some(&Genesis) - ); - assert_ne!(NetworkUpgrade::current(network, BlockHeight::MAX), Genesis); - assert_eq!(NetworkUpgrade::next(network, BlockHeight::MAX), None); -} - -#[test] -fn activation_consistent_mainnet() { - activation_consistent(Mainnet) -} - -#[test] -fn activation_consistent_testnet() { - activation_consistent(Testnet) -} - -/// Check that the activation_height, current, and next functions are consistent -/// for `network`. -fn activation_consistent(network: Network) { - let activation_list = NetworkUpgrade::activation_list(network); - let network_upgrades: HashSet<&NetworkUpgrade> = activation_list.values().collect(); - - for &network_upgrade in network_upgrades { - let height = network_upgrade - .activation_height(network) - .expect("activations must have a height"); - assert_eq!(NetworkUpgrade::current(network, height), network_upgrade); - // Network upgrades don't repeat - assert_ne!(NetworkUpgrade::next(network, height), Some(network_upgrade)); - assert_ne!( - NetworkUpgrade::next(network, BlockHeight(height.0 + 1)), - Some(network_upgrade) - ); - assert_ne!( - NetworkUpgrade::next(network, BlockHeight::MAX), - Some(network_upgrade) - ); - } -} - -/// Check that the network upgrades and branch ids are unique. -#[test] -fn branch_id_bijective() { - let branch_id_list = NetworkUpgrade::branch_id_list(); - let nus: HashSet<&NetworkUpgrade> = branch_id_list.keys().collect(); - assert_eq!(CONSENSUS_BRANCH_IDS.len(), nus.len()); - - let branch_ids: HashSet<&ConsensusBranchId> = branch_id_list.values().collect(); - assert_eq!(CONSENSUS_BRANCH_IDS.len(), branch_ids.len()); -} - -#[test] -fn branch_id_extremes_mainnet() { - branch_id_extremes(Mainnet) -} - -#[test] -fn branch_id_extremes_testnet() { - branch_id_extremes(Testnet) -} - -/// Test the branch_id_list, branch_id, and current functions for `network` with -/// extreme values. -fn branch_id_extremes(network: Network) { - // Branch ids were introduced in Overwinter - assert_eq!( - NetworkUpgrade::branch_id_list().get(&BeforeOverwinter), - None - ); - assert_eq!(ConsensusBranchId::current(network, BlockHeight(0)), None); - assert_eq!( - NetworkUpgrade::branch_id_list().get(&Overwinter).cloned(), - Overwinter.branch_id() - ); - - // We assume that the last upgrade we know about continues forever - // (even if we suspect that won't be true) - assert_ne!( - NetworkUpgrade::branch_id_list().get(&NetworkUpgrade::current(network, BlockHeight::MAX)), - None - ); - assert_ne!(ConsensusBranchId::current(network, BlockHeight::MAX), None); -} - -#[test] -fn branch_id_consistent_mainnet() { - branch_id_consistent(Mainnet) -} - -#[test] -fn branch_id_consistent_testnet() { - branch_id_consistent(Testnet) -} - -/// Check that the branch_id and current functions are consistent for `network`. -fn branch_id_consistent(network: Network) { - let branch_id_list = NetworkUpgrade::branch_id_list(); - let network_upgrades: HashSet<&NetworkUpgrade> = branch_id_list.keys().collect(); - - for &network_upgrade in network_upgrades { - let height = network_upgrade.activation_height(network); - - // Skip network upgrades that don't have activation heights yet - if let Some(height) = height { - assert_eq!( - ConsensusBranchId::current(network, height), - network_upgrade.branch_id() - ); - } - } -} - #[test] fn minimum_difficulty_mainnet() { minimum_difficulty(Mainnet) diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index 3204c89a..59cdf6bd 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -5,7 +5,7 @@ use std::time::Duration; // XXX should these constants be split into protocol also? use crate::protocol::external::types::*; -use zebra_consensus::parameters::NetworkUpgrade::{self, *}; +use zebra_chain::NetworkUpgrade::{self, *}; /// The buffer size for the peer set. pub const PEERSET_BUFFER_SIZE: usize = 10; diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 2c466928..7657658a 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -6,7 +6,7 @@ use std::fmt; use zebra_chain::types::BlockHeight; use zebra_chain::Network::{self, *}; -use zebra_consensus::parameters::NetworkUpgrade::{self, *}; +use zebra_chain::NetworkUpgrade::{self, *}; #[cfg(test)] use proptest_derive::Arbitrary;