From 7d309b2309e7d0c3ff298d8bfa85e8218de5c75e Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 6 Jul 2018 18:11:53 +0200 Subject: [PATCH] more generic: hash256rlp and hash256aux takes a Hasher --- triehash/src/lib.rs | 72 ++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/triehash/src/lib.rs b/triehash/src/lib.rs index 48b00c8..f0c2dda 100644 --- a/triehash/src/lib.rs +++ b/triehash/src/lib.rs @@ -28,8 +28,6 @@ extern crate rlp; use std::collections::BTreeMap; use std::cmp; use elastic_array::{ElasticArray4, ElasticArray8}; -// use ethereum_types::H256; -use hash::keccak; use hashdb::Hasher; use rlp::RlpStream; @@ -49,13 +47,14 @@ fn shared_prefix_len(first: &[T], second: &[T]) -> usize { /// fn main() { /// let v = &["doe", "reindeer"]; /// let root = "e766d5d51b89dc39d981b41bda63248d7abce4f0225eefd023792a540bcffee3"; -/// assert_eq!(ordered_trie_root::<_, _, KeccakHasher>(v), root.into()); +/// assert_eq!(ordered_trie_root::(v), root.into()); /// } /// ``` -pub fn ordered_trie_root(input: I) -> H::Out // TODO: return value here +pub fn ordered_trie_root(input: I) -> H::Out where I: IntoIterator, A: AsRef<[u8]>, H: Hasher, + ::Out: cmp::Ord + rlp::Encodable, { let gen_input: Vec<_> = input // first put elements into btree to sort them by nibbles (key'd by index) @@ -69,8 +68,7 @@ pub fn ordered_trie_root(input: I) -> H::Out // TODO: return value here .map(|(k, v)| (as_nibbles(&k), v) ) .collect(); - // gen_trie_root::(&gen_input) // TODO: should be able to infer this - gen_trie_root::<_, _, H>(&gen_input) // TODO: should be able to infer this + gen_trie_root::(&gen_input) } /// Generates a trie root hash for a vector of key-value tuples @@ -89,14 +87,15 @@ pub fn ordered_trie_root(input: I) -> H::Out // TODO: return value here /// ]; /// /// let root = "8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3"; -/// assert_eq!(trie_root::<_, _, _, KeccakHasher>(v), root.into()); +/// assert_eq!(trie_root::(v), root.into()); /// } /// ``` -pub fn trie_root(input: I) -> H::Out +pub fn trie_root(input: I) -> H::Out where I: IntoIterator, A: AsRef<[u8]> + Ord, B: AsRef<[u8]>, H: Hasher, + ::Out: cmp::Ord + rlp::Encodable, { let gen_input: Vec<_> = input // first put elements into btree to sort them and to remove duplicates @@ -107,8 +106,7 @@ pub fn trie_root(input: I) -> H::Out .map(|(k, v)| (as_nibbles(k.as_ref()), v) ) .collect(); - // gen_trie_root::(&gen_input) - gen_trie_root::<_, _, H>(&gen_input) + gen_trie_root::(&gen_input) } /// Generates a key-hashed (secure) trie root hash for a vector of key-value tuples. @@ -127,42 +125,38 @@ pub fn trie_root(input: I) -> H::Out /// ]; /// /// let root = "d4cd937e4a4368d7931a9cf51686b7e10abb3dce38a39000fd7902a092b64585"; -/// assert_eq!(sec_trie_root::<_, _, _, KeccakHasher>(v), root.into()); +/// assert_eq!(sec_trie_root::(v), root.into()); /// } /// ``` -pub fn sec_trie_root(input: I) -> H::Out +pub fn sec_trie_root(input: I) -> H::Out where I: IntoIterator, A: AsRef<[u8]>, B: AsRef<[u8]>, H: Hasher, - // ::Out: std::cmp::Ord, + ::Out: cmp::Ord + rlp::Encodable, { let gen_input: Vec<_> = input // first put elements into btree to sort them and to remove duplicates .into_iter() - .map(|(k, v)| (keccak(k), v)) // TODO: here - // .map(|(k, v)| (H::hash(&k), v)) + .map(|(k, v)| (H::hash(&k.as_ref()), v)) .collect::>() // then move them to a vector .into_iter() - .map(|(k, v)| (as_nibbles(&k), v) ) // maybe enough to .as_ref() here + .map(|(k, v)| (as_nibbles(&k.as_ref()), v) ) .collect(); - // gen_trie_root::(&gen_input) - gen_trie_root::<_, _, H>(&gen_input) + gen_trie_root::(&gen_input) } -// fn gen_trie_root, B: AsRef<[u8]>>(input: &[(A, B)]) -> H256 { // TODO: here -fn gen_trie_root(input: &[(A, B)]) -> H::Out +fn gen_trie_root(input: &[(A, B)]) -> H::Out where A: AsRef<[u8]>, B: AsRef<[u8]>, H: Hasher, + ::Out: cmp::Ord + rlp::Encodable, { - let mut stream = RlpStream::new(); // TODO: here - hash256rlp(input, 0, &mut stream); // TODO: here - // keccak(stream.out()) // TODO: here - // ::hash(&stream.out()) + let mut stream = RlpStream::new(); + hash256rlp::(input, 0, &mut stream); H::hash(&stream.out()) } @@ -221,7 +215,13 @@ fn as_nibbles(bytes: &[u8]) -> ElasticArray8 { res } -fn hash256rlp, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) { +fn hash256rlp(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) + where + A: AsRef<[u8]>, + B: AsRef<[u8]>, + H: Hasher, + ::Out: rlp::Encodable, +{ let inlen = input.len(); // in case of empty slice, just append empty data @@ -258,7 +258,7 @@ fn hash256rlp, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, if shared_prefix > pre_len { stream.begin_list(2); stream.append(&&*hex_prefix_encode(&key[pre_len..shared_prefix], false)); - hash256aux(input, shared_prefix, stream); + hash256aux::(input, shared_prefix, stream); return; } @@ -286,7 +286,7 @@ fn hash256rlp, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, // append their suffixes match len { 0 => { stream.append_empty_data(); }, - _ => hash256aux(&input[begin..(begin + len)], pre_len + 1, stream) + _ => hash256aux::(&input[begin..(begin + len)], pre_len + 1, stream) } begin += len; } @@ -298,13 +298,19 @@ fn hash256rlp, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, }; } -fn hash256aux, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) { +fn hash256aux(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) + where + A: AsRef<[u8]>, + B: AsRef<[u8]>, + H: Hasher, + ::Out: rlp::Encodable, +{ let mut s = RlpStream::new(); - hash256rlp(input, pre_len, &mut s); + hash256rlp::(input, pre_len, &mut s); let out = s.out(); match out.len() { 0...31 => stream.append_raw(&out, 1), - _ => stream.append(&keccak(out)) // TODO: here + _ => stream.append(&H::hash(&out)) }; } @@ -360,19 +366,19 @@ mod tests { #[test] fn simple_test() { - assert_eq!(trie_root::<_, _, _, KeccakHasher>(vec![ + assert_eq!(trie_root::(vec![ (b"A", b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" as &[u8]) ]), "d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab".into()); } #[test] fn test_triehash_out_of_order() { - assert!(trie_root::<_, _, _, KeccakHasher>(vec![ + assert!(trie_root::(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), ]) == - trie_root::<_, _, _, KeccakHasher>(vec![ + trie_root::(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), // last two tuples are swapped (vec![0x81u8, 0x23], vec![0x81u8, 0x23]),