chore(trie): hold direct reference to hashed accounts in cursor (#9078)

This commit is contained in:
Roman Krasiuk
2024-06-25 06:23:58 -07:00
committed by GitHub
parent c3cae95431
commit 6e146e1140
2 changed files with 27 additions and 17 deletions

View File

@ -1,5 +1,5 @@
use super::{HashedCursor, HashedCursorFactory, HashedStorageCursor};
use crate::{state::HashedPostStateSorted, HashedStorageSorted};
use crate::{HashedAccountsSorted, HashedPostStateSorted, HashedStorageSorted};
use reth_primitives::{Account, B256, U256};
/// The hashed cursor factory for the post state.
@ -22,7 +22,7 @@ impl<'a, CF: HashedCursorFactory> HashedCursorFactory for HashedPostStateCursorF
fn hashed_account_cursor(&self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
let cursor = self.cursor_factory.hashed_account_cursor()?;
Ok(HashedPostStateAccountCursor::new(cursor, self.post_state))
Ok(HashedPostStateAccountCursor::new(cursor, &self.post_state.accounts))
}
fn hashed_storage_cursor(
@ -40,8 +40,8 @@ impl<'a, CF: HashedCursorFactory> HashedCursorFactory for HashedPostStateCursorF
pub struct HashedPostStateAccountCursor<'a, C> {
/// The database cursor.
cursor: C,
/// The reference to the in-memory [`HashedPostStateSorted`].
post_state: &'a HashedPostStateSorted,
/// The reference to the in-memory [`HashedAccountsSorted`].
post_state_accounts: &'a HashedAccountsSorted,
/// The post state account index where the cursor is currently at.
post_state_account_index: usize,
/// The last hashed account that was returned by the cursor.
@ -51,8 +51,8 @@ pub struct HashedPostStateAccountCursor<'a, C> {
impl<'a, C> HashedPostStateAccountCursor<'a, C> {
/// Create new instance of [`HashedPostStateAccountCursor`].
pub const fn new(cursor: C, post_state: &'a HashedPostStateSorted) -> Self {
Self { cursor, post_state, last_account: None, post_state_account_index: 0 }
pub const fn new(cursor: C, post_state_accounts: &'a HashedAccountsSorted) -> Self {
Self { cursor, post_state_accounts, last_account: None, post_state_account_index: 0 }
}
/// Returns `true` if the account has been destroyed.
@ -61,7 +61,7 @@ impl<'a, C> HashedPostStateAccountCursor<'a, 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.destroyed_accounts.contains(account)
self.post_state_accounts.destroyed_accounts.contains(account)
}
/// Return the account with the lowest hashed account key.
@ -107,10 +107,11 @@ where
// Take the next account from the post state with the key greater than or equal to the
// sought key.
let mut post_state_entry = self.post_state.accounts.get(self.post_state_account_index);
let mut post_state_entry =
self.post_state_accounts.accounts.get(self.post_state_account_index);
while post_state_entry.map(|(k, _)| k < &key).unwrap_or_default() {
self.post_state_account_index += 1;
post_state_entry = self.post_state.accounts.get(self.post_state_account_index);
post_state_entry = self.post_state_accounts.accounts.get(self.post_state_account_index);
}
// It's an exact match, return the account from post state without looking up in the
@ -163,10 +164,11 @@ where
}
// Take the next account from the post state with the key greater than the last sought key.
let mut post_state_entry = self.post_state.accounts.get(self.post_state_account_index);
let mut post_state_entry =
self.post_state_accounts.accounts.get(self.post_state_account_index);
while post_state_entry.map(|(k, _)| k <= last_account).unwrap_or_default() {
self.post_state_account_index += 1;
post_state_entry = self.post_state.accounts.get(self.post_state_account_index);
post_state_entry = self.post_state_accounts.accounts.get(self.post_state_account_index);
}
// Compare two entries and return the lowest.

View File

@ -149,16 +149,17 @@ impl HashedPostState {
/// Converts hashed post state into [`HashedPostStateSorted`].
pub fn into_sorted(self) -> HashedPostStateSorted {
let mut accounts = Vec::new();
let mut updated_accounts = Vec::new();
let mut destroyed_accounts = HashSet::default();
for (hashed_address, info) in self.accounts {
if let Some(info) = info {
accounts.push((hashed_address, info));
updated_accounts.push((hashed_address, info));
} else {
destroyed_accounts.insert(hashed_address);
}
}
accounts.sort_unstable_by_key(|(address, _)| *address);
updated_accounts.sort_unstable_by_key(|(address, _)| *address);
let accounts = HashedAccountsSorted { accounts: updated_accounts, destroyed_accounts };
let storages = self
.storages
@ -166,7 +167,7 @@ impl HashedPostState {
.map(|(hashed_address, storage)| (hashed_address, storage.into_sorted()))
.collect();
HashedPostStateSorted { accounts, destroyed_accounts, storages }
HashedPostStateSorted { accounts, storages }
}
/// Construct [`TriePrefixSets`] from hashed post state.
@ -309,12 +310,19 @@ impl HashedStorage {
/// Sorted hashed post state optimized for iterating during state trie calculation.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct HashedPostStateSorted {
/// Updated state of accounts.
pub(crate) accounts: HashedAccountsSorted,
/// Map of hashed addresses to hashed storage.
pub(crate) storages: HashMap<B256, HashedStorageSorted>,
}
/// Sorted account state optimized for iterating during state trie calculation.
#[derive(Clone, Eq, PartialEq, Debug)]
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>,
/// Map of hashed addresses to hashed storage.
pub(crate) storages: HashMap<B256, HashedStorageSorted>,
}
/// Sorted hashed storage optimized for iterating during state trie calculation.