chore: simplify HashedCursorFactory trait (#4984)

This commit is contained in:
robinsdan
2023-10-12 19:41:06 +08:00
committed by GitHub
parent 505c6bc826
commit 3a8c062574
7 changed files with 75 additions and 79 deletions

View File

@ -6,15 +6,15 @@ use reth_db::{
};
use reth_primitives::{Account, StorageEntry, B256};
impl<'a, 'tx, TX: DbTx<'tx>> HashedCursorFactory<'a> for TX {
type AccountCursor = <TX as DbTxGAT<'a>>::Cursor<tables::HashedAccount> where Self: 'a;
type StorageCursor = <TX as DbTxGAT<'a>>::DupCursor<tables::HashedStorage> where Self: 'a;
impl<'a, 'tx, TX: DbTx<'tx>> HashedCursorFactory for &'a TX {
type AccountCursor = <TX as DbTxGAT<'a>>::Cursor<tables::HashedAccount>;
type StorageCursor = <TX as DbTxGAT<'a>>::DupCursor<tables::HashedStorage>;
fn hashed_account_cursor(&'a self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
fn hashed_account_cursor(&self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
self.cursor_read::<tables::HashedAccount>()
}
fn hashed_storage_cursor(&'a self) -> Result<Self::StorageCursor, reth_db::DatabaseError> {
fn hashed_storage_cursor(&self) -> Result<Self::StorageCursor, reth_db::DatabaseError> {
self.cursor_dup_read::<tables::HashedStorage>()
}
}

View File

@ -8,21 +8,17 @@ mod post_state;
pub use post_state::*;
/// The factory trait for creating cursors over the hashed state.
pub trait HashedCursorFactory<'a> {
pub trait HashedCursorFactory {
/// The hashed account cursor type.
type AccountCursor: HashedAccountCursor
where
Self: 'a;
type AccountCursor: HashedAccountCursor;
/// The hashed storage cursor type.
type StorageCursor: HashedStorageCursor
where
Self: 'a;
type StorageCursor: HashedStorageCursor;
/// Returns a cursor for iterating over all hashed accounts in the state.
fn hashed_account_cursor(&'a self) -> Result<Self::AccountCursor, reth_db::DatabaseError>;
fn hashed_account_cursor(&self) -> Result<Self::AccountCursor, reth_db::DatabaseError>;
/// Returns a cursor for iterating over all hashed storage entries in the state.
fn hashed_storage_cursor(&'a self) -> Result<Self::StorageCursor, reth_db::DatabaseError>;
fn hashed_storage_cursor(&self) -> Result<Self::StorageCursor, reth_db::DatabaseError>;
}
/// The cursor for iterating over hashed accounts.

View File

@ -156,6 +156,12 @@ pub struct HashedPostStateCursorFactory<'a, 'b, TX> {
post_state: &'b 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> {
/// Create a new factory.
pub fn new(tx: &'a TX, post_state: &'b HashedPostState) -> Self {
@ -163,20 +169,18 @@ impl<'a, 'b, TX> HashedPostStateCursorFactory<'a, 'b, TX> {
}
}
impl<'a, 'b, 'tx, TX: DbTx<'tx>> HashedCursorFactory<'a>
for HashedPostStateCursorFactory<'a, 'b, TX>
where
'a: 'b,
{
type AccountCursor = HashedPostStateAccountCursor<'b, <TX as DbTxGAT<'a>>::Cursor<tables::HashedAccount>> where Self: 'a;
type StorageCursor = HashedPostStateStorageCursor<'b, <TX as DbTxGAT<'a>>::DupCursor<tables::HashedStorage>> where Self: 'a;
impl<'a, 'b, 'tx, TX: DbTx<'tx>> HashedCursorFactory for HashedPostStateCursorFactory<'a, 'b, TX> {
type AccountCursor =
HashedPostStateAccountCursor<'b, <TX as DbTxGAT<'a>>::Cursor<tables::HashedAccount>>;
type StorageCursor =
HashedPostStateStorageCursor<'b, <TX as DbTxGAT<'a>>::DupCursor<tables::HashedStorage>>;
fn hashed_account_cursor(&'a self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
fn hashed_account_cursor(&self) -> Result<Self::AccountCursor, reth_db::DatabaseError> {
let cursor = self.tx.cursor_read::<tables::HashedAccount>()?;
Ok(HashedPostStateAccountCursor::new(cursor, self.post_state))
}
fn hashed_storage_cursor(&'a self) -> Result<Self::StorageCursor, reth_db::DatabaseError> {
fn hashed_storage_cursor(&self) -> Result<Self::StorageCursor, reth_db::DatabaseError> {
let cursor = self.tx.cursor_dup_read::<tables::HashedStorage>()?;
Ok(HashedPostStateStorageCursor::new(cursor, self.post_state))
}
@ -544,12 +548,10 @@ mod tests {
use reth_db::{database::Database, test_utils::create_test_rw_db, transaction::DbTxMut};
use std::collections::BTreeMap;
fn assert_account_cursor_order<'a, 'b>(
factory: &'a impl HashedCursorFactory<'b>,
fn assert_account_cursor_order(
factory: &impl HashedCursorFactory,
mut expected: impl Iterator<Item = (B256, Account)>,
) where
'a: 'b,
{
) {
let mut cursor = factory.hashed_account_cursor().unwrap();
let first_account = cursor.seek(B256::default()).unwrap();
@ -563,12 +565,10 @@ mod tests {
assert!(cursor.next().unwrap().is_none());
}
fn assert_storage_cursor_order<'a, 'b>(
factory: &'a impl HashedCursorFactory<'b>,
fn assert_storage_cursor_order(
factory: &impl HashedCursorFactory,
expected: impl Iterator<Item = (B256, BTreeMap<B256, U256>)>,
) where
'a: 'b,
{
) {
let mut cursor = factory.hashed_storage_cursor().unwrap();
for (account, storage) in expected {

View File

@ -35,32 +35,32 @@ use reth_primitives::{
/// After traversing the path, the proof generator continues to restore the root node of the trie
/// until completion. The root node is then inserted at the start of the proof.
#[derive(Debug)]
pub struct Proof<'a, 'b, TX, H> {
pub struct Proof<'a, TX, H> {
/// A reference to the database transaction.
tx: &'a TX,
/// The factory for hashed cursors.
hashed_cursor_factory: &'b H,
hashed_cursor_factory: H,
}
impl<'a, TX> Proof<'a, 'a, TX, TX> {
impl<'a, TX> Proof<'a, TX, &'a TX> {
/// Create a new [Proof] instance.
pub fn new(tx: &'a TX) -> Self {
Self { tx, hashed_cursor_factory: tx }
}
}
impl<'a, 'b, 'tx, TX, H> Proof<'a, 'b, TX, H>
impl<'a, 'tx, TX, H> Proof<'a, TX, H>
where
TX: DbTx<'tx>,
H: HashedCursorFactory<'b>,
H: HashedCursorFactory + Clone,
{
/// Generate an account proof from intermediate nodes.
pub fn account_proof(&self, address: Address) -> Result<Vec<Bytes>, ProofError> {
let hashed_address = keccak256(address);
let target_nibbles = Nibbles::unpack(hashed_address);
let mut proof_restorer =
ProofRestorer::new(self.tx)?.with_hashed_cursor_factory(self.hashed_cursor_factory)?;
let mut proof_restorer = ProofRestorer::new(self.tx)?
.with_hashed_cursor_factory(self.hashed_cursor_factory.clone())?;
let mut trie_cursor =
AccountTrieCursor::new(self.tx.cursor_read::<tables::AccountsTrie>()?);
@ -101,7 +101,7 @@ where
fn traverse_path<T: DbCursorRO<'a, tables::AccountsTrie>>(
&self,
trie_cursor: &mut AccountTrieCursor<T>,
proof_restorer: &mut ProofRestorer<'a, 'b, TX, H>,
proof_restorer: &mut ProofRestorer<'a, TX, H>,
hashed_address: B256,
) -> Result<Vec<Bytes>, ProofError> {
let mut intermediate_proofs = Vec::new();
@ -129,14 +129,14 @@ where
}
}
struct ProofRestorer<'a, 'b, TX, H>
struct ProofRestorer<'a, TX, H>
where
H: HashedCursorFactory<'b>,
H: HashedCursorFactory,
{
/// A reference to the database transaction.
tx: &'a TX,
/// The factory for hashed cursors.
hashed_cursor_factory: &'b H,
hashed_cursor_factory: H,
/// The hashed account cursor.
hashed_account_cursor: H::AccountCursor,
/// Pre-allocated buffer for account RLP encoding
@ -145,7 +145,7 @@ where
node_rlp_buf: Vec<u8>,
}
impl<'a, 'tx, TX> ProofRestorer<'a, 'a, TX, TX>
impl<'a, 'tx, TX> ProofRestorer<'a, TX, &'a TX>
where
TX: DbTx<'tx>,
{
@ -161,18 +161,18 @@ where
}
}
impl<'a, 'b, 'tx, TX, H> ProofRestorer<'a, 'b, TX, H>
impl<'a, 'tx, TX, H> ProofRestorer<'a, TX, H>
where
TX: DbTx<'tx> + HashedCursorFactory<'a>,
H: HashedCursorFactory<'b>,
TX: DbTx<'tx>,
H: HashedCursorFactory + Clone,
{
/// Set the hashed cursor factory.
fn with_hashed_cursor_factory<'c, HF>(
fn with_hashed_cursor_factory<HF>(
self,
hashed_cursor_factory: &'c HF,
) -> Result<ProofRestorer<'a, 'c, TX, HF>, ProofError>
hashed_cursor_factory: HF,
) -> Result<ProofRestorer<'a, TX, HF>, ProofError>
where
HF: HashedCursorFactory<'c>,
HF: HashedCursorFactory,
{
let hashed_account_cursor = hashed_cursor_factory.hashed_account_cursor()?;
Ok(ProofRestorer {
@ -222,7 +222,7 @@ where
// Restore account's storage root.
let storage_root = StorageRoot::new_hashed(self.tx, hashed_address)
.with_hashed_cursor_factory(self.hashed_cursor_factory)
.with_hashed_cursor_factory(self.hashed_cursor_factory.clone())
.root()?;
self.account_rlp_buf.clear();
@ -250,7 +250,7 @@ where
// Restore account's storage root.
let storage_root = StorageRoot::new_hashed(self.tx, hashed_address)
.with_hashed_cursor_factory(self.hashed_cursor_factory)
.with_hashed_cursor_factory(self.hashed_cursor_factory.clone())
.root()?;
self.account_rlp_buf.clear();

View File

@ -23,11 +23,11 @@ use std::{
/// StateRoot is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<'a, 'b, TX, H> {
pub struct StateRoot<'a, TX, H> {
/// A reference to the database transaction.
pub tx: &'a TX,
/// The factory for hashed cursors.
pub hashed_cursor_factory: &'b H,
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
@ -41,7 +41,7 @@ pub struct StateRoot<'a, 'b, TX, H> {
threshold: u64,
}
impl<'a, 'b, TX, H> StateRoot<'a, 'b, TX, H> {
impl<'a, TX, H> StateRoot<'a, TX, H> {
/// Set the changed account prefixes.
pub fn with_changed_account_prefixes(mut self, prefixes: PrefixSet) -> Self {
self.changed_account_prefixes = prefixes;
@ -79,10 +79,10 @@ impl<'a, 'b, TX, H> StateRoot<'a, 'b, TX, H> {
}
/// Set the hashed cursor factory.
pub fn with_hashed_cursor_factory<'c, HF>(
pub fn with_hashed_cursor_factory<HF>(
self,
hashed_cursor_factory: &'c HF,
) -> StateRoot<'a, 'c, TX, HF> {
hashed_cursor_factory: HF,
) -> StateRoot<'a, TX, HF> {
StateRoot {
tx: self.tx,
changed_account_prefixes: self.changed_account_prefixes,
@ -95,9 +95,9 @@ impl<'a, 'b, TX, H> StateRoot<'a, 'b, TX, H> {
}
}
impl<'a, 'tx, TX> StateRoot<'a, 'a, TX, TX>
impl<'a, 'tx, TX> StateRoot<'a, TX, &'a TX>
where
TX: DbTx<'tx> + HashedCursorFactory<'a>,
TX: DbTx<'tx>,
{
/// Create a new [StateRoot] instance.
pub fn new(tx: &'a TX) -> Self {
@ -180,10 +180,10 @@ where
}
}
impl<'a, 'b, 'tx, TX, H> StateRoot<'a, 'b, TX, H>
impl<'a, 'tx, TX, H> StateRoot<'a, TX, H>
where
TX: DbTx<'tx>,
H: HashedCursorFactory<'b>,
H: HashedCursorFactory + Clone,
{
/// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
/// nodes into the hash builder. Collects the updates in the process.
@ -300,7 +300,7 @@ where
// TODO: We can consider introducing the TrieProgress::Progress/Complete
// abstraction inside StorageRoot, but let's give it a try as-is for now.
let storage_root_calculator = StorageRoot::new_hashed(self.tx, hashed_address)
.with_hashed_cursor_factory(self.hashed_cursor_factory)
.with_hashed_cursor_factory(self.hashed_cursor_factory.clone())
.with_changed_prefixes(
self.changed_storage_prefixes
.get(&hashed_address)
@ -370,20 +370,20 @@ where
/// StorageRoot is used to compute the root node of an account storage trie.
#[derive(Debug)]
pub struct StorageRoot<'a, 'b, TX, H> {
pub struct StorageRoot<'a, TX, H> {
/// A reference to the database transaction.
pub tx: &'a TX,
/// The factory for hashed cursors.
pub hashed_cursor_factory: &'b H,
pub hashed_cursor_factory: H,
/// The hashed address of an account.
pub hashed_address: B256,
/// The set of storage slot prefixes that have changed.
pub changed_prefixes: PrefixSet,
}
impl<'a, 'tx, TX> StorageRoot<'a, 'a, TX, TX>
impl<'a, 'tx, TX> StorageRoot<'a, TX, &'a TX>
where
TX: DbTx<'tx> + HashedCursorFactory<'a>,
TX: DbTx<'tx>,
{
/// Creates a new storage root calculator given an raw address.
pub fn new(tx: &'a TX, address: Address) -> Self {
@ -401,16 +401,16 @@ where
}
}
impl<'a, 'b, TX, H> StorageRoot<'a, 'b, TX, H> {
impl<'a, TX, H> StorageRoot<'a, TX, H> {
/// Creates a new storage root calculator given an raw address.
pub fn new_with_factory(tx: &'a TX, hashed_cursor_factory: &'b H, address: Address) -> Self {
pub fn new_with_factory(tx: &'a TX, hashed_cursor_factory: H, address: Address) -> Self {
Self::new_hashed_with_factory(tx, hashed_cursor_factory, keccak256(address))
}
/// Creates a new storage root calculator given a hashed address.
pub fn new_hashed_with_factory(
tx: &'a TX,
hashed_cursor_factory: &'b H,
hashed_cursor_factory: H,
hashed_address: B256,
) -> Self {
Self {
@ -428,10 +428,10 @@ impl<'a, 'b, TX, H> StorageRoot<'a, 'b, TX, H> {
}
/// Set the hashed cursor factory.
pub fn with_hashed_cursor_factory<'c, HF>(
pub fn with_hashed_cursor_factory<HF>(
self,
hashed_cursor_factory: &'c HF,
) -> StorageRoot<'a, 'c, TX, HF> {
hashed_cursor_factory: HF,
) -> StorageRoot<'a, TX, HF> {
StorageRoot {
tx: self.tx,
hashed_address: self.hashed_address,
@ -441,10 +441,10 @@ impl<'a, 'b, TX, H> StorageRoot<'a, 'b, TX, H> {
}
}
impl<'a, 'b, 'tx, TX, H> StorageRoot<'a, 'b, TX, H>
impl<'a, 'tx, TX, H> StorageRoot<'a, TX, H>
where
TX: DbTx<'tx>,
H: HashedCursorFactory<'b>,
H: HashedCursorFactory,
{
/// Walks the hashed storage table entries for a given address and calculates the storage root.
///