From b3ed3016cd28e4f3d17247b8d40e2121d8ba6315 Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Fri, 26 Jan 2024 11:24:10 +0100 Subject: [PATCH] Hashed post state cursor works on top of a trait instead of &Tx. (#6226) Co-authored-by: Roman Krasiuk --- crates/trie/src/hashed_cursor/post_state.rs | 59 +++++++++------------ crates/trie/src/state.rs | 2 +- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/crates/trie/src/hashed_cursor/post_state.rs b/crates/trie/src/hashed_cursor/post_state.rs index 6a6aebb80b..2baf72a2de 100644 --- a/crates/trie/src/hashed_cursor/post_state.rs +++ b/crates/trie/src/hashed_cursor/post_state.rs @@ -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, ::Cursor>; - type StorageCursor = - HashedPostStateStorageCursor<'b, ::DupCursor>; +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 { - let cursor = self.tx.cursor_read::()?; + let cursor = self.cursor_factory.hashed_account_cursor()?; Ok(HashedPostStateAccountCursor::new(cursor, self.post_state)) } fn hashed_storage_cursor(&self) -> Result { - let cursor = self.tx.cursor_dup_read::()?; + 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, } @@ -100,7 +87,7 @@ impl<'b, C> HashedPostStateAccountCursor<'b, C> { impl<'b, C> HashedAccountCursor for HashedPostStateAccountCursor<'b, C> where - C: DbCursorRO, + 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 + DbDupCursorRO, + 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( diff --git a/crates/trie/src/state.rs b/crates/trie/src/state.rs index 620254edad..6d195cc5f1 100644 --- a/crates/trie/src/state.rs +++ b/crates/trie/src/state.rs @@ -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);