Skip to content

Commit

Permalink
Merge pull request #785 from ethereum/JustinDrake-patch-13
Browse files Browse the repository at this point in the history
Include recently slashed churn in exit churn queue
  • Loading branch information
djrtwo committed Mar 19, 2019
2 parents fe3eef2 + 24f1139 commit 571439b
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
23 changes: 14 additions & 9 deletions specs/core/0_beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -2089,16 +2089,21 @@ def update_validator_registry(state: BeaconState) -> None:
activate_validator(state, index, is_genesis=False)

# Exit validators within the allowable balance churn
balance_churn = 0
for index, validator in enumerate(state.validator_registry):
if validator.exit_epoch == FAR_FUTURE_EPOCH and validator.initiated_exit:
# Check the balance churn would be within the allowance
balance_churn += get_effective_balance(state, index)
if balance_churn > max_balance_churn:
break
if current_epoch < state.validator_registry_update_epoch + LATEST_SLASHED_EXIT_LENGTH:
balance_churn = (
state.latest_slashed_balances[state.validator_registry_update_epoch % LATEST_SLASHED_EXIT_LENGTH] -
state.latest_slashed_balances[current_epoch % LATEST_SLASHED_EXIT_LENGTH]
)

for index, validator in enumerate(state.validator_registry):
if validator.exit_epoch == FAR_FUTURE_EPOCH and validator.initiated_exit:
# Check the balance churn would be within the allowance
balance_churn += get_effective_balance(state, index)
if balance_churn > max_balance_churn:
break

# Exit validator
exit_validator(state, index)
# Exit validator
exit_validator(state, index)

state.validator_registry_update_epoch = current_epoch
```
Expand Down
48 changes: 46 additions & 2 deletions tests/phase0/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,18 @@ def test_attestation(state, pubkeys, privkeys):

def test_voluntary_exit(state, pubkeys, privkeys):
pre_state = deepcopy(state)
validator_index = get_active_validator_indices(pre_state.validator_registry, get_current_epoch(pre_state))[-1]
validator_index = get_active_validator_indices(
pre_state.validator_registry,
get_current_epoch(pre_state)
)[-1]

# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
# artificially trigger registry update at next epoch transition
pre_state.validator_registry_update_epoch -= 1
pre_state.finalized_epoch = get_current_epoch(pre_state) - 1
for crosslink in pre_state.latest_crosslinks:
crosslink.epoch = pre_state.finalized_epoch
pre_state.validator_registry_update_epoch = pre_state.finalized_epoch - 1

post_state = deepcopy(pre_state)

Expand Down Expand Up @@ -363,6 +369,44 @@ def test_voluntary_exit(state, pubkeys, privkeys):
return pre_state, [initiate_exit_block, exit_block], post_state


def test_no_exit_too_long_since_change(state):
pre_state = deepcopy(state)
validator_index = get_active_validator_indices(
pre_state.validator_registry,
get_current_epoch(pre_state)
)[-1]

#
# setup pre_state
#
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
# artificially trigger registry update at next epoch transition
pre_state.finalized_epoch = get_current_epoch(pre_state) - 1
for crosslink in pre_state.latest_crosslinks:
crosslink.epoch = pre_state.finalized_epoch
# make epochs since registry update greater than LATEST_SLASHED_EXIT_LENGTH
pre_state.validator_registry_update_epoch = (
get_current_epoch(pre_state) - spec.LATEST_SLASHED_EXIT_LENGTH
)
# set validator to have previously initiated exit
pre_state.validator_registry[validator_index].initiated_exit = True

post_state = deepcopy(pre_state)

#
# Process registry change but ensure no exit
#
block = build_empty_block_for_next_slot(post_state)
block.slot += spec.SLOTS_PER_EPOCH
state_transition(post_state, block)

assert post_state.validator_registry_update_epoch == get_current_epoch(post_state) - 1
assert post_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH

return pre_state, [block], post_state


def test_transfer(state, pubkeys, privkeys):
pre_state = deepcopy(state)
current_epoch = get_current_epoch(pre_state)
Expand Down

0 comments on commit 571439b

Please sign in to comment.