Skip to content
Open
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 3 additions & 8 deletions crates/optimism/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ reth-node-metrics.workspace = true
reth-optimism-primitives.workspace = true
reth-optimism-chainspec = { workspace = true, features = ["superchain-configs"] }
reth-optimism-consensus.workspace = true
reth-optimism-trie.workspace = true

reth-chainspec.workspace = true
reth-node-events.workspace = true
Expand Down Expand Up @@ -86,15 +87,9 @@ asm-keccak = [
]

# Jemalloc feature for vergen to generate correct env vars
jemalloc = [
"reth-node-core/jemalloc",
"reth-node-metrics/jemalloc",
]
jemalloc = ["reth-node-core/jemalloc", "reth-node-metrics/jemalloc"]

dev = [
"dep:proptest",
"reth-cli-commands/arbitrary",
]
dev = ["dep:proptest", "reth-cli-commands/arbitrary"]

serde = [
"alloy-consensus/serde",
Expand Down
3 changes: 3 additions & 0 deletions crates/optimism/cli/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ where
Commands::ReExecute(command) => {
runner.run_until_ctrl_c(command.execute::<OpNode>(components))
}
Commands::InitializeOpProofs(command) => {
runner.run_blocking_until_ctrl_c(command.execute::<OpNode>())
}
}
}

Expand Down
100 changes: 100 additions & 0 deletions crates/optimism/cli/src/commands/initialize_proofs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//! Command that initializes the OP proofs storage with the current state of the chain.

use clap::Parser;
use reth_chainspec::ChainInfo;
use reth_cli::chainspec::ChainSpecParser;
use reth_cli_commands::common::{AccessRights, CliNodeTypes, Environment, EnvironmentArgs};
use reth_node_core::version::version_metadata;
use reth_optimism_chainspec::OpChainSpec;
use reth_optimism_primitives::OpPrimitives;
use reth_optimism_trie::{db::MdbxProofsStorage, BackfillJob, OpProofsStorage, OpProofsStore};
use reth_provider::{BlockNumReader, DBProvider, DatabaseProviderFactory};
use std::{path::PathBuf, sync::Arc};
use tracing::info;

/// Initializes the proofs storage with the current state of the chain.
///
/// This command must be run before starting the node with proofs history enabled.
/// It backfills the proofs storage with trie nodes from the current chain state.
#[derive(Debug, Parser)]
pub struct InitializeOpProofsCommand<C: ChainSpecParser> {
#[command(flatten)]
env: EnvironmentArgs<C>,

/// The path to the storage DB for proofs history.
///
/// This should match the path used when starting the node with
/// `--proofs-history.storage-path`.
#[arg(
long = "proofs-history.storage-path",
value_name = "PROOFS_HISTORY_STORAGE_PATH",
required = true
)]
pub storage_path: PathBuf,
}

impl<C: ChainSpecParser<ChainSpec = OpChainSpec>> InitializeOpProofsCommand<C> {
/// Execute `initialize-op-proofs` command
pub async fn execute<N: CliNodeTypes<ChainSpec = C::ChainSpec, Primitives = OpPrimitives>>(
self,
) -> eyre::Result<()> {
info!(target: "reth::cli", "reth {} starting", version_metadata().short_version);
info!(target: "reth::cli", "Initializing OP proofs storage at: {:?}", self.storage_path);

// Initialize the environment with read-only access
let Environment { provider_factory, .. } = self.env.init::<N>(AccessRights::RO)?;

// Create the proofs storage
let storage: OpProofsStorage<Arc<MdbxProofsStorage>> = Arc::new(
MdbxProofsStorage::new(&self.storage_path)
.map_err(|e| eyre::eyre!("Failed to create MdbxProofsStorage: {e}"))?,
)
.into();

// Check if already initialized
if let Some((block_number, block_hash)) = storage.get_earliest_block_number().await? {
info!(
target: "reth::cli",
block_number = block_number,
block_hash = ?block_hash,
"Proofs storage already initialized"
);
return Ok(());
}

// Get the current chain state
let ChainInfo { best_number, best_hash, .. } = provider_factory.chain_info()?;

info!(
target: "reth::cli",
best_number = best_number,
best_hash = ?best_hash,
"Starting backfill job for current chain state"
);

// Run the backfill job
{
let db_provider =
provider_factory.database_provider_ro()?.disable_long_read_transaction_safety();
let db_tx = db_provider.into_tx();

BackfillJob::new(storage.clone(), &db_tx).run(best_number, best_hash).await?;
}

info!(
target: "reth::cli",
best_number = best_number,
best_hash = ?best_hash,
"Proofs storage initialized successfully"
);

Ok(())
}
}

