diff --git a/eth2/utils/tree_hash/README.md b/eth2/utils/tree_hash/README.md new file mode 100644 index 000000000..3c6e13a2e --- /dev/null +++ b/eth2/utils/tree_hash/README.md @@ -0,0 +1,76 @@ +# Tree hashing + +Provides both cached and non-cached tree hashing methods. + +## Standard Tree Hash + +```rust +use tree_hash_derive::TreeHash; + +#[derive(TreeHash)] +struct Foo { + a: u64, + b: Vec, +} + +fn main() { + let foo = Foo { + a: 42, + b: vec![1, 2, 3] + } + + println!("root: {}", foo.tree_hash_root()); +} +``` + +## Cached Tree Hash + + +```rust +use tree_hash_derive::{TreeHash, CachedTreeHash}; + +#[derive(TreeHash, CachedTreeHash)] +struct Foo { + a: u64, + b: Vec, +} + +#[derive(TreeHash, CachedTreeHash)] +struct Bar { + a: Vec, + b: u64, +} + +fn main() { + let bar = Bar { + a: vec![ + Foo { + a: 42, + b: vec![1, 2, 3] + } + ], + b: 42 + }; + + let modified_bar = Bar { + a: vec![ + Foo { + a: 100, + b: vec![1, 2, 3, 4, 5, 6] + } + Foo { + a: 42, + b: vec![] + } + ], + b: 99 + }; + + + let mut hasher = CachedTreeHasher::new(&bar).unwrap(); + hasher.update(&modified_bar); + + // Assert that the cached tree hash matches a standard tree hash. + assert_eq!(hasher.tree_hash_root(), modified_bar.tree_hash_root()); +} +``` diff --git a/eth2/utils/tree_hash/src/cached_tree_hash.rs b/eth2/utils/tree_hash/src/cached_tree_hash.rs index 66ccbb680..0183f5c84 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash.rs @@ -19,7 +19,7 @@ pub struct CachedTreeHasher { impl CachedTreeHasher { pub fn new(item: &T) -> Result where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { Ok(Self { cache: TreeHashCache::new(item, 0)?, @@ -28,7 +28,7 @@ impl CachedTreeHasher { pub fn update(&mut self, item: &T) -> Result<(), Error> where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { // Reset the per-hash counters. self.cache.chunk_index = 0; @@ -66,15 +66,7 @@ pub enum Error { NotLeafNode(usize), } -pub trait CachedTreeHash: CachedTreeHashSubTree + Sized { - fn update_internal_tree_hash_cache(self, old: T) -> Result<(Self, Self), Error>; - - fn cached_tree_hash_root(&self) -> Option>; - - fn clone_without_tree_hash_cache(&self) -> Self; -} - -pub trait CachedTreeHashSubTree: TreeHash { +pub trait CachedTreeHash: TreeHash { fn tree_hash_cache_overlay( &self, chunk_offset: usize, 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 463586d40..9fd1251d7 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 @@ -11,7 +11,7 @@ pub struct BTreeOverlay { impl BTreeOverlay { pub fn new(item: &T, initial_offset: usize, depth: usize) -> Result where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { item.tree_hash_cache_overlay(initial_offset, depth) } 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 34902f062..74ab986cb 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash/impls.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash/impls.rs @@ -2,7 +2,7 @@ use super::*; mod vec; -impl CachedTreeHashSubTree for u64 { +impl CachedTreeHash for u64 { fn new_tree_hash_cache(&self, _depth: usize) -> Result { Ok(TreeHashCache::from_bytes( merkleize(self.to_le_bytes().to_vec()), @@ -35,7 +35,7 @@ impl CachedTreeHashSubTree for u64 { } } -impl CachedTreeHashSubTree for usize { +impl CachedTreeHash for usize { fn new_tree_hash_cache(&self, _depth: usize) -> Result { Ok(TreeHashCache::from_bytes( merkleize(self.to_le_bytes().to_vec()), 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 fc43cc9b8..6a0770681 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 @@ -1,8 +1,8 @@ use super::*; -impl CachedTreeHashSubTree> for Vec +impl CachedTreeHash> for Vec where - T: CachedTreeHashSubTree + TreeHash, + T: CachedTreeHash + TreeHash, { fn new_tree_hash_cache(&self, depth: usize) -> Result { let mut overlay = self.tree_hash_cache_overlay(0, depth)?; @@ -186,7 +186,7 @@ where fn get_packed_leaves(vec: &Vec) -> Result, Error> where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { let num_packed_bytes = (BYTES_PER_CHUNK / T::tree_hash_packing_factor()) * vec.len(); let num_leaves = num_sanitized_leaves(num_packed_bytes); diff --git a/eth2/utils/tree_hash/src/cached_tree_hash/tree_hash_cache.rs b/eth2/utils/tree_hash/src/cached_tree_hash/tree_hash_cache.rs index 8fa08e306..336d28028 100644 --- a/eth2/utils/tree_hash/src/cached_tree_hash/tree_hash_cache.rs +++ b/eth2/utils/tree_hash/src/cached_tree_hash/tree_hash_cache.rs @@ -19,7 +19,7 @@ impl Into> for TreeHashCache { impl TreeHashCache { pub fn new(item: &T, depth: usize) -> Result where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { item.new_tree_hash_cache(depth) } @@ -30,7 +30,7 @@ impl TreeHashCache { depth: usize, ) -> Result where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { let overlay = BTreeOverlay::new(item, 0, depth)?; diff --git a/eth2/utils/tree_hash/src/lib.rs b/eth2/utils/tree_hash/src/lib.rs index ed60079c8..5aaf2d585 100644 --- a/eth2/utils/tree_hash/src/lib.rs +++ b/eth2/utils/tree_hash/src/lib.rs @@ -6,7 +6,7 @@ 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::{BTreeOverlay, CachedTreeHashSubTree, Error, TreeHashCache}; +pub use cached_tree_hash::{BTreeOverlay, CachedTreeHash, Error, TreeHashCache}; pub use signed_root::SignedRoot; pub use standard_tree_hash::{merkle_root, TreeHash}; diff --git a/eth2/utils/tree_hash/tests/tests.rs b/eth2/utils/tree_hash/tests/tests.rs index cef366da4..6f339b8f2 100644 --- a/eth2/utils/tree_hash/tests/tests.rs +++ b/eth2/utils/tree_hash/tests/tests.rs @@ -1,8 +1,8 @@ use int_to_bytes::int_to_bytes32; use tree_hash::cached_tree_hash::*; -use tree_hash_derive::{CachedTreeHashSubTree, TreeHash}; +use tree_hash_derive::{CachedTreeHash, TreeHash}; -#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct NestedStruct { pub a: u64, pub b: Inner, @@ -10,7 +10,7 @@ pub struct NestedStruct { fn test_routine(original: T, modified: Vec) where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { let mut hasher = CachedTreeHasher::new(&original).unwrap(); @@ -113,7 +113,7 @@ fn test_nested_list_of_u64() { test_routine(original, modified); } -#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct StructWithVec { pub a: u64, pub b: Inner, @@ -224,7 +224,7 @@ fn test_vec_of_struct_with_vec() { test_routine(original, modified); } -#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct StructWithVecOfStructs { pub a: u64, pub b: Inner, @@ -302,7 +302,7 @@ fn test_struct_with_vec_of_structs() { test_routine(f, variants); } -#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct Inner { pub a: u64, pub b: u64, @@ -481,7 +481,7 @@ fn works_when_embedded() { assert_eq!(&merkle[0..32], &root[..]); } -impl CachedTreeHashSubTree for InternalCache { +impl CachedTreeHash for InternalCache { fn new_tree_hash_cache(&self) -> Result { let tree = TreeHashCache::from_leaves_and_subtrees( self, @@ -562,7 +562,7 @@ impl TreeHash for Inner { } } -impl CachedTreeHashSubTree for Inner { +impl CachedTreeHash for Inner { fn new_tree_hash_cache(&self) -> Result { let tree = TreeHashCache::from_leaves_and_subtrees( self, @@ -646,7 +646,7 @@ impl TreeHash for Outer { } } -impl CachedTreeHashSubTree for Outer { +impl CachedTreeHash for Outer { fn new_tree_hash_cache(&self) -> Result { let tree = TreeHashCache::from_leaves_and_subtrees( self, diff --git a/eth2/utils/tree_hash_derive/src/lib.rs b/eth2/utils/tree_hash_derive/src/lib.rs index 272ea7e96..9b35512a9 100644 --- a/eth2/utils/tree_hash_derive/src/lib.rs +++ b/eth2/utils/tree_hash_derive/src/lib.rs @@ -37,10 +37,10 @@ fn should_skip_hashing(field: &syn::Field) -> bool { .any(|attr| attr.into_token_stream().to_string() == "# [ tree_hash ( skip_hashing ) ]") } -/// Implements `tree_hash::CachedTreeHashSubTree` for some `struct`. +/// Implements `tree_hash::CachedTreeHash` for some `struct`. /// /// Fields are hashed in the order they are defined. -#[proc_macro_derive(CachedTreeHashSubTree, attributes(tree_hash))] +#[proc_macro_derive(CachedTreeHash, attributes(tree_hash))] pub fn subtree_derive(input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as DeriveInput); @@ -58,7 +58,7 @@ pub fn subtree_derive(input: TokenStream) -> TokenStream { let num_items = idents_a.len(); let output = quote! { - impl tree_hash::CachedTreeHashSubTree<#name> for #name { + impl tree_hash::CachedTreeHash<#name> for #name { fn new_tree_hash_cache(&self, depth: usize) -> Result { let tree = tree_hash::TreeHashCache::from_leaves_and_subtrees( self, diff --git a/eth2/utils/tree_hash_derive/tests/tests.rs b/eth2/utils/tree_hash_derive/tests/tests.rs index a7c74b23e..10d0aa853 100644 --- a/eth2/utils/tree_hash_derive/tests/tests.rs +++ b/eth2/utils/tree_hash_derive/tests/tests.rs @@ -1,7 +1,7 @@ -use tree_hash::{CachedTreeHashSubTree, SignedRoot, TreeHash}; -use tree_hash_derive::{CachedTreeHashSubTree, SignedRoot, TreeHash}; +use tree_hash::{CachedTreeHash, SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; -#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct Inner { pub a: u64, pub b: u64, @@ -11,7 +11,7 @@ pub struct Inner { fn test_standard_and_cached(original: &T, modified: &T) where - T: CachedTreeHashSubTree, + T: CachedTreeHash, { let mut cache = original.new_tree_hash_cache().unwrap(); @@ -44,7 +44,7 @@ fn inner_standard_vs_cached() { test_standard_and_cached(&original, &modified); } -#[derive(Clone, Debug, TreeHash, CachedTreeHashSubTree)] +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct Uneven { pub a: u64, pub b: u64,