Merge remote-tracking branch 'origin/master' into spec-0.6

This commit is contained in:
Michael Sproul
2019-05-14 12:09:59 +10:00
161 changed files with 1785 additions and 4645 deletions

View File

@@ -33,8 +33,8 @@ impl std::ops::AddAssign for Delta {
/// Apply attester and proposer rewards.
///
/// Spec v0.6.1
pub fn process_rewards_and_penalties(
state: &mut BeaconState,
pub fn process_rewards_and_penalties<T: EthSpec>(
state: &mut BeaconState<T>,
validator_statuses: &mut ValidatorStatuses,
winning_root_for_shards: &WinningRootHashSet,
spec: &ChainSpec,
@@ -75,9 +75,9 @@ pub fn process_rewards_and_penalties(
/// For each attesting validator, reward the proposer who was first to include their attestation.
///
/// Spec v0.6.1
fn get_proposer_deltas(
fn get_proposer_deltas<T: EthSpec>(
deltas: &mut Vec<Delta>,
state: &BeaconState,
state: &BeaconState<T>,
validator_statuses: &mut ValidatorStatuses,
winning_root_for_shards: &WinningRootHashSet,
spec: &ChainSpec,
@@ -112,9 +112,9 @@ fn get_proposer_deltas(
/// Apply rewards for participation in attestations during the previous epoch.
///
/// Spec v0.6.1
fn get_attestation_deltas(
fn get_attestation_deltas<T: EthSpec>(
deltas: &mut Vec<Delta>,
state: &BeaconState,
state: &BeaconState<T>,
validator_statuses: &ValidatorStatuses,
spec: &ChainSpec,
) -> Result<(), Error> {
@@ -225,9 +225,9 @@ fn get_attestation_delta(
/// Calculate the deltas based upon the winning roots for attestations during the previous epoch.
///
/// Spec v0.6.1
fn get_crosslink_deltas(
fn get_crosslink_deltas<T: EthSpec>(
deltas: &mut Vec<Delta>,
state: &BeaconState,
state: &BeaconState<T>,
validator_statuses: &ValidatorStatuses,
spec: &ChainSpec,
) -> Result<(), Error> {
@@ -259,8 +259,8 @@ fn get_crosslink_deltas(
/// Returns the base reward for some validator.
///
/// Spec v0.6.1
fn get_base_reward(
state: &BeaconState,
fn get_base_reward<T: EthSpec>(
state: &BeaconState<T>,
index: usize,
// Should be == get_total_active_balance(state, spec)
total_active_balance: u64,

View File

@@ -0,0 +1,38 @@
use crate::common::verify_bitfield_length;
use types::*;
/// Returns validator indices which participated in the attestation.
///
/// Spec v0.5.1
pub fn get_attestation_participants<T: EthSpec>(
state: &BeaconState<T>,
attestation_data: &AttestationData,
bitfield: &Bitfield,
spec: &ChainSpec,
) -> Result<Vec<usize>, BeaconStateError> {
let epoch = attestation_data.slot.epoch(spec.slots_per_epoch);
let crosslink_committee =
state.get_crosslink_committee_for_shard(epoch, attestation_data.shard, spec)?;
if crosslink_committee.slot != attestation_data.slot {
return Err(BeaconStateError::NoCommitteeForShard);
}
let committee = &crosslink_committee.committee;
if !verify_bitfield_length(&bitfield, committee.len()) {
return Err(BeaconStateError::InvalidBitfield);
}
let mut participants = Vec::with_capacity(committee.len());
for (i, validator_index) in committee.iter().enumerate() {
match bitfield.get(i) {
Ok(bit) if bit => participants.push(*validator_index),
_ => {}
}
}
participants.shrink_to_fit();
Ok(participants)
}

View File

@@ -4,8 +4,8 @@ use types::*;
/// Returns validator indices which participated in the attestation.
///
/// Spec v0.6.1
pub fn get_attesting_indices_unsorted(
state: &BeaconState,
pub fn get_attesting_indices_unsorted<T: EthSpec>(
state: &BeaconState<T>,
attestation_data: &AttestationData,
bitfield: &Bitfield,
spec: &ChainSpec,

View File

@@ -5,8 +5,8 @@ use types::*;
/// slot.
///
/// Spec v0.5.1
pub fn inclusion_distance(
state: &BeaconState,
pub fn inclusion_distance<T: EthSpec>(
state: &BeaconState<T>,
attestations: &[&PendingAttestation],
validator_index: usize,
spec: &ChainSpec,
@@ -20,8 +20,8 @@ pub fn inclusion_distance(
/// Returns the slot of the earliest included attestation for some validator.
///
/// Spec v0.5.1
pub fn inclusion_slot(
state: &BeaconState,
pub fn inclusion_slot<T: EthSpec>(
state: &BeaconState<T>,
attestations: &[&PendingAttestation],
validator_index: usize,
spec: &ChainSpec,
@@ -36,8 +36,8 @@ pub fn inclusion_slot(
/// Finds the earliest included attestation for some validator.
///
/// Spec v0.5.1
fn earliest_included_attestation(
state: &BeaconState,
fn earliest_included_attestation<T: EthSpec>(
state: &BeaconState<T>,
attestations: &[&PendingAttestation],
validator_index: usize,
spec: &ChainSpec,

View File

@@ -5,7 +5,10 @@ use types::{BeaconStateError as Error, *};
/// ``EJECTION_BALANCE``.
///
/// Spec v0.5.1
pub fn process_ejections(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
pub fn process_ejections<T: EthSpec>(
state: &mut BeaconState<T>,
spec: &ChainSpec,
) -> Result<(), Error> {
// There is an awkward double (triple?) loop here because we can't loop across the borrowed
// active validator indices and mutate state in the one loop.
let exitable: Vec<usize> = state

View File

@@ -3,7 +3,7 @@ use types::*;
/// Process the exit queue.
///
/// Spec v0.5.1
pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
pub fn process_exit_queue<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
let current_epoch = state.current_epoch(spec);
let eligible = |index: usize| {
@@ -34,8 +34,8 @@ pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
/// Initiate an exit for the validator of the given `index`.
///
/// Spec v0.5.1
fn prepare_validator_for_withdrawal(
state: &mut BeaconState,
fn prepare_validator_for_withdrawal<T: EthSpec>(
state: &mut BeaconState<T>,
validator_index: usize,
spec: &ChainSpec,
) {

View File

@@ -3,20 +3,20 @@ use types::{BeaconStateError as Error, *};
/// Process slashings.
///
/// Spec v0.5.1
pub fn process_slashings(
state: &mut BeaconState,
pub fn process_slashings<T: EthSpec>(
state: &mut BeaconState<T>,
current_total_balance: u64,
spec: &ChainSpec,
) -> Result<(), Error> {
let current_epoch = state.current_epoch(spec);
let total_at_start = state.get_slashed_balance(current_epoch + 1, spec)?;
let total_at_end = state.get_slashed_balance(current_epoch, spec)?;
let total_at_start = state.get_slashed_balance(current_epoch + 1)?;
let total_at_end = state.get_slashed_balance(current_epoch)?;
let total_penalities = total_at_end - total_at_start;
for (index, validator) in state.validator_registry.iter().enumerate() {
let should_penalize = current_epoch.as_usize()
== validator.withdrawable_epoch.as_usize() - spec.latest_slashed_exit_length / 2;
== validator.withdrawable_epoch.as_usize() - T::LatestSlashedExitLength::to_usize() / 2;
if validator.slashed && should_penalize {
let effective_balance = state.get_effective_balance(index, spec)?;

View File

@@ -6,8 +6,8 @@ use types::*;
/// Peforms a validator registry update, if required.
///
/// Spec v0.6.1
pub fn process_registry_updates(
state: &mut BeaconState,
pub fn process_registry_updates<T: EthSpec>(
state: &mut BeaconState<T>,
current_total_balance: u64,
spec: &ChainSpec,
) -> Result<(), Error> {

View File

@@ -8,9 +8,10 @@ use types::*;
fn runs_without_error() {
Builder::from_env(Env::default().default_filter_or("error")).init();
let spec = ChainSpec::few_validators();
let spec = FewValidatorsEthSpec::spec();
let mut builder = TestingBeaconStateBuilder::from_deterministic_keypairs(8, &spec);
let mut builder: TestingBeaconStateBuilder<FewValidatorsEthSpec> =
TestingBeaconStateBuilder::from_deterministic_keypairs(8, &spec);
let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
builder.teleport_to_slot(target_slot, &spec);

View File

@@ -0,0 +1,150 @@
use super::super::common::exit_validator;
use super::Error;
use types::*;
/// Peforms a validator registry update, if required.
///
/// Spec v0.5.1
pub fn update_registry_and_shuffling_data<T: EthSpec>(
state: &mut BeaconState<T>,
current_total_balance: u64,
spec: &ChainSpec,
) -> Result<(), Error> {
// First set previous shuffling data to current shuffling data.
state.previous_shuffling_epoch = state.current_shuffling_epoch;
state.previous_shuffling_start_shard = state.previous_shuffling_start_shard;
state.previous_shuffling_seed = state.previous_shuffling_seed;
let current_epoch = state.current_epoch(spec);
let next_epoch = current_epoch + 1;
// Check we should update, and if so, update.
if should_update_validator_registry(state, spec)? {
update_validator_registry(state, current_total_balance, spec)?;
// If we update the registry, update the shuffling data and shards as well.
state.current_shuffling_epoch = next_epoch;
state.current_shuffling_start_shard = {
let active_validators =
state.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?;
let epoch_committee_count = spec.get_epoch_committee_count(active_validators.len());
(state.current_shuffling_start_shard + epoch_committee_count) % spec.shard_count
};
state.current_shuffling_seed = state.generate_seed(state.current_shuffling_epoch, spec)?;
} else {
// If processing at least on crosslink keeps failing, the reshuffle every power of two, but
// don't update the current_shuffling_start_shard.
let epochs_since_last_update = current_epoch - state.validator_registry_update_epoch;
if epochs_since_last_update > 1 && epochs_since_last_update.is_power_of_two() {
state.current_shuffling_epoch = next_epoch;
state.current_shuffling_seed =
state.generate_seed(state.current_shuffling_epoch, spec)?;
}
}
Ok(())
}
/// Returns `true` if the validator registry should be updated during an epoch processing.
///
/// Spec v0.5.1
pub fn should_update_validator_registry<T: EthSpec>(
state: &BeaconState<T>,
spec: &ChainSpec,
) -> Result<bool, BeaconStateError> {
if state.finalized_epoch <= state.validator_registry_update_epoch {
return Ok(false);
}
let num_active_validators = state
.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?
.len();
let current_epoch_committee_count = spec.get_epoch_committee_count(num_active_validators);
for shard in (0..current_epoch_committee_count)
.map(|i| (state.current_shuffling_start_shard + i as u64) % spec.shard_count)
{
if state.latest_crosslinks[shard as usize].epoch <= state.validator_registry_update_epoch {
return Ok(false);
}
}
Ok(true)
}
/// Update validator registry, activating/exiting validators if possible.
///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
///
/// Spec v0.5.1
pub fn update_validator_registry<T: EthSpec>(
state: &mut BeaconState<T>,
current_total_balance: u64,
spec: &ChainSpec,
) -> Result<(), Error> {
let current_epoch = state.current_epoch(spec);
let max_balance_churn = std::cmp::max(
spec.max_deposit_amount,
current_total_balance / (2 * spec.max_balance_churn_quotient),
);
// Activate validators within the allowable balance churn.
let mut balance_churn = 0;
for index in 0..state.validator_registry.len() {
let not_activated =
state.validator_registry[index].activation_epoch == spec.far_future_epoch;
let has_enough_balance = state.validator_balances[index] >= spec.max_deposit_amount;
if not_activated && has_enough_balance {
// Check the balance churn would be within the allowance.
balance_churn += state.get_effective_balance(index, spec)?;
if balance_churn > max_balance_churn {
break;
}
activate_validator(state, index, false, spec);
}
}
// Exit validators within the allowable balance churn.
let mut balance_churn = 0;
for index in 0..state.validator_registry.len() {
let not_exited = state.validator_registry[index].exit_epoch == spec.far_future_epoch;
let has_initiated_exit = state.validator_registry[index].initiated_exit;
if not_exited && has_initiated_exit {
// Check the balance churn would be within the allowance.
balance_churn += state.get_effective_balance(index, spec)?;
if balance_churn > max_balance_churn {
break;
}
exit_validator(state, index, spec)?;
}
}
state.validator_registry_update_epoch = current_epoch;
Ok(())
}
/// Activate the validator of the given ``index``.
///
/// Spec v0.5.1
pub fn activate_validator<T: EthSpec>(
state: &mut BeaconState<T>,
validator_index: usize,
is_genesis: bool,
spec: &ChainSpec,
) {
let current_epoch = state.current_epoch(spec);
state.validator_registry[validator_index].activation_epoch = if is_genesis {
spec.genesis_epoch
} else {
state.get_delayed_activation_exit_epoch(current_epoch, spec)
}
}

View File

@@ -163,7 +163,10 @@ impl ValidatorStatuses {
/// - Total balances for the current and previous epochs.
///
/// Spec v0.6.1
pub fn new(state: &BeaconState, spec: &ChainSpec) -> Result<Self, BeaconStateError> {
pub fn new<T: EthSpec>(
state: &BeaconState<T>,
spec: &ChainSpec,
) -> Result<Self, BeaconStateError> {
let mut statuses = Vec::with_capacity(state.validator_registry.len());
let mut total_balances = TotalBalances::default();
@@ -200,9 +203,9 @@ impl ValidatorStatuses {
/// `total_balances` fields.
///
/// Spec v0.6.1
pub fn process_attestations(
pub fn process_attestations<T: EthSpec>(
&mut self,
state: &BeaconState,
state: &BeaconState<T>,
spec: &ChainSpec,
) -> Result<(), BeaconStateError> {
for a in state
@@ -286,9 +289,9 @@ impl ValidatorStatuses {
/// "winning" shard block root for the previous epoch.
///
/// Spec v0.6.1
pub fn process_winning_roots(
pub fn process_winning_roots<T: EthSpec>(
&mut self,
state: &BeaconState,
state: &BeaconState<T>,
winning_roots: &WinningRootHashSet,
spec: &ChainSpec,
) -> Result<(), BeaconStateError> {
@@ -329,14 +332,14 @@ fn is_from_epoch(a: &PendingAttestation, epoch: Epoch) -> bool {
/// beacon block in the given `epoch`.
///
/// Spec v0.6.1
fn target_matches_epoch_start_block(
fn target_matches_epoch_start_block<T: EthSpec>(
a: &PendingAttestation,
state: &BeaconState,
state: &BeaconState<T>,
epoch: Epoch,
spec: &ChainSpec,
) -> Result<bool, BeaconStateError> {
let slot = epoch.start_slot(spec.slots_per_epoch);
let state_boundary_root = *state.get_block_root(slot, spec)?;
let state_boundary_root = *state.get_block_root(slot)?;
Ok(a.data.target_root == state_boundary_root)
}
@@ -345,13 +348,13 @@ fn target_matches_epoch_start_block(
/// the current slot of the `PendingAttestation`.
///
/// Spec v0.6.1
fn has_common_beacon_block_root(
fn has_common_beacon_block_root<T: EthSpec>(
a: &PendingAttestation,
state: &BeaconState,
state: &BeaconState<T>,
spec: &ChainSpec,
) -> Result<bool, BeaconStateError> {
let attestation_slot = state.get_attestation_slot(&a.data, spec)?;
let state_block_root = *state.get_block_root(attestation_slot, spec)?;
let state_block_root = *state.get_block_root(attestation_slot)?;
Ok(a.data.beacon_block_root == state_block_root)
}

View File

@@ -35,8 +35,8 @@ impl WinningRoot {
/// per-epoch processing.
///
/// Spec v0.6.1
pub fn winning_root(
state: &BeaconState,
pub fn winning_root<T: EthSpec>(
state: &BeaconState<T>,
shard: u64,
epoch: Epoch,
spec: &ChainSpec,
@@ -99,8 +99,8 @@ pub fn winning_root(
Ok(winning_root)
}
pub fn get_unslashed_attesting_indices_unsorted(
state: &BeaconState,
pub fn get_unslashed_attesting_indices_unsorted<T: EthSpec>(
state: &BeaconState<T>,
attestations: &[&PendingAttestation],
spec: &ChainSpec,
) -> Result<Vec<usize>, BeaconStateError> {