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:
parent
5ece62f0a5
commit
993532b604
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue