mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-06 10:11:44 +00:00
spec: initiate_validator_exit v0.6.1
Added a new field `exit_cache` to the BeaconState, which caches the number of validators exiting at each epoch.
This commit is contained in:
39
eth2/state_processing/src/common/exit.rs
Normal file
39
eth2/state_processing/src/common/exit.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::cmp::max;
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Initiate the exit of the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn initiate_validator_exit(
|
||||
state: &mut BeaconState,
|
||||
index: usize,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
if index >= state.validator_registry.len() {
|
||||
return Err(Error::UnknownValidator);
|
||||
}
|
||||
|
||||
// Return if the validator already initiated exit
|
||||
if state.validator_registry[index].exit_epoch != spec.far_future_epoch {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Compute exit queue epoch
|
||||
let delayed_epoch = state.get_delayed_activation_exit_epoch(state.current_epoch(spec), spec);
|
||||
let mut exit_queue_epoch = state
|
||||
.exit_cache
|
||||
.max_epoch()
|
||||
.map_or(delayed_epoch, |epoch| max(epoch, delayed_epoch));
|
||||
let exit_queue_churn = state.exit_cache.get_churn_at(exit_queue_epoch);
|
||||
|
||||
if exit_queue_churn >= state.get_churn_limit(spec)? {
|
||||
exit_queue_epoch += 1;
|
||||
}
|
||||
|
||||
state.exit_cache.record_validator_exit(exit_queue_epoch);
|
||||
state.validator_registry[index].exit_epoch = exit_queue_epoch;
|
||||
state.validator_registry[index].withdrawable_epoch =
|
||||
exit_queue_epoch + spec.min_validator_withdrawability_delay;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Exit the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn exit_validator(
|
||||
state: &mut BeaconState,
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
if validator_index >= state.validator_registry.len() {
|
||||
return Err(Error::UnknownValidator);
|
||||
}
|
||||
|
||||
let delayed_epoch = state.get_delayed_activation_exit_epoch(state.current_epoch(spec), spec);
|
||||
|
||||
if state.validator_registry[validator_index].exit_epoch > delayed_epoch {
|
||||
state.validator_registry[validator_index].exit_epoch = delayed_epoch;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
mod exit_validator;
|
||||
mod exit;
|
||||
mod slash_validator;
|
||||
mod verify_bitfield;
|
||||
|
||||
pub use exit_validator::exit_validator;
|
||||
pub use exit::initiate_validator_exit;
|
||||
pub use slash_validator::slash_validator;
|
||||
pub use verify_bitfield::verify_bitfield_length;
|
||||
|
||||
@@ -1,62 +1,46 @@
|
||||
use crate::common::exit_validator;
|
||||
use crate::common::initiate_validator_exit;
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Slash the validator with index ``index``.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
/// Spec v0.6.1
|
||||
pub fn slash_validator(
|
||||
state: &mut BeaconState,
|
||||
validator_index: usize,
|
||||
slashed_index: usize,
|
||||
opt_whistleblower_index: Option<usize>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
if (validator_index >= state.validator_registry.len())
|
||||
| (validator_index >= state.validator_balances.len())
|
||||
{
|
||||
if slashed_index >= state.validator_registry.len() || slashed_index >= state.balances.len() {
|
||||
return Err(BeaconStateError::UnknownValidator);
|
||||
}
|
||||
|
||||
let validator = &state.validator_registry[validator_index];
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
let effective_balance = state.get_effective_balance(validator_index, spec)?;
|
||||
initiate_validator_exit(state, slashed_index, spec)?;
|
||||
|
||||
// A validator that is withdrawn cannot be slashed.
|
||||
//
|
||||
// This constraint will be lifted in Phase 0.
|
||||
if state.slot
|
||||
>= validator
|
||||
.withdrawable_epoch
|
||||
.start_slot(spec.slots_per_epoch)
|
||||
{
|
||||
return Err(Error::ValidatorIsWithdrawable);
|
||||
}
|
||||
|
||||
exit_validator(state, validator_index, spec)?;
|
||||
state.validator_registry[slashed_index].slashed = true;
|
||||
state.validator_registry[slashed_index].withdrawable_epoch =
|
||||
current_epoch + Epoch::from(spec.latest_slashed_exit_length);
|
||||
let slashed_balance = state.get_effective_balance(slashed_index, spec)?;
|
||||
|
||||
state.set_slashed_balance(
|
||||
current_epoch,
|
||||
state.get_slashed_balance(current_epoch, spec)? + effective_balance,
|
||||
state.get_slashed_balance(current_epoch, spec)? + slashed_balance,
|
||||
spec,
|
||||
)?;
|
||||
|
||||
let whistleblower_index =
|
||||
let proposer_index =
|
||||
state.get_beacon_proposer_index(state.slot, RelativeEpoch::Current, spec)?;
|
||||
let whistleblower_reward = effective_balance / spec.whistleblower_reward_quotient;
|
||||
let whistleblower_index = opt_whistleblower_index.unwrap_or(proposer_index);
|
||||
let whistleblowing_reward = slashed_balance / spec.whistleblowing_reward_quotient;
|
||||
let proposer_reward = whistleblowing_reward / spec.proposer_reward_quotient;
|
||||
|
||||
safe_add_assign!(state.balances[proposer_index], proposer_reward);
|
||||
safe_add_assign!(
|
||||
state.validator_balances[whistleblower_index as usize],
|
||||
whistleblower_reward
|
||||
state.balances[whistleblower_index],
|
||||
whistleblowing_reward - proposer_reward
|
||||
);
|
||||
safe_sub_assign!(
|
||||
state.validator_balances[validator_index],
|
||||
whistleblower_reward
|
||||
);
|
||||
|
||||
state.validator_registry[validator_index].slashed = true;
|
||||
|
||||
state.validator_registry[validator_index].withdrawable_epoch =
|
||||
current_epoch + Epoch::from(spec.latest_slashed_exit_length);
|
||||
safe_sub_assign!(state.balances[slashed_index], whistleblowing_reward);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user