Merge branch 'master' of https://github.com/gavofyork/ethcore-util
This commit is contained in:
commit
a1c017b7ff
@ -1,5 +1,4 @@
|
|||||||
use hash::*;
|
use hash::*;
|
||||||
use bytes::Bytes;
|
|
||||||
|
|
||||||
pub trait HashDB {
|
pub trait HashDB {
|
||||||
/// Look up a given hash into the bytes that hash to it, returning None if the
|
/// Look up a given hash into the bytes that hash to it, returning None if the
|
||||||
@ -17,7 +16,7 @@ pub trait HashDB {
|
|||||||
/// assert_eq!(m.lookup(&hash).unwrap(), hello_bytes);
|
/// assert_eq!(m.lookup(&hash).unwrap(), hello_bytes);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
fn lookup(&self, key: &H256) -> Option<Bytes>;
|
fn lookup(&self, key: &H256) -> Option<&[u8]>;
|
||||||
|
|
||||||
/// Check for the existance of a hash-key.
|
/// Check for the existance of a hash-key.
|
||||||
///
|
///
|
||||||
|
@ -34,6 +34,7 @@ pub mod math;
|
|||||||
pub mod chainfilter;
|
pub mod chainfilter;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod triehash;
|
pub mod triehash;
|
||||||
|
pub mod trie;
|
||||||
|
|
||||||
//pub mod network;
|
//pub mod network;
|
||||||
|
|
||||||
|
@ -100,12 +100,22 @@ impl MemoryDB {
|
|||||||
mem::swap(&mut self.data, &mut data);
|
mem::swap(&mut self.data, &mut data);
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn denote(&self, key: &H256, value: Bytes) -> &(Bytes, i32) {
|
||||||
|
if self.data.get(&key) == None {
|
||||||
|
unsafe {
|
||||||
|
let p = &self.data as *const HashMap<H256, (Bytes, i32)> as *mut HashMap<H256, (Bytes, i32)>;
|
||||||
|
(*p).insert(key.clone(), (value, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.data.get(key).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HashDB for MemoryDB {
|
impl HashDB for MemoryDB {
|
||||||
fn lookup(&self, key: &H256) -> Option<Bytes> {
|
fn lookup(&self, key: &H256) -> Option<&[u8]> {
|
||||||
match self.data.get(key) {
|
match self.data.get(key) {
|
||||||
Some(&(ref d, rc)) if rc > 0 => Some(d.clone()),
|
Some(&(ref d, rc)) if rc > 0 => Some(d),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,3 +153,20 @@ impl HashDB for MemoryDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn memorydb_denote() {
|
||||||
|
let mut m = MemoryDB::new();
|
||||||
|
let hello_bytes = b"Hello world!";
|
||||||
|
let hash = m.insert(hello_bytes);
|
||||||
|
assert_eq!(m.lookup(&hash).unwrap(), b"Hello world!");
|
||||||
|
|
||||||
|
for _ in 0..1000 {
|
||||||
|
let r = H256::random();
|
||||||
|
let k = r.sha3();
|
||||||
|
let &(ref v, ref rc) = m.denote(&k, r.bytes().to_vec());
|
||||||
|
assert_eq!(v, &r.bytes());
|
||||||
|
assert_eq!(*rc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(m.lookup(&hash).unwrap(), b"Hello world!");
|
||||||
|
}
|
@ -135,19 +135,19 @@ impl OverlayDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HashDB for OverlayDB {
|
impl HashDB for OverlayDB {
|
||||||
fn lookup(&self, key: &H256) -> Option<Bytes> {
|
fn lookup(&self, key: &H256) -> Option<&[u8]> {
|
||||||
// return ok if positive; if negative, check backing - might be enough references there to make
|
// return ok if positive; if negative, check backing - might be enough references there to make
|
||||||
// it positive again.
|
// it positive again.
|
||||||
let k = self.overlay.raw(key);
|
let k = self.overlay.raw(key);
|
||||||
match k {
|
match k {
|
||||||
Some(&(ref d, rc)) if rc > 0 => Some(d.clone()),
|
Some(&(ref d, rc)) if rc > 0 => Some(d),
|
||||||
_ => {
|
_ => {
|
||||||
let memrc = k.map(|&(_, rc)| rc).unwrap_or(0);
|
let memrc = k.map(|&(_, rc)| rc).unwrap_or(0);
|
||||||
match self.payload(key) {
|
match self.payload(key) {
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
let (d, rc) = x;
|
let (d, rc) = x;
|
||||||
if rc as i32 + memrc > 0 {
|
if rc as i32 + memrc > 0 {
|
||||||
Some(d)
|
Some(&self.overlay.denote(key, d).0)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
None
|
None
|
||||||
@ -193,7 +193,7 @@ impl HashDB for OverlayDB {
|
|||||||
fn overlaydb_overlay_insert_and_kill() {
|
fn overlaydb_overlay_insert_and_kill() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let h = trie.insert(b"hello world");
|
let h = trie.insert(b"hello world");
|
||||||
assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec()));
|
assert_eq!(trie.lookup(&h).unwrap(), b"hello world");
|
||||||
trie.kill(&h);
|
trie.kill(&h);
|
||||||
assert_eq!(trie.lookup(&h), None);
|
assert_eq!(trie.lookup(&h), None);
|
||||||
}
|
}
|
||||||
@ -202,11 +202,11 @@ fn overlaydb_overlay_insert_and_kill() {
|
|||||||
fn overlaydb_backing_insert_revert() {
|
fn overlaydb_backing_insert_revert() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let h = trie.insert(b"hello world");
|
let h = trie.insert(b"hello world");
|
||||||
assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec()));
|
assert_eq!(trie.lookup(&h).unwrap(), b"hello world");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec()));
|
assert_eq!(trie.lookup(&h).unwrap(), b"hello world");
|
||||||
trie.revert();
|
trie.revert();
|
||||||
assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec()));
|
assert_eq!(trie.lookup(&h).unwrap(), b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -230,7 +230,7 @@ fn overlaydb_backing_kill_revert() {
|
|||||||
trie.kill(&h);
|
trie.kill(&h);
|
||||||
assert_eq!(trie.lookup(&h), None);
|
assert_eq!(trie.lookup(&h), None);
|
||||||
trie.revert();
|
trie.revert();
|
||||||
assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec()));
|
assert_eq!(trie.lookup(&h).unwrap(), b"hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -248,29 +248,29 @@ fn overlaydb_negative() {
|
|||||||
fn overlaydb_complex() {
|
fn overlaydb_complex() {
|
||||||
let mut trie = OverlayDB::new_temp();
|
let mut trie = OverlayDB::new_temp();
|
||||||
let hfoo = trie.insert(b"foo");
|
let hfoo = trie.insert(b"foo");
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
let hbar = trie.insert(b"bar");
|
let hbar = trie.insert(b"bar");
|
||||||
assert_eq!(trie.lookup(&hbar), Some(b"bar".to_vec()));
|
assert_eq!(trie.lookup(&hbar).unwrap(), b"bar");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
assert_eq!(trie.lookup(&hbar), Some(b"bar".to_vec()));
|
assert_eq!(trie.lookup(&hbar).unwrap(), b"bar");
|
||||||
trie.insert(b"foo"); // two refs
|
trie.insert(b"foo"); // two refs
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
assert_eq!(trie.lookup(&hbar), Some(b"bar".to_vec()));
|
assert_eq!(trie.lookup(&hbar).unwrap(), b"bar");
|
||||||
trie.kill(&hbar); // zero refs - delete
|
trie.kill(&hbar); // zero refs - delete
|
||||||
assert_eq!(trie.lookup(&hbar), None);
|
assert_eq!(trie.lookup(&hbar), None);
|
||||||
trie.kill(&hfoo); // one ref - keep
|
trie.kill(&hfoo); // one ref - keep
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
trie.kill(&hfoo); // zero ref - would delete, but...
|
trie.kill(&hfoo); // zero ref - would delete, but...
|
||||||
assert_eq!(trie.lookup(&hfoo), None);
|
assert_eq!(trie.lookup(&hfoo), None);
|
||||||
trie.insert(b"foo"); // one ref - keep after all.
|
trie.insert(b"foo"); // one ref - keep after all.
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
trie.commit().unwrap();
|
trie.commit().unwrap();
|
||||||
assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec()));
|
assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo");
|
||||||
trie.kill(&hfoo); // zero ref - delete
|
trie.kill(&hfoo); // zero ref - delete
|
||||||
assert_eq!(trie.lookup(&hfoo), None);
|
assert_eq!(trie.lookup(&hfoo), None);
|
||||||
trie.commit().unwrap(); //
|
trie.commit().unwrap(); //
|
||||||
|
64
src/trie.rs
Normal file
64
src/trie.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use memorydb::*;
|
||||||
|
use hashdb::*;
|
||||||
|
use hash::*;
|
||||||
|
//use rlp::*;
|
||||||
|
//use bytes::*;
|
||||||
|
|
||||||
|
pub const NULL_RLP: [u8; 1] = [0x80; 1];
|
||||||
|
pub const SHA3_NULL_RLP: H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21] );
|
||||||
|
|
||||||
|
/*lazy_static! {
|
||||||
|
pub static ref NULL_RLP: Bytes = { let mut r = RlpStream::new(); r.append(&""); r.out().unwrap() };
|
||||||
|
pub static ref SHA3_NULL_RLP: H256 = { use sha3::Hashable; NULL_RLP.sha3() };
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pub trait Trie {
|
||||||
|
fn root(&self) -> &H256;
|
||||||
|
fn is_empty(&self) -> bool { *self.root() == SHA3_NULL_RLP }
|
||||||
|
|
||||||
|
// TODO: consider returning &[u8]...
|
||||||
|
/* fn at(key: &[u8]) -> Option<Bytes>;
|
||||||
|
fn insert(key: &[u8], value: &[u8]);
|
||||||
|
fn remove(key: &[u8]);
|
||||||
|
fn contains(key: &[u8]) -> bool;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TrieDB {
|
||||||
|
db: Box<HashDB>,
|
||||||
|
root: H256,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrieDB {
|
||||||
|
pub fn new<T>(db: T) -> Self where T: HashDB + 'static { TrieDB{ db: Box::new(db), root: H256::new() } }
|
||||||
|
|
||||||
|
pub fn new_boxed(db_box: Box<HashDB>) -> Self { TrieDB{ db: db_box, root: H256::new() } }
|
||||||
|
|
||||||
|
pub fn new_memory() -> Self { TrieDB{ db: Box::new(MemoryDB::new()), root: H256::new() } }
|
||||||
|
|
||||||
|
pub fn init(&mut self) { self.insert_root(&NULL_RLP); }
|
||||||
|
|
||||||
|
pub fn db(&self) -> &HashDB { self.db.as_ref() }
|
||||||
|
|
||||||
|
// pub fn db_mut(&mut self) -> &mut HashDB { self.db.as }
|
||||||
|
|
||||||
|
fn insert_root(&mut self, root_data: &[u8]) { self.root = self.db.insert(root_data); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trie for TrieDB {
|
||||||
|
fn root(&self) -> &H256 { &self.root }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
use overlaydb::*;
|
||||||
|
|
||||||
|
(&[1, 2, 3]).starts_with(&[1, 2]);
|
||||||
|
|
||||||
|
let mut t = TrieDB::new(OverlayDB::new_temp());
|
||||||
|
t.init();
|
||||||
|
assert_eq!(*t.root(), SHA3_NULL_RLP);
|
||||||
|
assert!(t.is_empty());
|
||||||
|
// TODO: make work:
|
||||||
|
//assert_eq!(t.root(), SHA3_NULL_RLP);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user