mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-26 15:48:13 -05:00
feat(rpc): Add FromConsensusTx and implement IntoRpcTx for generic RPC transaction (#16784)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::fees::{CallFees, CallFeesError};
|
||||
use alloy_consensus::{
|
||||
error::ValueError, transaction::Recovered, EthereumTxEnvelope, Extended, SignableTransaction,
|
||||
error::ValueError, transaction::Recovered, EthereumTxEnvelope, SignableTransaction,
|
||||
Transaction as ConsensusTransaction, TxEip4844,
|
||||
};
|
||||
use alloy_network::Network;
|
||||
@@ -82,38 +82,63 @@ pub trait TransactionCompat: Send + Sync + Unpin + Clone + Debug {
|
||||
) -> Result<Self::TxEnv, Self::Error>;
|
||||
}
|
||||
|
||||
/// Converts `self` into `T`.
|
||||
/// Converts `self` into `T`. The opposite of [`FromConsensusTx`].
|
||||
///
|
||||
/// Should create an RPC transaction response object based on a consensus transaction, its signer
|
||||
/// [`Address`] and an additional context.
|
||||
/// [`Address`] and an additional context [`IntoRpcTx::TxInfo`].
|
||||
///
|
||||
/// Avoid implementing [`IntoRpcTx`] and use [`FromConsensusTx`] instead. Implementing it
|
||||
/// automatically provides an implementation of [`IntoRpcTx`] thanks to the blanket implementation
|
||||
/// in this crate.
|
||||
///
|
||||
/// Prefer using [`IntoRpcTx`] over [`FromConsensusTx`] when specifying trait bounds on a generic
|
||||
/// function to ensure that types that only implement [`IntoRpcTx`] can be used as well.
|
||||
pub trait IntoRpcTx<T> {
|
||||
/// An additional context, usually [`TransactionInfo`] in a wrapper that carries some
|
||||
/// implementation specific extra information.
|
||||
type TxInfo;
|
||||
|
||||
/// Performs the conversion.
|
||||
/// Performs the conversion consuming `self` with `signer` and `tx_info`. See [`IntoRpcTx`]
|
||||
/// for details.
|
||||
fn into_rpc_tx(self, signer: Address, tx_info: Self::TxInfo) -> T;
|
||||
}
|
||||
|
||||
impl<BuiltIn, Other> IntoRpcTx<Transaction<Self>> for Extended<BuiltIn, Other>
|
||||
where
|
||||
BuiltIn: ConsensusTransaction,
|
||||
Other: ConsensusTransaction,
|
||||
{
|
||||
/// Converts `T` into `self`. It is reciprocal of [`IntoRpcTx`].
|
||||
///
|
||||
/// Should create an RPC transaction response object based on a consensus transaction, its signer
|
||||
/// [`Address`] and an additional context [`FromConsensusTx::TxInfo`].
|
||||
///
|
||||
/// Prefer implementing [`FromConsensusTx`] over [`IntoRpcTx`] because it automatically provides an
|
||||
/// implementation of [`IntoRpcTx`] thanks to the blanket implementation in this crate.
|
||||
///
|
||||
/// Prefer using [`IntoRpcTx`] over using [`FromConsensusTx`] when specifying trait bounds on a
|
||||
/// generic function. This way, types that directly implement [`IntoRpcTx`] can be used as arguments
|
||||
/// as well.
|
||||
pub trait FromConsensusTx<T> {
|
||||
/// An additional context, usually [`TransactionInfo`] in a wrapper that carries some
|
||||
/// implementation specific extra information.
|
||||
type TxInfo;
|
||||
|
||||
/// Performs the conversion consuming `tx` with `signer` and `tx_info`. See [`FromConsensusTx`]
|
||||
/// for details.
|
||||
fn from_consensus_tx(tx: T, signer: Address, tx_info: Self::TxInfo) -> Self;
|
||||
}
|
||||
|
||||
impl<T: ConsensusTransaction> FromConsensusTx<T> for Transaction<T> {
|
||||
type TxInfo = TransactionInfo;
|
||||
|
||||
fn into_rpc_tx(self, signer: Address, tx_info: Self::TxInfo) -> Transaction<Self> {
|
||||
fn from_consensus_tx(tx: T, signer: Address, tx_info: Self::TxInfo) -> Self {
|
||||
let TransactionInfo {
|
||||
block_hash, block_number, index: transaction_index, base_fee, ..
|
||||
} = tx_info;
|
||||
let effective_gas_price = base_fee
|
||||
.map(|base_fee| {
|
||||
self.effective_tip_per_gas(base_fee).unwrap_or_default() + base_fee as u128
|
||||
tx.effective_tip_per_gas(base_fee).unwrap_or_default() + base_fee as u128
|
||||
})
|
||||
.unwrap_or_else(|| self.max_fee_per_gas());
|
||||
.unwrap_or_else(|| tx.max_fee_per_gas());
|
||||
|
||||
Transaction {
|
||||
inner: Recovered::new_unchecked(self, signer),
|
||||
Self {
|
||||
inner: Recovered::new_unchecked(tx, signer),
|
||||
block_hash,
|
||||
block_number,
|
||||
transaction_index,
|
||||
@@ -122,6 +147,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<ConsensusTx, RpcTx> IntoRpcTx<RpcTx> for ConsensusTx
|
||||
where
|
||||
ConsensusTx: ConsensusTransaction,
|
||||
RpcTx: FromConsensusTx<Self>,
|
||||
{
|
||||
type TxInfo = RpcTx::TxInfo;
|
||||
|
||||
fn into_rpc_tx(self, signer: Address, tx_info: Self::TxInfo) -> RpcTx {
|
||||
RpcTx::from_consensus_tx(self, signer, tx_info)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `self` into `T`.
|
||||
///
|
||||
/// Should create a fake transaction for simulation using [`TransactionRequest`].
|
||||
@@ -189,15 +226,11 @@ pub fn try_into_op_tx_info<T: ReceiptProvider<Receipt: DepositReceipt>>(
|
||||
Ok(OpTransactionInfo::new(tx_info, deposit_meta))
|
||||
}
|
||||
|
||||
impl IntoRpcTx<op_alloy_rpc_types::Transaction> for OpTxEnvelope {
|
||||
impl FromConsensusTx<OpTxEnvelope> for op_alloy_rpc_types::Transaction {
|
||||
type TxInfo = OpTransactionInfo;
|
||||
|
||||
fn into_rpc_tx(
|
||||
self,
|
||||
signer: Address,
|
||||
tx_info: OpTransactionInfo,
|
||||
) -> op_alloy_rpc_types::Transaction {
|
||||
op_alloy_rpc_types::Transaction::from_transaction(self.with_signer(signer), tx_info)
|
||||
fn from_consensus_tx(tx: OpTxEnvelope, signer: Address, tx_info: Self::TxInfo) -> Self {
|
||||
Self::from_transaction(tx.with_signer(signer), tx_info)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user