Skip to content

Commit

Permalink
show storage trie updates diff
Browse files Browse the repository at this point in the history
  • Loading branch information
fgimenez committed Dec 2, 2024
1 parent 63fd992 commit 2f8eafa
Showing 1 changed file with 151 additions and 2 deletions.
153 changes: 151 additions & 2 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ use reth_provider::{
};
use reth_revm::database::StateProviderDatabase;
use reth_stages_api::ControlFlow;
use reth_trie::{updates::TrieUpdates, HashedPostState, TrieInput};
use reth_trie::{
updates::{StorageTrieUpdates, TrieUpdates},
HashedPostState, Nibbles, TrieInput,
};
use reth_trie_parallel::root::{ParallelStateRoot, ParallelStateRootError};
use revm_primitives::EvmState;
use root::{StateRootConfig, StateRootMessage, StateRootTask};
Expand Down Expand Up @@ -2286,7 +2289,17 @@ where
match state_root_handle.wait_for_result() {
Ok(state_root_task_result) => {
info!(target: "engine::tree", block=?sealed_block.num_hash(), state_root_task_result=?state_root_task_result.0, regular_state_root_result = ?result.0);
info!(target: "engine::tree", block=?sealed_block.num_hash(), state_root_task_trie_updates=?state_root_task_result.1, regular_state_root_trie_updates = ?result.1);
let diff = compare_trie_updates(&state_root_task_result.1, &result.1);
if diff.has_differences() {
info!(target: "engine::tree",
block=?sealed_block.num_hash(),
storage_nodes_only_in_first= ?diff.storage_nodes_only_in_first,
storage_nodes_only_in_second= ?diff.storage_nodes_only_in_second,
storage_nodes_with_differences= ?diff.storage_nodes_with_differences,
"Found differences in TrieUpdates");
} else {
debug!(target: "engine::tree", block=?sealed_block.num_hash(), "TrieUpdates match exactly");
}
}
Err(e) => {
info!(target: "engine::tree", error=?e, "on state root task wait_for_result")
Expand Down Expand Up @@ -2643,6 +2656,142 @@ pub enum AdvancePersistenceError {
Provider(#[from] ProviderError),
}

#[derive(Debug, Default)]
struct TrieUpdatesDiff {
pub account_nodes_only_in_first: HashSet<Nibbles>,
pub account_nodes_only_in_second: HashSet<Nibbles>,
pub account_nodes_with_different_values: HashSet<Nibbles>,
pub removed_nodes_only_in_first: HashSet<Nibbles>,
pub removed_nodes_only_in_second: HashSet<Nibbles>,
pub storage_tries_only_in_first: HashSet<B256>,
pub storage_tries_only_in_second: HashSet<B256>,
pub storage_tries_with_differences: HashMap<B256, StorageTrieUpdatesDiff>,
}

#[derive(Debug, Default)]
struct StorageTrieUpdatesDiff {
pub is_deleted_differs: bool,
pub storage_nodes_only_in_first: HashSet<Nibbles>,
pub storage_nodes_only_in_second: HashSet<Nibbles>,
pub storage_nodes_with_different_values: HashSet<Nibbles>,
pub removed_nodes_only_in_first: HashSet<Nibbles>,
pub removed_nodes_only_in_second: HashSet<Nibbles>,
}

fn compare_trie_updates(first: &TrieUpdates, second: &TrieUpdates) -> TrieUpdatesDiff {
let mut diff = TrieUpdatesDiff::default();

// compare account nodes
for key in first.account_nodes.keys() {
if !second.account_nodes.contains_key(key) {
diff.account_nodes_only_in_first.insert(key.clone());
} else if first.account_nodes.get(key) != second.account_nodes.get(key) {
diff.account_nodes_with_different_values.insert(key.clone());
}
}
for key in second.account_nodes.keys() {
if !first.account_nodes.contains_key(key) {
diff.account_nodes_only_in_second.insert(key.clone());
}
}

// compare removed nodes
for node in &first.removed_nodes {
if !second.removed_nodes.contains(node) {
diff.removed_nodes_only_in_first.insert(node.clone());
}
}
for node in &second.removed_nodes {
if !first.removed_nodes.contains(node) {
diff.removed_nodes_only_in_second.insert(node.clone());
}
}

// compare storage tries
for key in first.storage_tries.keys() {
if second.storage_tries.contains_key(key) {
let storage_diff = compare_storage_trie_updates(
first.storage_tries.get(key).unwrap(),
second.storage_tries.get(key).unwrap(),
);
if storage_diff.has_differences() {
diff.storage_tries_with_differences.insert(*key, storage_diff);
}
} else {
diff.storage_tries_only_in_first.insert(*key);
}
}
for key in second.storage_tries.keys() {
if !first.storage_tries.contains_key(key) {
diff.storage_tries_only_in_second.insert(*key);
}
}

diff
}

fn compare_storage_trie_updates(
first: &StorageTrieUpdates,
second: &StorageTrieUpdates,
) -> StorageTrieUpdatesDiff {
let mut diff = StorageTrieUpdatesDiff {
is_deleted_differs: first.is_deleted != second.is_deleted,
..Default::default()
};

// compare storage nodes
for key in first.storage_nodes.keys() {
if !second.storage_nodes.contains_key(key) {
diff.storage_nodes_only_in_first.insert(key.clone());
} else if first.storage_nodes.get(key) != second.storage_nodes.get(key) {
diff.storage_nodes_with_different_values.insert(key.clone());
}
}
for key in second.storage_nodes.keys() {
if !first.storage_nodes.contains_key(key) {
diff.storage_nodes_only_in_second.insert(key.clone());
}
}

// compare removed nodes
for node in &first.removed_nodes {
if !second.removed_nodes.contains(node) {
diff.removed_nodes_only_in_first.insert(node.clone());
}
}
for node in &second.removed_nodes {
if !first.removed_nodes.contains(node) {
diff.removed_nodes_only_in_second.insert(node.clone());
}
}

diff
}

impl StorageTrieUpdatesDiff {
fn has_differences(&self) -> bool {
self.is_deleted_differs ||
!self.storage_nodes_only_in_first.is_empty() ||
!self.storage_nodes_only_in_second.is_empty() ||
!self.storage_nodes_with_different_values.is_empty() ||
!self.removed_nodes_only_in_first.is_empty() ||
!self.removed_nodes_only_in_second.is_empty()
}
}

impl TrieUpdatesDiff {
fn has_differences(&self) -> bool {
!self.account_nodes_only_in_first.is_empty() ||
!self.account_nodes_only_in_second.is_empty() ||
!self.account_nodes_with_different_values.is_empty() ||
!self.removed_nodes_only_in_first.is_empty() ||
!self.removed_nodes_only_in_second.is_empty() ||
!self.storage_tries_only_in_first.is_empty() ||
!self.storage_tries_only_in_second.is_empty() ||
!self.storage_tries_with_differences.is_empty()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 2f8eafa

Please sign in to comment.