Ejemplo n.º 1
0
def test_activation_queue_sorting(spec, state):
    churn_limit = spec.get_validator_churn_limit(state)

    # try to activate more than the per-epoch churn linmit
    mock_activations = churn_limit * 2

    epoch = spec.get_current_epoch(state)
    for i in range(mock_activations):
        mock_deposit(spec, state, i)
        state.validators[i].activation_eligibility_epoch = epoch + 1

    # give the last priority over the others
    state.validators[mock_activations - 1].activation_eligibility_epoch = epoch

    # move state forward and finalize to allow for activations
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 3)
    state.finalized_checkpoint.epoch = epoch + 1

    yield from run_process_registry_updates(spec, state)

    # the first got in as second
    assert state.validators[0].activation_epoch != spec.FAR_FUTURE_EPOCH
    # the prioritized got in as first
    assert state.validators[mock_activations - 1].activation_epoch != spec.FAR_FUTURE_EPOCH
    # the second last is at the end of the queue, and did not make the churn,
    #  hence is not assigned an activation_epoch yet.
    assert state.validators[mock_activations - 2].activation_epoch == spec.FAR_FUTURE_EPOCH
    # the one at churn_limit did not make it, it was out-prioritized
    assert state.validators[churn_limit].activation_epoch == spec.FAR_FUTURE_EPOCH
    # but the the one in front of the above did
    assert state.validators[churn_limit - 1].activation_epoch != spec.FAR_FUTURE_EPOCH
Ejemplo n.º 2
0
def test_activation_queue_efficiency(spec, state):
    churn_limit = spec.get_validator_churn_limit(state)
    mock_activations = churn_limit * 2

    epoch = spec.get_current_epoch(state)
    for i in range(mock_activations):
        mock_deposit(spec, state, i)
        state.validators[i].activation_eligibility_epoch = epoch + 1

    # move state forward and finalize to allow for activations
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 3)

    state.finalized_checkpoint.epoch = epoch + 1

    # Run first registry update. Do not yield test vectors
    for _ in run_process_registry_updates(spec, state):
        pass

    # Half should churn in first run of registry update
    for i in range(mock_activations):
        if i < mock_activations // 2:
            assert state.validators[i].activation_epoch < spec.FAR_FUTURE_EPOCH
        else:
            assert state.validators[i].activation_epoch == spec.FAR_FUTURE_EPOCH

    # Second half should churn in second run of registry update
    yield from run_process_registry_updates(spec, state)
    for i in range(mock_activations):
        assert state.validators[i].activation_epoch < spec.FAR_FUTURE_EPOCH
def test_activation_queue_to_activated_if_finalized(spec, state):
    # move past first two irregular epochs wrt finality
    next_epoch(spec, state)
    next_epoch(spec, state)

    index = 0
    mock_deposit(spec, state, index)

    # mock validator as having been in queue since latest finalized
    state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1
    state.validators[
        index].activation_eligibility_epoch = state.finalized_checkpoint.epoch

    assert not spec.is_active_validator(state.validators[index],
                                        spec.get_current_epoch(state))

    yield from run_process_registry_updates(spec, state)

    # validator activated for future epoch
    assert state.validators[
        index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert state.validators[index].activation_epoch != spec.FAR_FUTURE_EPOCH
    assert not spec.is_active_validator(state.validators[index],
                                        spec.get_current_epoch(state))
    assert spec.is_active_validator(
        state.validators[index],
        spec.compute_activation_exit_epoch(spec.get_current_epoch(state)))
Ejemplo n.º 4
0
def set_some_new_deposits(spec, state, rng):
    num_validators = len(state.validators)
    # Set ~1/10 to just recently deposited
    for index in range(num_validators):
        # If not already active, skip
        if not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)):
            continue
        if rng.randrange(num_validators) < num_validators // 10:
            mock_deposit(spec, state, index)
            # Set ~half of selected to eligible for activation
            if rng.choice([True, False]):
                state.validators[index].activation_eligibility_epoch = spec.get_current_epoch(state)
Ejemplo n.º 5
0
def test_add_to_activation_queue(spec, state):
    # move past first two irregular epochs wrt finality
    next_epoch(spec, state)
    next_epoch(spec, state)

    index = 0
    mock_deposit(spec, state, index)

    yield from run_process_registry_updates(spec, state)

    # validator moved into queue
    assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert state.validators[index].activation_epoch == spec.FAR_FUTURE_EPOCH
    assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
