Skip to content

Commit

Permalink
Merge of #8368
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Apr 15, 2024
2 parents 1534442 + eca7f6b commit a4c0813
Show file tree
Hide file tree
Showing 59 changed files with 813 additions and 447 deletions.
4 changes: 2 additions & 2 deletions zebra-chain/src/block/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ fn block_test_vectors_height_mainnet() {
fn block_test_vectors_height_testnet() {
let _init_guard = zebra_test::init();

block_test_vectors_height(Testnet);
block_test_vectors_height(Network::new_default_testnet());
}

/// Test that the block test vector indexes match the heights in the block data,
Expand Down Expand Up @@ -245,7 +245,7 @@ fn block_commitment_mainnet() {
fn block_commitment_testnet() {
let _init_guard = zebra_test::init();

block_commitment(Testnet);
block_commitment(Network::new_default_testnet());
}

/// Check that the block commitment field parses without errors.
Expand Down
4 changes: 2 additions & 2 deletions zebra-chain/src/history_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,8 @@ impl NonEmptyHistoryTree {
}

/// Return the network where this tree is used.
pub fn network(&self) -> Network {
self.network.clone()
pub fn network(&self) -> &Network {
&self.network
}
}

Expand Down
13 changes: 7 additions & 6 deletions zebra-chain/src/history_tree/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ use eyre::Result;
/// higher level API.
#[test]
fn push_and_prune() -> Result<()> {
push_and_prune_for_network_upgrade(Network::Mainnet, NetworkUpgrade::Heartwood)?;
push_and_prune_for_network_upgrade(Network::Testnet, NetworkUpgrade::Heartwood)?;
push_and_prune_for_network_upgrade(Network::Mainnet, NetworkUpgrade::Canopy)?;
push_and_prune_for_network_upgrade(Network::Testnet, NetworkUpgrade::Canopy)?;
for network in Network::iter() {
push_and_prune_for_network_upgrade(network.clone(), NetworkUpgrade::Heartwood)?;
push_and_prune_for_network_upgrade(network, NetworkUpgrade::Canopy)?;
}
Ok(())
}

Expand Down Expand Up @@ -109,8 +109,9 @@ fn push_and_prune_for_network_upgrade(
fn upgrade() -> Result<()> {
// The history tree only exists Hearwood-onward, and the only upgrade for which
// we have vectors since then is Canopy. Therefore, only test the Heartwood->Canopy upgrade.
upgrade_for_network_upgrade(Network::Mainnet, NetworkUpgrade::Canopy)?;
upgrade_for_network_upgrade(Network::Testnet, NetworkUpgrade::Canopy)?;
for network in Network::iter() {
upgrade_for_network_upgrade(network, NetworkUpgrade::Canopy)?;
}
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion zebra-chain/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod transaction;
pub mod arbitrary;

pub use genesis::*;
pub use network::Network;
pub use network::{testnet, Network, NetworkKind};
pub use network_upgrade::*;
pub use transaction::*;

Expand Down
157 changes: 127 additions & 30 deletions zebra-chain/src/parameters/network.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//! Consensus parameters for each Zcash network.
use std::{fmt, str::FromStr};
use std::{fmt, str::FromStr, sync::Arc};

use thiserror::Error;

use zcash_primitives::constants;

use crate::{
block::{self, Height, HeightDiff},
parameters::NetworkUpgrade::Canopy,
};

pub mod testnet;

#[cfg(any(test, feature = "proptest-impl"))]
use proptest_derive::Arbitrary;

Expand Down Expand Up @@ -51,52 +55,102 @@ mod tests;
/// after the grace period.
const ZIP_212_GRACE_PERIOD_DURATION: HeightDiff = 32_256;

/// An enum describing the kind of network, whether it's the production mainnet or a testnet.
// Note: The order of these variants is important for correct bincode (de)serialization
// of history trees in the db format.
// TODO: Replace bincode (de)serialization of `HistoryTreeParts` in a db format upgrade?
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum NetworkKind {
/// The production mainnet.
#[default]
Mainnet,

/// A test network.
Testnet,

/// Regtest mode, not yet implemented
// TODO: Add `new_regtest()` and `is_regtest` methods on `Network`.
Regtest,
}

impl From<Network> for NetworkKind {
fn from(network: Network) -> Self {
network.kind()
}
}

/// An enum describing the possible network choices.
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
#[serde(into = "NetworkKind")]
pub enum Network {
/// The production mainnet.
#[default]
Mainnet,

/// The oldest public test network.
Testnet,
/// A test network such as the default public testnet,
/// a configured testnet, or Regtest.
Testnet(Arc<testnet::Parameters>),
}

use zcash_primitives::consensus::{Network as ZcashPrimitivesNetwork, Parameters as _};
impl Network {
impl NetworkKind {
/// 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] {
<ZcashPrimitivesNetwork>::from(self).b58_pubkey_address_prefix()
pub fn b58_pubkey_address_prefix(self) -> [u8; 2] {
match self {
Self::Mainnet => constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
Self::Testnet | Self::Regtest => constants::testnet::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] {
<ZcashPrimitivesNetwork>::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 <https://zips.z.cash/protocol/protocol.pdf#blockheader>
pub fn is_max_block_time_enforced(&self, height: block::Height) -> bool {
pub fn b58_script_address_prefix(self) -> [u8; 2] {
match self {
Network::Mainnet => true,
Network::Testnet => height >= super::TESTNET_MAX_TIME_START_HEIGHT,
Self::Mainnet => constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
Self::Testnet | Self::Regtest => constants::testnet::B58_SCRIPT_ADDRESS_PREFIX,
}
}

/// Return the network name as defined in
/// [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#paymentdetailspaymentrequest)
pub fn bip70_network_name(&self) -> String {
if *self == Self::Mainnet {
"main".to_string()
} else {
"test".to_string()
}
}
}

impl From<NetworkKind> for &'static str {
fn from(network: NetworkKind) -> &'static str {
// These should be different from the `Display` impl for `Network` so that its lowercase form
// can't be parsed as the default Testnet in the `Network` `FromStr` impl, it's easy to
// distinguish them in logs, and so it's generally harder to confuse the two.
match network {
NetworkKind::Mainnet => "MainnetKind",
NetworkKind::Testnet => "TestnetKind",
NetworkKind::Regtest => "RegtestKind",
}
}
}

impl fmt::Display for NetworkKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str((*self).into())
}
}

impl From<&Network> for &'static str {
fn from(network: &Network) -> &'static str {
match network {
Network::Mainnet => "Mainnet",
Network::Testnet => "Testnet",
// TODO:
// - Add a `name` field to use here instead of checking `is_default_testnet()`
// - zcashd calls the Regtest cache dir 'regtest' (#8327).
Network::Testnet(params) if params.is_default_testnet() => "Testnet",
Network::Testnet(_params) => "UnknownTestnet",
}
}
}
Expand All @@ -108,17 +162,62 @@ impl fmt::Display for Network {
}

impl Network {
/// Creates a new [`Network::Testnet`] with the default Testnet [`testnet::Parameters`].
pub fn new_default_testnet() -> Self {
Self::Testnet(Arc::new(testnet::Parameters::default()))
}

/// Creates a new configured [`Network::Testnet`] with the provided Testnet [`testnet::Parameters`].
pub fn new_configured_testnet(params: testnet::Parameters) -> Self {
Self::Testnet(Arc::new(params))
}

/// Returns true if the network is the default Testnet, or false otherwise.
pub fn is_default_testnet(&self) -> bool {
if let Self::Testnet(params) = self {
params.is_default_testnet()
} else {
false
}
}

/// Returns the [`NetworkKind`] for this network.
pub fn kind(&self) -> NetworkKind {
match self {
Network::Mainnet => NetworkKind::Mainnet,
// TODO: Return `NetworkKind::Regtest` if the parameters match the default Regtest params
Network::Testnet(_) => NetworkKind::Testnet,
}
}

/// Returns an iterator over [`Network`] variants.
pub fn iter() -> impl Iterator<Item = Self> {
// TODO: Use default values of `Testnet` variant when adding fields for #7845.
[Self::Mainnet, Self::Testnet].into_iter()
[Self::Mainnet, Self::new_default_testnet()].into_iter()
}

/// 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 <https://zips.z.cash/protocol/protocol.pdf#blockheader>
pub fn is_max_block_time_enforced(&self, height: block::Height) -> bool {
match self {
Network::Mainnet => true,
// TODO: Move `TESTNET_MAX_TIME_START_HEIGHT` to a field on testnet::Parameters (#8364)
Network::Testnet(_params) => height >= super::TESTNET_MAX_TIME_START_HEIGHT,
}
}

/// Get the default port associated to this network.
pub fn default_port(&self) -> u16 {
match self {
Network::Mainnet => 8233,
Network::Testnet => 18233,
// TODO: Add a `default_port` field to `testnet::Parameters` to return here. (zcashd uses 18344 for Regtest)
Network::Testnet(_params) => 18233,
}
}

Expand All @@ -143,10 +242,7 @@ impl Network {
/// Return the network name as defined in
/// [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#paymentdetailspaymentrequest)
pub fn bip70_network_name(&self) -> String {
match self {
Network::Mainnet => "main".to_string(),
Network::Testnet => "test".to_string(),
}
self.kind().bip70_network_name()
}

/// Return the lowercase network name.
Expand All @@ -167,13 +263,14 @@ impl Network {
}
}

// This is used for parsing a command-line argument for the `TipHeight` command in zebrad.
impl FromStr for Network {
type Err = InvalidNetworkError;

fn from_str(string: &str) -> Result<Self, Self::Err> {
match string.to_lowercase().as_str() {
"mainnet" => Ok(Network::Mainnet),
"testnet" => Ok(Network::Testnet),
"testnet" => Ok(Network::new_default_testnet()),
_ => Err(InvalidNetworkError(string.to_owned())),
}
}
Expand Down
16 changes: 16 additions & 0 deletions zebra-chain/src/parameters/network/testnet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! Types and implementation for Testnet consensus parameters
#[cfg(any(test, feature = "proptest-impl"))]
use proptest_derive::Arbitrary;

/// Network consensus parameters for test networks such as Regtest and the default Testnet.
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
pub struct Parameters {}

impl Parameters {
/// Returns true if the instance of [`Parameters`] represents the default public Testnet.
pub fn is_default_testnet(&self) -> bool {
self == &Self::default()
}
}
2 changes: 1 addition & 1 deletion zebra-chain/src/parameters/network/tests/prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ proptest! {
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);
assert_eq!(Network::new_default_testnet().is_max_block_time_enforced(height), TESTNET_MAX_TIME_START_HEIGHT <= height);
}
}
12 changes: 9 additions & 3 deletions zebra-chain/src/parameters/network_upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ impl Network {
};
match self {
Mainnet => mainnet_heights,
Testnet => testnet_heights,
// TODO: Add an `activation_heights` field to `testnet::Parameters` to return here. (#7970)
Testnet(_params) => testnet_heights,
}
.iter()
.cloned()
Expand Down Expand Up @@ -394,9 +395,14 @@ impl NetworkUpgrade {
height: block::Height,
) -> Option<Duration> {
match (network, height) {
(Network::Testnet, height) if height < TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT => None,
// TODO: Move `TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT` to a field on testnet::Parameters (#8364)
(Network::Testnet(_params), height)
if height < TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT =>
{
None
}
(Network::Mainnet, _) => None,
(Network::Testnet, _) => {
(Network::Testnet(_params), _) => {
let network_upgrade = NetworkUpgrade::current(network, height);
Some(network_upgrade.target_spacing() * TESTNET_MINIMUM_DIFFICULTY_GAP_MULTIPLIER)
}
Expand Down
10 changes: 5 additions & 5 deletions zebra-chain/src/parameters/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn activation_bijective() {
let mainnet_nus: HashSet<&NetworkUpgrade> = mainnet_activations.values().collect();
assert_eq!(MAINNET_ACTIVATION_HEIGHTS.len(), mainnet_nus.len());

let testnet_activations = Testnet.activation_list();
let testnet_activations = Network::new_default_testnet().activation_list();
let testnet_heights: HashSet<&block::Height> = testnet_activations.keys().collect();
assert_eq!(TESTNET_ACTIVATION_HEIGHTS.len(), testnet_heights.len());

Expand All @@ -38,7 +38,7 @@ fn activation_extremes_mainnet() {
#[test]
fn activation_extremes_testnet() {
let _init_guard = zebra_test::init();
activation_extremes(Testnet)
activation_extremes(Network::new_default_testnet())
}

/// Test the activation_list, activation_height, current, and next functions
Expand Down Expand Up @@ -115,7 +115,7 @@ fn activation_consistent_mainnet() {
#[test]
fn activation_consistent_testnet() {
let _init_guard = zebra_test::init();
activation_consistent(Testnet)
activation_consistent(Network::new_default_testnet())
}

/// Check that the `activation_height`, `is_activation_height`,
Expand Down Expand Up @@ -178,7 +178,7 @@ fn branch_id_extremes_mainnet() {
#[test]
fn branch_id_extremes_testnet() {
let _init_guard = zebra_test::init();
branch_id_extremes(Testnet)
branch_id_extremes(Network::new_default_testnet())
}

/// Test the branch_id_list, branch_id, and current functions for `network` with
Expand Down Expand Up @@ -217,7 +217,7 @@ fn branch_id_consistent_mainnet() {
#[test]
fn branch_id_consistent_testnet() {
let _init_guard = zebra_test::init();
branch_id_consistent(Testnet)
branch_id_consistent(Network::new_default_testnet())
}

/// Check that the branch_id and current functions are consistent for `network`.
Expand Down
Loading

0 comments on commit a4c0813

Please sign in to comment.