refactor: Move the checkpoint list tests to their own file
This commit is contained in:
parent
5b9703f95a
commit
e74ff18708
|
@ -5,6 +5,9 @@
|
||||||
//! Checkpoints can be used to verify their ancestors, by chaining backwards
|
//! Checkpoints can be used to verify their ancestors, by chaining backwards
|
||||||
//! to another checkpoint, via each block's parent block hash.
|
//! to another checkpoint, via each block's parent block hash.
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use crate::parameters;
|
use crate::parameters;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -171,274 +174,3 @@ impl CheckpointList {
|
||||||
self.0.range(range).map(|(height, _)| *height).next_back()
|
self.0.range(range).map(|(height, _)| *height).next_back()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use crate::parameters::NetworkUpgrade::Sapling;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use zebra_chain::{block::Block, serialization::ZcashDeserialize};
|
|
||||||
|
|
||||||
/// Make a checkpoint list containing only the genesis block
|
|
||||||
#[test]
|
|
||||||
fn checkpoint_list_genesis() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
// Parse the genesis block
|
|
||||||
let mut checkpoint_data = Vec::new();
|
|
||||||
let block =
|
|
||||||
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
|
||||||
let hash: BlockHeaderHash = block.as_ref().into();
|
|
||||||
checkpoint_data.push((
|
|
||||||
block.coinbase_height().expect("test block has height"),
|
|
||||||
hash,
|
|
||||||
));
|
|
||||||
|
|
||||||
// Make a checkpoint list containing the genesis block
|
|
||||||
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
|
||||||
checkpoint_data.iter().cloned().collect();
|
|
||||||
let _ = CheckpointList::from_list(checkpoint_list)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make a checkpoint list containing multiple blocks
|
|
||||||
#[test]
|
|
||||||
fn checkpoint_list_multiple() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
// 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)?;
|
|
||||||
let hash: BlockHeaderHash = block.as_ref().into();
|
|
||||||
checkpoint_data.push((
|
|
||||||
block.coinbase_height().expect("test block has height"),
|
|
||||||
hash,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a checkpoint list containing all the blocks
|
|
||||||
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
|
||||||
checkpoint_data.iter().cloned().collect();
|
|
||||||
let _ = CheckpointList::from_list(checkpoint_list)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make sure that an empty checkpoint list fails
|
|
||||||
#[test]
|
|
||||||
fn checkpoint_list_empty_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
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]
|
|
||||||
fn checkpoint_list_no_genesis_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
// Parse a non-genesis block
|
|
||||||
let mut checkpoint_data = Vec::new();
|
|
||||||
let block =
|
|
||||||
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])?;
|
|
||||||
let hash: BlockHeaderHash = block.as_ref().into();
|
|
||||||
checkpoint_data.push((
|
|
||||||
block.coinbase_height().expect("test block has height"),
|
|
||||||
hash,
|
|
||||||
));
|
|
||||||
|
|
||||||
// Make a checkpoint list containing the non-genesis block
|
|
||||||
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
|
||||||
checkpoint_data.iter().cloned().collect();
|
|
||||||
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]
|
|
||||||
fn checkpoint_list_null_hash_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
let checkpoint_data = vec![(BlockHeight(0), BlockHeaderHash([0; 32]))];
|
|
||||||
|
|
||||||
// Make a checkpoint list containing the non-genesis block
|
|
||||||
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
|
||||||
checkpoint_data.iter().cloned().collect();
|
|
||||||
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]
|
|
||||||
fn checkpoint_list_bad_height_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
let checkpoint_data = vec![(
|
|
||||||
BlockHeight(BlockHeight::MAX.0 + 1),
|
|
||||||
BlockHeaderHash([1; 32]),
|
|
||||||
)];
|
|
||||||
|
|
||||||
// Make a checkpoint list containing the non-genesis block
|
|
||||||
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
|
||||||
checkpoint_data.iter().cloned().collect();
|
|
||||||
let _ = CheckpointList::from_list(checkpoint_list).expect_err(
|
|
||||||
"a checkpoint list with an invalid block height (BlockHeight::MAX + 1) should fail",
|
|
||||||
);
|
|
||||||
|
|
||||||
let checkpoint_data = vec![(BlockHeight(u32::MAX), BlockHeaderHash([1; 32]))];
|
|
||||||
|
|
||||||
// Make a checkpoint list containing the non-genesis block
|
|
||||||
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
|
||||||
checkpoint_data.iter().cloned().collect();
|
|
||||||
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]
|
|
||||||
fn checkpoint_list_duplicate_blocks_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
// 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)?;
|
|
||||||
let hash: BlockHeaderHash = block.as_ref().into();
|
|
||||||
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]
|
|
||||||
fn checkpoint_list_duplicate_heights_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
// Parse the genesis block
|
|
||||||
let mut checkpoint_data = Vec::new();
|
|
||||||
for b in &[&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..]] {
|
|
||||||
let block = Arc::<Block>::zcash_deserialize(*b)?;
|
|
||||||
let hash: BlockHeaderHash = block.as_ref().into();
|
|
||||||
checkpoint_data.push((
|
|
||||||
block.coinbase_height().expect("test block has height"),
|
|
||||||
hash,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then add some fake entries with duplicate heights
|
|
||||||
checkpoint_data.push((BlockHeight(1), BlockHeaderHash([0xaa; 32])));
|
|
||||||
checkpoint_data.push((BlockHeight(1), BlockHeaderHash([0xbb; 32])));
|
|
||||||
|
|
||||||
// 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]
|
|
||||||
fn checkpoint_list_duplicate_hashes_fail() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
// Parse the genesis block
|
|
||||||
let mut checkpoint_data = Vec::new();
|
|
||||||
for b in &[&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..]] {
|
|
||||||
let block = Arc::<Block>::zcash_deserialize(*b)?;
|
|
||||||
let hash: BlockHeaderHash = block.as_ref().into();
|
|
||||||
checkpoint_data.push((
|
|
||||||
block.coinbase_height().expect("test block has height"),
|
|
||||||
hash,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then add some fake entries with duplicate hashes
|
|
||||||
checkpoint_data.push((BlockHeight(1), BlockHeaderHash([0xcc; 32])));
|
|
||||||
checkpoint_data.push((BlockHeight(2), BlockHeaderHash([0xcc; 32])));
|
|
||||||
|
|
||||||
// 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]
|
|
||||||
fn checkpoint_list_load_hard_coded() -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
let _ = CheckpointList::new(Mainnet);
|
|
||||||
let _ = CheckpointList::new(Testnet);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn checkpoint_list_hard_coded_sapling_mainnet() -> Result<(), Error> {
|
|
||||||
checkpoint_list_hard_coded_sapling(Mainnet)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn checkpoint_list_hard_coded_sapling_testnet() -> Result<(), Error> {
|
|
||||||
checkpoint_list_hard_coded_sapling(Testnet)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that the hard-coded lists cover the Sapling network upgrade
|
|
||||||
fn checkpoint_list_hard_coded_sapling(network: Network) -> Result<(), Error> {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
let sapling_activation = Sapling
|
|
||||||
.activation_height(network)
|
|
||||||
.expect("Unexpected network upgrade info: Sapling must have an activation height");
|
|
||||||
|
|
||||||
let list = CheckpointList::new(network);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
list.max_height() >= sapling_activation,
|
|
||||||
"Pre-Sapling blocks must be verified by checkpoints"
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,267 @@
|
||||||
|
//! Tests for CheckpointList
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::parameters::NetworkUpgrade::Sapling;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use zebra_chain::{block::Block, serialization::ZcashDeserialize};
|
||||||
|
|
||||||
|
/// Make a checkpoint list containing only the genesis block
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_list_genesis() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// Parse the genesis block
|
||||||
|
let mut checkpoint_data = Vec::new();
|
||||||
|
let block =
|
||||||
|
Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?;
|
||||||
|
let hash: BlockHeaderHash = block.as_ref().into();
|
||||||
|
checkpoint_data.push((
|
||||||
|
block.coinbase_height().expect("test block has height"),
|
||||||
|
hash,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make a checkpoint list containing the genesis block
|
||||||
|
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
||||||
|
checkpoint_data.iter().cloned().collect();
|
||||||
|
let _ = CheckpointList::from_list(checkpoint_list)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make a checkpoint list containing multiple blocks
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_list_multiple() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// 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)?;
|
||||||
|
let hash: BlockHeaderHash = block.as_ref().into();
|
||||||
|
checkpoint_data.push((
|
||||||
|
block.coinbase_height().expect("test block has height"),
|
||||||
|
hash,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a checkpoint list containing all the blocks
|
||||||
|
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
||||||
|
checkpoint_data.iter().cloned().collect();
|
||||||
|
let _ = CheckpointList::from_list(checkpoint_list)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure that an empty checkpoint list fails
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_list_empty_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
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]
|
||||||
|
fn checkpoint_list_no_genesis_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// Parse a non-genesis block
|
||||||
|
let mut checkpoint_data = Vec::new();
|
||||||
|
let block = Arc::<Block>::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])?;
|
||||||
|
let hash: BlockHeaderHash = block.as_ref().into();
|
||||||
|
checkpoint_data.push((
|
||||||
|
block.coinbase_height().expect("test block has height"),
|
||||||
|
hash,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make a checkpoint list containing the non-genesis block
|
||||||
|
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
||||||
|
checkpoint_data.iter().cloned().collect();
|
||||||
|
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]
|
||||||
|
fn checkpoint_list_null_hash_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
let checkpoint_data = vec![(BlockHeight(0), BlockHeaderHash([0; 32]))];
|
||||||
|
|
||||||
|
// Make a checkpoint list containing the non-genesis block
|
||||||
|
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
||||||
|
checkpoint_data.iter().cloned().collect();
|
||||||
|
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]
|
||||||
|
fn checkpoint_list_bad_height_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
let checkpoint_data = vec![(
|
||||||
|
BlockHeight(BlockHeight::MAX.0 + 1),
|
||||||
|
BlockHeaderHash([1; 32]),
|
||||||
|
)];
|
||||||
|
|
||||||
|
// Make a checkpoint list containing the non-genesis block
|
||||||
|
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
||||||
|
checkpoint_data.iter().cloned().collect();
|
||||||
|
let _ = CheckpointList::from_list(checkpoint_list).expect_err(
|
||||||
|
"a checkpoint list with an invalid block height (BlockHeight::MAX + 1) should fail",
|
||||||
|
);
|
||||||
|
|
||||||
|
let checkpoint_data = vec![(BlockHeight(u32::MAX), BlockHeaderHash([1; 32]))];
|
||||||
|
|
||||||
|
// Make a checkpoint list containing the non-genesis block
|
||||||
|
let checkpoint_list: BTreeMap<BlockHeight, BlockHeaderHash> =
|
||||||
|
checkpoint_data.iter().cloned().collect();
|
||||||
|
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]
|
||||||
|
fn checkpoint_list_duplicate_blocks_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// 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)?;
|
||||||
|
let hash: BlockHeaderHash = block.as_ref().into();
|
||||||
|
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]
|
||||||
|
fn checkpoint_list_duplicate_heights_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// Parse the genesis block
|
||||||
|
let mut checkpoint_data = Vec::new();
|
||||||
|
for b in &[&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..]] {
|
||||||
|
let block = Arc::<Block>::zcash_deserialize(*b)?;
|
||||||
|
let hash: BlockHeaderHash = block.as_ref().into();
|
||||||
|
checkpoint_data.push((
|
||||||
|
block.coinbase_height().expect("test block has height"),
|
||||||
|
hash,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add some fake entries with duplicate heights
|
||||||
|
checkpoint_data.push((BlockHeight(1), BlockHeaderHash([0xaa; 32])));
|
||||||
|
checkpoint_data.push((BlockHeight(1), BlockHeaderHash([0xbb; 32])));
|
||||||
|
|
||||||
|
// 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]
|
||||||
|
fn checkpoint_list_duplicate_hashes_fail() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
// Parse the genesis block
|
||||||
|
let mut checkpoint_data = Vec::new();
|
||||||
|
for b in &[&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..]] {
|
||||||
|
let block = Arc::<Block>::zcash_deserialize(*b)?;
|
||||||
|
let hash: BlockHeaderHash = block.as_ref().into();
|
||||||
|
checkpoint_data.push((
|
||||||
|
block.coinbase_height().expect("test block has height"),
|
||||||
|
hash,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add some fake entries with duplicate hashes
|
||||||
|
checkpoint_data.push((BlockHeight(1), BlockHeaderHash([0xcc; 32])));
|
||||||
|
checkpoint_data.push((BlockHeight(2), BlockHeaderHash([0xcc; 32])));
|
||||||
|
|
||||||
|
// 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]
|
||||||
|
fn checkpoint_list_load_hard_coded() -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
let _ = CheckpointList::new(Mainnet);
|
||||||
|
let _ = CheckpointList::new(Testnet);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_list_hard_coded_sapling_mainnet() -> Result<(), Error> {
|
||||||
|
checkpoint_list_hard_coded_sapling(Mainnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkpoint_list_hard_coded_sapling_testnet() -> Result<(), Error> {
|
||||||
|
checkpoint_list_hard_coded_sapling(Testnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check that the hard-coded lists cover the Sapling network upgrade
|
||||||
|
fn checkpoint_list_hard_coded_sapling(network: Network) -> Result<(), Error> {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
let sapling_activation = Sapling
|
||||||
|
.activation_height(network)
|
||||||
|
.expect("Unexpected network upgrade info: Sapling must have an activation height");
|
||||||
|
|
||||||
|
let list = CheckpointList::new(network);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
list.max_height() >= sapling_activation,
|
||||||
|
"Pre-Sapling blocks must be verified by checkpoints"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue