lighthouse/eth2/utils/tree_hash/src/impls.rs

167 lines
3.9 KiB
Rust
Raw Normal View History

2019-04-16 02:29:39 +00:00
use super::*;
2019-04-26 00:37:50 +00:00
use crate::merkleize::merkle_root;
2019-04-16 02:29:39 +00:00
use ethereum_types::H256;
2019-04-26 00:37:50 +00:00
use hashing::hash;
2019-04-25 23:55:03 +00:00
use int_to_bytes::int_to_bytes32;
2019-04-16 02:29:39 +00:00
macro_rules! impl_for_bitsize {
($type: ident, $bit_size: expr) => {
impl TreeHash for $type {
fn tree_hash_type() -> TreeHashType {
TreeHashType::Basic
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
2019-04-17 01:18:00 +00:00
self.to_le_bytes().to_vec()
2019-04-16 02:29:39 +00:00
}
fn tree_hash_packing_factor() -> usize {
HASHSIZE / ($bit_size / 8)
}
#[allow(clippy::cast_lossless)]
2019-04-16 02:29:39 +00:00
fn tree_hash_root(&self) -> Vec<u8> {
int_to_bytes32(*self as u64)
}
}
};
}
impl_for_bitsize!(u8, 8);
impl_for_bitsize!(u16, 16);
impl_for_bitsize!(u32, 32);
impl_for_bitsize!(u64, 64);
impl_for_bitsize!(usize, 64);
2019-04-17 01:18:00 +00:00
impl TreeHash for bool {
fn tree_hash_type() -> TreeHashType {
TreeHashType::Basic
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
(*self as u8).tree_hash_packed_encoding()
}
fn tree_hash_packing_factor() -> usize {
u8::tree_hash_packing_factor()
}
fn tree_hash_root(&self) -> Vec<u8> {
int_to_bytes32(*self as u64)
}
}
2019-04-16 02:29:39 +00:00
2019-04-16 04:14:38 +00:00
impl TreeHash for [u8; 4] {
fn tree_hash_type() -> TreeHashType {
TreeHashType::Vector
2019-04-16 04:14:38 +00:00
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
unreachable!("bytesN should never be packed.")
2019-04-16 04:14:38 +00:00
}
fn tree_hash_packing_factor() -> usize {
unreachable!("bytesN should never be packed.")
2019-04-16 04:14:38 +00:00
}
fn tree_hash_root(&self) -> Vec<u8> {
2019-04-17 01:18:00 +00:00
merkle_root(&self[..])
2019-04-16 04:14:38 +00:00
}
}
2019-04-16 02:29:39 +00:00
impl TreeHash for H256 {
fn tree_hash_type() -> TreeHashType {
2019-04-17 00:57:36 +00:00
TreeHashType::Vector
2019-04-16 02:29:39 +00:00
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
2019-04-17 01:18:00 +00:00
self.as_bytes().to_vec()
2019-04-16 02:29:39 +00:00
}
fn tree_hash_packing_factor() -> usize {
1
}
fn tree_hash_root(&self) -> Vec<u8> {
2019-04-17 01:18:00 +00:00
merkle_root(&self.as_bytes().to_vec())
2019-04-16 02:29:39 +00:00
}
}
macro_rules! impl_for_list {
($type: ty) => {
impl<T> TreeHash for $type
where
T: TreeHash,
{
fn tree_hash_type() -> TreeHashType {
TreeHashType::List
}
2019-04-16 02:29:39 +00:00
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
unreachable!("List should never be packed.")
}
2019-04-16 02:29:39 +00:00
fn tree_hash_packing_factor() -> usize {
unreachable!("List should never be packed.")
}
2019-04-16 02:29:39 +00:00
fn tree_hash_root(&self) -> Vec<u8> {
let mut root_and_len = Vec::with_capacity(HASHSIZE * 2);
root_and_len.append(&mut vec_tree_hash_root(self));
root_and_len.append(&mut int_to_bytes32(self.len() as u64));
2019-04-16 02:29:39 +00:00
hash(&root_and_len)
}
}
};
2019-04-17 00:57:36 +00:00
}
impl_for_list!(Vec<T>);
impl_for_list!(&[T]);
2019-04-17 00:57:36 +00:00
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());
2019-04-16 02:29:39 +00:00
2019-04-17 00:57:36 +00:00
for item in vec {
leaves.append(&mut item.tree_hash_packed_encoding());
2019-04-16 02:29:39 +00:00
}
2019-04-17 00:57:36 +00:00
leaves
}
TreeHashType::Container | TreeHashType::List | TreeHashType::Vector => {
let mut leaves = Vec::with_capacity(vec.len() * HASHSIZE);
2019-04-16 02:29:39 +00:00
2019-04-17 00:57:36 +00:00
for item in vec {
leaves.append(&mut item.tree_hash_root())
2019-04-16 02:29:39 +00:00
}
2019-04-17 00:57:36 +00:00
leaves
}
};
2019-04-16 02:29:39 +00:00
2019-04-17 00:57:36 +00:00
merkle_root(&leaves)
2019-04-16 02:29:39 +00:00
}
2019-04-16 04:14:38 +00:00
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bool() {
let mut true_bytes: Vec<u8> = vec![1];
true_bytes.append(&mut vec![0; 31]);
let false_bytes: Vec<u8> = vec![0; 32];
assert_eq!(true.tree_hash_root(), true_bytes);
assert_eq!(false.tree_hash_root(), false_bytes);
}
}