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

feat(error): revamp make_canonical error #3899

Merged
merged 11 commits into from
Sep 20, 2023
14 changes: 7 additions & 7 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx};
use reth_interfaces::{
blockchain_tree::{
error::{BlockchainTreeError, InsertBlockError, InsertBlockErrorKind},
error::{BlockchainTreeError, CanonicalError, InsertBlockError, InsertBlockErrorKind},
BlockStatus, CanonicalOutcome, InsertPayloadOk,
},
consensus::{Consensus, ConsensusError},
Expand Down Expand Up @@ -906,12 +906,12 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
if let Some(header) = self.find_canonical_header(block_hash)? {
info!(target: "blockchain_tree", ?block_hash, "Block is already canonical, ignoring.");
let td = self.externals.database().provider()?.header_td(block_hash)?.ok_or(
BlockExecutionError::from(BlockValidationError::MissingTotalDifficulty {
CanonicalError::from(BlockValidationError::MissingTotalDifficulty {
hash: *block_hash,
}),
)?;
if !self.externals.chain_spec.fork(Hardfork::Paris).active_at_ttd(td, U256::ZERO) {
return Err(BlockExecutionError::from(BlockValidationError::BlockPreMerge {
return Err(CanonicalError::from(BlockValidationError::BlockPreMerge {
hash: *block_hash,
})
.into())
Expand All @@ -921,10 +921,10 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>

let Some(chain_id) = self.block_indices.get_blocks_chain_id(block_hash) else {
warn!(target: "blockchain_tree", ?block_hash, "Block hash not found in block indices");
// TODO: better error
return Err(
BlockExecutionError::BlockHashNotFoundInChain { block_hash: *block_hash }.into()
)
return Err(CanonicalError::from(BlockchainTreeError::BlockHashNotFoundInChain {
block_hash: *block_hash,
})
.into())
};
let chain = self.chains.remove(&chain_id).expect("To be present");

Expand Down
8 changes: 5 additions & 3 deletions crates/consensus/beacon/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use futures::{Future, StreamExt};
use reth_db::database::Database;
use reth_interfaces::{
blockchain_tree::{
error::{InsertBlockError, InsertBlockErrorKind},
error::{BlockchainTreeError, CanonicalError, InsertBlockError, InsertBlockErrorKind},
BlockStatus, BlockchainTreeEngine, CanonicalOutcome, InsertPayloadOk,
},
consensus::ForkchoiceState,
Expand Down Expand Up @@ -668,7 +668,7 @@ where
PayloadStatus::new(PayloadStatusEnum::Valid, Some(state.head_block_hash))
}
Err(error) => {
if let Error::Execution(ref err) = error {
if let Error::Canonical(ref err) = error {
if err.is_fatal() {
tracing::error!(target: "consensus::engine", ?err, "Encountered fatal error");
return Err(error)
Expand Down Expand Up @@ -1398,7 +1398,9 @@ where
// it's part of the canonical chain: if it's the safe or the finalized block
if matches!(
err,
Error::Execution(BlockExecutionError::BlockHashNotFoundInChain { .. })
Error::Canonical(CanonicalError::BlockchainTree(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mattsse @Rjected I still don't understand what's going wrong with this one. @mattsse I just saw that you had merge master in there two weeks ago but that doesn't change anything. Considering where the tests are slow, I imagine it's coming from that place in the code right? but it seems strange to me because there is no major change right?

Copy link
Collaborator

@mattsse mattsse Sep 19, 2023

Choose a reason for hiding this comment

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

some change must have led to an issue with the tokio test runner

try with #[tokio::test(flavor = "multi_thread")] for forkchoice_updated_invalid_pow

and you'll see a failing assertion

assertion left == right failed
left: ForkchoiceUpdated { payload_status: PayloadStatus { status: Syncing, latest_valid_hash: None }, payload_id: None }
right: ForkchoiceUpdated { payload_status: PayloadStatus { status: Invalid { validation_error: "Block 0x1a46761f926c32ba02e1da554fc3e4b53af8b44fb55e20036370745b54a2246f is pre merge" }, latest_valid_hash: Some(0x0000000000000000000000000000000000000000000000000000000000000000) }, payload_id: None }

BlockchainTreeError::BlockHashNotFoundInChain { .. }
))
) {
// if the inserted block is the currently targeted `finalized` or `safe`
// block, we will attempt to make them canonical,
Expand Down
36 changes: 36 additions & 0 deletions crates/interfaces/src/blockchain_tree/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,32 @@ pub enum BlockchainTreeError {
BlockBufferingFailed { block_hash: BlockHash },
}

/// Result alias for `CanonicalError`
pub type CanonicalResult<T> = std::result::Result<T, CanonicalError>;

/// Canonical Errors
#[allow(missing_docs)]
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
pub enum CanonicalError {
#[error(transparent)]
Validation(#[from] BlockValidationError),
#[error(transparent)]
BlockchainTree(#[from] BlockchainTreeError),

// === transaction errors ===
#[error("Transaction error on revert: {inner:?}")]
CanonicalRevert { inner: String },
#[error("Transaction error on commit: {inner:?}")]
CanonicalCommit { inner: String },
}

impl CanonicalError {
/// Returns `true` if the error is fatal.
pub fn is_fatal(&self) -> bool {
matches!(self, Self::CanonicalCommit { .. } | Self::CanonicalRevert { .. })
}
}

/// Error thrown when inserting a block failed because the block is considered invalid.
#[derive(thiserror::Error)]
#[error(transparent)]
Expand Down Expand Up @@ -161,6 +187,9 @@ pub enum InsertBlockErrorKind {
/// An internal error occurred, like interacting with the database.
#[error("Internal error")]
Internal(Box<dyn std::error::Error + Send + Sync>),
/// Canonical error.
#[error(transparent)]
Canonical(CanonicalError),
}

impl InsertBlockErrorKind {
Expand Down Expand Up @@ -213,6 +242,12 @@ impl InsertBlockErrorKind {
// any other error, such as database errors, are considered internal errors
false
}
InsertBlockErrorKind::Canonical(err) => match err {
CanonicalError::BlockchainTree(_) |
CanonicalError::CanonicalCommit { .. } |
CanonicalError::CanonicalRevert { .. } => false,
CanonicalError::Validation(_) => true,
},
}
}

Expand Down Expand Up @@ -273,6 +308,7 @@ impl From<crate::Error> for InsertBlockErrorKind {
Error::Provider(err) => InsertBlockErrorKind::Internal(Box::new(err)),
Error::Network(err) => InsertBlockErrorKind::Internal(Box::new(err)),
Error::Custom(err) => InsertBlockErrorKind::Internal(err.into()),
Error::Canonical(err) => InsertBlockErrorKind::Canonical(err),
}
}
}
3 changes: 3 additions & 0 deletions crates/interfaces/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub enum Error {
#[error(transparent)]
Network(#[from] reth_network_api::NetworkError),

#[error(transparent)]
Canonical(#[from] crate::blockchain_tree::error::CanonicalError),

#[error("{0}")]
Custom(std::string::String),
}
Loading