mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
Refactor tree hashing (#861)
* Pre-allocated tree hash caches * Add SmallVec to tree hash cache * Avoid allocation for validator.pubkey * Avoid iterator which seems to be doing heap alloc * Add more smallvecs * MOAR SMALLVEC * Move non-test code to Hash256 tree hash * Fix byte ordering error * Add incomplete but working merkle stream impl * Fix zero hash error * Add zero hash fn * Add MerkleStream comments * Add smallvec, tidy * Integrate into tree hash derive * Update ssz_types tree hash * Don't heap alloc for mix in length * Add byte-level streaming to MerkleStream * Avoid recursion in write method * Update BLS to MerkleStream * Fix some not-compiling tests * Remove debug profiling * Remove code duplication * Move beacon state tree hash to new hasher * Fix failing tests * Update comments * Add some fast-paths to tree_hash::merkle_root * Remove unncessary test * Rename MerkleStream -> MerkleHasher * Rename new_with_leaf_count -> with_leaves * Tidy * Remove NonZeroUsize * Remove todo * Update smallvec
This commit is contained in:
@@ -56,13 +56,20 @@ macro_rules! impl_tree_hash {
|
||||
unreachable!("Vector should never be packed.")
|
||||
}
|
||||
|
||||
fn tree_hash_root(&self) -> Vec<u8> {
|
||||
fn tree_hash_root(&self) -> tree_hash::Hash256 {
|
||||
// We could use the tree hash implementation for `FixedVec<u8, $byte_size>`,
|
||||
// but benchmarks have show that to be at least 15% slower because of the
|
||||
// unnecessary copying and allocation (one Vec per byte)
|
||||
let values_per_chunk = tree_hash::BYTES_PER_CHUNK;
|
||||
let minimum_chunk_count = ($byte_size + values_per_chunk - 1) / values_per_chunk;
|
||||
tree_hash::merkle_root(&self.as_ssz_bytes(), minimum_chunk_count)
|
||||
|
||||
let mut hasher = tree_hash::MerkleHasher::with_leaves(minimum_chunk_count);
|
||||
hasher
|
||||
.write(&self.as_ssz_bytes())
|
||||
.expect("bls should not exceed leaf count");
|
||||
hasher
|
||||
.finish()
|
||||
.expect("bls should not exceed leaf count from buffer")
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -111,6 +118,10 @@ macro_rules! bytes_struct {
|
||||
self.bytes.to_vec()
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
}
|
||||
|
||||
fn get_bytes(bytes: &[u8]) -> Result<[u8; $byte_size], ssz::DecodeError> {
|
||||
let mut result = [0; $byte_size];
|
||||
if bytes.len() != $byte_size {
|
||||
@@ -171,7 +182,28 @@ macro_rules! bytes_struct {
|
||||
|
||||
impl_ssz!($name, $byte_size, "$type");
|
||||
|
||||
impl_tree_hash!($name, $byte_size);
|
||||
impl tree_hash::TreeHash for $name {
|
||||
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) -> tree_hash::Hash256 {
|
||||
let values_per_chunk = tree_hash::BYTES_PER_CHUNK;
|
||||
let minimum_chunk_count = ($byte_size + values_per_chunk - 1) / values_per_chunk;
|
||||
|
||||
let mut hasher = tree_hash::MerkleHasher::with_leaves(minimum_chunk_count);
|
||||
hasher.write(&self.bytes).expect("bls should not exceed leaf count");
|
||||
hasher.finish().expect("bls should not exceed leaf count from buffer")
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::Serialize for $name {
|
||||
/// Serde serialization is compliant the Ethereum YAML test format.
|
||||
|
||||
Reference in New Issue
Block a user