reth_optimism_storage/
chain.rs

1use alloc::{vec, vec::Vec};
2use alloy_consensus::{BlockBody, Header};
3use alloy_primitives::BlockNumber;
4use core::marker::PhantomData;
5use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks};
6use reth_db_api::transaction::{DbTx, DbTxMut};
7use reth_node_api::{FullNodePrimitives, FullSignedTx};
8use reth_optimism_primitives::OpTransactionSigned;
9use reth_primitives_traits::{Block, FullBlockHeader, SignedTransaction};
10use reth_provider::{
11    providers::{ChainStorage, NodeTypesForProvider},
12    DatabaseProvider,
13};
14use reth_storage_api::{
15    errors::ProviderResult, BlockBodyReader, BlockBodyWriter, ChainStorageReader,
16    ChainStorageWriter, DBProvider, ReadBodyInput, StorageLocation,
17};
18
19/// Optimism storage implementation.
20#[derive(Debug, Clone, Copy)]
21pub struct OpStorage<T = OpTransactionSigned, H = Header>(PhantomData<(T, H)>);
22
23impl<T, H> Default for OpStorage<T, H> {
24    fn default() -> Self {
25        Self(Default::default())
26    }
27}
28
29impl<N, T, H> ChainStorage<N> for OpStorage<T, H>
30where
31    T: FullSignedTx,
32    H: FullBlockHeader,
33    N: FullNodePrimitives<
34        Block = alloy_consensus::Block<T, H>,
35        BlockHeader = H,
36        BlockBody = alloy_consensus::BlockBody<T, H>,
37        SignedTx = T,
38    >,
39{
40    fn reader<TX, Types>(&self) -> impl ChainStorageReader<DatabaseProvider<TX, Types>, N>
41    where
42        TX: DbTx + 'static,
43        Types: NodeTypesForProvider<Primitives = N>,
44    {
45        self
46    }
47
48    fn writer<TX, Types>(&self) -> impl ChainStorageWriter<DatabaseProvider<TX, Types>, N>
49    where
50        TX: DbTxMut + DbTx + 'static,
51        Types: NodeTypesForProvider<Primitives = N>,
52    {
53        self
54    }
55}
56
57impl<Provider, T, H> BlockBodyWriter<Provider, alloy_consensus::BlockBody<T, H>> for OpStorage<T, H>
58where
59    Provider: DBProvider<Tx: DbTxMut>,
60    T: SignedTransaction,
61    H: FullBlockHeader,
62{
63    fn write_block_bodies(
64        &self,
65        _provider: &Provider,
66        _bodies: Vec<(u64, Option<alloy_consensus::BlockBody<T, H>>)>,
67        _write_to: StorageLocation,
68    ) -> ProviderResult<()> {
69        // noop
70        Ok(())
71    }
72
73    fn remove_block_bodies_above(
74        &self,
75        _provider: &Provider,
76        _block: BlockNumber,
77        _remove_from: StorageLocation,
78    ) -> ProviderResult<()> {
79        // noop
80        Ok(())
81    }
82}
83
84impl<Provider, T, H> BlockBodyReader<Provider> for OpStorage<T, H>
85where
86    Provider: ChainSpecProvider<ChainSpec: EthChainSpec + EthereumHardforks> + DBProvider,
87    T: SignedTransaction,
88    H: FullBlockHeader,
89{
90    type Block = alloy_consensus::Block<T, H>;
91
92    fn read_block_bodies(
93        &self,
94        provider: &Provider,
95        inputs: Vec<ReadBodyInput<'_, Self::Block>>,
96    ) -> ProviderResult<Vec<<Self::Block as Block>::Body>> {
97        let chain_spec = provider.chain_spec();
98
99        Ok(inputs
100            .into_iter()
101            .map(|(header, transactions)| BlockBody {
102                transactions,
103                ommers: vec![],
104                // after shanghai the body should have an empty withdrawals list
105                withdrawals: chain_spec
106                    .is_shanghai_active_at_timestamp(header.timestamp())
107                    .then(Default::default),
108            })
109            .collect())
110    }
111}