Skip to main content

reth_provider/test_utils/
mod.rs

1use crate::{
2    providers::{NodeTypesForProvider, ProviderNodeTypes, RocksDBBuilder, StaticFileProvider},
3    HashingWriter, ProviderFactory, TrieWriter,
4};
5use alloy_primitives::B256;
6use reth_chainspec::{ChainSpec, MAINNET};
7use reth_db::{test_utils::TempDatabase, DatabaseEnv};
8use reth_errors::ProviderResult;
9use reth_ethereum_engine_primitives::EthEngineTypes;
10use reth_node_types::NodeTypesWithDBAdapter;
11use reth_primitives_traits::{Account, StorageEntry};
12use reth_trie::StateRoot;
13use reth_trie_db::DatabaseStateRoot;
14use std::sync::Arc;
15
16pub mod blocks;
17mod mock;
18mod noop;
19
20pub use mock::{ExtendedAccount, MockEthProvider};
21pub use noop::NoopProvider;
22pub use reth_chain_state::test_utils::TestCanonStateSubscriptions;
23
24/// Mock [`reth_node_types::NodeTypes`] for testing.
25pub type MockNodeTypes = reth_node_types::AnyNodeTypesWithEngine<
26    reth_ethereum_primitives::EthPrimitives,
27    reth_ethereum_engine_primitives::EthEngineTypes,
28    reth_chainspec::ChainSpec,
29    crate::EthStorage,
30    EthEngineTypes,
31>;
32
33/// Mock [`reth_node_types::NodeTypesWithDB`] for testing.
34pub type MockNodeTypesWithDB<DB = Arc<TempDatabase<DatabaseEnv>>> =
35    NodeTypesWithDBAdapter<MockNodeTypes, DB>;
36
37/// Creates test provider factory with mainnet chain spec.
38pub fn create_test_provider_factory() -> ProviderFactory<MockNodeTypesWithDB> {
39    create_test_provider_factory_with_chain_spec(MAINNET.clone())
40}
41
42/// Creates test provider factory with provided chain spec.
43pub fn create_test_provider_factory_with_chain_spec(
44    chain_spec: Arc<ChainSpec>,
45) -> ProviderFactory<MockNodeTypesWithDB> {
46    create_test_provider_factory_with_node_types::<MockNodeTypes>(chain_spec)
47}
48
49/// Creates test provider factory with provided chain spec.
50pub fn create_test_provider_factory_with_node_types<N: NodeTypesForProvider>(
51    chain_spec: Arc<N::ChainSpec>,
52) -> ProviderFactory<NodeTypesWithDBAdapter<N, Arc<TempDatabase<DatabaseEnv>>>> {
53    // Create a single temp directory that contains all data dirs (db, static_files, rocksdb).
54    // TempDatabase will clean up the entire directory on drop.
55    let datadir_path = reth_db::test_utils::tempdir_path();
56
57    let static_files_path = datadir_path.join("static_files");
58    let rocksdb_path = datadir_path.join("rocksdb");
59
60    // Create static_files directory
61    std::fs::create_dir_all(&static_files_path).expect("failed to create static_files dir");
62
63    // Create database with the datadir path so TempDatabase cleans up everything on drop
64    let db = reth_db::test_utils::create_test_rw_db_with_datadir(&datadir_path);
65
66    ProviderFactory::new(
67        db,
68        chain_spec,
69        StaticFileProvider::read_write(static_files_path).expect("static file provider"),
70        RocksDBBuilder::new(&rocksdb_path)
71            .with_default_tables()
72            .build()
73            .expect("failed to create test RocksDB provider"),
74        reth_tasks::Runtime::test(),
75    )
76    .expect("failed to create test provider factory")
77}
78
79/// Inserts the genesis alloc from the provided chain spec into the trie.
80pub fn insert_genesis<N: ProviderNodeTypes<ChainSpec = ChainSpec>>(
81    provider_factory: &ProviderFactory<N>,
82    chain_spec: Arc<N::ChainSpec>,
83) -> ProviderResult<B256> {
84    let provider = provider_factory.provider_rw()?;
85
86    // Hash accounts and insert them into hashing table.
87    let genesis = chain_spec.genesis();
88    let alloc_accounts =
89        genesis.alloc.iter().map(|(addr, account)| (*addr, Some(Account::from(account))));
90    provider.insert_account_for_hashing(alloc_accounts).unwrap();
91
92    let alloc_storage = genesis.alloc.clone().into_iter().filter_map(|(addr, account)| {
93        // Only return `Some` if there is storage.
94        account.storage.map(|storage| {
95            (
96                addr,
97                storage.into_iter().map(|(key, value)| StorageEntry { key, value: value.into() }),
98            )
99        })
100    });
101    provider.insert_storage_for_hashing(alloc_storage)?;
102
103    let (root, updates) = StateRoot::from_tx(provider.tx_ref()).root_with_updates()?;
104    provider.write_trie_updates(updates).unwrap();
105
106    provider.commit()?;
107
108    Ok(root)
109}