fixed encoding of bytes in rlp, fixed encoding of long lists, triehash + basic tests... more tests todo
This commit is contained in:
parent
d23b8d9a74
commit
0c9ef317b2
39
src/rlp.rs
39
src/rlp.rs
@ -456,9 +456,8 @@ impl RlpStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Apends value to the end of stream, chainable.
|
/// Apends value to the end of stream, chainable.
|
||||||
pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream
|
pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable + fmt::Debug {
|
||||||
where E: Encodable
|
//println!("append: {:?}", object);
|
||||||
{
|
|
||||||
// encode given value and add it at the end of the stream
|
// encode given value and add it at the end of the stream
|
||||||
object.encode(&mut self.encoder);
|
object.encode(&mut self.encoder);
|
||||||
|
|
||||||
@ -471,6 +470,7 @@ impl RlpStream {
|
|||||||
|
|
||||||
/// Declare appending the list of given size, chainable.
|
/// Declare appending the list of given size, chainable.
|
||||||
pub fn append_list<'a>(&'a mut self, len: usize) -> &'a mut RlpStream {
|
pub fn append_list<'a>(&'a mut self, len: usize) -> &'a mut RlpStream {
|
||||||
|
//println!("append_list: {}", len);
|
||||||
// push new list
|
// push new list
|
||||||
let position = self.encoder.bytes.len();
|
let position = self.encoder.bytes.len();
|
||||||
match len {
|
match len {
|
||||||
@ -488,6 +488,7 @@ impl RlpStream {
|
|||||||
|
|
||||||
/// Appends raw (pre-serialised) RLP data. Use with caution. Chainable.
|
/// 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 {
|
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
|
// push raw items
|
||||||
self.encoder.bytes.extend(bytes);
|
self.encoder.bytes.extend(bytes);
|
||||||
|
|
||||||
@ -623,7 +624,7 @@ impl BasicEncoder {
|
|||||||
match len {
|
match len {
|
||||||
0...55 => res.push(0xc0u8 + len as u8),
|
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());
|
res.extend(len.to_bytes());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -658,8 +659,7 @@ impl Encoder for BasicEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_list<F>(&mut self, f: F) -> ()
|
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ()
|
||||||
where F: FnOnce(&mut Self) -> ()
|
|
||||||
{
|
{
|
||||||
// get len before inserting a list
|
// get len before inserting a list
|
||||||
let before_len = self.bytes.len();
|
let before_len = self.bytes.len();
|
||||||
@ -891,6 +891,33 @@ mod tests {
|
|||||||
assert_eq!(out, vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0]);
|
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;
|
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 {
|
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: rlp::Decodable + fmt::Debug + cmp::Eq {
|
||||||
|
136
src/triehash.rs
136
src/triehash.rs
@ -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 {
|
pub fn ordered_trie_root(data: Vec<Vec<u8>>) -> H256 {
|
||||||
let vec: Vec<NibblePair> = data
|
let vec: Vec<NibblePair> = data
|
||||||
// first put elements into btree to sort them by nibbles
|
// 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()
|
out.sha3()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,13 +195,7 @@ fn hash256rlp(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) {
|
|||||||
stream.append(&vec[0].data);
|
stream.append(&vec[0].data);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let shared_prefix = vec.iter()
|
let shared_prefix = shared_nibble_prefix_len(vec);
|
||||||
// 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)
|
|
||||||
});
|
|
||||||
|
|
||||||
match shared_prefix > pre_len {
|
match shared_prefix > pre_len {
|
||||||
true => {
|
true => {
|
||||||
@ -199,12 +206,12 @@ fn hash256rlp(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) {
|
|||||||
false => {
|
false => {
|
||||||
stream.append_list(17);
|
stream.append_list(17);
|
||||||
|
|
||||||
// every nibble is longer then previous one
|
// if first nibble len is equal to pre_len
|
||||||
let iter = vec.iter()
|
// move forward
|
||||||
// move to first element with len different then pre_len
|
let mut begin = match pre_len == vec[0].nibble.len() {
|
||||||
.take_while(| pair | { pair.nibble.len() == pre_len });
|
true => 1,
|
||||||
|
false => 0
|
||||||
let mut begin = iter.count();
|
};
|
||||||
|
|
||||||
for i in 0..16 {
|
for i in 0..16 {
|
||||||
// cout how many successive elements have same next nibble
|
// 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 {
|
match len {
|
||||||
0 => { stream.append(&""); },
|
0 => { stream.append(&""); },
|
||||||
_ => hash256aux(&vec[begin..begin + len], pre_len + 1, stream)
|
_ => hash256aux(&vec[begin..(begin + len)], pre_len + 1, stream)
|
||||||
}
|
}
|
||||||
begin += len;
|
begin += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
match pre_len == vec[0].nibble.len() {
|
match pre_len == vec[0].nibble.len() {
|
||||||
true => stream.append(&vec[0].data),
|
true => { stream.append(&vec[0].data); } ,
|
||||||
false => stream.append(&"")
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -246,6 +286,8 @@ mod tests {
|
|||||||
use hash::*;
|
use hash::*;
|
||||||
use triehash::*;
|
use triehash::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_trie_root() {
|
fn empty_trie_root() {
|
||||||
assert_eq!(hash256(&vec![]), H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap());
|
assert_eq!(hash256(&vec![]), H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap());
|
||||||
@ -262,9 +304,60 @@ mod tests {
|
|||||||
assert_eq!(hash256(&v), H256::from_str("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab").unwrap());
|
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]
|
#[test]
|
||||||
fn test_trie_root() {
|
fn test_trie_root() {
|
||||||
let _v = vec![
|
let v = vec![
|
||||||
NibblePair::new_raw("0000000000000000000000000000000000000000000000000000000000000045".from_hex().unwrap(),
|
NibblePair::new_raw("0000000000000000000000000000000000000000000000000000000000000045".from_hex().unwrap(),
|
||||||
"22b224a1420a802ab51d326e29fa98e34c4f24ea".from_hex().unwrap()),
|
"22b224a1420a802ab51d326e29fa98e34c4f24ea".from_hex().unwrap()),
|
||||||
|
|
||||||
@ -290,10 +383,9 @@ mod tests {
|
|||||||
"697c7b8c961b56f675d570498424ac8de1a918f6".from_hex().unwrap())
|
"697c7b8c961b56f675d570498424ac8de1a918f6".from_hex().unwrap())
|
||||||
];
|
];
|
||||||
|
|
||||||
let _root = H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap();
|
let root = H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap();
|
||||||
|
|
||||||
//let res = hash256(&v);
|
let res = hash256(&v);
|
||||||
//println!("{:?}", res);
|
assert_eq!(res, root);
|
||||||
//assert_eq!(res, root);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,22 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_shared_prefix() {
|
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 a = vec![1,2,3,3,5];
|
||||||
let b = vec![1,2,3];
|
let b = vec![1,2,3];
|
||||||
assert_eq!(a.shared_prefix_len(&b), 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user