Add progress on epoch caching
This commit is contained in:
parent
0885d56b36
commit
944ac73ef9
@ -23,7 +23,7 @@ mod exit_cache;
|
|||||||
mod pubkey_cache;
|
mod pubkey_cache;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub const CACHED_EPOCHS: usize = 4;
|
pub const CACHED_EPOCHS: usize = 3;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -49,6 +49,7 @@ pub enum Error {
|
|||||||
},
|
},
|
||||||
PreviousEpochCacheUninitialized,
|
PreviousEpochCacheUninitialized,
|
||||||
CurrentEpochCacheUnintialized,
|
CurrentEpochCacheUnintialized,
|
||||||
|
EpochCacheUnintialized(RelativeEpoch),
|
||||||
EpochCacheError(EpochCacheError),
|
EpochCacheError(EpochCacheError),
|
||||||
TreeHashCacheError(TreeHashCacheError),
|
TreeHashCacheError(TreeHashCacheError),
|
||||||
}
|
}
|
||||||
@ -117,13 +118,7 @@ where
|
|||||||
#[ssz(skip_deserializing)]
|
#[ssz(skip_deserializing)]
|
||||||
#[tree_hash(skip_hashing)]
|
#[tree_hash(skip_hashing)]
|
||||||
#[test_random(default)]
|
#[test_random(default)]
|
||||||
pub previous_epoch_cache: EpochCache,
|
pub epoch_caches: [EpochCache; CACHED_EPOCHS],
|
||||||
#[serde(default)]
|
|
||||||
#[ssz(skip_serializing)]
|
|
||||||
#[ssz(skip_deserializing)]
|
|
||||||
#[tree_hash(skip_hashing)]
|
|
||||||
#[test_random(default)]
|
|
||||||
pub current_epoch_cache: EpochCache,
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[ssz(skip_serializing)]
|
#[ssz(skip_serializing)]
|
||||||
#[ssz(skip_deserializing)]
|
#[ssz(skip_deserializing)]
|
||||||
@ -214,8 +209,11 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/*
|
/*
|
||||||
* Caching (not in spec)
|
* Caching (not in spec)
|
||||||
*/
|
*/
|
||||||
previous_epoch_cache: EpochCache::default(),
|
epoch_caches: [
|
||||||
current_epoch_cache: EpochCache::default(),
|
EpochCache::default(),
|
||||||
|
EpochCache::default(),
|
||||||
|
EpochCache::default(),
|
||||||
|
],
|
||||||
pubkey_cache: PubkeyCache::default(),
|
pubkey_cache: PubkeyCache::default(),
|
||||||
tree_hash_cache: TreeHashCache::default(),
|
tree_hash_cache: TreeHashCache::default(),
|
||||||
exit_cache: ExitCache::default(),
|
exit_cache: ExitCache::default(),
|
||||||
@ -254,8 +252,8 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/// The epoch corresponding to `self.slot`.
|
/// The epoch corresponding to `self.slot`.
|
||||||
///
|
///
|
||||||
/// Spec v0.6.1
|
/// Spec v0.6.1
|
||||||
pub fn current_epoch(&self, spec: &ChainSpec) -> Epoch {
|
pub fn current_epoch(&self) -> Epoch {
|
||||||
self.slot.epoch(spec.slots_per_epoch)
|
self.slot.epoch(T::slots_per_epoch())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The epoch prior to `self.current_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.
|
/// If the current epoch is the genesis epoch, the genesis_epoch is returned.
|
||||||
///
|
///
|
||||||
/// Spec v0.6.1
|
/// Spec v0.6.1
|
||||||
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
|
pub fn previous_epoch(&self) -> Epoch {
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch();
|
||||||
if current_epoch > spec.genesis_epoch {
|
if current_epoch > T::genesis_epoch() {
|
||||||
current_epoch - 1
|
current_epoch - 1
|
||||||
} else {
|
} else {
|
||||||
current_epoch
|
current_epoch
|
||||||
@ -275,8 +273,8 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/// The epoch following `self.current_epoch()`.
|
/// The epoch following `self.current_epoch()`.
|
||||||
///
|
///
|
||||||
/// Spec v0.6.1
|
/// Spec v0.6.1
|
||||||
pub fn next_epoch(&self, spec: &ChainSpec) -> Epoch {
|
pub fn next_epoch(&self) -> Epoch {
|
||||||
self.current_epoch(spec) + 1
|
self.current_epoch() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of committees at ``epoch``.
|
/// Return the number of committees at ``epoch``.
|
||||||
@ -301,13 +299,13 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Spec v0.6.1
|
/// Spec v0.6.1
|
||||||
pub fn get_epoch_start_shard(&self, epoch: Epoch, spec: &ChainSpec) -> Result<u64, Error> {
|
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);
|
return Err(Error::EpochOutOfBounds);
|
||||||
}
|
}
|
||||||
let shard_count = T::ShardCount::to_u64();
|
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
|
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;
|
% shard_count;
|
||||||
while check_epoch > epoch {
|
while check_epoch > epoch {
|
||||||
check_epoch -= 1;
|
check_epoch -= 1;
|
||||||
@ -458,8 +456,8 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/// Safely obtains the index for `latest_randao_mixes`
|
/// Safely obtains the index for `latest_randao_mixes`
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
fn get_randao_mix_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
|
fn get_randao_mix_index(&self, epoch: Epoch) -> Result<usize, Error> {
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch();
|
||||||
let len = T::LatestRandaoMixesLength::to_u64();
|
let len = T::LatestRandaoMixesLength::to_u64();
|
||||||
|
|
||||||
if (current_epoch - len < epoch) & (epoch <= current_epoch) {
|
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)));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -494,21 +492,16 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/// Return the randao mix at a recent ``epoch``.
|
/// Return the randao mix at a recent ``epoch``.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn get_randao_mix(&self, epoch: Epoch, spec: &ChainSpec) -> Result<&Hash256, Error> {
|
pub fn get_randao_mix(&self, epoch: Epoch) -> Result<&Hash256, Error> {
|
||||||
let i = self.get_randao_mix_index(epoch, spec)?;
|
let i = self.get_randao_mix_index(epoch)?;
|
||||||
Ok(&self.latest_randao_mixes[i])
|
Ok(&self.latest_randao_mixes[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the randao mix at a recent ``epoch``.
|
/// Set the randao mix at a recent ``epoch``.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn set_randao_mix(
|
pub fn set_randao_mix(&mut self, epoch: Epoch, mix: Hash256) -> Result<(), Error> {
|
||||||
&mut self,
|
let i = self.get_randao_mix_index(epoch)?;
|
||||||
epoch: Epoch,
|
|
||||||
mix: Hash256,
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let i = self.get_randao_mix_index(epoch, spec)?;
|
|
||||||
self.latest_randao_mixes[i] = mix;
|
self.latest_randao_mixes[i] = mix;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -517,7 +510,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Spec v0.6.1
|
/// Spec v0.6.1
|
||||||
fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
|
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
|
if current_epoch - self.latest_active_index_roots.len() as u64 + spec.activation_exit_delay
|
||||||
< epoch
|
< epoch
|
||||||
@ -627,9 +620,9 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<&[PendingAttestation], Error> {
|
) -> Result<&[PendingAttestation], Error> {
|
||||||
if epoch == self.current_epoch(spec) {
|
if epoch == self.current_epoch() {
|
||||||
Ok(&self.current_epoch_attestations)
|
Ok(&self.current_epoch_attestations)
|
||||||
} else if epoch == self.previous_epoch(spec) {
|
} else if epoch == self.previous_epoch() {
|
||||||
Ok(&self.previous_epoch_attestations)
|
Ok(&self.previous_epoch_attestations)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::EpochOutOfBounds)
|
Err(Error::EpochOutOfBounds)
|
||||||
@ -659,7 +652,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
|
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
|
||||||
let mut input = self
|
let mut input = self
|
||||||
.get_randao_mix(epoch - spec.min_seed_lookahead, spec)?
|
.get_randao_mix(epoch - spec.min_seed_lookahead)?
|
||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
@ -699,7 +692,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
pub fn get_churn_limit(&self, spec: &ChainSpec) -> Result<u64, Error> {
|
pub fn get_churn_limit(&self, spec: &ChainSpec) -> Result<u64, Error> {
|
||||||
Ok(std::cmp::max(
|
Ok(std::cmp::max(
|
||||||
spec.min_per_epoch_churn_limit,
|
spec.min_per_epoch_churn_limit,
|
||||||
self.cache(RelativeEpoch::Current, spec)?
|
self.cache(self.current_epoch(), spec)?
|
||||||
.active_validator_indices
|
.active_validator_indices
|
||||||
.len() as u64
|
.len() as u64
|
||||||
/ spec.churn_limit_quotient,
|
/ spec.churn_limit_quotient,
|
||||||
@ -719,7 +712,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<&Option<AttestationDuty>, Error> {
|
) -> Result<&Option<AttestationDuty>, Error> {
|
||||||
let cache = self.cache(RelativeEpoch::Current, spec)?;
|
let cache = self.cache(self.current_epoch(), spec)?;
|
||||||
|
|
||||||
Ok(cache
|
Ok(cache
|
||||||
.attestation_duties
|
.attestation_duties
|
||||||
@ -743,8 +736,9 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Build all the caches, if they need to be built.
|
/// Build all the caches, if they need to be built.
|
||||||
pub fn build_all_caches(&mut self, spec: &ChainSpec) -> Result<(), Error> {
|
pub fn build_all_caches(&mut self, spec: &ChainSpec) -> Result<(), Error> {
|
||||||
self.build_previous_epoch_cache(spec)?;
|
self.build_epoch_cache(RelativeEpoch::Previous, spec)?;
|
||||||
self.build_current_epoch_cache(spec)?;
|
self.build_epoch_cache(RelativeEpoch::Current, spec)?;
|
||||||
|
self.build_epoch_cache(RelativeEpoch::Next, spec)?;
|
||||||
self.update_pubkey_cache()?;
|
self.update_pubkey_cache()?;
|
||||||
self.update_tree_hash_cache()?;
|
self.update_tree_hash_cache()?;
|
||||||
self.exit_cache
|
self.exit_cache
|
||||||
@ -754,9 +748,14 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build an epoch cache, unless it is has already been built.
|
/// Build an epoch cache, unless it is has already been built.
|
||||||
pub fn build_previous_epoch_cache(&mut self, spec: &ChainSpec) -> Result<(), Error> {
|
pub fn build_epoch_cache(
|
||||||
if self.caches[cache_index].initialized_epoch == Some(self.slot.epoch(spec.slots_per_epoch))
|
&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(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
self.force_build_epoch_cache(relative_epoch, spec)
|
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.
|
/// 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> {
|
pub fn force_build_epoch_cache(
|
||||||
let epoch = self.previous_epoch(spec);
|
&mut self,
|
||||||
self.previous_epoch_cache = EpochCache::initialized(
|
relative_epoch: RelativeEpoch,
|
||||||
&self,
|
spec: &ChainSpec,
|
||||||
epoch,
|
) -> Result<(), Error> {
|
||||||
self.generate_seed(epoch, spec)?,
|
let epoch = relative_epoch.into_epoch(self.current_epoch());
|
||||||
self.get_epoch_start_shard(epoch, spec)?,
|
|
||||||
spec,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Always builds the current epoch cache, even if it is already initialized.
|
self.epoch_caches[Self::cache_index(relative_epoch)] = EpochCache::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,
|
&self,
|
||||||
epoch,
|
epoch,
|
||||||
self.generate_seed(epoch, spec)?,
|
self.generate_seed(epoch, spec)?,
|
||||||
@ -792,10 +783,39 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
/// Advances the cache for this state into the next epoch.
|
/// 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.
|
/// 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 =
|
/// Note: whilst this function will preserve already-built caches, it will not build any.
|
||||||
std::mem::replace(&mut self.current_epoch_cache, EpochCache::default());
|
pub fn advance_caches(&mut self, spec: &ChainSpec) {
|
||||||
self.force_build_current_epoch_cache();
|
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
|
// FIXME(sproul): drop_previous/current_epoch_cache
|
||||||
|
@ -14,6 +14,20 @@ pub trait EthSpec:
|
|||||||
|
|
||||||
fn spec() -> ChainSpec;
|
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.
|
/// Returns the `SHARD_COUNT` constant for this specification.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use super::BeaconState;
|
use super::BeaconState;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use honey_badger_split::SplitExt;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use swap_or_not_shuffle::shuffle_list;
|
use swap_or_not_shuffle::shuffle_list;
|
||||||
|
|
||||||
@ -17,8 +16,12 @@ mod tests;
|
|||||||
pub struct EpochCache {
|
pub struct EpochCache {
|
||||||
/// `Some(epoch)` if the cache is initialized, where `epoch` is the cache it holds.
|
/// `Some(epoch)` if the cache is initialized, where `epoch` is the cache it holds.
|
||||||
pub initialized_epoch: Option<Epoch>,
|
pub initialized_epoch: Option<Epoch>,
|
||||||
/// All crosslink committees for an epoch.
|
/// All crosslink committees.
|
||||||
pub epoch_crosslink_committees: EpochCrosslinkCommittees,
|
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.
|
/// Maps validator index to a slot, shard and committee index for attestation.
|
||||||
pub attestation_duties: Vec<Option<AttestationDuty>>,
|
pub attestation_duties: Vec<Option<AttestationDuty>>,
|
||||||
/// Indices of all active validators in the epoch
|
/// Indices of all active validators in the epoch
|
||||||
@ -33,28 +36,33 @@ impl EpochCache {
|
|||||||
seed: Hash256,
|
seed: Hash256,
|
||||||
epoch_start_shard: u64,
|
epoch_start_shard: u64,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<EpochCache, Error> {
|
) -> Result<EpochCache, BeaconStateError> {
|
||||||
if epoch != state.previous_epoch(spec) && epoch != state.current_epoch(spec) {
|
if epoch != state.previous_epoch() && epoch != state.current_epoch() {
|
||||||
return Err(Error::EpochOutOfBounds);
|
return Err(BeaconStateError::EpochOutOfBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
let active_validator_indices =
|
let active_validator_indices =
|
||||||
get_active_validator_indices(&state.validator_registry, epoch);
|
get_active_validator_indices(&state.validator_registry, epoch);
|
||||||
|
|
||||||
let epoch_crosslink_committees = EpochCrosslinkCommittees::new(
|
let epoch_committee_count = state.get_epoch_committee_count(epoch, spec);
|
||||||
epoch,
|
|
||||||
active_validator_indices.clone(),
|
|
||||||
seed,
|
|
||||||
epoch_start_shard,
|
|
||||||
state.get_epoch_committee_count(epoch, spec),
|
|
||||||
spec,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Loop through all the validators in the committees and create the following map:
|
let crosslink_committees = compute_epoch_commitees(
|
||||||
//
|
epoch,
|
||||||
// `attestation_duties`: maps `ValidatorIndex` to `AttestationDuty`.
|
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()];
|
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
|
for (committee_index, validator_index) in
|
||||||
crosslink_committee.committee.iter().enumerate()
|
crosslink_committee.committee.iter().enumerate()
|
||||||
{
|
{
|
||||||
@ -70,20 +78,16 @@ impl EpochCache {
|
|||||||
|
|
||||||
Ok(EpochCache {
|
Ok(EpochCache {
|
||||||
initialized_epoch: Some(epoch),
|
initialized_epoch: Some(epoch),
|
||||||
epoch_crosslink_committees,
|
crosslink_committees,
|
||||||
attestation_duties,
|
attestation_duties,
|
||||||
|
shard_crosslink_committees,
|
||||||
|
slot_crosslink_committees,
|
||||||
active_validator_indices,
|
active_validator_indices,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a vec of `CrosslinkCommittee` for a given slot.
|
pub fn is_initialized_at(&self, epoch: Epoch) -> bool {
|
||||||
pub fn get_crosslink_committees_at_slot(
|
Some(epoch) == self.initialized_epoch
|
||||||
&self,
|
|
||||||
slot: Slot,
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> Option<&Vec<CrosslinkCommittee>> {
|
|
||||||
self.epoch_crosslink_committees
|
|
||||||
.get_crosslink_committees_at_slot(slot, spec)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `Some(CrosslinkCommittee)` if the given shard has a committee during the given
|
/// Return `Some(CrosslinkCommittee)` if the given shard has a committee during the given
|
||||||
@ -93,12 +97,11 @@ impl EpochCache {
|
|||||||
shard: Shard,
|
shard: Shard,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Option<&CrosslinkCommittee> {
|
) -> Option<&CrosslinkCommittee> {
|
||||||
if shard > self.shard_committee_indices.len() as u64 {
|
if shard > self.shard_crosslink_committees.len() as u64 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let (slot, committee) = self.shard_committee_indices[shard as usize]?;
|
let i = self.shard_crosslink_committees[shard as usize]?;
|
||||||
let slot_committees = self.get_crosslink_committees_at_slot(slot, spec)?;
|
Some(&self.crosslink_committees[i])
|
||||||
slot_committees.get(committee)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,16 +124,52 @@ pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> V
|
|||||||
active
|
active
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Contains all `CrosslinkCommittees` for an epoch.
|
pub fn compute_epoch_commitees<T: EthSpec>(
|
||||||
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct EpochCrosslinkCommittees {
|
|
||||||
/// The epoch the committees are present in.
|
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
/// Committees indexed by the `index` parameter of `compute_committee` from the spec.
|
state: &BeaconState<T>,
|
||||||
///
|
active_validator_indices: Vec<usize>,
|
||||||
/// The length of the vector is equal to the number of committees in the epoch
|
epoch_committee_count: u64,
|
||||||
/// i.e. `state.get_epoch_committee_count(self.epoch)`
|
spec: &ChainSpec,
|
||||||
pub crosslink_committees: Vec<CrosslinkCommittee>,
|
) -> 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(
|
fn crosslink_committee_slot(
|
||||||
@ -144,74 +183,3 @@ fn crosslink_committee_slot(
|
|||||||
let offset = (shard + spec.shard_count - epoch_start_shard) % spec.shard_count;
|
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)
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![cfg(all(not(test), test))]
|
#![cfg(test)]
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::beacon_state::FewValidatorsEthSpec;
|
use crate::beacon_state::FewValidatorsEthSpec;
|
||||||
|
@ -6,6 +6,7 @@ use crate::test_utils::*;
|
|||||||
ssz_tests!(FoundationBeaconState);
|
ssz_tests!(FoundationBeaconState);
|
||||||
cached_tree_hash_tests!(FoundationBeaconState);
|
cached_tree_hash_tests!(FoundationBeaconState);
|
||||||
|
|
||||||
|
/*
|
||||||
/// Test that
|
/// Test that
|
||||||
///
|
///
|
||||||
/// 1. Using the cache before it's built fails.
|
/// 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.
|
// Assuming the cache isn't already built, assert that a call to a cache-using function fails.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state.get_beacon_proposer_index(slot, relative_epoch, spec),
|
state.get_attestation_duties(0, spec),
|
||||||
Err(BeaconStateError::EpochCacheUninitialized(relative_epoch))
|
Err(BeaconStateError::EpochCacheUninitialized(relative_epoch))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Build the cache.
|
// 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.
|
// Assert a call to a cache-using function passes.
|
||||||
let _ = state
|
let _ = state
|
||||||
@ -59,6 +62,7 @@ fn cache_initialization() {
|
|||||||
test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &spec);
|
test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &spec);
|
||||||
test_cache_initialization(&mut state, RelativeEpoch::NextWithoutRegistryChange, &spec);
|
test_cache_initialization(&mut state, RelativeEpoch::NextWithoutRegistryChange, &spec);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tree_hash_cache() {
|
fn tree_hash_cache() {
|
||||||
|
@ -4,7 +4,6 @@ use crate::*;
|
|||||||
pub enum Error {
|
pub enum Error {
|
||||||
EpochTooLow { base: Epoch, other: Epoch },
|
EpochTooLow { base: Epoch, other: Epoch },
|
||||||
EpochTooHigh { 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
|
/// Defines the epochs relative to some epoch. Most useful when referring to the committees prior
|
||||||
@ -17,28 +16,19 @@ pub enum RelativeEpoch {
|
|||||||
Previous,
|
Previous,
|
||||||
/// The current epoch.
|
/// The current epoch.
|
||||||
Current,
|
Current,
|
||||||
/// The next epoch if there _is_ a validator registry update.
|
/// The next epoch.
|
||||||
///
|
Next,
|
||||||
/// 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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelativeEpoch {
|
impl RelativeEpoch {
|
||||||
/// Returns the `epoch` that `self` refers to, with respect to the `base` epoch.
|
/// 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 {
|
pub fn into_epoch(self, base: Epoch) -> Epoch {
|
||||||
match self {
|
match self {
|
||||||
RelativeEpoch::Previous => base - 1,
|
RelativeEpoch::Previous => base - 1,
|
||||||
RelativeEpoch::Current => base,
|
RelativeEpoch::Current => base,
|
||||||
RelativeEpoch::NextWithoutRegistryChange => base + 1,
|
RelativeEpoch::Next => base + 1,
|
||||||
RelativeEpoch::NextWithRegistryChange => base + 1,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,17 +38,15 @@ impl RelativeEpoch {
|
|||||||
/// Returns an error when:
|
/// Returns an error when:
|
||||||
/// - `EpochTooLow` when `other` is more than 1 prior to `base`.
|
/// - `EpochTooLow` when `other` is more than 1 prior to `base`.
|
||||||
/// - `EpochTooHigh` when `other` is more than 1 after `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> {
|
pub fn from_epoch(base: Epoch, other: Epoch) -> Result<Self, Error> {
|
||||||
if other == base - 1 {
|
if other == base - 1 {
|
||||||
Ok(RelativeEpoch::Previous)
|
Ok(RelativeEpoch::Previous)
|
||||||
} else if other == base {
|
} else if other == base {
|
||||||
Ok(RelativeEpoch::Current)
|
Ok(RelativeEpoch::Current)
|
||||||
} else if other == base + 1 {
|
} else if other == base + 1 {
|
||||||
Err(Error::AmbiguiousNextEpoch)
|
Ok(RelativeEpoch::Next)
|
||||||
} else if other < base {
|
} else if other < base {
|
||||||
Err(Error::EpochTooLow { base, other })
|
Err(Error::EpochTooLow { base, other })
|
||||||
} else {
|
} else {
|
||||||
@ -67,11 +55,8 @@ impl RelativeEpoch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function for `Self::from_epoch` where both slots are converted into epochs.
|
/// 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> {
|
pub fn from_slot(base: Slot, other: Slot, slots_per_epoch: u64) -> Result<Self, Error> {
|
||||||
Self::from_epoch(
|
Self::from_epoch(base.epoch(slots_per_epoch), other.epoch(slots_per_epoch))
|
||||||
base.epoch(spec.slots_per_epoch),
|
|
||||||
other.epoch(spec.slots_per_epoch),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,14 +70,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(RelativeEpoch::Current.into_epoch(base), base);
|
assert_eq!(RelativeEpoch::Current.into_epoch(base), base);
|
||||||
assert_eq!(RelativeEpoch::Previous.into_epoch(base), base - 1);
|
assert_eq!(RelativeEpoch::Previous.into_epoch(base), base - 1);
|
||||||
assert_eq!(
|
assert_eq!(RelativeEpoch::Next.into_epoch(base), base + 1);
|
||||||
RelativeEpoch::NextWithRegistryChange.into_epoch(base),
|
|
||||||
base + 1
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
RelativeEpoch::NextWithoutRegistryChange.into_epoch(base),
|
|
||||||
base + 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -109,26 +87,26 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RelativeEpoch::from_epoch(base, base + 1),
|
RelativeEpoch::from_epoch(base, base + 1),
|
||||||
Err(RelativeEpochError::AmbiguiousNextEpoch)
|
Ok(RelativeEpoch::Next)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_slot() {
|
fn from_slot() {
|
||||||
let spec = ChainSpec::foundation();
|
let slots_per_epoch: u64 = 64;
|
||||||
let base = Epoch::new(10).start_slot(spec.slots_per_epoch);
|
let base = Slot::new(10 * slots_per_epoch);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RelativeEpoch::from_slot(base, base - 1, &spec),
|
RelativeEpoch::from_slot(base, base - 1, slots_per_epoch),
|
||||||
Ok(RelativeEpoch::Previous)
|
Ok(RelativeEpoch::Previous)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RelativeEpoch::from_slot(base, base, &spec),
|
RelativeEpoch::from_slot(base, base, slots_per_epoch),
|
||||||
Ok(RelativeEpoch::Current)
|
Ok(RelativeEpoch::Current)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RelativeEpoch::from_slot(base, base + spec.slots_per_epoch, &spec),
|
RelativeEpoch::from_slot(base, base + slots_per_epoch, slots_per_epoch),
|
||||||
Err(RelativeEpochError::AmbiguiousNextEpoch)
|
Ok(RelativeEpoch::Next)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
eth2/types/src/test_utils/builders.rs
Normal file
21
eth2/types/src/test_utils/builders.rs
Normal 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::*;
|
@ -16,8 +16,8 @@ impl TestingAttestationDataBuilder {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let current_epoch = state.current_epoch(spec);
|
let current_epoch = state.current_epoch();
|
||||||
let previous_epoch = state.previous_epoch(spec);
|
let previous_epoch = state.previous_epoch();
|
||||||
|
|
||||||
let is_previous_epoch =
|
let is_previous_epoch =
|
||||||
state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_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 {
|
let target_epoch = if is_previous_epoch {
|
||||||
state.previous_epoch(spec)
|
state.previous_epoch()
|
||||||
} else {
|
} else {
|
||||||
state.current_epoch(spec)
|
state.current_epoch()
|
||||||
};
|
};
|
||||||
|
|
||||||
let target_root = if is_previous_epoch {
|
let target_root = if is_previous_epoch {
|
@ -1,4 +1,4 @@
|
|||||||
use super::{generate_deterministic_keypairs, KeypairsFile};
|
use super::super::{generate_deterministic_keypairs, KeypairsFile};
|
||||||
use crate::test_utils::TestingPendingAttestationBuilder;
|
use crate::test_utils::TestingPendingAttestationBuilder;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use bls::get_withdrawal_credentials;
|
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
|
/// Note: this performs the build when called. Ensure that no changes are made that would
|
||||||
/// invalidate this cache.
|
/// invalidate this cache.
|
||||||
pub fn build_caches(&mut self, spec: &ChainSpec) -> Result<(), BeaconStateError> {
|
pub fn build_caches(&mut self, spec: &ChainSpec) -> Result<(), BeaconStateError> {
|
||||||
let state = &mut self.state;
|
self.state.build_all_caches(spec);
|
||||||
|
|
||||||
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()?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -218,8 +211,8 @@ impl<T: EthSpec> TestingBeaconStateBuilder<T> {
|
|||||||
.build_epoch_cache(RelativeEpoch::Current, spec)
|
.build_epoch_cache(RelativeEpoch::Current, spec)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let current_epoch = state.current_epoch(spec);
|
let current_epoch = state.current_epoch();
|
||||||
let previous_epoch = state.previous_epoch(spec);
|
let previous_epoch = state.previous_epoch();
|
||||||
|
|
||||||
let first_slot = previous_epoch.start_slot(spec.slots_per_epoch).as_u64();
|
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()
|
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);
|
builder.add_committee_participation(signers);
|
||||||
let attestation = builder.build();
|
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)
|
state.previous_epoch_attestations.push(attestation)
|
||||||
} else {
|
} else {
|
||||||
state.current_epoch_attestations.push(attestation)
|
state.current_epoch_attestations.push(attestation)
|
@ -1,20 +1,12 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
mod builders;
|
||||||
mod generate_deterministic_keypairs;
|
mod generate_deterministic_keypairs;
|
||||||
mod keypairs_file;
|
mod keypairs_file;
|
||||||
mod serde_utils;
|
mod serde_utils;
|
||||||
mod test_random;
|
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_keypair;
|
||||||
pub use generate_deterministic_keypairs::generate_deterministic_keypairs;
|
pub use generate_deterministic_keypairs::generate_deterministic_keypairs;
|
||||||
pub use keypairs_file::KeypairsFile;
|
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 serde_utils::{fork_from_hex_str, u8_from_hex_str};
|
||||||
pub use test_random::TestRandom;
|
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;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user