use std::sync::Arc; use chrono::{DateTime, Utc}; use thiserror::Error; use zebra_chain::{ block::{self, ChainHistoryMmrRootHash}, history_tree::HistoryTreeError, work::difficulty::CompactDifficulty, }; /// A wrapper for type erased errors that is itself clonable and implements the /// Error trait #[derive(Debug, Error, Clone)] #[error(transparent)] pub struct CloneError { source: Arc, } impl From for CloneError { fn from(source: CommitBlockError) -> Self { let source = Arc::new(source); Self { source } } } impl From for CloneError { fn from(source: BoxError) -> Self { let source = Arc::from(source); Self { source } } } /// A boxed [`std::error::Error`]. pub type BoxError = Box; /// An error describing the reason a block could not be committed to the state. #[derive(Debug, Error)] #[error("block is not contextually valid")] pub struct CommitBlockError(#[from] ValidateContextError); /// An error describing why a block failed contextual validation. #[derive(Debug, Error)] #[non_exhaustive] #[allow(missing_docs)] pub enum ValidateContextError { #[error("block height {candidate_height:?} is lower than the current finalized height {finalized_tip_height:?}")] #[non_exhaustive] OrphanedBlock { candidate_height: block::Height, finalized_tip_height: block::Height, }, #[error("block height {candidate_height:?} is not one greater than its parent block's height {parent_height:?}")] #[non_exhaustive] NonSequentialBlock { candidate_height: block::Height, parent_height: block::Height, }, #[error("block time {candidate_time:?} is less than or equal to the median-time-past for the block {median_time_past:?}")] #[non_exhaustive] TimeTooEarly { candidate_time: DateTime, median_time_past: DateTime, }, #[error("block time {candidate_time:?} is greater than the median-time-past for the block plus 90 minutes {block_time_max:?}")] #[non_exhaustive] TimeTooLate { candidate_time: DateTime, block_time_max: DateTime, }, #[error("block difficulty threshold {difficulty_threshold:?} is not equal to the expected difficulty for the block {expected_difficulty:?}")] #[non_exhaustive] InvalidDifficultyThreshold { difficulty_threshold: CompactDifficulty, expected_difficulty: CompactDifficulty, }, #[error("block contains an invalid commitment")] InvalidBlockCommitment(#[from] block::CommitmentError), #[error("block history commitment {candidate_commitment:?} is different to the expected commitment {expected_commitment:?}")] #[non_exhaustive] InvalidHistoryCommitment { candidate_commitment: ChainHistoryMmrRootHash, expected_commitment: ChainHistoryMmrRootHash, }, #[error("error building the history tree")] HistoryTreeError(#[from] HistoryTreeError), }