reth_rpc_eth_types/
block.rs1use std::sync::Arc;
4
5use alloy_consensus::{transaction::TxHashRef, TxReceipt};
6use alloy_primitives::TxHash;
7use reth_primitives_traits::{
8 Block, BlockBody, BlockTy, IndexedTx, NodePrimitives, ReceiptTy, Recovered, RecoveredBlock,
9 SealedBlock,
10};
11use reth_rpc_convert::{transaction::ConvertReceiptInput, RpcConvert, RpcTypes};
12
13use crate::utils::calculate_gas_used_and_next_log_index;
14
15#[derive(Debug, Clone)]
17pub struct CachedTransaction<B: Block, R> {
18 pub block: Arc<RecoveredBlock<B>>,
20 pub tx_index: usize,
22 pub receipts: Option<Arc<Vec<R>>>,
24}
25
26impl<B: Block, R> CachedTransaction<B, R> {
27 pub const fn new(
29 block: Arc<RecoveredBlock<B>>,
30 tx_index: usize,
31 receipts: Option<Arc<Vec<R>>>,
32 ) -> Self {
33 Self { block, tx_index, receipts }
34 }
35
36 pub fn recovered_transaction(&self) -> Option<Recovered<&<B::Body as BlockBody>::Transaction>> {
38 self.block.recovered_transaction(self.tx_index)
39 }
40
41 pub fn into_receipt<N, C>(
45 self,
46 converter: &C,
47 ) -> Option<Result<<C::Network as RpcTypes>::Receipt, C::Error>>
48 where
49 N: NodePrimitives<Block = B, Receipt = R>,
50 R: TxReceipt + Clone,
51 C: RpcConvert<Primitives = N>,
52 {
53 let receipts = self.receipts?;
54 let receipt = receipts.get(self.tx_index)?;
55 let tx_hash = *self.block.body().transactions().get(self.tx_index)?.tx_hash();
56 let tx = self.block.find_indexed(tx_hash)?;
57 convert_transaction_receipt::<N, C>(
58 self.block.as_ref(),
59 receipts.as_ref(),
60 tx,
61 receipt,
62 converter,
63 )
64 }
65}
66
67#[derive(Debug, Clone)]
72pub struct BlockAndReceipts<N: NodePrimitives> {
73 pub block: Arc<RecoveredBlock<BlockTy<N>>>,
75 pub receipts: Arc<Vec<ReceiptTy<N>>>,
77}
78
79impl<N: NodePrimitives> BlockAndReceipts<N> {
80 pub const fn new(
82 block: Arc<RecoveredBlock<BlockTy<N>>>,
83 receipts: Arc<Vec<ReceiptTy<N>>>,
84 ) -> Self {
85 Self { block, receipts }
86 }
87
88 pub fn find_transaction_and_receipt_by_hash(
92 &self,
93 tx_hash: TxHash,
94 ) -> Option<(IndexedTx<'_, N::Block>, &N::Receipt)> {
95 let indexed_tx = self.block.find_indexed(tx_hash)?;
96 let receipt = self.receipts.get(indexed_tx.index())?;
97 Some((indexed_tx, receipt))
98 }
99
100 pub fn sealed_block(&self) -> &SealedBlock<BlockTy<N>> {
102 self.block.sealed_block()
103 }
104
105 pub fn find_and_convert_transaction_receipt<C>(
110 &self,
111 tx_hash: TxHash,
112 converter: &C,
113 ) -> Option<Result<<C::Network as RpcTypes>::Receipt, C::Error>>
114 where
115 C: RpcConvert<Primitives = N>,
116 {
117 let (tx, receipt) = self.find_transaction_and_receipt_by_hash(tx_hash)?;
118 convert_transaction_receipt(
119 self.block.as_ref(),
120 self.receipts.as_ref(),
121 tx,
122 receipt,
123 converter,
124 )
125 }
126}
127
128pub fn convert_transaction_receipt<N, C>(
130 block: &RecoveredBlock<BlockTy<N>>,
131 all_receipts: &[ReceiptTy<N>],
132 tx: IndexedTx<'_, BlockTy<N>>,
133 receipt: &ReceiptTy<N>,
134 converter: &C,
135) -> Option<Result<<C::Network as RpcTypes>::Receipt, C::Error>>
136where
137 N: NodePrimitives,
138 C: RpcConvert<Primitives = N>,
139{
140 let meta = tx.meta();
141 let (gas_used, next_log_index) =
142 calculate_gas_used_and_next_log_index(meta.index, all_receipts);
143
144 converter
145 .convert_receipts_with_block(
146 vec![ConvertReceiptInput {
147 tx: tx.recovered_tx(),
148 gas_used: receipt.cumulative_gas_used() - gas_used,
149 receipt: receipt.clone(),
150 next_log_index,
151 meta,
152 }],
153 block.sealed_block(),
154 )
155 .map(|mut receipts| receipts.pop())
156 .transpose()
157}