Skip to content
This repository has been archived by the owner on Jul 1, 2021. It is now read-only.

Implement process_ejections #359

Merged
merged 2 commits into from
Mar 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions eth2/beacon/state_machines/forks/serenity/epoch_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
get_randao_mix,
slot_to_epoch,
)
from eth2.beacon.validator_status_helpers import (
exit_validator,
)
from eth2.beacon._utils.hash import (
hash_eth2,
)
Expand Down Expand Up @@ -784,6 +787,30 @@ def process_rewards_and_penalties(state: BeaconState, config: BeaconConfig) -> B
return state


#
# Ejections
#
def process_ejections(state: BeaconState,
config: BeaconConfig) -> BeaconState:
"""
Iterate through the validator registry and eject active validators
with balance below ``EJECTION_BALANCE``.
"""
active_validator_indices = get_active_validator_indices(
state.validator_registry,
state.current_epoch(config.SLOTS_PER_EPOCH),
)
for index in set(active_validator_indices):
if state.validator_balances[index] < config.EJECTION_BALANCE:
state = exit_validator(
state,
index,
slots_per_epoch=config.SLOTS_PER_EPOCH,
activation_exit_delay=config.ACTIVATION_EXIT_DELAY,
)
return state


#
# Validator registry and shuffling seed data
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from .epoch_processing import (
process_justification,
process_crosslinks,
process_ejections,
process_final_updates,
process_rewards_and_penalties,
process_validator_registry,
Expand Down Expand Up @@ -90,7 +91,7 @@ def per_epoch_transition(self, state: BeaconState, block: BaseBeaconBlock) -> Be
state = process_justification(state, self.config)
state = process_crosslinks(state, self.config)
state = process_rewards_and_penalties(state, self.config)
# TODO: state = process_ejections(state, self.config)
state = process_ejections(state, self.config)
state = process_validator_registry(state, self.config)
state = process_final_updates(state, self.config)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@
from eth2.beacon.configs import (
CommitteeConfig,
)
from eth2.beacon.constants import (
FAR_FUTURE_EPOCH,
)
from eth2.beacon.helpers import (
get_active_validator_indices,
get_block_root,
get_epoch_start_slot,
get_delayed_activation_exit_epoch,
get_randao_mix,
slot_to_epoch,
)
Expand All @@ -50,16 +54,17 @@
from eth2.beacon.types.pending_attestation_records import PendingAttestationRecord
from eth2.beacon.state_machines.forks.serenity.epoch_processing import (
_check_if_update_validator_registry,
_update_latest_active_index_roots,
process_crosslinks,
process_final_updates,
_current_previous_epochs_justifiable,
_get_finalized_epoch,
_process_rewards_and_penalties_for_attestation_inclusion,
_process_rewards_and_penalties_for_crosslinks,
_process_rewards_and_penalties_for_finality,
process_validator_registry,
_current_previous_epochs_justifiable,
_get_finalized_epoch,
_update_latest_active_index_roots,
process_crosslinks,
process_ejections,
process_final_updates,
process_justification,
process_validator_registry,
)

from eth2.beacon.types.states import BeaconState
Expand Down Expand Up @@ -838,6 +843,41 @@ def test_process_rewards_and_penalties_for_crosslinks(
assert rewards_received[index] == expected_rewards_received[index]


#
# Ejections
#
def test_process_ejections(genesis_state, config, activation_exit_delay):
current_epoch = 8
state = genesis_state.copy(
slot=get_epoch_start_slot(current_epoch, config.SLOTS_PER_EPOCH),
)
delayed_activation_exit_epoch = get_delayed_activation_exit_epoch(
current_epoch,
activation_exit_delay,
)

ejecting_validator_index = 0
validator = state.validator_registry[ejecting_validator_index]
assert validator.is_active(current_epoch)
assert validator.exit_epoch > delayed_activation_exit_epoch

state = state.update_validator_balance(
validator_index=ejecting_validator_index,
balance=config.EJECTION_BALANCE - 1,
)
result_state = process_ejections(state, config)
result_validator = result_state.validator_registry[ejecting_validator_index]
assert result_validator.is_active(current_epoch)
assert result_validator.exit_epoch == delayed_activation_exit_epoch
# The ejecting validator will be inactive at the exit_epoch
assert not result_validator.is_active(result_validator.exit_epoch)
# Other validators are not ejected
assert (
result_state.validator_registry[ejecting_validator_index + 1].exit_epoch ==
FAR_FUTURE_EPOCH
)


#
# Validator registry and shuffling seed data
#
Expand Down