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},
11 OpPrimitives,
12};
13use reth_primitives_traits::SealedHeader;
14use reth_provider::{
15 BlockNumReader, DBProvider, 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")]
36 without_ovm: bool,
37}
38
39impl<C: ChainSpecParser<ChainSpec = OpChainSpec>> InitStateCommandOp<C> {
40 pub async fn execute<N: CliNodeTypes<ChainSpec = C::ChainSpec, Primitives = OpPrimitives>>(
42 mut self,
43 ) -> eyre::Result<()> {
44 if self.without_ovm {
47 if self.init_state.env.chain.is_optimism_mainnet() {
48 return self.execute_with_bedrock_header::<N>();
49 }
50
51 self.init_state.without_evm = true;
54 }
55
56 self.init_state.execute::<N>().await
57 }
58
59 fn execute_with_bedrock_header<
61 N: CliNodeTypes<ChainSpec = C::ChainSpec, Primitives = OpPrimitives>,
62 >(
63 self,
64 ) -> eyre::Result<()> {
65 info!(target: "reth::cli", "Reth init-state starting for OP mainnet");
66 let env = self.init_state.env.init::<N>(AccessRights::RW)?;
67
68 let Environment { config, provider_factory, .. } = env;
69 let static_file_provider = provider_factory.static_file_provider();
70 let provider_rw = provider_factory.database_provider_rw()?;
71
72 let last_block_number = provider_rw.last_block_number()?;
73
74 if last_block_number == 0 {
75 reth_cli_commands::init_state::without_evm::setup_without_evm(
76 &provider_rw,
77 SealedHeader::new(BEDROCK_HEADER, BEDROCK_HEADER_HASH),
78 |number| {
79 let mut header = Header::default();
80 header.set_number(number);
81 header
82 },
83 )?;
84
85 static_file_provider.commit()?;
91 } else if last_block_number > 0 && last_block_number < BEDROCK_HEADER.number {
92 return Err(eyre::eyre!(
93 "Data directory should be empty when calling init-state with --without-ovm."
94 ))
95 }
96
97 info!(target: "reth::cli", "Initiating state dump");
98
99 let reader = BufReader::new(reth_fs_util::open(self.init_state.state)?);
100 let hash = init_from_state_dump(reader, &provider_rw, config.stages.etl)?;
101
102 provider_rw.commit()?;
103
104 info!(target: "reth::cli", hash = ?hash, "Genesis block written");
105 Ok(())
106 }
107}
108
109impl<C: ChainSpecParser> InitStateCommandOp<C> {
110 pub fn chain_spec(&self) -> Option<&Arc<C::ChainSpec>> {
112 self.init_state.chain_spec()
113 }
114}