feat: abstract over Evm::Error (#14085)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Arsenii Kulikov
2025-01-30 17:02:20 +04:00
committed by GitHub
parent 6b13409812
commit 98a021ee7d
40 changed files with 298 additions and 247 deletions

View File

@ -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<N> + Clone + Unpin + Sync + Send + 'static,
{
type Primitives = N;
type Strategy<DB: Database<Error: Into<ProviderError> + Display>> =
OpExecutionStrategy<DB, N, EvmConfig>;
type Strategy<DB: Database> = OpExecutionStrategy<DB, N, EvmConfig>;
fn create_strategy<DB>(&self, db: DB) -> Self::Strategy<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
DB: Database,
{
let state =
State::builder().with_database(db).with_bundle_update().without_state_clear().build();
@ -131,7 +128,7 @@ where
impl<DB, N, EvmConfig> BlockExecutionStrategy for OpExecutionStrategy<DB, N, EvmConfig>
where
DB: Database<Error: Into<ProviderError> + 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),
}
})?;

View File

@ -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<DBError: core::error::Error + Send + Sync + 'static> = EVMError<DBError>;
fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> {
let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg {

View File

@ -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

View File

@ -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<TxEnv = TxEnv>,
>,
OpEthApiError: FromEvmError<N::Evm>,
{
type Handle = RpcHandle<N, OpEthApi<N>>;
@ -241,8 +245,9 @@ where
Storage = OpStorage,
Engine = OpEngineTypes,
>,
Evm: ConfigureEvmEnv<TxEnv = TxEnv>,
Evm: ConfigureEvm<TxEnv = TxEnv>,
>,
OpEthApiError: FromEvmError<N::Evm>,
{
type EthApi = OpEthApi<N>;

View File

@ -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)))
}
};

View File

@ -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<BlockError> for OpEthApiError {
Self::Eth(error.into())
}
}
impl<DB> From<EVMError<DB>> for OpEthApiError
where
EthApiError: From<EVMError<DB>>,
{
fn from(error: EVMError<DB>) -> Self {
Self::Eth(error.into())
}
}

View File

@ -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()

View File

@ -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<N> Call for OpEthApi<N>
where
Self: LoadState<Evm: ConfigureEvm<Header = ProviderHeader<Self::Provider>, TxEnv = TxEnv>>
+ SpawnBlocking,
Self: LoadState<
Evm: ConfigureEvm<Header = ProviderHeader<Self::Provider>, TxEnv = TxEnv>,
Error: FromEvmError<Self::Evm>,
> + SpawnBlocking,
Self::Error: From<OpEthApiError>,
N: OpNodeCore,
{

View File

@ -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<Self::Provider>,
Transaction = ProviderTx<Self::Provider>,
>,
Error: FromEvmError<Self::Evm>,
>,
N: OpNodeCore,
{

View File

@ -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<ProviderHeader<Self::Provider>>,
>,
Error: FromEvmError<Self::Evm>,
>,
N: RpcNodeCore<
Provider: BlockReaderIdExt<