Merge branch 'master' of github.com:gavofyork/ethcore-util into network

Conflicts:
	src/triehash.rs
This commit is contained in:
arkpar
2015-12-03 15:15:17 +01:00
38 changed files with 2027 additions and 481 deletions

View File

@@ -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.
///

View File

@@ -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,

View File

@@ -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() }

View File

@@ -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.

View File

@@ -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);
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}