Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and use a function for mandatory checkpoint #2314

Merged
merged 5 commits into from
Jun 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = []
Comment on lines +63 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is ok, but it also needs an update to the GitHub workflows:
https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/regenerate-stateful-test-disks.yml#L68
https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/regenerate-stateful-test-disks.yml#L69
https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/test.yml#L72

If you're using fastmod, it skips hidden files and directories like .github by default.
You can use fastmod --hidden to change them as well, but you'll need fastmod version 0.4.2.

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 @@ -826,7 +823,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 @@ -839,7 +836,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 @@ -860,12 +857,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 @@ -876,48 +873,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