Fix failing tree hash tests
This commit is contained in:
parent
e0104e6199
commit
fc17d5fea4
@ -13,9 +13,9 @@ const MERKLE_HASH_CHUNCK: usize = 2 * BYTES_PER_CHUNK;
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
LeavesAndSubtreesIncomplete(usize),
|
|
||||||
ShouldNotProduceOffsetHandler,
|
ShouldNotProduceOffsetHandler,
|
||||||
NoFirstNode,
|
NoFirstNode,
|
||||||
|
NoBytesForRoot,
|
||||||
BytesAreNotEvenChunks(usize),
|
BytesAreNotEvenChunks(usize),
|
||||||
NoModifiedFieldForChunk(usize),
|
NoModifiedFieldForChunk(usize),
|
||||||
NoBytesForChunk(usize),
|
NoBytesForChunk(usize),
|
||||||
@ -25,7 +25,7 @@ pub enum Error {
|
|||||||
pub trait CachedTreeHash {
|
pub trait CachedTreeHash {
|
||||||
type Item: CachedTreeHash;
|
type Item: CachedTreeHash;
|
||||||
|
|
||||||
fn leaves_and_subtrees(&self) -> Vec<u8>;
|
fn build_tree_hash_cache(&self) -> Result<TreeHashCache, Error>;
|
||||||
|
|
||||||
/// Return the number of bytes when this element is encoded as raw SSZ _without_ length
|
/// Return the number of bytes when this element is encoded as raw SSZ _without_ length
|
||||||
/// prefixes.
|
/// prefixes.
|
||||||
@ -60,42 +60,44 @@ impl TreeHashCache {
|
|||||||
where
|
where
|
||||||
T: CachedTreeHash,
|
T: CachedTreeHash,
|
||||||
{
|
{
|
||||||
Self::from_leaves_and_subtrees(item.leaves_and_subtrees(), OffsetHandler::new(item, 0)?)
|
item.build_tree_hash_cache()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_leaves_and_subtrees(
|
pub fn from_leaves_and_subtrees<T>(
|
||||||
mut leaves_and_subtrees: Vec<u8>,
|
item: &T,
|
||||||
offset_handler: OffsetHandler,
|
leaves_and_subtrees: Vec<Self>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error>
|
||||||
// Pad the leaves with zeros if the number of immediate leaf-nodes (without recursing into
|
where
|
||||||
// sub-trees) is not an even power-of-two.
|
T: CachedTreeHash,
|
||||||
pad_for_leaf_count(offset_handler.num_leaf_nodes, &mut leaves_and_subtrees);
|
{
|
||||||
|
let offset_handler = OffsetHandler::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
|
// 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.
|
// 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 internal_node_bytes = offset_handler.num_internal_nodes * BYTES_PER_CHUNK;
|
||||||
let mut cache = Vec::with_capacity(internal_node_bytes + leaves_and_subtrees.len());
|
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);
|
cache.resize(internal_node_bytes, 0);
|
||||||
cache.append(&mut leaves_and_subtrees);
|
|
||||||
|
|
||||||
dbg!(cache.len() / BYTES_PER_CHUNK);
|
// Allocate enough bytes to store all the leaves.
|
||||||
|
let mut leaves = Vec::with_capacity(offset_handler.num_leaf_nodes * HASHSIZE);
|
||||||
|
|
||||||
// Concat all the leaves into one big byte array, ready for `merkleize`.
|
// Iterate through all of the leaves/subtrees, adding their root as a leaf node and then
|
||||||
let mut leaves = vec![];
|
// concatenating their merkle trees.
|
||||||
for leaf_chunk in offset_handler.iter_leaf_nodes() {
|
for t in leaves_and_subtrees {
|
||||||
let start = leaf_chunk * BYTES_PER_CHUNK;
|
leaves.append(&mut t.root()?);
|
||||||
let end = start + BYTES_PER_CHUNK;
|
cache.append(&mut t.into_merkle_tree());
|
||||||
|
|
||||||
dbg!(end);
|
|
||||||
dbg!(cache.len());
|
|
||||||
|
|
||||||
leaves.extend_from_slice(
|
|
||||||
cache
|
|
||||||
.get(start..end)
|
|
||||||
.ok_or_else(|| Error::LeavesAndSubtreesIncomplete(*leaf_chunk))?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// 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`.
|
// internal nodes created earlier with the internal nodes generated by `merkleize`.
|
||||||
let mut merkleized = merkleize(leaves);
|
let mut merkleized = merkleize(leaves);
|
||||||
@ -108,6 +110,17 @@ impl TreeHashCache {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bytes_len(&self) -> usize {
|
||||||
|
self.cache.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root(&self) -> Result<Vec<u8>, Error> {
|
||||||
|
self.cache
|
||||||
|
.get(0..HASHSIZE)
|
||||||
|
.ok_or_else(|| Error::NoBytesForRoot)
|
||||||
|
.and_then(|slice| Ok(slice.to_vec()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, Error> {
|
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, Error> {
|
||||||
if bytes.len() % BYTES_PER_CHUNK > 0 {
|
if bytes.len() % BYTES_PER_CHUNK > 0 {
|
||||||
return Err(Error::BytesAreNotEvenChunks(bytes.len()));
|
return Err(Error::BytesAreNotEvenChunks(bytes.len()));
|
||||||
@ -195,6 +208,10 @@ impl TreeHashCache {
|
|||||||
|
|
||||||
Ok(hash(children))
|
Ok(hash(children))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_merkle_tree(self) -> Vec<u8> {
|
||||||
|
self.cache
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children(parent: usize) -> (usize, usize) {
|
fn children(parent: usize) -> (usize, usize) {
|
||||||
@ -205,6 +222,7 @@ fn num_nodes(num_leaves: usize) -> usize {
|
|||||||
2 * num_leaves - 1
|
2 * num_leaves - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct OffsetHandler {
|
pub struct OffsetHandler {
|
||||||
num_internal_nodes: usize,
|
num_internal_nodes: usize,
|
||||||
num_leaf_nodes: usize,
|
num_leaf_nodes: usize,
|
||||||
|
@ -4,8 +4,8 @@ use crate::{ssz_encode, Encodable};
|
|||||||
impl CachedTreeHash for u64 {
|
impl CachedTreeHash for u64 {
|
||||||
type Item = Self;
|
type Item = Self;
|
||||||
|
|
||||||
fn leaves_and_subtrees(&self) -> Vec<u8> {
|
fn build_tree_hash_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
merkleize(ssz_encode(self))
|
Ok(TreeHashCache::from_bytes(merkleize(ssz_encode(self)))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_bytes(&self) -> usize {
|
fn num_bytes(&self) -> usize {
|
||||||
|
@ -12,15 +12,18 @@ pub struct Inner {
|
|||||||
impl CachedTreeHash for Inner {
|
impl CachedTreeHash for Inner {
|
||||||
type Item = Self;
|
type Item = Self;
|
||||||
|
|
||||||
fn leaves_and_subtrees(&self) -> Vec<u8> {
|
fn build_tree_hash_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
let mut leaves_and_subtrees = vec![];
|
let tree = TreeHashCache::from_leaves_and_subtrees(
|
||||||
|
self,
|
||||||
|
vec![
|
||||||
|
self.a.build_tree_hash_cache()?,
|
||||||
|
self.b.build_tree_hash_cache()?,
|
||||||
|
self.c.build_tree_hash_cache()?,
|
||||||
|
self.d.build_tree_hash_cache()?,
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
|
||||||
leaves_and_subtrees.append(&mut self.a.leaves_and_subtrees());
|
Ok(tree)
|
||||||
leaves_and_subtrees.append(&mut self.b.leaves_and_subtrees());
|
|
||||||
leaves_and_subtrees.append(&mut self.c.leaves_and_subtrees());
|
|
||||||
leaves_and_subtrees.append(&mut self.d.leaves_and_subtrees());
|
|
||||||
|
|
||||||
leaves_and_subtrees
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_bytes(&self) -> usize {
|
fn num_bytes(&self) -> usize {
|
||||||
@ -94,14 +97,17 @@ pub struct Outer {
|
|||||||
impl CachedTreeHash for Outer {
|
impl CachedTreeHash for Outer {
|
||||||
type Item = Self;
|
type Item = Self;
|
||||||
|
|
||||||
fn leaves_and_subtrees(&self) -> Vec<u8> {
|
fn build_tree_hash_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
let mut leaves_and_subtrees = vec![];
|
let tree = TreeHashCache::from_leaves_and_subtrees(
|
||||||
|
self,
|
||||||
|
vec![
|
||||||
|
self.a.build_tree_hash_cache()?,
|
||||||
|
self.b.build_tree_hash_cache()?,
|
||||||
|
self.c.build_tree_hash_cache()?,
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
|
||||||
leaves_and_subtrees.append(&mut self.a.leaves_and_subtrees());
|
Ok(tree)
|
||||||
leaves_and_subtrees.append(&mut self.b.leaves_and_subtrees());
|
|
||||||
leaves_and_subtrees.append(&mut self.c.leaves_and_subtrees());
|
|
||||||
|
|
||||||
leaves_and_subtrees
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_bytes(&self) -> usize {
|
fn num_bytes(&self) -> usize {
|
||||||
@ -193,10 +199,8 @@ fn partial_modification_to_inner_struct() {
|
|||||||
..original_outer.clone()
|
..original_outer.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("AAAAAAAAA");
|
|
||||||
// Perform a differential hash
|
// Perform a differential hash
|
||||||
let mut cache_struct = TreeHashCache::new(&original_outer).unwrap();
|
let mut cache_struct = TreeHashCache::new(&original_outer).unwrap();
|
||||||
println!("BBBBBBBBBB");
|
|
||||||
|
|
||||||
modified_outer
|
modified_outer
|
||||||
.cached_hash_tree_root(&original_outer, &mut cache_struct, 0)
|
.cached_hash_tree_root(&original_outer, &mut cache_struct, 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user