Optimise epoch building
This commit is contained in:
parent
8154397114
commit
902b80a579
@ -537,8 +537,8 @@ impl BeaconState {
|
||||
let cache = self.cache(relative_epoch)?;
|
||||
|
||||
let (committee_slot_index, committee_index) = cache
|
||||
.shard_committee_index_map
|
||||
.get(&attestation_data.shard)
|
||||
.shard_committee_indices
|
||||
.get(attestation_data.shard as usize)
|
||||
.ok_or_else(|| Error::ShardOutOfBounds)?;
|
||||
let (committee, shard) = &cache.committees[*committee_slot_index][*committee_index];
|
||||
|
||||
@ -787,7 +787,6 @@ impl BeaconState {
|
||||
&self,
|
||||
slot: Slot,
|
||||
registry_change: bool,
|
||||
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<Vec<usize>>, Error> {
|
||||
let (_committees_per_epoch, seed, shuffling_epoch, _shuffling_start_shard) =
|
||||
@ -810,7 +809,6 @@ impl BeaconState {
|
||||
) -> Result<Vec<Vec<usize>>, Error> {
|
||||
let active_validator_indices =
|
||||
get_active_validator_indices(&self.validator_registry, epoch);
|
||||
|
||||
if active_validator_indices.is_empty() {
|
||||
error!("get_shuffling: no validators.");
|
||||
return Err(Error::InsufficientValidators);
|
||||
@ -912,22 +910,18 @@ impl BeaconState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the list of ``(committee, shard)`` tuples for the ``slot``.
|
||||
/// Return the ordered list of shards tuples for the `slot`.
|
||||
///
|
||||
/// Note: There are two possible shufflings for crosslink committees for a
|
||||
/// `slot` in the next epoch: with and without a `registry_change`
|
||||
///
|
||||
/// Note: does not utilize the cache, `get_crosslink_committees_at_slot` is an equivalent
|
||||
/// function which uses the cache.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
pub(crate) fn calculate_crosslink_committees_at_slot(
|
||||
pub(crate) fn get_shards_for_slot(
|
||||
&self,
|
||||
slot: Slot,
|
||||
registry_change: bool,
|
||||
shuffling: Vec<Vec<usize>>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<(Vec<usize>, u64)>, Error> {
|
||||
) -> Result<Vec<u64>, Error> {
|
||||
let (committees_per_epoch, _seed, _shuffling_epoch, shuffling_start_shard) =
|
||||
self.get_committee_params_at_slot(slot, registry_change, spec)?;
|
||||
|
||||
@ -936,15 +930,12 @@ impl BeaconState {
|
||||
let slot_start_shard =
|
||||
(shuffling_start_shard + committees_per_slot * offset) % spec.shard_count;
|
||||
|
||||
let mut crosslinks_at_slot = vec![];
|
||||
let mut shards_at_slot = vec![];
|
||||
for i in 0..committees_per_slot {
|
||||
let tuple = (
|
||||
shuffling[(committees_per_slot * offset + i) as usize].clone(),
|
||||
(slot_start_shard + i) % spec.shard_count,
|
||||
);
|
||||
crosslinks_at_slot.push(tuple)
|
||||
shards_at_slot.push((slot_start_shard + i) % spec.shard_count)
|
||||
}
|
||||
Ok(crosslinks_at_slot)
|
||||
|
||||
Ok(shards_at_slot)
|
||||
}
|
||||
|
||||
/// Returns the `slot`, `shard` and `committee_index` for which a validator must produce an
|
||||
@ -962,10 +953,10 @@ impl BeaconState {
|
||||
) -> Result<Option<(Slot, u64, u64)>, Error> {
|
||||
let cache = self.cache(RelativeEpoch::Current)?;
|
||||
|
||||
Ok(cache
|
||||
.attestation_duty_map
|
||||
.get(&(validator_index as u64))
|
||||
.and_then(|tuple| Some(*tuple)))
|
||||
Ok(*cache
|
||||
.attestation_duties
|
||||
.get(validator_index)
|
||||
.ok_or_else(|| Error::UnknownValidator)?)
|
||||
}
|
||||
|
||||
/// Process the slashings.
|
||||
|
@ -1,8 +1,6 @@
|
||||
use super::{AttestationDutyMap, BeaconState, CrosslinkCommittees, Error, ShardCommitteeIndexMap};
|
||||
use super::{AttestationDuty, BeaconState, CrosslinkCommittees, Error};
|
||||
use crate::{ChainSpec, Epoch};
|
||||
use log::trace;
|
||||
use serde_derive::Serialize;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
pub struct EpochCache {
|
||||
@ -11,21 +9,23 @@ pub struct EpochCache {
|
||||
/// The crosslink committees for an epoch.
|
||||
pub committees: Vec<CrosslinkCommittees>,
|
||||
/// Maps validator index to a slot, shard and committee index for attestation.
|
||||
pub attestation_duty_map: AttestationDutyMap,
|
||||
pub attestation_duties: Vec<Option<AttestationDuty>>,
|
||||
/// Maps a shard to an index of `self.committees`.
|
||||
pub shard_committee_index_map: ShardCommitteeIndexMap,
|
||||
pub shard_committee_indices: Vec<(usize, usize)>,
|
||||
}
|
||||
|
||||
impl EpochCache {
|
||||
/// Return a new, completely empty cache.
|
||||
pub fn empty() -> EpochCache {
|
||||
EpochCache {
|
||||
initialized: false,
|
||||
committees: vec![],
|
||||
attestation_duty_map: AttestationDutyMap::new(),
|
||||
shard_committee_index_map: ShardCommitteeIndexMap::new(),
|
||||
attestation_duties: vec![],
|
||||
shard_committee_indices: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a new, fully initialized cache.
|
||||
pub fn initialized(
|
||||
state: &BeaconState,
|
||||
epoch: Epoch,
|
||||
@ -33,42 +33,36 @@ impl EpochCache {
|
||||
) -> Result<EpochCache, Error> {
|
||||
let mut epoch_committees: Vec<CrosslinkCommittees> =
|
||||
Vec::with_capacity(spec.slots_per_epoch as usize);
|
||||
let mut shard_committee_index_map: ShardCommitteeIndexMap = HashMap::new();
|
||||
|
||||
let shuffling =
|
||||
let mut attestation_duties = vec![None; state.validator_registry.len()];
|
||||
|
||||
let mut shard_committee_indices = vec![(0, 0); spec.shard_count as usize];
|
||||
|
||||
let mut shuffling =
|
||||
state.get_shuffling_for_slot(epoch.start_slot(spec.slots_per_epoch), false, spec)?;
|
||||
|
||||
let mut attestation_duty_map: AttestationDutyMap = HashMap::with_capacity(shuffling.len());
|
||||
for (epoch_committees_index, slot) in epoch.slot_iter(spec.slots_per_epoch).enumerate() {
|
||||
let mut slot_committees: Vec<(Vec<usize>, u64)> = vec![];
|
||||
|
||||
for (epoch_committeess_index, slot) in epoch.slot_iter(spec.slots_per_epoch).enumerate() {
|
||||
let slot_committees = state.calculate_crosslink_committees_at_slot(
|
||||
slot,
|
||||
false,
|
||||
shuffling.clone(),
|
||||
spec,
|
||||
)?;
|
||||
let shards = state.get_shards_for_slot(slot, false, spec)?;
|
||||
for shard in shards {
|
||||
let committee = shuffling.remove(0);
|
||||
slot_committees.push((committee, shard));
|
||||
}
|
||||
|
||||
for (slot_committees_index, (committee, shard)) in slot_committees.iter().enumerate() {
|
||||
// Empty committees are not permitted.
|
||||
if committee.is_empty() {
|
||||
return Err(Error::InsufficientValidators);
|
||||
}
|
||||
|
||||
trace!(
|
||||
"shard: {}, epoch_i: {}, slot_i: {}",
|
||||
shard,
|
||||
epoch_committeess_index,
|
||||
slot_committees_index
|
||||
);
|
||||
|
||||
shard_committee_index_map
|
||||
.insert(*shard, (epoch_committeess_index, slot_committees_index));
|
||||
// Store the slot and committee index for this shard.
|
||||
shard_committee_indices[*shard as usize] =
|
||||
(epoch_committees_index, slot_committees_index);
|
||||
|
||||
// For each validator, store their attestation duties.
|
||||
for (committee_index, validator_index) in committee.iter().enumerate() {
|
||||
attestation_duty_map.insert(
|
||||
*validator_index as u64,
|
||||
(slot, *shard, committee_index as u64),
|
||||
);
|
||||
attestation_duties[*validator_index] =
|
||||
Some((slot, *shard, committee_index as u64))
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,8 +72,8 @@ impl EpochCache {
|
||||
Ok(EpochCache {
|
||||
initialized: true,
|
||||
committees: epoch_committees,
|
||||
attestation_duty_map,
|
||||
shard_committee_index_map,
|
||||
attestation_duties,
|
||||
shard_committee_indices,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -7,17 +7,17 @@ use crate::Epoch;
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> {
|
||||
validators
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, validator)| {
|
||||
if validator.is_active_at(epoch) {
|
||||
Some(index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
let mut active = Vec::with_capacity(validators.len());
|
||||
|
||||
for (index, validator) in validators.iter().enumerate() {
|
||||
if validator.is_active_at(epoch) {
|
||||
active.push(index)
|
||||
}
|
||||
}
|
||||
|
||||
active.shrink_to_fit();
|
||||
|
||||
active
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
Reference in New Issue
Block a user