feat: extract proof generation into StateProofProvider (#9303)

This commit is contained in:
Roman Krasiuk
2024-07-04 08:06:48 -07:00
committed by GitHub
parent ddc6ab902b
commit e8af47636c
11 changed files with 92 additions and 55 deletions

View File

@ -1,7 +1,9 @@
use super::ExecutedBlock; use super::ExecutedBlock;
use reth_errors::ProviderResult; use reth_errors::ProviderResult;
use reth_primitives::{Account, Address, BlockNumber, Bytecode, StorageKey, StorageValue, B256}; use reth_primitives::{Account, Address, BlockNumber, Bytecode, StorageKey, StorageValue, B256};
use reth_provider::{AccountReader, BlockHashReader, StateProvider, StateRootProvider}; use reth_provider::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider,
};
use reth_trie::{updates::TrieUpdates, AccountProof}; use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::db::BundleState; use revm::db::BundleState;
@ -89,6 +91,15 @@ where
} }
} }
impl<H> StateProofProvider for MemoryOverlayStateProvider<H>
where
H: StateProofProvider + Send,
{
fn proof(&self, address: Address, slots: &[B256]) -> ProviderResult<AccountProof> {
todo!()
}
}
impl<H> StateProvider for MemoryOverlayStateProvider<H> impl<H> StateProvider for MemoryOverlayStateProvider<H>
where where
H: StateProvider + Send, H: StateProvider + Send,
@ -116,8 +127,4 @@ where
self.historical.bytecode_by_hash(code_hash) self.historical.bytecode_by_hash(code_hash)
} }
fn proof(&self, address: Address, keys: &[B256]) -> ProviderResult<AccountProof> {
todo!()
}
} }

View File

@ -1,7 +1,9 @@
use reth_primitives::{ use reth_primitives::{
keccak256, Account, Address, BlockNumber, Bytecode, Bytes, StorageKey, B256, U256, keccak256, Account, Address, BlockNumber, Bytecode, Bytes, StorageKey, B256, U256,
}; };
use reth_storage_api::{AccountReader, BlockHashReader, StateProvider, StateRootProvider}; use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider,
};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, AccountProof}; use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::db::BundleState; use revm::db::BundleState;
@ -76,6 +78,12 @@ impl StateRootProvider for StateProviderTest {
} }
} }
impl StateProofProvider for StateProviderTest {
fn proof(&self, _address: Address, _slots: &[B256]) -> ProviderResult<AccountProof> {
unimplemented!("proof generation is not supported")
}
}
impl StateProvider for StateProviderTest { impl StateProvider for StateProviderTest {
fn storage( fn storage(
&self, &self,
@ -88,8 +96,4 @@ impl StateProvider for StateProviderTest {
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> { fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
Ok(self.contracts.get(&code_hash).cloned()) Ok(self.contracts.get(&code_hash).cloned())
} }
fn proof(&self, _address: Address, _keys: &[B256]) -> ProviderResult<AccountProof> {
unimplemented!("proof generation is not supported")
}
} }

View File

@ -31,6 +31,16 @@ impl<'a> reth_provider::StateRootProvider for StateProviderTraitObjWrapper<'a> {
} }
} }
impl<'a> reth_provider::StateProofProvider for StateProviderTraitObjWrapper<'a> {
fn proof(
&self,
address: revm_primitives::Address,
slots: &[B256],
) -> reth_errors::ProviderResult<reth_trie::AccountProof> {
self.0.proof(address, slots)
}
}
impl<'a> reth_provider::AccountReader for StateProviderTraitObjWrapper<'a> { impl<'a> reth_provider::AccountReader for StateProviderTraitObjWrapper<'a> {
fn basic_account( fn basic_account(
&self, &self,
@ -93,14 +103,6 @@ impl<'a> StateProvider for StateProviderTraitObjWrapper<'a> {
self.0.bytecode_by_hash(code_hash) self.0.bytecode_by_hash(code_hash)
} }
fn proof(
&self,
address: revm_primitives::Address,
keys: &[B256],
) -> reth_errors::ProviderResult<reth_trie::AccountProof> {
self.0.proof(address, keys)
}
fn storage( fn storage(
&self, &self,
account: revm_primitives::Address, account: revm_primitives::Address,

View File

@ -2,6 +2,7 @@ use crate::{
AccountReader, BlockHashReader, ExecutionDataProvider, StateProvider, StateRootProvider, AccountReader, BlockHashReader, ExecutionDataProvider, StateProvider, StateRootProvider,
}; };
use reth_primitives::{Account, Address, BlockNumber, Bytecode, B256}; use reth_primitives::{Account, Address, BlockNumber, Bytecode, B256};
use reth_storage_api::StateProofProvider;
use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::{updates::TrieUpdates, AccountProof}; use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::db::BundleState; use revm::db::BundleState;
@ -80,6 +81,14 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
} }
} }
impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
for BundleStateProvider<SP, EDP>
{
fn proof(&self, _address: Address, _slots: &[B256]) -> ProviderResult<AccountProof> {
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
}
}
impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStateProvider<SP, EDP> { impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStateProvider<SP, EDP> {
fn storage( fn storage(
&self, &self,
@ -107,8 +116,4 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStat
self.state_provider.bytecode_by_hash(code_hash) self.state_provider.bytecode_by_hash(code_hash)
} }
fn proof(&self, _address: Address, _keys: &[B256]) -> ProviderResult<AccountProof> {
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
}
} }

