mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 12:11:59 +00:00
Move state trans fns into state_processing
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use types::{beacon_state::helpers::verify_bitfield_length, *};
|
||||
use crate::common::verify_bitfield_length;
|
||||
use types::*;
|
||||
|
||||
/// Returns validator indices which participated in the attestation.
|
||||
///
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
use crate::common::exit_validator;
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Iterate through the validator registry and eject active validators with balance below
|
||||
/// ``EJECTION_BALANCE``.
|
||||
///
|
||||
/// Spec v0.5.0
|
||||
pub fn process_ejections(state: &mut BeaconState, 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
|
||||
.get_active_validator_indices(state.current_epoch(spec), spec)?
|
||||
.iter()
|
||||
.filter_map(|&i| {
|
||||
if state.validator_balances[i as usize] < spec.ejection_balance {
|
||||
Some(i)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
for validator_index in exitable {
|
||||
exit_validator(state, validator_index, spec)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use types::*;
|
||||
|
||||
/// Process the exit queue.
|
||||
///
|
||||
/// Spec v0.5.0
|
||||
pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
let eligible = |index: usize| {
|
||||
let validator = &state.validator_registry[index];
|
||||
|
||||
if validator.withdrawable_epoch != spec.far_future_epoch {
|
||||
false
|
||||
} else {
|
||||
current_epoch >= validator.exit_epoch + spec.min_validator_withdrawability_delay
|
||||
}
|
||||
};
|
||||
|
||||
let mut eligable_indices: Vec<usize> = (0..state.validator_registry.len())
|
||||
.filter(|i| eligible(*i))
|
||||
.collect();
|
||||
eligable_indices.sort_by_key(|i| state.validator_registry[*i].exit_epoch);
|
||||
|
||||
for (withdrawn_so_far, index) in eligable_indices.iter().enumerate() {
|
||||
if withdrawn_so_far as u64 >= spec.max_exit_dequeues_per_epoch {
|
||||
break;
|
||||
}
|
||||
prepare_validator_for_withdrawal(state, *index, spec);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initiate an exit for the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.5.0
|
||||
fn prepare_validator_for_withdrawal(
|
||||
state: &mut BeaconState,
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
) {
|
||||
state.validator_registry[validator_index].withdrawable_epoch =
|
||||
state.current_epoch(spec) + spec.min_validator_withdrawability_delay;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Process slashings.
|
||||
///
|
||||
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
pub fn process_slashings(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
let active_validator_indices = state.get_active_validator_indices(current_epoch, spec)?;
|
||||
let total_balance = state.get_total_balance(&active_validator_indices[..], spec)?;
|
||||
|
||||
for (index, validator) in state.validator_registry.iter().enumerate() {
|
||||
if validator.slashed
|
||||
&& (current_epoch
|
||||
== validator.withdrawable_epoch - Epoch::from(spec.latest_slashed_exit_length / 2))
|
||||
{
|
||||
// TODO: check the following two lines are correct.
|
||||
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_penalities = total_at_end.saturating_sub(total_at_start);
|
||||
|
||||
let effective_balance = state.get_effective_balance(index, spec)?;
|
||||
let penalty = std::cmp::max(
|
||||
effective_balance * std::cmp::min(total_penalities * 3, total_balance)
|
||||
/ total_balance,
|
||||
effective_balance / spec.min_penalty_quotient,
|
||||
);
|
||||
|
||||
safe_sub_assign!(state.validator_balances[index], penalty);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::update_validator_registry::update_validator_registry;
|
||||
use super::Error;
|
||||
use types::*;
|
||||
|
||||
@@ -14,7 +15,7 @@ pub fn process_validator_registry(state: &mut BeaconState, spec: &ChainSpec) ->
|
||||
state.previous_shuffling_seed = state.current_shuffling_seed;
|
||||
|
||||
if should_update_validator_registry(state, spec)? {
|
||||
state.update_validator_registry(spec)?;
|
||||
update_validator_registry(state, spec)?;
|
||||
|
||||
state.current_shuffling_epoch = next_epoch;
|
||||
state.current_shuffling_start_shard = (state.current_shuffling_start_shard
|
||||
@@ -37,9 +38,6 @@ pub fn process_validator_registry(state: &mut BeaconState, spec: &ChainSpec) ->
|
||||
}
|
||||
}
|
||||
|
||||
state.process_slashings(spec)?;
|
||||
state.process_exit_queue(spec);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::common::exit_validator;
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Update validator registry, activating/exiting validators if possible.
|
||||
///
|
||||
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
pub fn update_validator_registry(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
let active_validator_indices = state.get_active_validator_indices(current_epoch, spec)?;
|
||||
let total_balance = state.get_total_balance(&active_validator_indices[..], spec)?;
|
||||
|
||||
let max_balance_churn = std::cmp::max(
|
||||
spec.max_deposit_amount,
|
||||
total_balance / (2 * spec.max_balance_churn_quotient),
|
||||
);
|
||||
|
||||
let mut balance_churn = 0;
|
||||
for index in 0..state.validator_registry.len() {
|
||||
let validator = &state.validator_registry[index];
|
||||
|
||||
if (validator.activation_epoch == spec.far_future_epoch)
|
||||
& (state.validator_balances[index] == spec.max_deposit_amount)
|
||||
{
|
||||
balance_churn += state.get_effective_balance(index, spec)?;
|
||||
if balance_churn > max_balance_churn {
|
||||
break;
|
||||
}
|
||||
state.activate_validator(index, false, spec);
|
||||
}
|
||||
}
|
||||
|
||||
let mut balance_churn = 0;
|
||||
for index in 0..state.validator_registry.len() {
|
||||
let validator = &state.validator_registry[index];
|
||||
|
||||
if (validator.exit_epoch == spec.far_future_epoch) & (validator.initiated_exit) {
|
||||
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(())
|
||||
}
|
||||
Reference in New Issue
Block a user