Add new build method for cached hashes

This commit is contained in:
Paul Hauner 2019-03-29 00:47:42 +11:00
parent 40bfd5a6c7
commit 7b05c506df
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
2 changed files with 46 additions and 31 deletions

View File

@ -44,6 +44,39 @@ impl Into<Vec<u8>> for TreeHashCache {
}
impl TreeHashCache {
pub fn new(mut leaves_and_subtrees: Vec<u8>, offset_handler: OffsetHandler) -> Option<Self> {
if leaves_and_subtrees.len() % BYTES_PER_CHUNK != 0 {
return None;
}
// 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 mut cache = Vec::with_capacity(internal_node_bytes + leaves_and_subtrees.len());
cache.resize(internal_node_bytes, 0);
cache.append(&mut leaves_and_subtrees);
// Concat all the leaves into one big byte array, ready for `merkleize`.
let mut leaves = vec![];
for leaf_chunk in offset_handler.iter_leaf_nodes() {
let start = leaf_chunk * BYTES_PER_CHUNK;
let end = start + BYTES_PER_CHUNK;
leaves.extend_from_slice(cache.get(start..end)?);
}
// 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);
Some(Self {
chunk_modified: vec![false; cache.len() / BYTES_PER_CHUNK],
cache,
})
}
pub fn from_bytes(bytes: Vec<u8>) -> Option<Self> {
if bytes.len() % BYTES_PER_CHUNK > 0 {
return None;

View File

@ -13,28 +13,18 @@ impl CachedTreeHash for Inner {
type Item = Self;
fn build_cache_bytes(&self) -> Vec<u8> {
let cache_a = self.a.build_cache_bytes();
let cache_b = self.b.build_cache_bytes();
let cache_c = self.c.build_cache_bytes();
let cache_d = self.d.build_cache_bytes();
let mut leaves_and_subtrees = vec![];
let mut leaves = vec![];
leaves.extend_from_slice(&cache_a[0..32].to_vec());
leaves.extend_from_slice(&cache_b[0..32].to_vec());
leaves.extend_from_slice(&cache_c[0..32].to_vec());
leaves.extend_from_slice(&cache_d[0..32].to_vec());
// TODO: fix unwrap
let mut cache = TreeHashCache::from_bytes(merkleize(leaves)).unwrap();
leaves_and_subtrees.append(&mut self.a.build_cache_bytes());
leaves_and_subtrees.append(&mut self.b.build_cache_bytes());
leaves_and_subtrees.append(&mut self.c.build_cache_bytes());
leaves_and_subtrees.append(&mut self.d.build_cache_bytes());
// TODO: fix unwrap
let offset_handler = self.offset_handler(0).unwrap();
let mut iter = offset_handler.iter_leaf_nodes();
cache.single_chunk_splice(*iter.next().unwrap(), cache_a);
cache.single_chunk_splice(*iter.next().unwrap(), cache_b);
cache.single_chunk_splice(*iter.next().unwrap(), cache_c);
cache.single_chunk_splice(*iter.next().unwrap(), cache_d);
// TODO: fix unwrap
let cache = TreeHashCache::new(leaves_and_subtrees, offset_handler).unwrap();
cache.into()
}
@ -111,25 +101,17 @@ impl CachedTreeHash for Outer {
type Item = Self;
fn build_cache_bytes(&self) -> Vec<u8> {
let cache_a = self.a.build_cache_bytes();
let cache_b = self.b.build_cache_bytes();
let cache_c = self.c.build_cache_bytes();
let mut leaves_and_subtrees = vec![];
let mut leaves = vec![];
leaves.extend_from_slice(&cache_a[0..32].to_vec());
leaves.extend_from_slice(&cache_b[0..32].to_vec());
leaves.extend_from_slice(&cache_c[0..32].to_vec());
// TODO: fix unwrap
let mut cache = TreeHashCache::from_bytes(merkleize(leaves)).unwrap();
leaves_and_subtrees.append(&mut self.a.build_cache_bytes());
leaves_and_subtrees.append(&mut self.b.build_cache_bytes());
leaves_and_subtrees.append(&mut self.c.build_cache_bytes());
// TODO: fix unwrap
let offset_handler = self.offset_handler(0).unwrap();
let mut iter = offset_handler.iter_leaf_nodes();
cache.single_chunk_splice(*iter.next().unwrap(), cache_a);
cache.single_chunk_splice(*iter.next().unwrap(), cache_b);
cache.single_chunk_splice(*iter.next().unwrap(), cache_c);
// TODO: fix unwrap
let cache = TreeHashCache::new(leaves_and_subtrees, offset_handler).unwrap();
cache.into()
}