reth_cli_commands/stage/
drop.rs1use crate::common::{AccessRights, CliNodeTypes, Environment, EnvironmentArgs};
3use clap::Parser;
4use itertools::Itertools;
5use reth_chainspec::EthChainSpec;
6use reth_cli::chainspec::ChainSpecParser;
7use reth_db::{mdbx::tx::Tx, static_file::iter_static_files, DatabaseError};
8use reth_db_api::{
9 tables,
10 transaction::{DbTx, DbTxMut},
11};
12use reth_db_common::{
13 init::{insert_genesis_header, insert_genesis_history, insert_genesis_state},
14 DbTool,
15};
16use reth_node_api::{HeaderTy, ReceiptTy, TxTy};
17use reth_node_core::args::StageEnum;
18use reth_provider::{DBProvider, DatabaseProviderFactory, StaticFileProviderFactory, TrieWriter};
19use reth_prune::PruneSegment;
20use reth_stages::StageId;
21use reth_static_file_types::StaticFileSegment;
22use std::sync::Arc;
23
24#[derive(Debug, Parser)]
26pub struct Command<C: ChainSpecParser> {
27 #[command(flatten)]
28 env: EnvironmentArgs<C>,
29
30 stage: StageEnum,
31}
32
33impl<C: ChainSpecParser> Command<C> {
34 pub async fn execute<N: CliNodeTypes>(self) -> eyre::Result<()>
36 where
37 C: ChainSpecParser<ChainSpec = N::ChainSpec>,
38 {
39 let Environment { provider_factory, .. } = self.env.init::<N>(AccessRights::RW)?;
40
41 let tool = DbTool::new(provider_factory)?;
42
43 let static_file_segment = match self.stage {
44 StageEnum::Headers => Some(StaticFileSegment::Headers),
45 StageEnum::Bodies => Some(StaticFileSegment::Transactions),
46 StageEnum::Execution => Some(StaticFileSegment::Receipts),
47 _ => None,
48 };
49
50 if let Some(static_file_segment) = static_file_segment {
52 let static_file_provider = tool.provider_factory.static_file_provider();
53 let static_files = iter_static_files(static_file_provider.directory())?;
54 if let Some(segment_static_files) = static_files.get(&static_file_segment) {
55 for (block_range, _) in segment_static_files
57 .iter()
58 .sorted_by_key(|(block_range, _)| block_range.start())
59 .rev()
60 {
61 static_file_provider.delete_jar(static_file_segment, block_range.start())?;
62 }
63 }
64 }
65
66 let provider_rw = tool.provider_factory.database_provider_rw()?;
67 let tx = provider_rw.tx_ref();
68
69 match self.stage {
70 StageEnum::Headers => {
71 tx.clear::<tables::CanonicalHeaders>()?;
72 tx.clear::<tables::Headers<HeaderTy<N>>>()?;
73 tx.clear::<tables::HeaderNumbers>()?;
74 reset_stage_checkpoint(tx, StageId::Headers)?;
75
76 insert_genesis_header(&provider_rw, &self.env.chain)?;
77 }
78 StageEnum::Bodies => {
79 tx.clear::<tables::BlockBodyIndices>()?;
80 tx.clear::<tables::Transactions<TxTy<N>>>()?;
81
82 tx.clear::<tables::TransactionBlocks>()?;
83 tx.clear::<tables::BlockOmmers<HeaderTy<N>>>()?;
84 tx.clear::<tables::BlockWithdrawals>()?;
85 reset_stage_checkpoint(tx, StageId::Bodies)?;
86
87 insert_genesis_header(&provider_rw, &self.env.chain)?;
88 }
89 StageEnum::Senders => {
90 tx.clear::<tables::TransactionSenders>()?;
91 reset_prune_checkpoint(tx, PruneSegment::SenderRecovery)?;
93 reset_stage_checkpoint(tx, StageId::SenderRecovery)?;
94 }
95 StageEnum::Execution => {
96 tx.clear::<tables::PlainAccountState>()?;
97 tx.clear::<tables::PlainStorageState>()?;
98 tx.clear::<tables::AccountChangeSets>()?;
99 tx.clear::<tables::StorageChangeSets>()?;
100 tx.clear::<tables::Bytecodes>()?;
101 tx.clear::<tables::Receipts<ReceiptTy<N>>>()?;
102
103 reset_prune_checkpoint(tx, PruneSegment::Receipts)?;
104 reset_prune_checkpoint(tx, PruneSegment::ContractLogs)?;
105 reset_stage_checkpoint(tx, StageId::Execution)?;
106
107 let alloc = &self.env.chain.genesis().alloc;
108 insert_genesis_state(&provider_rw, alloc.iter())?;
109 }
110 StageEnum::AccountHashing => {
111 tx.clear::<tables::HashedAccounts>()?;
112 reset_stage_checkpoint(tx, StageId::AccountHashing)?;
113 }
114 StageEnum::StorageHashing => {
115 tx.clear::<tables::HashedStorages>()?;
116 reset_stage_checkpoint(tx, StageId::StorageHashing)?;
117 }
118 StageEnum::Hashing => {
119 tx.clear::<tables::HashedAccounts>()?;
121 reset_stage_checkpoint(tx, StageId::AccountHashing)?;
122
123 tx.clear::<tables::HashedStorages>()?;
125 reset_stage_checkpoint(tx, StageId::StorageHashing)?;
126 }
127 StageEnum::Merkle => {
128 tx.clear::<tables::AccountsTrie>()?;
129 tx.clear::<tables::StoragesTrie>()?;
130
131 reset_stage_checkpoint(tx, StageId::MerkleExecute)?;
132 reset_stage_checkpoint(tx, StageId::MerkleUnwind)?;
133
134 tx.delete::<tables::StageCheckpointProgresses>(
135 StageId::MerkleExecute.to_string(),
136 None,
137 )?;
138 }
139 StageEnum::MerkleChangeSets => {
140 provider_rw.clear_trie_changesets()?;
141 reset_stage_checkpoint(tx, StageId::MerkleChangeSets)?;
142 }
143 StageEnum::AccountHistory | StageEnum::StorageHistory => {
144 tx.clear::<tables::AccountsHistory>()?;
145 tx.clear::<tables::StoragesHistory>()?;
146
147 reset_stage_checkpoint(tx, StageId::IndexAccountHistory)?;
148 reset_stage_checkpoint(tx, StageId::IndexStorageHistory)?;
149
150 insert_genesis_history(&provider_rw, self.env.chain.genesis().alloc.iter())?;
151 }
152 StageEnum::TxLookup => {
153 tx.clear::<tables::TransactionHashNumbers>()?;
154 reset_prune_checkpoint(tx, PruneSegment::TransactionLookup)?;
155
156 reset_stage_checkpoint(tx, StageId::TransactionLookup)?;
157 insert_genesis_header(&provider_rw, &self.env.chain)?;
158 }
159 }
160
161 tx.put::<tables::StageCheckpoints>(StageId::Finish.to_string(), Default::default())?;
162
163 provider_rw.commit()?;
164
165 Ok(())
166 }
167 pub fn chain_spec(&self) -> Option<&Arc<C::ChainSpec>> {
169 Some(&self.env.chain)
170 }
171}
172
173fn reset_prune_checkpoint(
174 tx: &Tx<reth_db::mdbx::RW>,
175 prune_segment: PruneSegment,
176) -> Result<(), DatabaseError> {
177 if let Some(mut prune_checkpoint) = tx.get::<tables::PruneCheckpoints>(prune_segment)? {
178 prune_checkpoint.block_number = None;
179 prune_checkpoint.tx_number = None;
180 tx.put::<tables::PruneCheckpoints>(prune_segment, prune_checkpoint)?;
181 }
182
183 Ok(())
184}
185
186fn reset_stage_checkpoint(
187 tx: &Tx<reth_db::mdbx::RW>,
188 stage_id: StageId,
189) -> Result<(), DatabaseError> {
190 tx.put::<tables::StageCheckpoints>(stage_id.to_string(), Default::default())?;
191
192 Ok(())
193}