reth_db/implementation/mdbx/
mod.rs

1//! Module that interacts with MDBX.
2
3use crate::{
4    lockfile::StorageLock,
5    metrics::DatabaseEnvMetrics,
6    tables::{self, Tables},
7    utils::default_page_size,
8    DatabaseError, TableSet,
9};
10use eyre::Context;
11use metrics::{gauge, Label};
12use reth_db_api::{
13    cursor::{DbCursorRO, DbCursorRW},
14    database::Database,
15    database_metrics::{DatabaseMetadata, DatabaseMetadataValue, DatabaseMetrics},
16    models::ClientVersion,
17    transaction::{DbTx, DbTxMut},
18};
19use reth_libmdbx::{
20    ffi, DatabaseFlags, Environment, EnvironmentFlags, Geometry, HandleSlowReadersReturnCode,
21    MaxReadTransactionDuration, Mode, PageSize, SyncMode, RO, RW,
22};
23use reth_storage_errors::db::LogLevel;
24use reth_tracing::tracing::error;
25use std::{
26    ops::{Deref, Range},
27    path::Path,
28    sync::Arc,
29    time::{SystemTime, UNIX_EPOCH},
30};
31use tx::Tx;
32
33pub mod cursor;
34pub mod tx;
35
36/// 1 KB in bytes
37pub const KILOBYTE: usize = 1024;
38/// 1 MB in bytes
39pub const MEGABYTE: usize = KILOBYTE * 1024;
40/// 1 GB in bytes
41pub const GIGABYTE: usize = MEGABYTE * 1024;
42/// 1 TB in bytes
43pub const TERABYTE: usize = GIGABYTE * 1024;
44
45/// MDBX allows up to 32767 readers (`MDBX_READERS_LIMIT`), but we limit it to slightly below that
46const DEFAULT_MAX_READERS: u64 = 32_000;
47
48/// Space that a read-only transaction can occupy until the warning is emitted.
49/// See [`reth_libmdbx::EnvironmentBuilder::set_handle_slow_readers`] for more information.
50const MAX_SAFE_READER_SPACE: usize = 10 * GIGABYTE;
51
52/// Environment used when opening a MDBX environment. RO/RW.
53#[derive(Debug)]
54pub enum DatabaseEnvKind {
55    /// Read-only MDBX environment.
56    RO,
57    /// Read-write MDBX environment.
58    RW,
59}
60
61impl DatabaseEnvKind {
62    /// Returns `true` if the environment is read-write.
63    pub const fn is_rw(&self) -> bool {
64        matches!(self, Self::RW)
65    }
66}
67
68/// Arguments for database initialization.
69#[derive(Clone, Debug)]
70pub struct DatabaseArguments {
71    /// Client version that accesses the database.
72    client_version: ClientVersion,
73    /// Database geometry settings.
74    geometry: Geometry<Range<usize>>,
75    /// Database log level. If [None], the default value is used.
76    log_level: Option<LogLevel>,
77    /// Maximum duration of a read transaction. If [None], the default value is used.
78    max_read_transaction_duration: Option<MaxReadTransactionDuration>,
79    /// Open environment in exclusive/monopolistic mode. If [None], the default value is used.
80    ///
81    /// This can be used as a replacement for `MDB_NOLOCK`, which don't supported by MDBX. In this
82    /// way, you can get the minimal overhead, but with the correct multi-process and multi-thread
83    /// locking.
84    ///
85    /// If `true` = open environment in exclusive/monopolistic mode or return `MDBX_BUSY` if
86    /// environment already used by other process. The main feature of the exclusive mode is the
87    /// ability to open the environment placed on a network share.
88    ///
89    /// If `false` = open environment in cooperative mode, i.e. for multi-process
90    /// access/interaction/cooperation. The main requirements of the cooperative mode are:
91    /// - Data files MUST be placed in the LOCAL file system, but NOT on a network share.
92    /// - Environment MUST be opened only by LOCAL processes, but NOT over a network.
93    /// - OS kernel (i.e. file system and memory mapping implementation) and all processes that
94    ///   open the given environment MUST be running in the physically single RAM with
95    ///   cache-coherency. The only exception for cache-consistency requirement is Linux on MIPS
96    ///   architecture, but this case has not been tested for a long time).
97    ///
98    /// This flag affects only at environment opening but can't be changed after.
99    exclusive: Option<bool>,
100}
101
102impl Default for DatabaseArguments {
103    fn default() -> Self {
104        Self::new(ClientVersion::default())
105    }
106}
107
108impl DatabaseArguments {
109    /// Create new database arguments with given client version.
110    pub fn new(client_version: ClientVersion) -> Self {
111        Self {
112            client_version,
113            geometry: Geometry {
114                size: Some(0..(4 * TERABYTE)),
115                growth_step: Some(4 * GIGABYTE as isize),
116                shrink_threshold: Some(0),
117                page_size: Some(PageSize::Set(default_page_size())),
118            },
119            log_level: None,
120            max_read_transaction_duration: None,
121            exclusive: None,
122        }
123    }
124
125    /// Sets the upper size limit of the db environment, the maximum database size in bytes.
126    pub const fn with_geometry_max_size(mut self, max_size: Option<usize>) -> Self {
127        if let Some(max_size) = max_size {
128            self.geometry.size = Some(0..max_size);
129        }
130        self
131    }
132
133    /// Configures the database growth step in bytes.
134    pub const fn with_growth_step(mut self, growth_step: Option<usize>) -> Self {
135        if let Some(growth_step) = growth_step {
136            self.geometry.growth_step = Some(growth_step as isize);
137        }
138        self
139    }
140
141    /// Set the log level.
142    pub const fn with_log_level(mut self, log_level: Option<LogLevel>) -> Self {
143        self.log_level = log_level;
144        self
145    }
146
147    /// Set the maximum duration of a read transaction.
148    pub const fn with_max_read_transaction_duration(
149        mut self,
150        max_read_transaction_duration: Option<MaxReadTransactionDuration>,
151    ) -> Self {
152        self.max_read_transaction_duration = max_read_transaction_duration;
153        self
154    }
155
156    /// Set the mdbx exclusive flag.
157    pub const fn with_exclusive(mut self, exclusive: Option<bool>) -> Self {
158        self.exclusive = exclusive;
159        self
160    }
161
162    /// Returns the client version if any.
163    pub const fn client_version(&self) -> &ClientVersion {
164        &self.client_version
165    }
166}
167
168/// Wrapper for the libmdbx environment: [Environment]
169#[derive(Debug)]
170pub struct DatabaseEnv {
171    /// Libmdbx-sys environment.
172    inner: Environment,
173    /// Cache for metric handles. If `None`, metrics are not recorded.
174    metrics: Option<Arc<DatabaseEnvMetrics>>,
175    /// Write lock for when dealing with a read-write environment.
176    _lock_file: Option<StorageLock>,
177}
178
179impl Database for DatabaseEnv {
180    type TX = tx::Tx<RO>;
181    type TXMut = tx::Tx<RW>;
182
183    fn tx(&self) -> Result<Self::TX, DatabaseError> {
184        Tx::new_with_metrics(
185            self.inner.begin_ro_txn().map_err(|e| DatabaseError::InitTx(e.into()))?,
186            self.metrics.clone(),
187        )
188        .map_err(|e| DatabaseError::InitTx(e.into()))
189    }
190
191    fn tx_mut(&self) -> Result<Self::TXMut, DatabaseError> {
192        Tx::new_with_metrics(
193            self.inner.begin_rw_txn().map_err(|e| DatabaseError::InitTx(e.into()))?,
194            self.metrics.clone(),
195        )
196        .map_err(|e| DatabaseError::InitTx(e.into()))
197    }
198}
199
200impl DatabaseMetrics for DatabaseEnv {
201    fn report_metrics(&self) {
202        for (name, value, labels) in self.gauge_metrics() {
203            gauge!(name, labels).set(value);
204        }
205    }
206
207    fn gauge_metrics(&self) -> Vec<(&'static str, f64, Vec<Label>)> {
208        let mut metrics = Vec::new();
209
210        let _ = self
211            .view(|tx| {
212                for table in Tables::ALL.iter().map(Tables::name) {
213                    let table_db = tx.inner.open_db(Some(table)).wrap_err("Could not open db.")?;
214
215                    let stats = tx
216                        .inner
217                        .db_stat(&table_db)
218                        .wrap_err(format!("Could not find table: {table}"))?;
219
220                    let page_size = stats.page_size() as usize;
221                    let leaf_pages = stats.leaf_pages();
222                    let branch_pages = stats.branch_pages();
223                    let overflow_pages = stats.overflow_pages();
224                    let num_pages = leaf_pages + branch_pages + overflow_pages;
225                    let table_size = page_size * num_pages;
226                    let entries = stats.entries();
227
228                    metrics.push((
229                        "db.table_size",
230                        table_size as f64,
231                        vec![Label::new("table", table)],
232                    ));
233                    metrics.push((
234                        "db.table_pages",
235                        leaf_pages as f64,
236                        vec![Label::new("table", table), Label::new("type", "leaf")],
237                    ));
238                    metrics.push((
239                        "db.table_pages",
240                        branch_pages as f64,
241                        vec![Label::new("table", table), Label::new("type", "branch")],
242                    ));
243                    metrics.push((
244                        "db.table_pages",
245                        overflow_pages as f64,
246                        vec![Label::new("table", table), Label::new("type", "overflow")],
247                    ));
248                    metrics.push((
249                        "db.table_entries",
250                        entries as f64,
251                        vec![Label::new("table", table)],
252                    ));
253                }
254
255                Ok::<(), eyre::Report>(())
256            })
257            .map_err(|error| error!(%error, "Failed to read db table stats"));
258
259        if let Ok(freelist) =
260            self.freelist().map_err(|error| error!(%error, "Failed to read db.freelist"))
261        {
262            metrics.push(("db.freelist", freelist as f64, vec![]));
263        }
264
265        if let Ok(stat) = self.stat().map_err(|error| error!(%error, "Failed to read db.stat")) {
266            metrics.push(("db.page_size", stat.page_size() as f64, vec![]));
267        }
268
269        metrics.push((
270            "db.timed_out_not_aborted_transactions",
271            self.timed_out_not_aborted_transactions() as f64,
272            vec![],
273        ));
274
275        metrics
276    }
277}
278
279impl DatabaseMetadata for DatabaseEnv {
280    fn metadata(&self) -> DatabaseMetadataValue {
281        DatabaseMetadataValue::new(self.freelist().ok())
282    }
283}
284
285impl DatabaseEnv {
286    /// Opens the database at the specified path with the given `EnvKind`.
287    ///
288    /// It does not create the tables, for that call [`DatabaseEnv::create_tables`].
289    pub fn open(
290        path: &Path,
291        kind: DatabaseEnvKind,
292        args: DatabaseArguments,
293    ) -> Result<Self, DatabaseError> {
294        let _lock_file = if kind.is_rw() {
295            StorageLock::try_acquire(path)
296                .map_err(|err| DatabaseError::Other(err.to_string()))?
297                .into()
298        } else {
299            None
300        };
301
302        let mut inner_env = Environment::builder();
303
304        let mode = match kind {
305            DatabaseEnvKind::RO => Mode::ReadOnly,
306            DatabaseEnvKind::RW => {
307                // enable writemap mode in RW mode
308                inner_env.write_map();
309                Mode::ReadWrite { sync_mode: SyncMode::Durable }
310            }
311        };
312
313        // Note: We set max dbs to 256 here to allow for custom tables. This needs to be set on
314        // environment creation.
315        debug_assert!(Tables::ALL.len() <= 256, "number of tables exceed max dbs");
316        inner_env.set_max_dbs(256);
317        inner_env.set_geometry(args.geometry);
318
319        fn is_current_process(id: u32) -> bool {
320            #[cfg(unix)]
321            {
322                id == std::os::unix::process::parent_id() || id == std::process::id()
323            }
324
325            #[cfg(not(unix))]
326            {
327                id == std::process::id()
328            }
329        }
330
331        extern "C" fn handle_slow_readers(
332            _env: *const ffi::MDBX_env,
333            _txn: *const ffi::MDBX_txn,
334            process_id: ffi::mdbx_pid_t,
335            thread_id: ffi::mdbx_tid_t,
336            read_txn_id: u64,
337            gap: std::ffi::c_uint,
338            space: usize,
339            retry: std::ffi::c_int,
340        ) -> HandleSlowReadersReturnCode {
341            if space > MAX_SAFE_READER_SPACE {
342                let message = if is_current_process(process_id as u32) {
343                    "Current process has a long-lived database transaction that grows the database file."
344                } else {
345                    "External process has a long-lived database transaction that grows the database file. \
346                     Use shorter-lived read transactions or shut down the node."
347                };
348                reth_tracing::tracing::warn!(
349                    target: "storage::db::mdbx",
350                    ?process_id,
351                    ?thread_id,
352                    ?read_txn_id,
353                    ?gap,
354                    ?space,
355                    ?retry,
356                    "{message}"
357                )
358            }
359
360            reth_libmdbx::HandleSlowReadersReturnCode::ProceedWithoutKillingReader
361        }
362        inner_env.set_handle_slow_readers(handle_slow_readers);
363
364        inner_env.set_flags(EnvironmentFlags {
365            mode,
366            // We disable readahead because it improves performance for linear scans, but
367            // worsens it for random access (which is our access pattern outside of sync)
368            no_rdahead: true,
369            coalesce: true,
370            exclusive: args.exclusive.unwrap_or_default(),
371            ..Default::default()
372        });
373        // Configure more readers
374        inner_env.set_max_readers(DEFAULT_MAX_READERS);
375        // This parameter sets the maximum size of the "reclaimed list", and the unit of measurement
376        // is "pages". Reclaimed list is the list of freed pages that's populated during the
377        // lifetime of DB transaction, and through which MDBX searches when it needs to insert new
378        // record with overflow pages. The flow is roughly the following:
379        // 0. We need to insert a record that requires N number of overflow pages (in consecutive
380        //    sequence inside the DB file).
381        // 1. Get some pages from the freelist, put them into the reclaimed list.
382        // 2. Search through the reclaimed list for the sequence of size N.
383        // 3. a. If found, return the sequence.
384        // 3. b. If not found, repeat steps 1-3. If the reclaimed list size is larger than
385        //    the `rp augment limit`, stop the search and allocate new pages at the end of the file:
386        //    https://github.com/paradigmxyz/reth/blob/2a4c78759178f66e30c8976ec5d243b53102fc9a/crates/storage/libmdbx-rs/mdbx-sys/libmdbx/mdbx.c#L11479-L11480.
387        //
388        // Basically, this parameter controls for how long do we search through the freelist before
389        // trying to allocate new pages. Smaller value will make MDBX to fallback to
390        // allocation faster, higher value will force MDBX to search through the freelist
391        // longer until the sequence of pages is found.
392        //
393        // The default value of this parameter is set depending on the DB size. The bigger the
394        // database, the larger is `rp augment limit`.
395        // https://github.com/paradigmxyz/reth/blob/2a4c78759178f66e30c8976ec5d243b53102fc9a/crates/storage/libmdbx-rs/mdbx-sys/libmdbx/mdbx.c#L10018-L10024.
396        //
397        // Previously, MDBX set this value as `256 * 1024` constant. Let's fallback to this,
398        // because we want to prioritize freelist lookup speed over database growth.
399        // https://github.com/paradigmxyz/reth/blob/fa2b9b685ed9787636d962f4366caf34a9186e66/crates/storage/libmdbx-rs/mdbx-sys/libmdbx/mdbx.c#L16017.
400        inner_env.set_rp_augment_limit(256 * 1024);
401
402        if let Some(log_level) = args.log_level {
403            // Levels higher than [LogLevel::Notice] require libmdbx built with `MDBX_DEBUG` option.
404            let is_log_level_available = if cfg!(debug_assertions) {
405                true
406            } else {
407                matches!(
408                    log_level,
409                    LogLevel::Fatal | LogLevel::Error | LogLevel::Warn | LogLevel::Notice
410                )
411            };
412            if is_log_level_available {
413                inner_env.set_log_level(match log_level {
414                    LogLevel::Fatal => 0,
415                    LogLevel::Error => 1,
416                    LogLevel::Warn => 2,
417                    LogLevel::Notice => 3,
418                    LogLevel::Verbose => 4,
419                    LogLevel::Debug => 5,
420                    LogLevel::Trace => 6,
421                    LogLevel::Extra => 7,
422                });
423            } else {
424                return Err(DatabaseError::LogLevelUnavailable(log_level))
425            }
426        }
427
428        if let Some(max_read_transaction_duration) = args.max_read_transaction_duration {
429            inner_env.set_max_read_transaction_duration(max_read_transaction_duration);
430        }
431
432        let env = Self {
433            inner: inner_env.open(path).map_err(|e| DatabaseError::Open(e.into()))?,
434            metrics: None,
435            _lock_file,
436        };
437
438        Ok(env)
439    }
440
441    /// Enables metrics on the database.
442    pub fn with_metrics(mut self) -> Self {
443        self.metrics = Some(DatabaseEnvMetrics::new().into());
444        self
445    }
446
447    /// Creates all the tables defined in [`Tables`], if necessary.
448    pub fn create_tables(&self) -> Result<(), DatabaseError> {
449        self.create_tables_for::<Tables>()
450    }
451
452    /// Creates all the tables defined in the given [`TableSet`], if necessary.
453    pub fn create_tables_for<TS: TableSet>(&self) -> Result<(), DatabaseError> {
454        let tx = self.inner.begin_rw_txn().map_err(|e| DatabaseError::InitTx(e.into()))?;
455
456        for table in TS::tables() {
457            let flags =
458                if table.is_dupsort() { DatabaseFlags::DUP_SORT } else { DatabaseFlags::default() };
459
460            tx.create_db(Some(table.name()), flags)
461                .map_err(|e| DatabaseError::CreateTable(e.into()))?;
462        }
463
464        tx.commit().map_err(|e| DatabaseError::Commit(e.into()))?;
465
466        Ok(())
467    }
468
469    /// Records version that accesses the database with write privileges.
470    pub fn record_client_version(&self, version: ClientVersion) -> Result<(), DatabaseError> {
471        if version.is_empty() {
472            return Ok(())
473        }
474
475        let tx = self.tx_mut()?;
476        let mut version_cursor = tx.cursor_write::<tables::VersionHistory>()?;
477
478        let last_version = version_cursor.last()?.map(|(_, v)| v);
479        if Some(&version) != last_version.as_ref() {
480            version_cursor.upsert(
481                SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs(),
482                version,
483            )?;
484            tx.commit()?;
485        }
486
487        Ok(())
488    }
489}
490
491impl Deref for DatabaseEnv {
492    type Target = Environment;
493
494    fn deref(&self) -> &Self::Target {
495        &self.inner
496    }
497}
498
499#[cfg(test)]
500mod tests {
501    use super::*;
502    use crate::{
503        tables::{
504            AccountsHistory, CanonicalHeaders, Headers, PlainAccountState, PlainStorageState,
505        },
506        test_utils::*,
507        AccountChangeSets,
508    };
509    use alloy_consensus::Header;
510    use alloy_primitives::{Address, B256, U256};
511    use reth_db_api::{
512        cursor::{DbDupCursorRO, DbDupCursorRW, ReverseWalker, Walker},
513        models::{AccountBeforeTx, IntegerList, ShardedKey},
514        table::{Encode, Table},
515    };
516    use reth_libmdbx::Error;
517    use reth_primitives_traits::{Account, StorageEntry};
518    use reth_storage_errors::db::{DatabaseWriteError, DatabaseWriteOperation};
519    use std::str::FromStr;
520    use tempfile::TempDir;
521
522    /// Create database for testing
523    fn create_test_db(kind: DatabaseEnvKind) -> Arc<DatabaseEnv> {
524        Arc::new(create_test_db_with_path(
525            kind,
526            &tempfile::TempDir::new().expect(ERROR_TEMPDIR).into_path(),
527        ))
528    }
529
530    /// Create database for testing with specified path
531    fn create_test_db_with_path(kind: DatabaseEnvKind, path: &Path) -> DatabaseEnv {
532        let env = DatabaseEnv::open(path, kind, DatabaseArguments::new(ClientVersion::default()))
533            .expect(ERROR_DB_CREATION);
534        env.create_tables().expect(ERROR_TABLE_CREATION);
535        env
536    }
537
538    const ERROR_DB_CREATION: &str = "Not able to create the mdbx file.";
539    const ERROR_PUT: &str = "Not able to insert value into table.";
540    const ERROR_APPEND: &str = "Not able to append the value to the table.";
541    const ERROR_UPSERT: &str = "Not able to upsert the value to the table.";
542    const ERROR_GET: &str = "Not able to get value from table.";
543    const ERROR_DEL: &str = "Not able to delete from table.";
544    const ERROR_COMMIT: &str = "Not able to commit transaction.";
545    const ERROR_RETURN_VALUE: &str = "Mismatching result.";
546    const ERROR_INIT_TX: &str = "Failed to create a MDBX transaction.";
547    const ERROR_ETH_ADDRESS: &str = "Invalid address.";
548
549    #[test]
550    fn db_creation() {
551        create_test_db(DatabaseEnvKind::RW);
552    }
553
554    #[test]
555    fn db_manual_put_get() {
556        let env = create_test_db(DatabaseEnvKind::RW);
557
558        let value = Header::default();
559        let key = 1u64;
560
561        // PUT
562        let tx = env.tx_mut().expect(ERROR_INIT_TX);
563        tx.put::<Headers>(key, value.clone()).expect(ERROR_PUT);
564        tx.commit().expect(ERROR_COMMIT);
565
566        // GET
567        let tx = env.tx().expect(ERROR_INIT_TX);
568        let result = tx.get::<Headers>(key).expect(ERROR_GET);
569        assert_eq!(result.expect(ERROR_RETURN_VALUE), value);
570        tx.commit().expect(ERROR_COMMIT);
571    }
572
573    #[test]
574    fn db_dup_cursor_delete_first() {
575        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
576        let tx = db.tx_mut().expect(ERROR_INIT_TX);
577
578        let mut dup_cursor = tx.cursor_dup_write::<PlainStorageState>().unwrap();
579
580        let entry_0 = StorageEntry {
581            key: B256::with_last_byte(1),
582            value: U256::from(0),
583            ..Default::default()
584        };
585        let entry_1 = StorageEntry {
586            key: B256::with_last_byte(1),
587            value: U256::from(1),
588            ..Default::default()
589        };
590
591        dup_cursor.upsert(Address::with_last_byte(1), entry_0).expect(ERROR_UPSERT);
592        dup_cursor.upsert(Address::with_last_byte(1), entry_1).expect(ERROR_UPSERT);
593
594        assert_eq!(
595            dup_cursor.walk(None).unwrap().collect::<Result<Vec<_>, _>>(),
596            Ok(vec![(Address::with_last_byte(1), entry_0), (Address::with_last_byte(1), entry_1),])
597        );
598
599        let mut walker = dup_cursor.walk(None).unwrap();
600        walker.delete_current().expect(ERROR_DEL);
601
602        assert_eq!(walker.next(), Some(Ok((Address::with_last_byte(1), entry_1))));
603
604        // Check the tx view - it correctly holds entry_1
605        assert_eq!(
606            tx.cursor_dup_read::<PlainStorageState>()
607                .unwrap()
608                .walk(None)
609                .unwrap()
610                .collect::<Result<Vec<_>, _>>(),
611            Ok(vec![
612                (Address::with_last_byte(1), entry_1), // This is ok - we removed entry_0
613            ])
614        );
615
616        // Check the remainder of walker
617        assert_eq!(walker.next(), None);
618    }
619
620    #[test]
621    fn db_cursor_walk() {
622        let env = create_test_db(DatabaseEnvKind::RW);
623
624        let value = Header::default();
625        let key = 1u64;
626
627        // PUT
628        let tx = env.tx_mut().expect(ERROR_INIT_TX);
629        tx.put::<Headers>(key, value.clone()).expect(ERROR_PUT);
630        tx.commit().expect(ERROR_COMMIT);
631
632        // Cursor
633        let tx = env.tx().expect(ERROR_INIT_TX);
634        let mut cursor = tx.cursor_read::<Headers>().unwrap();
635
636        let first = cursor.first().unwrap();
637        assert!(first.is_some(), "First should be our put");
638
639        // Walk
640        let walk = cursor.walk(Some(key)).unwrap();
641        let first = walk.into_iter().next().unwrap().unwrap();
642        assert_eq!(first.1, value, "First next should be put value");
643    }
644
645    #[test]
646    fn db_cursor_walk_range() {
647        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
648
649        // PUT (0, 0), (1, 0), (2, 0), (3, 0)
650        let tx = db.tx_mut().expect(ERROR_INIT_TX);
651        vec![0, 1, 2, 3]
652            .into_iter()
653            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
654            .expect(ERROR_PUT);
655        tx.commit().expect(ERROR_COMMIT);
656
657        let tx = db.tx().expect(ERROR_INIT_TX);
658        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
659
660        // [1, 3)
661        let mut walker = cursor.walk_range(1..3).unwrap();
662        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
663        assert_eq!(walker.next(), Some(Ok((2, B256::ZERO))));
664        assert_eq!(walker.next(), None);
665        // next() returns None after walker is done
666        assert_eq!(walker.next(), None);
667
668        // [1, 2]
669        let mut walker = cursor.walk_range(1..=2).unwrap();
670        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
671        assert_eq!(walker.next(), Some(Ok((2, B256::ZERO))));
672        // next() returns None after walker is done
673        assert_eq!(walker.next(), None);
674
675        // [1, ∞)
676        let mut walker = cursor.walk_range(1..).unwrap();
677        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
678        assert_eq!(walker.next(), Some(Ok((2, B256::ZERO))));
679        assert_eq!(walker.next(), Some(Ok((3, B256::ZERO))));
680        // next() returns None after walker is done
681        assert_eq!(walker.next(), None);
682
683        // [2, 4)
684        let mut walker = cursor.walk_range(2..4).unwrap();
685        assert_eq!(walker.next(), Some(Ok((2, B256::ZERO))));
686        assert_eq!(walker.next(), Some(Ok((3, B256::ZERO))));
687        assert_eq!(walker.next(), None);
688        // next() returns None after walker is done
689        assert_eq!(walker.next(), None);
690
691        // (∞, 3)
692        let mut walker = cursor.walk_range(..3).unwrap();
693        assert_eq!(walker.next(), Some(Ok((0, B256::ZERO))));
694        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
695        assert_eq!(walker.next(), Some(Ok((2, B256::ZERO))));
696        // next() returns None after walker is done
697        assert_eq!(walker.next(), None);
698
699        // (∞, ∞)
700        let mut walker = cursor.walk_range(..).unwrap();
701        assert_eq!(walker.next(), Some(Ok((0, B256::ZERO))));
702        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
703        assert_eq!(walker.next(), Some(Ok((2, B256::ZERO))));
704        assert_eq!(walker.next(), Some(Ok((3, B256::ZERO))));
705        // next() returns None after walker is done
706        assert_eq!(walker.next(), None);
707    }
708
709    #[test]
710    fn db_cursor_walk_range_on_dup_table() {
711        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
712
713        let address0 = Address::ZERO;
714        let address1 = Address::with_last_byte(1);
715        let address2 = Address::with_last_byte(2);
716
717        let tx = db.tx_mut().expect(ERROR_INIT_TX);
718        tx.put::<AccountChangeSets>(0, AccountBeforeTx { address: address0, info: None })
719            .expect(ERROR_PUT);
720        tx.put::<AccountChangeSets>(0, AccountBeforeTx { address: address1, info: None })
721            .expect(ERROR_PUT);
722        tx.put::<AccountChangeSets>(0, AccountBeforeTx { address: address2, info: None })
723            .expect(ERROR_PUT);
724        tx.put::<AccountChangeSets>(1, AccountBeforeTx { address: address0, info: None })
725            .expect(ERROR_PUT);
726        tx.put::<AccountChangeSets>(1, AccountBeforeTx { address: address1, info: None })
727            .expect(ERROR_PUT);
728        tx.put::<AccountChangeSets>(1, AccountBeforeTx { address: address2, info: None })
729            .expect(ERROR_PUT);
730        tx.put::<AccountChangeSets>(2, AccountBeforeTx { address: address0, info: None }) // <- should not be returned by the walker
731            .expect(ERROR_PUT);
732        tx.commit().expect(ERROR_COMMIT);
733
734        let tx = db.tx().expect(ERROR_INIT_TX);
735        let mut cursor = tx.cursor_read::<AccountChangeSets>().unwrap();
736
737        let entries = cursor.walk_range(..).unwrap().collect::<Result<Vec<_>, _>>().unwrap();
738        assert_eq!(entries.len(), 7);
739
740        let mut walker = cursor.walk_range(0..=1).unwrap();
741        assert_eq!(walker.next(), Some(Ok((0, AccountBeforeTx { address: address0, info: None }))));
742        assert_eq!(walker.next(), Some(Ok((0, AccountBeforeTx { address: address1, info: None }))));
743        assert_eq!(walker.next(), Some(Ok((0, AccountBeforeTx { address: address2, info: None }))));
744        assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address0, info: None }))));
745        assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address1, info: None }))));
746        assert_eq!(walker.next(), Some(Ok((1, AccountBeforeTx { address: address2, info: None }))));
747        assert_eq!(walker.next(), None);
748    }
749
750    #[allow(clippy::reversed_empty_ranges)]
751    #[test]
752    fn db_cursor_walk_range_invalid() {
753        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
754
755        // PUT (0, 0), (1, 0), (2, 0), (3, 0)
756        let tx = db.tx_mut().expect(ERROR_INIT_TX);
757        vec![0, 1, 2, 3]
758            .into_iter()
759            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
760            .expect(ERROR_PUT);
761        tx.commit().expect(ERROR_COMMIT);
762
763        let tx = db.tx().expect(ERROR_INIT_TX);
764        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
765
766        // start bound greater than end bound
767        let mut res = cursor.walk_range(3..1).unwrap();
768        assert_eq!(res.next(), None);
769
770        // start bound greater than end bound
771        let mut res = cursor.walk_range(15..=2).unwrap();
772        assert_eq!(res.next(), None);
773
774        // returning nothing
775        let mut walker = cursor.walk_range(1..1).unwrap();
776        assert_eq!(walker.next(), None);
777    }
778
779    #[test]
780    fn db_walker() {
781        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
782
783        // PUT (0, 0), (1, 0), (3, 0)
784        let tx = db.tx_mut().expect(ERROR_INIT_TX);
785        vec![0, 1, 3]
786            .into_iter()
787            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
788            .expect(ERROR_PUT);
789        tx.commit().expect(ERROR_COMMIT);
790
791        let tx = db.tx().expect(ERROR_INIT_TX);
792        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
793
794        let mut walker = Walker::new(&mut cursor, None);
795
796        assert_eq!(walker.next(), Some(Ok((0, B256::ZERO))));
797        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
798        assert_eq!(walker.next(), Some(Ok((3, B256::ZERO))));
799        assert_eq!(walker.next(), None);
800
801        // transform to ReverseWalker
802        let mut reverse_walker = walker.rev();
803        assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO))));
804        assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO))));
805        assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO))));
806        assert_eq!(reverse_walker.next(), None);
807    }
808
809    #[test]
810    fn db_reverse_walker() {
811        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
812
813        // PUT (0, 0), (1, 0), (3, 0)
814        let tx = db.tx_mut().expect(ERROR_INIT_TX);
815        vec![0, 1, 3]
816            .into_iter()
817            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
818            .expect(ERROR_PUT);
819        tx.commit().expect(ERROR_COMMIT);
820
821        let tx = db.tx().expect(ERROR_INIT_TX);
822        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
823
824        let mut reverse_walker = ReverseWalker::new(&mut cursor, None);
825
826        assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO))));
827        assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO))));
828        assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO))));
829        assert_eq!(reverse_walker.next(), None);
830
831        // transform to Walker
832        let mut walker = reverse_walker.forward();
833        assert_eq!(walker.next(), Some(Ok((0, B256::ZERO))));
834        assert_eq!(walker.next(), Some(Ok((1, B256::ZERO))));
835        assert_eq!(walker.next(), Some(Ok((3, B256::ZERO))));
836        assert_eq!(walker.next(), None);
837    }
838
839    #[test]
840    fn db_walk_back() {
841        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
842
843        // PUT (0, 0), (1, 0), (3, 0)
844        let tx = db.tx_mut().expect(ERROR_INIT_TX);
845        vec![0, 1, 3]
846            .into_iter()
847            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
848            .expect(ERROR_PUT);
849        tx.commit().expect(ERROR_COMMIT);
850
851        let tx = db.tx().expect(ERROR_INIT_TX);
852        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
853
854        let mut reverse_walker = cursor.walk_back(Some(1)).unwrap();
855        assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO))));
856        assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO))));
857        assert_eq!(reverse_walker.next(), None);
858
859        let mut reverse_walker = cursor.walk_back(Some(2)).unwrap();
860        assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO))));
861        assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO))));
862        assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO))));
863        assert_eq!(reverse_walker.next(), None);
864
865        let mut reverse_walker = cursor.walk_back(Some(4)).unwrap();
866        assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO))));
867        assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO))));
868        assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO))));
869        assert_eq!(reverse_walker.next(), None);
870
871        let mut reverse_walker = cursor.walk_back(None).unwrap();
872        assert_eq!(reverse_walker.next(), Some(Ok((3, B256::ZERO))));
873        assert_eq!(reverse_walker.next(), Some(Ok((1, B256::ZERO))));
874        assert_eq!(reverse_walker.next(), Some(Ok((0, B256::ZERO))));
875        assert_eq!(reverse_walker.next(), None);
876    }
877
878    #[test]
879    fn db_cursor_seek_exact_or_previous_key() {
880        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
881
882        // PUT
883        let tx = db.tx_mut().expect(ERROR_INIT_TX);
884        vec![0, 1, 3]
885            .into_iter()
886            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
887            .expect(ERROR_PUT);
888        tx.commit().expect(ERROR_COMMIT);
889
890        // Cursor
891        let missing_key = 2;
892        let tx = db.tx().expect(ERROR_INIT_TX);
893        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
894        assert_eq!(cursor.current(), Ok(None));
895
896        // Seek exact
897        let exact = cursor.seek_exact(missing_key).unwrap();
898        assert_eq!(exact, None);
899        assert_eq!(cursor.current(), Ok(Some((missing_key + 1, B256::ZERO))));
900        assert_eq!(cursor.prev(), Ok(Some((missing_key - 1, B256::ZERO))));
901        assert_eq!(cursor.prev(), Ok(Some((missing_key - 2, B256::ZERO))));
902    }
903
904    #[test]
905    fn db_cursor_insert() {
906        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
907
908        // PUT
909        let tx = db.tx_mut().expect(ERROR_INIT_TX);
910        vec![0, 1, 3, 4, 5]
911            .into_iter()
912            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
913            .expect(ERROR_PUT);
914        tx.commit().expect(ERROR_COMMIT);
915
916        let key_to_insert = 2;
917        let tx = db.tx_mut().expect(ERROR_INIT_TX);
918        let mut cursor = tx.cursor_write::<CanonicalHeaders>().unwrap();
919
920        // INSERT
921        assert_eq!(cursor.insert(key_to_insert, B256::ZERO), Ok(()));
922        assert_eq!(cursor.current(), Ok(Some((key_to_insert, B256::ZERO))));
923
924        // INSERT (failure)
925        assert_eq!(
926            cursor.insert(key_to_insert, B256::ZERO),
927            Err(DatabaseWriteError {
928                info: Error::KeyExist.into(),
929                operation: DatabaseWriteOperation::CursorInsert,
930                table_name: CanonicalHeaders::NAME,
931                key: key_to_insert.encode().into(),
932            }
933            .into())
934        );
935        assert_eq!(cursor.current(), Ok(Some((key_to_insert, B256::ZERO))));
936
937        tx.commit().expect(ERROR_COMMIT);
938
939        // Confirm the result
940        let tx = db.tx().expect(ERROR_INIT_TX);
941        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
942        let res = cursor.walk(None).unwrap().map(|res| res.unwrap().0).collect::<Vec<_>>();
943        assert_eq!(res, vec![0, 1, 2, 3, 4, 5]);
944        tx.commit().expect(ERROR_COMMIT);
945    }
946
947    #[test]
948    fn db_cursor_insert_dup() {
949        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
950        let tx = db.tx_mut().expect(ERROR_INIT_TX);
951
952        let mut dup_cursor = tx.cursor_dup_write::<PlainStorageState>().unwrap();
953        let key = Address::random();
954        let subkey1 = B256::random();
955        let subkey2 = B256::random();
956
957        let entry1 = StorageEntry { key: subkey1, value: U256::ZERO, ..Default::default() };
958        assert!(dup_cursor.insert(key, entry1).is_ok());
959
960        // Can't insert
961        let entry2 = StorageEntry { key: subkey2, value: U256::ZERO, ..Default::default() };
962        assert!(dup_cursor.insert(key, entry2).is_err());
963    }
964
965    #[test]
966    fn db_cursor_delete_current_non_existent() {
967        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
968        let tx = db.tx_mut().expect(ERROR_INIT_TX);
969
970        let key1 = Address::with_last_byte(1);
971        let key2 = Address::with_last_byte(2);
972        let key3 = Address::with_last_byte(3);
973        let mut cursor = tx.cursor_write::<PlainAccountState>().unwrap();
974
975        assert!(cursor.insert(key1, Account::default()).is_ok());
976        assert!(cursor.insert(key2, Account::default()).is_ok());
977        assert!(cursor.insert(key3, Account::default()).is_ok());
978
979        // Seek & delete key2
980        cursor.seek_exact(key2).unwrap();
981        assert_eq!(cursor.delete_current(), Ok(()));
982        assert_eq!(cursor.seek_exact(key2), Ok(None));
983
984        // Seek & delete key2 again
985        assert_eq!(cursor.seek_exact(key2), Ok(None));
986        assert_eq!(cursor.delete_current(), Ok(()));
987        // Assert that key1 is still there
988        assert_eq!(cursor.seek_exact(key1), Ok(Some((key1, Account::default()))));
989        // Assert that key3 was deleted
990        assert_eq!(cursor.seek_exact(key3), Ok(None));
991    }
992
993    #[test]
994    fn db_cursor_insert_wherever_cursor_is() {
995        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
996        let tx = db.tx_mut().expect(ERROR_INIT_TX);
997
998        // PUT
999        vec![0, 1, 3, 5, 7, 9]
1000            .into_iter()
1001            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
1002            .expect(ERROR_PUT);
1003        tx.commit().expect(ERROR_COMMIT);
1004
1005        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1006        let mut cursor = tx.cursor_write::<CanonicalHeaders>().unwrap();
1007
1008        // INSERT (cursor starts at last)
1009        cursor.last().unwrap();
1010        assert_eq!(cursor.current(), Ok(Some((9, B256::ZERO))));
1011
1012        for pos in (2..=8).step_by(2) {
1013            assert_eq!(cursor.insert(pos, B256::ZERO), Ok(()));
1014            assert_eq!(cursor.current(), Ok(Some((pos, B256::ZERO))));
1015        }
1016        tx.commit().expect(ERROR_COMMIT);
1017
1018        // Confirm the result
1019        let tx = db.tx().expect(ERROR_INIT_TX);
1020        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
1021        let res = cursor.walk(None).unwrap().map(|res| res.unwrap().0).collect::<Vec<_>>();
1022        assert_eq!(res, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
1023        tx.commit().expect(ERROR_COMMIT);
1024    }
1025
1026    #[test]
1027    fn db_cursor_append() {
1028        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
1029
1030        // PUT
1031        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1032        vec![0, 1, 2, 3, 4]
1033            .into_iter()
1034            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
1035            .expect(ERROR_PUT);
1036        tx.commit().expect(ERROR_COMMIT);
1037
1038        // APPEND
1039        let key_to_append = 5;
1040        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1041        let mut cursor = tx.cursor_write::<CanonicalHeaders>().unwrap();
1042        assert_eq!(cursor.append(key_to_append, B256::ZERO), Ok(()));
1043        tx.commit().expect(ERROR_COMMIT);
1044
1045        // Confirm the result
1046        let tx = db.tx().expect(ERROR_INIT_TX);
1047        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
1048        let res = cursor.walk(None).unwrap().map(|res| res.unwrap().0).collect::<Vec<_>>();
1049        assert_eq!(res, vec![0, 1, 2, 3, 4, 5]);
1050        tx.commit().expect(ERROR_COMMIT);
1051    }
1052
1053    #[test]
1054    fn db_cursor_append_failure() {
1055        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
1056
1057        // PUT
1058        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1059        vec![0, 1, 3, 4, 5]
1060            .into_iter()
1061            .try_for_each(|key| tx.put::<CanonicalHeaders>(key, B256::ZERO))
1062            .expect(ERROR_PUT);
1063        tx.commit().expect(ERROR_COMMIT);
1064
1065        // APPEND
1066        let key_to_append = 2;
1067        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1068        let mut cursor = tx.cursor_write::<CanonicalHeaders>().unwrap();
1069        assert_eq!(
1070            cursor.append(key_to_append, B256::ZERO),
1071            Err(DatabaseWriteError {
1072                info: Error::KeyMismatch.into(),
1073                operation: DatabaseWriteOperation::CursorAppend,
1074                table_name: CanonicalHeaders::NAME,
1075                key: key_to_append.encode().into(),
1076            }
1077            .into())
1078        );
1079        assert_eq!(cursor.current(), Ok(Some((5, B256::ZERO)))); // the end of table
1080        tx.commit().expect(ERROR_COMMIT);
1081
1082        // Confirm the result
1083        let tx = db.tx().expect(ERROR_INIT_TX);
1084        let mut cursor = tx.cursor_read::<CanonicalHeaders>().unwrap();
1085        let res = cursor.walk(None).unwrap().map(|res| res.unwrap().0).collect::<Vec<_>>();
1086        assert_eq!(res, vec![0, 1, 3, 4, 5]);
1087        tx.commit().expect(ERROR_COMMIT);
1088    }
1089
1090    #[test]
1091    fn db_cursor_upsert() {
1092        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
1093        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1094
1095        let mut cursor = tx.cursor_write::<PlainAccountState>().unwrap();
1096        let key = Address::random();
1097
1098        let account = Account::default();
1099        cursor.upsert(key, account).expect(ERROR_UPSERT);
1100        assert_eq!(cursor.seek_exact(key), Ok(Some((key, account))));
1101
1102        let account = Account { nonce: 1, ..Default::default() };
1103        cursor.upsert(key, account).expect(ERROR_UPSERT);
1104        assert_eq!(cursor.seek_exact(key), Ok(Some((key, account))));
1105
1106        let account = Account { nonce: 2, ..Default::default() };
1107        cursor.upsert(key, account).expect(ERROR_UPSERT);
1108        assert_eq!(cursor.seek_exact(key), Ok(Some((key, account))));
1109
1110        let mut dup_cursor = tx.cursor_dup_write::<PlainStorageState>().unwrap();
1111        let subkey = B256::random();
1112
1113        let value = U256::from(1);
1114        let entry1 = StorageEntry { key: subkey, value, ..Default::default() };
1115        dup_cursor.upsert(key, entry1).expect(ERROR_UPSERT);
1116        assert_eq!(dup_cursor.seek_by_key_subkey(key, subkey), Ok(Some(entry1)));
1117
1118        let value = U256::from(2);
1119        let entry2 = StorageEntry { key: subkey, value, ..Default::default() };
1120        dup_cursor.upsert(key, entry2).expect(ERROR_UPSERT);
1121        assert_eq!(dup_cursor.seek_by_key_subkey(key, subkey), Ok(Some(entry1)));
1122        assert_eq!(dup_cursor.next_dup_val(), Ok(Some(entry2)));
1123    }
1124
1125    #[test]
1126    fn db_cursor_dupsort_append() {
1127        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
1128
1129        let transition_id = 2;
1130
1131        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1132        let mut cursor = tx.cursor_write::<AccountChangeSets>().unwrap();
1133        vec![0, 1, 3, 4, 5]
1134            .into_iter()
1135            .try_for_each(|val| {
1136                cursor.append(
1137                    transition_id,
1138                    AccountBeforeTx { address: Address::with_last_byte(val), info: None },
1139                )
1140            })
1141            .expect(ERROR_APPEND);
1142        tx.commit().expect(ERROR_COMMIT);
1143
1144        // APPEND DUP & APPEND
1145        let subkey_to_append = 2;
1146        let tx = db.tx_mut().expect(ERROR_INIT_TX);
1147        let mut cursor = tx.cursor_write::<AccountChangeSets>().unwrap();
1148        assert_eq!(
1149            cursor.append_dup(
1150                transition_id,
1151                AccountBeforeTx { address: Address::with_last_byte(subkey_to_append), info: None }
1152            ),
1153            Err(DatabaseWriteError {
1154                info: Error::KeyMismatch.into(),
1155                operation: DatabaseWriteOperation::CursorAppendDup,
1156                table_name: AccountChangeSets::NAME,
1157                key: transition_id.encode().into(),
1158            }
1159            .into())
1160        );
1161        assert_eq!(
1162            cursor.append(
1163                transition_id - 1,
1164                AccountBeforeTx { address: Address::with_last_byte(subkey_to_append), info: None }
1165            ),
1166            Err(DatabaseWriteError {
1167                info: Error::KeyMismatch.into(),
1168                operation: DatabaseWriteOperation::CursorAppend,
1169                table_name: AccountChangeSets::NAME,
1170                key: (transition_id - 1).encode().into(),
1171            }
1172            .into())
1173        );
1174        assert_eq!(
1175            cursor.append(
1176                transition_id,
1177                AccountBeforeTx { address: Address::with_last_byte(subkey_to_append), info: None }
1178            ),
1179            Ok(())
1180        );
1181    }
1182
1183    #[test]
1184    fn db_closure_put_get() {
1185        let path = TempDir::new().expect(ERROR_TEMPDIR).into_path();
1186
1187        let value = Account {
1188            nonce: 18446744073709551615,
1189            bytecode_hash: Some(B256::random()),
1190            balance: U256::MAX,
1191        };
1192        let key = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047")
1193            .expect(ERROR_ETH_ADDRESS);
1194
1195        {
1196            let env = create_test_db_with_path(DatabaseEnvKind::RW, &path);
1197
1198            // PUT
1199            let result = env.update(|tx| {
1200                tx.put::<PlainAccountState>(key, value).expect(ERROR_PUT);
1201                200
1202            });
1203            assert_eq!(result.expect(ERROR_RETURN_VALUE), 200);
1204        }
1205
1206        let env = DatabaseEnv::open(
1207            &path,
1208            DatabaseEnvKind::RO,
1209            DatabaseArguments::new(ClientVersion::default()),
1210        )
1211        .expect(ERROR_DB_CREATION);
1212
1213        // GET
1214        let result =
1215            env.view(|tx| tx.get::<PlainAccountState>(key).expect(ERROR_GET)).expect(ERROR_GET);
1216
1217        assert_eq!(result, Some(value))
1218    }
1219
1220    #[test]
1221    fn db_dup_sort() {
1222        let env = create_test_db(DatabaseEnvKind::RW);
1223        let key = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047")
1224            .expect(ERROR_ETH_ADDRESS);
1225
1226        // PUT (0,0)
1227        let value00 = StorageEntry::default();
1228        env.update(|tx| tx.put::<PlainStorageState>(key, value00).expect(ERROR_PUT)).unwrap();
1229
1230        // PUT (2,2)
1231        let value22 = StorageEntry {
1232            key: B256::with_last_byte(2),
1233            value: U256::from(2),
1234            ..Default::default()
1235        };
1236        env.update(|tx| tx.put::<PlainStorageState>(key, value22).expect(ERROR_PUT)).unwrap();
1237
1238        // PUT (1,1)
1239        let value11 = StorageEntry {
1240            key: B256::with_last_byte(1),
1241            value: U256::from(1),
1242            ..Default::default()
1243        };
1244        env.update(|tx| tx.put::<PlainStorageState>(key, value11).expect(ERROR_PUT)).unwrap();
1245
1246        // Iterate with cursor
1247        {
1248            let tx = env.tx().expect(ERROR_INIT_TX);
1249            let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1250
1251            // Notice that value11 and value22 have been ordered in the DB.
1252            assert_eq!(Some(value00), cursor.next_dup_val().unwrap());
1253            assert_eq!(Some(value11), cursor.next_dup_val().unwrap());
1254            assert_eq!(Some(value22), cursor.next_dup_val().unwrap());
1255        }
1256
1257        // Seek value with exact subkey
1258        {
1259            let tx = env.tx().expect(ERROR_INIT_TX);
1260            let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1261            let mut walker = cursor.walk_dup(Some(key), Some(B256::with_last_byte(1))).unwrap();
1262            assert_eq!(
1263                (key, value11),
1264                walker
1265                    .next()
1266                    .expect("element should exist.")
1267                    .expect("should be able to retrieve it.")
1268            );
1269        }
1270    }
1271
1272    #[test]
1273    fn db_iterate_over_all_dup_values() {
1274        let env = create_test_db(DatabaseEnvKind::RW);
1275        let key1 = Address::from_str("0x1111111111111111111111111111111111111111")
1276            .expect(ERROR_ETH_ADDRESS);
1277        let key2 = Address::from_str("0x2222222222222222222222222222222222222222")
1278            .expect(ERROR_ETH_ADDRESS);
1279
1280        // PUT key1 (0,0)
1281        let value00 = StorageEntry::default();
1282        env.update(|tx| tx.put::<PlainStorageState>(key1, value00).expect(ERROR_PUT)).unwrap();
1283
1284        // PUT key1 (1,1)
1285        let value11 = StorageEntry {
1286            key: B256::with_last_byte(1),
1287            value: U256::from(1),
1288            ..Default::default()
1289        };
1290        env.update(|tx| tx.put::<PlainStorageState>(key1, value11).expect(ERROR_PUT)).unwrap();
1291
1292        // PUT key2 (2,2)
1293        let value22 = StorageEntry {
1294            key: B256::with_last_byte(2),
1295            value: U256::from(2),
1296            ..Default::default()
1297        };
1298        env.update(|tx| tx.put::<PlainStorageState>(key2, value22).expect(ERROR_PUT)).unwrap();
1299
1300        // Iterate with walk_dup
1301        {
1302            let tx = env.tx().expect(ERROR_INIT_TX);
1303            let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1304            let mut walker = cursor.walk_dup(None, None).unwrap();
1305
1306            // Notice that value11 and value22 have been ordered in the DB.
1307            assert_eq!(Some(Ok((key1, value00))), walker.next());
1308            assert_eq!(Some(Ok((key1, value11))), walker.next());
1309            // NOTE: Dup cursor does NOT iterates on all values but only on duplicated values of the
1310            // same key. assert_eq!(Ok(Some(value22.clone())), walker.next());
1311            assert_eq!(None, walker.next());
1312        }
1313
1314        // Iterate by using `walk`
1315        {
1316            let tx = env.tx().expect(ERROR_INIT_TX);
1317            let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1318            let first = cursor.first().unwrap().unwrap();
1319            let mut walker = cursor.walk(Some(first.0)).unwrap();
1320            assert_eq!(Some(Ok((key1, value00))), walker.next());
1321            assert_eq!(Some(Ok((key1, value11))), walker.next());
1322            assert_eq!(Some(Ok((key2, value22))), walker.next());
1323        }
1324    }
1325
1326    #[test]
1327    fn dup_value_with_same_subkey() {
1328        let env = create_test_db(DatabaseEnvKind::RW);
1329        let key1 = Address::new([0x11; 20]);
1330        let key2 = Address::new([0x22; 20]);
1331
1332        // PUT key1 (0,1)
1333        let value01 = StorageEntry {
1334            key: B256::with_last_byte(0),
1335            value: U256::from(1),
1336            ..Default::default()
1337        };
1338        env.update(|tx| tx.put::<PlainStorageState>(key1, value01).expect(ERROR_PUT)).unwrap();
1339
1340        // PUT key1 (0,0)
1341        let value00 = StorageEntry::default();
1342        env.update(|tx| tx.put::<PlainStorageState>(key1, value00).expect(ERROR_PUT)).unwrap();
1343
1344        // PUT key2 (2,2)
1345        let value22 = StorageEntry {
1346            key: B256::with_last_byte(2),
1347            value: U256::from(2),
1348            ..Default::default()
1349        };
1350        env.update(|tx| tx.put::<PlainStorageState>(key2, value22).expect(ERROR_PUT)).unwrap();
1351
1352        // Iterate with walk
1353        {
1354            let tx = env.tx().expect(ERROR_INIT_TX);
1355            let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1356            let first = cursor.first().unwrap().unwrap();
1357            let mut walker = cursor.walk(Some(first.0)).unwrap();
1358
1359            // NOTE: Both values are present
1360            assert_eq!(Some(Ok((key1, value00))), walker.next());
1361            assert_eq!(Some(Ok((key1, value01))), walker.next());
1362            assert_eq!(Some(Ok((key2, value22))), walker.next());
1363        }
1364
1365        // seek_by_key_subkey
1366        {
1367            let tx = env.tx().expect(ERROR_INIT_TX);
1368            let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1369
1370            // NOTE: There are two values with same SubKey but only first one is shown
1371            assert_eq!(Ok(Some(value00)), cursor.seek_by_key_subkey(key1, value00.key));
1372            // key1 but value is greater than the one in the DB
1373            assert_eq!(Ok(None), cursor.seek_by_key_subkey(key1, value22.key));
1374        }
1375    }
1376
1377    #[test]
1378    fn db_sharded_key() {
1379        let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
1380        let real_key = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047").unwrap();
1381
1382        for i in 1..5 {
1383            let key = ShardedKey::new(real_key, i * 100);
1384            let list = IntegerList::new_pre_sorted([i * 100u64]);
1385
1386            db.update(|tx| tx.put::<AccountsHistory>(key.clone(), list.clone()).expect(""))
1387                .unwrap();
1388        }
1389
1390        // Seek value with non existing key.
1391        {
1392            let tx = db.tx().expect(ERROR_INIT_TX);
1393            let mut cursor = tx.cursor_read::<AccountsHistory>().unwrap();
1394
1395            // It will seek the one greater or equal to the query. Since we have `Address | 100`,
1396            // `Address | 200` in the database and we're querying `Address | 150` it will return us
1397            // `Address | 200`.
1398            let mut walker = cursor.walk(Some(ShardedKey::new(real_key, 150))).unwrap();
1399            let (key, list) = walker
1400                .next()
1401                .expect("element should exist.")
1402                .expect("should be able to retrieve it.");
1403
1404            assert_eq!(ShardedKey::new(real_key, 200), key);
1405            let list200 = IntegerList::new_pre_sorted([200u64]);
1406            assert_eq!(list200, list);
1407        }
1408        // Seek greatest index
1409        {
1410            let tx = db.tx().expect(ERROR_INIT_TX);
1411            let mut cursor = tx.cursor_read::<AccountsHistory>().unwrap();
1412
1413            // It will seek the MAX value of transition index and try to use prev to get first
1414            // biggers.
1415            let _unknown = cursor.seek_exact(ShardedKey::new(real_key, u64::MAX)).unwrap();
1416            let (key, list) = cursor
1417                .prev()
1418                .expect("element should exist.")
1419                .expect("should be able to retrieve it.");
1420
1421            assert_eq!(ShardedKey::new(real_key, 400), key);
1422            let list400 = IntegerList::new_pre_sorted([400u64]);
1423            assert_eq!(list400, list);
1424        }
1425    }
1426}