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

133 lines
3.1 KiB
Rust
Raw Normal View History

2019-04-16 02:29:39 +00:00
use super::*;
use ethereum_types::H256;
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> {
ssz_encode(self)
}
fn tree_hash_packing_factor() -> usize {
HASHSIZE / ($bit_size / 8)
}
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);
impl_for_bitsize!(bool, 8);
2019-04-16 04:14:38 +00:00
impl TreeHash for [u8; 4] {
fn tree_hash_type() -> TreeHashType {
TreeHashType::List
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
panic!("bytesN should never be packed.")
}
fn tree_hash_packing_factor() -> usize {
panic!("bytesN should never be packed.")
}
fn tree_hash_root(&self) -> Vec<u8> {
merkle_root(&ssz::ssz_encode(self))
}
}
2019-04-16 02:29:39 +00:00
impl TreeHash for H256 {
fn tree_hash_type() -> TreeHashType {
TreeHashType::Basic
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
ssz_encode(self)
}
fn tree_hash_packing_factor() -> usize {
1
}
fn tree_hash_root(&self) -> Vec<u8> {
ssz_encode(self)
}
}
impl<T> TreeHash for Vec<T>
where
T: TreeHash,
{
fn tree_hash_type() -> TreeHashType {
TreeHashType::List
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
unreachable!("List should never be packed.")
}
fn tree_hash_packing_factor() -> usize {
unreachable!("List should never be packed.")
}
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 int_to_bytes32(self.len() as u64));
hash(&root_and_len)
}
}
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);
}
}