Add and use a function for mandatory checkpoint (#2314)

* add `mandatory_checkpoint_height()` function

* use mandatory checkpoint instead of canopy in acceptance tests
This commit is contained in:
Alfredo Garcia 2021-06-17 21:05:28 -03:00 committed by GitHub
parent 1cb10ec9e7
commit 544d182d25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 52 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
@ -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 {

View File

@ -20,7 +20,7 @@ use tracing::instrument;
use zebra_chain::{
block::{self, Block},
parameters::{Network, NetworkUpgrade::Canopy},
parameters::Network,
};
use zebra_state as zs;
@ -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")
};

View File

@ -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,
@ -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(())

View File

@ -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,
};
@ -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"
);

View File

@ -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 = []

View File

@ -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;
@ -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();
@ -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);
@ -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())
}
@ -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.