Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use BlockExecutorProvider in InvalidBlockWitnessHook #14594

Merged
merged 1 commit into from
Feb 19, 2025
Merged
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
71 changes: 19 additions & 52 deletions crates/engine/invalid-block-hooks/src/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@ use alloy_rpc_types_debug::ExecutionWitness;
use pretty_assertions::Comparison;
use reth_chainspec::{EthChainSpec, EthereumHardforks};
use reth_engine_primitives::InvalidBlockHook;
use reth_evm::{
state_change::post_block_balance_increments, system_calls::SystemCaller, ConfigureEvmFor, Evm,
};
use reth_evm::execute::{BlockExecutorProvider, Executor};
use reth_primitives::{NodePrimitives, RecoveredBlock, SealedHeader};
use reth_provider::{BlockExecutionOutput, ChainSpecProvider, StateProviderFactory};
use reth_revm::{
database::StateProviderDatabase,
db::{states::bundle_state::BundleRetention, StateBuilder},
};
use reth_revm::database::StateProviderDatabase;
use reth_rpc_api::DebugApiClient;
use reth_tracing::tracing::warn;
use reth_trie::{updates::TrieUpdates, HashedStorage};
Expand All @@ -21,39 +16,41 @@ use std::{collections::HashMap, fmt::Debug, fs::File, io::Write, path::PathBuf};

/// Generates a witness for the given block and saves it to a file.
#[derive(Debug)]
pub struct InvalidBlockWitnessHook<P, EvmConfig> {
pub struct InvalidBlockWitnessHook<P, E> {
/// 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,
executor: E,
/// 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 healthy node client to compare the witness against.
healthy_node_client: Option<jsonrpsee::http_client::HttpClient>,
}

impl<P, EvmConfig> InvalidBlockWitnessHook<P, EvmConfig> {
impl<P, E> InvalidBlockWitnessHook<P, E> {
/// Creates a new witness hook.
pub const fn new(
provider: P,
evm_config: EvmConfig,
executor: E,
output_directory: PathBuf,
healthy_node_client: Option<jsonrpsee::http_client::HttpClient>,
) -> Self {
Self { provider, evm_config, output_directory, healthy_node_client }
Self { provider, executor, output_directory, healthy_node_client }
}
}

impl<P, EvmConfig> InvalidBlockWitnessHook<P, EvmConfig>
impl<P, E, N> InvalidBlockWitnessHook<P, E>
where
P: StateProviderFactory
+ ChainSpecProvider<ChainSpec: EthChainSpec + EthereumHardforks>
+ Send
+ Sync
+ 'static,
E: BlockExecutorProvider<Primitives = N>,
N: NodePrimitives,
{
fn on_invalid_block<N>(
fn on_invalid_block(
&self,
parent_header: &SealedHeader<N::BlockHeader>,
block: &RecoveredBlock<N::Block>,
Expand All @@ -62,46 +59,17 @@ where
) -> eyre::Result<()>
where
N: NodePrimitives,
EvmConfig: ConfigureEvmFor<N>,
{
// 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 EVM
let mut evm = self.evm_config.evm_for_block(&mut db, block.header());
let mut executor = self.executor.executor(StateProviderDatabase::new(
self.provider.state_by_block_hash(parent_header.hash())?,
));

let mut system_caller = SystemCaller::new(self.provider.chain_spec());

// Apply pre-block system contract calls.
system_caller.apply_pre_execution_changes(block.header(), &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_recovered() {
evm.transact_commit(self.evm_config.tx_env(tx))?;
}

drop(evm);

// use U256::MAX here for difficulty, because fetching it is annoying
// NOTE: This is not mut because we are not doing the DAO irregular state change here
let balance_increments =
post_block_balance_increments(self.provider.chain_spec().as_ref(), block);

// increment balances
db.increment_balances(balance_increments)?;

// Merge all state transitions
db.merge_transitions(BundleRetention::Reverts);
executor.execute_one(block)?;

// Take the bundle state
let mut db = executor.into_state();
let mut bundle_state = db.take_bundle();

// Initialize a map of preimages.
Expand Down Expand Up @@ -278,15 +246,14 @@ where
}
}

impl<P, EvmConfig, N> InvalidBlockHook<N> for InvalidBlockWitnessHook<P, EvmConfig>
impl<P, E, N: NodePrimitives> InvalidBlockHook<N> for InvalidBlockWitnessHook<P, E>
where
N: NodePrimitives,
P: StateProviderFactory
+ ChainSpecProvider<ChainSpec: EthChainSpec + EthereumHardforks>
+ Send
+ Sync
+ 'static,
EvmConfig: ConfigureEvmFor<N>,
E: BlockExecutorProvider<Primitives = N>,
{
fn on_invalid_block(
&self,
Expand All @@ -295,7 +262,7 @@ where
output: &BlockExecutionOutput<N::Receipt>,
trie_updates: Option<(&TrieUpdates, B256)>,
) {
if let Err(err) = self.on_invalid_block::<N>(parent_header, block, output, trie_updates) {
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");
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/node/builder/src/launch/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ where
Ok(match hook {
InvalidBlockHookType::Witness => Box::new(InvalidBlockWitnessHook::new(
self.blockchain_db().clone(),
self.components().evm_config().clone(),
self.components().block_executor().clone(),
output_directory,
healthy_node_rpc_client.clone(),
)),
Expand Down
Loading