|
1 | 1 | //! Loads and formats OP transaction RPC response. |
2 | 2 |
|
3 | | -use alloy_consensus::{transaction::Recovered, SignableTransaction}; |
4 | | -use alloy_primitives::{Bytes, Signature, B256}; |
5 | | -use alloy_rpc_types_eth::TransactionInfo; |
6 | | -use op_alloy_consensus::{ |
7 | | - transaction::{OpDepositInfo, OpTransactionInfo}, |
8 | | - OpTxEnvelope, |
| 3 | +use crate::{ |
| 4 | + eth::{OpEthApiInner, OpNodeCore}, |
| 5 | + OpEthApi, OpEthApiError, SequencerClient, |
9 | 6 | }; |
10 | | -use op_alloy_rpc_types::{OpTransactionRequest, Transaction}; |
11 | | -use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes}; |
| 7 | +use alloy_primitives::{Bytes, B256}; |
| 8 | +use alloy_rpc_types_eth::TransactionInfo; |
| 9 | +use op_alloy_consensus::{transaction::OpTransactionInfo, OpTxEnvelope}; |
| 10 | +use reth_node_api::FullNodeComponents; |
12 | 11 | use reth_optimism_primitives::DepositReceipt; |
13 | | -use reth_primitives_traits::{NodePrimitives, TxTy}; |
14 | 12 | use reth_rpc_eth_api::{ |
15 | 13 | helpers::{EthSigner, EthTransactions, LoadTransaction, SpawnBlocking}, |
16 | | - EthApiTypes, FromEthApiError, FullEthApiTypes, RpcNodeCore, RpcNodeCoreExt, TransactionCompat, |
| 14 | + try_into_op_tx_info, EthApiTypes, FromEthApiError, FullEthApiTypes, RpcNodeCore, |
| 15 | + RpcNodeCoreExt, TxInfoMapper, |
17 | 16 | }; |
18 | | -use reth_rpc_eth_types::{utils::recover_raw_transaction, EthApiError}; |
| 17 | +use reth_rpc_eth_types::utils::recover_raw_transaction; |
19 | 18 | use reth_storage_api::{ |
20 | | - BlockReader, BlockReaderIdExt, ProviderTx, ReceiptProvider, TransactionsProvider, |
| 19 | + errors::ProviderError, BlockReader, BlockReaderIdExt, ProviderTx, ReceiptProvider, |
| 20 | + TransactionsProvider, |
21 | 21 | }; |
22 | 22 | use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool}; |
23 | | - |
24 | | -use crate::{eth::OpNodeCore, OpEthApi, OpEthApiError, SequencerClient}; |
| 23 | +use std::{ |
| 24 | + fmt::{Debug, Formatter}, |
| 25 | + sync::Arc, |
| 26 | +}; |
25 | 27 |
|
26 | 28 | impl<N> EthTransactions for OpEthApi<N> |
27 | 29 | where |
@@ -87,59 +89,39 @@ where |
87 | 89 | } |
88 | 90 | } |
89 | 91 |
|
90 | | -impl<N> TransactionCompat for OpEthApi<N> |
| 92 | +/// Optimism implementation of [`TxInfoMapper`]. |
| 93 | +/// |
| 94 | +/// For deposits, receipt is fetched to extract `deposit_nonce` and `deposit_receipt_version`. |
| 95 | +/// Otherwise, it works like regular Ethereum implementation, i.e. uses [`TransactionInfo`]. |
| 96 | +#[derive(Clone)] |
| 97 | +pub struct OpTxInfoMapper<N: OpNodeCore>(Arc<OpEthApiInner<N>>); |
| 98 | + |
| 99 | +impl<N: OpNodeCore> Debug for OpTxInfoMapper<N> { |
| 100 | + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
| 101 | + f.debug_struct("OpTxInfoMapper").finish() |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +impl<N: OpNodeCore> OpTxInfoMapper<N> { |
| 106 | + /// Creates [`OpTxInfoMapper`] that uses [`ReceiptProvider`] borrowed from given `eth_api`. |
| 107 | + pub const fn new(eth_api: Arc<OpEthApiInner<N>>) -> Self { |
| 108 | + Self(eth_api) |
| 109 | + } |
| 110 | +} |
| 111 | + |
| 112 | +impl<N> TxInfoMapper<&OpTxEnvelope> for OpTxInfoMapper<N> |
91 | 113 | where |
92 | 114 | N: FullNodeComponents, |
93 | 115 | N::Provider: ReceiptProvider<Receipt: DepositReceipt>, |
94 | | - <<N as FullNodeTypes>::Types as NodeTypes>::Primitives: NodePrimitives<SignedTx = OpTxEnvelope>, |
95 | 116 | { |
96 | | - type Primitives = <<N as FullNodeTypes>::Types as NodeTypes>::Primitives; |
97 | | - type Transaction = Transaction; |
98 | | - type Error = OpEthApiError; |
| 117 | + type Out = OpTransactionInfo; |
| 118 | + type Err = ProviderError; |
99 | 119 |
|
100 | | - fn fill( |
| 120 | + fn try_map( |
101 | 121 | &self, |
102 | | - tx: Recovered<TxTy<Self::Primitives>>, |
| 122 | + tx: &OpTxEnvelope, |
103 | 123 | tx_info: TransactionInfo, |
104 | | - ) -> Result<Self::Transaction, Self::Error> { |
105 | | - let tx = tx.convert::<TxTy<Self::Primitives>>(); |
106 | | - let mut deposit_receipt_version = None; |
107 | | - let mut deposit_nonce = None; |
108 | | - |
109 | | - if tx.is_deposit() { |
110 | | - // for depost tx we need to fetch the receipt |
111 | | - self.inner |
112 | | - .eth_api |
113 | | - .provider() |
114 | | - .receipt_by_hash(tx.tx_hash()) |
115 | | - .map_err(Self::Error::from_eth_err)? |
116 | | - .inspect(|receipt| { |
117 | | - if let Some(receipt) = receipt.as_deposit_receipt() { |
118 | | - deposit_receipt_version = receipt.deposit_receipt_version; |
119 | | - deposit_nonce = receipt.deposit_nonce; |
120 | | - } |
121 | | - }); |
122 | | - } |
123 | | - |
124 | | - let tx_info = OpTransactionInfo::new( |
125 | | - tx_info, |
126 | | - OpDepositInfo { deposit_nonce, deposit_receipt_version }, |
127 | | - ); |
128 | | - |
129 | | - Ok(Transaction::from_transaction(tx, tx_info)) |
130 | | - } |
131 | | - |
132 | | - fn build_simulate_v1_transaction( |
133 | | - &self, |
134 | | - request: alloy_rpc_types_eth::TransactionRequest, |
135 | | - ) -> Result<TxTy<Self::Primitives>, Self::Error> { |
136 | | - let request: OpTransactionRequest = request.into(); |
137 | | - let Ok(tx) = request.build_typed_tx() else { |
138 | | - return Err(OpEthApiError::Eth(EthApiError::TransactionConversionError)) |
139 | | - }; |
140 | | - |
141 | | - // Create an empty signature for the transaction. |
142 | | - let signature = Signature::new(Default::default(), Default::default(), false); |
143 | | - Ok(tx.into_signed(signature).into()) |
| 124 | + ) -> Result<Self::Out, ProviderError> { |
| 125 | + try_into_op_tx_info(self.0.eth_api.provider(), tx, tx_info) |
144 | 126 | } |
145 | 127 | } |
0 commit comments