From 407bf5e06d15f00c00bfad0b5dce2e4bb9e6eec1 Mon Sep 17 00:00:00 2001 From: Kirk Baird Date: Thu, 24 Jan 2019 15:47:28 +1100 Subject: [PATCH] Minor updates to TreeHash --- eth2/utils/ssz/src/impl_tree_hash.rs | 80 ++++------------------------ eth2/utils/ssz/src/lib.rs | 2 +- eth2/utils/ssz/src/tree_hash.rs | 19 ++++--- 3 files changed, 22 insertions(+), 79 deletions(-) diff --git a/eth2/utils/ssz/src/impl_tree_hash.rs b/eth2/utils/ssz/src/impl_tree_hash.rs index 9d86da2dd..e9656e597 100644 --- a/eth2/utils/ssz/src/impl_tree_hash.rs +++ b/eth2/utils/ssz/src/impl_tree_hash.rs @@ -1,123 +1,63 @@ -extern crate hashing; - -use self::hashing::canonical_hash; use super::ethereum_types::{Address, H256}; use super::{merkle_hash, ssz_encode, TreeHash}; -use std::cmp::Ord; -use std::collections::HashMap; -use std::hash::Hash; impl TreeHash for u8 { - fn tree_hash(&self) -> Vec { + fn hash_tree_root(&self) -> Vec { ssz_encode(self) } } impl TreeHash for u16 { - fn tree_hash(&self) -> Vec { + fn hash_tree_root(&self) -> Vec { ssz_encode(self) } } impl TreeHash for u32 { - fn tree_hash(&self) -> Vec { + fn hash_tree_root(&self) -> Vec { ssz_encode(self) } } impl TreeHash for u64 { - fn tree_hash(&self) -> Vec { + fn hash_tree_root(&self) -> Vec { ssz_encode(self) } } impl TreeHash for Address { - fn tree_hash(&self) -> Vec { + fn hash_tree_root(&self) -> Vec { ssz_encode(self) } } impl TreeHash for H256 { - fn tree_hash(&self) -> Vec { + fn hash_tree_root(&self) -> Vec { ssz_encode(self) } } -impl TreeHash for [u8] { - fn tree_hash(&self) -> Vec { - hash(&self) - } -} - impl TreeHash for Vec where T: TreeHash, { - /// Returns the merkle_hash of a list of tree_hash values created + /// Returns the merkle_hash of a list of hash_tree_root values created /// from the given list. /// Note: A byte vector, Vec, must be converted to a slice (as_slice()) /// to be handled properly (i.e. hashed) as byte array. - fn tree_hash(&self) -> Vec { - let mut tree_hashes = self.iter().map(|x| x.tree_hash()).collect(); + fn hash_tree_root(&self) -> Vec { + let mut tree_hashes = self.iter().map(|x| x.hash_tree_root()).collect(); merkle_hash(&mut tree_hashes) } } -impl TreeHash for HashMap -where - K: Eq, - K: Hash, - K: Ord, - V: TreeHash, -{ - /// Appends the tree_hash for each value of 'self, sorted by key, - /// into a byte array and returns the hash of said byte array - fn tree_hash(&self) -> Vec { - let mut items: Vec<_> = self.iter().collect(); - items.sort_by(|a, b| a.0.cmp(b.0)); - let mut result = Vec::new(); - for item in items { - result.append(&mut item.1.tree_hash()); - } - - hash(&result) - } -} - -fn hash(data: &[u8]) -> Vec { - canonical_hash(data) -} - #[cfg(test)] mod tests { use super::*; #[test] fn test_impl_tree_hash_vec() { - let result = vec![1u32, 2, 3, 4, 5, 6, 7].tree_hash(); + let result = vec![1u32, 2, 3, 4, 5, 6, 7].hash_tree_root(); assert_eq!(result.len(), 32); } - - #[test] - fn test_impl_tree_hash_hashmap() { - let mut map = HashMap::new(); - map.insert("c", 3); - map.insert("b", 2); - map.insert("g", 7); - map.insert("d", 6); - map.insert("e", 4); - map.insert("a", 1u32); - map.insert("f", 5); - let result = map.tree_hash(); - - // TODO: create tests that tie-out to an offical result - assert_eq!( - result, - [ - 232, 63, 235, 91, 115, 69, 159, 54, 95, 239, 147, 30, 179, 96, 232, 210, 225, 31, - 12, 95, 149, 104, 134, 158, 45, 51, 20, 101, 202, 164, 200, 163 - ] - ); - } - } diff --git a/eth2/utils/ssz/src/lib.rs b/eth2/utils/ssz/src/lib.rs index bea15c054..206040c2d 100644 --- a/eth2/utils/ssz/src/lib.rs +++ b/eth2/utils/ssz/src/lib.rs @@ -20,7 +20,7 @@ mod impl_tree_hash; pub use crate::decode::{decode_ssz, decode_ssz_list, Decodable, DecodeError}; pub use crate::encode::{Encodable, SszStream}; -pub use crate::tree_hash::{merkle_hash, TreeHash}; +pub use crate::tree_hash::{hash, merkle_hash, TreeHash}; pub const LENGTH_BYTES: usize = 4; pub const MAX_LIST_SIZE: usize = 1 << (4 * 8); diff --git a/eth2/utils/ssz/src/tree_hash.rs b/eth2/utils/ssz/src/tree_hash.rs index 69929b0ab..f8abb451b 100644 --- a/eth2/utils/ssz/src/tree_hash.rs +++ b/eth2/utils/ssz/src/tree_hash.rs @@ -1,4 +1,4 @@ - +use hashing::canonical_hash; const SSZ_CHUNK_SIZE: usize = 128; const HASHSIZE: usize = 32; @@ -14,9 +14,7 @@ pub fn merkle_hash(list: &mut Vec>) -> Vec { let (chunk_size, mut data) = list_to_blob(list); // get data_len as bytes. It will hashed will the merkle root - let dlen = list.len() as u64; - let data_len_bytes = &mut dlen.tree_hash(); - data_len_bytes.resize(32, 0); + let datalen = list.len().to_le_bytes(); // merklize let mut mhash = hash_level(&mut data, chunk_size); @@ -24,8 +22,8 @@ pub fn merkle_hash(list: &mut Vec>) -> Vec { mhash = hash_level(&mut mhash, HASHSIZE); } - mhash.append(data_len_bytes); - mhash.as_slice().tree_hash() + mhash.append(&mut datalen.to_vec()); + hash(mhash.as_slice()) } /// Takes a flat vector of bytes. It then hashes 'chunk_size * 2' slices into @@ -38,9 +36,10 @@ fn hash_level(data: &mut Vec, chunk_size: usize) -> Vec { // SSZ_CHUNK_SIZE vector let mut c = two_chunks.to_vec(); c.append(&mut vec![0; SSZ_CHUNK_SIZE]); - result.append(&mut c.as_slice().tree_hash()); + result.append(&mut hash(c.as_slice())); } else { - result.append(&mut two_chunks.tree_hash()); + // Hash two chuncks together + result.append(&mut hash(two_chunks)); } } @@ -73,6 +72,10 @@ fn list_to_blob(list: &mut Vec>) -> (usize, Vec) { (chunk_size, data) } +pub fn hash(data: &[u8]) -> Vec { + canonical_hash(data) +} + #[cfg(test)] mod tests { use super::*;