From 7ee8461baca7f666a2e2efd8aba431df76950ba5 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 20 Feb 2025 13:22:22 +0400 Subject: [PATCH] feat: expose `InvalidTxError` in `BlockExecutionError` (#14597) --- Cargo.lock | 5 +++-- Cargo.toml | 4 ++-- book/sources/Cargo.toml | 4 ++-- crates/engine/util/src/reorg.rs | 8 ++----- crates/errors/src/error.rs | 4 ++-- crates/ethereum/evm/src/execute.rs | 6 ++---- crates/evm/execution-errors/Cargo.toml | 2 ++ crates/evm/execution-errors/src/lib.rs | 30 ++++++++++++++++++++++++-- crates/optimism/evm/src/execute.rs | 6 ++---- 9 files changed, 45 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e69e29f53..cd22ac4c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -261,7 +261,7 @@ dependencies = [ [[package]] name = "alloy-evm" version = "0.1.0" -source = "git+https://github.com/alloy-rs/evm?rev=b77a39a#b77a39aa954a95b1c0385905b7d39c9d096b0a1b" +source = "git+https://github.com/alloy-rs/evm?rev=3a57c0d#3a57c0db813d45ddf9b5dcbe4756ae2ce3fc2569" dependencies = [ "alloy-primitives", "revm", @@ -368,7 +368,7 @@ dependencies = [ [[package]] name = "alloy-op-evm" version = "0.1.0" -source = "git+https://github.com/alloy-rs/evm?rev=b77a39a#b77a39aa954a95b1c0385905b7d39c9d096b0a1b" +source = "git+https://github.com/alloy-rs/evm?rev=3a57c0d#3a57c0db813d45ddf9b5dcbe4756ae2ce3fc2569" dependencies = [ "alloy-evm", "alloy-primitives", @@ -7792,6 +7792,7 @@ name = "reth-execution-errors" version = "1.2.0" dependencies = [ "alloy-eips", + "alloy-evm", "alloy-primitives", "alloy-rlp", "nybbles", diff --git a/Cargo.toml b/Cargo.toml index f1ecb1a80..db81100df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -623,8 +623,8 @@ snmalloc-rs = { version = "0.3.7", features = ["build_cc"] } crunchy = "=0.2.2" [patch.crates-io] -alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "b77a39a" } -alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "b77a39a" } +alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "3a57c0d" } +alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "3a57c0d" } revm = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "a8a9893b" } diff --git a/book/sources/Cargo.toml b/book/sources/Cargo.toml index f1293df53..9b09846aa 100644 --- a/book/sources/Cargo.toml +++ b/book/sources/Cargo.toml @@ -13,8 +13,8 @@ reth-tracing = { path = "../../crates/tracing" } reth-node-api = { path = "../../crates/node/api" } [patch.crates-io] -alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "048248c" } -alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "048248c" } +alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "3a57c0d" } +alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "3a57c0d" } revm = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index a5e9e291b..50e19656a 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -11,7 +11,7 @@ use reth_chainspec::EthChainSpec; use reth_engine_primitives::{ BeaconEngineMessage, BeaconOnNewPayloadError, EngineTypes, OnForkChoiceUpdated, }; -use reth_errors::{BlockExecutionError, BlockValidationError, RethError, RethResult}; +use reth_errors::{BlockExecutionError, RethError, RethResult}; use reth_ethereum_forks::EthereumHardforks; use reth_evm::{ state_change::post_block_withdrawals_balance_increments, system_calls::SystemCaller, @@ -320,11 +320,7 @@ where continue } // Treat error as fatal - Err(error) => { - return Err(RethError::Execution(BlockExecutionError::Validation( - BlockValidationError::EVM { hash: *tx.tx_hash(), error: Box::new(error) }, - ))) - } + Err(error) => return Err(RethError::Execution(BlockExecutionError::other(error))), }; evm.db_mut().commit(exec_result.state); diff --git a/crates/errors/src/error.rs b/crates/errors/src/error.rs index 5141a7457..89011921d 100644 --- a/crates/errors/src/error.rs +++ b/crates/errors/src/error.rs @@ -67,8 +67,8 @@ mod size_asserts { }; } - static_assert_size!(RethError, 56); - static_assert_size!(BlockExecutionError, 56); + static_assert_size!(RethError, 64); + static_assert_size!(BlockExecutionError, 64); static_assert_size!(ConsensusError, 48); static_assert_size!(DatabaseError, 32); static_assert_size!(ProviderError, 48); diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 987c93cc3..761459da7 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -154,10 +154,8 @@ where let hash = tx.hash(); // Execute transaction. - let result_and_state = self.evm.transact(tx_env).map_err(move |err| { - // Ensure hash is calculated for error log, if not already done - BlockValidationError::EVM { hash: *hash, error: Box::new(err) } - })?; + let result_and_state = + self.evm.transact(tx_env).map_err(move |err| BlockExecutionError::evm(err, *hash))?; self.system_caller .on_state(StateChangeSource::Transaction(self.receipts.len()), &result_and_state.state); let ResultAndState { result, state } = result_and_state; diff --git a/crates/evm/execution-errors/Cargo.toml b/crates/evm/execution-errors/Cargo.toml index f71e904f3..b54518aa6 100644 --- a/crates/evm/execution-errors/Cargo.toml +++ b/crates/evm/execution-errors/Cargo.toml @@ -14,6 +14,7 @@ workspace = true # reth reth-storage-errors.workspace = true +alloy-evm.workspace = true alloy-primitives.workspace = true alloy-rlp.workspace = true alloy-eips.workspace = true @@ -33,4 +34,5 @@ std = [ "nybbles/std", "revm-database-interface/std", "reth-storage-errors/std", + "alloy-evm/std", ] diff --git a/crates/evm/execution-errors/src/lib.rs b/crates/evm/execution-errors/src/lib.rs index b309c2599..f28891acc 100644 --- a/crates/evm/execution-errors/src/lib.rs +++ b/crates/evm/execution-errors/src/lib.rs @@ -16,6 +16,7 @@ use alloc::{ string::{String, ToString}, }; use alloy_eips::BlockNumHash; +use alloy_evm::{EvmError, InvalidTxError}; use alloy_primitives::B256; use reth_storage_errors::provider::ProviderError; use thiserror::Error; @@ -28,11 +29,11 @@ pub use trie::*; pub enum BlockValidationError { /// EVM error with transaction hash and message #[error("EVM reported invalid transaction ({hash}): {error}")] - EVM { + InvalidTx { /// The hash of the transaction hash: B256, /// The EVM error. - error: Box, + error: Box, }, /// Error when incrementing balance in post execution #[error("incrementing balance in post execution failed")] @@ -141,6 +142,21 @@ impl BlockExecutionError { pub const fn is_state_root_error(&self) -> bool { matches!(self, Self::Validation(BlockValidationError::StateRoot(_))) } + + /// Handles an EVM error occured when executing a transaction. + /// + /// If an error matches [`EvmError::InvalidTransaction`], it will be wrapped into + /// [`BlockValidationError::InvalidTx`], otherwise into [`InternalBlockExecutionError::EVM`]. + pub fn evm(error: E, hash: B256) -> Self { + match error.try_into_invalid_tx_err() { + Ok(err) => { + Self::Validation(BlockValidationError::InvalidTx { hash, error: Box::new(err) }) + } + Err(err) => { + Self::Internal(InternalBlockExecutionError::EVM { hash, error: Box::new(err) }) + } + } + } } impl From for BlockExecutionError { @@ -164,6 +180,16 @@ pub enum InternalBlockExecutionError { /// The fork on the other chain other_chain_fork: Box, }, + /// EVM error occurred when executing transaction. This is different from + /// [`BlockValidationError::InvalidTx`] because it will only contain EVM errors which are not + /// transaction validation errors and are assumed to be fatal. + #[error("internal EVM error occurred when executing transaction {hash}: {error}")] + EVM { + /// The hash of the transaction + hash: B256, + /// The EVM error. + error: Box, + }, /// Error when fetching data from the db. #[error(transparent)] Provider(#[from] ProviderError), diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index 03e527694..95ad9993f 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -202,10 +202,8 @@ where let hash = tx.tx_hash(); // Execute transaction. - let result_and_state = self.evm.transact(tx_env).map_err(move |err| { - // Ensure hash is calculated for error log, if not already done - BlockValidationError::EVM { hash: *hash, error: Box::new(err) } - })?; + let result_and_state = + self.evm.transact(tx_env).map_err(move |err| BlockExecutionError::evm(err, *hash))?; trace!( target: "evm",