diff --git a/tests/core/pyspec/eth2spec/test/helpers/rewards.py b/tests/core/pyspec/eth2spec/test/helpers/rewards.py index 41497fe60..a98aa3415 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/rewards.py +++ b/tests/core/pyspec/eth2spec/test/helpers/rewards.py @@ -1,4 +1,10 @@ from eth2spec.test.helpers.attestations import prepare_state_with_full_attestations +from eth2spec.utils.ssz.ssz_typing import Container, uint64, List + + +# HACK to get the generators outputting correctly +class Deltas(Container): + delta_list: List[uint64, 2**30] def run_attestation_component_deltas(spec, state, component_delta_fn, matching_att_fn): @@ -12,8 +18,8 @@ def run_attestation_component_deltas(spec, state, component_delta_fn, matching_a rewards, penalties = component_delta_fn(state) - yield 'rewards', rewards - yield 'penalties', penalties + yield 'rewards', Deltas(delta_list=rewards) + yield 'penalties', Deltas(delta_list=penalties) matching_attestations = matching_att_fn(state, spec.get_previous_epoch(state)) matching_indices = spec.get_unslashed_attesting_indices(state, matching_attestations) diff --git a/tests/core/pyspec/eth2spec/test/phase_0/rewards/__init__.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/rewards/test_get_head_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/rewards/test_get_head_deltas.py rename to tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_head_deltas.py diff --git a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/rewards/test_get_source_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/rewards/test_get_source_deltas.py rename to tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_source_deltas.py diff --git a/tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/rewards/test_get_target_deltas.py b/tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/phase_0/epoch_processing/rewards/test_get_target_deltas.py rename to tests/core/pyspec/eth2spec/test/phase_0/rewards/test_get_target_deltas.py diff --git a/tests/formats/rewards/README.md b/tests/formats/rewards/README.md new file mode 100644 index 000000000..dce2b5ac8 --- /dev/null +++ b/tests/formats/rewards/README.md @@ -0,0 +1,47 @@ +# Rewards tests + +The different rewards deltas sub-functions are testing individually with the test handlers, each returning the related `rewards`/`penalties`. +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.) + + +## Test case format + +### `meta.yaml` + +```yaml +description: string -- Optional description of test case, purely for debugging purposes. + Tests should use the directory name of the test case as identifier, not the description. +bls_setting: int -- see general test-format spec. +``` + +### `pre.yaml` + +A YAML-encoded `BeaconState`, the state before running the rewards sub-function. + +Also available as `pre.ssz`. + + +### `rewards.yaml` + +A YAML-encoded list of integers representing the 0th item in the return value (i.e. the rewards deltas) + +### `penalties.yaml` + +A YAML-encoded list of integers representing the 1st item in the return value (i.e. the penalties deltas) + +## 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` + +The provided pre-state is ready to be input into the designated handler. + +The resulting `rewards`/`penalties` should match the return values of the +handler. Specifically the following must hold true: + +```python + rewards == handler(state)[0] + penalties == handler(state)[1] +``` diff --git a/tests/generators/rewards/README.md b/tests/generators/rewards/README.md new file mode 100644 index 000000000..60f106836 --- /dev/null +++ b/tests/generators/rewards/README.md @@ -0,0 +1,8 @@ +# Rewards + +Rewards covers the sub-functions of `process_rewards_and_penalties` for granular testing of components of the rewards function. + +A rewards test-runner can consume these sub-transition test-suites, + and handle different kinds of epoch sub-transitions by processing the cases using the specified test handler. + +Information on the format of the tests can be found in the [rewards test formats documentation](../../formats/rewards/README.md). diff --git a/tests/generators/rewards/main.py b/tests/generators/rewards/main.py new file mode 100644 index 000000000..caffc3bd1 --- /dev/null +++ b/tests/generators/rewards/main.py @@ -0,0 +1,44 @@ +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, +) +from gen_base import gen_runner, gen_typing +from gen_from_tests.gen import generate_from_tests +from importlib import reload +from eth2spec.config import config_util +from eth2spec.test.context import PHASE0 + + +def create_provider(handler_name: str, tests_src, config_name: str) -> gen_typing.TestProvider: + + def prepare_fn(configs_path: str) -> str: + config_util.prepare_config(configs_path, config_name) + reload(spec_phase0) + reload(spec_phase1) + return config_name + + def cases_fn() -> Iterable[gen_typing.TestCase]: + return generate_from_tests( + runner_name='rewards', + handler_name=handler_name, + src=tests_src, + fork_name=PHASE0, + ) + + return gen_typing.TestProvider(prepare=prepare_fn, make_cases=cases_fn) + + +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'), + ]) diff --git a/tests/generators/rewards/requirements.txt b/tests/generators/rewards/requirements.txt new file mode 100644 index 000000000..b82314298 --- /dev/null +++ b/tests/generators/rewards/requirements.txt @@ -0,0 +1,2 @@ +../../core/gen_helpers +../../../ \ No newline at end of file