Merge branch 'master' of github.com:gavofyork/ethcore-util into network
Conflicts: src/triehash.rs
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
use hash::*;
|
||||
use bytes::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub trait HashDB {
|
||||
/// Get the keys in the database together with number of underlying references.
|
||||
fn keys(&self) -> HashMap<H256, u32>;
|
||||
|
||||
/// Look up a given hash into the bytes that hash to it, returning None if the
|
||||
/// hash is not known.
|
||||
///
|
||||
|
||||
@@ -116,6 +116,10 @@ impl MemoryDB {
|
||||
}
|
||||
self.data.get(key).unwrap()
|
||||
}
|
||||
|
||||
pub fn raw_keys(&self) -> HashMap<H256, i32> {
|
||||
self.data.iter().filter_map(|(k, v)| if v.1 != 0 {Some((k.clone(), v.1))} else {None}).collect::<HashMap<H256, i32>>()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashDB for MemoryDB {
|
||||
@@ -126,6 +130,10 @@ impl HashDB for MemoryDB {
|
||||
}
|
||||
}
|
||||
|
||||
fn keys(&self) -> HashMap<H256, u32> {
|
||||
self.data.iter().filter_map(|(k, v)| if v.1 > 0 {Some((k.clone(), v.1 as u32))} else {None} ).collect::<HashMap<H256, u32>>()
|
||||
}
|
||||
|
||||
fn exists(&self, key: &H256) -> bool {
|
||||
match self.data.get(key) {
|
||||
Some(&(_, x)) if x > 0 => true,
|
||||
|
||||
@@ -30,6 +30,8 @@ use bytes::*;
|
||||
pub struct NibbleSlice<'a> {
|
||||
data: &'a [u8],
|
||||
offset: usize,
|
||||
data_encode_suffix: &'a [u8],
|
||||
offset_encode_suffix: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
|
||||
@@ -37,7 +39,26 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
|
||||
pub fn new(data: &[u8]) -> NibbleSlice { NibbleSlice::new_offset(data, 0) }
|
||||
|
||||
/// Create a new nibble slice with the given byte-slice with a nibble offset.
|
||||
pub fn new_offset(data: &'a [u8], offset: usize) -> NibbleSlice { NibbleSlice{data: data, offset: offset} }
|
||||
pub fn new_offset(data: &'a [u8], offset: usize) -> NibbleSlice { NibbleSlice{data: data, offset: offset, data_encode_suffix: &b""[..], offset_encode_suffix: 0} }
|
||||
|
||||
///
|
||||
pub fn new_composed(a: &'a NibbleSlice, b: &'a NibbleSlice) -> NibbleSlice<'a> { NibbleSlice{data: a.data, offset: a.offset, data_encode_suffix: b.data, offset_encode_suffix: b.offset} }
|
||||
|
||||
/*pub fn new_composed_bytes_offset(a: &NibbleSlice, b: &NibbleSlice) -> (Bytes, usize) {
|
||||
let r: Vec<u8>::with_capacity((a.len() + b.len() + 1) / 2);
|
||||
let mut i = (a.len() + b.len()) % 2;
|
||||
while i < a.len() {
|
||||
match i % 2 {
|
||||
0 => ,
|
||||
1 => ,
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
while i < a.len() + b.len() {
|
||||
i += 1;
|
||||
}
|
||||
(r, a.len() + b.len())
|
||||
}*/
|
||||
|
||||
/// Create a new nibble slice from the given HPE encoded data (e.g. output of `encoded()`).
|
||||
pub fn from_encoded(data: &'a [u8]) -> (NibbleSlice, bool) {
|
||||
@@ -48,20 +69,32 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
|
||||
pub fn is_empty(&self) -> bool { self.len() == 0 }
|
||||
|
||||
/// Get the length (in nibbles, naturally) of this slice.
|
||||
pub fn len(&self) -> usize { self.data.len() * 2 - self.offset }
|
||||
pub fn len(&self) -> usize { (self.data.len() + self.data_encode_suffix.len()) * 2 - self.offset - self.offset_encode_suffix }
|
||||
|
||||
/// Get the nibble at position `i`.
|
||||
pub fn at(&self, i: usize) -> u8 {
|
||||
if (self.offset + i) & 1 == 1 {
|
||||
self.data[(self.offset + i) / 2] & 15u8
|
||||
let l = self.data.len() * 2 - self.offset;
|
||||
if i < l {
|
||||
if (self.offset + i) & 1 == 1 {
|
||||
self.data[(self.offset + i) / 2] & 15u8
|
||||
}
|
||||
else {
|
||||
self.data[(self.offset + i) / 2] >> 4
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.data[(self.offset + i) / 2] >> 4
|
||||
let i = i - l;
|
||||
if (self.offset_encode_suffix + i) & 1 == 1 {
|
||||
self.data_encode_suffix[(self.offset_encode_suffix + i) / 2] & 15u8
|
||||
}
|
||||
else {
|
||||
self.data_encode_suffix[(self.offset_encode_suffix + i) / 2] >> 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return object which represents a view on to this slice (further) offset by `i` nibbles.
|
||||
pub fn mid(&'view self, i: usize) -> NibbleSlice<'a> { NibbleSlice{ data: self.data, offset: self.offset + i} }
|
||||
pub fn mid(&'view self, i: usize) -> NibbleSlice<'a> { NibbleSlice{ data: self.data, offset: self.offset + i, data_encode_suffix: &b""[..], offset_encode_suffix: 0 } }
|
||||
|
||||
/// Do we start with the same nibbles as the whole of `them`?
|
||||
pub fn starts_with(&self, them: &Self) -> bool { self.common_prefix(them) == them.len() }
|
||||
|
||||
@@ -9,6 +9,7 @@ use memorydb::*;
|
||||
use std::ops::*;
|
||||
use std::sync::*;
|
||||
use std::env;
|
||||
use std::collections::HashMap;
|
||||
use rocksdb::{DB, Writable};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -135,6 +136,20 @@ impl OverlayDB {
|
||||
}
|
||||
|
||||
impl HashDB for OverlayDB {
|
||||
fn keys(&self) -> HashMap<H256, u32> {
|
||||
let mut ret: HashMap<H256, u32> = HashMap::new();
|
||||
for (key, _) in self.backing.iterator().from_start() {
|
||||
let h = H256::from_slice(key.deref());
|
||||
let r = self.payload(&h).unwrap().1;
|
||||
ret.insert(h, r);
|
||||
}
|
||||
|
||||
for (key, refs) in self.overlay.raw_keys().into_iter() {
|
||||
let refs = *ret.get(&key).unwrap_or(&0u32) as i32 + refs as i32;
|
||||
ret.insert(key, refs as u32);
|
||||
}
|
||||
ret
|
||||
}
|
||||
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.
|
||||
|
||||
98
src/rlp.rs
98
src/rlp.rs
@@ -125,6 +125,7 @@ impl<'a> From<Rlp<'a>> for UntrustedRlp<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Prototype {
|
||||
Null,
|
||||
Data(usize),
|
||||
@@ -1098,6 +1099,9 @@ impl Encoder for BasicEncoder {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate json_tests;
|
||||
use self::json_tests::execute_tests_from_directory;
|
||||
use self::json_tests::rlp as rlptest;
|
||||
use std::{fmt, cmp};
|
||||
use std::str::FromStr;
|
||||
use rlp;
|
||||
@@ -1256,7 +1260,7 @@ mod tests {
|
||||
run_encode_tests(tests);
|
||||
}
|
||||
|
||||
/// Vec<u8> is treated as a single value
|
||||
/// Vec<u8> (Bytes) is treated as a single value
|
||||
#[test]
|
||||
fn encode_vector_u8() {
|
||||
let tests = vec![
|
||||
@@ -1292,60 +1296,6 @@ mod tests {
|
||||
run_encode_tests(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_bytes() {
|
||||
let vec = vec![0u8];
|
||||
let slice: &[u8] = &vec;
|
||||
let res = rlp::encode(&slice);
|
||||
assert_eq!(res, vec![0u8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rlp_stream() {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
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']);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rlp_stream_list() {
|
||||
let mut stream = RlpStream::new_list(3);
|
||||
stream.append_list(0);
|
||||
stream.append_list(1).append_list(0);
|
||||
stream.append_list(2).append_list(0).append_list(1).append_list(0);
|
||||
let out = stream.out();
|
||||
assert_eq!(out, vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rlp_stream_list2() {
|
||||
let mut stream = RlpStream::new();
|
||||
stream.append_list(17);
|
||||
for _ in 0..17 {
|
||||
stream.append(&"");
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rlp_stream_list3() {
|
||||
let mut stream = RlpStream::new();
|
||||
stream.append_list(17);
|
||||
|
||||
let mut res = vec![0xf8, 0x44];
|
||||
for _ in 0..17 {
|
||||
stream.append(&"aaa");
|
||||
res.extend(vec![0x83, b'a', b'a', b'a']);
|
||||
}
|
||||
let out = stream.out();
|
||||
assert_eq!(out, res);
|
||||
}
|
||||
|
||||
struct DTestPair<T>(T, Vec<u8>) where T: rlp::Decodable + fmt::Debug + cmp::Eq;
|
||||
|
||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: rlp::Decodable + fmt::Debug + cmp::Eq {
|
||||
@@ -1355,7 +1305,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// Vec<u8> is treated as a single value
|
||||
/// Vec<u8> (Bytes) is treated as a single value
|
||||
#[test]
|
||||
fn decode_vector_u8() {
|
||||
let tests = vec![
|
||||
@@ -1471,29 +1421,23 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_view() {
|
||||
struct View<'a> {
|
||||
bytes: &'a [u8]
|
||||
}
|
||||
fn test_rlp_json() {
|
||||
println!("Json rlp test: ");
|
||||
execute_tests_from_directory::<rlptest::RlpStreamTest, _>("json-tests/json/rlp/stream/*.json", &mut | file, input, output | {
|
||||
println!("file: {}", file);
|
||||
|
||||
impl <'a, 'view> View<'a> where 'a: 'view {
|
||||
fn new(bytes: &'a [u8]) -> View<'a> {
|
||||
View {
|
||||
bytes: bytes
|
||||
}
|
||||
let mut stream = RlpStream::new();
|
||||
for operation in input.into_iter() {
|
||||
match operation {
|
||||
rlptest::Operation::Append(ref v) => stream.append(v),
|
||||
rlptest::Operation::AppendList(len) => stream.append_list(len),
|
||||
rlptest::Operation::AppendRaw(ref raw, len) => stream.append_raw(raw, len),
|
||||
rlptest::Operation::AppendEmpty => stream.append_empty_data()
|
||||
};
|
||||
}
|
||||
|
||||
fn offset(&'view self, len: usize) -> View<'a> {
|
||||
View::new(&self.bytes[len..])
|
||||
}
|
||||
|
||||
fn data(&'view self) -> &'a [u8] {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![0, 1, 2, 3];
|
||||
let view = View::new(&data);
|
||||
let _data_slice = view.offset(1).data();
|
||||
assert_eq!(stream.out(), output);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
860
src/trie.rs
860
src/trie.rs
File diff suppressed because it is too large
Load Diff
106
src/triehash.rs
106
src/triehash.rs
@@ -277,63 +277,13 @@ fn test_hex_prefix_encode() {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
use std::collections::BTreeMap;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use rustc_serialize::json::Json;
|
||||
use bytes::*;
|
||||
extern crate json_tests;
|
||||
use self::json_tests::*;
|
||||
use hash::*;
|
||||
use triehash::*;
|
||||
|
||||
#[test]
|
||||
fn empty_trie_root() {
|
||||
assert_eq!(trie_root(vec![]), H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_trie_item() {
|
||||
let v = vec![(From::from("A"), From::from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))];
|
||||
assert_eq!(trie_root(v), H256::from_str("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn foo_trie_item() {
|
||||
|
||||
let v = vec![
|
||||
(From::from("foo"), From::from("bar")),
|
||||
(From::from("food"), From::from("bass"))
|
||||
];
|
||||
|
||||
assert_eq!(trie_root(v), H256::from_str("17beaa1648bafa633cda809c90c04af50fc8aed3cb40d16efbddee6fdf63c4c3").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dogs_trie_item() {
|
||||
|
||||
let v = vec![
|
||||
(From::from("doe"), From::from("reindeer")),
|
||||
(From::from("dog"), From::from("puppy")),
|
||||
(From::from("dogglesworth"), From::from("cat")),
|
||||
];
|
||||
|
||||
assert_eq!(trie_root(v), H256::from_str("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn puppy_trie_items() {
|
||||
|
||||
let v = vec![
|
||||
(From::from("do"), From::from("verb")),
|
||||
(From::from("dog"), From::from("puppy")),
|
||||
(From::from("doge"), From::from("coin")),
|
||||
(From::from("horse"), From::from("stallion")),
|
||||
];
|
||||
|
||||
assert_eq!(trie_root(v), H256::from_str("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn out_of_order() {
|
||||
fn test_triehash_out_of_order() {
|
||||
assert!(trie_root(vec![
|
||||
(vec![0x01u8, 0x23], vec![0x01u8, 0x23]),
|
||||
(vec![0x81u8, 0x23], vec![0x81u8, 0x23]),
|
||||
@@ -347,50 +297,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trie_root() {
|
||||
let v = vec![
|
||||
|
||||
("0000000000000000000000000000000000000000000000000000000000000045".from_hex().unwrap(),
|
||||
"22b224a1420a802ab51d326e29fa98e34c4f24ea".from_hex().unwrap()),
|
||||
|
||||
("0000000000000000000000000000000000000000000000000000000000000046".from_hex().unwrap(),
|
||||
"67706c2076330000000000000000000000000000000000000000000000000000".from_hex().unwrap()),
|
||||
|
||||
("000000000000000000000000697c7b8c961b56f675d570498424ac8de1a918f6".from_hex().unwrap(),
|
||||
"6f6f6f6820736f2067726561742c207265616c6c6c793f000000000000000000".from_hex().unwrap()),
|
||||
|
||||
("0000000000000000000000007ef9e639e2733cb34e4dfc576d4b23f72db776b2".from_hex().unwrap(),
|
||||
"4655474156000000000000000000000000000000000000000000000000000000".from_hex().unwrap()),
|
||||
|
||||
("000000000000000000000000ec4f34c97e43fbb2816cfd95e388353c7181dab1".from_hex().unwrap(),
|
||||
"4e616d6552656700000000000000000000000000000000000000000000000000".from_hex().unwrap()),
|
||||
|
||||
("4655474156000000000000000000000000000000000000000000000000000000".from_hex().unwrap(),
|
||||
"7ef9e639e2733cb34e4dfc576d4b23f72db776b2".from_hex().unwrap()),
|
||||
|
||||
("4e616d6552656700000000000000000000000000000000000000000000000000".from_hex().unwrap(),
|
||||
"ec4f34c97e43fbb2816cfd95e388353c7181dab1".from_hex().unwrap()),
|
||||
|
||||
("6f6f6f6820736f2067726561742c207265616c6c6c793f000000000000000000".from_hex().unwrap(),
|
||||
"697c7b8c961b56f675d570498424ac8de1a918f6".from_hex().unwrap())
|
||||
|
||||
];
|
||||
|
||||
assert_eq!(trie_root(v), H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap());
|
||||
fn test_triehash_json() {
|
||||
execute_tests_from_directory::<trie::TriehashTest, _>("json-tests/json/trie/*.json", &mut | file, input, output | {
|
||||
println!("file: {}, output: {:?}", file, output);
|
||||
assert_eq!(trie_root(input), H256::from_slice(&output));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_triehash_json_trietest_json() {
|
||||
//let data = include_bytes!("../tests/TrieTests/trietest.json");
|
||||
|
||||
//let s = String::from_bytes(data).unwrap();
|
||||
//let json = Json::from_str(&s).unwrap();
|
||||
//let obj = json.as_object().unwrap();
|
||||
|
||||
//for (key, value) in obj.iter() {
|
||||
// println!("running test: {}", key);
|
||||
//}
|
||||
//assert!(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user