feature: Add a "Genesis" network upgrade

We can use this network upgrade to implement different consensus rules
and chain context handling for genesis blocks.

Part of the chain state design in #682.
This commit is contained in:
teor 2020-07-27 17:54:55 +10:00 committed by Deirdre Connolly
parent 5ece62f0a5
commit 993532b604
3 changed files with 34 additions and 18 deletions

View File

@ -8,12 +8,18 @@ use std::ops::Bound::*;
use zebra_chain::types::BlockHeight; use zebra_chain::types::BlockHeight;
use zebra_chain::{Network, Network::*}; use zebra_chain::{Network, Network::*};
/// A Zcash network protocol upgrade. /// A Zcash network upgrade.
// ///
// TODO: are new network upgrades a breaking change, or should we make this /// Network upgrades can change the Zcash network protocol or consensus rules in
// enum non-exhaustive? /// incompatible ways.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum NetworkUpgrade { pub enum NetworkUpgrade {
/// The Zcash protocol for a Genesis block.
///
/// Zcash genesis blocks use a different set of consensus rules from
/// other BeforeOverwinter blocks, so we treat them like a separate network
/// upgrade.
Genesis,
/// The Zcash protocol before the Overwinter upgrade. /// The Zcash protocol before the Overwinter upgrade.
/// ///
/// We avoid using `Sprout`, because the specification says that Sprout /// We avoid using `Sprout`, because the specification says that Sprout
@ -36,7 +42,8 @@ pub enum NetworkUpgrade {
/// This is actually a bijective map, but it is const, so we use a vector, and /// This is actually a bijective map, but it is const, so we use a vector, and
/// do the uniqueness check in the unit tests. /// do the uniqueness check in the unit tests.
pub(crate) const MAINNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] = &[ pub(crate) const MAINNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] = &[
(BlockHeight(0), BeforeOverwinter), (BlockHeight(0), Genesis),
(BlockHeight(1), BeforeOverwinter),
(BlockHeight(347_500), Overwinter), (BlockHeight(347_500), Overwinter),
(BlockHeight(419_200), Sapling), (BlockHeight(419_200), Sapling),
(BlockHeight(653_600), Blossom), (BlockHeight(653_600), Blossom),
@ -49,7 +56,8 @@ pub(crate) const MAINNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] =
/// This is actually a bijective map, but it is const, so we use a vector, and /// This is actually a bijective map, but it is const, so we use a vector, and
/// do the uniqueness check in the unit tests. /// do the uniqueness check in the unit tests.
pub(crate) const TESTNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] = &[ pub(crate) const TESTNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] = &[
(BlockHeight(0), BeforeOverwinter), (BlockHeight(0), Genesis),
(BlockHeight(1), BeforeOverwinter),
(BlockHeight(207_500), Overwinter), (BlockHeight(207_500), Overwinter),
(BlockHeight(280_000), Sapling), (BlockHeight(280_000), Sapling),
(BlockHeight(584_000), Blossom), (BlockHeight(584_000), Blossom),
@ -68,8 +76,8 @@ pub struct ConsensusBranchId(u32);
/// Branch ids are the same for mainnet and testnet. If there is a testnet /// Branch ids are the same for mainnet and testnet. If there is a testnet
/// rollback after a bug, the branch id changes. /// rollback after a bug, the branch id changes.
/// ///
/// Branch ids were introduced in the Overwinter upgrade, so there is no /// Branch ids were introduced in the Overwinter upgrade, so there are no
/// BeforeOverwinter branch id. /// Genesis or BeforeOverwinter branch ids.
/// ///
/// This is actually a bijective map, but it is const, so we use a vector, and /// This is actually a bijective map, but it is const, so we use a vector, and
/// do the uniqueness check in the unit tests. /// do the uniqueness check in the unit tests.

View File

@ -39,21 +39,32 @@ fn activation_extremes_testnet() {
/// Test the activation_list, activation_height, current, and next functions /// Test the activation_list, activation_height, current, and next functions
/// for `network` with extreme values. /// for `network` with extreme values.
fn activation_extremes(network: Network) { fn activation_extremes(network: Network) {
// The first two upgrades are BeforeOverwinter and Overwinter // The first three upgrades are Genesis, BeforeOverwinter, and Overwinter
assert_eq!( assert_eq!(
NetworkUpgrade::activation_list(network).get(&BlockHeight(0)), 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) Some(&BeforeOverwinter)
); );
assert_eq!( assert_eq!(
BeforeOverwinter.activation_height(network), BeforeOverwinter.activation_height(network),
Some(BlockHeight(0)) Some(BlockHeight(1))
); );
assert_eq!( assert_eq!(
NetworkUpgrade::current(network, BlockHeight(0)), NetworkUpgrade::current(network, BlockHeight(1)),
BeforeOverwinter BeforeOverwinter
); );
assert_eq!( assert_eq!(
NetworkUpgrade::next(network, BlockHeight(0)), NetworkUpgrade::next(network, BlockHeight(1)),
Some(Overwinter) Some(Overwinter)
); );
@ -61,12 +72,9 @@ fn activation_extremes(network: Network) {
// (even if we suspect that won't be true) // (even if we suspect that won't be true)
assert_ne!( assert_ne!(
NetworkUpgrade::activation_list(network).get(&BlockHeight::MAX), NetworkUpgrade::activation_list(network).get(&BlockHeight::MAX),
Some(&BeforeOverwinter) Some(&Genesis)
);
assert_ne!(
NetworkUpgrade::current(network, BlockHeight::MAX),
BeforeOverwinter
); );
assert_ne!(NetworkUpgrade::current(network, BlockHeight::MAX), Genesis);
assert_eq!(NetworkUpgrade::next(network, BlockHeight::MAX), None); assert_eq!(NetworkUpgrade::next(network, BlockHeight::MAX), None);
} }

View File

@ -43,7 +43,7 @@ impl Version {
// TODO: Should we reject earlier protocol versions during our initial // TODO: Should we reject earlier protocol versions during our initial
// sync? zcashd accepts 170_002 or later during its initial sync. // sync? zcashd accepts 170_002 or later during its initial sync.
Version(match (network, network_upgrade) { Version(match (network, network_upgrade) {
(_, BeforeOverwinter) => 170_002, (_, Genesis) | (_, BeforeOverwinter) => 170_002,
(Testnet, Overwinter) => 170_003, (Testnet, Overwinter) => 170_003,
(Mainnet, Overwinter) => 170_005, (Mainnet, Overwinter) => 170_005,
(_, Sapling) => 170_007, (_, Sapling) => 170_007,