1use 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
36pub const KILOBYTE: usize = 1024;
38pub const MEGABYTE: usize = KILOBYTE * 1024;
40pub const GIGABYTE: usize = MEGABYTE * 1024;
42pub const TERABYTE: usize = GIGABYTE * 1024;
44
45const DEFAULT_MAX_READERS: u64 = 32_000;
47
48const MAX_SAFE_READER_SPACE: usize = 10 * GIGABYTE;
51
52#[derive(Debug)]
54pub enum DatabaseEnvKind {
55 RO,
57 RW,
59}
60
61impl DatabaseEnvKind {
62 pub const fn is_rw(&self) -> bool {
64 matches!(self, Self::RW)
65 }
66}
67
68#[derive(Clone, Debug)]
70pub struct DatabaseArguments {
71 client_version: ClientVersion,
73 geometry: Geometry<Range<usize>>,
75 log_level: Option<LogLevel>,
77 max_read_transaction_duration: Option<MaxReadTransactionDuration>,
79 exclusive: Option<bool>,
100}
101
102impl Default for DatabaseArguments {
103 fn default() -> Self {
104 Self::new(ClientVersion::default())
105 }
106}
107
108impl DatabaseArguments {
109 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 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 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 pub const fn with_log_level(mut self, log_level: Option<LogLevel>) -> Self {
143 self.log_level = log_level;
144 self
145 }
146
147 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 pub const fn with_exclusive(mut self, exclusive: Option<bool>) -> Self {
158 self.exclusive = exclusive;
159 self
160 }
161
162 pub const fn client_version(&self) -> &ClientVersion {
164 &self.client_version
165 }
166}
167
168#[derive(Debug)]
170pub struct DatabaseEnv {
171 inner: Environment,
173 metrics: Option<Arc<DatabaseEnvMetrics>>,
175 _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 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 inner_env.write_map();
309 Mode::ReadWrite { sync_mode: SyncMode::Durable }
310 }
311 };
312
313 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 no_rdahead: true,
369 coalesce: true,
370 exclusive: args.exclusive.unwrap_or_default(),
371 ..Default::default()
372 });
373 inner_env.set_max_readers(DEFAULT_MAX_READERS);
375 inner_env.set_rp_augment_limit(256 * 1024);
401
402 if let Some(log_level) = args.log_level {
403 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 pub fn with_metrics(mut self) -> Self {
443 self.metrics = Some(DatabaseEnvMetrics::new().into());
444 self
445 }
446
447 pub fn create_tables(&self) -> Result<(), DatabaseError> {
449 self.create_tables_for::<Tables>()
450 }
451
452 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 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 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 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 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 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 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), ])
614 );
615
616 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 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 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 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 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 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 assert_eq!(walker.next(), None);
667
668 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 assert_eq!(walker.next(), None);
674
675 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 assert_eq!(walker.next(), None);
682
683 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 assert_eq!(walker.next(), None);
690
691 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 assert_eq!(walker.next(), None);
698
699 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 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 }) .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 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 let mut res = cursor.walk_range(3..1).unwrap();
768 assert_eq!(res.next(), None);
769
770 let mut res = cursor.walk_range(15..=2).unwrap();
772 assert_eq!(res.next(), None);
773
774 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 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 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 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 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 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 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 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 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 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 assert_eq!(cursor.insert(key_to_insert, B256::ZERO), Ok(()));
922 assert_eq!(cursor.current(), Ok(Some((key_to_insert, B256::ZERO))));
923
924 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 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 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 cursor.seek_exact(key2).unwrap();
981 assert_eq!(cursor.delete_current(), Ok(()));
982 assert_eq!(cursor.seek_exact(key2), Ok(None));
983
984 assert_eq!(cursor.seek_exact(key2), Ok(None));
986 assert_eq!(cursor.delete_current(), Ok(()));
987 assert_eq!(cursor.seek_exact(key1), Ok(Some((key1, Account::default()))));
989 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 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 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 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 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 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 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 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 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)))); tx.commit().expect(ERROR_COMMIT);
1081
1082 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 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 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 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 let value00 = StorageEntry::default();
1228 env.update(|tx| tx.put::<PlainStorageState>(key, value00).expect(ERROR_PUT)).unwrap();
1229
1230 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 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 {
1248 let tx = env.tx().expect(ERROR_INIT_TX);
1249 let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1250
1251 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 {
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 let value00 = StorageEntry::default();
1282 env.update(|tx| tx.put::<PlainStorageState>(key1, value00).expect(ERROR_PUT)).unwrap();
1283
1284 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 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 {
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 assert_eq!(Some(Ok((key1, value00))), walker.next());
1308 assert_eq!(Some(Ok((key1, value11))), walker.next());
1309 assert_eq!(None, walker.next());
1312 }
1313
1314 {
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 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 let value00 = StorageEntry::default();
1342 env.update(|tx| tx.put::<PlainStorageState>(key1, value00).expect(ERROR_PUT)).unwrap();
1343
1344 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 {
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 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 {
1367 let tx = env.tx().expect(ERROR_INIT_TX);
1368 let mut cursor = tx.cursor_dup_read::<PlainStorageState>().unwrap();
1369
1370 assert_eq!(Ok(Some(value00)), cursor.seek_by_key_subkey(key1, value00.key));
1372 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 {
1392 let tx = db.tx().expect(ERROR_INIT_TX);
1393 let mut cursor = tx.cursor_read::<AccountsHistory>().unwrap();
1394
1395 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 {
1410 let tx = db.tx().expect(ERROR_INIT_TX);
1411 let mut cursor = tx.cursor_read::<AccountsHistory>().unwrap();
1412
1413 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}