Skip to content

Commit

Permalink
Add and use a function for mandatory checkpoint (#2314)
Browse files Browse the repository at this point in the history
* add `mandatory_checkpoint_height()` function

* use mandatory checkpoint instead of canopy in acceptance tests
  • Loading branch information
oxarbitrage authored Jun 18, 2021
1 parent 1cb10ec commit 544d182
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 52 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/regenerate-stateful-test-disks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ jobs:
"git clone -b $BRANCH_NAME https://github.com/ZcashFoundation/zebra.git;
cd zebra/;
docker build --build-arg SHORT_SHA=$SHORT_SHA -f docker/Dockerfile.test -t zebrad-test .;
docker run -i --mount type=bind,source=/mnt/disks/gce-containers-mounts/gce-persistent-disks/zebrad-cache-$SHORT_SHA-mainnet-1046400,target=/zebrad-cache zebrad-test:latest cargo test --verbose --features test_sync_past_canopy_mainnet --manifest-path zebrad/Cargo.toml sync_past_canopy_mainnet;
docker run -i --mount type=bind,source=/mnt/disks/gce-containers-mounts/gce-persistent-disks/zebrad-cache-$SHORT_SHA-testnet-1028500,target=/zebrad-cache zebrad-test:latest cargo test --verbose --features test_sync_past_canopy_testnet --manifest-path zebrad/Cargo.toml sync_past_canopy_testnet;
docker run -i --mount type=bind,source=/mnt/disks/gce-containers-mounts/gce-persistent-disks/zebrad-cache-$SHORT_SHA-mainnet-1046400,target=/zebrad-cache zebrad-test:latest cargo test --verbose --features test_sync_past_mandatory_checkpoint_mainnet --manifest-path zebrad/Cargo.toml sync_past_canopy_mainnet;
docker run -i --mount type=bind,source=/mnt/disks/gce-containers-mounts/gce-persistent-disks/zebrad-cache-$SHORT_SHA-testnet-1028500,target=/zebrad-cache zebrad-test:latest cargo test --verbose --features test_sync_past_mandatory_checkpoint_testnet --manifest-path zebrad/Cargo.toml sync_past_canopy_testnet;
"
# Clean up
- name: Delete test instance
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
cd zebra/;
docker build --build-arg SHORT_SHA=$SHORT_SHA -f docker/Dockerfile.test -t zebrad-test .;
docker run -i zebrad-test cargo test --workspace --no-fail-fast -- -Zunstable-options --include-ignored;
docker run -i --mount type=bind,source=/mnt/disks/gce-containers-mounts/gce-persistent-disks/zebrad-cache-$SHORT_SHA-mainnet-1046400,target=/zebrad-cache zebrad-test:latest cargo test --verbose --features test_sync_past_canopy_mainnet --manifest-path zebrad/Cargo.toml sync_past_canopy_mainnet;
docker run -i --mount type=bind,source=/mnt/disks/gce-containers-mounts/gce-persistent-disks/zebrad-cache-$SHORT_SHA-mainnet-1046400,target=/zebrad-cache zebrad-test:latest cargo test --verbose --features test_sync_past_mandatory_checkpoint_mainnet --manifest-path zebrad/Cargo.toml sync_past_canopy_mainnet;
"
# Clean up
- name: Delete test instance
Expand Down
14 changes: 14 additions & 0 deletions zebra-chain/src/parameters/network.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::{convert::From, fmt};

use crate::{block::Height, parameters::NetworkUpgrade::Canopy};

#[cfg(any(test, feature = "proptest-impl"))]
use proptest_derive::Arbitrary;

Expand Down Expand Up @@ -42,6 +44,18 @@ impl Network {
Network::Testnet => 18233,
}
}

/// Get the mandatory minimum checkpoint height for this 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.
pub fn mandatory_checkpoint_height(&self) -> Height {
// Currently this is the Canopy activation height for both networks.
Canopy
.activation_height(*self)
.expect("Canopy activation height must be present for both networks")
}
}

