Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add(consensus): Adds block construction and validation for NU5 from block height 1 for Regtest #8475

Merged
merged 19 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7b009b3
Always activate Canopy at Height(1) on Regtest
arya2 Apr 29, 2024
21e838a
Ignores the zip 212 grace period on configured Testnets and Regtest
arya2 Apr 23, 2024
52ff68f
- Returns early when there is no Heartwood activation height when cre…
arya2 Apr 29, 2024
37f9b76
- When proof of work is disabled, skips checking if Zebra is synced t…
arya2 Apr 29, 2024
2e95495
Sets full_verifier_utxo_lookahead to Height::MIN instead of panicking
arya2 Apr 29, 2024
7f1013a
When network is regtest, skips starting sync task and commits the gen…
arya2 Apr 29, 2024
071cb1c
updates/fixes test config
arya2 Apr 29, 2024
088e4e4
Adds test for committing Canopy blocks on Regtest
arya2 Apr 30, 2024
5564c38
- Updates median time past and difficulty checks to use fewer than 11…
arya2 Apr 30, 2024
445b8f1
uses SLOW_START_INTERVAL of 0 if PoW is disabled, adds TODOs
arya2 Apr 30, 2024
8fbf09e
Update getblocktemplate method to return reserved chain history activ…
arya2 Apr 30, 2024
97b5db8
Updates test to expect NU5 as the default nu activation at Height(1)
arya2 Apr 30, 2024
40951d5
Removes invalid difficulty snapshot
arya2 Apr 30, 2024
e7a09ae
fixes tests
arya2 Apr 30, 2024
855ad12
removes regtest NU5 activation height config field
arya2 Apr 30, 2024
8128a07
Apply suggestions from code review
arya2 May 1, 2024
aeebad7
Update zebra-state/src/service/check/difficulty.rs
arya2 May 1, 2024
5be5ee1
Update zebra-state/src/service/check/difficulty.rs
arya2 May 1, 2024
2ad072a
Updates docs/comments, renames an argument
arya2 May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion zebra-chain/src/block/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl Commitment {
Ok(root) => Ok(FinalSaplingRoot(root)),
_ => Err(InvalidSapingRootBytes),
},
Heartwood if Some(height) == Heartwood.activation_height(network) => {
Heartwood | Nu5 if Some(height) == Heartwood.activation_height(network) => {
upbqdn marked this conversation as resolved.
Show resolved Hide resolved
if bytes == CHAIN_HISTORY_ACTIVATION_RESERVED {
Ok(ChainHistoryActivationReserved)
} else {
Expand Down
8 changes: 5 additions & 3 deletions zebra-chain/src/history_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,11 @@ impl HistoryTree {
sapling_root: &sapling::tree::Root,
orchard_root: &orchard::tree::Root,
) -> Result<Self, HistoryTreeError> {
let heartwood_height = NetworkUpgrade::Heartwood
.activation_height(network)
.expect("Heartwood height is known");
let Some(heartwood_height) = NetworkUpgrade::Heartwood.activation_height(network) else {
// Return early if there is no Heartwood activation height.
return Ok(HistoryTree(None));
};

match block
.coinbase_height()
.expect("must have height")
Expand Down
30 changes: 22 additions & 8 deletions zebra-chain/src/parameters/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ use crate::{
parameters::NetworkUpgrade,
};

use self::testnet::ConfiguredActivationHeights;

pub mod testnet;

#[cfg(test)]
Expand Down Expand Up @@ -167,8 +165,8 @@ impl Network {
}

/// Creates a new [`Network::Testnet`] with `Regtest` parameters and the provided network upgrade activation heights.
pub fn new_regtest(activation_heights: ConfiguredActivationHeights) -> Self {
Self::new_configured_testnet(testnet::Parameters::new_regtest(activation_heights))
pub fn new_regtest() -> Self {
Self::new_configured_testnet(testnet::Parameters::new_regtest())
}

/// Returns true if the network is the default Testnet, or false otherwise.
Expand Down Expand Up @@ -201,14 +199,13 @@ impl 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(params) if params.is_regtest() => NetworkKind::Regtest,
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::new_default_testnet()].into_iter()
}

Expand Down Expand Up @@ -242,6 +239,12 @@ impl Network {
/// Mandatory checkpoints are a Zebra-specific feature.
/// If a Zcash consensus rule only applies before the mandatory checkpoint,
/// Zebra can skip validation of that rule.
///
/// ZIP-212 grace period is only applied to default networks.
// TODO:
// - Support constructing pre-Canopy coinbase tx and block templates and return `Height::MAX` instead of panicking
// when Canopy activation height is `None` (#8434)
// - Add semantic block validation during the ZIP-212 grace period and update this method to always apply the ZIP-212 grace period
pub fn mandatory_checkpoint_height(&self) -> Height {
// Currently this is after the ZIP-212 grace period.
//
Expand All @@ -251,8 +254,19 @@ impl Network {
.activation_height(self)
.expect("Canopy activation height must be present for both networks");

(canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
.expect("ZIP-212 grace period ends at a valid block height")
let is_a_default_network = match self {
Network::Mainnet => true,
Network::Testnet(params) => params.is_default_testnet(),
};

if is_a_default_network {
(canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
.expect("ZIP-212 grace period ends at a valid block height")
} else {
canopy_activation
.previous()
.expect("Canopy activation must be above Genesis height")
}
arya2 marked this conversation as resolved.
Show resolved Hide resolved
}

/// Return the network name as defined in
Expand Down
9 changes: 6 additions & 3 deletions zebra-chain/src/parameters/network/testnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ impl Parameters {
/// Accepts a [`ConfiguredActivationHeights`].
///
/// Creates an instance of [`Parameters`] with `Regtest` values.
pub fn new_regtest(activation_heights: ConfiguredActivationHeights) -> Self {
pub fn new_regtest() -> Self {
Self {
network_name: "Regtest".to_string(),
..Self::build()
Expand All @@ -323,7 +323,10 @@ impl Parameters {
)
// Removes default Testnet activation heights if not configured,
// most network upgrades are disabled by default for Regtest in zcashd
.with_activation_heights(activation_heights)
.with_activation_heights(ConfiguredActivationHeights {
nu5: Some(1),
..Default::default()
})
.finish()
}
}
Expand All @@ -344,7 +347,7 @@ impl Parameters {
hrp_sapling_extended_full_viewing_key,
hrp_sapling_payment_address,
disable_pow,
} = Self::new_regtest(ConfiguredActivationHeights::default());
} = Self::new_regtest();

self.network_name == network_name
&& self.genesis_hash == genesis_hash
Expand Down
6 changes: 3 additions & 3 deletions zebra-chain/src/parameters/network/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ fn activates_network_upgrades_correctly() {

let expected_default_regtest_activation_heights = &[
(Height(0), NetworkUpgrade::Genesis),
(Height(1), NetworkUpgrade::BeforeOverwinter),
(Height(1), NetworkUpgrade::Nu5),
];

for (network, expected_activation_heights) in [
(Network::Mainnet, MAINNET_ACTIVATION_HEIGHTS),
(Network::new_default_testnet(), TESTNET_ACTIVATION_HEIGHTS),
(
Network::new_regtest(Default::default()),
Network::new_regtest(),
expected_default_regtest_activation_heights,
),
] {
Expand Down Expand Up @@ -193,7 +193,7 @@ fn check_configured_network_name() {
"Mainnet should be displayed as 'Mainnet'"
);
assert_eq!(
Network::new_regtest(Default::default()).to_string(),
Network::new_regtest().to_string(),
"Regtest",
"Regtest should be displayed as 'Regtest'"
);
Expand Down
10 changes: 3 additions & 7 deletions zebra-chain/src/parameters/network_upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
/// Network upgrades can change the Zcash network protocol or consensus rules in
/// incompatible ways.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]

Check warning on line 34 in zebra-chain/src/parameters/network_upgrade.rs

View workflow job for this annotation

GitHub Actions / Build and Deploy Zebra Internal Docs

non-local `impl` definition, they should be avoided as they go against expectation

Check warning on line 34 in zebra-chain/src/parameters/network_upgrade.rs

View workflow job for this annotation

GitHub Actions / Test beta on ubuntu-latest

non-local `impl` definition, they should be avoided as they go against expectation

Check warning on line 34 in zebra-chain/src/parameters/network_upgrade.rs

View workflow job for this annotation

GitHub Actions / Test beta on windows-latest

non-local `impl` definition, they should be avoided as they go against expectation
pub enum NetworkUpgrade {
/// The Zcash protocol for a Genesis block.
///
Expand Down Expand Up @@ -402,14 +402,10 @@
),
]
.into_iter()
.map(move |(upgrade, spacing_seconds)| {
let activation_height = upgrade
.activation_height(network)
.expect("missing activation height for target spacing change");

.filter_map(move |(upgrade, spacing_seconds)| {
let activation_height = upgrade.activation_height(network)?;
let target_spacing = Duration::seconds(spacing_seconds);

(activation_height, target_spacing)
Some((activation_height, target_spacing))
})
}

Expand Down
2 changes: 1 addition & 1 deletion zebra-chain/src/work/difficulty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ impl ParameterDifficulty for Network {
/* 2^243 - 1 */
Network::Mainnet => (U256::one() << 243) - 1,
/* 2^251 - 1 */
// TODO: Add a `target_difficulty_limit` field to `testnet::Parameters` to return here.
// TODO: Add a `target_difficulty_limit` field to `testnet::Parameters` to return here. (`U256::from_big_endian(&[0x0f].repeat(8))` for Regtest)
Network::Testnet(_params) => (U256::one() << 251) - 1,
};

Expand Down
12 changes: 10 additions & 2 deletions zebra-consensus/src/block/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,18 @@ pub fn subsidy_is_valid(block: &Block, network: &Network) -> Result<(), BlockErr
.activation_height(network)
.expect("Canopy activation height is known");

if height < SLOW_START_INTERVAL {
// TODO: Add this as a field on `testnet::Parameters` instead of checking `disable_pow()`, this is 0 for Regtest in zcashd,
// see <https://github.com/zcash/zcash/blob/master/src/chainparams.cpp#L640>
let slow_start_interval = if network.disable_pow() {
Height(0)
} else {
SLOW_START_INTERVAL
};

if height < slow_start_interval {
unreachable!(
"unsupported block height: callers should handle blocks below {:?}",
SLOW_START_INTERVAL
slow_start_interval
)
} else if halving_div.count_ones() != 1 {
unreachable!("invalid halving divisor: the halving divisor must be a non-zero power of two")
Expand Down
20 changes: 15 additions & 5 deletions zebra-consensus/src/block/subsidy/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,20 @@ pub fn halving_divisor(height: Height, network: &Network) -> Option<u64> {
.activation_height(network)
.expect("blossom activation height should be available");

if height < SLOW_START_SHIFT {
// TODO: Add this as a field on `testnet::Parameters` instead of checking `disable_pow()`, this is 0 for Regtest in zcashd,
// see <https://github.com/zcash/zcash/blob/master/src/chainparams.cpp#L640>
let slow_start_shift = if network.disable_pow() {
Height(0)
} else {
SLOW_START_SHIFT
};

if height < slow_start_shift {
unreachable!(
"unsupported block height {height:?}: checkpoints should handle blocks below {SLOW_START_SHIFT:?}",
"unsupported block height {height:?}: checkpoints should handle blocks below {slow_start_shift:?}",
)
} else if height < blossom_height {
let pre_blossom_height = height - SLOW_START_SHIFT;
let pre_blossom_height = height - slow_start_shift;
let halving_shift = pre_blossom_height / PRE_BLOSSOM_HALVING_INTERVAL;

let halving_div = 1u64
Expand All @@ -43,7 +51,7 @@ pub fn halving_divisor(height: Height, network: &Network) -> Option<u64> {

Some(halving_div)
} else {
let pre_blossom_height = blossom_height - SLOW_START_SHIFT;
let pre_blossom_height = blossom_height - slow_start_shift;
let scaled_pre_blossom_height =
pre_blossom_height * HeightDiff::from(BLOSSOM_POW_TARGET_SPACING_RATIO);

Expand Down Expand Up @@ -77,7 +85,9 @@ pub fn block_subsidy(height: Height, network: &Network) -> Result<Amount<NonNega
return Ok(Amount::zero());
};

if height < SLOW_START_INTERVAL {
// TODO: Add this as a field on `testnet::Parameters` instead of checking `disable_pow()`, this is 0 for Regtest in zcashd,
// see <https://github.com/zcash/zcash/blob/master/src/chainparams.cpp#L640>
if height < SLOW_START_SHIFT && !network.disable_pow() {
arya2 marked this conversation as resolved.
Show resolved Hide resolved
unreachable!(
"unsupported block height {height:?}: callers should handle blocks below {SLOW_START_INTERVAL:?}",
)
Expand Down
2 changes: 1 addition & 1 deletion zebra-consensus/src/checkpoint/list/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> {

let _ = Mainnet.checkpoint_list();
let _ = Network::new_default_testnet().checkpoint_list();
let _ = Network::new_regtest(Default::default()).checkpoint_list();
let _ = Network::new_regtest().checkpoint_list();

Ok(())
}
Expand Down
13 changes: 11 additions & 2 deletions zebra-consensus/src/parameters/subsidy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,11 @@ lazy_static! {
let mut hash_map = HashMap::new();
hash_map.insert(NetworkKind::Mainnet, Height(1_046_400)..Height(2_726_400));
hash_map.insert(NetworkKind::Testnet, Height(1_028_500)..Height(2_796_000));
hash_map.insert(NetworkKind::Regtest, Height(1_028_500)..Height(2_796_000));
hash_map
};

/// Convenient storage for all addresses, for all receivers and networks
// TODO: Move the value here to a field on `testnet::Parameters` (#8367)
// There are no funding stream addresses on Regtest in zcashd, zebrad should do the same for compatibility.
pub static ref FUNDING_STREAM_ADDRESSES: HashMap<NetworkKind, HashMap<FundingStreamReceiver, Vec<String>>> = {
let mut addresses_by_network = HashMap::with_capacity(2);

Expand All @@ -132,6 +131,16 @@ lazy_static! {
testnet_addresses.insert(FundingStreamReceiver::MajorGrants, FUNDING_STREAM_MG_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
addresses_by_network.insert(NetworkKind::Testnet, testnet_addresses);


// Regtest addresses
// TODO: Move the value here to a field on `testnet::Parameters` (#8367)
// There are no funding stream addresses on Regtest in zcashd, zebrad should do the same for compatibility.
let mut regtest_addresses = HashMap::with_capacity(3);
regtest_addresses.insert(FundingStreamReceiver::Ecc, FUNDING_STREAM_ECC_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
regtest_addresses.insert(FundingStreamReceiver::ZcashFoundation, FUNDING_STREAM_ZF_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
regtest_addresses.insert(FundingStreamReceiver::MajorGrants, FUNDING_STREAM_MG_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
addresses_by_network.insert(NetworkKind::Testnet, regtest_addresses);

addresses_by_network
};
}
Expand Down
1 change: 0 additions & 1 deletion zebra-consensus/src/transaction/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,6 @@ pub fn coinbase_expiry_height(
) -> Result<(), TransactionError> {
let expiry_height = coinbase.expiry_height();

// TODO: replace `if let` with `expect` after NU5 mainnet activation
if let Some(nu5_activation_height) = NetworkUpgrade::Nu5.activation_height(network) {
// # Consensus
//
Expand Down
9 changes: 2 additions & 7 deletions zebra-network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,7 @@ impl Config {
Network::Testnet(params) if params.is_default_testnet() => {
self.initial_testnet_peers.clone()
}
// TODO: Check if the network is an incompatible custom testnet (_not_ Regtest), then panic if `initial_testnet_peers`
// contains any of the default testnet peers, or return `initial_testnet_peers` otherwise. See:
// <https://github.com/ZcashFoundation/zebra/pull/7924#discussion_r1385881828>
// TODO: Add a `disable_peers` field to `Network` to check instead of `is_default_testnet()` (#8361)
Network::Testnet(_params) => IndexSet::new(),
}
}
Expand Down Expand Up @@ -639,7 +637,6 @@ impl<'de> Deserialize<'de> for Config {
listen_addr: String,
network: NetworkKind,
testnet_parameters: Option<DTestnetParameters>,
regtest_activation_heights: ConfiguredActivationHeights,
initial_mainnet_peers: IndexSet<String>,
initial_testnet_peers: IndexSet<String>,
cache_dir: CacheDir,
Expand All @@ -656,7 +653,6 @@ impl<'de> Deserialize<'de> for Config {
listen_addr: "0.0.0.0".to_string(),
network: Default::default(),
testnet_parameters: None,
regtest_activation_heights: ConfiguredActivationHeights::default(),
initial_mainnet_peers: config.initial_mainnet_peers,
initial_testnet_peers: config.initial_testnet_peers,
cache_dir: config.cache_dir,
Expand All @@ -671,7 +667,6 @@ impl<'de> Deserialize<'de> for Config {
listen_addr,
network: network_kind,
testnet_parameters,
regtest_activation_heights,
initial_mainnet_peers,
initial_testnet_peers,
cache_dir,
Expand Down Expand Up @@ -700,7 +695,7 @@ impl<'de> Deserialize<'de> for Config {
let network = match (network_kind, testnet_parameters) {
(NetworkKind::Mainnet, _) => Network::Mainnet,
(NetworkKind::Testnet, None) => Network::new_default_testnet(),
(NetworkKind::Regtest, _) => Network::new_regtest(regtest_activation_heights),
(NetworkKind::Regtest, _) => Network::new_regtest(),
(
NetworkKind::Testnet,
Some(DTestnetParameters {
Expand Down
1 change: 1 addition & 0 deletions zebra-network/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ lazy_static! {

hash_map.insert(NetworkKind::Mainnet, Version::min_specified_for_upgrade(&Mainnet, Nu5));
hash_map.insert(NetworkKind::Testnet, Version::min_specified_for_upgrade(&Network::new_default_testnet(), Nu5));
hash_map.insert(NetworkKind::Regtest, Version::min_specified_for_upgrade(&Network::new_regtest(), Nu5));

hash_map
};
Expand Down
8 changes: 6 additions & 2 deletions zebra-rpc/src/methods/get_block_template_rpcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,12 @@ where
//
// Optional TODO:
// - add `async changed()` method to ChainSyncStatus (like `ChainTip`)
check_synced_to_tip(&network, latest_chain_tip.clone(), sync_status.clone())?;

// TODO:
// - Add a `disable_peers` field to `Network` to check instead of `disable_pow()` (#8361)
// - Check the field in `sync_status` so it applies to the mempool as well.
if !network.disable_pow() {
check_synced_to_tip(&network, latest_chain_tip.clone(), sync_status.clone())?;
}
// TODO: return an error if we have no peers, like `zcashd` does,
// and add a developer config that mines regardless of how many peers we have.
// https://github.com/zcash/zcash/blob/6fdd9f1b81d3b228326c9826fa10696fc516444b/src/miner.cpp#L865-L880
Expand Down
Loading
Loading