diff --git a/Cargo.lock b/Cargo.lock index ab9e1c42db9a..4b8570d9b74f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2370,6 +2370,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.9.0" @@ -5568,6 +5574,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.22" @@ -6870,7 +6886,10 @@ name = "reth-engine-primitives" version = "1.0.6" dependencies = [ "reth-chainspec", + "reth-execution-types", "reth-payload-primitives", + "reth-primitives", + "reth-trie", "serde", ] @@ -7306,9 +7325,19 @@ dependencies = [ name = "reth-invalid-block-hooks" version = "1.0.6" dependencies = [ + "alloy-rlp", + "alloy-rpc-types-debug", + "eyre", + "pretty_assertions", + "reth-chainspec", + "reth-engine-primitives", + "reth-evm", "reth-primitives", "reth-provider", + "reth-revm", + "reth-tracing", "reth-trie", + "serde_json", ] [[package]] @@ -7591,6 +7620,7 @@ dependencies = [ "reth-engine-util", "reth-evm", "reth-exex", + "reth-fs-util", "reth-invalid-block-hooks", "reth-network", "reth-network-api", @@ -11254,6 +11284,12 @@ dependencies = [ "tap", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "yoke" version = "0.7.4" diff --git a/crates/engine/invalid-block-hooks/Cargo.toml b/crates/engine/invalid-block-hooks/Cargo.toml index 404ff96ce68d..17ac3cec5523 100644 --- a/crates/engine/invalid-block-hooks/Cargo.toml +++ b/crates/engine/invalid-block-hooks/Cargo.toml @@ -12,6 +12,20 @@ workspace = true [dependencies] # reth +reth-chainspec.workspace = true +reth-engine-primitives.workspace = true +reth-evm.workspace = true reth-primitives.workspace = true reth-provider.workspace = true -reth-trie.workspace = true +reth-revm.workspace = true +reth-tracing.workspace = true +reth-trie = { workspace = true, features = ["serde"] } + +# alloy +alloy-rlp.workspace = true +alloy-rpc-types-debug.workspace = true + +# misc +eyre.workspace = true +pretty_assertions = "1.4" +serde_json.workspace = true diff --git a/crates/engine/invalid-block-hooks/src/lib.rs b/crates/engine/invalid-block-hooks/src/lib.rs index 4a27e1fd1e42..26e208da6436 100644 --- a/crates/engine/invalid-block-hooks/src/lib.rs +++ b/crates/engine/invalid-block-hooks/src/lib.rs @@ -2,4 +2,4 @@ mod witness; -pub use witness::witness; +pub use witness::InvalidBlockWitnessHook; diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index 75261ce5e18f..d22dc2b21de4 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -1,13 +1,226 @@ -use reth_primitives::{Receipt, SealedBlockWithSenders, SealedHeader, B256}; -use reth_provider::BlockExecutionOutput; -use reth_trie::updates::TrieUpdates; +use std::{collections::HashMap, fmt::Debug, fs::File, io::Write, path::PathBuf}; + +use alloy_rpc_types_debug::ExecutionWitness; +use eyre::OptionExt; +use pretty_assertions::Comparison; +use reth_chainspec::ChainSpec; +use reth_engine_primitives::InvalidBlockHook; +use reth_evm::{ + system_calls::{apply_beacon_root_contract_call, apply_blockhashes_contract_call}, + ConfigureEvm, +}; +use reth_primitives::{keccak256, Receipt, SealedBlockWithSenders, SealedHeader, B256, U256}; +use reth_provider::{BlockExecutionOutput, ChainSpecProvider, StateProviderFactory}; +use reth_revm::{ + database::StateProviderDatabase, + db::states::bundle_state::BundleRetention, + primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg}, + DatabaseCommit, StateBuilder, +}; +use reth_tracing::tracing::warn; +use reth_trie::{updates::TrieUpdates, HashedPostState, HashedStorage}; /// Generates a witness for the given block and saves it to a file. -pub fn witness( - _block: &SealedBlockWithSenders, - _header: &SealedHeader, - _output: &BlockExecutionOutput, - _trie_updates: Option<(&TrieUpdates, B256)>, -) { - unimplemented!("witness generation is not supported") +#[derive(Debug)] +pub struct InvalidBlockWitnessHook { + /// The directory to write the witness to. Additionally, diff files will be written to this + /// directory in case of failed sanity checks. + output_directory: PathBuf, + /// The provider to read the historical state and do the EVM execution. + provider: P, + /// The EVM configuration to use for the execution. + evm_config: EvmConfig, +} + +impl InvalidBlockWitnessHook { + /// Creates a new witness hook. + pub const fn new(output_directory: PathBuf, provider: P, evm_config: EvmConfig) -> Self { + Self { output_directory, provider, evm_config } + } +} + +impl InvalidBlockWitnessHook +where + P: StateProviderFactory + ChainSpecProvider + Send + Sync + 'static, + EvmConfig: ConfigureEvm, +{ + fn on_invalid_block( + &self, + parent_header: &SealedHeader, + block: &SealedBlockWithSenders, + output: &BlockExecutionOutput, + trie_updates: Option<(&TrieUpdates, B256)>, + ) -> eyre::Result<()> { + // TODO(alexey): unify with `DebugApi::debug_execution_witness` + + // Setup database. + let mut db = StateBuilder::new() + .with_database(StateProviderDatabase::new( + self.provider.state_by_block_hash(parent_header.hash())?, + )) + .with_bundle_update() + .build(); + + // Setup environment for the execution. + let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default()); + let mut block_env = BlockEnv::default(); + self.evm_config.fill_cfg_and_block_env( + &mut cfg, + &mut block_env, + &self.provider.chain_spec(), + block.header(), + U256::MAX, + ); + + // Setup EVM + let mut evm = self.evm_config.evm_with_env( + &mut db, + EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, Default::default()), + ); + + // Apply pre-block system contract calls. + apply_beacon_root_contract_call( + &self.evm_config, + &self.provider.chain_spec(), + block.timestamp, + block.number, + block.parent_beacon_block_root, + &mut evm, + )?; + apply_blockhashes_contract_call( + &self.evm_config, + &self.provider.chain_spec(), + block.timestamp, + block.number, + block.parent_hash, + &mut evm, + )?; + + // Re-execute all of the transactions in the block to load all touched accounts into + // the cache DB. + for tx in block.transactions() { + self.evm_config.fill_tx_env( + evm.tx_mut(), + tx, + tx.recover_signer().ok_or_eyre("failed to recover sender")?, + ); + let result = evm.transact()?; + evm.db_mut().commit(result.state); + } + + drop(evm); + + // Merge all state transitions + db.merge_transitions(BundleRetention::Reverts); + + // Take the bundle state + let bundle_state = db.take_bundle(); + + // Initialize a map of preimages. + let mut state_preimages = HashMap::new(); + + // Grab all account proofs for the data accessed during block execution. + // + // Note: We grab *all* accounts in the cache here, as the `BundleState` prunes + // referenced accounts + storage slots. + let mut hashed_state = HashedPostState::from_bundle_state(&bundle_state.state); + for (address, account) in db.cache.accounts { + let hashed_address = keccak256(address); + hashed_state + .accounts + .insert(hashed_address, account.account.as_ref().map(|a| a.info.clone().into())); + + let storage = hashed_state + .storages + .entry(hashed_address) + .or_insert_with(|| HashedStorage::new(account.status.was_destroyed())); + + if let Some(account) = account.account { + state_preimages.insert(hashed_address, alloy_rlp::encode(address).into()); + + for (slot, value) in account.storage { + let slot = B256::from(slot); + let hashed_slot = keccak256(slot); + storage.storage.insert(hashed_slot, value); + + state_preimages.insert(hashed_slot, alloy_rlp::encode(slot).into()); + } + } + } + + // Generate an execution witness for the aggregated state of accessed accounts. + // Destruct the cache database to retrieve the state provider. + let state_provider = db.database.into_inner(); + let witness = state_provider.witness(HashedPostState::default(), hashed_state.clone())?; + + // Write the witness to the output directory. + let mut file = File::options() + .write(true) + .create_new(true) + .open(self.output_directory.join(format!("{}_{}.json", block.number, block.hash())))?; + let response = ExecutionWitness { witness, state_preimages: Some(state_preimages) }; + file.write_all(serde_json::to_string(&response)?.as_bytes())?; + + // The bundle state after re-execution should match the original one. + if bundle_state != output.state { + let filename = format!("{}_{}.bundle_state.diff", block.number, block.hash()); + let path = self.save_diff(filename, &bundle_state, &output.state)?; + warn!(target: "engine::invalid_block_hooks::witness", path = %path.display(), "Bundle state mismatch after re-execution"); + } + + // Calculate the state root and trie updates after re-execution. They should match + // the original ones. + let (state_root, trie_output) = state_provider.state_root_with_updates(hashed_state)?; + if let Some(trie_updates) = trie_updates { + if state_root != trie_updates.1 { + let filename = format!("{}_{}.state_root.diff", block.number, block.hash()); + let path = self.save_diff(filename, &state_root, &trie_updates.1)?; + warn!(target: "engine::invalid_block_hooks::witness", path = %path.display(), "State root mismatch after re-execution"); + } + + if &trie_output != trie_updates.0 { + let filename = format!("{}_{}.trie_updates.diff", block.number, block.hash()); + let path = self.save_diff(filename, &trie_output, trie_updates.0)?; + warn!(target: "engine::invalid_block_hooks::witness", path = %path.display(), "Trie updates mismatch after re-execution"); + } + } + + Ok(()) + } + + /// Saves the diff of two values into a file with the given name in the output directory. + fn save_diff( + &self, + filename: String, + original: &T, + new: &T, + ) -> eyre::Result { + let path = self.output_directory.join(filename); + let diff = Comparison::new(original, new); + File::options() + .write(true) + .create_new(true) + .open(&path)? + .write_all(diff.to_string().as_bytes())?; + + Ok(path) + } +} + +impl InvalidBlockHook for InvalidBlockWitnessHook +where + P: StateProviderFactory + ChainSpecProvider + Send + Sync + 'static, + EvmConfig: ConfigureEvm, +{ + fn on_invalid_block( + &self, + parent_header: &SealedHeader, + block: &SealedBlockWithSenders, + output: &BlockExecutionOutput, + trie_updates: Option<(&TrieUpdates, B256)>, + ) { + if let Err(err) = self.on_invalid_block(parent_header, block, output, trie_updates) { + warn!(target: "engine::invalid_block_hooks::witness", %err, "Failed to invoke hook"); + } + } } diff --git a/crates/engine/primitives/Cargo.toml b/crates/engine/primitives/Cargo.toml index b44a4a8aa4e7..437aac6a8793 100644 --- a/crates/engine/primitives/Cargo.toml +++ b/crates/engine/primitives/Cargo.toml @@ -13,7 +13,10 @@ workspace = true [dependencies] # reth reth-chainspec.workspace = true +reth-execution-types.workspace = true reth-payload-primitives.workspace = true +reth-primitives.workspace = true +reth-trie.workspace = true # misc -serde.workspace = true \ No newline at end of file +serde.workspace = true diff --git a/crates/engine/primitives/src/invalid_block_hook.rs b/crates/engine/primitives/src/invalid_block_hook.rs new file mode 100644 index 000000000000..9e1737dda047 --- /dev/null +++ b/crates/engine/primitives/src/invalid_block_hook.rs @@ -0,0 +1,36 @@ +use reth_execution_types::BlockExecutionOutput; +use reth_primitives::{Receipt, SealedBlockWithSenders, SealedHeader, B256}; +use reth_trie::updates::TrieUpdates; + +/// An invalid block hook. +pub trait InvalidBlockHook: Send + Sync { + /// Invoked when an invalid block is encountered. + fn on_invalid_block( + &self, + parent_header: &SealedHeader, + block: &SealedBlockWithSenders, + output: &BlockExecutionOutput, + trie_updates: Option<(&TrieUpdates, B256)>, + ); +} + +impl InvalidBlockHook for F +where + F: Fn( + &SealedHeader, + &SealedBlockWithSenders, + &BlockExecutionOutput, + Option<(&TrieUpdates, B256)>, + ) + Send + + Sync, +{ + fn on_invalid_block( + &self, + parent_header: &SealedHeader, + block: &SealedBlockWithSenders, + output: &BlockExecutionOutput, + trie_updates: Option<(&TrieUpdates, B256)>, + ) { + self(parent_header, block, output, trie_updates) + } +} diff --git a/crates/engine/primitives/src/lib.rs b/crates/engine/primitives/src/lib.rs index 4b0db7c0a14c..284ed9f0fb02 100644 --- a/crates/engine/primitives/src/lib.rs +++ b/crates/engine/primitives/src/lib.rs @@ -8,6 +8,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +mod invalid_block_hook; +pub use invalid_block_hook::InvalidBlockHook; + use reth_chainspec::ChainSpec; pub use reth_payload_primitives::{ BuiltPayload, EngineApiMessageVersion, EngineObjectValidationError, PayloadOrAttributes, diff --git a/crates/engine/tree/src/tree/invalid_block_hook.rs b/crates/engine/tree/src/tree/invalid_block_hook.rs index 9c32b781b12a..7e401b53c575 100644 --- a/crates/engine/tree/src/tree/invalid_block_hook.rs +++ b/crates/engine/tree/src/tree/invalid_block_hook.rs @@ -1,40 +1,8 @@ +use reth_engine_primitives::InvalidBlockHook; use reth_primitives::{Receipt, SealedBlockWithSenders, SealedHeader, B256}; use reth_provider::BlockExecutionOutput; use reth_trie::updates::TrieUpdates; -/// A bad block hook. -pub trait InvalidBlockHook: Send + Sync { - /// Invoked when a bad block is encountered. - fn on_invalid_block( - &self, - block: &SealedBlockWithSenders, - header: &SealedHeader, - output: &BlockExecutionOutput, - trie_updates: Option<(&TrieUpdates, B256)>, - ); -} - -impl InvalidBlockHook for F -where - F: Fn( - &SealedBlockWithSenders, - &SealedHeader, - &BlockExecutionOutput, - Option<(&TrieUpdates, B256)>, - ) + Send - + Sync, -{ - fn on_invalid_block( - &self, - block: &SealedBlockWithSenders, - header: &SealedHeader, - output: &BlockExecutionOutput, - trie_updates: Option<(&TrieUpdates, B256)>, - ) { - self(block, header, output, trie_updates) - } -} - /// A no-op [`InvalidBlockHook`] that does nothing. #[derive(Debug, Default)] #[non_exhaustive] @@ -43,8 +11,8 @@ pub struct NoopInvalidBlockHook; impl InvalidBlockHook for NoopInvalidBlockHook { fn on_invalid_block( &self, + _parent_header: &SealedHeader, _block: &SealedBlockWithSenders, - _header: &SealedHeader, _output: &BlockExecutionOutput, _trie_updates: Option<(&TrieUpdates, B256)>, ) { @@ -63,13 +31,13 @@ impl std::fmt::Debug for InvalidBlockHooks { impl InvalidBlockHook for InvalidBlockHooks { fn on_invalid_block( &self, + parent_header: &SealedHeader, block: &SealedBlockWithSenders, - header: &SealedHeader, output: &BlockExecutionOutput, trie_updates: Option<(&TrieUpdates, B256)>, ) { for hook in &self.0 { - hook.on_invalid_block(block, header, output, trie_updates); + hook.on_invalid_block(parent_header, block, output, trie_updates); } } } diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index fd988579d1ef..4fa7cb577406 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -63,7 +63,8 @@ mod invalid_block_hook; mod metrics; use crate::{engine::EngineApiRequest, tree::metrics::EngineApiMetrics}; pub use config::TreeConfig; -pub use invalid_block_hook::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook}; +pub use invalid_block_hook::{InvalidBlockHooks, NoopInvalidBlockHook}; +pub use reth_engine_primitives::InvalidBlockHook; /// Keeps track of the state of the tree. /// @@ -490,7 +491,7 @@ pub struct EngineApiTreeHandler { config: TreeConfig, /// Metrics for the engine api. metrics: EngineApiMetrics, - /// A bad block hook. + /// An invalid block hook. invalid_block_hook: Box, } @@ -2156,8 +2157,8 @@ where ) { // call post-block hook self.invalid_block_hook.on_invalid_block( - &block.seal_slow(), &parent_block, + &block.seal_slow(), &output, None, ); @@ -2172,8 +2173,8 @@ where if state_root != block.state_root { // call post-block hook self.invalid_block_hook.on_invalid_block( - &block.clone().seal_slow(), &parent_block, + &block.clone().seal_slow(), &output, Some((&trie_output, state_root)), ); diff --git a/crates/node/builder/Cargo.toml b/crates/node/builder/Cargo.toml index 933c85af2287..93830ef7d947 100644 --- a/crates/node/builder/Cargo.toml +++ b/crates/node/builder/Cargo.toml @@ -13,48 +13,49 @@ workspace = true [dependencies] ## reth -reth-chainspec.workspace = true reth-auto-seal-consensus.workspace = true reth-beacon-consensus.workspace = true reth-blockchain-tree.workspace = true -reth-db-common.workspace = true -reth-exex.workspace = true -reth-evm.workspace = true -reth-provider.workspace = true +reth-chainspec.workspace = true +reth-cli-util.workspace = true +reth-config.workspace = true +reth-consensus-debug-client.workspace = true +reth-consensus.workspace = true reth-db = { workspace = true, features = ["mdbx"], optional = true } reth-db-api.workspace = true -reth-rpc-engine-api.workspace = true -reth-rpc.workspace = true -reth-rpc-builder.workspace = true -reth-rpc-layer.workspace = true +reth-db-common.workspace = true +reth-downloaders.workspace = true +reth-engine-service.workspace = true +reth-engine-tree.workspace = true +reth-engine-util.workspace = true +reth-evm.workspace = true +reth-exex.workspace = true +reth-fs-util.workspace = true +reth-invalid-block-hooks.workspace = true +reth-network-api.workspace = true +reth-network-p2p.workspace = true +reth-network.workspace = true reth-node-api.workspace = true reth-node-core.workspace = true +reth-node-events.workspace = true reth-node-metrics.workspace = true -reth-network.workspace = true -reth-primitives.workspace = true reth-payload-builder.workspace = true -reth-transaction-pool.workspace = true -reth-tasks.workspace = true -reth-tracing.workspace = true -reth-network-p2p.workspace = true -reth-static-file.workspace = true +reth-payload-validator.workspace = true +reth-primitives.workspace = true +reth-provider.workspace = true reth-prune.workspace = true -reth-stages.workspace = true -reth-config.workspace = true -reth-downloaders.workspace = true -reth-node-events.workspace = true -reth-consensus.workspace = true -reth-consensus-debug-client.workspace = true -reth-rpc-types.workspace = true -reth-engine-util.workspace = true -reth-cli-util.workspace = true +reth-rpc-builder.workspace = true +reth-rpc-engine-api.workspace = true reth-rpc-eth-types.workspace = true -reth-network-api.workspace = true -reth-payload-validator.workspace = true -reth-engine-service.workspace = true +reth-rpc-layer.workspace = true +reth-rpc-types.workspace = true +reth-rpc.workspace = true +reth-stages.workspace = true +reth-static-file.workspace = true +reth-tasks.workspace = true reth-tokio-util.workspace = true -reth-engine-tree.workspace = true -reth-invalid-block-hooks.workspace = true +reth-tracing.workspace = true +reth-transaction-pool.workspace = true ## ethereum alloy-network.workspace = true diff --git a/crates/node/builder/src/launch/common.rs b/crates/node/builder/src/launch/common.rs index 8e1d065389c3..34a187426275 100644 --- a/crates/node/builder/src/launch/common.rs +++ b/crates/node/builder/src/launch/common.rs @@ -17,6 +17,8 @@ use reth_db_common::init::{init_genesis, InitDatabaseError}; use reth_downloaders::{bodies::noop::NoopBodiesDownloader, headers::noop::NoopHeaderDownloader}; use reth_engine_tree::tree::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook}; use reth_evm::noop::NoopBlockExecutorProvider; +use reth_fs_util as fs; +use reth_invalid_block_hooks::InvalidBlockWitnessHook; use reth_network_p2p::headers::client::HeadersClient; use reth_node_api::{FullNodeTypes, NodeTypes, NodeTypesWithDB}; use reth_node_core::{ @@ -35,8 +37,9 @@ use reth_node_metrics::{ use reth_primitives::{BlockNumber, Head, B256}; use reth_provider::{ providers::{BlockchainProvider, BlockchainProvider2, StaticFileProvider}, - BlockHashReader, CanonStateNotificationSender, ProviderFactory, ProviderResult, - StageCheckpointReader, StaticFileProviderFactory, TreeViewer, + BlockHashReader, CanonStateNotificationSender, ChainSpecProvider, ProviderFactory, + ProviderResult, StageCheckpointReader, StateProviderFactory, StaticFileProviderFactory, + TreeViewer, }; use reth_prune::{PruneModes, PrunerBuilder}; use reth_rpc_builder::config::RethRpcServerConfig; @@ -837,17 +840,34 @@ where pub const fn components(&self) -> &CB::Components { &self.node_adapter().components } +} +impl LaunchContextWith>> +where + T: FullNodeTypes< + Provider: WithTree + StateProviderFactory + ChainSpecProvider, + Types: NodeTypes, + >, + CB: NodeComponentsBuilder, +{ /// Returns the [`InvalidBlockHook`] to use for the node. pub fn invalid_block_hook(&self) -> eyre::Result> { Ok(if let Some(ref hook) = self.node_config().debug.invalid_block_hook { + let output_directory = self.data_dir().invalid_block_hooks(); let hooks = hook .iter() .copied() .map(|hook| { + let output_directory = output_directory.join(hook.to_string()); + fs::create_dir_all(&output_directory)?; + Ok(match hook { reth_node_core::args::InvalidBlockHook::Witness => { - Box::new(reth_invalid_block_hooks::witness) as Box + Box::new(InvalidBlockWitnessHook::new( + output_directory, + self.blockchain_db().clone(), + self.components().evm_config().clone(), + )) as Box } reth_node_core::args::InvalidBlockHook::PreState | reth_node_core::args::InvalidBlockHook::Opcode => { diff --git a/crates/node/builder/src/launch/engine.rs b/crates/node/builder/src/launch/engine.rs index 80f4b79cbace..7ce1c37a6c33 100644 --- a/crates/node/builder/src/launch/engine.rs +++ b/crates/node/builder/src/launch/engine.rs @@ -33,7 +33,7 @@ use reth_rpc_engine_api::{capabilities::EngineCapabilities, EngineApi}; use reth_rpc_types::{engine::ClientVersionV1, WithOtherFields}; use reth_tasks::TaskExecutor; use reth_tokio_util::EventSender; -use reth_tracing::tracing::{debug, error, info, warn}; +use reth_tracing::tracing::{debug, error, info}; use std::sync::Arc; use tokio::sync::{mpsc::unbounded_channel, oneshot}; use tokio_stream::wrappers::UnboundedReceiverStream; @@ -204,11 +204,6 @@ where let pruner_events = pruner.events(); info!(target: "reth::cli", prune_config=?ctx.prune_config().unwrap_or_default(), "Pruner initialized"); - // TODO: implement methods which convert this value into an actual function - if let Some(ref hook_type) = ctx.node_config().debug.invalid_block_hook { - warn!(target: "reth::cli", ?hook_type, "Invalid block hooks are not implemented yet! The `debug.invalid-block-hook` flag will do nothing for now."); - } - // Configure the consensus engine let mut eth_service = EngineService::new( ctx.consensus(), diff --git a/crates/node/builder/src/launch/mod.rs b/crates/node/builder/src/launch/mod.rs index e4d57805cbe6..39698f6e68e1 100644 --- a/crates/node/builder/src/launch/mod.rs +++ b/crates/node/builder/src/launch/mod.rs @@ -36,7 +36,7 @@ use reth_provider::providers::BlockchainProvider; use reth_rpc_engine_api::{capabilities::EngineCapabilities, EngineApi}; use reth_rpc_types::{engine::ClientVersionV1, WithOtherFields}; use reth_tasks::TaskExecutor; -use reth_tracing::tracing::{debug, info, warn}; +use reth_tracing::tracing::{debug, info}; use reth_transaction_pool::TransactionPool; use tokio::sync::{mpsc::unbounded_channel, oneshot}; use tokio_stream::wrappers::UnboundedReceiverStream; @@ -210,10 +210,6 @@ where let max_block = ctx.max_block(network_client.clone()).await?; let mut hooks = EngineHooks::new(); - if let Some(ref hook_type) = ctx.node_config().debug.invalid_block_hook { - warn!(target: "reth::cli", ?hook_type, "Bad block hooks are not implemented yet! The `debug.bad-block-hook` flag will do nothing for now."); - } - let static_file_producer = ctx.static_file_producer(); let static_file_producer_events = static_file_producer.lock().events(); hooks.add(StaticFileHook::new( diff --git a/crates/node/core/src/dirs.rs b/crates/node/core/src/dirs.rs index 5922b6818cd9..c788f35da1d6 100644 --- a/crates/node/core/src/dirs.rs +++ b/crates/node/core/src/dirs.rs @@ -343,6 +343,13 @@ impl ChainPath { pub fn jwt(&self) -> PathBuf { self.data_dir().join("jwt.hex") } + + /// Returns the path to the invalid block hooks directory for this chain. + /// + /// `//invalid_block_hooks` + pub fn invalid_block_hooks(&self) -> PathBuf { + self.data_dir().join("invalid_block_hooks") + } } impl AsRef for ChainPath { diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index adf0601eb9a2..25da9ef4d2f0 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -140,7 +140,7 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync { /// Note: this only looks at historical blocks, not pending blocks. fn history_by_block_hash(&self, block: BlockHash) -> ProviderResult; - /// Returns _any_[StateProvider] with matching block hash. + /// Returns _any_ [StateProvider] with matching block hash. /// /// This will return a [StateProvider] for either a historical or pending block. fn state_by_block_hash(&self, block: BlockHash) -> ProviderResult;