Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion crates/optimism/rpc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -212,3 +212,9 @@ impl From<BlockError> for OpEthApiError {
Self::Eth(EthApiError::from(value))
}
}

impl From<Infallible> for OpEthApiError {
fn from(value: Infallible) -> Self {
match value {}
}
}
2 changes: 1 addition & 1 deletion crates/optimism/rpc/src/eth/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl<Provider> OpTxInfoMapper<Provider> {
}
}

impl<T, Provider> TxInfoMapper<&T> for OpTxInfoMapper<Provider>
impl<T, Provider> TxInfoMapper<T> for OpTxInfoMapper<Provider>
where
T: OpTransaction + SignedTransaction,
Provider: ReceiptProvider<Receipt: DepositReceipt>,
Expand Down
206 changes: 170 additions & 36 deletions crates/rpc/rpc-convert/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Tx, RpcTx, TxInfo>: 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<RpcTx, Self::Err>;
}

impl<Tx, RpcTx> RpcTxConverter<Tx, RpcTx, Tx::TxInfo> for ()
where
Tx: IntoRpcTx<RpcTx>,
{
type Err = Infallible;

fn convert_rpc_tx(
&self,
tx: Tx,
signer: Address,
tx_info: Tx::TxInfo,
) -> Result<RpcTx, Self::Err> {
Ok(tx.into_rpc_tx(signer, tx_info))
}
}

impl<Tx, RpcTx, F, TxInfo, E> RpcTxConverter<Tx, RpcTx, TxInfo> for F
where
F: Fn(Tx, Address, TxInfo) -> Result<RpcTx, E> + Clone + Debug + Unpin + Send + Sync + 'static,
{
type Err = E;

fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err> {
self(tx, signer, tx_info)
}
}

/// Converts `TxReq` into `SimTx`.
///
/// Where:
Expand Down Expand Up @@ -297,10 +351,10 @@ pub trait TxInfoMapper<T> {
type Err;

/// Performs the conversion.
fn try_map(&self, tx: T, tx_info: TransactionInfo) -> Result<Self::Out, Self::Err>;
fn try_map(&self, tx: &T, tx_info: TransactionInfo) -> Result<Self::Out, Self::Err>;
}

