panic in `NonFinalizedState::commit_block` before Canopy (#1909)
* add a panic in commit_block() for blocks before canopy * update tests to use a post canopy block and network Co-authored-by: teor <teor@riseup.net>
This commit is contained in:
parent
d49eaab68e
commit
9e1662d2d7
|
@ -64,7 +64,10 @@ impl StateService {
|
||||||
|
|
||||||
pub fn new(config: Config, network: Network) -> Self {
|
pub fn new(config: Config, network: Network) -> Self {
|
||||||
let disk = FinalizedState::new(&config, network);
|
let disk = FinalizedState::new(&config, network);
|
||||||
let mem = NonFinalizedState::default();
|
let mem = NonFinalizedState {
|
||||||
|
network,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
let queued_blocks = QueuedBlocks::default();
|
let queued_blocks = QueuedBlocks::default();
|
||||||
let pending_utxos = PendingUtxos::default();
|
let pending_utxos = PendingUtxos::default();
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ use std::{collections::BTreeSet, mem, ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
block::{self, Block},
|
block::{self, Block},
|
||||||
|
parameters::{Network, NetworkUpgrade::Canopy},
|
||||||
transaction::{self, Transaction},
|
transaction::{self, Transaction},
|
||||||
transparent,
|
transparent,
|
||||||
};
|
};
|
||||||
|
@ -25,7 +26,9 @@ pub struct NonFinalizedState {
|
||||||
/// Verified, non-finalized chains, in ascending order.
|
/// Verified, non-finalized chains, in ascending order.
|
||||||
///
|
///
|
||||||
/// The best chain is `chain_set.last()` or `chain_set.iter().next_back()`.
|
/// The best chain is `chain_set.last()` or `chain_set.iter().next_back()`.
|
||||||
chain_set: BTreeSet<Box<Chain>>,
|
pub chain_set: BTreeSet<Box<Chain>>,
|
||||||
|
/// The configured Zcash network
|
||||||
|
pub network: Network,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonFinalizedState {
|
impl NonFinalizedState {
|
||||||
|
@ -70,6 +73,14 @@ impl NonFinalizedState {
|
||||||
/// Commit block to the non-finalized state.
|
/// Commit block to the non-finalized state.
|
||||||
pub fn commit_block(&mut self, prepared: PreparedBlock) {
|
pub fn commit_block(&mut self, prepared: PreparedBlock) {
|
||||||
let parent_hash = prepared.block.header.previous_block_hash;
|
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 {
|
||||||
|
panic!(
|
||||||
|
"invalid non-finalized block height: the canopy checkpoint is mandatory, pre-canopy blocks must be committed to the state as finalized blocks"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut parent_chain = self
|
let mut parent_chain = self
|
||||||
.take_chain_if(|chain| chain.non_finalized_tip_hash() == parent_hash)
|
.take_chain_if(|chain| chain.non_finalized_tip_hash() == parent_hash)
|
||||||
|
@ -81,7 +92,6 @@ impl NonFinalizedState {
|
||||||
})
|
})
|
||||||
.expect("commit_block is only called with blocks that are ready to be commited");
|
.expect("commit_block is only called with blocks that are ready to be commited");
|
||||||
|
|
||||||
let (height, hash) = (prepared.height, prepared.hash);
|
|
||||||
parent_chain.push(prepared);
|
parent_chain.push(prepared);
|
||||||
self.chain_set.insert(parent_chain);
|
self.chain_set.insert(parent_chain);
|
||||||
self.update_metrics_for_committed_block(height, hash);
|
self.update_metrics_for_committed_block(height, hash);
|
||||||
|
@ -276,8 +286,22 @@ mod tests {
|
||||||
fn best_chain_wins() -> Result<()> {
|
fn best_chain_wins() -> Result<()> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let block1: Arc<Block> =
|
best_chain_wins_for_network(Network::Mainnet)?;
|
||||||
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
|
best_chain_wins_for_network(Network::Testnet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn best_chain_wins_for_network(network: Network) -> Result<()> {
|
||||||
|
let block1: Arc<Block> = match network {
|
||||||
|
Network::Mainnet => {
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_1180900_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
Network::Testnet => {
|
||||||
|
zebra_test::vectors::BLOCK_TESTNET_1326100_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let block2 = block1.make_fake_child().set_work(10);
|
let block2 = block1.make_fake_child().set_work(10);
|
||||||
let child = block1.make_fake_child().set_work(1);
|
let child = block1.make_fake_child().set_work(1);
|
||||||
|
|
||||||
|
@ -297,8 +321,22 @@ mod tests {
|
||||||
fn finalize_pops_from_best_chain() -> Result<()> {
|
fn finalize_pops_from_best_chain() -> Result<()> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let block1: Arc<Block> =
|
finalize_pops_from_best_chain_for_network(Network::Mainnet)?;
|
||||||
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
|
finalize_pops_from_best_chain_for_network(Network::Testnet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize_pops_from_best_chain_for_network(network: Network) -> Result<()> {
|
||||||
|
let block1: Arc<Block> = match network {
|
||||||
|
Network::Mainnet => {
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_1180900_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
Network::Testnet => {
|
||||||
|
zebra_test::vectors::BLOCK_TESTNET_1326100_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let block2 = block1.make_fake_child().set_work(10);
|
let block2 = block1.make_fake_child().set_work(10);
|
||||||
let child = block1.make_fake_child().set_work(1);
|
let child = block1.make_fake_child().set_work(1);
|
||||||
|
|
||||||
|
@ -323,8 +361,24 @@ mod tests {
|
||||||
fn commit_block_extending_best_chain_doesnt_drop_worst_chains() -> Result<()> {
|
fn commit_block_extending_best_chain_doesnt_drop_worst_chains() -> Result<()> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let block1: Arc<Block> =
|
commit_block_extending_best_chain_doesnt_drop_worst_chains_for_network(Network::Mainnet)?;
|
||||||
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
|
commit_block_extending_best_chain_doesnt_drop_worst_chains_for_network(Network::Testnet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit_block_extending_best_chain_doesnt_drop_worst_chains_for_network(
|
||||||
|
network: Network,
|
||||||
|
) -> Result<()> {
|
||||||
|
let block1: Arc<Block> = match network {
|
||||||
|
Network::Mainnet => {
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_1180900_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
Network::Testnet => {
|
||||||
|
zebra_test::vectors::BLOCK_TESTNET_1326100_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let block2 = block1.make_fake_child().set_work(10);
|
let block2 = block1.make_fake_child().set_work(10);
|
||||||
let child1 = block1.make_fake_child().set_work(1);
|
let child1 = block1.make_fake_child().set_work(1);
|
||||||
let child2 = block2.make_fake_child().set_work(1);
|
let child2 = block2.make_fake_child().set_work(1);
|
||||||
|
@ -347,8 +401,21 @@ mod tests {
|
||||||
fn shorter_chain_can_be_best_chain() -> Result<()> {
|
fn shorter_chain_can_be_best_chain() -> Result<()> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let block1: Arc<Block> =
|
shorter_chain_can_be_best_chain_for_network(Network::Mainnet)?;
|
||||||
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
|
shorter_chain_can_be_best_chain_for_network(Network::Testnet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shorter_chain_can_be_best_chain_for_network(network: Network) -> Result<()> {
|
||||||
|
let block1: Arc<Block> = match network {
|
||||||
|
Network::Mainnet => {
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_1180900_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
Network::Testnet => {
|
||||||
|
zebra_test::vectors::BLOCK_TESTNET_1326100_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let long_chain_block1 = block1.make_fake_child().set_work(1);
|
let long_chain_block1 = block1.make_fake_child().set_work(1);
|
||||||
let long_chain_block2 = long_chain_block1.make_fake_child().set_work(1);
|
let long_chain_block2 = long_chain_block1.make_fake_child().set_work(1);
|
||||||
|
@ -371,8 +438,21 @@ mod tests {
|
||||||
fn longer_chain_with_more_work_wins() -> Result<()> {
|
fn longer_chain_with_more_work_wins() -> Result<()> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let block1: Arc<Block> =
|
longer_chain_with_more_work_wins_for_network(Network::Mainnet)?;
|
||||||
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
|
longer_chain_with_more_work_wins_for_network(Network::Testnet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn longer_chain_with_more_work_wins_for_network(network: Network) -> Result<()> {
|
||||||
|
let block1: Arc<Block> = match network {
|
||||||
|
Network::Mainnet => {
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_1180900_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
Network::Testnet => {
|
||||||
|
zebra_test::vectors::BLOCK_TESTNET_1326100_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let long_chain_block1 = block1.make_fake_child().set_work(1);
|
let long_chain_block1 = block1.make_fake_child().set_work(1);
|
||||||
let long_chain_block2 = long_chain_block1.make_fake_child().set_work(1);
|
let long_chain_block2 = long_chain_block1.make_fake_child().set_work(1);
|
||||||
|
@ -399,8 +479,20 @@ mod tests {
|
||||||
fn equal_length_goes_to_more_work() -> Result<()> {
|
fn equal_length_goes_to_more_work() -> Result<()> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let block1: Arc<Block> =
|
equal_length_goes_to_more_work_for_network(Network::Mainnet)?;
|
||||||
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
|
equal_length_goes_to_more_work_for_network(Network::Testnet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn equal_length_goes_to_more_work_for_network(network: Network) -> Result<()> {
|
||||||
|
let block1: Arc<Block> = match network {
|
||||||
|
Network::Mainnet => {
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_1180900_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
Network::Testnet => {
|
||||||
|
zebra_test::vectors::BLOCK_TESTNET_1326100_BYTES.zcash_deserialize_into()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let less_work_child = block1.make_fake_child().set_work(1);
|
let less_work_child = block1.make_fake_child().set_work(1);
|
||||||
let more_work_child = block1.make_fake_child().set_work(3);
|
let more_work_child = block1.make_fake_child().set_work(3);
|
||||||
|
|
Loading…
Reference in New Issue