diff --git a/crates/ethereum/node/src/node.rs b/crates/ethereum/node/src/node.rs index dee30efe006..f5d138be4b2 100644 --- a/crates/ethereum/node/src/node.rs +++ b/crates/ethereum/node/src/node.rs @@ -15,7 +15,7 @@ use reth_ethereum_engine_primitives::{ use reth_ethereum_primitives::{EthPrimitives, TransactionSigned}; use reth_evm::{ eth::spec::EthExecutorSpec, ConfigureEvm, EvmFactory, EvmFactoryFor, NextBlockEnvAttributes, - TxEnvFor, + SpecFor, TxEnvFor, }; use reth_network::{primitives::BasicNetworkPrimitives, NetworkHandle, PeersInfo}; use reth_node_api::{ @@ -160,6 +160,7 @@ where TxEnv = TxEnvFor, Error = EthApiError, Network = NetworkT, + Spec = SpecFor, >, EthApiError: FromEvmError, { diff --git a/crates/optimism/rpc/src/eth/call.rs b/crates/optimism/rpc/src/eth/call.rs index e929ef7ca75..b7ce75c51b2 100644 --- a/crates/optimism/rpc/src/eth/call.rs +++ b/crates/optimism/rpc/src/eth/call.rs @@ -1,5 +1,5 @@ use crate::{eth::RpcNodeCore, OpEthApi, OpEthApiError}; -use reth_evm::TxEnvFor; +use reth_evm::{SpecFor, TxEnvFor}; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall}, FromEvmError, RpcConvert, @@ -9,7 +9,12 @@ impl EthCall for OpEthApi where N: RpcNodeCore, OpEthApiError: FromEvmError, - Rpc: RpcConvert>, + Rpc: RpcConvert< + Primitives = N::Primitives, + Error = OpEthApiError, + TxEnv = TxEnvFor, + Spec = SpecFor, + >, { } @@ -17,7 +22,12 @@ impl EstimateCall for OpEthApi where N: RpcNodeCore, OpEthApiError: FromEvmError, - Rpc: RpcConvert>, + Rpc: RpcConvert< + Primitives = N::Primitives, + Error = OpEthApiError, + TxEnv = TxEnvFor, + Spec = SpecFor, + >, { } @@ -25,7 +35,12 @@ impl Call for OpEthApi where N: RpcNodeCore, OpEthApiError: FromEvmError, - Rpc: RpcConvert>, + Rpc: RpcConvert< + Primitives = N::Primitives, + Error = OpEthApiError, + TxEnv = TxEnvFor, + Spec = SpecFor, + >, { #[inline] fn call_gas_limit(&self) -> u64 { diff --git a/crates/rpc/rpc-convert/src/transaction.rs b/crates/rpc/rpc-convert/src/transaction.rs index affba2aa0a4..c5bc4b71c0d 100644 --- a/crates/rpc/rpc-convert/src/transaction.rs +++ b/crates/rpc/rpc-convert/src/transaction.rs @@ -16,7 +16,7 @@ use alloy_rpc_types_eth::{ use core::error; use reth_evm::{ revm::context_interface::{either::Either, Block}, - ConfigureEvm, TxEnvFor, + ConfigureEvm, SpecFor, TxEnvFor, }; use reth_primitives_traits::{ HeaderTy, NodePrimitives, SealedHeader, SealedHeaderFor, TransactionMeta, TxTy, @@ -107,6 +107,9 @@ pub trait RpcConvert: Send + Sync + Unpin + Clone + Debug + 'static { /// An associated RPC conversion error. type Error: error::Error + Into>; + /// The EVM specification identifier. + type Spec; + /// Wrapper for `fill()` with default `TransactionInfo` /// Create a new rpc transaction result for a _pending_ signed transaction, setting block /// environment related fields to `None`. @@ -137,10 +140,10 @@ pub trait RpcConvert: Send + Sync + Unpin + Clone + Debug + 'static { /// Creates a transaction environment for execution based on `request` with corresponding /// `cfg_env` and `block_env`. - fn tx_env( + fn tx_env( &self, request: RpcTxReq, - cfg_env: &CfgEnv, + cfg_env: &CfgEnv, block_env: &BlockEnv, ) -> Result; @@ -369,6 +372,79 @@ impl TryIntoSimTx> for TransactionRequest { } } +/// Converts `TxReq` into `TxEnv`. +/// +/// Where: +/// * `TxReq` is a transaction request received from an RPC API +/// * `TxEnv` is the corresponding transaction environment for execution +/// +/// The `TxEnvConverter` has two blanket implementations: +/// * `()` assuming `TxReq` implements [`TryIntoTxEnv`] and is used as default for [`RpcConverter`]. +/// * `Fn(TxReq, &CfgEnv, &BlockEnv) -> Result` and can be applied using +/// [`RpcConverter::with_tx_env_converter`]. +/// +/// One should prefer to implement [`TryIntoTxEnv`] for `TxReq` to get the `TxEnvConverter` +/// implementation for free, thanks to the blanket implementation, unless the conversion requires +/// more context. For example, some configuration parameters or access handles to database, network, +/// etc. +pub trait TxEnvConverter: + Debug + Send + Sync + Unpin + Clone + 'static +{ + /// An associated error that can occur during conversion. + type Error; + + /// Converts a rpc transaction request into a transaction environment. + /// + /// See [`TxEnvConverter`] for more information. + fn convert_tx_env( + &self, + tx_req: TxReq, + cfg_env: &CfgEnv, + block_env: &BlockEnv, + ) -> Result; +} + +impl TxEnvConverter for () +where + TxReq: TryIntoTxEnv, +{ + type Error = TxReq::Err; + + fn convert_tx_env( + &self, + tx_req: TxReq, + cfg_env: &CfgEnv, + block_env: &BlockEnv, + ) -> Result { + tx_req.try_into_tx_env(cfg_env, block_env) + } +} + +/// Converts rpc transaction requests into transaction environment using a closure. +impl TxEnvConverter for F +where + F: Fn(TxReq, &CfgEnv, &BlockEnv) -> Result + + Debug + + Send + + Sync + + Unpin + + Clone + + 'static, + TxReq: Clone, + E: error::Error + Send + Sync + 'static, +{ + type Error = E; + + fn convert_tx_env( + &self, + tx_req: TxReq, + cfg_env: &CfgEnv, + block_env: &BlockEnv, + ) -> Result { + self(tx_req, cfg_env, block_env) + } +} + /// Converts `self` into `T`. /// /// Should create an executable transaction environment using [`TransactionRequest`]. @@ -499,18 +575,29 @@ pub struct TransactionConversionError(String); /// network and EVM associated primitives: /// * [`FromConsensusTx`]: from signed transaction into RPC response object. /// * [`TryIntoSimTx`]: from RPC transaction request into a simulated transaction. -/// * [`TryIntoTxEnv`]: from RPC transaction request into an executable transaction. +/// * [`TryIntoTxEnv`] or [`TxEnvConverter`]: from RPC transaction request into an executable +/// transaction. /// * [`TxInfoMapper`]: from [`TransactionInfo`] into [`FromConsensusTx::TxInfo`]. Should be /// implemented for a dedicated struct that is assigned to `Map`. If [`FromConsensusTx::TxInfo`] /// is [`TransactionInfo`] then `()` can be used as `Map` which trivially passes over the input /// object. #[derive(Debug)] -pub struct RpcConverter { +pub struct RpcConverter< + Network, + Evm, + Receipt, + Header = (), + Map = (), + SimTx = (), + RpcTx = (), + TxEnv = (), +> { network: PhantomData, evm: PhantomData, receipt_converter: Receipt, header_converter: Header, mapper: Map, + tx_env_converter: TxEnv, sim_tx_converter: SimTx, rpc_tx_converter: RpcTx, } @@ -524,17 +611,20 @@ impl RpcConverter { receipt_converter, header_converter: (), mapper: (), + tx_env_converter: (), sim_tx_converter: (), rpc_tx_converter: (), } } } -impl - RpcConverter +impl + RpcConverter { /// Converts the network type - pub fn with_network(self) -> RpcConverter { + pub fn with_network( + self, + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -542,6 +632,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, .. } = self; RpcConverter { @@ -552,6 +643,35 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, + } + } + + /// Converts the transaction environment type. + pub fn with_tx_env_converter( + self, + tx_env_converter: TxEnvNew, + ) -> RpcConverter { + let Self { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + tx_env_converter: _, + .. + } = self; + RpcConverter { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + tx_env_converter, } } @@ -559,7 +679,7 @@ impl pub fn with_header_converter( self, header_converter: HeaderNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter: _, @@ -568,6 +688,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, } = self; RpcConverter { receipt_converter, @@ -577,6 +698,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, } } @@ -584,7 +706,7 @@ impl pub fn with_mapper( self, mapper: MapNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -593,6 +715,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, } = self; RpcConverter { receipt_converter, @@ -602,6 +725,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, } } @@ -609,7 +733,7 @@ impl pub fn with_sim_tx_converter( self, sim_tx_converter: SimTxNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -617,6 +741,7 @@ impl network, evm, rpc_tx_converter, + tx_env_converter, .. } = self; RpcConverter { @@ -627,6 +752,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, } } @@ -634,7 +760,7 @@ impl pub fn with_rpc_tx_converter( self, rpc_tx_converter: RpcTxNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -642,6 +768,7 @@ impl network, evm, sim_tx_converter, + tx_env_converter, .. } = self; RpcConverter { @@ -652,18 +779,20 @@ impl evm, sim_tx_converter, rpc_tx_converter, + tx_env_converter, } } } -impl Default - for RpcConverter +impl Default + for RpcConverter where Receipt: Default, Header: Default, Map: Default, SimTx: Default, RpcTx: Default, + TxEnv: Default, { fn default() -> Self { Self { @@ -674,12 +803,21 @@ where mapper: Default::default(), sim_tx_converter: Default::default(), rpc_tx_converter: Default::default(), + tx_env_converter: Default::default(), } } } -impl Clone - for RpcConverter +impl< + Network, + Evm, + Receipt: Clone, + Header: Clone, + Map: Clone, + SimTx: Clone, + RpcTx: Clone, + TxEnv: Clone, + > Clone for RpcConverter { fn clone(&self) -> Self { Self { @@ -690,23 +828,22 @@ impl RpcConvert - for RpcConverter +impl RpcConvert + for RpcConverter where N: NodePrimitives, Network: RpcTypes + Send + Sync + Unpin + Clone + Debug, Evm: ConfigureEvm + 'static, - TxTy: Clone + Debug, - RpcTxReq: TryIntoTxEnv>, Receipt: ReceiptConverter< N, RpcReceipt = RpcReceipt, Error: From - + From< as TryIntoTxEnv>>::Err> + + From + From<>>::Err> + From + Error @@ -724,11 +861,13 @@ where SimTx: SimTxConverter, TxTy>, RpcTx: RpcTxConverter, Network::TransactionResponse, >>::Out>, + TxEnv: TxEnvConverter, TxEnvFor, SpecFor>, { type Primitives = N; type Network = Network; type TxEnv = TxEnvFor; type Error = Receipt::Error; + type Spec = SpecFor; fn fill( &self, @@ -751,13 +890,13 @@ where .map_err(|e| TransactionConversionError(e.to_string()))?) } - fn tx_env( + fn tx_env( &self, request: RpcTxReq, - cfg_env: &CfgEnv, + cfg_env: &CfgEnv>, block_env: &BlockEnv, ) -> Result { - Ok(request.try_into_tx_env(cfg_env, block_env)?) + self.tx_env_converter.convert_tx_env(request, cfg_env, block_env).map_err(Into::into) } fn convert_receipts( diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index b95b290de46..726f6b5776e 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -452,7 +452,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA /// Executes code on state. pub trait Call: LoadState< - RpcConvert: RpcConvert>, + RpcConvert: RpcConvert, Spec = SpecFor>, Error: FromEvmError + From<::Error> + From, diff --git a/crates/rpc/rpc/src/eth/helpers/call.rs b/crates/rpc/rpc/src/eth/helpers/call.rs index 8a8377f7abc..a76e146042d 100644 --- a/crates/rpc/rpc/src/eth/helpers/call.rs +++ b/crates/rpc/rpc/src/eth/helpers/call.rs @@ -1,7 +1,7 @@ //! Contains RPC handler implementations specific to endpoints that call/execute within evm. use crate::EthApi; -use reth_evm::TxEnvFor; +use reth_evm::{SpecFor, TxEnvFor}; use reth_rpc_convert::RpcConvert; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall}, @@ -13,7 +13,12 @@ impl EthCall for EthApi where N: RpcNodeCore, EthApiError: FromEvmError, - Rpc: RpcConvert>, + Rpc: RpcConvert< + Primitives = N::Primitives, + Error = EthApiError, + TxEnv = TxEnvFor, + Spec = SpecFor, + >, { } @@ -21,7 +26,12 @@ impl Call for EthApi where N: RpcNodeCore, EthApiError: FromEvmError, - Rpc: RpcConvert>, + Rpc: RpcConvert< + Primitives = N::Primitives, + Error = EthApiError, + TxEnv = TxEnvFor, + Spec = SpecFor, + >, { #[inline] fn call_gas_limit(&self) -> u64 { @@ -38,6 +48,11 @@ impl EstimateCall for EthApi where N: RpcNodeCore, EthApiError: FromEvmError, - Rpc: RpcConvert>, + Rpc: RpcConvert< + Primitives = N::Primitives, + Error = EthApiError, + TxEnv = TxEnvFor, + Spec = SpecFor, + >, { }