示例#1
0
def test_initiate_validator_exit(genesis_state, is_already_exited, config):
    state = genesis_state
    index = random.choice(range(len(state.validators)))
    validator = state.validators[index]
    assert not validator.slashed
    assert validator.activation_epoch == config.GENESIS_EPOCH
    assert validator.activation_eligibility_epoch == config.GENESIS_EPOCH
    assert validator.exit_epoch == FAR_FUTURE_EPOCH
    assert validator.withdrawable_epoch == FAR_FUTURE_EPOCH

    if is_already_exited:
        churn_limit = get_validator_churn_limit(state, config)
        exit_queue_epoch = _compute_exit_queue_epoch(state, churn_limit,
                                                     config)
        validator = validator.copy(
            exit_epoch=exit_queue_epoch,
            withdrawable_epoch=exit_queue_epoch +
            config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY,
        )

    exited_validator = initiate_exit_for_validator(validator, state, config)

    if is_already_exited:
        assert exited_validator == validator
    else:
        churn_limit = get_validator_churn_limit(state, config)
        exit_queue_epoch = _compute_exit_queue_epoch(state, churn_limit,
                                                     config)
        assert exited_validator.exit_epoch == exit_queue_epoch
        assert exited_validator.withdrawable_epoch == (
            exit_queue_epoch + config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
示例#2
0
def test_compute_exit_queue_epoch(
    genesis_state,
    is_delayed_exit_epoch_the_maximum_exit_queue_epoch,
    is_churn_limit_met,
    config,
):
    state = genesis_state
    for index in random.sample(range(len(state.validators)),
                               len(state.validators) // 4):
        some_future_epoch = config.GENESIS_EPOCH + random.randrange(1, 2**32)
        state = state.update_validator_with_fn(
            index,
            lambda validator, *_: validator.copy(exit_epoch=some_future_epoch))

    if is_delayed_exit_epoch_the_maximum_exit_queue_epoch:
        expected_candidate_exit_queue_epoch = compute_activation_exit_epoch(
            state.current_epoch(config.SLOTS_PER_EPOCH),
            config.MAX_SEED_LOOKAHEAD)
        for index, validator in enumerate(state.validators):
            if validator.exit_epoch == FAR_FUTURE_EPOCH:
                continue
            some_prior_epoch = random.randrange(
                config.GENESIS_EPOCH, expected_candidate_exit_queue_epoch)
            state = state.update_validator_with_fn(
                index, lambda validator, *_: validator.copy(exit_epoch=
                                                            some_prior_epoch))
            validator = state.validators[index]
            assert expected_candidate_exit_queue_epoch >= validator.exit_epoch
    else:
        expected_candidate_exit_queue_epoch = -1
        for validator in state.validators:
            if validator.exit_epoch == FAR_FUTURE_EPOCH:
                continue
            if validator.exit_epoch > expected_candidate_exit_queue_epoch:
                expected_candidate_exit_queue_epoch = validator.exit_epoch
        assert expected_candidate_exit_queue_epoch >= config.GENESIS_EPOCH

    if is_churn_limit_met:
        churn_limit = 0
        expected_exit_queue_epoch = expected_candidate_exit_queue_epoch + 1
    else:
        # add more validators to the queued epoch to make the test less trivial
        # with the setup so far, it is likely that the queue in the target epoch is size 1.
        queued_validators = {
            index: validator
            for index, validator in state.validators
            if validator.exit_epoch == expected_candidate_exit_queue_epoch
        }
        additional_queued_validator_count = random.randrange(
            len(queued_validators), len(state.validators))
        unqueued_validators = tuple(v for v in state.validators
                                    if v.exit_epoch == FAR_FUTURE_EPOCH)
        for index in random.sample(range(len(unqueued_validators)),
                                   additional_queued_validator_count):
            state = state.update_validator_with_fn(
                index,
                lambda validator, *_: validator.copy(
                    exit_epoch=expected_candidate_exit_queue_epoch),
            )

        all_queued_validators = tuple(
            v for v in state.validators
            if v.exit_epoch == expected_candidate_exit_queue_epoch)
        churn_limit = len(all_queued_validators) + 1

        expected_exit_queue_epoch = expected_candidate_exit_queue_epoch

    assert (_compute_exit_queue_epoch(state, churn_limit,
                                      config) == expected_exit_queue_epoch)