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<Network> 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 <gygaxis@zingolabs.org>
This commit is contained in:
parent
9b91d4bc0e
commit
3bef54b764
14
CHANGELOG.md
14
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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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] {
|
||||
<ZcashPrimitivesNetwork>::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] {
|
||||
<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 {
|
||||
match self {
|
||||
Network::Mainnet => true,
|
||||
Network::Testnet => height >= super::TESTNET_MAX_TIME_START_HEIGHT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Network> for &'static str {
|
||||
fn from(network: Network) -> &'static str {
|
||||
match network {
|
||||
|
|
|
@ -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::<Height>()) {
|
||||
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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ const TESTNET_MINIMUM_DIFFICULTY_START_HEIGHT: block::Height = block::Height(299
|
|||
/// <https://zips.z.cash/protocol/protocol.pdf#blockheader>
|
||||
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<block::Height, NetworkUpgrade> {
|
||||
pub fn activation_list(&self) -> BTreeMap<block::Height, NetworkUpgrade> {
|
||||
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> {
|
||||
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<block::Height> {
|
||||
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 <https://zips.z.cash/protocol/protocol.pdf#blockheader>
|
||||
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<NetworkUpgrade> {
|
||||
CONSENSUS_BRANCH_IDS
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
let recovery = zcash_primitives::sapling::note_encryption::try_sapling_output_recovery(
|
||||
&<zcash_primitives::consensus::Network>::from(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,
|
||||
)
|
||||
}
|
||||
};
|
||||
);
|
||||
if recovery.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
zcash_primitives::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX => {
|
||||
Ok(Address::PayToScriptHash {
|
||||
network: Network::Mainnet,
|
||||
script_hash: hash_bytes,
|
||||
}),
|
||||
magics::p2sh::TESTNET => Ok(Address::PayToScriptHash {
|
||||
})
|
||||
}
|
||||
zcash_primitives::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX => {
|
||||
Ok(Address::PayToScriptHash {
|
||||
network: Network::Testnet,
|
||||
script_hash: hash_bytes,
|
||||
}),
|
||||
magics::p2pkh::MAINNET => Ok(Address::PayToPublicKeyHash {
|
||||
})
|
||||
}
|
||||
zcash_primitives::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX => {
|
||||
Ok(Address::PayToPublicKeyHash {
|
||||
network: Network::Mainnet,
|
||||
pub_key_hash: hash_bytes,
|
||||
}),
|
||||
magics::p2pkh::TESTNET => Ok(Address::PayToPublicKeyHash {
|
||||
})
|
||||
}
|
||||
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")),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
/// <https://zips.z.cash/protocol/protocol.pdf#constants>
|
||||
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:
|
||||
/// <https://zips.z.cash/protocol/protocol.pdf#constants>
|
||||
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<Work> for PartialCumulativeWork {
|
||||
fn from(work: Work) -> Self {
|
||||
PartialCumulativeWork(work.0)
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
))?;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
|||
// <https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators>
|
||||
// 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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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")?
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
// <https://zips.z.cash/protocol/protocol.pdf#blockchain>
|
||||
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()
|
||||
|
|
|
@ -163,7 +163,7 @@ impl Encoder<Message> 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::<LittleEndian>(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 {
|
||||
|
|
|
@ -23,11 +23,13 @@ impl fmt::Debug for Magic {
|
|||
f.debug_tuple("Magic").field(&hex::encode(self.0)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Network> 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,
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<State, ReadState>(
|
|||
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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue