diff --git a/Cargo.lock b/Cargo.lock index 17a339ec9..d88b4f549 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7515,7 +7515,6 @@ dependencies = [ "reth-consensus", "reth-prune-types", "reth-storage-errors", - "revm-primitives", "thiserror 2.0.11", ] @@ -8321,6 +8320,7 @@ dependencies = [ "reth-primitives-traits", "reth-provider", "reth-revm", + "reth-rpc-eth-types", "reth-rpc-server-types", "reth-rpc-types-compat", "reth-tasks", @@ -8503,7 +8503,6 @@ dependencies = [ "reth-chainspec", "reth-errors", "reth-primitives", - "revm-primitives", "serde", "thiserror 2.0.11", "tokio", diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index 16771731a..3120264f5 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -14,7 +14,7 @@ use reth_errors::{BlockExecutionError, BlockValidationError, RethError, RethResu use reth_ethereum_forks::EthereumHardforks; use reth_evm::{ state_change::post_block_withdrawals_balance_increments, system_calls::SystemCaller, - ConfigureEvm, Evm, + ConfigureEvm, Evm, EvmError, }; use reth_payload_primitives::EngineApiMessageVersion; use reth_payload_validator::ExecutionPayloadValidator; @@ -29,7 +29,6 @@ use reth_revm::{ DatabaseCommit, }; use reth_rpc_types_compat::engine::payload::block_to_payload; -use revm_primitives::EVMError; use std::{ collections::VecDeque, future::Future, @@ -328,8 +327,8 @@ where let tx_env = evm_config.tx_env(&tx_recovered, tx_recovered.signer()); let exec_result = match evm.transact(tx_env) { Ok(result) => result, - error @ Err(EVMError::Transaction(_) | EVMError::Header(_)) => { - trace!(target: "engine::stream::reorg", hash = %tx.tx_hash(), ?error, "Error executing transaction from next block"); + Err(err) if err.is_invalid_tx_err() => { + trace!(target: "engine::stream::reorg", hash = %tx.tx_hash(), ?err, "Error executing transaction from next block"); continue } // Treat error as fatal diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index e162c8557..f782b6b1c 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -7,7 +7,6 @@ use crate::{ use alloc::{boxed::Box, sync::Arc, vec::Vec}; use alloy_consensus::{BlockHeader, Transaction}; use alloy_eips::{eip6110, eip7685::Requests}; -use core::fmt::Display; use reth_chainspec::{ChainSpec, EthereumHardfork, EthereumHardforks, MAINNET}; use reth_consensus::ConsensusError; use reth_ethereum_consensus::validate_block_post_execution; @@ -15,19 +14,15 @@ use reth_evm::{ execute::{ balance_increment_state, BasicBlockExecutorProvider, BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, ExecuteOutput, - ProviderError, }, state_change::post_block_balance_increments, system_calls::{OnStateHook, SystemCaller}, - ConfigureEvm, Evm, + ConfigureEvm, Database, Evm, }; use reth_primitives::{EthPrimitives, Receipt, RecoveredBlock}; use reth_primitives_traits::{BlockBody, SignedTransaction}; use reth_revm::db::State; -use revm_primitives::{ - db::{Database, DatabaseCommit}, - ResultAndState, -}; +use revm_primitives::{db::DatabaseCommit, ResultAndState}; /// Factory for [`EthExecutionStrategy`]. #[derive(Debug, Clone)] @@ -71,12 +66,11 @@ where { type Primitives = EthPrimitives; - type Strategy + Display>> = - EthExecutionStrategy; + type Strategy = EthExecutionStrategy; fn create_strategy(&self, db: DB) -> Self::Strategy where - DB: Database + Display>, + DB: Database, { let state = State::builder().with_database(db).with_bundle_update().without_state_clear().build(); @@ -113,7 +107,7 @@ where impl BlockExecutionStrategy for EthExecutionStrategy where - DB: Database + Display>, + DB: Database, EvmConfig: ConfigureEvm< Header = alloy_consensus::Header, Transaction = reth_primitives::TransactionSigned, @@ -163,11 +157,10 @@ where // Execute transaction. let result_and_state = evm.transact(tx_env).map_err(move |err| { - let new_err = err.map_db_err(|e| e.into()); // Ensure hash is calculated for error log, if not already done BlockValidationError::EVM { hash: transaction.recalculate_hash(), - error: Box::new(new_err), + error: Box::new(err), } })?; self.system_caller.on_state(&result_and_state.state); @@ -307,7 +300,7 @@ mod tests { use reth_primitives::{Account, Block, BlockBody, Transaction}; use reth_primitives_traits::{crypto::secp256k1::public_key_to_address, Block as _}; use reth_revm::{ - database::StateProviderDatabase, test_utils::StateProviderTest, TransitionState, + database::StateProviderDatabase, test_utils::StateProviderTest, Database, TransitionState, }; use reth_testing_utils::generators::{self, sign_tx_with_key_pair}; use revm_primitives::{address, EvmState, BLOCKHASH_SERVE_WINDOW}; @@ -393,7 +386,7 @@ mod tests { ); assert!(matches!( - err.as_validation().unwrap().clone(), + err.as_validation().unwrap(), BlockValidationError::MissingParentBeaconBlockRoot )); diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index 408aa415c..39073c7a7 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -22,10 +22,10 @@ use alloy_consensus::{BlockHeader, Header}; use alloy_primitives::{Address, U256}; use core::{convert::Infallible, fmt::Debug}; use reth_chainspec::ChainSpec; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Evm, NextBlockEnvAttributes}; +use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, NextBlockEnvAttributes}; use reth_primitives::TransactionSigned; use reth_primitives_traits::transaction::execute::FillTxEnv; -use reth_revm::{inspector_handle_register, Database, EvmBuilder}; +use reth_revm::{inspector_handle_register, EvmBuilder}; use revm_primitives::{ AnalysisKind, BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv, CfgEnvWithHandlerCfg, EVMError, HandlerCfg, ResultAndState, SpecId, TxEnv, TxKind, @@ -237,6 +237,7 @@ impl ConfigureEvmEnv for EthEvmConfig { impl ConfigureEvm for EthEvmConfig { type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>; + type EvmError = EVMError; fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 10483b7f4..9bc89561a 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -22,7 +22,8 @@ use reth_basic_payload_builder::{ use reth_chainspec::{ChainSpec, ChainSpecProvider}; use reth_errors::RethError; use reth_evm::{ - env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, Evm, NextBlockEnvAttributes, + env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, Evm, EvmError, InvalidTxError, + NextBlockEnvAttributes, }; use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig}; use reth_execution_types::ExecutionOutcome; @@ -44,7 +45,7 @@ use reth_transaction_pool::{ }; use revm::{ db::{states::bundle_state::BundleRetention, State}, - primitives::{EVMError, InvalidTransaction, ResultAndState}, + primitives::ResultAndState, DatabaseCommit, }; use std::sync::Arc; @@ -276,30 +277,25 @@ where let ResultAndState { result, state } = match evm.transact(tx_env) { Ok(res) => res, Err(err) => { - match err { - EVMError::Transaction(err) => { - if matches!(err, InvalidTransaction::NonceTooLow { .. }) { - // if the nonce is too low, we can skip this transaction - trace!(target: "payload_builder", %err, ?tx, "skipping nonce too low transaction"); - } else { - // if the transaction is invalid, we can skip it and all of its - // descendants - trace!(target: "payload_builder", %err, ?tx, "skipping invalid transaction and its descendants"); - best_txs.mark_invalid( - &pool_tx, - InvalidPoolTransactionError::Consensus( - InvalidTransactionError::TxTypeNotSupported, - ), - ); - } - - continue - } - err => { - // this is an error that we should treat as fatal for this attempt - return Err(PayloadBuilderError::EvmExecutionError(err)) + if let Some(err) = err.as_invalid_tx_err() { + if err.is_nonce_too_low() { + // if the nonce is too low, we can skip this transaction + trace!(target: "payload_builder", %err, ?tx, "skipping nonce too low transaction"); + } else { + // if the transaction is invalid, we can skip it and all of its + // descendants + trace!(target: "payload_builder", %err, ?tx, "skipping invalid transaction and its descendants"); + best_txs.mark_invalid( + &pool_tx, + InvalidPoolTransactionError::Consensus( + InvalidTransactionError::TxTypeNotSupported, + ), + ); } + continue } + // this is an error that we should treat as fatal for this attempt + return Err(PayloadBuilderError::evm(err)) } }; diff --git a/crates/evm/execution-errors/Cargo.toml b/crates/evm/execution-errors/Cargo.toml index 468fcfc1d..70ae29ae2 100644 --- a/crates/evm/execution-errors/Cargo.toml +++ b/crates/evm/execution-errors/Cargo.toml @@ -19,7 +19,6 @@ reth-prune-types.workspace = true alloy-primitives.workspace = true alloy-rlp.workspace = true alloy-eips.workspace = true -revm-primitives.workspace = true nybbles.workspace = true thiserror.workspace = true @@ -30,7 +29,6 @@ std = [ "reth-consensus/std", "alloy-eips/std", "alloy-primitives/std", - "revm-primitives/std", "alloy-rlp/std", "thiserror/std", "nybbles/std", diff --git a/crates/evm/execution-errors/src/lib.rs b/crates/evm/execution-errors/src/lib.rs index cc723fa11..ffe853d42 100644 --- a/crates/evm/execution-errors/src/lib.rs +++ b/crates/evm/execution-errors/src/lib.rs @@ -20,14 +20,13 @@ use alloy_primitives::B256; use reth_consensus::ConsensusError; use reth_prune_types::PruneSegmentError; use reth_storage_errors::provider::ProviderError; -use revm_primitives::EVMError; use thiserror::Error; pub mod trie; pub use trie::*; /// Transaction validation errors -#[derive(Error, Clone, Debug)] +#[derive(Error, Debug)] pub enum BlockValidationError { /// EVM error with transaction hash and message #[error("EVM reported invalid transaction ({hash}): {error}")] @@ -35,7 +34,7 @@ pub enum BlockValidationError { /// The hash of the transaction hash: B256, /// The EVM error. - error: Box>, + error: Box, }, /// Error when recovering the sender for a transaction #[error("failed to recover sender for transaction")] diff --git a/crates/evm/src/either.rs b/crates/evm/src/either.rs index 7a31122ef..84ba942cc 100644 --- a/crates/evm/src/either.rs +++ b/crates/evm/src/either.rs @@ -1,13 +1,10 @@ //! Helper type that represents one of two possible executor types -use core::fmt::Display; - use crate::{ execute::{BatchExecutor, BlockExecutorProvider, Executor}, system_calls::OnStateHook, + Database, }; -use reth_storage_errors::provider::ProviderError; -use revm_primitives::db::Database; // re-export Either pub use futures_util::future::Either; @@ -20,15 +17,13 @@ where { type Primitives = A::Primitives; - type Executor + Display>> = - Either, B::Executor>; + type Executor = Either, B::Executor>; - type BatchExecutor + Display>> = - Either, B::BatchExecutor>; + type BatchExecutor = Either, B::BatchExecutor>; fn executor(&self, db: DB) -> Self::Executor where - DB: Database + Display>, + DB: Database, { match self { Self::Left(a) => Either::Left(a.executor(db)), @@ -38,7 +33,7 @@ where fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: Database, { match self { Self::Left(a) => Either::Left(a.batch_executor(db)), @@ -51,7 +46,7 @@ impl Executor for Either where A: Executor, B: for<'a> Executor = A::Input<'a>, Output = A::Output, Error = A::Error>, - DB: Database + Display>, + DB: Database, { type Input<'a> = A::Input<'a>; type Output = A::Output; @@ -97,7 +92,7 @@ impl BatchExecutor for Either where A: BatchExecutor, B: for<'a> BatchExecutor = A::Input<'a>, Output = A::Output, Error = A::Error>, - DB: Database + Display>, + DB: Database, { type Input<'a> = A::Input<'a>; type Output = A::Output; diff --git a/crates/evm/src/error.rs b/crates/evm/src/error.rs new file mode 100644 index 000000000..55dac3b57 --- /dev/null +++ b/crates/evm/src/error.rs @@ -0,0 +1,49 @@ +use revm_primitives::{EVMError, InvalidTransaction}; + +/// Abstraction over transaction validation error. +pub trait InvalidTxError: core::error::Error + Send + Sync + 'static { + /// Returns whether the error cause by transaction having a nonce lower than expected. + fn is_nonce_too_low(&self) -> bool; +} + +impl InvalidTxError for InvalidTransaction { + fn is_nonce_too_low(&self) -> bool { + matches!(self, Self::NonceTooLow { .. }) + } +} + +/// Abstraction over errors that can occur during EVM execution. +/// +/// It's assumed that errors can occur either because of an invalid transaction, meaning that other +/// transaction might still result in successful execution, or because of a general EVM +/// misconfiguration. +/// +/// If caller occurs a error different from [`EvmError::InvalidTransaction`], it should most likely +/// be treated as fatal error flagging some EVM misconfiguration. +pub trait EvmError: core::error::Error + Send + Sync + 'static { + /// Errors which might occur as a result of an invalid transaction. i.e unrelated to general EVM + /// configuration. + type InvalidTransaction: InvalidTxError; + + /// Returns the [`EvmError::InvalidTransaction`] if the error is an invalid transaction error. + fn as_invalid_tx_err(&self) -> Option<&Self::InvalidTransaction>; + + /// Returns `true` if the error is an invalid transaction error. + fn is_invalid_tx_err(&self) -> bool { + self.as_invalid_tx_err().is_some() + } +} + +impl EvmError for EVMError +where + DBError: core::error::Error + Send + Sync + 'static, +{ + type InvalidTransaction = InvalidTransaction; + + fn as_invalid_tx_err(&self) -> Option<&Self::InvalidTransaction> { + match self { + Self::Transaction(err) => Some(err), + _ => None, + } + } +} diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index 84639a701..c2f2ee3cb 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -8,14 +8,13 @@ pub use reth_execution_errors::{ pub use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome}; pub use reth_storage_errors::provider::ProviderError; -use crate::system_calls::OnStateHook; +use crate::{system_calls::OnStateHook, Database}; use alloc::{boxed::Box, vec::Vec}; use alloy_eips::eip7685::Requests; use alloy_primitives::{ map::{DefaultHashBuilder, HashMap}, Address, }; -use core::fmt::Display; use reth_consensus::ConsensusError; use reth_primitives::{NodePrimitives, Receipt, RecoveredBlock}; use reth_revm::batch::BlockBatchRecord; @@ -23,7 +22,7 @@ use revm::{ db::{states::bundle_state::BundleRetention, BundleState}, State, }; -use revm_primitives::{db::Database, Account, AccountStatus, EvmState}; +use revm_primitives::{Account, AccountStatus, EvmState}; /// A general purpose executor trait that executes an input (e.g. block) and produces an output /// (e.g. state changes and receipts). @@ -134,7 +133,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { /// /// It is not expected to validate the state trie root, this must be done by the caller using /// the returned state. - type Executor + Display>>: for<'a> Executor< + type Executor: for<'a> Executor< DB, Input<'a> = &'a RecoveredBlock<::Block>, Output = BlockExecutionOutput<::Receipt>, @@ -142,7 +141,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { >; /// An executor that can execute a batch of blocks given a database. - type BatchExecutor + Display>>: for<'a> BatchExecutor< + type BatchExecutor: for<'a> BatchExecutor< DB, Input<'a> = &'a RecoveredBlock<::Block>, Output = ExecutionOutcome<::Receipt>, @@ -154,7 +153,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { /// This is used to execute a single block and get the changed state. fn executor(&self, db: DB) -> Self::Executor where - DB: Database + Display>; + DB: Database; /// Creates a new batch executor with the given database and pruning modes. /// @@ -162,7 +161,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { /// during historical sync which involves executing multiple blocks in sequence. fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + Display>; + DB: Database; } /// Helper type for the output of executing a block. @@ -177,13 +176,13 @@ pub struct ExecuteOutput { /// Defines the strategy for executing a single block. pub trait BlockExecutionStrategy { /// Database this strategy operates on. - type DB: Database; + type DB: revm::Database; /// Primitive types used by the strategy. type Primitives: NodePrimitives; /// The error type returned by this strategy's methods. - type Error: From + core::error::Error; + type Error: core::error::Error; /// Applies any necessary changes before executing the block's transactions. fn apply_pre_execution_changes( @@ -236,7 +235,7 @@ pub trait BlockExecutionStrategyFactory: Send + Sync + Clone + Unpin + 'static { type Primitives: NodePrimitives; /// Associated strategy type. - type Strategy + Display>>: BlockExecutionStrategy< + type Strategy: BlockExecutionStrategy< DB = DB, Primitives = Self::Primitives, Error = BlockExecutionError, @@ -245,7 +244,7 @@ pub trait BlockExecutionStrategyFactory: Send + Sync + Clone + Unpin + 'static { /// Creates a strategy using the give database. fn create_strategy(&self, db: DB) -> Self::Strategy where - DB: Database + Display>; + DB: Database; } impl Clone for BasicBlockExecutorProvider @@ -276,15 +275,13 @@ where { type Primitives = F::Primitives; - type Executor + Display>> = - BasicBlockExecutor>; + type Executor = BasicBlockExecutor>; - type BatchExecutor + Display>> = - BasicBatchExecutor>; + type BatchExecutor = BasicBatchExecutor>; fn executor(&self, db: DB) -> Self::Executor where - DB: Database + Display>, + DB: Database, { let strategy = self.strategy_factory.create_strategy(db); BasicBlockExecutor::new(strategy) @@ -292,7 +289,7 @@ where fn batch_executor(&self, db: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: Database, { let strategy = self.strategy_factory.create_strategy(db); let batch_record = BlockBatchRecord::default(); @@ -318,7 +315,7 @@ impl BasicBlockExecutor { impl Executor for BasicBlockExecutor where S: BlockExecutionStrategy, - DB: Database + Display>, + DB: Database, { type Input<'a> = &'a RecoveredBlock<::Block>; type Output = BlockExecutionOutput<::Receipt>; @@ -401,7 +398,7 @@ where impl BatchExecutor for BasicBatchExecutor where S: BlockExecutionStrategy, - DB: Database + Display>, + DB: Database, { type Input<'a> = &'a RecoveredBlock<::Block>; type Output = ExecutionOutcome<::Receipt>; @@ -495,19 +492,19 @@ mod tests { impl BlockExecutorProvider for TestExecutorProvider { type Primitives = EthPrimitives; - type Executor + Display>> = TestExecutor; - type BatchExecutor + Display>> = TestExecutor; + type Executor = TestExecutor; + type BatchExecutor = TestExecutor; fn executor(&self, _db: DB) -> Self::Executor where - DB: Database + Display>, + DB: Database, { TestExecutor(PhantomData) } fn batch_executor(&self, _db: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: Database, { TestExecutor(PhantomData) } @@ -585,12 +582,11 @@ mod tests { impl BlockExecutionStrategyFactory for TestExecutorStrategyFactory { type Primitives = EthPrimitives; - type Strategy + Display>> = - TestExecutorStrategy; + type Strategy = TestExecutorStrategy; fn create_strategy(&self, db: DB) -> Self::Strategy where - DB: Database + Display>, + DB: Database, { let state = State::builder() .with_database(db) diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index 47a00252f..f116e11b7 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -22,12 +22,15 @@ use alloy_eips::eip2930::AccessList; use alloy_primitives::{Address, Bytes, B256, U256}; use core::fmt::Debug; use reth_primitives_traits::{BlockHeader, SignedTransaction}; -use revm::{Database, DatabaseCommit, GetInspector}; -use revm_primitives::{BlockEnv, EVMError, ResultAndState, TxEnv, TxKind}; +use revm::{DatabaseCommit, GetInspector}; +use revm_primitives::{BlockEnv, ResultAndState, TxEnv, TxKind}; pub mod either; /// EVM environment configuration. pub mod env; +/// EVM error types. +mod error; +pub use error::*; pub mod execute; pub use env::EvmEnv; @@ -82,6 +85,9 @@ pub trait Evm { Ok(result) } } +/// Helper trait to bound [`revm::Database::Error`] with common requirements. +pub trait Database: revm::Database {} +impl Database for T where T: revm::Database {} /// Trait for configuring the EVM for executing full blocks. pub trait ConfigureEvm: ConfigureEvmEnv { @@ -89,9 +95,12 @@ pub trait ConfigureEvm: ConfigureEvmEnv { type Evm<'a, DB: Database + 'a, I: 'a>: Evm< Tx = Self::TxEnv, DB = DB, - Error = EVMError, + Error = Self::EvmError, >; + /// The error type returned by the EVM. + type EvmError: EvmError; + /// Returns a new EVM with the given database configured with the given environment settings, /// including the spec id and transaction environment. /// @@ -137,6 +146,7 @@ where &'b T: ConfigureEvmEnv
, { type Evm<'a, DB: Database + 'a, I: 'a> = T::Evm<'a, DB, I>; + type EvmError = T::EvmError; fn evm_for_block(&self, db: DB, header: &Self::Header) -> Self::Evm<'_, DB, ()> { (*self).evm_for_block(db, header) diff --git a/crates/evm/src/noop.rs b/crates/evm/src/noop.rs index 3ffa325f7..bb52d7f3b 100644 --- a/crates/evm/src/noop.rs +++ b/crates/evm/src/noop.rs @@ -1,16 +1,14 @@ //! A no operation block executor implementation. -use core::fmt::Display; use reth_execution_errors::BlockExecutionError; use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome}; use reth_primitives::{NodePrimitives, RecoveredBlock}; -use reth_storage_errors::provider::ProviderError; use revm::State; -use revm_primitives::db::Database; use crate::{ execute::{BatchExecutor, BlockExecutorProvider, Executor}, system_calls::OnStateHook, + Database, }; const UNAVAILABLE_FOR_NOOP: &str = "execution unavailable for noop"; @@ -23,20 +21,20 @@ pub struct NoopBlockExecutorProvider

(core::marker::PhantomData

); impl BlockExecutorProvider for NoopBlockExecutorProvider

{ type Primitives = P; - type Executor + Display>> = Self; + type Executor = Self; - type BatchExecutor + Display>> = Self; + type BatchExecutor = Self; fn executor(&self, _: DB) -> Self::Executor where - DB: Database + Display>, + DB: Database, { Self::default() } fn batch_executor(&self, _: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: Database, { Self::default() } diff --git a/crates/evm/src/system_calls/mod.rs b/crates/evm/src/system_calls/mod.rs index 4fa63dbda..535bda938 100644 --- a/crates/evm/src/system_calls/mod.rs +++ b/crates/evm/src/system_calls/mod.rs @@ -1,6 +1,6 @@ //! System contract call functions. -use crate::{ConfigureEvm, Evm, EvmEnv}; +use crate::{ConfigureEvm, Database, Evm, EvmEnv}; use alloc::{boxed::Box, sync::Arc}; use alloy_consensus::BlockHeader; use alloy_eips::{ @@ -10,7 +10,7 @@ use alloy_primitives::Bytes; use core::fmt::Display; use reth_chainspec::EthereumHardforks; use reth_execution_errors::BlockExecutionError; -use revm::{Database, DatabaseCommit}; +use revm::DatabaseCommit; use revm_primitives::{EvmState, B256}; mod eip2935; @@ -260,7 +260,6 @@ where ) -> Result where DB: Database + DatabaseCommit, - DB::Error: Display, { let evm_config = self.evm_config.clone(); let mut evm = evm_config.evm_with_env(db, evm_env.clone()); diff --git a/crates/evm/src/test_utils.rs b/crates/evm/src/test_utils.rs index 0e023455b..a78004d15 100644 --- a/crates/evm/src/test_utils.rs +++ b/crates/evm/src/test_utils.rs @@ -6,16 +6,15 @@ use crate::{ BlockExecutionStrategy, BlockExecutorProvider, Executor, }, system_calls::OnStateHook, + Database, }; use alloy_eips::eip7685::Requests; use parking_lot::Mutex; use reth_execution_errors::BlockExecutionError; use reth_execution_types::ExecutionOutcome; use reth_primitives::{EthPrimitives, NodePrimitives, Receipt, Receipts, RecoveredBlock}; -use reth_storage_errors::provider::ProviderError; use revm::State; -use revm_primitives::db::Database; -use std::{fmt::Display, sync::Arc}; +use std::sync::Arc; /// A [`BlockExecutorProvider`] that returns mocked execution results. #[derive(Clone, Debug, Default)] @@ -33,20 +32,20 @@ impl MockExecutorProvider { impl BlockExecutorProvider for MockExecutorProvider { type Primitives = EthPrimitives; - type Executor + Display>> = Self; + type Executor = Self; - type BatchExecutor + Display>> = Self; + type BatchExecutor = Self; fn executor(&self, _: DB) -> Self::Executor where - DB: Database + Display>, + DB: Database, { self.clone() } fn batch_executor(&self, _: DB) -> Self::BatchExecutor where - DB: Database + Display>, + DB: Database, { self.clone() } diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index e911fad66..69bd39572 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -7,7 +7,6 @@ use crate::{ use alloc::{boxed::Box, sync::Arc, vec::Vec}; use alloy_consensus::{BlockHeader, Eip658Value, Receipt, Transaction as _}; use alloy_eips::eip7685::Requests; -use core::fmt::Display; use op_alloy_consensus::OpDepositReceipt; use reth_chainspec::EthereumHardforks; use reth_consensus::ConsensusError; @@ -15,11 +14,10 @@ use reth_evm::{ execute::{ balance_increment_state, BasicBlockExecutorProvider, BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, ExecuteOutput, - ProviderError, }, state_change::post_block_balance_increments, system_calls::{OnStateHook, SystemCaller}, - ConfigureEvmFor, Evm, + ConfigureEvmFor, Database, Evm, }; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::validate_block_post_execution; @@ -29,7 +27,7 @@ use reth_optimism_primitives::{ }; use reth_primitives::{NodePrimitives, RecoveredBlock}; use reth_primitives_traits::{BlockBody, SignedTransaction}; -use reth_revm::{Database, State}; +use reth_revm::State; use revm_primitives::{db::DatabaseCommit, ResultAndState}; use tracing::trace; @@ -76,12 +74,11 @@ where EvmConfig: ConfigureEvmFor + Clone + Unpin + Sync + Send + 'static, { type Primitives = N; - type Strategy + Display>> = - OpExecutionStrategy; + type Strategy = OpExecutionStrategy; fn create_strategy(&self, db: DB) -> Self::Strategy where - DB: Database + Display>, + DB: Database, { let state = State::builder().with_database(db).with_bundle_update().without_state_clear().build(); @@ -131,7 +128,7 @@ where impl BlockExecutionStrategy for OpExecutionStrategy where - DB: Database + Display>, + DB: Database, N: NodePrimitives< BlockHeader = alloy_consensus::Header, SignedTx: OpTransaction, @@ -214,11 +211,10 @@ where // Execute transaction. let result_and_state = evm.transact(tx_env).map_err(move |err| { - let new_err = err.map_db_err(|e| e.into()); // Ensure hash is calculated for error log, if not already done BlockValidationError::EVM { hash: transaction.recalculate_hash(), - error: Box::new(new_err), + error: Box::new(err), } })?; diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index a17a7e870..0997dd706 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -18,14 +18,14 @@ use alloy_eips::eip7840::BlobParams; use alloy_primitives::{Address, U256}; use core::fmt::Debug; use op_alloy_consensus::EIP1559ParamError; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Evm, NextBlockEnvAttributes}; +use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, NextBlockEnvAttributes}; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_primitives::OpTransactionSigned; use reth_primitives_traits::FillTxEnv; use reth_revm::{ inspector_handle_register, primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv}, - Database, EvmBuilder, GetInspector, + EvmBuilder, GetInspector, }; mod config; @@ -224,6 +224,7 @@ impl ConfigureEvmEnv for OpEvmConfig { impl ConfigureEvm for OpEvmConfig { type Evm<'a, DB: Database + 'a, I: 'a> = OpEvm<'a, I, DB>; + type EvmError = EVMError; fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { diff --git a/crates/optimism/node/Cargo.toml b/crates/optimism/node/Cargo.toml index 97a627959..7abd72dad 100644 --- a/crates/optimism/node/Cargo.toml +++ b/crates/optimism/node/Cargo.toml @@ -33,6 +33,7 @@ reth-revm = { workspace = true, features = ["std"] } reth-trie-db.workspace = true reth-rpc-server-types.workspace = true reth-rpc-types-compat.workspace = true +reth-rpc-eth-types.workspace = true reth-tasks = { workspace = true, optional = true } # op-reth diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 4bcf99cbb..3fa2ac685 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -9,7 +9,9 @@ use crate::{ use op_alloy_consensus::OpPooledTransaction; use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig}; use reth_chainspec::{EthChainSpec, Hardforks}; -use reth_evm::{execute::BasicBlockExecutorProvider, ConfigureEvmEnv, ConfigureEvmFor}; +use reth_evm::{ + execute::BasicBlockExecutorProvider, ConfigureEvm, ConfigureEvmEnv, ConfigureEvmFor, +}; use reth_network::{NetworkConfig, NetworkHandle, NetworkManager, NetworkPrimitives, PeersInfo}; use reth_node_api::{AddOnsContext, FullNodeComponents, NodeAddOns, PrimitivesTy, TxTy}; use reth_node_builder::{ @@ -32,10 +34,11 @@ use reth_optimism_primitives::{OpPrimitives, OpReceipt, OpTransactionSigned}; use reth_optimism_rpc::{ miner::{MinerApiExtServer, OpMinerExtApi}, witness::{DebugExecutionWitnessApiServer, OpDebugWitnessApi}, - OpEthApi, SequencerClient, + OpEthApi, OpEthApiError, SequencerClient, }; use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; use reth_provider::{CanonStateSubscriptions, EthStorage}; +use reth_rpc_eth_types::error::FromEvmError; use reth_rpc_server_types::RethRpcModule; use reth_tracing::tracing::{debug, info}; use reth_transaction_pool::{ @@ -193,6 +196,7 @@ where >, Evm: ConfigureEvmEnv, >, + OpEthApiError: FromEvmError, { type Handle = RpcHandle>; @@ -241,8 +245,9 @@ where Storage = OpStorage, Engine = OpEngineTypes, >, - Evm: ConfigureEvmEnv, + Evm: ConfigureEvm, >, + OpEthApiError: FromEvmError, { type EthApi = OpEthApi; diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 47bec70b1..15a350190 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -17,8 +17,8 @@ use reth_basic_payload_builder::*; use reth_chain_state::{ExecutedBlock, ExecutedBlockWithTrieUpdates}; use reth_chainspec::{ChainSpecProvider, EthereumHardforks}; use reth_evm::{ - env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Evm, - NextBlockEnvAttributes, + env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Database, Evm, + EvmError, InvalidTxError, NextBlockEnvAttributes, }; use reth_execution_types::ExecutionOutcome; use reth_optimism_chainspec::OpChainSpec; @@ -42,8 +42,8 @@ use reth_transaction_pool::{ }; use revm::{ db::{states::bundle_state::BundleRetention, State}, - primitives::{EVMError, InvalidTransaction, ResultAndState}, - Database, DatabaseCommit, + primitives::ResultAndState, + DatabaseCommit, }; use std::{fmt::Display, sync::Arc}; use tracing::{debug, trace, warn}; @@ -818,16 +818,12 @@ where let ResultAndState { result, state } = match evm.transact(tx_env) { Ok(res) => res, Err(err) => { - match err { - EVMError::Transaction(err) => { - trace!(target: "payload_builder", %err, ?sequencer_tx, "Error in sequencer transaction, skipping."); - continue - } - err => { - // this is an error that we should treat as fatal for this attempt - return Err(PayloadBuilderError::EvmExecutionError(err)) - } + if err.is_invalid_tx_err() { + trace!(target: "payload_builder", %err, ?sequencer_tx, "Error in sequencer transaction, skipping."); + continue } + // this is an error that we should treat as fatal for this attempt + return Err(PayloadBuilderError::EvmExecutionError(Box::new(err))) } }; @@ -915,25 +911,21 @@ where let ResultAndState { result, state } = match evm.transact(tx_env) { Ok(res) => res, Err(err) => { - match err { - EVMError::Transaction(err) => { - if matches!(err, InvalidTransaction::NonceTooLow { .. }) { - // if the nonce is too low, we can skip this transaction - trace!(target: "payload_builder", %err, ?tx, "skipping nonce too low transaction"); - } else { - // if the transaction is invalid, we can skip it and all of its - // descendants - trace!(target: "payload_builder", %err, ?tx, "skipping invalid transaction and its descendants"); - best_txs.mark_invalid(tx.signer(), tx.nonce()); - } + if let Some(err) = err.as_invalid_tx_err() { + if err.is_nonce_too_low() { + // if the nonce is too low, we can skip this transaction + trace!(target: "payload_builder", %err, ?tx, "skipping nonce too low transaction"); + } else { + // if the transaction is invalid, we can skip it and all of its + // descendants + trace!(target: "payload_builder", %err, ?tx, "skipping invalid transaction and its descendants"); + best_txs.mark_invalid(tx.signer(), tx.nonce()); + } - continue - } - err => { - // this is an error that we should treat as fatal for this attempt - return Err(PayloadBuilderError::EvmExecutionError(err)) - } + continue } + // this is an error that we should treat as fatal for this attempt + return Err(PayloadBuilderError::EvmExecutionError(Box::new(err))) } }; diff --git a/crates/optimism/rpc/src/error.rs b/crates/optimism/rpc/src/error.rs index caafe798c..5147647b2 100644 --- a/crates/optimism/rpc/src/error.rs +++ b/crates/optimism/rpc/src/error.rs @@ -6,7 +6,7 @@ use reth_optimism_evm::OpBlockExecutionError; use reth_rpc_eth_api::AsEthApiError; use reth_rpc_eth_types::EthApiError; use reth_rpc_server_types::result::{internal_rpc_err, rpc_err}; -use revm::primitives::{InvalidTransaction, OptimismInvalidTransaction}; +use revm::primitives::{EVMError, InvalidTransaction, OptimismInvalidTransaction}; /// Optimism specific errors, that extend [`EthApiError`]. #[derive(Debug, thiserror::Error)] @@ -119,3 +119,12 @@ impl From for OpEthApiError { Self::Eth(error.into()) } } + +impl From> for OpEthApiError +where + EthApiError: From>, +{ + fn from(error: EVMError) -> Self { + Self::Eth(error.into()) + } +} diff --git a/crates/optimism/rpc/src/eth/block.rs b/crates/optimism/rpc/src/eth/block.rs index b53fd0730..faded8f39 100644 --- a/crates/optimism/rpc/src/eth/block.rs +++ b/crates/optimism/rpc/src/eth/block.rs @@ -40,8 +40,7 @@ where let excess_blob_gas = block.excess_blob_gas(); let timestamp = block.timestamp(); - let mut l1_block_info = - reth_optimism_evm::extract_l1_info(block.body()).map_err(OpEthApiError::from)?; + let mut l1_block_info = reth_optimism_evm::extract_l1_info(block.body())?; return block .body() diff --git a/crates/optimism/rpc/src/eth/call.rs b/crates/optimism/rpc/src/eth/call.rs index aed5cf689..21f2792b1 100644 --- a/crates/optimism/rpc/src/eth/call.rs +++ b/crates/optimism/rpc/src/eth/call.rs @@ -6,7 +6,7 @@ use reth_evm::ConfigureEvm; use reth_provider::ProviderHeader; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall, LoadBlock, LoadState, SpawnBlocking}, - FromEthApiError, FullEthApiTypes, IntoEthApiError, + FromEthApiError, FromEvmError, FullEthApiTypes, IntoEthApiError, }; use reth_rpc_eth_types::{revm_utils::CallFees, RpcInvalidTransactionError}; use revm::primitives::{BlockEnv, OptimismFields, TxEnv}; @@ -28,8 +28,10 @@ where impl Call for OpEthApi where - Self: LoadState, TxEnv = TxEnv>> - + SpawnBlocking, + Self: LoadState< + Evm: ConfigureEvm

, TxEnv = TxEnv>, + Error: FromEvmError, + > + SpawnBlocking, Self::Error: From, N: OpNodeCore, { diff --git a/crates/optimism/rpc/src/eth/mod.rs b/crates/optimism/rpc/src/eth/mod.rs index eb3e2b3bf..ecc53c9db 100644 --- a/crates/optimism/rpc/src/eth/mod.rs +++ b/crates/optimism/rpc/src/eth/mod.rs @@ -30,7 +30,7 @@ use reth_rpc_eth_api::{ AddDevSigners, EthApiSpec, EthFees, EthSigner, EthState, LoadBlock, LoadFee, LoadState, SpawnBlocking, Trace, }, - EthApiTypes, RpcNodeCore, RpcNodeCoreExt, + EthApiTypes, FromEvmError, RpcNodeCore, RpcNodeCoreExt, }; use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasPriceOracle}; use reth_tasks::{ @@ -252,6 +252,7 @@ where Header = ProviderHeader, Transaction = ProviderTx, >, + Error: FromEvmError, >, N: OpNodeCore, { diff --git a/crates/optimism/rpc/src/eth/pending_block.rs b/crates/optimism/rpc/src/eth/pending_block.rs index b33a3dda8..13e3d0351 100644 --- a/crates/optimism/rpc/src/eth/pending_block.rs +++ b/crates/optimism/rpc/src/eth/pending_block.rs @@ -21,7 +21,7 @@ use reth_provider::{ }; use reth_rpc_eth_api::{ helpers::{LoadPendingBlock, SpawnBlocking}, - EthApiTypes, FromEthApiError, RpcNodeCore, + EthApiTypes, FromEthApiError, FromEvmError, RpcNodeCore, }; use reth_rpc_eth_types::{EthApiError, PendingBlock}; use reth_transaction_pool::{PoolTransaction, TransactionPool}; @@ -34,6 +34,7 @@ where NetworkTypes: Network< HeaderResponse = alloy_rpc_types_eth::Header>, >, + Error: FromEvmError, >, N: RpcNodeCore< Provider: BlockReaderIdExt< diff --git a/crates/payload/primitives/Cargo.toml b/crates/payload/primitives/Cargo.toml index 4d1649184..7bab266e3 100644 --- a/crates/payload/primitives/Cargo.toml +++ b/crates/payload/primitives/Cargo.toml @@ -18,8 +18,6 @@ reth-errors.workspace = true reth-primitives.workspace = true reth-chain-state.workspace = true -revm-primitives.workspace = true - # alloy alloy-eips.workspace = true alloy-primitives.workspace = true @@ -39,7 +37,6 @@ default = ["std"] std = [ "reth-chainspec/std", "reth-primitives/std", - "revm-primitives/std", "alloy-eips/std", "alloy-primitives/std", "alloy-rpc-types-engine/std", diff --git a/crates/payload/primitives/src/error.rs b/crates/payload/primitives/src/error.rs index c4f518b66..5465c02f9 100644 --- a/crates/payload/primitives/src/error.rs +++ b/crates/payload/primitives/src/error.rs @@ -4,7 +4,6 @@ use alloc::boxed::Box; use alloy_primitives::B256; use alloy_rpc_types_engine::ForkchoiceUpdateError; use reth_errors::{ProviderError, RethError}; -use revm_primitives::EVMError; use tokio::sync::oneshot; /// Possible error variants during payload building. @@ -27,13 +26,21 @@ pub enum PayloadBuilderError { Internal(#[from] RethError), /// Unrecoverable error during evm execution. #[error("evm execution error: {0}")] - EvmExecutionError(EVMError), + EvmExecutionError(Box), /// Any other payload building errors. #[error(transparent)] Other(Box), } impl PayloadBuilderError { + /// Create a new EVM error from a boxed error. + pub fn evm(error: E) -> Self + where + E: core::error::Error + Send + Sync + 'static, + { + Self::EvmExecutionError(Box::new(error)) + } + /// Create a new error from a boxed error. pub fn other(error: E) -> Self where diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index d03776e98..33339e91c 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -17,7 +17,8 @@ use alloy_rpc_types_eth::{ }; use futures::Future; use reth_chainspec::EthChainSpec; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Evm, TransactionEnv}; +use reth_errors::ProviderError; +use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, TransactionEnv}; use reth_node_api::BlockBody; use reth_primitives_traits::SignedTransaction; use reth_provider::{BlockIdReader, ChainSpecProvider, ProviderHeader}; @@ -36,7 +37,7 @@ use reth_rpc_eth_types::{ simulate::{self, EthSimulateError}, EthApiError, RevertError, RpcInvalidTransactionError, StateCacheDb, }; -use revm::{Database, DatabaseCommit, GetInspector}; +use revm::{DatabaseCommit, GetInspector}; use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector}; use tracing::trace; @@ -473,7 +474,10 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA /// Executes code on state. pub trait Call: - LoadState>> + SpawnBlocking + LoadState< + Evm: ConfigureEvm
>, + Error: FromEvmError, + > + SpawnBlocking { /// Returns default gas limit to use for `eth_call` and tracing RPC methods. /// @@ -508,8 +512,7 @@ pub trait Call: Self::Error, > where - DB: Database, - EthApiError: From, + DB: Database, { let mut evm = self.evm_config().evm_with_env(db, evm_env.clone()); let res = evm.transact(tx_env.clone()).map_err(Self::Error::from_evm_err)?; @@ -534,8 +537,7 @@ pub trait Call: Self::Error, > where - DB: Database, - EthApiError: From, + DB: Database, { let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env.clone(), inspector); let res = evm.transact(tx_env.clone()).map_err(Self::Error::from_evm_err)?; @@ -704,8 +706,7 @@ pub trait Call: target_tx_hash: B256, ) -> Result where - DB: Database + DatabaseCommit, - EthApiError: From, + DB: Database + DatabaseCommit, I: IntoIterator::Transaction)>, ::Transaction: SignedTransaction, { diff --git a/crates/rpc/rpc-eth-api/src/helpers/estimate.rs b/crates/rpc/rpc-eth-api/src/helpers/estimate.rs index b64edaf16..ec8b17c76 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/estimate.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/estimate.rs @@ -6,7 +6,8 @@ use alloy_primitives::U256; use alloy_rpc_types_eth::{state::StateOverride, transaction::TransactionRequest, BlockId}; use futures::Future; use reth_chainspec::MIN_TRANSACTION_GAS; -use reth_evm::{env::EvmEnv, ConfigureEvmEnv, TransactionEnv}; +use reth_errors::ProviderError; +use reth_evm::{env::EvmEnv, ConfigureEvmEnv, Database, TransactionEnv}; use reth_provider::StateProvider; use reth_revm::{ database::StateProviderDatabase, @@ -18,7 +19,7 @@ use reth_rpc_eth_types::{ EthApiError, RevertError, RpcInvalidTransactionError, }; use reth_rpc_server_types::constants::gas_oracle::{CALL_STIPEND_GAS, ESTIMATE_GAS_ERROR_RATIO}; -use revm_primitives::{db::Database, TxKind}; +use revm_primitives::TxKind; use tracing::trace; /// Gas execution estimates @@ -286,7 +287,7 @@ pub trait EstimateCall: Call { db: &mut DB, ) -> Self::Error where - DB: Database, + DB: Database, EthApiError: From, { let req_gas_limit = tx_env.gas_limit(); diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 1c61ebc2c..46ff3d66a 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -13,7 +13,8 @@ use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_errors::RethError; use reth_evm::{ env::EvmEnv, state_change::post_block_withdrawals_balance_increments, - system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Evm, NextBlockEnvAttributes, + system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Evm, EvmError, InvalidTxError, + NextBlockEnvAttributes, }; use reth_primitives::{InvalidTransactionError, RecoveredBlock}; use reth_primitives_traits::Receipt; @@ -23,7 +24,7 @@ use reth_provider::{ }; use reth_revm::{ database::StateProviderDatabase, - primitives::{BlockEnv, EVMError, ExecutionResult, InvalidTransaction, ResultAndState}, + primitives::{BlockEnv, ExecutionResult, ResultAndState}, }; use reth_rpc_eth_types::{EthApiError, PendingBlock, PendingBlockEnv, PendingBlockEnvOrigin}; use reth_transaction_pool::{ @@ -43,6 +44,7 @@ pub trait LoadPendingBlock: NetworkTypes: Network< HeaderResponse = alloy_rpc_types_eth::Header>, >, + Error: FromEvmError, > + RpcNodeCore< Provider: BlockReaderIdExt + ChainSpecProvider @@ -334,27 +336,23 @@ pub trait LoadPendingBlock: let ResultAndState { result, state } = match evm.transact(tx_env) { Ok(res) => res, Err(err) => { - match err { - EVMError::Transaction(err) => { - if matches!(err, InvalidTransaction::NonceTooLow { .. }) { - // if the nonce is too low, we can skip this transaction - } else { - // if the transaction is invalid, we can skip it and all of its - // descendants - best_txs.mark_invalid( - &pool_tx, - InvalidPoolTransactionError::Consensus( - InvalidTransactionError::TxTypeNotSupported, - ), - ); - } - continue - } - err => { - // this is an error that we should treat as fatal for this attempt - return Err(Self::Error::from_evm_err(err)) + if let Some(err) = err.as_invalid_tx_err() { + if err.is_nonce_too_low() { + // if the nonce is too low, we can skip this transaction + } else { + // if the transaction is invalid, we can skip it and all of its + // descendants + best_txs.mark_invalid( + &pool_tx, + InvalidPoolTransactionError::Consensus( + InvalidTransactionError::TxTypeNotSupported, + ), + ); } + continue } + // this is an error that we should treat as fatal for this attempt + return Err(Self::Error::from_evm_err(err)); } }; // drop evm to release db reference. diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index 85cb1ce5b..5e08d81d8 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -7,7 +7,10 @@ use alloy_primitives::B256; use alloy_rpc_types_eth::{BlockId, TransactionInfo}; use futures::Future; use reth_chainspec::ChainSpecProvider; -use reth_evm::{env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Evm}; +use reth_errors::ProviderError; +use reth_evm::{ + env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Database, Evm, +}; use reth_primitives::RecoveredBlock; use reth_primitives_traits::{BlockBody, SignedTransaction}; use reth_provider::{BlockReader, ProviderBlock, ProviderHeader, ProviderTx}; @@ -16,7 +19,7 @@ use reth_rpc_eth_types::{ cache::db::{StateCacheDb, StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper}, EthApiError, }; -use revm::{db::CacheDB, Database, DatabaseCommit, GetInspector, Inspector}; +use revm::{db::CacheDB, DatabaseCommit, GetInspector, Inspector}; use revm_inspectors::tracing::{TracingInspector, TracingInspectorConfig}; use revm_primitives::{EvmState, ExecutionResult, ResultAndState}; use std::{fmt::Display, sync::Arc}; @@ -29,6 +32,7 @@ pub trait Trace: Header = ProviderHeader, Transaction = ProviderTx, >, + Error: FromEvmError, > { /// Executes the [`EvmEnv`] against the given [Database] without committing state @@ -48,8 +52,7 @@ pub trait Trace: Self::Error, > where - DB: Database, - EthApiError: From, + DB: Database, I: GetInspector, { let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env.clone(), inspector); diff --git a/crates/rpc/rpc-eth-api/src/types.rs b/crates/rpc/rpc-eth-api/src/types.rs index 2da1bdac2..f73dbb5a1 100644 --- a/crates/rpc/rpc-eth-api/src/types.rs +++ b/crates/rpc/rpc-eth-api/src/types.rs @@ -11,7 +11,7 @@ use reth_provider::{ProviderTx, ReceiptProvider, TransactionsProvider}; use reth_rpc_types_compat::TransactionCompat; use reth_transaction_pool::{PoolTransaction, TransactionPool}; -use crate::{AsEthApiError, FromEthApiError, FromEvmError, RpcNodeCore}; +use crate::{AsEthApiError, FromEthApiError, RpcNodeCore}; /// Network specific `eth` API types. pub trait EthApiTypes: Send + Sync + Clone { @@ -19,7 +19,6 @@ pub trait EthApiTypes: Send + Sync + Clone { type Error: Into> + FromEthApiError + AsEthApiError - + FromEvmError + Error + Send + Sync; diff --git a/crates/rpc/rpc-eth-types/src/error/api.rs b/crates/rpc/rpc-eth-types/src/error/api.rs index 419f530c4..bb2b5617e 100644 --- a/crates/rpc/rpc-eth-types/src/error/api.rs +++ b/crates/rpc/rpc-eth-types/src/error/api.rs @@ -1,7 +1,8 @@ //! Helper traits to wrap generic l1 errors, in network specific error type configured in //! `reth_rpc_eth_api::EthApiTypes`. -use revm_primitives::EVMError; +use reth_errors::ProviderError; +use reth_evm::ConfigureEvm; use crate::EthApiError; @@ -79,21 +80,16 @@ impl AsEthApiError for EthApiError { } /// Helper trait to convert from revm errors. -pub trait FromEvmError: From { - /// Converts from a revm error. - fn from_evm_err(err: EVMError) -> Self - where - EthApiError: From; -} - -impl FromEvmError for T -where - T: From, -{ - fn from_evm_err(err: EVMError) -> Self - where - EthApiError: From, - { - err.into_eth_err() +pub trait FromEvmError: From> { + /// Converts from EVM error to this type. + fn from_evm_err(err: Evm::EvmError) -> Self { + err.into() } } + +impl FromEvmError for T +where + T: From>, + Evm: ConfigureEvm, +{ +} diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index fc6f27f60..e241bf8a4 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -651,8 +651,9 @@ where let ExecutionWitnessRecord { hashed_state, codes, keys } = witness_record; - let state = - state_provider.witness(Default::default(), hashed_state).map_err(Into::into)?; + let state = state_provider + .witness(Default::default(), hashed_state) + .map_err(EthApiError::from)?; Ok(ExecutionWitness { state: state.into_iter().collect(), codes, keys }) }) .await diff --git a/crates/rpc/rpc/src/eth/helpers/call.rs b/crates/rpc/rpc/src/eth/helpers/call.rs index 898ca5d5a..2e08e7775 100644 --- a/crates/rpc/rpc/src/eth/helpers/call.rs +++ b/crates/rpc/rpc/src/eth/helpers/call.rs @@ -7,7 +7,7 @@ use reth_evm::ConfigureEvm; use reth_provider::{BlockReader, ProviderHeader}; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall, LoadPendingBlock, LoadState, SpawnBlocking}, - FromEthApiError, FullEthApiTypes, IntoEthApiError, + FromEthApiError, FromEvmError, FullEthApiTypes, IntoEthApiError, }; use reth_rpc_eth_types::{revm_utils::CallFees, RpcInvalidTransactionError}; use revm_primitives::{BlockEnv, TxEnv, TxKind, U256}; @@ -21,8 +21,10 @@ where impl Call for EthApi where - Self: LoadState>> - + SpawnBlocking, + Self: LoadState< + Evm: ConfigureEvm>, + Error: FromEvmError, + > + SpawnBlocking, EvmConfig: ConfigureEvm
, Provider: BlockReader, { diff --git a/crates/rpc/rpc/src/eth/helpers/pending_block.rs b/crates/rpc/rpc/src/eth/helpers/pending_block.rs index cabc0d011..f4bf68737 100644 --- a/crates/rpc/rpc/src/eth/helpers/pending_block.rs +++ b/crates/rpc/rpc/src/eth/helpers/pending_block.rs @@ -13,7 +13,7 @@ use reth_provider::{ }; use reth_rpc_eth_api::{ helpers::{LoadPendingBlock, SpawnBlocking}, - RpcNodeCore, + FromEvmError, RpcNodeCore, }; use reth_rpc_eth_types::PendingBlock; use reth_transaction_pool::{PoolTransaction, TransactionPool}; @@ -26,6 +26,7 @@ impl LoadPendingBlock where Self: SpawnBlocking< NetworkTypes: alloy_network::Network, + Error: FromEvmError, > + RpcNodeCore< Provider: BlockReaderIdExt< Transaction = reth_primitives::TransactionSigned, diff --git a/crates/rpc/rpc/src/eth/helpers/trace.rs b/crates/rpc/rpc/src/eth/helpers/trace.rs index 69b4d9806..f18c76b32 100644 --- a/crates/rpc/rpc/src/eth/helpers/trace.rs +++ b/crates/rpc/rpc/src/eth/helpers/trace.rs @@ -2,7 +2,10 @@ use reth_evm::ConfigureEvm; use reth_provider::{BlockReader, ProviderHeader, ProviderTx}; -use reth_rpc_eth_api::helpers::{LoadState, Trace}; +use reth_rpc_eth_api::{ + helpers::{LoadState, Trace}, + FromEvmError, +}; use crate::EthApi; @@ -14,6 +17,7 @@ where Header = ProviderHeader, Transaction = ProviderTx, >, + Error: FromEvmError, >, Provider: BlockReader, { diff --git a/crates/rpc/rpc/src/eth/sim_bundle.rs b/crates/rpc/rpc/src/eth/sim_bundle.rs index 940fa48f9..103bfeafd 100644 --- a/crates/rpc/rpc/src/eth/sim_bundle.rs +++ b/crates/rpc/rpc/src/eth/sim_bundle.rs @@ -14,7 +14,7 @@ use reth_revm::database::StateProviderDatabase; use reth_rpc_api::MevSimApiServer; use reth_rpc_eth_api::{ helpers::{Call, EthTransactions, LoadPendingBlock}, - FromEthApiError, + FromEthApiError, FromEvmError, }; use reth_rpc_eth_types::{utils::recover_raw_transaction, EthApiError}; use reth_tasks::pool::BlockingTaskGuard; @@ -307,7 +307,7 @@ where let ResultAndState { result, state } = evm .transact(eth_api.evm_config().tx_env(&item.tx, item.signer)) - .map_err(EthApiError::from_eth_err)?; + .map_err(Eth::Error::from_evm_err)?; if !result.is_success() && !item.can_revert { return Err(EthApiError::InvalidParams( diff --git a/examples/custom-beacon-withdrawals/src/main.rs b/examples/custom-beacon-withdrawals/src/main.rs index 8e52447ac..5e2bdae99 100644 --- a/examples/custom-beacon-withdrawals/src/main.rs +++ b/examples/custom-beacon-withdrawals/src/main.rs @@ -11,10 +11,9 @@ use reth::{ api::{ConfigureEvm, NodeTypesWithEngine}, builder::{components::ExecutorBuilder, BuilderContext, FullNodeTypes}, cli::Cli, - providers::ProviderError, revm::{ primitives::{address, Address}, - Database, DatabaseCommit, State, + DatabaseCommit, State, }, }; use reth_chainspec::{ChainSpec, EthereumHardforks}; @@ -23,7 +22,7 @@ use reth_evm::{ BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, ExecuteOutput, InternalBlockExecutionError, }, - Evm, + Database, Evm, }; use reth_evm_ethereum::EthEvmConfig; use reth_node_ethereum::{node::EthereumAddOns, BasicBlockExecutorProvider, EthereumNode}; @@ -90,11 +89,11 @@ pub struct CustomExecutorStrategyFactory { impl BlockExecutionStrategyFactory for CustomExecutorStrategyFactory { type Primitives = EthPrimitives; - type Strategy + Display>> = CustomExecutorStrategy; + type Strategy = CustomExecutorStrategy; fn create_strategy(&self, db: DB) -> Self::Strategy where - DB: Database + Display>, + DB: Database, { let state = State::builder().with_database(db).with_bundle_update().without_state_clear().build(); @@ -108,7 +107,7 @@ impl BlockExecutionStrategyFactory for CustomExecutorStrategyFactory { pub struct CustomExecutorStrategy where - DB: Database + Display>, + DB: Database, { /// The chainspec chain_spec: Arc, @@ -120,7 +119,7 @@ where impl BlockExecutionStrategy for CustomExecutorStrategy where - DB: Database + Display>, + DB: Database, { type DB = DB; type Primitives = EthPrimitives; diff --git a/examples/custom-evm/src/main.rs b/examples/custom-evm/src/main.rs index 4efa8d86b..08fcc578b 100644 --- a/examples/custom-evm/src/main.rs +++ b/examples/custom-evm/src/main.rs @@ -15,15 +15,17 @@ use reth::{ handler::register::EvmHandler, inspector_handle_register, precompile::{Precompile, PrecompileOutput, PrecompileSpecId}, - primitives::{CfgEnvWithHandlerCfg, Env, HandlerCfg, PrecompileResult, SpecId, TxEnv}, - ContextPrecompiles, Database, EvmBuilder, GetInspector, + primitives::{ + CfgEnvWithHandlerCfg, EVMError, Env, HandlerCfg, PrecompileResult, SpecId, TxEnv, + }, + ContextPrecompiles, EvmBuilder, GetInspector, }, rpc::types::engine::PayloadAttributes, tasks::TaskManager, transaction_pool::{PoolTransaction, TransactionPool}, }; use reth_chainspec::{Chain, ChainSpec}; -use reth_evm::env::EvmEnv; +use reth_evm::{env::EvmEnv, Database}; use reth_evm_ethereum::{EthEvm, EthEvmConfig}; use reth_node_api::{ ConfigureEvm, ConfigureEvmEnv, FullNodeTypes, NextBlockEnvAttributes, NodeTypes, @@ -109,6 +111,7 @@ impl ConfigureEvmEnv for MyEvmConfig { impl ConfigureEvm for MyEvmConfig { type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>; + type EvmError = EVMError; fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { diff --git a/examples/stateful-precompile/src/main.rs b/examples/stateful-precompile/src/main.rs index 92599b79f..99568e9c3 100644 --- a/examples/stateful-precompile/src/main.rs +++ b/examples/stateful-precompile/src/main.rs @@ -14,15 +14,15 @@ use reth::{ inspector_handle_register, precompile::{Precompile, PrecompileSpecId}, primitives::{ - CfgEnvWithHandlerCfg, Env, HandlerCfg, PrecompileResult, SpecId, StatefulPrecompileMut, - TxEnv, + CfgEnvWithHandlerCfg, EVMError, Env, HandlerCfg, PrecompileResult, SpecId, + StatefulPrecompileMut, TxEnv, }, - ContextPrecompile, ContextPrecompiles, Database, EvmBuilder, GetInspector, + ContextPrecompile, ContextPrecompiles, EvmBuilder, GetInspector, }, tasks::TaskManager, }; use reth_chainspec::{Chain, ChainSpec}; -use reth_evm::env::EvmEnv; +use reth_evm::{env::EvmEnv, Database}; use reth_node_api::{ConfigureEvm, ConfigureEvmEnv, FullNodeTypes, NodeTypes}; use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig}; use reth_node_ethereum::{ @@ -173,6 +173,7 @@ impl ConfigureEvmEnv for MyEvmConfig { impl ConfigureEvm for MyEvmConfig { type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>; + type EvmError = EVMError; fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg {