Add progress on epoch caching

This commit is contained in:
Paul Hauner 2019-05-16 16:54:11 +10:00
parent 0885d56b36
commit 944ac73ef9
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
18 changed files with 230 additions and 250 deletions

View File

@ -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<T: EthSpec> BeaconState<T> {
/*
* 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<T: EthSpec> BeaconState<T> {
/// 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<T: EthSpec> BeaconState<T> {
/// 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<T: EthSpec> BeaconState<T> {
/// 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<T: EthSpec> BeaconState<T> {
///
/// Spec v0.6.1
pub fn get_epoch_start_shard(&self, epoch: Epoch, spec: &ChainSpec) -> Result<u64, Error> {
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<T: EthSpec> BeaconState<T> {
/// Safely obtains the index for `latest_randao_mixes`
///
/// Spec v0.5.1
fn get_randao_mix_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let current_epoch = self.current_epoch(spec);
fn get_randao_mix_index(&self, epoch: Epoch) -> Result<usize, Error> {
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<T: EthSpec> BeaconState<T> {
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<T: EthSpec> BeaconState<T> {
/// 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<T: EthSpec> BeaconState<T> {
///
/// Spec v0.6.1
fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
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<T: EthSpec> BeaconState<T> {
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<T: EthSpec> BeaconState<T> {
/// Spec v0.5.1
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
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<T: EthSpec> BeaconState<T> {
pub fn get_churn_limit(&self, spec: &ChainSpec) -> Result<u64, Error> {
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<T: EthSpec> BeaconState<T> {
validator_index: usize,
spec: &ChainSpec,
) -> Result<&Option<AttestationDuty>, 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<T: EthSpec> BeaconState<T> {
/// 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<T: EthSpec> BeaconState<T> {
}
/// 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<T: EthSpec> BeaconState<T> {
}
/// 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<T: EthSpec> BeaconState<T> {
/// 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

View File

@ -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

View File

@ -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<Epoch>,
/// All crosslink committees for an epoch.
pub epoch_crosslink_committees: EpochCrosslinkCommittees,
/// All crosslink committees.
pub crosslink_committees: Vec<CrosslinkCommittee>,
/// Maps a shard to `self.epoch_crosslink_committees`.
pub shard_crosslink_committees: Vec<Option<usize>>,
/// Maps a slot to `self.epoch_crosslink_committees`.
pub slot_crosslink_committees: Vec<Option<usize>>,
/// Maps validator index to a slot, shard and committee index for attestation.
pub attestation_duties: Vec<Option<AttestationDuty>>,
/// Indices of all active validators in the epoch
@ -33,28 +36,33 @@ impl EpochCache {
seed: Hash256,
epoch_start_shard: u64,
spec: &ChainSpec,
) -> Result<EpochCache, Error> {
if epoch != state.previous_epoch(spec) && epoch != state.current_epoch(spec) {
return Err(Error::EpochOutOfBounds);
) -> Result<EpochCache, BeaconStateError> {
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<CrosslinkCommittee>> {
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<T: EthSpec>(
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<CrosslinkCommittee>,
state: &BeaconState<T>,
active_validator_indices: Vec<usize>,
epoch_committee_count: u64,
spec: &ChainSpec,
) -> Result<Vec<CrosslinkCommittee>, 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<usize>,
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<CrosslinkCommittee>> {
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
}
}
}

View File

@ -1,4 +1,4 @@
#![cfg(all(not(test), test))]
#![cfg(test)]
use super::*;
use crate::beacon_state::FewValidatorsEthSpec;

View File

@ -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() {

View File

@ -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<Self, Error> {
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, Error> {
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, Error> {
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)
);
}
}

View File

@ -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::*;

View File

@ -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 {

View File

@ -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<T: EthSpec> TestingBeaconStateBuilder<T> {
/// 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<T: EthSpec> TestingBeaconStateBuilder<T> {
.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<T: EthSpec> TestingBeaconStateBuilder<T> {
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)

View File

@ -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;