Fix failing grow tree test

This commit is contained in:
Paul Hauner 2019-04-13 17:21:50 +10:00
parent 42d6a39832
commit 1ce1fce03c
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
4 changed files with 129 additions and 81 deletions

View File

@ -1,9 +1,7 @@
use hashing::hash; use hashing::hash;
use std::fmt::Debug; use std::fmt::Debug;
use std::iter::IntoIterator;
use std::iter::Iterator; use std::iter::Iterator;
use std::ops::Range; use std::ops::Range;
use std::vec::Splice;
mod impls; mod impls;
mod resize; mod resize;
@ -21,7 +19,6 @@ pub enum Error {
BytesAreNotEvenChunks(usize), BytesAreNotEvenChunks(usize),
NoModifiedFieldForChunk(usize), NoModifiedFieldForChunk(usize),
NoBytesForChunk(usize), NoBytesForChunk(usize),
NoChildrenForHashing((usize, usize)),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -150,27 +147,11 @@ impl TreeHashCache {
let (bytes, bools) = replace_with.into_components(); let (bytes, bools) = replace_with.into_components();
// Update the `chunk_modified` vec, marking all spliced-in nodes as changed. // Update the `chunk_modified` vec, marking all spliced-in nodes as changed.
self.chunk_modified.splice( self.chunk_modified.splice(chunk_range.clone(), bools);
chunk_range.clone(), self.cache
bools, .splice(node_range_to_byte_range(chunk_range), bytes);
);
self.cache.splice(node_range_to_byte_range(chunk_range), bytes);
} }
/*
pub fn byte_splice(&mut self, chunk_range: Range<usize>, replace_with: Vec<u8>) {
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> { pub fn maybe_update_chunk(&mut self, chunk: usize, to: &[u8]) -> Result<(), Error> {
let start = chunk * BYTES_PER_CHUNK; let start = chunk * BYTES_PER_CHUNK;
let end = start + BYTES_PER_CHUNK; let end = start + BYTES_PER_CHUNK;

View File

@ -1,5 +1,6 @@
use super::resize::grow_merkle_cache;
use super::*; use super::*;
use crate::{ssz_encode, Encodable}; use crate::ssz_encode;
impl CachedTreeHash<u64> for u64 { impl CachedTreeHash<u64> for u64 {
fn item_type() -> ItemType { fn item_type() -> ItemType {
@ -112,8 +113,10 @@ where
) -> Result<usize, Error> { ) -> Result<usize, Error> {
let offset_handler = OffsetHandler::new(self, chunk)?; let offset_handler = OffsetHandler::new(self, chunk)?;
if self.len().next_power_of_two() != other.len().next_power_of_two() { if other.len().next_power_of_two() > self.len().next_power_of_two() {
panic!("not implemented: vary between power-of-two boundary"); //
} 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() { match T::item_type() {

View File

@ -1,12 +1,12 @@
use super::*; use super::*;
/// New vec is bigger than old vec. /// New vec is bigger than old vec.
fn grow_merkle_cache( pub fn grow_merkle_cache(
old_bytes: &[u8], old_bytes: &[u8],
old_flags: &[bool], old_flags: &[bool],
from_height: usize, from_height: usize,
to_height: usize, to_height: usize,
) -> Option<Vec<u8>> { ) -> Option<(Vec<u8>, Vec<bool>)> {
let to_nodes = (1 << to_height.next_power_of_two()) - 1; 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 // 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); let additional_from_nodes = old_bytes.len() / HASHSIZE - ((1 << from_height) - 1);
((1 << to_height + additional_from_nodes) - 1) * HASHSIZE ((1 << to_height + additional_from_nodes) - 1) * HASHSIZE
}; };
dbg!(new_byte_count / 32);
let mut bytes = vec![0; new_byte_count]; let mut bytes = vec![0; new_byte_count];
let mut flags = vec![true; to_nodes]; let mut flags = vec![true; to_nodes];
@ -23,53 +22,45 @@ fn grow_merkle_cache(
let leaf_level = from_height - 1; let leaf_level = from_height - 1;
// Loop through all internal levels of the tree (skipping the final, leaves level). // 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. // 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 // 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). // (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. // If we're not on a leaf level, the number of nodes is fixed and known.
let old_slice = if i == leaf_level { let (byte_slice, flag_slice) = if i == leaf_level {
old_bytes.get(first_byte_at_height(i)..) (
old_bytes.get(first_byte_at_height(i)..)?,
old_flags.get(first_node_at_height(i)..)?,
)
} else { } 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(byte_range_at_height(i + to_height - from_height))?
.get_mut(0..old_slice.len())?; .get_mut(0..byte_slice.len())?
.copy_from_slice(byte_slice);
new_slice.copy_from_slice(old_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) Some((bytes, flags))
}
/*
fn copy_bytes(
from_range: Range<usize>,
to_range: Range<usize>,
from: &[u8],
to: &mut Vec<u8>,
) -> 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<usize>) -> Range<usize> {
node_range.start * HASHSIZE..node_range.end * HASHSIZE
} }
fn byte_range_at_height(h: usize) -> Range<usize> { fn byte_range_at_height(h: usize) -> Range<usize> {
first_byte_at_height(h)..last_node_at_height(h) * HASHSIZE first_byte_at_height(h)..last_node_at_height(h) * HASHSIZE
} }
fn node_range_at_height(h: usize) -> Range<usize> {
first_node_at_height(h)..last_node_at_height(h)
}
fn first_byte_at_height(h: usize) -> usize { fn first_byte_at_height(h: usize) -> usize {
first_node_at_height(h) * HASHSIZE first_node_at_height(h) * HASHSIZE
} }
@ -87,14 +78,14 @@ mod test {
use super::*; use super::*;
#[test] #[test]
fn can_grow() { fn can_grow_three_levels() {
let from: usize = 7; let from: usize = 1;
let to: usize = 15; let to: usize = 15;
let old_bytes = vec![42; from * HASHSIZE]; let old_bytes = vec![42; from * HASHSIZE];
let old_flags = vec![false; from]; let old_flags = vec![false; from];
let new = grow_merkle_cache( let (new_bytes, new_flags) = grow_merkle_cache(
&old_bytes, &old_bytes,
&old_flags, &old_flags,
(from + 1).trailing_zeros() as usize, (from + 1).trailing_zeros() as usize,
@ -102,28 +93,101 @@ mod test {
) )
.unwrap(); .unwrap();
println!("{:?}", new); let mut expected_bytes = vec![];
let mut expected = vec![]; let mut expected_flags = vec![];
// First level // First level
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected_flags.push(true);
// Second level // Second level
expected.append(&mut vec![42; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected_flags.push(true);
expected_flags.push(true);
// Third level // Third level
expected.append(&mut vec![42; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![42; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.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 // Fourth level
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![42; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.append(&mut vec![0; 32]); expected_bytes.append(&mut vec![0; 32]);
expected.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);
} }
} }

View File

@ -1,5 +1,5 @@
#![cfg(test)]
use super::*; use super::*;
use crate::Encodable;
use int_to_bytes::{int_to_bytes32, int_to_bytes8}; use int_to_bytes::{int_to_bytes32, int_to_bytes8};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]