2020-07-29 04:12:53 -07:00
|
|
|
//! Tests for CheckpointList
|
|
|
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
2023-04-26 16:35:53 -07:00
|
|
|
use num_integer::div_ceil;
|
|
|
|
|
2020-08-15 23:20:01 -07:00
|
|
|
use zebra_chain::{
|
2024-04-17 18:45:22 -07:00
|
|
|
block::{Block, HeightDiff, MAX_BLOCK_BYTES},
|
|
|
|
parameters::Network::*,
|
2020-08-15 23:20:01 -07:00
|
|
|
serialization::ZcashDeserialize,
|
|
|
|
};
|
2023-04-26 16:35:53 -07:00
|
|
|
use zebra_node_services::constants::{MAX_CHECKPOINT_BYTE_COUNT, MAX_CHECKPOINT_HEIGHT_GAP};
|
2020-07-29 04:12:53 -07:00
|
|
|
|
2023-03-29 16:06:31 -07:00
|
|
|
use super::*;
|
|
|
|
|
2020-07-29 04:12:53 -07:00
|
|
|
/// Make a checkpoint list containing only the genesis block
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_genesis() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Parse the genesis block
|
|
|
|
let mut checkpoint_data = Vec::new();
|
|
|
|
let block =
|
|
|
|
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
2020-08-15 23:20:01 -07:00
|
|
|
let hash = block.hash();
|
2020-07-29 04:12:53 -07:00
|
|
|
checkpoint_data.push((
|
|
|
|
block.coinbase_height().expect("test block has height"),
|
|
|
|
hash,
|
|
|
|
));
|
|
|
|
|
|
|
|
// Make a checkpoint list containing the genesis block
|
2020-08-16 11:42:02 -07:00
|
|
|
let checkpoint_list: BTreeMap<block::Height, block::Hash> =
|
2020-07-29 04:12:53 -07:00
|
|
|
checkpoint_data.iter().cloned().collect();
|
|
|
|
let _ = CheckpointList::from_list(checkpoint_list)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make a checkpoint list containing multiple blocks
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_multiple() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Parse all the blocks
|
|
|
|
let mut checkpoint_data = Vec::new();
|
|
|
|
for b in &[
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..],
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..],
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_415000_BYTES[..],
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_434873_BYTES[..],
|
|
|
|
] {
|
|
|
|
let block = Arc::<Block>::zcash_deserialize(*b)?;
|
2020-08-15 23:20:01 -07:00
|
|
|
let hash = block.hash();
|
2020-07-29 04:12:53 -07:00
|
|
|
checkpoint_data.push((
|
|
|
|
block.coinbase_height().expect("test block has height"),
|
|
|
|
hash,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make a checkpoint list containing all the blocks
|
2020-08-16 11:42:02 -07:00
|
|
|
let checkpoint_list: BTreeMap<block::Height, block::Hash> =
|
|
|
|
checkpoint_data.iter().cloned().collect();
|
2020-07-29 04:12:53 -07:00
|
|
|
let _ = CheckpointList::from_list(checkpoint_list)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure that an empty checkpoint list fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_empty_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
let _ = CheckpointList::from_list(Vec::new()).expect_err("empty checkpoint lists should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure a checkpoint list that doesn't contain the genesis block fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_no_genesis_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Parse a non-genesis block
|
|
|
|
let mut checkpoint_data = Vec::new();
|
|
|
|
let block = Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])?;
|
2020-08-15 23:20:01 -07:00
|
|
|
let hash = block.hash();
|
2020-07-29 04:12:53 -07:00
|
|
|
checkpoint_data.push((
|
|
|
|
block.coinbase_height().expect("test block has height"),
|
|
|
|
hash,
|
|
|
|
));
|
|
|
|
|
|
|
|
// Make a checkpoint list containing the non-genesis block
|
2020-08-16 11:42:02 -07:00
|
|
|
let checkpoint_list: BTreeMap<block::Height, block::Hash> =
|
|
|
|
checkpoint_data.iter().cloned().collect();
|
2020-07-29 04:12:53 -07:00
|
|
|
let _ = CheckpointList::from_list(checkpoint_list)
|
|
|
|
.expect_err("a checkpoint list with no genesis block should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure a checkpoint list that contains a null hash fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_null_hash_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
2023-07-05 00:11:27 -07:00
|
|
|
let checkpoint_data = [(block::Height(0), block::Hash([0; 32]))];
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Make a checkpoint list containing the non-genesis block
|
2020-08-16 11:42:02 -07:00
|
|
|
let checkpoint_list: BTreeMap<block::Height, block::Hash> =
|
|
|
|
checkpoint_data.iter().cloned().collect();
|
2020-07-29 04:12:53 -07:00
|
|
|
let _ = CheckpointList::from_list(checkpoint_list)
|
|
|
|
.expect_err("a checkpoint list with a null block hash should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure a checkpoint list that contains an invalid block height fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_bad_height_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
2023-07-05 00:11:27 -07:00
|
|
|
let checkpoint_data = [(
|
2020-08-16 11:42:02 -07:00
|
|
|
block::Height(block::Height::MAX.0 + 1),
|
|
|
|
block::Hash([1; 32]),
|
|
|
|
)];
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Make a checkpoint list containing the non-genesis block
|
2020-08-16 11:42:02 -07:00
|
|
|
let checkpoint_list: BTreeMap<block::Height, block::Hash> =
|
|
|
|
checkpoint_data.iter().cloned().collect();
|
2020-07-29 04:12:53 -07:00
|
|
|
let _ = CheckpointList::from_list(checkpoint_list).expect_err(
|
2020-08-16 11:42:02 -07:00
|
|
|
"a checkpoint list with an invalid block height (block::Height::MAX + 1) should fail",
|
2020-07-29 04:12:53 -07:00
|
|
|
);
|
|
|
|
|
2023-07-05 00:11:27 -07:00
|
|
|
let checkpoint_data = [(block::Height(u32::MAX), block::Hash([1; 32]))];
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Make a checkpoint list containing the non-genesis block
|
2020-08-16 11:42:02 -07:00
|
|
|
let checkpoint_list: BTreeMap<block::Height, block::Hash> =
|
|
|
|
checkpoint_data.iter().cloned().collect();
|
2020-07-29 04:12:53 -07:00
|
|
|
let _ = CheckpointList::from_list(checkpoint_list)
|
|
|
|
.expect_err("a checkpoint list with an invalid block height (u32::MAX) should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure that a checkpoint list containing duplicate blocks fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_duplicate_blocks_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Parse some blocks twice
|
|
|
|
let mut checkpoint_data = Vec::new();
|
|
|
|
for b in &[
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..],
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..],
|
|
|
|
&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..],
|
|
|
|
] {
|
|
|
|
let block = Arc::<Block>::zcash_deserialize(*b)?;
|
2020-08-15 23:20:01 -07:00
|
|
|
let hash = block.hash();
|
2020-07-29 04:12:53 -07:00
|
|
|
checkpoint_data.push((
|
|
|
|
block.coinbase_height().expect("test block has height"),
|
|
|
|
hash,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make a checkpoint list containing some duplicate blocks
|
|
|
|
let _ = CheckpointList::from_list(checkpoint_data)
|
|
|
|
.expect_err("checkpoint lists with duplicate blocks should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure that a checkpoint list containing duplicate heights
|
|
|
|
/// (with different hashes) fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_duplicate_heights_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Parse the genesis block
|
|
|
|
let mut checkpoint_data = Vec::new();
|
2022-02-15 08:31:36 -08:00
|
|
|
let block =
|
|
|
|
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
|
|
|
let hash = block.hash();
|
|
|
|
checkpoint_data.push((
|
|
|
|
block.coinbase_height().expect("test block has height"),
|
|
|
|
hash,
|
|
|
|
));
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Then add some fake entries with duplicate heights
|
2020-08-16 11:42:02 -07:00
|
|
|
checkpoint_data.push((block::Height(1), block::Hash([0xaa; 32])));
|
|
|
|
checkpoint_data.push((block::Height(1), block::Hash([0xbb; 32])));
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Make a checkpoint list containing some duplicate blocks
|
|
|
|
let _ = CheckpointList::from_list(checkpoint_data)
|
|
|
|
.expect_err("checkpoint lists with duplicate heights should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure that a checkpoint list containing duplicate hashes
|
|
|
|
/// (at different heights) fails
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_duplicate_hashes_fail() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Parse the genesis block
|
|
|
|
let mut checkpoint_data = Vec::new();
|
2022-02-15 08:31:36 -08:00
|
|
|
let block =
|
|
|
|
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
|
|
|
let hash = block.hash();
|
|
|
|
checkpoint_data.push((
|
|
|
|
block.coinbase_height().expect("test block has height"),
|
|
|
|
hash,
|
|
|
|
));
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Then add some fake entries with duplicate hashes
|
2020-08-16 11:42:02 -07:00
|
|
|
checkpoint_data.push((block::Height(1), block::Hash([0xcc; 32])));
|
|
|
|
checkpoint_data.push((block::Height(2), block::Hash([0xcc; 32])));
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
// Make a checkpoint list containing some duplicate blocks
|
|
|
|
let _ = CheckpointList::from_list(checkpoint_data)
|
|
|
|
.expect_err("checkpoint lists with duplicate hashes should fail");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse and check the hard-coded Mainnet and Testnet lists
|
|
|
|
#[test]
|
2020-09-21 11:54:06 -07:00
|
|
|
fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
let _: CheckpointList = MAINNET_CHECKPOINTS
|
|
|
|
.parse()
|
|
|
|
.expect("hard-coded Mainnet checkpoint list should parse");
|
|
|
|
let _: CheckpointList = TESTNET_CHECKPOINTS
|
|
|
|
.parse()
|
|
|
|
.expect("hard-coded Testnet checkpoint list should parse");
|
|
|
|
|
2024-03-12 14:41:44 -07:00
|
|
|
let _ = Mainnet.checkpoint_list();
|
2024-04-16 19:20:34 -07:00
|
|
|
let _ = Network::new_default_testnet().checkpoint_list();
|
add(consensus): Adds `disable_pow` and `genesis_hash` fields, converts `equihash::Solution` to an enum (#8421)
* minor cleanup and rename
* Adds an empty NetworkParameters struct to Network::Testnet variant, updates production code.
* Updates tests
* Adds `NetworkKind` and uses it instead of `Network` in `HistoryTreeParts` and `transparent::Address`
* Adds a [network.testnet_parameters] section to the config, uses `NetworkKind` as zebra_network::Config::network field type, and converts 'Network' to `NetworkKind` before serializing
* Applies some suggestions from code review
* Applies suggestions from code review
* returns b58 prefix constants directly to remove From<NetworkKind> impl for zcash_primitives::consensus::Network
* Applies more suggestions from code review.
* moves conversions to zcash_primitives::consensus::Network to where they're used.
* Apply suggestions from code review
Co-authored-by: Marek <mail@marek.onl>
* rename `network` variables and method names typed as NetworkKind to `network_kind`
* use only test block heights for the network associated with them
* Applies more suggestions from code review.
* Rename `NetworkParameters` to `Parameters` and move it a new `testnet` module
* adds activation heights field
* updates stored test config, adds a quicker test for checking that stored configs can be parsed, adds an intermediate representation of activation heights
* implement Parameters for Network
* Passes &Network directly instead of converting to zp_consensus::Network where there were conversions
* fixes a bad merge (removes a network conversion in zcash_note_encryption)
* Adds a test for the Parameters impl for zebra_chain::Network
* fixes doc links
* - Makes the `activation_heights` config field optional by adding a #[serde(default)]
- Panics if a non-zero activation height is provided for the `Genesis` network upgrade
- Always sets the `Genesis` and `BeforeOverwinter` network upgrade activation heights to 0 and 1, `BeforeOverwinter` could be overwritten by a later network upgrade
- Makes the `activation_heights` field on `Parameters` private, adds/uses an accessor method instead, and adds a builder struct and `build()` method
* small refactor of activation_heights() method
* check that activation heights are in the right order
* Updates `NetworkUpgrade::activation_height()` to return the height of the next NetworkUpgrade if it doesn't find the activation height of `&self`
* checks that the miner address is of TestnetKind on Regtest and update assertion message
* Adds a DNetworkUpgradeActivationHeights struct for better control over how activation heights can be configured
* moves all ordered network upgrades to a constant, adds a no_duplicates test, moves struct with activation heights outside deserialization impl and accepts it in `ParametersBuilder::activation_heights()` instead of a Vec
* panics if any network upgrades are configured to activate at Height(0) because it's reserved for Genesis
* Simplifies the `ParametersBuilder::activation_heights()` method and removes an unnecessary test.
* Adds Sapling HRPs as fields on testnet params. (#8398)
* Applies suggestions from code review.
* Update zebra-chain/src/parameters/network_upgrade.rs
Co-authored-by: Marek <mail@marek.onl>
* Adds `network_name` field and accessor method on `Parameters`, uses it in the `Display` impl for `Network`
* Removes unnecessary `.filter()`
* adds constraints on valid network names and a test
* adds config field for setting network name, adds "with_" prefix to ParameterBuilder setter methods
* Adds `MainnetKind`, `TestnetKind`, and `RegtestKind` to reserved network names
* updates stored test configs and fixes `network_name()` docs
* Adds a `new_regtest()` method on `Network` and `testnet::Parameters`, updates config deserialization to return an error if the initial_testnet_peers include any default initial peers AND contain configured activation heights
* Updates `activates_network_upgrades_correctly` test to check Regtest activation heights (and default Mainnet/Testnet)
* Refactors if-let & match statement into general match statement, removes constraint against including `testnet_parameters` field/section in the config when using `Mainnet` or `Regtest`
* Removes outdated TODO
* Restores `testnet_parameters` section of the latest stored config.
* Adds `with_sapling_hrps()` method and uses it to set the Regtest HRPs in `new_regtest()`.
Adds a test for Sapling HRP validation
* Checks that default Mainnet/Testnet/Regtest Sapling HRPs pass validation in `with_sapling_hrps()`
* Uses the correct constant in test
* Adds `is_regtest()` methods
* Adds genesis hash methods and fields to `testnet::Parameters` and its builder
* Copies Regtest genesis block from zcashd
* moves genesis hash check to Network.checkpoint_list()
* Checks the first line in the checkpoint list instead of the first item in the BTreeMap
* Checks that there is _some_ genesis block in the checkpoints list in `from_list()`, adds Regtest checkpoints (which only includes the genesis block)
* Adds a doc comment to `ParametersBuilder::default()`
* Adds a `disable_pow` field and skips checking proof of work if it's true
* Makes `equihash::Solution` an enum to support Regtest solutions, adds a test for validating and committing the Regtest genesis block
* use genesis_hash as first checkpoint when checkpoints are missing for configured testnets too
* Applies suggestions from code review.
* Reverts changes to `activation_height()` method
* Avoids panic in test
* Updates test docs
* drop custom panic hooks after expected panics
---------
Co-authored-by: Marek <mail@marek.onl>
2024-04-25 22:30:36 -07:00
|
|
|
let _ = Network::new_regtest(Default::default()).checkpoint_list();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2021-06-17 17:05:28 -07:00
|
|
|
fn checkpoint_list_hard_coded_mandatory_mainnet() -> Result<(), BoxError> {
|
|
|
|
checkpoint_list_hard_coded_mandatory(Mainnet)
|
2020-07-29 04:12:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2021-06-17 17:05:28 -07:00
|
|
|
fn checkpoint_list_hard_coded_mandatory_testnet() -> Result<(), BoxError> {
|
2024-04-16 19:20:34 -07:00
|
|
|
checkpoint_list_hard_coded_mandatory(Network::new_default_testnet())
|
2020-07-29 04:12:53 -07:00
|
|
|
}
|
|
|
|
|
2021-06-17 17:05:28 -07:00
|
|
|
/// Check that the hard-coded lists cover the mandatory checkpoint
|
|
|
|
fn checkpoint_list_hard_coded_mandatory(network: Network) -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
2021-06-17 17:05:28 -07:00
|
|
|
let mandatory_checkpoint = network.mandatory_checkpoint_height();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
2024-03-12 14:41:44 -07:00
|
|
|
let list = network.checkpoint_list();
|
2020-07-29 04:12:53 -07:00
|
|
|
|
|
|
|
assert!(
|
2021-06-17 17:05:28 -07:00
|
|
|
list.max_height() >= mandatory_checkpoint,
|
|
|
|
"Mandatory checkpoint block must be verified by checkpoints"
|
2020-07-29 04:12:53 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-10-25 21:42:11 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn checkpoint_list_hard_coded_max_gap_mainnet() -> Result<(), BoxError> {
|
|
|
|
checkpoint_list_hard_coded_max_gap(Mainnet)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn checkpoint_list_hard_coded_max_gap_testnet() -> Result<(), BoxError> {
|
2024-04-16 19:20:34 -07:00
|
|
|
checkpoint_list_hard_coded_max_gap(Network::new_default_testnet())
|
2020-10-25 21:42:11 -07:00
|
|
|
}
|
|
|
|
|
2023-04-26 16:35:53 -07:00
|
|
|
/// Check that the hard-coded checkpoints are within [`MAX_CHECKPOINT_HEIGHT_GAP`],
|
|
|
|
/// and a calculated minimum number of blocks. This also checks the heights are in order.
|
2020-10-25 21:42:11 -07:00
|
|
|
///
|
2023-04-27 19:26:13 -07:00
|
|
|
/// We can't test [`MAX_CHECKPOINT_BYTE_COUNT`] directly, because we don't have access to a large
|
|
|
|
/// enough blockchain in the tests. Instead, we check the number of maximum-size blocks in a
|
2023-04-26 16:35:53 -07:00
|
|
|
/// checkpoint. (This is ok, because the byte count only impacts performance.)
|
2020-10-25 21:42:11 -07:00
|
|
|
fn checkpoint_list_hard_coded_max_gap(network: Network) -> Result<(), BoxError> {
|
2022-08-04 08:44:44 -07:00
|
|
|
let _init_guard = zebra_test::init();
|
2020-10-25 21:42:11 -07:00
|
|
|
|
2023-04-26 16:35:53 -07:00
|
|
|
let max_checkpoint_height_gap =
|
|
|
|
HeightDiff::try_from(MAX_CHECKPOINT_HEIGHT_GAP).expect("constant fits in HeightDiff");
|
|
|
|
let min_checkpoint_height_gap =
|
|
|
|
HeightDiff::try_from(div_ceil(MAX_CHECKPOINT_BYTE_COUNT, MAX_BLOCK_BYTES))
|
|
|
|
.expect("constant fits in HeightDiff");
|
|
|
|
|
2024-03-12 14:41:44 -07:00
|
|
|
let list = network.checkpoint_list();
|
2020-10-25 21:42:11 -07:00
|
|
|
let mut heights = list.0.keys();
|
|
|
|
|
|
|
|
// Check that we start at the genesis height
|
|
|
|
let mut previous_height = block::Height(0);
|
|
|
|
assert_eq!(heights.next(), Some(&previous_height));
|
|
|
|
|
|
|
|
for height in heights {
|
2023-04-26 16:35:53 -07:00
|
|
|
let height_upper_limit = (previous_height + max_checkpoint_height_gap)
|
|
|
|
.expect("checkpoint heights are valid blockchain heights");
|
|
|
|
|
|
|
|
let height_lower_limit = (previous_height + min_checkpoint_height_gap)
|
|
|
|
.expect("checkpoint heights are valid blockchain heights");
|
|
|
|
|
2020-10-25 21:42:11 -07:00
|
|
|
assert!(
|
2023-04-26 16:35:53 -07:00
|
|
|
height <= &height_upper_limit,
|
|
|
|
"Checkpoint gaps must be MAX_CHECKPOINT_HEIGHT_GAP or less \
|
|
|
|
actually: {height:?} - {previous_height:?} = {} \
|
|
|
|
should be: less than or equal to {max_checkpoint_height_gap}",
|
|
|
|
*height - previous_height,
|
2020-10-25 21:42:11 -07:00
|
|
|
);
|
2023-04-26 16:35:53 -07:00
|
|
|
assert!(
|
|
|
|
height >= &height_lower_limit,
|
|
|
|
"Checkpoint gaps must be ceil(MAX_CHECKPOINT_BYTE_COUNT/MAX_BLOCK_BYTES) or greater \
|
|
|
|
actually: {height:?} - {previous_height:?} = {} \
|
|
|
|
should be: greater than or equal to {min_checkpoint_height_gap}",
|
|
|
|
*height - previous_height,
|
|
|
|
);
|
|
|
|
|
2020-10-25 21:42:11 -07:00
|
|
|
previous_height = *height;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|