Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(trie): expose multiproof via StateProofProvider #10915

Merged
merged 3 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion crates/chain-state/src/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,8 @@ mod tests {
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider,
StorageRootProvider,
};
use reth_trie::{AccountProof, HashedStorage, TrieInput};
use reth_trie::{AccountProof, HashedStorage, MultiProof, TrieInput};
use std::collections::HashSet;

fn create_mock_state(
test_block_builder: &mut TestBlockBuilder,
Expand Down Expand Up @@ -952,6 +953,14 @@ mod tests {
Ok(AccountProof::new(Address::random()))
}

fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
fgimenez marked this conversation as resolved.
Show resolved Hide resolved
}

fn witness(
&self,
_input: TrieInput,
Expand Down
19 changes: 17 additions & 2 deletions crates/chain-state/src/memory_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateProviderBox,
StateRootProvider, StorageRootProvider,
};
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput};
use std::{collections::HashMap, sync::OnceLock};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
};
use std::{
collections::{HashMap, HashSet},
sync::OnceLock,
};

/// A state provider that stores references to in-memory blocks along with their state as well as
/// the historical state provider for fallback lookups.
Expand Down Expand Up @@ -147,6 +152,16 @@ impl StateProofProvider for MemoryOverlayStateProvider {
self.historical.proof(input, address, slots)
}

fn multiproof(
&self,
mut input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
input.prepend_cached(nodes, state);
self.historical.multiproof(input, targets)
}

fn witness(
&self,
mut input: TrieInput,
Expand Down
14 changes: 13 additions & 1 deletion crates/revm/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashSet;

use crate::precompile::HashMap;
use alloc::vec::Vec;
use reth_primitives::{
Expand All @@ -8,7 +10,9 @@ use reth_storage_api::{
StorageRootProvider,
};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
};

/// Mock state for testing
#[derive(Debug, Default, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -110,6 +114,14 @@ impl StateProofProvider for StateProviderTest {
unimplemented!("proof generation is not supported")
}

fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
unimplemented!("proof generation is not supported")
}

fn witness(
&self,
_input: TrieInput,
Expand Down
8 changes: 8 additions & 0 deletions crates/rpc/rpc-eth-types/src/cache/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ impl<'a> reth_storage_api::StateProofProvider for StateProviderTraitObjWrapper<'
self.0.proof(input, address, slots)
}

fn multiproof(
&self,
input: reth_trie::TrieInput,
targets: std::collections::HashMap<B256, std::collections::HashSet<B256>>,
) -> ProviderResult<reth_trie::MultiProof> {
self.0.multiproof(input, targets)
}

fn witness(
&self,
input: reth_trie::TrieInput,
Expand Down
16 changes: 14 additions & 2 deletions crates/storage/provider/src/providers/bundle_state_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ 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::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput};
use std::collections::HashMap;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
};
use std::collections::{HashMap, HashSet};

/// A state provider that resolves to data from either a wrapped [`crate::ExecutionOutcome`]
/// or an underlying state provider.
Expand Down Expand Up @@ -133,6 +135,16 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
self.state_provider.proof(input, address, slots)
}

fn multiproof(
&self,
mut input: reth_trie::TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state));
self.state_provider.multiproof(input, targets)
}

fn witness(
&self,
mut input: TrieInput,
Expand Down
16 changes: 14 additions & 2 deletions crates/storage/provider/src/providers/state/historical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ use reth_storage_api::{StateProofProvider, StorageRootProvider};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
proof::Proof, updates::TrieUpdates, witness::TrieWitness, AccountProof, HashedPostState,
HashedStorage, StateRoot, StorageRoot, TrieInput,
HashedStorage, MultiProof, StateRoot, StorageRoot, TrieInput,
};
use reth_trie_db::{
DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot,
DatabaseStorageRoot, DatabaseTrieWitness,
};
use std::{collections::HashMap, fmt::Debug};
use std::{
collections::{HashMap, HashSet},
fmt::Debug,
};

/// State provider for a given block number which takes a tx reference.
///
Expand Down Expand Up @@ -344,6 +347,15 @@ impl<'b, TX: DbTx> StateProofProvider for HistoricalStateProviderRef<'b, TX> {
.map_err(Into::<ProviderError>::into)
}

fn multiproof(
&self,
mut input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
input.prepend(self.revert_state()?);
Proof::overlay_multiproof(self.tx, input, targets).map_err(Into::<ProviderError>::into)
}

