mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-17 12:58:31 +00:00
Add vector type to tree hashing
This commit is contained in:
@@ -9,7 +9,7 @@ where
|
||||
TreeHashType::Basic => {
|
||||
TreeHashCache::from_bytes(merkleize(get_packed_leaves(self)?), false)
|
||||
}
|
||||
TreeHashType::Composite | TreeHashType::List => {
|
||||
TreeHashType::Container | TreeHashType::List | TreeHashType::Vector => {
|
||||
let subtrees = self
|
||||
.iter()
|
||||
.map(|item| TreeHashCache::new(item))
|
||||
@@ -23,7 +23,7 @@ where
|
||||
fn tree_hash_cache_overlay(&self, chunk_offset: usize) -> Result<BTreeOverlay, Error> {
|
||||
let lengths = match T::tree_hash_type() {
|
||||
TreeHashType::Basic => vec![1; self.len() / T::tree_hash_packing_factor()],
|
||||
TreeHashType::Composite | TreeHashType::List => {
|
||||
TreeHashType::Container | TreeHashType::List | TreeHashType::Vector => {
|
||||
let mut lengths = vec![];
|
||||
|
||||
for item in self {
|
||||
@@ -97,7 +97,7 @@ where
|
||||
TreeHashCache::from_bytes(leaves, true)?,
|
||||
);
|
||||
}
|
||||
TreeHashType::Composite | TreeHashType::List => {
|
||||
TreeHashType::Container | TreeHashType::List | TreeHashType::Vector => {
|
||||
let mut i = offset_handler.num_leaf_nodes;
|
||||
for &start_chunk in offset_handler.iter_leaf_nodes().rev() {
|
||||
i -= 1;
|
||||
|
||||
@@ -13,8 +13,9 @@ pub use standard_tree_hash::{merkle_root, TreeHash};
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum TreeHashType {
|
||||
Basic,
|
||||
Vector,
|
||||
List,
|
||||
Composite,
|
||||
Container,
|
||||
}
|
||||
|
||||
fn num_sanitized_leaves(num_bytes: usize) -> usize {
|
||||
@@ -31,15 +32,15 @@ macro_rules! impl_tree_hash_for_ssz_bytes {
|
||||
($type: ident) => {
|
||||
impl tree_hash::TreeHash for $type {
|
||||
fn tree_hash_type() -> tree_hash::TreeHashType {
|
||||
tree_hash::TreeHashType::List
|
||||
tree_hash::TreeHashType::Vector
|
||||
}
|
||||
|
||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||
panic!("bytesN should never be packed.")
|
||||
unreachable!("Vector should never be packed.")
|
||||
}
|
||||
|
||||
fn tree_hash_packing_factor() -> usize {
|
||||
panic!("bytesN should never be packed.")
|
||||
unreachable!("Vector should never be packed.")
|
||||
}
|
||||
|
||||
fn tree_hash_root(&self) -> Vec<u8> {
|
||||
@@ -48,3 +49,26 @@ macro_rules! impl_tree_hash_for_ssz_bytes {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_vec_as_fixed_len {
|
||||
($type: ty) => {
|
||||
impl tree_hash::TreeHash for $type {
|
||||
fn tree_hash_type() -> tree_hash::TreeHashType {
|
||||
tree_hash::TreeHashType::Vector
|
||||
}
|
||||
|
||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||
unreachable!("Vector should never be packed.")
|
||||
}
|
||||
|
||||
fn tree_hash_packing_factor() -> usize {
|
||||
unreachable!("Vector should never be packed.")
|
||||
}
|
||||
|
||||
fn tree_hash_root(&self) -> Vec<u8> {
|
||||
tree_hash::standard_tree_hash::vec_tree_hash_root(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ use hashing::hash;
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use ssz::ssz_encode;
|
||||
|
||||
pub use impls::vec_tree_hash_root;
|
||||
|
||||
mod impls;
|
||||
|
||||
pub trait TreeHash {
|
||||
@@ -16,11 +18,18 @@ pub trait TreeHash {
|
||||
}
|
||||
|
||||
pub fn merkle_root(bytes: &[u8]) -> Vec<u8> {
|
||||
// TODO: replace this with a _more_ efficient fn which is more memory efficient.
|
||||
// TODO: replace this with a more memory efficient method.
|
||||
efficient_merkleize(&bytes)[0..32].to_vec()
|
||||
}
|
||||
|
||||
pub fn efficient_merkleize(bytes: &[u8]) -> Vec<u8> {
|
||||
// If the bytes are just one chunk (or less than one chunk) just return them.
|
||||
if bytes.len() <= HASHSIZE {
|
||||
let mut o = bytes.to_vec();
|
||||
o.resize(HASHSIZE, 0);
|
||||
return o;
|
||||
}
|
||||
|
||||
let leaves = num_sanitized_leaves(bytes.len());
|
||||
let nodes = num_nodes(leaves);
|
||||
let internal_nodes = nodes - leaves;
|
||||
@@ -29,10 +38,6 @@ pub fn efficient_merkleize(bytes: &[u8]) -> Vec<u8> {
|
||||
|
||||
let mut o: Vec<u8> = vec![0; internal_nodes * HASHSIZE];
|
||||
|
||||
if o.len() < HASHSIZE {
|
||||
o.resize(HASHSIZE, 0);
|
||||
}
|
||||
|
||||
o.append(&mut bytes.to_vec());
|
||||
|
||||
assert_eq!(o.len(), num_bytes);
|
||||
|
||||
@@ -50,7 +50,7 @@ impl TreeHash for [u8; 4] {
|
||||
|
||||
impl TreeHash for H256 {
|
||||
fn tree_hash_type() -> TreeHashType {
|
||||
TreeHashType::Basic
|
||||
TreeHashType::Vector
|
||||
}
|
||||
|
||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||
@@ -62,7 +62,7 @@ impl TreeHash for H256 {
|
||||
}
|
||||
|
||||
fn tree_hash_root(&self) -> Vec<u8> {
|
||||
ssz_encode(self)
|
||||
merkle_root(&ssz::ssz_encode(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,37 +83,43 @@ where
|
||||
}
|
||||
|
||||
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 {
|
||||
leaves.append(&mut item.tree_hash_packed_encoding());
|
||||
}
|
||||
|
||||
leaves
|
||||
}
|
||||
TreeHashType::Composite | TreeHashType::List => {
|
||||
let mut leaves = Vec::with_capacity(self.len() * HASHSIZE);
|
||||
|
||||
for item in self {
|
||||
leaves.append(&mut item.tree_hash_root())
|
||||
}
|
||||
|
||||
leaves
|
||||
}
|
||||
};
|
||||
|
||||
// Mix in the length
|
||||
let mut root_and_len = Vec::with_capacity(HASHSIZE * 2);
|
||||
root_and_len.append(&mut merkle_root(&leaves));
|
||||
root_and_len.append(&mut vec_tree_hash_root(self));
|
||||
root_and_len.append(&mut int_to_bytes32(self.len() as u64));
|
||||
|
||||
hash(&root_and_len)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vec_tree_hash_root<T>(vec: &[T]) -> Vec<u8>
|
||||
where
|
||||
T: TreeHash,
|
||||
{
|
||||
let leaves = match T::tree_hash_type() {
|
||||
TreeHashType::Basic => {
|
||||
let mut leaves =
|
||||
Vec::with_capacity((HASHSIZE / T::tree_hash_packing_factor()) * vec.len());
|
||||
|
||||
for item in vec {
|
||||
leaves.append(&mut item.tree_hash_packed_encoding());
|
||||
}
|
||||
|
||||
leaves
|
||||
}
|
||||
TreeHashType::Container | TreeHashType::List | TreeHashType::Vector => {
|
||||
let mut leaves = Vec::with_capacity(vec.len() * HASHSIZE);
|
||||
|
||||
for item in vec {
|
||||
leaves.append(&mut item.tree_hash_root())
|
||||
}
|
||||
|
||||
leaves
|
||||
}
|
||||
};
|
||||
|
||||
merkle_root(&leaves)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user