View File

@ -13,6 +13,7 @@ use reth_primitives::{
constants::EPOCH_SLOTS, Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey, constants::EPOCH_SLOTS, Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey,
StorageValue, B256, StorageValue, B256,
}; };
use reth_storage_api::StateProofProvider;
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState}; use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState};
use revm::db::BundleState; use revm::db::BundleState;
@ -271,6 +272,13 @@ impl<'b, TX: DbTx> StateRootProvider for HistoricalStateProviderRef<'b, TX> {
} }
} }
impl<'b, TX: DbTx> StateProofProvider for HistoricalStateProviderRef<'b, TX> {
/// Get account and storage proofs.
fn proof(&self, _address: Address, _slots: &[B256]) -> ProviderResult<AccountProof> {
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
}
}
impl<'b, TX: DbTx> StateProvider for HistoricalStateProviderRef<'b, TX> { impl<'b, TX: DbTx> StateProvider for HistoricalStateProviderRef<'b, TX> {
/// Get storage. /// Get storage.
fn storage( fn storage(
@ -306,11 +314,6 @@ impl<'b, TX: DbTx> StateProvider for HistoricalStateProviderRef<'b, TX> {
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> { fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
self.tx.get::<tables::Bytecodes>(code_hash).map_err(Into::into) self.tx.get::<tables::Bytecodes>(code_hash).map_err(Into::into)
} }
/// Get account and storage proofs.
fn proof(&self, _address: Address, _keys: &[B256]) -> ProviderResult<AccountProof> {
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
}
} }
/// State provider for a given block number. /// State provider for a given block number.

View File

@ -10,6 +10,7 @@ use reth_db_api::{
use reth_primitives::{ use reth_primitives::{
Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey, StorageValue, B256, Account, Address, BlockNumber, Bytecode, StaticFileSegment, StorageKey, StorageValue, B256,
}; };
use reth_storage_api::StateProofProvider;
use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::{proof::Proof, updates::TrieUpdates, AccountProof, HashedPostState}; use reth_trie::{proof::Proof, updates::TrieUpdates, AccountProof, HashedPostState};
use revm::db::BundleState; use revm::db::BundleState;
@ -90,6 +91,14 @@ impl<'b, TX: DbTx> StateRootProvider for LatestStateProviderRef<'b, TX> {
} }
} }
impl<'b, TX: DbTx> StateProofProvider for LatestStateProviderRef<'b, TX> {
fn proof(&self, address: Address, slots: &[B256]) -> ProviderResult<AccountProof> {
Ok(Proof::new(self.tx)
.account_proof(address, slots)
.map_err(Into::<reth_db::DatabaseError>::into)?)
}
}
impl<'b, TX: DbTx> StateProvider for LatestStateProviderRef<'b, TX> { impl<'b, TX: DbTx> StateProvider for LatestStateProviderRef<'b, TX> {
/// Get storage. /// Get storage.
fn storage( fn storage(
@ -110,12 +119,6 @@ impl<'b, TX: DbTx> StateProvider for LatestStateProviderRef<'b, TX> {
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> { fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
self.tx.get::<tables::Bytecodes>(code_hash).map_err(Into::into) self.tx.get::<tables::Bytecodes>(code_hash).map_err(Into::into)
} }
fn proof(&self, address: Address, slots: &[B256]) -> ProviderResult<AccountProof> {
Ok(Proof::new(self.tx)
.account_proof(address, slots)
.map_err(Into::<reth_db::DatabaseError>::into)?)
}
} }
/// State provider for the latest state. /// State provider for the latest state.

View File

@ -30,10 +30,6 @@ macro_rules! delegate_provider_impls {
($target:ty $(where [$($generics:tt)*])?) => { ($target:ty $(where [$($generics:tt)*])?) => {
$crate::providers::state::macros::delegate_impls_to_as_ref!( $crate::providers::state::macros::delegate_impls_to_as_ref!(
for $target => for $target =>
StateRootProvider $(where [$($generics)*])? {
fn state_root(&self, state: &revm::db::BundleState) -> reth_storage_errors::provider::ProviderResult<reth_primitives::B256>;
fn state_root_with_updates(&self, state: &revm::db::BundleState) -> reth_storage_errors::provider::ProviderResult<(reth_primitives::B256, reth_trie::updates::TrieUpdates)>;
}
AccountReader $(where [$($generics)*])? { AccountReader $(where [$($generics)*])? {
fn basic_account(&self, address: reth_primitives::Address) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Account>>; fn basic_account(&self, address: reth_primitives::Address) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Account>>;
} }
@ -41,11 +37,17 @@ macro_rules! delegate_provider_impls {
fn block_hash(&self, number: u64) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::B256>>; fn block_hash(&self, number: u64) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::B256>>;
fn canonical_hashes_range(&self, start: reth_primitives::BlockNumber, end: reth_primitives::BlockNumber) -> reth_storage_errors::provider::ProviderResult<Vec<reth_primitives::B256>>; fn canonical_hashes_range(&self, start: reth_primitives::BlockNumber, end: reth_primitives::BlockNumber) -> reth_storage_errors::provider::ProviderResult<Vec<reth_primitives::B256>>;
} }
StateProvider $(where [$($generics)*])?{ StateProvider $(where [$($generics)*])? {
fn storage(&self, account: reth_primitives::Address, storage_key: reth_primitives::StorageKey) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::StorageValue>>; fn storage(&self, account: reth_primitives::Address, storage_key: reth_primitives::StorageKey) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::StorageValue>>;
fn proof(&self, address: reth_primitives::Address, keys: &[reth_primitives::B256]) -> reth_storage_errors::provider::ProviderResult<reth_trie::AccountProof>;
fn bytecode_by_hash(&self, code_hash: reth_primitives::B256) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Bytecode>>; fn bytecode_by_hash(&self, code_hash: reth_primitives::B256) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Bytecode>>;
} }
StateRootProvider $(where [$($generics)*])? {
fn state_root(&self, state: &revm::db::BundleState) -> reth_storage_errors::provider::ProviderResult<reth_primitives::B256>;
fn state_root_with_updates(&self, state: &revm::db::BundleState) -> reth_storage_errors::provider::ProviderResult<(reth_primitives::B256, reth_trie::updates::TrieUpdates)>;
}
StateProofProvider $(where [$($generics)*])? {
fn proof(&self, address: reth_primitives::Address, slots: &[reth_primitives::B256]) -> reth_storage_errors::provider::ProviderResult<reth_trie::AccountProof>;
}
); );
} }
} }

