From 1f0bd66cfaea3c73fc4cb01ebfa78cd73ac3bce9 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Tue, 18 Nov 2025 16:23:41 +0100 Subject: [PATCH 01/14] Rm redundant PartialEq and Eq impl for db error --- crates/evm/execution-errors/src/trie.rs | 6 +++--- crates/storage/errors/src/db.rs | 4 +++- crates/storage/provider/src/changesets_utils/trie.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/evm/execution-errors/src/trie.rs b/crates/evm/execution-errors/src/trie.rs index 7dd749f0c11..1f331e35ff6 100644 --- a/crates/evm/execution-errors/src/trie.rs +++ b/crates/evm/execution-errors/src/trie.rs @@ -7,7 +7,7 @@ use reth_storage_errors::{db::DatabaseError, provider::ProviderError}; use thiserror::Error; /// State root errors. -#[derive(Error, PartialEq, Eq, Clone, Debug)] +#[derive(Error, Clone, Debug)] pub enum StateRootError { /// Internal database error. #[error(transparent)] @@ -27,7 +27,7 @@ impl From for DatabaseError { } /// Storage root error. -#[derive(Error, PartialEq, Eq, Clone, Debug)] +#[derive(Error, Clone, Debug)] pub enum StorageRootError { /// Internal database error. #[error(transparent)] @@ -43,7 +43,7 @@ impl From for DatabaseError { } /// State proof errors. -#[derive(Error, PartialEq, Eq, Clone, Debug)] +#[derive(Error, Clone, Debug)] pub enum StateProofError { /// Internal database error. #[error(transparent)] diff --git a/crates/storage/errors/src/db.rs b/crates/storage/errors/src/db.rs index b12ad28898f..5331f9f429f 100644 --- a/crates/storage/errors/src/db.rs +++ b/crates/storage/errors/src/db.rs @@ -2,15 +2,17 @@ use alloc::{ boxed::Box, format, string::{String, ToString}, + sync::Arc, vec::Vec, }; use core::{ + error::Error, fmt::{Debug, Display}, str::FromStr, }; /// Database error type. -#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum DatabaseError { /// Failed to open the database. #[error("failed to open the database: {_0}")] diff --git a/crates/storage/provider/src/changesets_utils/trie.rs b/crates/storage/provider/src/changesets_utils/trie.rs index f4365aab103..cc14b516b30 100644 --- a/crates/storage/provider/src/changesets_utils/trie.rs +++ b/crates/storage/provider/src/changesets_utils/trie.rs @@ -140,7 +140,7 @@ pub fn storage_trie_wiped_changeset_iter( // Due to the ordering closure passed to `merge_join_by` it's not possible for either // value to be an error here. debug_assert!(changed.is_ok(), "unreachable error condition: {changed:?}"); - debug_assert_eq!(changed, _wiped); + debug_assert_eq!(*changed.as_ref().unwrap(), _wiped.unwrap()); changed } })) From 23828f5594bf7023281400f4179463e60f79f41c Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Tue, 18 Nov 2025 16:26:55 +0100 Subject: [PATCH 02/14] Add error trait obj variant --- crates/storage/errors/src/db.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/storage/errors/src/db.rs b/crates/storage/errors/src/db.rs index 5331f9f429f..2eaf2fe44d1 100644 --- a/crates/storage/errors/src/db.rs +++ b/crates/storage/errors/src/db.rs @@ -50,6 +50,9 @@ pub enum DatabaseError { /// Other unspecified error. #[error("{_0}")] Other(String), + /// Other unspecified error. + #[error(transparent)] + Custom(#[from] Arc), } /// Common error struct to propagate implementation-specific error information. From 649aaf3ce063038d8e916b39ecfef1b35afc48f8 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Tue, 18 Nov 2025 17:30:51 +0100 Subject: [PATCH 03/14] Rm redundant OpProofsTrieCursorRO trait --- crates/cli/util/src/sigsegv_handler.rs | 2 +- crates/optimism/trie/src/api.rs | 30 ++---------- crates/optimism/trie/src/backfill.rs | 7 ++- crates/optimism/trie/src/cursor.rs | 8 +-- crates/optimism/trie/src/db/cursor.rs | 68 +++++++++++++------------- crates/optimism/trie/src/db/store.rs | 14 ++++-- crates/optimism/trie/src/in_memory.rs | 18 ++++--- crates/optimism/trie/src/lib.rs | 2 +- crates/optimism/trie/src/metrics.rs | 29 +++++------ crates/optimism/trie/tests/lib.rs | 2 +- 10 files changed, 87 insertions(+), 93 deletions(-) diff --git a/crates/cli/util/src/sigsegv_handler.rs b/crates/cli/util/src/sigsegv_handler.rs index dabbf866cee..eeca446b72a 100644 --- a/crates/cli/util/src/sigsegv_handler.rs +++ b/crates/cli/util/src/sigsegv_handler.rs @@ -126,7 +126,7 @@ pub fn install() { libc::sigaltstack(&raw const alt_stack, ptr::null_mut()); let mut sa: libc::sigaction = mem::zeroed(); - sa.sa_sigaction = print_stack_trace as libc::sighandler_t; + sa.sa_sigaction = print_stack_trace as *const () as libc::sighandler_t; sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; libc::sigemptyset(&raw mut sa.sa_mask); libc::sigaction(libc::SIGSEGV, &raw const sa, ptr::null_mut()); diff --git a/crates/optimism/trie/src/api.rs b/crates/optimism/trie/src/api.rs index c43c852e5b6..28da7d149db 100644 --- a/crates/optimism/trie/src/api.rs +++ b/crates/optimism/trie/src/api.rs @@ -5,31 +5,11 @@ use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; use auto_impl::auto_impl; use reth_primitives_traits::Account; -use reth_trie::{updates::TrieUpdates, BranchNodeCompact, HashedPostState, Nibbles}; +use reth_trie::{ + trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, HashedPostState, Nibbles, +}; use std::{fmt::Debug, time::Duration}; -/// Seeks and iterates over trie nodes in the database by path (lexicographical order) -pub trait OpProofsTrieCursorRO: Send + Sync { - /// Seek to an exact path, otherwise return None if not found. - fn seek_exact( - &mut self, - path: Nibbles, - ) -> OpProofsStorageResult>; - - /// Seek to a path, otherwise return the first path greater than the given path - /// lexicographically. - fn seek( - &mut self, - path: Nibbles, - ) -> OpProofsStorageResult>; - - /// Move the cursor to the next path and return it. - fn next(&mut self) -> OpProofsStorageResult>; - - /// Get the current path. - fn current(&mut self) -> OpProofsStorageResult>; -} - /// Seeks and iterates over hashed entries in the database by key. pub trait OpProofsHashedCursorRO: Send + Sync { /// Value returned by the cursor. @@ -90,12 +70,12 @@ pub struct OperationDurations { #[auto_impl(Arc)] pub trait OpProofsStore: Send + Sync + Debug { /// Cursor for iterating over trie branches. - type StorageTrieCursor<'tx>: OpProofsTrieCursorRO + 'tx + type StorageTrieCursor<'tx>: TrieCursor + 'tx where Self: 'tx; /// Cursor for iterating over account trie branches. - type AccountTrieCursor<'tx>: OpProofsTrieCursorRO + 'tx + type AccountTrieCursor<'tx>: TrieCursor + 'tx where Self: 'tx; diff --git a/crates/optimism/trie/src/backfill.rs b/crates/optimism/trie/src/backfill.rs index 2de8f864567..ac0e7adddac 100644 --- a/crates/optimism/trie/src/backfill.rs +++ b/crates/optimism/trie/src/backfill.rs @@ -348,13 +348,16 @@ impl<'a, Tx: DbTx, S: OpProofsStore + Send> BackfillJob<'a, Tx, S> { #[cfg(test)] mod tests { use super::*; - use crate::{InMemoryProofsStorage, OpProofsHashedCursorRO, OpProofsTrieCursorRO}; + use crate::{InMemoryProofsStorage, OpProofsHashedCursorRO}; use alloy_primitives::{keccak256, Address, U256}; use reth_db::{ cursor::DbCursorRW, test_utils::create_test_rw_db, transaction::DbTxMut, Database, }; use reth_primitives_traits::Account; - use reth_trie::{BranchNodeCompact, StorageTrieEntry, StoredNibbles, StoredNibblesSubKey}; + use reth_trie::{ + trie_cursor::TrieCursor, BranchNodeCompact, StorageTrieEntry, StoredNibbles, + StoredNibblesSubKey, + }; use std::sync::Arc; /// Helper function to create a test branch node diff --git a/crates/optimism/trie/src/cursor.rs b/crates/optimism/trie/src/cursor.rs index 8d6d0ae840e..8eff47d0e33 100644 --- a/crates/optimism/trie/src/cursor.rs +++ b/crates/optimism/trie/src/cursor.rs @@ -1,7 +1,7 @@ //! Implementation of [`HashedCursor`] and [`TrieCursor`] for //! [`OpProofsStorage`](crate::OpProofsStorage). -use crate::{OpProofsHashedCursorRO, OpProofsTrieCursorRO}; +use crate::OpProofsHashedCursorRO; use alloy_primitives::{B256, U256}; use derive_more::{Constructor, From}; use reth_db::DatabaseError; @@ -12,13 +12,13 @@ use reth_trie::{ BranchNodeCompact, Nibbles, }; -/// Manages reading storage or account trie nodes from [`OpProofsTrieCursorRO`]. +/// Manages reading storage or account trie nodes from [`TrieCursor`]. #[derive(Debug, Clone, Constructor, From)] -pub struct OpProofsTrieCursor(pub C); +pub struct OpProofsTrieCursor(pub C); impl TrieCursor for OpProofsTrieCursor where - C: OpProofsTrieCursorRO, + C: TrieCursor, { #[inline] fn seek_exact( diff --git a/crates/optimism/trie/src/db/cursor.rs b/crates/optimism/trie/src/db/cursor.rs index 5982d359400..02e26d4d32b 100644 --- a/crates/optimism/trie/src/db/cursor.rs +++ b/crates/optimism/trie/src/db/cursor.rs @@ -5,17 +5,17 @@ use crate::{ AccountTrieHistory, HashedAccountHistory, HashedStorageHistory, HashedStorageKey, MaybeDeleted, StorageTrieHistory, StorageTrieKey, VersionedValue, }, - OpProofsHashedCursorRO, OpProofsStorageResult, OpProofsTrieCursorRO, + OpProofsHashedCursorRO, OpProofsStorageResult, }; use alloy_primitives::{B256, U256}; use reth_db::{ cursor::{DbCursorRO, DbDupCursorRO}, table::{DupSort, Table}, transaction::DbTx, - Database, DatabaseEnv, + Database, DatabaseEnv, DatabaseError, }; use reth_primitives_traits::Account; -use reth_trie::{BranchNodeCompact, Nibbles, StoredNibbles}; +use reth_trie::{trie_cursor::TrieCursor, BranchNodeCompact, Nibbles, StoredNibbles}; /// Generic alias for dup cursor for T pub(crate) type Dup<'tx, T> = <::TX as DbTx>::DupCursor; @@ -141,7 +141,7 @@ where } } -/// MDBX implementation of [`OpProofsTrieCursorRO`]. +/// MDBX implementation of [`TrieCursor`]. #[derive(Debug)] pub struct MdbxTrieCursor { inner: BlockNumberVersionedCursor, @@ -160,14 +160,14 @@ impl< } } -impl OpProofsTrieCursorRO for MdbxTrieCursor +impl TrieCursor for MdbxTrieCursor where Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, { fn seek_exact( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { self.inner .seek_exact(StoredNibbles(path)) .map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node))) @@ -176,29 +176,29 @@ where fn seek( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { self.inner .seek(StoredNibbles(path)) .map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node))) } - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { self.inner.next().map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node))) } - fn current(&mut self) -> OpProofsStorageResult> { + fn current(&mut self) -> Result, DatabaseError> { Ok(self.inner.cursor.current().map(|opt| opt.map(|(StoredNibbles(n), _)| n))?) } } -impl OpProofsTrieCursorRO for MdbxTrieCursor +impl TrieCursor for MdbxTrieCursor where Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, { fn seek_exact( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { let key = StorageTrieKey::new(address, StoredNibbles(path)); return self.inner.seek_exact(key).map(|opt| { @@ -211,7 +211,7 @@ where fn seek( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { let key = StorageTrieKey::new(address, StoredNibbles(path)); return self.inner.seek(key).map(|opt| { @@ -221,7 +221,7 @@ where Ok(None) } - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { return self.inner.next().map(|opt| { opt.and_then(|(k, node)| (k.hashed_address == address).then_some((k.path.0, node))) @@ -230,7 +230,7 @@ where Ok(None) } - fn current(&mut self) -> OpProofsStorageResult> { + fn current(&mut self) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { return Ok(self.inner.cursor.current().map(|opt| { opt.and_then(|(k, _)| (k.hashed_address == address).then_some(k.path.0)) @@ -930,7 +930,7 @@ mod tests { let mut cur = account_trie_cursor(&tx, 100); // Wrapper should return (Nibbles, BranchNodeCompact) - let out = OpProofsTrieCursorRO::seek_exact(&mut cur, k).expect("ok").expect("some"); + let out = TrieCursor::seek_exact(&mut cur, k).expect("ok").expect("some"); assert_eq!(out.0, k); } @@ -949,7 +949,7 @@ mod tests { let tx = db.tx().expect("ro tx"); let mut cur = account_trie_cursor(&tx, 10); - let out = OpProofsTrieCursorRO::seek_exact(&mut cur, k).expect("ok"); + let out = TrieCursor::seek_exact(&mut cur, k).expect("ok"); assert!(out.is_none(), "account seek_exact must filter tombstone"); } @@ -970,15 +970,15 @@ mod tests { let mut cur = account_trie_cursor(&tx, 100); // seek at k1 - let out1 = OpProofsTrieCursorRO::seek(&mut cur, k1).expect("ok").expect("some"); + let out1 = TrieCursor::seek(&mut cur, k1).expect("ok").expect("some"); assert_eq!(out1.0, k1); // current should be k1 - let cur_k = OpProofsTrieCursorRO::current(&mut cur).expect("ok").expect("some"); + let cur_k = TrieCursor::current(&mut cur).expect("ok").expect("some"); assert_eq!(cur_k, k1); // next should move to k2 - let out2 = OpProofsTrieCursorRO::next(&mut cur).expect("ok").expect("some"); + let out2 = TrieCursor::next(&mut cur).expect("ok").expect("some"); assert_eq!(out2.0, k2); } @@ -1004,12 +1004,12 @@ mod tests { // Cursor bound to A must not see B’s data let mut cur_a = storage_trie_cursor(&tx, 100, addr_a); - let out_a = OpProofsTrieCursorRO::seek_exact(&mut cur_a, path).expect("ok"); + let out_a = TrieCursor::seek_exact(&mut cur_a, path).expect("ok"); assert!(out_a.is_none(), "no data for addr A"); // Cursor bound to B should see it let mut cur_b = storage_trie_cursor(&tx, 100, addr_b); - let out_b = OpProofsTrieCursorRO::seek_exact(&mut cur_b, path).expect("ok").expect("some"); + let out_b = TrieCursor::seek_exact(&mut cur_b, path).expect("ok").expect("some"); assert_eq!(out_b.0, path); } @@ -1039,15 +1039,15 @@ mod tests { let mut cur_a = storage_trie_cursor(&tx, 100, addr_a); // seek at p1: for A there is no p1; the next key >= p1 under A is p2 - let out = OpProofsTrieCursorRO::seek(&mut cur_a, p1).expect("ok").expect("some"); + let out = TrieCursor::seek(&mut cur_a, p1).expect("ok").expect("some"); assert_eq!(out.0, p2); // seek at p2: exact match - let out = OpProofsTrieCursorRO::seek(&mut cur_a, p2).expect("ok").expect("some"); + let out = TrieCursor::seek(&mut cur_a, p2).expect("ok").expect("some"); assert_eq!(out.0, p2); // seek at p3: no p3 under A; no next key ≥ p3 under A → None - let out = OpProofsTrieCursorRO::seek(&mut cur_a, p3).expect("ok"); + let out = TrieCursor::seek(&mut cur_a, p3).expect("ok"); assert!(out.is_none(), "no key ≥ p3 under A"); } @@ -1056,15 +1056,15 @@ mod tests { let tx = db.tx().expect("ro tx"); let mut cur_a = storage_trie_cursor(&tx, 100, addr_a); - let out = OpProofsTrieCursorRO::next(&mut cur_a).expect("ok").expect("some"); + let out = TrieCursor::next(&mut cur_a).expect("ok").expect("some"); assert_eq!(out.0, p2); // next should yield None as there is no further key under A - let out = OpProofsTrieCursorRO::next(&mut cur_a).expect("ok"); + let out = TrieCursor::next(&mut cur_a).expect("ok"); assert!(out.is_none(), "no more keys under A"); // current should return None - let out = OpProofsTrieCursorRO::current(&mut cur_a).expect("ok"); + let out = TrieCursor::current(&mut cur_a).expect("ok"); assert!(out.is_none(), "no current key after EOF"); } @@ -1074,15 +1074,15 @@ mod tests { let mut cur_a = storage_trie_cursor(&tx, 100, addr_a); // seek_exact at p1: no exact match - let out = OpProofsTrieCursorRO::seek_exact(&mut cur_a, p1).expect("ok"); + let out = TrieCursor::seek_exact(&mut cur_a, p1).expect("ok"); assert!(out.is_none(), "no exact p1 under A"); // seek_exact at p2: exact match - let out = OpProofsTrieCursorRO::seek_exact(&mut cur_a, p2).expect("ok").expect("some"); + let out = TrieCursor::seek_exact(&mut cur_a, p2).expect("ok").expect("some"); assert_eq!(out.0, p2); // seek_exact at p3: no exact match - let out = OpProofsTrieCursorRO::seek_exact(&mut cur_a, p3).expect("ok"); + let out = TrieCursor::seek_exact(&mut cur_a, p3).expect("ok"); assert!(out.is_none(), "no exact p3 under A"); } } @@ -1108,10 +1108,10 @@ mod tests { let mut cur_a = storage_trie_cursor(&tx, 100, addr_a); // position at p1 (A) - let _ = OpProofsTrieCursorRO::seek_exact(&mut cur_a, p1).expect("ok").expect("some"); + let _ = TrieCursor::seek_exact(&mut cur_a, p1).expect("ok").expect("some"); // next should reach boundary; impl filters different address and returns None - let out = OpProofsTrieCursorRO::next(&mut cur_a).expect("ok"); + let out = TrieCursor::next(&mut cur_a).expect("ok"); assert!(out.is_none(), "next() should stop when next key is a different address"); } @@ -1131,9 +1131,9 @@ mod tests { let tx = db.tx().expect("ro tx"); let mut cur = storage_trie_cursor(&tx, 100, addr); - let _ = OpProofsTrieCursorRO::seek_exact(&mut cur, p).expect("ok").expect("some"); + let _ = TrieCursor::seek_exact(&mut cur, p).expect("ok").expect("some"); - let now = OpProofsTrieCursorRO::current(&mut cur).expect("ok").expect("some"); + let now = TrieCursor::current(&mut cur).expect("ok").expect("some"); assert_eq!(now, p); } diff --git a/crates/optimism/trie/src/db/store.rs b/crates/optimism/trie/src/db/store.rs index 6098a581283..683f56a446a 100644 --- a/crates/optimism/trie/src/db/store.rs +++ b/crates/optimism/trie/src/db/store.rs @@ -11,7 +11,7 @@ use crate::{ MdbxAccountCursor, MdbxStorageCursor, MdbxTrieCursor, }, BlockStateDiff, OpProofsHashedCursorRO, OpProofsStorageError, OpProofsStorageResult, - OpProofsStore, OpProofsTrieCursorRO, + OpProofsStore, }; use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; @@ -24,7 +24,9 @@ use reth_db::{ Database, DatabaseEnv, DatabaseError, }; use reth_primitives_traits::Account; -use reth_trie::{updates::StorageTrieUpdates, BranchNodeCompact, HashedStorage, Nibbles}; +use reth_trie::{ + trie_cursor::TrieCursor, updates::StorageTrieUpdates, BranchNodeCompact, HashedStorage, Nibbles, +}; use std::{cmp::max, ops::RangeBounds, path::Path}; /// MDBX implementation of [`OpProofsStore`]. @@ -275,7 +277,13 @@ impl MdbxProofsStorage { // Yet to have any update for the current block number - So just using up to // previous block number let mut ro = self.storage_trie_cursor(hashed_address, block_number - 1)?; - let keys = self.wipe_storage(tx, block_number, hashed_address, || ro.next())?; + let Some(keys) = self + .wipe_storage(tx, block_number, hashed_address, || ro.next()) + .map_err(|e| { + e.downcast_ref::() + .expect("should be caught by catch all variant wrapping db error") + })?; + storage_trie_keys.extend(keys); // Skip any further processing for this hashed_address diff --git a/crates/optimism/trie/src/in_memory.rs b/crates/optimism/trie/src/in_memory.rs index 0efb501969d..b781be91101 100644 --- a/crates/optimism/trie/src/in_memory.rs +++ b/crates/optimism/trie/src/in_memory.rs @@ -2,12 +2,14 @@ use crate::{ api::WriteCounts, BlockStateDiff, OpProofsHashedCursorRO, OpProofsStorageResult, OpProofsStore, - OpProofsTrieCursorRO, }; use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; +use reth_db::DatabaseError; use reth_primitives_traits::Account; -use reth_trie::{updates::TrieUpdates, BranchNodeCompact, HashedPostState, Nibbles}; +use reth_trie::{ + trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, HashedPostState, Nibbles, +}; use std::{collections::BTreeMap, sync::Arc}; use tokio::sync::RwLock; @@ -156,7 +158,7 @@ impl InMemoryProofsStorage { } } -/// In-memory implementation of [`OpProofsTrieCursorRO`]. +/// In-memory implementation of [`TrieCursor`]. #[derive(Debug)] pub struct InMemoryTrieCursor { /// Current position in the iteration (-1 means not positioned yet) @@ -223,11 +225,11 @@ impl InMemoryTrieCursor { } } -impl OpProofsTrieCursorRO for InMemoryTrieCursor { +impl TrieCursor for InMemoryTrieCursor { fn seek_exact( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { if let Some(pos) = self.entries.iter().position(|(p, _)| *p == path) { self.position = pos as isize; Ok(Some(self.entries[pos].clone())) @@ -239,7 +241,7 @@ impl OpProofsTrieCursorRO for InMemoryTrieCursor { fn seek( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { if let Some(pos) = self.entries.iter().position(|(p, _)| *p >= path) { self.position = pos as isize; Ok(Some(self.entries[pos].clone())) @@ -248,7 +250,7 @@ impl OpProofsTrieCursorRO for InMemoryTrieCursor { } } - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { self.position += 1; if self.position >= 0 && (self.position as usize) < self.entries.len() { Ok(Some(self.entries[self.position as usize].clone())) @@ -257,7 +259,7 @@ impl OpProofsTrieCursorRO for InMemoryTrieCursor { } } - fn current(&mut self) -> OpProofsStorageResult> { + fn current(&mut self) -> Result, DatabaseError> { if self.position >= 0 && (self.position as usize) < self.entries.len() { Ok(Some(self.entries[self.position as usize].0)) } else { diff --git a/crates/optimism/trie/src/lib.rs b/crates/optimism/trie/src/lib.rs index cee57d0af82..f8bff214704 100644 --- a/crates/optimism/trie/src/lib.rs +++ b/crates/optimism/trie/src/lib.rs @@ -13,7 +13,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] pub mod api; -pub use api::{BlockStateDiff, OpProofsHashedCursorRO, OpProofsStore, OpProofsTrieCursorRO}; +pub use api::{BlockStateDiff, OpProofsHashedCursorRO, OpProofsStore}; pub mod backfill; pub use backfill::BackfillJob; diff --git a/crates/optimism/trie/src/metrics.rs b/crates/optimism/trie/src/metrics.rs index bb625c6cd05..e8a36556db2 100644 --- a/crates/optimism/trie/src/metrics.rs +++ b/crates/optimism/trie/src/metrics.rs @@ -3,15 +3,15 @@ use crate::{ api::{OperationDurations, WriteCounts}, cursor, BlockStateDiff, OpProofsHashedCursorRO, OpProofsStorageResult, OpProofsStore, - OpProofsTrieCursorRO, }; use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; use derive_more::Constructor; use metrics::{Counter, Gauge, Histogram}; +use reth_db::DatabaseError; use reth_metrics::Metrics; use reth_primitives_traits::Account; -use reth_trie::{BranchNodeCompact, Nibbles}; +use reth_trie::{trie_cursor::TrieCursor, BranchNodeCompact, Nibbles}; use std::{ fmt::Debug, future::Future, @@ -23,8 +23,9 @@ use strum::{EnumCount, EnumIter, IntoEnumIterator}; /// Alias for [`OpProofsStorageWithMetrics`]. pub type OpProofsStorage = OpProofsStorageWithMetrics; -/// Alias for [`OpProofsTrieCursorRO`](cursor::OpProofsTrieCursor) with metrics layer. -pub type OpProofsTrieCursor = cursor::OpProofsTrieCursor>; +/// Alias for [`TrieCursor`](cursor::OpProofsTrieCursor) with metrics layer. +pub type OpProofsTrieCursor = + cursor::OpProofsTrieCursor>; /// Alias for [`OpProofsHashedAccountCursor`](cursor::OpProofsHashedAccountCursor) with metrics /// layer. @@ -243,19 +244,19 @@ impl BlockMetrics { } } -/// Wrapper for [`OpProofsTrieCursorRO`] that records metrics. +/// Wrapper for [`TrieCursor`] that records metrics. #[derive(Debug, Constructor, Clone)] pub struct OpProofsTrieCursorWithMetrics { cursor: C, metrics: Arc, } -impl OpProofsTrieCursorRO for OpProofsTrieCursorWithMetrics { +impl TrieCursor for OpProofsTrieCursorWithMetrics { #[inline] fn seek_exact( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { self.metrics.record_operation(StorageOperation::TrieCursorSeekExact, || { self.cursor.seek_exact(path) }) @@ -265,17 +266,17 @@ impl OpProofsTrieCursorRO for OpProofsTrieCursorWithMet fn seek( &mut self, path: Nibbles, - ) -> OpProofsStorageResult> { + ) -> Result, DatabaseError> { self.metrics.record_operation(StorageOperation::TrieCursorSeek, || self.cursor.seek(path)) } #[inline] - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { self.metrics.record_operation(StorageOperation::TrieCursorNext, || self.cursor.next()) } #[inline] - fn current(&mut self) -> OpProofsStorageResult> { + fn current(&mut self) -> Result, DatabaseError> { self.metrics.record_operation(StorageOperation::TrieCursorCurrent, || self.cursor.current()) } } @@ -332,19 +333,19 @@ where type StorageTrieCursor<'tx> = OpProofsTrieCursorWithMetrics> where - S: 'tx; + Self: 'tx; type AccountTrieCursor<'tx> = OpProofsTrieCursorWithMetrics> where - S: 'tx; + Self: 'tx; type StorageCursor<'tx> = OpProofsHashedCursorWithMetrics> where - S: 'tx; + Self: 'tx; type AccountHashedCursor<'tx> = OpProofsHashedCursorWithMetrics> where - S: 'tx; + Self: 'tx; #[inline] async fn store_account_branches( diff --git a/crates/optimism/trie/tests/lib.rs b/crates/optimism/trie/tests/lib.rs index 15c5fd2eea8..ef1d798d9c8 100644 --- a/crates/optimism/trie/tests/lib.rs +++ b/crates/optimism/trie/tests/lib.rs @@ -4,7 +4,7 @@ use alloy_eips::{eip1898::BlockWithParent, NumHash}; use alloy_primitives::{map::HashMap, B256, U256}; use reth_optimism_trie::{ db::MdbxProofsStorage, BlockStateDiff, InMemoryProofsStorage, OpProofsHashedCursorRO, - OpProofsStorageError, OpProofsStore, OpProofsTrieCursorRO, + OpProofsStorageError, OpProofsStore, TrieCursor, }; use reth_primitives_traits::Account; use reth_trie::{ From e36e0f54dbf604a407128cb3e7e9bf270d0d41ad Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 10:14:41 +0100 Subject: [PATCH 04/14] fixup! Rm redundant OpProofsTrieCursorRO trait --- crates/optimism/trie/src/cursor.rs | 8 +++---- crates/optimism/trie/src/db/cursor.rs | 30 ++++++++++++++------------- crates/optimism/trie/src/db/store.rs | 8 ++----- crates/optimism/trie/src/metrics.rs | 3 +-- crates/optimism/trie/tests/lib.rs | 5 +++-- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/crates/optimism/trie/src/cursor.rs b/crates/optimism/trie/src/cursor.rs index 8eff47d0e33..4e4fcd05f54 100644 --- a/crates/optimism/trie/src/cursor.rs +++ b/crates/optimism/trie/src/cursor.rs @@ -25,7 +25,7 @@ where &mut self, key: Nibbles, ) -> Result, DatabaseError> { - Ok(self.0.seek_exact(key)?) + self.0.seek_exact(key) } #[inline] @@ -33,17 +33,17 @@ where &mut self, key: Nibbles, ) -> Result, DatabaseError> { - Ok(self.0.seek(key)?) + self.0.seek(key) } #[inline] fn next(&mut self) -> Result, DatabaseError> { - Ok(self.0.next()?) + self.0.next() } #[inline] fn current(&mut self) -> Result, DatabaseError> { - Ok(self.0.current()?) + self.0.current() } } diff --git a/crates/optimism/trie/src/db/cursor.rs b/crates/optimism/trie/src/db/cursor.rs index 02e26d4d32b..8bcf36fa2df 100644 --- a/crates/optimism/trie/src/db/cursor.rs +++ b/crates/optimism/trie/src/db/cursor.rs @@ -168,26 +168,28 @@ where &mut self, path: Nibbles, ) -> Result, DatabaseError> { - self.inner + Ok(self + .inner .seek_exact(StoredNibbles(path)) - .map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node))) + .map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node)))?) } fn seek( &mut self, path: Nibbles, ) -> Result, DatabaseError> { - self.inner + Ok(self + .inner .seek(StoredNibbles(path)) - .map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node))) + .map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node)))?) } fn next(&mut self) -> Result, DatabaseError> { - self.inner.next().map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node))) + Ok(self.inner.next().map(|opt| opt.map(|(StoredNibbles(n), node)| (n, node)))?) } fn current(&mut self) -> Result, DatabaseError> { - Ok(self.inner.cursor.current().map(|opt| opt.map(|(StoredNibbles(n), _)| n))?) + self.inner.cursor.current().map(|opt| opt.map(|(StoredNibbles(n), _)| n)) } } @@ -201,9 +203,9 @@ where ) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { let key = StorageTrieKey::new(address, StoredNibbles(path)); - return self.inner.seek_exact(key).map(|opt| { + return Ok(self.inner.seek_exact(key).map(|opt| { opt.and_then(|(k, node)| (k.hashed_address == address).then_some((k.path.0, node))) - }) + })?) } Ok(None) } @@ -214,27 +216,27 @@ where ) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { let key = StorageTrieKey::new(address, StoredNibbles(path)); - return self.inner.seek(key).map(|opt| { + return Ok(self.inner.seek(key).map(|opt| { opt.and_then(|(k, node)| (k.hashed_address == address).then_some((k.path.0, node))) - }) + })?) } Ok(None) } fn next(&mut self) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { - return self.inner.next().map(|opt| { + return Ok(self.inner.next().map(|opt| { opt.and_then(|(k, node)| (k.hashed_address == address).then_some((k.path.0, node))) - }) + })?) } Ok(None) } fn current(&mut self) -> Result, DatabaseError> { if let Some(address) = self.hashed_address { - return Ok(self.inner.cursor.current().map(|opt| { + return self.inner.cursor.current().map(|opt| { opt.and_then(|(k, _)| (k.hashed_address == address).then_some(k.path.0)) - })?); + }); } Ok(None) } diff --git a/crates/optimism/trie/src/db/store.rs b/crates/optimism/trie/src/db/store.rs index 683f56a446a..351ac5f356c 100644 --- a/crates/optimism/trie/src/db/store.rs +++ b/crates/optimism/trie/src/db/store.rs @@ -277,12 +277,8 @@ impl MdbxProofsStorage { // Yet to have any update for the current block number - So just using up to // previous block number let mut ro = self.storage_trie_cursor(hashed_address, block_number - 1)?; - let Some(keys) = self - .wipe_storage(tx, block_number, hashed_address, || ro.next()) - .map_err(|e| { - e.downcast_ref::() - .expect("should be caught by catch all variant wrapping db error") - })?; + let keys = + self.wipe_storage(tx, block_number, hashed_address, || Ok(ro.next()?))?; storage_trie_keys.extend(keys); diff --git a/crates/optimism/trie/src/metrics.rs b/crates/optimism/trie/src/metrics.rs index e8a36556db2..7b6869ce1e3 100644 --- a/crates/optimism/trie/src/metrics.rs +++ b/crates/optimism/trie/src/metrics.rs @@ -24,8 +24,7 @@ use strum::{EnumCount, EnumIter, IntoEnumIterator}; pub type OpProofsStorage = OpProofsStorageWithMetrics; /// Alias for [`TrieCursor`](cursor::OpProofsTrieCursor) with metrics layer. -pub type OpProofsTrieCursor = - cursor::OpProofsTrieCursor>; +pub type OpProofsTrieCursor = cursor::OpProofsTrieCursor>; /// Alias for [`OpProofsHashedAccountCursor`](cursor::OpProofsHashedAccountCursor) with metrics /// layer. diff --git a/crates/optimism/trie/tests/lib.rs b/crates/optimism/trie/tests/lib.rs index ef1d798d9c8..89623b6cd78 100644 --- a/crates/optimism/trie/tests/lib.rs +++ b/crates/optimism/trie/tests/lib.rs @@ -4,11 +4,12 @@ use alloy_eips::{eip1898::BlockWithParent, NumHash}; use alloy_primitives::{map::HashMap, B256, U256}; use reth_optimism_trie::{ db::MdbxProofsStorage, BlockStateDiff, InMemoryProofsStorage, OpProofsHashedCursorRO, - OpProofsStorageError, OpProofsStore, TrieCursor, + OpProofsStorageError, OpProofsStore, }; use reth_primitives_traits::Account; use reth_trie::{ - updates::TrieUpdates, BranchNodeCompact, HashedPostState, HashedStorage, Nibbles, TrieMask, + trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, HashedPostState, + HashedStorage, Nibbles, TrieMask, }; use serial_test::serial; use std::sync::Arc; From 6c2eadff8d4d214acfdf40d6a5181c69f6b57acc Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 11:13:53 +0100 Subject: [PATCH 05/14] Rm redundant trait OpProofsHashedCursorRO --- crates/optimism/trie/src/api.rs | 27 +++-------- crates/optimism/trie/src/backfill.rs | 6 +-- crates/optimism/trie/src/cursor.rs | 17 ++++--- crates/optimism/trie/src/db/cursor.rs | 65 +++++++++++++++------------ crates/optimism/trie/src/db/store.rs | 9 ++-- crates/optimism/trie/src/in_memory.rs | 31 ++++++++----- crates/optimism/trie/src/lib.rs | 2 +- crates/optimism/trie/src/metrics.rs | 23 +++++++--- crates/optimism/trie/src/provider.rs | 3 +- crates/optimism/trie/tests/lib.rs | 8 ++-- 10 files changed, 102 insertions(+), 89 deletions(-) diff --git a/crates/optimism/trie/src/api.rs b/crates/optimism/trie/src/api.rs index 28da7d149db..5a4f005cb21 100644 --- a/crates/optimism/trie/src/api.rs +++ b/crates/optimism/trie/src/api.rs @@ -6,28 +6,13 @@ use alloy_primitives::{map::HashMap, B256, U256}; use auto_impl::auto_impl; use reth_primitives_traits::Account; use reth_trie::{ - trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, HashedPostState, Nibbles, + hashed_cursor::{HashedCursor, HashedStorageCursor}, + trie_cursor::TrieCursor, + updates::TrieUpdates, + BranchNodeCompact, HashedPostState, Nibbles, }; use std::{fmt::Debug, time::Duration}; -/// Seeks and iterates over hashed entries in the database by key. -pub trait OpProofsHashedCursorRO: Send + Sync { - /// Value returned by the cursor. - type Value: Debug; - - /// Seek an entry greater or equal to the given key and position the cursor there. - /// Returns the first entry with the key greater or equal to the sought key. - fn seek(&mut self, key: B256) -> OpProofsStorageResult>; - - /// Move the cursor to the next entry and return it. - fn next(&mut self) -> OpProofsStorageResult>; - - /// Returns `true` if there are no entries for a given key. - fn is_storage_empty(&mut self) -> OpProofsStorageResult { - Ok(self.seek(B256::ZERO)?.is_none()) - } -} - /// Diff of trie updates and post state for a block. #[derive(Debug, Clone, Default)] pub struct BlockStateDiff { @@ -80,12 +65,12 @@ pub trait OpProofsStore: Send + Sync + Debug { Self: 'tx; /// Cursor for iterating over storage leaves. - type StorageCursor<'tx>: OpProofsHashedCursorRO + 'tx + type StorageCursor<'tx>: HashedStorageCursor + Send + Sync + 'tx where Self: 'tx; /// Cursor for iterating over account leaves. - type AccountHashedCursor<'tx>: OpProofsHashedCursorRO + 'tx + type AccountHashedCursor<'tx>: HashedCursor + Send + Sync + 'tx where Self: 'tx; diff --git a/crates/optimism/trie/src/backfill.rs b/crates/optimism/trie/src/backfill.rs index ac0e7adddac..830da66dd23 100644 --- a/crates/optimism/trie/src/backfill.rs +++ b/crates/optimism/trie/src/backfill.rs @@ -348,15 +348,15 @@ impl<'a, Tx: DbTx, S: OpProofsStore + Send> BackfillJob<'a, Tx, S> { #[cfg(test)] mod tests { use super::*; - use crate::{InMemoryProofsStorage, OpProofsHashedCursorRO}; + use crate::InMemoryProofsStorage; use alloy_primitives::{keccak256, Address, U256}; use reth_db::{ cursor::DbCursorRW, test_utils::create_test_rw_db, transaction::DbTxMut, Database, }; use reth_primitives_traits::Account; use reth_trie::{ - trie_cursor::TrieCursor, BranchNodeCompact, StorageTrieEntry, StoredNibbles, - StoredNibblesSubKey, + hashed_cursor::HashedCursor, trie_cursor::TrieCursor, BranchNodeCompact, StorageTrieEntry, + StoredNibbles, StoredNibblesSubKey, }; use std::sync::Arc; diff --git a/crates/optimism/trie/src/cursor.rs b/crates/optimism/trie/src/cursor.rs index 4e4fcd05f54..78a60f0b0f6 100644 --- a/crates/optimism/trie/src/cursor.rs +++ b/crates/optimism/trie/src/cursor.rs @@ -1,7 +1,6 @@ //! Implementation of [`HashedCursor`] and [`TrieCursor`] for //! [`OpProofsStorage`](crate::OpProofsStorage). -use crate::OpProofsHashedCursorRO; use alloy_primitives::{B256, U256}; use derive_more::{Constructor, From}; use reth_db::DatabaseError; @@ -53,18 +52,18 @@ pub struct OpProofsHashedAccountCursor(pub C); impl HashedCursor for OpProofsHashedAccountCursor where - C: OpProofsHashedCursorRO + Send + Sync, + C: HashedCursor + Send + Sync, { type Value = Account; #[inline] fn seek(&mut self, key: B256) -> Result, DatabaseError> { - Ok(self.0.seek(key)?) + self.0.seek(key) } #[inline] fn next(&mut self) -> Result, DatabaseError> { - Ok(self.0.next()?) + self.0.next() } } @@ -74,27 +73,27 @@ pub struct OpProofsHashedStorageCursor(pub C); impl HashedCursor for OpProofsHashedStorageCursor where - C: OpProofsHashedCursorRO + Send + Sync, + C: HashedCursor + Send + Sync, { type Value = U256; #[inline] fn seek(&mut self, key: B256) -> Result, DatabaseError> { - Ok(self.0.seek(key)?) + self.0.seek(key) } #[inline] fn next(&mut self) -> Result, DatabaseError> { - Ok(self.0.next()?) + self.0.next() } } impl HashedStorageCursor for OpProofsHashedStorageCursor where - C: OpProofsHashedCursorRO + Send + Sync, + C: HashedStorageCursor + Send + Sync, { #[inline] fn is_storage_empty(&mut self) -> Result { - Ok(self.0.is_storage_empty()?) + self.0.is_storage_empty() } } diff --git a/crates/optimism/trie/src/db/cursor.rs b/crates/optimism/trie/src/db/cursor.rs index 8bcf36fa2df..2cc7248c0aa 100644 --- a/crates/optimism/trie/src/db/cursor.rs +++ b/crates/optimism/trie/src/db/cursor.rs @@ -5,7 +5,7 @@ use crate::{ AccountTrieHistory, HashedAccountHistory, HashedStorageHistory, HashedStorageKey, MaybeDeleted, StorageTrieHistory, StorageTrieKey, VersionedValue, }, - OpProofsHashedCursorRO, OpProofsStorageResult, + OpProofsStorageResult, }; use alloy_primitives::{B256, U256}; use reth_db::{ @@ -15,7 +15,11 @@ use reth_db::{ Database, DatabaseEnv, DatabaseError, }; use reth_primitives_traits::Account; -use reth_trie::{trie_cursor::TrieCursor, BranchNodeCompact, Nibbles, StoredNibbles}; +use reth_trie::{ + hashed_cursor::{HashedCursor, HashedStorageCursor}, + trie_cursor::TrieCursor, + BranchNodeCompact, Nibbles, StoredNibbles, +}; /// Generic alias for dup cursor for T pub(crate) type Dup<'tx, T> = <::TX as DbTx>::DupCursor; @@ -242,7 +246,7 @@ where } } -/// MDBX implementation of [`OpProofsHashedCursorRO`] for storage state. +/// MDBX implementation of [`HashedCursor`] for storage state. #[derive(Debug)] pub struct MdbxStorageCursor { inner: BlockNumberVersionedCursor, @@ -259,13 +263,13 @@ where } } -impl OpProofsHashedCursorRO for MdbxStorageCursor +impl HashedCursor for MdbxStorageCursor where Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, { type Value = U256; - fn seek(&mut self, key: B256) -> OpProofsStorageResult> { + fn seek(&mut self, key: B256) -> Result, DatabaseError> { let storage_key = HashedStorageKey::new(self.hashed_address, key); // hashed storage values can be zero, which means the storage slot is deleted, so we should @@ -286,7 +290,7 @@ where Ok(result) } - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { let result = self.inner.next().map(|opt| { opt.and_then(|(k, v)| { // Only return entries that belong to the bound address @@ -306,7 +310,14 @@ where } } -/// MDBX implementation of [`OpProofsHashedCursorRO`] for account state. +impl HashedStorageCursor for MdbxStorageCursor> { + #[inline] + fn is_storage_empty(&mut self) -> Result { + Ok(self.seek(B256::ZERO)?.is_none()) + } +} + +/// MDBX implementation of [`HashedCursor`] for account state. #[derive(Debug)] pub struct MdbxAccountCursor { inner: BlockNumberVersionedCursor, @@ -322,18 +333,18 @@ where } } -impl OpProofsHashedCursorRO for MdbxAccountCursor +impl HashedCursor for MdbxAccountCursor where Cursor: DbCursorRO + DbDupCursorRO + Send + Sync, { type Value = Account; - fn seek(&mut self, key: B256) -> OpProofsStorageResult> { - self.inner.seek(key) + fn seek(&mut self, key: B256) -> Result, DatabaseError> { + Ok(self.inner.seek(key)?) } - fn next(&mut self) -> OpProofsStorageResult> { - self.inner.next() + fn next(&mut self) -> Result, DatabaseError> { + Ok(self.inner.next()?) } } @@ -1154,8 +1165,7 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = storage_cursor(&tx, 100, addr); - let (got_slot, got_val) = - OpProofsHashedCursorRO::seek(&mut cur, slot).expect("ok").expect("some"); + let (got_slot, got_val) = cur.seek(slot).expect("ok").expect("some"); assert_eq!(got_slot, slot); assert_eq!(got_val, U256::from(7)); } @@ -1176,7 +1186,7 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = storage_cursor(&tx, 10, addr); - let out = OpProofsHashedCursorRO::seek(&mut cur, slot).expect("ok"); + let out = cur.seek(slot).expect("ok"); assert!(out.is_none(), "wrapper must filter tombstoned latest"); } @@ -1197,10 +1207,10 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = storage_cursor(&tx, 100, addr); - let (k1, v1) = OpProofsHashedCursorRO::seek(&mut cur, s1).expect("ok").expect("some"); + let (k1, v1) = cur.seek(s1).expect("ok").expect("some"); assert_eq!((k1, v1), (s1, U256::from(11))); - let (k2, v2) = OpProofsHashedCursorRO::next(&mut cur).expect("ok").expect("some"); + let (k2, v2) = cur.next().expect("ok").expect("some"); assert_eq!((k2, v2), (s2, U256::from(22))); } @@ -1230,22 +1240,22 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = storage_cursor(&tx, 100, addr1); - let (k1, v1) = OpProofsHashedCursorRO::next(&mut cur).expect("ok").expect("some"); + let (k1, v1) = cur.next().expect("ok").expect("some"); assert_eq!((k1, v1), (s1, U256::from(11))); - let (k2, v2) = OpProofsHashedCursorRO::next(&mut cur).expect("ok").expect("some"); + let (k2, v2) = cur.next().expect("ok").expect("some"); assert_eq!((k2, v2), (s2, U256::from(22))); - let out = OpProofsHashedCursorRO::next(&mut cur).expect("ok"); + let out = cur.next().expect("ok"); assert!(out.is_none(), "should stop at address boundary"); - let (k1, v1) = OpProofsHashedCursorRO::seek(&mut cur, s1).expect("ok").expect("some"); + let (k1, v1) = cur.seek(s1).expect("ok").expect("some"); assert_eq!((k1, v1), (s1, U256::from(11))); - let (k2, v2) = OpProofsHashedCursorRO::seek(&mut cur, s2).expect("ok").expect("some"); + let (k2, v2) = cur.seek(s2).expect("ok").expect("some"); assert_eq!((k2, v2), (s2, U256::from(22))); - let out = OpProofsHashedCursorRO::seek(&mut cur, s3).expect("ok"); + let out = cur.seek(s3).expect("ok"); assert!(out.is_none(), "should not see keys from other address"); } @@ -1263,8 +1273,7 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = account_cursor(&tx, 100); - let (got_key, _acc) = - OpProofsHashedCursorRO::seek(&mut cur, key).expect("ok").expect("some"); + let (got_key, _acc) = cur.seek(key).expect("ok").expect("some"); assert_eq!(got_key, key); } @@ -1283,7 +1292,7 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = account_cursor(&tx, 10); - let out = OpProofsHashedCursorRO::seek(&mut cur, key).expect("ok"); + let out = cur.seek(key).expect("ok"); assert!(out.is_none(), "wrapper must filter tombstoned latest"); } @@ -1303,10 +1312,10 @@ mod tests { let tx = db.tx().expect("ro"); let mut cur = account_cursor(&tx, 100); - let (got1, _) = OpProofsHashedCursorRO::seek(&mut cur, k1).expect("ok").expect("some"); + let (got1, _) = cur.seek(k1).expect("ok").expect("some"); assert_eq!(got1, k1); - let (got2, _) = OpProofsHashedCursorRO::next(&mut cur).expect("ok").expect("some"); + let (got2, _) = cur.next().expect("ok").expect("some"); assert_eq!(got2, k2); } } diff --git a/crates/optimism/trie/src/db/store.rs b/crates/optimism/trie/src/db/store.rs index 351ac5f356c..7e54cbbd47c 100644 --- a/crates/optimism/trie/src/db/store.rs +++ b/crates/optimism/trie/src/db/store.rs @@ -10,8 +10,7 @@ use crate::{ }, MdbxAccountCursor, MdbxStorageCursor, MdbxTrieCursor, }, - BlockStateDiff, OpProofsHashedCursorRO, OpProofsStorageError, OpProofsStorageResult, - OpProofsStore, + BlockStateDiff, OpProofsStorageError, OpProofsStorageResult, OpProofsStore, }; use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; @@ -25,7 +24,8 @@ use reth_db::{ }; use reth_primitives_traits::Account; use reth_trie::{ - trie_cursor::TrieCursor, updates::StorageTrieUpdates, BranchNodeCompact, HashedStorage, Nibbles, + hashed_cursor::HashedCursor, trie_cursor::TrieCursor, updates::StorageTrieUpdates, + BranchNodeCompact, HashedStorage, Nibbles, }; use std::{cmp::max, ops::RangeBounds, path::Path}; @@ -302,7 +302,8 @@ impl MdbxProofsStorage { // Yet to have any update for the current block number - So just using up to // previous block number let mut ro = self.storage_hashed_cursor(hashed_address, block_number - 1)?; - let keys = self.wipe_storage(tx, block_number, hashed_address, || ro.next())?; + let keys = + self.wipe_storage(tx, block_number, hashed_address, || Ok(ro.next()?))?; hashed_storage_keys.extend(keys); // Skip any further processing for this hashed_address continue; diff --git a/crates/optimism/trie/src/in_memory.rs b/crates/optimism/trie/src/in_memory.rs index b781be91101..437e9ce6e6a 100644 --- a/crates/optimism/trie/src/in_memory.rs +++ b/crates/optimism/trie/src/in_memory.rs @@ -1,14 +1,15 @@ //! In-memory implementation of [`OpProofsStore`] for testing purposes -use crate::{ - api::WriteCounts, BlockStateDiff, OpProofsHashedCursorRO, OpProofsStorageResult, OpProofsStore, -}; +use crate::{api::WriteCounts, BlockStateDiff, OpProofsStorageResult, OpProofsStore}; use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; use reth_db::DatabaseError; use reth_primitives_traits::Account; use reth_trie::{ - trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, HashedPostState, Nibbles, + hashed_cursor::{HashedCursor, HashedStorageCursor}, + trie_cursor::TrieCursor, + updates::TrieUpdates, + BranchNodeCompact, HashedPostState, Nibbles, }; use std::{collections::BTreeMap, sync::Arc}; use tokio::sync::RwLock; @@ -268,7 +269,7 @@ impl TrieCursor for InMemoryTrieCursor { } } -/// In-memory implementation of [`OpProofsHashedCursorRO`] for storage slots +/// In-memory implementation of [`HashedCursor`] for storage slots #[derive(Debug)] pub struct InMemoryStorageCursor { /// Current position in the iteration (-1 means not positioned yet) @@ -315,10 +316,10 @@ impl InMemoryStorageCursor { } } -impl OpProofsHashedCursorRO for InMemoryStorageCursor { +impl HashedCursor for InMemoryStorageCursor { type Value = U256; - fn seek(&mut self, key: B256) -> OpProofsStorageResult> { + fn seek(&mut self, key: B256) -> Result, DatabaseError> { if let Some(pos) = self.entries.iter().position(|(k, _)| *k >= key) { self.position = pos as isize; Ok(Some(self.entries[pos])) @@ -327,7 +328,7 @@ impl OpProofsHashedCursorRO for InMemoryStorageCursor { } } - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { self.position += 1; if self.position >= 0 && (self.position as usize) < self.entries.len() { Ok(Some(self.entries[self.position as usize])) @@ -337,7 +338,13 @@ impl OpProofsHashedCursorRO for InMemoryStorageCursor { } } -/// In-memory implementation of [`OpProofsHashedCursorRO`] for accounts +impl HashedStorageCursor for InMemoryStorageCursor { + fn is_storage_empty(&mut self) -> Result { + Ok(self.seek(B256::ZERO)?.is_none()) + } +} + +/// In-memory implementation of [`HashedCursor`] for accounts #[derive(Debug)] pub struct InMemoryAccountCursor { /// Current position in the iteration (-1 means not positioned yet) @@ -375,10 +382,10 @@ impl InMemoryAccountCursor { } } -impl OpProofsHashedCursorRO for InMemoryAccountCursor { +impl HashedCursor for InMemoryAccountCursor { type Value = Account; - fn seek(&mut self, key: B256) -> OpProofsStorageResult> { + fn seek(&mut self, key: B256) -> Result, DatabaseError> { if let Some(pos) = self.entries.iter().position(|(k, _)| *k >= key) { self.position = pos as isize; Ok(Some(self.entries[pos])) @@ -387,7 +394,7 @@ impl OpProofsHashedCursorRO for InMemoryAccountCursor { } } - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { self.position += 1; if self.position >= 0 && (self.position as usize) < self.entries.len() { Ok(Some(self.entries[self.position as usize])) diff --git a/crates/optimism/trie/src/lib.rs b/crates/optimism/trie/src/lib.rs index f8bff214704..9256be93732 100644 --- a/crates/optimism/trie/src/lib.rs +++ b/crates/optimism/trie/src/lib.rs @@ -13,7 +13,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] pub mod api; -pub use api::{BlockStateDiff, OpProofsHashedCursorRO, OpProofsStore}; +pub use api::{BlockStateDiff, OpProofsStore}; pub mod backfill; pub use backfill::BackfillJob; diff --git a/crates/optimism/trie/src/metrics.rs b/crates/optimism/trie/src/metrics.rs index 7b6869ce1e3..b1b5a99aae7 100644 --- a/crates/optimism/trie/src/metrics.rs +++ b/crates/optimism/trie/src/metrics.rs @@ -2,7 +2,7 @@ use crate::{ api::{OperationDurations, WriteCounts}, - cursor, BlockStateDiff, OpProofsHashedCursorRO, OpProofsStorageResult, OpProofsStore, + cursor, BlockStateDiff, OpProofsStorageResult, OpProofsStore, }; use alloy_eips::eip1898::BlockWithParent; use alloy_primitives::{map::HashMap, B256, U256}; @@ -11,7 +11,11 @@ use metrics::{Counter, Gauge, Histogram}; use reth_db::DatabaseError; use reth_metrics::Metrics; use reth_primitives_traits::Account; -use reth_trie::{trie_cursor::TrieCursor, BranchNodeCompact, Nibbles}; +use reth_trie::{ + hashed_cursor::{HashedCursor, HashedStorageCursor}, + trie_cursor::TrieCursor, + BranchNodeCompact, Nibbles, +}; use std::{ fmt::Debug, future::Future, @@ -280,27 +284,34 @@ impl TrieCursor for OpProofsTrieCursorWithMetrics { } } -/// Wrapper for [`OpProofsHashedCursorRO`] type that records metrics. +/// Wrapper for [`HashedCursor`] type that records metrics. #[derive(Debug, Constructor, Clone)] pub struct OpProofsHashedCursorWithMetrics { cursor: C, metrics: Arc, } -impl OpProofsHashedCursorRO for OpProofsHashedCursorWithMetrics { +impl HashedCursor for OpProofsHashedCursorWithMetrics { type Value = C::Value; #[inline] - fn seek(&mut self, key: B256) -> OpProofsStorageResult> { + fn seek(&mut self, key: B256) -> Result, DatabaseError> { self.metrics.record_operation(StorageOperation::HashedCursorSeek, || self.cursor.seek(key)) } #[inline] - fn next(&mut self) -> OpProofsStorageResult> { + fn next(&mut self) -> Result, DatabaseError> { self.metrics.record_operation(StorageOperation::HashedCursorNext, || self.cursor.next()) } } +impl HashedStorageCursor for OpProofsHashedCursorWithMetrics { + #[inline] + fn is_storage_empty(&mut self) -> Result { + self.cursor.is_storage_empty() + } +} + /// Wrapper around [`OpProofsStore`] type that records metrics for all operations. #[derive(Debug, Clone)] pub struct OpProofsStorageWithMetrics { diff --git a/crates/optimism/trie/src/provider.rs b/crates/optimism/trie/src/provider.rs index ce7f2d99e5d..044e97c8070 100644 --- a/crates/optimism/trie/src/provider.rs +++ b/crates/optimism/trie/src/provider.rs @@ -5,7 +5,7 @@ use crate::{ DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, }, - OpProofsHashedCursorRO, OpProofsStorage, OpProofsStorageError, OpProofsStore, + OpProofsStorage, OpProofsStorageError, OpProofsStore, }; use alloy_primitives::keccak256; use derive_more::Constructor; @@ -19,6 +19,7 @@ use reth_revm::{ primitives::{alloy_primitives::BlockNumber, Address, Bytes, StorageValue, B256}, }; use reth_trie::{ + hashed_cursor::HashedCursor, proof::{Proof, StorageProof}, updates::TrieUpdates, witness::TrieWitness, diff --git a/crates/optimism/trie/tests/lib.rs b/crates/optimism/trie/tests/lib.rs index 89623b6cd78..db884f1391c 100644 --- a/crates/optimism/trie/tests/lib.rs +++ b/crates/optimism/trie/tests/lib.rs @@ -3,13 +3,13 @@ use alloy_eips::{eip1898::BlockWithParent, NumHash}; use alloy_primitives::{map::HashMap, B256, U256}; use reth_optimism_trie::{ - db::MdbxProofsStorage, BlockStateDiff, InMemoryProofsStorage, OpProofsHashedCursorRO, - OpProofsStorageError, OpProofsStore, + db::MdbxProofsStorage, BlockStateDiff, InMemoryProofsStorage, OpProofsStorageError, + OpProofsStore, }; use reth_primitives_traits::Account; use reth_trie::{ - trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, HashedPostState, - HashedStorage, Nibbles, TrieMask, + hashed_cursor::HashedCursor, trie_cursor::TrieCursor, updates::TrieUpdates, BranchNodeCompact, + HashedPostState, HashedStorage, Nibbles, TrieMask, }; use serial_test::serial; use std::sync::Arc; From 40f7cb61acf7da50a2e9d02fb3163dd723a5c691 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 11:57:55 +0100 Subject: [PATCH 06/14] Support bijective relation between OpProofsStorageError and DatabaseError without matching on error msg string --- crates/optimism/trie/src/error.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/crates/optimism/trie/src/error.rs b/crates/optimism/trie/src/error.rs index 00ac2984fed..c1f7e60ded7 100644 --- a/crates/optimism/trie/src/error.rs +++ b/crates/optimism/trie/src/error.rs @@ -3,11 +3,12 @@ use alloy_primitives::B256; use reth_db::DatabaseError; use reth_trie::Nibbles; +use std::sync::Arc; use thiserror::Error; use tokio::sync::TryLockError; /// Error type for storage operations -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum OpProofsStorageError { /// No blocks found #[error("No blocks found")] @@ -69,15 +70,32 @@ pub enum OpProofsStorageError { }, /// Error occurred while interacting with the database. #[error(transparent)] - DatabaseError(#[from] DatabaseError), + DatabaseError(DatabaseError), /// Error occurred while trying to acquire a lock. - #[error(transparent)] - TryLockError(#[from] TryLockError), + #[error("failed lock attempt")] + TryLockError, +} + +impl From for OpProofsStorageError { + fn from(_: TryLockError) -> Self { + Self::TryLockError + } } impl From for DatabaseError { fn from(error: OpProofsStorageError) -> Self { - Self::Other(error.to_string()) + Self::Custom(Arc::new(error)) + } +} + +impl From for OpProofsStorageError { + fn from(error: DatabaseError) -> Self { + if let DatabaseError::Custom(ref err) = error && + let Some(err) = err.downcast_ref::() + { + return err.clone() + } + Self::DatabaseError(error) } } From 01392121cc334081baee809728e7e629417bb61b Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 17:02:02 +0100 Subject: [PATCH 07/14] Add test for error conversion --- crates/optimism/trie/src/error.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/crates/optimism/trie/src/error.rs b/crates/optimism/trie/src/error.rs index c1f7e60ded7..8ba65e016a0 100644 --- a/crates/optimism/trie/src/error.rs +++ b/crates/optimism/trie/src/error.rs @@ -84,7 +84,10 @@ impl From for OpProofsStorageError { impl From for DatabaseError { fn from(error: OpProofsStorageError) -> Self { - Self::Custom(Arc::new(error)) + match error { + OpProofsStorageError::DatabaseError(err) => err, + _ => Self::Custom(Arc::new(error)), + } } } @@ -101,3 +104,27 @@ impl From for OpProofsStorageError { /// Result type for storage operations pub type OpProofsStorageResult = Result; + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_op_proofs_store_error_to_db_error() { + let original_error = OpProofsStorageError::NoBlocksFound; + let db_error: DatabaseError = original_error.into(); + let converted_error: OpProofsStorageError = db_error.into(); + + assert!(matches!(converted_error, OpProofsStorageError::NoBlocksFound)) + } + + #[test] + fn test_db_error_to_op_proofs_store_error() { + let original_error = DatabaseError::Decode; + let op_proofs_store_error: OpProofsStorageError = original_error.into(); + let converted_error: DatabaseError = op_proofs_store_error.into(); + println!("{:?}", converted_error); + + assert!(matches!(converted_error, DatabaseError::Decode)) + } +} From c32afd7bfad6352bcf7fe11da63f40094efe733a Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 17:28:02 +0100 Subject: [PATCH 08/14] Fix lint --- .../storage/db/src/implementation/mdbx/mod.rs | 95 ++++++++++--------- .../provider/src/providers/database/mod.rs | 6 +- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/crates/storage/db/src/implementation/mdbx/mod.rs b/crates/storage/db/src/implementation/mdbx/mod.rs index b00bfd3c9a5..a405cc89a4f 100644 --- a/crates/storage/db/src/implementation/mdbx/mod.rs +++ b/crates/storage/db/src/implementation/mdbx/mod.rs @@ -670,14 +670,14 @@ mod tests { dup_cursor.upsert(Address::with_last_byte(1), &entry_1).expect(ERROR_UPSERT); assert_eq!( - dup_cursor.walk(None).unwrap().collect::, _>>(), - Ok(vec![(Address::with_last_byte(1), entry_0), (Address::with_last_byte(1), entry_1),]) + dup_cursor.walk(None).unwrap().collect::, _>>().unwrap(), + vec![(Address::with_last_byte(1), entry_0), (Address::with_last_byte(1), entry_1),] ); let mut walker = dup_cursor.walk(None).unwrap(); walker.delete_current().expect(ERROR_DEL); - assert_eq!(walker.next(), Some(Ok((Address::with_last_byte(1), entry_1)))); + assert_eq!(walker.next().unwrap().unwrap(), (Address::with_last_byte(1), entry_1)); // Check the tx view - it correctly holds entry_1 assert_eq!( @@ -685,14 +685,15 @@ mod tests { .unwrap() .walk(None) .unwrap() - .collect::, _>>(), - Ok(vec![ + .collect::, _>>() + .unwrap(), + vec![ (Address::with_last_byte(1), entry_1), // This is ok - we removed entry_0 - ]) + ] ); // Check the remainder of walker - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); } #[test] @@ -737,51 +738,51 @@ mod tests { // [1, 3) let mut walker = cursor.walk_range(1..3).unwrap(); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((2, B256::ZERO)))); - assert_eq!(walker.next(), None); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (2, B256::ZERO)); + assert!(walker.next().is_none()); // next() returns None after walker is done - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); // [1, 2] let mut walker = cursor.walk_range(1..=2).unwrap(); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((2, B256::ZERO)))); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (2, B256::ZERO)); // next() returns None after walker is done - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); // [1, ∞) let mut walker = cursor.walk_range(1..).unwrap(); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((2, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (2, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (3, B256::ZERO)); // next() returns None after walker is done - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); // [2, 4) let mut walker = cursor.walk_range(2..4).unwrap(); - assert_eq!(walker.next(), Some(Ok((2, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(walker.next(), None); + assert_eq!(walker.next().unwrap().unwrap(), (2, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (3, B256::ZERO)); + assert!(walker.next().is_none()); // next() returns None after walker is done - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); // (∞, 3) let mut walker = cursor.walk_range(..3).unwrap(); - assert_eq!(walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((2, B256::ZERO)))); + assert_eq!(walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (2, B256::ZERO)); // next() returns None after walker is done - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); // (∞, ∞) let mut walker = cursor.walk_range(..).unwrap(); - assert_eq!(walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((2, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); + assert_eq!(walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (2, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (3, B256::ZERO)); // next() returns None after walker is done - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); } #[test] @@ -822,7 +823,7 @@ mod tests { assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address0, info: None })))); assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address1, info: None })))); assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address2, info: None })))); - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); } #[expect(clippy::reversed_empty_ranges)] @@ -851,7 +852,7 @@ mod tests { // returning nothing let mut walker = cursor.walk_range(1..1).unwrap(); - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); } #[test] @@ -874,7 +875,7 @@ mod tests { assert_eq!(walker.next(), Some(Ok((0, B256::ZERO)))); assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); // transform to ReverseWalker let mut reverse_walker = walker.rev(); @@ -911,7 +912,7 @@ mod tests { assert_eq!(walker.next(), Some(Ok((0, B256::ZERO)))); assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); } #[test] @@ -1364,7 +1365,7 @@ mod tests { let mut cursor = tx.cursor_dup_read::().unwrap(); let not_existing_key = Address::ZERO; let mut walker = cursor.walk_dup(Some(not_existing_key), None).unwrap(); - assert_eq!(walker.next(), None); + assert!(walker.next().is_none()); } } @@ -1395,11 +1396,11 @@ mod tests { let mut walker = cursor.walk_dup(None, None).unwrap(); // Notice that value11 and value22 have been ordered in the DB. - assert_eq!(Some(Ok((key1, value00))), walker.next()); - assert_eq!(Some(Ok((key1, value11))), walker.next()); + assert_eq!((key1, value00), walker.next().unwrap().unwrap()); + assert_eq!((key1, value11), walker.next().unwrap().unwrap()); // NOTE: Dup cursor does NOT iterates on all values but only on duplicated values of the // same key. assert_eq!(Ok(Some(value22.clone())), walker.next()); - assert_eq!(None, walker.next()); + assert!(walker.next().is_none()); } // Iterate by using `walk` @@ -1408,9 +1409,9 @@ mod tests { let mut cursor = tx.cursor_dup_read::().unwrap(); let first = cursor.first().unwrap().unwrap(); let mut walker = cursor.walk(Some(first.0)).unwrap(); - assert_eq!(Some(Ok((key1, value00))), walker.next()); - assert_eq!(Some(Ok((key1, value11))), walker.next()); - assert_eq!(Some(Ok((key2, value22))), walker.next()); + assert_eq!((key1, value00), walker.next().unwrap().unwrap()); + assert_eq!((key1, value11), walker.next().unwrap().unwrap()); + assert_eq!((key2, value22), walker.next().unwrap().unwrap()); } } @@ -1440,9 +1441,9 @@ mod tests { let mut walker = cursor.walk(Some(first.0)).unwrap(); // NOTE: Both values are present - assert_eq!(Some(Ok((key1, value00))), walker.next()); - assert_eq!(Some(Ok((key1, value01))), walker.next()); - assert_eq!(Some(Ok((key2, value22))), walker.next()); + assert_eq!((key1, value00), walker.next().unwrap().unwrap()); + assert_eq!((key1, value01), walker.next().unwrap().unwrap()); + assert_eq!((key2, value22), walker.next().unwrap().unwrap()); } // seek_by_key_subkey @@ -1451,9 +1452,9 @@ mod tests { let mut cursor = tx.cursor_dup_read::().unwrap(); // NOTE: There are two values with same SubKey but only first one is shown - assert_eq!(Ok(Some(value00)), cursor.seek_by_key_subkey(key1, value00.key)); + assert_eq!(value00, cursor.seek_by_key_subkey(key1, value00.key).unwrap().unwrap()); // key1 but value is greater than the one in the DB - assert_eq!(Ok(None), cursor.seek_by_key_subkey(key1, value22.key)); + assert_eq!(None, cursor.seek_by_key_subkey(key1, value22.key).unwrap()); } } diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 6e8f1f1f800..cb59c2be25c 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -721,16 +721,16 @@ mod tests { assert_matches!(provider.insert_block(block.clone().try_recover().unwrap()), Ok(_)); - let senders = provider.take::(range.clone()); + let senders = provider.take::(range.clone()).unwrap(); assert_eq!( senders, - Ok(range + range .clone() .map(|tx_number| ( tx_number, block.body().transactions[tx_number as usize].recover_signer().unwrap() )) - .collect()) + .collect::>() ); let db_senders = provider.senders_by_tx_range(range); From b5ac48a6f1412da24db6433bf6a6df202ae63ae7 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 17:40:58 +0100 Subject: [PATCH 09/14] Fix lint test target --- .../storage/db/src/implementation/mdbx/mod.rs | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/crates/storage/db/src/implementation/mdbx/mod.rs b/crates/storage/db/src/implementation/mdbx/mod.rs index a405cc89a4f..cd7dbca396a 100644 --- a/crates/storage/db/src/implementation/mdbx/mod.rs +++ b/crates/storage/db/src/implementation/mdbx/mod.rs @@ -1055,19 +1055,18 @@ mod tests { // Seek & delete key2 cursor.seek_exact(key2).unwrap(); - assert_eq!(cursor.delete_current(), Ok(())); - assert_eq!(cursor.seek_exact(key2), Ok(None)); + assert!(cursor.delete_current().is_ok()); + assert!(cursor.seek_exact(key2).unwrap().is_none()); // Seek & delete key2 again - assert_eq!(cursor.seek_exact(key2), Ok(None)); - assert_eq!( - cursor.delete_current(), - Err(DatabaseError::Delete(reth_libmdbx::Error::NoData.into())) - ); + assert!(cursor.seek_exact(key2).unwrap().is_none()); + assert!(matches!( + cursor.delete_current().unwrap_err(), + DatabaseError::Delete(err) if err = reth_libmdbx::Error::NoData.into())); // Assert that key1 is still there - assert_eq!(cursor.seek_exact(key1), Ok(Some((key1, Account::default())))); + assert!(matches!(cursor.seek_exact(key1).unwrap(), Some((key1, Account::default())))); // Assert that key3 is still there - assert_eq!(cursor.seek_exact(key3), Ok(Some((key3, Account::default())))); + assert!(matches!(cursor.seek_exact(key3).unwrap(), Some((key3, Account::default())))); } #[test] @@ -1226,38 +1225,47 @@ mod tests { let tx = db.tx_mut().expect(ERROR_INIT_TX); let mut cursor = tx.cursor_write::().unwrap(); assert_eq!( - cursor.append_dup( - transition_id, - AccountBeforeTx { address: Address::with_last_byte(subkey_to_append), info: None } - ), - Err(DatabaseWriteError { + cursor + .append_dup( + transition_id, + AccountBeforeTx { + address: Address::with_last_byte(subkey_to_append), + info: None + } + ) + .unwrap_err(), + DatabaseWriteError { info: Error::KeyMismatch.into(), operation: DatabaseWriteOperation::CursorAppendDup, table_name: AccountChangeSets::NAME, key: transition_id.encode().into(), } - .into()) + .into() ); assert_eq!( - cursor.append( - transition_id - 1, - &AccountBeforeTx { address: Address::with_last_byte(subkey_to_append), info: None } - ), - Err(DatabaseWriteError { + cursor + .append( + transition_id - 1, + &AccountBeforeTx { + address: Address::with_last_byte(subkey_to_append), + info: None + } + ) + .unwrap_err(), + DatabaseWriteError { info: Error::KeyMismatch.into(), operation: DatabaseWriteOperation::CursorAppend, table_name: AccountChangeSets::NAME, key: (transition_id - 1).encode().into(), } - .into()) + .into() ); - assert_eq!( - cursor.append( + assert!(cursor + .append( transition_id, &AccountBeforeTx { address: Address::with_last_byte(subkey_to_append), info: None } - ), - Ok(()) - ); + ) + .is_ok()); } #[test] From 52ab9d277537eea7b7270bf126fb218935e47254 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 17:45:59 +0100 Subject: [PATCH 10/14] Fix lint --- .../storage/db/src/implementation/mdbx/mod.rs | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/crates/storage/db/src/implementation/mdbx/mod.rs b/crates/storage/db/src/implementation/mdbx/mod.rs index cd7dbca396a..9d73a9218d2 100644 --- a/crates/storage/db/src/implementation/mdbx/mod.rs +++ b/crates/storage/db/src/implementation/mdbx/mod.rs @@ -817,12 +817,30 @@ mod tests { assert_eq!(entries.len(), 7); let mut walker = cursor.walk_range(0..=1).unwrap(); - assert_eq!(walker.next(), Some(Ok((0, AccountBeforeTx { address: address0, info: None })))); - assert_eq!(walker.next(), Some(Ok((0, AccountBeforeTx { address: address1, info: None })))); - assert_eq!(walker.next(), Some(Ok((0, AccountBeforeTx { address: address2, info: None })))); - assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address0, info: None })))); - assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address1, info: None })))); - assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address2, info: None })))); + assert_eq!( + walker.next().unwrap().unwrap(), + (0, AccountBeforeTx { address: address0, info: None }) + ); + assert_eq!( + walker.next().unwrap().unwrap(), + (0, AccountBeforeTx { address: address1, info: None }) + ); + assert_eq!( + walker.next().unwrap().unwrap(), + (0, AccountBeforeTx { address: address2, info: None }) + ); + assert_eq!( + walker.next().unwrap().unwrap(), + (1, AccountBeforeTx { address: address0, info: None }) + ); + assert_eq!( + walker.next().unwrap().unwrap(), + (1, AccountBeforeTx { address: address1, info: None }) + ); + assert_eq!( + walker.next().unwrap().unwrap(), + (1, AccountBeforeTx { address: address2, info: None }) + ); assert!(walker.next().is_none()); } @@ -1062,11 +1080,11 @@ mod tests { assert!(cursor.seek_exact(key2).unwrap().is_none()); assert!(matches!( cursor.delete_current().unwrap_err(), - DatabaseError::Delete(err) if err = reth_libmdbx::Error::NoData.into())); + DatabaseError::Delete(err) if err == reth_libmdbx::Error::NoData.into())); // Assert that key1 is still there - assert!(matches!(cursor.seek_exact(key1).unwrap(), Some((key1, Account::default())))); + assert_eq!(cursor.seek_exact(key1).unwrap(), Some((key1, Account::default()))); // Assert that key3 is still there - assert!(matches!(cursor.seek_exact(key3).unwrap(), Some((key3, Account::default())))); + assert_eq!(cursor.seek_exact(key3).unwrap(), Some((key3, Account::default()))); } #[test] From 8e44e2a87e11c82d87b114865b57ad2ab6c83be4 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 18:15:01 +0100 Subject: [PATCH 11/14] Fix lint test target --- .../storage/db/src/implementation/mdbx/mod.rs | 172 +++++++++--------- .../storage/db/src/implementation/mdbx/tx.rs | 14 +- 2 files changed, 88 insertions(+), 98 deletions(-) diff --git a/crates/storage/db/src/implementation/mdbx/mod.rs b/crates/storage/db/src/implementation/mdbx/mod.rs index 9d73a9218d2..d89a35fbf9d 100644 --- a/crates/storage/db/src/implementation/mdbx/mod.rs +++ b/crates/storage/db/src/implementation/mdbx/mod.rs @@ -862,11 +862,11 @@ mod tests { // start bound greater than end bound let mut res = cursor.walk_range(3..1).unwrap(); - assert_eq!(res.next(), None); + assert!(res.next().is_none()); // start bound greater than end bound let mut res = cursor.walk_range(15..=2).unwrap(); - assert_eq!(res.next(), None); + assert!(res.next().is_none()); // returning nothing let mut walker = cursor.walk_range(1..1).unwrap(); @@ -890,17 +890,17 @@ mod tests { let mut walker = Walker::new(&mut cursor, None); - assert_eq!(walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); + assert_eq!(walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (3, B256::ZERO)); assert!(walker.next().is_none()); // transform to ReverseWalker let mut reverse_walker = walker.rev(); - assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(reverse_walker.next(), None); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (3, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert!(reverse_walker.next().is_none()); } #[test] @@ -920,16 +920,16 @@ mod tests { let mut reverse_walker = ReverseWalker::new(&mut cursor, None); - assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(reverse_walker.next(), None); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (3, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert!(reverse_walker.next().is_none()); // transform to Walker let mut walker = reverse_walker.forward(); - assert_eq!(walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(walker.next(), Some(Ok((3, B256::ZERO)))); + assert_eq!(walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(walker.next().unwrap().unwrap(), (3, B256::ZERO)); assert!(walker.next().is_none()); } @@ -949,27 +949,27 @@ mod tests { let mut cursor = tx.cursor_read::().unwrap(); let mut reverse_walker = cursor.walk_back(Some(1)).unwrap(); - assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(reverse_walker.next(), None); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert!(reverse_walker.next().is_none()); let mut reverse_walker = cursor.walk_back(Some(2)).unwrap(); - assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(reverse_walker.next(), None); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (3, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert!(reverse_walker.next().is_none()); let mut reverse_walker = cursor.walk_back(Some(4)).unwrap(); - assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(reverse_walker.next(), None); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (3, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert!(reverse_walker.next().is_none()); let mut reverse_walker = cursor.walk_back(None).unwrap(); - assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO)))); - assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO)))); - assert_eq!(reverse_walker.next(), None); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (3, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (1, B256::ZERO)); + assert_eq!(reverse_walker.next().unwrap().unwrap(), (0, B256::ZERO)); + assert!(reverse_walker.next().is_none()); } #[test] @@ -988,12 +988,12 @@ mod tests { let missing_key = 2; let tx = db.tx().expect(ERROR_INIT_TX); let mut cursor = tx.cursor_read::().unwrap(); - assert_eq!(cursor.current(), Ok(None)); + assert!(cursor.current().unwrap().is_none()); // Seek exact let exact = cursor.seek_exact(missing_key).unwrap(); assert_eq!(exact, None); - assert_eq!(cursor.current(), Ok(None)); + assert!(cursor.current().unwrap().is_none()); } #[test] @@ -1013,21 +1013,18 @@ mod tests { let mut cursor = tx.cursor_write::().unwrap(); // INSERT - assert_eq!(cursor.insert(key_to_insert, &B256::ZERO), Ok(())); - assert_eq!(cursor.current(), Ok(Some((key_to_insert, B256::ZERO)))); - + assert!(cursor.insert(key_to_insert, &B256::ZERO).is_ok()); + assert_eq!(cursor.current().unwrap(), Some((key_to_insert, B256::ZERO))); // INSERT (failure) - assert_eq!( - cursor.insert(key_to_insert, &B256::ZERO), - Err(DatabaseWriteError { - info: Error::KeyExist.into(), - operation: DatabaseWriteOperation::CursorInsert, - table_name: CanonicalHeaders::NAME, - key: key_to_insert.encode().into(), - } - .into()) - ); - assert_eq!(cursor.current(), Ok(Some((key_to_insert, B256::ZERO)))); + assert!(matches!( + cursor.insert(key_to_insert, &B256::ZERO).unwrap_err(), + DatabaseError::Write(err) if *err == DatabaseWriteError { + info: Error::KeyExist.into(), + operation: DatabaseWriteOperation::CursorInsert, + table_name: CanonicalHeaders::NAME, + key: key_to_insert.encode().into(), + })); + assert_eq!(cursor.current().unwrap(), Some((key_to_insert, B256::ZERO))); tx.commit().expect(ERROR_COMMIT); @@ -1104,11 +1101,11 @@ mod tests { // INSERT (cursor starts at last) cursor.last().unwrap(); - assert_eq!(cursor.current(), Ok(Some((9, B256::ZERO)))); + assert_eq!(cursor.current().unwrap(), Some((9, B256::ZERO))); for pos in (2..=8).step_by(2) { - assert_eq!(cursor.insert(pos, &B256::ZERO), Ok(())); - assert_eq!(cursor.current(), Ok(Some((pos, B256::ZERO)))); + assert!(cursor.insert(pos, &B256::ZERO).is_ok()); + assert_eq!(cursor.current().unwrap(), Some((pos, B256::ZERO))); } tx.commit().expect(ERROR_COMMIT); @@ -1136,7 +1133,7 @@ mod tests { let key_to_append = 5; let tx = db.tx_mut().expect(ERROR_INIT_TX); let mut cursor = tx.cursor_write::().unwrap(); - assert_eq!(cursor.append(key_to_append, &B256::ZERO), Ok(())); + assert!(cursor.append(key_to_append, &B256::ZERO).is_ok()); tx.commit().expect(ERROR_COMMIT); // Confirm the result @@ -1163,17 +1160,15 @@ mod tests { let key_to_append = 2; let tx = db.tx_mut().expect(ERROR_INIT_TX); let mut cursor = tx.cursor_write::().unwrap(); - assert_eq!( - cursor.append(key_to_append, &B256::ZERO), - Err(DatabaseWriteError { - info: Error::KeyMismatch.into(), - operation: DatabaseWriteOperation::CursorAppend, - table_name: CanonicalHeaders::NAME, - key: key_to_append.encode().into(), - } - .into()) - ); - assert_eq!(cursor.current(), Ok(Some((5, B256::ZERO)))); // the end of table + assert!(matches!( + cursor.append(key_to_append, &B256::ZERO).unwrap_err(), + DatabaseError::Write(err) if *err == DatabaseWriteError { + info: Error::KeyMismatch.into(), + operation: DatabaseWriteOperation::CursorAppend, + table_name: CanonicalHeaders::NAME, + key: key_to_append.encode().into(), + })); + assert_eq!(cursor.current().unwrap(), Some((5, B256::ZERO))); // the end of table tx.commit().expect(ERROR_COMMIT); // Confirm the result @@ -1194,15 +1189,15 @@ mod tests { let account = Account::default(); cursor.upsert(key, &account).expect(ERROR_UPSERT); - assert_eq!(cursor.seek_exact(key), Ok(Some((key, account)))); + assert_eq!(cursor.seek_exact(key).unwrap(), Some((key, account))); let account = Account { nonce: 1, ..Default::default() }; cursor.upsert(key, &account).expect(ERROR_UPSERT); - assert_eq!(cursor.seek_exact(key), Ok(Some((key, account)))); + assert_eq!(cursor.seek_exact(key).unwrap(), Some((key, account))); let account = Account { nonce: 2, ..Default::default() }; cursor.upsert(key, &account).expect(ERROR_UPSERT); - assert_eq!(cursor.seek_exact(key), Ok(Some((key, account)))); + assert_eq!(cursor.seek_exact(key).unwrap(), Some((key, account))); let mut dup_cursor = tx.cursor_dup_write::().unwrap(); let subkey = B256::random(); @@ -1210,13 +1205,13 @@ mod tests { let value = U256::from(1); let entry1 = StorageEntry { key: subkey, value }; dup_cursor.upsert(key, &entry1).expect(ERROR_UPSERT); - assert_eq!(dup_cursor.seek_by_key_subkey(key, subkey), Ok(Some(entry1))); + assert_eq!(dup_cursor.seek_by_key_subkey(key, subkey).unwrap(), Some(entry1)); let value = U256::from(2); let entry2 = StorageEntry { key: subkey, value }; dup_cursor.upsert(key, &entry2).expect(ERROR_UPSERT); - assert_eq!(dup_cursor.seek_by_key_subkey(key, subkey), Ok(Some(entry1))); - assert_eq!(dup_cursor.next_dup_val(), Ok(Some(entry2))); + assert_eq!(dup_cursor.seek_by_key_subkey(key, subkey).unwrap(), Some(entry1)); + assert_eq!(dup_cursor.next_dup_val().unwrap(), Some(entry2)); } #[test] @@ -1242,25 +1237,23 @@ mod tests { let subkey_to_append = 2; let tx = db.tx_mut().expect(ERROR_INIT_TX); let mut cursor = tx.cursor_write::().unwrap(); - assert_eq!( - cursor - .append_dup( - transition_id, - AccountBeforeTx { - address: Address::with_last_byte(subkey_to_append), - info: None - } - ) - .unwrap_err(), - DatabaseWriteError { - info: Error::KeyMismatch.into(), - operation: DatabaseWriteOperation::CursorAppendDup, - table_name: AccountChangeSets::NAME, - key: transition_id.encode().into(), - } - .into() - ); - assert_eq!( + assert!(matches!( + cursor + .append_dup( + transition_id, + AccountBeforeTx { + address: Address::with_last_byte(subkey_to_append), + info: None + } + ) + .unwrap_err(), + DatabaseError::Write(err) if *err == DatabaseWriteError { + info: Error::KeyMismatch.into(), + operation: DatabaseWriteOperation::CursorAppendDup, + table_name: AccountChangeSets::NAME, + key: transition_id.encode().into(), + })); + assert!(matches!( cursor .append( transition_id - 1, @@ -1270,14 +1263,13 @@ mod tests { } ) .unwrap_err(), - DatabaseWriteError { + DatabaseError::Write(err) if *err == DatabaseWriteError { info: Error::KeyMismatch.into(), operation: DatabaseWriteOperation::CursorAppend, table_name: AccountChangeSets::NAME, key: (transition_id - 1).encode().into(), } - .into() - ); + )); assert!(cursor .append( transition_id, diff --git a/crates/storage/db/src/implementation/mdbx/tx.rs b/crates/storage/db/src/implementation/mdbx/tx.rs index 0ca4d44a6cd..6f9ca4f230b 100644 --- a/crates/storage/db/src/implementation/mdbx/tx.rs +++ b/crates/storage/db/src/implementation/mdbx/tx.rs @@ -460,10 +460,9 @@ mod tests { sleep(MAX_DURATION + Duration::from_millis(100)); // Transaction has not timed out. - assert_eq!( - tx.get::(0), - Err(DatabaseError::Open(reth_libmdbx::Error::NotFound.into())) - ); + assert!(matches!( + tx.get::(0).unwrap_err(), + DatabaseError::Open(err) if err == reth_libmdbx::Error::NotFound.into())); // Backtrace is not recorded. assert!(!tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed)); } @@ -485,10 +484,9 @@ mod tests { sleep(MAX_DURATION + Duration::from_millis(100)); // Transaction has timed out. - assert_eq!( - tx.get::(0), - Err(DatabaseError::Open(reth_libmdbx::Error::ReadTransactionTimeout.into())) - ); + assert!(matches!( + tx.get::(0).unwrap_err(), + DatabaseError::Open(err) if err == reth_libmdbx::Error::ReadTransactionTimeout.into())); // Backtrace is recorded. assert!(tx.metrics_handler.unwrap().backtrace_recorded.load(Ordering::Relaxed)); } From 237de83dbb5a2baa51be8b35199a0d6a9a9a3bae Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 18:26:37 +0100 Subject: [PATCH 12/14] Fix merge conflicts with unstable --- crates/optimism/trie/src/prune/pruner.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/optimism/trie/src/prune/pruner.rs b/crates/optimism/trie/src/prune/pruner.rs index 4b4f19d47ad..25f8a406f2a 100644 --- a/crates/optimism/trie/src/prune/pruner.rs +++ b/crates/optimism/trie/src/prune/pruner.rs @@ -111,13 +111,16 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{db::MdbxProofsStorage, OpProofsHashedCursorRO, OpProofsTrieCursorRO}; + use crate::db::MdbxProofsStorage; use alloy_eips::{BlockHashOrNumber, NumHash}; use alloy_primitives::{BlockNumber, B256, U256}; use mockall::mock; use reth_primitives_traits::Account; use reth_storage_errors::provider::ProviderResult; - use reth_trie::{updates::StorageTrieUpdates, BranchNodeCompact, HashedStorage, Nibbles}; + use reth_trie::{ + hashed_cursor::HashedCursor, trie_cursor::TrieCursor, updates::StorageTrieUpdates, + BranchNodeCompact, HashedStorage, Nibbles, + }; use std::sync::Arc; use tempfile::TempDir; From a919fa579371092a808b463b64fe4089760b3b92 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Wed, 19 Nov 2025 18:31:47 +0100 Subject: [PATCH 13/14] Revert unrelated change --- crates/cli/util/src/sigsegv_handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/util/src/sigsegv_handler.rs b/crates/cli/util/src/sigsegv_handler.rs index eeca446b72a..dabbf866cee 100644 --- a/crates/cli/util/src/sigsegv_handler.rs +++ b/crates/cli/util/src/sigsegv_handler.rs @@ -126,7 +126,7 @@ pub fn install() { libc::sigaltstack(&raw const alt_stack, ptr::null_mut()); let mut sa: libc::sigaction = mem::zeroed(); - sa.sa_sigaction = print_stack_trace as *const () as libc::sighandler_t; + sa.sa_sigaction = print_stack_trace as libc::sighandler_t; sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; libc::sigemptyset(&raw mut sa.sa_mask); libc::sigaction(libc::SIGSEGV, &raw const sa, ptr::null_mut()); From 31b39cf26d1bcfacf443915f01f1c378323a8e75 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Fri, 21 Nov 2025 19:08:05 +0100 Subject: [PATCH 14/14] Fix lint --- crates/optimism/trie/src/prune/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/optimism/trie/src/prune/error.rs b/crates/optimism/trie/src/prune/error.rs index ca43536633a..bbfcfcc573a 100644 --- a/crates/optimism/trie/src/prune/error.rs +++ b/crates/optimism/trie/src/prune/error.rs @@ -8,7 +8,7 @@ use std::{ use strum::Display; use thiserror::Error; -/// Result of [`OpProofStoragePruner::run`] execution. +/// Result of [`OpProofStoragePruner::run`](crate::OpProofStoragePruner::run) execution. pub type OpProofStoragePrunerResult = Result; /// Successful prune summary.