journaldb changes (#10929)
* inject_batch && commit_batch are no longer a part of journaldb * get rid of redundant KeyedHashDB trait * journaldb edition 2018 * journaldb trait moved to the lib.rs file * making journaldb more idiomatic * fix parity_bytes reexport * rename parity-util-mem package in Cargo.toml file
This commit is contained in:
parent
72279856cd
commit
46954527e7
@ -21,7 +21,7 @@
|
|||||||
//! should become general over time to the point where not even a
|
//! should become general over time to the point where not even a
|
||||||
//! merkle trie is strictly necessary.
|
//! merkle trie is strictly necessary.
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ethereum_types::{Address, H256};
|
use ethereum_types::{Address, H256};
|
||||||
@ -29,7 +29,6 @@ use hash_db::{AsHashDB, EMPTY_PREFIX, HashDB, Prefix};
|
|||||||
use kvdb::DBValue;
|
use kvdb::DBValue;
|
||||||
use memory_db::{HashKey, MemoryDB};
|
use memory_db::{HashKey, MemoryDB};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use journaldb::AsKeyedHashDB;
|
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
|
|
||||||
use crate::account::Account;
|
use crate::account::Account;
|
||||||
@ -90,10 +89,6 @@ impl ProofCheck {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl journaldb::KeyedHashDB for ProofCheck {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> { self.0.keys() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HashDB<KeccakHasher, DBValue> for ProofCheck {
|
impl HashDB<KeccakHasher, DBValue> for ProofCheck {
|
||||||
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
||||||
self.0.get(key, prefix)
|
self.0.get(key, prefix)
|
||||||
@ -146,23 +141,11 @@ pub struct Proving<H> {
|
|||||||
proof: Mutex<HashSet<DBValue>>,
|
proof: Mutex<HashSet<DBValue>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AH: AsKeyedHashDB + Send + Sync> AsKeyedHashDB for Proving<AH> {
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn journaldb::KeyedHashDB { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<AH: AsHashDB<KeccakHasher, DBValue> + Send + Sync> AsHashDB<KeccakHasher, DBValue> for Proving<AH> {
|
impl<AH: AsHashDB<KeccakHasher, DBValue> + Send + Sync> AsHashDB<KeccakHasher, DBValue> for Proving<AH> {
|
||||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||||
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: AsKeyedHashDB + Send + Sync> journaldb::KeyedHashDB for Proving<H> {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> {
|
|
||||||
let mut keys = self.base.as_keyed_hash_db().keys();
|
|
||||||
keys.extend(self.changed.keys());
|
|
||||||
keys
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> HashDB<KeccakHasher, DBValue> for Proving<H> {
|
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> HashDB<KeccakHasher, DBValue> for Proving<H> {
|
||||||
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
||||||
match self.base.as_hash_db().get(key, prefix) {
|
match self.base.as_hash_db().get(key, prefix) {
|
||||||
|
@ -4,12 +4,13 @@ version = "0.2.0"
|
|||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
description = "A `HashDB` which can manage a short-term journal potentially containing many forks of mutually exclusive actions"
|
description = "A `HashDB` which can manage a short-term journal potentially containing many forks of mutually exclusive actions"
|
||||||
license = "GPL3"
|
license = "GPL3"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
parity-bytes = "0.1"
|
parity-bytes = "0.1"
|
||||||
ethereum-types = "0.6.0"
|
ethereum-types = "0.6.0"
|
||||||
hash-db = "0.12.4"
|
hash-db = "0.12.4"
|
||||||
parity-util-mem = "0.1"
|
malloc_size_of = { version = "0.1", package = "parity-util-mem" }
|
||||||
keccak-hasher = { path = "../keccak-hasher" }
|
keccak-hasher = { path = "../keccak-hasher" }
|
||||||
kvdb = "0.1"
|
kvdb = "0.1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -16,20 +16,24 @@
|
|||||||
|
|
||||||
//! Disk-backed `HashDB` implementation.
|
//! Disk-backed `HashDB` implementation.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::collections::hash_map::Entry;
|
collections::{HashMap, hash_map::Entry},
|
||||||
use std::io;
|
io,
|
||||||
use std::sync::Arc;
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use parity_util_mem::MallocSizeOfExt;
|
|
||||||
use hash_db::{HashDB, Prefix};
|
use hash_db::{HashDB, Prefix};
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
||||||
|
use malloc_size_of::MallocSizeOfExt;
|
||||||
|
use parity_bytes::Bytes;
|
||||||
use rlp::{encode, decode};
|
use rlp::{encode, decode};
|
||||||
use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, error_key_already_exists, error_negatively_reference_hash};
|
|
||||||
use traits::JournalDB;
|
use crate::{
|
||||||
|
DB_PREFIX_LEN, LATEST_ERA_KEY, error_key_already_exists, error_negatively_reference_hash,
|
||||||
|
JournalDB, new_memory_db
|
||||||
|
};
|
||||||
|
|
||||||
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay
|
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay
|
||||||
/// and latent-removal semantics.
|
/// and latent-removal semantics.
|
||||||
@ -52,7 +56,7 @@ impl ArchiveDB {
|
|||||||
.expect("Low-level database error.")
|
.expect("Low-level database error.")
|
||||||
.map(|val| decode::<u64>(&val).expect("decoding db value failed"));
|
.map(|val| decode::<u64>(&val).expect("decoding db value failed"));
|
||||||
ArchiveDB {
|
ArchiveDB {
|
||||||
overlay: ::new_memory_db(),
|
overlay: new_memory_db(),
|
||||||
backing,
|
backing,
|
||||||
latest_era,
|
latest_era,
|
||||||
column,
|
column,
|
||||||
@ -92,28 +96,7 @@ impl HashDB<KeccakHasher, DBValue> for ArchiveDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::traits::KeyedHashDB for ArchiveDB {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> {
|
|
||||||
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
|
||||||
.map(|(key, _)| (H256::from_slice(&*key), 1))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for (key, refs) in self.overlay.keys() {
|
|
||||||
match ret.entry(key) {
|
|
||||||
Entry::Occupied(mut entry) => {
|
|
||||||
*entry.get_mut() += refs;
|
|
||||||
},
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
entry.insert(refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl JournalDB for ArchiveDB {
|
impl JournalDB for ArchiveDB {
|
||||||
|
|
||||||
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
||||||
Box::new(ArchiveDB {
|
Box::new(ArchiveDB {
|
||||||
overlay: self.overlay.clone(),
|
overlay: self.overlay.clone(),
|
||||||
@ -200,15 +183,33 @@ impl JournalDB for ArchiveDB {
|
|||||||
fn consolidate(&mut self, with: super::MemoryDB) {
|
fn consolidate(&mut self, with: super::MemoryDB) {
|
||||||
self.overlay.consolidate(with);
|
self.overlay.consolidate(with);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn keys(&self) -> HashMap<H256, i32> {
|
||||||
|
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
||||||
|
.map(|(key, _)| (H256::from_slice(&*key), 1))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (key, refs) in self.overlay.keys() {
|
||||||
|
match ret.entry(key) {
|
||||||
|
Entry::Occupied(mut entry) => {
|
||||||
|
*entry.get_mut() += refs;
|
||||||
|
},
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(refs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use keccak_hash::keccak;
|
||||||
use keccak::keccak;
|
|
||||||
use hash_db::{HashDB, EMPTY_PREFIX};
|
use hash_db::{HashDB, EMPTY_PREFIX};
|
||||||
use super::*;
|
use super::*;
|
||||||
use {kvdb_memorydb, JournalDB};
|
use kvdb_memorydb;
|
||||||
|
use crate::{JournalDB, inject_batch, commit_batch};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_same_in_fork() {
|
fn insert_same_in_fork() {
|
||||||
@ -216,18 +217,18 @@ mod tests {
|
|||||||
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
||||||
|
|
||||||
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
jdb.commit_batch(3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap();
|
||||||
jdb.commit_batch(4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap();
|
||||||
|
|
||||||
jdb.remove(&x, EMPTY_PREFIX);
|
jdb.remove(&x, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap();
|
||||||
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
||||||
jdb.commit_batch(4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap();
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap();
|
||||||
jdb.commit_batch(6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap();
|
||||||
|
|
||||||
assert!(jdb.contains(&x, EMPTY_PREFIX));
|
assert!(jdb.contains(&x, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -237,16 +238,16 @@ mod tests {
|
|||||||
// history is 3
|
// history is 3
|
||||||
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
||||||
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,13 +256,13 @@ mod tests {
|
|||||||
fn multiple_owed_removal_not_allowed() {
|
fn multiple_owed_removal_not_allowed() {
|
||||||
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
||||||
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
// commit_batch would call journal_under(),
|
// commit_batch would call journal_under(),
|
||||||
// and we don't allow multiple owned removals.
|
// and we don't allow multiple owned removals.
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -271,29 +272,29 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.remove(&baz, EMPTY_PREFIX);
|
jdb.remove(&baz, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -303,22 +304,22 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,16 +329,16 @@ mod tests {
|
|||||||
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,16 +346,16 @@ mod tests {
|
|||||||
fn fork_same_key() {
|
fn fork_same_key() {
|
||||||
// history is 1
|
// history is 1
|
||||||
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,21 +369,21 @@ mod tests {
|
|||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar"));
|
jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar"));
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
foo
|
foo
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut jdb = ArchiveDB::new(shared_db, None);
|
let mut jdb = ArchiveDB::new(shared_db, None);
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,24 +395,24 @@ mod tests {
|
|||||||
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
foo
|
foo
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut jdb = ArchiveDB::new(shared_db, None);
|
let mut jdb = ArchiveDB::new(shared_db, None);
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,19 +424,19 @@ mod tests {
|
|||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
(foo, bar, baz)
|
(foo, bar, baz)
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut jdb = ArchiveDB::new(shared_db, None);
|
let mut jdb = ArchiveDB::new(shared_db, None);
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +448,7 @@ mod tests {
|
|||||||
let key = {
|
let key = {
|
||||||
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
let mut jdb = ArchiveDB::new(shared_db.clone(), None);
|
||||||
let key = jdb.insert(EMPTY_PREFIX, b"foo");
|
let key = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
key
|
key
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -462,11 +463,11 @@ mod tests {
|
|||||||
fn inject() {
|
fn inject() {
|
||||||
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None);
|
||||||
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
||||||
jdb.remove(&key, EMPTY_PREFIX);
|
jdb.remove(&key, EMPTY_PREFIX);
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,16 @@
|
|||||||
//! Impls of the `AsHashDB` upcast trait for all different variants of DB
|
//! Impls of the `AsHashDB` upcast trait for all different variants of DB
|
||||||
use hash_db::{HashDB, AsHashDB};
|
use hash_db::{HashDB, AsHashDB};
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
use archivedb::ArchiveDB;
|
|
||||||
use earlymergedb::EarlyMergeDB;
|
|
||||||
use overlayrecentdb::OverlayRecentDB;
|
|
||||||
use refcounteddb::RefCountedDB;
|
|
||||||
use overlaydb::OverlayDB;
|
|
||||||
use kvdb::DBValue;
|
use kvdb::DBValue;
|
||||||
use crate::{KeyedHashDB, AsKeyedHashDB};
|
|
||||||
|
use crate::{
|
||||||
|
archivedb::ArchiveDB,
|
||||||
|
earlymergedb::EarlyMergeDB,
|
||||||
|
overlayrecentdb::OverlayRecentDB,
|
||||||
|
refcounteddb::RefCountedDB,
|
||||||
|
overlaydb::OverlayDB,
|
||||||
|
};
|
||||||
|
|
||||||
impl AsHashDB<KeccakHasher, DBValue> for ArchiveDB {
|
impl AsHashDB<KeccakHasher, DBValue> for ArchiveDB {
|
||||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||||
@ -49,23 +52,3 @@ impl AsHashDB<KeccakHasher, DBValue> for OverlayDB {
|
|||||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||||
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsKeyedHashDB for ArchiveDB {
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsKeyedHashDB for EarlyMergeDB {
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsKeyedHashDB for OverlayRecentDB {
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsKeyedHashDB for RefCountedDB {
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsKeyedHashDB for OverlayDB {
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self }
|
|
||||||
}
|
|
||||||
|
@ -16,22 +16,27 @@
|
|||||||
|
|
||||||
//! Disk-backed `HashDB` implementation.
|
//! Disk-backed `HashDB` implementation.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::collections::hash_map::Entry;
|
collections::{HashMap, hash_map::Entry},
|
||||||
use std::io;
|
io,
|
||||||
use std::sync::Arc;
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use hash_db::{HashDB, Prefix};
|
use hash_db::{HashDB, Prefix};
|
||||||
use parity_util_mem::{MallocSizeOf, allocators::new_malloc_size_ops};
|
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
||||||
|
use log::{trace, warn};
|
||||||
|
use malloc_size_of::{MallocSizeOf, allocators::new_malloc_size_ops};
|
||||||
|
use parity_bytes::Bytes;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use rlp::{encode, decode};
|
use rlp::{encode, decode};
|
||||||
use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, error_negatively_reference_hash, error_key_already_exists};
|
|
||||||
use super::traits::JournalDB;
|
use crate::{
|
||||||
use util::{DatabaseKey, DatabaseValueView, DatabaseValueRef};
|
DB_PREFIX_LEN, LATEST_ERA_KEY, error_negatively_reference_hash, error_key_already_exists,
|
||||||
|
JournalDB, new_memory_db,
|
||||||
|
util::{DatabaseKey, DatabaseValueView, DatabaseValueRef},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)]
|
#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)]
|
||||||
struct RefInfo {
|
struct RefInfo {
|
||||||
@ -115,7 +120,7 @@ impl EarlyMergeDB {
|
|||||||
let (latest_era, refs) = EarlyMergeDB::read_refs(&*backing, col);
|
let (latest_era, refs) = EarlyMergeDB::read_refs(&*backing, col);
|
||||||
let refs = Some(Arc::new(RwLock::new(refs)));
|
let refs = Some(Arc::new(RwLock::new(refs)));
|
||||||
EarlyMergeDB {
|
EarlyMergeDB {
|
||||||
overlay: ::new_memory_db(),
|
overlay: new_memory_db(),
|
||||||
backing: backing,
|
backing: backing,
|
||||||
refs: refs,
|
refs: refs,
|
||||||
latest_era: latest_era,
|
latest_era: latest_era,
|
||||||
@ -311,26 +316,6 @@ impl HashDB<KeccakHasher, DBValue> for EarlyMergeDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::traits::KeyedHashDB for EarlyMergeDB {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> {
|
|
||||||
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
|
||||||
.map(|(key, _)| (H256::from_slice(&*key), 1))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for (key, refs) in self.overlay.keys() {
|
|
||||||
match ret.entry(key) {
|
|
||||||
Entry::Occupied(mut entry) => {
|
|
||||||
*entry.get_mut() += refs;
|
|
||||||
},
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
entry.insert(refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl JournalDB for EarlyMergeDB {
|
impl JournalDB for EarlyMergeDB {
|
||||||
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
||||||
Box::new(EarlyMergeDB {
|
Box::new(EarlyMergeDB {
|
||||||
@ -519,16 +504,33 @@ impl JournalDB for EarlyMergeDB {
|
|||||||
fn consolidate(&mut self, with: super::MemoryDB) {
|
fn consolidate(&mut self, with: super::MemoryDB) {
|
||||||
self.overlay.consolidate(with);
|
self.overlay.consolidate(with);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn keys(&self) -> HashMap<H256, i32> {
|
||||||
|
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
||||||
|
.map(|(key, _)| (H256::from_slice(&*key), 1))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (key, refs) in self.overlay.keys() {
|
||||||
|
match ret.entry(key) {
|
||||||
|
Entry::Occupied(mut entry) => {
|
||||||
|
*entry.get_mut() += refs;
|
||||||
|
},
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(refs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use keccak_hash::keccak;
|
||||||
use keccak::keccak;
|
|
||||||
use hash_db::{HashDB, EMPTY_PREFIX};
|
use hash_db::{HashDB, EMPTY_PREFIX};
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::super::traits::JournalDB;
|
|
||||||
use kvdb_memorydb;
|
use kvdb_memorydb;
|
||||||
|
use crate::{inject_batch, commit_batch};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_same_in_fork() {
|
fn insert_same_in_fork() {
|
||||||
@ -536,25 +538,25 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&x, EMPTY_PREFIX);
|
jdb.remove(&x, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
||||||
jdb.commit_batch(4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&x, EMPTY_PREFIX));
|
assert!(jdb.contains(&x, EMPTY_PREFIX));
|
||||||
@ -564,17 +566,17 @@ mod tests {
|
|||||||
fn insert_older_era() {
|
fn insert_older_era() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0a"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(0, &keccak(b"0b"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -585,20 +587,20 @@ mod tests {
|
|||||||
// history is 3
|
// history is 3
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&h, EMPTY_PREFIX));
|
assert!(!jdb.contains(&h, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -610,7 +612,7 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -618,7 +620,7 @@ mod tests {
|
|||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -626,20 +628,20 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.remove(&baz, EMPTY_PREFIX);
|
jdb.remove(&baz, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -653,25 +655,25 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
@ -684,19 +686,19 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -705,24 +707,24 @@ mod tests {
|
|||||||
fn fork_same_key_one() {
|
fn fork_same_key_one() {
|
||||||
|
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -730,24 +732,24 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn fork_same_key_other() {
|
fn fork_same_key_other() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -755,33 +757,33 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn fork_ins_del_ins() {
|
fn fork_ins_del_ins() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -800,7 +802,7 @@ mod tests {
|
|||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar"));
|
jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar"));
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
foo
|
foo
|
||||||
};
|
};
|
||||||
@ -808,7 +810,7 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,7 +818,7 @@ mod tests {
|
|||||||
let mut jdb = EarlyMergeDB::new(shared_db, None);
|
let mut jdb = EarlyMergeDB::new(shared_db, None);
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -830,22 +832,22 @@ mod tests {
|
|||||||
|
|
||||||
// history is 4
|
// history is 4
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
// expunge foo
|
// expunge foo
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -856,43 +858,43 @@ mod tests {
|
|||||||
|
|
||||||
// history is 4
|
// history is 4
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3a"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3b"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// expunge foo
|
// expunge foo
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -902,25 +904,25 @@ mod tests {
|
|||||||
|
|
||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -931,30 +933,30 @@ mod tests {
|
|||||||
|
|
||||||
// history is 4
|
// history is 4
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(3, &keccak(b"3"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.insert(EMPTY_PREFIX, b"bar");
|
jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,20 +971,20 @@ mod tests {
|
|||||||
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
||||||
// history is 1
|
// history is 1
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
@ -991,7 +993,7 @@ mod tests {
|
|||||||
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
@ -999,7 +1001,7 @@ mod tests {
|
|||||||
}; {
|
}; {
|
||||||
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
let mut jdb = EarlyMergeDB::new(shared_db.clone(), None);
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
@ -1007,7 +1009,7 @@ mod tests {
|
|||||||
}; {
|
}; {
|
||||||
let mut jdb = EarlyMergeDB::new(shared_db, None);
|
let mut jdb = EarlyMergeDB::new(shared_db, None);
|
||||||
|
|
||||||
jdb.commit_batch(6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -1022,22 +1024,22 @@ mod tests {
|
|||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
(foo, bar, baz)
|
(foo, bar, baz)
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut jdb = EarlyMergeDB::new(shared_db, None);
|
let mut jdb = EarlyMergeDB::new(shared_db, None);
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
@ -1049,11 +1051,11 @@ mod tests {
|
|||||||
fn inject() {
|
fn inject() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
||||||
jdb.remove(&key, EMPTY_PREFIX);
|
jdb.remove(&key, EMPTY_PREFIX);
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
||||||
}
|
}
|
||||||
|
@ -16,51 +16,84 @@
|
|||||||
|
|
||||||
//! `JournalDB` interface and implementation.
|
//! `JournalDB` interface and implementation.
|
||||||
|
|
||||||
extern crate parity_util_mem;
|
use std::{
|
||||||
extern crate parity_util_mem as mem;
|
fmt, str, io,
|
||||||
extern crate parity_util_mem as malloc_size_of;
|
sync::Arc,
|
||||||
#[macro_use]
|
collections::HashMap,
|
||||||
extern crate log;
|
};
|
||||||
|
|
||||||
extern crate ethereum_types;
|
use ethereum_types::H256;
|
||||||
extern crate parity_bytes as bytes;
|
use hash_db::HashDB;
|
||||||
extern crate hash_db;
|
use keccak_hasher::KeccakHasher;
|
||||||
extern crate keccak_hasher;
|
use kvdb::{self, DBTransaction, DBValue};
|
||||||
extern crate kvdb;
|
use parity_bytes::Bytes;
|
||||||
extern crate memory_db;
|
|
||||||
extern crate parking_lot;
|
|
||||||
extern crate fastmap;
|
|
||||||
extern crate rlp;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
extern crate env_logger;
|
|
||||||
#[cfg(test)]
|
|
||||||
extern crate keccak_hash as keccak;
|
|
||||||
#[cfg(test)]
|
|
||||||
extern crate kvdb_memorydb;
|
|
||||||
|
|
||||||
use std::{fmt, str, io};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
/// Export the journaldb module.
|
|
||||||
mod traits;
|
|
||||||
mod archivedb;
|
mod archivedb;
|
||||||
mod earlymergedb;
|
mod earlymergedb;
|
||||||
mod overlayrecentdb;
|
mod overlayrecentdb;
|
||||||
mod refcounteddb;
|
mod refcounteddb;
|
||||||
mod util;
|
mod util;
|
||||||
mod as_hash_db_impls;
|
mod as_hash_db_impls;
|
||||||
|
mod overlaydb;
|
||||||
|
|
||||||
pub mod overlaydb;
|
/// A `HashDB` which can manage a short-term journal potentially containing many forks of mutually
|
||||||
|
/// exclusive actions.
|
||||||
|
pub trait JournalDB: HashDB<KeccakHasher, DBValue> {
|
||||||
|
/// Return a copy of ourself, in a box.
|
||||||
|
fn boxed_clone(&self) -> Box<dyn JournalDB>;
|
||||||
|
|
||||||
/// Export the `JournalDB` trait.
|
/// Returns heap memory size used
|
||||||
pub use self::traits::JournalDB;
|
fn mem_used(&self) -> usize;
|
||||||
|
|
||||||
/// Export keyed hash trait
|
/// Returns the size of journalled state in memory.
|
||||||
pub use self::traits::KeyedHashDB;
|
/// This function has a considerable speed requirement --
|
||||||
/// Export as keyed hash trait
|
/// it must be fast enough to call several times per block imported.
|
||||||
pub use self::traits::AsKeyedHashDB;
|
fn journal_size(&self) -> usize { 0 }
|
||||||
|
|
||||||
|
/// Check if this database has any commits
|
||||||
|
fn is_empty(&self) -> bool;
|
||||||
|
|
||||||
|
/// Get the earliest era in the DB. None if there isn't yet any data in there.
|
||||||
|
fn earliest_era(&self) -> Option<u64> { None }
|
||||||
|
|
||||||
|
/// Get the latest era in the DB. None if there isn't yet any data in there.
|
||||||
|
fn latest_era(&self) -> Option<u64>;
|
||||||
|
|
||||||
|
/// Journal recent database operations as being associated with a given era and id.
|
||||||
|
// TODO: give the overlay to this function so journaldbs don't manage the overlays themselves.
|
||||||
|
fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> io::Result<u32>;
|
||||||
|
|
||||||
|
/// Mark a given block as canonical, indicating that competing blocks' states may be pruned out.
|
||||||
|
fn mark_canonical(&mut self, batch: &mut DBTransaction, era: u64, id: &H256) -> io::Result<u32>;
|
||||||
|
|
||||||
|
/// Commit all queued insert and delete operations without affecting any journalling -- this requires that all insertions
|
||||||
|
/// and deletions are indeed canonical and will likely lead to an invalid database if that assumption is violated.
|
||||||
|
///
|
||||||
|
/// Any keys or values inserted or deleted must be completely independent of those affected
|
||||||
|
/// by any previous `commit` operations. Essentially, this means that `inject` can be used
|
||||||
|
/// either to restore a state to a fresh database, or to insert data which may only be journalled
|
||||||
|
/// from this point onwards.
|
||||||
|
fn inject(&mut self, batch: &mut DBTransaction) -> io::Result<u32>;
|
||||||
|
|
||||||
|
/// State data query
|
||||||
|
fn state(&self, _id: &H256) -> Option<Bytes>;
|
||||||
|
|
||||||
|
/// Whether this database is pruned.
|
||||||
|
fn is_prunable(&self) -> bool { true }
|
||||||
|
|
||||||
|
/// Get backing database.
|
||||||
|
fn backing(&self) -> &Arc<dyn kvdb::KeyValueDB>;
|
||||||
|
|
||||||
|
/// Clear internal strucutres. This should called after changes have been written
|
||||||
|
/// to the backing strage
|
||||||
|
fn flush(&self) {}
|
||||||
|
|
||||||
|
/// Consolidate all the insertions and deletions in the given memory overlay.
|
||||||
|
fn consolidate(&mut self, overlay: MemoryDB);
|
||||||
|
|
||||||
|
/// Primarily use for tests, highly inefficient.
|
||||||
|
fn keys(&self) -> HashMap<H256, i32>;
|
||||||
|
}
|
||||||
|
|
||||||
/// Alias to ethereum MemoryDB
|
/// Alias to ethereum MemoryDB
|
||||||
type MemoryDB = memory_db::MemoryDB<
|
type MemoryDB = memory_db::MemoryDB<
|
||||||
@ -177,6 +210,29 @@ pub fn new_memory_db() -> MemoryDB {
|
|||||||
MemoryDB::from_null_node(&rlp::NULL_RLP, rlp::NULL_RLP.as_ref().into())
|
MemoryDB::from_null_node(&rlp::NULL_RLP, rlp::NULL_RLP.as_ref().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
/// Inject all changes in a single batch.
|
||||||
|
pub fn inject_batch(jdb: &mut dyn JournalDB) -> io::Result<u32> {
|
||||||
|
let mut batch = jdb.backing().transaction();
|
||||||
|
let res = jdb.inject(&mut batch)?;
|
||||||
|
jdb.backing().write(batch).map(|_| res).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Commit all changes in a single batch
|
||||||
|
#[cfg(test)]
|
||||||
|
fn commit_batch(jdb: &mut dyn JournalDB, now: u64, id: &H256, end: Option<(u64, H256)>) -> io::Result<u32> {
|
||||||
|
let mut batch = jdb.backing().transaction();
|
||||||
|
let mut ops = jdb.journal_under(&mut batch, now, id)?;
|
||||||
|
|
||||||
|
if let Some((end_era, canon_id)) = end {
|
||||||
|
ops += jdb.mark_canonical(&mut batch, end_era, &canon_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = jdb.backing().write(batch).map(|_| ops).map_err(Into::into);
|
||||||
|
jdb.flush();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Algorithm;
|
use super::Algorithm;
|
||||||
|
@ -16,17 +16,20 @@
|
|||||||
|
|
||||||
//! Disk-backed `HashDB` implementation.
|
//! Disk-backed `HashDB` implementation.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::collections::hash_map::Entry;
|
collections::{HashMap, hash_map::Entry},
|
||||||
use std::io;
|
io,
|
||||||
use std::sync::Arc;
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use rlp::{Rlp, RlpStream, Encodable, DecoderError, Decodable, encode, decode};
|
use hash_db::{HashDB, Prefix};
|
||||||
use hash_db::{HashDB, Prefix, EMPTY_PREFIX};
|
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
||||||
use super::{error_negatively_reference_hash};
|
use log::trace;
|
||||||
|
use rlp::{Rlp, RlpStream, Encodable, DecoderError, Decodable, encode, decode};
|
||||||
|
|
||||||
|
use crate::{error_negatively_reference_hash, new_memory_db};
|
||||||
|
|
||||||
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay.
|
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay.
|
||||||
///
|
///
|
||||||
@ -78,8 +81,12 @@ impl Decodable for Payload {
|
|||||||
|
|
||||||
impl OverlayDB {
|
impl OverlayDB {
|
||||||
/// Create a new instance of OverlayDB given a `backing` database.
|
/// Create a new instance of OverlayDB given a `backing` database.
|
||||||
pub fn new(backing: Arc<dyn KeyValueDB>, col: Option<u32>) -> OverlayDB {
|
pub fn new(backing: Arc<dyn KeyValueDB>, column: Option<u32>) -> OverlayDB {
|
||||||
OverlayDB{ overlay: ::new_memory_db(), backing: backing, column: col }
|
OverlayDB {
|
||||||
|
overlay: new_memory_db(),
|
||||||
|
backing,
|
||||||
|
column,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new instance of OverlayDB with an anonymous temporary database.
|
/// Create a new instance of OverlayDB with an anonymous temporary database.
|
||||||
@ -128,13 +135,6 @@ impl OverlayDB {
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Revert all operations on this object (i.e. `insert()`s and `remove()`s) since the
|
|
||||||
/// last `commit()`.
|
|
||||||
pub fn revert(&mut self) { self.overlay.clear(); }
|
|
||||||
|
|
||||||
/// Get the number of references that would be committed.
|
|
||||||
pub fn commit_refs(&self, key: &H256) -> i32 { self.overlay.raw(key, EMPTY_PREFIX).map_or(0, |(_, refs)| refs) }
|
|
||||||
|
|
||||||
/// Get the refs and value of the given key.
|
/// Get the refs and value of the given key.
|
||||||
fn payload(&self, key: &H256) -> Option<Payload> {
|
fn payload(&self, key: &H256) -> Option<Payload> {
|
||||||
self.backing.get(self.column, key.as_bytes())
|
self.backing.get(self.column, key.as_bytes())
|
||||||
@ -153,10 +153,7 @@ impl OverlayDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
pub fn keys(&self) -> HashMap<H256, i32> {
|
||||||
|
|
||||||
impl crate::KeyedHashDB for OverlayDB {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> {
|
|
||||||
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
||||||
.map(|(key, _)| {
|
.map(|(key, _)| {
|
||||||
let h = H256::from_slice(&*key);
|
let h = H256::from_slice(&*key);
|
||||||
@ -177,7 +174,6 @@ impl crate::KeyedHashDB for OverlayDB {
|
|||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HashDB<KeccakHasher, DBValue> for OverlayDB {
|
impl HashDB<KeccakHasher, DBValue> for OverlayDB {
|
||||||
@ -233,106 +229,103 @@ impl HashDB<KeccakHasher, DBValue> for OverlayDB {
|
|||||||
fn remove(&mut self, key: &H256, prefix: Prefix) { self.overlay.remove(key, prefix); }
|
fn remove(&mut self, key: &H256, prefix: Prefix) { self.overlay.remove(key, prefix); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[cfg(test)]
|
||||||
fn overlaydb_revert() {
|
mod tests {
|
||||||
let mut m = OverlayDB::new_temp();
|
use hash_db::EMPTY_PREFIX;
|
||||||
let foo = m.insert(EMPTY_PREFIX, b"foo"); // insert foo.
|
use super::*;
|
||||||
let mut batch = m.backing.transaction();
|
|
||||||
m.commit_to_batch(&mut batch).unwrap(); // commit - new operations begin here...
|
|
||||||
m.backing.write(batch).unwrap();
|
|
||||||
let bar = m.insert(EMPTY_PREFIX, b"bar"); // insert bar.
|
|
||||||
m.remove(&foo, EMPTY_PREFIX); // remove foo.
|
|
||||||
assert!(!m.contains(&foo, EMPTY_PREFIX)); // foo is gone.
|
|
||||||
assert!(m.contains(&bar, EMPTY_PREFIX)); // bar is here.
|
|
||||||
m.revert(); // revert the last two operations.
|
|
||||||
assert!(m.contains(&foo, EMPTY_PREFIX)); // foo is here.
|
|
||||||
assert!(!m.contains(&bar, EMPTY_PREFIX)); // bar is gone.
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlaydb_overlay_insert_and_remove() {
|
fn overlaydb_revert() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut m = OverlayDB::new_temp();
|
||||||
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
let foo = m.insert(EMPTY_PREFIX, b"foo"); // insert foo.
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
let mut batch = m.backing.transaction();
|
||||||
trie.remove(&h, EMPTY_PREFIX);
|
m.commit_to_batch(&mut batch).unwrap(); // commit - new operations begin here...
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
m.backing.write(batch).unwrap();
|
||||||
}
|
let bar = m.insert(EMPTY_PREFIX, b"bar"); // insert bar.
|
||||||
|
m.remove(&foo, EMPTY_PREFIX); // remove foo.
|
||||||
|
assert!(!m.contains(&foo, EMPTY_PREFIX)); // foo is gone.
|
||||||
|
assert!(m.contains(&bar, EMPTY_PREFIX)); // bar is here.
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlaydb_backing_insert_revert() {
|
fn overlaydb_overlay_insert_and_remove() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
||||||
trie.commit().unwrap();
|
trie.remove(&h, EMPTY_PREFIX);
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
||||||
trie.revert();
|
}
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlaydb_backing_remove() {
|
fn overlaydb_backing_insert_revert() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
||||||
trie.commit().unwrap();
|
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
||||||
trie.remove(&h, EMPTY_PREFIX);
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
||||||
trie.commit().unwrap();
|
}
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
|
||||||
trie.revert();
|
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlaydb_backing_remove_revert() {
|
fn overlaydb_backing_remove() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
trie.remove(&h, EMPTY_PREFIX);
|
trie.remove(&h, EMPTY_PREFIX);
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
||||||
trie.revert();
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world"));
|
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlaydb_negative() {
|
fn overlaydb_backing_remove_revert() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
trie.remove(&h, EMPTY_PREFIX);
|
trie.remove(&h, EMPTY_PREFIX);
|
||||||
trie.remove(&h, EMPTY_PREFIX); //bad - sends us into negative refs.
|
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
||||||
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
}
|
||||||
assert!(trie.commit().is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlaydb_complex() {
|
fn overlaydb_negative() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let hfoo = trie.insert(EMPTY_PREFIX, b"foo");
|
let h = trie.insert(EMPTY_PREFIX, b"hello world");
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
trie.commit().unwrap();
|
||||||
let hbar = trie.insert(EMPTY_PREFIX, b"bar");
|
trie.remove(&h, EMPTY_PREFIX);
|
||||||
assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar"));
|
trie.remove(&h, EMPTY_PREFIX); //bad - sends us into negative refs.
|
||||||
trie.commit().unwrap();
|
assert_eq!(trie.get(&h, EMPTY_PREFIX), None);
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
assert!(trie.commit().is_err());
|
||||||
assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar"));
|
}
|
||||||
trie.insert(EMPTY_PREFIX, b"foo"); // two refs
|
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
#[test]
|
||||||
trie.commit().unwrap();
|
fn overlaydb_complex() {
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
let mut trie = OverlayDB::new_temp();
|
||||||
assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar"));
|
let hfoo = trie.insert(EMPTY_PREFIX, b"foo");
|
||||||
trie.remove(&hbar, EMPTY_PREFIX); // zero refs - delete
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
assert_eq!(trie.get(&hbar, EMPTY_PREFIX), None);
|
let hbar = trie.insert(EMPTY_PREFIX, b"bar");
|
||||||
trie.remove(&hfoo, EMPTY_PREFIX); // one ref - keep
|
assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar"));
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
trie.commit().unwrap();
|
||||||
trie.commit().unwrap();
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar"));
|
||||||
trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - would delete, but...
|
trie.insert(EMPTY_PREFIX, b"foo"); // two refs
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None);
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
trie.insert(EMPTY_PREFIX, b"foo"); // one ref - keep after all.
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
trie.commit().unwrap();
|
assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar"));
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
trie.remove(&hbar, EMPTY_PREFIX); // zero refs - delete
|
||||||
trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - delete
|
assert_eq!(trie.get(&hbar, EMPTY_PREFIX), None);
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None);
|
trie.remove(&hfoo, EMPTY_PREFIX); // one ref - keep
|
||||||
trie.commit().unwrap(); //
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None);
|
trie.commit().unwrap();
|
||||||
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
|
trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - would delete, but...
|
||||||
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None);
|
||||||
|
trie.insert(EMPTY_PREFIX, b"foo"); // one ref - keep after all.
|
||||||
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
|
trie.commit().unwrap();
|
||||||
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo"));
|
||||||
|
trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - delete
|
||||||
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None);
|
||||||
|
trie.commit().unwrap(); //
|
||||||
|
assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,28 @@
|
|||||||
|
|
||||||
//! `JournalDB` over in-memory overlay
|
//! `JournalDB` over in-memory overlay
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::collections::hash_map::Entry;
|
collections::{HashMap, hash_map::Entry},
|
||||||
use std::io;
|
io,
|
||||||
use std::sync::Arc;
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
|
use fastmap::H256FastMap;
|
||||||
use hash_db::{HashDB, Prefix, EMPTY_PREFIX};
|
use hash_db::{HashDB, Prefix, EMPTY_PREFIX};
|
||||||
use parity_util_mem::{MallocSizeOf, allocators::new_malloc_size_ops};
|
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
||||||
|
use log::trace;
|
||||||
|
use malloc_size_of::{MallocSizeOf, allocators::new_malloc_size_ops};
|
||||||
|
use parity_bytes::Bytes;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use fastmap::H256FastMap;
|
|
||||||
use rlp::{Rlp, RlpStream, encode, decode, DecoderError, Decodable, Encodable};
|
use rlp::{Rlp, RlpStream, encode, decode, DecoderError, Decodable, Encodable};
|
||||||
use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, JournalDB, error_negatively_reference_hash};
|
|
||||||
use util::DatabaseKey;
|
use crate::{
|
||||||
|
DB_PREFIX_LEN, LATEST_ERA_KEY, JournalDB, error_negatively_reference_hash,
|
||||||
|
new_memory_db,
|
||||||
|
util::DatabaseKey
|
||||||
|
};
|
||||||
|
|
||||||
/// Implementation of the `JournalDB` trait for a disk-backed database with a memory overlay
|
/// Implementation of the `JournalDB` trait for a disk-backed database with a memory overlay
|
||||||
/// and, possibly, latent-removal semantics.
|
/// and, possibly, latent-removal semantics.
|
||||||
@ -150,7 +156,7 @@ impl OverlayRecentDB {
|
|||||||
pub fn new(backing: Arc<dyn KeyValueDB>, col: Option<u32>) -> OverlayRecentDB {
|
pub fn new(backing: Arc<dyn KeyValueDB>, col: Option<u32>) -> OverlayRecentDB {
|
||||||
let journal_overlay = Arc::new(RwLock::new(OverlayRecentDB::read_overlay(&*backing, col)));
|
let journal_overlay = Arc::new(RwLock::new(OverlayRecentDB::read_overlay(&*backing, col)));
|
||||||
OverlayRecentDB {
|
OverlayRecentDB {
|
||||||
transaction_overlay: ::new_memory_db(),
|
transaction_overlay: new_memory_db(),
|
||||||
backing: backing,
|
backing: backing,
|
||||||
journal_overlay: journal_overlay,
|
journal_overlay: journal_overlay,
|
||||||
column: col,
|
column: col,
|
||||||
@ -176,7 +182,7 @@ impl OverlayRecentDB {
|
|||||||
|
|
||||||
fn read_overlay(db: &dyn KeyValueDB, col: Option<u32>) -> JournalOverlay {
|
fn read_overlay(db: &dyn KeyValueDB, col: Option<u32>) -> JournalOverlay {
|
||||||
let mut journal = HashMap::new();
|
let mut journal = HashMap::new();
|
||||||
let mut overlay = ::new_memory_db();
|
let mut overlay = new_memory_db();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut latest_era = None;
|
let mut latest_era = None;
|
||||||
let mut earliest_era = None;
|
let mut earliest_era = None;
|
||||||
@ -238,26 +244,6 @@ fn to_short_key(key: &H256) -> H256 {
|
|||||||
k
|
k
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::traits::KeyedHashDB for OverlayRecentDB {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> {
|
|
||||||
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
|
||||||
.map(|(key, _)| (H256::from_slice(&*key), 1))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for (key, refs) in self.transaction_overlay.keys() {
|
|
||||||
match ret.entry(key) {
|
|
||||||
Entry::Occupied(mut entry) => {
|
|
||||||
*entry.get_mut() += refs;
|
|
||||||
},
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
entry.insert(refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl JournalDB for OverlayRecentDB {
|
impl JournalDB for OverlayRecentDB {
|
||||||
|
|
||||||
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
||||||
@ -455,6 +441,24 @@ impl JournalDB for OverlayRecentDB {
|
|||||||
fn consolidate(&mut self, with: super::MemoryDB) {
|
fn consolidate(&mut self, with: super::MemoryDB) {
|
||||||
self.transaction_overlay.consolidate(with);
|
self.transaction_overlay.consolidate(with);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn keys(&self) -> HashMap<H256, i32> {
|
||||||
|
let mut ret: HashMap<H256, i32> = self.backing.iter(self.column)
|
||||||
|
.map(|(key, _)| (H256::from_slice(&*key), 1))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (key, refs) in self.transaction_overlay.keys() {
|
||||||
|
match ret.entry(key) {
|
||||||
|
Entry::Occupied(mut entry) => {
|
||||||
|
*entry.get_mut() += refs;
|
||||||
|
},
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(refs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HashDB<KeccakHasher, DBValue> for OverlayRecentDB {
|
impl HashDB<KeccakHasher, DBValue> for OverlayRecentDB {
|
||||||
@ -490,11 +494,11 @@ impl HashDB<KeccakHasher, DBValue> for OverlayRecentDB {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use keccak_hash::keccak;
|
||||||
use keccak::keccak;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use hash_db::{HashDB, EMPTY_PREFIX};
|
use hash_db::{HashDB, EMPTY_PREFIX};
|
||||||
use {kvdb_memorydb, JournalDB};
|
use kvdb_memorydb;
|
||||||
|
use crate::{JournalDB, inject_batch, commit_batch};
|
||||||
|
|
||||||
fn new_db() -> OverlayRecentDB {
|
fn new_db() -> OverlayRecentDB {
|
||||||
let backing = Arc::new(kvdb_memorydb::create(0));
|
let backing = Arc::new(kvdb_memorydb::create(0));
|
||||||
@ -507,25 +511,25 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&x, EMPTY_PREFIX);
|
jdb.remove(&x, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
let x = jdb.insert(EMPTY_PREFIX, b"X");
|
||||||
jdb.commit_batch(4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&x, EMPTY_PREFIX));
|
assert!(jdb.contains(&x, EMPTY_PREFIX));
|
||||||
@ -536,20 +540,20 @@ mod tests {
|
|||||||
// history is 3
|
// history is 3
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&h, EMPTY_PREFIX));
|
assert!(!jdb.contains(&h, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -561,7 +565,7 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -569,7 +573,7 @@ mod tests {
|
|||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -577,20 +581,20 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.remove(&baz, EMPTY_PREFIX);
|
jdb.remove(&baz, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -604,25 +608,25 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
@ -635,19 +639,19 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -655,24 +659,24 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn fork_same_key_one() {
|
fn fork_same_key_one() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -681,24 +685,24 @@ mod tests {
|
|||||||
fn fork_same_key_other() {
|
fn fork_same_key_other() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -707,33 +711,33 @@ mod tests {
|
|||||||
fn fork_ins_del_ins() {
|
fn fork_ins_del_ins() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,7 +751,7 @@ mod tests {
|
|||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar"));
|
jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar"));
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
foo
|
foo
|
||||||
};
|
};
|
||||||
@ -755,7 +759,7 @@ mod tests {
|
|||||||
{
|
{
|
||||||
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +767,7 @@ mod tests {
|
|||||||
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -776,22 +780,22 @@ mod tests {
|
|||||||
|
|
||||||
// history is 4
|
// history is 4
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
// expunge foo
|
// expunge foo
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,43 +806,43 @@ mod tests {
|
|||||||
|
|
||||||
// history is 4
|
// history is 4
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2a"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3a"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3b"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// expunge foo
|
// expunge foo
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,25 +851,25 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -875,30 +879,30 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
// history is 4
|
// history is 4
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(3, &keccak(b"3"), None).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.insert(EMPTY_PREFIX, b"bar");
|
jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,20 +917,20 @@ mod tests {
|
|||||||
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
||||||
// history is 1
|
// history is 1
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
// foo is ancient history.
|
// foo is ancient history.
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.insert(EMPTY_PREFIX, b"foo");
|
jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
@ -935,7 +939,7 @@ mod tests {
|
|||||||
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
@ -943,7 +947,7 @@ mod tests {
|
|||||||
}; {
|
}; {
|
||||||
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
let mut jdb = OverlayRecentDB::new(shared_db.clone(), None);
|
||||||
|
|
||||||
jdb.commit_batch(5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
|
|
||||||
@ -951,7 +955,7 @@ mod tests {
|
|||||||
}; {
|
}; {
|
||||||
let mut jdb = OverlayRecentDB::new(shared_db, None);
|
let mut jdb = OverlayRecentDB::new(shared_db, None);
|
||||||
|
|
||||||
jdb.commit_batch(6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap();
|
commit_batch(&mut jdb, 6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
@ -966,22 +970,22 @@ mod tests {
|
|||||||
// history is 1
|
// history is 1
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
(foo, bar, baz)
|
(foo, bar, baz)
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut jdb = OverlayRecentDB::new(shared_db, None);
|
let mut jdb = OverlayRecentDB::new(shared_db, None);
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
@ -993,17 +997,17 @@ mod tests {
|
|||||||
fn insert_older_era() {
|
fn insert_older_era() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0a"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0a"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(0, &keccak(b"0b"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0b"), None).unwrap();
|
||||||
assert!(jdb.can_reconstruct_refs());
|
assert!(jdb.can_reconstruct_refs());
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -1013,11 +1017,11 @@ mod tests {
|
|||||||
fn inject() {
|
fn inject() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
||||||
jdb.remove(&key, EMPTY_PREFIX);
|
jdb.remove(&key, EMPTY_PREFIX);
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,26 @@
|
|||||||
|
|
||||||
//! Disk-backed, ref-counted `JournalDB` implementation.
|
//! Disk-backed, ref-counted `JournalDB` implementation.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::io;
|
io,
|
||||||
use std::sync::Arc;
|
sync::Arc,
|
||||||
|
collections::HashMap,
|
||||||
|
};
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use hash_db::{HashDB, Prefix, EMPTY_PREFIX};
|
use hash_db::{HashDB, Prefix, EMPTY_PREFIX};
|
||||||
use parity_util_mem::{MallocSizeOf, allocators::new_malloc_size_ops};
|
|
||||||
use keccak_hasher::KeccakHasher;
|
use keccak_hasher::KeccakHasher;
|
||||||
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
use kvdb::{KeyValueDB, DBTransaction, DBValue};
|
||||||
use overlaydb::OverlayDB;
|
use log::trace;
|
||||||
|
use malloc_size_of::{MallocSizeOf, allocators::new_malloc_size_ops};
|
||||||
|
use parity_bytes::Bytes;
|
||||||
use rlp::{encode, decode};
|
use rlp::{encode, decode};
|
||||||
use super::{DB_PREFIX_LEN, LATEST_ERA_KEY};
|
|
||||||
use super::traits::JournalDB;
|
use crate::{
|
||||||
use util::{DatabaseKey, DatabaseValueView, DatabaseValueRef};
|
overlaydb::OverlayDB,
|
||||||
|
JournalDB, DB_PREFIX_LEN, LATEST_ERA_KEY,
|
||||||
|
util::{DatabaseKey, DatabaseValueView, DatabaseValueRef},
|
||||||
|
};
|
||||||
|
|
||||||
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay
|
/// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay
|
||||||
/// and latent-removal semantics.
|
/// and latent-removal semantics.
|
||||||
@ -87,10 +92,6 @@ impl HashDB<KeccakHasher, DBValue> for RefCountedDB {
|
|||||||
fn remove(&mut self, key: &H256, _prefix: Prefix) { self.removes.push(key.clone()); }
|
fn remove(&mut self, key: &H256, _prefix: Prefix) { self.removes.push(key.clone()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::traits::KeyedHashDB for RefCountedDB {
|
|
||||||
fn keys(&self) -> HashMap<H256, i32> { self.forward.keys() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl JournalDB for RefCountedDB {
|
impl JournalDB for RefCountedDB {
|
||||||
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
fn boxed_clone(&self) -> Box<dyn JournalDB> {
|
||||||
Box::new(RefCountedDB {
|
Box::new(RefCountedDB {
|
||||||
@ -213,15 +214,19 @@ impl JournalDB for RefCountedDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn keys(&self) -> HashMap<H256, i32> {
|
||||||
|
self.forward.keys()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use keccak_hash::keccak;
|
||||||
use keccak::keccak;
|
|
||||||
use hash_db::{HashDB, EMPTY_PREFIX};
|
use hash_db::{HashDB, EMPTY_PREFIX};
|
||||||
use super::*;
|
use super::*;
|
||||||
use {JournalDB, kvdb_memorydb};
|
use kvdb_memorydb;
|
||||||
|
use crate::{JournalDB, inject_batch, commit_batch};
|
||||||
|
|
||||||
fn new_db() -> RefCountedDB {
|
fn new_db() -> RefCountedDB {
|
||||||
let backing = Arc::new(kvdb_memorydb::create(0));
|
let backing = Arc::new(kvdb_memorydb::create(0));
|
||||||
@ -233,16 +238,16 @@ mod tests {
|
|||||||
// history is 3
|
// history is 3
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
assert!(jdb.contains(&h, EMPTY_PREFIX));
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(!jdb.contains(&h, EMPTY_PREFIX));
|
assert!(!jdb.contains(&h, EMPTY_PREFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,16 +257,16 @@ mod tests {
|
|||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
assert_eq!(jdb.latest_era(), None);
|
assert_eq!(jdb.latest_era(), None);
|
||||||
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
let h = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert_eq!(jdb.latest_era(), Some(0));
|
assert_eq!(jdb.latest_era(), Some(0));
|
||||||
jdb.remove(&h, EMPTY_PREFIX);
|
jdb.remove(&h, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1"), None).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap();
|
||||||
assert_eq!(jdb.latest_era(), Some(1));
|
assert_eq!(jdb.latest_era(), Some(1));
|
||||||
jdb.commit_batch(2, &keccak(b"2"), None).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap();
|
||||||
assert_eq!(jdb.latest_era(), Some(2));
|
assert_eq!(jdb.latest_era(), Some(2));
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert_eq!(jdb.latest_era(), Some(3));
|
assert_eq!(jdb.latest_era(), Some(3));
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert_eq!(jdb.latest_era(), Some(4));
|
assert_eq!(jdb.latest_era(), Some(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,32 +277,32 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
jdb.remove(&baz, EMPTY_PREFIX);
|
jdb.remove(&baz, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap();
|
||||||
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(!jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
@ -310,22 +315,22 @@ mod tests {
|
|||||||
|
|
||||||
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
let foo = jdb.insert(EMPTY_PREFIX, b"foo");
|
||||||
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
let bar = jdb.insert(EMPTY_PREFIX, b"bar");
|
||||||
jdb.commit_batch(0, &keccak(b"0"), None).unwrap();
|
commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.remove(&foo, EMPTY_PREFIX);
|
jdb.remove(&foo, EMPTY_PREFIX);
|
||||||
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
let baz = jdb.insert(EMPTY_PREFIX, b"baz");
|
||||||
jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
jdb.remove(&bar, EMPTY_PREFIX);
|
jdb.remove(&bar, EMPTY_PREFIX);
|
||||||
jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap();
|
||||||
|
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
|
|
||||||
jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap();
|
||||||
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
assert!(jdb.contains(&foo, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
assert!(!jdb.contains(&baz, EMPTY_PREFIX));
|
||||||
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
assert!(!jdb.contains(&bar, EMPTY_PREFIX));
|
||||||
@ -335,11 +340,11 @@ mod tests {
|
|||||||
fn inject() {
|
fn inject() {
|
||||||
let mut jdb = new_db();
|
let mut jdb = new_db();
|
||||||
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
let key = jdb.insert(EMPTY_PREFIX, b"dog");
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog"));
|
||||||
jdb.remove(&key, EMPTY_PREFIX);
|
jdb.remove(&key, EMPTY_PREFIX);
|
||||||
jdb.inject_batch().unwrap();
|
inject_batch(&mut jdb).unwrap();
|
||||||
|
|
||||||
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
assert!(jdb.get(&key, EMPTY_PREFIX).is_none());
|
||||||
}
|
}
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity Ethereum.
|
|
||||||
|
|
||||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Disk-backed `HashDB` implementation.
|
|
||||||
|
|
||||||
use std::io;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use ethereum_types::H256;
|
|
||||||
use hash_db::{HashDB, AsHashDB};
|
|
||||||
use keccak_hasher::KeccakHasher;
|
|
||||||
use kvdb::{self, DBTransaction, DBValue};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
|
|
||||||
/// expose keys of a hashDB for debugging or tests (slow).
|
|
||||||
pub trait KeyedHashDB: HashDB<KeccakHasher, DBValue> {
|
|
||||||
/// Primarily use for tests, highly inefficient.
|
|
||||||
fn keys(&self) -> HashMap<H256, i32>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Upcast to `KeyedHashDB`
|
|
||||||
pub trait AsKeyedHashDB: AsHashDB<KeccakHasher, DBValue> {
|
|
||||||
/// Perform upcast to KeyedHashDB.
|
|
||||||
fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A `HashDB` which can manage a short-term journal potentially containing many forks of mutually
|
|
||||||
/// exclusive actions.
|
|
||||||
pub trait JournalDB: KeyedHashDB {
|
|
||||||
|
|
||||||
/// Return a copy of ourself, in a box.
|
|
||||||
fn boxed_clone(&self) -> Box<dyn JournalDB>;
|
|
||||||
|
|
||||||
/// Returns heap memory size used
|
|
||||||
fn mem_used(&self) -> usize;
|
|
||||||
|
|
||||||
/// Returns the size of journalled state in memory.
|
|
||||||
/// This function has a considerable speed requirement --
|
|
||||||
/// it must be fast enough to call several times per block imported.
|
|
||||||
fn journal_size(&self) -> usize { 0 }
|
|
||||||
|
|
||||||
/// Check if this database has any commits
|
|
||||||
fn is_empty(&self) -> bool;
|
|
||||||
|
|
||||||
/// Get the earliest era in the DB. None if there isn't yet any data in there.
|
|
||||||
fn earliest_era(&self) -> Option<u64> { None }
|
|
||||||
|
|
||||||
/// Get the latest era in the DB. None if there isn't yet any data in there.
|
|
||||||
fn latest_era(&self) -> Option<u64>;
|
|
||||||
|
|
||||||
/// Journal recent database operations as being associated with a given era and id.
|
|
||||||
// TODO: give the overlay to this function so journaldbs don't manage the overlays themselves.
|
|
||||||
fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> io::Result<u32>;
|
|
||||||
|
|
||||||
/// Mark a given block as canonical, indicating that competing blocks' states may be pruned out.
|
|
||||||
fn mark_canonical(&mut self, batch: &mut DBTransaction, era: u64, id: &H256) -> io::Result<u32>;
|
|
||||||
|
|
||||||
/// Commit all queued insert and delete operations without affecting any journalling -- this requires that all insertions
|
|
||||||
/// and deletions are indeed canonical and will likely lead to an invalid database if that assumption is violated.
|
|
||||||
///
|
|
||||||
/// Any keys or values inserted or deleted must be completely independent of those affected
|
|
||||||
/// by any previous `commit` operations. Essentially, this means that `inject` can be used
|
|
||||||
/// either to restore a state to a fresh database, or to insert data which may only be journalled
|
|
||||||
/// from this point onwards.
|
|
||||||
fn inject(&mut self, batch: &mut DBTransaction) -> io::Result<u32>;
|
|
||||||
|
|
||||||
/// State data query
|
|
||||||
fn state(&self, _id: &H256) -> Option<Bytes>;
|
|
||||||
|
|
||||||
/// Whether this database is pruned.
|
|
||||||
fn is_prunable(&self) -> bool { true }
|
|
||||||
|
|
||||||
/// Get backing database.
|
|
||||||
fn backing(&self) -> &Arc<dyn kvdb::KeyValueDB>;
|
|
||||||
|
|
||||||
/// Clear internal strucutres. This should called after changes have been written
|
|
||||||
/// to the backing strage
|
|
||||||
fn flush(&self) {}
|
|
||||||
|
|
||||||
/// Consolidate all the insertions and deletions in the given memory overlay.
|
|
||||||
fn consolidate(&mut self, overlay: super::MemoryDB);
|
|
||||||
|
|
||||||
/// Commit all changes in a single batch
|
|
||||||
#[cfg(test)]
|
|
||||||
fn commit_batch(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> io::Result<u32> {
|
|
||||||
let mut batch = self.backing().transaction();
|
|
||||||
let mut ops = self.journal_under(&mut batch, now, id)?;
|
|
||||||
|
|
||||||
if let Some((end_era, canon_id)) = end {
|
|
||||||
ops += self.mark_canonical(&mut batch, end_era, &canon_id)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = self.backing().write(batch).map(|_| ops).map_err(Into::into);
|
|
||||||
self.flush();
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Inject all changes in a single batch.
|
|
||||||
#[cfg(test)]
|
|
||||||
fn inject_batch(&mut self) -> io::Result<u32> {
|
|
||||||
let mut batch = self.backing().transaction();
|
|
||||||
let res = self.inject(&mut batch)?;
|
|
||||||
self.backing().write(batch).map(|_| res).map_err(Into::into)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user