diff --git a/crates/optimism/rpc/src/error.rs b/crates/optimism/rpc/src/error.rs index f5445863497..40d34ef7cc0 100644 --- a/crates/optimism/rpc/src/error.rs +++ b/crates/optimism/rpc/src/error.rs @@ -11,7 +11,7 @@ use reth_rpc_eth_api::{AsEthApiError, EthTxEnvError, TransactionConversionError} use reth_rpc_eth_types::{error::api::FromEvmHalt, EthApiError}; use reth_rpc_server_types::result::{internal_rpc_err, rpc_err}; use revm::context_interface::result::{EVMError, InvalidTransaction}; -use std::fmt::Display; +use std::{convert::Infallible, fmt::Display}; /// Optimism specific errors, that extend [`EthApiError`]. #[derive(Debug, thiserror::Error)] @@ -212,3 +212,9 @@ impl From for OpEthApiError { Self::Eth(EthApiError::from(value)) } } + +impl From for OpEthApiError { + fn from(value: Infallible) -> Self { + match value {} + } +} diff --git a/crates/optimism/rpc/src/eth/transaction.rs b/crates/optimism/rpc/src/eth/transaction.rs index f8437c12623..c6f4e4e04d2 100644 --- a/crates/optimism/rpc/src/eth/transaction.rs +++ b/crates/optimism/rpc/src/eth/transaction.rs @@ -112,7 +112,7 @@ impl OpTxInfoMapper { } } -impl TxInfoMapper<&T> for OpTxInfoMapper +impl TxInfoMapper for OpTxInfoMapper where T: OpTransaction + SignedTransaction, Provider: ReceiptProvider, diff --git a/crates/rpc/rpc-convert/src/transaction.rs b/crates/rpc/rpc-convert/src/transaction.rs index e33d254e272..affba2aa0a4 100644 --- a/crates/rpc/rpc-convert/src/transaction.rs +++ b/crates/rpc/rpc-convert/src/transaction.rs @@ -223,6 +223,60 @@ where } } +/// Converts `Tx` into `RpcTx` +/// +/// Where: +/// * `Tx` is a transaction from the consensus layer. +/// * `RpcTx` is a transaction response object of the RPC API +/// +/// The conversion function is accompanied by `signer`'s address and `tx_info` providing extra +/// context about a transaction in a block. +/// +/// The `RpcTxConverter` has two blanket implementations: +/// * `()` assuming `Tx` implements [`IntoRpcTx`] and is used as default for [`RpcConverter`]. +/// * `Fn(Tx, Address, TxInfo) -> RpcTx` and can be applied using +/// [`RpcConverter::with_rpc_tx_converter`]. +/// +/// One should prefer to implement [`IntoRpcTx`] for `Tx` to get the `RpcTxConverter` 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 RpcTxConverter: Clone + Debug + Unpin + Send + Sync + 'static { + /// An associated error that can happen during the conversion. + type Err; + + /// Performs the conversion of `tx` from `Tx` into `RpcTx`. + /// + /// See [`RpcTxConverter`] for more information. + fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result; +} + +impl RpcTxConverter for () +where + Tx: IntoRpcTx, +{ + type Err = Infallible; + + fn convert_rpc_tx( + &self, + tx: Tx, + signer: Address, + tx_info: Tx::TxInfo, + ) -> Result { + Ok(tx.into_rpc_tx(signer, tx_info)) + } +} + +impl RpcTxConverter for F +where + F: Fn(Tx, Address, TxInfo) -> Result + Clone + Debug + Unpin + Send + Sync + 'static, +{ + type Err = E; + + fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result { + self(tx, signer, tx_info) + } +} + /// Converts `TxReq` into `SimTx`. /// /// Where: @@ -297,10 +351,10 @@ pub trait TxInfoMapper { type Err; /// Performs the conversion. - fn try_map(&self, tx: T, tx_info: TransactionInfo) -> Result; + fn try_map(&self, tx: &T, tx_info: TransactionInfo) -> Result; } -impl TxInfoMapper<&T> for () { +impl TxInfoMapper for () { type Out = TransactionInfo; type Err = Infallible; @@ -451,13 +505,14 @@ pub struct TransactionConversionError(String); /// is [`TransactionInfo`] then `()` can be used as `Map` which trivially passes over the input /// object. #[derive(Debug)] -pub struct RpcConverter { +pub struct RpcConverter { network: PhantomData, evm: PhantomData, receipt_converter: Receipt, header_converter: Header, mapper: Map, sim_tx_converter: SimTx, + rpc_tx_converter: RpcTx, } impl RpcConverter { @@ -470,16 +525,25 @@ impl RpcConverter { header_converter: (), mapper: (), sim_tx_converter: (), + rpc_tx_converter: (), } } } -impl - RpcConverter +impl + RpcConverter { /// Converts the network type - pub fn with_network(self) -> RpcConverter { - let Self { receipt_converter, header_converter, mapper, evm, sim_tx_converter, .. } = self; + pub fn with_network(self) -> RpcConverter { + let Self { + receipt_converter, + header_converter, + mapper, + evm, + sim_tx_converter, + rpc_tx_converter, + .. + } = self; RpcConverter { receipt_converter, header_converter, @@ -487,6 +551,7 @@ impl network: Default::default(), evm, sim_tx_converter, + rpc_tx_converter, } } @@ -494,39 +559,111 @@ impl pub fn with_header_converter( self, header_converter: HeaderNew, - ) -> RpcConverter { - let Self { receipt_converter, header_converter: _, mapper, network, evm, sim_tx_converter } = - self; - RpcConverter { receipt_converter, header_converter, mapper, network, evm, sim_tx_converter } + ) -> RpcConverter { + let Self { + receipt_converter, + header_converter: _, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + } = self; + RpcConverter { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + } } /// Configures the mapper. pub fn with_mapper( self, mapper: MapNew, - ) -> RpcConverter { - let Self { receipt_converter, header_converter, mapper: _, network, evm, sim_tx_converter } = - self; - RpcConverter { receipt_converter, header_converter, mapper, network, evm, sim_tx_converter } + ) -> RpcConverter { + let Self { + receipt_converter, + header_converter, + mapper: _, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + } = self; + RpcConverter { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + } } /// Swaps the simulate transaction converter with `sim_tx_converter`. pub fn with_sim_tx_converter( self, sim_tx_converter: SimTxNew, - ) -> RpcConverter { - let Self { receipt_converter, header_converter, mapper, network, evm, .. } = self; - RpcConverter { receipt_converter, header_converter, mapper, network, evm, sim_tx_converter } + ) -> RpcConverter { + let Self { + receipt_converter, + header_converter, + mapper, + network, + evm, + rpc_tx_converter, + .. + } = self; + RpcConverter { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + } + } + + /// Swaps the RPC transaction converter with `rpc_tx_converter`. + pub fn with_rpc_tx_converter( + self, + rpc_tx_converter: RpcTxNew, + ) -> RpcConverter { + let Self { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + .. + } = self; + RpcConverter { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + } } } -impl Default - for RpcConverter +impl Default + for RpcConverter where Receipt: Default, Header: Default, Map: Default, SimTx: Default, + RpcTx: Default, { fn default() -> Self { Self { @@ -536,12 +673,13 @@ where header_converter: Default::default(), mapper: Default::default(), sim_tx_converter: Default::default(), + rpc_tx_converter: Default::default(), } } } -impl Clone - for RpcConverter +impl Clone + for RpcConverter { fn clone(&self) -> Self { Self { @@ -551,24 +689,26 @@ impl Clon header_converter: self.header_converter.clone(), mapper: self.mapper.clone(), sim_tx_converter: self.sim_tx_converter.clone(), + rpc_tx_converter: self.rpc_tx_converter.clone(), } } } -impl RpcConvert - for RpcConverter +impl RpcConvert + for RpcConverter where N: NodePrimitives, Network: RpcTypes + Send + Sync + Unpin + Clone + Debug, Evm: ConfigureEvm + 'static, - TxTy: IntoRpcTx + Clone + Debug, + TxTy: Clone + Debug, RpcTxReq: TryIntoTxEnv>, Receipt: ReceiptConverter< N, RpcReceipt = RpcReceipt, Error: From + From< as TryIntoTxEnv>>::Err> - + for<'a> From<>>::Err> + + From<>>::Err> + + From + Error + Unpin + Sync @@ -580,16 +720,10 @@ where + Clone + Debug, Header: HeaderConverter, RpcHeader>, - Map: for<'a> TxInfoMapper< - &'a TxTy, - Out = as IntoRpcTx>::TxInfo, - > + Clone - + Debug - + Unpin - + Send - + Sync - + 'static, + Map: TxInfoMapper> + Clone + Debug + Unpin + Send + Sync + 'static, SimTx: SimTxConverter, TxTy>, + RpcTx: + RpcTxConverter, Network::TransactionResponse, >>::Out>, { type Primitives = N; type Network = Network; @@ -604,7 +738,7 @@ where let (tx, signer) = tx.into_parts(); let tx_info = self.mapper.try_map(&tx, tx_info)?; - Ok(tx.into_rpc_tx(signer, tx_info)) + Ok(self.rpc_tx_converter.convert_rpc_tx(tx, signer, tx_info)?) } fn build_simulate_v1_transaction(