From 6f2b11956226d2854339cc77b15decc34f02da40 Mon Sep 17 00:00:00 2001 From: frisitano Date: Fri, 18 Oct 2024 20:14:54 +0800 Subject: [PATCH] feat: introduce HashedStorageProvider --- crates/chain-state/src/in_memory.rs | 13 +++++++++-- crates/chain-state/src/memory_overlay.rs | 13 +++++++++-- crates/revm/src/test_utils.rs | 13 +++++++++-- crates/rpc/rpc-eth-types/src/cache/db.rs | 9 ++++++++ .../src/providers/bundle_state_provider.rs | 22 +++++++++++++------ .../src/providers/state/historical.rs | 15 ++++++++++++- .../provider/src/providers/state/latest.rs | 13 ++++++++++- .../provider/src/providers/state/macros.rs | 3 +++ .../storage/provider/src/test_utils/mock.rs | 13 +++++++++-- .../storage/provider/src/test_utils/noop.rs | 13 ++++++++++- crates/storage/storage-api/src/state.rs | 3 +++ crates/storage/storage-api/src/storage.rs | 9 ++++++++ crates/trie/trie/src/state.rs | 21 +++++++++++++----- 13 files changed, 137 insertions(+), 23 deletions(-) diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index 195d2b5fbf67..1d01617c4108 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -870,8 +870,8 @@ mod tests { use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, Receipt, Requests}; use reth_storage_api::{ - AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, - StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, + StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_trie::{AccountProof, HashedStorage, MultiProof, StorageProof, TrieInput}; @@ -1028,6 +1028,15 @@ mod tests { } } + impl HashedStorageProvider for MockStateProvider { + fn hashed_storage_from_bundle_account( + &self, + _account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + HashedStorage::default() + } + } + #[test] fn test_in_memory_state_impl_state_by_hash() { let mut state_by_hash = HashMap::default(); diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index b19ae8508be9..7c91148c93e4 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -7,8 +7,8 @@ use alloy_primitives::{ use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, - StateProviderBox, StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, + StateProofProvider, StateProvider, StateProviderBox, StateRootProvider, StorageRootProvider, }; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -204,6 +204,15 @@ impl HashedPostStateProvider for MemoryOverlayStateProvider { } } +impl HashedStorageProvider for MemoryOverlayStateProvider { + fn hashed_storage_from_bundle_account( + &self, + account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + self.historical.hashed_storage_from_bundle_account(account) + } +} + impl StateProvider for MemoryOverlayStateProvider { fn storage( &self, diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index f15398a81cfa..bb51859ee63f 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -6,8 +6,8 @@ use alloy_primitives::{ }; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, - StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, + StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ @@ -155,6 +155,15 @@ impl HashedPostStateProvider for StateProviderTest { } } +impl HashedStorageProvider for StateProviderTest { + fn hashed_storage_from_bundle_account( + &self, + account: &revm::db::BundleAccount, + ) -> HashedStorage { + HashedStorage::from_bundle_account::(account) + } +} + impl StateProvider for StateProviderTest { fn storage( &self, diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index fafa9fe7d721..6cc678cbf5af 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -146,6 +146,15 @@ impl reth_storage_api::HashedPostStateProvider for StateProviderTraitObjWrapper< } } +impl reth_storage_api::HashedStorageProvider for StateProviderTraitObjWrapper<'_> { + fn hashed_storage_from_bundle_account( + &self, + account: &reth_execution_types::BundleAccount, + ) -> reth_trie::HashedStorage { + self.0.hashed_storage_from_bundle_account(account) + } +} + impl StateProvider for StateProviderTraitObjWrapper<'_> { fn account_balance( &self, diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index 8c45a0133093..70e2eaa9b2c2 100644 --- a/crates/storage/provider/src/providers/bundle_state_provider.rs +++ b/crates/storage/provider/src/providers/bundle_state_provider.rs @@ -6,7 +6,9 @@ use alloy_primitives::{ Address, BlockNumber, Bytes, B256, }; use reth_primitives::{Account, Bytecode}; -use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -37,12 +39,7 @@ impl BundleStateProvider let bundle_state = self.block_execution_data_provider.execution_outcome().state(); bundle_state .account(&address) - .map(|account| { - HashedStorage::from_plain_storage( - account.status, - account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), - ) - }) + .map(|account| self.state_provider.hashed_storage_from_bundle_account(account)) .unwrap_or_default() } } @@ -193,6 +190,17 @@ impl HashedPostStateProvider } } +impl HashedStorageProvider + for BundleStateProvider +{ + fn hashed_storage_from_bundle_account( + &self, + account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + self.state_provider.hashed_storage_from_bundle_account(account) + } +} + impl StateProvider for BundleStateProvider { fn storage( &self, diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 6f5ee4403e5f..d7c0de0472ba 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -14,7 +14,9 @@ use reth_db_api::{ transaction::DbTx, }; use reth_primitives::{constants::EPOCH_SLOTS, Account, Bytecode, StaticFileSegment}; -use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ proof::{Proof, StorageProof}, @@ -428,6 +430,17 @@ impl HashedPostStateProvider } } +impl HashedStorageProvider + for HistoricalStateProviderRef<'_, TX, SC> +{ + fn hashed_storage_from_bundle_account( + &self, + account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + HashedStorage::from_bundle_account::(account) + } +} + impl StateProvider for HistoricalStateProviderRef<'_, TX, SC> { /// Get storage. fn storage( diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index f20f00954fab..a546ba3a9256 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -12,7 +12,9 @@ use reth_db_api::{ transaction::DbTx, }; use reth_primitives::{Account, Bytecode, StaticFileSegment}; -use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ proof::{Proof, StorageProof}, @@ -180,6 +182,15 @@ impl HashedPostStateProvider for LatestStateProvi } } +impl HashedStorageProvider for LatestStateProviderRef<'_, TX, SC> { + fn hashed_storage_from_bundle_account( + &self, + account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + HashedStorage::from_bundle_account::(account) + } +} + impl StateProvider for LatestStateProviderRef<'_, TX, SC> { /// Get storage. fn storage( diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index 424565340b11..5a8a371636d6 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -60,6 +60,9 @@ macro_rules! delegate_provider_impls { fn hashed_post_state_from_reverts(&self, block_number: alloy_primitives::BlockNumber) -> reth_storage_errors::provider::ProviderResult; fn hashed_post_state_from_bundle_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState; } + HashedStorageProvider $(where [$($generics)*])? { + fn hashed_storage_from_bundle_account(&self, account: &revm::db::BundleAccount) -> reth_trie::HashedStorage; + } ); } } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 479b075deced..fffb86bc188c 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -27,8 +27,8 @@ use reth_primitives::{ }; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader, StateProofProvider, - StorageRootProvider, + DatabaseProviderFactory, HashedPostStateProvider, HashedStorageProvider, StageCheckpointReader, + StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_trie::{ @@ -687,6 +687,15 @@ impl HashedPostStateProvider for MockEthProvider { } } +impl HashedStorageProvider for MockEthProvider { + fn hashed_storage_from_bundle_account( + &self, + account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + HashedStorage::from_bundle_account::(account) + } +} + impl StateProvider for MockEthProvider { fn storage( &self, diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index dd4091a2c07e..d21d238b8f1e 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -24,7 +24,9 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -410,6 +412,15 @@ impl HashedPostStateProvider for NoopProvider { } } +impl HashedStorageProvider for NoopProvider { + fn hashed_storage_from_bundle_account( + &self, + _account: &reth_execution_types::BundleAccount, + ) -> HashedStorage { + HashedStorage::default() + } +} + impl StateProvider for NoopProvider { fn storage( &self, diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index de8ed0eea220..94612694ae18 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -1,3 +1,5 @@ +use crate::HashedStorageProvider; + use super::{ AccountReader, BlockHashReader, BlockIdReader, StateProofProvider, StateRootProvider, StorageRootProvider, @@ -23,6 +25,7 @@ pub trait StateProvider: + StorageRootProvider + StateProofProvider + HashedPostStateProvider + + HashedStorageProvider + Send + Sync { diff --git a/crates/storage/storage-api/src/storage.rs b/crates/storage/storage-api/src/storage.rs index e1443347e4bb..b9c7afc814db 100644 --- a/crates/storage/storage-api/src/storage.rs +++ b/crates/storage/storage-api/src/storage.rs @@ -1,7 +1,9 @@ use alloy_primitives::{Address, BlockNumber, B256}; use reth_db_api::models::BlockNumberAddress; +use reth_execution_types::BundleAccount; use reth_primitives::StorageEntry; use reth_storage_errors::provider::ProviderResult; +use reth_trie::HashedStorage; use std::{ collections::{BTreeMap, BTreeSet}, ops::RangeInclusive, @@ -32,6 +34,13 @@ pub trait StorageReader: Send + Sync { ) -> ProviderResult>>; } +/// [`HashedStorage`] provider +#[auto_impl::auto_impl(&, Arc, Box)] +pub trait HashedStorageProvider: Send + Sync { + /// Returns the [`HashedStorage`] for the provided `BundleAccount`. + fn hashed_storage_from_bundle_account(&self, account: &BundleAccount) -> HashedStorage; +} + /// Storage ChangeSet reader #[auto_impl::auto_impl(&, Arc, Box)] pub trait StorageChangeSetReader: Send + Sync { diff --git a/crates/trie/trie/src/state.rs b/crates/trie/trie/src/state.rs index c53d2fd71aa8..8979b6d78a8a 100644 --- a/crates/trie/trie/src/state.rs +++ b/crates/trie/trie/src/state.rs @@ -2,7 +2,7 @@ use crate::{ prefix_set::{PrefixSetMut, TriePrefixSetsMut}, Nibbles, }; -use alloy_primitives::{keccak256, Address, B256, U256}; +use alloy_primitives::{Address, B256, U256}; use itertools::Itertools; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use reth_primitives::Account; @@ -34,7 +34,7 @@ impl HashedPostState { .map(|(address, account)| { let hashed_address = KH::hash_key(address); let hashed_account = account.info.clone().map(Into::into); - let hashed_storage = HashedStorage::from_plain_storage( + let hashed_storage = HashedStorage::from_plain_storage::( account.status, account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), ); @@ -61,7 +61,7 @@ impl HashedPostState { .map(|(address, account)| { let hashed_address = KH::hash_key(address); let hashed_account = account.account.as_ref().map(|a| a.info.clone().into()); - let hashed_storage = HashedStorage::from_plain_storage( + let hashed_storage = HashedStorage::from_plain_storage::( account.status, account.account.as_ref().map(|a| a.storage.iter()).into_iter().flatten(), ); @@ -220,13 +220,24 @@ impl HashedStorage { } /// Create new hashed storage from account status and plain storage. - pub fn from_plain_storage<'a>( + pub fn from_plain_storage<'a, KH: KeyHasher>( status: AccountStatus, storage: impl IntoIterator, ) -> Self { Self::from_iter( status.was_destroyed(), - storage.into_iter().map(|(key, value)| (keccak256(B256::from(*key)), *value)), + storage.into_iter().map(|(key, value)| (KH::hash_key(B256::from(*key)), *value)), + ) + } + + /// Create a new hashed storage from the provided [`BundleAccount`] + /// + /// This function will use the present value of the storage slots in the account to create the + /// hashed storage. + pub fn from_bundle_account(account: &BundleAccount) -> Self { + Self::from_plain_storage::( + account.status, + account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), ) }