diff --git a/beacon_node/beacon_chain/src/initialise.rs b/beacon_node/beacon_chain/src/initialise.rs index 0951e06fbb..c66dd63b18 100644 --- a/beacon_node/beacon_chain/src/initialise.rs +++ b/beacon_node/beacon_chain/src/initialise.rs @@ -7,9 +7,9 @@ use db::stores::{BeaconBlockStore, BeaconStateStore}; use db::{DiskDB, MemoryDB}; use fork_choice::BitwiseLMDGhost; use slot_clock::SystemTimeSlotClock; -use ssz::TreeHash; use std::path::PathBuf; use std::sync::Arc; +use tree_hash::TreeHash; use types::test_utils::TestingBeaconStateBuilder; use types::{BeaconBlock, ChainSpec, Hash256}; @@ -32,7 +32,7 @@ pub fn initialise_beacon_chain( let (genesis_state, _keypairs) = state_builder.build(); let mut genesis_block = BeaconBlock::empty(&spec); - genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); + genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root()); // Slot clock let slot_clock = SystemTimeSlotClock::new( @@ -73,7 +73,7 @@ pub fn initialise_test_beacon_chain( let (genesis_state, _keypairs) = state_builder.build(); let mut genesis_block = BeaconBlock::empty(spec); - genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); + genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root()); // Slot clock let slot_clock = SystemTimeSlotClock::new( diff --git a/beacon_node/beacon_chain/src/test_utils/testing_beacon_chain_builder.rs b/beacon_node/beacon_chain/src/test_utils/testing_beacon_chain_builder.rs index 5c5477e556..d174670c00 100644 --- a/beacon_node/beacon_chain/src/test_utils/testing_beacon_chain_builder.rs +++ b/beacon_node/beacon_chain/src/test_utils/testing_beacon_chain_builder.rs @@ -5,8 +5,8 @@ use db::{ }; use fork_choice::BitwiseLMDGhost; use slot_clock::TestingSlotClock; -use ssz::TreeHash; use std::sync::Arc; +use tree_hash::TreeHash; use types::test_utils::TestingBeaconStateBuilder; use types::*; @@ -27,7 +27,7 @@ impl TestingBeaconChainBuilder { let (genesis_state, _keypairs) = self.state_builder.build(); let mut genesis_block = BeaconBlock::empty(&spec); - genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); + genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root()); // Create the Beacon Chain BeaconChain::from_genesis( diff --git a/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs b/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs index aeb734a4e4..34b5594784 100644 --- a/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs +++ b/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs @@ -9,8 +9,8 @@ use fork_choice::BitwiseLMDGhost; use log::debug; use rayon::prelude::*; use slot_clock::TestingSlotClock; -use ssz::TreeHash; use std::sync::Arc; +use tree_hash::TreeHash; use types::{test_utils::TestingBeaconStateBuilder, *}; type TestingBeaconChain = BeaconChain>; @@ -54,7 +54,7 @@ impl BeaconChainHarness { let (mut genesis_state, keypairs) = state_builder.build(); let mut genesis_block = BeaconBlock::empty(&spec); - genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); + genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root()); genesis_state .build_epoch_cache(RelativeEpoch::Previous, &spec) @@ -163,7 +163,7 @@ impl BeaconChainHarness { data: data.clone(), custody_bit: false, } - .hash_tree_root(); + .tree_hash_root(); let domain = self.spec.get_domain( state.slot.epoch(self.spec.slots_per_epoch), Domain::Attestation, diff --git a/beacon_node/beacon_chain/test_harness/src/test_case.rs b/beacon_node/beacon_chain/test_harness/src/test_case.rs index f65b45505e..28c7ae8a89 100644 --- a/beacon_node/beacon_chain/test_harness/src/test_case.rs +++ b/beacon_node/beacon_chain/test_harness/src/test_case.rs @@ -4,7 +4,7 @@ use crate::beacon_chain_harness::BeaconChainHarness; use beacon_chain::CheckPoint; use log::{info, warn}; -use ssz::SignedRoot; +use tree_hash::SignedRoot; use types::*; use types::test_utils::*; diff --git a/beacon_node/network/src/sync/import_queue.rs b/beacon_node/network/src/sync/import_queue.rs index 0026347eb2..106e3eb663 100644 --- a/beacon_node/network/src/sync/import_queue.rs +++ b/beacon_node/network/src/sync/import_queue.rs @@ -2,9 +2,9 @@ use crate::beacon_chain::BeaconChain; use eth2_libp2p::rpc::methods::*; use eth2_libp2p::PeerId; use slog::{debug, error}; -use ssz::TreeHash; use std::sync::Arc; use std::time::{Duration, Instant}; +use tree_hash::TreeHash; use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Hash256, Slot}; /// Provides a queue for fully and partially built `BeaconBlock`s. @@ -15,7 +15,7 @@ use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Hash256, Slot}; /// /// - When we receive a `BeaconBlockBody`, the only way we can find it's matching /// `BeaconBlockHeader` is to find a header such that `header.beacon_block_body == -/// hash_tree_root(body)`. Therefore, if we used a `HashMap` we would need to use the root of +/// tree_hash_root(body)`. Therefore, if we used a `HashMap` we would need to use the root of /// `BeaconBlockBody` as the key. /// - It is possible for multiple distinct blocks to have identical `BeaconBlockBodies`. Therefore /// we cannot use a `HashMap` keyed by the root of `BeaconBlockBody`. @@ -166,7 +166,7 @@ impl ImportQueue { let mut required_bodies: Vec = vec![]; for header in headers { - let block_root = Hash256::from_slice(&header.hash_tree_root()[..]); + let block_root = Hash256::from_slice(&header.tree_hash_root()[..]); if self.chain_has_not_seen_block(&block_root) { self.insert_header(block_root, header, sender.clone()); @@ -230,7 +230,7 @@ impl ImportQueue { /// /// If the body already existed, the `inserted` time is set to `now`. fn insert_body(&mut self, body: BeaconBlockBody, sender: PeerId) { - let body_root = Hash256::from_slice(&body.hash_tree_root()[..]); + let body_root = Hash256::from_slice(&body.tree_hash_root()[..]); self.partials.iter_mut().for_each(|mut p| { if let Some(header) = &mut p.header { @@ -250,7 +250,7 @@ impl ImportQueue { /// /// If the partial already existed, the `inserted` time is set to `now`. fn insert_full_block(&mut self, block: BeaconBlock, sender: PeerId) { - let block_root = Hash256::from_slice(&block.hash_tree_root()[..]); + let block_root = Hash256::from_slice(&block.tree_hash_root()[..]); let partial = PartialBeaconBlock { slot: block.slot, diff --git a/beacon_node/network/src/sync/simple_sync.rs b/beacon_node/network/src/sync/simple_sync.rs index 824458b894..1b57fbc00b 100644 --- a/beacon_node/network/src/sync/simple_sync.rs +++ b/beacon_node/network/src/sync/simple_sync.rs @@ -5,10 +5,10 @@ use eth2_libp2p::rpc::methods::*; use eth2_libp2p::rpc::{RPCRequest, RPCResponse, RequestId}; use eth2_libp2p::PeerId; use slog::{debug, error, info, o, warn}; -use ssz::TreeHash; use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; +use tree_hash::TreeHash; use types::{Attestation, BeaconBlock, Epoch, Hash256, Slot}; /// The number of slots that we can import blocks ahead of us, before going into full Sync mode. @@ -565,7 +565,7 @@ impl SimpleSync { return false; } - let block_root = Hash256::from_slice(&block.hash_tree_root()); + let block_root = Hash256::from_slice(&block.tree_hash_root()); // Ignore any block that the chain already knows about. if self.chain_has_seen_block(&block_root) { diff --git a/eth2/attester/src/lib.rs b/eth2/attester/src/lib.rs index a4295f0052..a9e3091aff 100644 --- a/eth2/attester/src/lib.rs +++ b/eth2/attester/src/lib.rs @@ -2,8 +2,8 @@ pub mod test_utils; mod traits; use slot_clock::SlotClock; -use ssz::TreeHash; use std::sync::Arc; +use tree_hash::TreeHash; use types::{AttestationData, AttestationDataAndCustodyBit, FreeAttestation, Signature, Slot}; pub use self::traits::{ @@ -141,7 +141,8 @@ impl Attester BlockProducer Result< let active_index_root = Hash256::from_slice( &state .get_active_validator_indices(next_epoch + spec.activation_exit_delay) - .hash_tree_root()[..], + .tree_hash_root()[..], ); state.set_active_index_root(next_epoch, active_index_root, spec)?; @@ -261,7 +261,7 @@ pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result< let historical_batch: HistoricalBatch = state.historical_batch(); state .historical_roots - .push(Hash256::from_slice(&historical_batch.hash_tree_root()[..])); + .push(Hash256::from_slice(&historical_batch.tree_hash_root()[..])); } state.previous_epoch_attestations = state.current_epoch_attestations.clone(); diff --git a/eth2/state_processing/src/per_slot_processing.rs b/eth2/state_processing/src/per_slot_processing.rs index c6b5312c70..cd129a5f15 100644 --- a/eth2/state_processing/src/per_slot_processing.rs +++ b/eth2/state_processing/src/per_slot_processing.rs @@ -1,5 +1,5 @@ use crate::*; -use ssz::TreeHash; +use tree_hash::TreeHash; use types::*; #[derive(Debug, PartialEq)] @@ -32,7 +32,7 @@ fn cache_state( latest_block_header: &BeaconBlockHeader, spec: &ChainSpec, ) -> Result<(), Error> { - let previous_slot_state_root = Hash256::from_slice(&state.hash_tree_root()[..]); + let previous_slot_state_root = Hash256::from_slice(&state.tree_hash_root()[..]); // Note: increment the state slot here to allow use of our `state_root` and `block_root` // getter/setter functions. @@ -46,7 +46,7 @@ fn cache_state( state.latest_block_header.state_root = previous_slot_state_root } - let latest_block_root = Hash256::from_slice(&latest_block_header.hash_tree_root()[..]); + let latest_block_root = Hash256::from_slice(&latest_block_header.tree_hash_root()[..]); state.set_block_root(previous_slot, latest_block_root, spec)?; // Set the state slot back to what it should be. diff --git a/eth2/types/Cargo.toml b/eth2/types/Cargo.toml index 613eb79360..b88e1d4cf9 100644 --- a/eth2/types/Cargo.toml +++ b/eth2/types/Cargo.toml @@ -26,6 +26,8 @@ ssz = { path = "../utils/ssz" } ssz_derive = { path = "../utils/ssz_derive" } swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" } test_random_derive = { path = "../utils/test_random_derive" } +tree_hash = { path = "../utils/tree_hash" } +tree_hash_derive = { path = "../utils/tree_hash_derive" } libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" } [dev-dependencies] diff --git a/eth2/types/src/attestation.rs b/eth2/types/src/attestation.rs index a8eeea9099..c43692a7ba 100644 --- a/eth2/types/src/attestation.rs +++ b/eth2/types/src/attestation.rs @@ -2,9 +2,10 @@ use super::{AggregateSignature, AttestationData, Bitfield}; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// Details an attestation that can be slashable. /// diff --git a/eth2/types/src/attestation_data.rs b/eth2/types/src/attestation_data.rs index 4a6b57823e..305ddafe0a 100644 --- a/eth2/types/src/attestation_data.rs +++ b/eth2/types/src/attestation_data.rs @@ -2,9 +2,10 @@ use crate::test_utils::TestRandom; use crate::{Crosslink, Epoch, Hash256, Slot}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// The data upon which an attestation is based. /// diff --git a/eth2/types/src/attestation_data_and_custody_bit.rs b/eth2/types/src/attestation_data_and_custody_bit.rs index 2cc6bc80ca..59a4eee772 100644 --- a/eth2/types/src/attestation_data_and_custody_bit.rs +++ b/eth2/types/src/attestation_data_and_custody_bit.rs @@ -2,7 +2,8 @@ use super::AttestationData; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::Serialize; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; +use tree_hash_derive::TreeHash; /// Used for pairing an attestation with a proof-of-custody. /// diff --git a/eth2/types/src/attester_slashing.rs b/eth2/types/src/attester_slashing.rs index 6fc404f422..0600e0ecc5 100644 --- a/eth2/types/src/attester_slashing.rs +++ b/eth2/types/src/attester_slashing.rs @@ -1,8 +1,9 @@ use crate::{test_utils::TestRandom, SlashableAttestation}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Two conflicting attestations. /// diff --git a/eth2/types/src/beacon_block.rs b/eth2/types/src/beacon_block.rs index 77c1620f3d..bc6ccb0d53 100644 --- a/eth2/types/src/beacon_block.rs +++ b/eth2/types/src/beacon_block.rs @@ -3,9 +3,10 @@ use crate::*; use bls::Signature; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// A block of the `BeaconChain`. /// @@ -57,11 +58,11 @@ impl BeaconBlock { } } - /// Returns the `hash_tree_root` of the block. + /// Returns the `tree_hash_root | update` of the block. /// /// Spec v0.5.0 pub fn canonical_root(&self) -> Hash256 { - Hash256::from_slice(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.tree_hash_root()[..]) } /// Returns a full `BeaconBlockHeader` of this block. @@ -77,7 +78,7 @@ impl BeaconBlock { slot: self.slot, previous_block_root: self.previous_block_root, state_root: self.state_root, - block_body_root: Hash256::from_slice(&self.body.hash_tree_root()[..]), + block_body_root: Hash256::from_slice(&self.body.tree_hash_root()[..]), signature: self.signature.clone(), } } diff --git a/eth2/types/src/beacon_block_body.rs b/eth2/types/src/beacon_block_body.rs index 677e24cec3..0414d0d72f 100644 --- a/eth2/types/src/beacon_block_body.rs +++ b/eth2/types/src/beacon_block_body.rs @@ -2,8 +2,9 @@ use crate::test_utils::TestRandom; use crate::*; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// The body of a `BeaconChain` block, containing operations. /// diff --git a/eth2/types/src/beacon_block_header.rs b/eth2/types/src/beacon_block_header.rs index 090d0a9653..9076437c0b 100644 --- a/eth2/types/src/beacon_block_header.rs +++ b/eth2/types/src/beacon_block_header.rs @@ -3,9 +3,10 @@ use crate::*; use bls::Signature; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// A header of a `BeaconBlock`. /// @@ -32,11 +33,11 @@ pub struct BeaconBlockHeader { } impl BeaconBlockHeader { - /// Returns the `hash_tree_root` of the header. + /// Returns the `tree_hash_root` of the header. /// /// Spec v0.5.0 pub fn canonical_root(&self) -> Hash256 { - Hash256::from_slice(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.tree_hash_root()[..]) } /// Given a `body`, consumes `self` and returns a complete `BeaconBlock`. diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index 774e8eb761..19c1b4c11c 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -5,9 +5,11 @@ use int_to_bytes::int_to_bytes32; use pubkey_cache::PubkeyCache; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::{hash, ssz_encode, TreeHash}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz::{hash, ssz_encode}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::TreeHash; mod epoch_cache; mod pubkey_cache; @@ -186,11 +188,11 @@ impl BeaconState { } } - /// Returns the `hash_tree_root` of the state. + /// Returns the `tree_hash_root` of the state. /// /// Spec v0.5.0 pub fn canonical_root(&self) -> Hash256 { - Hash256::from_slice(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.tree_hash_root()[..]) } pub fn historical_batch(&self) -> HistoricalBatch { diff --git a/eth2/types/src/crosslink.rs b/eth2/types/src/crosslink.rs index f91680c756..a0fd7e0b3e 100644 --- a/eth2/types/src/crosslink.rs +++ b/eth2/types/src/crosslink.rs @@ -2,8 +2,9 @@ use crate::test_utils::TestRandom; use crate::{Epoch, Hash256}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Specifies the block hash for a shard at an epoch. /// diff --git a/eth2/types/src/crosslink_committee.rs b/eth2/types/src/crosslink_committee.rs index af1778a1b7..e8fc1b96d9 100644 --- a/eth2/types/src/crosslink_committee.rs +++ b/eth2/types/src/crosslink_committee.rs @@ -1,6 +1,7 @@ use crate::*; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; +use tree_hash_derive::TreeHash; #[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize, Decode, Encode, TreeHash)] pub struct CrosslinkCommittee { diff --git a/eth2/types/src/deposit.rs b/eth2/types/src/deposit.rs index ff8d83d77d..5eb565c2b0 100644 --- a/eth2/types/src/deposit.rs +++ b/eth2/types/src/deposit.rs @@ -2,8 +2,9 @@ use super::{DepositData, Hash256}; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// A deposit to potentially become a beacon chain validator. /// diff --git a/eth2/types/src/deposit_data.rs b/eth2/types/src/deposit_data.rs index a1e30032fb..f8726e95d6 100644 --- a/eth2/types/src/deposit_data.rs +++ b/eth2/types/src/deposit_data.rs @@ -2,8 +2,9 @@ use super::DepositInput; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Data generated by the deposit contract. /// diff --git a/eth2/types/src/deposit_input.rs b/eth2/types/src/deposit_input.rs index 380528dc0b..8284962937 100644 --- a/eth2/types/src/deposit_input.rs +++ b/eth2/types/src/deposit_input.rs @@ -3,9 +3,10 @@ use crate::*; use bls::{PublicKey, Signature}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::{SignedRoot, TreeHash}; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::{SignedRoot, TreeHash}; +use tree_hash_derive::{SignedRoot, TreeHash}; /// The data supplied by the user to the deposit contract. /// diff --git a/eth2/types/src/epoch_cache.rs b/eth2/types/src/epoch_cache.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/eth2/types/src/eth1_data.rs b/eth2/types/src/eth1_data.rs index deced19fb6..c1348cfba5 100644 --- a/eth2/types/src/eth1_data.rs +++ b/eth2/types/src/eth1_data.rs @@ -2,8 +2,9 @@ use super::Hash256; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Contains data obtained from the Eth1 chain. /// diff --git a/eth2/types/src/eth1_data_vote.rs b/eth2/types/src/eth1_data_vote.rs index 2f3a1ade1a..a9741f0659 100644 --- a/eth2/types/src/eth1_data_vote.rs +++ b/eth2/types/src/eth1_data_vote.rs @@ -2,8 +2,9 @@ use super::Eth1Data; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// A summation of votes for some `Eth1Data`. /// diff --git a/eth2/types/src/fork.rs b/eth2/types/src/fork.rs index b9d16c3332..99908e9eda 100644 --- a/eth2/types/src/fork.rs +++ b/eth2/types/src/fork.rs @@ -5,8 +5,9 @@ use crate::{ use int_to_bytes::int_to_bytes4; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Specifies a fork of the `BeaconChain`, to prevent replay attacks. /// diff --git a/eth2/types/src/historical_batch.rs b/eth2/types/src/historical_batch.rs index 77859ed1ae..33dc9c4503 100644 --- a/eth2/types/src/historical_batch.rs +++ b/eth2/types/src/historical_batch.rs @@ -2,8 +2,9 @@ use crate::test_utils::TestRandom; use crate::Hash256; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Historical block and state roots. /// diff --git a/eth2/types/src/pending_attestation.rs b/eth2/types/src/pending_attestation.rs index 938e59beff..5cbe1edeb2 100644 --- a/eth2/types/src/pending_attestation.rs +++ b/eth2/types/src/pending_attestation.rs @@ -2,8 +2,9 @@ use crate::test_utils::TestRandom; use crate::{Attestation, AttestationData, Bitfield, Slot}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// An attestation that has been included in the state but not yet fully processed. /// diff --git a/eth2/types/src/proposer_slashing.rs b/eth2/types/src/proposer_slashing.rs index 02216a2fc6..901f023886 100644 --- a/eth2/types/src/proposer_slashing.rs +++ b/eth2/types/src/proposer_slashing.rs @@ -2,8 +2,9 @@ use super::BeaconBlockHeader; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Two conflicting proposals from the same proposer (validator). /// diff --git a/eth2/types/src/slashable_attestation.rs b/eth2/types/src/slashable_attestation.rs index e557285b80..37462f0069 100644 --- a/eth2/types/src/slashable_attestation.rs +++ b/eth2/types/src/slashable_attestation.rs @@ -1,9 +1,10 @@ use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// Details an attestation that can be slashable. /// diff --git a/eth2/types/src/slot_epoch.rs b/eth2/types/src/slot_epoch.rs index d334177e58..6c6a92ecb9 100644 --- a/eth2/types/src/slot_epoch.rs +++ b/eth2/types/src/slot_epoch.rs @@ -14,7 +14,7 @@ use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use slog; -use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; +use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use std::cmp::{Ord, Ordering}; use std::fmt; use std::hash::{Hash, Hasher}; diff --git a/eth2/types/src/slot_epoch_macros.rs b/eth2/types/src/slot_epoch_macros.rs index 300ad3f6f4..b3ca5c4bc6 100644 --- a/eth2/types/src/slot_epoch_macros.rs +++ b/eth2/types/src/slot_epoch_macros.rs @@ -206,11 +206,21 @@ macro_rules! impl_ssz { } } - impl TreeHash for $type { - fn hash_tree_root(&self) -> Vec { - let mut result: Vec = vec![]; - result.append(&mut self.0.hash_tree_root()); - hash(&result) + impl tree_hash::TreeHash for $type { + fn tree_hash_type() -> tree_hash::TreeHashType { + tree_hash::TreeHashType::Basic + } + + fn tree_hash_packed_encoding(&self) -> Vec { + ssz_encode(self) + } + + fn tree_hash_packing_factor() -> usize { + 32 / 8 + } + + fn tree_hash_root(&self) -> Vec { + int_to_bytes::int_to_bytes32(self.0) } } diff --git a/eth2/types/src/slot_height.rs b/eth2/types/src/slot_height.rs index 4a783d4a06..f7a34cbbaf 100644 --- a/eth2/types/src/slot_height.rs +++ b/eth2/types/src/slot_height.rs @@ -2,7 +2,7 @@ use crate::slot_epoch::{Epoch, Slot}; use crate::test_utils::TestRandom; use rand::RngCore; use serde_derive::Serialize; -use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; +use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use std::cmp::{Ord, Ordering}; use std::fmt; use std::hash::{Hash, Hasher}; diff --git a/eth2/types/src/test_utils/macros.rs b/eth2/types/src/test_utils/macros.rs index d580fd818f..d5711e96e3 100644 --- a/eth2/types/src/test_utils/macros.rs +++ b/eth2/types/src/test_utils/macros.rs @@ -17,14 +17,14 @@ macro_rules! ssz_tests { } #[test] - pub fn test_hash_tree_root() { + pub fn test_tree_hash_root() { use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::TreeHash; + use tree_hash::TreeHash; let mut rng = XorShiftRng::from_seed([42; 16]); let original = $type::random_for_test(&mut rng); - let result = original.hash_tree_root(); + let result = original.tree_hash_root(); assert_eq!(result.len(), 32); // TODO: Add further tests diff --git a/eth2/types/src/test_utils/testing_attestation_builder.rs b/eth2/types/src/test_utils/testing_attestation_builder.rs index 60624b48d7..162facc8ea 100644 --- a/eth2/types/src/test_utils/testing_attestation_builder.rs +++ b/eth2/types/src/test_utils/testing_attestation_builder.rs @@ -1,6 +1,6 @@ use crate::test_utils::TestingAttestationDataBuilder; use crate::*; -use ssz::TreeHash; +use tree_hash::TreeHash; /// Builds an attestation to be used for testing purposes. /// @@ -74,7 +74,7 @@ impl TestingAttestationBuilder { data: self.attestation.data.clone(), custody_bit: false, } - .hash_tree_root(); + .tree_hash_root(); let domain = spec.get_domain( self.attestation.data.slot.epoch(spec.slots_per_epoch), diff --git a/eth2/types/src/test_utils/testing_attester_slashing_builder.rs b/eth2/types/src/test_utils/testing_attester_slashing_builder.rs index fcaa3285be..dc01f7fb02 100644 --- a/eth2/types/src/test_utils/testing_attester_slashing_builder.rs +++ b/eth2/types/src/test_utils/testing_attester_slashing_builder.rs @@ -1,5 +1,5 @@ use crate::*; -use ssz::TreeHash; +use tree_hash::TreeHash; /// Builds an `AttesterSlashing`. /// @@ -66,7 +66,7 @@ impl TestingAttesterSlashingBuilder { data: attestation.data.clone(), custody_bit: false, }; - let message = attestation_data_and_custody_bit.hash_tree_root(); + let message = attestation_data_and_custody_bit.tree_hash_root(); for (i, validator_index) in validator_indices.iter().enumerate() { attestation.custody_bitfield.set(i, false); diff --git a/eth2/types/src/test_utils/testing_beacon_block_builder.rs b/eth2/types/src/test_utils/testing_beacon_block_builder.rs index c5cd22ed46..549c00ac08 100644 --- a/eth2/types/src/test_utils/testing_beacon_block_builder.rs +++ b/eth2/types/src/test_utils/testing_beacon_block_builder.rs @@ -6,7 +6,7 @@ use crate::{ *, }; use rayon::prelude::*; -use ssz::{SignedRoot, TreeHash}; +use tree_hash::{SignedRoot, TreeHash}; /// Builds a beacon block to be used for testing purposes. /// @@ -43,7 +43,7 @@ impl TestingBeaconBlockBuilder { /// Modifying the block's slot after signing may invalidate the signature. pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { let epoch = self.block.slot.epoch(spec.slots_per_epoch); - let message = epoch.hash_tree_root(); + let message = epoch.tree_hash_root(); let domain = spec.get_domain(epoch, Domain::Randao, fork); self.block.body.randao_reveal = Signature::new(&message, domain, sk); } diff --git a/eth2/types/src/test_utils/testing_proposer_slashing_builder.rs b/eth2/types/src/test_utils/testing_proposer_slashing_builder.rs index 2cfebd9153..03c257b2d2 100644 --- a/eth2/types/src/test_utils/testing_proposer_slashing_builder.rs +++ b/eth2/types/src/test_utils/testing_proposer_slashing_builder.rs @@ -1,5 +1,5 @@ use crate::*; -use ssz::SignedRoot; +use tree_hash::SignedRoot; /// Builds a `ProposerSlashing`. /// diff --git a/eth2/types/src/test_utils/testing_transfer_builder.rs b/eth2/types/src/test_utils/testing_transfer_builder.rs index 354e29aa56..2680f7b664 100644 --- a/eth2/types/src/test_utils/testing_transfer_builder.rs +++ b/eth2/types/src/test_utils/testing_transfer_builder.rs @@ -1,5 +1,5 @@ use crate::*; -use ssz::SignedRoot; +use tree_hash::SignedRoot; /// Builds a transfer to be used for testing purposes. /// diff --git a/eth2/types/src/test_utils/testing_voluntary_exit_builder.rs b/eth2/types/src/test_utils/testing_voluntary_exit_builder.rs index fe5c8325ad..8583bc4517 100644 --- a/eth2/types/src/test_utils/testing_voluntary_exit_builder.rs +++ b/eth2/types/src/test_utils/testing_voluntary_exit_builder.rs @@ -1,5 +1,5 @@ use crate::*; -use ssz::SignedRoot; +use tree_hash::SignedRoot; /// Builds an exit to be used for testing purposes. /// diff --git a/eth2/types/src/transfer.rs b/eth2/types/src/transfer.rs index f291190b29..f40050bc4e 100644 --- a/eth2/types/src/transfer.rs +++ b/eth2/types/src/transfer.rs @@ -4,9 +4,10 @@ use bls::{PublicKey, Signature}; use derivative::Derivative; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// The data submitted to the deposit contract. /// diff --git a/eth2/types/src/validator.rs b/eth2/types/src/validator.rs index f572611757..67b4e85df1 100644 --- a/eth2/types/src/validator.rs +++ b/eth2/types/src/validator.rs @@ -1,8 +1,9 @@ use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash_derive::TreeHash; /// Information about a `BeaconChain` validator. /// diff --git a/eth2/types/src/voluntary_exit.rs b/eth2/types/src/voluntary_exit.rs index 0cdc63149d..16d22c5441 100644 --- a/eth2/types/src/voluntary_exit.rs +++ b/eth2/types/src/voluntary_exit.rs @@ -2,9 +2,10 @@ use crate::{test_utils::TestRandom, Epoch}; use bls::Signature; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; -use ssz::TreeHash; -use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; +use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; +use tree_hash::TreeHash; +use tree_hash_derive::{SignedRoot, TreeHash}; /// An exit voluntarily submitted a validator who wishes to withdraw. /// diff --git a/eth2/utils/bls/Cargo.toml b/eth2/utils/bls/Cargo.toml index 4230a06eae..439debdcbb 100644 --- a/eth2/utils/bls/Cargo.toml +++ b/eth2/utils/bls/Cargo.toml @@ -12,3 +12,4 @@ serde = "1.0" serde_derive = "1.0" serde_hex = { path = "../serde_hex" } ssz = { path = "../ssz" } +tree_hash = { path = "../tree_hash" } diff --git a/eth2/utils/bls/src/aggregate_signature.rs b/eth2/utils/bls/src/aggregate_signature.rs index 8c7ae5222e..156e362e25 100644 --- a/eth2/utils/bls/src/aggregate_signature.rs +++ b/eth2/utils/bls/src/aggregate_signature.rs @@ -166,7 +166,7 @@ impl<'de> Deserialize<'de> for AggregateSignature { } impl TreeHash for AggregateSignature { - fn hash_tree_root(&self) -> Vec { + fn tree_hash_root(&self) -> Vec { hash(&self.as_bytes()) } } diff --git a/eth2/utils/bls/src/fake_aggregate_signature.rs b/eth2/utils/bls/src/fake_aggregate_signature.rs index 3f0ec0d6df..602639b6bd 100644 --- a/eth2/utils/bls/src/fake_aggregate_signature.rs +++ b/eth2/utils/bls/src/fake_aggregate_signature.rs @@ -2,7 +2,8 @@ use super::{fake_signature::FakeSignature, AggregatePublicKey, BLS_AGG_SIG_BYTE_ use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; -use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; +use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream}; +use tree_hash::impl_tree_hash_for_ssz_bytes; /// A BLS aggregate signature. /// @@ -98,11 +99,7 @@ impl<'de> Deserialize<'de> for FakeAggregateSignature { } } -impl TreeHash for FakeAggregateSignature { - fn hash_tree_root(&self) -> Vec { - hash(&self.bytes) - } -} +impl_tree_hash_for_ssz_bytes!(FakeAggregateSignature); #[cfg(test)] mod tests { diff --git a/eth2/utils/bls/src/fake_signature.rs b/eth2/utils/bls/src/fake_signature.rs index 3c9f3a9f44..b07dd66a59 100644 --- a/eth2/utils/bls/src/fake_signature.rs +++ b/eth2/utils/bls/src/fake_signature.rs @@ -3,7 +3,8 @@ use hex::encode as hex_encode; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::HexVisitor; -use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; +use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream}; +use tree_hash::impl_tree_hash_for_ssz_bytes; /// A single BLS signature. /// @@ -73,11 +74,7 @@ impl Decodable for FakeSignature { } } -impl TreeHash for FakeSignature { - fn hash_tree_root(&self) -> Vec { - hash(&self.bytes) - } -} +impl_tree_hash_for_ssz_bytes!(FakeSignature); 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 177a735c42..a553ee888c 100644 --- a/eth2/utils/bls/src/public_key.rs +++ b/eth2/utils/bls/src/public_key.rs @@ -3,10 +3,11 @@ use bls_aggregates::PublicKey as RawPublicKey; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::{encode as hex_encode, HexVisitor}; -use ssz::{decode, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; +use ssz::{decode, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use std::default; use std::fmt; use std::hash::{Hash, Hasher}; +use tree_hash::impl_tree_hash_for_ssz_bytes; /// A single BLS signature. /// @@ -104,11 +105,7 @@ impl<'de> Deserialize<'de> for PublicKey { } } -impl TreeHash for PublicKey { - fn hash_tree_root(&self) -> Vec { - hash(&self.0.as_bytes()) - } -} +impl_tree_hash_for_ssz_bytes!(PublicKey); impl PartialEq for PublicKey { fn eq(&self, other: &PublicKey) -> bool { diff --git a/eth2/utils/bls/src/secret_key.rs b/eth2/utils/bls/src/secret_key.rs index 40c4695131..38fd2d379c 100644 --- a/eth2/utils/bls/src/secret_key.rs +++ b/eth2/utils/bls/src/secret_key.rs @@ -4,7 +4,8 @@ use hex::encode as hex_encode; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_hex::HexVisitor; -use ssz::{decode, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; +use ssz::{decode, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; +use tree_hash::impl_tree_hash_for_ssz_bytes; /// A single BLS signature. /// @@ -69,11 +70,7 @@ impl<'de> Deserialize<'de> for SecretKey { } } -impl TreeHash for SecretKey { - fn hash_tree_root(&self) -> Vec { - self.0.as_bytes().clone() - } -} +impl_tree_hash_for_ssz_bytes!(SecretKey); #[cfg(test)] mod tests { diff --git a/eth2/utils/bls/src/signature.rs b/eth2/utils/bls/src/signature.rs index d19af545f0..30b55a787d 100644 --- a/eth2/utils/bls/src/signature.rs +++ b/eth2/utils/bls/src/signature.rs @@ -115,7 +115,7 @@ impl Decodable for Signature { } impl TreeHash for Signature { - fn hash_tree_root(&self) -> Vec { + fn tree_hash_root(&self) -> Vec { hash(&self.as_bytes()) } } diff --git a/eth2/utils/boolean-bitfield/Cargo.toml b/eth2/utils/boolean-bitfield/Cargo.toml index cf037c5d70..f08695bd13 100644 --- a/eth2/utils/boolean-bitfield/Cargo.toml +++ b/eth2/utils/boolean-bitfield/Cargo.toml @@ -10,3 +10,4 @@ ssz = { path = "../ssz" } bit-vec = "0.5.0" serde = "1.0" serde_derive = "1.0" +tree_hash = { path = "../tree_hash" } diff --git a/eth2/utils/boolean-bitfield/src/lib.rs b/eth2/utils/boolean-bitfield/src/lib.rs index d04516dbac..fbd0e2ecd5 100644 --- a/eth2/utils/boolean-bitfield/src/lib.rs +++ b/eth2/utils/boolean-bitfield/src/lib.rs @@ -9,6 +9,7 @@ use serde_hex::{encode, PrefixedHexVisitor}; use ssz::{Decodable, Encodable}; use std::cmp; use std::default; +use tree_hash::impl_tree_hash_for_ssz_bytes; /// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits. /// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set. @@ -256,11 +257,7 @@ impl<'de> Deserialize<'de> for BooleanBitfield { } } -impl ssz::TreeHash for BooleanBitfield { - fn hash_tree_root(&self) -> Vec { - self.to_bytes().hash_tree_root() - } -} +impl_tree_hash_for_ssz_bytes!(BooleanBitfield); #[cfg(test)] mod tests { diff --git a/eth2/utils/ssz_derive/tests/test_derives.rs b/eth2/utils/ssz_derive/tests/test_derives.rs deleted file mode 100644 index e025dc3a5e..0000000000 --- a/eth2/utils/ssz_derive/tests/test_derives.rs +++ /dev/null @@ -1,94 +0,0 @@ -use ssz::{SignedRoot, TreeHash}; -use ssz_derive::{SignedRoot, TreeHash}; - -#[derive(TreeHash, SignedRoot)] -struct CryptoKitties { - best_kitty: u64, - worst_kitty: u8, - kitties: Vec, -} - -impl CryptoKitties { - fn new() -> Self { - CryptoKitties { - best_kitty: 9999, - worst_kitty: 1, - kitties: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43], - } - } - - fn hash(&self) -> Vec { - let mut list: Vec> = Vec::new(); - list.push(self.best_kitty.hash_tree_root()); - list.push(self.worst_kitty.hash_tree_root()); - list.push(self.kitties.hash_tree_root()); - ssz::merkle_hash(&mut list) - } -} - -#[test] -fn test_cryptokitties_hash() { - let kitties = CryptoKitties::new(); - let expected_hash = vec![ - 201, 9, 139, 14, 24, 247, 21, 55, 132, 211, 51, 125, 183, 186, 177, 33, 147, 210, 42, 108, - 174, 162, 221, 227, 157, 179, 15, 7, 97, 239, 82, 220, - ]; - assert_eq!(kitties.hash(), expected_hash); -} - -#[test] -fn test_simple_tree_hash_derive() { - let kitties = CryptoKitties::new(); - assert_eq!(kitties.hash_tree_root(), kitties.hash()); -} - -#[test] -fn test_simple_signed_root_derive() { - let kitties = CryptoKitties::new(); - assert_eq!(kitties.signed_root(), kitties.hash()); -} - -#[derive(TreeHash, SignedRoot)] -struct Casper { - friendly: bool, - #[tree_hash(skip_hashing)] - friends: Vec, - #[signed_root(skip_hashing)] - dead: bool, -} - -impl Casper { - fn new() -> Self { - Casper { - friendly: true, - friends: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - dead: true, - } - } - - fn expected_signed_hash(&self) -> Vec { - let mut list = Vec::new(); - list.push(self.friendly.hash_tree_root()); - list.push(self.friends.hash_tree_root()); - ssz::merkle_hash(&mut list) - } - - fn expected_tree_hash(&self) -> Vec { - let mut list = Vec::new(); - list.push(self.friendly.hash_tree_root()); - list.push(self.dead.hash_tree_root()); - ssz::merkle_hash(&mut list) - } -} - -#[test] -fn test_annotated_tree_hash_derive() { - let casper = Casper::new(); - assert_eq!(casper.hash_tree_root(), casper.expected_tree_hash()); -} - -#[test] -fn test_annotated_signed_root_derive() { - let casper = Casper::new(); - assert_eq!(casper.signed_root(), casper.expected_signed_hash()); -} diff --git a/eth2/utils/tree_hash/src/standard_tree_hash.rs b/eth2/utils/tree_hash/src/standard_tree_hash.rs index ea06771805..473d2a5f0d 100644 --- a/eth2/utils/tree_hash/src/standard_tree_hash.rs +++ b/eth2/utils/tree_hash/src/standard_tree_hash.rs @@ -25,9 +25,14 @@ pub fn efficient_merkleize(bytes: &[u8]) -> Vec { let nodes = num_nodes(leaves); let internal_nodes = nodes - leaves; - let num_bytes = internal_nodes * HASHSIZE + bytes.len(); + let num_bytes = std::cmp::max(internal_nodes, 1) * HASHSIZE + bytes.len(); let mut o: Vec = vec![0; internal_nodes * HASHSIZE]; + + if o.len() < HASHSIZE { + o.resize(HASHSIZE, 0); + } + o.append(&mut bytes.to_vec()); assert_eq!(o.len(), num_bytes); diff --git a/eth2/utils/tree_hash/src/standard_tree_hash/impls.rs b/eth2/utils/tree_hash/src/standard_tree_hash/impls.rs index 070e314b81..749d5b3bbc 100644 --- a/eth2/utils/tree_hash/src/standard_tree_hash/impls.rs +++ b/eth2/utils/tree_hash/src/standard_tree_hash/impls.rs @@ -30,6 +30,24 @@ impl_for_bitsize!(u64, 64); impl_for_bitsize!(usize, 64); impl_for_bitsize!(bool, 8); +impl TreeHash for [u8; 4] { + fn tree_hash_type() -> TreeHashType { + TreeHashType::List + } + + fn tree_hash_packed_encoding(&self) -> Vec { + panic!("bytesN should never be packed.") + } + + fn tree_hash_packing_factor() -> usize { + panic!("bytesN should never be packed.") + } + + fn tree_hash_root(&self) -> Vec { + merkle_root(&ssz::ssz_encode(self)) + } +} + impl TreeHash for H256 { fn tree_hash_type() -> TreeHashType { TreeHashType::Basic @@ -95,3 +113,20 @@ where hash(&root_and_len) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn bool() { + let mut true_bytes: Vec = vec![1]; + true_bytes.append(&mut vec![0; 31]); + + let false_bytes: Vec = vec![0; 32]; + + assert_eq!(true.tree_hash_root(), true_bytes); + assert_eq!(false.tree_hash_root(), false_bytes); + } + +} diff --git a/eth2/utils/tree_hash_derive/src/lib.rs b/eth2/utils/tree_hash_derive/src/lib.rs index dc3702c723..e3a7b4aaa2 100644 --- a/eth2/utils/tree_hash_derive/src/lib.rs +++ b/eth2/utils/tree_hash_derive/src/lib.rs @@ -31,12 +31,10 @@ fn get_hashable_named_field_idents<'a>(struct_data: &'a syn::DataStruct) -> Vec< /// /// The field attribute is: `#[tree_hash(skip_hashing)]` fn should_skip_hashing(field: &syn::Field) -> bool { - for attr in &field.attrs { - if attr.tts.to_string() == "( skip_hashing )" { - return true; - } - } - false + field + .attrs + .iter() + .any(|attr| attr.into_token_stream().to_string() == "# [ tree_hash ( skip_hashing ) ]") } /// Implements `tree_hash::CachedTreeHashSubTree` for some `struct`. diff --git a/eth2/utils/tree_hash_derive/tests/tests.rs b/eth2/utils/tree_hash_derive/tests/tests.rs index 721e77715a..a7c74b23e2 100644 --- a/eth2/utils/tree_hash_derive/tests/tests.rs +++ b/eth2/utils/tree_hash_derive/tests/tests.rs @@ -98,3 +98,85 @@ fn signed_root() { assert_eq!(unsigned.tree_hash_root(), signed.signed_root()); } + +#[derive(TreeHash, SignedRoot)] +struct CryptoKitties { + best_kitty: u64, + worst_kitty: u8, + kitties: Vec, +} + +impl CryptoKitties { + fn new() -> Self { + CryptoKitties { + best_kitty: 9999, + worst_kitty: 1, + kitties: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43], + } + } + + fn hash(&self) -> Vec { + let mut leaves = vec![]; + leaves.append(&mut self.best_kitty.tree_hash_root()); + leaves.append(&mut self.worst_kitty.tree_hash_root()); + leaves.append(&mut self.kitties.tree_hash_root()); + tree_hash::merkle_root(&leaves) + } +} + +#[test] +fn test_simple_tree_hash_derive() { + let kitties = CryptoKitties::new(); + assert_eq!(kitties.tree_hash_root(), kitties.hash()); +} + +#[test] +fn test_simple_signed_root_derive() { + let kitties = CryptoKitties::new(); + assert_eq!(kitties.signed_root(), kitties.hash()); +} + +#[derive(TreeHash, SignedRoot)] +struct Casper { + friendly: bool, + #[tree_hash(skip_hashing)] + friends: Vec, + #[signed_root(skip_hashing)] + dead: bool, +} + +impl Casper { + fn new() -> Self { + Casper { + friendly: true, + friends: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + dead: true, + } + } + + fn expected_signed_hash(&self) -> Vec { + let mut list = Vec::new(); + list.append(&mut self.friendly.tree_hash_root()); + list.append(&mut self.friends.tree_hash_root()); + tree_hash::merkle_root(&list) + } + + fn expected_tree_hash(&self) -> Vec { + let mut list = Vec::new(); + list.append(&mut self.friendly.tree_hash_root()); + list.append(&mut self.dead.tree_hash_root()); + tree_hash::merkle_root(&list) + } +} + +#[test] +fn test_annotated_tree_hash_derive() { + let casper = Casper::new(); + assert_eq!(casper.tree_hash_root(), casper.expected_tree_hash()); +} + +#[test] +fn test_annotated_signed_root_derive() { + let casper = Casper::new(); + assert_eq!(casper.signed_root(), casper.expected_signed_hash()); +} diff --git a/validator_client/src/attestation_producer/mod.rs b/validator_client/src/attestation_producer/mod.rs index 0fbc7bcbaa..d2dbdf2e27 100644 --- a/validator_client/src/attestation_producer/mod.rs +++ b/validator_client/src/attestation_producer/mod.rs @@ -8,7 +8,7 @@ use super::block_producer::{BeaconNodeError, PublishOutcome, ValidatorEvent}; use crate::signer::Signer; use beacon_node_attestation::BeaconNodeAttestation; use slog::{error, info, warn}; -use ssz::TreeHash; +use tree_hash::TreeHash; use types::{ AggregateSignature, Attestation, AttestationData, AttestationDataAndCustodyBit, AttestationDuty, Bitfield, @@ -123,7 +123,7 @@ impl<'a, B: BeaconNodeAttestation, S: Signer> AttestationProducer<'a, B, S> { data: attestation.clone(), custody_bit: false, } - .hash_tree_root(); + .tree_hash_root(); let sig = self.signer.sign_message(&message, domain)?; diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index 8b4f5abda0..9cc0460c7a 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -86,7 +86,7 @@ impl<'a, B: BeaconNodeBlock, S: Signer> BlockProducer<'a, B, S> { pub fn produce_block(&mut self) -> Result { let epoch = self.slot.epoch(self.spec.slots_per_epoch); - let message = epoch.hash_tree_root(); + let message = epoch.tree_hash_root(); let randao_reveal = match self.signer.sign_message( &message, self.spec.get_domain(epoch, Domain::Randao, &self.fork),