Skip to content

Commit

Permalink
feature: Add a "Genesis" network upgrade
Browse files Browse the repository at this point in the history
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 ZcashFoundation#682.
  • Loading branch information
teor2345 committed Jul 27, 2020
1 parent 5b3c6e4 commit ebc111c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 18 deletions.
24 changes: 16 additions & 8 deletions zebra-consensus/src/parameters/network_upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ use std::ops::Bound::*;
use zebra_chain::types::BlockHeight;
use zebra_chain::{Network, Network::*};

/// A Zcash network protocol upgrade.
//
// TODO: are new network upgrades a breaking change, or should we make this
// enum non-exhaustive?
/// A Zcash network upgrade.
///
/// Network upgrades can change the Zcash network protocol or consensus rules in
/// incompatible ways.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
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.
///
/// We avoid using `Sprout`, because the specification says that Sprout
Expand All @@ -36,7 +42,8 @@ pub enum NetworkUpgrade {
/// This is actually a bijective map, but it is const, so we use a vector, and
/// do the uniqueness check in the unit tests.
pub(crate) const MAINNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] = &[
(BlockHeight(0), BeforeOverwinter),
(BlockHeight(0), Genesis),
(BlockHeight(1), BeforeOverwinter),
(BlockHeight(347_500), Overwinter),
(BlockHeight(419_200), Sapling),
(BlockHeight(653_600), Blossom),
Expand All @@ -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
/// do the uniqueness check in the unit tests.
pub(crate) const TESTNET_ACTIVATION_HEIGHTS: &[(BlockHeight, NetworkUpgrade)] = &[
(BlockHeight(0), BeforeOverwinter),
(BlockHeight(0), Genesis),
(BlockHeight(1), BeforeOverwinter),
(BlockHeight(207_500), Overwinter),
(BlockHeight(280_000), Sapling),
(BlockHeight(584_000), Blossom),
Expand All @@ -68,8 +76,8 @@ pub struct ConsensusBranchId(u32);
/// Branch ids are the same for mainnet and testnet. If there is a testnet
/// rollback after a bug, the branch id changes.
///
/// Branch ids were introduced in the Overwinter upgrade, so there is no
/// BeforeOverwinter branch id.
/// Branch ids were introduced in the Overwinter upgrade, so there are no
/// Genesis or BeforeOverwinter branch ids.
///
/// This is actually a bijective map, but it is const, so we use a vector, and
/// do the uniqueness check in the unit tests.
Expand Down
26 changes: 17 additions & 9 deletions zebra-consensus/src/parameters/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,42 @@ fn activation_extremes_testnet() {
/// Test the activation_list, activation_height, current, and next functions
/// for `network` with extreme values.
fn activation_extremes(network: Network) {
// The first two upgrades are BeforeOverwinter and Overwinter
// The first three upgrades are Genesis, BeforeOverwinter, and Overwinter
assert_eq!(
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)
);
assert_eq!(
BeforeOverwinter.activation_height(network),
Some(BlockHeight(0))
Some(BlockHeight(1))
);
assert_eq!(
NetworkUpgrade::current(network, BlockHeight(0)),
NetworkUpgrade::current(network, BlockHeight(1)),
BeforeOverwinter
);
assert_eq!(
NetworkUpgrade::next(network, BlockHeight(0)),
NetworkUpgrade::next(network, BlockHeight(1)),
Some(Overwinter)
);

// 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(&BlockHeight::MAX),
Some(&BeforeOverwinter)
);
assert_ne!(
NetworkUpgrade::current(network, BlockHeight::MAX),
BeforeOverwinter
Some(&Genesis)
);
assert_ne!(NetworkUpgrade::current(network, BlockHeight::MAX), Genesis);
assert_eq!(NetworkUpgrade::next(network, BlockHeight::MAX), None);
}

Expand Down
2 changes: 1 addition & 1 deletion zebra-network/src/protocol/external/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl Version {
// TODO: Should we reject earlier protocol versions during our initial
// sync? zcashd accepts 170_002 or later during its initial sync.
Version(match (network, network_upgrade) {
(_, BeforeOverwinter) => 170_002,
(_, Genesis) | (_, BeforeOverwinter) => 170_002,
(Testnet, Overwinter) => 170_003,
(Mainnet, Overwinter) => 170_005,
(_, Sapling) => 170_007,
Expand Down

0 comments on commit ebc111c

Please sign in to comment.