mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 10:52:43 +00:00
Merge remote-tracking branch 'origin/master' into spec-0.6
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user