Tidy, fix & extend BeaconState
impls.
This commit is contained in:
parent
d7f8c60f93
commit
25ae0f64c2
@ -2,21 +2,17 @@ use crate::test_utils::TestRandom;
|
|||||||
use crate::{
|
use crate::{
|
||||||
validator::StatusFlags, validator_registry::get_active_validator_indices, AggregatePublicKey,
|
validator::StatusFlags, validator_registry::get_active_validator_indices, AggregatePublicKey,
|
||||||
Attestation, AttestationData, Bitfield, ChainSpec, Crosslink, Epoch, Eth1Data, Eth1DataVote,
|
Attestation, AttestationData, Bitfield, ChainSpec, Crosslink, Epoch, Eth1Data, Eth1DataVote,
|
||||||
Fork, Hash256, PendingAttestation, PublicKey, Signature, Slot, Validator,
|
Fork, Hash256, PendingAttestation, Slot, Validator,
|
||||||
};
|
};
|
||||||
use bls::bls_verify_aggregate;
|
use bls::bls_verify_aggregate;
|
||||||
use honey_badger_split::SplitExt;
|
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::collections::HashMap;
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use vec_shuffle::shuffle;
|
use vec_shuffle::shuffle;
|
||||||
|
|
||||||
// TODO: define elsehwere.
|
// TODO: define elsehwere.
|
||||||
const DOMAIN_PROPOSAL: u64 = 2;
|
|
||||||
const DOMAIN_EXIT: u64 = 3;
|
|
||||||
const DOMAIN_RANDAO: u64 = 4;
|
|
||||||
const PHASE_0_CUSTODY_BIT: bool = false;
|
const PHASE_0_CUSTODY_BIT: bool = false;
|
||||||
const DOMAIN_ATTESTATION: u64 = 1;
|
const DOMAIN_ATTESTATION: u64 = 1;
|
||||||
|
|
||||||
@ -27,61 +23,11 @@ pub enum Error {
|
|||||||
CommitteesError(CommitteesError),
|
CommitteesError(CommitteesError),
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum BlockProcessingError {
|
|
||||||
DBError(String),
|
|
||||||
StateAlreadyTransitioned,
|
|
||||||
PresentSlotIsNone,
|
|
||||||
UnableToDecodeBlock,
|
|
||||||
MissingParentState(Hash256),
|
|
||||||
InvalidParentState(Hash256),
|
|
||||||
MissingBeaconBlock(Hash256),
|
|
||||||
InvalidBeaconBlock(Hash256),
|
|
||||||
MissingParentBlock(Hash256),
|
|
||||||
NoBlockProducer,
|
|
||||||
StateSlotMismatch,
|
|
||||||
BadBlockSignature,
|
|
||||||
BadRandaoSignature,
|
|
||||||
MaxProposerSlashingsExceeded,
|
|
||||||
BadProposerSlashing,
|
|
||||||
MaxAttestationsExceeded,
|
|
||||||
InvalidAttestation(AttestationValidationError),
|
|
||||||
NoBlockRoot,
|
|
||||||
MaxDepositsExceeded,
|
|
||||||
MaxExitsExceeded,
|
|
||||||
BadExit,
|
|
||||||
BadCustodyReseeds,
|
|
||||||
BadCustodyChallenges,
|
|
||||||
BadCustodyResponses,
|
|
||||||
CommitteesError(CommitteesError),
|
|
||||||
SlotProcessingError(SlotProcessingError),
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum EpochError {
|
|
||||||
UnableToDetermineProducer,
|
|
||||||
NoBlockRoots,
|
|
||||||
BaseRewardQuotientIsZero,
|
|
||||||
CommitteesError(CommitteesError),
|
|
||||||
AttestationParticipantsError(AttestationParticipantsError),
|
|
||||||
InclusionError(InclusionError),
|
|
||||||
WinningRootError(WinningRootError),
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum WinningRootError {
|
|
||||||
NoWinningRoot,
|
|
||||||
AttestationParticipantsError(AttestationParticipantsError),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum CommitteesError {
|
pub enum CommitteesError {
|
||||||
InvalidEpoch,
|
InvalidEpoch,
|
||||||
InsufficientNumberOfValidators,
|
InsufficientNumberOfValidators,
|
||||||
|
BadRandao,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -119,14 +65,6 @@ pub enum AttestationValidationError {
|
|||||||
AttestationParticipantsError(AttestationParticipantsError),
|
AttestationParticipantsError(AttestationParticipantsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct WinningRoot {
|
|
||||||
pub shard_block_root: Hash256,
|
|
||||||
pub attesting_validator_indices: Vec<usize>,
|
|
||||||
pub total_balance: u64,
|
|
||||||
pub total_attesting_balance: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! ensure {
|
macro_rules! ensure {
|
||||||
($condition: expr, $result: expr) => {
|
($condition: expr, $result: expr) => {
|
||||||
if !$condition {
|
if !$condition {
|
||||||
@ -146,9 +84,6 @@ macro_rules! safe_sub_assign {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custody will not be added to the specs until Phase 1 (Sharding Phase) so dummy class used.
|
|
||||||
type CustodyChallenge = usize;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Default, Serialize)]
|
#[derive(Debug, PartialEq, Clone, Default, Serialize)]
|
||||||
pub struct BeaconState {
|
pub struct BeaconState {
|
||||||
// Misc
|
// Misc
|
||||||
@ -179,6 +114,7 @@ pub struct BeaconState {
|
|||||||
// Recent state
|
// Recent state
|
||||||
pub latest_crosslinks: Vec<Crosslink>,
|
pub latest_crosslinks: Vec<Crosslink>,
|
||||||
pub latest_block_roots: Vec<Hash256>,
|
pub latest_block_roots: Vec<Hash256>,
|
||||||
|
pub latest_index_roots: Vec<Hash256>,
|
||||||
pub latest_penalized_balances: Vec<u64>,
|
pub latest_penalized_balances: Vec<u64>,
|
||||||
pub latest_attestations: Vec<PendingAttestation>,
|
pub latest_attestations: Vec<PendingAttestation>,
|
||||||
pub batched_block_roots: Vec<Hash256>,
|
pub batched_block_roots: Vec<Hash256>,
|
||||||
@ -217,7 +153,7 @@ impl BeaconState {
|
|||||||
///
|
///
|
||||||
/// TODO: this should probably be a method on `ChainSpec`.
|
/// TODO: this should probably be a method on `ChainSpec`.
|
||||||
///
|
///
|
||||||
/// Spec v0.1
|
/// Spec v0.2.0
|
||||||
pub fn get_epoch_committee_count(
|
pub fn get_epoch_committee_count(
|
||||||
&self,
|
&self,
|
||||||
active_validator_count: usize,
|
active_validator_count: usize,
|
||||||
@ -258,7 +194,7 @@ impl BeaconState {
|
|||||||
|
|
||||||
/// Return the number of committees in the previous epoch.
|
/// Return the number of committees in the previous epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.1
|
/// Spec v0.2.0
|
||||||
fn get_previous_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
fn get_previous_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
||||||
let previous_active_validators =
|
let previous_active_validators =
|
||||||
get_active_validator_indices(&self.validator_registry, self.previous_calculation_epoch);
|
get_active_validator_indices(&self.validator_registry, self.previous_calculation_epoch);
|
||||||
@ -267,7 +203,7 @@ impl BeaconState {
|
|||||||
|
|
||||||
/// Return the number of committees in the current epoch.
|
/// Return the number of committees in the current epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.1
|
/// Spec v0.2.0
|
||||||
pub fn get_current_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
pub fn get_current_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
||||||
let current_active_validators =
|
let current_active_validators =
|
||||||
get_active_validator_indices(&self.validator_registry, self.current_calculation_epoch);
|
get_active_validator_indices(&self.validator_registry, self.current_calculation_epoch);
|
||||||
@ -276,19 +212,45 @@ impl BeaconState {
|
|||||||
|
|
||||||
/// Return the number of committees in the next epoch.
|
/// Return the number of committees in the next epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.1
|
/// Spec v0.2.0
|
||||||
pub fn get_next_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
pub fn get_next_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
||||||
let current_active_validators =
|
let current_active_validators =
|
||||||
get_active_validator_indices(&self.validator_registry, self.current_epoch(spec) + 1);
|
get_active_validator_indices(&self.validator_registry, self.next_epoch(spec));
|
||||||
self.get_epoch_committee_count(current_active_validators.len(), spec)
|
self.get_epoch_committee_count(current_active_validators.len(), spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Option<Hash256> {
|
||||||
|
let current_epoch = self.current_epoch(spec);
|
||||||
|
|
||||||
|
let earliest_index_root = current_epoch - Epoch::from(spec.latest_index_roots_length)
|
||||||
|
+ Epoch::from(spec.entry_exit_delay)
|
||||||
|
+ 1;
|
||||||
|
let latest_index_root = current_epoch + spec.entry_exit_delay;
|
||||||
|
|
||||||
|
if (epoch <= earliest_index_root) & (epoch >= latest_index_root) {
|
||||||
|
Some(self.latest_index_roots[epoch.as_usize() % spec.latest_index_roots_length])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a seed for the given ``epoch``.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
|
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Option<Hash256> {
|
||||||
|
let mut input = self.get_randao_mix(epoch, spec)?.to_vec();
|
||||||
|
input.append(&mut self.get_active_index_root(epoch, spec)?.to_vec());
|
||||||
|
// TODO: ensure `Hash256::from(u64)` == `int_to_bytes32`.
|
||||||
|
input.append(&mut Hash256::from(epoch.as_u64()).to_vec());
|
||||||
|
Some(Hash256::from(&hash(&input[..])[..]))
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the list of ``(committee, shard)`` tuples for the ``slot``.
|
/// Return the list of ``(committee, shard)`` tuples for the ``slot``.
|
||||||
///
|
///
|
||||||
/// Note: There are two possible shufflings for crosslink committees for a
|
/// Note: There are two possible shufflings for crosslink committees for a
|
||||||
/// `slot` in the next epoch: with and without a `registry_change`
|
/// `slot` in the next epoch: with and without a `registry_change`
|
||||||
///
|
///
|
||||||
/// Spec v0.1
|
/// Spec v0.2.0
|
||||||
pub fn get_crosslink_committees_at_slot(
|
pub fn get_crosslink_committees_at_slot(
|
||||||
&self,
|
&self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
@ -302,36 +264,61 @@ impl BeaconState {
|
|||||||
} else {
|
} else {
|
||||||
current_epoch.saturating_sub(1_u64)
|
current_epoch.saturating_sub(1_u64)
|
||||||
};
|
};
|
||||||
let next_epoch = current_epoch + 1;
|
let next_epoch = self.next_epoch(spec);
|
||||||
|
|
||||||
ensure!(
|
let (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) =
|
||||||
(previous_epoch <= epoch) & (epoch < next_epoch),
|
if epoch == previous_epoch {
|
||||||
CommitteesError::InvalidEpoch
|
(
|
||||||
);
|
self.get_previous_epoch_committee_count(spec),
|
||||||
|
self.previous_epoch_seed,
|
||||||
|
self.previous_calculation_epoch,
|
||||||
|
self.previous_epoch_start_shard,
|
||||||
|
)
|
||||||
|
} else if epoch == current_epoch {
|
||||||
|
(
|
||||||
|
self.get_current_epoch_committee_count(spec),
|
||||||
|
self.current_epoch_seed,
|
||||||
|
self.current_calculation_epoch,
|
||||||
|
self.current_epoch_start_shard,
|
||||||
|
)
|
||||||
|
} else if epoch == next_epoch {
|
||||||
|
let current_committees_per_epoch = self.get_current_epoch_committee_count(spec);
|
||||||
|
let epochs_since_last_registry_update =
|
||||||
|
current_epoch - self.validator_registry_update_epoch;
|
||||||
|
let (seed, shuffling_start_shard) = if registry_change {
|
||||||
|
let next_seed = self
|
||||||
|
.generate_seed(next_epoch, spec)
|
||||||
|
.ok_or_else(|| CommitteesError::BadRandao)?;
|
||||||
|
(
|
||||||
|
next_seed,
|
||||||
|
(self.current_epoch_start_shard + current_committees_per_epoch)
|
||||||
|
% spec.shard_count,
|
||||||
|
)
|
||||||
|
} else if (epochs_since_last_registry_update > 1)
|
||||||
|
& epochs_since_last_registry_update.is_power_of_two()
|
||||||
|
{
|
||||||
|
let next_seed = self
|
||||||
|
.generate_seed(next_epoch, spec)
|
||||||
|
.ok_or_else(|| CommitteesError::BadRandao)?;
|
||||||
|
(next_seed, self.current_epoch_start_shard)
|
||||||
|
} else {
|
||||||
|
(self.current_epoch_seed, self.current_epoch_start_shard)
|
||||||
|
};
|
||||||
|
(
|
||||||
|
self.get_next_epoch_committee_count(spec),
|
||||||
|
seed,
|
||||||
|
next_epoch,
|
||||||
|
shuffling_start_shard,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
panic!("Epoch out-of-bounds.")
|
||||||
|
};
|
||||||
|
|
||||||
|
let shuffling = self.get_shuffling(seed, shuffling_epoch, spec);
|
||||||
let offset = slot.as_u64() % spec.epoch_length;
|
let offset = slot.as_u64() % spec.epoch_length;
|
||||||
|
let committees_per_slot = committees_per_epoch / spec.epoch_length;
|
||||||
let (committees_per_slot, shuffling, slot_start_shard) = if epoch < current_epoch {
|
let slot_start_shard =
|
||||||
let committees_per_slot = self.get_previous_epoch_committee_count(spec);
|
(shuffling_start_shard + committees_per_slot * offset) % spec.shard_count;
|
||||||
let shuffling = self.get_shuffling(
|
|
||||||
self.previous_epoch_seed,
|
|
||||||
self.previous_calculation_epoch,
|
|
||||||
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(spec);
|
|
||||||
let shuffling = self.get_shuffling(
|
|
||||||
self.current_epoch_seed,
|
|
||||||
self.current_calculation_epoch,
|
|
||||||
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 mut crosslinks_at_slot = vec![];
|
let mut crosslinks_at_slot = vec![];
|
||||||
for i in 0..committees_per_slot {
|
for i in 0..committees_per_slot {
|
||||||
@ -361,12 +348,19 @@ impl BeaconState {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An entry or exit triggered in the ``epoch`` given by the input takes effect at
|
||||||
|
/// the epoch given by the output.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
pub fn get_entry_exit_effect_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch {
|
pub fn get_entry_exit_effect_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch {
|
||||||
epoch + 1 + spec.entry_exit_delay
|
epoch + 1 + spec.entry_exit_delay
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the beacon proposer index for the `slot`.
|
/// 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.
|
/// If the state does not contain an index for a beacon proposer at the requested `slot`, then `None` is returned.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
pub fn get_beacon_proposer_index(
|
pub fn get_beacon_proposer_index(
|
||||||
&self,
|
&self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
@ -380,7 +374,7 @@ impl BeaconState {
|
|||||||
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(CommitteesError::InsufficientNumberOfValidators)?;
|
||||||
// NOTE: next index will not panic as we have already returned if this is the case
|
// NOTE: next index will not panic as we have already returned if this is the case.
|
||||||
Ok(first_committee[index])
|
Ok(first_committee[index])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -388,7 +382,7 @@ impl BeaconState {
|
|||||||
/// Process the penalties and prepare the validators who are eligible to withdrawal.
|
/// Process the penalties and prepare the validators who are eligible to withdrawal.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn process_penalties_and_exits(&mut self, spec: &ChainSpec) {
|
pub fn process_penalties_and_exits(&mut self, spec: &ChainSpec) {
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch(spec);
|
||||||
let active_validator_indices =
|
let active_validator_indices =
|
||||||
get_active_validator_indices(&self.validator_registry, current_epoch);
|
get_active_validator_indices(&self.validator_registry, current_epoch);
|
||||||
@ -444,7 +438,7 @@ impl BeaconState {
|
|||||||
/// Returns `None` if the epoch is out-of-bounds of `self.latest_randao_mixes`.
|
/// Returns `None` if the epoch is out-of-bounds of `self.latest_randao_mixes`.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn get_randao_mix(&mut self, epoch: Epoch, spec: &ChainSpec) -> Option<&Hash256> {
|
pub fn get_randao_mix(&self, epoch: Epoch, spec: &ChainSpec) -> Option<&Hash256> {
|
||||||
self.latest_randao_mixes
|
self.latest_randao_mixes
|
||||||
.get(epoch.as_usize() % spec.latest_randao_mixes_length)
|
.get(epoch.as_usize() % spec.latest_randao_mixes_length)
|
||||||
}
|
}
|
||||||
@ -452,7 +446,7 @@ impl BeaconState {
|
|||||||
/// Update validator registry, activating/exiting validators if possible.
|
/// Update validator registry, activating/exiting validators if possible.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn update_validator_registry(&mut self, spec: &ChainSpec) {
|
pub fn update_validator_registry(&mut self, spec: &ChainSpec) {
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch(spec);
|
||||||
let active_validator_indices =
|
let active_validator_indices =
|
||||||
get_active_validator_indices(&self.validator_registry, current_epoch);
|
get_active_validator_indices(&self.validator_registry, current_epoch);
|
||||||
@ -500,7 +494,12 @@ impl BeaconState {
|
|||||||
/// Activate the validator of the given ``index``.
|
/// Activate the validator of the given ``index``.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn activate_validator(&mut self, validator_index: usize, is_genesis: bool, spec: &ChainSpec) {
|
pub fn activate_validator(
|
||||||
|
&mut self,
|
||||||
|
validator_index: usize,
|
||||||
|
is_genesis: bool,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) {
|
||||||
let current_epoch = self.current_epoch(spec);
|
let current_epoch = self.current_epoch(spec);
|
||||||
|
|
||||||
self.validator_registry[validator_index].activation_epoch = if is_genesis {
|
self.validator_registry[validator_index].activation_epoch = if is_genesis {
|
||||||
@ -513,7 +512,7 @@ impl BeaconState {
|
|||||||
/// Initiate an exit for the validator of the given `index`.
|
/// Initiate an exit for the validator of the given `index`.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn initiate_validator_exit(&mut self, validator_index: usize, spec: &ChainSpec) {
|
pub fn initiate_validator_exit(&mut self, validator_index: usize) {
|
||||||
// TODO: the spec does an `|=` here, ensure this isn't buggy.
|
// TODO: the spec does an `|=` here, ensure this isn't buggy.
|
||||||
self.validator_registry[validator_index].status_flags = Some(StatusFlags::InitiatedExit);
|
self.validator_registry[validator_index].status_flags = Some(StatusFlags::InitiatedExit);
|
||||||
}
|
}
|
||||||
@ -569,7 +568,7 @@ impl BeaconState {
|
|||||||
/// Initiate an exit for the validator of the given `index`.
|
/// Initiate an exit for the validator of the given `index`.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn prepare_validator_for_withdrawal(&mut self, validator_index: usize) {
|
pub fn prepare_validator_for_withdrawal(&mut self, validator_index: usize) {
|
||||||
//TODO: we're not ANDing here, we're setting. Potentially wrong.
|
//TODO: we're not ANDing here, we're setting. Potentially wrong.
|
||||||
self.validator_registry[validator_index].status_flags = Some(StatusFlags::Withdrawable);
|
self.validator_registry[validator_index].status_flags = Some(StatusFlags::Withdrawable);
|
||||||
}
|
}
|
||||||
@ -578,7 +577,7 @@ impl BeaconState {
|
|||||||
/// ``EJECTION_BALANCE``.
|
/// ``EJECTION_BALANCE``.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn process_ejections(&mut self, spec: &ChainSpec) {
|
pub fn process_ejections(&mut self, spec: &ChainSpec) {
|
||||||
for validator_index in
|
for validator_index in
|
||||||
get_active_validator_indices(&self.validator_registry, self.current_epoch(spec))
|
get_active_validator_indices(&self.validator_registry, self.current_epoch(spec))
|
||||||
{
|
{
|
||||||
@ -593,7 +592,7 @@ impl BeaconState {
|
|||||||
/// Note: this is defined "inline" in the spec, not as a helper function.
|
/// Note: this is defined "inline" in the spec, not as a helper function.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn inactivity_penalty(
|
pub fn inactivity_penalty(
|
||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
epochs_since_finality: u64,
|
epochs_since_finality: u64,
|
||||||
@ -611,7 +610,7 @@ impl BeaconState {
|
|||||||
/// Note: In the spec this is defined "inline", not as a helper function.
|
/// Note: In the spec this is defined "inline", not as a helper function.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn inclusion_distance(
|
pub fn inclusion_distance(
|
||||||
&self,
|
&self,
|
||||||
attestations: &[&PendingAttestation],
|
attestations: &[&PendingAttestation],
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
@ -627,7 +626,7 @@ impl BeaconState {
|
|||||||
/// Note: In the spec this is defined "inline", not as a helper function.
|
/// Note: In the spec this is defined "inline", not as a helper function.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn inclusion_slot(
|
pub fn inclusion_slot(
|
||||||
&self,
|
&self,
|
||||||
attestations: &[&PendingAttestation],
|
attestations: &[&PendingAttestation],
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
@ -675,7 +674,7 @@ impl BeaconState {
|
|||||||
/// Note: In the spec this is defined "inline", not as a helper function.
|
/// Note: In the spec this is defined "inline", not as a helper function.
|
||||||
///
|
///
|
||||||
/// Spec v0.2.0
|
/// Spec v0.2.0
|
||||||
fn base_reward(
|
pub fn base_reward(
|
||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
base_reward_quotient: u64,
|
base_reward_quotient: u64,
|
||||||
@ -711,86 +710,6 @@ impl BeaconState {
|
|||||||
.get(slot.as_usize() % spec.latest_block_roots_length)
|
.get(slot.as_usize() % spec.latest_block_roots_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn winning_root(
|
|
||||||
&self,
|
|
||||||
shard: u64,
|
|
||||||
current_epoch_attestations: &[&PendingAttestation],
|
|
||||||
previous_epoch_attestations: &[&PendingAttestation],
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> Result<WinningRoot, WinningRootError> {
|
|
||||||
let mut attestations = current_epoch_attestations.to_vec();
|
|
||||||
attestations.append(&mut previous_epoch_attestations.to_vec());
|
|
||||||
|
|
||||||
let mut candidates: HashMap<Hash256, WinningRoot> = HashMap::new();
|
|
||||||
|
|
||||||
let mut highest_seen_balance = 0;
|
|
||||||
|
|
||||||
for a in &attestations {
|
|
||||||
if a.data.shard != shard {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let shard_block_root = &a.data.shard_block_root;
|
|
||||||
|
|
||||||
if candidates.contains_key(shard_block_root) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: `cargo fmt` makes this rather ugly; tidy up.
|
|
||||||
let attesting_validator_indices = attestations.iter().try_fold::<_, _, Result<
|
|
||||||
_,
|
|
||||||
AttestationParticipantsError,
|
|
||||||
>>(
|
|
||||||
vec![],
|
|
||||||
|mut acc, a| {
|
|
||||||
if (a.data.shard == shard) && (a.data.shard_block_root == *shard_block_root) {
|
|
||||||
acc.append(&mut self.get_attestation_participants(
|
|
||||||
&a.data,
|
|
||||||
&a.aggregation_bitfield,
|
|
||||||
spec,
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
Ok(acc)
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let total_balance: u64 = attesting_validator_indices
|
|
||||||
.iter()
|
|
||||||
.fold(0, |acc, i| acc + self.get_effective_balance(*i, spec));
|
|
||||||
|
|
||||||
let total_attesting_balance: u64 = attesting_validator_indices
|
|
||||||
.iter()
|
|
||||||
.fold(0, |acc, i| acc + self.get_effective_balance(*i, spec));
|
|
||||||
|
|
||||||
if total_attesting_balance > highest_seen_balance {
|
|
||||||
highest_seen_balance = total_attesting_balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
let candidate_root = WinningRoot {
|
|
||||||
shard_block_root: shard_block_root.clone(),
|
|
||||||
attesting_validator_indices,
|
|
||||||
total_attesting_balance,
|
|
||||||
total_balance,
|
|
||||||
};
|
|
||||||
|
|
||||||
candidates.insert(*shard_block_root, candidate_root);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(candidates
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(_hash, candidate)| {
|
|
||||||
if candidate.total_attesting_balance == highest_seen_balance {
|
|
||||||
Some(candidate)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.min_by_key(|candidate| candidate.shard_block_root)
|
|
||||||
.ok_or_else(|| WinningRootError::NoWinningRoot)?
|
|
||||||
// TODO: avoid clone.
|
|
||||||
.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_attestation_participants_union(
|
pub fn get_attestation_participants_union(
|
||||||
&self,
|
&self,
|
||||||
attestations: &[&PendingAttestation],
|
attestations: &[&PendingAttestation],
|
||||||
@ -812,11 +731,16 @@ impl BeaconState {
|
|||||||
Ok(all_participants)
|
Ok(all_participants)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: analyse for efficiency improvments. This implementation is naive.
|
/// Return the participant indices at for the ``attestation_data`` and ``bitfield``.
|
||||||
|
///
|
||||||
|
/// In effect, this converts the "committee indices" on the bitfield into "validator indices"
|
||||||
|
/// for self.validator_registy.
|
||||||
|
///
|
||||||
|
/// Spec v0.2.0
|
||||||
pub fn get_attestation_participants(
|
pub fn get_attestation_participants(
|
||||||
&self,
|
&self,
|
||||||
attestation_data: &AttestationData,
|
attestation_data: &AttestationData,
|
||||||
aggregation_bitfield: &Bitfield,
|
bitfield: &Bitfield,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<Vec<usize>, AttestationParticipantsError> {
|
) -> Result<Vec<usize>, AttestationParticipantsError> {
|
||||||
let crosslink_committees =
|
let crosslink_committees =
|
||||||
@ -829,13 +753,12 @@ impl BeaconState {
|
|||||||
let (crosslink_committee, _shard) = &crosslink_committees[committee_index];
|
let (crosslink_committee, _shard) = &crosslink_committees[committee_index];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: that bitfield length is valid.
|
* TODO: verify bitfield length is valid.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let mut participants = vec![];
|
let mut participants = vec![];
|
||||||
for (i, validator_index) in crosslink_committee.iter().enumerate() {
|
for (i, validator_index) in crosslink_committee.iter().enumerate() {
|
||||||
if aggregation_bitfield.get(i).unwrap() {
|
if bitfield.get(i).unwrap() {
|
||||||
participants.push(*validator_index);
|
participants.push(*validator_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -939,32 +862,17 @@ impl BeaconState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merkle_root(_input: &[Hash256]) -> Hash256 {
|
|
||||||
Hash256::zero()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_domain(_fork: &Fork, _epoch: Epoch, _domain_type: u64) -> u64 {
|
fn get_domain(_fork: &Fork, _epoch: Epoch, _domain_type: u64) -> u64 {
|
||||||
// TODO: stubbed out.
|
// TODO: stubbed out.
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bls_verify(pubkey: &PublicKey, message: &[u8], signature: &Signature, _domain: u64) -> bool {
|
|
||||||
// TODO: add domain
|
|
||||||
signature.verify(message, pubkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AttestationParticipantsError> for AttestationValidationError {
|
impl From<AttestationParticipantsError> for AttestationValidationError {
|
||||||
fn from(e: AttestationParticipantsError) -> AttestationValidationError {
|
fn from(e: AttestationParticipantsError) -> AttestationValidationError {
|
||||||
AttestationValidationError::AttestationParticipantsError(e)
|
AttestationValidationError::AttestationParticipantsError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AttestationParticipantsError> for WinningRootError {
|
|
||||||
fn from(e: AttestationParticipantsError) -> WinningRootError {
|
|
||||||
WinningRootError::AttestationParticipantsError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CommitteesError> for AttestationParticipantsError {
|
impl From<CommitteesError> for AttestationParticipantsError {
|
||||||
fn from(e: CommitteesError) -> AttestationParticipantsError {
|
fn from(e: CommitteesError) -> AttestationParticipantsError {
|
||||||
AttestationParticipantsError::CommitteesError(e)
|
AttestationParticipantsError::CommitteesError(e)
|
||||||
@ -972,23 +880,6 @@ impl From<CommitteesError> for AttestationParticipantsError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
impl From<AttestationValidationError> for BlockProcessingError {
|
|
||||||
fn from(e: AttestationValidationError) -> BlockProcessingError {
|
|
||||||
BlockProcessingError::InvalidAttestation(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CommitteesError> for BlockProcessingError {
|
|
||||||
fn from(e: CommitteesError) -> BlockProcessingError {
|
|
||||||
BlockProcessingError::CommitteesError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SlotProcessingError> for BlockProcessingError {
|
|
||||||
fn from(e: SlotProcessingError) -> BlockProcessingError {
|
|
||||||
BlockProcessingError::SlotProcessingError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CommitteesError> for SlotProcessingError {
|
impl From<CommitteesError> for SlotProcessingError {
|
||||||
fn from(e: CommitteesError) -> SlotProcessingError {
|
fn from(e: CommitteesError) -> SlotProcessingError {
|
||||||
@ -1009,26 +900,6 @@ impl From<AttestationParticipantsError> for InclusionError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
impl From<InclusionError> for EpochError {
|
|
||||||
fn from(e: InclusionError) -> EpochError {
|
|
||||||
EpochError::InclusionError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CommitteesError> for EpochError {
|
|
||||||
fn from(e: CommitteesError) -> EpochError {
|
|
||||||
EpochError::CommitteesError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AttestationParticipantsError> for EpochError {
|
|
||||||
fn from(e: AttestationParticipantsError) -> EpochError {
|
|
||||||
EpochError::AttestationParticipantsError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
impl From<CommitteesError> for Error {
|
||||||
fn from(e: CommitteesError) -> Error {
|
fn from(e: CommitteesError) -> Error {
|
||||||
Error::CommitteesError(e)
|
Error::CommitteesError(e)
|
||||||
@ -1056,6 +927,7 @@ impl Encodable for BeaconState {
|
|||||||
s.append(&self.finalized_epoch);
|
s.append(&self.finalized_epoch);
|
||||||
s.append(&self.latest_crosslinks);
|
s.append(&self.latest_crosslinks);
|
||||||
s.append(&self.latest_block_roots);
|
s.append(&self.latest_block_roots);
|
||||||
|
s.append(&self.latest_index_roots);
|
||||||
s.append(&self.latest_penalized_balances);
|
s.append(&self.latest_penalized_balances);
|
||||||
s.append(&self.latest_attestations);
|
s.append(&self.latest_attestations);
|
||||||
s.append(&self.batched_block_roots);
|
s.append(&self.batched_block_roots);
|
||||||
@ -1085,6 +957,7 @@ impl Decodable for BeaconState {
|
|||||||
let (finalized_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
let (finalized_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (latest_crosslinks, i) = <_>::ssz_decode(bytes, i)?;
|
let (latest_crosslinks, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (latest_block_roots, i) = <_>::ssz_decode(bytes, i)?;
|
let (latest_block_roots, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
|
let (latest_index_roots, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (latest_penalized_balances, i) = <_>::ssz_decode(bytes, i)?;
|
let (latest_penalized_balances, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?;
|
let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
let (batched_block_roots, i) = <_>::ssz_decode(bytes, i)?;
|
let (batched_block_roots, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
@ -1112,6 +985,7 @@ impl Decodable for BeaconState {
|
|||||||
finalized_epoch,
|
finalized_epoch,
|
||||||
latest_crosslinks,
|
latest_crosslinks,
|
||||||
latest_block_roots,
|
latest_block_roots,
|
||||||
|
latest_index_roots,
|
||||||
latest_penalized_balances,
|
latest_penalized_balances,
|
||||||
latest_attestations,
|
latest_attestations,
|
||||||
batched_block_roots,
|
batched_block_roots,
|
||||||
@ -1145,6 +1019,7 @@ impl TreeHash for BeaconState {
|
|||||||
result.append(&mut self.finalized_epoch.hash_tree_root());
|
result.append(&mut self.finalized_epoch.hash_tree_root());
|
||||||
result.append(&mut self.latest_crosslinks.hash_tree_root());
|
result.append(&mut self.latest_crosslinks.hash_tree_root());
|
||||||
result.append(&mut self.latest_block_roots.hash_tree_root());
|
result.append(&mut self.latest_block_roots.hash_tree_root());
|
||||||
|
result.append(&mut self.latest_index_roots.hash_tree_root());
|
||||||
result.append(&mut self.latest_penalized_balances.hash_tree_root());
|
result.append(&mut self.latest_penalized_balances.hash_tree_root());
|
||||||
result.append(&mut self.latest_attestations.hash_tree_root());
|
result.append(&mut self.latest_attestations.hash_tree_root());
|
||||||
result.append(&mut self.batched_block_roots.hash_tree_root());
|
result.append(&mut self.batched_block_roots.hash_tree_root());
|
||||||
@ -1176,6 +1051,7 @@ impl<T: RngCore> TestRandom<T> for BeaconState {
|
|||||||
finalized_epoch: <_>::random_for_test(rng),
|
finalized_epoch: <_>::random_for_test(rng),
|
||||||
latest_crosslinks: <_>::random_for_test(rng),
|
latest_crosslinks: <_>::random_for_test(rng),
|
||||||
latest_block_roots: <_>::random_for_test(rng),
|
latest_block_roots: <_>::random_for_test(rng),
|
||||||
|
latest_index_roots: <_>::random_for_test(rng),
|
||||||
latest_penalized_balances: <_>::random_for_test(rng),
|
latest_penalized_balances: <_>::random_for_test(rng),
|
||||||
latest_attestations: <_>::random_for_test(rng),
|
latest_attestations: <_>::random_for_test(rng),
|
||||||
batched_block_roots: <_>::random_for_test(rng),
|
batched_block_roots: <_>::random_for_test(rng),
|
||||||
|
Loading…
Reference in New Issue
Block a user