reth_cli_commands/db/checksum/
rocksdb.rs1use super::{checksum_hasher, PROGRESS_LOG_INTERVAL};
4use crate::common::CliNodeTypes;
5use clap::ValueEnum;
6use reth_chainspec::EthereumHardforks;
7use reth_db::{tables, DatabaseEnv};
8use reth_db_api::table::Table;
9use reth_db_common::DbTool;
10use reth_node_builder::NodeTypesWithDBAdapter;
11use reth_provider::RocksDBProviderFactory;
12use std::{hash::Hasher, sync::Arc, time::Instant};
13use tracing::info;
14
15#[derive(Debug, Clone, Copy, ValueEnum)]
17pub enum RocksDbTable {
18 TransactionHashNumbers,
20 AccountsHistory,
22 StoragesHistory,
24}
25
26impl RocksDbTable {
27 const fn name(&self) -> &'static str {
29 match self {
30 Self::TransactionHashNumbers => tables::TransactionHashNumbers::NAME,
31 Self::AccountsHistory => tables::AccountsHistory::NAME,
32 Self::StoragesHistory => tables::StoragesHistory::NAME,
33 }
34 }
35}
36
37pub fn checksum_rocksdb<N: CliNodeTypes<ChainSpec: EthereumHardforks>>(
39 tool: &DbTool<NodeTypesWithDBAdapter<N, Arc<DatabaseEnv>>>,
40 table: RocksDbTable,
41 limit: Option<usize>,
42) -> eyre::Result<()> {
43 let rocksdb = tool.provider_factory.rocksdb_provider();
44
45 let start_time = Instant::now();
46 let limit = limit.unwrap_or(usize::MAX);
47
48 info!(
49 "Computing checksum for RocksDB table `{}`, limit={:?}",
50 table.name(),
51 if limit == usize::MAX { None } else { Some(limit) }
52 );
53
54 let (checksum, total) = match table {
55 RocksDbTable::TransactionHashNumbers => {
56 checksum_rocksdb_table::<tables::TransactionHashNumbers>(&rocksdb, limit)?
57 }
58 RocksDbTable::AccountsHistory => {
59 checksum_rocksdb_table::<tables::AccountsHistory>(&rocksdb, limit)?
60 }
61 RocksDbTable::StoragesHistory => {
62 checksum_rocksdb_table::<tables::StoragesHistory>(&rocksdb, limit)?
63 }
64 };
65
66 let elapsed = start_time.elapsed();
67
68 info!(
69 "Checksum for RocksDB table `{}`: {:#x} ({} entries, elapsed: {:?})",
70 table.name(),
71 checksum,
72 total,
73 elapsed
74 );
75
76 Ok(())
77}
78
79fn checksum_rocksdb_table<T: Table>(
81 rocksdb: &reth_provider::providers::RocksDBProvider,
82 limit: usize,
83) -> eyre::Result<(u64, usize)> {
84 let iter = rocksdb.raw_iter::<T>()?;
85 let mut hasher = checksum_hasher();
86 let mut total = 0usize;
87
88 for entry in iter {
89 let (key_bytes, value_bytes) = entry?;
90
91 hasher.write(&key_bytes);
92 hasher.write(&value_bytes);
93
94 total += 1;
95
96 if total.is_multiple_of(PROGRESS_LOG_INTERVAL) {
97 info!("Hashed {total} entries.");
98 }
99
100 if total >= limit {
101 break;
102 }
103 }
104
105 Ok((hasher.finish(), total))
106}