diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index 79eb8b11fc..4125f80a80 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -839,7 +839,7 @@ mod tests { AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; - use reth_trie::{prefix_set::TriePrefixSetsMut, AccountProof, HashedStorage}; + use reth_trie::{AccountProof, HashedStorage, TrieInput}; fn create_mock_state( test_block_builder: &mut TestBlockBuilder, @@ -913,12 +913,7 @@ mod tests { Ok(B256::random()) } - fn state_root_from_nodes( - &self, - _nodes: TrieUpdates, - _post_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { + fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult { Ok(B256::random()) } @@ -931,9 +926,7 @@ mod tests { fn state_root_from_nodes_with_updates( &self, - _nodes: TrieUpdates, - _post_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, + _input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { Ok((B256::random(), TrieUpdates::default())) } diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index 1782627b91..fb88e4ab31 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -7,10 +7,7 @@ use reth_storage_api::{ AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateProviderBox, StateRootProvider, StorageRootProvider, }; -use reth_trie::{ - prefix_set::TriePrefixSetsMut, updates::TrieUpdates, AccountProof, HashedPostState, - HashedStorage, -}; +use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput}; use std::{collections::HashMap, sync::OnceLock}; /// A state provider that stores references to in-memory blocks along with their state as well as @@ -45,13 +42,12 @@ impl MemoryOverlayStateProvider { /// Return lazy-loaded trie state aggregated from in-memory blocks. fn trie_state(&self) -> &MemoryOverlayTrieState { self.trie_state.get_or_init(|| { - let mut hashed_state = HashedPostState::default(); - let mut trie_nodes = TrieUpdates::default(); + let mut trie_state = MemoryOverlayTrieState::default(); for block in self.in_memory.iter().rev() { - hashed_state.extend_ref(block.hashed_state.as_ref()); - trie_nodes.extend_ref(block.trie.as_ref()); + trie_state.state.extend_ref(block.hashed_state.as_ref()); + trie_state.nodes.extend_ref(block.trie.as_ref()); } - MemoryOverlayTrieState { trie_nodes, hashed_state } + trie_state }) } } @@ -102,54 +98,38 @@ impl AccountReader for MemoryOverlayStateProvider { } impl StateRootProvider for MemoryOverlayStateProvider { - fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { - let prefix_sets = hashed_state.construct_prefix_sets(); - self.state_root_from_nodes(TrieUpdates::default(), hashed_state, prefix_sets) + fn state_root(&self, state: HashedPostState) -> ProviderResult { + self.state_root_from_nodes(TrieInput::from_state(state)) } - fn state_root_from_nodes( - &self, - nodes: TrieUpdates, - state: HashedPostState, - prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { - let MemoryOverlayTrieState { mut trie_nodes, mut hashed_state } = self.trie_state().clone(); - trie_nodes.extend(nodes); - hashed_state.extend(state); - self.historical.state_root_from_nodes(trie_nodes, hashed_state, prefix_sets) + fn state_root_from_nodes(&self, mut input: TrieInput) -> ProviderResult { + let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone(); + input.prepend_cached(nodes, state); + self.historical.state_root_from_nodes(input) } fn state_root_with_updates( &self, - hashed_state: HashedPostState, + state: HashedPostState, ) -> ProviderResult<(B256, TrieUpdates)> { - let prefix_sets = hashed_state.construct_prefix_sets(); - self.state_root_from_nodes_with_updates(TrieUpdates::default(), hashed_state, prefix_sets) + self.state_root_from_nodes_with_updates(TrieInput::from_state(state)) } fn state_root_from_nodes_with_updates( &self, - nodes: TrieUpdates, - state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + mut input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { - let MemoryOverlayTrieState { mut trie_nodes, mut hashed_state } = self.trie_state().clone(); - trie_nodes.extend(nodes); - hashed_state.extend(state); - self.historical.state_root_from_nodes_with_updates(trie_nodes, hashed_state, prefix_sets) + let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone(); + input.prepend_cached(nodes, state); + self.historical.state_root_from_nodes_with_updates(input) } } impl StorageRootProvider for MemoryOverlayStateProvider { // TODO: Currently this does not reuse available in-memory trie nodes. fn storage_root(&self, address: Address, storage: HashedStorage) -> ProviderResult { - let mut hashed_storage = self - .trie_state() - .hashed_state - .storages - .get(&keccak256(address)) - .cloned() - .unwrap_or_default(); + let mut hashed_storage = + self.trie_state().state.storages.get(&keccak256(address)).cloned().unwrap_or_default(); hashed_storage.extend(&storage); self.historical.storage_root(address, hashed_storage) } @@ -163,7 +143,7 @@ impl StateProofProvider for MemoryOverlayStateProvider { address: Address, slots: &[B256], ) -> ProviderResult { - let mut hashed_state = self.trie_state().hashed_state.clone(); + let mut hashed_state = self.trie_state().state.clone(); hashed_state.extend(state); self.historical.proof(hashed_state, address, slots) } @@ -174,7 +154,7 @@ impl StateProofProvider for MemoryOverlayStateProvider { overlay: HashedPostState, target: HashedPostState, ) -> ProviderResult> { - let mut hashed_state = self.trie_state().hashed_state.clone(); + let mut hashed_state = self.trie_state().state.clone(); hashed_state.extend(overlay); self.historical.witness(hashed_state, target) } @@ -207,10 +187,10 @@ impl StateProvider for MemoryOverlayStateProvider { } /// The collection of data necessary for trie-related operations for [`MemoryOverlayStateProvider`]. -#[derive(Clone, Debug)] +#[derive(Clone, Default, Debug)] pub(crate) struct MemoryOverlayTrieState { /// The collection of aggregated in-memory trie updates. - pub(crate) trie_nodes: TrieUpdates, + pub(crate) nodes: TrieUpdates, /// The collection of hashed state from in-memory blocks. - pub(crate) hashed_state: HashedPostState, + pub(crate) state: HashedPostState, } diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index f54f10a381..1a1c1d8c41 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -8,10 +8,7 @@ use reth_storage_api::{ StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; -use reth_trie::{ - prefix_set::TriePrefixSetsMut, updates::TrieUpdates, AccountProof, HashedPostState, - HashedStorage, -}; +use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput}; /// Mock state for testing #[derive(Debug, Default, Clone, Eq, PartialEq)] @@ -74,12 +71,7 @@ impl StateRootProvider for StateProviderTest { unimplemented!("state root computation is not supported") } - fn state_root_from_nodes( - &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { + fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult { unimplemented!("state root computation is not supported") } @@ -92,9 +84,7 @@ impl StateRootProvider for StateProviderTest { fn state_root_from_nodes_with_updates( &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, + _input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { unimplemented!("state root computation is not supported") } diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index 60b895c47b..21dec6bdf2 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -27,11 +27,9 @@ impl<'a> reth_storage_api::StateRootProvider for StateProviderTraitObjWrapper<'a fn state_root_from_nodes( &self, - nodes: reth_trie::updates::TrieUpdates, - hashed_state: reth_trie::HashedPostState, - prefix_sets: reth_trie::prefix_set::TriePrefixSetsMut, + input: reth_trie::TrieInput, ) -> reth_errors::ProviderResult { - self.0.state_root_from_nodes(nodes, hashed_state, prefix_sets) + self.0.state_root_from_nodes(input) } fn state_root_with_updates( @@ -43,11 +41,9 @@ impl<'a> reth_storage_api::StateRootProvider for StateProviderTraitObjWrapper<'a fn state_root_from_nodes_with_updates( &self, - nodes: reth_trie::updates::TrieUpdates, - hashed_state: reth_trie::HashedPostState, - prefix_sets: reth_trie::prefix_set::TriePrefixSetsMut, + input: reth_trie::TrieInput, ) -> reth_errors::ProviderResult<(B256, reth_trie::updates::TrieUpdates)> { - self.0.state_root_from_nodes_with_updates(nodes, hashed_state, prefix_sets) + self.0.state_root_from_nodes_with_updates(input) } } diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index 50c88a51fc..465d934f6c 100644 --- a/crates/storage/provider/src/providers/bundle_state_provider.rs +++ b/crates/storage/provider/src/providers/bundle_state_provider.rs @@ -4,10 +4,7 @@ use crate::{ use reth_primitives::{Account, Address, BlockNumber, Bytecode, Bytes, B256}; use reth_storage_api::{StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::ProviderResult; -use reth_trie::{ - prefix_set::TriePrefixSetsMut, updates::TrieUpdates, AccountProof, HashedPostState, - HashedStorage, -}; +use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput}; use std::collections::HashMap; /// A state provider that resolves to data from either a wrapped [`crate::ExecutionOutcome`] @@ -75,12 +72,7 @@ impl StateRootProvider self.state_provider.state_root(state) } - fn state_root_from_nodes( - &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { + fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult { unimplemented!() } @@ -96,16 +88,11 @@ impl StateRootProvider fn state_root_from_nodes_with_updates( &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + mut input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - let mut state = HashedPostState::from_bundle_state(&bundle_state.state); - let mut state_prefix_sets = state.construct_prefix_sets(); - state.extend(hashed_state); - state_prefix_sets.extend(prefix_sets); - self.state_provider.state_root_from_nodes_with_updates(nodes, state, state_prefix_sets) + input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); + self.state_provider.state_root_from_nodes_with_updates(input) } } diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 19f758bc62..b1caf66fab 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -16,8 +16,8 @@ use reth_primitives::{ use reth_storage_api::{StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ - prefix_set::TriePrefixSetsMut, proof::Proof, updates::TrieUpdates, witness::TrieWitness, - AccountProof, HashedPostState, HashedStorage, StateRoot, StorageRoot, + proof::Proof, updates::TrieUpdates, witness::TrieWitness, AccountProof, HashedPostState, + HashedStorage, StateRoot, StorageRoot, TrieInput, }; use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, @@ -292,17 +292,9 @@ impl<'b, TX: DbTx> StateRootProvider for HistoricalStateProviderRef<'b, TX> { .map_err(|err| ProviderError::Database(err.into())) } - fn state_root_from_nodes( - &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { - let mut revert_state = self.revert_state()?; - let mut revert_prefix_sets = revert_state.construct_prefix_sets(); - revert_state.extend(hashed_state); - revert_prefix_sets.extend(prefix_sets); - StateRoot::overlay_root_from_nodes(self.tx, nodes, revert_state, revert_prefix_sets) + fn state_root_from_nodes(&self, mut input: TrieInput) -> ProviderResult { + input.prepend(self.revert_state()?); + StateRoot::overlay_root_from_nodes(self.tx, input) .map_err(|err| ProviderError::Database(err.into())) } @@ -318,21 +310,11 @@ impl<'b, TX: DbTx> StateRootProvider for HistoricalStateProviderRef<'b, TX> { fn state_root_from_nodes_with_updates( &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + mut input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { - let mut revert_state = self.revert_state()?; - let mut revert_prefix_sets = revert_state.construct_prefix_sets(); - revert_state.extend(hashed_state); - revert_prefix_sets.extend(prefix_sets); - StateRoot::overlay_root_from_nodes_with_updates( - self.tx, - nodes, - revert_state, - revert_prefix_sets, - ) - .map_err(|err| ProviderError::Database(err.into())) + input.prepend(self.revert_state()?); + StateRoot::overlay_root_from_nodes_with_updates(self.tx, input) + .map_err(|err| ProviderError::Database(err.into())) } } diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index 72fd5baac0..4ef98c5f8b 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use crate::{ providers::{state::macros::delegate_provider_impls, StaticFileProvider}, AccountReader, BlockHashReader, StateProvider, StateRootProvider, @@ -16,10 +14,11 @@ use reth_primitives::{ use reth_storage_api::{StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ - prefix_set::TriePrefixSetsMut, proof::Proof, updates::TrieUpdates, witness::TrieWitness, - AccountProof, HashedPostState, HashedStorage, StateRoot, StorageRoot, + proof::Proof, updates::TrieUpdates, witness::TrieWitness, AccountProof, HashedPostState, + HashedStorage, StateRoot, StorageRoot, TrieInput, }; use reth_trie_db::{DatabaseProof, DatabaseStateRoot, DatabaseStorageRoot, DatabaseTrieWitness}; +use std::collections::HashMap; /// State provider over latest state that takes tx reference. #[derive(Debug)] @@ -86,13 +85,8 @@ impl<'b, TX: DbTx> StateRootProvider for LatestStateProviderRef<'b, TX> { .map_err(|err| ProviderError::Database(err.into())) } - fn state_root_from_nodes( - &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { - StateRoot::overlay_root_from_nodes(self.tx, nodes, hashed_state, prefix_sets) + fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult { + StateRoot::overlay_root_from_nodes(self.tx, input) .map_err(|err| ProviderError::Database(err.into())) } @@ -106,11 +100,9 @@ impl<'b, TX: DbTx> StateRootProvider for LatestStateProviderRef<'b, TX> { fn state_root_from_nodes_with_updates( &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { - StateRoot::overlay_root_from_nodes_with_updates(self.tx, nodes, hashed_state, prefix_sets) + StateRoot::overlay_root_from_nodes_with_updates(self.tx, input) .map_err(|err| ProviderError::Database(err.into())) } } diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index e3499c96ff..435d06a2a6 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -43,9 +43,9 @@ macro_rules! delegate_provider_impls { } StateRootProvider $(where [$($generics)*])? { fn state_root(&self, state: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult; - fn state_root_from_nodes(&self, nodes: reth_trie::updates::TrieUpdates, state: reth_trie::HashedPostState, prefix_sets: reth_trie::prefix_set::TriePrefixSetsMut) -> reth_storage_errors::provider::ProviderResult; + fn state_root_from_nodes(&self, input: reth_trie::TrieInput) -> reth_storage_errors::provider::ProviderResult; fn state_root_with_updates(&self, state: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult<(reth_primitives::B256, reth_trie::updates::TrieUpdates)>; - fn state_root_from_nodes_with_updates(&self, nodes: reth_trie::updates::TrieUpdates, state: reth_trie::HashedPostState, prefix_sets: reth_trie::prefix_set::TriePrefixSetsMut) -> reth_storage_errors::provider::ProviderResult<(reth_primitives::B256, reth_trie::updates::TrieUpdates)>; + fn state_root_from_nodes_with_updates(&self, input: reth_trie::TrieInput) -> reth_storage_errors::provider::ProviderResult<(reth_primitives::B256, reth_trie::updates::TrieUpdates)>; } StorageRootProvider $(where [$($generics)*])? { fn storage_root(&self, address: reth_primitives::Address, storage: reth_trie::HashedStorage) -> reth_storage_errors::provider::ProviderResult; diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index c539c0d2c7..b081dfed23 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -24,10 +24,7 @@ use reth_storage_api::{ DatabaseProviderFactory, StageCheckpointReader, StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; -use reth_trie::{ - prefix_set::TriePrefixSetsMut, updates::TrieUpdates, AccountProof, HashedPostState, - HashedStorage, -}; +use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput}; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ collections::{BTreeMap, HashMap}, @@ -586,12 +583,7 @@ impl StateRootProvider for MockEthProvider { Ok(self.state_roots.lock().pop().unwrap_or_default()) } - fn state_root_from_nodes( - &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { + fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult { Ok(self.state_roots.lock().pop().unwrap_or_default()) } @@ -605,9 +597,7 @@ impl StateRootProvider for MockEthProvider { fn state_root_from_nodes_with_updates( &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, + _input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { let state_root = self.state_roots.lock().pop().unwrap_or_default(); Ok((state_root, Default::default())) diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 338dc6fca1..b78e153ddc 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -22,10 +22,7 @@ use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::ProviderResult; -use reth_trie::{ - prefix_set::TriePrefixSetsMut, updates::TrieUpdates, AccountProof, HashedPostState, - HashedStorage, -}; +use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput}; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use tokio::sync::{broadcast, watch}; @@ -326,12 +323,7 @@ impl StateRootProvider for NoopProvider { Ok(B256::default()) } - fn state_root_from_nodes( - &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult { + fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult { Ok(B256::default()) } @@ -344,9 +336,7 @@ impl StateRootProvider for NoopProvider { fn state_root_from_nodes_with_updates( &self, - _nodes: TrieUpdates, - _hashed_state: HashedPostState, - _prefix_sets: TriePrefixSetsMut, + _input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { Ok((B256::default(), TrieUpdates::default())) } diff --git a/crates/storage/storage-api/src/trie.rs b/crates/storage/storage-api/src/trie.rs index d4a8c6aab5..eaac67cfe2 100644 --- a/crates/storage/storage-api/src/trie.rs +++ b/crates/storage/storage-api/src/trie.rs @@ -1,9 +1,6 @@ use alloy_primitives::{Address, Bytes, B256}; use reth_storage_errors::provider::ProviderResult; -use reth_trie::{ - prefix_set::TriePrefixSetsMut, updates::TrieUpdates, AccountProof, HashedPostState, - HashedStorage, -}; +use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput}; use std::collections::HashMap; /// A type that can compute the state root of a given post state. @@ -21,12 +18,7 @@ pub trait StateRootProvider: Send + Sync { /// Returns the state root of the `HashedPostState` on top of the current state but re-uses the /// intermediate nodes to speed up the computation. It's up to the caller to construct the /// prefix sets and inform the provider of the trie paths that have changes. - fn state_root_from_nodes( - &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, - ) -> ProviderResult; + fn state_root_from_nodes(&self, input: TrieInput) -> ProviderResult; /// Returns the state root of the `HashedPostState` on top of the current state with trie /// updates to be committed to the database. @@ -39,9 +31,7 @@ pub trait StateRootProvider: Send + Sync { /// See [`StateRootProvider::state_root_from_nodes`] for more info. fn state_root_from_nodes_with_updates( &self, - nodes: TrieUpdates, - hashed_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)>; } diff --git a/crates/trie/db/src/state.rs b/crates/trie/db/src/state.rs index a138ee5791..c883f3ad89 100644 --- a/crates/trie/db/src/state.rs +++ b/crates/trie/db/src/state.rs @@ -9,9 +9,8 @@ use reth_execution_errors::StateRootError; use reth_primitives::{keccak256, Account, Address, BlockNumber, B256, U256}; use reth_storage_errors::db::DatabaseError; use reth_trie::{ - hashed_cursor::HashedPostStateCursorFactory, prefix_set::TriePrefixSetsMut, - trie_cursor::InMemoryTrieCursorFactory, updates::TrieUpdates, HashedPostState, HashedStorage, - StateRoot, StateRootProgress, + hashed_cursor::HashedPostStateCursorFactory, trie_cursor::InMemoryTrieCursorFactory, + updates::TrieUpdates, HashedPostState, HashedStorage, StateRoot, StateRootProgress, TrieInput, }; use std::{ collections::{hash_map, HashMap}, @@ -111,20 +110,13 @@ pub trait DatabaseStateRoot<'a, TX>: Sized { ) -> Result<(B256, TrieUpdates), StateRootError>; /// Calculates the state root for provided [`HashedPostState`] using cached intermediate nodes. - fn overlay_root_from_nodes( - tx: &'a TX, - intermediate_nodes: TrieUpdates, - post_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, - ) -> Result; + fn overlay_root_from_nodes(tx: &'a TX, input: TrieInput) -> Result; /// Calculates the state root and trie updates for provided [`HashedPostState`] using /// cached intermediate nodes. fn overlay_root_from_nodes_with_updates( tx: &'a TX, - intermediate_nodes: TrieUpdates, - post_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + input: TrieInput, ) -> Result<(B256, TrieUpdates), StateRootError>; } @@ -199,35 +191,28 @@ impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX> .root_with_updates() } - fn overlay_root_from_nodes( - tx: &'a TX, - intermediate_nodes: TrieUpdates, - post_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, - ) -> Result { - let state_sorted = post_state.into_sorted(); - let nodes_sorted = intermediate_nodes.into_sorted(); + fn overlay_root_from_nodes(tx: &'a TX, input: TrieInput) -> Result { + let state_sorted = input.state.into_sorted(); + let nodes_sorted = input.nodes.into_sorted(); StateRoot::new( InMemoryTrieCursorFactory::new(DatabaseTrieCursorFactory::new(tx), &nodes_sorted), HashedPostStateCursorFactory::new(DatabaseHashedCursorFactory::new(tx), &state_sorted), ) - .with_prefix_sets(prefix_sets.freeze()) + .with_prefix_sets(input.prefix_sets.freeze()) .root() } fn overlay_root_from_nodes_with_updates( tx: &'a TX, - intermediate_nodes: TrieUpdates, - post_state: HashedPostState, - prefix_sets: TriePrefixSetsMut, + input: TrieInput, ) -> Result<(B256, TrieUpdates), StateRootError> { - let state_sorted = post_state.into_sorted(); - let nodes_sorted = intermediate_nodes.into_sorted(); + let state_sorted = input.state.into_sorted(); + let nodes_sorted = input.nodes.into_sorted(); StateRoot::new( InMemoryTrieCursorFactory::new(DatabaseTrieCursorFactory::new(tx), &nodes_sorted), HashedPostStateCursorFactory::new(DatabaseHashedCursorFactory::new(tx), &state_sorted), ) - .with_prefix_sets(prefix_sets.freeze()) + .with_prefix_sets(input.prefix_sets.freeze()) .root_with_updates() } } diff --git a/crates/trie/trie/src/input.rs b/crates/trie/trie/src/input.rs new file mode 100644 index 0000000000..f8ca95361e --- /dev/null +++ b/crates/trie/trie/src/input.rs @@ -0,0 +1,49 @@ +use crate::{prefix_set::TriePrefixSetsMut, updates::TrieUpdates, HashedPostState}; + +/// Inputs for trie-related computations. +#[derive(Debug)] +pub struct TrieInput { + /// The collection of cached in-memory intermediate trie nodes that + /// can be reused for computation. + pub nodes: TrieUpdates, + /// The in-memory overlay hashed state. + pub state: HashedPostState, + /// The collection of prefix sets for the computation. Since the prefix sets _always_ + /// invalidate the in-memory nodes, not all keys from `self.state` might be present here, + /// if we have cached nodes for them. + pub prefix_sets: TriePrefixSetsMut, +} + +impl TrieInput { + /// Create new trie input. + pub const fn new( + nodes: TrieUpdates, + state: HashedPostState, + prefix_sets: TriePrefixSetsMut, + ) -> Self { + Self { nodes, state, prefix_sets } + } + + /// Create new trie input from in-memory state. The prefix sets will be constructed and + /// set automatically. + pub fn from_state(state: HashedPostState) -> Self { + let prefix_sets = state.construct_prefix_sets(); + Self { nodes: TrieUpdates::default(), state, prefix_sets } + } + + /// Prepend state to the input and extend the prefix sets + pub fn prepend(&mut self, mut state: HashedPostState) { + self.prefix_sets.extend(state.construct_prefix_sets()); + std::mem::swap(&mut self.state, &mut state); + self.state.extend(state); + } + + /// Prepend intermediate nodes and state to the input. Prefix sets for incoming state will be + /// ignored. + pub fn prepend_cached(&mut self, mut nodes: TrieUpdates, mut state: HashedPostState) { + std::mem::swap(&mut self.nodes, &mut nodes); + self.nodes.extend(nodes); + std::mem::swap(&mut self.state, &mut state); + self.state.extend(state); + } +} diff --git a/crates/trie/trie/src/lib.rs b/crates/trie/trie/src/lib.rs index 600b630013..317ec36554 100644 --- a/crates/trie/trie/src/lib.rs +++ b/crates/trie/trie/src/lib.rs @@ -36,6 +36,10 @@ pub mod node_iter; mod state; pub use state::*; +/// Input for trie computation. +mod input; +pub use input::TrieInput; + /// Merkle proof generation. pub mod proof;