fixed encoding of bytes in rlp, fixed encoding of long lists, triehash + basic tests... more tests todo

This commit is contained in:
debris 2015-11-30 00:28:03 +01:00
parent d23b8d9a74
commit 0c9ef317b2
3 changed files with 161 additions and 28 deletions

View File

@ -456,9 +456,8 @@ impl RlpStream {
}
/// Apends value to the end of stream, chainable.
pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream
where E: Encodable
{
pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable + fmt::Debug {
//println!("append: {:?}", object);
// encode given value and add it at the end of the stream
object.encode(&mut self.encoder);
@ -471,6 +470,7 @@ impl RlpStream {
/// Declare appending the list of given size, chainable.
pub fn append_list<'a>(&'a mut self, len: usize) -> &'a mut RlpStream {
//println!("append_list: {}", len);
// push new list
let position = self.encoder.bytes.len();
match len {
@ -488,6 +488,7 @@ impl RlpStream {
/// Appends raw (pre-serialised) RLP data. Use with caution. Chainable.
pub fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream {
//println!("append_raw: {:?} len: {}, count: {}", bytes, bytes.len(), item_count);
// push raw items
self.encoder.bytes.extend(bytes);
@ -623,7 +624,7 @@ impl BasicEncoder {
match len {
0...55 => res.push(0xc0u8 + len as u8),
_ => {
res.push(0x7fu8 + len.to_bytes_len() as u8);
res.push(0xf7u8 + len.to_bytes_len() as u8);
res.extend(len.to_bytes());
}
};
@ -658,8 +659,7 @@ impl Encoder for BasicEncoder {
}
}
fn emit_list<F>(&mut self, f: F) -> ()
where F: FnOnce(&mut Self) -> ()
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ()
{
// get len before inserting a list
let before_len = self.bytes.len();
@ -891,6 +891,33 @@ mod tests {
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().unwrap();
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().unwrap();
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 {

View File

@ -139,6 +139,20 @@ impl NibblePair {
}
}
fn shared_nibble_prefix_len(vec: &[NibblePair]) -> usize {
if vec.len() == 0 {
return 0;
}
vec.iter()
// skip first element
.skip(1)
// get minimum number of shared nibbles between first and each successive
.fold(vec[0].nibble.len(), | acc, pair | {
cmp::min(vec[0].nibble.shared_prefix_len(&pair.nibble), acc)
})
}
pub fn ordered_trie_root(data: Vec<Vec<u8>>) -> H256 {
let vec: Vec<NibblePair> = data
// first put elements into btree to sort them by nibbles
@ -167,7 +181,6 @@ pub fn hash256(vec: &[NibblePair]) -> H256 {
}
};
println!("out: {:?}", out);
out.sha3()
}
@ -182,13 +195,7 @@ fn hash256rlp(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) {
stream.append(&vec[0].data);
},
_ => {
let shared_prefix = vec.iter()
// skip first element
.skip(1)
// get minimum number of shared nibbles between first and each successive
.fold(usize::max_value(), | acc, pair | {
cmp::min(vec[0].nibble.shared_prefix_len(&pair.nibble), acc)
});
let shared_prefix = shared_nibble_prefix_len(vec);
match shared_prefix > pre_len {
true => {
@ -199,12 +206,12 @@ fn hash256rlp(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) {
false => {
stream.append_list(17);
// every nibble is longer then previous one
let iter = vec.iter()
// move to first element with len different then pre_len
.take_while(| pair | { pair.nibble.len() == pre_len });
let mut begin = iter.count();
// if first nibble len is equal to pre_len
// move forward
let mut begin = match pre_len == vec[0].nibble.len() {
true => 1,
false => 0
};
for i in 0..16 {
// cout how many successive elements have same next nibble
@ -214,14 +221,14 @@ fn hash256rlp(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) {
match len {
0 => { stream.append(&""); },
_ => hash256aux(&vec[begin..begin + len], pre_len + 1, stream)
_ => hash256aux(&vec[begin..(begin + len)], pre_len + 1, stream)
}
begin += len;
}
match pre_len == vec[0].nibble.len() {
true => stream.append(&vec[0].data),
false => stream.append(&"")
true => { stream.append(&vec[0].data); } ,
false => { stream.append(&""); }
};
}
}
@ -239,6 +246,39 @@ fn hash256aux(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) {
};
}
#[test]
fn test_shared_nibble_len() {
let len = shared_nibble_prefix_len(&vec![
NibblePair::new(vec![0, 1, 2, 3, 4, 5, 6], vec![]),
NibblePair::new(vec![0, 1, 2, 3, 4, 5, 6], vec![]),
]);
assert_eq!(len , 7);
}
#[test]
fn test_shared_nibble_len2() {
let len = shared_nibble_prefix_len(&vec![
NibblePair::new(vec![0, 1, 2, 3, 4, 5, 6], vec![]),
NibblePair::new(vec![0, 1, 2, 3, 4, 5, 6], vec![]),
NibblePair::new(vec![4, 1, 2, 3, 4, 5, 6], vec![])
]);
assert_eq!(len , 0);
}
#[test]
fn test_shared_nibble_len3() {
let len = shared_nibble_prefix_len(&vec![
NibblePair::new(vec![0, 1, 2, 3, 4, 5, 6], vec![]),
NibblePair::new(vec![0, 1, 2, 3, 4, 5, 6], vec![]),
NibblePair::new(vec![0, 1, 2, 4, 4, 5, 6], vec![])
]);
assert_eq!(len , 3);
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
@ -246,6 +286,8 @@ mod tests {
use hash::*;
use triehash::*;
#[test]
fn empty_trie_root() {
assert_eq!(hash256(&vec![]), H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap());
@ -262,9 +304,60 @@ mod tests {
assert_eq!(hash256(&v), H256::from_str("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab").unwrap());
}
#[test]
fn foo_trie_item() {
let v = vec![
NibblePair::new_raw(From::from("foo"),
From::from("bar")),
NibblePair::new_raw(From::from("food"),
From::from("bass"))
];
assert_eq!(hash256(&v), H256::from_str("17beaa1648bafa633cda809c90c04af50fc8aed3cb40d16efbddee6fdf63c4c3").unwrap());
}
#[test]
fn dogs_trie_item() {
let v = vec![
NibblePair::new_raw(From::from("doe"),
From::from("reindeer")),
NibblePair::new_raw(From::from("dog"),
From::from("puppy")),
NibblePair::new_raw(From::from("dogglesworth"),
From::from("cat")),
];
assert_eq!(hash256(&v), H256::from_str("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3").unwrap());
}
#[test]
fn puppy_trie_items() {
let v = vec![
NibblePair::new_raw(From::from("do"),
From::from("verb")),
NibblePair::new_raw(From::from("dog"),
From::from("puppy")),
NibblePair::new_raw(From::from("doge"),
From::from("coin")),
NibblePair::new_raw(From::from("horse"),
From::from("stallion")),
];
assert_eq!(hash256(&v), H256::from_str("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84").unwrap());
}
#[test]
fn test_trie_root() {
let _v = vec![
let v = vec![
NibblePair::new_raw("0000000000000000000000000000000000000000000000000000000000000045".from_hex().unwrap(),
"22b224a1420a802ab51d326e29fa98e34c4f24ea".from_hex().unwrap()),
@ -290,10 +383,9 @@ mod tests {
"697c7b8c961b56f675d570498424ac8de1a918f6".from_hex().unwrap())
];
let _root = H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap();
let root = H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap();
//let res = hash256(&v);
//println!("{:?}", res);
//assert_eq!(res, root);
let res = hash256(&v);
assert_eq!(res, root);
}
}

View File

@ -64,8 +64,22 @@ mod test {
#[test]
fn test_shared_prefix() {
let a = vec![1,2,3,4,5,6];
let b = vec![4,2,3,4,5,6];
assert_eq!(a.shared_prefix_len(&b), 0);
}
#[test]
fn test_shared_prefix2() {
let a = vec![1,2,3,3,5];
let b = vec![1,2,3];
assert_eq!(a.shared_prefix_len(&b), 3);
}
#[test]
fn test_shared_prefix3() {
let a = vec![1,2,3,4,5,6];
let b = vec![1,2,3,4,5,6];
assert_eq!(a.shared_prefix_len(&b), 6);
}
}