From 03ced9c2639269ef9503c18d36c2c7a3646fcf67 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 13 Oct 2022 14:53:40 -0500 Subject: [PATCH 1/5] Add Capella tests --- tests/core/pyspec/eth2spec/test/capella/__init__.py | 0 .../eth2spec/test/capella/block_processing/__init__.py | 0 .../eth2spec/test/capella/epoch_processing/__init__.py | 0 .../core/pyspec/eth2spec/test/capella/fork/__init__.py | 0 .../pyspec/eth2spec/test/capella/sanity/__init__.py | 0 tests/core/pyspec/eth2spec/test/helpers/constants.py | 5 +++-- tests/generators/epoch_processing/main.py | 9 ++++++++- tests/generators/finality/main.py | 8 +++++--- tests/generators/fork_choice/main.py | 5 +++-- tests/generators/forks/main.py | 8 +++++++- tests/generators/genesis/main.py | 7 ++++--- tests/generators/light_client/main.py | 4 +++- tests/generators/operations/main.py | 10 +++++++++- tests/generators/random/main.py | 6 +++++- tests/generators/rewards/main.py | 4 +++- tests/generators/sanity/main.py | 8 +++++++- tests/generators/sync/main.py | 4 +++- 17 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/capella/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/capella/block_processing/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/capella/epoch_processing/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/capella/fork/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/capella/sanity/__init__.py diff --git a/tests/core/pyspec/eth2spec/test/capella/__init__.py b/tests/core/pyspec/eth2spec/test/capella/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/__init__.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/capella/epoch_processing/__init__.py b/tests/core/pyspec/eth2spec/test/capella/epoch_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/capella/fork/__init__.py b/tests/core/pyspec/eth2spec/test/capella/fork/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/__init__.py b/tests/core/pyspec/eth2spec/test/capella/sanity/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py index b1463b97b..0763c42cc 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/constants.py +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -24,11 +24,12 @@ ALL_PHASES = ( EIP4844, ) # The forks that output to the test vectors. -TESTGEN_FORKS = (PHASE0, ALTAIR, BELLATRIX) +TESTGEN_FORKS = (PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844) FORKS_BEFORE_ALTAIR = (PHASE0,) FORKS_BEFORE_BELLATRIX = (PHASE0, ALTAIR) -FORKS_BEFORE_CAPELLA = (PHASE0, ALTAIR, BELLATRIX) + +# TODO: no EIP4844 fork tests now. Should add when we figure out the content of Capella. ALL_FORK_UPGRADES = { # pre_fork_name: post_fork_name PHASE0: ALTAIR, diff --git a/tests/generators/epoch_processing/main.py b/tests/generators/epoch_processing/main.py index 7ba270929..946a6c2c0 100644 --- a/tests/generators/epoch_processing/main.py +++ b/tests/generators/epoch_processing/main.py @@ -1,5 +1,5 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA if __name__ == "__main__": @@ -27,6 +27,12 @@ if __name__ == "__main__": # so no additional tests required. bellatrix_mods = altair_mods + _new_capella_mods = {key: 'eth2spec.test.capella.epoch_processing.test_process_' + key for key in [ + 'full_withdrawals', + 'partial_withdrawals', + ]} + capella_mods = combine_mods(_new_capella_mods, altair_mods) + # TODO Custody Game testgen is disabled for now # custody_game_mods = {**{key: 'eth2spec.test.custody_game.epoch_processing.test_process_' + key for key in [ # 'reveal_deadlines', @@ -38,6 +44,7 @@ if __name__ == "__main__": PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="epoch_processing", all_mods=all_mods) diff --git a/tests/generators/finality/main.py b/tests/generators/finality/main.py index 24c7d0c6e..cb40e7cc9 100644 --- a/tests/generators/finality/main.py +++ b/tests/generators/finality/main.py @@ -1,16 +1,18 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA if __name__ == "__main__": phase_0_mods = {'finality': 'eth2spec.test.phase0.finality.test_finality'} - altair_mods = phase_0_mods # No additional Altair specific finality tests - bellatrix_mods = altair_mods # No additional Bellatrix specific finality tests + altair_mods = phase_0_mods # No additional Altair specific finality tests + bellatrix_mods = altair_mods # No additional Bellatrix specific finality tests + capella_mods = bellatrix_mods # No additional Capella specific finality tests all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="finality", all_mods=all_mods) diff --git a/tests/generators/fork_choice/main.py b/tests/generators/fork_choice/main.py index 87d3a3fdf..2c95b70e5 100644 --- a/tests/generators/fork_choice/main.py +++ b/tests/generators/fork_choice/main.py @@ -1,5 +1,5 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA if __name__ == "__main__": @@ -17,11 +17,12 @@ if __name__ == "__main__": 'on_merge_block', ]} bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) - + capella_mods = bellatrix_mods all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="fork_choice", all_mods=all_mods) diff --git a/tests/generators/forks/main.py b/tests/generators/forks/main.py index fbf75a221..628114979 100644 --- a/tests/generators/forks/main.py +++ b/tests/generators/forks/main.py @@ -1,9 +1,13 @@ from typing import Iterable -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, MINIMAL, MAINNET +from eth2spec.test.helpers.constants import ( + PHASE0, ALTAIR, BELLATRIX, CAPELLA, + MINIMAL, MAINNET, +) from eth2spec.test.helpers.typing import SpecForkName, PresetBaseName from eth2spec.test.altair.fork import test_altair_fork_basic, test_altair_fork_random from eth2spec.test.bellatrix.fork import test_bellatrix_fork_basic, test_bellatrix_fork_random +from eth2spec.test.capella.fork import test_capella_fork_basic, test_capella_fork_random from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing from eth2spec.gen_helpers.gen_from_tests.gen import generate_from_tests @@ -33,6 +37,8 @@ def _get_fork_tests_providers(): yield create_provider(test_altair_fork_random, preset, PHASE0, ALTAIR) yield create_provider(test_bellatrix_fork_basic, preset, ALTAIR, BELLATRIX) yield create_provider(test_bellatrix_fork_random, preset, ALTAIR, BELLATRIX) + yield create_provider(test_capella_fork_basic, preset, BELLATRIX, CAPELLA) + yield create_provider(test_capella_fork_random, preset, BELLATRIX, CAPELLA) if __name__ == "__main__": diff --git a/tests/generators/genesis/main.py b/tests/generators/genesis/main.py index 272eebb4e..e71b15401 100644 --- a/tests/generators/genesis/main.py +++ b/tests/generators/genesis/main.py @@ -1,5 +1,5 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA if __name__ == "__main__": @@ -8,18 +8,19 @@ if __name__ == "__main__": 'validity', ]} - # we have new unconditional lines in `initialize_beacon_state_from_eth1` and we want to test it altair_mods = phase_0_mods + # we have new unconditional lines in `initialize_beacon_state_from_eth1` and we want to test it _new_bellatrix_mods = {key: 'eth2spec.test.bellatrix.genesis.test_' + key for key in [ 'initialization', ]} bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) - + capella_mods = bellatrix_mods all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="genesis", all_mods=all_mods) diff --git a/tests/generators/light_client/main.py b/tests/generators/light_client/main.py index 68a0da529..0ff3fe786 100644 --- a/tests/generators/light_client/main.py +++ b/tests/generators/light_client/main.py @@ -1,4 +1,4 @@ -from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX, CAPELLA from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators @@ -9,10 +9,12 @@ if __name__ == "__main__": 'update_ranking', ]} bellatrix_mods = altair_mods + capella_mods = bellatrix_mods all_mods = { ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="light_client", all_mods=all_mods) diff --git a/tests/generators/operations/main.py b/tests/generators/operations/main.py index 2a634cd5b..1977ec217 100644 --- a/tests/generators/operations/main.py +++ b/tests/generators/operations/main.py @@ -1,5 +1,5 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA if __name__ == "__main__": @@ -24,6 +24,13 @@ if __name__ == "__main__": ]} bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) + _new_capella_mods = {key: 'eth2spec.test.capella.block_processing.test_process_' + key for key in [ + 'deposit', + 'bls_to_execution_change', + 'withdrawals', + ]} + capella_mods = combine_mods(_new_capella_mods, bellatrix_mods) + # TODO Custody Game testgen is disabled for now # _new_custody_game_mods = {key: 'eth2spec.test.custody_game.block_processing.test_process_' + key for key in [ # 'attestation', @@ -38,6 +45,7 @@ if __name__ == "__main__": PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="operations", all_mods=all_mods) diff --git a/tests/generators/random/main.py b/tests/generators/random/main.py index 1791da83b..9983da96c 100644 --- a/tests/generators/random/main.py +++ b/tests/generators/random/main.py @@ -1,4 +1,4 @@ -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators @@ -12,11 +12,15 @@ if __name__ == "__main__": bellatrix_mods = {key: 'eth2spec.test.bellatrix.random.test_' + key for key in [ 'random', ]} + capella_mods = {key: 'eth2spec.test.capella.random.test_' + key for key in [ + 'random', + ]} all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="random", all_mods=all_mods) diff --git a/tests/generators/rewards/main.py b/tests/generators/rewards/main.py index 22b4be5c3..33763144b 100644 --- a/tests/generators/rewards/main.py +++ b/tests/generators/rewards/main.py @@ -1,5 +1,5 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA if __name__ == "__main__": @@ -15,11 +15,13 @@ if __name__ == "__main__": # Note: Block rewards are non-epoch rewards and are tested as part of block processing tests. # Transaction fees are part of the execution-layer. bellatrix_mods = altair_mods + capella_mods = bellatrix_mods all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="rewards", all_mods=all_mods) diff --git a/tests/generators/sanity/main.py b/tests/generators/sanity/main.py index 259e79059..bb3c954c2 100644 --- a/tests/generators/sanity/main.py +++ b/tests/generators/sanity/main.py @@ -1,4 +1,4 @@ -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods @@ -18,10 +18,16 @@ if __name__ == "__main__": ]} bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) + _new_capella_mods = {key: 'eth2spec.test.capella.sanity.test_' + key for key in [ + 'blocks', + ]} + capella_mods = combine_mods(_new_capella_mods, bellatrix_mods) + all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="sanity", all_mods=all_mods) diff --git a/tests/generators/sync/main.py b/tests/generators/sync/main.py index ad83b78a0..eba3ac152 100644 --- a/tests/generators/sync/main.py +++ b/tests/generators/sync/main.py @@ -1,14 +1,16 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators -from eth2spec.test.helpers.constants import BELLATRIX +from eth2spec.test.helpers.constants import BELLATRIX, CAPELLA if __name__ == "__main__": bellatrix_mods = {key: 'eth2spec.test.bellatrix.sync.test_' + key for key in [ 'optimistic', ]} + capella_mods = bellatrix_mods all_mods = { BELLATRIX: bellatrix_mods, + CAPELLA: capella_mods, } run_state_test_generators(runner_name="sync", all_mods=all_mods) From b90436c98837924c3a929652b57b07ac9d3c2254 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 14 Oct 2022 18:14:50 -0500 Subject: [PATCH 2/5] Fix capella random & fork --- Makefile | 2 + specs/capella/fork.md | 19 +- .../eth2spec/test/capella/random/__init__.py | 0 .../test/capella/random/test_random.py | 438 ++++++++++++++++++ .../eth2spec/test/helpers/capella/__init__.py | 0 .../test/utils/randomized_block_tests.py | 14 + tests/generators/random/Makefile | 2 + tests/generators/random/generate.py | 11 +- 8 files changed, 484 insertions(+), 2 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/capella/random/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/capella/random/test_random.py create mode 100644 tests/core/pyspec/eth2spec/test/helpers/capella/__init__.py diff --git a/Makefile b/Makefile index 5f0706dd9..639fae953 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,8 @@ partial_clean: rm -rf $(ETH2SPEC_MODULE_DIR)/phase0 rm -rf $(ETH2SPEC_MODULE_DIR)/altair rm -rf $(ETH2SPEC_MODULE_DIR)/bellatrix + rm -rf $(ETH2SPEC_MODULE_DIR)/capella + rm -rf $(ETH2SPEC_MODULE_DIR)/eip4844 rm -rf $(COV_HTML_OUT_DIR) rm -rf $(TEST_REPORT_DIR) rm -rf eth2spec.egg-info dist build diff --git a/specs/capella/fork.md b/specs/capella/fork.md index e6e70f797..bc3c95aed 100644 --- a/specs/capella/fork.md +++ b/specs/capella/fork.md @@ -70,6 +70,23 @@ In particular, the outer `state_transition` function defined in the Phase 0 docu ```python def upgrade_to_capella(pre: bellatrix.BeaconState) -> BeaconState: epoch = bellatrix.get_current_epoch(pre) + latest_execution_payload_header = ExecutionPayloadHeader( + parent_hash=pre.latest_execution_payload_header.parent_hash, + fee_recipient=pre.latest_execution_payload_header.fee_recipient, + state_root=pre.latest_execution_payload_header.state_root, + receipts_root=pre.latest_execution_payload_header.receipts_root, + logs_bloom=pre.latest_execution_payload_header.logs_bloom, + prev_randao=pre.latest_execution_payload_header.prev_randao, + block_number=pre.latest_execution_payload_header.block_number, + gas_limit=pre.latest_execution_payload_header.gas_limit, + gas_used=pre.latest_execution_payload_header.gas_used, + timestamp=pre.latest_execution_payload_header.timestamp, + extra_data=pre.latest_execution_payload_header.extra_data, + base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas, + block_hash=pre.latest_execution_payload_header.block_hash, + transactions_root=pre.latest_execution_payload_header.transactions_root, + withdrawals_root=Root(), # [New in Capella] + ) post = BeaconState( # Versioning genesis_time=pre.genesis_time, @@ -110,7 +127,7 @@ def upgrade_to_capella(pre: bellatrix.BeaconState) -> BeaconState: current_sync_committee=pre.current_sync_committee, next_sync_committee=pre.next_sync_committee, # Execution-layer - latest_execution_payload_header=pre.latest_execution_payload_header, + latest_execution_payload_header=latest_execution_payload_header, # Withdrawals withdrawal_queue=[], next_withdrawal_index=WithdrawalIndex(0), diff --git a/tests/core/pyspec/eth2spec/test/capella/random/__init__.py b/tests/core/pyspec/eth2spec/test/capella/random/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/capella/random/test_random.py b/tests/core/pyspec/eth2spec/test/capella/random/test_random.py new file mode 100644 index 000000000..47ee93187 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/capella/random/test_random.py @@ -0,0 +1,438 @@ +""" +This module is generated from the ``random`` test generator. +Please do not edit this file manually. +See the README for that generator for more information. +""" + +from eth2spec.test.helpers.constants import CAPELLA +from eth2spec.test.context import ( + misc_balances_in_default_range_with_many_validators, + with_phases, + zero_activation_threshold, + only_generator, +) +from eth2spec.test.context import ( + always_bls, + spec_test, + with_custom_state, + single_phase, +) +from eth2spec.test.utils.randomized_block_tests import ( + run_generated_randomized_test, +) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_0(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_1(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_2(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_3(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_4(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_5(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_6(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_7(spec, state): + # scenario as high-level, informal text: + # epochs:0,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_8(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_9(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_10(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_11(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_12(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_13(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_14(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@only_generator("randomized test for broad coverage, not point-to-point CI") +@with_phases([CAPELLA]) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) +@spec_test +@single_phase +@always_bls +def test_randomized_15(spec, state): + # scenario as high-level, informal text: + # epochs:epochs_until_leak,slots:0,with-block:no_block + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_capella + scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_capella', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_capella'} # noqa: E501 + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) diff --git a/tests/core/pyspec/eth2spec/test/helpers/capella/__init__.py b/tests/core/pyspec/eth2spec/test/helpers/capella/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py index 386b4c8b2..c66970ba7 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -71,6 +71,15 @@ def randomize_state_bellatrix(spec, state, stats, exit_fraction=0.1, slash_fract return scenario_state +def randomize_state_capella(spec, state, stats, exit_fraction=0.1, slash_fraction=0.1): + scenario_state = randomize_state_bellatrix(spec, + state, + stats, + exit_fraction=exit_fraction, + slash_fraction=slash_fraction) + return scenario_state + + # epochs def epochs_until_leak(spec): @@ -195,6 +204,11 @@ def random_block_bellatrix(spec, state, signed_blocks, scenario_state): return block +def random_block_capella(spec, state, signed_blocks, scenario_state): + block = random_block_bellatrix(spec, state, signed_blocks, scenario_state) + return block + + # validations def no_op_validation(_spec, _state): diff --git a/tests/generators/random/Makefile b/tests/generators/random/Makefile index 607d69a47..8b77a3617 100644 --- a/tests/generators/random/Makefile +++ b/tests/generators/random/Makefile @@ -5,6 +5,8 @@ all: rm -f ../../core/pyspec/eth2spec/test/phase0/random/test_random.py rm -f ../../core/pyspec/eth2spec/test/altair/random/test_random.py rm -f ../../core/pyspec/eth2spec/test/bellatrix/random/test_random.py + rm -f ../../core/pyspec/eth2spec/test/capella/random/test_random.py python3 generate.py phase0 > ../../core/pyspec/eth2spec/test/phase0/random/test_random.py python3 generate.py altair > ../../core/pyspec/eth2spec/test/altair/random/test_random.py python3 generate.py bellatrix > ../../core/pyspec/eth2spec/test/bellatrix/random/test_random.py + python3 generate.py capella > ../../core/pyspec/eth2spec/test/capella/random/test_random.py diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index f71595c02..39d43b0aa 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -20,9 +20,11 @@ from eth2spec.test.utils.randomized_block_tests import ( randomize_state, randomize_state_altair, randomize_state_bellatrix, + randomize_state_capella, random_block, random_block_altair_with_cycling_sync_committee_participation, random_block_bellatrix, + random_block_capella, last_slot_in_epoch, random_slot_in_epoch, penultimate_slot_in_epoch, @@ -32,7 +34,7 @@ from eth2spec.test.utils.randomized_block_tests import ( transition_to_leaking, transition_without_leak, ) -from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX +from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA # Ensure this many blocks are present in *each* randomized scenario @@ -263,5 +265,12 @@ if __name__ == "__main__": state_randomizer=randomize_state_bellatrix, block_randomizer=random_block_bellatrix, ) + if CAPELLA in sys.argv: + did_generate = True + run_generate_tests_to_std_out( + CAPELLA, + state_randomizer=randomize_state_capella, + block_randomizer=random_block_capella, + ) if not did_generate: warnings.warn("no phase given for test generation") From 940fc207587ae7c6f3db946928ec7c5900aa02ab Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 17 Oct 2022 23:21:15 +0800 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Danny Ryan --- tests/generators/fork_choice/main.py | 2 +- tests/generators/genesis/main.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generators/fork_choice/main.py b/tests/generators/fork_choice/main.py index 2c95b70e5..7982902c5 100644 --- a/tests/generators/fork_choice/main.py +++ b/tests/generators/fork_choice/main.py @@ -17,7 +17,7 @@ if __name__ == "__main__": 'on_merge_block', ]} bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) - capella_mods = bellatrix_mods + capella_mods = bellatrix_mods # No additional Capella specific fork choice tests all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, diff --git a/tests/generators/genesis/main.py b/tests/generators/genesis/main.py index e71b15401..c8f5a83d5 100644 --- a/tests/generators/genesis/main.py +++ b/tests/generators/genesis/main.py @@ -15,7 +15,7 @@ if __name__ == "__main__": 'initialization', ]} bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) - capella_mods = bellatrix_mods + capella_mods = bellatrix_mods # No additional Capella specific genesis tests all_mods = { PHASE0: phase_0_mods, ALTAIR: altair_mods, From 0e2c3d89e020f43e0c2af1c246ec772ec54ee250 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 20 Oct 2022 22:22:04 -0500 Subject: [PATCH 4/5] Fill `bls_to_execution_changes` field in Capella random tests --- .../eth2spec/test/helpers/multi_operations.py | 19 ++++++++++++++++++- .../test/utils/randomized_block_tests.py | 8 +++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 44ed0ae89..c11bb5584 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -16,6 +16,7 @@ from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing from eth2spec.test.helpers.attestations import get_valid_attestation from eth2spec.test.helpers.deposits import build_deposit, deposit_from_context from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits +from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change def run_slash_and_exit(spec, state, slash_index, exit_index, valid=True): @@ -126,13 +127,15 @@ def get_random_deposits(spec, state, rng, num_deposits=None): # First build deposit data leaves for i in range(num_deposits): index = len(state.validators) + i + withdrawal_pubkey = pubkeys[-1 - index] + withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(withdrawal_pubkey)[1:] _, root, deposit_data_leaves = build_deposit( spec, deposit_data_leaves, pubkeys[index], privkeys[index], spec.MAX_EFFECTIVE_BALANCE, - withdrawal_credentials=b'\x00' * 32, + withdrawal_credentials=withdrawal_credentials, signed=True, ) @@ -200,6 +203,20 @@ def get_random_sync_aggregate(spec, state, slot, block_root=None, fraction_parti ) +def get_random_bls_to_execution_changes(spec, state, rng=Random(2188), num_address_changes=0): + bls_indices = [ + index + for index, validator in enumerate(state.validators) + if validator.withdrawal_credentials[:1] == spec.BLS_WITHDRAWAL_PREFIX + ] + assert len(bls_indices) > 0 + + return [ + get_signed_address_change(spec, state, validator_index=validator_index) + for validator_index in rng.sample(bls_indices, min(num_address_changes, len(bls_indices))) + ] + + def build_random_block_from_state_for_next_slot(spec, state, rng=Random(2188), deposits=None): block = build_empty_block_for_next_slot(spec, state) proposer_slashings = get_random_proposer_slashings(spec, state, rng) diff --git a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py index c66970ba7..5504a53d7 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -9,6 +9,7 @@ from typing import Callable from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state_for_next_slot, + get_random_bls_to_execution_changes, get_random_sync_aggregate, prepare_state_and_get_random_deposits, ) @@ -204,8 +205,13 @@ def random_block_bellatrix(spec, state, signed_blocks, scenario_state): return block -def random_block_capella(spec, state, signed_blocks, scenario_state): +def random_block_capella(spec, state, signed_blocks, scenario_state, rng=Random(3456)): block = random_block_bellatrix(spec, state, signed_blocks, scenario_state) + block.body.bls_to_execution_changes = get_random_bls_to_execution_changes( + spec, + state, + num_address_changes=rng.randint(1, spec.MAX_BLS_TO_EXECUTION_CHANGES) + ) return block From f48d6b324d8c23204b9868b1af6bf7cec935127b Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 20 Oct 2022 22:27:49 -0500 Subject: [PATCH 5/5] Update test formats --- tests/formats/epoch_processing/README.md | 2 ++ tests/formats/operations/README.md | 1 + 2 files changed, 3 insertions(+) diff --git a/tests/formats/epoch_processing/README.md b/tests/formats/epoch_processing/README.md index e0e6dc367..41d2a102a 100644 --- a/tests/formats/epoch_processing/README.md +++ b/tests/formats/epoch_processing/README.md @@ -45,5 +45,7 @@ Sub-transitions: - `participation_record_updates` (Phase 0 only) - `participation_flag_updates` (Altair) - `sync_committee_updates` (Altair) +- `full_withdrawals` (Capella) +- `partial_withdrawals` (Capella) The resulting state should match the expected `post` state. diff --git a/tests/formats/operations/README.md b/tests/formats/operations/README.md index e532c5047..ba2c64b3a 100644 --- a/tests/formats/operations/README.md +++ b/tests/formats/operations/README.md @@ -43,6 +43,7 @@ Operations: | `voluntary_exit` | `SignedVoluntaryExit` | `voluntary_exit` | `process_voluntary_exit(state, voluntary_exit)` | | `sync_aggregate` | `SyncAggregate` | `sync_aggregate` | `process_sync_aggregate(state, sync_aggregate)` (new in Altair) | | `execution_payload` | `ExecutionPayload` | `execution_payload` | `process_execution_payload(state, execution_payload)` (new in Bellatrix) | +| `bls_to_execution_change` | `SignedBLSToExecutionChange` | `signed_address_change` | `process_bls_to_execution_change(state, signed_address_change)` (new in Capella) | Note that `block_header` is not strictly an operation (and is a full `Block`), but processed in the same manner, and hence included here.