From b334a8f824708543364b817b4131dbeef0c69742 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 29 Nov 2015 15:50:33 +0100 Subject: [PATCH 1/3] Return lookup by reference. --- src/hashdb.rs | 2 +- src/lib.rs | 1 + src/memorydb.rs | 32 ++++++++++++++++++++++-- src/overlaydb.rs | 39 +++++++++++++++-------------- src/trie.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 src/trie.rs diff --git a/src/hashdb.rs b/src/hashdb.rs index 48f5182bc..eb41d23df 100644 --- a/src/hashdb.rs +++ b/src/hashdb.rs @@ -17,7 +17,7 @@ pub trait HashDB { /// assert_eq!(m.lookup(&hash).unwrap(), hello_bytes); /// } /// ``` - fn lookup(&self, key: &H256) -> Option; + fn lookup(&self, key: &H256) -> Option<&[u8]>; /// Check for the existance of a hash-key. /// diff --git a/src/lib.rs b/src/lib.rs index 098e42928..983dc322c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ pub mod math; pub mod chainfilter; pub mod crypto; pub mod triehash; +pub mod trie; //pub mod network; diff --git a/src/memorydb.rs b/src/memorydb.rs index cbb9e426b..58dc980ca 100644 --- a/src/memorydb.rs +++ b/src/memorydb.rs @@ -100,12 +100,23 @@ impl MemoryDB { mem::swap(&mut self.data, &mut 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; + let mp = p as *mut HashMap; + (*mp).insert(key.clone(), (value, 0)); + } + } + self.data.get(key).unwrap() + } } impl HashDB for MemoryDB { - fn lookup(&self, key: &H256) -> Option { + fn lookup(&self, key: &H256) -> Option<&[u8]> { 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 } } @@ -143,3 +154,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 i 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!"); +} \ No newline at end of file diff --git a/src/overlaydb.rs b/src/overlaydb.rs index 0f6ae3d77..86ad266c9 100644 --- a/src/overlaydb.rs +++ b/src/overlaydb.rs @@ -8,6 +8,7 @@ use hashdb::*; use memorydb::*; use std::ops::*; use std::sync::*; +use std::cell::*; use std::env; use rocksdb::{DB, Writable}; @@ -135,19 +136,19 @@ impl OverlayDB { } impl HashDB for OverlayDB { - fn lookup(&self, key: &H256) -> Option { + fn lookup(&self, key: &H256) -> Option<&[u8]> { // return ok if positive; if negative, check backing - might be enough references there to make // it positive again. let k = self.overlay.raw(key); 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); match self.payload(key) { Some(x) => { let (d, rc) = x; if rc as i32 + memrc > 0 { - Some(d) + Some(&self.overlay.denote(key, d).0) } else { None @@ -193,7 +194,7 @@ impl HashDB for OverlayDB { fn overlaydb_overlay_insert_and_kill() { let mut trie = OverlayDB::new_temp(); 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); assert_eq!(trie.lookup(&h), None); } @@ -202,11 +203,11 @@ fn overlaydb_overlay_insert_and_kill() { fn overlaydb_backing_insert_revert() { let mut trie = OverlayDB::new_temp(); 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(); - assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec())); + assert_eq!(trie.lookup(&h).unwrap(), b"hello world"); trie.revert(); - assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec())); + assert_eq!(trie.lookup(&h).unwrap(), b"hello world"); } #[test] @@ -230,7 +231,7 @@ fn overlaydb_backing_kill_revert() { trie.kill(&h); assert_eq!(trie.lookup(&h), None); trie.revert(); - assert_eq!(trie.lookup(&h), Some(b"hello world".to_vec())); + assert_eq!(trie.lookup(&h).unwrap(), b"hello world"); } #[test] @@ -248,29 +249,29 @@ fn overlaydb_negative() { fn overlaydb_complex() { let mut trie = OverlayDB::new_temp(); 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"); - assert_eq!(trie.lookup(&hbar), Some(b"bar".to_vec())); + assert_eq!(trie.lookup(&hbar).unwrap(), b"bar"); trie.commit().unwrap(); - assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec())); - assert_eq!(trie.lookup(&hbar), Some(b"bar".to_vec())); + assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo"); + assert_eq!(trie.lookup(&hbar).unwrap(), b"bar"); 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(); - assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec())); - assert_eq!(trie.lookup(&hbar), Some(b"bar".to_vec())); + assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo"); + assert_eq!(trie.lookup(&hbar).unwrap(), b"bar"); trie.kill(&hbar); // zero refs - delete assert_eq!(trie.lookup(&hbar), None); 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(); - 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... assert_eq!(trie.lookup(&hfoo), None); 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(); - assert_eq!(trie.lookup(&hfoo), Some(b"foo".to_vec())); + assert_eq!(trie.lookup(&hfoo).unwrap(), b"foo"); trie.kill(&hfoo); // zero ref - delete assert_eq!(trie.lookup(&hfoo), None); trie.commit().unwrap(); // diff --git a/src/trie.rs b/src/trie.rs new file mode 100644 index 000000000..41c8f58ea --- /dev/null +++ b/src/trie.rs @@ -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; + fn insert(key: &[u8], value: &[u8]); + fn remove(key: &[u8]); + fn contains(key: &[u8]) -> bool;*/ +} + +pub struct TrieDB { + db: Box, + root: H256, +} + +impl TrieDB { + pub fn new(db: T) -> Self where T: HashDB + 'static { TrieDB{ db: Box::new(db), root: H256::new() } } + + pub fn new_boxed(db_box: Box) -> 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); +} \ No newline at end of file From cf62f67b5f3d2ab19f054775c9bfe7481aa1e682 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 29 Nov 2015 16:00:23 +0100 Subject: [PATCH 2/3] Fix warnings. --- src/hashdb.rs | 1 - src/memorydb.rs | 7 +++---- src/overlaydb.rs | 1 - src/trie.rs | 4 ++-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/hashdb.rs b/src/hashdb.rs index eb41d23df..561c7843d 100644 --- a/src/hashdb.rs +++ b/src/hashdb.rs @@ -1,5 +1,4 @@ use hash::*; -use bytes::Bytes; pub trait HashDB { /// Look up a given hash into the bytes that hash to it, returning None if the diff --git a/src/memorydb.rs b/src/memorydb.rs index 58dc980ca..4ec02bd5e 100644 --- a/src/memorydb.rs +++ b/src/memorydb.rs @@ -104,9 +104,8 @@ impl MemoryDB { pub fn denote(&self, key: &H256, value: Bytes) -> &(Bytes, i32) { if self.data.get(&key) == None { unsafe { - let p = &self.data as *const HashMap; - let mp = p as *mut HashMap; - (*mp).insert(key.clone(), (value, 0)); + let p = &self.data as *const HashMap as *mut HashMap; + (*p).insert(key.clone(), (value, 0)); } } self.data.get(key).unwrap() @@ -161,7 +160,7 @@ fn memorydb_denote() { let hash = m.insert(hello_bytes); assert_eq!(m.lookup(&hash).unwrap(), b"Hello world!"); - for i in 0..1000 { + for _ in 0..1000 { let r = H256::random(); let k = r.sha3(); let &(ref v, ref rc) = m.denote(&k, r.bytes().to_vec()); diff --git a/src/overlaydb.rs b/src/overlaydb.rs index 86ad266c9..b6f2b3eb2 100644 --- a/src/overlaydb.rs +++ b/src/overlaydb.rs @@ -8,7 +8,6 @@ use hashdb::*; use memorydb::*; use std::ops::*; use std::sync::*; -use std::cell::*; use std::env; use rocksdb::{DB, Writable}; diff --git a/src/trie.rs b/src/trie.rs index 41c8f58ea..392e40a04 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -1,8 +1,8 @@ use memorydb::*; use hashdb::*; use hash::*; -use rlp::*; -use bytes::*; +//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] ); From 9c632d58f2d1b6270087e50e58a9240254adf1f6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 29 Nov 2015 18:45:41 +0100 Subject: [PATCH 3/3] Possible fix? --- src/trie.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/trie.rs b/src/trie.rs index 392e40a04..889c9b5dc 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -17,10 +17,10 @@ pub trait Trie { fn is_empty(&self) -> bool { *self.root() == SHA3_NULL_RLP } // TODO: consider returning &[u8]... -/* fn at(key: &[u8]) -> Option; + fn contains(key: &[u8]) -> bool; + fn at(key: &[u8]) -> Option<&[u8]>; fn insert(key: &[u8], value: &[u8]); fn remove(key: &[u8]); - fn contains(key: &[u8]) -> bool;*/ } pub struct TrieDB { @@ -39,14 +39,28 @@ impl TrieDB { 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 } + + fn contains(_key: &[u8]) -> bool { + unimplemented!(); + } + + fn at(_key: &[u8]) -> Option<&[u8]> { + unimplemented!(); + } + + fn insert(_key: &[u8], _value: &[u8]) { + unimplemented!(); + } + + fn remove(_key: &[u8]) { + unimplemented!(); + } } #[test]