reth_cli_commands/stage/dump/
hashing_storage.rs1use super::setup;
2use eyre::Result;
3use reth_db::DatabaseEnv;
4use reth_db_api::{database::Database, table::TableImporter, tables};
5use reth_db_common::DbTool;
6use reth_node_core::dirs::{ChainPath, DataDirPath};
7use reth_provider::{
8 providers::{ProviderNodeTypes, StaticFileProvider},
9 DatabaseProviderFactory, ProviderFactory,
10};
11use reth_stages::{stages::StorageHashingStage, Stage, StageCheckpoint, UnwindInput};
12use std::sync::Arc;
13use tracing::info;
14
15pub(crate) async fn dump_hashing_storage_stage<N: ProviderNodeTypes<DB = Arc<DatabaseEnv>>>(
16 db_tool: &DbTool<N>,
17 from: u64,
18 to: u64,
19 output_datadir: ChainPath<DataDirPath>,
20 should_run: bool,
21) -> Result<()> {
22 let (output_db, tip_block_number) = setup(from, to, &output_datadir.db(), db_tool)?;
23
24 unwind_and_copy(db_tool, from, tip_block_number, &output_db)?;
25
26 if should_run {
27 dry_run(
28 ProviderFactory::<N>::new(
29 Arc::new(output_db),
30 db_tool.chain(),
31 StaticFileProvider::read_write(output_datadir.static_files())?,
32 )?,
33 to,
34 from,
35 )?;
36 }
37
38 Ok(())
39}
40
41fn unwind_and_copy<N: ProviderNodeTypes>(
43 db_tool: &DbTool<N>,
44 from: u64,
45 tip_block_number: u64,
46 output_db: &DatabaseEnv,
47) -> eyre::Result<()> {
48 let provider = db_tool.provider_factory.database_provider_rw()?;
49
50 let mut exec_stage = StorageHashingStage::default();
51
52 exec_stage.unwind(
53 &provider,
54 UnwindInput {
55 unwind_to: from,
56 checkpoint: StageCheckpoint::new(tip_block_number),
57 bad_block: None,
58 },
59 )?;
60 let unwind_inner_tx = provider.into_tx();
61
62 output_db
64 .update(|tx| tx.import_dupsort::<tables::PlainStorageState, _>(&unwind_inner_tx))??;
65 output_db
66 .update(|tx| tx.import_dupsort::<tables::StorageChangeSets, _>(&unwind_inner_tx))??;
67
68 Ok(())
69}
70
71fn dry_run<N: ProviderNodeTypes>(
73 output_provider_factory: ProviderFactory<N>,
74 to: u64,
75 from: u64,
76) -> eyre::Result<()> {
77 info!(target: "reth::cli", "Executing stage.");
78
79 let provider = output_provider_factory.database_provider_rw()?;
80 let mut stage = StorageHashingStage {
81 clean_threshold: 1, ..Default::default()
83 };
84
85 loop {
86 let input = reth_stages::ExecInput {
87 target: Some(to),
88 checkpoint: Some(StageCheckpoint::new(from)),
89 };
90 if stage.execute(&provider, input)?.done {
91 break
92 }
93 }
94
95 info!(target: "reth::cli", "Success.");
96
97 Ok(())
98}