feat(db): Add DupSort PlainStorageState table (#121)

* add dupsort table and test

* use env.update instead

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
joshieDo
2022-10-25 02:23:28 +08:00
committed by GitHub
parent 4eca851429
commit 3c5b235455
5 changed files with 75 additions and 12 deletions

View File

@ -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::<PlainState>(key, value).expect(ERROR_PUT);
tx.put::<PlainAccountState>(key, value).expect(ERROR_PUT);
200
});
assert!(result.expect(ERROR_RETURN_VALUE) == 200);
@ -226,10 +226,44 @@ mod tests {
let env = Env::<WriteMap>::open(&path, EnvKind::RO).expect(ERROR_DB_CREATION);
// GET
let result = env.view(|tx| tx.get::<PlainState>(key).expect(ERROR_GET)).expect(ERROR_GET);
let result =
env.view(|tx| tx.get::<PlainAccountState>(key).expect(ERROR_GET)).expect(ERROR_GET);
assert!(result == Some(value))
}
#[test]
fn db_dup_sort() {
let env = test_utils::create_test_db::<NoWriteMap>(EnvKind::RW);
let key = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047")
.expect(ERROR_ETH_ADDRESS);
// PUT (0,0)
let value00 = StorageEntry::default();
env.update(|tx| tx.put::<PlainStorageState>(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::<PlainStorageState>(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::<PlainStorageState>(key.into(), value11.clone()).expect(ERROR_PUT))
.unwrap();
// GET DUPSORT
{
let tx = env.tx().expect(ERROR_INIT_TX);
let mut cursor = tx.cursor_dup::<PlainStorageState>().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)]

View File

@ -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<u8> {}
impl sealed::Sealed for Vec<u8> {}

View File

@ -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<u8>;
type BlockNumHashTxNumber = Vec<u8>;
type RlpTotalDifficulty = Vec<u8>;
type RlpTxBody = Vec<u8>;
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<u8>;
type AccountBeforeTx = Vec<u8>;

View File

@ -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,
};

View File

@ -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,
}