Skip to content

Commit

Permalink
always save mismatched bundle state / state root / trie updates
Browse files Browse the repository at this point in the history
  • Loading branch information
shekhirin committed Sep 6, 2024
1 parent 3306332 commit a6f5e3b
Showing 1 changed file with 63 additions and 22 deletions.
85 changes: 63 additions & 22 deletions crates/engine/invalid-block-hooks/src/witness.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use std::{collections::HashMap, fs::File, io::Write, path::PathBuf};
use std::{
collections::HashMap,
fmt::Debug,
fs::File,
io::Write,
path::{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::{
Expand All @@ -16,6 +23,7 @@ use reth_revm::{
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.
Expand All @@ -33,6 +41,34 @@ impl<P, EvmConfig> Witness<P, EvmConfig> {
}
}

impl<P, EvmConfig> Witness<P, EvmConfig> {
/// Compares two values and saves the diff if they are different.
///
/// Returns the path of the saved diff file if the values are different.
fn compare_and_save_diff<T: PartialEq + Debug>(
&self,
filename: String,
original: &T,
new: &T,
) -> Option<PathBuf> {
if original == new {
return None
}

let path = self.output_directory.join(filename);
let diff = Comparison::new(original, new);
File::options()
.write(true)
.create_new(true)
.open(&path)
.unwrap()
.write_all(diff.to_string().as_bytes())
.unwrap();

Some(path)
}
}

impl<P, EvmConfig> InvalidBlockHook for Witness<P, EvmConfig>
where
P: StateProviderFactory + ChainSpecProvider<ChainSpec = ChainSpec> + Send + Sync + 'static,
Expand Down Expand Up @@ -155,28 +191,33 @@ where
let response = ExecutionWitness { witness, state_preimages: Some(state_preimages) };
file.write_all(serde_json::to_string(&response)?.as_bytes())?;

if cfg!(debug_assertions) {
// The bundle state after re-execution should match the original one.
pretty_assertions::assert_eq!(
bundle_state,
output.state,
"Bundle state mismatch after re-execution"
);
// The bundle state after re-execution should match the original one.
if let Some(path) = self.compare_and_save_diff(
format!("{}_{}.bundle_state.diff", block.number, block.hash()),
&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 let Some(path) = self.compare_and_save_diff(
format!("{}_{}.state_root.diff", block.number, block.hash()),
&state_root,
&trie_updates.1,
) {
warn!(target: "engine::invalid_block_hooks::witness", path = %path.display(), "State root 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 {
pretty_assertions::assert_eq!(
state_root,
trie_updates.1,
"State root mismatch after re-execution"
);
pretty_assertions::assert_eq!(
&trie_output,
trie_updates.0,
"Trie updates mismatch after re-execution"
);
if let Some(path) = self.compare_and_save_diff(
format!("{}_{}.trie_updates.diff", block.number, block.hash()),
&trie_output,
trie_updates.0,
) {
warn!(target: "engine::invalid_block_hooks::witness", path = %path.display(), "Trie updates mismatch after re-execution");
}
}

Expand Down

0 comments on commit a6f5e3b

Please sign in to comment.