impl<T> TxInfoMapper<&T> for () {
impl<T> TxInfoMapper<T> for () {
type Out = TransactionInfo;
type Err = Infallible;

Expand Down Expand Up @@ -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<Network, Evm, Receipt, Header = (), Map = (), SimTx = ()> {
pub struct RpcConverter<Network, Evm, Receipt, Header = (), Map = (), SimTx = (), RpcTx = ()> {
network: PhantomData<Network>,
evm: PhantomData<Evm>,
receipt_converter: Receipt,
header_converter: Header,
mapper: Map,
sim_tx_converter: SimTx,
rpc_tx_converter: RpcTx,
}

impl<Network, Evm, Receipt> RpcConverter<Network, Evm, Receipt> {
Expand All @@ -470,63 +525,145 @@ impl<Network, Evm, Receipt> RpcConverter<Network, Evm, Receipt> {
header_converter: (),
mapper: (),
sim_tx_converter: (),
rpc_tx_converter: (),
}
}
}

impl<Network, Evm, Receipt, Header, Map, SimTx>
RpcConverter<Network, Evm, Receipt, Header, Map, SimTx>
impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx>
RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx>
{
/// Converts the network type
pub fn with_network<N>(self) -> RpcConverter<N, Evm, Receipt, Header, Map, SimTx> {
let Self { receipt_converter, header_converter, mapper, evm, sim_tx_converter, .. } = self;
pub fn with_network<N>(self) -> RpcConverter<N, Evm, Receipt, Header, Map, SimTx, RpcTx> {
let Self {
receipt_converter,
header_converter,
mapper,
evm,
sim_tx_converter,
rpc_tx_converter,
..
} = self;
RpcConverter {
receipt_converter,
header_converter,
mapper,
network: Default::default(),
evm,
sim_tx_converter,
rpc_tx_converter,
}
}

/// Configures the header converter.
pub fn with_header_converter<HeaderNew>(
self,
header_converter: HeaderNew,
) -> RpcConverter<Network, Evm, Receipt, HeaderNew, Map, SimTx> {
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<Network, Evm, Receipt, HeaderNew, Map, SimTx, RpcTx> {
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<MapNew>(
self,
mapper: MapNew,
) -> RpcConverter<Network, Evm, Receipt, Header, MapNew, SimTx> {
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<Network, Evm, Receipt, Header, MapNew, SimTx, RpcTx> {
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<SimTxNew>(
self,
sim_tx_converter: SimTxNew,
) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTxNew> {
let Self { receipt_converter, header_converter, mapper, network, evm, .. } = self;
RpcConverter { receipt_converter, header_converter, mapper, network, evm, sim_tx_converter }
) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTxNew, RpcTx> {
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<RpcTxNew>(
self,
rpc_tx_converter: RpcTxNew,
) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTxNew> {
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<Network, Evm, Receipt, Header, Map, SimTx> Default
for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx>
impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx> Default
for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx>
where
Receipt: Default,
Header: Default,
Map: Default,
SimTx: Default,
RpcTx: Default,
{
fn default() -> Self {
Self {
Expand All @@ -536,12 +673,13 @@ where
header_converter: Default::default(),
mapper: Default::default(),
sim_tx_converter: Default::default(),
rpc_tx_converter: Default::default(),
}
}
}

impl<Network, Evm, Receipt: Clone, Header: Clone, Map: Clone, SimTx: Clone> Clone
for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx>
impl<Network, Evm, Receipt: Clone, Header: Clone, Map: Clone, SimTx: Clone, RpcTx: Clone> Clone
for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx>
{
fn clone(&self) -> Self {
Self {
Expand All @@ -551,24 +689,26 @@ impl<Network, Evm, Receipt: Clone, Header: Clone, Map: Clone, SimTx: Clone> 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<N, Network, Evm, Receipt, Header, Map, SimTx> RpcConvert
for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx>
impl<N, Network, Evm, Receipt, Header, Map, SimTx, RpcTx> RpcConvert
for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx>
where
N: NodePrimitives,
Network: RpcTypes + Send + Sync + Unpin + Clone + Debug,
Evm: ConfigureEvm<Primitives = N> + 'static,
TxTy<N>: IntoRpcTx<Network::TransactionResponse> + Clone + Debug,
TxTy<N>: Clone + Debug,
RpcTxReq<Network>: TryIntoTxEnv<TxEnvFor<Evm>>,
Receipt: ReceiptConverter<
N,
RpcReceipt = RpcReceipt<Network>,
Error: From<TransactionConversionError>
+ From<<RpcTxReq<Network> as TryIntoTxEnv<TxEnvFor<Evm>>>::Err>
+ for<'a> From<<Map as TxInfoMapper<&'a TxTy<N>>>::Err>
+ From<<Map as TxInfoMapper<TxTy<N>>>::Err>
+ From<RpcTx::Err>
+ Error
+ Unpin
+ Sync
Expand All @@ -580,16 +720,10 @@ where
+ Clone
+ Debug,
Header: HeaderConverter<HeaderTy<N>, RpcHeader<Network>>,
Map: for<'a> TxInfoMapper<
&'a TxTy<N>,
Out = <TxTy<N> as IntoRpcTx<Network::TransactionResponse>>::TxInfo,
> + Clone
+ Debug
+ Unpin
+ Send
+ Sync
+ 'static,
Map: TxInfoMapper<TxTy<N>> + Clone + Debug + Unpin + Send + Sync + 'static,
SimTx: SimTxConverter<RpcTxReq<Network>, TxTy<N>>,
RpcTx:
RpcTxConverter<TxTy<N>, Network::TransactionResponse, <Map as TxInfoMapper<TxTy<N>>>::Out>,
{
type Primitives = N;
type Network = Network;
Expand All @@ -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(
Expand Down