def test_get_delayed_activation_exit_epoch(activation_exit_delay): epoch = random.randint(0, FAR_FUTURE_EPOCH) entry_exit_effect_epoch = get_delayed_activation_exit_epoch( epoch, activation_exit_delay, ) assert entry_exit_effect_epoch == (epoch + 1 + activation_exit_delay)
def test_activate_validator(is_genesis, filled_beacon_state, genesis_epoch, slots_per_epoch, activation_exit_delay, max_deposit_amount, config): validator_count = 10 state = filled_beacon_state.copy( validator_registry=tuple( mock_validator( pubkey=index.to_bytes(48, 'little'), config=config, is_active=False, ) for index in range(validator_count)), validator_balances=(max_deposit_amount, ) * validator_count, ) index = 1 # Check that the `index`th validator in `state` is inactivated assert state.validator_registry[index].activation_epoch == FAR_FUTURE_EPOCH result_state = activate_validator( state=state, index=index, is_genesis=is_genesis, genesis_epoch=genesis_epoch, slots_per_epoch=slots_per_epoch, activation_exit_delay=activation_exit_delay, ) if is_genesis: assert result_state.validator_registry[ index].activation_epoch == genesis_epoch else: assert (result_state.validator_registry[index].activation_epoch == get_delayed_activation_exit_epoch( state.current_epoch(slots_per_epoch), activation_exit_delay, ))
def test_exit_validator(num_validators, activation_exit_delay, committee, state_slot, exit_epoch, n_validators_state, slots_per_epoch): # Unchanged state = n_validators_state.copy(slot=state_slot, ) index = 1 # Set validator `exit_epoch` prior to running `exit_validator` validator = state.validator_registry[index].copy(exit_epoch=exit_epoch, ) state = state.update_validator_registry( validator_index=index, validator=validator, ) result_state = exit_validator( state=state, index=index, slots_per_epoch=slots_per_epoch, activation_exit_delay=activation_exit_delay, ) if validator.exit_epoch <= state.current_epoch( slots_per_epoch) + activation_exit_delay: assert state == result_state return else: assert validator.exit_epoch > state.current_epoch( slots_per_epoch) + activation_exit_delay result_validator = result_state.validator_registry[index] assert result_validator.exit_epoch == get_delayed_activation_exit_epoch( state.current_epoch(slots_per_epoch), activation_exit_delay, )
def exit_validator(state: BeaconState, index: ValidatorIndex, slots_per_epoch: int, activation_exit_delay: int) -> BeaconState: """ Exit the validator with the given ``index``. Return the updated state (immutable). """ validator = state.validator_registry[index] delayed_activation_exit_epoch = get_delayed_activation_exit_epoch( state.current_epoch(slots_per_epoch), activation_exit_delay, ) # The following updates only occur if not previous exited if validator.exit_epoch <= delayed_activation_exit_epoch: return state validator = validator.copy( exit_epoch=delayed_activation_exit_epoch, ) state = state.update_validator_registry(index, validator) return state
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 )
def validate_voluntary_exit_validator_exit_epoch( state: 'BeaconState', validator: 'ValidatorRecord', current_epoch: Epoch, slots_per_epoch: int, activation_exit_delay: int) -> None: current_epoch = state.current_epoch(slots_per_epoch) # Verify the validator has not yet exited delayed_activation_exit_epoch = get_delayed_activation_exit_epoch( current_epoch, activation_exit_delay, ) if validator.exit_epoch <= delayed_activation_exit_epoch: raise ValidationError( f"validator.exit_epoch ({validator.exit_epoch}) should be greater than " f"delayed_activation_exit_epoch ({delayed_activation_exit_epoch})")
def activate_validator(state: BeaconState, index: ValidatorIndex, is_genesis: bool, genesis_epoch: Epoch, slots_per_epoch: int, activation_exit_delay: int) -> BeaconState: """ Activate the validator with the given ``index``. Return the updated state (immutable). """ # Update validator.activation_epoch validator = state.validator_registry[index].copy( activation_epoch=genesis_epoch if is_genesis else get_delayed_activation_exit_epoch( state.current_epoch(slots_per_epoch), activation_exit_delay, )) state = state.update_validator_registry(index, validator) return state
def test_update_validator_registry(n, n_validators_state, config, slots_per_epoch): validator_registry = list(n_validators_state.validator_registry) activating_index = n exiting_index = 0 activating_validator = ValidatorRecord.create_pending_validator( pubkey=b'\x10' * 48, withdrawal_credentials=b'\x11' * 32, ) exiting_validator = n_validators_state.validator_registry[exiting_index].copy( exit_epoch=FAR_FUTURE_EPOCH, initiated_exit=True, ) validator_registry[exiting_index] = exiting_validator validator_registry.append(activating_validator) state = n_validators_state.copy( validator_registry=validator_registry, validator_balances=n_validators_state.validator_balances + (config.MAX_DEPOSIT_AMOUNT,), ) state = update_validator_registry(state, config) entry_exit_effect_epoch = get_delayed_activation_exit_epoch( state.current_epoch(slots_per_epoch), config.ACTIVATION_EXIT_DELAY, ) # Check if the activating_validator is activated assert state.validator_registry[activating_index].activation_epoch == entry_exit_effect_epoch # Check if the activating_validator is exited assert state.validator_registry[exiting_index].exit_epoch == entry_exit_effect_epoch