From 8a1bde3e2f9d64f06000208e1940082007c241de Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 16 Apr 2019 10:47:58 +1000 Subject: [PATCH] Update naming for tree_hash fns/structs/traits --- eth2/utils/tree_hash/src/cached_tree_hash.rs | 8 +-- .../src/cached_tree_hash/btree_overlay.rs | 2 +- .../tree_hash/src/cached_tree_hash/impls.rs | 6 +- .../src/cached_tree_hash/impls/vec.rs | 8 +-- eth2/utils/tree_hash/src/lib.rs | 4 +- eth2/utils/tree_hash/tests/tests.rs | 72 ++++++++++--------- eth2/utils/tree_hash_derive/src/lib.rs | 70 +++++++++++++----- eth2/utils/tree_hash_derive/tests/tests.rs | 66 ++++++++++++++++- 8 files changed, 166 insertions(+), 70 deletions(-) diff --git a/eth2/utils/tree_hash/src/cached_tree_hash.rs b/eth2/utils/tree_hash/src/cached_tree_hash.rs index 43c0ba2fe..e093b2dd7 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash.rs @@ -32,11 +32,11 @@ pub trait CachedTreeHash: CachedTreeHashSubTree + Sized { } pub trait CachedTreeHashSubTree: TreeHash { - fn btree_overlay(&self, chunk_offset: usize) -> Result; + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result; - fn new_cache(&self) -> Result; + fn new_tree_hash_cache(&self) -> Result; - fn update_cache( + fn update_tree_hash_cache( &self, other: &Item, cache: &mut TreeHashCache, @@ -136,7 +136,7 @@ impl TreeHashCache { where T: CachedTreeHashSubTree, { - item.new_cache() + item.new_tree_hash_cache() } pub fn from_elems(cache: Vec, chunk_modified: Vec) -> Self { diff --git a/eth2/utils/tree_hash/src/cached_tree_hash/btree_overlay.rs b/eth2/utils/tree_hash/src/cached_tree_hash/btree_overlay.rs index 1e188da60..e8c04a91e 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash/btree_overlay.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash/btree_overlay.rs @@ -14,7 +14,7 @@ impl BTreeOverlay { where T: CachedTreeHashSubTree, { - item.btree_overlay(initial_offset) + item.tree_hash_cache_overlay(initial_offset) } pub fn from_lengths(offset: usize, mut lengths: Vec) -> Result { diff --git a/eth2/utils/tree_hash/src/cached_tree_hash/impls.rs b/eth2/utils/tree_hash/src/cached_tree_hash/impls.rs index 190deaf27..62d013881 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash/impls.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash/impls.rs @@ -5,18 +5,18 @@ use ssz::ssz_encode; mod vec; impl CachedTreeHashSubTree for u64 { - fn new_cache(&self) -> Result { + fn new_tree_hash_cache(&self) -> Result { Ok(TreeHashCache::from_bytes( merkleize(ssz_encode(self)), false, )?) } - fn btree_overlay(&self, chunk_offset: usize) -> Result { + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result { BTreeOverlay::from_lengths(chunk_offset, vec![1]) } - fn update_cache( + fn update_tree_hash_cache( &self, other: &Self, cache: &mut TreeHashCache, diff --git a/eth2/utils/tree_hash/src/cached_tree_hash/impls/vec.rs b/eth2/utils/tree_hash/src/cached_tree_hash/impls/vec.rs index bc86e6054..6c0970cef 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash/impls/vec.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash/impls/vec.rs @@ -4,7 +4,7 @@ impl CachedTreeHashSubTree> for Vec where T: CachedTreeHashSubTree + TreeHash, { - fn new_cache(&self) -> Result { + fn new_tree_hash_cache(&self) -> Result { match T::tree_hash_type() { TreeHashType::Basic => { TreeHashCache::from_bytes(merkleize(get_packed_leaves(self)?), false) @@ -20,7 +20,7 @@ where } } - fn btree_overlay(&self, chunk_offset: usize) -> Result { + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result { let lengths = match T::tree_hash_type() { TreeHashType::Basic => vec![1; self.len() / T::tree_hash_packing_factor()], TreeHashType::Composite | TreeHashType::List => { @@ -37,7 +37,7 @@ where BTreeOverlay::from_lengths(chunk_offset, lengths) } - fn update_cache( + fn update_tree_hash_cache( &self, other: &Vec, cache: &mut TreeHashCache, @@ -104,7 +104,7 @@ where match (other.get(i), self.get(i)) { // The item existed in the previous list and exsits in the current list. (Some(old), Some(new)) => { - new.update_cache(old, cache, start_chunk)?; + new.update_tree_hash_cache(old, cache, start_chunk)?; } // The item existed in the previous list but does not exist in this list. // diff --git a/eth2/utils/tree_hash/src/lib.rs b/eth2/utils/tree_hash/src/lib.rs index 0f0fb60f4..04eb6d80f 100644 --- a/eth2/utils/tree_hash/src/lib.rs +++ b/eth2/utils/tree_hash/src/lib.rs @@ -5,8 +5,8 @@ pub const BYTES_PER_CHUNK: usize = 32; pub const HASHSIZE: usize = 32; pub const MERKLE_HASH_CHUNCK: usize = 2 * BYTES_PER_CHUNK; -pub use cached_tree_hash::CachedTreeHashSubTree; -pub use standard_tree_hash::TreeHash; +pub use cached_tree_hash::{BTreeOverlay, CachedTreeHashSubTree, Error, TreeHashCache}; +pub use standard_tree_hash::{efficient_merkleize, TreeHash}; #[derive(Debug, PartialEq, Clone)] pub enum TreeHashType { diff --git a/eth2/utils/tree_hash/tests/tests.rs b/eth2/utils/tree_hash/tests/tests.rs index f52a17272..db33709ac 100644 --- a/eth2/utils/tree_hash/tests/tests.rs +++ b/eth2/utils/tree_hash/tests/tests.rs @@ -40,9 +40,9 @@ impl CachedTreeHash for InternalCache { old.cache = None; if let Some(ref mut local_cache) = local_cache { - self.update_cache(&old, local_cache, 0)?; + self.update_tree_hash_cache(&old, local_cache, 0)?; } else { - local_cache = Some(self.new_cache()?) + local_cache = Some(self.new_tree_hash_cache()?) } self.cache = local_cache; @@ -89,16 +89,16 @@ fn works_when_embedded() { } impl CachedTreeHashSubTree for InternalCache { - fn new_cache(&self) -> Result { + fn new_tree_hash_cache(&self) -> Result { let tree = TreeHashCache::from_leaves_and_subtrees( self, - vec![self.a.new_cache()?, self.b.new_cache()?], + vec![self.a.new_tree_hash_cache()?, self.b.new_tree_hash_cache()?], )?; Ok(tree) } - fn btree_overlay(&self, chunk_offset: usize) -> Result { + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result { let mut lengths = vec![]; lengths.push(BTreeOverlay::new(&self.a, 0)?.total_nodes()); @@ -107,7 +107,7 @@ impl CachedTreeHashSubTree for InternalCache { BTreeOverlay::from_lengths(chunk_offset, lengths) } - fn update_cache( + fn update_tree_hash_cache( &self, other: &Self, cache: &mut TreeHashCache, @@ -118,8 +118,8 @@ impl CachedTreeHashSubTree for InternalCache { // Skip past the internal nodes and update any changed leaf nodes. { let chunk = offset_handler.first_leaf_node()?; - let chunk = self.a.update_cache(&other.a, cache, chunk)?; - let _chunk = self.b.update_cache(&other.b, cache, chunk)?; + let chunk = self.a.update_tree_hash_cache(&other.a, cache, chunk)?; + let _chunk = self.b.update_tree_hash_cache(&other.b, cache, chunk)?; } for (&parent, children) in offset_handler.iter_internal_nodes().rev() { @@ -170,21 +170,21 @@ impl TreeHash for Inner { } impl CachedTreeHashSubTree for Inner { - fn new_cache(&self) -> Result { + fn new_tree_hash_cache(&self) -> Result { let tree = TreeHashCache::from_leaves_and_subtrees( self, vec![ - self.a.new_cache()?, - self.b.new_cache()?, - self.c.new_cache()?, - self.d.new_cache()?, + self.a.new_tree_hash_cache()?, + self.b.new_tree_hash_cache()?, + self.c.new_tree_hash_cache()?, + self.d.new_tree_hash_cache()?, ], )?; Ok(tree) } - fn btree_overlay(&self, chunk_offset: usize) -> Result { + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result { let mut lengths = vec![]; lengths.push(BTreeOverlay::new(&self.a, 0)?.total_nodes()); @@ -195,7 +195,7 @@ impl CachedTreeHashSubTree for Inner { BTreeOverlay::from_lengths(chunk_offset, lengths) } - fn update_cache( + fn update_tree_hash_cache( &self, other: &Self, cache: &mut TreeHashCache, @@ -206,10 +206,10 @@ impl CachedTreeHashSubTree for Inner { // Skip past the internal nodes and update any changed leaf nodes. { let chunk = offset_handler.first_leaf_node()?; - let chunk = self.a.update_cache(&other.a, cache, chunk)?; - let chunk = self.b.update_cache(&other.b, cache, chunk)?; - let chunk = self.c.update_cache(&other.c, cache, chunk)?; - let _chunk = self.d.update_cache(&other.d, cache, chunk)?; + let chunk = self.a.update_tree_hash_cache(&other.a, cache, chunk)?; + let chunk = self.b.update_tree_hash_cache(&other.b, cache, chunk)?; + let chunk = self.c.update_tree_hash_cache(&other.c, cache, chunk)?; + let _chunk = self.d.update_tree_hash_cache(&other.d, cache, chunk)?; } for (&parent, children) in offset_handler.iter_internal_nodes().rev() { @@ -254,20 +254,20 @@ impl TreeHash for Outer { } impl CachedTreeHashSubTree for Outer { - fn new_cache(&self) -> Result { + fn new_tree_hash_cache(&self) -> Result { let tree = TreeHashCache::from_leaves_and_subtrees( self, vec![ - self.a.new_cache()?, - self.b.new_cache()?, - self.c.new_cache()?, + self.a.new_tree_hash_cache()?, + self.b.new_tree_hash_cache()?, + self.c.new_tree_hash_cache()?, ], )?; Ok(tree) } - fn btree_overlay(&self, chunk_offset: usize) -> Result { + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result { let mut lengths = vec![]; lengths.push(BTreeOverlay::new(&self.a, 0)?.total_nodes()); @@ -277,7 +277,7 @@ impl CachedTreeHashSubTree for Outer { BTreeOverlay::from_lengths(chunk_offset, lengths) } - fn update_cache( + fn update_tree_hash_cache( &self, other: &Self, cache: &mut TreeHashCache, @@ -288,9 +288,9 @@ impl CachedTreeHashSubTree for Outer { // Skip past the internal nodes and update any changed leaf nodes. { let chunk = offset_handler.first_leaf_node()?; - let chunk = self.a.update_cache(&other.a, cache, chunk)?; - let chunk = self.b.update_cache(&other.b, cache, chunk)?; - let _chunk = self.c.update_cache(&other.c, cache, chunk)?; + let chunk = self.a.update_tree_hash_cache(&other.a, cache, chunk)?; + let chunk = self.b.update_tree_hash_cache(&other.b, cache, chunk)?; + let _chunk = self.c.update_tree_hash_cache(&other.c, cache, chunk)?; } for (&parent, children) in offset_handler.iter_internal_nodes().rev() { @@ -341,7 +341,7 @@ fn partial_modification_to_inner_struct() { let mut cache_struct = TreeHashCache::new(&original_outer).unwrap(); modified_outer - .update_cache(&original_outer, &mut cache_struct, 0) + .update_tree_hash_cache(&original_outer, &mut cache_struct, 0) .unwrap(); let modified_cache: Vec = cache_struct.into(); @@ -395,7 +395,7 @@ fn partial_modification_to_outer() { let mut cache_struct = TreeHashCache::new(&original_outer).unwrap(); modified_outer - .update_cache(&original_outer, &mut cache_struct, 0) + .update_tree_hash_cache(&original_outer, &mut cache_struct, 0) .unwrap(); let modified_cache: Vec = cache_struct.into(); @@ -481,7 +481,7 @@ fn test_u64_vec_modifications(original: Vec, modified: Vec) { // Perform a differential hash let mut cache_struct = TreeHashCache::from_bytes(original_cache.clone(), false).unwrap(); modified - .update_cache(&original, &mut cache_struct, 0) + .update_tree_hash_cache(&original, &mut cache_struct, 0) .unwrap(); let modified_cache: Vec = cache_struct.into(); @@ -586,7 +586,9 @@ fn large_vec_of_u64_builds() { fn test_inner_vec_modifications(original: Vec, modified: Vec, reference: Vec) { let mut cache = TreeHashCache::new(&original).unwrap(); - modified.update_cache(&original, &mut cache, 0).unwrap(); + modified + .update_tree_hash_cache(&original, &mut cache, 0) + .unwrap(); let modified_cache: Vec = cache.into(); // Build the reference vec. @@ -947,12 +949,12 @@ fn generic_test(index: usize) { let mut cache_struct = TreeHashCache::from_bytes(cache.clone(), false).unwrap(); changed_inner - .update_cache(&inner, &mut cache_struct, 0) + .update_tree_hash_cache(&inner, &mut cache_struct, 0) .unwrap(); // assert_eq!(*cache_struct.hash_count, 3); - let new_cache: Vec = cache_struct.into(); + let new_tree_hash_cache: Vec = cache_struct.into(); let data1 = int_to_bytes32(1); let data2 = int_to_bytes32(2); @@ -965,7 +967,7 @@ fn generic_test(index: usize) { let expected = merkleize(join(data)); - assert_eq!(expected, new_cache); + assert_eq!(expected, new_tree_hash_cache); } #[test] diff --git a/eth2/utils/tree_hash_derive/src/lib.rs b/eth2/utils/tree_hash_derive/src/lib.rs index 217e91c24..b2afabaa9 100644 --- a/eth2/utils/tree_hash_derive/src/lib.rs +++ b/eth2/utils/tree_hash_derive/src/lib.rs @@ -39,9 +39,9 @@ fn should_skip_hashing(field: &syn::Field) -> bool { false } -/// Implements `ssz::Encodable` for some `struct`. +/// Implements `tree_hash::CachedTreeHashSubTree` for some `struct`. /// -/// Fields are encoded in the order they are defined. +/// Fields are hashed in the order they are defined. #[proc_macro_derive(CachedTreeHashSubTree, attributes(tree_hash))] pub fn subtree_derive(input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as DeriveInput); @@ -60,16 +60,12 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream { let output = quote! { impl tree_hash::CachedTreeHashSubTree<#name> for #name { - fn item_type() -> tree_hash::ItemType { - tree_hash::ItemType::Composite - } - - fn new_cache(&self) -> Result { + fn new_tree_hash_cache(&self) -> Result { let tree = tree_hash::TreeHashCache::from_leaves_and_subtrees( self, vec![ #( - self.#idents_a.new_cache()?, + self.#idents_a.new_tree_hash_cache()?, )* ], )?; @@ -77,7 +73,7 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream { Ok(tree) } - fn btree_overlay(&self, chunk_offset: usize) -> Result { + fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result { let mut lengths = vec![]; #( @@ -87,15 +83,7 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream { tree_hash::BTreeOverlay::from_lengths(chunk_offset, lengths) } - fn packed_encoding(&self) -> Result, tree_hash::Error> { - Err(tree_hash::Error::ShouldNeverBePacked(Self::item_type())) - } - - fn packing_factor() -> usize { - 1 - } - - fn update_cache( + fn update_tree_hash_cache( &self, other: &Self, cache: &mut tree_hash::TreeHashCache, @@ -107,7 +95,7 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream { { let chunk = offset_handler.first_leaf_node()?; #( - let chunk = self.#idents_c.update_cache(&other.#idents_d, cache, chunk)?; + let chunk = self.#idents_c.update_tree_hash_cache(&other.#idents_d, cache, chunk)?; )* } @@ -123,3 +111,47 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream { }; output.into() } + +/// Implements `tree_hash::TreeHash` for some `struct`. +/// +/// Fields are hashed in the order they are defined. +#[proc_macro_derive(TreeHash, attributes(tree_hash))] +pub fn tree_hash_derive(input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as DeriveInput); + + let name = &item.ident; + + let struct_data = match &item.data { + syn::Data::Struct(s) => s, + _ => panic!("tree_hash_derive only supports structs."), + }; + + let idents = get_hashable_named_field_idents(&struct_data); + + let output = quote! { + impl tree_hash::TreeHash for #name { + fn tree_hash_type() -> tree_hash::TreeHashType { + tree_hash::TreeHashType::Composite + } + + fn tree_hash_packed_encoding(&self) -> Vec { + unreachable!("Struct should never be packed.") + } + + fn tree_hash_packing_factor() -> usize { + unreachable!("Struct should never be packed.") + } + + fn tree_hash_root(&self) -> Vec { + let mut leaves = Vec::with_capacity(4 * tree_hash::HASHSIZE); + + #( + leaves.append(&mut self.#idents.tree_hash_root()); + )* + + tree_hash::efficient_merkleize(&leaves)[0..32].to_vec() + } + } + }; + output.into() +} diff --git a/eth2/utils/tree_hash_derive/tests/tests.rs b/eth2/utils/tree_hash_derive/tests/tests.rs index a5ab112a2..5f065c982 100644 --- a/eth2/utils/tree_hash_derive/tests/tests.rs +++ b/eth2/utils/tree_hash_derive/tests/tests.rs @@ -1,9 +1,71 @@ -use tree_hash_derive::CachedTreeHashSubTree; +use tree_hash::CachedTreeHashSubTree; +use tree_hash_derive::{CachedTreeHashSubTree, TreeHash}; -#[derive(Clone, Debug, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] pub struct Inner { pub a: u64, pub b: u64, pub c: u64, pub d: u64, } + +fn test_standard_and_cached(original: &T, modified: &T) +where + T: CachedTreeHashSubTree, +{ + let mut cache = original.new_tree_hash_cache().unwrap(); + + let standard_root = original.tree_hash_root(); + let cached_root = cache.root().unwrap().to_vec(); + assert_eq!(standard_root, cached_root); + + // Test after a modification + modified + .update_tree_hash_cache(&original, &mut cache, 0) + .unwrap(); + let standard_root = modified.tree_hash_root(); + let cached_root = cache.root().unwrap().to_vec(); + assert_eq!(standard_root, cached_root); +} + +#[test] +fn inner_standard_vs_cached() { + let original = Inner { + a: 1, + b: 2, + c: 3, + d: 4, + }; + let modified = Inner { + b: 42, + ..original.clone() + }; + + test_standard_and_cached(&original, &modified); +} + +#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +pub struct Uneven { + pub a: u64, + pub b: u64, + pub c: u64, + pub d: u64, + pub e: u64, +} + +#[test] +fn uneven_standard_vs_cached() { + let original = Uneven { + a: 1, + b: 2, + c: 3, + d: 4, + e: 5, + }; + let modified = Uneven { + e: 42, + ..original.clone() + }; + + test_standard_and_cached(&original, &modified); +}