Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 52 additions & 36 deletions crates/optimism/cli/src/commands/init_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use reth_optimism_primitives::{
};
use reth_primitives_traits::SealedHeader;
use reth_provider::{
BlockNumReader, ChainSpecProvider, DBProvider, DatabaseProviderFactory,
StaticFileProviderFactory, StaticFileWriter,
BlockNumReader, DBProvider, DatabaseProviderFactory, StaticFileProviderFactory,
StaticFileWriter,
};
use std::{io::BufReader, sync::Arc};
use tracing::info;
Expand All @@ -24,12 +24,11 @@ pub struct InitStateCommandOp<C: ChainSpecParser> {
#[command(flatten)]
init_state: reth_cli_commands::init_state::InitStateCommand<C>,

/// **Optimism Mainnet Only**
///
/// Specifies whether to initialize the state without relying on OVM historical data.
/// Specifies whether to initialize the state without relying on OVM or EVM historical data.
///
/// When enabled, and before inserting the state, it creates a dummy chain up to the last OVM
/// block (#105235062) (14GB / 90 seconds). It then, appends the Bedrock block.
/// block (#105235062) (14GB / 90 seconds). It then, appends the Bedrock block. This is
/// hardcoded for OP mainnet, for other OP chains you will need to pass in a header.
///
/// - **Note**: **Do not** import receipts and blocks beforehand, or this will fail or be
/// ignored.
Expand All @@ -40,42 +39,59 @@ pub struct InitStateCommandOp<C: ChainSpecParser> {
impl<C: ChainSpecParser<ChainSpec = OpChainSpec>> InitStateCommandOp<C> {
/// Execute the `init` command
pub async fn execute<N: CliNodeTypes<ChainSpec = C::ChainSpec, Primitives = OpPrimitives>>(
self,
mut self,
) -> eyre::Result<()> {
info!(target: "reth::cli", "Reth init-state starting");
// If using --without-ovm for OP mainnet, handle the special case with hardcoded Bedrock
// header. Otherwise delegate to the base InitStateCommand implementation.
if self.without_ovm {
if self.init_state.env.chain.is_optimism_mainnet() {
return self.execute_with_bedrock_header::<N>();
}

// For non-mainnet OP chains with --without-ovm, use the base implementation
// by setting the without_evm flag
self.init_state.without_evm = true;
}

self.init_state.execute::<N>().await
}

let Environment { config, provider_factory, .. } =
self.init_state.env.init::<N>(AccessRights::RW)?;
/// Execute init-state with hardcoded Bedrock header for OP mainnet.
fn execute_with_bedrock_header<
N: CliNodeTypes<ChainSpec = C::ChainSpec, Primitives = OpPrimitives>,
>(
self,
) -> eyre::Result<()> {
info!(target: "reth::cli", "Reth init-state starting for OP mainnet");
let env = self.init_state.env.init::<N>(AccessRights::RW)?;

let Environment { config, provider_factory, .. } = env;
let static_file_provider = provider_factory.static_file_provider();
let provider_rw = provider_factory.database_provider_rw()?;

// OP-Mainnet may want to bootstrap a chain without OVM historical data
if provider_factory.chain_spec().is_optimism_mainnet() && self.without_ovm {
let last_block_number = provider_rw.last_block_number()?;

if last_block_number == 0 {
reth_cli_commands::init_state::without_evm::setup_without_evm(
&provider_rw,
SealedHeader::new(BEDROCK_HEADER, BEDROCK_HEADER_HASH),
|number| {
let mut header = Header::default();
header.set_number(number);
header
},
)?;

// SAFETY: it's safe to commit static files, since in the event of a crash, they
// will be unwound according to database checkpoints.
//
// Necessary to commit, so the BEDROCK_HEADER is accessible to provider_rw and
// init_state_dump
static_file_provider.commit()?;
} else if last_block_number > 0 && last_block_number < BEDROCK_HEADER.number {
return Err(eyre::eyre!(
"Data directory should be empty when calling init-state with --without-ovm."
))
}
let last_block_number = provider_rw.last_block_number()?;

if last_block_number == 0 {
reth_cli_commands::init_state::without_evm::setup_without_evm(
&provider_rw,
SealedHeader::new(BEDROCK_HEADER, BEDROCK_HEADER_HASH),
|number| {
let mut header = Header::default();
header.set_number(number);
header
},
)?;

// SAFETY: it's safe to commit static files, since in the event of a crash, they
// will be unwound according to database checkpoints.
//
// Necessary to commit, so the BEDROCK_HEADER is accessible to provider_rw and
// init_state_dump
static_file_provider.commit()?;
} else if last_block_number > 0 && last_block_number < BEDROCK_HEADER.number {
return Err(eyre::eyre!(
"Data directory should be empty when calling init-state with --without-ovm."
))
}

info!(target: "reth::cli", "Initiating state dump");
Expand Down
Loading