Merge pull request #232 from sigp/tidy-beacon-state
Add beacon state test builder, tidy errors
This commit is contained in:
commit
0800091a43
@ -1,7 +1,7 @@
|
|||||||
use state_processing::validate_attestation_without_signature;
|
use state_processing::validate_attestation_without_signature;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use types::{
|
use types::{
|
||||||
beacon_state::CommitteesError, AggregateSignature, Attestation, AttestationData, BeaconState,
|
beacon_state::BeaconStateError, AggregateSignature, Attestation, AttestationData, BeaconState,
|
||||||
Bitfield, ChainSpec, FreeAttestation, Signature,
|
Bitfield, ChainSpec, FreeAttestation, Signature,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ impl AttestationAggregator {
|
|||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
free_attestation: &FreeAttestation,
|
free_attestation: &FreeAttestation,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<Outcome, CommitteesError> {
|
) -> Result<Outcome, BeaconStateError> {
|
||||||
let (slot, shard, committee_index) = some_or_invalid!(
|
let (slot, shard, committee_index) = some_or_invalid!(
|
||||||
state.attestation_slot_and_shard_for_validator(
|
state.attestation_slot_and_shard_for_validator(
|
||||||
free_attestation.validator_index as usize,
|
free_attestation.validator_index as usize,
|
||||||
|
@ -14,7 +14,7 @@ use state_processing::{
|
|||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{
|
use types::{
|
||||||
beacon_state::CommitteesError,
|
beacon_state::BeaconStateError,
|
||||||
readers::{BeaconBlockReader, BeaconStateReader},
|
readers::{BeaconBlockReader, BeaconStateReader},
|
||||||
AttestationData, BeaconBlock, BeaconBlockBody, BeaconState, ChainSpec, Crosslink, Deposit,
|
AttestationData, BeaconBlock, BeaconBlockBody, BeaconState, ChainSpec, Crosslink, Deposit,
|
||||||
Epoch, Eth1Data, FreeAttestation, Hash256, PublicKey, Signature, Slot,
|
Epoch, Eth1Data, FreeAttestation, Hash256, PublicKey, Signature, Slot,
|
||||||
@ -24,7 +24,7 @@ use types::{
|
|||||||
pub enum Error {
|
pub enum Error {
|
||||||
InsufficientValidators,
|
InsufficientValidators,
|
||||||
BadRecentBlockRoots,
|
BadRecentBlockRoots,
|
||||||
CommitteesError(CommitteesError),
|
BeaconStateError(BeaconStateError),
|
||||||
DBInconsistent(String),
|
DBInconsistent(String),
|
||||||
DBError(String),
|
DBError(String),
|
||||||
ForkChoiceError(ForkChoiceError),
|
ForkChoiceError(ForkChoiceError),
|
||||||
@ -99,7 +99,7 @@ where
|
|||||||
initial_validator_deposits,
|
initial_validator_deposits,
|
||||||
latest_eth1_data,
|
latest_eth1_data,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
)?;
|
||||||
let state_root = genesis_state.canonical_root();
|
let state_root = genesis_state.canonical_root();
|
||||||
state_store.put(&state_root, &ssz_encode(&genesis_state)[..])?;
|
state_store.put(&state_root, &ssz_encode(&genesis_state)[..])?;
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ where
|
|||||||
///
|
///
|
||||||
/// Information is read from the present `beacon_state` shuffling, so only information from the
|
/// Information is read from the present `beacon_state` shuffling, so only information from the
|
||||||
/// present and prior epoch is available.
|
/// present and prior epoch is available.
|
||||||
pub fn block_proposer(&self, slot: Slot) -> Result<usize, CommitteesError> {
|
pub fn block_proposer(&self, slot: Slot) -> Result<usize, BeaconStateError> {
|
||||||
let index = self
|
let index = self
|
||||||
.state
|
.state
|
||||||
.read()
|
.read()
|
||||||
@ -273,7 +273,7 @@ where
|
|||||||
pub fn validator_attestion_slot_and_shard(
|
pub fn validator_attestion_slot_and_shard(
|
||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
) -> Result<Option<(Slot, u64)>, CommitteesError> {
|
) -> Result<Option<(Slot, u64)>, BeaconStateError> {
|
||||||
if let Some((slot, shard, _committee)) = self
|
if let Some((slot, shard, _committee)) = self
|
||||||
.state
|
.state
|
||||||
.read()
|
.read()
|
||||||
@ -588,8 +588,8 @@ impl From<ForkChoiceError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
impl From<BeaconStateError> for Error {
|
||||||
fn from(e: CommitteesError) -> Error {
|
fn from(e: BeaconStateError) -> Error {
|
||||||
Error::CommitteesError(e)
|
Error::BeaconStateError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use int_to_bytes::int_to_bytes32;
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use ssz::{ssz_encode, TreeHash};
|
use ssz::{ssz_encode, TreeHash};
|
||||||
use types::{
|
use types::{
|
||||||
beacon_state::{AttestationValidationError, CommitteesError},
|
beacon_state::{AttestationParticipantsError, BeaconStateError},
|
||||||
AggregatePublicKey, Attestation, BeaconBlock, BeaconState, ChainSpec, Crosslink, Epoch, Exit,
|
AggregatePublicKey, Attestation, BeaconBlock, BeaconState, ChainSpec, Crosslink, Epoch, Exit,
|
||||||
Fork, Hash256, PendingAttestation, PublicKey, Signature,
|
Fork, Hash256, PendingAttestation, PublicKey, Signature,
|
||||||
};
|
};
|
||||||
@ -42,10 +42,23 @@ pub enum Error {
|
|||||||
BadCustodyReseeds,
|
BadCustodyReseeds,
|
||||||
BadCustodyChallenges,
|
BadCustodyChallenges,
|
||||||
BadCustodyResponses,
|
BadCustodyResponses,
|
||||||
CommitteesError(CommitteesError),
|
BeaconStateError(BeaconStateError),
|
||||||
SlotProcessingError(SlotProcessingError),
|
SlotProcessingError(SlotProcessingError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum AttestationValidationError {
|
||||||
|
IncludedTooEarly,
|
||||||
|
IncludedTooLate,
|
||||||
|
WrongJustifiedSlot,
|
||||||
|
WrongJustifiedRoot,
|
||||||
|
BadLatestCrosslinkRoot,
|
||||||
|
BadSignature,
|
||||||
|
ShardBlockRootNotZero,
|
||||||
|
NoBlockRoot,
|
||||||
|
AttestationParticipantsError(AttestationParticipantsError),
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! ensure {
|
macro_rules! ensure {
|
||||||
($condition: expr, $result: expr) => {
|
($condition: expr, $result: expr) => {
|
||||||
if !$condition {
|
if !$condition {
|
||||||
@ -391,9 +404,9 @@ impl From<AttestationValidationError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
impl From<BeaconStateError> for Error {
|
||||||
fn from(e: CommitteesError) -> Error {
|
fn from(e: BeaconStateError) -> Error {
|
||||||
Error::CommitteesError(e)
|
Error::BeaconStateError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,3 +415,9 @@ impl From<SlotProcessingError> for Error {
|
|||||||
Error::SlotProcessingError(e)
|
Error::SlotProcessingError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<AttestationParticipantsError> for AttestationValidationError {
|
||||||
|
fn from(e: AttestationParticipantsError) -> AttestationValidationError {
|
||||||
|
AttestationValidationError::AttestationParticipantsError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ use ssz::TreeHash;
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use types::{
|
use types::{
|
||||||
beacon_state::{AttestationParticipantsError, CommitteesError, InclusionError},
|
beacon_state::{AttestationParticipantsError, BeaconStateError, InclusionError},
|
||||||
validator_registry::get_active_validator_indices,
|
validator_registry::get_active_validator_indices,
|
||||||
BeaconState, ChainSpec, Crosslink, Epoch, Hash256, PendingAttestation,
|
BeaconState, ChainSpec, Crosslink, Epoch, Hash256, PendingAttestation,
|
||||||
};
|
};
|
||||||
@ -27,7 +27,7 @@ pub enum Error {
|
|||||||
NoBlockRoots,
|
NoBlockRoots,
|
||||||
BaseRewardQuotientIsZero,
|
BaseRewardQuotientIsZero,
|
||||||
NoRandaoSeed,
|
NoRandaoSeed,
|
||||||
CommitteesError(CommitteesError),
|
BeaconStateError(BeaconStateError),
|
||||||
AttestationParticipantsError(AttestationParticipantsError),
|
AttestationParticipantsError(AttestationParticipantsError),
|
||||||
InclusionError(InclusionError),
|
InclusionError(InclusionError),
|
||||||
WinningRootError(WinningRootError),
|
WinningRootError(WinningRootError),
|
||||||
@ -559,9 +559,7 @@ impl EpochProcessable for 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(spec) as u64)
|
+ self.get_current_epoch_committee_count(spec) as u64)
|
||||||
% spec.shard_count;
|
% spec.shard_count;
|
||||||
self.current_epoch_seed = self
|
self.current_epoch_seed = self.generate_seed(self.current_calculation_epoch, spec)?
|
||||||
.generate_seed(self.current_calculation_epoch, spec)
|
|
||||||
.ok_or_else(|| Error::NoRandaoSeed)?;
|
|
||||||
} else {
|
} else {
|
||||||
let epochs_since_last_registry_update =
|
let epochs_since_last_registry_update =
|
||||||
current_epoch - self.validator_registry_update_epoch;
|
current_epoch - self.validator_registry_update_epoch;
|
||||||
@ -569,9 +567,8 @@ impl EpochProcessable for BeaconState {
|
|||||||
& epochs_since_last_registry_update.is_power_of_two()
|
& epochs_since_last_registry_update.is_power_of_two()
|
||||||
{
|
{
|
||||||
self.current_calculation_epoch = next_epoch;
|
self.current_calculation_epoch = next_epoch;
|
||||||
self.current_epoch_seed = self
|
self.current_epoch_seed =
|
||||||
.generate_seed(self.current_calculation_epoch, spec)
|
self.generate_seed(self.current_calculation_epoch, spec)?
|
||||||
.ok_or_else(|| Error::NoRandaoSeed)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,9 +686,9 @@ impl From<InclusionError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
impl From<BeaconStateError> for Error {
|
||||||
fn from(e: CommitteesError) -> Error {
|
fn from(e: BeaconStateError) -> Error {
|
||||||
Error::CommitteesError(e)
|
Error::BeaconStateError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::{EpochProcessable, EpochProcessingError};
|
use crate::{EpochProcessable, EpochProcessingError};
|
||||||
use types::{beacon_state::CommitteesError, BeaconState, ChainSpec, Hash256};
|
use types::{beacon_state::BeaconStateError, BeaconState, ChainSpec, Hash256};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
CommitteesError(CommitteesError),
|
BeaconStateError(BeaconStateError),
|
||||||
EpochProcessingError(EpochProcessingError),
|
EpochProcessingError(EpochProcessingError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,9 +49,9 @@ fn merkle_root(_input: &[Hash256]) -> Hash256 {
|
|||||||
Hash256::zero()
|
Hash256::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
impl From<BeaconStateError> for Error {
|
||||||
fn from(e: CommitteesError) -> Error {
|
fn from(e: BeaconStateError) -> Error {
|
||||||
Error::CommitteesError(e)
|
Error::BeaconStateError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,3 +19,6 @@ serde_json = "1.0"
|
|||||||
slog = "^2.2.3"
|
slog = "^2.2.3"
|
||||||
ssz = { path = "../utils/ssz" }
|
ssz = { path = "../utils/ssz" }
|
||||||
fisher_yates_shuffle = { path = "../utils/fisher_yates_shuffle" }
|
fisher_yates_shuffle = { path = "../utils/fisher_yates_shuffle" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
env_logger = "0.6.0"
|
||||||
|
@ -10,47 +10,30 @@ use honey_badger_split::SplitExt;
|
|||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||||
use std::ops::Range;
|
|
||||||
|
|
||||||
pub enum Error {
|
|
||||||
InsufficientValidators,
|
|
||||||
BadBlockSignature,
|
|
||||||
InvalidEpoch(Slot, Range<Epoch>),
|
|
||||||
CommitteesError(CommitteesError),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum CommitteesError {
|
pub enum BeaconStateError {
|
||||||
InvalidEpoch,
|
EpochOutOfBounds,
|
||||||
InsufficientNumberOfValidators,
|
InsufficientRandaoMixes,
|
||||||
BadRandao,
|
InsufficientValidators,
|
||||||
|
InsufficientBlockRoots,
|
||||||
|
InsufficientIndexRoots,
|
||||||
|
InsufficientAttestations,
|
||||||
|
InsufficientCommittees,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum InclusionError {
|
pub enum InclusionError {
|
||||||
NoIncludedAttestations,
|
/// The validator did not participate in an attestation in this period.
|
||||||
|
NoAttestationsForValidator,
|
||||||
AttestationParticipantsError(AttestationParticipantsError),
|
AttestationParticipantsError(AttestationParticipantsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AttestationParticipantsError {
|
pub enum AttestationParticipantsError {
|
||||||
|
/// There is no committee for the given shard in the given epoch.
|
||||||
NoCommitteeForShard,
|
NoCommitteeForShard,
|
||||||
NoCommittees,
|
BeaconStateError(BeaconStateError),
|
||||||
BadBitfieldLength,
|
|
||||||
CommitteesError(CommitteesError),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum AttestationValidationError {
|
|
||||||
IncludedTooEarly,
|
|
||||||
IncludedTooLate,
|
|
||||||
WrongJustifiedSlot,
|
|
||||||
WrongJustifiedRoot,
|
|
||||||
BadLatestCrosslinkRoot,
|
|
||||||
BadSignature,
|
|
||||||
ShardBlockRootNotZero,
|
|
||||||
NoBlockRoot,
|
|
||||||
AttestationParticipantsError(AttestationParticipantsError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! safe_add_assign {
|
macro_rules! safe_add_assign {
|
||||||
@ -111,7 +94,7 @@ impl BeaconState {
|
|||||||
initial_validator_deposits: Vec<Deposit>,
|
initial_validator_deposits: Vec<Deposit>,
|
||||||
latest_eth1_data: Eth1Data,
|
latest_eth1_data: Eth1Data,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> BeaconState {
|
) -> Result<BeaconState, BeaconStateError> {
|
||||||
let initial_crosslink = Crosslink {
|
let initial_crosslink = Crosslink {
|
||||||
epoch: spec.genesis_epoch,
|
epoch: spec.genesis_epoch,
|
||||||
shard_block_root: spec.zero_hash,
|
shard_block_root: spec.zero_hash,
|
||||||
@ -195,11 +178,9 @@ impl BeaconState {
|
|||||||
));
|
));
|
||||||
genesis_state.latest_index_roots =
|
genesis_state.latest_index_roots =
|
||||||
vec![genesis_active_index_root; spec.latest_index_roots_length];
|
vec![genesis_active_index_root; spec.latest_index_roots_length];
|
||||||
genesis_state.current_epoch_seed = genesis_state
|
genesis_state.current_epoch_seed = genesis_state.generate_seed(spec.genesis_epoch, spec)?;
|
||||||
.generate_seed(spec.genesis_epoch, spec)
|
|
||||||
.expect("Unable to generate seed.");
|
|
||||||
|
|
||||||
genesis_state
|
Ok(genesis_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the tree hash root for this `BeaconState`.
|
/// Return the tree hash root for this `BeaconState`.
|
||||||
@ -322,7 +303,7 @@ impl BeaconState {
|
|||||||
+ 1;
|
+ 1;
|
||||||
let latest_index_root = current_epoch + spec.entry_exit_delay;
|
let latest_index_root = current_epoch + spec.entry_exit_delay;
|
||||||
|
|
||||||
if (epoch <= earliest_index_root) & (epoch >= latest_index_root) {
|
if (epoch >= earliest_index_root) & (epoch <= latest_index_root) {
|
||||||
Some(self.latest_index_roots[epoch.as_usize() % spec.latest_index_roots_length])
|
Some(self.latest_index_roots[epoch.as_usize() % spec.latest_index_roots_length])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -332,12 +313,27 @@ impl BeaconState {
|
|||||||
/// Generate a seed for the given ``epoch``.
|
/// Generate a seed for the given ``epoch``.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Option<Hash256> {
|
pub fn generate_seed(
|
||||||
let mut input = self.get_randao_mix(epoch, spec)?.to_vec();
|
&self,
|
||||||
input.append(&mut self.get_active_index_root(epoch, spec)?.to_vec());
|
epoch: Epoch,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<Hash256, BeaconStateError> {
|
||||||
|
let mut input = self
|
||||||
|
.get_randao_mix(epoch, spec)
|
||||||
|
.ok_or_else(|| BeaconStateError::InsufficientRandaoMixes)?
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
|
input.append(
|
||||||
|
&mut self
|
||||||
|
.get_active_index_root(epoch, spec)
|
||||||
|
.ok_or_else(|| BeaconStateError::InsufficientIndexRoots)?
|
||||||
|
.to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: ensure `Hash256::from(u64)` == `int_to_bytes32`.
|
// TODO: ensure `Hash256::from(u64)` == `int_to_bytes32`.
|
||||||
input.append(&mut Hash256::from(epoch.as_u64()).to_vec());
|
input.append(&mut Hash256::from(epoch.as_u64()).to_vec());
|
||||||
Some(Hash256::from(&hash(&input[..])[..]))
|
|
||||||
|
Ok(Hash256::from(&hash(&input[..])[..]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the list of ``(committee, shard)`` tuples for the ``slot``.
|
/// Return the list of ``(committee, shard)`` tuples for the ``slot``.
|
||||||
@ -351,7 +347,7 @@ impl BeaconState {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
registry_change: bool,
|
registry_change: bool,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<Vec<(Vec<usize>, u64)>, CommitteesError> {
|
) -> Result<Vec<(Vec<usize>, u64)>, BeaconStateError> {
|
||||||
let epoch = slot.epoch(spec.epoch_length);
|
let epoch = slot.epoch(spec.epoch_length);
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch(spec);
|
||||||
let previous_epoch = if current_epoch == spec.genesis_epoch {
|
let previous_epoch = if current_epoch == spec.genesis_epoch {
|
||||||
@ -381,9 +377,7 @@ impl BeaconState {
|
|||||||
let epochs_since_last_registry_update =
|
let epochs_since_last_registry_update =
|
||||||
current_epoch - self.validator_registry_update_epoch;
|
current_epoch - self.validator_registry_update_epoch;
|
||||||
let (seed, shuffling_start_shard) = if registry_change {
|
let (seed, shuffling_start_shard) = if registry_change {
|
||||||
let next_seed = self
|
let next_seed = self.generate_seed(next_epoch, spec)?;
|
||||||
.generate_seed(next_epoch, spec)
|
|
||||||
.ok_or_else(|| CommitteesError::BadRandao)?;
|
|
||||||
(
|
(
|
||||||
next_seed,
|
next_seed,
|
||||||
(self.current_epoch_start_shard + current_committees_per_epoch)
|
(self.current_epoch_start_shard + current_committees_per_epoch)
|
||||||
@ -392,9 +386,7 @@ impl BeaconState {
|
|||||||
} else if (epochs_since_last_registry_update > 1)
|
} else if (epochs_since_last_registry_update > 1)
|
||||||
& epochs_since_last_registry_update.is_power_of_two()
|
& epochs_since_last_registry_update.is_power_of_two()
|
||||||
{
|
{
|
||||||
let next_seed = self
|
let next_seed = self.generate_seed(next_epoch, spec)?;
|
||||||
.generate_seed(next_epoch, spec)
|
|
||||||
.ok_or_else(|| CommitteesError::BadRandao)?;
|
|
||||||
(next_seed, self.current_epoch_start_shard)
|
(next_seed, self.current_epoch_start_shard)
|
||||||
} else {
|
} else {
|
||||||
(self.current_epoch_seed, self.current_epoch_start_shard)
|
(self.current_epoch_seed, self.current_epoch_start_shard)
|
||||||
@ -406,7 +398,7 @@ impl BeaconState {
|
|||||||
shuffling_start_shard,
|
shuffling_start_shard,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
panic!("Epoch out-of-bounds.")
|
return Err(BeaconStateError::EpochOutOfBounds);
|
||||||
};
|
};
|
||||||
|
|
||||||
let shuffling = self.get_shuffling(seed, shuffling_epoch, spec);
|
let shuffling = self.get_shuffling(seed, shuffling_epoch, spec);
|
||||||
@ -434,7 +426,7 @@ impl BeaconState {
|
|||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<Option<(Slot, u64, u64)>, CommitteesError> {
|
) -> Result<Option<(Slot, u64, u64)>, BeaconStateError> {
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
for slot in self.current_epoch(spec).slot_iter(spec.epoch_length) {
|
for slot in self.current_epoch(spec).slot_iter(spec.epoch_length) {
|
||||||
for (committee, shard) in self.get_crosslink_committees_at_slot(slot, false, spec)? {
|
for (committee, shard) in self.get_crosslink_committees_at_slot(slot, false, spec)? {
|
||||||
@ -464,16 +456,15 @@ impl BeaconState {
|
|||||||
&self,
|
&self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<usize, CommitteesError> {
|
) -> Result<usize, BeaconStateError> {
|
||||||
let committees = self.get_crosslink_committees_at_slot(slot, false, spec)?;
|
let committees = self.get_crosslink_committees_at_slot(slot, false, spec)?;
|
||||||
committees
|
committees
|
||||||
.first()
|
.first()
|
||||||
.ok_or(CommitteesError::InsufficientNumberOfValidators)
|
.ok_or(BeaconStateError::InsufficientValidators)
|
||||||
.and_then(|(first_committee, _)| {
|
.and_then(|(first_committee, _)| {
|
||||||
let index = (slot.as_usize())
|
let index = (slot.as_usize())
|
||||||
.checked_rem(first_committee.len())
|
.checked_rem(first_committee.len())
|
||||||
.ok_or(CommitteesError::InsufficientNumberOfValidators)?;
|
.ok_or(BeaconStateError::InsufficientValidators)?;
|
||||||
// NOTE: next index will not panic as we have already returned if this is the case.
|
|
||||||
Ok(first_committee[index])
|
Ok(first_committee[index])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -682,7 +673,7 @@ impl BeaconState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), CommitteesError> {
|
) -> Result<(), BeaconStateError> {
|
||||||
self.exit_validator(validator_index, spec);
|
self.exit_validator(validator_index, spec);
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch(spec);
|
||||||
|
|
||||||
@ -802,7 +793,7 @@ impl BeaconState {
|
|||||||
let earliest_attestation_index = included_attestations
|
let earliest_attestation_index = included_attestations
|
||||||
.iter()
|
.iter()
|
||||||
.min_by_key(|i| attestations[**i].inclusion_slot)
|
.min_by_key(|i| attestations[**i].inclusion_slot)
|
||||||
.ok_or_else(|| InclusionError::NoIncludedAttestations)?;
|
.ok_or_else(|| InclusionError::NoAttestationsForValidator)?;
|
||||||
Ok(attestations[*earliest_attestation_index].clone())
|
Ok(attestations[*earliest_attestation_index].clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,34 +898,18 @@ fn hash_tree_root<T: TreeHash>(input: Vec<T>) -> Hash256 {
|
|||||||
Hash256::from(&input.hash_tree_root()[..])
|
Hash256::from(&input.hash_tree_root()[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AttestationParticipantsError> for AttestationValidationError {
|
impl From<BeaconStateError> for AttestationParticipantsError {
|
||||||
fn from(e: AttestationParticipantsError) -> AttestationValidationError {
|
fn from(e: BeaconStateError) -> AttestationParticipantsError {
|
||||||
AttestationValidationError::AttestationParticipantsError(e)
|
AttestationParticipantsError::BeaconStateError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for AttestationParticipantsError {
|
|
||||||
fn from(e: CommitteesError) -> AttestationParticipantsError {
|
|
||||||
AttestationParticipantsError::CommitteesError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
impl From<AttestationParticipantsError> for InclusionError {
|
impl From<AttestationParticipantsError> for InclusionError {
|
||||||
fn from(e: AttestationParticipantsError) -> InclusionError {
|
fn from(e: AttestationParticipantsError) -> InclusionError {
|
||||||
InclusionError::AttestationParticipantsError(e)
|
InclusionError::AttestationParticipantsError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
|
||||||
fn from(e: CommitteesError) -> Error {
|
|
||||||
Error::CommitteesError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encodable for BeaconState {
|
impl Encodable for BeaconState {
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
fn ssz_append(&self, s: &mut SszStream) {
|
||||||
s.append(&self.slot);
|
s.append(&self.slot);
|
||||||
|
72
eth2/types/src/beacon_state_tests.rs
Normal file
72
eth2/types/src/beacon_state_tests.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
beacon_state::BeaconStateError, BeaconState, ChainSpec, Deposit, DepositData, DepositInput,
|
||||||
|
Eth1Data, Hash256, Keypair,
|
||||||
|
};
|
||||||
|
use bls::create_proof_of_possession;
|
||||||
|
|
||||||
|
struct BeaconStateTestBuilder {
|
||||||
|
pub genesis_time: u64,
|
||||||
|
pub initial_validator_deposits: Vec<Deposit>,
|
||||||
|
pub latest_eth1_data: Eth1Data,
|
||||||
|
pub spec: ChainSpec,
|
||||||
|
pub keypairs: Vec<Keypair>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BeaconStateTestBuilder {
|
||||||
|
pub fn with_random_validators(validator_count: usize) -> Self {
|
||||||
|
let genesis_time = 10_000_000;
|
||||||
|
let keypairs: Vec<Keypair> = (0..validator_count)
|
||||||
|
.collect::<Vec<usize>>()
|
||||||
|
.iter()
|
||||||
|
.map(|_| Keypair::random())
|
||||||
|
.collect();
|
||||||
|
let initial_validator_deposits = keypairs
|
||||||
|
.iter()
|
||||||
|
.map(|keypair| Deposit {
|
||||||
|
branch: vec![], // branch verification is not specified.
|
||||||
|
index: 0, // index verification is not specified.
|
||||||
|
deposit_data: DepositData {
|
||||||
|
amount: 32_000_000_000, // 32 ETH (in Gwei)
|
||||||
|
timestamp: genesis_time - 1,
|
||||||
|
deposit_input: DepositInput {
|
||||||
|
pubkey: keypair.pk.clone(),
|
||||||
|
withdrawal_credentials: Hash256::zero(), // Withdrawal not possible.
|
||||||
|
proof_of_possession: create_proof_of_possession(&keypair),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let latest_eth1_data = Eth1Data {
|
||||||
|
deposit_root: Hash256::zero(),
|
||||||
|
block_hash: Hash256::zero(),
|
||||||
|
};
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
genesis_time,
|
||||||
|
initial_validator_deposits,
|
||||||
|
latest_eth1_data,
|
||||||
|
spec,
|
||||||
|
keypairs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> Result<BeaconState, BeaconStateError> {
|
||||||
|
BeaconState::genesis(
|
||||||
|
self.genesis_time,
|
||||||
|
self.initial_validator_deposits.clone(),
|
||||||
|
self.latest_eth1_data.clone(),
|
||||||
|
&self.spec,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn can_produce_genesis_block() {
|
||||||
|
let builder = BeaconStateTestBuilder::with_random_validators(2);
|
||||||
|
|
||||||
|
builder.build().unwrap();
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ pub mod attester_slashing;
|
|||||||
pub mod beacon_block;
|
pub mod beacon_block;
|
||||||
pub mod beacon_block_body;
|
pub mod beacon_block_body;
|
||||||
pub mod beacon_state;
|
pub mod beacon_state;
|
||||||
|
pub mod beacon_state_tests;
|
||||||
pub mod casper_slashing;
|
pub mod casper_slashing;
|
||||||
pub mod crosslink;
|
pub mod crosslink;
|
||||||
pub mod deposit;
|
pub mod deposit;
|
||||||
|
Loading…
Reference in New Issue
Block a user