fn witness(
&self,
mut input: TrieInput,
Expand Down
12 changes: 10 additions & 2 deletions crates/storage/provider/src/providers/state/latest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use reth_storage_api::{StateProofProvider, StorageRootProvider};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::{
proof::Proof, updates::TrieUpdates, witness::TrieWitness, AccountProof, HashedPostState,
HashedStorage, StateRoot, StorageRoot, TrieInput,
HashedStorage, MultiProof, StateRoot, StorageRoot, TrieInput,
};
use reth_trie_db::{DatabaseProof, DatabaseStateRoot, DatabaseStorageRoot, DatabaseTrieWitness};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

/// State provider over latest state that takes tx reference.
#[derive(Debug)]
Expand Down Expand Up @@ -129,6 +129,14 @@ impl<'b, TX: DbTx> StateProofProvider for LatestStateProviderRef<'b, TX> {
.map_err(Into::<ProviderError>::into)
}

fn multiproof(
&self,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
Proof::overlay_multiproof(self.tx, input, targets).map_err(Into::<ProviderError>::into)
}

fn witness(
&self,
input: TrieInput,
Expand Down
1 change: 1 addition & 0 deletions crates/storage/provider/src/providers/state/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ macro_rules! delegate_provider_impls {
}
StateProofProvider $(where [$($generics)*])? {
fn proof(&self, input: reth_trie::TrieInput, address: reth_primitives::Address, slots: &[reth_primitives::B256]) -> reth_storage_errors::provider::ProviderResult<reth_trie::AccountProof>;
fn multiproof(&self, input: reth_trie::TrieInput, targets: std::collections::HashMap<reth_primitives::B256, std::collections::HashSet<reth_primitives::B256>>) -> reth_storage_errors::provider::ProviderResult<reth_trie::MultiProof>;
fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult<std::collections::HashMap<reth_primitives::B256, reth_primitives::Bytes>>;
}
);
Expand Down
14 changes: 12 additions & 2 deletions crates/storage/provider/src/test_utils/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ use reth_storage_api::{
DatabaseProviderFactory, StageCheckpointReader, StateProofProvider, StorageRootProvider,
};
use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult};
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use std::{
collections::{BTreeMap, HashMap},
collections::{BTreeMap, HashMap, HashSet},
ops::{RangeBounds, RangeInclusive},
sync::Arc,
};
Expand Down Expand Up @@ -624,6 +626,14 @@ impl StateProofProvider for MockEthProvider {
Ok(AccountProof::new(address))
}

fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
}

fn witness(
&self,
_input: TrieInput,
Expand Down
14 changes: 12 additions & 2 deletions crates/storage/provider/src/test_utils/noop.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
ops::{RangeBounds, RangeInclusive},
sync::Arc,
};
Expand All @@ -22,7 +22,9 @@ 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::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use tokio::sync::{broadcast, watch};

Expand Down Expand Up @@ -362,6 +364,14 @@ impl StateProofProvider for NoopProvider {
Ok(AccountProof::new(address))
}

fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
}

fn witness(
&self,
_input: TrieInput,
Expand Down
14 changes: 12 additions & 2 deletions crates/storage/storage-api/src/trie.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use alloy_primitives::{Address, Bytes, B256};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, TrieInput};
use std::collections::HashMap;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
};
use std::collections::{HashMap, HashSet};

/// A type that can compute the state root of a given post state.
#[auto_impl::auto_impl(&, Box, Arc)]
Expand Down Expand Up @@ -56,6 +58,14 @@ pub trait StateProofProvider: Send + Sync {
slots: &[B256],
) -> ProviderResult<AccountProof>;

/// Generate [`MultiProof`] for target hashed account and corresponding
/// hashed storage slot keys.
fn multiproof(
&self,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof>;

/// Get trie witness for provided state.
fn witness(
&self,
Expand Down
2 changes: 2 additions & 0 deletions crates/trie/common/src/proofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};

/// The state multiproof of target accounts and multiproofs of their storage tries.
/// Multiproof is effectively a state subtrie that only contains the nodes
/// in the paths of target accounts.
#[derive(Clone, Default, Debug)]
pub struct MultiProof {
/// State trie multiproof for requested accounts.
Expand Down
31 changes: 30 additions & 1 deletion crates/trie/db/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use reth_execution_errors::StateProofError;
use reth_primitives::{Address, B256};
use reth_trie::{
hashed_cursor::HashedPostStateCursorFactory, proof::Proof,
trie_cursor::InMemoryTrieCursorFactory, TrieInput,
trie_cursor::InMemoryTrieCursorFactory, MultiProof, TrieInput,
};
use reth_trie_common::AccountProof;
use std::collections::{HashMap, HashSet};

/// Extends [`Proof`] with operations specific for working with a database transaction.
pub trait DatabaseProof<'a, TX> {
Expand All @@ -20,6 +21,13 @@ pub trait DatabaseProof<'a, TX> {
address: Address,
slots: &[B256],
) -> Result<AccountProof, StateProofError>;

/// Generates the state [`MultiProof`] for target hashed account and storage keys.
fn overlay_multiproof(
tx: &'a TX,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> Result<MultiProof, StateProofError>;
}

impl<'a, TX: DbTx> DatabaseProof<'a, TX>
Expand Down Expand Up @@ -50,4 +58,25 @@ impl<'a, TX: DbTx> DatabaseProof<'a, TX>
.with_prefix_sets_mut(input.prefix_sets)
.account_proof(address, slots)
}

fn overlay_multiproof(
tx: &'a TX,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
) -> Result<MultiProof, StateProofError> {
let nodes_sorted = input.nodes.into_sorted();
let state_sorted = input.state.into_sorted();
Self::from_tx(tx)
.with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
DatabaseTrieCursorFactory::new(tx),
&nodes_sorted,
))
.with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
DatabaseHashedCursorFactory::new(tx),
&state_sorted,
))
.with_prefix_sets_mut(input.prefix_sets)
.with_targets(targets)
.multiproof()
}
}
Loading
Loading