reth_e2e_test_utils/
trie.rs1use crate::TmpDB;
4use alloy_consensus::BlockHeader;
5use eyre::{ensure, eyre, Result};
6use reth_provider::{
7 BlockNumReader, DBProvider, DatabaseProviderFactory, HeaderProvider, StorageSettingsCache,
8};
9use reth_trie::{
10 prefix_set::{PrefixSetMut, TriePrefixSets},
11 verify::{default_storage_workers, Output, DEFAULT_STORAGE_LOOKAHEAD},
12 StateRoot,
13};
14use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, DatabaseVerifier};
15
16pub fn assert_trie_consistency<F>(factory: &F) -> Result<()>
30where
31 F: DatabaseProviderFactory<
32 DB = TmpDB,
33 Provider: DBProvider + StorageSettingsCache + BlockNumReader + HeaderProvider,
34 > + AsRef<F::DB>,
35{
36 let snapshot_guard = factory.database_provider_rw()?;
38 let provider = factory.database_provider_ro()?;
39 let tip = provider.best_block_number()?;
40 let header = provider
41 .header_by_number(tip)?
42 .ok_or_else(|| eyre!("missing persisted header for block {tip}"))?;
43 let tx = provider.tx_ref();
44
45 reth_trie_db::with_adapter!(provider, |A| {
46 let db = factory.as_ref().db().clone().with_disable_long_read_transaction_safety();
47 let verifier = DatabaseVerifier::<_, A>::new(
48 &db,
49 default_storage_workers(),
50 DEFAULT_STORAGE_LOOKAHEAD,
51 )?;
52 drop(snapshot_guard);
53
54 let recomputed = StateRoot::new(
58 DatabaseTrieCursorFactory::<_, A>::new(tx),
59 DatabaseHashedCursorFactory::new(tx),
60 )
61 .with_prefix_sets(TriePrefixSets {
62 account_prefix_set: PrefixSetMut::all().freeze(),
63 ..Default::default()
64 })
65 .root()?;
66 ensure!(
67 recomputed == header.state_root(),
68 "state root {recomputed} recomputed from the persisted state does not match the state root of persisted block {tip}: {}",
69 header.state_root()
70 );
71
72 let mut inconsistencies = Vec::new();
73 for output in verifier {
74 match output? {
75 Output::Progress(_) => {}
76 inconsistency => inconsistencies.push(inconsistency),
77 }
78 }
79 ensure!(
80 inconsistencies.is_empty(),
81 "persisted trie is inconsistent with the persisted hashed state: {inconsistencies:?}"
82 );
83
84 Ok(())
85 })
86}