Merge pull request #785 from ethereum/JustinDrake-patch-13

Include recently slashed churn in exit churn queue
This commit is contained in:
Danny Ryan 2019-03-19 13:50:23 -06:00 committed by GitHub
commit 571439bb6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 11 deletions

View File

@ -2089,16 +2089,21 @@ def update_validator_registry(state: BeaconState) -> None:
activate_validator(state, index, is_genesis=False) activate_validator(state, index, is_genesis=False)
# Exit validators within the allowable balance churn # Exit validators within the allowable balance churn
balance_churn = 0 if current_epoch < state.validator_registry_update_epoch + LATEST_SLASHED_EXIT_LENGTH:
for index, validator in enumerate(state.validator_registry): balance_churn = (
if validator.exit_epoch == FAR_FUTURE_EPOCH and validator.initiated_exit: state.latest_slashed_balances[state.validator_registry_update_epoch % LATEST_SLASHED_EXIT_LENGTH] -
# Check the balance churn would be within the allowance state.latest_slashed_balances[current_epoch % LATEST_SLASHED_EXIT_LENGTH]
balance_churn += get_effective_balance(state, index) )
if balance_churn > max_balance_churn:
break
# Exit validator for index, validator in enumerate(state.validator_registry):
exit_validator(state, index) 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)
state.validator_registry_update_epoch = current_epoch state.validator_registry_update_epoch = current_epoch
``` ```

View File

@ -316,12 +316,18 @@ def test_attestation(state, pubkeys, privkeys):
def test_voluntary_exit(state, pubkeys, privkeys): def test_voluntary_exit(state, pubkeys, privkeys):
pre_state = deepcopy(state) 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 # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
# artificially trigger registry update at next epoch transition # 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) post_state = deepcopy(pre_state)
@ -363,6 +369,44 @@ def test_voluntary_exit(state, pubkeys, privkeys):
return pre_state, [initiate_exit_block, exit_block], post_state 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): def test_transfer(state, pubkeys, privkeys):
pre_state = deepcopy(state) pre_state = deepcopy(state)
current_epoch = get_current_epoch(pre_state) current_epoch = get_current_epoch(pre_state)