Ejemplo n.º 6
0
def test_activation_queue_activation_and_ejection(spec, state):
    # move past first two irregular epochs wrt finality
    next_epoch(spec, state)
    next_epoch(spec, state)

    # ready for entrance into activation queue
    activation_queue_index = 0
    mock_deposit(spec, state, activation_queue_index)

    # ready for activation
    activation_index = 1
    mock_deposit(spec, state, activation_index)
    state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1
    state.validators[activation_index].activation_eligibility_epoch = state.finalized_checkpoint.epoch

    # ready for ejection
    ejection_index = 2
    state.validators[ejection_index].effective_balance = spec.EJECTION_BALANCE

    yield from run_process_registry_updates(spec, state)

    # validator moved into activation queue
    validator = state.validators[activation_queue_index]
    assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert validator.activation_epoch == spec.FAR_FUTURE_EPOCH
    assert not spec.is_active_validator(validator, spec.get_current_epoch(state))

    # validator activated for future epoch
    validator = state.validators[activation_index]
    assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert validator.activation_epoch != spec.FAR_FUTURE_EPOCH
    assert not spec.is_active_validator(validator, spec.get_current_epoch(state))
    assert spec.is_active_validator(
        validator,
        spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
    )

    # validator ejected for future epoch
    validator = state.validators[ejection_index]
    assert validator.exit_epoch != spec.FAR_FUTURE_EPOCH
    assert spec.is_active_validator(validator, spec.get_current_epoch(state))
    assert not spec.is_active_validator(
        validator,
        spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
    )
Ejemplo n.º 7
0
def test_activation_queue_no_activation_no_finality(spec, state):
    # move past first two irregular epochs wrt finality
    next_epoch(spec, state)
    next_epoch(spec, state)

    index = 0
    mock_deposit(spec, state, index)

    # mock validator as having been in queue only after latest finalized
    state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1
    state.validators[index].activation_eligibility_epoch = state.finalized_checkpoint.epoch + 1

    assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))

    yield from run_process_registry_updates(spec, state)

    # validator not activated
    assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert state.validators[index].activation_epoch == spec.FAR_FUTURE_EPOCH
def run_test_activation_queue_activation_and_ejection(spec, state,
                                                      num_per_status):
    # move past first two irregular epochs wrt finality
    next_epoch(spec, state)
    next_epoch(spec, state)

    # ready for entrance into activation queue
    activation_queue_start_index = 0
    activation_queue_indices = list(
        range(activation_queue_start_index,
              activation_queue_start_index + num_per_status))
    for validator_index in activation_queue_indices:
        mock_deposit(spec, state, validator_index)

    # ready for activation
    state.finalized_checkpoint.epoch = spec.get_current_epoch(state) - 1
    activation_start_index = num_per_status
    activation_indices = list(
        range(activation_start_index, activation_start_index + num_per_status))
    for validator_index in activation_indices:
        mock_deposit(spec, state, validator_index)
        state.validators[
            validator_index].activation_eligibility_epoch = state.finalized_checkpoint.epoch

    # ready for ejection
    ejection_start_index = num_per_status * 2
    ejection_indices = list(
        range(ejection_start_index, ejection_start_index + num_per_status))
    for validator_index in ejection_indices:
        state.validators[
            validator_index].effective_balance = spec.config.EJECTION_BALANCE

    churn_limit = spec.get_validator_churn_limit(state)
    yield from run_process_registry_updates(spec, state)

    # all eligible validators moved into activation queue
    for validator_index in activation_queue_indices:
        validator = state.validators[validator_index]
        assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
        assert validator.activation_epoch == spec.FAR_FUTURE_EPOCH
        assert not spec.is_active_validator(validator,
                                            spec.get_current_epoch(state))

    # up to churn limit validators get activated for future epoch from the queue
    for validator_index in activation_indices[:churn_limit]:
        validator = state.validators[validator_index]
        assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
        assert validator.activation_epoch != spec.FAR_FUTURE_EPOCH
        assert not spec.is_active_validator(validator,
                                            spec.get_current_epoch(state))
        assert spec.is_active_validator(
            validator,
            spec.compute_activation_exit_epoch(spec.get_current_epoch(state)))

    # any remaining validators do not exit the activation queue
    for validator_index in activation_indices[churn_limit:]:
        validator = state.validators[validator_index]
        assert validator.activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
        assert validator.activation_epoch == spec.FAR_FUTURE_EPOCH

    # all ejection balance validators ejected for a future epoch
    for i, validator_index in enumerate(ejection_indices):
        validator = state.validators[validator_index]
        assert validator.exit_epoch != spec.FAR_FUTURE_EPOCH
        assert spec.is_active_validator(validator,
                                        spec.get_current_epoch(state))
        queue_offset = i // churn_limit
        assert not spec.is_active_validator(
            validator,
            spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) +
            queue_offset)