From 944ac73ef9be8c4864c85401d2a40dd0ab97b124 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 16 May 2019 16:54:11 +1000 Subject: [PATCH] Add progress on epoch caching --- eth2/types/src/beacon_state.rs | 144 +++++++------ .../src/beacon_state/beacon_state_types.rs | 14 ++ eth2/types/src/beacon_state/epoch_cache.rs | 190 ++++++++---------- .../src/beacon_state/epoch_cache/tests.rs | 2 +- eth2/types/src/beacon_state/tests.rs | 8 +- eth2/types/src/relative_epoch.rs | 54 ++--- eth2/types/src/test_utils/builders.rs | 21 ++ .../testing_attestation_builder.rs | 0 .../testing_attestation_data_builder.rs | 8 +- .../testing_attester_slashing_builder.rs | 0 .../testing_beacon_block_builder.rs | 0 .../testing_beacon_state_builder.rs | 17 +- .../{ => builders}/testing_deposit_builder.rs | 0 .../testing_pending_attestation_builder.rs | 0 .../testing_proposer_slashing_builder.rs | 0 .../testing_transfer_builder.rs | 0 .../testing_voluntary_exit_builder.rs | 0 eth2/types/src/test_utils/mod.rs | 22 +- 18 files changed, 230 insertions(+), 250 deletions(-) create mode 100644 eth2/types/src/test_utils/builders.rs rename eth2/types/src/test_utils/{ => builders}/testing_attestation_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_attestation_data_builder.rs (91%) rename eth2/types/src/test_utils/{ => builders}/testing_attester_slashing_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_beacon_block_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_beacon_state_builder.rs (94%) rename eth2/types/src/test_utils/{ => builders}/testing_deposit_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_pending_attestation_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_proposer_slashing_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_transfer_builder.rs (100%) rename eth2/types/src/test_utils/{ => builders}/testing_voluntary_exit_builder.rs (100%) diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index 80677f563..cb218fe1f 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -23,7 +23,7 @@ mod exit_cache; mod pubkey_cache; mod tests; -pub const CACHED_EPOCHS: usize = 4; +pub const CACHED_EPOCHS: usize = 3; #[derive(Debug, PartialEq)] pub enum Error { @@ -49,6 +49,7 @@ pub enum Error { }, PreviousEpochCacheUninitialized, CurrentEpochCacheUnintialized, + EpochCacheUnintialized(RelativeEpoch), EpochCacheError(EpochCacheError), TreeHashCacheError(TreeHashCacheError), } @@ -117,13 +118,7 @@ where #[ssz(skip_deserializing)] #[tree_hash(skip_hashing)] #[test_random(default)] - pub previous_epoch_cache: EpochCache, - #[serde(default)] - #[ssz(skip_serializing)] - #[ssz(skip_deserializing)] - #[tree_hash(skip_hashing)] - #[test_random(default)] - pub current_epoch_cache: EpochCache, + pub epoch_caches: [EpochCache; CACHED_EPOCHS], #[serde(default)] #[ssz(skip_serializing)] #[ssz(skip_deserializing)] @@ -214,8 +209,11 @@ impl BeaconState { /* * Caching (not in spec) */ - previous_epoch_cache: EpochCache::default(), - current_epoch_cache: EpochCache::default(), + epoch_caches: [ + EpochCache::default(), + EpochCache::default(), + EpochCache::default(), + ], pubkey_cache: PubkeyCache::default(), tree_hash_cache: TreeHashCache::default(), exit_cache: ExitCache::default(), @@ -254,8 +252,8 @@ impl BeaconState { /// The epoch corresponding to `self.slot`. /// /// Spec v0.6.1 - pub fn current_epoch(&self, spec: &ChainSpec) -> Epoch { - self.slot.epoch(spec.slots_per_epoch) + pub fn current_epoch(&self) -> Epoch { + self.slot.epoch(T::slots_per_epoch()) } /// The epoch prior to `self.current_epoch()`. @@ -263,9 +261,9 @@ impl BeaconState { /// If the current epoch is the genesis epoch, the genesis_epoch is returned. /// /// Spec v0.6.1 - pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch { - let current_epoch = self.current_epoch(spec); - if current_epoch > spec.genesis_epoch { + pub fn previous_epoch(&self) -> Epoch { + let current_epoch = self.current_epoch(); + if current_epoch > T::genesis_epoch() { current_epoch - 1 } else { current_epoch @@ -275,8 +273,8 @@ impl BeaconState { /// The epoch following `self.current_epoch()`. /// /// Spec v0.6.1 - pub fn next_epoch(&self, spec: &ChainSpec) -> Epoch { - self.current_epoch(spec) + 1 + pub fn next_epoch(&self) -> Epoch { + self.current_epoch() + 1 } /// Return the number of committees at ``epoch``. @@ -301,13 +299,13 @@ impl BeaconState { /// /// Spec v0.6.1 pub fn get_epoch_start_shard(&self, epoch: Epoch, spec: &ChainSpec) -> Result { - if epoch > self.current_epoch(spec) + 1 { + if epoch > self.current_epoch() + 1 { return Err(Error::EpochOutOfBounds); } let shard_count = T::ShardCount::to_u64(); - let mut check_epoch = self.current_epoch(spec) + 1; + let mut check_epoch = self.current_epoch() + 1; let mut shard = (self.latest_start_shard - + self.get_shard_delta(self.current_epoch(spec), spec)) + + self.get_shard_delta(self.current_epoch(), spec)) % shard_count; while check_epoch > epoch { check_epoch -= 1; @@ -458,8 +456,8 @@ impl BeaconState { /// Safely obtains the index for `latest_randao_mixes` /// /// Spec v0.5.1 - fn get_randao_mix_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result { - let current_epoch = self.current_epoch(spec); + fn get_randao_mix_index(&self, epoch: Epoch) -> Result { + let current_epoch = self.current_epoch(); let len = T::LatestRandaoMixesLength::to_u64(); if (current_epoch - len < epoch) & (epoch <= current_epoch) { @@ -486,7 +484,7 @@ impl BeaconState { let signature_hash = Hash256::from_slice(&hash(&ssz_encode(signature))); - self.latest_randao_mixes[i] = *self.get_randao_mix(epoch, spec)? ^ signature_hash; + self.latest_randao_mixes[i] = *self.get_randao_mix(epoch)? ^ signature_hash; Ok(()) } @@ -494,21 +492,16 @@ impl BeaconState { /// Return the randao mix at a recent ``epoch``. /// /// Spec v0.5.1 - pub fn get_randao_mix(&self, epoch: Epoch, spec: &ChainSpec) -> Result<&Hash256, Error> { - let i = self.get_randao_mix_index(epoch, spec)?; + pub fn get_randao_mix(&self, epoch: Epoch) -> Result<&Hash256, Error> { + let i = self.get_randao_mix_index(epoch)?; Ok(&self.latest_randao_mixes[i]) } /// Set the randao mix at a recent ``epoch``. /// /// Spec v0.5.1 - pub fn set_randao_mix( - &mut self, - epoch: Epoch, - mix: Hash256, - spec: &ChainSpec, - ) -> Result<(), Error> { - let i = self.get_randao_mix_index(epoch, spec)?; + pub fn set_randao_mix(&mut self, epoch: Epoch, mix: Hash256) -> Result<(), Error> { + let i = self.get_randao_mix_index(epoch)?; self.latest_randao_mixes[i] = mix; Ok(()) } @@ -517,7 +510,7 @@ impl BeaconState { /// /// Spec v0.6.1 fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result { - let current_epoch = self.current_epoch(spec); + let current_epoch = self.current_epoch(); if current_epoch - self.latest_active_index_roots.len() as u64 + spec.activation_exit_delay < epoch @@ -627,9 +620,9 @@ impl BeaconState { epoch: Epoch, spec: &ChainSpec, ) -> Result<&[PendingAttestation], Error> { - if epoch == self.current_epoch(spec) { + if epoch == self.current_epoch() { Ok(&self.current_epoch_attestations) - } else if epoch == self.previous_epoch(spec) { + } else if epoch == self.previous_epoch() { Ok(&self.previous_epoch_attestations) } else { Err(Error::EpochOutOfBounds) @@ -659,7 +652,7 @@ impl BeaconState { /// Spec v0.5.1 pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result { let mut input = self - .get_randao_mix(epoch - spec.min_seed_lookahead, spec)? + .get_randao_mix(epoch - spec.min_seed_lookahead)? .as_bytes() .to_vec(); @@ -699,7 +692,7 @@ impl BeaconState { pub fn get_churn_limit(&self, spec: &ChainSpec) -> Result { Ok(std::cmp::max( spec.min_per_epoch_churn_limit, - self.cache(RelativeEpoch::Current, spec)? + self.cache(self.current_epoch(), spec)? .active_validator_indices .len() as u64 / spec.churn_limit_quotient, @@ -719,7 +712,7 @@ impl BeaconState { validator_index: usize, spec: &ChainSpec, ) -> Result<&Option, Error> { - let cache = self.cache(RelativeEpoch::Current, spec)?; + let cache = self.cache(self.current_epoch(), spec)?; Ok(cache .attestation_duties @@ -743,8 +736,9 @@ impl BeaconState { /// Build all the caches, if they need to be built. pub fn build_all_caches(&mut self, spec: &ChainSpec) -> Result<(), Error> { - self.build_previous_epoch_cache(spec)?; - self.build_current_epoch_cache(spec)?; + self.build_epoch_cache(RelativeEpoch::Previous, spec)?; + self.build_epoch_cache(RelativeEpoch::Current, spec)?; + self.build_epoch_cache(RelativeEpoch::Next, spec)?; self.update_pubkey_cache()?; self.update_tree_hash_cache()?; self.exit_cache @@ -754,9 +748,14 @@ impl BeaconState { } /// Build an epoch cache, unless it is has already been built. - pub fn build_previous_epoch_cache(&mut self, spec: &ChainSpec) -> Result<(), Error> { - if self.caches[cache_index].initialized_epoch == Some(self.slot.epoch(spec.slots_per_epoch)) - { + pub fn build_epoch_cache( + &mut self, + relative_epoch: RelativeEpoch, + spec: &ChainSpec, + ) -> Result<(), Error> { + let i = Self::cache_index(relative_epoch); + + if self.epoch_caches[i].is_initialized_at(self.previous_epoch()) { Ok(()) } else { self.force_build_epoch_cache(relative_epoch, spec) @@ -764,22 +763,14 @@ impl BeaconState { } /// Always builds the previous epoch cache, even if it is already initialized. - pub fn force_build_previous_epoch_cache(&mut self, spec: &ChainSpec) -> Result<(), Error> { - let epoch = self.previous_epoch(spec); - self.previous_epoch_cache = EpochCache::initialized( - &self, - epoch, - self.generate_seed(epoch, spec)?, - self.get_epoch_start_shard(epoch, spec)?, - spec, - )?; - Ok(()) - } + pub fn force_build_epoch_cache( + &mut self, + relative_epoch: RelativeEpoch, + spec: &ChainSpec, + ) -> Result<(), Error> { + let epoch = relative_epoch.into_epoch(self.current_epoch()); - /// Always builds the current epoch cache, even if it is already initialized. - pub fn force_build_current_epoch_cache(&mut self, spec: &ChainSpec) -> Result<(), Error> { - let epoch = self.current_epoch(spec); - self.current_epoch_cache = EpochCache::initialized( + self.epoch_caches[Self::cache_index(relative_epoch)] = EpochCache::initialized( &self, epoch, self.generate_seed(epoch, spec)?, @@ -792,10 +783,39 @@ impl BeaconState { /// Advances the cache for this state into the next epoch. /// /// This should be used if the `slot` of this state is advanced beyond an epoch boundary. - pub fn advance_caches(&mut self) { - self.previous_epoch_cache = - std::mem::replace(&mut self.current_epoch_cache, EpochCache::default()); - self.force_build_current_epoch_cache(); + /// + /// Note: whilst this function will preserve already-built caches, it will not build any. + pub fn advance_caches(&mut self, spec: &ChainSpec) { + let previous = Self::cache_index(RelativeEpoch::Previous); + let current = Self::cache_index(RelativeEpoch::Previous); + let next = Self::cache_index(RelativeEpoch::Previous); + + let caches = &mut self.epoch_caches[..]; + caches.rotate_left(1); + caches[next] = EpochCache::default(); + } + + fn cache_index(relative_epoch: RelativeEpoch) -> usize { + match relative_epoch { + RelativeEpoch::Previous => 0, + RelativeEpoch::Current => 1, + RelativeEpoch::Next => 2, + } + } + + /// Returns the cache for some `RelativeEpoch`. Returns an error if the cache has not been + /// initialized. + fn cache(&self, epoch: Epoch, spec: &ChainSpec) -> Result<&EpochCache, Error> { + let relative_epoch = RelativeEpoch::from_epoch(self.current_epoch(), epoch) + .map_err(|e| Error::EpochOutOfBounds)?; + + let cache = &self.epoch_caches[Self::cache_index(relative_epoch)]; + + if cache.is_initialized_at(epoch) { + Ok(cache) + } else { + Err(Error::EpochCacheUnintialized(relative_epoch)) + } } // FIXME(sproul): drop_previous/current_epoch_cache diff --git a/eth2/types/src/beacon_state/beacon_state_types.rs b/eth2/types/src/beacon_state/beacon_state_types.rs index b6c943a36..4957d44f7 100644 --- a/eth2/types/src/beacon_state/beacon_state_types.rs +++ b/eth2/types/src/beacon_state/beacon_state_types.rs @@ -14,6 +14,20 @@ pub trait EthSpec: fn spec() -> ChainSpec; + /// Returns the `SLOTS_PER_EPOCH` constant for this specification. + /// + /// Spec v0.6.1 + fn slots_per_epoch() -> u64 { + Self::spec().slots_per_epoch + } + + /// Returns the `SLOTS_PER_EPOCH` constant for this specification. + /// + /// Spec v0.6.1 + fn genesis_epoch() -> Epoch { + Self::spec().genesis_epoch + } + /// Returns the `SHARD_COUNT` constant for this specification. /// /// Spec v0.5.1 diff --git a/eth2/types/src/beacon_state/epoch_cache.rs b/eth2/types/src/beacon_state/epoch_cache.rs index d8f199002..9b23b677a 100644 --- a/eth2/types/src/beacon_state/epoch_cache.rs +++ b/eth2/types/src/beacon_state/epoch_cache.rs @@ -1,6 +1,5 @@ use super::BeaconState; use crate::*; -use honey_badger_split::SplitExt; use serde_derive::{Deserialize, Serialize}; use swap_or_not_shuffle::shuffle_list; @@ -17,8 +16,12 @@ mod tests; pub struct EpochCache { /// `Some(epoch)` if the cache is initialized, where `epoch` is the cache it holds. pub initialized_epoch: Option, - /// All crosslink committees for an epoch. - pub epoch_crosslink_committees: EpochCrosslinkCommittees, + /// All crosslink committees. + pub crosslink_committees: Vec, + /// Maps a shard to `self.epoch_crosslink_committees`. + pub shard_crosslink_committees: Vec>, + /// Maps a slot to `self.epoch_crosslink_committees`. + pub slot_crosslink_committees: Vec>, /// Maps validator index to a slot, shard and committee index for attestation. pub attestation_duties: Vec>, /// Indices of all active validators in the epoch @@ -33,28 +36,33 @@ impl EpochCache { seed: Hash256, epoch_start_shard: u64, spec: &ChainSpec, - ) -> Result { - if epoch != state.previous_epoch(spec) && epoch != state.current_epoch(spec) { - return Err(Error::EpochOutOfBounds); + ) -> Result { + if epoch != state.previous_epoch() && epoch != state.current_epoch() { + return Err(BeaconStateError::EpochOutOfBounds); } let active_validator_indices = get_active_validator_indices(&state.validator_registry, epoch); - let epoch_crosslink_committees = EpochCrosslinkCommittees::new( - epoch, - active_validator_indices.clone(), - seed, - epoch_start_shard, - state.get_epoch_committee_count(epoch, spec), - spec, - ); + let epoch_committee_count = state.get_epoch_committee_count(epoch, spec); - // Loop through all the validators in the committees and create the following map: - // - // `attestation_duties`: maps `ValidatorIndex` to `AttestationDuty`. + let crosslink_committees = compute_epoch_commitees( + epoch, + state, + active_validator_indices.clone(), + epoch_committee_count, + spec, + )?; + + let mut shard_crosslink_committees = vec![None; T::shard_count()]; + let mut slot_crosslink_committees = vec![None; spec.slots_per_epoch as usize]; let mut attestation_duties = vec![None; state.validator_registry.len()]; - for crosslink_committee in epoch_crosslink_committees.crosslink_committees.iter() { + + for (i, crosslink_committee) in crosslink_committees.iter().enumerate() { + shard_crosslink_committees[crosslink_committee.shard as usize] = Some(i); + slot_crosslink_committees[crosslink_committee.slot.as_usize()] = Some(i); + + // Loop through each validator in the committee and store its attestation duties. for (committee_index, validator_index) in crosslink_committee.committee.iter().enumerate() { @@ -70,20 +78,16 @@ impl EpochCache { Ok(EpochCache { initialized_epoch: Some(epoch), - epoch_crosslink_committees, + crosslink_committees, attestation_duties, + shard_crosslink_committees, + slot_crosslink_committees, active_validator_indices, }) } - /// Return a vec of `CrosslinkCommittee` for a given slot. - pub fn get_crosslink_committees_at_slot( - &self, - slot: Slot, - spec: &ChainSpec, - ) -> Option<&Vec> { - self.epoch_crosslink_committees - .get_crosslink_committees_at_slot(slot, spec) + pub fn is_initialized_at(&self, epoch: Epoch) -> bool { + Some(epoch) == self.initialized_epoch } /// Return `Some(CrosslinkCommittee)` if the given shard has a committee during the given @@ -93,12 +97,11 @@ impl EpochCache { shard: Shard, spec: &ChainSpec, ) -> Option<&CrosslinkCommittee> { - if shard > self.shard_committee_indices.len() as u64 { + if shard > self.shard_crosslink_committees.len() as u64 { None } else { - let (slot, committee) = self.shard_committee_indices[shard as usize]?; - let slot_committees = self.get_crosslink_committees_at_slot(slot, spec)?; - slot_committees.get(committee) + let i = self.shard_crosslink_committees[shard as usize]?; + Some(&self.crosslink_committees[i]) } } } @@ -121,16 +124,52 @@ pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> V active } -/// Contains all `CrosslinkCommittees` for an epoch. -#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)] -pub struct EpochCrosslinkCommittees { - /// The epoch the committees are present in. +pub fn compute_epoch_commitees( epoch: Epoch, - /// Committees indexed by the `index` parameter of `compute_committee` from the spec. - /// - /// The length of the vector is equal to the number of committees in the epoch - /// i.e. `state.get_epoch_committee_count(self.epoch)` - pub crosslink_committees: Vec, + state: &BeaconState, + active_validator_indices: Vec, + epoch_committee_count: u64, + spec: &ChainSpec, +) -> Result, BeaconStateError> { + let seed = state.generate_seed(epoch, spec)?; + + // The shuffler fails on a empty list, so if there are no active validator indices, simply + // return an empty list. + let shuffled_active_validator_indices = if active_validator_indices.is_empty() { + vec![] + } else { + shuffle_list( + active_validator_indices, + spec.shuffle_round_count, + &seed[..], + false, + ) + .ok_or_else(|| Error::UnableToShuffle)? + }; + + let committee_size = shuffled_active_validator_indices.len() / epoch_committee_count as usize; + + let epoch_start_shard = state.get_epoch_start_shard(epoch, spec)?; + + Ok(shuffled_active_validator_indices + .chunks(committee_size) + .enumerate() + .map(|(index, committee)| { + let shard = (epoch_start_shard + index as u64) % spec.shard_count; + let slot = crosslink_committee_slot( + shard, + epoch, + epoch_start_shard, + epoch_committee_count, + spec, + ); + CrosslinkCommittee { + slot, + shard, + committee: committee.to_vec(), + } + }) + .collect()) } fn crosslink_committee_slot( @@ -144,74 +183,3 @@ fn crosslink_committee_slot( let offset = (shard + spec.shard_count - epoch_start_shard) % spec.shard_count; epoch.start_slot(spec.slots_per_epoch) + offset / (epoch_committee_count / spec.slots_per_epoch) } - -impl EpochCrosslinkCommittees { - fn new( - epoch: Epoch, - active_validator_indices: Vec, - seed: Hash256, - epoch_start_shard: u64, - epoch_committee_count: u64, - spec: &ChainSpec, - ) -> Self { - // The shuffler fails on a empty list, so if there are no active validator indices, simply - // return an empty list. - let shuffled_active_validator_indices = if active_validator_indices.is_empty() { - vec![] - } else { - shuffle_list( - active_validator_indices, - spec.shuffle_round_count, - &seed[..], - false, - ) - .ok_or_else(|| Error::UnableToShuffle)? - }; - - let committee_size = - shuffled_active_validator_indices.len() / epoch_committee_count as usize; - - let crosslink_committees = shuffled_active_validator_indices - .into_iter() - .chunks(committee_size) - .enumerate() - .map(|(index, committee)| { - let shard = (epoch_start_start_shard + index) % spec.shard_count; - let slot = crosslink_committee_slot( - shard, - epoch, - epoch_start_shard, - epoch_committee_count, - spec, - ); - CrosslinkCommittee { - slot, - shard, - committee: committee.to_vec(), - } - }) - .collect(); - - Ok(Self { - epoch, - crosslink_committees, - }) - } - - /// Return a vec of `CrosslinkCommittee` for a given slot. - fn get_crosslink_committees_at_slot( - &self, - slot: Slot, - spec: &ChainSpec, - ) -> Option<&Vec> { - let epoch_start_slot = self.epoch.start_slot(spec.slots_per_epoch); - let epoch_end_slot = self.epoch.end_slot(spec.slots_per_epoch); - - if (epoch_start_slot <= slot) && (slot <= epoch_end_slot) { - let index = slot - epoch_start_slot; - self.crosslink_committees.get(index.as_usize()) - } else { - None - } - } -} diff --git a/eth2/types/src/beacon_state/epoch_cache/tests.rs b/eth2/types/src/beacon_state/epoch_cache/tests.rs index 03f140243..2a3034192 100644 --- a/eth2/types/src/beacon_state/epoch_cache/tests.rs +++ b/eth2/types/src/beacon_state/epoch_cache/tests.rs @@ -1,4 +1,4 @@ -#![cfg(all(not(test), test))] +#![cfg(test)] use super::*; use crate::beacon_state::FewValidatorsEthSpec; diff --git a/eth2/types/src/beacon_state/tests.rs b/eth2/types/src/beacon_state/tests.rs index aa3c0b98a..aff49d53e 100644 --- a/eth2/types/src/beacon_state/tests.rs +++ b/eth2/types/src/beacon_state/tests.rs @@ -6,6 +6,7 @@ use crate::test_utils::*; ssz_tests!(FoundationBeaconState); cached_tree_hash_tests!(FoundationBeaconState); +/* /// Test that /// /// 1. Using the cache before it's built fails. @@ -22,12 +23,14 @@ fn test_cache_initialization<'a, T: EthSpec>( // Assuming the cache isn't already built, assert that a call to a cache-using function fails. assert_eq!( - state.get_beacon_proposer_index(slot, relative_epoch, spec), + state.get_attestation_duties(0, spec), Err(BeaconStateError::EpochCacheUninitialized(relative_epoch)) ); // Build the cache. - state.build_epoch_cache(relative_epoch, spec).unwrap(); + state + .build_current_epoch_cache(relative_epoch, spec) + .unwrap(); // Assert a call to a cache-using function passes. let _ = state @@ -59,6 +62,7 @@ fn cache_initialization() { test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &spec); test_cache_initialization(&mut state, RelativeEpoch::NextWithoutRegistryChange, &spec); } +*/ #[test] fn tree_hash_cache() { diff --git a/eth2/types/src/relative_epoch.rs b/eth2/types/src/relative_epoch.rs index 6538ca4aa..4a4ed4ce5 100644 --- a/eth2/types/src/relative_epoch.rs +++ b/eth2/types/src/relative_epoch.rs @@ -4,7 +4,6 @@ use crate::*; pub enum Error { EpochTooLow { base: Epoch, other: Epoch }, EpochTooHigh { base: Epoch, other: Epoch }, - AmbiguiousNextEpoch, } /// Defines the epochs relative to some epoch. Most useful when referring to the committees prior @@ -17,28 +16,19 @@ pub enum RelativeEpoch { Previous, /// The current epoch. Current, - /// The next epoch if there _is_ a validator registry update. - /// - /// If the validator registry is updated during an epoch transition, a new shuffling seed is - /// generated, this changes the attestation and proposal roles. - NextWithRegistryChange, - /// The next epoch if there _is not_ a validator registry update. - /// - /// If the validator registry _is not_ updated during an epoch transition, the shuffling stays - /// the same. - NextWithoutRegistryChange, + /// The next epoch. + Next, } impl RelativeEpoch { /// Returns the `epoch` that `self` refers to, with respect to the `base` epoch. /// - /// Spec v0.5.1 + /// Spec v0.6.1 pub fn into_epoch(self, base: Epoch) -> Epoch { match self { RelativeEpoch::Previous => base - 1, RelativeEpoch::Current => base, - RelativeEpoch::NextWithoutRegistryChange => base + 1, - RelativeEpoch::NextWithRegistryChange => base + 1, + RelativeEpoch::Next => base + 1, } } @@ -48,17 +38,15 @@ impl RelativeEpoch { /// Returns an error when: /// - `EpochTooLow` when `other` is more than 1 prior to `base`. /// - `EpochTooHigh` when `other` is more than 1 after `base`. - /// - `AmbiguiousNextEpoch` whenever `other` is one after `base`, because it's unknowable if - /// there will be a registry change. /// - /// Spec v0.5.1 + /// Spec v0.6.1 pub fn from_epoch(base: Epoch, other: Epoch) -> Result { if other == base - 1 { Ok(RelativeEpoch::Previous) } else if other == base { Ok(RelativeEpoch::Current) } else if other == base + 1 { - Err(Error::AmbiguiousNextEpoch) + Ok(RelativeEpoch::Next) } else if other < base { Err(Error::EpochTooLow { base, other }) } else { @@ -67,11 +55,8 @@ impl RelativeEpoch { } /// Convenience function for `Self::from_epoch` where both slots are converted into epochs. - pub fn from_slot(base: Slot, other: Slot, spec: &ChainSpec) -> Result { - Self::from_epoch( - base.epoch(spec.slots_per_epoch), - other.epoch(spec.slots_per_epoch), - ) + pub fn from_slot(base: Slot, other: Slot, slots_per_epoch: u64) -> Result { + Self::from_epoch(base.epoch(slots_per_epoch), other.epoch(slots_per_epoch)) } } @@ -85,14 +70,7 @@ mod tests { assert_eq!(RelativeEpoch::Current.into_epoch(base), base); assert_eq!(RelativeEpoch::Previous.into_epoch(base), base - 1); - assert_eq!( - RelativeEpoch::NextWithRegistryChange.into_epoch(base), - base + 1 - ); - assert_eq!( - RelativeEpoch::NextWithoutRegistryChange.into_epoch(base), - base + 1 - ); + assert_eq!(RelativeEpoch::Next.into_epoch(base), base + 1); } #[test] @@ -109,26 +87,26 @@ mod tests { ); assert_eq!( RelativeEpoch::from_epoch(base, base + 1), - Err(RelativeEpochError::AmbiguiousNextEpoch) + Ok(RelativeEpoch::Next) ); } #[test] fn from_slot() { - let spec = ChainSpec::foundation(); - let base = Epoch::new(10).start_slot(spec.slots_per_epoch); + let slots_per_epoch: u64 = 64; + let base = Slot::new(10 * slots_per_epoch); assert_eq!( - RelativeEpoch::from_slot(base, base - 1, &spec), + RelativeEpoch::from_slot(base, base - 1, slots_per_epoch), Ok(RelativeEpoch::Previous) ); assert_eq!( - RelativeEpoch::from_slot(base, base, &spec), + RelativeEpoch::from_slot(base, base, slots_per_epoch), Ok(RelativeEpoch::Current) ); assert_eq!( - RelativeEpoch::from_slot(base, base + spec.slots_per_epoch, &spec), - Err(RelativeEpochError::AmbiguiousNextEpoch) + RelativeEpoch::from_slot(base, base + slots_per_epoch, slots_per_epoch), + Ok(RelativeEpoch::Next) ); } } diff --git a/eth2/types/src/test_utils/builders.rs b/eth2/types/src/test_utils/builders.rs new file mode 100644 index 000000000..8017e4e5d --- /dev/null +++ b/eth2/types/src/test_utils/builders.rs @@ -0,0 +1,21 @@ +mod testing_attestation_builder; +mod testing_attestation_data_builder; +mod testing_attester_slashing_builder; +mod testing_beacon_block_builder; +mod testing_beacon_state_builder; +mod testing_deposit_builder; +mod testing_pending_attestation_builder; +mod testing_proposer_slashing_builder; +mod testing_transfer_builder; +mod testing_voluntary_exit_builder; + +pub use testing_attestation_builder::*; +pub use testing_attestation_data_builder::*; +pub use testing_attester_slashing_builder::*; +pub use testing_beacon_block_builder::*; +pub use testing_beacon_state_builder::*; +pub use testing_deposit_builder::*; +pub use testing_pending_attestation_builder::*; +pub use testing_proposer_slashing_builder::*; +pub use testing_transfer_builder::*; +pub use testing_voluntary_exit_builder::*; diff --git a/eth2/types/src/test_utils/testing_attestation_builder.rs b/eth2/types/src/test_utils/builders/testing_attestation_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_attestation_builder.rs rename to eth2/types/src/test_utils/builders/testing_attestation_builder.rs diff --git a/eth2/types/src/test_utils/testing_attestation_data_builder.rs b/eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs similarity index 91% rename from eth2/types/src/test_utils/testing_attestation_data_builder.rs rename to eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs index 6fdf23e9a..dbf5dbae7 100644 --- a/eth2/types/src/test_utils/testing_attestation_data_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs @@ -16,8 +16,8 @@ impl TestingAttestationDataBuilder { slot: Slot, spec: &ChainSpec, ) -> Self { - let current_epoch = state.current_epoch(spec); - let previous_epoch = state.previous_epoch(spec); + let current_epoch = state.current_epoch(); + let previous_epoch = state.previous_epoch(); let is_previous_epoch = state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch); @@ -29,9 +29,9 @@ impl TestingAttestationDataBuilder { }; let target_epoch = if is_previous_epoch { - state.previous_epoch(spec) + state.previous_epoch() } else { - state.current_epoch(spec) + state.current_epoch() }; let target_root = if is_previous_epoch { diff --git a/eth2/types/src/test_utils/testing_attester_slashing_builder.rs b/eth2/types/src/test_utils/builders/testing_attester_slashing_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_attester_slashing_builder.rs rename to eth2/types/src/test_utils/builders/testing_attester_slashing_builder.rs diff --git a/eth2/types/src/test_utils/testing_beacon_block_builder.rs b/eth2/types/src/test_utils/builders/testing_beacon_block_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_beacon_block_builder.rs rename to eth2/types/src/test_utils/builders/testing_beacon_block_builder.rs diff --git a/eth2/types/src/test_utils/testing_beacon_state_builder.rs b/eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs similarity index 94% rename from eth2/types/src/test_utils/testing_beacon_state_builder.rs rename to eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs index 95c7bff20..68da6d37f 100644 --- a/eth2/types/src/test_utils/testing_beacon_state_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs @@ -1,4 +1,4 @@ -use super::{generate_deterministic_keypairs, KeypairsFile}; +use super::super::{generate_deterministic_keypairs, KeypairsFile}; use crate::test_utils::TestingPendingAttestationBuilder; use crate::*; use bls::get_withdrawal_credentials; @@ -166,14 +166,7 @@ impl TestingBeaconStateBuilder { /// Note: this performs the build when called. Ensure that no changes are made that would /// invalidate this cache. pub fn build_caches(&mut self, spec: &ChainSpec) -> Result<(), BeaconStateError> { - let state = &mut self.state; - - state.build_epoch_cache(RelativeEpoch::Previous, &spec)?; - state.build_epoch_cache(RelativeEpoch::Current, &spec)?; - state.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &spec)?; - state.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &spec)?; - - state.update_pubkey_cache()?; + self.state.build_all_caches(spec); Ok(()) } @@ -218,8 +211,8 @@ impl TestingBeaconStateBuilder { .build_epoch_cache(RelativeEpoch::Current, spec) .unwrap(); - let current_epoch = state.current_epoch(spec); - let previous_epoch = state.previous_epoch(spec); + let current_epoch = state.current_epoch(); + let previous_epoch = state.previous_epoch(); let first_slot = previous_epoch.start_slot(spec.slots_per_epoch).as_u64(); let last_slot = current_epoch.end_slot(spec.slots_per_epoch).as_u64() @@ -246,7 +239,7 @@ impl TestingBeaconStateBuilder { builder.add_committee_participation(signers); let attestation = builder.build(); - if attestation.data.target_epoch < state.current_epoch(spec) { + if attestation.data.target_epoch < state.current_epoch() { state.previous_epoch_attestations.push(attestation) } else { state.current_epoch_attestations.push(attestation) diff --git a/eth2/types/src/test_utils/testing_deposit_builder.rs b/eth2/types/src/test_utils/builders/testing_deposit_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_deposit_builder.rs rename to eth2/types/src/test_utils/builders/testing_deposit_builder.rs diff --git a/eth2/types/src/test_utils/testing_pending_attestation_builder.rs b/eth2/types/src/test_utils/builders/testing_pending_attestation_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_pending_attestation_builder.rs rename to eth2/types/src/test_utils/builders/testing_pending_attestation_builder.rs diff --git a/eth2/types/src/test_utils/testing_proposer_slashing_builder.rs b/eth2/types/src/test_utils/builders/testing_proposer_slashing_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_proposer_slashing_builder.rs rename to eth2/types/src/test_utils/builders/testing_proposer_slashing_builder.rs diff --git a/eth2/types/src/test_utils/testing_transfer_builder.rs b/eth2/types/src/test_utils/builders/testing_transfer_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_transfer_builder.rs rename to eth2/types/src/test_utils/builders/testing_transfer_builder.rs diff --git a/eth2/types/src/test_utils/testing_voluntary_exit_builder.rs b/eth2/types/src/test_utils/builders/testing_voluntary_exit_builder.rs similarity index 100% rename from eth2/types/src/test_utils/testing_voluntary_exit_builder.rs rename to eth2/types/src/test_utils/builders/testing_voluntary_exit_builder.rs diff --git a/eth2/types/src/test_utils/mod.rs b/eth2/types/src/test_utils/mod.rs index 20d53e72e..b88a623a3 100644 --- a/eth2/types/src/test_utils/mod.rs +++ b/eth2/types/src/test_utils/mod.rs @@ -1,20 +1,12 @@ #[macro_use] mod macros; +mod builders; mod generate_deterministic_keypairs; mod keypairs_file; mod serde_utils; mod test_random; -mod testing_attestation_builder; -mod testing_attestation_data_builder; -mod testing_attester_slashing_builder; -mod testing_beacon_block_builder; -mod testing_beacon_state_builder; -mod testing_deposit_builder; -mod testing_pending_attestation_builder; -mod testing_proposer_slashing_builder; -mod testing_transfer_builder; -mod testing_voluntary_exit_builder; +pub use builders::*; pub use generate_deterministic_keypairs::generate_deterministic_keypair; pub use generate_deterministic_keypairs::generate_deterministic_keypairs; pub use keypairs_file::KeypairsFile; @@ -24,13 +16,3 @@ pub use rand::{ }; pub use serde_utils::{fork_from_hex_str, u8_from_hex_str}; pub use test_random::TestRandom; -pub use testing_attestation_builder::TestingAttestationBuilder; -pub use testing_attestation_data_builder::TestingAttestationDataBuilder; -pub use testing_attester_slashing_builder::TestingAttesterSlashingBuilder; -pub use testing_beacon_block_builder::TestingBeaconBlockBuilder; -pub use testing_beacon_state_builder::{keypairs_path, TestingBeaconStateBuilder}; -pub use testing_deposit_builder::TestingDepositBuilder; -pub use testing_pending_attestation_builder::TestingPendingAttestationBuilder; -pub use testing_proposer_slashing_builder::TestingProposerSlashingBuilder; -pub use testing_transfer_builder::TestingTransferBuilder; -pub use testing_voluntary_exit_builder::TestingVoluntaryExitBuilder;