perf: trie micro optimizations (#13282)

This commit is contained in:
DaniPopes
2024-12-11 05:52:42 +01:00
committed by GitHub
parent 0144a433df
commit 0494ca01d5
37 changed files with 306 additions and 246 deletions

View File

@ -1244,7 +1244,7 @@ where
))
.with_prefix_sets(prefix_sets)
.root_with_updates()
.map_err(Into::<BlockValidationError>::into)?;
.map_err(BlockValidationError::from)?;
let tip = blocks.tip();
if state_root != tip.state_root {
return Err(ProviderError::StateRootMismatch(Box::new(RootMismatch {

View File

@ -944,7 +944,7 @@ mod tests {
use super::*;
use crate::test_utils::TestBlockBuilder;
use alloy_eips::eip7685::Requests;
use alloy_primitives::{map::HashSet, BlockNumber, Bytes, StorageKey, StorageValue};
use alloy_primitives::{map::B256HashMap, BlockNumber, Bytes, StorageKey, StorageValue};
use rand::Rng;
use reth_errors::ProviderResult;
use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt};
@ -953,7 +953,8 @@ mod tests {
StateRootProvider, StorageRootProvider,
};
use reth_trie::{
AccountProof, HashedStorage, MultiProof, StorageMultiProof, StorageProof, TrieInput,
AccountProof, HashedStorage, MultiProof, MultiProofTargets, StorageMultiProof,
StorageProof, TrieInput,
};
fn create_mock_state(
@ -1094,7 +1095,7 @@ mod tests {
fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
_targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
}
@ -1103,7 +1104,7 @@ mod tests {
&self,
_input: TrieInput,
_target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
Ok(HashMap::default())
}
}

View File

@ -1,9 +1,7 @@
use super::ExecutedBlock;
use alloy_consensus::BlockHeader;
use alloy_primitives::{
keccak256,
map::{HashMap, HashSet},
Address, BlockNumber, Bytes, StorageKey, StorageValue, B256,
keccak256, map::B256HashMap, Address, BlockNumber, Bytes, StorageKey, StorageValue, B256,
};
use reth_errors::ProviderResult;
use reth_primitives::{Account, Bytecode, NodePrimitives};
@ -13,7 +11,7 @@ use reth_storage_api::{
};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
StorageMultiProof, TrieInput,
MultiProofTargets, StorageMultiProof, TrieInput,
};
use revm::db::BundleState;
use std::sync::OnceLock;
@ -201,7 +199,7 @@ macro_rules! impl_state_provider {
fn multiproof(
&self,
mut input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
input.prepend_cached(nodes, state);
@ -212,7 +210,7 @@ macro_rules! impl_state_provider {
&self,
mut input: TrieInput,
target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
let MemoryOverlayTrieState { nodes, state } = self.trie_state().clone();
input.prepend_cached(nodes, state);
self.historical.witness(input, target)

View File

@ -8,13 +8,13 @@ use reth_provider::{
StateCommitmentProvider,
};
use reth_trie::{
proof::Proof, updates::TrieUpdates, HashedPostState, HashedStorage, MultiProof, Nibbles,
TrieInput,
proof::Proof, updates::TrieUpdates, HashedPostState, HashedStorage, MultiProof,
MultiProofTargets, Nibbles, TrieInput,
};
use reth_trie_db::DatabaseProof;
use reth_trie_parallel::root::ParallelStateRootError;
use reth_trie_sparse::{
errors::{SparseStateTrieResult, SparseTrieError},
errors::{SparseStateTrieResult, SparseTrieErrorKind},
SparseStateTrie,
};
use revm_primitives::{keccak256, EvmState, B256};
@ -232,7 +232,7 @@ pub struct StateRootTask<Factory> {
/// Sender for state root related messages.
tx: Sender<StateRootMessage>,
/// Proof targets that have been already fetched.
fetched_proof_targets: HashMap<B256, HashSet<B256>>,
fetched_proof_targets: MultiProofTargets,
/// Proof sequencing handler.
proof_sequencer: ProofSequencer,
/// The sparse trie used for the state root calculation. If [`None`], then update is in
@ -297,7 +297,7 @@ where
view: ConsistentDbView<Factory>,
input: Arc<TrieInput>,
update: EvmState,
fetched_proof_targets: &mut HashMap<B256, HashSet<B256>>,
fetched_proof_targets: &mut MultiProofTargets,
proof_sequence_number: u64,
state_root_message_sender: Sender<StateRootMessage>,
) {
@ -525,8 +525,8 @@ where
/// account shouldn't be included.
fn get_proof_targets(
state_update: &HashedPostState,
fetched_proof_targets: &HashMap<B256, HashSet<B256>>,
) -> HashMap<B256, HashSet<B256>> {
fetched_proof_targets: &MultiProofTargets,
) -> MultiProofTargets {
let mut targets = HashMap::default();
// first collect all new accounts (not previously fetched)
@ -558,7 +558,7 @@ fn get_proof_targets(
fn update_sparse_trie(
mut trie: Box<SparseStateTrie>,
multiproof: MultiProof,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
state: HashedPostState,
) -> SparseStateTrieResult<(Box<SparseStateTrie>, Duration)> {
trace!(target: "engine::root::sparse", "Updating sparse trie");
@ -576,7 +576,7 @@ fn update_sparse_trie(
.par_bridge()
.map(|(address, storage, storage_trie)| {
trace!(target: "engine::root::sparse", ?address, "Updating storage");
let mut storage_trie = storage_trie.ok_or(SparseTrieError::Blind)?;
let mut storage_trie = storage_trie.ok_or(SparseTrieErrorKind::Blind)?;
if storage.wiped {
trace!(target: "engine::root::sparse", ?address, "Wiping storage");

View File

@ -67,7 +67,38 @@ pub type SparseStateTrieResult<Ok> = Result<Ok, SparseStateTrieError>;
/// Error encountered in `SparseStateTrie`.
#[derive(Error, Debug)]
pub enum SparseStateTrieError {
#[error(transparent)]
pub struct SparseStateTrieError(#[from] Box<SparseStateTrieErrorKind>);
impl<T: Into<SparseStateTrieErrorKind>> From<T> for SparseStateTrieError {
#[cold]
fn from(value: T) -> Self {
Self(Box::new(value.into()))
}
}
impl From<SparseTrieError> for SparseStateTrieErrorKind {
#[cold]
fn from(value: SparseTrieError) -> Self {
Self::Sparse(*value.0)
}
}
impl SparseStateTrieError {
/// Returns the error kind.
pub const fn kind(&self) -> &SparseStateTrieErrorKind {
&self.0
}
/// Consumes the error and returns the error kind.
pub fn into_kind(self) -> SparseStateTrieErrorKind {
*self.0
}
}
/// Error encountered in `SparseStateTrie`.
#[derive(Error, Debug)]
pub enum SparseStateTrieErrorKind {
/// Encountered invalid root node.
#[error("invalid root node at {path:?}: {node:?}")]
InvalidRootNode {
@ -78,7 +109,7 @@ pub enum SparseStateTrieError {
},
/// Sparse trie error.
#[error(transparent)]
Sparse(#[from] SparseTrieError),
Sparse(#[from] SparseTrieErrorKind),
/// RLP error.
#[error(transparent)]
Rlp(#[from] alloy_rlp::Error),
@ -89,7 +120,31 @@ pub type SparseTrieResult<Ok> = Result<Ok, SparseTrieError>;
/// Error encountered in `SparseTrie`.
#[derive(Error, Debug)]
pub enum SparseTrieError {
#[error(transparent)]
pub struct SparseTrieError(#[from] Box<SparseTrieErrorKind>);
impl<T: Into<SparseTrieErrorKind>> From<T> for SparseTrieError {
#[cold]
fn from(value: T) -> Self {
Self(Box::new(value.into()))
}
}
impl SparseTrieError {
/// Returns the error kind.
pub const fn kind(&self) -> &SparseTrieErrorKind {
&self.0
}
/// Consumes the error and returns the error kind.
pub fn into_kind(self) -> SparseTrieErrorKind {
*self.0
}
}
/// [`SparseTrieError`] kind.
#[derive(Error, Debug)]
pub enum SparseTrieErrorKind {
/// Sparse trie is still blind. Thrown on attempt to update it.
#[error("sparse trie is blind")]
Blind,
@ -134,6 +189,12 @@ pub enum TrieWitnessError {
MissingAccount(B256),
}
impl From<SparseStateTrieErrorKind> for TrieWitnessError {
fn from(error: SparseStateTrieErrorKind) -> Self {
Self::Sparse(error.into())
}
}
impl From<TrieWitnessError> for ProviderError {
fn from(error: TrieWitnessError) -> Self {
Self::TrieWitnessError(error.to_string())

View File

@ -1,7 +1,7 @@
use alloc::vec::Vec;
use alloy_primitives::{
keccak256,
map::{HashMap, HashSet},
map::{B256HashMap, HashMap},
Address, BlockNumber, Bytes, StorageKey, B256, U256,
};
use reth_primitives::{Account, Bytecode};
@ -12,7 +12,7 @@ use reth_storage_api::{
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, KeccakKeyHasher,
MultiProof, StorageMultiProof, StorageProof, TrieInput,
MultiProof, MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
};
/// Mock state for testing
@ -136,7 +136,7 @@ impl StateProofProvider for StateProviderTest {
fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
_targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
unimplemented!("proof generation is not supported")
}
@ -145,7 +145,7 @@ impl StateProofProvider for StateProviderTest {
&self,
_input: TrieInput,
_target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
unimplemented!("witness generation is not supported")
}
}

View File

@ -253,7 +253,7 @@ mod tests {
fn test_rpc_gas_cap() {
let args = CommandParser::<RpcServerArgs>::parse_from(["reth"]).args;
let config = args.eth_config();
assert_eq!(config.rpc_gas_cap, Into::<u64>::into(RPC_DEFAULT_GAS_CAP));
assert_eq!(config.rpc_gas_cap, u64::from(RPC_DEFAULT_GAS_CAP));
let args =
CommandParser::<RpcServerArgs>::parse_from(["reth", "--rpc.gascap", "1000"]).args;

View File

@ -2,14 +2,11 @@
//! <https://github.com/rust-lang/rust/issues/100013> in default implementation of
//! `reth_rpc_eth_api::helpers::Call`.
use alloy_primitives::{
map::{HashMap, HashSet},
Address, B256, U256,
};
use alloy_primitives::{Address, B256, U256};
use reth_errors::ProviderResult;
use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef};
use reth_storage_api::{HashedPostStateProvider, StateProvider};
use reth_trie::HashedStorage;
use reth_trie::{HashedStorage, MultiProofTargets};
use revm::Database;
/// Helper alias type for the state's [`CacheDB`]
@ -91,7 +88,7 @@ impl reth_storage_api::StateProofProvider for StateProviderTraitObjWrapper<'_> {
fn multiproof(
&self,
input: reth_trie::TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> ProviderResult<reth_trie::MultiProof> {
self.0.multiproof(input, targets)
}
@ -100,7 +97,7 @@ impl reth_storage_api::StateProofProvider for StateProviderTraitObjWrapper<'_> {
&self,
input: reth_trie::TrieInput,
target: reth_trie::HashedPostState,
) -> reth_errors::ProviderResult<alloy_primitives::map::HashMap<B256, alloy_primitives::Bytes>>
) -> reth_errors::ProviderResult<alloy_primitives::map::B256HashMap<alloy_primitives::Bytes>>
{
self.0.witness(input, target)
}

View File

@ -1,16 +1,13 @@
use crate::{
AccountReader, BlockHashReader, ExecutionDataProvider, StateProvider, StateRootProvider,
};
use alloy_primitives::{
map::{HashMap, HashSet},
Address, BlockNumber, Bytes, B256,
};
use alloy_primitives::{map::B256HashMap, Address, BlockNumber, Bytes, B256};
use reth_primitives::{Account, Bytecode};
use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
StorageMultiProof, TrieInput,
MultiProofTargets, StorageMultiProof, TrieInput,
};
/// A state provider that resolves to data from either a wrapped [`crate::ExecutionOutcome`]
@ -169,7 +166,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
fn multiproof(
&self,
mut input: reth_trie::TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(self.hashed_post_state(bundle_state));
@ -180,7 +177,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
&self,
mut input: TrieInput,
target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.witness(input, target)

View File

@ -27,7 +27,7 @@ use alloy_eips::{
};
use alloy_primitives::{
keccak256,
map::{hash_map, HashMap, HashSet},
map::{hash_map, B256HashMap, HashMap, HashSet},
Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256,
};
use itertools::Itertools;
@ -296,7 +296,7 @@ impl<TX: DbTx + DbTxMut + 'static, N: NodeTypesForProvider> DatabaseProvider<TX,
// Unwind storage hashes. Add changed account and storage keys to corresponding prefix
// sets.
let mut storage_prefix_sets = HashMap::<B256, PrefixSet>::default();
let mut storage_prefix_sets = B256HashMap::<PrefixSet>::default();
let storage_entries = self.unwind_storage_hashing(changed_storages.iter().copied())?;
for (hashed_address, hashed_slots) in storage_entries {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
@ -321,7 +321,7 @@ impl<TX: DbTx + DbTxMut + 'static, N: NodeTypesForProvider> DatabaseProvider<TX,
let (new_state_root, trie_updates) = StateRoot::from_tx(&self.tx)
.with_prefix_sets(prefix_sets)
.root_with_updates()
.map_err(Into::<reth_db::DatabaseError>::into)?;
.map_err(reth_db::DatabaseError::from)?;
let parent_number = range.start().saturating_sub(1);
let parent_state_root = self
@ -2310,7 +2310,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypes> StorageTrieWriter for DatabaseP
/// updates by the hashed address, writing in sorted order.
fn write_storage_trie_updates(
&self,
storage_tries: &HashMap<B256, StorageTrieUpdates>,
storage_tries: &B256HashMap<StorageTrieUpdates>,
) -> ProviderResult<usize> {
let mut num_entries = 0;
let mut storage_tries = Vec::from_iter(storage_tries);
@ -2549,7 +2549,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypes> HashingWriter for DatabaseProvi
let (state_root, trie_updates) = StateRoot::from_tx(&self.tx)
.with_prefix_sets(prefix_sets)
.root_with_updates()
.map_err(Into::<reth_db::DatabaseError>::into)?;
.map_err(reth_db::DatabaseError::from)?;
if state_root != expected_state_root {
return Err(ProviderError::StateRootMismatch(Box::new(RootMismatch {
root: GotExpected { got: state_root, expected: expected_state_root },

View File

@ -4,8 +4,7 @@ use crate::{
};
use alloy_eips::merge::EPOCH_SLOTS;
use alloy_primitives::{
map::{HashMap, HashSet},
Address, BlockNumber, Bytes, StorageKey, StorageValue, B256,
map::B256HashMap, Address, BlockNumber, Bytes, StorageKey, StorageValue, B256,
};
use reth_db::{tables, BlockNumberList};
use reth_db_api::{
@ -23,8 +22,8 @@ use reth_trie::{
proof::{Proof, StorageProof},
updates::TrieUpdates,
witness::TrieWitness,
AccountProof, HashedPostState, HashedStorage, MultiProof, StateRoot, StorageMultiProof,
StorageRoot, TrieInput,
AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StateRoot,
StorageMultiProof, StorageRoot, TrieInput,
};
use reth_trie_db::{
DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot,
@ -346,7 +345,7 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider> StorageRoo
let mut revert_storage = self.revert_storage(address)?;
revert_storage.extend(&hashed_storage);
StorageProof::overlay_storage_proof(self.tx(), address, slot, revert_storage)
.map_err(Into::<ProviderError>::into)
.map_err(ProviderError::from)
}
fn storage_multiproof(
@ -358,7 +357,7 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider> StorageRoo
let mut revert_storage = self.revert_storage(address)?;
revert_storage.extend(&hashed_storage);
StorageProof::overlay_storage_multiproof(self.tx(), address, slots, revert_storage)
.map_err(Into::<ProviderError>::into)
.map_err(ProviderError::from)
}
}
@ -373,26 +372,25 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider> StateProof
slots: &[B256],
) -> ProviderResult<AccountProof> {
input.prepend(self.revert_state()?);
Proof::overlay_account_proof(self.tx(), input, address, slots)
.map_err(Into::<ProviderError>::into)
Proof::overlay_account_proof(self.tx(), input, address, slots).map_err(ProviderError::from)
}
fn multiproof(
&self,
mut input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
input.prepend(self.revert_state()?);
Proof::overlay_multiproof(self.tx(), input, targets).map_err(Into::<ProviderError>::into)
Proof::overlay_multiproof(self.tx(), input, targets).map_err(ProviderError::from)
}
fn witness(
&self,
mut input: TrieInput,
target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
input.prepend(self.revert_state()?);
TrieWitness::overlay_witness(self.tx(), input, target).map_err(Into::<ProviderError>::into)
TrieWitness::overlay_witness(self.tx(), input, target).map_err(ProviderError::from)
}
}

View File

@ -3,8 +3,7 @@ use crate::{
HashedPostStateProvider, StateProvider, StateRootProvider,
};
use alloy_primitives::{
map::{HashMap, HashSet},
Address, BlockNumber, Bytes, StorageKey, StorageValue, B256,
map::B256HashMap, Address, BlockNumber, Bytes, StorageKey, StorageValue, B256,
};
use reth_db::tables;
use reth_db_api::{cursor::DbDupCursorRO, transaction::DbTx};
@ -17,8 +16,8 @@ use reth_trie::{
proof::{Proof, StorageProof},
updates::TrieUpdates,
witness::TrieWitness,
AccountProof, HashedPostState, HashedStorage, MultiProof, StateRoot, StorageMultiProof,
StorageRoot, TrieInput,
AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StateRoot,
StorageMultiProof, StorageRoot, TrieInput,
};
use reth_trie_db::{
DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot,
@ -113,7 +112,7 @@ impl<Provider: DBProvider + StateCommitmentProvider> StorageRootProvider
hashed_storage: HashedStorage,
) -> ProviderResult<reth_trie::StorageProof> {
StorageProof::overlay_storage_proof(self.tx(), address, slot, hashed_storage)
.map_err(Into::<ProviderError>::into)
.map_err(ProviderError::from)
}
fn storage_multiproof(
@ -123,7 +122,7 @@ impl<Provider: DBProvider + StateCommitmentProvider> StorageRootProvider
hashed_storage: HashedStorage,
) -> ProviderResult<StorageMultiProof> {
StorageProof::overlay_storage_multiproof(self.tx(), address, slots, hashed_storage)
.map_err(Into::<ProviderError>::into)
.map_err(ProviderError::from)
}
}
@ -136,24 +135,23 @@ impl<Provider: DBProvider + StateCommitmentProvider> StateProofProvider
address: Address,
slots: &[B256],
) -> ProviderResult<AccountProof> {
Proof::overlay_account_proof(self.tx(), input, address, slots)
.map_err(Into::<ProviderError>::into)
Proof::overlay_account_proof(self.tx(), input, address, slots).map_err(ProviderError::from)
}
fn multiproof(
&self,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
Proof::overlay_multiproof(self.tx(), input, targets).map_err(Into::<ProviderError>::into)
Proof::overlay_multiproof(self.tx(), input, targets).map_err(ProviderError::from)
}
fn witness(
&self,
input: TrieInput,
target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
TrieWitness::overlay_witness(self.tx(), input, target).map_err(Into::<ProviderError>::into)
) -> ProviderResult<B256HashMap<Bytes>> {
TrieWitness::overlay_witness(self.tx(), input, target).map_err(ProviderError::from)
}
}

View File

@ -54,8 +54,8 @@ macro_rules! delegate_provider_impls {
}
StateProofProvider $(where [$($generics)*])? {
fn proof(&self, input: reth_trie::TrieInput, address: alloy_primitives::Address, slots: &[alloy_primitives::B256]) -> reth_storage_errors::provider::ProviderResult<reth_trie::AccountProof>;
fn multiproof(&self, input: reth_trie::TrieInput, targets: alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::map::HashSet<alloy_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<alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::Bytes>>;
fn multiproof(&self, input: reth_trie::TrieInput, targets: reth_trie::MultiProofTargets) -> reth_storage_errors::provider::ProviderResult<reth_trie::MultiProof>;
fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult<alloy_primitives::map::B256HashMap<alloy_primitives::Bytes>>;
}
HashedPostStateProvider $(where [$($generics)*])? {
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState;

View File

@ -171,7 +171,7 @@ fn bundle_state_root(execution_outcome: &ExecutionOutcome) -> B256 {
(
address,
(
Into::<Account>::into(info),
Account::from(info),
storage_root_unhashed(
account
.storage

View File

@ -12,7 +12,7 @@ use alloy_eips::{
};
use alloy_primitives::{
keccak256,
map::{HashMap, HashSet},
map::{B256HashMap, HashMap},
Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256, U256,
};
use parking_lot::Mutex;
@ -35,7 +35,7 @@ use reth_storage_api::{
use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
StorageMultiProof, StorageProof, TrieInput,
MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
};
use reth_trie_db::MerklePatriciaTrie;
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
@ -673,7 +673,7 @@ impl StateProofProvider for MockEthProvider {
fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
_targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
}
@ -682,7 +682,7 @@ impl StateProofProvider for MockEthProvider {
&self,
_input: TrieInput,
_target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
Ok(HashMap::default())
}
}

View File

@ -80,7 +80,7 @@ pub fn insert_genesis<N: ProviderNodeTypes<ChainSpec = ChainSpec>>(
let (root, updates) = StateRoot::from_tx(provider.tx_ref())
.root_with_updates()
.map_err(Into::<reth_db::DatabaseError>::into)?;
.map_err(reth_db::DatabaseError::from)?;
provider.write_trie_updates(&updates).unwrap();
provider.commit()?;

View File

@ -10,7 +10,7 @@ use alloy_eips::{
BlockHashOrNumber, BlockId, BlockNumberOrTag,
};
use alloy_primitives::{
map::{HashMap, HashSet},
map::{B256HashMap, HashMap},
Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256, U256,
};
use reth_chain_state::{
@ -32,7 +32,8 @@ use reth_storage_api::{
};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
MultiProofTargets, TrieInput,
};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use tokio::sync::{broadcast, watch};
@ -401,7 +402,7 @@ impl StateProofProvider for NoopProvider {
fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
_targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
}
@ -410,7 +411,7 @@ impl StateProofProvider for NoopProvider {
&self,
_input: TrieInput,
_target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
Ok(HashMap::default())
}
}

View File

@ -12,7 +12,7 @@ use alloy_eips::{
BlockHashOrNumber, BlockId, BlockNumberOrTag,
};
use alloy_primitives::{
map::{HashMap, HashSet},
map::{B256HashMap, HashMap},
Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256, U256,
};
use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, MAINNET};
@ -25,7 +25,8 @@ use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
MultiProofTargets, TrieInput,
};
use std::{
marker::PhantomData,
@ -442,7 +443,7 @@ impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N
fn multiproof(
&self,
_input: TrieInput,
_targets: HashMap<B256, HashSet<B256>>,
_targets: MultiProofTargets,
) -> ProviderResult<MultiProof> {
Ok(MultiProof::default())
}
@ -451,7 +452,7 @@ impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N
&self,
_input: TrieInput,
_target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
) -> ProviderResult<B256HashMap<Bytes>> {
Ok(HashMap::default())
}
}

View File

@ -1,12 +1,9 @@
use alloy_primitives::{
map::{HashMap, HashSet},
Address, Bytes, B256,
};
use alloy_primitives::{map::B256HashMap, Address, Bytes, B256};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
updates::{StorageTrieUpdates, TrieUpdates},
AccountProof, HashedPostState, HashedStorage, MultiProof, StorageMultiProof, StorageProof,
TrieInput,
AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StorageMultiProof,
StorageProof, TrieInput,
};
/// A type that can compute the state root of a given post state.
@ -84,7 +81,7 @@ pub trait StateProofProvider: Send + Sync {
fn multiproof(
&self,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> ProviderResult<MultiProof>;
/// Get trie witness for provided state.
@ -92,7 +89,7 @@ pub trait StateProofProvider: Send + Sync {
&self,
input: TrieInput,
target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>>;
) -> ProviderResult<B256HashMap<Bytes>>;
}
/// Trie Writer
@ -114,7 +111,7 @@ pub trait StorageTrieWriter: Send + Sync {
/// Returns the number of entries modified.
fn write_storage_trie_updates(
&self,
storage_tries: &HashMap<B256, StorageTrieUpdates>,
storage_tries: &B256HashMap<StorageTrieUpdates>,
) -> ProviderResult<usize>;
/// Writes storage trie updates for the given hashed address.

View File

@ -92,13 +92,10 @@ mod tests {
assert_eq!(trie_account.code_hash, KECCAK_EMPTY);
// Check that the default Account converts to the same TrieAccount
assert_eq!(Into::<TrieAccount>::into((Account::default(), EMPTY_ROOT_HASH)), trie_account);
assert_eq!(TrieAccount::from((Account::default(), EMPTY_ROOT_HASH)), trie_account);
// Check that the default AccountInfo converts to the same TrieAccount
assert_eq!(
Into::<TrieAccount>::into((AccountInfo::default(), EMPTY_ROOT_HASH)),
trie_account
);
assert_eq!(TrieAccount::from((AccountInfo::default(), EMPTY_ROOT_HASH)), trie_account);
}
#[test]
@ -131,7 +128,7 @@ mod tests {
// Check that the Account converts to the same TrieAccount
assert_eq!(
Into::<TrieAccount>::into((
TrieAccount::from((
Account {
nonce: 10,
balance: U256::from(1000),
@ -144,7 +141,7 @@ mod tests {
// Check that the AccountInfo converts to the same TrieAccount
assert_eq!(
Into::<TrieAccount>::into((
TrieAccount::from((
AccountInfo {
nonce: 10,
balance: U256::from(1000),

View File

@ -1,8 +1,5 @@
use crate::Nibbles;
use alloy_primitives::{
map::{HashMap, HashSet},
B256,
};
use alloy_primitives::map::{B256HashMap, B256HashSet};
use std::sync::Arc;
/// Collection of mutable prefix sets.
@ -12,9 +9,9 @@ pub struct TriePrefixSetsMut {
pub account_prefix_set: PrefixSetMut,
/// A map containing storage changes with the hashed address as key and a set of storage key
/// prefixes as the value.
pub storage_prefix_sets: HashMap<B256, PrefixSetMut>,
pub storage_prefix_sets: B256HashMap<PrefixSetMut>,
/// A set of hashed addresses of destroyed accounts.
pub destroyed_accounts: HashSet<B256>,
pub destroyed_accounts: B256HashSet,
}
impl TriePrefixSetsMut {
@ -50,9 +47,9 @@ pub struct TriePrefixSets {
pub account_prefix_set: PrefixSet,
/// A map containing storage changes with the hashed address as key and a set of storage key
/// prefixes as the value.
pub storage_prefix_sets: HashMap<B256, PrefixSet>,
pub storage_prefix_sets: B256HashMap<PrefixSet>,
/// A set of hashed addresses of destroyed accounts.
pub destroyed_accounts: HashSet<B256>,
pub destroyed_accounts: B256HashSet,
}
/// A container for efficiently storing and checking for the presence of key prefixes.
@ -146,9 +143,9 @@ impl PrefixSetMut {
if self.all {
PrefixSet { index: 0, all: true, keys: Arc::new(Vec::new()) }
} else {
self.keys.sort();
self.keys.sort_unstable();
self.keys.dedup();
// we need to shrink in both the sorted and non-sorted cases because deduping may have
// We need to shrink in both the sorted and non-sorted cases because deduping may have
// occurred either on `freeze`, or during `contains`.
self.keys.shrink_to_fit();
PrefixSet { index: 0, all: false, keys: Arc::new(self.keys) }

View File

@ -4,7 +4,7 @@ use crate::{Nibbles, TrieAccount};
use alloy_consensus::constants::KECCAK_EMPTY;
use alloy_primitives::{
keccak256,
map::{hash_map, HashMap},
map::{hash_map, B256HashMap, B256HashSet, HashMap},
Address, Bytes, B256, U256,
};
use alloy_rlp::{encode_fixed_size, Decodable, EMPTY_STRING_CODE};
@ -16,6 +16,9 @@ use alloy_trie::{
use itertools::Itertools;
use reth_primitives_traits::Account;
/// Proof targets map.
pub type MultiProofTargets = B256HashMap<B256HashSet>;
/// 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.
@ -26,7 +29,7 @@ pub struct MultiProof {
/// The hash masks of the branch nodes in the account proof.
pub branch_node_hash_masks: HashMap<Nibbles, TrieMask>,
/// Storage trie multiproofs.
pub storages: HashMap<B256, StorageMultiProof>,
pub storages: B256HashMap<StorageMultiProof>,
}
impl MultiProof {

View File

@ -1,6 +1,6 @@
use crate::{BranchNodeCompact, HashBuilder, Nibbles};
use alloy_primitives::{
map::{HashMap, HashSet},
map::{B256HashMap, B256HashSet, HashMap, HashSet},
B256,
};
@ -15,7 +15,7 @@ pub struct TrieUpdates {
#[cfg_attr(any(test, feature = "serde"), serde(with = "serde_nibbles_set"))]
pub removed_nodes: HashSet<Nibbles>,
/// Collection of updated storage tries indexed by the hashed address.
pub storage_tries: HashMap<B256, StorageTrieUpdates>,
pub storage_tries: B256HashMap<StorageTrieUpdates>,
}
impl TrieUpdates {
@ -37,7 +37,7 @@ impl TrieUpdates {
}
/// Returns a reference to updated storage tries.
pub const fn storage_tries_ref(&self) -> &HashMap<B256, StorageTrieUpdates> {
pub const fn storage_tries_ref(&self) -> &B256HashMap<StorageTrieUpdates> {
&self.storage_tries
}
@ -84,7 +84,7 @@ impl TrieUpdates {
&mut self,
hash_builder: HashBuilder,
removed_keys: HashSet<Nibbles>,
destroyed_accounts: HashSet<B256>,
destroyed_accounts: B256HashSet,
) {
// Retrieve updated nodes from hash builder.
let (_, updated_nodes) = hash_builder.split();
@ -347,7 +347,7 @@ pub struct TrieUpdatesSorted {
pub removed_nodes: HashSet<Nibbles>,
/// Storage tries storage stored by hashed address of the account
/// the trie belongs to.
pub storage_tries: HashMap<B256, StorageTrieUpdatesSorted>,
pub storage_tries: B256HashMap<StorageTrieUpdatesSorted>,
}
impl TrieUpdatesSorted {
@ -362,7 +362,7 @@ impl TrieUpdatesSorted {
}
/// Returns reference to updated storage tries.
pub const fn storage_tries_ref(&self) -> &HashMap<B256, StorageTrieUpdatesSorted> {
pub const fn storage_tries_ref(&self) -> &B256HashMap<StorageTrieUpdatesSorted> {
&self.storage_tries
}
}
@ -411,10 +411,7 @@ fn exclude_empty_from_pair<V>(
#[cfg(feature = "serde-bincode-compat")]
pub mod serde_bincode_compat {
use crate::{BranchNodeCompact, Nibbles};
use alloy_primitives::{
map::{HashMap, HashSet},
B256,
};
use alloy_primitives::map::{B256HashMap, HashMap, HashSet};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};
use std::borrow::Cow;
@ -438,7 +435,7 @@ pub mod serde_bincode_compat {
pub struct TrieUpdates<'a> {
account_nodes: Cow<'a, HashMap<Nibbles, BranchNodeCompact>>,
removed_nodes: Cow<'a, HashSet<Nibbles>>,
storage_tries: HashMap<B256, StorageTrieUpdates<'a>>,
storage_tries: B256HashMap<StorageTrieUpdates<'a>>,
}
impl<'a> From<&'a super::TrieUpdates> for TrieUpdates<'a> {

View File

@ -1,7 +1,7 @@
use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory};
use alloy_primitives::{
keccak256,
map::{HashMap, HashSet},
map::{B256HashMap, B256HashSet, HashMap},
Address, B256,
};
use reth_db_api::transaction::DbTx;
@ -30,7 +30,7 @@ pub trait DatabaseProof<'a, TX> {
fn overlay_multiproof(
tx: &'a TX,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: B256HashMap<B256HashSet>,
) -> Result<MultiProof, StateProofError>;
}
@ -66,7 +66,7 @@ impl<'a, TX: DbTx> DatabaseProof<'a, TX>
fn overlay_multiproof(
tx: &'a TX,
input: TrieInput,
targets: HashMap<B256, HashSet<B256>>,
targets: B256HashMap<B256HashSet>,
) -> Result<MultiProof, StateProofError> {
let nodes_sorted = input.nodes.into_sorted();
let state_sorted = input.state.into_sorted();

View File

@ -1,5 +1,8 @@
use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, PrefixSetLoader};
use alloy_primitives::{Address, BlockNumber, B256, U256};
use alloy_primitives::{
map::{AddressHashMap, B256HashMap},
Address, BlockNumber, B256, U256,
};
use reth_db::tables;
use reth_db_api::{
cursor::DbCursorRO,
@ -227,7 +230,7 @@ impl<TX: DbTx> DatabaseHashedPostState<TX> for HashedPostState {
}
// Iterate over storage changesets and record value before first occurring storage change.
let mut storages = HashMap::<Address, HashMap<B256, U256>>::default();
let mut storages = AddressHashMap::<B256HashMap<U256>>::default();
let mut storage_changesets_cursor = tx.cursor_read::<tables::StorageChangeSets>()?;
for entry in
storage_changesets_cursor.walk_range(BlockNumberAddress((from, Address::ZERO))..)?

View File

@ -1,5 +1,5 @@
use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory};
use alloy_primitives::{map::HashMap, Bytes, B256};
use alloy_primitives::{map::B256HashMap, Bytes};
use reth_db_api::transaction::DbTx;
use reth_execution_errors::TrieWitnessError;
use reth_trie::{
@ -17,7 +17,7 @@ pub trait DatabaseTrieWitness<'a, TX> {
tx: &'a TX,
input: TrieInput,
target: HashedPostState,
) -> Result<HashMap<B256, Bytes>, TrieWitnessError>;
) -> Result<B256HashMap<Bytes>, TrieWitnessError>;
}
impl<'a, TX: DbTx> DatabaseTrieWitness<'a, TX>
@ -31,7 +31,7 @@ impl<'a, TX: DbTx> DatabaseTrieWitness<'a, TX>
tx: &'a TX,
input: TrieInput,
target: HashedPostState,
) -> Result<HashMap<B256, Bytes>, TrieWitnessError> {
) -> Result<B256HashMap<Bytes>, TrieWitnessError> {
let nodes_sorted = input.nodes.into_sorted();
let state_sorted = input.state.into_sorted();
Self::from_tx(tx)

View File

@ -1,8 +1,5 @@
use crate::{root::ParallelStateRootError, stats::ParallelTrieTracker, StorageRootTargets};
use alloy_primitives::{
map::{HashMap, HashSet},
B256,
};
use alloy_primitives::{map::HashMap, B256};
use alloy_rlp::{BufMut, Encodable};
use itertools::Itertools;
use reth_db::DatabaseError;
@ -18,7 +15,8 @@ use reth_trie::{
proof::StorageProof,
trie_cursor::{InMemoryTrieCursorFactory, TrieCursorFactory},
walker::TrieWalker,
HashBuilder, MultiProof, Nibbles, TrieAccount, TrieInput, TRIE_ACCOUNT_RLP_MAX_SIZE,
HashBuilder, MultiProof, MultiProofTargets, Nibbles, TrieAccount, TrieInput,
TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use reth_trie_common::proof::ProofRetainer;
use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory};
@ -73,7 +71,7 @@ where
/// Generate a state multiproof according to specified targets.
pub fn multiproof(
self,
targets: HashMap<B256, HashSet<B256>>,
targets: MultiProofTargets,
) -> Result<MultiProof, ParallelStateRootError> {
let mut tracker = ParallelTrieTracker::default();
@ -108,8 +106,7 @@ where
storage_root_targets.into_iter().sorted_unstable_by_key(|(address, _)| *address)
{
let view = self.view.clone();
let target_slots: HashSet<B256> =
targets.get(&hashed_address).cloned().unwrap_or_default();
let target_slots = targets.get(&hashed_address).cloned().unwrap_or_default();
let trie_nodes_sorted = trie_nodes_sorted.clone();
let hashed_state_sorted = hashed_state_sorted.clone();
@ -249,7 +246,11 @@ where
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{keccak256, map::DefaultHashBuilder, Address, U256};
use alloy_primitives::{
keccak256,
map::{B256HashSet, DefaultHashBuilder},
Address, U256,
};
use rand::Rng;
use reth_primitives::{Account, StorageEntry};
use reth_provider::{test_utils::create_test_provider_factory, HashingWriter};
@ -300,11 +301,10 @@ mod tests {
provider_rw.commit().unwrap();
}
let mut targets =
HashMap::<B256, HashSet<B256, DefaultHashBuilder>, DefaultHashBuilder>::default();
let mut targets = MultiProofTargets::default();
for (address, (_, storage)) in state.iter().take(10) {
let hashed_address = keccak256(*address);
let mut target_slots = HashSet::<B256, DefaultHashBuilder>::default();
let mut target_slots = B256HashSet::default();
for (slot, _) in storage.iter().take(5) {
target_slots.insert(*slot);

View File

@ -1,11 +1,10 @@
use alloy_primitives::B256;
use alloy_primitives::{map::B256HashMap, B256};
use derive_more::{Deref, DerefMut};
use reth_trie::prefix_set::PrefixSet;
use std::collections::HashMap;
/// Target accounts with corresponding prefix sets for storage root calculation.
#[derive(Deref, DerefMut, Debug)]
pub struct StorageRootTargets(HashMap<B256, PrefixSet>);
pub struct StorageRootTargets(B256HashMap<PrefixSet>);
impl StorageRootTargets {
/// Create new storage root targets from updated post state accounts

View File

@ -1,6 +1,6 @@
#![allow(missing_docs, unreachable_pub)]
use alloy_primitives::{map::HashMap, B256, U256};
use alloy_primitives::{map::B256HashMap, B256, U256};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use itertools::Itertools;
use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner};
@ -193,7 +193,7 @@ pub fn calculate_root_from_leaves_repeated(c: &mut Criterion) {
}
}
fn generate_test_data(size: usize) -> HashMap<B256, U256> {
fn generate_test_data(size: usize) -> B256HashMap<U256> {
let mut runner = TestRunner::new(ProptestConfig::default());
proptest::collection::hash_map(any::<B256>(), any::<U256>(), size)
.new_tree(&mut runner)

View File

@ -11,6 +11,7 @@ pub mod blinded;
/// Re-export sparse trie error types.
pub mod errors {
pub use reth_execution_errors::{
SparseStateTrieError, SparseStateTrieResult, SparseTrieError, SparseTrieResult,
SparseStateTrieError, SparseStateTrieErrorKind, SparseStateTrieResult, SparseTrieError,
SparseTrieErrorKind, SparseTrieResult,
};
}

View File

@ -4,11 +4,13 @@ use crate::{
};
use alloy_primitives::{
hex,
map::{HashMap, HashSet},
map::{B256HashMap, B256HashSet},
Bytes, B256,
};
use alloy_rlp::{Decodable, Encodable};
use reth_execution_errors::{SparseStateTrieError, SparseStateTrieResult, SparseTrieError};
use reth_execution_errors::{
SparseStateTrieErrorKind, SparseStateTrieResult, SparseTrieError, SparseTrieErrorKind,
};
use reth_primitives_traits::Account;
use reth_tracing::tracing::trace;
use reth_trie_common::{
@ -24,9 +26,9 @@ pub struct SparseStateTrie<F: BlindedProviderFactory = DefaultBlindedProviderFac
/// Sparse account trie.
state: SparseTrie<F::AccountNodeProvider>,
/// Sparse storage tries.
storages: HashMap<B256, SparseTrie<F::StorageNodeProvider>>,
storages: B256HashMap<SparseTrie<F::StorageNodeProvider>>,
/// Collection of revealed account and storage keys.
revealed: HashMap<B256, HashSet<B256>>,
revealed: B256HashMap<B256HashSet>,
/// Flag indicating whether trie updates should be retained.
retain_updates: bool,
/// Reusable buffer for RLP encoding of trie accounts.
@ -204,7 +206,7 @@ impl<F: BlindedProviderFactory> SparseStateTrie<F> {
/// NOTE: This method does not extensively validate the proof.
pub fn reveal_multiproof(
&mut self,
targets: HashMap<B256, HashSet<B256>>,
targets: B256HashMap<B256HashSet>,
multiproof: MultiProof,
) -> SparseStateTrieResult<()> {
let account_subtree = multiproof.account_subtree.into_nodes_sorted();
@ -278,13 +280,13 @@ impl<F: BlindedProviderFactory> SparseStateTrie<F> {
// Validate root node.
let Some((path, node)) = proof.next() else { return Ok(None) };
if !path.is_empty() {
return Err(SparseStateTrieError::InvalidRootNode { path, node })
return Err(SparseStateTrieErrorKind::InvalidRootNode { path, node }.into())
}
// Decode root node and perform sanity check.
let root_node = TrieNode::decode(&mut &node[..])?;
if matches!(root_node, TrieNode::EmptyRoot) && proof.peek().is_some() {
return Err(SparseStateTrieError::InvalidRootNode { path, node })
return Err(SparseStateTrieErrorKind::InvalidRootNode { path, node }.into())
}
Ok(Some(root_node))
@ -364,11 +366,9 @@ where
slot: Nibbles,
value: Vec<u8>,
) -> SparseStateTrieResult<()> {
if let Some(storage_trie) = self.storages.get_mut(&address) {
Ok(storage_trie.update_leaf(slot, value)?)
} else {
Err(SparseStateTrieError::Sparse(SparseTrieError::Blind))
}
let storage_trie = self.storages.get_mut(&address).ok_or(SparseTrieErrorKind::Blind)?;
storage_trie.update_leaf(slot, value)?;
Ok(())
}
/// Update or remove trie account based on new account info. This method will either recompute
@ -379,10 +379,10 @@ where
let nibbles = Nibbles::unpack(address);
let storage_root = if let Some(storage_trie) = self.storages.get_mut(&address) {
trace!(target: "trie::sparse", ?address, "Calculating storage root to update account");
storage_trie.root().ok_or(SparseTrieError::Blind)?
storage_trie.root().ok_or(SparseTrieErrorKind::Blind)?
} else if self.revealed.contains_key(&address) {
trace!(target: "trie::sparse", ?address, "Retrieving storage root from account leaf to update account");
let state = self.state.as_revealed_mut().ok_or(SparseTrieError::Blind)?;
let state = self.state.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
// The account was revealed, either...
if let Some(value) = state.get_leaf_value(&nibbles) {
// ..it exists and we should take it's current storage root or...
@ -392,7 +392,7 @@ where
EMPTY_ROOT_HASH
}
} else {
return Err(SparseTrieError::Blind.into())
return Err(SparseTrieErrorKind::Blind.into())
};
if account.is_empty() && storage_root == EMPTY_ROOT_HASH {
@ -418,18 +418,20 @@ where
address: B256,
slot: &Nibbles,
) -> SparseStateTrieResult<()> {
if let Some(storage_trie) = self.storages.get_mut(&address) {
Ok(storage_trie.remove_leaf(slot)?)
} else {
Err(SparseStateTrieError::Sparse(SparseTrieError::Blind))
}
let storage_trie = self.storages.get_mut(&address).ok_or(SparseTrieErrorKind::Blind)?;
storage_trie.remove_leaf(slot)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{b256, Bytes, U256};
use alloy_primitives::{
b256,
map::{HashMap, HashSet},
Bytes, U256,
};
use alloy_rlp::EMPTY_STRING_CODE;
use arbitrary::Arbitrary;
use assert_matches::assert_matches;
@ -443,8 +445,8 @@ mod tests {
let sparse = SparseStateTrie::default();
let proof = [(Nibbles::from_nibbles([0x1]), Bytes::from([EMPTY_STRING_CODE]))];
assert_matches!(
sparse.validate_root_node(&mut proof.into_iter().peekable(),),
Err(SparseStateTrieError::InvalidRootNode { .. })
sparse.validate_root_node(&mut proof.into_iter().peekable()).map_err(|e| e.into_kind()),
Err(SparseStateTrieErrorKind::InvalidRootNode { .. })
);
}
@ -456,8 +458,8 @@ mod tests {
(Nibbles::from_nibbles([0x1]), Bytes::new()),
];
assert_matches!(
sparse.validate_root_node(&mut proof.into_iter().peekable(),),
Err(SparseStateTrieError::InvalidRootNode { .. })
sparse.validate_root_node(&mut proof.into_iter().peekable()).map_err(|e| e.into_kind()),
Err(SparseStateTrieErrorKind::InvalidRootNode { .. })
);
}

View File

@ -5,7 +5,7 @@ use alloy_primitives::{
B256,
};
use alloy_rlp::Decodable;
use reth_execution_errors::{SparseTrieError, SparseTrieResult};
use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind, SparseTrieResult};
use reth_tracing::tracing::trace;
use reth_trie_common::{
prefix_set::{PrefixSet, PrefixSetMut},
@ -106,7 +106,7 @@ impl<P> SparseTrie<P> {
/// Wipe the trie, removing all values and nodes, and replacing the root with an empty node.
pub fn wipe(&mut self) -> SparseTrieResult<()> {
let revealed = self.as_revealed_mut().ok_or(SparseTrieError::Blind)?;
let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
revealed.wipe();
Ok(())
}
@ -129,14 +129,14 @@ where
{
/// Update the leaf node.
pub fn update_leaf(&mut self, path: Nibbles, value: Vec<u8>) -> SparseTrieResult<()> {
let revealed = self.as_revealed_mut().ok_or(SparseTrieError::Blind)?;
let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
revealed.update_leaf(path, value)?;
Ok(())
}
/// Remove the leaf node.
pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> {
let revealed = self.as_revealed_mut().ok_or(SparseTrieError::Blind)?;
let revealed = self.as_revealed_mut().ok_or(SparseTrieErrorKind::Blind)?;
revealed.remove_leaf(path)?;
Ok(())
}
@ -313,10 +313,11 @@ impl<P> RevealedSparseTrie<P> {
SparseNode::Branch { .. } | SparseNode::Extension { .. } => {}
// All other node types can't be handled.
node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
return Err(SparseTrieError::Reveal {
return Err(SparseTrieErrorKind::Reveal {
path: entry.key().clone(),
node: Box::new(node.clone()),
})
}
.into())
}
},
Entry::Vacant(entry) => {
@ -337,10 +338,11 @@ impl<P> RevealedSparseTrie<P> {
SparseNode::Extension { .. } | SparseNode::Branch { .. } => {}
// All other node types can't be handled.
node @ (SparseNode::Empty | SparseNode::Leaf { .. }) => {
return Err(SparseTrieError::Reveal {
return Err(SparseTrieErrorKind::Reveal {
path: entry.key().clone(),
node: Box::new(node.clone()),
})
}
.into())
}
},
Entry::Vacant(entry) => {
@ -364,10 +366,11 @@ impl<P> RevealedSparseTrie<P> {
node @ (SparseNode::Empty |
SparseNode::Extension { .. } |
SparseNode::Branch { .. }) => {
return Err(SparseTrieError::Reveal {
return Err(SparseTrieErrorKind::Reveal {
path: entry.key().clone(),
node: Box::new(node.clone()),
})
}
.into())
}
},
Entry::Vacant(entry) => {
@ -389,10 +392,11 @@ impl<P> RevealedSparseTrie<P> {
Entry::Occupied(entry) => match entry.get() {
// Hash node with a different hash can't be handled.
SparseNode::Hash(previous_hash) if previous_hash != &hash => {
return Err(SparseTrieError::Reveal {
return Err(SparseTrieErrorKind::Reveal {
path: entry.key().clone(),
node: Box::new(SparseNode::Hash(hash)),
})
}
.into())
}
_ => {}
},
@ -413,9 +417,9 @@ impl<P> RevealedSparseTrie<P> {
while let Some(node) = self.nodes.remove(&current) {
match &node {
SparseNode::Empty => return Err(SparseTrieError::Blind),
SparseNode::Hash(hash) => {
return Err(SparseTrieError::BlindedNode { path: current, hash: *hash })
SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
&SparseNode::Hash(hash) => {
return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
}
SparseNode::Leaf { key: _key, .. } => {
// Leaf node is always the one that we're deleting, and no other leaf nodes can
@ -603,13 +607,13 @@ impl<P> RevealedSparseTrie<P> {
}
SparseNode::Hash(hash) => (RlpNode::word_rlp(hash), false, SparseNodeType::Hash),
SparseNode::Leaf { key, hash } => {
self.rlp_buf.clear();
let mut path = path.clone();
path.extend_from_slice_unchecked(key);
if let Some(hash) = hash.filter(|_| !prefix_set_contains(&path)) {
(RlpNode::word_rlp(&hash), false, SparseNodeType::Leaf)
} else {
let value = self.values.get(&path).unwrap();
self.rlp_buf.clear();
let rlp_node = LeafNodeRef { key, value }.rlp(&mut self.rlp_buf);
*hash = rlp_node.as_hash();
(rlp_node, true, SparseNodeType::Leaf)
@ -825,8 +829,8 @@ where
*node = SparseNode::new_leaf(path);
break
}
SparseNode::Hash(hash) => {
return Err(SparseTrieError::BlindedNode { path: current, hash: *hash })
&mut SparseNode::Hash(hash) => {
return Err(SparseTrieErrorKind::BlindedNode { path: current, hash }.into())
}
SparseNode::Leaf { key: current_key, .. } => {
current.extend_from_slice_unchecked(current_key);
@ -844,6 +848,7 @@ where
*node = SparseNode::new_ext(new_ext_key);
// create a branch node and corresponding leaves
self.nodes.reserve(3);
self.nodes.insert(
current.slice(..common),
SparseNode::new_split_branch(current[common], path[common]),
@ -887,6 +892,7 @@ where
// create state mask for new branch node
// NOTE: this might overwrite the current extension node
self.nodes.reserve(3);
let branch = SparseNode::new_split_branch(current[common], path[common]);
self.nodes.insert(current.slice(..common), branch);
@ -922,9 +928,9 @@ where
/// Remove leaf node from the trie.
pub fn remove_leaf(&mut self, path: &Nibbles) -> SparseTrieResult<()> {
if self.values.remove(path).is_none() {
if let Some(SparseNode::Hash(hash)) = self.nodes.get(path) {
if let Some(&SparseNode::Hash(hash)) = self.nodes.get(path) {
// Leaf is present in the trie, but it's blinded.
return Err(SparseTrieError::BlindedNode { path: path.clone(), hash: *hash })
return Err(SparseTrieErrorKind::BlindedNode { path: path.clone(), hash }.into())
}
// Leaf is not present in the trie.
@ -962,9 +968,9 @@ where
let removed_path = removed_node.path;
let new_node = match &removed_node.node {
SparseNode::Empty => return Err(SparseTrieError::Blind),
SparseNode::Hash(hash) => {
return Err(SparseTrieError::BlindedNode { path: removed_path, hash: *hash })
SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
&SparseNode::Hash(hash) => {
return Err(SparseTrieErrorKind::BlindedNode { path: removed_path, hash }.into())
}
SparseNode::Leaf { .. } => {
unreachable!("we already popped the leaf node")
@ -973,12 +979,11 @@ where
// If the node is an extension node, we need to look at its child to see if we
// need to merge them.
match &child.node {
SparseNode::Empty => return Err(SparseTrieError::Blind),
SparseNode::Hash(hash) => {
return Err(SparseTrieError::BlindedNode {
path: child.path,
hash: *hash,
})
SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
&SparseNode::Hash(hash) => {
return Err(
SparseTrieErrorKind::BlindedNode { path: child.path, hash }.into()
)
}
// For a leaf node, we collapse the extension node into a leaf node,
// extending the key. While it's impossible to encounter an extension node
@ -1041,12 +1046,13 @@ where
let mut delete_child = false;
let new_node = match child {
SparseNode::Empty => return Err(SparseTrieError::Blind),
SparseNode::Hash(hash) => {
return Err(SparseTrieError::BlindedNode {
SparseNode::Empty => return Err(SparseTrieErrorKind::Blind.into()),
&SparseNode::Hash(hash) => {
return Err(SparseTrieErrorKind::BlindedNode {
path: child_path,
hash: *hash,
})
hash,
}
.into())
}
// If the only child is a leaf node, we downgrade the branch node into a
// leaf node, prepending the nibble to the key, and delete the old
@ -1273,7 +1279,10 @@ impl SparseTrieUpdates {
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{map::HashSet, U256};
use alloy_primitives::{
map::{B256HashSet, HashSet},
U256,
};
use alloy_rlp::Encodable;
use assert_matches::assert_matches;
use itertools::Itertools;
@ -1316,7 +1325,7 @@ mod tests {
/// Returns the state root and the retained proof nodes.
fn run_hash_builder(
state: impl IntoIterator<Item = (Nibbles, Account)> + Clone,
destroyed_accounts: HashSet<B256>,
destroyed_accounts: B256HashSet,
proof_targets: impl IntoIterator<Item = Nibbles>,
) -> (B256, TrieUpdates, ProofNodes, HashMap<Nibbles, TrieMask>) {
let mut account_rlp = Vec::new();
@ -1866,8 +1875,8 @@ mod tests {
// Removing a blinded leaf should result in an error
assert_matches!(
sparse.remove_leaf(&Nibbles::from_nibbles([0x0])),
Err(SparseTrieError::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
sparse.remove_leaf(&Nibbles::from_nibbles([0x0])).map_err(|e| e.into_kind()),
Err(SparseTrieErrorKind::BlindedNode { path, hash }) if path == Nibbles::from_nibbles([0x0]) && hash == B256::repeat_byte(1)
);
}

View File

@ -3,7 +3,7 @@ use crate::{
forward_cursor::ForwardInMemoryCursor, HashedAccountsSorted, HashedPostStateSorted,
HashedStorageSorted,
};
use alloy_primitives::{map::HashSet, B256, U256};
use alloy_primitives::{map::B256HashSet, B256, U256};
use reth_primitives::Account;
use reth_storage_errors::db::DatabaseError;
@ -48,7 +48,7 @@ pub struct HashedPostStateAccountCursor<'a, C> {
/// Forward-only in-memory cursor over accounts.
post_state_cursor: ForwardInMemoryCursor<'a, B256, Account>,
/// Reference to the collection of account keys that were destroyed.
destroyed_accounts: &'a HashSet<B256>,
destroyed_accounts: &'a B256HashSet,
/// The last hashed account that was returned by the cursor.
/// De facto, this is a current cursor position.
last_account: Option<B256>,
@ -182,7 +182,7 @@ pub struct HashedPostStateStorageCursor<'a, C> {
/// Forward-only in-memory cursor over non zero-valued account storage slots.
post_state_cursor: Option<ForwardInMemoryCursor<'a, B256, U256>>,
/// Reference to the collection of storage slot keys that were cleared.
cleared_slots: Option<&'a HashSet<B256>>,
cleared_slots: Option<&'a B256HashSet>,
/// Flag indicating whether database storage was wiped.
storage_wiped: bool,
/// The last slot that has been returned by the cursor.

View File

@ -4,7 +4,7 @@ use alloy_primitives::{
map::{HashMap, HashSet},
Bytes, B256,
};
use reth_execution_errors::SparseTrieError;
use reth_execution_errors::{SparseTrieError, SparseTrieErrorKind};
use reth_trie_common::{prefix_set::TriePrefixSetsMut, Nibbles};
use reth_trie_sparse::blinded::{pad_path_to_key, BlindedProvider, BlindedProviderFactory};
use std::sync::Arc;
@ -92,7 +92,7 @@ where
Proof::new(self.trie_cursor_factory.clone(), self.hashed_cursor_factory.clone())
.with_prefix_sets_mut(self.prefix_sets.as_ref().clone())
.multiproof(targets)
.map_err(|error| SparseTrieError::Other(Box::new(error)))?;
.map_err(|error| SparseTrieErrorKind::Other(Box::new(error)))?;
Ok(proof.account_subtree.into_inner().remove(&path))
}
@ -141,7 +141,7 @@ where
)
.with_prefix_set_mut(storage_prefix_set)
.storage_multiproof(targets)
.map_err(|error| SparseTrieError::Other(Box::new(error)))?;
.map_err(|error| SparseTrieErrorKind::Other(Box::new(error)))?;
Ok(proof.subtree.into_inner().remove(&path))
}

View File

@ -8,7 +8,7 @@ use crate::{
};
use alloy_primitives::{
keccak256,
map::{HashMap, HashSet},
map::{B256HashMap, B256HashSet, HashMap, HashSet},
Address, B256,
};
use alloy_rlp::{BufMut, Encodable};
@ -103,7 +103,7 @@ where
/// Generate a state multiproof according to specified targets.
pub fn multiproof(
mut self,
mut targets: HashMap<B256, HashSet<B256>>,
mut targets: B256HashMap<B256HashSet>,
) -> Result<MultiProof, StateProofError> {
let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;
let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
@ -121,7 +121,7 @@ where
// Initialize all storage multiproofs as empty.
// Storage multiproofs for non empty tries will be overwritten if necessary.
let mut storages: HashMap<_, _> =
let mut storages: B256HashMap<_> =
targets.keys().map(|key| (*key, StorageMultiProof::empty())).collect();
let mut account_rlp = Vec::with_capacity(TRIE_ACCOUNT_RLP_MAX_SIZE);
let mut account_node_iter = TrieNodeIter::new(walker, hashed_account_cursor);
@ -263,7 +263,7 @@ where
/// Generate storage proof.
pub fn storage_multiproof(
mut self,
targets: HashSet<B256>,
targets: B256HashSet,
) -> Result<StorageMultiProof, StateProofError> {
let mut hashed_storage_cursor =
self.hashed_cursor_factory.hashed_storage_cursor(self.hashed_address)?;

View File

@ -4,7 +4,7 @@ use crate::{
};
use alloy_primitives::{
keccak256,
map::{hash_map, HashMap, HashSet},
map::{hash_map, B256HashMap, B256HashSet, HashMap, HashSet},
Address, B256, U256,
};
use itertools::Itertools;
@ -18,9 +18,9 @@ use std::borrow::Cow;
#[derive(PartialEq, Eq, Clone, Default, Debug)]
pub struct HashedPostState {
/// Mapping of hashed address to account info, `None` if destroyed.
pub accounts: HashMap<B256, Option<Account>>,
pub accounts: B256HashMap<Option<Account>>,
/// Mapping of hashed address to hashed storage.
pub storages: HashMap<B256, HashedStorage>,
pub storages: B256HashMap<HashedStorage>,
}
impl HashedPostState {
@ -210,7 +210,7 @@ pub struct HashedStorage {
/// Flag indicating whether the storage was wiped or not.
pub wiped: bool,
/// Mapping of hashed storage slot to storage value.
pub storage: HashMap<B256, U256>,
pub storage: B256HashMap<U256>,
}
impl HashedStorage {
@ -281,14 +281,14 @@ pub struct HashedPostStateSorted {
/// Updated state of accounts.
pub(crate) accounts: HashedAccountsSorted,
/// Map of hashed addresses to hashed storage.
pub(crate) storages: HashMap<B256, HashedStorageSorted>,
pub(crate) storages: B256HashMap<HashedStorageSorted>,
}
impl HashedPostStateSorted {
/// Create new instance of [`HashedPostStateSorted`]
pub const fn new(
accounts: HashedAccountsSorted,
storages: HashMap<B256, HashedStorageSorted>,
storages: B256HashMap<HashedStorageSorted>,
) -> Self {
Self { accounts, storages }
}
@ -299,7 +299,7 @@ impl HashedPostStateSorted {
}
/// Returns reference to hashed account storages.
pub const fn account_storages(&self) -> &HashMap<B256, HashedStorageSorted> {
pub const fn account_storages(&self) -> &B256HashMap<HashedStorageSorted> {
&self.storages
}
}
@ -310,7 +310,7 @@ pub struct HashedAccountsSorted {
/// Sorted collection of hashed addresses and their account info.
pub(crate) accounts: Vec<(B256, Account)>,
/// Set of destroyed account keys.
pub(crate) destroyed_accounts: HashSet<B256>,
pub(crate) destroyed_accounts: B256HashSet,
}
impl HashedAccountsSorted {
@ -330,7 +330,7 @@ pub struct HashedStorageSorted {
/// Sorted hashed storage slots with non-zero value.
pub(crate) non_zero_valued_slots: Vec<(B256, U256)>,
/// Slots that have been zero valued.
pub(crate) zero_valued_slots: HashSet<B256>,
pub(crate) zero_valued_slots: B256HashSet,
/// Flag indicating whether the storage was wiped or not.
pub(crate) wiped: bool,
}

View File

@ -7,12 +7,13 @@ use crate::{
};
use alloy_primitives::{
keccak256,
map::{Entry, HashMap, HashSet},
map::{B256HashMap, B256HashSet, Entry, HashMap},
Bytes, B256,
};
use itertools::Itertools;
use reth_execution_errors::{
SparseStateTrieError, SparseTrieError, StateProofError, TrieWitnessError,
SparseStateTrieError, SparseStateTrieErrorKind, SparseTrieError, SparseTrieErrorKind,
StateProofError, TrieWitnessError,
};
use reth_trie_common::Nibbles;
use reth_trie_sparse::{
@ -31,7 +32,7 @@ pub struct TrieWitness<T, H> {
/// A set of prefix sets that have changes.
prefix_sets: TriePrefixSetsMut,
/// Recorded witness.
witness: HashMap<B256, Bytes>,
witness: B256HashMap<Bytes>,
}
impl<T, H> TrieWitness<T, H> {
@ -86,7 +87,7 @@ where
pub fn compute(
mut self,
state: HashedPostState,
) -> Result<HashMap<B256, Bytes>, TrieWitnessError> {
) -> Result<B256HashMap<Bytes>, TrieWitnessError> {
if state.is_empty() {
return Ok(self.witness)
}
@ -127,7 +128,7 @@ where
let storage = state.storages.get(&hashed_address);
let storage_trie = sparse_trie
.storage_trie_mut(&hashed_address)
.ok_or(SparseStateTrieError::Sparse(SparseTrieError::Blind))?;
.ok_or(SparseStateTrieErrorKind::Sparse(SparseTrieErrorKind::Blind))?;
for hashed_slot in hashed_slots.into_iter().sorted_unstable() {
let storage_nibbles = Nibbles::unpack(hashed_slot);
let maybe_leaf_value = storage
@ -138,11 +139,11 @@ where
if let Some(value) = maybe_leaf_value {
storage_trie
.update_leaf(storage_nibbles, value)
.map_err(SparseStateTrieError::Sparse)?;
.map_err(SparseStateTrieError::from)?;
} else {
storage_trie
.remove_leaf(&storage_nibbles)
.map_err(SparseStateTrieError::Sparse)?;
.map_err(SparseStateTrieError::from)?;
}
}
@ -170,13 +171,13 @@ where
fn get_proof_targets(
&self,
state: &HashedPostState,
) -> Result<HashMap<B256, HashSet<B256>>, StateProofError> {
let mut proof_targets = HashMap::default();
) -> Result<B256HashMap<B256HashSet>, StateProofError> {
let mut proof_targets = B256HashMap::default();
for hashed_address in state.accounts.keys() {
proof_targets.insert(*hashed_address, HashSet::default());
proof_targets.insert(*hashed_address, B256HashSet::default());
}
for (hashed_address, storage) in &state.storages {
let mut storage_keys = storage.storage.keys().copied().collect::<HashSet<_>>();
let mut storage_keys = storage.storage.keys().copied().collect::<B256HashSet>();
if storage.wiped {
// storage for this account was destroyed, gather all slots from the current state
let mut storage_cursor =
@ -251,7 +252,9 @@ where
fn blinded_node(&mut self, path: Nibbles) -> Result<Option<Bytes>, Self::Error> {
let maybe_node = self.provider.blinded_node(path)?;
if let Some(node) = &maybe_node {
self.tx.send(node.clone()).map_err(|error| SparseTrieError::Other(Box::new(error)))?;
self.tx
.send(node.clone())
.map_err(|error| SparseTrieErrorKind::Other(Box::new(error)))?;
}
Ok(maybe_node)
}