From e4ef0fc9d4fa322d4b3356d025f5526aa2805a52 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 9 Jul 2019 11:00:40 +1000 Subject: [PATCH] Add crate-level docs to ssz_types --- eth2/utils/ssz_types/src/bitfield.rs | 77 +++++++++++++++++++++++++++- eth2/utils/ssz_types/src/lib.rs | 35 +++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/eth2/utils/ssz_types/src/bitfield.rs b/eth2/utils/ssz_types/src/bitfield.rs index a929405ed..b7cdb2876 100644 --- a/eth2/utils/ssz_types/src/bitfield.rs +++ b/eth2/utils/ssz_types/src/bitfield.rs @@ -471,7 +471,82 @@ impl tree_hash::TreeHash for Bitfield> { } } -// TODO: test ssz decode a zero-length bitlist. +impl cached_tree_hash::CachedTreeHash for Bitfield> { + fn new_tree_hash_cache( + &self, + depth: usize, + ) -> Result { + let bytes = self.to_bytes(); + + let (mut cache, schema) = cached_tree_hash::vec::new_tree_hash_cache(&bytes, depth)?; + + cache.add_length_nodes(schema.into_overlay(0).chunk_range(), bytes.len())?; + + Ok(cache) + } + + fn num_tree_hash_cache_chunks(&self) -> usize { + // Add two extra nodes to cater for the node before and after to allow mixing-in length. + cached_tree_hash::BTreeOverlay::new(self, 0, 0).num_chunks() + 2 + } + + fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema { + let bytes = self.to_bytes(); + cached_tree_hash::vec::produce_schema(&bytes, depth) + } + + fn update_tree_hash_cache( + &self, + cache: &mut cached_tree_hash::TreeHashCache, + ) -> Result<(), cached_tree_hash::Error> { + let bytes = self.to_bytes(); + + // Skip the length-mixed-in root node. + cache.chunk_index += 1; + + // Update the cache, returning the new overlay. + let new_overlay = cached_tree_hash::vec::update_tree_hash_cache(&bytes, cache)?; + + // Mix in length + cache.mix_in_length(new_overlay.chunk_range(), bytes.len())?; + + // Skip an extra node to clear the length node. + cache.chunk_index += 1; + + Ok(()) + } +} + +impl cached_tree_hash::CachedTreeHash for Bitfield> { + fn new_tree_hash_cache( + &self, + depth: usize, + ) -> Result { + let (cache, _schema) = + cached_tree_hash::vec::new_tree_hash_cache(&ssz::ssz_encode(self), depth)?; + + Ok(cache) + } + + fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema { + let lengths = vec![ + 1; + cached_tree_hash::merkleize::num_unsanitized_leaves(bytes_for_bit_len( + N::to_usize() + )) + ]; + cached_tree_hash::BTreeSchema::from_lengths(depth, lengths) + } + + fn update_tree_hash_cache( + &self, + cache: &mut cached_tree_hash::TreeHashCache, + ) -> Result<(), cached_tree_hash::Error> { + cached_tree_hash::vec::update_tree_hash_cache(&ssz::ssz_encode(self), cache)?; + + Ok(()) + } +} #[cfg(test)] mod test { diff --git a/eth2/utils/ssz_types/src/lib.rs b/eth2/utils/ssz_types/src/lib.rs index 8eff665de..610888229 100644 --- a/eth2/utils/ssz_types/src/lib.rs +++ b/eth2/utils/ssz_types/src/lib.rs @@ -1,3 +1,38 @@ +//! Provides types with unique properties required for SSZ serialization and Merklization: +//! +//! - `FixedVector`: A heap-allocated list with a size that is fixed at compile time. +//! - `VariableList`: A heap-allocated list that cannot grow past a type-level maximum length. +//! - `Bitfield`: A heap-allocated bitfield that with a type-level _maximum_ length. +//! - `Bitfield`: A heap-allocated bitfield that with a type-level _fixed__ length. +//! +//! These structs are required as SSZ serialization and Merklization rely upon type-level lengths +//! for padding and verification. +//! +//! ## Example +//! ``` +//! use ssz_types::*; +//! +//! pub struct Example { +//! bit_vector: Bitfield>, +//! bit_list: Bitfield>, +//! variable_list: VariableList, +//! fixed_vector: FixedVector, +//! } +//! +//! let mut example = Example { +//! bit_vector: Bitfield::new(), +//! bit_list: Bitfield::with_capacity(4).unwrap(), +//! variable_list: <_>::from(vec![0, 1]), +//! fixed_vector: <_>::from(vec![2, 3]), +//! }; +//! +//! assert_eq!(example.bit_vector.len(), 8); +//! assert_eq!(example.bit_list.len(), 4); +//! assert_eq!(&example.variable_list[..], &[0, 1]); +//! assert_eq!(&example.fixed_vector[..], &[2, 3, 0, 0, 0, 0, 0, 0]); +//! +//! ``` + #[macro_use] mod bitfield; mod fixed_vector;