From 20a6a851482b3a65e42208fbc5f41c5a8671019e Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:36:21 +0000 Subject: [PATCH] refactor(trie): initialize sparse trie with the provider (#15199) --- Cargo.lock | 1 + .../src/tree/payload_processor/sparse_trie.rs | 35 +-- crates/trie/sparse/Cargo.toml | 1 + crates/trie/sparse/benches/rlp_node.rs | 9 +- crates/trie/sparse/benches/root.rs | 5 +- crates/trie/sparse/src/blinded.rs | 2 + crates/trie/sparse/src/state.rs | 184 +++++++------ crates/trie/sparse/src/trie.rs | 242 ++++++++---------- crates/trie/trie/src/witness.rs | 9 +- 9 files changed, 215 insertions(+), 273 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8448e70661..adac7422cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10056,6 +10056,7 @@ dependencies = [ "alloy-rlp", "arbitrary", "assert_matches", + "auto_impl", "codspeed-criterion-compat", "itertools 0.14.0", "metrics", diff --git a/crates/engine/tree/src/tree/payload_processor/sparse_trie.rs b/crates/engine/tree/src/tree/payload_processor/sparse_trie.rs index 8cc5999b83..4fa48817b2 100644 --- a/crates/engine/tree/src/tree/payload_processor/sparse_trie.rs +++ b/crates/engine/tree/src/tree/payload_processor/sparse_trie.rs @@ -62,7 +62,7 @@ where let now = Instant::now(); let mut num_iterations = 0; - let mut trie = SparseStateTrie::default().with_updates(true); + let mut trie = SparseStateTrie::new(&self.blinded_provider_factory).with_updates(true); while let Ok(mut update) = self.updates.recv() { num_iterations += 1; @@ -80,10 +80,9 @@ where "Updating sparse trie" ); - let elapsed = update_sparse_trie(&mut trie, update, &self.blinded_provider_factory) - .map_err(|e| { - ParallelStateRootError::Other(format!("could not calculate state root: {e:?}")) - })?; + let elapsed = update_sparse_trie(&mut trie, update).map_err(|e| { + ParallelStateRootError::Other(format!("could not calculate state root: {e:?}")) + })?; self.metrics.sparse_trie_update_duration_histogram.record(elapsed); trace!(target: "engine::root", ?elapsed, num_iterations, "Root calculation completed"); } @@ -91,10 +90,9 @@ where debug!(target: "engine::root", num_iterations, "All proofs processed, ending calculation"); let start = Instant::now(); - let (state_root, trie_updates) = - trie.root_with_updates(&self.blinded_provider_factory).map_err(|e| { - ParallelStateRootError::Other(format!("could not calculate state root: {e:?}")) - })?; + let (state_root, trie_updates) = trie.root_with_updates().map_err(|e| { + ParallelStateRootError::Other(format!("could not calculate state root: {e:?}")) + })?; self.metrics.sparse_trie_final_update_duration_histogram.record(start.elapsed()); self.metrics.sparse_trie_total_duration_histogram.record(now.elapsed()); @@ -115,9 +113,8 @@ pub struct StateRootComputeOutcome { /// Updates the sparse trie with the given proofs and state, and returns the elapsed time. pub(crate) fn update_sparse_trie( - trie: &mut SparseStateTrie, + trie: &mut SparseStateTrie, SparseTrieUpdate { mut state, multiproof }: SparseTrieUpdate, - blinded_provider_factory: &BPF, ) -> SparseStateTrieResult where BPF: BlindedProviderFactory + Send + Sync, @@ -148,7 +145,6 @@ where let _enter = span.enter(); trace!(target: "engine::root::sparse", "Updating storage"); let mut storage_trie = storage_trie.ok_or(SparseTrieErrorKind::Blind)?; - let provider = blinded_provider_factory.storage_node_provider(address); if storage.wiped { trace!(target: "engine::root::sparse", "Wiping storage"); @@ -158,14 +154,11 @@ where let slot_nibbles = Nibbles::unpack(slot); if value.is_zero() { trace!(target: "engine::root::sparse", ?slot, "Removing storage slot"); - storage_trie.remove_leaf(&slot_nibbles, &provider)?; + storage_trie.remove_leaf(&slot_nibbles)?; } else { trace!(target: "engine::root::sparse", ?slot, "Updating storage slot"); - storage_trie.update_leaf( - slot_nibbles, - alloy_rlp::encode_fixed_size(&value).to_vec(), - &provider, - )?; + storage_trie + .update_leaf(slot_nibbles, alloy_rlp::encode_fixed_size(&value).to_vec())?; } } @@ -185,18 +178,18 @@ where // If the account itself has an update, remove it from the state update and update in // one go instead of doing it down below. trace!(target: "engine::root::sparse", ?address, "Updating account and its storage root"); - trie.update_account(address, account.unwrap_or_default(), blinded_provider_factory)?; + trie.update_account(address, account.unwrap_or_default())?; } else if trie.is_account_revealed(address) { // Otherwise, if the account is revealed, only update its storage root. trace!(target: "engine::root::sparse", ?address, "Updating account storage root"); - trie.update_account_storage_root(address, blinded_provider_factory)?; + trie.update_account_storage_root(address)?; } } // Update accounts for (address, account) in state.accounts { trace!(target: "engine::root::sparse", ?address, "Updating account"); - trie.update_account(address, account.unwrap_or_default(), blinded_provider_factory)?; + trie.update_account(address, account.unwrap_or_default())?; } let elapsed_before = started_at.elapsed(); diff --git a/crates/trie/sparse/Cargo.toml b/crates/trie/sparse/Cargo.toml index d69ab7c661..d448598331 100644 --- a/crates/trie/sparse/Cargo.toml +++ b/crates/trie/sparse/Cargo.toml @@ -23,6 +23,7 @@ alloy-primitives.workspace = true alloy-rlp.workspace = true # misc +auto_impl.workspace = true smallvec = { workspace = true, features = ["const_new"] } thiserror.workspace = true diff --git a/crates/trie/sparse/benches/rlp_node.rs b/crates/trie/sparse/benches/rlp_node.rs index 75c6f5f4ad..bebf1cbb98 100644 --- a/crates/trie/sparse/benches/rlp_node.rs +++ b/crates/trie/sparse/benches/rlp_node.rs @@ -7,7 +7,7 @@ use proptest::{prelude::*, test_runner::TestRunner}; use rand::seq::IteratorRandom; use reth_testing_utils::generators; use reth_trie::Nibbles; -use reth_trie_sparse::{blinded::DefaultBlindedProvider, RevealedSparseTrie}; +use reth_trie_sparse::RevealedSparseTrie; fn update_rlp_node_level(c: &mut Criterion) { let mut rng = generators::rng(); @@ -25,11 +25,7 @@ fn update_rlp_node_level(c: &mut Criterion) { let mut sparse = RevealedSparseTrie::default(); for (key, value) in &state { sparse - .update_leaf( - Nibbles::unpack(key), - alloy_rlp::encode_fixed_size(value).to_vec(), - &DefaultBlindedProvider, - ) + .update_leaf(Nibbles::unpack(key), alloy_rlp::encode_fixed_size(value).to_vec()) .unwrap(); } sparse.root(); @@ -43,7 +39,6 @@ fn update_rlp_node_level(c: &mut Criterion) { .update_leaf( Nibbles::unpack(key), alloy_rlp::encode_fixed_size(&rng.gen::()).to_vec(), - &DefaultBlindedProvider, ) .unwrap(); } diff --git a/crates/trie/sparse/benches/root.rs b/crates/trie/sparse/benches/root.rs index fff530efd6..95e401630a 100644 --- a/crates/trie/sparse/benches/root.rs +++ b/crates/trie/sparse/benches/root.rs @@ -13,7 +13,7 @@ use reth_trie::{ HashedStorage, }; use reth_trie_common::{HashBuilder, Nibbles}; -use reth_trie_sparse::{blinded::DefaultBlindedProvider, SparseTrie}; +use reth_trie_sparse::SparseTrie; fn calculate_root_from_leaves(c: &mut Criterion) { let mut group = c.benchmark_group("calculate root from leaves"); @@ -47,7 +47,6 @@ fn calculate_root_from_leaves(c: &mut Criterion) { .update_leaf( Nibbles::unpack(key), alloy_rlp::encode_fixed_size(value).to_vec(), - &DefaultBlindedProvider, ) .unwrap(); } @@ -189,7 +188,6 @@ fn calculate_root_from_leaves_repeated(c: &mut Criterion) { .update_leaf( Nibbles::unpack(key), alloy_rlp::encode_fixed_size(value).to_vec(), - &DefaultBlindedProvider, ) .unwrap(); } @@ -203,7 +201,6 @@ fn calculate_root_from_leaves_repeated(c: &mut Criterion) { .update_leaf( Nibbles::unpack(key), alloy_rlp::encode_fixed_size(value).to_vec(), - &DefaultBlindedProvider, ) .unwrap(); } diff --git a/crates/trie/sparse/src/blinded.rs b/crates/trie/sparse/src/blinded.rs index f2954b5df5..dc46e86067 100644 --- a/crates/trie/sparse/src/blinded.rs +++ b/crates/trie/sparse/src/blinded.rs @@ -5,6 +5,7 @@ use reth_execution_errors::SparseTrieError; use reth_trie_common::{Nibbles, TrieMask}; /// Factory for instantiating blinded node providers. +#[auto_impl::auto_impl(&)] pub trait BlindedProviderFactory { /// Type capable of fetching blinded account nodes. type AccountNodeProvider: BlindedProvider; @@ -30,6 +31,7 @@ pub struct RevealedNode { } /// Trie node provider for retrieving blinded nodes. +#[auto_impl::auto_impl(&)] pub trait BlindedProvider { /// Retrieve blinded node by path. fn blinded_node(&self, path: &Nibbles) -> Result, SparseTrieError>; diff --git a/crates/trie/sparse/src/state.rs b/crates/trie/sparse/src/state.rs index a078cf6126..2b0bae9480 100644 --- a/crates/trie/sparse/src/state.rs +++ b/crates/trie/sparse/src/state.rs @@ -1,13 +1,15 @@ use crate::{ - blinded::{BlindedProvider, BlindedProviderFactory}, + blinded::{BlindedProvider, BlindedProviderFactory, DefaultBlindedProviderFactory}, metrics::SparseStateTrieMetrics, RevealedSparseTrie, SparseTrie, TrieMasks, }; use alloy_primitives::{ + hex, map::{B256Map, HashMap, HashSet}, Bytes, B256, }; use alloy_rlp::{Decodable, Encodable}; +use core::fmt; use reth_execution_errors::{SparseStateTrieErrorKind, SparseStateTrieResult, SparseTrieErrorKind}; use reth_primitives_traits::Account; use reth_tracing::tracing::trace; @@ -20,12 +22,13 @@ use reth_trie_common::{ use std::{collections::VecDeque, iter::Peekable}; /// Sparse state trie representing lazy-loaded Ethereum state trie. -#[derive(Debug)] -pub struct SparseStateTrie { +pub struct SparseStateTrie { + /// Blinded node provider factory. + provider_factory: F, /// Sparse account trie. - state: SparseTrie, + state: SparseTrie, /// Sparse storage tries. - storages: B256Map, + storages: B256Map>, /// Collection of revealed account trie paths. revealed_account_paths: HashSet, /// Collection of revealed storage trie paths, per account. @@ -38,9 +41,11 @@ pub struct SparseStateTrie { metrics: SparseStateTrieMetrics, } +#[cfg(test)] impl Default for SparseStateTrie { fn default() -> Self { Self { + provider_factory: DefaultBlindedProviderFactory, state: Default::default(), storages: Default::default(), revealed_account_paths: Default::default(), @@ -52,6 +57,20 @@ impl Default for SparseStateTrie { } } +impl fmt::Debug for SparseStateTrie

{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SparseStateTrie") + .field("state", &self.state) + .field("storages", &self.storages) + .field("revealed_account_paths", &self.revealed_account_paths) + .field("revealed_storage_paths", &self.revealed_storage_paths) + .field("retain_updates", &self.retain_updates) + .field("account_rlp_buf", &hex::encode(&self.account_rlp_buf)) + .finish_non_exhaustive() + } +} + +#[cfg(test)] impl SparseStateTrie { /// Create state trie from state trie. pub fn from_state(state: SparseTrie) -> Self { @@ -59,7 +78,21 @@ impl SparseStateTrie { } } -impl SparseStateTrie { +impl SparseStateTrie { + /// Create new [`SparseStateTrie`] with blinded node provider factory. + pub fn new(provider_factory: F) -> Self { + Self { + provider_factory, + state: Default::default(), + storages: Default::default(), + revealed_account_paths: Default::default(), + revealed_storage_paths: Default::default(), + retain_updates: false, + account_rlp_buf: Vec::with_capacity(TRIE_ACCOUNT_RLP_MAX_SIZE), + metrics: Default::default(), + } + } + /// Set the retention of branch node updates and deletions. pub const fn with_updates(mut self, retain_updates: bool) -> Self { self.retain_updates = retain_updates; @@ -89,27 +122,40 @@ impl SparseStateTrie { } /// Returns reference to state trie if it was revealed. - pub const fn state_trie_ref(&self) -> Option<&RevealedSparseTrie> { + pub const fn state_trie_ref(&self) -> Option<&RevealedSparseTrie> { self.state.as_revealed_ref() } /// Returns reference to storage trie if it was revealed. - pub fn storage_trie_ref(&self, address: &B256) -> Option<&RevealedSparseTrie> { + pub fn storage_trie_ref( + &self, + address: &B256, + ) -> Option<&RevealedSparseTrie> { self.storages.get(address).and_then(|e| e.as_revealed_ref()) } /// Returns mutable reference to storage sparse trie if it was revealed. - pub fn storage_trie_mut(&mut self, address: &B256) -> Option<&mut RevealedSparseTrie> { + pub fn storage_trie_mut( + &mut self, + address: &B256, + ) -> Option<&mut RevealedSparseTrie> { self.storages.get_mut(address).and_then(|e| e.as_revealed_mut()) } /// Takes the storage trie for the provided address. - pub fn take_storage_trie(&mut self, address: &B256) -> Option { + pub fn take_storage_trie( + &mut self, + address: &B256, + ) -> Option> { self.storages.remove(address) } /// Inserts storage trie for the provided address. - pub fn insert_storage_trie(&mut self, address: B256, storage_trie: SparseTrie) { + pub fn insert_storage_trie( + &mut self, + address: B256, + storage_trie: SparseTrie, + ) { self.storages.insert(address, storage_trie); } @@ -135,6 +181,7 @@ impl SparseStateTrie { // Reveal root node if it wasn't already. let trie = self.state.reveal_root_with_provider( + self.provider_factory.account_node_provider(), root_node, TrieMasks::none(), self.retain_updates, @@ -178,6 +225,7 @@ impl SparseStateTrie { // Reveal root node if it wasn't already. let trie = self.storages.entry(account).or_default().reveal_root_with_provider( + self.provider_factory.storage_node_provider(account), root_node, TrieMasks::none(), self.retain_updates, @@ -239,6 +287,7 @@ impl SparseStateTrie { if let Some(root_node) = self.validate_root_node(&mut account_nodes)? { // Reveal root node if it wasn't already. let trie = self.state.reveal_root_with_provider( + self.provider_factory.account_node_provider(), root_node, TrieMasks { hash_mask: branch_node_hash_masks.get(&Nibbles::default()).copied(), @@ -288,6 +337,7 @@ impl SparseStateTrie { if let Some(root_node) = self.validate_root_node(&mut nodes)? { // Reveal root node if it wasn't already. let trie = self.storages.entry(account).or_default().reveal_root_with_provider( + self.provider_factory.storage_node_provider(account), root_node, TrieMasks { hash_mask: storage_subtree @@ -397,6 +447,7 @@ impl SparseStateTrie { if path.is_empty() { // Handle special storage state root node case. storage_trie_entry.reveal_root_with_provider( + self.provider_factory.storage_node_provider(account), trie_node, TrieMasks::none(), self.retain_updates, @@ -418,6 +469,7 @@ impl SparseStateTrie { if path.is_empty() { // Handle special state root node case. self.state.reveal_root_with_provider( + self.provider_factory.account_node_provider(), trie_node, TrieMasks::none(), self.retain_updates, @@ -488,11 +540,11 @@ impl SparseStateTrie { /// If the trie is not revealed yet, its root will be revealed using the blinded node provider. fn revealed_trie_mut( &mut self, - provider_factory: &impl BlindedProviderFactory, - ) -> SparseStateTrieResult<&mut RevealedSparseTrie> { + ) -> SparseStateTrieResult<&mut RevealedSparseTrie> { match self.state { SparseTrie::Blind => { - let (root_node, hash_mask, tree_mask) = provider_factory + let (root_node, hash_mask, tree_mask) = self + .provider_factory .account_node_provider() .blinded_node(&Nibbles::default())? .map(|node| { @@ -503,6 +555,7 @@ impl SparseStateTrie { .unwrap_or((TrieNode::EmptyRoot, None, None)); self.state .reveal_root_with_provider( + self.provider_factory.account_node_provider(), root_node, TrieMasks { hash_mask, tree_mask }, self.retain_updates, @@ -516,26 +569,20 @@ impl SparseStateTrie { /// Returns sparse trie root. /// /// If the trie has not been revealed, this function reveals the root node and returns its hash. - pub fn root( - &mut self, - provider_factory: &impl BlindedProviderFactory, - ) -> SparseStateTrieResult { + pub fn root(&mut self) -> SparseStateTrieResult { // record revealed node metrics self.metrics.record(); - Ok(self.revealed_trie_mut(provider_factory)?.root()) + Ok(self.revealed_trie_mut()?.root()) } /// Returns sparse trie root and trie updates if the trie has been revealed. - pub fn root_with_updates( - &mut self, - provider_factory: &impl BlindedProviderFactory, - ) -> SparseStateTrieResult<(B256, TrieUpdates)> { + pub fn root_with_updates(&mut self) -> SparseStateTrieResult<(B256, TrieUpdates)> { // record revealed node metrics self.metrics.record(); let storage_tries = self.storage_trie_updates(); - let revealed = self.revealed_trie_mut(provider_factory)?; + let revealed = self.revealed_trie_mut()?; let (root, updates) = (revealed.root(), revealed.take_updates()); let updates = TrieUpdates { @@ -586,13 +633,12 @@ impl SparseStateTrie { &mut self, path: Nibbles, value: Vec, - provider_factory: &impl BlindedProviderFactory, ) -> SparseStateTrieResult<()> { if !self.revealed_account_paths.contains(&path) { self.revealed_account_paths.insert(path.clone()); } - self.state.update_leaf(path, value, &provider_factory.account_node_provider())?; + self.state.update_leaf(path, value)?; Ok(()) } @@ -602,14 +648,13 @@ impl SparseStateTrie { address: B256, slot: Nibbles, value: Vec, - provider_factory: &impl BlindedProviderFactory, ) -> SparseStateTrieResult<()> { if !self.revealed_storage_paths.get(&address).is_some_and(|slots| slots.contains(&slot)) { self.revealed_storage_paths.entry(address).or_default().insert(slot.clone()); } let storage_trie = self.storages.get_mut(&address).ok_or(SparseTrieErrorKind::Blind)?; - storage_trie.update_leaf(slot, value, &provider_factory.storage_node_provider(address))?; + storage_trie.update_leaf(slot, value)?; Ok(()) } @@ -617,12 +662,7 @@ impl SparseStateTrie { /// the storage root based on update storage trie or look it up from existing leaf value. /// /// If the new account info and storage trie are empty, the account leaf will be removed. - pub fn update_account( - &mut self, - address: B256, - account: Account, - provider_factory: &impl BlindedProviderFactory, - ) -> SparseStateTrieResult<()> { + pub fn update_account(&mut self, address: B256, account: Account) -> SparseStateTrieResult<()> { let nibbles = Nibbles::unpack(address); let storage_root = if let Some(storage_trie) = self.storages.get_mut(&address) { @@ -644,12 +684,12 @@ impl SparseStateTrie { if account.is_empty() && storage_root == EMPTY_ROOT_HASH { trace!(target: "trie::sparse", ?address, "Removing account"); - self.remove_account_leaf(&nibbles, provider_factory) + self.remove_account_leaf(&nibbles) } else { trace!(target: "trie::sparse", ?address, "Updating account"); self.account_rlp_buf.clear(); account.into_trie_account(storage_root).encode(&mut self.account_rlp_buf); - self.update_account_leaf(nibbles, self.account_rlp_buf.clone(), provider_factory) + self.update_account_leaf(nibbles, self.account_rlp_buf.clone()) } } @@ -659,11 +699,7 @@ impl SparseStateTrie { /// /// If the new storage root is empty, and the account info was already empty, the account leaf /// will be removed. - pub fn update_account_storage_root( - &mut self, - address: B256, - provider_factory: &impl BlindedProviderFactory, - ) -> SparseStateTrieResult<()> { + pub fn update_account_storage_root(&mut self, address: B256) -> SparseStateTrieResult<()> { if !self.is_account_revealed(address) { return Err(SparseTrieErrorKind::Blind.into()) } @@ -694,25 +730,21 @@ impl SparseStateTrie { if trie_account == TrieAccount::default() { // If the account is empty, remove it. trace!(target: "trie::sparse", ?address, "Removing account because the storage root is empty"); - self.remove_account_leaf(&nibbles, provider_factory)?; + self.remove_account_leaf(&nibbles)?; } else { // Otherwise, update the account leaf. trace!(target: "trie::sparse", ?address, "Updating account with the new storage root"); self.account_rlp_buf.clear(); trie_account.encode(&mut self.account_rlp_buf); - self.update_account_leaf(nibbles, self.account_rlp_buf.clone(), provider_factory)?; + self.update_account_leaf(nibbles, self.account_rlp_buf.clone())?; } Ok(()) } /// Remove the account leaf node. - pub fn remove_account_leaf( - &mut self, - path: &Nibbles, - provider_factory: &impl BlindedProviderFactory, - ) -> SparseStateTrieResult<()> { - self.state.remove_leaf(path, &provider_factory.account_node_provider())?; + pub fn remove_account_leaf(&mut self, path: &Nibbles) -> SparseStateTrieResult<()> { + self.state.remove_leaf(path)?; Ok(()) } @@ -721,18 +753,15 @@ impl SparseStateTrie { &mut self, address: B256, slot: &Nibbles, - provider_factory: &impl BlindedProviderFactory, ) -> SparseStateTrieResult<()> { let storage_trie = self.storages.get_mut(&address).ok_or(SparseTrieErrorKind::Blind)?; - storage_trie.remove_leaf(slot, &provider_factory.account_node_provider())?; + storage_trie.remove_leaf(slot)?; Ok(()) } } #[cfg(test)] mod tests { - use crate::blinded::DefaultBlindedProviderFactory; - use super::*; use alloy_primitives::{ b256, @@ -852,9 +881,7 @@ mod tests { // Remove the leaf node and check that the state trie does not contain the leaf node and // value - sparse - .remove_account_leaf(&Nibbles::from_nibbles([0x0]), &DefaultBlindedProviderFactory) - .unwrap(); + sparse.remove_account_leaf(&Nibbles::from_nibbles([0x0])).unwrap(); assert!(!sparse .state_trie_ref() .unwrap() @@ -936,13 +963,7 @@ mod tests { // Remove the leaf node and check that the storage trie does not contain the leaf node and // value - sparse - .remove_storage_leaf( - B256::ZERO, - &Nibbles::from_nibbles([0x0]), - &DefaultBlindedProviderFactory, - ) - .unwrap(); + sparse.remove_storage_leaf(B256::ZERO, &Nibbles::from_nibbles([0x0])).unwrap(); assert!(!sparse .storage_trie_ref(&B256::ZERO) .unwrap() @@ -1056,49 +1077,24 @@ mod tests { }) .unwrap(); - assert_eq!(sparse.root(&DefaultBlindedProviderFactory).unwrap(), root); + assert_eq!(sparse.root().unwrap(), root); let address_3 = b256!("0x2000000000000000000000000000000000000000000000000000000000000000"); let address_path_3 = Nibbles::unpack(address_3); let account_3 = Account { nonce: account_1.nonce + 1, ..account_1 }; let trie_account_3 = account_3.into_trie_account(EMPTY_ROOT_HASH); - sparse - .update_account_leaf( - address_path_3, - alloy_rlp::encode(trie_account_3), - &DefaultBlindedProviderFactory, - ) - .unwrap(); + sparse.update_account_leaf(address_path_3, alloy_rlp::encode(trie_account_3)).unwrap(); - sparse - .update_storage_leaf( - address_1, - slot_path_3, - alloy_rlp::encode(value_3), - &DefaultBlindedProviderFactory, - ) - .unwrap(); + sparse.update_storage_leaf(address_1, slot_path_3, alloy_rlp::encode(value_3)).unwrap(); trie_account_1.storage_root = sparse.storage_root(address_1).unwrap(); - sparse - .update_account_leaf( - address_path_1, - alloy_rlp::encode(trie_account_1), - &DefaultBlindedProviderFactory, - ) - .unwrap(); + sparse.update_account_leaf(address_path_1, alloy_rlp::encode(trie_account_1)).unwrap(); sparse.wipe_storage(address_2).unwrap(); trie_account_2.storage_root = sparse.storage_root(address_2).unwrap(); - sparse - .update_account_leaf( - address_path_2, - alloy_rlp::encode(trie_account_2), - &DefaultBlindedProviderFactory, - ) - .unwrap(); + sparse.update_account_leaf(address_path_2, alloy_rlp::encode(trie_account_2)).unwrap(); - sparse.root(&DefaultBlindedProviderFactory).unwrap(); + sparse.root().unwrap(); let sparse_updates = sparse.take_trie_updates().unwrap(); // TODO(alexey): assert against real state root calculation updates diff --git a/crates/trie/sparse/src/trie.rs b/crates/trie/sparse/src/trie.rs index 937253dd06..343de19035 100644 --- a/crates/trie/sparse/src/trie.rs +++ b/crates/trie/sparse/src/trie.rs @@ -1,4 +1,4 @@ -use crate::blinded::{BlindedProvider, RevealedNode}; +use crate::blinded::{BlindedProvider, DefaultBlindedProvider, RevealedNode}; use alloy_primitives::{ hex, keccak256, map::{Entry, HashMap, HashSet}, @@ -34,14 +34,14 @@ impl TrieMasks { /// Inner representation of the sparse trie. /// Sparse trie is blind by default until nodes are revealed. #[derive(PartialEq, Eq)] -pub enum SparseTrie { +pub enum SparseTrie

{ /// None of the trie nodes are known. Blind, /// The trie nodes have been revealed. - Revealed(Box), + Revealed(Box>), } -impl fmt::Debug for SparseTrie { +impl

fmt::Debug for SparseTrie

{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Blind => write!(f, "Blind"), @@ -50,7 +50,7 @@ impl fmt::Debug for SparseTrie { } } -impl Default for SparseTrie { +impl

Default for SparseTrie

{ fn default() -> Self { Self::Blind } @@ -78,18 +78,18 @@ impl SparseTrie { masks: TrieMasks, retain_updates: bool, ) -> SparseTrieResult<&mut RevealedSparseTrie> { - self.reveal_root_with_provider(root, masks, retain_updates) + self.reveal_root_with_provider(Default::default(), root, masks, retain_updates) } } -impl SparseTrie { +impl

SparseTrie

{ /// Returns `true` if the sparse trie has no revealed nodes. pub const fn is_blind(&self) -> bool { matches!(self, Self::Blind) } /// Returns reference to revealed sparse trie if the trie is not blind. - pub const fn as_revealed_ref(&self) -> Option<&RevealedSparseTrie> { + pub const fn as_revealed_ref(&self) -> Option<&RevealedSparseTrie

> { if let Self::Revealed(revealed) = self { Some(revealed) } else { @@ -98,7 +98,7 @@ impl SparseTrie { } /// Returns mutable reference to revealed sparse trie if the trie is not blind. - pub fn as_revealed_mut(&mut self) -> Option<&mut RevealedSparseTrie> { + pub fn as_revealed_mut(&mut self) -> Option<&mut RevealedSparseTrie

> { if let Self::Revealed(revealed) = self { Some(revealed) } else { @@ -113,12 +113,14 @@ impl SparseTrie { /// Mutable reference to [`RevealedSparseTrie`]. pub fn reveal_root_with_provider( &mut self, + provider: P, root: TrieNode, masks: TrieMasks, retain_updates: bool, - ) -> SparseTrieResult<&mut RevealedSparseTrie> { + ) -> SparseTrieResult<&mut RevealedSparseTrie

> { if self.is_blind() { - *self = Self::Revealed(Box::new(RevealedSparseTrie::from_root_node( + *self = Self::Revealed(Box::new(RevealedSparseTrie::from_provider_and_root( + provider, root, masks, retain_updates, @@ -146,27 +148,18 @@ impl SparseTrie { } } -impl SparseTrie { +impl SparseTrie

{ /// Update the leaf node. - pub fn update_leaf( - &mut self, - path: Nibbles, - value: Vec, - provider: &P, - ) -> SparseTrieResult<()> { + pub fn update_leaf(&mut self, path: Nibbles, value: Vec) -> SparseTrieResult<()> { let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?; - revealed.update_leaf(path, value, provider)?; + revealed.update_leaf(path, value)?; Ok(()) } /// Remove the leaf node. - pub fn remove_leaf( - &mut self, - path: &Nibbles, - provider: &P, - ) -> SparseTrieResult<()> { + pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> { let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?; - revealed.remove_leaf(path, provider)?; + revealed.remove_leaf(path)?; Ok(()) } } @@ -180,7 +173,9 @@ impl SparseTrie { /// The opposite is also true. /// - All keys in `values` collection are full leaf paths. #[derive(Clone, PartialEq, Eq)] -pub struct RevealedSparseTrie { +pub struct RevealedSparseTrie

{ + /// Blinded node provider. + provider: P, /// All trie nodes. nodes: HashMap, /// All branch node tree masks. @@ -197,7 +192,7 @@ pub struct RevealedSparseTrie { rlp_buf: Vec, } -impl fmt::Debug for RevealedSparseTrie { +impl

fmt::Debug for RevealedSparseTrie

{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RevealedSparseTrie") .field("nodes", &self.nodes) @@ -217,7 +212,7 @@ fn encode_nibbles(nibbles: &Nibbles) -> String { encoded[..nibbles.len()].to_string() } -impl fmt::Display for RevealedSparseTrie { +impl fmt::Display for RevealedSparseTrie

{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // This prints the trie in preorder traversal, using a stack let mut stack = Vec::new(); @@ -286,6 +281,7 @@ impl fmt::Display for RevealedSparseTrie { impl Default for RevealedSparseTrie { fn default() -> Self { Self { + provider: Default::default(), nodes: HashMap::from_iter([(Nibbles::default(), SparseNode::Empty)]), branch_node_tree_masks: HashMap::default(), branch_node_hash_masks: HashMap::default(), @@ -305,6 +301,7 @@ impl RevealedSparseTrie { retain_updates: bool, ) -> SparseTrieResult { let mut this = Self { + provider: Default::default(), nodes: HashMap::default(), branch_node_tree_masks: HashMap::default(), branch_node_hash_masks: HashMap::default(), @@ -319,14 +316,16 @@ impl RevealedSparseTrie { } } -impl RevealedSparseTrie { +impl

RevealedSparseTrie

{ /// Create new revealed sparse trie from the given root node. - pub fn from_root_node( + pub fn from_provider_and_root( + provider: P, node: TrieNode, masks: TrieMasks, retain_updates: bool, ) -> SparseTrieResult { let mut this = Self { + provider, nodes: HashMap::default(), branch_node_tree_masks: HashMap::default(), branch_node_hash_masks: HashMap::default(), @@ -341,8 +340,17 @@ impl RevealedSparseTrie { } /// Set new blinded node provider on sparse trie. - pub fn with_provider(self) -> Self { - self + pub fn with_provider(self, provider: BP) -> RevealedSparseTrie { + RevealedSparseTrie { + provider, + nodes: self.nodes, + branch_node_tree_masks: self.branch_node_tree_masks, + branch_node_hash_masks: self.branch_node_hash_masks, + values: self.values, + prefix_set: self.prefix_set, + updates: self.updates, + rlp_buf: self.rlp_buf, + } } /// Set the retention of branch node updates and deletions. @@ -668,26 +676,10 @@ impl RevealedSparseTrie { path, is_in_prefix_set: Some(true), }); - - self.rlp_node_using_buf(&mut prefix_set, &mut buffers); + self.rlp_node(&mut prefix_set, &mut buffers); } } - /// Helper function to take out the rlp buffer while calling the `rlp_node` function. - fn rlp_node_using_buf( - &mut self, - prefix_set: &mut PrefixSet, - buffers: &mut RlpNodeBuffers, - ) -> RlpNode { - // take rlp_buf out, so we can pass it to the function - let mut rlp_buf = std::mem::take(&mut self.rlp_buf); - let rlp_node = self.rlp_node(prefix_set, buffers, &mut rlp_buf); - - // put the buf back - self.rlp_buf = rlp_buf; - rlp_node - } - /// Returns a list of levels and paths to the nodes that were changed according to the prefix /// set and are located at the provided depth when counting from the root node. If there's a /// leaf at a depth less than the provided depth, it will be included in the result. @@ -752,15 +744,14 @@ impl RevealedSparseTrie { (targets, unchanged_prefix_set) } - /// Look up or calculate the RLP of the node at the root path. Allocates a new - /// [`RlpNodeBuffers`] for the computation. + /// Look up or calculate the RLP of the node at the root path. /// /// # Panics /// /// If the node at provided path does not exist. pub fn rlp_node_allocate(&mut self, prefix_set: &mut PrefixSet) -> RlpNode { let mut buffers = RlpNodeBuffers::new_with_root_path(); - self.rlp_node_using_buf(prefix_set, &mut buffers) + self.rlp_node(prefix_set, &mut buffers) } /// Look up or calculate the RLP of the node at the given path specified in [`RlpNodeBuffers`]. @@ -772,7 +763,6 @@ impl RevealedSparseTrie { &mut self, prefix_set: &mut PrefixSet, buffers: &mut RlpNodeBuffers, - rlp_buf: &mut Vec, ) -> RlpNode { let starting_path = buffers.path_stack.last().map(|item| item.path.clone()); @@ -806,8 +796,8 @@ impl RevealedSparseTrie { (RlpNode::word_rlp(&hash), SparseNodeType::Leaf) } else { let value = self.values.get(&path).unwrap(); - rlp_buf.clear(); - let rlp_node = LeafNodeRef { key, value }.rlp(rlp_buf); + self.rlp_buf.clear(); + let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.rlp_buf); *hash = rlp_node.as_hash(); (rlp_node, SparseNodeType::Leaf) } @@ -828,8 +818,8 @@ impl RevealedSparseTrie { rlp_node: child, node_type: child_node_type, } = buffers.rlp_node_stack.pop().unwrap(); - rlp_buf.clear(); - let rlp_node = ExtensionNodeRef::new(key, &child).rlp(rlp_buf); + self.rlp_buf.clear(); + let rlp_node = ExtensionNodeRef::new(key, &child).rlp(&mut self.rlp_buf); *hash = rlp_node.as_hash(); let store_in_db_trie_value = child_node_type.store_in_db_trie(); @@ -980,10 +970,10 @@ impl RevealedSparseTrie { "Branch node masks" ); - rlp_buf.clear(); + self.rlp_buf.clear(); let branch_node_ref = BranchNodeRef::new(&buffers.branch_value_stack_buf, *state_mask); - let rlp_node = branch_node_ref.rlp(rlp_buf); + let rlp_node = branch_node_ref.rlp(&mut self.rlp_buf); *hash = rlp_node.as_hash(); // Save a branch node update only if it's not a root node, and we need to @@ -1062,14 +1052,9 @@ impl RevealedSparseTrie { } } -impl RevealedSparseTrie { +impl RevealedSparseTrie

{ /// Update the leaf node with provided value. - pub fn update_leaf( - &mut self, - path: Nibbles, - value: Vec, - provider: &P, - ) -> SparseTrieResult<()> { + pub fn update_leaf(&mut self, path: Nibbles, value: Vec) -> SparseTrieResult<()> { self.prefix_set.insert(path.clone()); let existing = self.values.insert(path.clone(), value); if existing.is_some() { @@ -1134,7 +1119,7 @@ impl RevealedSparseTrie { // Check if the extension node child is a hash that needs to be revealed if self.nodes.get(¤t).unwrap().is_hash() { if let Some(RevealedNode { node, tree_mask, hash_mask }) = - provider.blinded_node(¤t)? + self.provider.blinded_node(¤t)? { let decoded = TrieNode::decode(&mut &node[..])?; trace!( @@ -1190,11 +1175,7 @@ impl RevealedSparseTrie { } /// Remove leaf node from the trie. - pub fn remove_leaf( - &mut self, - path: &Nibbles, - provider: &P, - ) -> SparseTrieResult<()> { + pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> { if self.values.remove(path).is_none() { if let Some(&SparseNode::Hash(hash)) = self.nodes.get(path) { // Leaf is present in the trie, but it's blinded. @@ -1301,7 +1282,7 @@ impl RevealedSparseTrie { if self.nodes.get(&child_path).unwrap().is_hash() { trace!(target: "trie::sparse", ?child_path, "Retrieving remaining blinded branch child"); if let Some(RevealedNode { node, tree_mask, hash_mask }) = - provider.blinded_node(&child_path)? + self.provider.blinded_node(&child_path)? { let decoded = TrieNode::decode(&mut &node[..])?; trace!( @@ -1594,8 +1575,6 @@ impl SparseTrieUpdates { #[cfg(test)] mod tests { - use crate::blinded::DefaultBlindedProvider; - use super::*; use alloy_primitives::{map::B256Set, U256}; use alloy_rlp::Encodable; @@ -1781,8 +1760,7 @@ mod tests { ); let mut sparse = RevealedSparseTrie::default().with_updates(true); - let provider = DefaultBlindedProvider; - sparse.update_leaf(key, value_encoded(), &provider).unwrap(); + sparse.update_leaf(key, value_encoded()).unwrap(); let sparse_root = sparse.root(); let sparse_updates = sparse.take_updates(); @@ -1812,9 +1790,8 @@ mod tests { ); let mut sparse = RevealedSparseTrie::default().with_updates(true); - let provider = DefaultBlindedProvider; for path in &paths { - sparse.update_leaf(path.clone(), value_encoded(), &provider).unwrap(); + sparse.update_leaf(path.clone(), value_encoded()).unwrap(); } let sparse_root = sparse.root(); let sparse_updates = sparse.take_updates(); @@ -1843,9 +1820,8 @@ mod tests { ); let mut sparse = RevealedSparseTrie::default().with_updates(true); - let provider = DefaultBlindedProvider; for path in &paths { - sparse.update_leaf(path.clone(), value_encoded(), &provider).unwrap(); + sparse.update_leaf(path.clone(), value_encoded()).unwrap(); } let sparse_root = sparse.root(); let sparse_updates = sparse.take_updates(); @@ -1882,9 +1858,8 @@ mod tests { ); let mut sparse = RevealedSparseTrie::default().with_updates(true); - let provider = DefaultBlindedProvider; for path in &paths { - sparse.update_leaf(path.clone(), value_encoded(), &provider).unwrap(); + sparse.update_leaf(path.clone(), value_encoded()).unwrap(); } let sparse_root = sparse.root(); let sparse_updates = sparse.take_updates(); @@ -1922,9 +1897,8 @@ mod tests { ); let mut sparse = RevealedSparseTrie::default().with_updates(true); - let provider = DefaultBlindedProvider; for path in &paths { - sparse.update_leaf(path.clone(), old_value_encoded.clone(), &provider).unwrap(); + sparse.update_leaf(path.clone(), old_value_encoded.clone()).unwrap(); } let sparse_root = sparse.root(); let sparse_updates = sparse.updates_ref(); @@ -1940,9 +1914,9 @@ mod tests { Default::default(), paths.clone(), ); - let provider = DefaultBlindedProvider; + for path in &paths { - sparse.update_leaf(path.clone(), new_value_encoded.clone(), &provider).unwrap(); + sparse.update_leaf(path.clone(), new_value_encoded.clone()).unwrap(); } let sparse_root = sparse.root(); let sparse_updates = sparse.take_updates(); @@ -1959,26 +1933,23 @@ mod tests { let mut sparse = RevealedSparseTrie::default(); let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec(); - let provider = DefaultBlindedProvider; sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider) - .unwrap(); - sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()) .unwrap(); + sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap(); // Extension (Key = 5) // └── Branch (Mask = 1011) @@ -2034,7 +2005,7 @@ mod tests { ]) ); - sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), &provider).unwrap(); + sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3])).unwrap(); // Extension (Key = 5) // └── Branch (Mask = 1001) @@ -2085,7 +2056,7 @@ mod tests { ]) ); - sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), &provider).unwrap(); + sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1])).unwrap(); // Extension (Key = 5) // └── Branch (Mask = 1001) @@ -2121,7 +2092,7 @@ mod tests { ]) ); - sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), &provider).unwrap(); + sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2])).unwrap(); // Extension (Key = 5) // └── Branch (Mask = 1001) @@ -2154,7 +2125,7 @@ mod tests { ]) ); - sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), &provider).unwrap(); + sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0])).unwrap(); // Extension (Key = 5) // └── Branch (Mask = 1001) @@ -2176,7 +2147,7 @@ mod tests { ]) ); - sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), &provider).unwrap(); + sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3])).unwrap(); // Leaf (Key = 53302) pretty_assertions::assert_eq!( @@ -2187,7 +2158,7 @@ mod tests { ),]) ); - sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), &provider).unwrap(); + sparse.remove_leaf(&Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2])).unwrap(); // Empty pretty_assertions::assert_eq!( @@ -2235,7 +2206,7 @@ mod tests { // Removing a blinded leaf should result in an error assert_matches!( - sparse.remove_leaf(&Nibbles::from_nibbles([0x0]), &DefaultBlindedProvider).map_err(|e| e.into_kind()), + sparse.remove_leaf(&Nibbles::from_nibbles([0x0])).map_err(|e| e.into_kind()), Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1) ); } @@ -2279,10 +2250,7 @@ mod tests { // Removing a non-existent leaf should be a noop let sparse_old = sparse.clone(); - assert_matches!( - sparse.remove_leaf(&Nibbles::from_nibbles([0x2]), &DefaultBlindedProvider), - Ok(()) - ); + assert_matches!(sparse.remove_leaf(&Nibbles::from_nibbles([0x2])), Ok(())); assert_eq!(sparse, sparse_old); } @@ -2306,7 +2274,7 @@ mod tests { let account = account.into_trie_account(EMPTY_ROOT_HASH); let mut account_rlp = Vec::new(); account.encode(&mut account_rlp); - sparse.update_leaf(key, account_rlp, &DefaultBlindedProvider).unwrap(); + sparse.update_leaf(key, account_rlp).unwrap(); } // We need to clone the sparse trie, so that all updated branch nodes are // preserved, and not only those that were changed after the last call to @@ -2346,7 +2314,7 @@ mod tests { // that the sparse trie root still matches the hash builder root for key in &keys_to_delete { state.remove(key).unwrap(); - sparse.remove_leaf(key, &DefaultBlindedProvider).unwrap(); + sparse.remove_leaf(key).unwrap(); } // We need to clone the sparse trie, so that all updated branch nodes are @@ -2492,7 +2460,7 @@ mod tests { ); // Insert the leaf for the second key - sparse.update_leaf(key2(), value_encoded(), &DefaultBlindedProvider).unwrap(); + sparse.update_leaf(key2(), value_encoded()).unwrap(); // Check that the branch node was updated and another nibble was set assert_eq!( @@ -2601,7 +2569,7 @@ mod tests { ); // Remove the leaf for the first key - sparse.remove_leaf(&key1(), &DefaultBlindedProvider).unwrap(); + sparse.remove_leaf(&key1()).unwrap(); // Check that the branch node was turned into an extension node assert_eq!( @@ -2681,7 +2649,7 @@ mod tests { ); // Insert the leaf with a different prefix - sparse.update_leaf(key3(), value_encoded(), &DefaultBlindedProvider).unwrap(); + sparse.update_leaf(key3(), value_encoded()).unwrap(); // Check that the extension node was turned into a branch node assert_matches!( @@ -2721,7 +2689,6 @@ mod tests { let mut sparse = RevealedSparseTrie::default(); let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec(); - let provider = DefaultBlindedProvider; // Extension (Key = 5) – Level 0 // └── Branch (Mask = 1011) – Level 1 @@ -2736,23 +2703,21 @@ mod tests { // ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4 // └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4 sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider) - .unwrap(); - sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()) .unwrap(); + sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap(); assert_eq!( sparse.get_changed_nodes_at_depth(&mut PrefixSet::default(), 0), @@ -2833,9 +2798,8 @@ mod tests { [Nibbles::default()], ); let mut sparse = RevealedSparseTrie::default(); - let provider = DefaultBlindedProvider; - sparse.update_leaf(key1(), value_encoded(), &provider).unwrap(); - sparse.update_leaf(key2(), value_encoded(), &provider).unwrap(); + sparse.update_leaf(key1(), value_encoded()).unwrap(); + sparse.update_leaf(key2(), value_encoded()).unwrap(); let sparse_root = sparse.root(); let sparse_updates = sparse.take_updates(); @@ -2848,7 +2812,6 @@ mod tests { let mut sparse = RevealedSparseTrie::default().with_updates(true); let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec(); - let provider = DefaultBlindedProvider; // Extension (Key = 5) – Level 0 // └── Branch (Mask = 1011) – Level 1 @@ -2863,23 +2826,21 @@ mod tests { // ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4 // └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4 sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider) - .unwrap(); - sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()) .unwrap(); + sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap(); sparse.wipe(); @@ -2891,7 +2852,6 @@ mod tests { let mut sparse = RevealedSparseTrie::default(); let value = alloy_rlp::encode_fixed_size(&U256::ZERO).to_vec(); - let provider = DefaultBlindedProvider; // Extension (Key = 5) – Level 0 // └── Branch (Mask = 1011) – Level 1 @@ -2906,23 +2866,21 @@ mod tests { // ├── 0 -> Leaf (Key = 3302, Path = 53302) – Level 4 // └── 2 -> Leaf (Key = 3320, Path = 53320) – Level 4 sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x1]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x0, 0x2, 0x3, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x2, 0x0, 0x1, 0x3]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone(), &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x1, 0x0, 0x2]), value.clone()) .unwrap(); sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone(), &provider) - .unwrap(); - sparse - .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value, &provider) + .update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x0, 0x2]), value.clone()) .unwrap(); + sparse.update_leaf(Nibbles::from_nibbles([0x5, 0x3, 0x3, 0x2, 0x0]), value).unwrap(); let normal_printed = format!("{sparse}"); let expected = "\ diff --git a/crates/trie/trie/src/witness.rs b/crates/trie/trie/src/witness.rs index e745d3c502..57b91f8264 100644 --- a/crates/trie/trie/src/witness.rs +++ b/crates/trie/trie/src/witness.rs @@ -117,7 +117,7 @@ where ), tx, ); - let mut sparse_trie = SparseStateTrie::default(); + let mut sparse_trie = SparseStateTrie::new(blinded_provider_factory); sparse_trie.reveal_multiproof(multiproof)?; // Attempt to update state trie to gather additional information for the witness. @@ -132,7 +132,6 @@ where SparseTrieErrorKind::Blind, ), )?; - let provider = blinded_provider_factory.storage_node_provider(hashed_address); for hashed_slot in hashed_slots.into_iter().sorted_unstable() { let storage_nibbles = Nibbles::unpack(hashed_slot); let maybe_leaf_value = storage @@ -141,11 +140,11 @@ where .map(|v| alloy_rlp::encode_fixed_size(v).to_vec()); if let Some(value) = maybe_leaf_value { - storage_trie.update_leaf(storage_nibbles, value, &provider).map_err(|err| { + storage_trie.update_leaf(storage_nibbles, value).map_err(|err| { SparseStateTrieErrorKind::SparseStorageTrie(hashed_address, err.into_kind()) })?; } else { - storage_trie.remove_leaf(&storage_nibbles, &provider).map_err(|err| { + storage_trie.remove_leaf(&storage_nibbles).map_err(|err| { SparseStateTrieErrorKind::SparseStorageTrie(hashed_address, err.into_kind()) })?; } @@ -159,7 +158,7 @@ where .get(&hashed_address) .ok_or(TrieWitnessError::MissingAccount(hashed_address))? .unwrap_or_default(); - sparse_trie.update_account(hashed_address, account, &blinded_provider_factory)?; + sparse_trie.update_account(hashed_address, account)?; while let Ok(node) = rx.try_recv() { self.witness.insert(keccak256(&node), node);