diff --git a/crates/optimism/trie/src/api.rs b/crates/optimism/trie/src/api.rs index 30a519bdbc7..81b6368c613 100644 --- a/crates/optimism/trie/src/api.rs +++ b/crates/optimism/trie/src/api.rs @@ -101,10 +101,14 @@ pub trait OpProofsStorage: Send + Sync + Debug { Self: 'tx; /// Cursor for iterating over storage leaves. - type StorageCursor: OpProofsHashedCursor; + type StorageCursor<'tx>: OpProofsHashedCursor + 'tx + where + Self: 'tx; /// Cursor for iterating over account leaves. - type AccountHashedCursor: OpProofsHashedCursor; + type AccountHashedCursor<'tx>: OpProofsHashedCursor + 'tx + where + Self: 'tx; /// Store a batch of account trie branches. Used for saving existing state. For live state /// capture, use [store_trie_updates](OpProofsStorage::store_trie_updates). @@ -160,17 +164,17 @@ pub trait OpProofsStorage: Send + Sync + Debug { ) -> OpProofsStorageResult>; /// Get a storage cursor for the storage backend - fn storage_hashed_cursor( + fn storage_hashed_cursor<'tx>( &self, hashed_address: B256, max_block_number: u64, - ) -> OpProofsStorageResult; + ) -> OpProofsStorageResult>; /// Get an account hashed cursor for the storage backend - fn account_hashed_cursor( + fn account_hashed_cursor<'tx>( &self, max_block_number: u64, - ) -> OpProofsStorageResult; + ) -> OpProofsStorageResult>; /// Store a batch of trie updates. /// diff --git a/crates/optimism/trie/src/db/cursor.rs b/crates/optimism/trie/src/db/cursor.rs index ff11b2b17fd..854ed87a8bf 100644 --- a/crates/optimism/trie/src/db/cursor.rs +++ b/crates/optimism/trie/src/db/cursor.rs @@ -1,7 +1,10 @@ use std::marker::PhantomData; use crate::{ - db::{AccountTrieHistory, MaybeDeleted, StorageTrieHistory, StorageTrieKey, VersionedValue}, + db::{ + AccountTrieHistory, HashedAccountHistory, HashedStorageHistory, HashedStorageKey, + MaybeDeleted, StorageTrieHistory, StorageTrieKey, VersionedValue, + }, OpProofsHashedCursor, OpProofsStorageError, OpProofsStorageResult, OpProofsTrieCursor, }; use alloy_primitives::{B256, U256}; @@ -260,45 +263,80 @@ where /// MDBX implementation of `OpProofsHashedCursor` for storage state. #[derive(Debug)] -pub struct MdbxStorageCursor {} +pub struct MdbxStorageCursor { + inner: BlockNumberVersionedCursor, + hashed_address: B256, +} -impl OpProofsHashedCursor for MdbxStorageCursor { +impl MdbxStorageCursor +where + Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, +{ + /// Initializes new [`MdbxStorageCursor`] + pub const fn new(cursor: Cursor, block_number: u64, hashed_address: B256) -> Self { + Self { inner: BlockNumberVersionedCursor::new(cursor, block_number), hashed_address } + } +} + +impl OpProofsHashedCursor for MdbxStorageCursor +where + Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, +{ type Value = U256; - fn seek(&mut self, _key: B256) -> OpProofsStorageResult> { - unimplemented!() + fn seek(&mut self, key: B256) -> OpProofsStorageResult> { + let storage_key = HashedStorageKey::new(self.hashed_address, key); + self.inner.seek(storage_key).map(|opt| opt.map(|(k, v)| (k.hashed_storage_key, v.0))) } fn next(&mut self) -> OpProofsStorageResult> { - unimplemented!() + self.inner.next().map(|opt| opt.map(|(k, v)| (k.hashed_storage_key, v.0))) } } /// MDBX implementation of `OpProofsHashedCursor` for account state. #[derive(Debug)] -pub struct MdbxAccountCursor {} +pub struct MdbxAccountCursor { + inner: BlockNumberVersionedCursor, +} + +impl MdbxAccountCursor +where + Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, +{ + /// Initializes new `MdbxAccountCursor` + pub const fn new(cursor: Cursor, block_number: u64) -> Self { + Self { inner: BlockNumberVersionedCursor::new(cursor, block_number) } + } +} -impl OpProofsHashedCursor for MdbxAccountCursor { +impl OpProofsHashedCursor for MdbxAccountCursor +where + Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, +{ type Value = Account; - fn seek(&mut self, _key: B256) -> OpProofsStorageResult> { - unimplemented!() + fn seek(&mut self, key: B256) -> OpProofsStorageResult> { + self.inner.seek(key) } fn next(&mut self) -> OpProofsStorageResult> { - unimplemented!() + self.inner.next() } } #[cfg(test)] mod tests { use super::*; - use crate::db::models; + use crate::db::{models, StorageValue}; use reth_db::{ - cursor::DbDupCursorRW, mdbx::{init_db_for, DatabaseArguments}, + DatabaseEnv, + }; + use reth_db_api::{ + cursor::DbDupCursorRW, transaction::{DbTx, DbTxMut}, - Database, DatabaseEnv, + Database, }; use reth_trie::{BranchNodeCompact, Nibbles, StoredNibbles}; use tempfile::TempDir; @@ -340,6 +378,30 @@ mod tests { c.append_dup(key, vv).expect("append dup"); } + fn append_hashed_storage( + wtx: &::TXMut, + addr: B256, + slot: B256, + block: u64, + val: Option, + ) { + let mut c = wtx.cursor_dup_write::().expect("dup write"); + let key = HashedStorageKey::new(addr, slot); + let vv = VersionedValue { block_number: block, value: MaybeDeleted(val.map(StorageValue)) }; + c.append_dup(key, vv).expect("append dup"); + } + + fn append_hashed_account( + wtx: &::TXMut, + key: B256, + block: u64, + val: Option, + ) { + let mut c = wtx.cursor_dup_write::().expect("dup write"); + let vv = VersionedValue { block_number: block, value: MaybeDeleted(val) }; + c.append_dup(key, vv).expect("append dup"); + } + // Open a dup-RO cursor and wrap it in a BlockNumberVersionedCursor with a given bound. fn version_cursor( tx: &::TX, @@ -368,6 +430,23 @@ mod tests { MdbxTrieCursor::new(c, max_block, Some(address)) } + fn storage_cursor( + tx: &'_ ::TX, + max_block: u64, + address: B256, + ) -> MdbxStorageCursor> { + let c = tx.cursor_dup_read::().expect("dup ro cursor"); + MdbxStorageCursor::new(c, max_block, address) + } + + fn account_cursor( + tx: &'_ ::TX, + max_block: u64, + ) -> MdbxAccountCursor> { + let c = tx.cursor_dup_read::().expect("dup ro cursor"); + MdbxAccountCursor::new(c, max_block) + } + // Assert helper: ensure the chosen VersionedValue has the expected block and deletion flag. fn assert_block( got: Option<(StoredNibbles, VersionedValue)>, @@ -1000,4 +1079,129 @@ mod tests { let now = OpProofsTrieCursor::current(&mut cur).expect("ok").expect("some"); assert_eq!(now, p); } + + #[test] + fn hashed_storage_seek_maps_slot_and_value() { + let db = setup_db(); + let addr = B256::from([0xAA; 32]); + let slot = B256::from([0x10; 32]); + + { + let wtx = db.tx_mut().expect("rw"); + append_hashed_storage(&wtx, addr, slot, 10, Some(U256::from(7))); + wtx.commit().expect("commit"); + } + + let tx = db.tx().expect("ro"); + let mut cur = storage_cursor(&tx, 100, addr); + + let (got_slot, got_val) = + OpProofsHashedCursor::seek(&mut cur, slot).expect("ok").expect("some"); + assert_eq!(got_slot, slot); + assert_eq!(got_val, U256::from(7)); + } + + #[test] + fn hashed_storage_seek_filters_tombstone() { + let db = setup_db(); + let addr = B256::from([0xAB; 32]); + let slot = B256::from([0x11; 32]); + + { + let wtx = db.tx_mut().expect("rw"); + append_hashed_storage(&wtx, addr, slot, 5, Some(U256::from(1))); + append_hashed_storage(&wtx, addr, slot, 9, None); // latest ≤ max is tombstone + wtx.commit().expect("commit"); + } + + let tx = db.tx().expect("ro"); + let mut cur = storage_cursor(&tx, 10, addr); + + let out = OpProofsHashedCursor::seek(&mut cur, slot).expect("ok"); + assert!(out.is_none(), "wrapper must filter tombstoned latest"); + } + + #[test] + fn hashed_storage_seek_and_next_roundtrip() { + let db = setup_db(); + let addr = B256::from([0xAC; 32]); + let s1 = B256::from([0x01; 32]); + let s2 = B256::from([0x02; 32]); + + { + let wtx = db.tx_mut().expect("rw"); + append_hashed_storage(&wtx, addr, s1, 10, Some(U256::from(11))); + append_hashed_storage(&wtx, addr, s2, 10, Some(U256::from(22))); + wtx.commit().expect("commit"); + } + + let tx = db.tx().expect("ro"); + let mut cur = storage_cursor(&tx, 100, addr); + + let (k1, v1) = OpProofsHashedCursor::seek(&mut cur, s1).expect("ok").expect("some"); + assert_eq!((k1, v1), (s1, U256::from(11))); + + let (k2, v2) = OpProofsHashedCursor::next(&mut cur).expect("ok").expect("some"); + assert_eq!((k2, v2), (s2, U256::from(22))); + } + + #[test] + fn hashed_account_seek_maps_key_and_value() { + let db = setup_db(); + let key = B256::from([0x20; 32]); + + { + let wtx = db.tx_mut().expect("rw"); + append_hashed_account(&wtx, key, 10, Some(Account::default())); + wtx.commit().expect("commit"); + } + + let tx = db.tx().expect("ro"); + let mut cur = account_cursor(&tx, 100); + + let (got_key, _acc) = OpProofsHashedCursor::seek(&mut cur, key).expect("ok").expect("some"); + assert_eq!(got_key, key); + } + + #[test] + fn hashed_account_seek_filters_tombstone() { + let db = setup_db(); + let key = B256::from([0x21; 32]); + + { + let wtx = db.tx_mut().expect("rw"); + append_hashed_account(&wtx, key, 5, Some(Account::default())); + append_hashed_account(&wtx, key, 9, None); // latest ≤ max is tombstone + wtx.commit().expect("commit"); + } + + let tx = db.tx().expect("ro"); + let mut cur = account_cursor(&tx, 10); + + let out = OpProofsHashedCursor::seek(&mut cur, key).expect("ok"); + assert!(out.is_none(), "wrapper must filter tombstoned latest"); + } + + #[test] + fn hashed_account_seek_and_next_roundtrip() { + let db = setup_db(); + let k1 = B256::from([0x01; 32]); + let k2 = B256::from([0x02; 32]); + + { + let wtx = db.tx_mut().expect("rw"); + append_hashed_account(&wtx, k1, 10, Some(Account::default())); + append_hashed_account(&wtx, k2, 10, Some(Account::default())); + wtx.commit().expect("commit"); + } + + let tx = db.tx().expect("ro"); + let mut cur = account_cursor(&tx, 100); + + let (got1, _) = OpProofsHashedCursor::seek(&mut cur, k1).expect("ok").expect("some"); + assert_eq!(got1, k1); + + let (got2, _) = OpProofsHashedCursor::next(&mut cur).expect("ok").expect("some"); + assert_eq!(got2, k2); + } } diff --git a/crates/optimism/trie/src/db/models/storage.rs b/crates/optimism/trie/src/db/models/storage.rs index bddef114e9b..f8caf0e0e98 100644 --- a/crates/optimism/trie/src/db/models/storage.rs +++ b/crates/optimism/trie/src/db/models/storage.rs @@ -59,7 +59,7 @@ impl Decode for StorageTrieKey { /// /// Used to efficiently index storage values by both account address and storage key. /// The encoding ensures lexicographic ordering: first by address, then by storage key. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct HashedStorageKey { /// Hashed account address pub hashed_address: B256, diff --git a/crates/optimism/trie/src/db/store.rs b/crates/optimism/trie/src/db/store.rs index 73f3da5d08b..9be13b2efb7 100644 --- a/crates/optimism/trie/src/db/store.rs +++ b/crates/optimism/trie/src/db/store.rs @@ -72,8 +72,14 @@ impl OpProofsStorage for MdbxProofsStorage { = MdbxTrieCursor> where Self: 'tx; - type StorageCursor = MdbxStorageCursor; - type AccountHashedCursor = MdbxAccountCursor; + type StorageCursor<'tx> + = MdbxStorageCursor> + where + Self: 'tx; + type AccountHashedCursor<'tx> + = MdbxAccountCursor> + where + Self: 'tx; async fn store_account_branches( &self, @@ -206,19 +212,29 @@ impl OpProofsStorage for MdbxProofsStorage { Ok(MdbxTrieCursor::new(cursor, max_block_number, None)) } - fn storage_hashed_cursor( + fn storage_hashed_cursor<'tx>( &self, - _hashed_address: B256, - _max_block_number: u64, - ) -> OpProofsStorageResult { - unimplemented!() + hashed_address: B256, + max_block_number: u64, + ) -> OpProofsStorageResult> { + let tx = self.env.tx().map_err(|e| OpProofsStorageError::Other(e.into()))?; + let cursor = tx + .cursor_dup_read::() + .map_err(|e| OpProofsStorageError::Other(e.into()))?; + + Ok(MdbxStorageCursor::new(cursor, max_block_number, hashed_address)) } - fn account_hashed_cursor( + fn account_hashed_cursor<'tx>( &self, - _max_block_number: u64, - ) -> OpProofsStorageResult { - unimplemented!() + max_block_number: u64, + ) -> OpProofsStorageResult> { + let tx = self.env.tx().map_err(|e| OpProofsStorageError::Other(e.into()))?; + let cursor = tx + .cursor_dup_read::() + .map_err(|e| OpProofsStorageError::Other(e.into()))?; + + Ok(MdbxAccountCursor::new(cursor, max_block_number)) } async fn store_trie_updates( diff --git a/crates/optimism/trie/src/in_memory.rs b/crates/optimism/trie/src/in_memory.rs index 4f616da2c89..babdfcf53ec 100644 --- a/crates/optimism/trie/src/in_memory.rs +++ b/crates/optimism/trie/src/in_memory.rs @@ -382,8 +382,8 @@ impl OpProofsHashedCursor for InMemoryAccountCursor { impl OpProofsStorage for InMemoryProofsStorage { type StorageTrieCursor<'tx> = InMemoryTrieCursor; type AccountTrieCursor<'tx> = InMemoryTrieCursor; - type StorageCursor = InMemoryStorageCursor; - type AccountHashedCursor = InMemoryAccountCursor; + type StorageCursor<'tx> = InMemoryStorageCursor; + type AccountHashedCursor<'tx> = InMemoryAccountCursor; async fn store_account_branches( &self, @@ -480,11 +480,11 @@ impl OpProofsStorage for InMemoryProofsStorage { Ok(InMemoryTrieCursor::new(&inner, None, max_block_number)) } - fn storage_hashed_cursor( + fn storage_hashed_cursor<'tx>( &self, hashed_address: B256, max_block_number: u64, - ) -> OpProofsStorageResult { + ) -> OpProofsStorageResult> { let inner = self .inner .try_read() @@ -492,10 +492,10 @@ impl OpProofsStorage for InMemoryProofsStorage { Ok(InMemoryStorageCursor::new(&inner, hashed_address, max_block_number)) } - fn account_hashed_cursor( + fn account_hashed_cursor<'tx>( &self, max_block_number: u64, - ) -> OpProofsStorageResult { + ) -> OpProofsStorageResult> { let inner = self .inner .try_read() diff --git a/crates/optimism/trie/src/metrics.rs b/crates/optimism/trie/src/metrics.rs index ceef1c3bf30..1477b5dff78 100644 --- a/crates/optimism/trie/src/metrics.rs +++ b/crates/optimism/trie/src/metrics.rs @@ -302,8 +302,14 @@ where = TrieCursorWithMetrics> where S: 'tx; - type StorageCursor = HashedCursorWithMetrics; - type AccountHashedCursor = HashedCursorWithMetrics; + type StorageCursor<'tx> + = HashedCursorWithMetrics> + where + S: 'tx; + type AccountHashedCursor<'tx> + = HashedCursorWithMetrics> + where + S: 'tx; async fn store_account_branches( &self, @@ -416,19 +422,19 @@ where Ok(TrieCursorWithMetrics::new(cursor, self.metrics.clone())) } - fn storage_hashed_cursor( + fn storage_hashed_cursor<'tx>( &self, hashed_address: B256, max_block_number: u64, - ) -> OpProofsStorageResult { + ) -> OpProofsStorageResult> { let cursor = self.storage.storage_hashed_cursor(hashed_address, max_block_number)?; Ok(HashedCursorWithMetrics::new(cursor, self.metrics.clone())) } - fn account_hashed_cursor( + fn account_hashed_cursor<'tx>( &self, max_block_number: u64, - ) -> OpProofsStorageResult { + ) -> OpProofsStorageResult> { let cursor = self.storage.account_hashed_cursor(max_block_number)?; Ok(HashedCursorWithMetrics::new(cursor, self.metrics.clone())) } diff --git a/crates/optimism/trie/src/proof.rs b/crates/optimism/trie/src/proof.rs index 0df47e6e848..08098f13f4b 100644 --- a/crates/optimism/trie/src/proof.rs +++ b/crates/optimism/trie/src/proof.rs @@ -171,21 +171,24 @@ impl + Send + Sync> HashedStorageCursor /// Factory for creating hashed account cursors for [`OpProofsStorage`]. #[derive(Debug, Clone)] -pub struct OpProofsHashedAccountCursorFactory { - storage: Storage, +pub struct OpProofsHashedAccountCursorFactory<'tx, Storage: OpProofsStorage> { + storage: &'tx Storage, block_number: u64, + _marker: core::marker::PhantomData<&'tx ()>, } -impl OpProofsHashedAccountCursorFactory { +impl<'tx, Storage: OpProofsStorage + 'tx> OpProofsHashedAccountCursorFactory<'tx, Storage> { /// Creates a new `OpProofsHashedAccountCursorFactory` instance. - pub const fn new(storage: Storage, block_number: u64) -> Self { - Self { storage, block_number } + pub const fn new(storage: &'tx Storage, block_number: u64) -> Self { + Self { storage, block_number, _marker: core::marker::PhantomData } } } -impl HashedCursorFactory for OpProofsHashedAccountCursorFactory { - type AccountCursor = OpProofsHashedAccountCursor; - type StorageCursor = OpProofsHashedStorageCursor; +impl<'tx, Storage: OpProofsStorage + 'tx> HashedCursorFactory + for OpProofsHashedAccountCursorFactory<'tx, Storage> +{ + type AccountCursor = OpProofsHashedAccountCursor>; + type StorageCursor = OpProofsHashedStorageCursor>; fn hashed_account_cursor(&self) -> Result { Ok(OpProofsHashedAccountCursor::new(self.storage.account_hashed_cursor(self.block_number)?)) @@ -225,13 +228,16 @@ pub trait DatabaseProof<'tx, Storage> { } impl<'tx, Storage: OpProofsStorage + Clone> DatabaseProof<'tx, Storage> - for Proof, OpProofsHashedAccountCursorFactory> + for Proof< + OpProofsTrieCursorFactory<'tx, Storage>, + OpProofsHashedAccountCursorFactory<'tx, Storage>, + > { /// Create a new [`Proof`] instance from [`OpProofsStorage`]. fn from_tx(storage: &'tx Storage, block_number: u64) -> Self { Self::new( OpProofsTrieCursorFactory::new(storage, block_number), - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), ) } @@ -251,7 +257,7 @@ impl<'tx, Storage: OpProofsStorage + Clone> DatabaseProof<'tx, Storage> &nodes_sorted, )) .with_hashed_cursor_factory(HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, )) .with_prefix_sets_mut(input.prefix_sets) @@ -273,7 +279,7 @@ impl<'tx, Storage: OpProofsStorage + Clone> DatabaseProof<'tx, Storage> &nodes_sorted, )) .with_hashed_cursor_factory(HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, )) .with_prefix_sets_mut(input.prefix_sets) @@ -308,14 +314,14 @@ pub trait DatabaseStorageProof<'tx, Storage> { impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStorageProof<'tx, Storage> for StorageProof< OpProofsTrieCursorFactory<'tx, Storage>, - OpProofsHashedAccountCursorFactory, + OpProofsHashedAccountCursorFactory<'tx, Storage>, > { /// Create a new [`StorageProof`] from [`OpProofsStorage`] and account address. fn from_tx(storage: &'tx Storage, block_number: u64, address: Address) -> Self { Self::new( OpProofsTrieCursorFactory::new(storage, block_number), - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), address, ) } @@ -335,7 +341,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStorageProof<'tx, Stor ); Self::from_tx(storage, block_number, address) .with_hashed_cursor_factory(HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, )) .with_prefix_set_mut(prefix_set) @@ -358,7 +364,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStorageProof<'tx, Stor ); Self::from_tx(storage, block_number, address) .with_hashed_cursor_factory(HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, )) .with_prefix_set_mut(prefix_set) @@ -408,7 +414,7 @@ pub trait DatabaseStateRoot<'tx, Storage: OpProofsStorage + 'tx + Clone>: Sized impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStateRoot<'tx, Storage> for StateRoot< OpProofsTrieCursorFactory<'tx, Storage>, - OpProofsHashedAccountCursorFactory, + OpProofsHashedAccountCursorFactory<'tx, Storage>, > { fn overlay_root( @@ -421,7 +427,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStateRoot<'tx, Storage StateRoot::new( OpProofsTrieCursorFactory::new(storage, block_number), HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, ), ) @@ -439,7 +445,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStateRoot<'tx, Storage StateRoot::new( OpProofsTrieCursorFactory::new(storage, block_number), HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, ), ) @@ -460,7 +466,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStateRoot<'tx, Storage &nodes_sorted, ), HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, ), ) @@ -481,7 +487,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStateRoot<'tx, Storage &nodes_sorted, ), HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, ), ) @@ -504,7 +510,7 @@ pub trait DatabaseStorageRoot<'tx, Storage: OpProofsStorage + 'tx + Clone> { impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStorageRoot<'tx, Storage> for StorageRoot< OpProofsTrieCursorFactory<'tx, Storage>, - OpProofsHashedAccountCursorFactory, + OpProofsHashedAccountCursorFactory<'tx, Storage>, > { fn overlay_root( @@ -519,7 +525,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseStorageRoot<'tx, Stora StorageRoot::new( OpProofsTrieCursorFactory::new(storage, block_number), HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, ), address, @@ -547,13 +553,13 @@ pub trait DatabaseTrieWitness<'tx, Storage: OpProofsStorage + 'tx + Clone> { impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseTrieWitness<'tx, Storage> for TrieWitness< OpProofsTrieCursorFactory<'tx, Storage>, - OpProofsHashedAccountCursorFactory, + OpProofsHashedAccountCursorFactory<'tx, Storage>, > { fn from_tx(storage: &'tx Storage, block_number: u64) -> Self { Self::new( OpProofsTrieCursorFactory::new(storage, block_number), - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), ) } @@ -571,7 +577,7 @@ impl<'tx, Storage: OpProofsStorage + 'tx + Clone> DatabaseTrieWitness<'tx, Stora &nodes_sorted, )) .with_hashed_cursor_factory(HashedPostStateCursorFactory::new( - OpProofsHashedAccountCursorFactory::new(storage.clone(), block_number), + OpProofsHashedAccountCursorFactory::new(storage, block_number), &state_sorted, )) .with_prefix_sets_mut(input.prefix_sets)