diff --git a/eth2/types/src/attestation.rs b/eth2/types/src/attestation.rs index f7bfdaab9..d1511763d 100644 --- a/eth2/types/src/attestation.rs +++ b/eth2/types/src/attestation.rs @@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// Details an attestation that can be slashable. /// @@ -19,6 +19,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, )] @@ -58,4 +59,5 @@ mod tests { use super::*; ssz_tests!(Attestation); + cached_tree_hash_tests!(Attestation); } diff --git a/eth2/types/src/attestation_data.rs b/eth2/types/src/attestation_data.rs index f8a0ecd15..c963d6001 100644 --- a/eth2/types/src/attestation_data.rs +++ b/eth2/types/src/attestation_data.rs @@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// The data upon which an attestation is based. /// @@ -21,6 +21,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, )] @@ -47,4 +48,5 @@ mod tests { use super::*; ssz_tests!(AttestationData); + cached_tree_hash_tests!(AttestationData); } diff --git a/eth2/types/src/attestation_data_and_custody_bit.rs b/eth2/types/src/attestation_data_and_custody_bit.rs index e5dc920dc..85a5875ab 100644 --- a/eth2/types/src/attestation_data_and_custody_bit.rs +++ b/eth2/types/src/attestation_data_and_custody_bit.rs @@ -3,12 +3,12 @@ use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::Serialize; use ssz_derive::{Decode, Encode}; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Used for pairing an attestation with a proof-of-custody. /// /// Spec v0.5.1 -#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)] +#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, CachedTreeHash)] pub struct AttestationDataAndCustodyBit { pub data: AttestationData, pub custody_bit: bool, @@ -28,4 +28,5 @@ mod test { use super::*; ssz_tests!(AttestationDataAndCustodyBit); + cached_tree_hash_tests!(AttestationDataAndCustodyBit); } diff --git a/eth2/types/src/attester_slashing.rs b/eth2/types/src/attester_slashing.rs index b5e851dbd..d4848b01c 100644 --- a/eth2/types/src/attester_slashing.rs +++ b/eth2/types/src/attester_slashing.rs @@ -3,12 +3,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Two conflicting attestations. /// /// Spec v0.5.1 -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + PartialEq, + Clone, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct AttesterSlashing { pub slashable_attestation_1: SlashableAttestation, pub slashable_attestation_2: SlashableAttestation, @@ -19,4 +30,5 @@ mod tests { use super::*; ssz_tests!(AttesterSlashing); + cached_tree_hash_tests!(AttesterSlashing); } diff --git a/eth2/types/src/beacon_block.rs b/eth2/types/src/beacon_block.rs index b4d2752d6..d198d16fc 100644 --- a/eth2/types/src/beacon_block.rs +++ b/eth2/types/src/beacon_block.rs @@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// A block of the `BeaconChain`. /// @@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, )] @@ -100,4 +101,5 @@ mod tests { use super::*; ssz_tests!(BeaconBlock); + cached_tree_hash_tests!(BeaconBlock); } diff --git a/eth2/types/src/beacon_block_body.rs b/eth2/types/src/beacon_block_body.rs index de4951f1f..15ba00d6b 100644 --- a/eth2/types/src/beacon_block_body.rs +++ b/eth2/types/src/beacon_block_body.rs @@ -4,12 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// The body of a `BeaconChain` block, containing operations. /// /// Spec v0.5.1 -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + PartialEq, + Clone, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct BeaconBlockBody { pub randao_reveal: Signature, pub eth1_data: Eth1Data, @@ -26,4 +37,5 @@ mod tests { use super::*; ssz_tests!(BeaconBlockBody); + cached_tree_hash_tests!(BeaconBlockBody); } diff --git a/eth2/types/src/beacon_block_header.rs b/eth2/types/src/beacon_block_header.rs index e4db3a721..5b35da1b6 100644 --- a/eth2/types/src/beacon_block_header.rs +++ b/eth2/types/src/beacon_block_header.rs @@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::{SignedRoot, TreeHash}; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// A header of a `BeaconBlock`. /// @@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, )] @@ -59,4 +60,5 @@ mod tests { use super::*; ssz_tests!(BeaconBlockHeader); + cached_tree_hash_tests!(BeaconBlockHeader); } diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index eef408308..227e6a4f9 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -9,7 +9,7 @@ use ssz::{hash, ssz_encode}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; mod epoch_cache; mod pubkey_cache; @@ -47,7 +47,18 @@ pub enum Error { /// The state of the `BeaconChain` at some slot. /// /// Spec v0.5.1 -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, TestRandom, Encode, Decode, TreeHash)] +#[derive( + Debug, + PartialEq, + Clone, + Serialize, + Deserialize, + TestRandom, + Encode, + Decode, + TreeHash, + CachedTreeHash, +)] pub struct BeaconState { // Misc pub slot: Slot, diff --git a/eth2/types/src/beacon_state/tests.rs b/eth2/types/src/beacon_state/tests.rs index dc16a013b..f417dd555 100644 --- a/eth2/types/src/beacon_state/tests.rs +++ b/eth2/types/src/beacon_state/tests.rs @@ -3,6 +3,7 @@ use super::*; use crate::test_utils::*; ssz_tests!(BeaconState); +cached_tree_hash_tests!(BeaconState); /// Test that /// diff --git a/eth2/types/src/crosslink.rs b/eth2/types/src/crosslink.rs index 623226ad6..448f5ea30 100644 --- a/eth2/types/src/crosslink.rs +++ b/eth2/types/src/crosslink.rs @@ -4,7 +4,7 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Specifies the block hash for a shard at an epoch. /// @@ -20,6 +20,7 @@ use tree_hash_derive::TreeHash; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, )] pub struct Crosslink { @@ -32,4 +33,5 @@ mod tests { use super::*; ssz_tests!(Crosslink); + cached_tree_hash_tests!(Crosslink); } diff --git a/eth2/types/src/crosslink_committee.rs b/eth2/types/src/crosslink_committee.rs index e8fc1b96d..25c42c07b 100644 --- a/eth2/types/src/crosslink_committee.rs +++ b/eth2/types/src/crosslink_committee.rs @@ -1,9 +1,20 @@ use crate::*; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; -#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize, Decode, Encode, TreeHash)] +#[derive( + Default, + Clone, + Debug, + PartialEq, + Serialize, + Deserialize, + Decode, + Encode, + TreeHash, + CachedTreeHash, +)] pub struct CrosslinkCommittee { pub slot: Slot, pub shard: Shard, diff --git a/eth2/types/src/deposit.rs b/eth2/types/src/deposit.rs index 291173d34..e8d2f5a4b 100644 --- a/eth2/types/src/deposit.rs +++ b/eth2/types/src/deposit.rs @@ -4,12 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// A deposit to potentially become a beacon chain validator. /// /// Spec v0.5.1 -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + PartialEq, + Clone, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct Deposit { pub proof: TreeHashVector, pub index: u64, @@ -21,4 +32,5 @@ mod tests { use super::*; ssz_tests!(Deposit); + cached_tree_hash_tests!(Deposit); } diff --git a/eth2/types/src/deposit_data.rs b/eth2/types/src/deposit_data.rs index bc96ac7c4..38c44d1a7 100644 --- a/eth2/types/src/deposit_data.rs +++ b/eth2/types/src/deposit_data.rs @@ -4,12 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Data generated by the deposit contract. /// /// Spec v0.5.1 -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + PartialEq, + Clone, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct DepositData { pub amount: u64, pub timestamp: u64, @@ -21,4 +32,5 @@ mod tests { use super::*; ssz_tests!(DepositData); + cached_tree_hash_tests!(DepositData); } diff --git a/eth2/types/src/deposit_input.rs b/eth2/types/src/deposit_input.rs index be2106cb4..af1049a20 100644 --- a/eth2/types/src/deposit_input.rs +++ b/eth2/types/src/deposit_input.rs @@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::{SignedRoot, TreeHash}; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// The data supplied by the user to the deposit contract. /// @@ -21,6 +21,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Decode, SignedRoot, TreeHash, + CachedTreeHash, TestRandom, )] pub struct DepositInput { @@ -68,6 +69,7 @@ mod tests { use super::*; ssz_tests!(DepositInput); + cached_tree_hash_tests!(DepositInput); #[test] fn can_create_and_validate() { diff --git a/eth2/types/src/eth1_data.rs b/eth2/types/src/eth1_data.rs index 2ad460d13..3c0c3af02 100644 --- a/eth2/types/src/eth1_data.rs +++ b/eth2/types/src/eth1_data.rs @@ -4,13 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Contains data obtained from the Eth1 chain. /// /// Spec v0.5.1 #[derive( - Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, + Debug, + PartialEq, + Clone, + Default, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, )] pub struct Eth1Data { pub deposit_root: Hash256, @@ -22,4 +32,5 @@ mod tests { use super::*; ssz_tests!(Eth1Data); + cached_tree_hash_tests!(Eth1Data); } diff --git a/eth2/types/src/eth1_data_vote.rs b/eth2/types/src/eth1_data_vote.rs index 7a77c8ff0..00818ebf4 100644 --- a/eth2/types/src/eth1_data_vote.rs +++ b/eth2/types/src/eth1_data_vote.rs @@ -4,13 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// A summation of votes for some `Eth1Data`. /// /// Spec v0.5.1 #[derive( - Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, + Debug, + PartialEq, + Clone, + Default, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, )] pub struct Eth1DataVote { pub eth1_data: Eth1Data, @@ -22,4 +32,5 @@ mod tests { use super::*; ssz_tests!(Eth1DataVote); + cached_tree_hash_tests!(Eth1DataVote); } diff --git a/eth2/types/src/fork.rs b/eth2/types/src/fork.rs index d99842855..83d4f5dc6 100644 --- a/eth2/types/src/fork.rs +++ b/eth2/types/src/fork.rs @@ -7,13 +7,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Specifies a fork of the `BeaconChain`, to prevent replay attacks. /// /// Spec v0.5.1 #[derive( - Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, + Debug, + Clone, + PartialEq, + Default, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, )] pub struct Fork { #[serde(deserialize_with = "fork_from_hex_str")] @@ -54,6 +64,7 @@ mod tests { use super::*; ssz_tests!(Fork); + cached_tree_hash_tests!(Fork); fn test_genesis(version: u32, epoch: Epoch) { let mut spec = ChainSpec::foundation(); diff --git a/eth2/types/src/historical_batch.rs b/eth2/types/src/historical_batch.rs index c4f62fcfc..13e57131a 100644 --- a/eth2/types/src/historical_batch.rs +++ b/eth2/types/src/historical_batch.rs @@ -4,12 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Historical block and state roots. /// /// Spec v0.5.1 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + Clone, + PartialEq, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct HistoricalBatch { pub block_roots: TreeHashVector, pub state_roots: TreeHashVector, @@ -20,4 +31,5 @@ mod tests { use super::*; ssz_tests!(HistoricalBatch); + cached_tree_hash_tests!(HistoricalBatch); } diff --git a/eth2/types/src/pending_attestation.rs b/eth2/types/src/pending_attestation.rs index ce9ce3d77..b71351f9a 100644 --- a/eth2/types/src/pending_attestation.rs +++ b/eth2/types/src/pending_attestation.rs @@ -4,12 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// An attestation that has been included in the state but not yet fully processed. /// /// Spec v0.5.1 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + Clone, + PartialEq, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct PendingAttestation { pub aggregation_bitfield: Bitfield, pub data: AttestationData, @@ -34,4 +45,5 @@ mod tests { use super::*; ssz_tests!(PendingAttestation); + cached_tree_hash_tests!(PendingAttestation); } diff --git a/eth2/types/src/proposer_slashing.rs b/eth2/types/src/proposer_slashing.rs index a3501a5bd..bf26ae508 100644 --- a/eth2/types/src/proposer_slashing.rs +++ b/eth2/types/src/proposer_slashing.rs @@ -4,12 +4,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Two conflicting proposals from the same proposer (validator). /// /// Spec v0.5.1 -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] +#[derive( + Debug, + PartialEq, + Clone, + Serialize, + Deserialize, + Encode, + Decode, + TreeHash, + CachedTreeHash, + TestRandom, +)] pub struct ProposerSlashing { pub proposer_index: u64, pub header_1: BeaconBlockHeader, @@ -21,4 +32,5 @@ mod tests { use super::*; ssz_tests!(ProposerSlashing); + cached_tree_hash_tests!(ProposerSlashing); } diff --git a/eth2/types/src/slashable_attestation.rs b/eth2/types/src/slashable_attestation.rs index 9c460e482..fb838e0c4 100644 --- a/eth2/types/src/slashable_attestation.rs +++ b/eth2/types/src/slashable_attestation.rs @@ -4,7 +4,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// Details an attestation that can be slashable. /// @@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, )] @@ -133,6 +134,7 @@ mod tests { } ssz_tests!(SlashableAttestation); + cached_tree_hash_tests!(SlashableAttestation); fn create_slashable_attestation( slot_factor: u64, diff --git a/eth2/types/src/slot_epoch_macros.rs b/eth2/types/src/slot_epoch_macros.rs index b3ca5c4bc..446838d0a 100644 --- a/eth2/types/src/slot_epoch_macros.rs +++ b/eth2/types/src/slot_epoch_macros.rs @@ -224,6 +224,26 @@ macro_rules! impl_ssz { } } + impl cached_tree_hash::CachedTreeHash<$type> for $type { + fn new_tree_hash_cache( + &self, + depth: usize, + ) -> Result { + self.0.new_tree_hash_cache(depth) + } + + fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema { + self.0.tree_hash_cache_schema(depth) + } + + fn update_tree_hash_cache( + &self, + cache: &mut cached_tree_hash::TreeHashCache, + ) -> Result<(), cached_tree_hash::Error> { + self.0.update_tree_hash_cache(cache) + } + } + impl TestRandom for $type { fn random_for_test(rng: &mut T) -> Self { $type::from(u64::random_for_test(rng)) @@ -545,6 +565,7 @@ macro_rules! all_tests { math_between_tests!($type, $type); math_tests!($type); ssz_tests!($type); + cached_tree_hash_tests!($type); mod u64_tests { use super::*; diff --git a/eth2/types/src/test_utils/macros.rs b/eth2/types/src/test_utils/macros.rs index d5711e96e..5f355bfe9 100644 --- a/eth2/types/src/test_utils/macros.rs +++ b/eth2/types/src/test_utils/macros.rs @@ -32,3 +32,29 @@ macro_rules! ssz_tests { } }; } + +#[cfg(test)] +#[macro_export] +macro_rules! cached_tree_hash_tests { + ($type: ident) => { + #[test] + pub fn test_cached_tree_hash() { + use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use tree_hash::TreeHash; + + let mut rng = XorShiftRng::from_seed([42; 16]); + + let original = $type::random_for_test(&mut rng); + + let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root()); + + let modified = $type::random_for_test(&mut rng); + + hasher.update(&modified).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root()); + } + }; +} diff --git a/eth2/types/src/transfer.rs b/eth2/types/src/transfer.rs index 82ead03d5..aea13fdd7 100644 --- a/eth2/types/src/transfer.rs +++ b/eth2/types/src/transfer.rs @@ -7,7 +7,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// The data submitted to the deposit contract. /// @@ -20,6 +20,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, Derivative, @@ -42,4 +43,5 @@ mod tests { use super::*; ssz_tests!(Transfer); + cached_tree_hash_tests!(Transfer); } diff --git a/eth2/types/src/tree_hash_vector.rs b/eth2/types/src/tree_hash_vector.rs index 4b6ebad37..6279c4512 100644 --- a/eth2/types/src/tree_hash_vector.rs +++ b/eth2/types/src/tree_hash_vector.rs @@ -108,3 +108,25 @@ where Vec::random_for_test(rng).into() } } + +#[cfg(test)] +mod test { + use super::*; + use tree_hash::TreeHash; + + #[test] + pub fn test_cached_tree_hash() { + let original = TreeHashVector::from(vec![1_u64, 2, 3, 4]); + + let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root()); + + let modified = TreeHashVector::from(vec![1_u64, 1, 1, 1]); + + hasher.update(&modified).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root()); + } + +} diff --git a/eth2/types/src/validator.rs b/eth2/types/src/validator.rs index bbd68ed2b..a20eb6426 100644 --- a/eth2/types/src/validator.rs +++ b/eth2/types/src/validator.rs @@ -3,12 +3,23 @@ use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; +use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Information about a `BeaconChain` validator. /// /// Spec v0.5.1 -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)] +#[derive( + Debug, + Clone, + PartialEq, + Serialize, + Deserialize, + Encode, + Decode, + TestRandom, + TreeHash, + CachedTreeHash, +)] pub struct Validator { pub pubkey: PublicKey, pub withdrawal_credentials: Hash256, @@ -111,4 +122,5 @@ mod tests { } ssz_tests!(Validator); + cached_tree_hash_tests!(Validator); } diff --git a/eth2/types/src/voluntary_exit.rs b/eth2/types/src/voluntary_exit.rs index cb872cb98..8a780db75 100644 --- a/eth2/types/src/voluntary_exit.rs +++ b/eth2/types/src/voluntary_exit.rs @@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; use tree_hash::TreeHash; -use tree_hash_derive::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// An exit voluntarily submitted a validator who wishes to withdraw. /// @@ -19,6 +19,7 @@ use tree_hash_derive::{SignedRoot, TreeHash}; Encode, Decode, TreeHash, + CachedTreeHash, TestRandom, SignedRoot, )] @@ -34,4 +35,5 @@ mod tests { use super::*; ssz_tests!(VoluntaryExit); + cached_tree_hash_tests!(VoluntaryExit); } diff --git a/eth2/utils/bls/Cargo.toml b/eth2/utils/bls/Cargo.toml index 4ce499580..dcace15c8 100644 --- a/eth2/utils/bls/Cargo.toml +++ b/eth2/utils/bls/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] bls-aggregates = { git = "https://github.com/sigp/signature-schemes", tag = "0.6.1" } +cached_tree_hash = { path = "../cached_tree_hash" } hashing = { path = "../hashing" } hex = "0.3" serde = "1.0" diff --git a/eth2/utils/bls/src/aggregate_signature.rs b/eth2/utils/bls/src/aggregate_signature.rs index 0fbcc3493..e6c6cff9a 100644 --- a/eth2/utils/bls/src/aggregate_signature.rs +++ b/eth2/utils/bls/src/aggregate_signature.rs @@ -2,6 +2,7 @@ use super::{AggregatePublicKey, Signature, BLS_AGG_SIG_BYTE_SIZE}; use bls_aggregates::{ AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature, }; +use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::{encode as hex_encode, HexVisitor}; @@ -167,6 +168,7 @@ impl<'de> Deserialize<'de> for AggregateSignature { } tree_hash_ssz_encoding_as_vector!(AggregateSignature); +cached_tree_hash_ssz_encoding_as_vector!(AggregateSignature, 96); #[cfg(test)] mod tests { diff --git a/eth2/utils/bls/src/fake_aggregate_signature.rs b/eth2/utils/bls/src/fake_aggregate_signature.rs index f201eba3e..aeb89507d 100644 --- a/eth2/utils/bls/src/fake_aggregate_signature.rs +++ b/eth2/utils/bls/src/fake_aggregate_signature.rs @@ -1,4 +1,5 @@ use super::{fake_signature::FakeSignature, AggregatePublicKey, BLS_AGG_SIG_BYTE_SIZE}; +use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; @@ -100,6 +101,7 @@ impl<'de> Deserialize<'de> for FakeAggregateSignature { } tree_hash_ssz_encoding_as_vector!(FakeAggregateSignature); +cached_tree_hash_ssz_encoding_as_vector!(FakeAggregateSignature, 96); #[cfg(test)] mod tests { diff --git a/eth2/utils/bls/src/fake_signature.rs b/eth2/utils/bls/src/fake_signature.rs index 3208ed992..8a333b9c0 100644 --- a/eth2/utils/bls/src/fake_signature.rs +++ b/eth2/utils/bls/src/fake_signature.rs @@ -1,4 +1,5 @@ use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE}; +use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; use hex::encode as hex_encode; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; @@ -75,6 +76,7 @@ impl Decodable for FakeSignature { } tree_hash_ssz_encoding_as_vector!(FakeSignature); +cached_tree_hash_ssz_encoding_as_vector!(FakeSignature, 96); impl Serialize for FakeSignature { fn serialize(&self, serializer: S) -> Result diff --git a/eth2/utils/bls/src/public_key.rs b/eth2/utils/bls/src/public_key.rs index dcbbc622a..e6e4d3508 100644 --- a/eth2/utils/bls/src/public_key.rs +++ b/eth2/utils/bls/src/public_key.rs @@ -1,5 +1,6 @@ use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE}; use bls_aggregates::PublicKey as RawPublicKey; +use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::{encode as hex_encode, HexVisitor}; @@ -106,6 +107,7 @@ impl<'de> Deserialize<'de> for PublicKey { } tree_hash_ssz_encoding_as_vector!(PublicKey); +cached_tree_hash_ssz_encoding_as_vector!(PublicKey, 48); impl PartialEq for PublicKey { fn eq(&self, other: &PublicKey) -> bool { @@ -129,6 +131,7 @@ impl Hash for PublicKey { mod tests { use super::*; use ssz::ssz_encode; + use tree_hash::TreeHash; #[test] pub fn test_ssz_round_trip() { @@ -140,4 +143,21 @@ mod tests { assert_eq!(original, decoded); } + + #[test] + pub fn test_cached_tree_hash() { + let sk = SecretKey::random(); + let original = PublicKey::from_secret_key(&sk); + + let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root()); + + let sk = SecretKey::random(); + let modified = PublicKey::from_secret_key(&sk); + + hasher.update(&modified).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root()); + } } diff --git a/eth2/utils/bls/src/signature.rs b/eth2/utils/bls/src/signature.rs index 3fb68dc53..75f43aaf4 100644 --- a/eth2/utils/bls/src/signature.rs +++ b/eth2/utils/bls/src/signature.rs @@ -1,5 +1,6 @@ use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE}; use bls_aggregates::Signature as RawSignature; +use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; use hex::encode as hex_encode; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; @@ -116,6 +117,7 @@ impl Decodable for Signature { } tree_hash_ssz_encoding_as_vector!(Signature); +cached_tree_hash_ssz_encoding_as_vector!(Signature, 96); impl Serialize for Signature { /// Serde serialization is compliant the Ethereum YAML test format. @@ -145,6 +147,7 @@ mod tests { use super::super::Keypair; use super::*; use ssz::ssz_encode; + use tree_hash::TreeHash; #[test] pub fn test_ssz_round_trip() { @@ -158,6 +161,22 @@ mod tests { assert_eq!(original, decoded); } + #[test] + pub fn test_cached_tree_hash() { + let keypair = Keypair::random(); + let original = Signature::new(&[42, 42], 0, &keypair.sk); + + let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root()); + + let modified = Signature::new(&[99, 99], 0, &keypair.sk); + + hasher.update(&modified).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root()); + } + #[test] pub fn test_empty_signature() { let sig = Signature::empty_signature(); diff --git a/eth2/utils/boolean-bitfield/Cargo.toml b/eth2/utils/boolean-bitfield/Cargo.toml index 61bbc60a8..dfc97ce77 100644 --- a/eth2/utils/boolean-bitfield/Cargo.toml +++ b/eth2/utils/boolean-bitfield/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] +cached_tree_hash = { path = "../cached_tree_hash" } serde_hex = { path = "../serde_hex" } ssz = { path = "../ssz" } bit-vec = "0.5.0" diff --git a/eth2/utils/boolean-bitfield/src/lib.rs b/eth2/utils/boolean-bitfield/src/lib.rs index 1d0f1c02e..cdc58173f 100644 --- a/eth2/utils/boolean-bitfield/src/lib.rs +++ b/eth2/utils/boolean-bitfield/src/lib.rs @@ -3,6 +3,7 @@ extern crate ssz; use bit_reverse::LookupReverse; use bit_vec::BitVec; +use cached_tree_hash::cached_tree_hash_bytes_as_list; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::{encode, PrefixedHexVisitor}; @@ -270,11 +271,31 @@ impl tree_hash::TreeHash for BooleanBitfield { } } +cached_tree_hash_bytes_as_list!(BooleanBitfield); + #[cfg(test)] mod tests { use super::*; use serde_yaml; use ssz::{decode, ssz_encode, SszStream}; + use tree_hash::TreeHash; + + #[test] + pub fn test_cached_tree_hash() { + let original = BooleanBitfield::from_bytes(&vec![18; 12][..]); + + let mut hasher = cached_tree_hash::CachedTreeHasher::new(&original).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), original.tree_hash_root()); + /* + + let modified = BooleanBitfield::from_bytes(&vec![2; 1][..]); + + hasher.update(&modified).unwrap(); + + assert_eq!(hasher.tree_hash_root().unwrap(), modified.tree_hash_root()); + */ + } #[test] fn test_new_bitfield() { diff --git a/eth2/utils/cached_tree_hash/src/impls.rs b/eth2/utils/cached_tree_hash/src/impls.rs index 687e74918..a859a8847 100644 --- a/eth2/utils/cached_tree_hash/src/impls.rs +++ b/eth2/utils/cached_tree_hash/src/impls.rs @@ -1,12 +1,46 @@ use super::*; use crate::merkleize::merkleize; +use ethereum_types::H256; pub mod vec; -impl CachedTreeHash for u64 { +macro_rules! impl_for_single_leaf_int { + ($type: ident) => { + impl CachedTreeHash<$type> for $type { + fn new_tree_hash_cache(&self, _depth: usize) -> Result { + Ok(TreeHashCache::from_bytes( + merkleize(self.to_le_bytes().to_vec()), + false, + None, + )?) + } + + fn tree_hash_cache_schema(&self, depth: usize) -> BTreeSchema { + BTreeSchema::from_lengths(depth, vec![1]) + } + + fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> { + let leaf = merkleize(self.to_le_bytes().to_vec()); + cache.maybe_update_chunk(cache.chunk_index, &leaf)?; + + cache.chunk_index += 1; + + Ok(()) + } + } + }; +} + +impl_for_single_leaf_int!(u8); +impl_for_single_leaf_int!(u16); +impl_for_single_leaf_int!(u32); +impl_for_single_leaf_int!(u64); +impl_for_single_leaf_int!(usize); + +impl CachedTreeHash for bool { fn new_tree_hash_cache(&self, _depth: usize) -> Result { Ok(TreeHashCache::from_bytes( - merkleize(self.to_le_bytes().to_vec()), + merkleize((*self as u8).to_le_bytes().to_vec()), false, None, )?) @@ -17,20 +51,19 @@ impl CachedTreeHash for u64 { } fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> { - let leaf = merkleize(self.to_le_bytes().to_vec()); + let leaf = merkleize((*self as u8).to_le_bytes().to_vec()); cache.maybe_update_chunk(cache.chunk_index, &leaf)?; cache.chunk_index += 1; - // cache.overlay_index += 1; Ok(()) } } -impl CachedTreeHash for usize { +impl CachedTreeHash<[u8; 4]> for [u8; 4] { fn new_tree_hash_cache(&self, _depth: usize) -> Result { Ok(TreeHashCache::from_bytes( - merkleize(self.to_le_bytes().to_vec()), + merkleize(self.to_vec()), false, None, )?) @@ -41,11 +74,33 @@ impl CachedTreeHash for usize { } fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> { - let leaf = merkleize(self.to_le_bytes().to_vec()); + let leaf = merkleize(self.to_vec()); + cache.maybe_update_chunk(cache.chunk_index, &leaf)?; + + cache.chunk_index += 1; + + Ok(()) + } +} + +impl CachedTreeHash for H256 { + fn new_tree_hash_cache(&self, _depth: usize) -> Result { + Ok(TreeHashCache::from_bytes( + merkleize(self.as_bytes().to_vec()), + false, + None, + )?) + } + + fn tree_hash_cache_schema(&self, depth: usize) -> BTreeSchema { + BTreeSchema::from_lengths(depth, vec![1]) + } + + fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error> { + let leaf = merkleize(self.as_bytes().to_vec()); cache.maybe_update_chunk(cache.chunk_index, &leaf)?; cache.chunk_index += 1; - // cache.overlay_index += 1; Ok(()) } diff --git a/eth2/utils/cached_tree_hash/src/impls/vec.rs b/eth2/utils/cached_tree_hash/src/impls/vec.rs index f8ed32399..87ea3bcc3 100644 --- a/eth2/utils/cached_tree_hash/src/impls/vec.rs +++ b/eth2/utils/cached_tree_hash/src/impls/vec.rs @@ -95,6 +95,11 @@ pub fn update_tree_hash_cache>( let old_overlay = cache.get_overlay(cache.schema_index, cache.chunk_index)?; let new_overlay = BTreeOverlay::new(vec, cache.chunk_index, old_overlay.depth); + dbg!(cache.schema_index); + dbg!(cache.schemas.len()); + dbg!(&old_overlay); + dbg!(&new_overlay); + cache.replace_overlay(cache.schema_index, cache.chunk_index, new_overlay.clone())?; cache.schema_index += 1; diff --git a/eth2/utils/cached_tree_hash/src/lib.rs b/eth2/utils/cached_tree_hash/src/lib.rs index 316d52d07..24bbe0b07 100644 --- a/eth2/utils/cached_tree_hash/src/lib.rs +++ b/eth2/utils/cached_tree_hash/src/lib.rs @@ -1,4 +1,5 @@ use hashing::hash; +use merkleize::num_unsanitized_leaves; use std::ops::Range; use tree_hash::{TreeHash, TreeHashType, BYTES_PER_CHUNK, HASHSIZE}; @@ -62,3 +63,92 @@ impl CachedTreeHasher { Ok(self.cache.root()?.to_vec()) } } + +#[macro_export] +macro_rules! cached_tree_hash_ssz_encoding_as_vector { + ($type: ident, $num_bytes: expr) => { + impl cached_tree_hash::CachedTreeHash<$type> for $type { + fn new_tree_hash_cache( + &self, + depth: usize, + ) -> Result { + let (cache, _schema) = cached_tree_hash::impls::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($num_bytes)]; + 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::impls::vec::update_tree_hash_cache( + &ssz::ssz_encode(self), + cache, + )?; + + Ok(()) + } + } + }; +} + +#[macro_export] +macro_rules! cached_tree_hash_bytes_as_list { + ($type: ident) => { + impl cached_tree_hash::CachedTreeHash<$type> for $type { + fn new_tree_hash_cache( + &self, + depth: usize, + ) -> Result { + let bytes = self.to_bytes(); + + let (mut cache, schema) = + cached_tree_hash::impls::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 { + cached_tree_hash::impls::vec::produce_schema(&ssz::ssz_encode(self), 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::impls::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 = new_overlay.next_node() + 1; + + Ok(()) + } + } + }; +} diff --git a/eth2/utils/cached_tree_hash/src/merkleize.rs b/eth2/utils/cached_tree_hash/src/merkleize.rs index 6bfa73888..e744961b0 100644 --- a/eth2/utils/cached_tree_hash/src/merkleize.rs +++ b/eth2/utils/cached_tree_hash/src/merkleize.rs @@ -60,7 +60,7 @@ fn last_leaf_needs_padding(num_bytes: usize) -> bool { } /// Rounds up -fn num_unsanitized_leaves(num_bytes: usize) -> usize { +pub fn num_unsanitized_leaves(num_bytes: usize) -> usize { (num_bytes + HASHSIZE - 1) / HASHSIZE } diff --git a/eth2/utils/cached_tree_hash/tests/tests.rs b/eth2/utils/cached_tree_hash/tests/tests.rs index 8837fa1da..bc93e0176 100644 --- a/eth2/utils/cached_tree_hash/tests/tests.rs +++ b/eth2/utils/cached_tree_hash/tests/tests.rs @@ -231,6 +231,41 @@ pub struct StructWithVecOfStructs { pub c: Vec, } +fn get_inners() -> Vec { + vec![ + Inner { + a: 12, + b: 13, + c: 14, + d: 15, + }, + Inner { + a: 99, + b: 100, + c: 101, + d: 102, + }, + Inner { + a: 255, + b: 256, + c: 257, + d: 0, + }, + Inner { + a: 1000, + b: 2000, + c: 3000, + d: 0, + }, + Inner { + a: 0, + b: 0, + c: 0, + d: 0, + }, + ] +} + fn get_struct_with_vec_of_structs() -> Vec { let inner_a = Inner { a: 12, @@ -342,6 +377,56 @@ fn test_struct_with_vec_of_struct_with_vec_of_structs() { } } +#[derive(Clone, Debug, TreeHash, CachedTreeHash)] +pub struct StructWithTwoVecs { + pub a: Vec, + pub b: Vec, +} + +#[test] +fn test_struct_with_two_vecs() { + let inners = get_inners(); + + let variants = vec![ + StructWithTwoVecs { + a: inners[..].to_vec(), + b: inners[..].to_vec(), + }, + StructWithTwoVecs { + a: inners[0..1].to_vec(), + b: inners[..].to_vec(), + }, + StructWithTwoVecs { + a: inners[0..1].to_vec(), + b: inners[0..2].to_vec(), + }, + StructWithTwoVecs { + a: inners[0..4].to_vec(), + b: inners[0..2].to_vec(), + }, + StructWithTwoVecs { + a: vec![], + b: inners[..].to_vec(), + }, + StructWithTwoVecs { + a: inners[..].to_vec(), + b: vec![], + }, + StructWithTwoVecs { + a: inners[0..3].to_vec(), + b: inners[0..1].to_vec(), + }, + ]; + + test_routine(variants[0].clone(), variants[6..7].to_vec()); + + /* + for v in &variants { + test_routine(v.clone(), variants.clone()); + } + */ +} + #[derive(Clone, Debug, TreeHash, CachedTreeHash)] pub struct Inner { pub a: u64, diff --git a/eth2/utils/tree_hash/src/impls.rs b/eth2/utils/tree_hash/src/impls.rs index f2ff8c2bc..e8485dc2f 100644 --- a/eth2/utils/tree_hash/src/impls.rs +++ b/eth2/utils/tree_hash/src/impls.rs @@ -52,7 +52,7 @@ impl TreeHash for bool { impl TreeHash for [u8; 4] { fn tree_hash_type() -> TreeHashType { - TreeHashType::List + TreeHashType::Vector } fn tree_hash_packed_encoding(&self) -> Vec {