//! Database debugging tool use crate::common::{AccessRights, Environment, EnvironmentArgs}; use clap::Parser; use itertools::Itertools; use reth_db::{static_file::iter_static_files, tables}; use reth_db_api::transaction::DbTxMut; use reth_db_common::{ init::{insert_genesis_header, insert_genesis_history, insert_genesis_state}, DbTool, }; use reth_node_core::args::StageEnum; use reth_provider::{writer::UnifiedStorageWriter, StaticFileProviderFactory}; use reth_stages::StageId; use reth_static_file_types::{find_fixed_range, StaticFileSegment}; /// `reth drop-stage` command #[derive(Debug, Parser)] pub struct Command { #[command(flatten)] env: EnvironmentArgs, stage: StageEnum, } impl Command { /// Execute `db` command pub async fn execute(self) -> eyre::Result<()> { let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; let static_file_provider = provider_factory.static_file_provider(); let tool = DbTool::new(provider_factory)?; let static_file_segment = match self.stage { StageEnum::Headers => Some(StaticFileSegment::Headers), StageEnum::Bodies => Some(StaticFileSegment::Transactions), StageEnum::Execution => Some(StaticFileSegment::Receipts), _ => None, }; // Delete static file segment data before inserting the genesis header below if let Some(static_file_segment) = static_file_segment { let static_file_provider = tool.provider_factory.static_file_provider(); let static_files = iter_static_files(static_file_provider.directory())?; if let Some(segment_static_files) = static_files.get(&static_file_segment) { // Delete static files from the highest to the lowest block range for (block_range, _) in segment_static_files .iter() .sorted_by_key(|(block_range, _)| block_range.start()) .rev() { static_file_provider .delete_jar(static_file_segment, find_fixed_range(block_range.start()))?; } } } let provider_rw = tool.provider_factory.provider_rw()?; let tx = provider_rw.tx_ref(); match self.stage { StageEnum::Headers => { tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.put::( StageId::Headers.to_string(), Default::default(), )?; insert_genesis_header(&provider_rw, &static_file_provider, self.env.chain)?; } StageEnum::Bodies => { tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.put::( StageId::Bodies.to_string(), Default::default(), )?; insert_genesis_header(&provider_rw, &static_file_provider, self.env.chain)?; } StageEnum::Senders => { tx.clear::()?; tx.put::( StageId::SenderRecovery.to_string(), Default::default(), )?; } StageEnum::Execution => { tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.clear::()?; tx.put::( StageId::Execution.to_string(), Default::default(), )?; let alloc = &self.env.chain.genesis().alloc; insert_genesis_state(&provider_rw, alloc.len(), alloc.iter())?; } StageEnum::AccountHashing => { tx.clear::()?; tx.put::( StageId::AccountHashing.to_string(), Default::default(), )?; } StageEnum::StorageHashing => { tx.clear::()?; tx.put::( StageId::StorageHashing.to_string(), Default::default(), )?; } StageEnum::Hashing => { // Clear hashed accounts tx.clear::()?; tx.put::( StageId::AccountHashing.to_string(), Default::default(), )?; // Clear hashed storages tx.clear::()?; tx.put::( StageId::StorageHashing.to_string(), Default::default(), )?; } StageEnum::Merkle => { tx.clear::()?; tx.clear::()?; tx.put::( StageId::MerkleExecute.to_string(), Default::default(), )?; tx.put::( StageId::MerkleUnwind.to_string(), Default::default(), )?; tx.delete::( StageId::MerkleExecute.to_string(), None, )?; } StageEnum::AccountHistory | StageEnum::StorageHistory => { tx.clear::()?; tx.clear::()?; tx.put::( StageId::IndexAccountHistory.to_string(), Default::default(), )?; tx.put::( StageId::IndexStorageHistory.to_string(), Default::default(), )?; insert_genesis_history(&provider_rw, self.env.chain.genesis.alloc.iter())?; } StageEnum::TxLookup => { tx.clear::()?; tx.put::( StageId::TransactionLookup.to_string(), Default::default(), )?; insert_genesis_header(&provider_rw, &static_file_provider, self.env.chain)?; } } tx.put::(StageId::Finish.to_string(), Default::default())?; UnifiedStorageWriter::commit_unwind(provider_rw, static_file_provider)?; Ok(()) } }