refactor(trie): prefix sets (#6502)

This commit is contained in:
Roman Krasiuk
2024-02-09 13:33:04 +01:00
committed by GitHub
parent 20e59153d9
commit 84efe14063
6 changed files with 133 additions and 157 deletions

View File

@@ -1662,12 +1662,9 @@ mod tests {
);
let provider = tree.externals.provider_factory.provider().unwrap();
let (acc_prefix_set, storage_prefix_set) = exec5.hash_state_slow().construct_prefix_sets();
let state_root = StateRoot::from_tx(provider.tx_ref())
.with_changed_account_prefixes(acc_prefix_set)
.with_changed_storage_prefixes(storage_prefix_set)
.root()
.unwrap();
let prefix_sets = exec5.hash_state_slow().construct_prefix_sets();
let state_root =
StateRoot::from_tx(provider.tx_ref()).with_prefix_sets(prefix_sets).root().unwrap();
assert_eq!(state_root, block5.state_root);
}

View File

@@ -42,7 +42,11 @@ use reth_primitives::{
StorageEntry, TransactionMeta, TransactionSigned, TransactionSignedEcRecovered,
TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256,
};
use reth_trie::{prefix_set::PrefixSetMut, updates::TrieUpdates, HashedPostState, StateRoot};
use reth_trie::{
prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets},
updates::TrieUpdates,
HashedPostState, StateRoot,
};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg, SpecId};
use std::{
collections::{hash_map, BTreeMap, BTreeSet, HashMap, HashSet},
@@ -2081,7 +2085,7 @@ impl<TX: DbTxMut + DbTx> HashingWriter for DatabaseProvider<TX> {
) -> ProviderResult<()> {
// Initialize prefix sets.
let mut account_prefix_set = PrefixSetMut::default();
let mut storage_prefix_set: HashMap<B256, PrefixSetMut> = HashMap::default();
let mut storage_prefix_sets: HashMap<B256, PrefixSetMut> = HashMap::default();
let mut destroyed_accounts = HashSet::default();
let mut durations_recorder = metrics::DurationsRecorder::default();
@@ -2094,7 +2098,7 @@ impl<TX: DbTxMut + DbTx> HashingWriter for DatabaseProvider<TX> {
for (hashed_address, hashed_slots) in storage_entries {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
for slot in hashed_slots {
storage_prefix_set
storage_prefix_sets
.entry(hashed_address)
.or_default()
.insert(Nibbles::unpack(slot));
@@ -2121,12 +2125,16 @@ impl<TX: DbTxMut + DbTx> HashingWriter for DatabaseProvider<TX> {
{
// This is the same as `StateRoot::incremental_root_with_updates`, only the prefix sets
// are pre-loaded.
let prefix_sets = TriePrefixSets {
account_prefix_set: account_prefix_set.freeze(),
storage_prefix_sets: storage_prefix_sets
.into_iter()
.map(|(k, v)| (k, v.freeze()))
.collect(),
destroyed_accounts,
};
let (state_root, trie_updates) = StateRoot::from_tx(&self.tx)
.with_changed_account_prefixes(account_prefix_set.freeze())
.with_changed_storage_prefixes(
storage_prefix_set.into_iter().map(|(k, v)| (k, v.freeze())).collect(),
)
.with_destroyed_accounts(destroyed_accounts)
.with_prefix_sets(prefix_sets)
.root_with_updates()
.map_err(Into::<reth_db::DatabaseError>::into)?;
if state_root != expected_state_root {
@@ -2269,13 +2277,10 @@ impl<TX: DbTxMut + DbTx> BlockExecutionWriter for DatabaseProvider<TX> {
if TAKE {
let storage_range = BlockNumberAddress::range(range.clone());
// Initialize prefix sets.
let mut account_prefix_set = PrefixSetMut::default();
let mut storage_prefix_set: HashMap<B256, PrefixSetMut> = HashMap::default();
let mut destroyed_accounts = HashSet::default();
// Unwind account hashes. Add changed accounts to account prefix set.
let hashed_addresses = self.unwind_account_hashing(range.clone())?;
let mut account_prefix_set = PrefixSetMut::with_capacity(hashed_addresses.len());
let mut destroyed_accounts = HashSet::default();
for (hashed_address, account) in hashed_addresses {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
if account.is_none() {
@@ -2288,15 +2293,15 @@ impl<TX: DbTxMut + DbTx> BlockExecutionWriter for 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 storage_entries = self.unwind_storage_hashing(storage_range.clone())?;
for (hashed_address, hashed_slots) in storage_entries {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
let mut storage_prefix_set = PrefixSetMut::with_capacity(hashed_slots.len());
for slot in hashed_slots {
storage_prefix_set
.entry(hashed_address)
.or_default()
.insert(Nibbles::unpack(slot));
storage_prefix_set.insert(Nibbles::unpack(slot));
}
storage_prefix_sets.insert(hashed_address, storage_prefix_set.freeze());
}
// Unwind storage history indices.
@@ -2305,12 +2310,13 @@ impl<TX: DbTxMut + DbTx> BlockExecutionWriter for DatabaseProvider<TX> {
// Calculate the reverted merkle root.
// This is the same as `StateRoot::incremental_root_with_updates`, only the prefix sets
// are pre-loaded.
let prefix_sets = TriePrefixSets {
account_prefix_set: account_prefix_set.freeze(),
storage_prefix_sets,
destroyed_accounts,
};
let (new_state_root, trie_updates) = StateRoot::from_tx(&self.tx)
.with_changed_account_prefixes(account_prefix_set.freeze())
.with_changed_storage_prefixes(
storage_prefix_set.into_iter().map(|(k, v)| (k, v.freeze())).collect(),
)
.with_destroyed_accounts(destroyed_accounts)
.with_prefix_sets(prefix_sets)
.root_with_updates()
.map_err(Into::<reth_db::DatabaseError>::into)?;

View File

@@ -1,4 +1,4 @@
use super::PrefixSetMut;
use super::{PrefixSetMut, TriePrefixSets};
use derive_more::Deref;
use reth_db::{
cursor::DbCursorRO,
@@ -13,19 +13,8 @@ use std::{
ops::RangeInclusive,
};
/// Loaded prefix sets.
#[derive(Debug, Default)]
pub struct LoadedPrefixSets {
/// The account prefix set
pub account_prefix_set: PrefixSetMut,
/// The mapping of hashed account key to the corresponding storage prefix set
pub storage_prefix_sets: HashMap<B256, PrefixSetMut>,
/// The account keys of destroyed accounts
pub destroyed_accounts: HashSet<B256>,
}
/// A wrapper around a database transaction that loads prefix sets within a given block range.
#[derive(Debug, Deref)]
#[derive(Deref, Debug)]
pub struct PrefixSetLoader<'a, TX>(&'a TX);
impl<'a, TX> PrefixSetLoader<'a, TX> {
@@ -37,12 +26,11 @@ impl<'a, TX> PrefixSetLoader<'a, TX> {
impl<'a, TX: DbTx> PrefixSetLoader<'a, TX> {
/// Load all account and storage changes for the given block range.
pub fn load(
self,
range: RangeInclusive<BlockNumber>,
) -> Result<LoadedPrefixSets, DatabaseError> {
pub fn load(self, range: RangeInclusive<BlockNumber>) -> Result<TriePrefixSets, DatabaseError> {
// Initialize prefix sets.
let mut loaded_prefix_sets = LoadedPrefixSets::default();
let mut account_prefix_set = PrefixSetMut::default();
let mut storage_prefix_sets = HashMap::<B256, PrefixSetMut>::default();
let mut destroyed_accounts = HashSet::default();
// Walk account changeset and insert account prefixes.
let mut account_changeset_cursor = self.cursor_read::<tables::AccountChangeSet>()?;
@@ -50,10 +38,10 @@ impl<'a, TX: DbTx> PrefixSetLoader<'a, TX> {
for account_entry in account_changeset_cursor.walk_range(range.clone())? {
let (_, AccountBeforeTx { address, .. }) = account_entry?;
let hashed_address = keccak256(address);
loaded_prefix_sets.account_prefix_set.insert(Nibbles::unpack(hashed_address));
account_prefix_set.insert(Nibbles::unpack(hashed_address));
if account_plain_state_cursor.seek_exact(address)?.is_none() {
loaded_prefix_sets.destroyed_accounts.insert(hashed_address);
destroyed_accounts.insert(hashed_address);
}
}
@@ -64,14 +52,20 @@ impl<'a, TX: DbTx> PrefixSetLoader<'a, TX> {
for storage_entry in storage_cursor.walk_range(storage_range)? {
let (BlockNumberAddress((_, address)), StorageEntry { key, .. }) = storage_entry?;
let hashed_address = keccak256(address);
loaded_prefix_sets.account_prefix_set.insert(Nibbles::unpack(hashed_address));
loaded_prefix_sets
.storage_prefix_sets
account_prefix_set.insert(Nibbles::unpack(hashed_address));
storage_prefix_sets
.entry(hashed_address)
.or_default()
.insert(Nibbles::unpack(keccak256(key)));
}
Ok(loaded_prefix_sets)
Ok(TriePrefixSets {
account_prefix_set: account_prefix_set.freeze(),
storage_prefix_sets: storage_prefix_sets
.into_iter()
.map(|(k, v)| (k, v.freeze()))
.collect(),
destroyed_accounts,
})
}
}

View File

@@ -1,8 +1,23 @@
use reth_primitives::trie::Nibbles;
use std::rc::Rc;
use reth_primitives::{trie::Nibbles, B256};
use std::{
collections::{HashMap, HashSet},
rc::Rc,
};
mod loader;
pub use loader::{LoadedPrefixSets, PrefixSetLoader};
pub use loader::PrefixSetLoader;
/// Collection of trie prefix sets.
#[derive(Default, Debug)]
pub struct TriePrefixSets {
/// A set of account prefixes that have changed.
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>,
/// A set of hashed addresses of destroyed accounts.
pub destroyed_accounts: HashSet<B256>,
}
/// A container for efficiently storing and checking for the presence of key prefixes.
///

View File

@@ -1,6 +1,6 @@
use crate::{
hashed_cursor::HashedPostStateCursorFactory,
prefix_set::{PrefixSet, PrefixSetMut},
prefix_set::{PrefixSetMut, TriePrefixSets},
updates::TrieUpdates,
StateRoot, StateRootError,
};
@@ -163,14 +163,19 @@ impl HashedPostState {
HashedPostStateSorted { accounts, destroyed_accounts, storages }
}
/// Construct [PrefixSet] from hashed post state.
/// Construct [TriePrefixSets] from hashed post state.
/// The prefix sets contain the hashed account and storage keys that have been changed in the
/// post state.
pub fn construct_prefix_sets(&self) -> (PrefixSet, HashMap<B256, PrefixSet>) {
pub fn construct_prefix_sets(&self) -> TriePrefixSets {
// Populate account prefix set.
let mut account_prefix_set = PrefixSetMut::with_capacity(self.accounts.len());
for hashed_address in self.accounts.keys() {
let mut destroyed_accounts = HashSet::default();
for (hashed_address, account) in &self.accounts {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
if account.is_none() {
destroyed_accounts.insert(*hashed_address);
}
}
// Populate storage prefix sets.
@@ -185,7 +190,11 @@ impl HashedPostState {
storage_prefix_sets.insert(*hashed_address, prefix_set.freeze());
}
(account_prefix_set.freeze(), storage_prefix_sets)
TriePrefixSets {
account_prefix_set: account_prefix_set.freeze(),
storage_prefix_sets,
destroyed_accounts,
}
}
/// Calculate the state root for this [HashedPostState].
@@ -219,11 +228,10 @@ impl HashedPostState {
/// The state root for this [HashedPostState].
pub fn state_root<TX: DbTx>(&self, tx: &TX) -> Result<B256, StateRootError> {
let sorted = self.clone().into_sorted();
let (account_prefix_set, storage_prefix_set) = self.construct_prefix_sets();
sorted
.state_root_calculator(tx)
.with_changed_account_prefixes(account_prefix_set)
.with_changed_storage_prefixes(storage_prefix_set)
let prefix_sets = self.construct_prefix_sets();
StateRoot::from_tx(tx)
.with_hashed_cursor_factory(HashedPostStateCursorFactory::new(tx, &sorted))
.with_prefix_sets(prefix_sets)
.root()
}
@@ -234,11 +242,10 @@ impl HashedPostState {
tx: &TX,
) -> Result<(B256, TrieUpdates), StateRootError> {
let sorted = self.clone().into_sorted();
let (account_prefix_set, storage_prefix_set) = self.construct_prefix_sets();
sorted
.state_root_calculator(tx)
.with_changed_account_prefixes(account_prefix_set)
.with_changed_storage_prefixes(storage_prefix_set)
let prefix_sets = self.construct_prefix_sets();
StateRoot::from_tx(tx)
.with_hashed_cursor_factory(HashedPostStateCursorFactory::new(tx, &sorted))
.with_prefix_sets(prefix_sets)
.root_with_updates()
}
}
@@ -303,24 +310,6 @@ pub struct HashedPostStateSorted {
pub(crate) storages: HashMap<B256, HashedStorageSorted>,
}
impl HashedPostStateSorted {
/// Returns all destroyed accounts.
pub fn destroyed_accounts(&self) -> HashSet<B256> {
self.destroyed_accounts.clone()
}
/// Returns [StateRoot] calculator based on database and in-memory state.
fn state_root_calculator<'a, TX: DbTx>(
&self,
tx: &'a TX,
) -> StateRoot<&'a TX, HashedPostStateCursorFactory<'_, &'a TX>> {
let hashed_cursor_factory = HashedPostStateCursorFactory::new(tx, self);
StateRoot::from_tx(tx)
.with_hashed_cursor_factory(hashed_cursor_factory)
.with_destroyed_accounts(self.destroyed_accounts())
}
}
/// Sorted hashed storage optimized for iterating during state trie calculation.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct HashedStorageSorted {

View File

@@ -1,7 +1,7 @@
use crate::{
hashed_cursor::{HashedCursorFactory, HashedStorageCursor},
node_iter::{AccountNode, AccountNodeIter, StorageNode, StorageNodeIter},
prefix_set::{PrefixSet, PrefixSetLoader, PrefixSetMut},
prefix_set::{PrefixSet, PrefixSetLoader, PrefixSetMut, TriePrefixSets},
progress::{IntermediateStateRootState, StateRootProgress},
trie_cursor::TrieCursorFactory,
updates::{TrieKey, TrieOp, TrieUpdates},
@@ -16,10 +16,7 @@ use reth_primitives::{
trie::{HashBuilder, Nibbles, TrieAccount},
Address, BlockNumber, B256,
};
use std::{
collections::{HashMap, HashSet},
ops::RangeInclusive,
};
use std::ops::RangeInclusive;
use tracing::{debug, trace};
/// StateRoot is used to compute the root node of a state trie.
@@ -29,13 +26,8 @@ pub struct StateRoot<T, H> {
pub trie_cursor_factory: T,
/// The factory for hashed cursors.
pub hashed_cursor_factory: H,
/// A set of account prefixes that have changed.
pub changed_account_prefixes: PrefixSet,
/// A map containing storage changes with the hashed address as key and a set of storage key
/// prefixes as the value.
pub changed_storage_prefixes: HashMap<B256, PrefixSet>,
/// A map containing keys of accounts that were destroyed.
pub destroyed_accounts: HashSet<B256>,
/// A set of prefix sets that have changes.
pub prefix_sets: TriePrefixSets,
/// Previous intermediate state.
previous_state: Option<IntermediateStateRootState>,
/// The number of updates after which the intermediate progress should be returned.
@@ -43,21 +35,9 @@ pub struct StateRoot<T, H> {
}
impl<T, H> StateRoot<T, H> {
/// Set the changed account prefixes.
pub fn with_changed_account_prefixes(mut self, prefixes: PrefixSet) -> Self {
self.changed_account_prefixes = prefixes;
self
}
/// Set the changed storage prefixes.
pub fn with_changed_storage_prefixes(mut self, prefixes: HashMap<B256, PrefixSet>) -> Self {
self.changed_storage_prefixes = prefixes;
self
}
/// Set the destroyed accounts.
pub fn with_destroyed_accounts(mut self, accounts: HashSet<B256>) -> Self {
self.destroyed_accounts = accounts;
/// Set the prefix sets.
pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
self.prefix_sets = prefix_sets;
self
}
@@ -84,9 +64,7 @@ impl<T, H> StateRoot<T, H> {
StateRoot {
trie_cursor_factory: self.trie_cursor_factory,
hashed_cursor_factory,
changed_account_prefixes: self.changed_account_prefixes,
changed_storage_prefixes: self.changed_storage_prefixes,
destroyed_accounts: self.destroyed_accounts,
prefix_sets: self.prefix_sets,
threshold: self.threshold,
previous_state: self.previous_state,
}
@@ -97,9 +75,7 @@ impl<T, H> StateRoot<T, H> {
StateRoot {
trie_cursor_factory,
hashed_cursor_factory: self.hashed_cursor_factory,
changed_account_prefixes: self.changed_account_prefixes,
changed_storage_prefixes: self.changed_storage_prefixes,
destroyed_accounts: self.destroyed_accounts,
prefix_sets: self.prefix_sets,
threshold: self.threshold,
previous_state: self.previous_state,
}
@@ -112,9 +88,7 @@ impl<'a, TX: DbTx> StateRoot<&'a TX, &'a TX> {
Self {
trie_cursor_factory: tx,
hashed_cursor_factory: tx,
changed_account_prefixes: PrefixSetMut::default().freeze(),
changed_storage_prefixes: HashMap::default(),
destroyed_accounts: HashSet::default(),
prefix_sets: TriePrefixSets::default(),
previous_state: None,
threshold: 100_000,
}
@@ -131,16 +105,7 @@ impl<'a, TX: DbTx> StateRoot<&'a TX, &'a TX> {
range: RangeInclusive<BlockNumber>,
) -> Result<Self, StateRootError> {
let loaded_prefix_sets = PrefixSetLoader::new(tx).load(range)?;
Ok(Self::from_tx(tx)
.with_changed_account_prefixes(loaded_prefix_sets.account_prefix_set.freeze())
.with_changed_storage_prefixes(
loaded_prefix_sets
.storage_prefix_sets
.into_iter()
.map(|(k, v)| (k, v.freeze()))
.collect(),
)
.with_destroyed_accounts(loaded_prefix_sets.destroyed_accounts))
Ok(Self::from_tx(tx).with_prefix_sets(loaded_prefix_sets))
}
/// Computes the state root of the trie with the changed account and storage prefixes and
@@ -243,7 +208,7 @@ where
let walker = TrieWalker::from_stack(
trie_cursor,
state.walker_stack,
self.changed_account_prefixes,
self.prefix_sets.account_prefix_set,
);
(
state.hash_builder,
@@ -252,7 +217,7 @@ where
)
}
None => {
let walker = TrieWalker::new(trie_cursor, self.changed_account_prefixes);
let walker = TrieWalker::new(trie_cursor, self.prefix_sets.account_prefix_set);
(HashBuilder::default(), AccountNodeIter::new(walker, hashed_account_cursor))
}
};
@@ -282,8 +247,9 @@ where
self.hashed_cursor_factory.clone(),
hashed_address,
)
.with_changed_prefixes(
self.changed_storage_prefixes
.with_prefix_set(
self.prefix_sets
.storage_prefix_sets
.get(&hashed_address)
.cloned()
.unwrap_or_default(),
@@ -340,8 +306,9 @@ where
trie_updates.extend(walker_updates.into_iter());
trie_updates.extend_with_account_updates(hash_builder_updates);
trie_updates
.extend_with_deletes(self.destroyed_accounts.into_iter().map(TrieKey::StorageTrie));
trie_updates.extend_with_deletes(
self.prefix_sets.destroyed_accounts.into_iter().map(TrieKey::StorageTrie),
);
Ok(StateRootProgress::Complete(root, hashed_entries_walked, trie_updates))
}
@@ -357,7 +324,7 @@ pub struct StorageRoot<T, H> {
/// The hashed address of an account.
pub hashed_address: B256,
/// The set of storage slot prefixes that have changed.
pub changed_prefixes: PrefixSet,
pub prefix_set: PrefixSet,
}
impl<T, H> StorageRoot<T, H> {
@@ -376,13 +343,13 @@ impl<T, H> StorageRoot<T, H> {
trie_cursor_factory,
hashed_cursor_factory,
hashed_address,
changed_prefixes: PrefixSetMut::default().freeze(),
prefix_set: PrefixSetMut::default().freeze(),
}
}
/// Set the changed prefixes.
pub fn with_changed_prefixes(mut self, prefixes: PrefixSet) -> Self {
self.changed_prefixes = prefixes;
pub fn with_prefix_set(mut self, prefix_set: PrefixSet) -> Self {
self.prefix_set = prefix_set;
self
}
@@ -392,7 +359,7 @@ impl<T, H> StorageRoot<T, H> {
trie_cursor_factory: self.trie_cursor_factory,
hashed_cursor_factory,
hashed_address: self.hashed_address,
changed_prefixes: self.changed_prefixes,
prefix_set: self.prefix_set,
}
}
@@ -402,7 +369,7 @@ impl<T, H> StorageRoot<T, H> {
trie_cursor_factory,
hashed_cursor_factory: self.hashed_cursor_factory,
hashed_address: self.hashed_address,
changed_prefixes: self.changed_prefixes,
prefix_set: self.prefix_set,
}
}
}
@@ -429,7 +396,7 @@ where
/// # Returns
///
/// The storage root and storage trie updates for a given address.
pub fn root_with_updates(&self) -> Result<(B256, usize, TrieUpdates), StorageRootError> {
pub fn root_with_updates(self) -> Result<(B256, usize, TrieUpdates), StorageRootError> {
self.calculate(true)
}
@@ -438,13 +405,13 @@ where
/// # Returns
///
/// The storage root.
pub fn root(&self) -> Result<B256, StorageRootError> {
pub fn root(self) -> Result<B256, StorageRootError> {
let (root, _, _) = self.calculate(false)?;
Ok(root)
}
fn calculate(
&self,
self,
retain_updates: bool,
) -> Result<(B256, usize, TrieUpdates), StorageRootError> {
trace!(target: "trie::storage_root", hashed_address = ?self.hashed_address, "calculating storage root");
@@ -460,8 +427,7 @@ where
}
let trie_cursor = self.trie_cursor_factory.storage_tries_cursor(self.hashed_address)?;
let walker = TrieWalker::new(trie_cursor, self.changed_prefixes.clone())
.with_updates(retain_updates);
let walker = TrieWalker::new(trie_cursor, self.prefix_set).with_updates(retain_updates);
let mut hash_builder = HashBuilder::default().with_updates(retain_updates);
@@ -586,7 +552,7 @@ mod tests {
let mut storage_changes = PrefixSetMut::default();
storage_changes.insert(Nibbles::unpack(modified_key));
let loader = StorageRoot::from_tx_hashed(tx.tx_ref(), hashed_address)
.with_changed_prefixes(storage_changes.freeze());
.with_prefix_set(storage_changes.freeze());
let incremental_root = loader.root().unwrap();
assert_eq!(modified_root, incremental_root);
@@ -1001,7 +967,10 @@ mod tests {
.unwrap();
let (root, trie_updates) = StateRoot::from_tx(tx.tx_ref())
.with_changed_account_prefixes(prefix_set.freeze())
.with_prefix_sets(TriePrefixSets {
account_prefix_set: prefix_set.freeze(),
..Default::default()
})
.root_with_updates()
.unwrap();
assert_eq!(root, expected_state_root);
@@ -1053,7 +1022,10 @@ mod tests {
]);
let (root, trie_updates) = StateRoot::from_tx(tx.tx_ref())
.with_changed_account_prefixes(account_prefix_set.freeze())
.with_prefix_sets(TriePrefixSets {
account_prefix_set: account_prefix_set.freeze(),
..Default::default()
})
.root_with_updates()
.unwrap();
assert_eq!(root, computed_expected_root);
@@ -1110,7 +1082,10 @@ mod tests {
]);
let (root, trie_updates) = StateRoot::from_tx(tx.tx_ref())
.with_changed_account_prefixes(account_prefix_set.freeze())
.with_prefix_sets(TriePrefixSets {
account_prefix_set: account_prefix_set.freeze(),
..Default::default()
})
.root_with_updates()
.unwrap();
assert_eq!(root, computed_expected_root);
@@ -1205,14 +1180,14 @@ mod tests {
let should_generate_changeset = !state.is_empty();
let mut changes = PrefixSetMut::default();
for (hashed_address, balance) in accounts.clone() {
hashed_account_cursor.upsert(hashed_address, Account { balance,..Default::default() }).unwrap();
hashed_account_cursor.upsert(hashed_address, Account { balance, ..Default::default() }).unwrap();
if should_generate_changeset {
changes.insert(Nibbles::unpack(hashed_address));
}
}
let (state_root, trie_updates) = StateRoot::from_tx(tx.tx_ref())
.with_changed_account_prefixes(changes.freeze())
.with_prefix_sets(TriePrefixSets { account_prefix_set: changes.freeze(), ..Default::default() })
.root_with_updates()
.unwrap();