View File

@ -15,6 +15,7 @@ use reth_primitives::{
SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned, SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned,
TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256,
}; };
use reth_storage_api::StateProofProvider;
use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::{updates::TrieUpdates, AccountProof}; use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::{ use revm::{
@ -553,6 +554,12 @@ impl StateRootProvider for MockEthProvider {
} }
} }
impl StateProofProvider for MockEthProvider {
fn proof(&self, address: Address, _slots: &[B256]) -> ProviderResult<AccountProof> {
Ok(AccountProof::new(address))
}
}
impl StateProvider for MockEthProvider { impl StateProvider for MockEthProvider {
fn storage( fn storage(
&self, &self,
@ -574,10 +581,6 @@ impl StateProvider for MockEthProvider {
} }
})) }))
} }
fn proof(&self, address: Address, _keys: &[B256]) -> ProviderResult<AccountProof> {
Ok(AccountProof::new(address))
}
} }
impl EvmEnvProvider for MockEthProvider { impl EvmEnvProvider for MockEthProvider {

View File

@ -14,6 +14,7 @@ use reth_primitives::{
}; };
use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId}; use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::StateProofProvider;
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, AccountProof}; use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::{ use revm::{
@ -326,6 +327,12 @@ impl StateRootProvider for NoopProvider {
} }
} }
impl StateProofProvider for NoopProvider {
fn proof(&self, address: Address, _slots: &[B256]) -> ProviderResult<AccountProof> {
Ok(AccountProof::new(address))
}
}
impl StateProvider for NoopProvider { impl StateProvider for NoopProvider {
fn storage( fn storage(
&self, &self,
@ -338,10 +345,6 @@ impl StateProvider for NoopProvider {
fn bytecode_by_hash(&self, _code_hash: B256) -> ProviderResult<Option<Bytecode>> { fn bytecode_by_hash(&self, _code_hash: B256) -> ProviderResult<Option<Bytecode>> {
Ok(None) Ok(None)
} }
fn proof(&self, address: Address, _keys: &[B256]) -> ProviderResult<AccountProof> {
Ok(AccountProof::new(address))
}
} }
impl EvmEnvProvider for NoopProvider { impl EvmEnvProvider for NoopProvider {

View File

@ -1,4 +1,4 @@
use super::{AccountReader, BlockHashReader, BlockIdReader, StateRootProvider}; use super::{AccountReader, BlockHashReader, BlockIdReader, StateProofProvider, StateRootProvider};
use auto_impl::auto_impl; use auto_impl::auto_impl;
use reth_execution_types::ExecutionOutcome; use reth_execution_types::ExecutionOutcome;
use reth_primitives::{ use reth_primitives::{
@ -6,14 +6,15 @@ use reth_primitives::{
StorageValue, B256, KECCAK_EMPTY, U256, StorageValue, B256, KECCAK_EMPTY, U256,
}; };
use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::AccountProof;
/// Type alias of boxed [`StateProvider`]. /// Type alias of boxed [`StateProvider`].
pub type StateProviderBox = Box<dyn StateProvider>; pub type StateProviderBox = Box<dyn StateProvider>;
/// An abstraction for a type that provides state data. /// An abstraction for a type that provides state data.
#[auto_impl(&, Arc, Box)] #[auto_impl(&, Arc, Box)]
pub trait StateProvider: BlockHashReader + AccountReader + StateRootProvider + Send + Sync { pub trait StateProvider:
BlockHashReader + AccountReader + StateRootProvider + StateProofProvider + Send + Sync
{
/// Get storage of given account. /// Get storage of given account.
fn storage( fn storage(
&self, &self,
@ -24,9 +25,6 @@ pub trait StateProvider: BlockHashReader + AccountReader + StateRootProvider + S
/// Get account code by its hash /// Get account code by its hash
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>>; fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>>;
/// Get account and storage proofs.
fn proof(&self, address: Address, keys: &[B256]) -> ProviderResult<AccountProof>;
/// Get account code by its address. /// Get account code by its address.
/// ///
/// Returns `None` if the account doesn't exist or account is not a contract /// Returns `None` if the account doesn't exist or account is not a contract

View File

@ -1,6 +1,6 @@
use reth_primitives::B256; use reth_primitives::{Address, B256};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::updates::TrieUpdates; use reth_trie::{updates::TrieUpdates, AccountProof};
use revm::db::BundleState; use revm::db::BundleState;
/// A type that can compute the state root of a given post state. /// A type that can compute the state root of a given post state.
@ -22,3 +22,10 @@ pub trait StateRootProvider: Send + Sync {
bundle_state: &BundleState, bundle_state: &BundleState,
) -> ProviderResult<(B256, TrieUpdates)>; ) -> ProviderResult<(B256, TrieUpdates)>;
} }
/// A type that can generate state proof on top of a given post state.
#[auto_impl::auto_impl(&, Box, Arc)]
pub trait StateProofProvider: Send + Sync {
/// Get account and storage proofs.
fn proof(&self, address: Address, slots: &[B256]) -> ProviderResult<AccountProof>;
}