reth_optimism_cli/commands/
init_state.rs1use alloy_consensus::Header;
4use clap::Parser;
5use reth_cli::chainspec::ChainSpecParser;
6use reth_cli_commands::common::{AccessRights, CliHeader, CliNodeTypes, Environment};
7use reth_db_common::init::init_from_state_dump;
8use reth_optimism_chainspec::OpChainSpec;
9use reth_optimism_primitives::{
10 bedrock::{BEDROCK_HEADER, BEDROCK_HEADER_HASH, BEDROCK_HEADER_TTD},
11 OpPrimitives,
12};
13use reth_primitives_traits::SealedHeader;
14use reth_provider::{
15 BlockNumReader, ChainSpecProvider, DatabaseProviderFactory, StaticFileProviderFactory,
16 StaticFileWriter,
17};
18use std::{io::BufReader, sync::Arc};
19use tracing::info;
20
21#[derive(Debug, Parser)]
23pub struct InitStateCommandOp<C: ChainSpecParser> {
24 #[command(flatten)]
25 init_state: reth_cli_commands::init_state::InitStateCommand<C>,
26
27 #[arg(long, default_value = "false")]
37 without_ovm: bool,
38}
39
40impl<C: ChainSpecParser<ChainSpec = OpChainSpec>> InitStateCommandOp<C> {
41 pub async fn execute<N: CliNodeTypes<ChainSpec = C::ChainSpec, Primitives = OpPrimitives>>(
43 self,
44 ) -> eyre::Result<()> {
45 info!(target: "reth::cli", "Reth init-state starting");
46
47 let Environment { config, provider_factory, .. } =
48 self.init_state.env.init::<N>(AccessRights::RW)?;
49
50 let static_file_provider = provider_factory.static_file_provider();
51 let provider_rw = provider_factory.database_provider_rw()?;
52
53 if provider_factory.chain_spec().is_optimism_mainnet() && self.without_ovm {
55 let last_block_number = provider_rw.last_block_number()?;
56
57 if last_block_number == 0 {
58 reth_cli_commands::init_state::without_evm::setup_without_evm(
59 &provider_rw,
60 SealedHeader::new(BEDROCK_HEADER, BEDROCK_HEADER_HASH),
61 BEDROCK_HEADER_TTD,
62 |number| {
63 let mut header = Header::default();
64 header.set_number(number);
65 header
66 },
67 )?;
68
69 static_file_provider.commit()?;
75 } else if last_block_number > 0 && last_block_number < BEDROCK_HEADER.number {
76 return Err(eyre::eyre!(
77 "Data directory should be empty when calling init-state with --without-ovm."
78 ))
79 }
80 }
81
82 info!(target: "reth::cli", "Initiating state dump");
83
84 let reader = BufReader::new(reth_fs_util::open(self.init_state.state)?);
85 let hash = init_from_state_dump(reader, &provider_rw, config.stages.etl)?;
86
87 provider_rw.commit()?;
88
89 info!(target: "reth::cli", hash = ?hash, "Genesis block written");
90 Ok(())
91 }
92}
93
94impl<C: ChainSpecParser> InitStateCommandOp<C> {
95 pub fn chain_spec(&self) -> Option<&Arc<C::ChainSpec>> {
97 self.init_state.chain_spec()
98 }
99}