From 8060505743911f6855254a386a07f5efd85cabeb Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 18 May 2020 16:00:59 -0600 Subject: [PATCH] refactor rewards/penalties tests to use a single structure --- .../pyspec/eth2spec/test/helpers/rewards.py | 250 +++++++++++++++--- ...est_get_source_deltas.py => test_basic.py} | 88 +++--- .../phase_0/rewards/test_get_head_deltas.py | 136 ---------- .../test_get_inactivity_penalty_deltas.py | 231 ---------------- .../test_get_inclusion_delay_deltas.py | 213 --------------- .../phase_0/rewards/test_get_target_deltas.py | 140 ---------- .../test/phase_0/rewards/test_leak.py | 165 ++++++++++++ .../test/phase_0/rewards/test_random.py | 22 ++ tests/formats/rewards/README.md | 57 ++-- tests/generators/rewards/main.py | 24 +- 10 files changed, 504 insertions(+), 822 deletions(-) rename tests/core/pyspec/eth2spec/test/phase_0/rewards/{test_get_source_deltas.py => test_basic.py} (67%) delete mode 100644 tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py delete mode 100644 tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inactivity_penalty_deltas.py delete mode 100644 tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inclusion_delay_deltas.py delete mode 100644 tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py create mode 100644 tests/core/pyspec/eth2spec/test/phase_0/rewards/test_leak.py create mode 100644 tests/core/pyspec/eth2spec/test/phase_0/rewards/test_random.py diff --git a/tests/core/pyspec/eth2spec/test/helpers/rewards.py b/tests/core/pyspec/eth2spec/test/helpers/rewards.py index 9c445f968..fc9f1f93a 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/rewards.py +++ b/tests/core/pyspec/eth2spec/test/helpers/rewards.py @@ -25,17 +25,50 @@ def has_enough_for_reward(spec, state, index): ) -def run_attestation_component_deltas(spec, state, component_delta_fn, matching_att_fn): +def run_deltas(spec, state): """ - Run ``component_delta_fn``, yielding: + Run all deltas functions yielding: - pre-state ('pre') - - deltas ('deltas') + - source deltas ('source_deltas') + - target deltas ('target_deltas') + - head deltas ('head_deltas') + - inclusion delay deltas ('inclusion_delay_deltas') + - inactivity penalty deltas ('inactivity_penalty_deltas') """ yield 'pre', state + yield from run_attestation_component_deltas( + spec, + state, + spec.get_source_deltas, + spec.get_matching_source_attestations, + 'source_deltas', + ) + yield from run_attestation_component_deltas( + spec, + state, + spec.get_target_deltas, + spec.get_matching_target_attestations, + 'target_deltas', + ) + yield from run_attestation_component_deltas( + spec, + state, + spec.get_head_deltas, + spec.get_matching_head_attestations, + 'head_deltas', + ) + yield from run_get_inclusion_delay_deltas(spec, state) + yield from run_get_inactivity_penalty_deltas(spec, state) + +def run_attestation_component_deltas(spec, state, component_delta_fn, matching_att_fn, deltas_name): + """ + Run ``component_delta_fn``, yielding: + - deltas ('{``deltas_name``}') + """ rewards, penalties = component_delta_fn(state) - yield 'deltas', Deltas(rewards=rewards, penalties=penalties) + yield deltas_name, Deltas(rewards=rewards, penalties=penalties) matching_attestations = matching_att_fn(state, spec.get_previous_epoch(state)) matching_indices = spec.get_unslashed_attesting_indices(state, matching_attestations) @@ -62,6 +95,81 @@ def run_attestation_component_deltas(spec, state, component_delta_fn, matching_a assert penalties[index] == 0 +def run_get_inclusion_delay_deltas(spec, state): + """ + Run ``get_inclusion_delay_deltas``, yielding: + - inclusion delay deltas ('inclusion_delay_deltas') + """ + rewards, penalties = spec.get_inclusion_delay_deltas(state) + + yield 'inclusion_delay_deltas', Deltas(rewards=rewards, penalties=penalties) + + eligible_attestations = spec.get_matching_source_attestations(state, spec.get_previous_epoch(state)) + attesting_indices = spec.get_unslashed_attesting_indices(state, eligible_attestations) + + rewarded_indices = set() + rewarded_proposer_indices = set() + # Ensure attesters with enough balance are rewarded for attestations + # Track those that are rewarded and track proposers that should be rewarded + for index in range(len(state.validators)): + if index in attesting_indices and has_enough_for_reward(spec, state, index): + assert rewards[index] > 0 + rewarded_indices.add(index) + + # Track proposer of earliest included attestation for the validator defined by index + earliest_attestation = min([ + a for a in eligible_attestations + if index in spec.get_attesting_indices(state, a.data, a.aggregation_bits) + ], key=lambda a: a.inclusion_delay) + rewarded_proposer_indices.add(earliest_attestation.proposer_index) + + # Ensure all expected proposers have been rewarded + # Track rewarde indices + proposing_indices = [a.proposer_index for a in eligible_attestations] + for index in proposing_indices: + if index in rewarded_proposer_indices: + assert rewards[index] > 0 + rewarded_indices.add(index) + + # Ensure all expected non-rewarded indices received no reward + for index in range(len(state.validators)): + assert penalties[index] == 0 + if index not in rewarded_indices: + assert rewards[index] == 0 + + +def run_get_inactivity_penalty_deltas(spec, state): + """ + Run ``get_inactivity_penalty_deltas``, yielding: + - inactivity penalty deltas ('inactivity_penalty_deltas') + """ + rewards, penalties = spec.get_inactivity_penalty_deltas(state) + + yield 'inactivity_penalty_deltas', Deltas(rewards=rewards, penalties=penalties) + + matching_attestations = spec.get_matching_target_attestations(state, spec.get_previous_epoch(state)) + matching_attesting_indices = spec.get_unslashed_attesting_indices(state, matching_attestations) + + finality_delay = spec.get_previous_epoch(state) - state.finalized_checkpoint.epoch + eligible_indices = spec.get_eligible_validator_indices(state) + for index in range(len(state.validators)): + assert rewards[index] == 0 + if index not in eligible_indices: + assert penalties[index] == 0 + continue + + if finality_delay > spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY: + base_penalty = spec.BASE_REWARDS_PER_EPOCH * spec.get_base_reward(state, index) + if not has_enough_for_reward(spec, state, index): + assert penalties[index] == 0 + elif index in matching_attesting_indices: + assert penalties[index] == base_penalty + else: + assert penalties[index] > base_penalty + else: + assert penalties[index] == 0 + + def set_some_new_deposits(spec, state, rng): num_validators = len(state.validators) # Set ~1/10 to just recently deposited @@ -102,74 +210,74 @@ def slash_random_validators(spec, state, rng): spec.slash_validator(state, index) -def run_test_empty(spec, state, runner): +def run_test_empty(spec, state): # Do not add any attestations to state - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_full_all_correct(spec, state, runner): +def run_test_full_all_correct(spec, state): prepare_state_with_attestations(spec, state) - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_full_but_partial_participation(spec, state, runner, rng=Random(5522)): +def run_test_full_but_partial_participation(spec, state, rng=Random(5522)): prepare_state_with_attestations(spec, state) for a in state.previous_epoch_attestations: a.aggregation_bits = [rng.choice([True, False]) for _ in a.aggregation_bits] - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_partial(spec, state, fraction_filled, runner): +def run_test_partial(spec, state, fraction_filled): prepare_state_with_attestations(spec, state) # Remove portion of attestations num_attestations = int(len(state.previous_epoch_attestations) * fraction_filled) state.previous_epoch_attestations = state.previous_epoch_attestations[:num_attestations] - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_half_full(spec, state, runner): - yield from run_test_partial(spec, state, 0.5, runner) +def run_test_half_full(spec, state): + yield from run_test_partial(spec, state, 0.5) -def run_test_one_attestation_one_correct(spec, state, runner): +def run_test_one_attestation_one_correct(spec, state): prepare_state_with_attestations(spec, state) # Remove all attestations except for the first one state.previous_epoch_attestations = state.previous_epoch_attestations[:1] - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_with_not_yet_activated_validators(spec, state, runner, rng=Random(5555)): +def run_test_with_not_yet_activated_validators(spec, state, rng=Random(5555)): set_some_new_deposits(spec, state, rng) prepare_state_with_attestations(spec, state) - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_with_exited_validators(spec, state, runner, rng=Random(1337)): +def run_test_with_exited_validators(spec, state, rng=Random(1337)): exit_random_validators(spec, state, rng) prepare_state_with_attestations(spec, state) - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_with_slashed_validators(spec, state, runner, rng=Random(3322)): +def run_test_with_slashed_validators(spec, state, rng=Random(3322)): exit_random_validators(spec, state, rng) slash_random_validators(spec, state, rng) prepare_state_with_attestations(spec, state) - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_some_very_low_effective_balances_that_attested(spec, state, runner): +def run_test_some_very_low_effective_balances_that_attested(spec, state): state.balances prepare_state_with_attestations(spec, state) @@ -178,10 +286,10 @@ def run_test_some_very_low_effective_balances_that_attested(spec, state, runner) for i, index in enumerate(range(5)): state.validators[index].effective_balance = i - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_some_very_low_effective_balances_that_did_not_attest(spec, state, runner): +def run_test_some_very_low_effective_balances_that_did_not_attest(spec, state): prepare_state_with_attestations(spec, state) # Remove attestation @@ -192,10 +300,10 @@ def run_test_some_very_low_effective_balances_that_did_not_attest(spec, state, r for i, index in enumerate(indices): state.validators[index].effective_balance = i - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_full_fraction_incorrect(spec, state, correct_target, correct_head, fraction_incorrect, runner): +def run_test_full_fraction_incorrect(spec, state, correct_target, correct_head, fraction_incorrect): prepare_state_with_attestations(spec, state) # Make fraction_incorrect of pending attestations have bad target/head as specified @@ -206,10 +314,92 @@ def run_test_full_fraction_incorrect(spec, state, correct_target, correct_head, if not correct_head: pending_attestation.data.beacon_block_root = b'\x66' * 32 - yield from runner(spec, state) + yield from run_deltas(spec, state) -def run_test_full_random(spec, state, runner, rng=Random(8020)): +def run_test_full_delay_one_slot(spec, state): + prepare_state_with_attestations(spec, state) + for a in state.previous_epoch_attestations: + a.inclusion_delay += 1 + + yield from run_deltas(spec, state) + + +def run_test_full_delay_max_slots(spec, state): + prepare_state_with_attestations(spec, state) + for a in state.previous_epoch_attestations: + a.inclusion_delay += spec.SLOTS_PER_EPOCH + + yield from run_deltas(spec, state) + + +def run_test_full_mixed_delay(spec, state, rng=Random(1234)): + prepare_state_with_attestations(spec, state) + for a in state.previous_epoch_attestations: + a.inclusion_delay = rng.randint(1, spec.SLOTS_PER_EPOCH) + + yield from run_deltas(spec, state) + + +def run_test_proposer_not_in_attestations(spec, state): + prepare_state_with_attestations(spec, state) + + # Get an attestation where the proposer is not in the committee + non_proposer_attestations = [] + for a in state.previous_epoch_attestations: + if a.proposer_index not in spec.get_unslashed_attesting_indices(state, [a]): + non_proposer_attestations.append(a) + + assert any(non_proposer_attestations) + state.previous_epoch_attestations = non_proposer_attestations + + yield from run_deltas(spec, state) + + +def run_test_duplicate_attestations_at_later_slots(spec, state): + prepare_state_with_attestations(spec, state) + + # Remove 2/3 of attestations to make it more interesting + num_attestations = int(len(state.previous_epoch_attestations) * 0.33) + state.previous_epoch_attestations = state.previous_epoch_attestations[:num_attestations] + + # Get map of the proposer at each slot to make valid-looking duplicate attestations + per_slot_proposers = { + (a.data.slot + a.inclusion_delay): a.proposer_index + for a in state.previous_epoch_attestations + } + max_slot = max([a.data.slot + a.inclusion_delay for a in state.previous_epoch_attestations]) + later_attestations = [] + for a in state.previous_epoch_attestations: + # Only have proposers for previous epoch so do not create later + # duplicate if slot exceeds the max slot in previous_epoch_attestations + if a.data.slot + a.inclusion_delay >= max_slot: + continue + later_a = a.copy() + later_a.inclusion_delay += 1 + later_a.proposer_index = per_slot_proposers[later_a.data.slot + later_a.inclusion_delay] + later_attestations.append(later_a) + + assert any(later_attestations) + + state.previous_epoch_attestations = sorted( + state.previous_epoch_attestations + later_attestations, + key=lambda a: a.data.slot + a.inclusion_delay + ) + + yield from run_deltas(spec, state) + + +def run_test_all_balances_too_low_for_reward(spec, state): + prepare_state_with_attestations(spec, state) + + for index in range(len(state.validators)): + state.validators[index].effective_balance = 10 + + yield from run_deltas(spec, state) + + +def run_test_full_random(spec, state, rng=Random(8020)): set_some_new_deposits(spec, state, rng) exit_random_validators(spec, state, rng) slash_random_validators(spec, state, rng) @@ -228,4 +418,4 @@ def run_test_full_random(spec, state, runner, rng=Random(8020)): # Random inclusion delay pending_attestation.inclusion_delay = rng.randint(1, spec.SLOTS_PER_EPOCH) - yield from runner(spec, state) + yield from run_deltas(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_basic.py similarity index 67% rename from tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py rename to tests/core/pyspec/eth2spec/test/phase_0/rewards/test_basic.py index 1d7891eca..92277fdd7 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_basic.py @@ -1,89 +1,71 @@ from eth2spec.test.context import with_all_phases, spec_state_test -from eth2spec.test.helpers.rewards import run_attestation_component_deltas import eth2spec.test.helpers.rewards as rewards_helpers -def run_get_source_deltas(spec, state): - """ - Run ``get_source_deltas``, yielding: - - pre-state ('pre') - - deltas ('deltas') - """ - - yield from run_attestation_component_deltas( - spec, - state, - spec.get_source_deltas, - spec.get_matching_source_attestations, - ) - - @with_all_phases @spec_state_test def test_empty(spec, state): - yield from rewards_helpers.run_test_empty(spec, state, run_get_source_deltas) + yield from rewards_helpers.run_test_empty(spec, state) @with_all_phases @spec_state_test def test_full_all_correct(spec, state): - yield from rewards_helpers.run_test_full_all_correct(spec, state, run_get_source_deltas) + yield from rewards_helpers.run_test_full_all_correct(spec, state) @with_all_phases @spec_state_test def test_half_full(spec, state): - yield from rewards_helpers.run_test_half_full(spec, state, run_get_source_deltas) + yield from rewards_helpers.run_test_half_full(spec, state) + + +@with_all_phases +@spec_state_test +def test_quarter_full(spec, state): + yield from rewards_helpers.run_test_partial(spec, state, 0.25) @with_all_phases @spec_state_test def test_full_but_partial_participation(spec, state): - yield from rewards_helpers.run_test_full_but_partial_participation(spec, state, run_get_source_deltas) + yield from rewards_helpers.run_test_full_but_partial_participation(spec, state) @with_all_phases @spec_state_test def test_one_attestation_one_correct(spec, state): - yield from rewards_helpers.run_test_one_attestation_one_correct(spec, state, run_get_source_deltas) + yield from rewards_helpers.run_test_one_attestation_one_correct(spec, state) @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) + yield from rewards_helpers.run_test_with_not_yet_activated_validators(spec, state) @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_source_deltas) + yield from rewards_helpers.run_test_with_exited_validators(spec, state) @with_all_phases @spec_state_test def test_with_slashed_validators(spec, state): - yield from rewards_helpers.run_test_with_slashed_validators(spec, state, run_get_source_deltas) + yield from rewards_helpers.run_test_with_slashed_validators(spec, state) @with_all_phases @spec_state_test def test_some_very_low_effective_balances_that_attested(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested( - spec, - state, - run_get_source_deltas - ) + yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested(spec, state) @with_all_phases @spec_state_test def test_some_very_low_effective_balances_that_did_not_attest(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest( - spec, - state, - run_get_source_deltas, - ) + yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest(spec, state) # @@ -101,7 +83,6 @@ def test_full_half_correct_target_incorrect_head(spec, state): correct_target=True, correct_head=False, fraction_incorrect=0.5, - runner=run_get_source_deltas ) @@ -113,7 +94,6 @@ def test_full_correct_target_incorrect_head(spec, state): correct_target=True, correct_head=False, fraction_incorrect=1.0, - runner=run_get_source_deltas ) @@ -125,7 +105,6 @@ def test_full_half_incorrect_target_incorrect_head(spec, state): correct_target=False, correct_head=False, fraction_incorrect=0.5, - runner=run_get_source_deltas ) @@ -137,11 +116,40 @@ def test_full_half_incorrect_target_correct_head(spec, state): correct_target=False, correct_head=True, fraction_incorrect=0.5, - runner=run_get_source_deltas ) @with_all_phases @spec_state_test -def test_full_random(spec, state): - yield from rewards_helpers.run_test_full_random(spec, state, run_get_source_deltas) +def test_full_delay_one_slot(spec, state): + yield from rewards_helpers.run_test_full_delay_one_slot(spec, state) + + +@with_all_phases +@spec_state_test +def test_full_delay_max_slots(spec, state): + yield from rewards_helpers.run_test_full_delay_max_slots(spec, state) + + +@with_all_phases +@spec_state_test +def test_full_mixed_delay(spec, state): + yield from rewards_helpers.run_test_full_mixed_delay(spec, state) + + +@with_all_phases +@spec_state_test +def test_proposer_not_in_attestations(spec, state): + yield from rewards_helpers.run_test_proposer_not_in_attestations(spec, state) + + +@with_all_phases +@spec_state_test +def test_duplicate_attestations_at_later_slots(spec, state): + yield from rewards_helpers.run_test_duplicate_attestations_at_later_slots(spec, state) + + +@with_all_phases +@spec_state_test +def test_all_balances_too_low_for_reward(spec, state): + yield from rewards_helpers.run_test_all_balances_too_low_for_reward(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 deleted file mode 100644 index e49a8567c..000000000 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py +++ /dev/null @@ -1,136 +0,0 @@ -from eth2spec.test.context import with_all_phases, spec_state_test -from eth2spec.test.helpers.rewards import run_attestation_component_deltas -import eth2spec.test.helpers.rewards as rewards_helpers - - -def run_get_head_deltas(spec, state): - """ - Run ``get_head_deltas``, yielding: - - pre-state ('pre') - - deltas ('deltas') - """ - - yield from run_attestation_component_deltas( - spec, - state, - spec.get_head_deltas, - spec.get_matching_head_attestations, - ) - - -@with_all_phases -@spec_state_test -def test_empty(spec, state): - yield from rewards_helpers.run_test_empty(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -def test_full_all_correct(spec, state): - yield from rewards_helpers.run_test_full_all_correct(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -def test_half_full(spec, state): - yield from rewards_helpers.run_test_half_full(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -def test_full_but_partial_participation(spec, state): - yield from rewards_helpers.run_test_full_but_partial_participation(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -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): - yield from rewards_helpers.run_test_with_exited_validators(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -def test_with_slashed_validators(spec, state): - yield from rewards_helpers.run_test_with_slashed_validators(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_attested(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested(spec, state, run_get_head_deltas) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_did_not_attest(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest( - spec, - state, - run_get_head_deltas, - ) - - -@with_all_phases -@spec_state_test -def test_full_half_correct_target_incorrect_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=True, - correct_head=False, - fraction_incorrect=0.5, - runner=run_get_head_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_correct_target_incorrect_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=True, - correct_head=False, - fraction_incorrect=1.0, - runner=run_get_head_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_half_incorrect_target_incorrect_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=False, - correct_head=False, - fraction_incorrect=0.5, - runner=run_get_head_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_half_incorrect_target_correct_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=False, - correct_head=True, - fraction_incorrect=0.5, - runner=run_get_head_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_random(spec, state): - yield from rewards_helpers.run_test_full_random(spec, state, run_get_head_deltas) 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 deleted file mode 100644 index 8588b3f52..000000000 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inactivity_penalty_deltas.py +++ /dev/null @@ -1,231 +0,0 @@ -from eth2spec.test.context import with_all_phases, spec_state_test -from eth2spec.test.helpers.rewards import has_enough_for_reward -from eth2spec.test.helpers.state import next_epoch -from eth2spec.test.helpers.rewards import Deltas -import eth2spec.test.helpers.rewards as rewards_helpers - - -def run_get_inactivity_penalty_deltas(spec, state): - """ - Run ``get_inactivity_penalty_deltas``, yielding: - - pre-state ('pre') - - deltas ('deltas') - """ - - yield 'pre', state - - rewards, penalties = spec.get_inactivity_penalty_deltas(state) - - yield 'deltas', Deltas(rewards=rewards, penalties=penalties) - - matching_attestations = spec.get_matching_target_attestations(state, spec.get_previous_epoch(state)) - matching_attesting_indices = spec.get_unslashed_attesting_indices(state, matching_attestations) - - finality_delay = spec.get_previous_epoch(state) - state.finalized_checkpoint.epoch - eligible_indices = spec.get_eligible_validator_indices(state) - for index in range(len(state.validators)): - assert rewards[index] == 0 - if index not in eligible_indices: - assert penalties[index] == 0 - continue - - if finality_delay > spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY: - base_penalty = spec.BASE_REWARDS_PER_EPOCH * spec.get_base_reward(state, index) - if not has_enough_for_reward(spec, state, index): - assert penalties[index] == 0 - elif index in matching_attesting_indices: - assert penalties[index] == base_penalty - else: - assert penalties[index] > base_penalty - else: - assert penalties[index] == 0 - - -def transition_state_to_leak(spec, state, epochs=None): - if epochs is None: - epochs = spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY - assert epochs >= spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY - - for _ in range(epochs): - next_epoch(spec, state) - - -@with_all_phases -@spec_state_test -def test_empty_no_leak(spec, state): - yield from rewards_helpers.run_test_empty(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_empty_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_empty(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_full_no_leak(spec, state): - yield from rewards_helpers.run_test_full_all_correct(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_full_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_full_all_correct(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_half_full_no_leak(spec, state): - yield from rewards_helpers.run_test_half_full(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_half_full_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_half_full(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_quarter_full_no_leak(spec, state): - yield from rewards_helpers.run_test_partial(spec, state, 0.25, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_quarter_full_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_partial(spec, state, 0.25, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_full_but_partial_participation_no_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_full_but_partial_participation_leak(spec, state): - transition_state_to_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): - yield from rewards_helpers.run_test_with_exited_validators(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_with_exited_validators_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_with_exited_validators(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_with_slashed_validators_no_leak(spec, state): - yield from rewards_helpers.run_test_with_slashed_validators(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_with_slashed_validators_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_with_slashed_validators(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_attested_no_leak(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested( - spec, - state, - run_get_inactivity_penalty_deltas, - ) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_attested_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested( - spec, - state, - run_get_inactivity_penalty_deltas, - ) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_did_not_attest_no_leak(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest( - spec, - state, - run_get_inactivity_penalty_deltas, - ) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_did_not_attest_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest( - spec, - state, - run_get_inactivity_penalty_deltas, - ) - - -@with_all_phases -@spec_state_test -def test_full_random_no_leak(spec, state): - yield from rewards_helpers.run_test_full_random(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_full_random_leak(spec, state): - transition_state_to_leak(spec, state) - yield from rewards_helpers.run_test_full_random(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_full_random_five_epoch_leak(spec, state): - transition_state_to_leak(spec, state, epochs=5) - yield from rewards_helpers.run_test_full_random(spec, state, run_get_inactivity_penalty_deltas) - - -@with_all_phases -@spec_state_test -def test_full_random_ten_epoch_leak(spec, state): - transition_state_to_leak(spec, state, epochs=10) - yield from rewards_helpers.run_test_full_random(spec, state, run_get_inactivity_penalty_deltas) 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 deleted file mode 100644 index 94fef5777..000000000 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_inclusion_delay_deltas.py +++ /dev/null @@ -1,213 +0,0 @@ -from random import Random - -from eth2spec.test.context import with_all_phases, spec_state_test -from eth2spec.test.helpers.attestations import prepare_state_with_attestations -from eth2spec.test.helpers.rewards import Deltas, has_enough_for_reward -import eth2spec.test.helpers.rewards as rewards_helpers - - -def run_get_inclusion_delay_deltas(spec, state): - """ - Run ``get_inclusion_delay_deltas``, yielding: - - pre-state ('pre') - - deltas ('deltas') - """ - - yield 'pre', state - - rewards, penalties = spec.get_inclusion_delay_deltas(state) - - yield 'deltas', Deltas(rewards=rewards, penalties=penalties) - - eligible_attestations = spec.get_matching_source_attestations(state, spec.get_previous_epoch(state)) - attesting_indices = spec.get_unslashed_attesting_indices(state, eligible_attestations) - - rewarded_indices = set() - rewarded_proposer_indices = set() - # Ensure attesters with enough balance are rewarded for attestations - # Track those that are rewarded and track proposers that should be rewarded - for index in range(len(state.validators)): - if index in attesting_indices and has_enough_for_reward(spec, state, index): - assert rewards[index] > 0 - rewarded_indices.add(index) - - # Track proposer of earliest included attestation for the validator defined by index - earliest_attestation = min([ - a for a in eligible_attestations - if index in spec.get_attesting_indices(state, a.data, a.aggregation_bits) - ], key=lambda a: a.inclusion_delay) - rewarded_proposer_indices.add(earliest_attestation.proposer_index) - - # Ensure all expected proposers have been rewarded - # Track rewarde indices - proposing_indices = [a.proposer_index for a in eligible_attestations] - for index in proposing_indices: - if index in rewarded_proposer_indices: - assert rewards[index] > 0 - rewarded_indices.add(index) - - # Ensure all expected non-rewarded indices received no reward - for index in range(len(state.validators)): - assert penalties[index] == 0 - if index not in rewarded_indices: - assert rewards[index] == 0 - - -@with_all_phases -@spec_state_test -def test_empty(spec, state): - yield from rewards_helpers.run_test_empty(spec, state, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -def test_full(spec, state): - yield from rewards_helpers.run_test_full_all_correct(spec, state, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -def test_half_full(spec, state): - yield from rewards_helpers.run_test_half_full(spec, state, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -def test_quarter_full(spec, state): - yield from rewards_helpers.run_test_partial(spec, state, 0.25, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -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): - yield from rewards_helpers.run_test_with_exited_validators(spec, state, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -def test_with_slashed_validators(spec, state): - yield from rewards_helpers.run_test_with_slashed_validators(spec, state, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_attested(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested( - spec, - state, - run_get_inclusion_delay_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_random(spec, state): - yield from rewards_helpers.run_test_full_random(spec, state, run_get_inclusion_delay_deltas) - - -@with_all_phases -@spec_state_test -def test_full_delay_one_slot(spec, state): - prepare_state_with_attestations(spec, state) - for a in state.previous_epoch_attestations: - a.inclusion_delay += 1 - - yield from run_get_inclusion_delay_deltas(spec, state) - - -@with_all_phases -@spec_state_test -def test_full_delay_max_slots(spec, state): - prepare_state_with_attestations(spec, state) - for a in state.previous_epoch_attestations: - a.inclusion_delay += spec.SLOTS_PER_EPOCH - - yield from run_get_inclusion_delay_deltas(spec, state) - - -@with_all_phases -@spec_state_test -def test_full_mixed_delay(spec, state): - rng = Random(1234) - - prepare_state_with_attestations(spec, state) - for a in state.previous_epoch_attestations: - a.inclusion_delay = rng.randint(1, spec.SLOTS_PER_EPOCH) - - yield from run_get_inclusion_delay_deltas(spec, state) - - -@with_all_phases -@spec_state_test -def test_proposer_not_in_attestations(spec, state): - prepare_state_with_attestations(spec, state) - - # Get an attestation where the proposer is not in the committee - non_proposer_attestations = [] - for a in state.previous_epoch_attestations: - if a.proposer_index not in spec.get_unslashed_attesting_indices(state, [a]): - non_proposer_attestations.append(a) - - assert any(non_proposer_attestations) - state.previous_epoch_attestations = non_proposer_attestations - - yield from run_get_inclusion_delay_deltas(spec, state) - - -@with_all_phases -@spec_state_test -def test_duplicate_attestations_at_later_slots(spec, state): - prepare_state_with_attestations(spec, state) - - # Remove 2/3 of attestations to make it more interesting - num_attestations = int(len(state.previous_epoch_attestations) * 0.33) - state.previous_epoch_attestations = state.previous_epoch_attestations[:num_attestations] - - # Get map of the proposer at each slot to make valid-looking duplicate attestations - per_slot_proposers = { - (a.data.slot + a.inclusion_delay): a.proposer_index - for a in state.previous_epoch_attestations - } - max_slot = max([a.data.slot + a.inclusion_delay for a in state.previous_epoch_attestations]) - later_attestations = [] - for a in state.previous_epoch_attestations: - # Only have proposers for previous epoch so do not create later - # duplicate if slot exceeds the max slot in previous_epoch_attestations - if a.data.slot + a.inclusion_delay >= max_slot: - continue - later_a = a.copy() - later_a.inclusion_delay += 1 - later_a.proposer_index = per_slot_proposers[later_a.data.slot + later_a.inclusion_delay] - later_attestations.append(later_a) - - assert any(later_attestations) - - state.previous_epoch_attestations = sorted( - state.previous_epoch_attestations + later_attestations, - key=lambda a: a.data.slot + a.inclusion_delay - ) - - yield from run_get_inclusion_delay_deltas(spec, state) - - -@with_all_phases -@spec_state_test -def test_all_balances_too_low_for_reward(spec, state): - prepare_state_with_attestations(spec, state) - - for index in range(len(state.validators)): - state.validators[index].effective_balance = 10 - - yield from run_get_inclusion_delay_deltas(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 deleted file mode 100644 index 5a02a246b..000000000 --- a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py +++ /dev/null @@ -1,140 +0,0 @@ -from eth2spec.test.context import with_all_phases, spec_state_test -from eth2spec.test.helpers.rewards import run_attestation_component_deltas -import eth2spec.test.helpers.rewards as rewards_helpers - - -def run_get_target_deltas(spec, state): - """ - Run ``get_target_deltas``, yielding: - - pre-state ('pre') - - deltas ('deltas') - """ - - yield from run_attestation_component_deltas( - spec, - state, - spec.get_target_deltas, - spec.get_matching_target_attestations, - ) - - -@with_all_phases -@spec_state_test -def test_empty(spec, state): - yield from rewards_helpers.run_test_empty(spec, state, run_get_target_deltas) - - -@with_all_phases -@spec_state_test -def test_full_all_correct(spec, state): - yield from rewards_helpers.run_test_full_all_correct(spec, state, run_get_target_deltas) - - -@with_all_phases -@spec_state_test -def test_half_full(spec, state): - yield from rewards_helpers.run_test_half_full(spec, state, run_get_target_deltas) - - -@with_all_phases -@spec_state_test -def test_full_but_partial_participation(spec, state): - yield from rewards_helpers.run_test_full_but_partial_participation(spec, state, run_get_target_deltas) - - -@with_all_phases -@spec_state_test -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): - yield from rewards_helpers.run_test_with_slashed_validators(spec, state, run_get_target_deltas) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_attested(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested( - spec, - state, - run_get_target_deltas - ) - - -@with_all_phases -@spec_state_test -def test_some_very_low_effective_balances_that_did_not_attest(spec, state): - yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest( - spec, - state, - run_get_target_deltas, - ) - - -@with_all_phases -@spec_state_test -def test_full_half_correct_target_incorrect_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=True, - correct_head=False, - fraction_incorrect=0.5, - runner=run_get_target_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_correct_target_incorrect_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=True, - correct_head=False, - fraction_incorrect=1.0, - runner=run_get_target_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_half_incorrect_target_incorrect_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=False, - correct_head=False, - fraction_incorrect=0.5, - runner=run_get_target_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_half_incorrect_target_correct_head(spec, state): - yield from rewards_helpers.run_test_full_fraction_incorrect( - spec, state, - correct_target=False, - correct_head=True, - fraction_incorrect=0.5, - runner=run_get_target_deltas - ) - - -@with_all_phases -@spec_state_test -def test_full_random(spec, state): - yield from rewards_helpers.run_test_full_random(spec, state, run_get_target_deltas) diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_leak.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_leak.py new file mode 100644 index 000000000..562a99b4b --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_leak.py @@ -0,0 +1,165 @@ +from eth2spec.test.context import with_all_phases, spec_state_test +from eth2spec.test.helpers.state import next_epoch +import eth2spec.test.helpers.rewards as rewards_helpers + + +def transition_state_to_leak(spec, state, epochs=None): + if epochs is None: + epochs = spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + assert epochs >= spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + + for _ in range(epochs): + next_epoch(spec, state) + + +@with_all_phases +@spec_state_test +def test_empty_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_empty(spec, state) + + +@with_all_phases +@spec_state_test +def test_full_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_all_correct(spec, state) + + +@with_all_phases +@spec_state_test +def test_half_full_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_half_full(spec, state) + + +@with_all_phases +@spec_state_test +def test_quarter_full_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_partial(spec, state, 0.25) + + +@with_all_phases +@spec_state_test +def test_full_but_partial_participation_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_but_partial_participation(spec, state) + + +@with_all_phases +@spec_state_test +def test_one_attestation_one_correct_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_one_attestation_one_correct(spec, state) + + +@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) + + +@with_all_phases +@spec_state_test +def test_with_exited_validators_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_with_exited_validators(spec, state) + + +@with_all_phases +@spec_state_test +def test_with_slashed_validators_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_with_slashed_validators(spec, state) + + +@with_all_phases +@spec_state_test +def test_some_very_low_effective_balances_that_attested_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_some_very_low_effective_balances_that_attested(spec, state) + + +@with_all_phases +@spec_state_test +def test_some_very_low_effective_balances_that_did_not_attest_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_some_very_low_effective_balances_that_did_not_attest(spec, state) + + +# +# NOTE: No source incorrect tests +# All PendingAttestations in state have source validated +# We choose to keep this invariant in these tests to not force clients to test with degenerate states +# + + +@with_all_phases +@spec_state_test +def test_full_half_correct_target_incorrect_head_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_fraction_incorrect( + spec, state, + correct_target=True, + correct_head=False, + fraction_incorrect=0.5, + ) + + +@with_all_phases +@spec_state_test +def test_full_correct_target_incorrect_head_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_fraction_incorrect( + spec, state, + correct_target=True, + correct_head=False, + fraction_incorrect=1.0, + ) + + +@with_all_phases +@spec_state_test +def test_full_half_incorrect_target_incorrect_head_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_fraction_incorrect( + spec, state, + correct_target=False, + correct_head=False, + fraction_incorrect=0.5, + ) + + +@with_all_phases +@spec_state_test +def test_full_half_incorrect_target_correct_head_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_fraction_incorrect( + spec, state, + correct_target=False, + correct_head=True, + fraction_incorrect=0.5, + ) + + +@with_all_phases +@spec_state_test +def test_full_random_leak(spec, state): + transition_state_to_leak(spec, state) + yield from rewards_helpers.run_test_full_random(spec, state) + + +@with_all_phases +@spec_state_test +def test_full_random_five_epoch_leak(spec, state): + transition_state_to_leak(spec, state, epochs=5) + yield from rewards_helpers.run_test_full_random(spec, state) + + +@with_all_phases +@spec_state_test +def test_full_random_ten_epoch_leak(spec, state): + transition_state_to_leak(spec, state, epochs=10) + yield from rewards_helpers.run_test_full_random(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_random.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_random.py new file mode 100644 index 000000000..bda0ca687 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_random.py @@ -0,0 +1,22 @@ +from random import Random + +from eth2spec.test.context import with_all_phases, spec_state_test +import eth2spec.test.helpers.rewards as rewards_helpers + + +@with_all_phases +@spec_state_test +def test_full_random_0(spec, state): + yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(1010)) + + +@with_all_phases +@spec_state_test +def test_full_random_1(spec, state): + yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(2020)) + + +@with_all_phases +@spec_state_test +def test_full_random_2(spec, state): + yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(3030)) diff --git a/tests/formats/rewards/README.md b/tests/formats/rewards/README.md index f70a20f9c..b00e7a32a 100644 --- a/tests/formats/rewards/README.md +++ b/tests/formats/rewards/README.md @@ -1,8 +1,15 @@ # Rewards tests -The different rewards deltas sub-functions are testing individually with the test handlers, each returning the related `rewards`/`penalties`. +All rewards deltas sub-functions are tested for each test case. There is no "change" factor, the rewards/penalties outputs are pure functions with just the pre-state as input. -Hence, the format is shared between each test-handler. (See test condition documentation on how to run the tests.) +(See test condition documentation on how to run the tests.) + +`Deltas` is defined as: +```python +class Deltas(Container): + rewards: List[uint64, VALIDATOR_REGISTRY_LIMIT] + penalties: List[uint64, VALIDATOR_REGISTRY_LIMIT] +``` ## Test case format @@ -22,31 +29,47 @@ A YAML-encoded `BeaconState`, the state before running the rewards sub-function. Also available as `pre.ssz`. -### `deltas.yaml` +### `source_deltas.yaml` -A YAML-encoded `Deltas` representing the rewards and penalties returned by the rewards sub-function +A YAML-encoded `Deltas` representing the rewards and penalties returned by the rewards the `get_source_deltas` function -Where `Deltas` is defined as: -```python -class Deltas(Container): - rewards: List[uint64, VALIDATOR_REGISTRY_LIMIT] - penalties: List[uint64, VALIDATOR_REGISTRY_LIMIT] -``` +Also available as `source_deltas.ssz`. -Also available as `deltas.ssz`. +### `target_deltas.yaml` + +A YAML-encoded `Deltas` representing the rewards and penalties returned by the rewards the `get_target_deltas` function + +Also available as `target_deltas.ssz`. + +### `head_deltas.yaml` + +A YAML-encoded `Deltas` representing the rewards and penalties returned by the rewards the `get_head_deltas` function + +Also available as `head_deltas.ssz`. + +### `inclusion_delay_deltas.yaml` + +A YAML-encoded `Deltas` representing the rewards and penalties returned by the rewards the `get_inclusion_delay_deltas` function + +Also available as `inclusion_delay_deltas.ssz`. + +### `inactivity_penalty_deltas.yaml` + +A YAML-encoded `Deltas` representing the rewards and penalties returned by the rewards the `get_inactivity_penalty_deltas` function + +Also available as `inactivity_penalty_deltas.ssz`. ## Condition A handler of the `rewards` test-runner should process these cases, - calling the corresponding rewards deltas function (same name in spec). -This excludes all other parts of `process_rewards_and_penalties` + calling the corresponding rewards deltas function for each set of deltas. -The provided pre-state is ready to be input into the designated handler. +The provided pre-state is ready to be input into each rewards deltas function. The provided `deltas` should match the return values of the - handler. Specifically the following must hold true: + deltas function. Specifically the following must hold true for each set of deltas: ```python - deltas.rewards == handler(state)[0] - deltas.penalties == handler(state)[1] + deltas.rewards == deltas_function(state)[0] + deltas.penalties == deltas_function(state)[1] ``` diff --git a/tests/generators/rewards/main.py b/tests/generators/rewards/main.py index fd95dcfaa..d8dae74fa 100644 --- a/tests/generators/rewards/main.py +++ b/tests/generators/rewards/main.py @@ -3,11 +3,9 @@ from typing import Iterable from eth2spec.phase0 import spec as spec_phase0 from eth2spec.phase1 import spec as spec_phase1 from eth2spec.test.phase_0.rewards import ( - test_get_source_deltas, - test_get_target_deltas, - test_get_head_deltas, - test_get_inclusion_delay_deltas, - test_get_inactivity_penalty_deltas, + test_basic, + test_leak, + test_random, ) from gen_base import gen_runner, gen_typing from gen_from_tests.gen import generate_from_tests @@ -37,14 +35,10 @@ def create_provider(handler_name: str, tests_src, config_name: str) -> gen_typin if __name__ == "__main__": gen_runner.run_generator("epoch_processing", [ - create_provider('get_source_deltas', test_get_source_deltas, 'minimal'), - create_provider('get_source_deltas', test_get_source_deltas, 'mainnet'), - create_provider('get_target_deltas', test_get_target_deltas, 'minimal'), - create_provider('get_target_deltas', test_get_target_deltas, 'mainnet'), - create_provider('get_head_deltas', test_get_head_deltas, 'minimal'), - create_provider('get_head_deltas', test_get_head_deltas, 'mainnet'), - create_provider('get_inclusion_delay_deltas', test_get_inclusion_delay_deltas, 'minimal'), - create_provider('get_inclusion_delay_deltas', test_get_inclusion_delay_deltas, 'mainnet'), - create_provider('get_inactivity_penalty_deltas', test_get_inactivity_penalty_deltas, 'minimal'), - create_provider('get_inactivity_penalty_deltas', test_get_inactivity_penalty_deltas, 'mainnet'), + create_provider('get_deltas', test_basic, 'minimal'), + create_provider('get_deltas', test_basic, 'mainnet'), + create_provider('get_deltas', test_leak, 'minimal'), + create_provider('get_deltas', test_leak, 'mainnet'), + create_provider('get_deltas', test_random, 'minimal'), + create_provider('get_deltas', test_random, 'mainnet'), ])