Unify tree hash methods
This commit is contained in:
parent
93f3fc858d
commit
d311b48a9f
@ -17,7 +17,7 @@ pub enum Error {
|
|||||||
UnableToObtainSlices,
|
UnableToObtainSlices,
|
||||||
UnableToGrowMerkleTree,
|
UnableToGrowMerkleTree,
|
||||||
UnableToShrinkMerkleTree,
|
UnableToShrinkMerkleTree,
|
||||||
ShouldNeverBePacked(ItemType),
|
ShouldNeverBePacked(TreeHashType),
|
||||||
BytesAreNotEvenChunks(usize),
|
BytesAreNotEvenChunks(usize),
|
||||||
NoModifiedFieldForChunk(usize),
|
NoModifiedFieldForChunk(usize),
|
||||||
NoBytesForChunk(usize),
|
NoBytesForChunk(usize),
|
||||||
@ -31,15 +31,9 @@ pub trait CachedTreeHash<T>: CachedTreeHashSubTree<T> + Sized {
|
|||||||
fn clone_without_tree_hash_cache(&self) -> Self;
|
fn clone_without_tree_hash_cache(&self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CachedTreeHashSubTree<Item> {
|
pub trait CachedTreeHashSubTree<Item>: TreeHash {
|
||||||
fn item_type() -> ItemType;
|
|
||||||
|
|
||||||
fn btree_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error>;
|
fn btree_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error>;
|
||||||
|
|
||||||
fn packed_encoding(&self) -> Result<Vec<u8>, Error>;
|
|
||||||
|
|
||||||
fn packing_factor() -> usize;
|
|
||||||
|
|
||||||
fn new_cache(&self) -> Result<TreeHashCache, Error>;
|
fn new_cache(&self) -> Result<TreeHashCache, Error>;
|
||||||
|
|
||||||
fn update_cache(
|
fn update_cache(
|
||||||
|
@ -5,10 +5,6 @@ use ssz::ssz_encode;
|
|||||||
mod vec;
|
mod vec;
|
||||||
|
|
||||||
impl CachedTreeHashSubTree<u64> for u64 {
|
impl CachedTreeHashSubTree<u64> for u64 {
|
||||||
fn item_type() -> ItemType {
|
|
||||||
ItemType::Basic
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
Ok(TreeHashCache::from_bytes(
|
Ok(TreeHashCache::from_bytes(
|
||||||
merkleize(ssz_encode(self)),
|
merkleize(ssz_encode(self)),
|
||||||
@ -20,14 +16,6 @@ impl CachedTreeHashSubTree<u64> for u64 {
|
|||||||
BTreeOverlay::from_lengths(chunk_offset, vec![1])
|
BTreeOverlay::from_lengths(chunk_offset, vec![1])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packed_encoding(&self) -> Result<Vec<u8>, Error> {
|
|
||||||
Ok(ssz_encode(self))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn packing_factor() -> usize {
|
|
||||||
HASHSIZE / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_cache(
|
fn update_cache(
|
||||||
&self,
|
&self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
@ -2,18 +2,14 @@ use super::*;
|
|||||||
|
|
||||||
impl<T> CachedTreeHashSubTree<Vec<T>> for Vec<T>
|
impl<T> CachedTreeHashSubTree<Vec<T>> for Vec<T>
|
||||||
where
|
where
|
||||||
T: CachedTreeHashSubTree<T>,
|
T: CachedTreeHashSubTree<T> + TreeHash,
|
||||||
{
|
{
|
||||||
fn item_type() -> ItemType {
|
|
||||||
ItemType::List
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
match T::item_type() {
|
match T::tree_hash_type() {
|
||||||
ItemType::Basic => {
|
TreeHashType::Basic => {
|
||||||
TreeHashCache::from_bytes(merkleize(get_packed_leaves(self)?), false)
|
TreeHashCache::from_bytes(merkleize(get_packed_leaves(self)?), false)
|
||||||
}
|
}
|
||||||
ItemType::Composite | ItemType::List => {
|
TreeHashType::Composite | TreeHashType::List => {
|
||||||
let subtrees = self
|
let subtrees = self
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| TreeHashCache::new(item))
|
.map(|item| TreeHashCache::new(item))
|
||||||
@ -25,9 +21,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn btree_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error> {
|
fn btree_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error> {
|
||||||
let lengths = match T::item_type() {
|
let lengths = match T::tree_hash_type() {
|
||||||
ItemType::Basic => vec![1; self.len() / T::packing_factor()],
|
TreeHashType::Basic => vec![1; self.len() / T::tree_hash_packing_factor()],
|
||||||
ItemType::Composite | ItemType::List => {
|
TreeHashType::Composite | TreeHashType::List => {
|
||||||
let mut lengths = vec![];
|
let mut lengths = vec![];
|
||||||
|
|
||||||
for item in self {
|
for item in self {
|
||||||
@ -41,14 +37,6 @@ where
|
|||||||
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packed_encoding(&self) -> Result<Vec<u8>, Error> {
|
|
||||||
Err(Error::ShouldNeverBePacked(Self::item_type()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn packing_factor() -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_cache(
|
fn update_cache(
|
||||||
&self,
|
&self,
|
||||||
other: &Vec<T>,
|
other: &Vec<T>,
|
||||||
@ -93,8 +81,8 @@ where
|
|||||||
cache.splice(old_offset_handler.chunk_range(), modified_cache);
|
cache.splice(old_offset_handler.chunk_range(), modified_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
match T::item_type() {
|
match T::tree_hash_type() {
|
||||||
ItemType::Basic => {
|
TreeHashType::Basic => {
|
||||||
let leaves = get_packed_leaves(self)?;
|
let leaves = get_packed_leaves(self)?;
|
||||||
|
|
||||||
for (i, chunk) in offset_handler.iter_leaf_nodes().enumerate() {
|
for (i, chunk) in offset_handler.iter_leaf_nodes().enumerate() {
|
||||||
@ -109,7 +97,7 @@ where
|
|||||||
TreeHashCache::from_bytes(leaves, true)?,
|
TreeHashCache::from_bytes(leaves, true)?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ItemType::Composite | ItemType::List => {
|
TreeHashType::Composite | TreeHashType::List => {
|
||||||
let mut i = offset_handler.num_leaf_nodes;
|
let mut i = offset_handler.num_leaf_nodes;
|
||||||
for &start_chunk in offset_handler.iter_leaf_nodes().rev() {
|
for &start_chunk in offset_handler.iter_leaf_nodes().rev() {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
@ -170,13 +158,13 @@ fn get_packed_leaves<T>(vec: &Vec<T>) -> Result<Vec<u8>, Error>
|
|||||||
where
|
where
|
||||||
T: CachedTreeHashSubTree<T>,
|
T: CachedTreeHashSubTree<T>,
|
||||||
{
|
{
|
||||||
let num_packed_bytes = (BYTES_PER_CHUNK / T::packing_factor()) * vec.len();
|
let num_packed_bytes = (BYTES_PER_CHUNK / T::tree_hash_packing_factor()) * vec.len();
|
||||||
let num_leaves = num_sanitized_leaves(num_packed_bytes);
|
let num_leaves = num_sanitized_leaves(num_packed_bytes);
|
||||||
|
|
||||||
let mut packed = Vec::with_capacity(num_leaves * HASHSIZE);
|
let mut packed = Vec::with_capacity(num_leaves * HASHSIZE);
|
||||||
|
|
||||||
for item in vec {
|
for item in vec {
|
||||||
packed.append(&mut item.packed_encoding()?);
|
packed.append(&mut item.tree_hash_packed_encoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(sanitise_bytes(packed))
|
Ok(sanitise_bytes(packed))
|
||||||
|
@ -5,8 +5,11 @@ pub const BYTES_PER_CHUNK: usize = 32;
|
|||||||
pub const HASHSIZE: usize = 32;
|
pub const HASHSIZE: usize = 32;
|
||||||
pub const MERKLE_HASH_CHUNCK: usize = 2 * BYTES_PER_CHUNK;
|
pub const MERKLE_HASH_CHUNCK: usize = 2 * BYTES_PER_CHUNK;
|
||||||
|
|
||||||
|
pub use cached_tree_hash::CachedTreeHashSubTree;
|
||||||
|
pub use standard_tree_hash::TreeHash;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum ItemType {
|
pub enum TreeHashType {
|
||||||
Basic,
|
Basic,
|
||||||
List,
|
List,
|
||||||
Composite,
|
Composite,
|
||||||
|
@ -4,23 +4,29 @@ use int_to_bytes::int_to_bytes32;
|
|||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
|
|
||||||
pub trait TreeHash {
|
pub trait TreeHash {
|
||||||
fn tree_hash_item_type() -> ItemType;
|
fn tree_hash_type() -> TreeHashType;
|
||||||
|
|
||||||
fn tree_hash_packed_encoding(&self) -> Vec<u8>;
|
fn tree_hash_packed_encoding(&self) -> Vec<u8>;
|
||||||
|
|
||||||
fn hash_tree_root(&self) -> Vec<u8>;
|
fn tree_hash_packing_factor() -> usize;
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for u64 {
|
impl TreeHash for u64 {
|
||||||
fn tree_hash_item_type() -> ItemType {
|
fn tree_hash_type() -> TreeHashType {
|
||||||
ItemType::Basic
|
TreeHashType::Basic
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||||
ssz_encode(self)
|
ssz_encode(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn tree_hash_packing_factor() -> usize {
|
||||||
|
HASHSIZE / 8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8> {
|
||||||
int_to_bytes32(*self)
|
int_to_bytes32(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,18 +35,23 @@ impl<T> TreeHash for Vec<T>
|
|||||||
where
|
where
|
||||||
T: TreeHash,
|
T: TreeHash,
|
||||||
{
|
{
|
||||||
fn tree_hash_item_type() -> ItemType {
|
fn tree_hash_type() -> TreeHashType {
|
||||||
ItemType::List
|
TreeHashType::List
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||||
unreachable!("List should never be packed.")
|
unreachable!("List should never be packed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn tree_hash_packing_factor() -> usize {
|
||||||
let leaves = match T::tree_hash_item_type() {
|
unreachable!("List should never be packed.")
|
||||||
ItemType::Basic => {
|
}
|
||||||
let mut leaves = vec![];
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8> {
|
||||||
|
let leaves = match T::tree_hash_type() {
|
||||||
|
TreeHashType::Basic => {
|
||||||
|
let mut leaves =
|
||||||
|
Vec::with_capacity((HASHSIZE / T::tree_hash_packing_factor()) * self.len());
|
||||||
|
|
||||||
for item in self {
|
for item in self {
|
||||||
leaves.append(&mut item.tree_hash_packed_encoding());
|
leaves.append(&mut item.tree_hash_packed_encoding());
|
||||||
@ -48,11 +59,11 @@ where
|
|||||||
|
|
||||||
leaves
|
leaves
|
||||||
}
|
}
|
||||||
ItemType::Composite | ItemType::List => {
|
TreeHashType::Composite | TreeHashType::List => {
|
||||||
let mut leaves = Vec::with_capacity(self.len() * HASHSIZE);
|
let mut leaves = Vec::with_capacity(self.len() * HASHSIZE);
|
||||||
|
|
||||||
for item in self {
|
for item in self {
|
||||||
leaves.append(&mut item.hash_tree_root())
|
leaves.append(&mut item.tree_hash_root())
|
||||||
}
|
}
|
||||||
|
|
||||||
leaves
|
leaves
|
||||||
|
@ -11,6 +11,29 @@ pub struct InternalCache {
|
|||||||
pub cache: Option<TreeHashCache>,
|
pub cache: Option<TreeHashCache>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TreeHash for InternalCache {
|
||||||
|
fn tree_hash_type() -> TreeHashType {
|
||||||
|
TreeHashType::Composite
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||||
|
unreachable!("Struct should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packing_factor() -> usize {
|
||||||
|
unreachable!("Struct should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8> {
|
||||||
|
let mut leaves = Vec::with_capacity(4 * HASHSIZE);
|
||||||
|
|
||||||
|
leaves.append(&mut self.a.tree_hash_root());
|
||||||
|
leaves.append(&mut self.b.tree_hash_root());
|
||||||
|
|
||||||
|
efficient_merkleize(&leaves)[0..32].to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CachedTreeHash<InternalCache> for InternalCache {
|
impl CachedTreeHash<InternalCache> for InternalCache {
|
||||||
fn update_internal_tree_hash_cache(mut self, mut old: Self) -> Result<(Self, Self), Error> {
|
fn update_internal_tree_hash_cache(mut self, mut old: Self) -> Result<(Self, Self), Error> {
|
||||||
let mut local_cache = old.cache;
|
let mut local_cache = old.cache;
|
||||||
@ -66,10 +89,6 @@ fn works_when_embedded() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CachedTreeHashSubTree<InternalCache> for InternalCache {
|
impl CachedTreeHashSubTree<InternalCache> for InternalCache {
|
||||||
fn item_type() -> ItemType {
|
|
||||||
ItemType::Composite
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
let tree = TreeHashCache::from_leaves_and_subtrees(
|
let tree = TreeHashCache::from_leaves_and_subtrees(
|
||||||
self,
|
self,
|
||||||
@ -88,14 +107,6 @@ impl CachedTreeHashSubTree<InternalCache> for InternalCache {
|
|||||||
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packed_encoding(&self) -> Result<Vec<u8>, Error> {
|
|
||||||
Err(Error::ShouldNeverBePacked(Self::item_type()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn packing_factor() -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_cache(
|
fn update_cache(
|
||||||
&self,
|
&self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
@ -134,31 +145,31 @@ pub struct Inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeHash for Inner {
|
impl TreeHash for Inner {
|
||||||
fn tree_hash_item_type() -> ItemType {
|
fn tree_hash_type() -> TreeHashType {
|
||||||
ItemType::Composite
|
TreeHashType::Composite
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||||
unreachable!("Struct should never be packed.")
|
unreachable!("Struct should never be packed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_tree_root(&self) -> Vec<u8> {
|
fn tree_hash_packing_factor() -> usize {
|
||||||
|
unreachable!("Struct should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8> {
|
||||||
let mut leaves = Vec::with_capacity(4 * HASHSIZE);
|
let mut leaves = Vec::with_capacity(4 * HASHSIZE);
|
||||||
|
|
||||||
leaves.append(&mut self.a.hash_tree_root());
|
leaves.append(&mut self.a.tree_hash_root());
|
||||||
leaves.append(&mut self.b.hash_tree_root());
|
leaves.append(&mut self.b.tree_hash_root());
|
||||||
leaves.append(&mut self.c.hash_tree_root());
|
leaves.append(&mut self.c.tree_hash_root());
|
||||||
leaves.append(&mut self.d.hash_tree_root());
|
leaves.append(&mut self.d.tree_hash_root());
|
||||||
|
|
||||||
efficient_merkleize(&leaves)[0..32].to_vec()
|
efficient_merkleize(&leaves)[0..32].to_vec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedTreeHashSubTree<Inner> for Inner {
|
impl CachedTreeHashSubTree<Inner> for Inner {
|
||||||
fn item_type() -> ItemType {
|
|
||||||
ItemType::Composite
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
let tree = TreeHashCache::from_leaves_and_subtrees(
|
let tree = TreeHashCache::from_leaves_and_subtrees(
|
||||||
self,
|
self,
|
||||||
@ -184,14 +195,6 @@ impl CachedTreeHashSubTree<Inner> for Inner {
|
|||||||
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packed_encoding(&self) -> Result<Vec<u8>, Error> {
|
|
||||||
Err(Error::ShouldNeverBePacked(Self::item_type()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn packing_factor() -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_cache(
|
fn update_cache(
|
||||||
&self,
|
&self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
@ -226,11 +229,31 @@ pub struct Outer {
|
|||||||
pub c: u64,
|
pub c: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedTreeHashSubTree<Outer> for Outer {
|
impl TreeHash for Outer {
|
||||||
fn item_type() -> ItemType {
|
fn tree_hash_type() -> TreeHashType {
|
||||||
ItemType::Composite
|
TreeHashType::Composite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||||
|
unreachable!("Struct should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packing_factor() -> usize {
|
||||||
|
unreachable!("Struct should never be packed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Vec<u8> {
|
||||||
|
let mut leaves = Vec::with_capacity(4 * HASHSIZE);
|
||||||
|
|
||||||
|
leaves.append(&mut self.a.tree_hash_root());
|
||||||
|
leaves.append(&mut self.b.tree_hash_root());
|
||||||
|
leaves.append(&mut self.c.tree_hash_root());
|
||||||
|
|
||||||
|
efficient_merkleize(&leaves)[0..32].to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CachedTreeHashSubTree<Outer> for Outer {
|
||||||
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
fn new_cache(&self) -> Result<TreeHashCache, Error> {
|
||||||
let tree = TreeHashCache::from_leaves_and_subtrees(
|
let tree = TreeHashCache::from_leaves_and_subtrees(
|
||||||
self,
|
self,
|
||||||
@ -254,14 +277,6 @@ impl CachedTreeHashSubTree<Outer> for Outer {
|
|||||||
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
BTreeOverlay::from_lengths(chunk_offset, lengths)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packed_encoding(&self) -> Result<Vec<u8>, Error> {
|
|
||||||
Err(Error::ShouldNeverBePacked(Self::item_type()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn packing_factor() -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_cache(
|
fn update_cache(
|
||||||
&self,
|
&self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
@ -481,7 +496,7 @@ fn test_u64_vec_modifications(original: Vec<u64>, modified: Vec<u64>) {
|
|||||||
mix_in_length(&mut expected[0..HASHSIZE], modified.len());
|
mix_in_length(&mut expected[0..HASHSIZE], modified.len());
|
||||||
|
|
||||||
assert_eq!(expected, modified_cache);
|
assert_eq!(expected, modified_cache);
|
||||||
assert_eq!(&expected[0..32], &modified.hash_tree_root()[..]);
|
assert_eq!(&expected[0..32], &modified.tree_hash_root()[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -604,7 +619,7 @@ fn test_inner_vec_modifications(original: Vec<Inner>, modified: Vec<Inner>, refe
|
|||||||
|
|
||||||
// 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);
|
||||||
assert_eq!(&expected[0..32], &modified.hash_tree_root()[..]);
|
assert_eq!(&expected[0..32], &modified.tree_hash_root()[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user