impl Default for Network {
Expand Down
4 changes: 2 additions & 2 deletions zebra-consensus/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use tracing::instrument;

use zebra_chain::{
block::{self, Block},
parameters::{Network, NetworkUpgrade::Canopy},
parameters::Network,
};

use zebra_state as zs;
Expand Down Expand Up @@ -147,7 +147,7 @@ where
let max_checkpoint_height = if config.checkpoint_sync {
list.max_height()
} else {
list.min_height_in_range(Canopy.activation_height(network).unwrap()..)
list.min_height_in_range(network.mandatory_checkpoint_height()..)
.expect("hardcoded checkpoint list extends past canopy activation")
};

Expand Down
23 changes: 10 additions & 13 deletions zebra-consensus/src/checkpoint/list/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::*;

use std::sync::Arc;

use zebra_chain::parameters::{Network, Network::*, NetworkUpgrade::*};
use zebra_chain::parameters::{Network, Network::*};
use zebra_chain::{
block::{self, Block},
serialization::ZcashDeserialize,
Expand Down Expand Up @@ -241,29 +241,26 @@ fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> {
}

#[test]
fn checkpoint_list_hard_coded_canopy_mainnet() -> Result<(), BoxError> {
checkpoint_list_hard_coded_canopy(Mainnet)
fn checkpoint_list_hard_coded_mandatory_mainnet() -> Result<(), BoxError> {
checkpoint_list_hard_coded_mandatory(Mainnet)
}

#[test]
fn checkpoint_list_hard_coded_canopy_testnet() -> Result<(), BoxError> {
checkpoint_list_hard_coded_canopy(Testnet)
fn checkpoint_list_hard_coded_mandatory_testnet() -> Result<(), BoxError> {
checkpoint_list_hard_coded_mandatory(Testnet)
}

/// Check that the hard-coded lists cover the Canopy network upgrade, and the
/// Canopy activation block
fn checkpoint_list_hard_coded_canopy(network: Network) -> Result<(), BoxError> {
/// Check that the hard-coded lists cover the mandatory checkpoint
fn checkpoint_list_hard_coded_mandatory(network: Network) -> Result<(), BoxError> {
zebra_test::init();

let canopy_activation = Canopy
.activation_height(network)
.expect("Unexpected network upgrade info: Canopy must have an activation height");
let mandatory_checkpoint = network.mandatory_checkpoint_height();

let list = CheckpointList::new(network);

assert!(
list.max_height() >= canopy_activation,
"Pre-Canopy blocks and the Canopy activation block must be verified by checkpoints"
list.max_height() >= mandatory_checkpoint,
"Mandatory checkpoint block must be verified by checkpoints"
);

Ok(())
Expand Down
6 changes: 3 additions & 3 deletions zebra-state/src/service/non_finalized_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{collections::BTreeSet, mem, ops::Deref, sync::Arc};

use zebra_chain::{
block::{self, Block},
parameters::{Network, NetworkUpgrade::Canopy},
parameters::Network,
transaction::{self, Transaction},
transparent,
};
Expand Down Expand Up @@ -80,8 +80,8 @@ impl NonFinalizedState {
let parent_hash = prepared.block.header.previous_block_hash;
let (height, hash) = (prepared.height, prepared.hash);

let canopy_activation_height = Canopy.activation_height(self.network).unwrap();
if height <= canopy_activation_height {
let mandatory_checkpoint = self.network.mandatory_checkpoint_height();
if height <= mandatory_checkpoint {
panic!(
"invalid non-finalized block height: the canopy checkpoint is mandatory, pre-canopy blocks, and the canopy activation block, must be committed to the state as finalized blocks"
);
Expand Down
8 changes: 4 additions & 4 deletions zebrad/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ zebra-test = { path = "../zebra-test" }

[features]
enable-sentry = []
test_sync_to_canopy_mainnet = []
test_sync_to_canopy_testnet = []
test_sync_past_canopy_mainnet = []
test_sync_past_canopy_testnet = []
test_sync_to_mandatory_checkpoint_mainnet = []
test_sync_to_mandatory_checkpoint_testnet = []
test_sync_past_mandatory_checkpoint_mainnet = []
test_sync_past_mandatory_checkpoint_testnet = []
51 changes: 24 additions & 27 deletions zebrad/tests/acceptance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ use std::{collections::HashSet, convert::TryInto, env, path::Path, path::PathBuf

use zebra_chain::{
block::Height,
parameters::{
Network::{self, *},
NetworkUpgrade,
},
parameters::Network::{self, *},
};
use zebra_network::constants::PORT_IN_USE_ERROR;
use zebra_state::constants::LOCK_FILE_ERROR;
Expand Down Expand Up @@ -835,7 +832,7 @@ fn sync_until(
Ok(child.dir)
}

fn cached_canopy_test_config() -> Result<ZebradConfig> {
fn cached_mandatory_checkpoint_test_config() -> Result<ZebradConfig> {
let mut config = persistent_test_config()?;
config.consensus.checkpoint_sync = true;
config.state.cache_dir = "/zebrad-cache".into();
Expand All @@ -848,7 +845,7 @@ fn create_cached_database_height(network: Network, height: Height) -> Result<()>
let timeout = Duration::from_secs(60 * 60 * 8);

// Use a persistent state, so we can handle large syncs
let mut config = cached_canopy_test_config()?;
let mut config = cached_mandatory_checkpoint_test_config()?;
// TODO: add convenience methods?
config.network.network = network;
config.state.debug_stop_at_height = Some(height.0);
Expand All @@ -869,12 +866,12 @@ fn create_cached_database_height(network: Network, height: Height) -> Result<()>
}

fn create_cached_database(network: Network) -> Result<()> {
let height = NetworkUpgrade::Canopy.activation_height(network).unwrap();
let height = network.mandatory_checkpoint_height();
create_cached_database_height(network, height)
}

fn sync_past_canopy(network: Network) -> Result<()> {
let height = NetworkUpgrade::Canopy.activation_height(network).unwrap() + 1200;
fn sync_past_mandatory_checkpoint(network: Network) -> Result<()> {
let height = network.mandatory_checkpoint_height() + 1200;
create_cached_database_height(network, height.unwrap())
}

Expand All @@ -885,48 +882,48 @@ fn sync_past_canopy(network: Network) -> Result<()> {
// drives populated by the first two tests, snapshot those drives, and then use
// those to more quickly run the second two tests.

/// Sync up to the canopy activation height on mainnet and stop.
/// Sync up to the mandatory checkpoint height on mainnet and stop.
#[allow(dead_code)]
#[cfg_attr(feature = "test_sync_to_canopy_mainnet", test)]
fn sync_to_canopy_mainnet() {
#[cfg_attr(feature = "test_sync_to_mandatory_checkpoint_mainnet", test)]
fn sync_to_mandatory_checkpoint_mainnet() {
zebra_test::init();
let network = Mainnet;
create_cached_database(network).unwrap();
}

/// Sync to the canopy activation height testnet and stop.
/// Sync to the mandatory checkpoint height testnet and stop.
#[allow(dead_code)]
#[cfg_attr(feature = "test_sync_to_canopy_testnet", test)]
fn sync_to_canopy_testnet() {
#[cfg_attr(feature = "test_sync_to_mandatory_checkpoint_testnet", test)]
fn sync_to_mandatory_checkpoint_testnet() {
zebra_test::init();
let network = Testnet;
create_cached_database(network).unwrap();
}

/// Test syncing 1200 blocks (3 checkpoints) past the last checkpoint on mainnet.
/// Test syncing 1200 blocks (3 checkpoints) past the mandatory checkpoint on mainnet.
///
/// This assumes that the config'd state is already synced at or near Canopy
/// activation on mainnet. If the state has already synced past Canopy
/// This assumes that the config'd state is already synced at or near the mandatory checkpoint
/// activation on mainnet. If the state has already synced past the mandatory checkpoint
/// activation by 1200 blocks, it will fail.
#[allow(dead_code)]
#[cfg_attr(feature = "test_sync_past_canopy_mainnet", test)]
fn sync_past_canopy_mainnet() {
#[cfg_attr(feature = "test_sync_past_mandatory_checkpoint_mainnet", test)]
fn sync_past_mandatory_checkpoint_mainnet() {
zebra_test::init();
let network = Mainnet;
sync_past_canopy(network).unwrap();
sync_past_mandatory_checkpoint(network).unwrap();
}

/// Test syncing 1200 blocks (3 checkpoints) past the last checkpoint on testnet.
/// Test syncing 1200 blocks (3 checkpoints) past the mandatory checkpoint on testnet.
///
/// This assumes that the config'd state is already synced at or near Canopy
/// activation on testnet. If the state has already synced past Canopy
/// This assumes that the config'd state is already synced at or near the mandatory checkpoint
/// activation on testnet. If the state has already synced past the mandatory checkpoint
/// activation by 1200 blocks, it will fail.
#[allow(dead_code)]
#[cfg_attr(feature = "test_sync_past_canopy_testnet", test)]
fn sync_past_canopy_testnet() {
#[cfg_attr(feature = "test_sync_past_mandatory_checkpoint_testnet", test)]
fn sync_past_mandatory_checkpoint_testnet() {
zebra_test::init();
let network = Testnet;
sync_past_canopy(network).unwrap();
sync_past_mandatory_checkpoint(network).unwrap();
}

/// Returns a random port number from the ephemeral port range.
Expand Down

0 comments on commit 544d182

Please sign in to comment.