diff --git a/src/hashdb.rs b/src/hashdb.rs index 561c7843d..dd0973bb3 100644 --- a/src/hashdb.rs +++ b/src/hashdb.rs @@ -1,4 +1,5 @@ use hash::*; +use bytes::*; pub trait HashDB { /// Look up a given hash into the bytes that hash to it, returning None if the @@ -56,6 +57,9 @@ pub trait HashDB { /// ``` fn insert(&mut self, value: &[u8]) -> H256; + /// Like `insert()` , except you provide the key and the data is all moved. + fn emplace(&mut self, key: H256, value: Bytes); + /// Remove a datum previously inserted. Insertions can be "owed" such that the same number of `insert()`s may /// happen without the data being eventually being inserted into the DB. /// diff --git a/src/memorydb.rs b/src/memorydb.rs index 4ec02bd5e..14fae12d0 100644 --- a/src/memorydb.rs +++ b/src/memorydb.rs @@ -37,6 +37,12 @@ use std::collections::HashMap; /// m.kill(&k); /// assert!(!m.exists(&k)); /// +/// m.kill(&k); +/// assert!(!m.exists(&k)); +/// +/// m.insert(d); +/// assert!(!m.exists(&k)); + /// m.insert(d); /// assert!(m.exists(&k)); /// assert_eq!(m.lookup(&k).unwrap(), d); @@ -130,9 +136,9 @@ impl HashDB for MemoryDB { fn insert(&mut self, value: &[u8]) -> H256 { let key = value.sha3(); if match self.data.get_mut(&key) { - Some(&mut (ref mut old_value, ref mut rc @ 0)) => { + Some(&mut (ref mut old_value, ref mut rc @ -0x80000000i32 ... 0)) => { *old_value = From::from(value.bytes()); - *rc = 1; + *rc += 1; false }, Some(&mut (_, ref mut x)) => { *x += 1; false } , @@ -143,6 +149,20 @@ impl HashDB for MemoryDB { key } + fn emplace(&mut self, key: H256, value: Bytes) { + match self.data.get_mut(&key) { + Some(&mut (ref mut old_value, ref mut rc @ -0x80000000i32 ... 0)) => { + *old_value = value; + *rc += 1; + return; + }, + Some(&mut (_, ref mut x)) => { *x += 1; return; } , + None => {}, + } + // ... None falls through into... + self.data.insert(key, (value, 1)); + } + fn kill(&mut self, key: &H256) { if match self.data.get_mut(key) { Some(&mut (_, ref mut x)) => { *x -= 1; false } diff --git a/src/nibbleslice.rs b/src/nibbleslice.rs index e49244325..5866ed8f0 100644 --- a/src/nibbleslice.rs +++ b/src/nibbleslice.rs @@ -1,5 +1,6 @@ //! Nibble-orientated view onto byte-slice, allowing nibble-precision offsets. use std::cmp::*; +use bytes::*; /// Nibble-orientated view onto byte-slice, allowing nibble-precision offsets. /// @@ -69,6 +70,18 @@ impl<'a> NibbleSlice<'a> { } i } + + pub fn encoded(&self, is_leaf: bool) -> Bytes { + let l = self.len(); + let mut r = Bytes::with_capacity(l / 2 + 1); + let mut i = l % 2; + r.push(if i == 1 {0x10 + self.at(0)} else {0} + if is_leaf {0x20} else {0}); + while i < l { + r.push(self.at(i) * 16 + self.at(i + 1)); + i += 2; + } + r + } } impl<'a> PartialEq for NibbleSlice<'a> { @@ -126,6 +139,15 @@ mod tests { } } + #[test] + fn encoded() { + let n = NibbleSlice::new(D); + assert_eq!(n.encoded(false), &[0x00, 0x01, 0x23, 0x45]); + assert_eq!(n.encoded(true), &[0x20, 0x01, 0x23, 0x45]); + assert_eq!(n.mid(1).encoded(false), &[0x11, 0x23, 0x45]); + assert_eq!(n.mid(1).encoded(true), &[0x31, 0x23, 0x45]); + } + #[test] fn shared() { let n = NibbleSlice::new(D); diff --git a/src/overlaydb.rs b/src/overlaydb.rs index 24e4ea8da..d69afa0f1 100644 --- a/src/overlaydb.rs +++ b/src/overlaydb.rs @@ -186,6 +186,7 @@ impl HashDB for OverlayDB { } } fn insert(&mut self, value: &[u8]) -> H256 { self.overlay.insert(value) } + fn emplace(&mut self, key: H256, value: Bytes) { self.overlay.emplace(key, value); } fn kill(&mut self, key: &H256) { self.overlay.kill(key); } } diff --git a/src/rlp.rs b/src/rlp.rs index 59eb4dd6a..1703850bb 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -126,6 +126,12 @@ impl<'a> From> for UntrustedRlp<'a> { } } +pub enum Prototype { + Null, + Data(usize), + List(usize), +} + impl<'a> Rlp<'a> { /// Create a new instance of `Rlp` pub fn new(bytes: &'a [u8]) -> Rlp<'a> { @@ -134,6 +140,19 @@ impl<'a> Rlp<'a> { } } + /// Get the prototype of the RLP. + pub fn prototype(&self) -> Prototype { + if self.is_data() { + Prototype::Data(self.size()) + } + else if self.is_list() { + Prototype::List(self.item_count()) + } + else { + Prototype::Null + } + } + /// The bare data of the rlp. /// /// ```rust @@ -208,6 +227,10 @@ impl<'a> Rlp<'a> { From::from(self.rlp.at(index).unwrap()) } + pub fn data_at(&self, _index: usize) -> &[u8] { + unimplemented!(); + } + /// No value /// /// ```rust @@ -588,7 +611,7 @@ pub struct UntrustedRlpIterator<'a> { impl<'a> IntoIterator for &'a UntrustedRlp<'a> { type Item = UntrustedRlp<'a>; - type IntoIter = UntrustedRlpIterator<'a>; + type IntoIter = UntrustedRlpIterator<'a>; fn into_iter(self) -> Self::IntoIter { UntrustedRlpIterator { @@ -617,7 +640,7 @@ pub struct RlpIterator<'a> { impl<'a> IntoIterator for &'a Rlp<'a> { type Item = Rlp<'a>; - type IntoIter = RlpIterator<'a>; + type IntoIter = RlpIterator<'a>; fn into_iter(self) -> Self::IntoIter { RlpIterator { @@ -1147,63 +1170,63 @@ mod tests { #[test] fn encode_u16() { let tests = vec![ - ETestPair(0u16, vec![0x80u8]), - ETestPair(0x100, vec![0x82, 0x01, 0x00]), - ETestPair(0xffff, vec![0x82, 0xff, 0xff]), - ]; + ETestPair(0u16, vec![0x80u8]), + ETestPair(0x100, vec![0x82, 0x01, 0x00]), + ETestPair(0xffff, vec![0x82, 0xff, 0xff]), + ]; run_encode_tests(tests); } #[test] fn encode_u32() { let tests = vec![ - ETestPair(0u32, vec![0x80u8]), - ETestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), - ETestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), - ]; + ETestPair(0u32, vec![0x80u8]), + ETestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), + ETestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), + ]; run_encode_tests(tests); } #[test] fn encode_u64() { let tests = vec![ - ETestPair(0u64, vec![0x80u8]), - ETestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), - ETestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), - ]; + ETestPair(0u64, vec![0x80u8]), + ETestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), + ETestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), + ]; run_encode_tests(tests); } #[test] fn encode_u256() { let tests = vec![ETestPair(U256::from(0u64), vec![0x80u8]), - ETestPair(U256::from(0x1000000u64), vec![0x84, 0x01, 0x00, 0x00, 0x00]), - ETestPair(U256::from(0xffffffffu64), - vec![0x84, 0xff, 0xff, 0xff, 0xff]), - ETestPair(U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000\ - 000100000000000012f0") - .unwrap(), - vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, - 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0])]; + ETestPair(U256::from(0x1000000u64), vec![0x84, 0x01, 0x00, 0x00, 0x00]), + ETestPair(U256::from(0xffffffffu64), + vec![0x84, 0xff, 0xff, 0xff, 0xff]), + ETestPair(U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000\ + 000100000000000012f0") + .unwrap(), + vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0])]; run_encode_tests(tests); } #[test] fn encode_str() { let tests = vec![ETestPair("cat", vec![0x83, b'c', b'a', b't']), - ETestPair("dog", vec![0x83, b'd', b'o', b'g']), - ETestPair("Marek", vec![0x85, b'M', b'a', b'r', b'e', b'k']), - ETestPair("", vec![0x80]), - ETestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit", - vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', - b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', - b'r', b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', - b't', b',', b' ', b'c', b'o', b'n', b's', b'e', b'c', - b't', b'e', b't', b'u', b'r', b' ', b'a', b'd', b'i', - b'p', b'i', b's', b'i', b'c', b'i', b'n', b'g', b' ', - b'e', b'l', b'i', b't'])]; + ETestPair("dog", vec![0x83, b'd', b'o', b'g']), + ETestPair("Marek", vec![0x85, b'M', b'a', b'r', b'e', b'k']), + ETestPair("", vec![0x80]), + ETestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit", + vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', + b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', + b'r', b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', + b't', b',', b' ', b'c', b'o', b'n', b's', b'e', b'c', + b't', b'e', b't', b'u', b'r', b' ', b'a', b'd', b'i', + b'p', b'i', b's', b'i', b'c', b'i', b'n', b'g', b' ', + b'e', b'l', b'i', b't'])]; run_encode_tests(tests); } @@ -1214,8 +1237,8 @@ mod tests { let tests = vec![ ETestPair(Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(), vec![0x94, 0xef, 0x2d, 0x6d, 0x19, 0x40, 0x84, 0xc2, 0xde, - 0x36, 0xe0, 0xda, 0xbf, 0xce, 0x45, 0xd0, 0x46, - 0xb3, 0x7d, 0x11, 0x06]) + 0x36, 0xe0, 0xda, 0xbf, 0xce, 0x45, 0xd0, 0x46, + 0xb3, 0x7d, 0x11, 0x06]) ]; run_encode_tests(tests); } @@ -1235,18 +1258,18 @@ mod tests { #[test] fn encode_vector_u64() { let tests = vec![ - ETestPair(vec![], vec![0xc0]), - ETestPair(vec![15u64], vec![0xc1, 0x0f]), - ETestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), - ETestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), - ]; + ETestPair(vec![], vec![0xc0]), + ETestPair(vec![15u64], vec![0xc1, 0x0f]), + ETestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), + ETestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), + ]; run_encode_tests(tests); } #[test] fn encode_vector_str() { let tests = vec![ETestPair(vec!["cat", "dog"], - vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; + vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; run_encode_tests(tests); } @@ -1270,7 +1293,7 @@ mod tests { stream.append(&"cat").append(&"dog"); let out = stream.out(); assert_eq!(out, - vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); + vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); } #[test] @@ -1292,7 +1315,7 @@ mod tests { } let out = stream.out(); assert_eq!(out, vec![0xd1, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80]); } @@ -1334,65 +1357,65 @@ mod tests { #[test] fn decode_untrusted_u16() { let tests = vec![ - DTestPair(0u16, vec![0u8]), - DTestPair(0x100, vec![0x82, 0x01, 0x00]), - DTestPair(0xffff, vec![0x82, 0xff, 0xff]), - ]; + DTestPair(0u16, vec![0u8]), + DTestPair(0x100, vec![0x82, 0x01, 0x00]), + DTestPair(0xffff, vec![0x82, 0xff, 0xff]), + ]; run_decode_tests(tests); } #[test] fn decode_untrusted_u32() { let tests = vec![ - DTestPair(0u32, vec![0u8]), - DTestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), - DTestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), - ]; + DTestPair(0u32, vec![0u8]), + DTestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), + DTestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), + ]; run_decode_tests(tests); } #[test] fn decode_untrusted_u64() { let tests = vec![ - DTestPair(0u64, vec![0u8]), - DTestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), - DTestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), - ]; + DTestPair(0u64, vec![0u8]), + DTestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), + DTestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), + ]; run_decode_tests(tests); } #[test] fn decode_untrusted_u256() { let tests = vec![DTestPair(U256::from(0u64), vec![0x80u8]), - DTestPair(U256::from(0x1000000u64), vec![0x84, 0x01, 0x00, 0x00, 0x00]), - DTestPair(U256::from(0xffffffffu64), - vec![0x84, 0xff, 0xff, 0xff, 0xff]), - DTestPair(U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000\ - 000100000000000012f0") - .unwrap(), - vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, - 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0])]; + DTestPair(U256::from(0x1000000u64), vec![0x84, 0x01, 0x00, 0x00, 0x00]), + DTestPair(U256::from(0xffffffffu64), + vec![0x84, 0xff, 0xff, 0xff, 0xff]), + DTestPair(U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000\ + 000100000000000012f0") + .unwrap(), + vec![0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0])]; run_decode_tests(tests); } #[test] fn decode_untrusted_str() { let tests = vec![DTestPair("cat".to_string(), vec![0x83, b'c', b'a', b't']), - DTestPair("dog".to_string(), vec![0x83, b'd', b'o', b'g']), - DTestPair("Marek".to_string(), - vec![0x85, b'M', b'a', b'r', b'e', b'k']), - DTestPair("".to_string(), vec![0x80]), - DTestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit" - .to_string(), - vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', - b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', - b'r', b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', - b't', b',', b' ', b'c', b'o', b'n', b's', b'e', b'c', - b't', b'e', b't', b'u', b'r', b' ', b'a', b'd', b'i', - b'p', b'i', b's', b'i', b'c', b'i', b'n', b'g', b' ', - b'e', b'l', b'i', b't'])]; + DTestPair("dog".to_string(), vec![0x83, b'd', b'o', b'g']), + DTestPair("Marek".to_string(), + vec![0x85, b'M', b'a', b'r', b'e', b'k']), + DTestPair("".to_string(), vec![0x80]), + DTestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit" + .to_string(), + vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', + b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', + b'r', b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', + b't', b',', b' ', b'c', b'o', b'n', b's', b'e', b'c', + b't', b'e', b't', b'u', b'r', b' ', b'a', b'd', b'i', + b'p', b'i', b's', b'i', b'c', b'i', b'n', b'g', b' ', + b'e', b'l', b'i', b't'])]; run_decode_tests(tests); } @@ -1403,8 +1426,8 @@ mod tests { let tests = vec![ DTestPair(Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(), vec![0x94, 0xef, 0x2d, 0x6d, 0x19, 0x40, 0x84, 0xc2, 0xde, - 0x36, 0xe0, 0xda, 0xbf, 0xce, 0x45, 0xd0, 0x46, - 0xb3, 0x7d, 0x11, 0x06]) + 0x36, 0xe0, 0xda, 0xbf, 0xce, 0x45, 0xd0, 0x46, + 0xb3, 0x7d, 0x11, 0x06]) ]; run_decode_tests(tests); } @@ -1412,25 +1435,25 @@ mod tests { #[test] fn decode_untrusted_vector_u64() { let tests = vec![ - DTestPair(vec![], vec![0xc0]), - DTestPair(vec![15u64], vec![0xc1, 0x0f]), - DTestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), - DTestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), - ]; + DTestPair(vec![], vec![0xc0]), + DTestPair(vec![15u64], vec![0xc1, 0x0f]), + DTestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), + DTestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), + ]; run_decode_tests(tests); } #[test] fn decode_untrusted_vector_str() { let tests = vec![DTestPair(vec!["cat".to_string(), "dog".to_string()], - vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; + vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; run_decode_tests(tests); } #[test] fn decode_untrusted_vector_of_vectors_str() { let tests = vec![DTestPair(vec![vec!["cat".to_string()]], - vec![0xc5, 0xc4, 0x83, b'c', b'a', b't'])]; + vec![0xc5, 0xc4, 0x83, b'c', b'a', b't'])]; run_decode_tests(tests); } } diff --git a/src/trie.rs b/src/trie.rs index 889c9b5dc..13b0a4e9a 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -1,8 +1,9 @@ use memorydb::*; use hashdb::*; use hash::*; -//use rlp::*; -//use bytes::*; +use nibbleslice::*; +use bytes::*; +use rlp::*; 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] ); @@ -17,10 +18,10 @@ pub trait Trie { fn is_empty(&self) -> bool { *self.root() == SHA3_NULL_RLP } // TODO: consider returning &[u8]... - fn contains(key: &[u8]) -> bool; - fn at(key: &[u8]) -> Option<&[u8]>; - fn insert(key: &[u8], value: &[u8]); - fn remove(key: &[u8]); + fn contains(&self, key: &[u8]) -> bool; + fn at(&self, key: &[u8]) -> Option<&[u8]>; + fn insert(&mut self, key: &[u8], value: &[u8]); + fn remove(&mut self, key: &[u8]); } pub struct TrieDB { @@ -28,6 +29,15 @@ pub struct TrieDB { root: H256, } +struct Diff { + new: Vec<(H256, Bytes)>, + old: Vec, +} + +impl Diff { + pub fn new() -> Diff { Diff { new: vec![], old: vec![] }} +} + impl TrieDB { pub fn new(db: T) -> Self where T: HashDB + 'static { TrieDB{ db: Box::new(db), root: H256::new() } } @@ -35,37 +45,95 @@ impl TrieDB { 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 init(&mut self) { self.set_root_rlp(&NULL_RLP); } pub fn db(&self) -> &HashDB { self.db.as_ref() } - fn insert_root(&mut self, root_data: &[u8]) { self.root = self.db.insert(root_data); } + fn set_root_rlp(&mut self, root_data: &[u8]) { + self.db.kill(&self.root); + self.root = self.db.insert(root_data); + println!("set_root_rlp {:?} {:?}", root_data, self.root); + } + fn add(&mut self, key: &NibbleSlice, value: &[u8]) { + // determine what the new root is, insert new nodes and remove old as necessary. + let todo = { + let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); + self.merge(root_rlp, key, value) + }; + self.apply(todo.1); + self.set_root_rlp(&todo.0); + } + + fn apply(&mut self, diff: Diff) { + for d in diff.old.iter() { + self.db.kill(&d); + } + for d in diff.new.into_iter() { + self.db.emplace(d.0, d.1); + } + } + + /// Determine the RLP of the node, assuming we're inserting `partial_key` into the + /// node at `old`. This will *not* delete the old mode; it will just return the new RLP + /// that includes the new node. + /// + /// The database will be updated so as to make the returned RLP valid through inserting + /// and deleting nodes as necessary. + fn merge(&self, old: &[u8], partial_key: &NibbleSlice, value: &[u8]) -> (Bytes, Diff) { + let o = Rlp::new(old); + match o.prototype() { + Prototype::List(17) => { + // already have a branch. route and merge. + unimplemented!(); + }, + Prototype::List(2) => { + // already have an extension. either fast_forward, cleve or transmute_to_branch. + unimplemented!(); + }, + Prototype::Data(0) => { + (Self::compose_extension(partial_key, value, true), Diff::new()) + }, + _ => panic!("Invalid RLP for node."), + } + } + + fn compose_extension(partial_key: &NibbleSlice, value: &[u8], is_leaf: bool) -> Bytes { + println!("compose_extension {:?} {:?} {:?} ({:?})", partial_key, value, is_leaf, partial_key.encoded(is_leaf)); + let mut s = RlpStream::new_list(2); + s.append(&partial_key.encoded(is_leaf)); + s.append(&value.to_vec()); // WTF?!?! + //s.append(value); // <-- should be. + let r = s.out(); + println!("output: -> {:?}", &r); + r + } } impl Trie for TrieDB { fn root(&self) -> &H256 { &self.root } - fn contains(_key: &[u8]) -> bool { + fn contains(&self, _key: &[u8]) -> bool { unimplemented!(); } - fn at(_key: &[u8]) -> Option<&[u8]> { + fn at(&self, _key: &[u8]) -> Option<&[u8]> { unimplemented!(); } - fn insert(_key: &[u8], _value: &[u8]) { - unimplemented!(); + fn insert(&mut self, key: &[u8], value: &[u8]) { + (self as &mut TrieDB).add(&NibbleSlice::new(key), value); } - fn remove(_key: &[u8]) { + fn remove(&mut self, _key: &[u8]) { unimplemented!(); } } #[test] -fn it_works() { +fn playpen() { use overlaydb::*; + use triehash::*; (&[1, 2, 3]).starts_with(&[1, 2]); @@ -73,6 +141,7 @@ fn it_works() { t.init(); assert_eq!(*t.root(), SHA3_NULL_RLP); assert!(t.is_empty()); - // TODO: make work: - //assert_eq!(t.root(), SHA3_NULL_RLP); + + t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); + assert_eq!(*t.root(), hash256(&[ NibblePair::new_raw(vec![0x01u8, 0x23], vec![0x01u8, 0x23])])); } \ No newline at end of file