From e81dce5f1994195998addfa78adcc4fe7180a2ec Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Wed, 15 May 2024 17:19:41 +0300 Subject: [PATCH] feat(storage): implement `BundleStateDataProvider` for `BundleStateWithReceipts` (#8282) --- crates/blockchain-tree/src/bundle.rs | 6 +++- crates/blockchain-tree/src/chain.rs | 4 +-- crates/blockchain-tree/src/noop.rs | 6 ++-- crates/blockchain-tree/src/shareable.rs | 4 +-- .../bundle_state_with_receipts.rs | 20 +++++++++-- crates/storage/provider/src/providers/mod.rs | 16 ++++----- .../storage/provider/src/test_utils/mock.rs | 8 ++--- .../storage/provider/src/test_utils/noop.rs | 2 +- crates/storage/provider/src/traits/mod.rs | 5 +-- crates/storage/provider/src/traits/state.rs | 34 ++++++++++++++----- 10 files changed, 71 insertions(+), 34 deletions(-) diff --git a/crates/blockchain-tree/src/bundle.rs b/crates/blockchain-tree/src/bundle.rs index d8c93439e5b17..ccfbc2adc31c1 100644 --- a/crates/blockchain-tree/src/bundle.rs +++ b/crates/blockchain-tree/src/bundle.rs @@ -1,7 +1,7 @@ //! [BundleStateDataProvider] implementations used by the tree. use reth_primitives::{BlockHash, BlockNumber, ForkBlock}; -use reth_provider::{BundleStateDataProvider, BundleStateWithReceipts}; +use reth_provider::{BundleStateDataProvider, BundleStateForkProvider, BundleStateWithReceipts}; use std::collections::BTreeMap; /// Structure that combines references of required data to be a [`BundleStateDataProvider`]. @@ -30,7 +30,9 @@ impl<'a> BundleStateDataProvider for BundleStateDataRef<'a> { self.canonical_block_hashes.get(&block_number).cloned() } +} +impl<'a> BundleStateForkProvider for BundleStateDataRef<'a> { fn canonical_fork(&self) -> ForkBlock { self.canonical_fork } @@ -57,7 +59,9 @@ impl BundleStateDataProvider for BundleStateData { fn block_hash(&self, block_number: BlockNumber) -> Option { self.parent_block_hashes.get(&block_number).cloned() } +} +impl BundleStateForkProvider for BundleStateData { fn canonical_fork(&self) -> ForkBlock { self.canonical_fork } diff --git a/crates/blockchain-tree/src/chain.rs b/crates/blockchain-tree/src/chain.rs index db4b4627abe7e..ce6487a060b93 100644 --- a/crates/blockchain-tree/src/chain.rs +++ b/crates/blockchain-tree/src/chain.rs @@ -21,7 +21,7 @@ use reth_primitives::{ }; use reth_provider::{ providers::{BundleStateProvider, ConsistentDbView}, - BundleStateDataProvider, BundleStateWithReceipts, Chain, ProviderError, StateRootProvider, + BundleStateWithReceipts, Chain, FullBundleStateDataProvider, ProviderError, StateRootProvider, }; use reth_revm::database::StateProviderDatabase; use reth_trie::updates::TrieUpdates; @@ -178,7 +178,7 @@ impl AppendableChain { block_validation_kind: BlockValidationKind, ) -> RethResult<(BundleStateWithReceipts, Option)> where - BSDP: BundleStateDataProvider, + BSDP: FullBundleStateDataProvider, DB: Database + Clone, E: BlockExecutorProvider, { diff --git a/crates/blockchain-tree/src/noop.rs b/crates/blockchain-tree/src/noop.rs index 776a153250bca..18423d3bb7e63 100644 --- a/crates/blockchain-tree/src/noop.rs +++ b/crates/blockchain-tree/src/noop.rs @@ -12,8 +12,8 @@ use reth_primitives::{ SealedHeader, }; use reth_provider::{ - BlockchainTreePendingStateProvider, BundleStateDataProvider, CanonStateNotificationSender, - CanonStateNotifications, CanonStateSubscriptions, + BlockchainTreePendingStateProvider, CanonStateNotificationSender, CanonStateNotifications, + CanonStateSubscriptions, FullBundleStateDataProvider, }; use std::collections::{BTreeMap, HashSet}; @@ -138,7 +138,7 @@ impl BlockchainTreePendingStateProvider for NoopBlockchainTree { fn find_pending_state_provider( &self, _block_hash: BlockHash, - ) -> Option> { + ) -> Option> { None } } diff --git a/crates/blockchain-tree/src/shareable.rs b/crates/blockchain-tree/src/shareable.rs index 77cc53c2d3096..66f76b0916f1b 100644 --- a/crates/blockchain-tree/src/shareable.rs +++ b/crates/blockchain-tree/src/shareable.rs @@ -17,7 +17,7 @@ use reth_primitives::{ SealedHeader, }; use reth_provider::{ - BlockchainTreePendingStateProvider, BundleStateDataProvider, CanonStateSubscriptions, + BlockchainTreePendingStateProvider, CanonStateSubscriptions, FullBundleStateDataProvider, ProviderError, }; use std::{ @@ -199,7 +199,7 @@ where fn find_pending_state_provider( &self, block_hash: BlockHash, - ) -> Option> { + ) -> Option> { trace!(target: "blockchain_tree", ?block_hash, "Finding pending state provider"); let provider = self.tree.read().post_state_data(block_hash)?; Some(Box::new(provider)) diff --git a/crates/storage/provider/src/bundle_state/bundle_state_with_receipts.rs b/crates/storage/provider/src/bundle_state/bundle_state_with_receipts.rs index 5f6d4af3f843b..947c6609b961d 100644 --- a/crates/storage/provider/src/bundle_state/bundle_state_with_receipts.rs +++ b/crates/storage/provider/src/bundle_state/bundle_state_with_receipts.rs @@ -1,4 +1,7 @@ -use crate::{providers::StaticFileProviderRWRefMut, StateChanges, StateReverts, StateWriter}; +use crate::{ + providers::StaticFileProviderRWRefMut, BundleStateDataProvider, StateChanges, StateReverts, + StateWriter, +}; use reth_db::{ cursor::{DbCursorRO, DbCursorRW}, tables, @@ -9,8 +12,8 @@ use reth_interfaces::provider::{ProviderError, ProviderResult}; use reth_primitives::{ logs_bloom, revm::compat::{into_reth_acc, into_revm_acc}, - Account, Address, BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts, StaticFileSegment, - StorageEntry, B256, U256, + Account, Address, BlockHash, BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts, + StaticFileSegment, StorageEntry, B256, U256, }; use reth_trie::HashedPostState; pub use revm::db::states::OriginalValuesKnown; @@ -365,6 +368,17 @@ impl StateWriter for BundleStateWithReceipts { } } +impl BundleStateDataProvider for BundleStateWithReceipts { + fn state(&self) -> &BundleStateWithReceipts { + self + } + + /// Always returns [None] because we don't have any information about the block header. + fn block_hash(&self, _block_number: BlockNumber) -> Option { + None + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 8a06f0c0d2044..f9969a9500dcc 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -1,11 +1,11 @@ use crate::{ AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, - BlockSource, BlockchainTreePendingStateProvider, BundleStateDataProvider, CanonChainTracker, - CanonStateNotifications, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, - DatabaseProviderFactory, EvmEnvProvider, HeaderProvider, ProviderError, PruneCheckpointReader, - ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProviderBox, - StateProviderFactory, StaticFileProviderFactory, TransactionVariant, TransactionsProvider, - TreeViewer, WithdrawalsProvider, + BlockSource, BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotifications, + CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, DatabaseProviderFactory, + EvmEnvProvider, FullBundleStateDataProvider, HeaderProvider, ProviderError, + PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, + StateProviderBox, StateProviderFactory, StaticFileProviderFactory, TransactionVariant, + TransactionsProvider, TreeViewer, WithdrawalsProvider, }; use reth_db::{ database::Database, @@ -638,7 +638,7 @@ where fn pending_with_provider( &self, - bundle_state_data: Box, + bundle_state_data: Box, ) -> ProviderResult { let canonical_fork = bundle_state_data.canonical_fork(); trace!(target: "providers::blockchain", ?canonical_fork, "Returning post state provider"); @@ -871,7 +871,7 @@ where fn find_pending_state_provider( &self, block_hash: BlockHash, - ) -> Option> { + ) -> Option> { self.tree.find_pending_state_provider(block_hash) } } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 96e137ac6fdf9..893bd052d0b31 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -1,9 +1,9 @@ use crate::{ traits::{BlockSource, ReceiptProvider}, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, - BundleStateDataProvider, ChainSpecProvider, ChangeSetReader, EvmEnvProvider, HeaderProvider, - ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, - TransactionVariant, TransactionsProvider, WithdrawalsProvider, + ChainSpecProvider, ChangeSetReader, EvmEnvProvider, FullBundleStateDataProvider, + HeaderProvider, ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory, + StateRootProvider, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use parking_lot::Mutex; use reth_db::models::{AccountBeforeTx, StoredBlockBodyIndices}; @@ -660,7 +660,7 @@ impl StateProviderFactory for MockEthProvider { fn pending_with_provider<'a>( &'a self, - _bundle_state_data: Box, + _bundle_state_data: Box, ) -> ProviderResult { Ok(Box::new(self.clone())) } diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 373dc4d7e5f09..02890eaf1935a 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -419,7 +419,7 @@ impl StateProviderFactory for NoopProvider { fn pending_with_provider<'a>( &'a self, - _bundle_state_data: Box, + _bundle_state_data: Box, ) -> ProviderResult { Ok(Box::new(*self)) } diff --git a/crates/storage/provider/src/traits/mod.rs b/crates/storage/provider/src/traits/mod.rs index c966cd9efa09d..10984240a5d84 100644 --- a/crates/storage/provider/src/traits/mod.rs +++ b/crates/storage/provider/src/traits/mod.rs @@ -35,8 +35,9 @@ pub use receipts::{ReceiptProvider, ReceiptProviderIdExt}; mod state; pub use state::{ - BlockchainTreePendingStateProvider, BundleStateDataProvider, StateProvider, StateProviderBox, - StateProviderFactory, StateWriter, + BlockchainTreePendingStateProvider, BundleStateDataProvider, BundleStateForkProvider, + FullBundleStateDataProvider, StateProvider, StateProviderBox, StateProviderFactory, + StateWriter, }; mod trie; diff --git a/crates/storage/provider/src/traits/state.rs b/crates/storage/provider/src/traits/state.rs index 4cb74dec61cbf..ac72d52f9f449 100644 --- a/crates/storage/provider/src/traits/state.rs +++ b/crates/storage/provider/src/traits/state.rs @@ -187,7 +187,7 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync { /// Used to inspect or execute transaction on the pending state. fn pending_with_provider( &self, - bundle_state_data: Box, + bundle_state_data: Box, ) -> ProviderResult; } @@ -201,7 +201,7 @@ pub trait BlockchainTreePendingStateProvider: Send + Sync { fn pending_state_provider( &self, block_hash: BlockHash, - ) -> ProviderResult> { + ) -> ProviderResult> { self.find_pending_state_provider(block_hash) .ok_or(ProviderError::StateForHashNotFound(block_hash)) } @@ -210,28 +210,46 @@ pub trait BlockchainTreePendingStateProvider: Send + Sync { fn find_pending_state_provider( &self, block_hash: BlockHash, - ) -> Option>; + ) -> Option>; } -/// Post state data needs for execution on it. -/// This trait is used to create a state provider over pending state. +/// Post state data needed for execution on it. /// -/// Pending state contains: +/// State contains: /// * [`BundleStateWithReceipts`] contains all changed of accounts and storage of pending chain /// * block hashes of pending chain and canonical blocks. -/// * canonical fork, the block on what pending chain was forked from. #[auto_impl(&, Box)] pub trait BundleStateDataProvider: Send + Sync { /// Return post state fn state(&self) -> &BundleStateWithReceipts; /// Return block hash by block number of pending or canonical chain. fn block_hash(&self, block_number: BlockNumber) -> Option; - /// return canonical fork, the block on what post state was forked from. +} + +/// Fork data needed for execution on it. +/// +/// It contains a canonical fork, the block on what pending chain was forked from. +#[auto_impl(&, Box)] +pub trait BundleStateForkProvider { + /// Return canonical fork, the block on what post state was forked from. /// /// Needed to create state provider. fn canonical_fork(&self) -> BlockNumHash; } +/// Full post state data needed for execution on it. +/// This trait is used to create a state provider over pending state. +/// +/// This trait is a combination of [`BundleStateDataProvider`] and [`BundleStateForkProvider`]. +/// +/// Pending state contains: +/// * [`BundleStateWithReceipts`] contains all changed of accounts and storage of pending chain +/// * block hashes of pending chain and canonical blocks. +/// * canonical fork, the block on what pending chain was forked from. +pub trait FullBundleStateDataProvider: BundleStateDataProvider + BundleStateForkProvider {} + +impl FullBundleStateDataProvider for T where T: BundleStateDataProvider + BundleStateForkProvider {} + /// A helper trait for [BundleStateWithReceipts] to write state and receipts to storage. pub trait StateWriter { /// Write the data and receipts to the database or static files if `static_file_producer` is