Skip to main content

reth_provider/
init.rs

1use crate::{
2    ChainSpecProvider, DBProvider, EitherWriter, HistoryWriter, NodePrimitivesProvider,
3    ProviderResult, RocksDBProviderFactory, StorageSettingsCache,
4};
5use alloy_consensus::BlockHeader;
6use alloy_genesis::GenesisAccount;
7use alloy_primitives::Address;
8use reth_chainspec::EthChainSpec;
9use reth_db::{
10    models::{storage_sharded_key::StorageShardedKey, ShardedKey},
11    transaction::DbTxMut,
12    BlockNumberList,
13};
14use tracing::trace;
15
16/// Inserts history indices for genesis accounts and storage.
17///
18/// Writes to either MDBX or `RocksDB` based on storage settings configuration,
19/// using [`EitherWriter`] to abstract over the storage backend.
20pub fn insert_genesis_history<'a, 'b, Provider>(
21    provider: &Provider,
22    alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)> + Clone,
23) -> ProviderResult<()>
24where
25    Provider: DBProvider<Tx: DbTxMut>
26        + HistoryWriter
27        + ChainSpecProvider
28        + StorageSettingsCache
29        + RocksDBProviderFactory
30        + NodePrimitivesProvider,
31{
32    let genesis_block_number = provider.chain_spec().genesis_header().number();
33    insert_history(provider, alloc, genesis_block_number)
34}
35
36/// Inserts account history indices for genesis accounts.
37pub fn insert_genesis_account_history<'a, 'b, Provider>(
38    provider: &Provider,
39    alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)>,
40) -> ProviderResult<()>
41where
42    Provider: DBProvider<Tx: DbTxMut>
43        + HistoryWriter
44        + ChainSpecProvider
45        + StorageSettingsCache
46        + RocksDBProviderFactory
47        + NodePrimitivesProvider,
48{
49    let genesis_block_number = provider.chain_spec().genesis_header().number();
50    insert_account_history(provider, alloc, genesis_block_number)
51}
52
53/// Inserts storage history indices for genesis accounts.
54pub fn insert_genesis_storage_history<'a, 'b, Provider>(
55    provider: &Provider,
56    alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)>,
57) -> ProviderResult<()>
58where
59    Provider: DBProvider<Tx: DbTxMut>
60        + HistoryWriter
61        + ChainSpecProvider
62        + StorageSettingsCache
63        + RocksDBProviderFactory
64        + NodePrimitivesProvider,
65{
66    let genesis_block_number = provider.chain_spec().genesis_header().number();
67    insert_storage_history(provider, alloc, genesis_block_number)
68}
69
70/// Inserts history indices for genesis accounts and storage.
71///
72/// Writes to either MDBX or `RocksDB` based on storage settings configuration,
73/// using [`EitherWriter`] to abstract over the storage backend.
74pub fn insert_history<'a, 'b, Provider>(
75    provider: &Provider,
76    alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)> + Clone,
77    block: u64,
78) -> ProviderResult<()>
79where
80    Provider: DBProvider<Tx: DbTxMut>
81        + HistoryWriter
82        + StorageSettingsCache
83        + RocksDBProviderFactory
84        + NodePrimitivesProvider,
85{
86    insert_account_history(provider, alloc.clone(), block)?;
87    insert_storage_history(provider, alloc, block)?;
88    Ok(())
89}
90
91/// Inserts account history indices at the given block.
92pub fn insert_account_history<'a, 'b, Provider>(
93    provider: &Provider,
94    alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)>,
95    block: u64,
96) -> ProviderResult<()>
97where
98    Provider: DBProvider<Tx: DbTxMut>
99        + HistoryWriter
100        + StorageSettingsCache
101        + RocksDBProviderFactory
102        + NodePrimitivesProvider,
103{
104    provider.with_rocksdb_batch(|batch| {
105        let mut writer = EitherWriter::new_accounts_history(provider, batch)?;
106        let list = BlockNumberList::new([block]).expect("single block always fits");
107        for (addr, _) in alloc {
108            writer.upsert_account_history(ShardedKey::last(*addr), &list)?;
109        }
110        trace!(target: "reth::provider", "Inserted account history");
111        Ok(((), writer.into_raw_rocksdb_batch()))
112    })?;
113
114    Ok(())
115}
116
117/// Inserts storage history indices at the given block.
118pub fn insert_storage_history<'a, 'b, Provider>(
119    provider: &Provider,
120    alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)>,
121    block: u64,
122) -> ProviderResult<()>
123where
124    Provider: DBProvider<Tx: DbTxMut>
125        + HistoryWriter
126        + StorageSettingsCache
127        + RocksDBProviderFactory
128        + NodePrimitivesProvider,
129{
130    provider.with_rocksdb_batch(|batch| {
131        let mut writer = EitherWriter::new_storages_history(provider, batch)?;
132        let list = BlockNumberList::new([block]).expect("single block always fits");
133        for (addr, account) in alloc {
134            if let Some(storage) = &account.storage {
135                for key in storage.keys() {
136                    writer.upsert_storage_history(StorageShardedKey::last(*addr, *key), &list)?;
137                }
138            }
139        }
140        trace!(target: "reth::cli", "Inserted storage history");
141        Ok(((), writer.into_raw_rocksdb_batch()))
142    })?;
143
144    Ok(())
145}