Implement tree hash caching (#584)

* Implement basic tree hash caching

* Use spaces to indent top-level Cargo.toml

* Optimize BLS tree hash by hashing bytes directly

* Implement tree hash caching for validator registry

* Persist BeaconState tree hash cache to disk

* Address Paul's review comments
This commit is contained in:
Michael Sproul
2019-11-05 15:46:52 +11:00
committed by GitHub
parent 4ef66a544a
commit c1a2238f1a
38 changed files with 1112 additions and 248 deletions

View File

@@ -42,7 +42,7 @@ macro_rules! impl_ssz {
}
macro_rules! impl_tree_hash {
($type: ty, $byte_size: ident) => {
($type: ty, $byte_size: expr) => {
impl tree_hash::TreeHash for $type {
fn tree_hash_type() -> tree_hash::TreeHashType {
tree_hash::TreeHashType::Vector
@@ -57,16 +57,19 @@ macro_rules! impl_tree_hash {
}
fn tree_hash_root(&self) -> Vec<u8> {
let vector: ssz_types::FixedVector<u8, ssz_types::typenum::$byte_size> =
ssz_types::FixedVector::from(self.as_ssz_bytes());
vector.tree_hash_root()
// 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)
}
}
};
}
macro_rules! bytes_struct {
($name: ident, $type: ty, $byte_size: expr, $small_name: expr, $ssz_type_size: ident,
($name: ident, $type: ty, $byte_size: expr, $small_name: expr,
$type_str: expr, $byte_size_str: expr) => {
#[doc = "Stores `"]
#[doc = $byte_size_str]
@@ -82,9 +85,9 @@ macro_rules! bytes_struct {
#[derive(Clone)]
pub struct $name([u8; $byte_size]);
};
($name: ident, $type: ty, $byte_size: expr, $small_name: expr, $ssz_type_size: ident) => {
bytes_struct!($name, $type, $byte_size, $small_name, $ssz_type_size, stringify!($type),
stringify!($byte_size));
($name: ident, $type: ty, $byte_size: expr, $small_name: expr) => {
bytes_struct!($name, $type, $byte_size, $small_name, stringify!($type),
stringify!($byte_size));
impl $name {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
@@ -144,7 +147,7 @@ macro_rules! bytes_struct {
impl_ssz!($name, $byte_size, "$type");
impl_tree_hash!($name, $ssz_type_size);
impl_tree_hash!($name, $byte_size);
impl serde::ser::Serialize for $name {
/// Serde serialization is compliant the Ethereum YAML test format.