diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index 0c5649190..0d6fc0b4e 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -778,23 +778,25 @@ def process_epoch(state: BeaconState) -> None: #### Modified `process_registry_updates` -*Note*: The function `process_registry_updates` is modified to use the updated definition of `initiate_validator_exit` +*Note*: The function `process_registry_updates` is modified to +use the updated definitions of `initiate_validator_exit` and `is_eligible_for_activation_queue` and changes how the activation epochs are computed for eligible validators. ```python def process_registry_updates(state: BeaconState) -> None: # Process activation eligibility and ejections for index, validator in enumerate(state.validators): - if is_eligible_for_activation_queue(validator): + if is_eligible_for_activation_queue(validator): # [Modified in Electra:EIP7251] validator.activation_eligibility_epoch = get_current_epoch(state) + 1 if ( is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE ): - initiate_validator_exit(state, ValidatorIndex(index)) + initiate_validator_exit(state, ValidatorIndex(index)) # [Modified in Electra:EIP7251] # Activate all eligible validators + # [Modified in Electra:EIP7251] activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) for validator in state.validators: if is_eligible_for_activation(state, validator): diff --git a/tests/core/pyspec/eth2spec/test/deneb/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/deneb/epoch_processing/test_process_registry_updates.py index 9d5a2e5d9..0914bc1fb 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/epoch_processing/test_process_registry_updates.py +++ b/tests/core/pyspec/eth2spec/test/deneb/epoch_processing/test_process_registry_updates.py @@ -23,6 +23,8 @@ def run_test_activation_churn_limit(spec, state): validator_count_0 = len(state.validators) + balance = spec.MIN_ACTIVATION_BALANCE if is_post_electra(spec) else spec.MAX_EFFECTIVE_BALANCE + for i in range(mock_activations): index = validator_count_0 + i validator = spec.Validator( @@ -32,10 +34,10 @@ def run_test_activation_churn_limit(spec, state): activation_epoch=spec.FAR_FUTURE_EPOCH, exit_epoch=spec.FAR_FUTURE_EPOCH, withdrawable_epoch=spec.FAR_FUTURE_EPOCH, - effective_balance=spec.MAX_EFFECTIVE_BALANCE, + effective_balance=balance, ) state.validators.append(validator) - state.balances.append(spec.MAX_EFFECTIVE_BALANCE) + state.balances.append(balance) state.previous_epoch_participation.append(spec.ParticipationFlags(0b0000_0000)) state.current_epoch_participation.append(spec.ParticipationFlags(0b0000_0000)) state.inactivity_scores.append(0) diff --git a/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py new file mode 100644 index 000000000..ce5915269 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/electra/epoch_processing/test_process_registry_updates.py @@ -0,0 +1,92 @@ +from eth2spec.test.helpers.deposits import mock_deposit +from eth2spec.test.helpers.state import next_epoch +from eth2spec.test.context import spec_state_test, with_electra_and_later +from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with +from eth2spec.test.helpers.withdrawals import ( + set_eth1_withdrawal_credential_with_balance, + set_compounding_withdrawal_credential_with_balance +) + + +def run_test_activation_queue_eligibility(spec, state, validator_index, balance): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + state.balances[validator_index] = balance + state.validators[validator_index].effective_balance = balance + + # ready for entrance into activation queue + mock_deposit(spec, state, validator_index) + + yield from run_epoch_processing_with(spec, state, 'process_registry_updates') + + # validator moved into activation queue if eligible + validator = state.validators[validator_index] + if validator.effective_balance < spec.MIN_ACTIVATION_BALANCE: + assert validator.activation_eligibility_epoch == spec.FAR_FUTURE_EPOCH + else: + assert validator.activation_eligibility_epoch < spec.FAR_FUTURE_EPOCH + + +@with_electra_and_later +@spec_state_test +def test_activation_queue_eligibility__less_than_min_activation_balance(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 3 + balance = spec.MIN_ACTIVATION_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT + yield from run_test_activation_queue_eligibility(spec, state, index, balance) + + +@with_electra_and_later +@spec_state_test +def test_activation_queue_eligibility__min_activation_balance(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 5 + balance = spec.MIN_ACTIVATION_BALANCE + yield from run_test_activation_queue_eligibility(spec, state, index, balance) + + +@with_electra_and_later +@spec_state_test +def test_activation_queue_eligibility__min_activation_balance_eth1_creds(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 7 + balance = spec.MIN_ACTIVATION_BALANCE + set_eth1_withdrawal_credential_with_balance(spec, state, index) + yield from run_test_activation_queue_eligibility(spec, state, index, balance) + + +@with_electra_and_later +@spec_state_test +def test_activation_queue_eligibility__min_activation_balance_compounding_creds(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 11 + balance = spec.MIN_ACTIVATION_BALANCE + set_compounding_withdrawal_credential_with_balance(spec, state, index) + yield from run_test_activation_queue_eligibility(spec, state, index, balance) + + +@with_electra_and_later +@spec_state_test +def test_activation_queue_eligibility__greater_than_min_activation_balance(spec, state): + # move past first two irregular epochs wrt finality + next_epoch(spec, state) + next_epoch(spec, state) + + index = 13 + balance = spec.MIN_ACTIVATION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT + set_compounding_withdrawal_credential_with_balance(spec, state, index) + yield from run_test_activation_queue_eligibility(spec, state, index, balance)