Add state helpers from #148
This commit is contained in:
parent
f92b9d618a
commit
6a4252b8c6
@ -1,5 +1,11 @@
|
|||||||
use super::{BeaconChain, ClientDB, SlotClock};
|
use super::{BeaconChain, ClientDB, SlotClock};
|
||||||
use types::PublicKey;
|
use types::{beacon_state::Error as BeaconStateError, PublicKey};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Error {
|
||||||
|
SlotClockError,
|
||||||
|
BeaconStateError(BeaconStateError),
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, U> BeaconChain<T, U>
|
impl<T, U> BeaconChain<T, U>
|
||||||
where
|
where
|
||||||
@ -39,10 +45,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_proposer(&self, slot: u64) -> Option<usize> {
|
pub fn block_proposer(&self, slot: u64) -> Result<usize, Error> {
|
||||||
let present_slot = self.present_slot()?;
|
// TODO: fix unwrap
|
||||||
let state = self.state(present_slot).ok()?;
|
let present_slot = self.present_slot().unwrap();
|
||||||
state.get_beacon_proposer_index(slot, &self.spec)
|
// TODO: fix unwrap
|
||||||
|
let state = self.state(present_slot).unwrap();
|
||||||
|
let index = state.get_beacon_proposer_index(slot, &self.spec)?;
|
||||||
|
|
||||||
|
Ok(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn justified_slot(&self) -> u64 {
|
pub fn justified_slot(&self) -> u64 {
|
||||||
@ -60,3 +70,9 @@ where
|
|||||||
Some(state.attestation_slot_and_shard_for_validator(validator_index, &self.spec))
|
Some(state.attestation_slot_and_shard_for_validator(validator_index, &self.spec))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<BeaconStateError> for Error {
|
||||||
|
fn from(e: BeaconStateError) -> Error {
|
||||||
|
Error::BeaconStateError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -98,7 +98,7 @@ where
|
|||||||
|
|
||||||
let block_proposer_index = state
|
let block_proposer_index = state
|
||||||
.get_beacon_proposer_index(block.slot, &self.spec)
|
.get_beacon_proposer_index(block.slot, &self.spec)
|
||||||
.ok_or(Error::NoBlockProducer)?;
|
.map_err(|_| Error::NoBlockProducer)?;
|
||||||
let block_proposer = &state.validator_registry[block_proposer_index];
|
let block_proposer = &state.validator_registry[block_proposer_index];
|
||||||
|
|
||||||
if verify_block_signature {
|
if verify_block_signature {
|
||||||
@ -294,7 +294,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
if state.slot % self.spec.epoch_length == 0 {
|
if state.slot % self.spec.epoch_length == 0 {
|
||||||
state.per_epoch_processing(&self.spec);
|
state.per_epoch_processing(&self.spec).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(state)
|
Ok(state)
|
||||||
|
@ -113,10 +113,7 @@ impl BeaconChainHarness {
|
|||||||
pub fn produce_block(&mut self) -> BeaconBlock {
|
pub fn produce_block(&mut self) -> BeaconBlock {
|
||||||
let present_slot = self.beacon_chain.present_slot().unwrap();
|
let present_slot = self.beacon_chain.present_slot().unwrap();
|
||||||
|
|
||||||
let proposer = self
|
let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();
|
||||||
.beacon_chain
|
|
||||||
.block_proposer(present_slot)
|
|
||||||
.expect("Unable to determine proposer.");
|
|
||||||
|
|
||||||
self.validators[proposer].produce_block().unwrap()
|
self.validators[proposer].produce_block().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,9 @@ where
|
|||||||
.ok_or_else(|| ProducerDutiesReaderError::UnknownValidator)?;
|
.ok_or_else(|| ProducerDutiesReaderError::UnknownValidator)?;
|
||||||
|
|
||||||
match self.beacon_chain.block_proposer(slot) {
|
match self.beacon_chain.block_proposer(slot) {
|
||||||
Some(proposer) if proposer == validator_index => Ok(true),
|
Ok(proposer) if proposer == validator_index => Ok(true),
|
||||||
Some(_) => Ok(false),
|
Ok(_) => Ok(false),
|
||||||
None => Err(ProducerDutiesReaderError::UnknownEpoch),
|
Err(_) => Err(ProducerDutiesReaderError::UnknownEpoch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,9 @@ use types::ChainSpec;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn it_can_build_on_genesis_block() {
|
fn it_can_build_on_genesis_block() {
|
||||||
let validator_count = 2;
|
let validator_count = 10;
|
||||||
let mut harness = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
let spec = ChainSpec::foundation();
|
||||||
|
let mut harness = BeaconChainHarness::new(spec, validator_count);
|
||||||
|
|
||||||
harness.advance_chain_with_block();
|
harness.advance_chain_with_block();
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,8 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result<BeaconState, Error> {
|
|||||||
current_epoch_start_shard: spec.genesis_start_shard,
|
current_epoch_start_shard: spec.genesis_start_shard,
|
||||||
previous_epoch_calculation_slot: spec.genesis_slot,
|
previous_epoch_calculation_slot: spec.genesis_slot,
|
||||||
current_epoch_calculation_slot: spec.genesis_slot,
|
current_epoch_calculation_slot: spec.genesis_slot,
|
||||||
previous_epoch_randao_mix: spec.zero_hash,
|
previous_epoch_seed: spec.zero_hash,
|
||||||
current_epoch_randao_mix: spec.zero_hash,
|
current_epoch_seed: spec.zero_hash,
|
||||||
/*
|
/*
|
||||||
* Custody challenges
|
* Custody challenges
|
||||||
*/
|
*/
|
||||||
|
@ -7,6 +7,7 @@ use integer_sqrt::IntegerSquareRoot;
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
UnableToDetermineProducer,
|
UnableToDetermineProducer,
|
||||||
NoBlockRoots,
|
NoBlockRoots,
|
||||||
@ -303,8 +304,8 @@ impl BeaconState {
|
|||||||
|
|
||||||
for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
||||||
let crosslink_committees_at_slot = self
|
let crosslink_committees_at_slot = self
|
||||||
.get_crosslink_committees_at_slot(slot)
|
.get_crosslink_committees_at_slot(slot, spec)
|
||||||
.ok_or_else(|| Error::UnableToGetCrosslinkCommittees)?;
|
.map_err(|_| Error::UnableToGetCrosslinkCommittees)?;
|
||||||
|
|
||||||
for (crosslink_committee, shard) in crosslink_committees_at_slot {
|
for (crosslink_committee, shard) in crosslink_committees_at_slot {
|
||||||
let shard = shard as u64;
|
let shard = shard as u64;
|
||||||
@ -454,7 +455,7 @@ impl BeaconState {
|
|||||||
};
|
};
|
||||||
let proposer_index = self
|
let proposer_index = self
|
||||||
.get_beacon_proposer_index(inclusion_slot, spec)
|
.get_beacon_proposer_index(inclusion_slot, spec)
|
||||||
.ok_or_else(|| Error::UnableToDetermineProducer)?;
|
.map_err(|_| Error::UnableToDetermineProducer)?;
|
||||||
let base_reward = self.base_reward(proposer_index, base_reward_quotient, spec);
|
let base_reward = self.base_reward(proposer_index, base_reward_quotient, spec);
|
||||||
safe_add_assign!(
|
safe_add_assign!(
|
||||||
self.validator_balances[proposer_index],
|
self.validator_balances[proposer_index],
|
||||||
@ -467,8 +468,8 @@ impl BeaconState {
|
|||||||
*/
|
*/
|
||||||
for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
||||||
let crosslink_committees_at_slot = self
|
let crosslink_committees_at_slot = self
|
||||||
.get_crosslink_committees_at_slot(slot)
|
.get_crosslink_committees_at_slot(slot, spec)
|
||||||
.ok_or_else(|| Error::UnableToGetCrosslinkCommittees)?;
|
.map_err(|_| Error::UnableToGetCrosslinkCommittees)?;
|
||||||
|
|
||||||
for (_crosslink_committee, shard) in crosslink_committees_at_slot {
|
for (_crosslink_committee, shard) in crosslink_committees_at_slot {
|
||||||
let shard = shard as u64;
|
let shard = shard as u64;
|
||||||
@ -514,7 +515,7 @@ impl BeaconState {
|
|||||||
*/
|
*/
|
||||||
self.previous_epoch_calculation_slot = self.current_epoch_calculation_slot;
|
self.previous_epoch_calculation_slot = self.current_epoch_calculation_slot;
|
||||||
self.previous_epoch_start_shard = self.current_epoch_start_shard;
|
self.previous_epoch_start_shard = self.current_epoch_start_shard;
|
||||||
self.previous_epoch_randao_mix = self.current_epoch_randao_mix;
|
self.previous_epoch_seed = self.current_epoch_seed;
|
||||||
|
|
||||||
let should_update_validator_registy = if self.finalized_slot
|
let should_update_validator_registy = if self.finalized_slot
|
||||||
> self.validator_registry_update_slot
|
> self.validator_registry_update_slot
|
||||||
@ -534,7 +535,7 @@ impl BeaconState {
|
|||||||
self.current_epoch_start_shard = (self.current_epoch_start_shard
|
self.current_epoch_start_shard = (self.current_epoch_start_shard
|
||||||
+ self.get_current_epoch_committee_count_per_slot(spec) as u64 * spec.epoch_length)
|
+ self.get_current_epoch_committee_count_per_slot(spec) as u64 * spec.epoch_length)
|
||||||
% spec.shard_count;
|
% spec.shard_count;
|
||||||
self.current_epoch_randao_mix = self.get_randao_mix(
|
self.current_epoch_seed = self.get_randao_mix(
|
||||||
self.current_epoch_calculation_slot
|
self.current_epoch_calculation_slot
|
||||||
.saturating_sub(spec.seed_lookahead),
|
.saturating_sub(spec.seed_lookahead),
|
||||||
spec,
|
spec,
|
||||||
@ -544,7 +545,7 @@ impl BeaconState {
|
|||||||
(self.slot - self.validator_registry_update_slot) / spec.epoch_length;
|
(self.slot - self.validator_registry_update_slot) / spec.epoch_length;
|
||||||
if epochs_since_last_registry_change.is_power_of_two() {
|
if epochs_since_last_registry_change.is_power_of_two() {
|
||||||
self.current_epoch_calculation_slot = self.slot;
|
self.current_epoch_calculation_slot = self.slot;
|
||||||
self.current_epoch_randao_mix = self.get_randao_mix(
|
self.current_epoch_seed = self.get_randao_mix(
|
||||||
self.current_epoch_calculation_slot
|
self.current_epoch_calculation_slot
|
||||||
.saturating_sub(spec.seed_lookahead),
|
.saturating_sub(spec.seed_lookahead),
|
||||||
spec,
|
spec,
|
||||||
@ -709,14 +710,6 @@ impl BeaconState {
|
|||||||
(slot - slot % spec.epoch_length) + spec.epoch_length + spec.entry_exit_delay
|
(slot - slot % spec.epoch_length) + spec.epoch_length + spec.entry_exit_delay
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_epoch_committee_count_per_slot(&self, spec: &ChainSpec) -> usize {
|
|
||||||
let current_active_validators = get_active_validator_indices(
|
|
||||||
&self.validator_registry,
|
|
||||||
self.current_epoch_calculation_slot,
|
|
||||||
);
|
|
||||||
self.get_committee_count_per_slot(current_active_validators.len(), spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_ejections(&self) {
|
fn process_ejections(&self) {
|
||||||
//TODO: stubbed out.
|
//TODO: stubbed out.
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,12 @@ pub use self::attestation_validation::Error as AttestationValidationError;
|
|||||||
pub use self::epoch_processing::Error as EpochProcessingError;
|
pub use self::epoch_processing::Error as EpochProcessingError;
|
||||||
pub use self::slot_processing::Error as SlotProcessingError;
|
pub use self::slot_processing::Error as SlotProcessingError;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Error {
|
||||||
|
InvalidSlot,
|
||||||
|
InsufficientNumberOfValidators,
|
||||||
|
}
|
||||||
|
|
||||||
// Custody will not be added to the specs until Phase 1 (Sharding Phase) so dummy class used.
|
// Custody will not be added to the specs until Phase 1 (Sharding Phase) so dummy class used.
|
||||||
type CustodyChallenge = usize;
|
type CustodyChallenge = usize;
|
||||||
|
|
||||||
@ -44,8 +50,8 @@ pub struct BeaconState {
|
|||||||
pub current_epoch_start_shard: u64,
|
pub current_epoch_start_shard: u64,
|
||||||
pub previous_epoch_calculation_slot: u64,
|
pub previous_epoch_calculation_slot: u64,
|
||||||
pub current_epoch_calculation_slot: u64,
|
pub current_epoch_calculation_slot: u64,
|
||||||
pub previous_epoch_randao_mix: Hash256,
|
pub previous_epoch_seed: Hash256,
|
||||||
pub current_epoch_randao_mix: Hash256,
|
pub current_epoch_seed: Hash256,
|
||||||
|
|
||||||
// Custody challenges
|
// Custody challenges
|
||||||
pub custody_challenges: Vec<CustodyChallenge>,
|
pub custody_challenges: Vec<CustodyChallenge>,
|
||||||
@ -90,8 +96,8 @@ impl Encodable for BeaconState {
|
|||||||
s.append(&self.current_epoch_start_shard);
|
s.append(&self.current_epoch_start_shard);
|
||||||
s.append(&self.previous_epoch_calculation_slot);
|
s.append(&self.previous_epoch_calculation_slot);
|
||||||
s.append(&self.current_epoch_calculation_slot);
|
s.append(&self.current_epoch_calculation_slot);
|
||||||
s.append(&self.previous_epoch_randao_mix);
|
s.append(&self.previous_epoch_seed);
|
||||||
s.append(&self.current_epoch_randao_mix);
|
s.append(&self.current_epoch_seed);
|
||||||
s.append(&self.custody_challenges);
|
s.append(&self.custody_challenges);
|
||||||
s.append(&self.previous_justified_slot);
|
s.append(&self.previous_justified_slot);
|
||||||
s.append(&self.justified_slot);
|
s.append(&self.justified_slot);
|
||||||
@ -123,8 +129,8 @@ impl Decodable for BeaconState {
|
|||||||
let (current_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?;
|
let (current_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (previous_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?;
|
let (previous_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (current_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?;
|
let (current_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (previous_epoch_randao_mix, i) = <_>::ssz_decode(bytes, i)?;
|
let (previous_epoch_seed, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (current_epoch_randao_mix, i) = <_>::ssz_decode(bytes, i)?;
|
let (current_epoch_seed, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (custody_challenges, i) = <_>::ssz_decode(bytes, i)?;
|
let (custody_challenges, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (previous_justified_slot, i) = <_>::ssz_decode(bytes, i)?;
|
let (previous_justified_slot, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (justified_slot, i) = <_>::ssz_decode(bytes, i)?;
|
let (justified_slot, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
@ -154,8 +160,8 @@ impl Decodable for BeaconState {
|
|||||||
current_epoch_start_shard,
|
current_epoch_start_shard,
|
||||||
previous_epoch_calculation_slot,
|
previous_epoch_calculation_slot,
|
||||||
current_epoch_calculation_slot,
|
current_epoch_calculation_slot,
|
||||||
previous_epoch_randao_mix,
|
previous_epoch_seed,
|
||||||
current_epoch_randao_mix,
|
current_epoch_seed,
|
||||||
custody_challenges,
|
custody_challenges,
|
||||||
previous_justified_slot,
|
previous_justified_slot,
|
||||||
justified_slot,
|
justified_slot,
|
||||||
@ -191,8 +197,8 @@ impl TreeHash for BeaconState {
|
|||||||
result.append(&mut self.current_epoch_start_shard.hash_tree_root());
|
result.append(&mut self.current_epoch_start_shard.hash_tree_root());
|
||||||
result.append(&mut self.previous_epoch_calculation_slot.hash_tree_root());
|
result.append(&mut self.previous_epoch_calculation_slot.hash_tree_root());
|
||||||
result.append(&mut self.current_epoch_calculation_slot.hash_tree_root());
|
result.append(&mut self.current_epoch_calculation_slot.hash_tree_root());
|
||||||
result.append(&mut self.previous_epoch_randao_mix.hash_tree_root());
|
result.append(&mut self.previous_epoch_seed.hash_tree_root());
|
||||||
result.append(&mut self.current_epoch_randao_mix.hash_tree_root());
|
result.append(&mut self.current_epoch_seed.hash_tree_root());
|
||||||
result.append(&mut self.custody_challenges.hash_tree_root());
|
result.append(&mut self.custody_challenges.hash_tree_root());
|
||||||
result.append(&mut self.previous_justified_slot.hash_tree_root());
|
result.append(&mut self.previous_justified_slot.hash_tree_root());
|
||||||
result.append(&mut self.justified_slot.hash_tree_root());
|
result.append(&mut self.justified_slot.hash_tree_root());
|
||||||
@ -226,8 +232,8 @@ impl<T: RngCore> TestRandom<T> for BeaconState {
|
|||||||
current_epoch_start_shard: <_>::random_for_test(rng),
|
current_epoch_start_shard: <_>::random_for_test(rng),
|
||||||
previous_epoch_calculation_slot: <_>::random_for_test(rng),
|
previous_epoch_calculation_slot: <_>::random_for_test(rng),
|
||||||
current_epoch_calculation_slot: <_>::random_for_test(rng),
|
current_epoch_calculation_slot: <_>::random_for_test(rng),
|
||||||
previous_epoch_randao_mix: <_>::random_for_test(rng),
|
previous_epoch_seed: <_>::random_for_test(rng),
|
||||||
current_epoch_randao_mix: <_>::random_for_test(rng),
|
current_epoch_seed: <_>::random_for_test(rng),
|
||||||
custody_challenges: <_>::random_for_test(rng),
|
custody_challenges: <_>::random_for_test(rng),
|
||||||
previous_justified_slot: <_>::random_for_test(rng),
|
previous_justified_slot: <_>::random_for_test(rng),
|
||||||
justified_slot: <_>::random_for_test(rng),
|
justified_slot: <_>::random_for_test(rng),
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
|
use super::Error;
|
||||||
use crate::{validator_registry::get_active_validator_indices, BeaconState, ChainSpec, Hash256};
|
use crate::{validator_registry::get_active_validator_indices, BeaconState, ChainSpec, Hash256};
|
||||||
use honey_badger_split::SplitExt;
|
use honey_badger_split::SplitExt;
|
||||||
|
use std::ops::Range;
|
||||||
use vec_shuffle::shuffle;
|
use vec_shuffle::shuffle;
|
||||||
|
|
||||||
type CrosslinkCommittee = (Vec<usize>, usize);
|
// utility function pending this functionality being stabilized on the `Range` type.
|
||||||
type CrosslinkCommittees = Vec<CrosslinkCommittee>;
|
fn range_contains<T: PartialOrd>(range: &Range<T>, target: T) -> bool {
|
||||||
|
range.start <= target && target < range.end
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
impl BeaconState {
|
impl BeaconState {
|
||||||
pub fn get_shuffling(&self, seed: Hash256, slot: u64, spec: &ChainSpec) -> Vec<Vec<usize>> {
|
pub fn get_shuffling(&self, seed: Hash256, slot: u64, spec: &ChainSpec) -> Vec<Vec<usize>> {
|
||||||
@ -20,7 +26,7 @@ impl BeaconState {
|
|||||||
shuffle(&seed, active_validator_indices).expect("Max validator count exceed!");
|
shuffle(&seed, active_validator_indices).expect("Max validator count exceed!");
|
||||||
|
|
||||||
shuffled_active_validator_indices
|
shuffled_active_validator_indices
|
||||||
.honey_badger_split(committees_per_slot * spec.epoch_length as usize)
|
.honey_badger_split((committees_per_slot * spec.epoch_length) as usize)
|
||||||
.filter_map(|slice: &[usize]| Some(slice.to_vec()))
|
.filter_map(|slice: &[usize]| Some(slice.to_vec()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -29,19 +35,110 @@ impl BeaconState {
|
|||||||
&self,
|
&self,
|
||||||
active_validator_count: usize,
|
active_validator_count: usize,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> usize {
|
) -> u64 {
|
||||||
std::cmp::max(
|
std::cmp::max(
|
||||||
1,
|
1,
|
||||||
std::cmp::min(
|
std::cmp::min(
|
||||||
spec.shard_count as usize / spec.epoch_length as usize,
|
spec.shard_count / spec.epoch_length,
|
||||||
active_validator_count
|
active_validator_count as u64 / spec.epoch_length / spec.target_committee_size,
|
||||||
/ spec.epoch_length as usize
|
|
||||||
/ spec.target_committee_size as usize,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_crosslink_committees_at_slot(&self, _slot: u64) -> Option<CrosslinkCommittees> {
|
/// Returns the start slot and end slot of the current epoch containing `self.slot`.
|
||||||
Some(vec![(vec![0], 0)])
|
fn get_current_epoch_boundaries(&self, epoch_length: u64) -> Range<u64> {
|
||||||
|
let slot_in_epoch = self.slot % epoch_length;
|
||||||
|
let start = self.slot - slot_in_epoch;
|
||||||
|
let end = self.slot + (epoch_length - slot_in_epoch);
|
||||||
|
start..end
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_previous_epoch_committee_count_per_slot(
|
||||||
|
&self,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
/*
|
||||||
|
shard_count: u64,
|
||||||
|
epoch_length: u64,
|
||||||
|
target_committee_size: u64,
|
||||||
|
*/
|
||||||
|
) -> u64 {
|
||||||
|
let previous_active_validators = get_active_validator_indices(
|
||||||
|
&self.validator_registry,
|
||||||
|
self.previous_epoch_calculation_slot,
|
||||||
|
);
|
||||||
|
self.get_committee_count_per_slot(previous_active_validators.len(), spec) as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_epoch_committee_count_per_slot(&self, spec: &ChainSpec) -> u64 {
|
||||||
|
let current_active_validators = get_active_validator_indices(
|
||||||
|
&self.validator_registry,
|
||||||
|
self.current_epoch_calculation_slot,
|
||||||
|
);
|
||||||
|
self.get_committee_count_per_slot(current_active_validators.len(), spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_crosslink_committees_at_slot(
|
||||||
|
&self,
|
||||||
|
slot: u64,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
/*
|
||||||
|
epoch_length: u64,
|
||||||
|
shard_count: u64,
|
||||||
|
target_committee_size: u64,
|
||||||
|
*/
|
||||||
|
) -> Result<Vec<(Vec<usize>, u64)>> {
|
||||||
|
let current_epoch_range = self.get_current_epoch_boundaries(spec.epoch_length);
|
||||||
|
if !range_contains(¤t_epoch_range, slot) {
|
||||||
|
return Err(Error::InvalidSlot);
|
||||||
|
}
|
||||||
|
let state_epoch_slot = current_epoch_range.start;
|
||||||
|
let offset = slot % spec.epoch_length;
|
||||||
|
|
||||||
|
let (committees_per_slot, shuffling, slot_start_shard) = if slot < state_epoch_slot {
|
||||||
|
let committees_per_slot = self.get_previous_epoch_committee_count_per_slot(spec);
|
||||||
|
let shuffling = self.get_shuffling(
|
||||||
|
self.previous_epoch_seed,
|
||||||
|
self.previous_epoch_calculation_slot,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
let slot_start_shard =
|
||||||
|
(self.previous_epoch_start_shard + committees_per_slot * offset) % spec.shard_count;
|
||||||
|
(committees_per_slot, shuffling, slot_start_shard)
|
||||||
|
} else {
|
||||||
|
let committees_per_slot = self.get_current_epoch_committee_count_per_slot(spec);
|
||||||
|
let shuffling = self.get_shuffling(
|
||||||
|
self.current_epoch_seed,
|
||||||
|
self.current_epoch_calculation_slot,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
let slot_start_shard =
|
||||||
|
(self.current_epoch_start_shard + committees_per_slot * offset) % spec.shard_count;
|
||||||
|
(committees_per_slot, shuffling, slot_start_shard)
|
||||||
|
};
|
||||||
|
|
||||||
|
let shard_range = slot_start_shard..;
|
||||||
|
Ok(shuffling
|
||||||
|
.into_iter()
|
||||||
|
.skip((committees_per_slot * offset) as usize)
|
||||||
|
.zip(shard_range.into_iter())
|
||||||
|
.take(committees_per_slot as usize)
|
||||||
|
.map(|(committees, shard_number)| (committees, shard_number % spec.shard_count))
|
||||||
|
.collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the beacon proposer index for the `slot`.
|
||||||
|
/// If the state does not contain an index for a beacon proposer at the requested `slot`, then `None` is returned.
|
||||||
|
pub fn get_beacon_proposer_index(&self, slot: u64, spec: &ChainSpec) -> Result<usize> {
|
||||||
|
let committees = self.get_crosslink_committees_at_slot(slot, spec)?;
|
||||||
|
committees
|
||||||
|
.first()
|
||||||
|
.ok_or(Error::InsufficientNumberOfValidators)
|
||||||
|
.and_then(|(first_committee, _)| {
|
||||||
|
let index = (slot as usize)
|
||||||
|
.checked_rem(first_committee.len())
|
||||||
|
.ok_or(Error::InsufficientNumberOfValidators)?;
|
||||||
|
// NOTE: next index will not panic as we have already returned if this is the case
|
||||||
|
Ok(first_committee[index])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ impl BeaconState {
|
|||||||
|
|
||||||
let block_proposer = self
|
let block_proposer = self
|
||||||
.get_beacon_proposer_index(self.slot, spec)
|
.get_beacon_proposer_index(self.slot, spec)
|
||||||
.ok_or_else(|| Error::UnableToDetermineProducer)?;
|
.map_err(|_| Error::UnableToDetermineProducer)?;
|
||||||
|
|
||||||
self.validator_registry[block_proposer].proposer_slots += 1;
|
self.validator_registry[block_proposer].proposer_slots += 1;
|
||||||
self.latest_randao_mixes[(self.slot % spec.latest_randao_mixes_length) as usize] =
|
self.latest_randao_mixes[(self.slot % spec.latest_randao_mixes_length) as usize] =
|
||||||
@ -31,14 +31,6 @@ impl BeaconState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_beacon_proposer_index(&self, slot: u64, spec: &ChainSpec) -> Option<usize> {
|
|
||||||
// TODO: this is a stub; implement it properly.
|
|
||||||
//
|
|
||||||
// https://github.com/sigp/lighthouse/pull/148/files
|
|
||||||
let validator_count = self.validator_registry.len();
|
|
||||||
Some((slot as usize) % validator_count)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn attestation_slot_and_shard_for_validator(
|
pub fn attestation_slot_and_shard_for_validator(
|
||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
|
Loading…
Reference in New Issue
Block a user