Hashed post state cursor works on top of a trait instead of &Tx. (#6226)

Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
This commit is contained in:
Vitaly Drogan
2024-01-26 11:24:10 +01:00
committed by GitHub
parent 4ea4556209
commit b3ed3016cd
2 changed files with 25 additions and 36 deletions

View File

@ -1,45 +1,32 @@
use super::{HashedAccountCursor, HashedCursorFactory, HashedStorageCursor};
use crate::state::HashedPostState;
use reth_db::{
cursor::{DbCursorRO, DbDupCursorRO},
tables,
transaction::DbTx,
};
use reth_primitives::{Account, StorageEntry, B256, U256};
/// The hashed cursor factory for the post state.
#[derive(Debug)]
pub struct HashedPostStateCursorFactory<'a, 'b, TX> {
tx: &'a TX,
post_state: &'b HashedPostState,
#[derive(Debug, Clone)]
pub struct HashedPostStateCursorFactory<'a, CF> {
cursor_factory: CF,
post_state: &'a HashedPostState,
}
impl<'a, 'b, TX> Clone for HashedPostStateCursorFactory<'a, 'b, TX> {
fn clone(&self) -> Self {
Self { tx: self.tx, post_state: self.post_state }
}
}
impl<'a, 'b, TX> HashedPostStateCursorFactory<'a, 'b, TX> {
impl<'a, CF> HashedPostStateCursorFactory<'a, CF> {
/// Create a new factory.
pub fn new(tx: &'a TX, post_state: &'b HashedPostState) -> Self {
Self { tx, post_state }
pub fn new(cursor_factory: CF, post_state: &'a HashedPostState) -> Self {
Self { cursor_factory, post_state }
}
}
impl<'a, 'b, TX: DbTx> HashedCursorFactory for HashedPostStateCursorFactory<'a, 'b, TX> {
type AccountCursor =
HashedPostStateAccountCursor<'b, <TX as DbTx>::Cursor<tables::HashedAccount>>;
type StorageCursor =
HashedPostStateStorageCursor<'b, <TX as DbTx>::DupCursor<tables::HashedStorage>>;
impl<'a, CF: HashedCursorFactory> HashedCursorFactory for HashedPostStateCursorFactory<'a, CF> {
type AccountCursor = HashedPostStateAccountCursor<'a, CF::AccountCursor>;
type StorageCursor = HashedPostStateStorageCursor<'a, CF::StorageCursor>;
fn hashed_account_cursor(&self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
let cursor = self.tx.cursor_read::<tables::HashedAccount>()?;
let cursor = self.cursor_factory.hashed_account_cursor()?;
Ok(HashedPostStateAccountCursor::new(cursor, self.post_state))
}
fn hashed_storage_cursor(&self) -> Result<Self::StorageCursor, reth_db::DatabaseError> {
let cursor = self.tx.cursor_dup_read::<tables::HashedStorage>()?;
let cursor = self.cursor_factory.hashed_storage_cursor()?;
Ok(HashedPostStateStorageCursor::new(cursor, self.post_state))
}
}
@ -54,7 +41,7 @@ pub struct HashedPostStateAccountCursor<'b, C> {
post_state: &'b HashedPostState,
/// The post state account index where the cursor is currently at.
post_state_account_index: usize,
/// The last hashed account key that was returned by the cursor.
/// The last hashed account that was returned by the cursor.
/// De facto, this is a current cursor position.
last_account: Option<B256>,
}
@ -100,7 +87,7 @@ impl<'b, C> HashedPostStateAccountCursor<'b, C> {
impl<'b, C> HashedAccountCursor for HashedPostStateAccountCursor<'b, C>
where
C: DbCursorRO<tables::HashedAccount>,
C: HashedAccountCursor,
{
/// Seek the next entry for a given hashed account key.
///
@ -165,7 +152,7 @@ where
};
// If post state was given precedence, move the cursor forward.
let mut db_entry = self.cursor.current()?;
let mut db_entry = self.cursor.seek(*last_account)?;
while db_entry
.as_ref()
.map(|(address, _)| address <= last_account || self.is_account_cleared(address))
@ -258,7 +245,7 @@ impl<'b, C> HashedPostStateStorageCursor<'b, C> {
impl<'b, C> HashedStorageCursor for HashedPostStateStorageCursor<'b, C>
where
C: DbCursorRO<tables::HashedStorage> + DbDupCursorRO<tables::HashedStorage>,
C: HashedStorageCursor,
{
/// Returns `true` if the account has no storage entries.
///
@ -272,7 +259,7 @@ where
// and the current storage does not contain any non-zero values
storage.non_zero_valued_slots.is_empty()
}
None => self.cursor.seek_exact(key)?.is_none(),
None => self.cursor.is_storage_empty(key)?,
};
Ok(is_empty)
}
@ -315,14 +302,14 @@ where
let db_entry = if self.is_db_storage_wiped(&account) {
None
} else {
let mut db_entry = self.cursor.seek_by_key_subkey(account, subkey)?;
let mut db_entry = self.cursor.seek(account, subkey)?;
while db_entry
.as_ref()
.map(|entry| self.is_slot_zero_valued(&account, &entry.key))
.unwrap_or_default()
{
db_entry = self.cursor.next_dup_val()?;
db_entry = self.cursor.next()?;
}
db_entry
@ -352,7 +339,7 @@ where
None
} else {
// If post state was given precedence, move the cursor forward.
let mut db_entry = self.cursor.seek_by_key_subkey(account, *last_slot)?;
let mut db_entry = self.cursor.seek(account, *last_slot)?;
// If the entry was already returned or is zero-values, move to the next.
while db_entry
@ -362,7 +349,7 @@ where
})
.unwrap_or_default()
{
db_entry = self.cursor.next_dup_val()?;
db_entry = self.cursor.next()?;
}
db_entry
@ -393,7 +380,9 @@ mod tests {
use super::*;
use proptest::prelude::*;
use reth_db::{database::Database, test_utils::create_test_rw_db, transaction::DbTxMut};
use reth_db::{
database::Database, tables, test_utils::create_test_rw_db, transaction::DbTxMut,
};
use std::collections::BTreeMap;
fn assert_account_cursor_order(

View File

@ -256,7 +256,7 @@ impl HashedPostState {
fn state_root_calculator<'a, TX: DbTx>(
&self,
tx: &'a TX,
) -> StateRoot<&'a TX, HashedPostStateCursorFactory<'a, '_, TX>> {
) -> StateRoot<&'a TX, HashedPostStateCursorFactory<'_, &'a TX>> {
assert!(self.sorted, "Hashed post state must be sorted for state root calculation");
let (account_prefix_set, storage_prefix_set) = self.construct_prefix_sets();
let hashed_cursor_factory = HashedPostStateCursorFactory::new(tx, self);