Add mix-in-len to cached tree hash
This commit is contained in:
parent
0632a00a48
commit
ab78a15313
@ -1,4 +1,5 @@
|
|||||||
use hashing::hash;
|
use hashing::hash;
|
||||||
|
use int_to_bytes::int_to_bytes32;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
@ -231,6 +232,15 @@ impl TreeHashCache {
|
|||||||
Ok(hash(&child_bytes))
|
Ok(hash(&child_bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mix_in_length(&self, chunk: usize, length: usize) -> Result<Vec<u8>, 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<u8> {
|
pub fn into_merkle_tree(self) -> Vec<u8> {
|
||||||
self.cache
|
self.cache
|
||||||
}
|
}
|
||||||
@ -300,6 +310,10 @@ impl OffsetHandler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root(&self) -> usize {
|
||||||
|
self.first_node
|
||||||
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> usize {
|
pub fn height(&self) -> usize {
|
||||||
self.num_leaf_nodes.trailing_zeros() as usize
|
self.num_leaf_nodes.trailing_zeros() as usize
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the root node or the length has changed, mix in the length of the list.
|
||||||
|
let root_node = offset_handler.root();
|
||||||
|
if cache.changed(root_node)? | (self.len() != other.len()) {
|
||||||
|
cache.modify_chunk(root_node, &cache.mix_in_length(root_node, self.len())?)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(offset_handler.next_node())
|
Ok(offset_handler.next_node())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,6 +343,13 @@ fn outer_builds() {
|
|||||||
assert_eq!(merkle, cache);
|
assert_eq!(merkle, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mix_in_length(root: &mut [u8], len: usize) {
|
||||||
|
let mut bytes = root.to_vec();
|
||||||
|
bytes.append(&mut int_to_bytes32(len as u64));
|
||||||
|
|
||||||
|
root.copy_from_slice(&hash(&bytes));
|
||||||
|
}
|
||||||
|
|
||||||
/// Generic test that covers:
|
/// Generic test that covers:
|
||||||
///
|
///
|
||||||
/// 1. Produce a new cache from `original`.
|
/// 1. Produce a new cache from `original`.
|
||||||
@ -367,7 +374,9 @@ fn test_u64_vec_modifications(original: Vec<u64>, modified: Vec<u64>) {
|
|||||||
data.append(&mut int_to_bytes8(*i));
|
data.append(&mut int_to_bytes8(*i));
|
||||||
}
|
}
|
||||||
let data = sanitise_bytes(data);
|
let data = sanitise_bytes(data);
|
||||||
let expected = merkleize(data);
|
let mut expected = merkleize(data);
|
||||||
|
|
||||||
|
mix_in_length(&mut expected[0..HASHSIZE], modified.len());
|
||||||
|
|
||||||
assert_eq!(expected, modified_cache);
|
assert_eq!(expected, modified_cache);
|
||||||
}
|
}
|
||||||
@ -490,6 +499,8 @@ fn test_inner_vec_modifications(original: Vec<Inner>, modified: Vec<Inner>, refe
|
|||||||
expected.append(&mut vec![0; HASHSIZE]);
|
expected.append(&mut vec![0; HASHSIZE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mix_in_length(&mut expected[0..HASHSIZE], modified.len());
|
||||||
|
|
||||||
// Compare the cached tree to the reference tree.
|
// Compare the cached tree to the reference tree.
|
||||||
assert_trees_eq(&expected, &modified_cache);
|
assert_trees_eq(&expected, &modified_cache);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user