Unify tree hash methods
This commit is contained in:
		
							parent
							
								
									93f3fc858d
								
							
						
					
					
						commit
						d311b48a9f
					
				| @ -17,7 +17,7 @@ pub enum Error { | ||||
|     UnableToObtainSlices, | ||||
|     UnableToGrowMerkleTree, | ||||
|     UnableToShrinkMerkleTree, | ||||
|     ShouldNeverBePacked(ItemType), | ||||
|     ShouldNeverBePacked(TreeHashType), | ||||
|     BytesAreNotEvenChunks(usize), | ||||
|     NoModifiedFieldForChunk(usize), | ||||
|     NoBytesForChunk(usize), | ||||
| @ -31,15 +31,9 @@ pub trait CachedTreeHash<T>: CachedTreeHashSubTree<T> + Sized { | ||||
|     fn clone_without_tree_hash_cache(&self) -> Self; | ||||
| } | ||||
| 
 | ||||
| pub trait CachedTreeHashSubTree<Item> { | ||||
|     fn item_type() -> ItemType; | ||||
| 
 | ||||
| pub trait CachedTreeHashSubTree<Item>: TreeHash { | ||||
|     fn btree_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error>; | ||||
| 
 | ||||
|     fn packed_encoding(&self) -> Result<Vec<u8>, Error>; | ||||
| 
 | ||||
|     fn packing_factor() -> usize; | ||||
| 
 | ||||
|     fn new_cache(&self) -> Result<TreeHashCache, Error>; | ||||
| 
 | ||||
|     fn update_cache( | ||||
|  | ||||
| @ -5,10 +5,6 @@ use ssz::ssz_encode; | ||||
| mod vec; | ||||
| 
 | ||||
| impl CachedTreeHashSubTree<u64> for u64 { | ||||
|     fn item_type() -> ItemType { | ||||
|         ItemType::Basic | ||||
|     } | ||||
| 
 | ||||
|     fn new_cache(&self) -> Result<TreeHashCache, Error> { | ||||
|         Ok(TreeHashCache::from_bytes( | ||||
|             merkleize(ssz_encode(self)), | ||||
| @ -20,14 +16,6 @@ impl CachedTreeHashSubTree<u64> for u64 { | ||||
|         BTreeOverlay::from_lengths(chunk_offset, vec![1]) | ||||
|     } | ||||
| 
 | ||||
|     fn packed_encoding(&self) -> Result<Vec<u8>, Error> { | ||||
|         Ok(ssz_encode(self)) | ||||
|     } | ||||
| 
 | ||||
|     fn packing_factor() -> usize { | ||||
|         HASHSIZE / 8 | ||||
|     } | ||||
| 
 | ||||
|     fn update_cache( | ||||
|         &self, | ||||
|         other: &Self, | ||||
|  | ||||
| @ -2,18 +2,14 @@ use super::*; | ||||
| 
 | ||||
| impl<T> CachedTreeHashSubTree<Vec<T>> for Vec<T> | ||||
| where | ||||
|     T: CachedTreeHashSubTree<T>, | ||||
|     T: CachedTreeHashSubTree<T> + TreeHash, | ||||
| { | ||||
|     fn item_type() -> ItemType { | ||||
|         ItemType::List | ||||
|     } | ||||
| 
 | ||||
|     fn new_cache(&self) -> Result<TreeHashCache, Error> { | ||||
|         match T::item_type() { | ||||
|             ItemType::Basic => { | ||||
|         match T::tree_hash_type() { | ||||
|             TreeHashType::Basic => { | ||||
|                 TreeHashCache::from_bytes(merkleize(get_packed_leaves(self)?), false) | ||||
|             } | ||||
|             ItemType::Composite | ItemType::List => { | ||||
|             TreeHashType::Composite | TreeHashType::List => { | ||||
|                 let subtrees = self | ||||
|                     .iter() | ||||
|                     .map(|item| TreeHashCache::new(item)) | ||||
| @ -25,9 +21,9 @@ where | ||||
|     } | ||||
| 
 | ||||
|     fn btree_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error> { | ||||
|         let lengths = match T::item_type() { | ||||
|             ItemType::Basic => vec![1; self.len() / T::packing_factor()], | ||||
|             ItemType::Composite | ItemType::List => { | ||||
|         let lengths = match T::tree_hash_type() { | ||||
|             TreeHashType::Basic => vec![1; self.len() / T::tree_hash_packing_factor()], | ||||
|             TreeHashType::Composite | TreeHashType::List => { | ||||
|                 let mut lengths = vec![]; | ||||
| 
 | ||||
|                 for item in self { | ||||
| @ -41,14 +37,6 @@ where | ||||
|         BTreeOverlay::from_lengths(chunk_offset, lengths) | ||||
|     } | ||||
| 
 | ||||
|     fn packed_encoding(&self) -> Result<Vec<u8>, Error> { | ||||
|         Err(Error::ShouldNeverBePacked(Self::item_type())) | ||||
|     } | ||||
| 
 | ||||
|     fn packing_factor() -> usize { | ||||
|         1 | ||||
|     } | ||||
| 
 | ||||
|     fn update_cache( | ||||
|         &self, | ||||
|         other: &Vec<T>, | ||||
| @ -93,8 +81,8 @@ where | ||||
|             cache.splice(old_offset_handler.chunk_range(), modified_cache); | ||||
|         } | ||||
| 
 | ||||
|         match T::item_type() { | ||||
|             ItemType::Basic => { | ||||
|         match T::tree_hash_type() { | ||||
|             TreeHashType::Basic => { | ||||
|                 let leaves = get_packed_leaves(self)?; | ||||
| 
 | ||||
|                 for (i, chunk) in offset_handler.iter_leaf_nodes().enumerate() { | ||||
| @ -109,7 +97,7 @@ where | ||||
|                     TreeHashCache::from_bytes(leaves, true)?, | ||||
|                 ); | ||||
|             } | ||||
|             ItemType::Composite | ItemType::List => { | ||||
|             TreeHashType::Composite | TreeHashType::List => { | ||||
|                 let mut i = offset_handler.num_leaf_nodes; | ||||
|                 for &start_chunk in offset_handler.iter_leaf_nodes().rev() { | ||||
|                     i -= 1; | ||||
| @ -170,13 +158,13 @@ fn get_packed_leaves<T>(vec: &Vec<T>) -> Result<Vec<u8>, Error> | ||||
| where | ||||
|     T: CachedTreeHashSubTree<T>, | ||||
| { | ||||
|     let num_packed_bytes = (BYTES_PER_CHUNK / T::packing_factor()) * vec.len(); | ||||
|     let num_packed_bytes = (BYTES_PER_CHUNK / T::tree_hash_packing_factor()) * vec.len(); | ||||
|     let num_leaves = num_sanitized_leaves(num_packed_bytes); | ||||
| 
 | ||||
|     let mut packed = Vec::with_capacity(num_leaves * HASHSIZE); | ||||
| 
 | ||||
|     for item in vec { | ||||
|         packed.append(&mut item.packed_encoding()?); | ||||
|         packed.append(&mut item.tree_hash_packed_encoding()); | ||||
|     } | ||||
| 
 | ||||
|     Ok(sanitise_bytes(packed)) | ||||
|  | ||||
| @ -5,8 +5,11 @@ 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; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Clone)] | ||||
| pub enum ItemType { | ||||
| pub enum TreeHashType { | ||||
|     Basic, | ||||
|     List, | ||||
|     Composite, | ||||
|  | ||||
| @ -4,23 +4,29 @@ use int_to_bytes::int_to_bytes32; | ||||
| use ssz::ssz_encode; | ||||
| 
 | ||||
| pub trait TreeHash { | ||||
|     fn tree_hash_item_type() -> ItemType; | ||||
|     fn tree_hash_type() -> TreeHashType; | ||||
| 
 | ||||
|     fn tree_hash_packed_encoding(&self) -> Vec<u8>; | ||||
| 
 | ||||
|     fn hash_tree_root(&self) -> Vec<u8>; | ||||
|     fn tree_hash_packing_factor() -> usize; | ||||
| 
 | ||||
|     fn tree_hash_root(&self) -> Vec<u8>; | ||||
| } | ||||
| 
 | ||||
| impl TreeHash for u64 { | ||||
|     fn tree_hash_item_type() -> ItemType { | ||||
|         ItemType::Basic | ||||
|     fn tree_hash_type() -> TreeHashType { | ||||
|         TreeHashType::Basic | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packed_encoding(&self) -> Vec<u8> { | ||||
|         ssz_encode(self) | ||||
|     } | ||||
| 
 | ||||
|     fn hash_tree_root(&self) -> Vec<u8> { | ||||
|     fn tree_hash_packing_factor() -> usize { | ||||
|         HASHSIZE / 8 | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_root(&self) -> Vec<u8> { | ||||
|         int_to_bytes32(*self) | ||||
|     } | ||||
| } | ||||
| @ -29,18 +35,23 @@ impl<T> TreeHash for Vec<T> | ||||
| where | ||||
|     T: TreeHash, | ||||
| { | ||||
|     fn tree_hash_item_type() -> ItemType { | ||||
|         ItemType::List | ||||
|     fn tree_hash_type() -> TreeHashType { | ||||
|         TreeHashType::List | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packed_encoding(&self) -> Vec<u8> { | ||||
|         unreachable!("List should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn hash_tree_root(&self) -> Vec<u8> { | ||||
|         let leaves = match T::tree_hash_item_type() { | ||||
|             ItemType::Basic => { | ||||
|                 let mut leaves = vec![]; | ||||
|     fn tree_hash_packing_factor() -> usize { | ||||
|         unreachable!("List should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_root(&self) -> Vec<u8> { | ||||
|         let leaves = match T::tree_hash_type() { | ||||
|             TreeHashType::Basic => { | ||||
|                 let mut leaves = | ||||
|                     Vec::with_capacity((HASHSIZE / T::tree_hash_packing_factor()) * self.len()); | ||||
| 
 | ||||
|                 for item in self { | ||||
|                     leaves.append(&mut item.tree_hash_packed_encoding()); | ||||
| @ -48,11 +59,11 @@ where | ||||
| 
 | ||||
|                 leaves | ||||
|             } | ||||
|             ItemType::Composite | ItemType::List => { | ||||
|             TreeHashType::Composite | TreeHashType::List => { | ||||
|                 let mut leaves = Vec::with_capacity(self.len() * HASHSIZE); | ||||
| 
 | ||||
|                 for item in self { | ||||
|                     leaves.append(&mut item.hash_tree_root()) | ||||
|                     leaves.append(&mut item.tree_hash_root()) | ||||
|                 } | ||||
| 
 | ||||
|                 leaves | ||||
|  | ||||
| @ -11,6 +11,29 @@ pub struct InternalCache { | ||||
|     pub cache: Option<TreeHashCache>, | ||||
| } | ||||
| 
 | ||||
| impl TreeHash for InternalCache { | ||||
|     fn tree_hash_type() -> TreeHashType { | ||||
|         TreeHashType::Composite | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packed_encoding(&self) -> Vec<u8> { | ||||
|         unreachable!("Struct should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packing_factor() -> usize { | ||||
|         unreachable!("Struct should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_root(&self) -> Vec<u8> { | ||||
|         let mut leaves = Vec::with_capacity(4 * HASHSIZE); | ||||
| 
 | ||||
|         leaves.append(&mut self.a.tree_hash_root()); | ||||
|         leaves.append(&mut self.b.tree_hash_root()); | ||||
| 
 | ||||
|         efficient_merkleize(&leaves)[0..32].to_vec() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl CachedTreeHash<InternalCache> for InternalCache { | ||||
|     fn update_internal_tree_hash_cache(mut self, mut old: Self) -> Result<(Self, Self), Error> { | ||||
|         let mut local_cache = old.cache; | ||||
| @ -66,10 +89,6 @@ fn works_when_embedded() { | ||||
| } | ||||
| 
 | ||||
| impl CachedTreeHashSubTree<InternalCache> for InternalCache { | ||||
|     fn item_type() -> ItemType { | ||||
|         ItemType::Composite | ||||
|     } | ||||
| 
 | ||||
|     fn new_cache(&self) -> Result<TreeHashCache, Error> { | ||||
|         let tree = TreeHashCache::from_leaves_and_subtrees( | ||||
|             self, | ||||
| @ -88,14 +107,6 @@ impl CachedTreeHashSubTree<InternalCache> for InternalCache { | ||||
|         BTreeOverlay::from_lengths(chunk_offset, lengths) | ||||
|     } | ||||
| 
 | ||||
|     fn packed_encoding(&self) -> Result<Vec<u8>, Error> { | ||||
|         Err(Error::ShouldNeverBePacked(Self::item_type())) | ||||
|     } | ||||
| 
 | ||||
|     fn packing_factor() -> usize { | ||||
|         1 | ||||
|     } | ||||
| 
 | ||||
|     fn update_cache( | ||||
|         &self, | ||||
|         other: &Self, | ||||
| @ -134,31 +145,31 @@ pub struct Inner { | ||||
| } | ||||
| 
 | ||||
| impl TreeHash for Inner { | ||||
|     fn tree_hash_item_type() -> ItemType { | ||||
|         ItemType::Composite | ||||
|     fn tree_hash_type() -> TreeHashType { | ||||
|         TreeHashType::Composite | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packed_encoding(&self) -> Vec<u8> { | ||||
|         unreachable!("Struct should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn hash_tree_root(&self) -> Vec<u8> { | ||||
|     fn tree_hash_packing_factor() -> usize { | ||||
|         unreachable!("Struct should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_root(&self) -> Vec<u8> { | ||||
|         let mut leaves = Vec::with_capacity(4 * HASHSIZE); | ||||
| 
 | ||||
|         leaves.append(&mut self.a.hash_tree_root()); | ||||
|         leaves.append(&mut self.b.hash_tree_root()); | ||||
|         leaves.append(&mut self.c.hash_tree_root()); | ||||
|         leaves.append(&mut self.d.hash_tree_root()); | ||||
|         leaves.append(&mut self.a.tree_hash_root()); | ||||
|         leaves.append(&mut self.b.tree_hash_root()); | ||||
|         leaves.append(&mut self.c.tree_hash_root()); | ||||
|         leaves.append(&mut self.d.tree_hash_root()); | ||||
| 
 | ||||
|         efficient_merkleize(&leaves)[0..32].to_vec() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl CachedTreeHashSubTree<Inner> for Inner { | ||||
|     fn item_type() -> ItemType { | ||||
|         ItemType::Composite | ||||
|     } | ||||
| 
 | ||||
|     fn new_cache(&self) -> Result<TreeHashCache, Error> { | ||||
|         let tree = TreeHashCache::from_leaves_and_subtrees( | ||||
|             self, | ||||
| @ -184,14 +195,6 @@ impl CachedTreeHashSubTree<Inner> for Inner { | ||||
|         BTreeOverlay::from_lengths(chunk_offset, lengths) | ||||
|     } | ||||
| 
 | ||||
|     fn packed_encoding(&self) -> Result<Vec<u8>, Error> { | ||||
|         Err(Error::ShouldNeverBePacked(Self::item_type())) | ||||
|     } | ||||
| 
 | ||||
|     fn packing_factor() -> usize { | ||||
|         1 | ||||
|     } | ||||
| 
 | ||||
|     fn update_cache( | ||||
|         &self, | ||||
|         other: &Self, | ||||
| @ -226,11 +229,31 @@ pub struct Outer { | ||||
|     pub c: u64, | ||||
| } | ||||
| 
 | ||||
| impl CachedTreeHashSubTree<Outer> for Outer { | ||||
|     fn item_type() -> ItemType { | ||||
|         ItemType::Composite | ||||
| impl TreeHash for Outer { | ||||
|     fn tree_hash_type() -> TreeHashType { | ||||
|         TreeHashType::Composite | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packed_encoding(&self) -> Vec<u8> { | ||||
|         unreachable!("Struct should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_packing_factor() -> usize { | ||||
|         unreachable!("Struct should never be packed.") | ||||
|     } | ||||
| 
 | ||||
|     fn tree_hash_root(&self) -> Vec<u8> { | ||||
|         let mut leaves = Vec::with_capacity(4 * HASHSIZE); | ||||
| 
 | ||||
|         leaves.append(&mut self.a.tree_hash_root()); | ||||
|         leaves.append(&mut self.b.tree_hash_root()); | ||||
|         leaves.append(&mut self.c.tree_hash_root()); | ||||
| 
 | ||||
|         efficient_merkleize(&leaves)[0..32].to_vec() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl CachedTreeHashSubTree<Outer> for Outer { | ||||
|     fn new_cache(&self) -> Result<TreeHashCache, Error> { | ||||
|         let tree = TreeHashCache::from_leaves_and_subtrees( | ||||
|             self, | ||||
| @ -254,14 +277,6 @@ impl CachedTreeHashSubTree<Outer> for Outer { | ||||
|         BTreeOverlay::from_lengths(chunk_offset, lengths) | ||||
|     } | ||||
| 
 | ||||
|     fn packed_encoding(&self) -> Result<Vec<u8>, Error> { | ||||
|         Err(Error::ShouldNeverBePacked(Self::item_type())) | ||||
|     } | ||||
| 
 | ||||
|     fn packing_factor() -> usize { | ||||
|         1 | ||||
|     } | ||||
| 
 | ||||
|     fn update_cache( | ||||
|         &self, | ||||
|         other: &Self, | ||||
| @ -481,7 +496,7 @@ fn test_u64_vec_modifications(original: Vec<u64>, modified: Vec<u64>) { | ||||
|     mix_in_length(&mut expected[0..HASHSIZE], modified.len()); | ||||
| 
 | ||||
|     assert_eq!(expected, modified_cache); | ||||
|     assert_eq!(&expected[0..32], &modified.hash_tree_root()[..]); | ||||
|     assert_eq!(&expected[0..32], &modified.tree_hash_root()[..]); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| @ -604,7 +619,7 @@ fn test_inner_vec_modifications(original: Vec<Inner>, modified: Vec<Inner>, refe | ||||
| 
 | ||||
|     // Compare the cached tree to the reference tree.
 | ||||
|     assert_trees_eq(&expected, &modified_cache); | ||||
|     assert_eq!(&expected[0..32], &modified.hash_tree_root()[..]); | ||||
|     assert_eq!(&expected[0..32], &modified.tree_hash_root()[..]); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user