perf(provider): compute hashes and trie updates before opening write tx (#5505)

This commit is contained in:
Roman Krasiuk
2023-11-28 00:54:09 -08:00
committed by GitHub
parent 98250f8b50
commit 608f100605
8 changed files with 236 additions and 30 deletions

View File

@ -32,6 +32,19 @@ impl HashedStorage {
}
}
/// Returns `true` if the storage was wiped.
pub fn wiped(&self) -> bool {
self.wiped
}
/// Returns all storage slots.
pub fn storage_slots(&self) -> impl Iterator<Item = (B256, U256)> + '_ {
self.zero_valued_slots
.iter()
.map(|slot| (*slot, U256::ZERO))
.chain(self.non_zero_valued_storage.iter().cloned())
}
/// Sorts the non zero value storage entries.
pub fn sort_storage(&mut self) {
if !self.sorted {
@ -58,8 +71,8 @@ impl HashedStorage {
pub struct HashedPostState {
/// Map of hashed addresses to account info.
accounts: Vec<(B256, Account)>,
/// Set of cleared accounts.
cleared_accounts: HashSet<B256>,
/// Set of destroyed accounts.
destroyed_accounts: HashSet<B256>,
/// Map of hashed addresses to hashed storage.
storages: HashMap<B256, HashedStorage>,
/// Whether the account and storage entries were sorted or not.
@ -70,7 +83,7 @@ impl Default for HashedPostState {
fn default() -> Self {
Self {
accounts: Vec::new(),
cleared_accounts: HashSet::new(),
destroyed_accounts: HashSet::new(),
storages: HashMap::new(),
sorted: true, // empty is sorted
}
@ -84,6 +97,18 @@ impl HashedPostState {
self
}
/// Returns all accounts with their state.
pub fn accounts(&self) -> impl Iterator<Item = (B256, Option<Account>)> + '_ {
self.destroyed_accounts.iter().map(|hashed_address| (*hashed_address, None)).chain(
self.accounts.iter().map(|(hashed_address, account)| (*hashed_address, Some(*account))),
)
}
/// Returns all account storages.
pub fn storages(&self) -> impl Iterator<Item = (&B256, &HashedStorage)> {
self.storages.iter()
}
/// Sort account and storage entries.
pub fn sort(&mut self) {
if !self.sorted {
@ -102,9 +127,9 @@ impl HashedPostState {
self.sorted = false;
}
/// Insert cleared hashed account key.
pub fn insert_cleared_account(&mut self, hashed_address: B256) {
self.cleared_accounts.insert(hashed_address);
/// Insert destroyed hashed account key.
pub fn insert_destroyed_account(&mut self, hashed_address: B256) {
self.destroyed_accounts.insert(hashed_address);
}
/// Insert hashed storage entry.
@ -113,6 +138,11 @@ impl HashedPostState {
self.storages.insert(hashed_address, hashed_storage);
}
/// Returns all destroyed accounts.
pub fn destroyed_accounts(&self) -> HashSet<B256> {
self.destroyed_accounts.clone()
}
/// Construct (PrefixSet)[PrefixSet] from hashed post state.
/// The prefix sets contain the hashed account and storage keys that have been changed in the
/// post state.
@ -125,7 +155,7 @@ impl HashedPostState {
for (hashed_address, _) in &self.accounts {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
}
for hashed_address in &self.cleared_accounts {
for hashed_address in &self.destroyed_accounts {
account_prefix_set.insert(Nibbles::unpack(hashed_address));
}
@ -213,7 +243,7 @@ impl<'b, C> HashedPostStateAccountCursor<'b, C> {
/// This function only checks the post state, not the database, because the latter does not
/// store destroyed accounts.
fn is_account_cleared(&self, account: &B256) -> bool {
self.post_state.cleared_accounts.contains(account)
self.post_state.destroyed_accounts.contains(account)
}
/// Return the account with the lowest hashed account key.
@ -667,7 +697,7 @@ mod tests {
let mut hashed_post_state = HashedPostState::default();
for (hashed_address, account) in accounts.iter().filter(|x| x.0[31] % 2 != 0) {
if removed_keys.contains(hashed_address) {
hashed_post_state.insert_cleared_account(*hashed_address);
hashed_post_state.insert_destroyed_account(*hashed_address);
} else {
hashed_post_state.insert_account(*hashed_address, *account);
}
@ -722,7 +752,7 @@ mod tests {
if let Some(account) = account {
hashed_post_state.insert_account(*hashed_address, *account);
} else {
hashed_post_state.insert_cleared_account(*hashed_address);
hashed_post_state.insert_destroyed_account(*hashed_address);
}
}
hashed_post_state.sort();