From 97b6db497188da5c6fe9c1205b25642eb12232e2 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 18 May 2020 10:05:06 -0600 Subject: [PATCH] add rewards tests for validators not yet activated --- .../pyspec/eth2spec/test/helpers/deposits.py | 11 +++++++++ .../pyspec/eth2spec/test/helpers/rewards.py | 23 ++++++++++++++++++- .../test_process_registry_updates.py | 9 +------- .../phase_0/rewards/test_get_head_deltas.py | 6 +++++ .../test_get_inactivity_penalty_deltas.py | 21 +++++++++++++++++ .../test_get_inclusion_delay_deltas.py | 6 +++++ .../phase_0/rewards/test_get_source_deltas.py | 6 +++++ .../phase_0/rewards/test_get_target_deltas.py | 12 ++++++++++ 8 files changed, 85 insertions(+), 9 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index a16f7a7bf..6a2e30497 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -5,6 +5,17 @@ from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.utils.ssz.ssz_typing import List +def mock_deposit(spec, state, index): + """ + Mock validator at ``index`` as having just made a deposit + """ + assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) + state.validators[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH + state.validators[index].activation_epoch = spec.FAR_FUTURE_EPOCH + state.validators[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE + assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) + + def build_deposit_data(spec, pubkey, privkey, amount, withdrawal_credentials, signed=False): deposit_data = spec.DepositData( pubkey=pubkey, diff --git a/tests/core/pyspec/eth2spec/test/helpers/rewards.py b/tests/core/pyspec/eth2spec/test/helpers/rewards.py index 0433e808a..ac863725c 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/rewards.py +++ b/tests/core/pyspec/eth2spec/test/helpers/rewards.py @@ -2,6 +2,7 @@ from random import Random from eth2spec.phase0 import spec as spec_phase0 from eth2spec.test.helpers.attestations import prepare_state_with_attestations +from eth2spec.test.helpers.deposits import mock_deposit from eth2spec.test.helpers.state import next_epoch from eth2spec.utils.ssz.ssz_typing import Container, uint64, List @@ -61,6 +62,17 @@ def run_attestation_component_deltas(spec, state, component_delta_fn, matching_a assert penalties[index] == 0 +def set_some_new_deposits(spec, state, rng): + num_validators = len(state.validators) + # last 10th of validators are new deposits + for i in range(len(state.validators))[0:num_validators // 10]: + index = num_validators - 1 - i + mock_deposit(spec, state, index) + # Set half to eligible for activation + if i % 2 == 0: + state.validators[index].activation_eligibility_epoch = spec.get_current_epoch(state) + + def exit_random_validators(spec, state, rng): if spec.get_current_epoch(state) < 5: # Move epochs forward to allow for some validators already exited/withdrawable @@ -69,10 +81,11 @@ def exit_random_validators(spec, state, rng): current_epoch = spec.get_current_epoch(state) # Exit ~1/2 of validators - for validator in state.validators: + for index in spec.get_active_validator_indices(state, current_epoch): if rng.choice([True, False]): continue + validator = state.validators[index] validator.exit_epoch = rng.choice([current_epoch - 1, current_epoch - 2, current_epoch - 3]) # ~1/2 are withdrawable if rng.choice([True, False]): @@ -133,6 +146,13 @@ def run_test_one_attestation_one_correct(spec, state, runner): yield from runner(spec, state) +def run_test_with_not_yet_activated_validators(spec, state, runner, rng=Random(5555)): + set_some_new_deposits(spec, state, rng) + prepare_state_with_attestations(spec, state) + + yield from runner(spec, state) + + def run_test_with_exited_validators(spec, state, runner, rng=Random(1337)): exit_random_validators(spec, state, rng) prepare_state_with_attestations(spec, state) @@ -190,6 +210,7 @@ def run_test_full_fraction_incorrect(spec, state, correct_target, correct_head, def run_test_full_random(spec, state, runner, rng=Random(8020)): + set_some_new_deposits(spec, state, rng) exit_random_validators(spec, state, rng) slash_random_validators(spec, state, rng) diff --git a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index a5f4d9227..b6597b1cf 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -1,3 +1,4 @@ +from eth2spec.test.helpers.deposits import mock_deposit from eth2spec.test.helpers.state import next_epoch, next_slots from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with @@ -7,14 +8,6 @@ def run_process_registry_updates(spec, state): yield from run_epoch_processing_with(spec, state, 'process_registry_updates') -def mock_deposit(spec, state, index): - assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) - state.validators[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - state.validators[index].activation_epoch = spec.FAR_FUTURE_EPOCH - state.validators[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE - assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state)) - - @with_all_phases @spec_state_test def test_add_to_activation_queue(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py index 2e4b9dbbc..e49a8567c 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py @@ -48,6 +48,12 @@ def test_one_attestation_one_correct(spec, state): yield from rewards_helpers.run_test_one_attestation_one_correct(spec, state, run_get_head_deltas) +@with_all_phases +@spec_state_test +def test_with_not_yet_activated_validators(spec, state): + yield from rewards_helpers.run_test_with_not_yet_activated_validators(spec, state, run_get_head_deltas) + + @with_all_phases @spec_state_test def test_with_exited_validators(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inactivity_penalty_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inactivity_penalty_deltas.py index 4940cdc63..8588b3f52 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inactivity_penalty_deltas.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inactivity_penalty_deltas.py @@ -115,6 +115,27 @@ def test_full_but_partial_participation_leak(spec, state): yield from rewards_helpers.run_test_full_but_partial_participation(spec, state, run_get_inactivity_penalty_deltas) +@with_all_phases +@spec_state_test +def test_with_not_yet_activated_validators_no_leak(spec, state): + yield from rewards_helpers.run_test_with_not_yet_activated_validators( + spec, + state, + run_get_inactivity_penalty_deltas, + ) + + +@with_all_phases +@spec_state_test +def test_with_not_yet_activated_validators_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_with_not_yet_activated_validators( + spec, + state, + run_get_inactivity_penalty_deltas, + ) + + @with_all_phases @spec_state_test def test_with_exited_validators_no_leak(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inclusion_delay_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inclusion_delay_deltas.py index 64e1a1796..94fef5777 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inclusion_delay_deltas.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inclusion_delay_deltas.py @@ -83,6 +83,12 @@ def test_full_but_partial_participation(spec, state): yield from rewards_helpers.run_test_full_but_partial_participation(spec, state, run_get_inclusion_delay_deltas) +@with_all_phases +@spec_state_test +def test_with_not_yet_activated_validators(spec, state): + yield from rewards_helpers.run_test_with_not_yet_activated_validators(spec, state, run_get_inclusion_delay_deltas) + + @with_all_phases @spec_state_test def test_with_exited_validators(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py index 54f8f3b5d..1d7891eca 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py @@ -48,6 +48,12 @@ def test_one_attestation_one_correct(spec, state): yield from rewards_helpers.run_test_one_attestation_one_correct(spec, state, run_get_source_deltas) +@with_all_phases +@spec_state_test +def test_with_not_yet_activated_validators(spec, state): + yield from rewards_helpers.run_test_with_not_yet_activated_validators(spec, state, run_get_source_deltas) + + @with_all_phases @spec_state_test def test_with_exited_validators(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py index 0ae985086..5a02a246b 100644 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py @@ -48,6 +48,18 @@ def test_one_attestation_one_correct(spec, state): yield from rewards_helpers.run_test_one_attestation_one_correct(spec, state, run_get_target_deltas) +@with_all_phases +@spec_state_test +def test_with_not_yet_activated_validators(spec, state): + yield from rewards_helpers.run_test_with_not_yet_activated_validators(spec, state, run_get_target_deltas) + + +@with_all_phases +@spec_state_test +def test_with_exited_validators(spec, state): + yield from rewards_helpers.run_test_with_exited_validators(spec, state, run_get_target_deltas) + + @with_all_phases @spec_state_test def test_with_slashed_validators(spec, state):