diff --git a/eth2/utils/ssz/src/impl_tree_hash.rs b/eth2/utils/ssz/src/impl_tree_hash.rs index 9463283cb..7249b7f73 100644 --- a/eth2/utils/ssz/src/impl_tree_hash.rs +++ b/eth2/utils/ssz/src/impl_tree_hash.rs @@ -1,5 +1,6 @@ use super::ethereum_types::{Address, H256}; use super::{hash, merkle_hash, ssz_encode, TreeHash}; +use std::collections::HashMap; impl TreeHash for u8 { fn hash_tree_root(&self) -> Vec { @@ -66,13 +67,57 @@ where } } +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) + } +} + #[cfg(test)] mod tests { use super::*; #[test] fn test_impl_tree_hash_vec() { - let result = vec![1u32, 2, 3, 4, 5, 6, 7].hash_tree_root(); + let result = vec![1u32, 2, 3, 4, 5, 6, 7].tree_hash(); 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, + [ + 130, 215, 165, 255, 224, 6, 144, 225, 14, 139, 67, 238, 205, 240, 20, 173, 53, 0, + 105, 62, 49, 174, 244, 160, 114, 92, 232, 11, 102, 200, 112, 24 + ] + ); + } + } diff --git a/eth2/utils/ssz/src/tree_hash.rs b/eth2/utils/ssz/src/tree_hash.rs index 913b961ab..6efe41a40 100644 --- a/eth2/utils/ssz/src/tree_hash.rs +++ b/eth2/utils/ssz/src/tree_hash.rs @@ -90,6 +90,5 @@ mod tests { //note: should test againt a known test hash value assert_eq!(HASHSIZE, result.len()); - println!("merkle_hash: {:?}", result); } }