From 3c5b235455e40fe152a2880c51c2145a1cabc976 Mon Sep 17 00:00:00 2001 From: joshieDo <93316087+joshieDo@users.noreply.github.com> Date: Tue, 25 Oct 2022 02:23:28 +0800 Subject: [PATCH] feat(db): Add DupSort `PlainStorageState` table (#121) * add dupsort table and test * use env.update instead Co-authored-by: Georgios Konstantopoulos --- crates/db/src/kv/mod.rs | 44 +++++++++++++++++++++--- crates/interfaces/src/db/codecs/scale.rs | 2 +- crates/interfaces/src/db/tables.rs | 27 +++++++++++---- crates/primitives/src/lib.rs | 2 ++ crates/primitives/src/storage.rs | 12 +++++++ 5 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 crates/primitives/src/storage.rs diff --git a/crates/db/src/kv/mod.rs b/crates/db/src/kv/mod.rs index 3be7eec38b..05dcfadfd9 100644 --- a/crates/db/src/kv/mod.rs +++ b/crates/db/src/kv/mod.rs @@ -136,10 +136,10 @@ mod tests { use super::{test_utils, Env, EnvKind}; use libmdbx::{NoWriteMap, WriteMap}; use reth_interfaces::db::{ - tables::{Headers, PlainState}, - Database, DbCursorRO, DbTx, DbTxMut, + tables::{Headers, PlainAccountState, PlainStorageState}, + Database, DbCursorRO, DbDupCursorRO, DbTx, DbTxMut, }; - use reth_primitives::{Account, Address, Header, H256, U256}; + use reth_primitives::{Account, Address, Header, StorageEntry, H256, U256}; use std::str::FromStr; use tempfile::TempDir; @@ -217,7 +217,7 @@ mod tests { // PUT let result = env.update(|tx| { - tx.put::(key, value).expect(ERROR_PUT); + tx.put::(key, value).expect(ERROR_PUT); 200 }); assert!(result.expect(ERROR_RETURN_VALUE) == 200); @@ -226,10 +226,44 @@ mod tests { let env = Env::::open(&path, EnvKind::RO).expect(ERROR_DB_CREATION); // GET - let result = env.view(|tx| tx.get::(key).expect(ERROR_GET)).expect(ERROR_GET); + let result = + env.view(|tx| tx.get::(key).expect(ERROR_GET)).expect(ERROR_GET); assert!(result == Some(value)) } + + #[test] + fn db_dup_sort() { + let env = test_utils::create_test_db::(EnvKind::RW); + let key = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047") + .expect(ERROR_ETH_ADDRESS); + + // PUT (0,0) + let value00 = StorageEntry::default(); + env.update(|tx| tx.put::(key.into(), value00.clone()).expect(ERROR_PUT)) + .unwrap(); + + // PUT (2,2) + let value22 = StorageEntry { key: H256::from_low_u64_be(2), value: U256::from(2) }; + env.update(|tx| tx.put::(key.into(), value22.clone()).expect(ERROR_PUT)) + .unwrap(); + + // PUT (1,1) + let value11 = StorageEntry { key: H256::from_low_u64_be(1), value: U256::from(1) }; + env.update(|tx| tx.put::(key.into(), value11.clone()).expect(ERROR_PUT)) + .unwrap(); + + // GET DUPSORT + { + let tx = env.tx().expect(ERROR_INIT_TX); + let mut cursor = tx.cursor_dup::().unwrap(); + + // Notice that value11 and value22 have been ordered in the DB. + assert!(Some(value00) == cursor.next_dup_val().unwrap()); + assert!(Some(value11) == cursor.next_dup_val().unwrap()); + assert!(Some(value22) == cursor.next_dup_val().unwrap()); + } + } } #[cfg(test)] diff --git a/crates/interfaces/src/db/codecs/scale.rs b/crates/interfaces/src/db/codecs/scale.rs index 3974913a26..15d3343aaf 100644 --- a/crates/interfaces/src/db/codecs/scale.rs +++ b/crates/interfaces/src/db/codecs/scale.rs @@ -37,7 +37,7 @@ macro_rules! impl_scale { }; } -impl_scale!(u16, H256, U256, H160, u8, u64, Header, Account, Log, Receipt, TxType); +impl_scale!(u16, H256, U256, H160, u8, u64, Header, Account, Log, Receipt, TxType, StorageEntry); impl ScaleOnly for Vec {} impl sealed::Sealed for Vec {} diff --git a/crates/interfaces/src/db/tables.rs b/crates/interfaces/src/db/tables.rs index a387c32ba6..eb43744b32 100644 --- a/crates/interfaces/src/db/tables.rs +++ b/crates/interfaces/src/db/tables.rs @@ -1,7 +1,12 @@ //! Declaration of all Database tables. -use crate::db::models::blocks::{BlockNumHash, HeaderHash, NumTransactions, NumTxesInBlock}; -use reth_primitives::{Account, Address, BlockNumber, Header, IntegerList, Receipt}; +use crate::db::{ + models::blocks::{BlockNumHash, HeaderHash, NumTransactions, NumTxesInBlock}, + DupSort, +}; +use reth_primitives::{ + Account, Address, BlockNumber, Header, IntegerList, Receipt, StorageEntry, H256, +}; /// Enum for the type of table present in libmdbx. #[derive(Debug)] @@ -12,7 +17,7 @@ pub enum TableType { DupSort, } /// Default tables that should be present inside database. -pub const TABLES: [(TableType, &str); 18] = [ +pub const TABLES: [(TableType, &str); 19] = [ (TableType::Table, CanonicalHeaders::const_name()), (TableType::Table, HeaderTD::const_name()), (TableType::Table, HeaderNumbers::const_name()), @@ -23,7 +28,8 @@ pub const TABLES: [(TableType, &str); 18] = [ (TableType::Table, Transactions::const_name()), (TableType::Table, Receipts::const_name()), (TableType::Table, Logs::const_name()), - (TableType::Table, PlainState::const_name()), + (TableType::Table, PlainAccountState::const_name()), + (TableType::DupSort, PlainStorageState::const_name()), (TableType::Table, AccountHistory::const_name()), (TableType::Table, StorageHistory::const_name()), (TableType::DupSort, AccountChangeSet::const_name()), @@ -67,6 +73,15 @@ macro_rules! table { }; } +macro_rules! dupsort { + ($name:ident => $key:ty => [$subkey:ty] $value:ty) => { + table!($name => $key => $value); + impl DupSort for $name { + type SubKey = $subkey; + } + }; +} + // // TABLE DEFINITIONS // @@ -84,7 +99,8 @@ table!(Transactions => TxNumber => RlpTxBody); // Canonical only table!(Receipts => TxNumber => Receipt); // Canonical only table!(Logs => TxNumber => Receipt); // Canonical only -table!(PlainState => PlainStateKey => Account); +table!(PlainAccountState => Address => Account); +dupsort!(PlainStorageState => Address => [H256] StorageEntry); table!(AccountHistory => Address => TxNumberList); table!(StorageHistory => Address_StorageKey => TxNumberList); @@ -113,7 +129,6 @@ type ConfigValue = Vec; type BlockNumHashTxNumber = Vec; type RlpTotalDifficulty = Vec; type RlpTxBody = Vec; -type PlainStateKey = Address; // TODO new type will have to account for address_incarna_skey as well #[allow(non_camel_case_types)] type Address_StorageKey = Vec; type AccountBeforeTx = Vec; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 9a3ad7e867..05cd975c21 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -16,6 +16,7 @@ mod integer_list; mod jsonu256; mod log; mod receipt; +mod storage; mod transaction; pub use account::Account; @@ -26,6 +27,7 @@ pub use integer_list::IntegerList; pub use jsonu256::JsonU256; pub use log::Log; pub use receipt::Receipt; +pub use storage::StorageEntry; pub use transaction::{ AccessList, AccessListItem, Signature, Transaction, TransactionKind, TransactionSigned, TxType, }; diff --git a/crates/primitives/src/storage.rs b/crates/primitives/src/storage.rs new file mode 100644 index 0000000000..28d6cfc28e --- /dev/null +++ b/crates/primitives/src/storage.rs @@ -0,0 +1,12 @@ +use super::{H256, U256}; +use reth_codecs::main_codec; + +/// Account storage entry. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[main_codec] +pub struct StorageEntry { + /// Storage key. + pub key: H256, + /// Value on storage key. + pub value: U256, +}