diff --git a/eth2/utils/ssz/src/cached_tree_hash.rs b/eth2/utils/ssz/src/cached_tree_hash.rs index b676ececce..84ef822330 100644 --- a/eth2/utils/ssz/src/cached_tree_hash.rs +++ b/eth2/utils/ssz/src/cached_tree_hash.rs @@ -1,9 +1,7 @@ use hashing::hash; use std::fmt::Debug; -use std::iter::IntoIterator; use std::iter::Iterator; use std::ops::Range; -use std::vec::Splice; mod impls; mod resize; @@ -21,7 +19,6 @@ pub enum Error { BytesAreNotEvenChunks(usize), NoModifiedFieldForChunk(usize), NoBytesForChunk(usize), - NoChildrenForHashing((usize, usize)), } #[derive(Debug, PartialEq, Clone)] @@ -150,27 +147,11 @@ impl TreeHashCache { let (bytes, bools) = replace_with.into_components(); // Update the `chunk_modified` vec, marking all spliced-in nodes as changed. - self.chunk_modified.splice( - chunk_range.clone(), - bools, - ); - self.cache.splice(node_range_to_byte_range(chunk_range), bytes); + self.chunk_modified.splice(chunk_range.clone(), bools); + self.cache + .splice(node_range_to_byte_range(chunk_range), bytes); } - /* - pub fn byte_splice(&mut self, chunk_range: Range, replace_with: Vec) { - let byte_start = chunk_range.start * BYTES_PER_CHUNK; - let byte_end = chunk_range.end * BYTES_PER_CHUNK; - - // Update the `chunk_modified` vec, marking all spliced-in nodes as changed. - self.chunk_modified.splice( - chunk_range.clone(), - vec![true; replace_with.len() / HASHSIZE], - ); - self.cache.splice(byte_start..byte_end, replace_with); - } - */ - pub fn maybe_update_chunk(&mut self, chunk: usize, to: &[u8]) -> Result<(), Error> { let start = chunk * BYTES_PER_CHUNK; let end = start + BYTES_PER_CHUNK; diff --git a/eth2/utils/ssz/src/cached_tree_hash/impls.rs b/eth2/utils/ssz/src/cached_tree_hash/impls.rs index f598de79a7..dca00b6ba1 100644 --- a/eth2/utils/ssz/src/cached_tree_hash/impls.rs +++ b/eth2/utils/ssz/src/cached_tree_hash/impls.rs @@ -1,5 +1,6 @@ +use super::resize::grow_merkle_cache; use super::*; -use crate::{ssz_encode, Encodable}; +use crate::ssz_encode; impl CachedTreeHash for u64 { fn item_type() -> ItemType { @@ -112,8 +113,10 @@ where ) -> Result { let offset_handler = OffsetHandler::new(self, chunk)?; - if self.len().next_power_of_two() != other.len().next_power_of_two() { - panic!("not implemented: vary between power-of-two boundary"); + if other.len().next_power_of_two() > self.len().next_power_of_two() { + // + } else if other.len().next_power_of_two() < self.len().next_power_of_two() { + panic!("shrinking below power of two is not implemented") } match T::item_type() { diff --git a/eth2/utils/ssz/src/cached_tree_hash/resize.rs b/eth2/utils/ssz/src/cached_tree_hash/resize.rs index 21b729c9e3..bce722a5e3 100644 --- a/eth2/utils/ssz/src/cached_tree_hash/resize.rs +++ b/eth2/utils/ssz/src/cached_tree_hash/resize.rs @@ -1,12 +1,12 @@ use super::*; /// New vec is bigger than old vec. -fn grow_merkle_cache( +pub fn grow_merkle_cache( old_bytes: &[u8], old_flags: &[bool], from_height: usize, to_height: usize, -) -> Option> { +) -> Option<(Vec, Vec)> { let to_nodes = (1 << to_height.next_power_of_two()) - 1; // Determine the size of our new tree. It is not just a simple `1 << to_height` as there can be @@ -15,7 +15,6 @@ fn grow_merkle_cache( let additional_from_nodes = old_bytes.len() / HASHSIZE - ((1 << from_height) - 1); ((1 << to_height + additional_from_nodes) - 1) * HASHSIZE }; - dbg!(new_byte_count / 32); let mut bytes = vec![0; new_byte_count]; let mut flags = vec![true; to_nodes]; @@ -23,53 +22,45 @@ fn grow_merkle_cache( let leaf_level = from_height - 1; // Loop through all internal levels of the tree (skipping the final, leaves level). - for i in 0..from_height - 1 as usize { + for i in 0..from_height as usize { // If we're on the leaf slice, grab the first byte and all the of the bytes after that. // This is required because we can have an arbitrary number of bytes at the leaf level // (e.g., the case where there are subtrees as leaves). // // If we're not on a leaf level, the number of nodes is fixed and known. - let old_slice = if i == leaf_level { - old_bytes.get(first_byte_at_height(i)..) + let (byte_slice, flag_slice) = if i == leaf_level { + ( + old_bytes.get(first_byte_at_height(i)..)?, + old_flags.get(first_node_at_height(i)..)?, + ) } else { - old_bytes.get(byte_range_at_height(i)) - }?; + ( + old_bytes.get(byte_range_at_height(i))?, + old_flags.get(node_range_at_height(i))? + ) + }; - let new_slice = bytes + bytes .get_mut(byte_range_at_height(i + to_height - from_height))? - .get_mut(0..old_slice.len())?; - - new_slice.copy_from_slice(old_slice); + .get_mut(0..byte_slice.len())? + .copy_from_slice(byte_slice); + flags + .get_mut(node_range_at_height(i + to_height - from_height))? + .get_mut(0..flag_slice.len())? + .copy_from_slice(flag_slice); } - Some(bytes) -} - -/* -fn copy_bytes( - from_range: Range, - to_range: Range, - from: &[u8], - to: &mut Vec, -) -> Option<()> { - let from_slice = from.get(node_range_to_byte_range(from_range)); - - let to_slice = to - .get_mut(byte_range_at_height(i + to_height - from_height))? - .get_mut(0..old_slice.len())?; - - Ok(()) -} -*/ - -fn node_range_to_byte_range(node_range: Range) -> Range { - node_range.start * HASHSIZE..node_range.end * HASHSIZE + Some((bytes, flags)) } fn byte_range_at_height(h: usize) -> Range { first_byte_at_height(h)..last_node_at_height(h) * HASHSIZE } +fn node_range_at_height(h: usize) -> Range { + first_node_at_height(h)..last_node_at_height(h) +} + fn first_byte_at_height(h: usize) -> usize { first_node_at_height(h) * HASHSIZE } @@ -87,14 +78,14 @@ mod test { use super::*; #[test] - fn can_grow() { - let from: usize = 7; + fn can_grow_three_levels() { + let from: usize = 1; let to: usize = 15; let old_bytes = vec![42; from * HASHSIZE]; let old_flags = vec![false; from]; - let new = grow_merkle_cache( + let (new_bytes, new_flags) = grow_merkle_cache( &old_bytes, &old_flags, (from + 1).trailing_zeros() as usize, @@ -102,28 +93,101 @@ mod test { ) .unwrap(); - println!("{:?}", new); - let mut expected = vec![]; + let mut expected_bytes = vec![]; + let mut expected_flags = vec![]; // First level - expected.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(true); // Second level - expected.append(&mut vec![42; 32]); - expected.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(true); + expected_flags.push(true); // Third level - expected.append(&mut vec![42; 32]); - expected.append(&mut vec![42; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); // Fourth level - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); - expected.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(false); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); - assert_eq!(expected, new); + assert_eq!(expected_bytes, new_bytes); + assert_eq!(expected_flags, new_flags); + } + + #[test] + fn can_grow_one_level() { + let from: usize = 7; + let to: usize = 15; + + let old_bytes = vec![42; from * HASHSIZE]; + let old_flags = vec![false; from]; + + let (new_bytes, new_flags) = grow_merkle_cache( + &old_bytes, + &old_flags, + (from + 1).trailing_zeros() as usize, + (to + 1).trailing_zeros() as usize, + ) + .unwrap(); + + let mut expected_bytes = vec![]; + let mut expected_flags = vec![]; + // First level + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(true); + // Second level + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(false); + expected_flags.push(true); + // Third level + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(false); + expected_flags.push(false); + expected_flags.push(true); + expected_flags.push(true); + // Fourth level + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![42; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_bytes.append(&mut vec![0; 32]); + expected_flags.push(false); + expected_flags.push(false); + expected_flags.push(false); + expected_flags.push(false); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + expected_flags.push(true); + + assert_eq!(expected_bytes, new_bytes); + assert_eq!(expected_flags, new_flags); } } diff --git a/eth2/utils/ssz/src/cached_tree_hash/tests.rs b/eth2/utils/ssz/src/cached_tree_hash/tests.rs index d784a08890..9b8e81bc93 100644 --- a/eth2/utils/ssz/src/cached_tree_hash/tests.rs +++ b/eth2/utils/ssz/src/cached_tree_hash/tests.rs @@ -1,5 +1,5 @@ +#![cfg(test)] use super::*; -use crate::Encodable; use int_to_bytes::{int_to_bytes32, int_to_bytes8}; #[derive(Clone, Debug)]