diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index b24921e317e..734b12ca83e 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -93,7 +93,6 @@ use std::io::Write; use std::sync::Arc; use store::{Error as DBError, HotStateSummary, KeyValueStore, StoreOp}; use task_executor::JoinHandle; -use tree_hash::TreeHash; use types::{ BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, ExecutionBlockHash, Hash256, InconsistentFork, PublicKey, PublicKeyBytes, RelativeEpoch, SignedBeaconBlock, @@ -2107,7 +2106,14 @@ pub fn verify_header_signature( fn write_state(prefix: &str, state: &BeaconState, log: &Logger) { if WRITE_BLOCK_PROCESSING_SSZ { - let root = state.tree_hash_root(); + let mut state = state.clone(); + let Ok(root) = state.canonical_root() else { + error!( + log, + "Unable to hash state for writing"; + ); + return; + }; let filename = format!("{}_slot_{}_root_{}.ssz", prefix, state.slot(), root); let mut path = std::env::temp_dir().join("lighthouse"); let _ = fs::create_dir_all(path.clone()); diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index 90461b8f03e..7217f2c640f 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -1195,7 +1195,7 @@ mod test { let head = chain.head_snapshot(); - let state = &head.beacon_state; + let mut state = head.beacon_state.clone(); let block = &head.beacon_block; assert_eq!(state.slot(), Slot::new(0), "should start from genesis"); @@ -1206,7 +1206,7 @@ mod test { ); assert_eq!( block.state_root(), - state.canonical_root(), + state.canonical_root().unwrap(), "block should have correct state root" ); assert_eq!( diff --git a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs index 3c05eba5eae..5e0513c8d30 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs @@ -720,12 +720,12 @@ mod test { let mut state_roots = Vec::new(); // Get enough blocks to fill the cache to capacity, ensuring all blocks have blobs while pending_blocks.len() < capacity { - let (pending_block, _) = availability_pending_block(&harness).await; + let (mut pending_block, _) = availability_pending_block(&harness).await; if pending_block.num_blobs_expected() == 0 { // we need blocks with blobs continue; } - let state_root = pending_block.import_data.state.canonical_root(); + let state_root = pending_block.import_data.state.canonical_root().unwrap(); states.push(pending_block.import_data.state.clone()); pending_blocks.push_back(pending_block); state_roots.push(state_root); diff --git a/beacon_node/beacon_chain/src/data_availability_checker/state_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/state_lru_cache.rs index e313ed06d2f..cf6eb669d5e 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker/state_lru_cache.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker/state_lru_cache.rs @@ -209,10 +209,10 @@ impl StateLRUCache { impl From> for DietAvailabilityPendingExecutedBlock { - fn from(value: AvailabilityPendingExecutedBlock) -> Self { + fn from(mut value: AvailabilityPendingExecutedBlock) -> Self { Self { block: value.block, - state_root: value.import_data.state.canonical_root(), + state_root: value.import_data.state.canonical_root().unwrap(), parent_block: value.import_data.parent_block, parent_eth1_finalization_data: value.import_data.parent_eth1_finalization_data, confirmed_state_roots: value.import_data.confirmed_state_roots, diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index bd98f19af6f..6b85d7aadf7 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -2246,7 +2246,7 @@ where .unwrap(); state = new_state; block_hash_from_slot.insert(*slot, block_hash); - state_hash_from_slot.insert(*slot, state.tree_hash_root().into()); + state_hash_from_slot.insert(*slot, state.canonical_root().unwrap().into()); latest_block_hash = Some(block_hash); } ( diff --git a/beacon_node/beacon_chain/tests/store_tests.rs b/beacon_node/beacon_chain/tests/store_tests.rs index 6b77df4f812..e675d6956e8 100644 --- a/beacon_node/beacon_chain/tests/store_tests.rs +++ b/beacon_node/beacon_chain/tests/store_tests.rs @@ -35,7 +35,6 @@ use store::{ }; use tempfile::{tempdir, TempDir}; use tokio::time::sleep; -use tree_hash::TreeHash; use types::test_utils::{SeedableRng, XorShiftRng}; use types::*; @@ -199,8 +198,8 @@ async fn heal_freezer_block_roots_with_skip_slots() { ); let harness = get_harness(store.clone(), LOW_VALIDATOR_COUNT); - let current_state = harness.get_current_state(); - let state_root = harness.get_current_state().tree_hash_root(); + let mut current_state = harness.get_current_state(); + let state_root = current_state.canonical_root().unwrap(); let all_validators = &harness.get_all_validators(); harness .add_attested_blocks_at_slots( @@ -611,12 +610,13 @@ async fn epoch_boundary_state_attestation_processing() { .get_blinded_block(&block_root) .unwrap() .expect("block exists"); - let epoch_boundary_state = store + let mut epoch_boundary_state = store .load_epoch_boundary_state(&block.state_root()) .expect("no error") .expect("epoch boundary state exists"); + let ebs_state_root = epoch_boundary_state.canonical_root().unwrap(); let ebs_of_ebs = store - .load_epoch_boundary_state(&epoch_boundary_state.canonical_root()) + .load_epoch_boundary_state(&ebs_state_root) .expect("no error") .expect("ebs of ebs exists"); assert_eq!(epoch_boundary_state, ebs_of_ebs); @@ -2604,9 +2604,9 @@ async fn weak_subjectivity_sync_test(slots: Vec, checkpoint_slot: Slot) { .unwrap() .map(Result::unwrap) { - let state = store.get_state(&state_root, Some(slot)).unwrap().unwrap(); + let mut state = store.get_state(&state_root, Some(slot)).unwrap().unwrap(); assert_eq!(state.slot(), slot); - assert_eq!(state.canonical_root(), state_root); + assert_eq!(state.canonical_root().unwrap(), state_root); } // Anchor slot is still set to the slot of the checkpoint block. diff --git a/beacon_node/http_api/tests/broadcast_validation_tests.rs b/beacon_node/http_api/tests/broadcast_validation_tests.rs index 6a3f7947e6b..78f9c819888 100644 --- a/beacon_node/http_api/tests/broadcast_validation_tests.rs +++ b/beacon_node/http_api/tests/broadcast_validation_tests.rs @@ -7,7 +7,6 @@ use eth2::types::{BroadcastValidation, PublishBlockRequest}; use http_api::test_utils::InteractiveTester; use http_api::{publish_blinded_block, publish_block, reconstruct_block, ProvenancedBlock}; use std::sync::Arc; -use tree_hash::TreeHash; use types::{Epoch, EthSpec, ForkName, Hash256, MainnetEthSpec, Slot}; use warp::Rejection; use warp_utils::reject::CustomBadRequest; @@ -353,13 +352,20 @@ pub async fn consensus_partial_pass_only_consensus() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block_a, _), state_after_a) = tester.harness.make_block(state_a.clone(), slot_b).await; - let ((block_b, blobs_b), state_after_b) = tester.harness.make_block(state_a, slot_b).await; + let ((block_a, _), mut state_after_a) = + tester.harness.make_block(state_a.clone(), slot_b).await; + let ((block_b, blobs_b), mut state_after_b) = tester.harness.make_block(state_a, slot_b).await; let block_b_root = block_b.canonical_root(); /* check for `make_block` curios */ - assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); - assert_eq!(block_b.state_root(), state_after_b.tree_hash_root()); + assert_eq!( + block_a.state_root(), + state_after_a.canonical_root().unwrap() + ); + assert_eq!( + block_b.state_root(), + state_after_b.canonical_root().unwrap() + ); assert_ne!(block_a.state_root(), block_b.state_root()); let gossip_block_contents_b = PublishBlockRequest::new(block_b, blobs_b) @@ -516,13 +522,19 @@ pub async fn equivocation_consensus_early_equivocation() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block_a, blobs_a), state_after_a) = + let ((block_a, blobs_a), mut state_after_a) = tester.harness.make_block(state_a.clone(), slot_b).await; - let ((block_b, blobs_b), state_after_b) = tester.harness.make_block(state_a, slot_b).await; + let ((block_b, blobs_b), mut state_after_b) = tester.harness.make_block(state_a, slot_b).await; /* check for `make_block` curios */ - assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); - assert_eq!(block_b.state_root(), state_after_b.tree_hash_root()); + assert_eq!( + block_a.state_root(), + state_after_a.canonical_root().unwrap() + ); + assert_eq!( + block_b.state_root(), + state_after_b.canonical_root().unwrap() + ); assert_ne!(block_a.state_root(), block_b.state_root()); /* submit `block_a` as valid */ @@ -642,13 +654,19 @@ pub async fn equivocation_consensus_late_equivocation() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let ((block_a, blobs_a), state_after_a) = + let ((block_a, blobs_a), mut state_after_a) = tester.harness.make_block(state_a.clone(), slot_b).await; - let ((block_b, blobs_b), state_after_b) = tester.harness.make_block(state_a, slot_b).await; + let ((block_b, blobs_b), mut state_after_b) = tester.harness.make_block(state_a, slot_b).await; /* check for `make_block` curios */ - assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); - assert_eq!(block_b.state_root(), state_after_b.tree_hash_root()); + assert_eq!( + block_a.state_root(), + state_after_a.canonical_root().unwrap() + ); + assert_eq!( + block_b.state_root(), + state_after_b.canonical_root().unwrap() + ); assert_ne!(block_a.state_root(), block_b.state_root()); let gossip_block_contents_b = PublishBlockRequest::new(block_b, blobs_b) @@ -1135,15 +1153,21 @@ pub async fn blinded_equivocation_consensus_early_equivocation() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let (block_a, state_after_a) = tester + let (block_a, mut state_after_a) = tester .harness .make_blinded_block(state_a.clone(), slot_b) .await; - let (block_b, state_after_b) = tester.harness.make_blinded_block(state_a, slot_b).await; + let (block_b, mut state_after_b) = tester.harness.make_blinded_block(state_a, slot_b).await; /* check for `make_blinded_block` curios */ - assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); - assert_eq!(block_b.state_root(), state_after_b.tree_hash_root()); + assert_eq!( + block_a.state_root(), + state_after_a.canonical_root().unwrap() + ); + assert_eq!( + block_b.state_root(), + state_after_b.canonical_root().unwrap() + ); assert_ne!(block_a.state_root(), block_b.state_root()); /* submit `block_a` as valid */ @@ -1259,16 +1283,22 @@ pub async fn blinded_equivocation_consensus_late_equivocation() { let slot_b = slot_a + 1; let state_a = tester.harness.get_current_state(); - let (block_a, state_after_a) = tester + let (block_a, mut state_after_a) = tester .harness .make_blinded_block(state_a.clone(), slot_b) .await; - let (block_b, state_after_b) = tester.harness.make_blinded_block(state_a, slot_b).await; + let (block_b, mut state_after_b) = tester.harness.make_blinded_block(state_a, slot_b).await; let block_b = Arc::new(block_b); /* check for `make_blinded_block` curios */ - assert_eq!(block_a.state_root(), state_after_a.tree_hash_root()); - assert_eq!(block_b.state_root(), state_after_b.tree_hash_root()); + assert_eq!( + block_a.state_root(), + state_after_a.canonical_root().unwrap() + ); + assert_eq!( + block_b.state_root(), + state_after_b.canonical_root().unwrap() + ); assert_ne!(block_a.state_root(), block_b.state_root()); let unblinded_block_a = reconstruct_block( diff --git a/beacon_node/http_api/tests/fork_tests.rs b/beacon_node/http_api/tests/fork_tests.rs index ad32ff1d579..1e20280da11 100644 --- a/beacon_node/http_api/tests/fork_tests.rs +++ b/beacon_node/http_api/tests/fork_tests.rs @@ -55,7 +55,7 @@ async fn sync_committee_duties_across_fork() { // though the head state hasn't transitioned yet. let fork_slot = fork_epoch.start_slot(E::slots_per_epoch()); let (genesis_state, genesis_state_root) = harness.get_current_state_and_root(); - let (_, state) = harness + let (_, mut state) = harness .add_attested_block_at_slot( fork_slot - 1, genesis_state, @@ -76,7 +76,7 @@ async fn sync_committee_duties_across_fork() { assert_eq!(sync_duties.len(), E::sync_committee_size()); // After applying a block at the fork slot the duties should remain unchanged. - let state_root = state.canonical_root(); + let state_root = state.canonical_root().unwrap(); harness .add_attested_block_at_slot(fork_slot, state, state_root, &all_validators) .await @@ -257,7 +257,7 @@ async fn sync_committee_indices_across_fork() { // applied. let fork_slot = fork_epoch.start_slot(E::slots_per_epoch()); let (genesis_state, genesis_state_root) = harness.get_current_state_and_root(); - let (_, state) = harness + let (_, mut state) = harness .add_attested_block_at_slot( fork_slot - 1, genesis_state, @@ -295,7 +295,7 @@ async fn sync_committee_indices_across_fork() { // Once the head is updated it should be useable for requests, including in the next sync // committee period. - let state_root = state.canonical_root(); + let state_root = state.canonical_root().unwrap(); harness .add_attested_block_at_slot(fork_slot + 1, state, state_root, &all_validators) .await diff --git a/beacon_node/http_api/tests/interactive_tests.rs b/beacon_node/http_api/tests/interactive_tests.rs index 711820ccac6..14673d23e12 100644 --- a/beacon_node/http_api/tests/interactive_tests.rs +++ b/beacon_node/http_api/tests/interactive_tests.rs @@ -17,7 +17,6 @@ use state_processing::{ use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; -use tree_hash::TreeHash; use types::{ Address, Epoch, EthSpec, ExecPayload, ExecutionBlockHash, ForkName, MainnetEthSpec, MinimalEthSpec, ProposerPreparationData, Slot, @@ -515,16 +514,17 @@ pub async fn proposer_boost_re_org_test( } harness.advance_slot(); - let (block_a_root, block_a, state_a) = harness + let (block_a_root, block_a, mut state_a) = harness .add_block_at_slot(slot_a, harness.get_current_state()) .await .unwrap(); + let state_a_root = state_a.canonical_root().unwrap(); // Attest to block A during slot A. let (block_a_parent_votes, _) = harness.make_attestations_with_limit( &all_validators, &state_a, - state_a.canonical_root(), + state_a_root, block_a_root, slot_a, num_parent_votes, @@ -538,7 +538,7 @@ pub async fn proposer_boost_re_org_test( let (block_a_empty_votes, block_a_attesters) = harness.make_attestations_with_limit( &all_validators, &state_a, - state_a.canonical_root(), + state_a_root, block_a_root, slot_b, num_empty_votes, @@ -553,6 +553,7 @@ pub async fn proposer_boost_re_org_test( // Produce block B and process it halfway through the slot. let (block_b, mut state_b) = harness.make_block(state_a.clone(), slot_b).await; + let state_b_root = state_b.canonical_root().unwrap(); let block_b_root = block_b.0.canonical_root(); let obs_time = slot_clock.start_of(slot_b).unwrap() + slot_clock.slot_duration() / 2; @@ -570,7 +571,7 @@ pub async fn proposer_boost_re_org_test( let (block_b_head_votes, _) = harness.make_attestations_with_limit( &remaining_attesters, &state_b, - state_b.canonical_root(), + state_b_root, block_b_root.into(), slot_b, num_head_votes, @@ -774,32 +775,34 @@ pub async fn fork_choice_before_proposal() { let slot_d = slot_a + 3; let state_a = harness.get_current_state(); - let (block_b, state_b) = harness.make_block(state_a.clone(), slot_b).await; + let (block_b, mut state_b) = harness.make_block(state_a.clone(), slot_b).await; let block_root_b = harness .process_block(slot_b, block_b.0.canonical_root(), block_b) .await .unwrap(); + let state_root_b = state_b.canonical_root().unwrap(); // Create attestations to B but keep them in reserve until after C has been processed. let attestations_b = harness.make_attestations( &all_validators, &state_b, - state_b.tree_hash_root(), + state_root_b, block_root_b, slot_b, ); - let (block_c, state_c) = harness.make_block(state_a, slot_c).await; + let (block_c, mut state_c) = harness.make_block(state_a, slot_c).await; let block_root_c = harness .process_block(slot_c, block_c.0.canonical_root(), block_c.clone()) .await .unwrap(); + let state_root_c = state_c.canonical_root().unwrap(); // Create attestations to C from a small number of validators and process them immediately. let attestations_c = harness.make_attestations( &all_validators[..validator_count / 2], &state_c, - state_c.tree_hash_root(), + state_root_c, block_root_c, slot_c, ); diff --git a/boot_node/src/config.rs b/boot_node/src/config.rs index a8b0f7aa563..aaa9f084826 100644 --- a/boot_node/src/config.rs +++ b/boot_node/src/config.rs @@ -102,14 +102,17 @@ impl BootNodeConfig { .map(Duration::from_secs)?; if eth2_network_config.genesis_state_is_known() { - let genesis_state = eth2_network_config + let mut genesis_state = eth2_network_config .genesis_state::(genesis_state_url.as_deref(), genesis_state_url_timeout, &logger).await? .ok_or_else(|| { "The genesis state for this network is not known, this is an unsupported mode" .to_string() })?; - slog::info!(logger, "Genesis state found"; "root" => genesis_state.canonical_root().to_string()); + let genesis_state_root = genesis_state + .canonical_root() + .map_err(|e| format!("Error hashing genesis state: {e:?}"))?; + slog::info!(logger, "Genesis state found"; "root" => ?genesis_state_root); let enr_fork = spec.enr_fork_id::( types::Slot::from(0u64), genesis_state.genesis_validators_root(), diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index 06220391793..456aa98fad7 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -214,6 +214,13 @@ impl From for Hash256 { } /// The state of the `BeaconChain` at some slot. +/// +/// Note: `BeaconState` does not implement `TreeHash` on the top-level type in order to +/// encourage use of the `canonical_root`/`update_tree_hash_cache` methods which flush pending +/// updates to the underlying persistent data structures. This is the safest option for now until +/// we add internal mutability to `milhouse::{List, Vector}`. See: +/// +/// https://github.com/sigp/milhouse/issues/43 #[superstruct( variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), variant_attributes( @@ -324,13 +331,10 @@ impl From for Hash256 { partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant"), map_ref_mut_into(BeaconStateRef) )] -#[derive( - Debug, PartialEq, Clone, Serialize, Deserialize, Encode, TreeHash, arbitrary::Arbitrary, -)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, arbitrary::Arbitrary)] #[serde(untagged)] #[serde(bound = "E: EthSpec")] #[arbitrary(bound = "E: EthSpec")] -#[tree_hash(enum_behaviour = "transparent")] #[ssz(enum_behaviour = "transparent")] pub struct BeaconState where @@ -652,10 +656,8 @@ impl BeaconState { } /// Returns the `tree_hash_root` of the state. - /// - /// Spec v0.12.1 - pub fn canonical_root(&self) -> Hash256 { - Hash256::from_slice(&self.tree_hash_root()[..]) + pub fn canonical_root(&mut self) -> Result { + self.update_tree_hash_cache() } pub fn historical_batch(&mut self) -> Result, Error> { @@ -2016,9 +2018,13 @@ impl BeaconState { /// Compute the tree hash root of the state using the tree hash cache. /// /// Initialize the tree hash cache if it isn't already initialized. - pub fn update_tree_hash_cache(&mut self) -> Result { + pub fn update_tree_hash_cache<'a>(&'a mut self) -> Result { self.apply_pending_mutations()?; - Ok(self.tree_hash_root()) + map_beacon_state_ref!(&'a _, self.to_ref(), |inner, cons| { + let root = inner.tree_hash_root(); + cons(inner); + Ok(root) + }) } /// Compute the tree hash root of the validators using the tree hash cache. diff --git a/consensus/types/src/light_client_update.rs b/consensus/types/src/light_client_update.rs index 76ad5689888..210fa0eeeb3 100644 --- a/consensus/types/src/light_client_update.rs +++ b/consensus/types/src/light_client_update.rs @@ -168,7 +168,7 @@ impl LightClientUpdate { let signature_period = block.epoch().sync_committee_period(chain_spec)?; // Compute and validate attested header. let mut attested_header = attested_state.latest_block_header().clone(); - attested_header.state_root = attested_state.tree_hash_root(); + attested_header.state_root = attested_state.update_tree_hash_cache()?; let attested_period = attested_header .slot .epoch(E::slots_per_epoch()) diff --git a/testing/ef_tests/src/cases/common.rs b/testing/ef_tests/src/cases/common.rs index 6763edbe22b..8b253919805 100644 --- a/testing/ef_tests/src/cases/common.rs +++ b/testing/ef_tests/src/cases/common.rs @@ -2,7 +2,6 @@ use serde::Deserialize; use ssz::Encode; use ssz_derive::{Decode, Encode}; use std::fmt::Debug; -use tree_hash::TreeHash; use types::ForkName; /// Macro to wrap U128 and U256 so they deserialize correctly. @@ -49,12 +48,12 @@ uint_wrapper!(TestU256, ethereum_types::U256); /// Trait for types that can be used in SSZ static tests. pub trait SszStaticType: - serde::de::DeserializeOwned + Encode + TreeHash + Clone + PartialEq + Debug + Sync + serde::de::DeserializeOwned + Encode + Clone + PartialEq + Debug + Sync { } impl SszStaticType for T where - T: serde::de::DeserializeOwned + Encode + TreeHash + Clone + PartialEq + Debug + Sync + T: serde::de::DeserializeOwned + Encode + Clone + PartialEq + Debug + Sync { } diff --git a/testing/ef_tests/src/cases/ssz_generic.rs b/testing/ef_tests/src/cases/ssz_generic.rs index 8de3e217f00..7933fc65c70 100644 --- a/testing/ef_tests/src/cases/ssz_generic.rs +++ b/testing/ef_tests/src/cases/ssz_generic.rs @@ -6,6 +6,7 @@ use crate::cases::ssz_static::{check_serialization, check_tree_hash}; use crate::decode::{log_file_access, snappy_decode_file, yaml_decode_file}; use serde::{de::Error as SerdeError, Deserialize, Deserializer}; use ssz_derive::{Decode, Encode}; +use tree_hash::TreeHash; use tree_hash_derive::TreeHash; use types::typenum::*; use types::{BitList, BitVector, FixedVector, ForkName, VariableList, Vector}; @@ -206,7 +207,7 @@ impl Case for SszGeneric { } } -fn ssz_generic_test(path: &Path) -> Result<(), Error> { +fn ssz_generic_test(path: &Path) -> Result<(), Error> { let meta_path = path.join("meta.yaml"); let meta: Option = if meta_path.is_file() { Some(yaml_decode_file(&meta_path)?) diff --git a/testing/ef_tests/src/cases/ssz_static.rs b/testing/ef_tests/src/cases/ssz_static.rs index 5f0ac3525c4..e17aa469bfc 100644 --- a/testing/ef_tests/src/cases/ssz_static.rs +++ b/testing/ef_tests/src/cases/ssz_static.rs @@ -101,7 +101,7 @@ pub fn check_tree_hash(expected_str: &str, actual_root: &[u8]) -> Result<(), Err compare_result::(&Ok(tree_hash_root), &Some(expected_root)) } -impl Case for SszStatic { +impl Case for SszStatic { fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> { check_serialization(&self.value, &self.serialized, T::from_ssz_bytes)?; check_tree_hash(&self.roots.root, self.value.tree_hash_root().as_bytes())?; @@ -115,7 +115,6 @@ impl Case for SszStaticTHC> { check_serialization(&self.value, &self.serialized, |bytes| { BeaconState::from_ssz_bytes(bytes, spec) })?; - check_tree_hash(&self.roots.root, self.value.tree_hash_root().as_bytes())?; let mut state = self.value.clone(); let cached_tree_hash_root = state.update_tree_hash_cache().unwrap(); diff --git a/testing/ef_tests/src/handler.rs b/testing/ef_tests/src/handler.rs index c1e7386bc45..69f6937ad85 100644 --- a/testing/ef_tests/src/handler.rs +++ b/testing/ef_tests/src/handler.rs @@ -262,7 +262,7 @@ pub struct SszStaticWithSpecHandler(PhantomData<(T, E)>); impl Handler for SszStaticHandler where - T: cases::SszStaticType + ssz::Decode + TypeName, + T: cases::SszStaticType + tree_hash::TreeHash + ssz::Decode + TypeName, E: TypeName, { type Case = cases::SszStatic;