impl<C: ChainSpecParser> InitializeOpProofsCommand<C> {
/// Returns the underlying chain being used to run this command
pub const fn chain_spec(&self) -> Option<&Arc<C::ChainSpec>> {
Some(&self.env.chain)
}
}
5 changes: 5 additions & 0 deletions crates/optimism/cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::{fmt, sync::Arc};
pub mod import;
pub mod import_receipts;
pub mod init_state;
pub mod initialize_proofs;

#[cfg(feature = "dev")]
pub mod test_vectors;
Expand Down Expand Up @@ -61,6 +62,9 @@ pub enum Commands<Spec: ChainSpecParser = OpChainSpecParser, Ext: clap::Args + f
/// Re-execute blocks in parallel to verify historical sync correctness.
#[command(name = "re-execute")]
ReExecute(re_execute::Command<Spec>),
/// Initializes the proofs storage with the current state of the chain.
#[command(name = "initialize-op-proofs")]
InitializeOpProofs(initialize_proofs::InitializeOpProofsCommand<Spec>),
}

impl<
Expand All @@ -85,6 +89,7 @@ impl<
#[cfg(feature = "dev")]
Self::TestVectors(_) => None,
Self::ReExecute(cmd) => cmd.chain_spec(),
Self::InitializeOpProofs(cmd) => cmd.chain_spec(),
}
}
}
6 changes: 2 additions & 4 deletions crates/optimism/exex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ workspace = true
reth-exex.workspace = true
reth-node-types.workspace = true
reth-node-api.workspace = true
reth-provider.workspace = true
reth-chainspec.workspace = true
reth-primitives-traits.workspace = true
reth-provider.workspace = true

# op-reth
# proofs exex handles `TrieUpdates` in notifications
Expand All @@ -44,12 +43,11 @@ tempfile.workspace = true

[features]
test-utils = [
"reth-provider/test-utils",
"reth-db/test-utils",
"reth-chainspec/test-utils",
"reth-node-builder/test-utils",
"reth-optimism-node/test-utils",
"reth-primitives-traits/test-utils",
"reth-provider/test-utils",
]

[package.metadata.cargo-udeps.ignore]
Expand Down
18 changes: 7 additions & 11 deletions crates/optimism/exex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@
use alloy_consensus::BlockHeader;
use derive_more::Constructor;
use futures_util::TryStreamExt;
use reth_chainspec::ChainInfo;
use reth_exex::{ExExContext, ExExEvent, ExExNotification};
use reth_node_api::{FullNodeComponents, NodePrimitives};
use reth_node_types::NodeTypes;
use reth_optimism_trie::{live::LiveTrieCollector, BackfillJob, OpProofsStorage, OpProofsStore};
use reth_optimism_trie::{live::LiveTrieCollector, OpProofsStorage, OpProofsStore};
use reth_primitives_traits::{BlockTy, RecoveredBlock};
use reth_provider::{
BlockNumReader, BlockReader, DBProvider, DatabaseProviderFactory, TransactionVariant,
};
use reth_provider::{BlockReader, TransactionVariant};
use tracing::{debug, error, info};

/// OP Proofs ExEx - processes blocks and tracks state changes within fault proof window.
Expand Down Expand Up @@ -101,12 +98,11 @@ where
{
/// Main execution loop for the ExEx
pub async fn run(mut self) -> eyre::Result<()> {
{
let db_provider =
self.ctx.provider().database_provider_ro()?.disable_long_read_transaction_safety();
let db_tx = db_provider.into_tx();
let ChainInfo { best_number, best_hash } = self.ctx.provider().chain_info()?;
BackfillJob::new(self.storage.clone(), &db_tx).run(best_number, best_hash).await?;
// Check if proofs storage is initialized
if self.storage.get_earliest_block_number().await?.is_none() {
return Err(eyre::eyre!(
"Proofs storage not initialized. Please run 'op-reth initialize-op-proofs --proofs-history.storage-path <PATH>' first."
));
}

let collector = LiveTrieCollector::new(
Expand Down
Loading