use super::*; #[derive(Debug, PartialEq, Clone)] pub struct TreeHashCache { cache: Vec, chunk_modified: Vec, } impl Into> for TreeHashCache { fn into(self) -> Vec { self.cache } } impl TreeHashCache { pub fn new(item: &T) -> Result where T: CachedTreeHash, { item.new_cache() } pub fn from_elems(cache: Vec, chunk_modified: Vec) -> Self { Self { cache, chunk_modified, } } pub fn from_leaves_and_subtrees( item: &T, leaves_and_subtrees: Vec, ) -> Result where T: CachedTreeHash, { let offset_handler = BTreeOverlay::new(item, 0)?; // Note how many leaves were provided. If is not a power-of-two, we'll need to pad it out // later. let num_provided_leaf_nodes = leaves_and_subtrees.len(); // Allocate enough bytes to store the internal nodes and the leaves and subtrees, then fill // all the to-be-built internal nodes with zeros and append the leaves and subtrees. let internal_node_bytes = offset_handler.num_internal_nodes * BYTES_PER_CHUNK; let leaves_and_subtrees_bytes = leaves_and_subtrees .iter() .fold(0, |acc, t| acc + t.bytes_len()); let mut cache = Vec::with_capacity(leaves_and_subtrees_bytes + internal_node_bytes); cache.resize(internal_node_bytes, 0); // Allocate enough bytes to store all the leaves. let mut leaves = Vec::with_capacity(offset_handler.num_leaf_nodes * HASHSIZE); // Iterate through all of the leaves/subtrees, adding their root as a leaf node and then // concatenating their merkle trees. for t in leaves_and_subtrees { leaves.append(&mut t.root()?); cache.append(&mut t.into_merkle_tree()); } // Pad the leaves to an even power-of-two, using zeros. pad_for_leaf_count(num_provided_leaf_nodes, &mut cache); // Merkleize the leaves, then split the leaf nodes off them. Then, replace all-zeros // internal nodes created earlier with the internal nodes generated by `merkleize`. let mut merkleized = merkleize(leaves); merkleized.split_off(internal_node_bytes); cache.splice(0..internal_node_bytes, merkleized); Ok(Self { chunk_modified: vec![false; cache.len() / BYTES_PER_CHUNK], cache, }) } pub fn from_bytes(bytes: Vec, initial_modified_state: bool) -> Result { if bytes.len() % BYTES_PER_CHUNK > 0 { return Err(Error::BytesAreNotEvenChunks(bytes.len())); } Ok(Self { chunk_modified: vec![initial_modified_state; bytes.len() / BYTES_PER_CHUNK], cache: bytes, }) } pub fn bytes_len(&self) -> usize { self.cache.len() } pub fn root(&self) -> Result, Error> { self.cache .get(0..HASHSIZE) .ok_or_else(|| Error::NoBytesForRoot) .and_then(|slice| Ok(slice.to_vec())) } pub fn splice(&mut self, chunk_range: Range, replace_with: Self) { 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); } 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; if !self.chunk_equals(chunk, to)? { self.cache .get_mut(start..end) .ok_or_else(|| Error::NoModifiedFieldForChunk(chunk))? .copy_from_slice(to); self.chunk_modified[chunk] = true; } Ok(()) } pub fn slices(&self, chunk_range: Range) -> Option<(&[u8], &[bool])> { Some(( self.cache.get(node_range_to_byte_range(&chunk_range))?, self.chunk_modified.get(chunk_range)?, )) } pub fn modify_chunk(&mut self, chunk: usize, to: &[u8]) -> Result<(), Error> { let start = chunk * BYTES_PER_CHUNK; let end = start + BYTES_PER_CHUNK; self.cache .get_mut(start..end) .ok_or_else(|| Error::NoBytesForChunk(chunk))? .copy_from_slice(to); self.chunk_modified[chunk] = true; Ok(()) } pub fn get_chunk(&self, chunk: usize) -> Result<&[u8], Error> { let start = chunk * BYTES_PER_CHUNK; let end = start + BYTES_PER_CHUNK; Ok(self .cache .get(start..end) .ok_or_else(|| Error::NoModifiedFieldForChunk(chunk))?) } pub fn chunk_equals(&mut self, chunk: usize, other: &[u8]) -> Result { Ok(self.get_chunk(chunk)? == other) } pub fn changed(&self, chunk: usize) -> Result { self.chunk_modified .get(chunk) .cloned() .ok_or_else(|| Error::NoModifiedFieldForChunk(chunk)) } pub fn either_modified(&self, children: (&usize, &usize)) -> Result { Ok(self.changed(*children.0)? | self.changed(*children.1)?) } pub fn hash_children(&self, children: (&usize, &usize)) -> Result, Error> { let mut child_bytes = Vec::with_capacity(BYTES_PER_CHUNK * 2); child_bytes.append(&mut self.get_chunk(*children.0)?.to_vec()); child_bytes.append(&mut self.get_chunk(*children.1)?.to_vec()); Ok(hash(&child_bytes)) } pub fn mix_in_length(&self, chunk: usize, length: usize) -> Result, Error> { let mut bytes = Vec::with_capacity(2 * BYTES_PER_CHUNK); bytes.append(&mut self.get_chunk(chunk)?.to_vec()); bytes.append(&mut int_to_bytes32(length as u64)); Ok(hash(&bytes)) } pub fn into_merkle_tree(self) -> Vec { self.cache } pub fn into_components(self) -> (Vec, Vec) { (self.cache, self.chunk_modified) } }