From eadefa274d2fac1840e14ae7f0c07a75b5941fb6 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 19 Aug 2021 12:54:21 -0600 Subject: [PATCH 01/55] WIP: broad-spectrum randomized block tests --- .../test/phase0/sanity/test_blocks_random.py | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py new file mode 100644 index 000000000..ffc37c7c2 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -0,0 +1,67 @@ +from eth2spec.test.helpers.state import ( + next_epoch, + next_slot, +) +from eth2spec.test.context import ( + with_all_phases, + spec_state_test, +) + + +def generate_randomized_scenarios(): + # TODO: WIP schema + return { + # ("randomize_state", "ensure all validator states present: pending/deposited, activated, exited, slashed"), + # ("randomized balances", "ensure distribution of bals"), + # ("transition to leak if not already, maybe", "assert is or is not leaking"), + "setup": [], + "epochs_to_skip": 0, # 0, 1, 2, N, EPOCHS_TO_INACTIVITY_LEAK, + "slots_to_skip": 0, # 0, 1, 2, N, SLOTS_PER_EPOCH - 1, + "transitions": [ # TODO: consider large numbers of blocks, load on generated data + { + "block_producer": lambda spec, state: spec.SignedBeaconBlock(), + "epochs_to_skip": 0, # 0, 1, 2, N, EPOCHS_TO_INACTIVITY_LEAK, + "slots_to_skip": 0, # 0, 1, 2, N, SLOTS_PER_EPOCH - 1, + } + ], + } + + +def id_from_scenario(test_description): + return '-'.join(':'.join((str(k),str(v))) for k,v in test_description.items()) + + +def pytest_generate_tests(metafunc): + """ + Pytest hook to generate test cases from dynamically computed data + """ + generated_name = "test_description" + generated_values = generate_randomized_scenarios() + metafunc.parametrize(generated_name, generated_values, ids=id_from_scenario, scope="module") + + +def pytest_generate_tests_adapter(f): + """ + Adapter decorator to allow dynamic test case generation + while leveraging existing decorators specific to spec tests. + """ + def wrapper(test_description, *args, **kwargs): + kwargs["test_description"] = test_description + f(*args, **kwargs) + return wrapper + + +@pytest_generate_tests_adapter +@with_all_phases +@spec_state_test +def test_harness_for_randomized_blocks(spec, state, test_description): + for mutation, validation in test_description["setup"]: + mutation(spec, state) + validation(spec, state) + for _ in range(len(test_description["epochs_to_skip"])): + next_epoch(spec, state) + for _ in range(len(test_description["slots_to_skip"])): + next_slot(spec, state) + for transition in test_description["transitions"]: + # TODO apply transition + pass From 00df808f59e6212ffc28d46fe39f99b63ed7253b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 20 Aug 2021 13:35:23 -0600 Subject: [PATCH 02/55] expose functionality to make random block --- .../eth2spec/test/helpers/multi_operations.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 4b6c9b25d..dc64882b8 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -125,10 +125,7 @@ def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): return prepare_signed_exits(spec, state, exit_indices) -def run_test_full_random_operations(spec, state, rng=Random(2080)): - # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit - state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - +def build_random_block_from_state(spec, state, rng=Random(2188)): # prepare state for deposits before building block deposits = prepare_state_and_get_random_deposits(spec, state, rng) @@ -148,6 +145,15 @@ def run_test_full_random_operations(spec, state, rng=Random(2080)): slashed_indices = slashed_indices.union(attester_slashing.attestation_2.attesting_indices) block.body.voluntary_exits = get_random_voluntary_exits(spec, state, slashed_indices, rng) + return block + + +def run_test_full_random_operations(spec, state, rng=Random(2080)): + # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit + state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH + + block = build_random_block_from_state(spec, state, rng) + yield 'pre', state signed_block = state_transition_and_sign_block(spec, state, block) From 4420d1381666a405b82429e76a50ffb513eb9ea1 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 20 Aug 2021 13:35:42 -0600 Subject: [PATCH 03/55] add helper to check existence of many validator types --- .../pyspec/eth2spec/test/helpers/state.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 666023fec..b4c9e1d67 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -1,5 +1,6 @@ from eth2spec.test.context import expect_assertion_error, is_post_altair from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block +from eth2spec.test.helpers.voluntary_exits import get_exited_validators def get_balance(state, index): @@ -133,3 +134,24 @@ def _set_empty_participation(spec, state, current=True, previous=True): def set_empty_participation(spec, state, rng=None): _set_empty_participation(spec, state) + + +def ensure_state_has_validators_across_lifecycle(spec, state): + """ + Scan the validator registry to ensure there is at least 1 validator + for each of the following lifecycle states: + 1. Pending / deposited + 2. Active + 3. Exited + 4. Slashed + """ + has_pending = any(filter(spec.is_eligible_for_activation_queue, state.validators)) + + current_epoch = spec.get_current_epoch(state) + has_active = any(filter(lambda v: spec.is_active_validator(v, current_epoch), state.validators)) + + has_exited = any(get_exited_validators(spec, state)) + + has_slashed = any(filter(lambda v: v.slashed, state.validators)) + + return has_pending and has_active and has_exited and has_slashed From 619e82889881354e1fef8b43e0f683b4c9f3105e Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 20 Aug 2021 13:57:26 -0600 Subject: [PATCH 04/55] Progress on block test gen --- .../test/phase0/sanity/test_blocks_random.py | 290 ++++++++++++++++-- 1 file changed, 263 insertions(+), 27 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index ffc37c7c2..9b10ab355 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,34 +1,240 @@ +import itertools +from random import Random +from typing import Callable +from tests.core.pyspec.eth2spec.test.context import default_activation_threshold +from eth2spec.test.helpers.multi_operations import ( + build_random_block_from_state, +) from eth2spec.test.helpers.state import ( next_epoch, next_slot, + ensure_state_has_validators_across_lifecycle, + state_transition_and_sign_block, +) +from eth2spec.test.helpers.random import ( + randomize_state, ) from eth2spec.test.context import ( with_all_phases, - spec_state_test, + always_bls, + spec_test, + with_custom_state, + default_activation_threshold, + single_phase, + misc_balances, ) +# primitives +## epochs -def generate_randomized_scenarios(): - # TODO: WIP schema +def _epochs_until_leak(spec): + return spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + + +def _epochs_for_shard_committee_period(spec): + return spec.config.SHARD_COMMITTEE_PERIOD + + +## slots + +def _last_slot_in_epoch(spec): + return spec.SLOTS_PER_EPOCH - 1 + + +def _random_slot_in_epoch(rng): + def f(spec): + return rng.randrange(1, spec.SLOTS_PER_EPOCH - 2) + return f + + +def _penultimate_slot_in_epoch(spec): + return spec.SLOTS_PER_EPOCH - 2 + + +## blocks + +def _no_block(_spec, _pre_state, _signed_blocks): + return None + + +def _random_block_for_next_slot(spec, pre_state, _signed_blocks): + return build_random_block_from_state(spec, pre_state) + + +## validations + +def _no_op_validation(spec, state): + return True + + +def _validate_is_leaking(spec, state): + return spec.is_in_inactivity_leak(state) + + +# transitions + +def _no_op_transition(): + return {} + + +def _epoch_transition(n=0): return { - # ("randomize_state", "ensure all validator states present: pending/deposited, activated, exited, slashed"), - # ("randomized balances", "ensure distribution of bals"), - # ("transition to leak if not already, maybe", "assert is or is not leaking"), - "setup": [], - "epochs_to_skip": 0, # 0, 1, 2, N, EPOCHS_TO_INACTIVITY_LEAK, - "slots_to_skip": 0, # 0, 1, 2, N, SLOTS_PER_EPOCH - 1, - "transitions": [ # TODO: consider large numbers of blocks, load on generated data - { - "block_producer": lambda spec, state: spec.SignedBeaconBlock(), - "epochs_to_skip": 0, # 0, 1, 2, N, EPOCHS_TO_INACTIVITY_LEAK, - "slots_to_skip": 0, # 0, 1, 2, N, SLOTS_PER_EPOCH - 1, - } - ], + "epochs_to_skip": n, } -def id_from_scenario(test_description): - return '-'.join(':'.join((str(k),str(v))) for k,v in test_description.items()) +def _slot_transition(n=0): + return { + "slots_to_skip": n, + } + + +def _transition_to_leaking(): + return { + "epochs_to_skip": _epochs_until_leak, + "validation": _validate_is_leaking, + } + + +## block transitions + +def _transition_with_random_block(epochs=None, slots=None): + """ + Build a block transition with randomized data. + Provide optional sub-transitions to advance some + number of epochs or slots before applying the random block. + """ + transition = { + "block_producer": _random_block_for_next_slot, + } + if epochs: + transition.update(epochs) + if slots: + transition.update(slots) + return transition + + +# setup and test gen + +def _randomized_scenario_setup(): + """ + Return a sequence of pairs of ("mutator", "validator"), + a function that accepts (spec, state) arguments and performs some change + and a function that accepts (spec, state) arguments and validates some change was made. + """ + def _skip_epochs(epoch_producer): + def f(spec, state): + """ + The unoptimized spec implementation is too slow to advance via ``next_epoch``. + Instead, just overwrite the ``state.slot`` and continue... + """ + epochs_to_skip = epoch_producer(spec) + slots_to_skip = epochs_to_skip * spec.SLOTS_PER_EPOCH + state.slot += slots_to_skip + return f + + return ( + # NOTE: the block randomization function assumes at least 1 shard committee period + # so advance the state before doing anything else. + (_skip_epochs(_epochs_for_shard_committee_period), _no_op_validation), + (randomize_state, ensure_state_has_validators_across_lifecycle), + ) + + +def _normalize_transition(transition): + """ + Provide "empty" or "no op" sub-transitions + to a given transition. + """ + if isinstance(transition, Callable): + transition = transition() + if "epochs_to_skip" not in transition: + transition["epochs_to_skip"] = 0 + if "slots_to_skip" not in transition: + transition["slots_to_skip"] = 0 + if "block_producer" not in transition: + transition["block_producer"] = _no_block + if "validation" not in transition: + transition["validation"] = _no_op_validation + return transition + + +def _normalize_scenarios(scenarios): + """ + "Normalize" a "scenario" so that a producer of a test case + does not need to provide every expected key/value. + """ + for scenario in scenarios: + if "setup" not in scenario: + scenario["setup"] = _randomized_scenario_setup() + + transitions = scenario["transitions"] + for i, transition in enumerate(transitions): + transitions[i] = _normalize_transition(transition) + + +def _generate_randomized_scenarios(): + """ + Generates a set of randomized testing scenarios. + Return a sequence of "scenarios" where each scenario: + 1. Provides some setup + 2. Provides a sequence of transitions that mutate the state in some way, + possibly yielding blocks along the way + NOTE: scenarios are "normalized" with empty/no-op elements before returning + to the test generation to facilitate brevity when writing scenarios by hand. + NOTE: the main block driver builds a block for the **next** slot, so + the slot transitions are offset by -1 to target certain boundaries. + """ + rng = Random(1336) + leak_transitions = (_no_op_transition, _transition_to_leaking) + + # go forward 0 or 1 epochs + epochs_set = (_epoch_transition(n=0), _epoch_transition(n=1)) + # within those epochs, go forward to: + slots_set = ( + # the first slot in an epoch (see note in docstring about offsets...) + _slot_transition(_last_slot_in_epoch), + # the second slot in an epoch + _slot_transition(n=0), + # some random number of slots, but not at epoch boundaries + _slot_transition(_random_slot_in_epoch(rng)), + # the last slot in an epoch (see note in docstring about offsets...) + _slot_transition(_penultimate_slot_in_epoch), + ) + # build a set of block transitions from combinations of sub-transitions + block_transitions = list( + _transition_with_random_block(epochs=epochs, slots=slots) + for epochs, slots in itertools.product(epochs_set, slots_set) + ) + + # and preface each block transition with the possible leak transitions + # (... either no leak or transition to a leak before applying the block transition) + scenarios = [ + {"transitions": list(t)} + for t in itertools.product(leak_transitions, block_transitions) + ] + _normalize_scenarios(scenarios) + return scenarios + + +def _id_from_scenario(test_description): + """ + Construct a test name for ``pytest`` infra. + """ + def _to_id_part(prefix, x): + suffix = str(x) + if isinstance(x, Callable): + suffix = x.__name__ + return f"{prefix}{suffix}" + + def _id_from_transition(transition): + return ",".join(( + _to_id_part("epochs:", transition["epochs_to_skip"]), + _to_id_part("slots:", transition["slots_to_skip"]), + _to_id_part("with-block:", transition["block_producer"]) + )) + + return "|".join(map(_id_from_transition, test_description["transitions"])) def pytest_generate_tests(metafunc): @@ -36,8 +242,8 @@ def pytest_generate_tests(metafunc): Pytest hook to generate test cases from dynamically computed data """ generated_name = "test_description" - generated_values = generate_randomized_scenarios() - metafunc.parametrize(generated_name, generated_values, ids=id_from_scenario, scope="module") + generated_values = _generate_randomized_scenarios() + metafunc.parametrize(generated_name, generated_values, ids=_id_from_scenario, scope="module") def pytest_generate_tests_adapter(f): @@ -51,17 +257,47 @@ def pytest_generate_tests_adapter(f): return wrapper +def _iter_temporal(spec, callable_or_int): + """ + Intended to advance some number of {epochs, slots}. + Caller can provide a constant integer or a callable deriving a number from + the ``spec`` under consideration. + """ + numeric = callable_or_int + if isinstance(callable_or_int, Callable): + numeric = callable_or_int(spec) + for i in range(numeric): + yield i + + @pytest_generate_tests_adapter @with_all_phases -@spec_state_test +@with_custom_state(balances_fn=misc_balances, threshold_fn=default_activation_threshold) +@spec_test +@single_phase +@always_bls def test_harness_for_randomized_blocks(spec, state, test_description): for mutation, validation in test_description["setup"]: mutation(spec, state) validation(spec, state) - for _ in range(len(test_description["epochs_to_skip"])): - next_epoch(spec, state) - for _ in range(len(test_description["slots_to_skip"])): - next_slot(spec, state) + + yield "pre", state + + blocks = [] for transition in test_description["transitions"]: - # TODO apply transition - pass + epochs_to_skip = _iter_temporal(spec, transition["epochs_to_skip"]) + for _ in epochs_to_skip: + next_epoch(spec, state) + slots_to_skip = _iter_temporal(spec, transition["slots_to_skip"]) + for _ in slots_to_skip: + next_slot(spec, state) + + block = transition["block_producer"](spec, state, blocks) + if block: + signed_block = state_transition_and_sign_block(spec, state, block) + blocks.append(signed_block) + + assert transition["validation"](spec, state) + + yield "blocks", blocks + yield "post", state From 92aabcd207c7564668ce70e04217d43cdd10c1e6 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 20 Aug 2021 18:49:04 -0600 Subject: [PATCH 05/55] add randomized block tests to test generator --- tests/generators/sanity/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/generators/sanity/main.py b/tests/generators/sanity/main.py index 8caedc8e5..63efa3897 100644 --- a/tests/generators/sanity/main.py +++ b/tests/generators/sanity/main.py @@ -5,6 +5,7 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators if __name__ == "__main__": phase_0_mods = {key: 'eth2spec.test.phase0.sanity.test_' + key for key in [ 'blocks', + 'blocks_random', 'slots', ]} altair_mods = {**{key: 'eth2spec.test.altair.sanity.test_' + key for key in [ From 5094193f9ab4c751a439b4c2de4763f65b17e3f1 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 16:59:02 -0700 Subject: [PATCH 06/55] formatting --- .../pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 9b10ab355..8767ad12c 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -186,7 +186,6 @@ def _generate_randomized_scenarios(): the slot transitions are offset by -1 to target certain boundaries. """ rng = Random(1336) - leak_transitions = (_no_op_transition, _transition_to_leaking) # go forward 0 or 1 epochs epochs_set = (_epoch_transition(n=0), _epoch_transition(n=1)) @@ -209,6 +208,7 @@ def _generate_randomized_scenarios(): # and preface each block transition with the possible leak transitions # (... either no leak or transition to a leak before applying the block transition) + leak_transitions = (_no_op_transition, _transition_to_leaking) scenarios = [ {"transitions": list(t)} for t in itertools.product(leak_transitions, block_transitions) From 6da2c7a91671868b6c3bdcc0daf1482d07a1b153 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 16:59:54 -0700 Subject: [PATCH 07/55] ensure all validators in randomized test are active --- tests/core/pyspec/eth2spec/test/context.py | 15 +++++++++++++++ .../test/phase0/sanity/test_blocks_random.py | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 7fddc0762..a6828f7e0 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -152,6 +152,21 @@ def misc_balances(spec): return balances +def misc_balances_in_default_range(spec): + """ + Helper method to create a series of balances that includes some misc. balances but + none that are below the ``EJECTION_BALANCE``. + """ + num_validators = spec.SLOTS_PER_EPOCH * 8 + floor = spec.config.EJECTION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT + balances = [ + max(spec.MAX_EFFECTIVE_BALANCE * 2 * i // num_validators, floor) for i in range(num_validators) + ] + rng = Random(1234) + rng.shuffle(balances) + return balances + + def low_single_balance(spec): """ Helper method to create a single of balance of 1 Gwei. diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 8767ad12c..f015362ac 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,7 +1,7 @@ import itertools from random import Random from typing import Callable -from tests.core.pyspec.eth2spec.test.context import default_activation_threshold +from tests.core.pyspec.eth2spec.test.context import default_activation_threshold, misc_balances_in_default_range from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state, ) @@ -272,7 +272,7 @@ def _iter_temporal(spec, callable_or_int): @pytest_generate_tests_adapter @with_all_phases -@with_custom_state(balances_fn=misc_balances, threshold_fn=default_activation_threshold) +@with_custom_state(balances_fn=misc_balances_in_default_range, threshold_fn=default_activation_threshold) @spec_test @single_phase @always_bls From 86643d805a82e6e8ec0bf700e3e99d1b8452ce21 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 17:36:50 -0700 Subject: [PATCH 08/55] adjust some helper code for randomized environment 1. randomized block helpers assume most of the validator set is not slashed 2. `randomize_state` helper slashes or exits ~1/2 of the validator set So, adjust helpers to be less aggresive with exits and slashings and to skip elements as needed if we happen to make something by a validator who has been slashed. --- .../pyspec/eth2spec/test/helpers/random.py | 26 ++++++++----- .../test/phase0/sanity/test_blocks_random.py | 37 ++++++++++++++++--- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/random.py b/tests/core/pyspec/eth2spec/test/helpers/random.py index 70c871a34..8f095aebb 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/random.py +++ b/tests/core/pyspec/eth2spec/test/helpers/random.py @@ -20,16 +20,20 @@ def set_some_new_deposits(spec, state, rng): state.validators[index].activation_eligibility_epoch = spec.get_current_epoch(state) -def exit_random_validators(spec, state, rng): +def exit_random_validators(spec, state, rng, fraction=None): + if fraction is None: + # Exit ~1/2 + fraction = 0.5 + if spec.get_current_epoch(state) < 5: # Move epochs forward to allow for some validators already exited/withdrawable for _ in range(5): next_epoch(spec, state) current_epoch = spec.get_current_epoch(state) - # Exit ~1/2 of validators for index in spec.get_active_validator_indices(state, current_epoch): - if rng.choice([True, False]): + sampled = rng.random() < fraction + if not sampled: continue validator = state.validators[index] @@ -41,11 +45,15 @@ def exit_random_validators(spec, state, rng): validator.withdrawable_epoch = current_epoch + 1 -def slash_random_validators(spec, state, rng): - # Slash ~1/2 of validators +def slash_random_validators(spec, state, rng, fraction=None): + if fraction is None: + # Slash ~1/2 of validators + fraction = 0.5 + for index in range(len(state.validators)): # slash at least one validator - if index == 0 or rng.choice([True, False]): + sampled = rng.random() < fraction + if index == 0 or sampled: spec.slash_validator(state, index) @@ -115,8 +123,8 @@ def randomize_attestation_participation(spec, state, rng=Random(8020)): randomize_epoch_participation(spec, state, spec.get_current_epoch(state), rng) -def randomize_state(spec, state, rng=Random(8020)): +def randomize_state(spec, state, rng=Random(8020), exit_fraction=None, slash_fraction=None): set_some_new_deposits(spec, state, rng) - exit_random_validators(spec, state, rng) - slash_random_validators(spec, state, rng) + exit_random_validators(spec, state, rng, fraction=exit_fraction) + slash_random_validators(spec, state, rng, fraction=slash_fraction) randomize_attestation_participation(spec, state, rng) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index f015362ac..d4740d080 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,7 +1,7 @@ import itertools from random import Random from typing import Callable -from tests.core.pyspec.eth2spec.test.context import default_activation_threshold, misc_balances_in_default_range +from tests.core.pyspec.eth2spec.test.context import misc_balances_in_default_range, zero_activation_threshold from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state, ) @@ -24,7 +24,17 @@ from eth2spec.test.context import ( misc_balances, ) +# May need to make several attempts to find a block that does not correspond to a slashed +# proposer with the randomization helpers... +BLOCK_ATTEMPTS = 32 + # primitives +## state + +def _randomize_state(spec, state): + return randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) + + ## epochs def _epochs_until_leak(spec): @@ -57,8 +67,23 @@ def _no_block(_spec, _pre_state, _signed_blocks): return None -def _random_block_for_next_slot(spec, pre_state, _signed_blocks): - return build_random_block_from_state(spec, pre_state) +def _random_block(spec, state, _signed_blocks): + """ + Produce a random block. + NOTE: this helper may mutate state, as it will attempt + to produce a block over ``BLOCK_ATTEMPTS`` slots in order + to find a valid block in the event that the proposer has already been slashed. + """ + block = build_random_block_from_state(spec, state) + for _ in range(BLOCK_ATTEMPTS): + proposer = state.validators[block.proposer_index] + if proposer.slashed: + next_slot(spec, state) + block = build_random_block_from_state(spec, state) + else: + return block + else: + raise AssertionError("could not find a block with an unslashed proposer, check ``state`` input") ## validations @@ -105,7 +130,7 @@ def _transition_with_random_block(epochs=None, slots=None): number of epochs or slots before applying the random block. """ transition = { - "block_producer": _random_block_for_next_slot, + "block_producer": _random_block, } if epochs: transition.update(epochs) @@ -137,7 +162,7 @@ def _randomized_scenario_setup(): # NOTE: the block randomization function assumes at least 1 shard committee period # so advance the state before doing anything else. (_skip_epochs(_epochs_for_shard_committee_period), _no_op_validation), - (randomize_state, ensure_state_has_validators_across_lifecycle), + (_randomize_state, ensure_state_has_validators_across_lifecycle), ) @@ -272,7 +297,7 @@ def _iter_temporal(spec, callable_or_int): @pytest_generate_tests_adapter @with_all_phases -@with_custom_state(balances_fn=misc_balances_in_default_range, threshold_fn=default_activation_threshold) +@with_custom_state(balances_fn=misc_balances_in_default_range, threshold_fn=zero_activation_threshold) @spec_test @single_phase @always_bls From 7bc2f9547a038d7ee9c271c262c114a3bf31f699 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 17:52:26 -0700 Subject: [PATCH 09/55] skip validators when building a random block if they are slashed --- .../eth2spec/test/helpers/multi_operations.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index dc64882b8..2629206e7 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -45,7 +45,11 @@ def run_slash_and_exit(spec, state, slash_index, exit_index, valid=True): def get_random_proposer_slashings(spec, state, rng): num_slashings = rng.randrange(spec.MAX_PROPOSER_SLASHINGS) - indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() + active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() + indices = [ + index for index in active_indices + if not state.validators[index].slashed + ] slashings = [ get_valid_proposer_slashing( spec, state, @@ -58,7 +62,11 @@ def get_random_proposer_slashings(spec, state, rng): def get_random_attester_slashings(spec, state, rng): num_slashings = rng.randrange(spec.MAX_ATTESTER_SLASHINGS) - indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() + active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() + indices = [ + index for index in active_indices + if not state.validators[index].slashed + ] slot_range = list(range(state.slot - spec.SLOTS_PER_HISTORICAL_ROOT + 1, state.slot)) slashings = [ get_valid_attester_slashing_by_indices( @@ -119,9 +127,14 @@ def prepare_state_and_get_random_deposits(spec, state, rng): def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): num_exits = rng.randrange(spec.MAX_VOLUNTARY_EXITS) - indices = set(spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy()) + active_indices = set(spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy()) + indices = set( + index for index in active_indices + if not state.validators[index].slashed + ) eligible_indices = indices - to_be_slashed_indices - exit_indices = [eligible_indices.pop() for _ in range(num_exits)] + indices_count = min(num_exits, len(eligible_indices)) + exit_indices = [eligible_indices.pop() for _ in range(indices_count)] return prepare_signed_exits(spec, state, exit_indices) From fde71cbe74b9aefa87593f54b9b6e246eda5d17e Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 18:07:00 -0700 Subject: [PATCH 10/55] add warnings if empty block --- .../test/phase0/sanity/test_blocks_random.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index d4740d080..d7749909e 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,4 +1,5 @@ import itertools +import warnings from random import Random from typing import Callable from tests.core.pyspec.eth2spec.test.context import misc_balances_in_default_range, zero_activation_threshold @@ -24,6 +25,23 @@ from eth2spec.test.context import ( misc_balances, ) +def _warn_if_empty_operations(block): + if len(block.body.deposits) == 0: + warnings.warn(f"deposits missing in block at slot {block.slot}") + + if len(block.body.proposer_slashings) == 0: + warnings.warn(f"proposer slashings missing in block at slot {block.slot}") + + if len(block.body.attester_slashings) == 0: + warnings.warn(f"attester slashings missing in block at slot {block.slot}") + + if len(block.body.attestations) == 0: + warnings.warn(f"attestations missing in block at slot {block.slot}") + + if len(block.body.voluntary_exits) == 0: + warnings.warn(f"voluntary exits missing in block at slot {block.slot}") + + # May need to make several attempts to find a block that does not correspond to a slashed # proposer with the randomization helpers... BLOCK_ATTEMPTS = 32 @@ -81,6 +99,7 @@ def _random_block(spec, state, _signed_blocks): next_slot(spec, state) block = build_random_block_from_state(spec, state) else: + _warn_if_empty_operations(block) return block else: raise AssertionError("could not find a block with an unslashed proposer, check ``state`` input") From 9e6a51ef70f3e93d0fe4c5c802ee3c2d20b62ff9 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 18:07:12 -0700 Subject: [PATCH 11/55] update fn name for test id --- .../pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index d7749909e..98b251add 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -70,9 +70,9 @@ def _last_slot_in_epoch(spec): def _random_slot_in_epoch(rng): - def f(spec): + def _a_slot_in_epoch(spec): return rng.randrange(1, spec.SLOTS_PER_EPOCH - 2) - return f + return _a_slot_in_epoch def _penultimate_slot_in_epoch(spec): From b17ada2d67ba9c944c75ebc9c9ff52e796a6c8f3 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sat, 21 Aug 2021 18:24:26 -0700 Subject: [PATCH 12/55] only target phase 0 and altair for now --- .../pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 98b251add..05ae545b8 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,8 +1,9 @@ import itertools import warnings from random import Random +from tests.core.pyspec.eth2spec.test.helpers.constants import PHASE0, ALTAIR from typing import Callable -from tests.core.pyspec.eth2spec.test.context import misc_balances_in_default_range, zero_activation_threshold +from tests.core.pyspec.eth2spec.test.context import misc_balances_in_default_range, with_phases, zero_activation_threshold from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state, ) @@ -315,7 +316,7 @@ def _iter_temporal(spec, callable_or_int): @pytest_generate_tests_adapter -@with_all_phases +@with_phases([PHASE0, ALTAIR]) @with_custom_state(balances_fn=misc_balances_in_default_range, threshold_fn=zero_activation_threshold) @spec_test @single_phase From 513f57f74c923d7300fe06a879d56a8340be6d6f Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 09:55:41 -0700 Subject: [PATCH 13/55] formatting --- .../eth2spec/test/phase0/sanity/test_blocks_random.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 05ae545b8..cead514a5 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -233,7 +233,10 @@ def _generate_randomized_scenarios(): rng = Random(1336) # go forward 0 or 1 epochs - epochs_set = (_epoch_transition(n=0), _epoch_transition(n=1)) + epochs_set = ( + _epoch_transition(n=0), + _epoch_transition(n=1), + ) # within those epochs, go forward to: slots_set = ( # the first slot in an epoch (see note in docstring about offsets...) @@ -253,7 +256,10 @@ def _generate_randomized_scenarios(): # and preface each block transition with the possible leak transitions # (... either no leak or transition to a leak before applying the block transition) - leak_transitions = (_no_op_transition, _transition_to_leaking) + leak_transitions = ( + _no_op_transition, + _transition_to_leaking, + ) scenarios = [ {"transitions": list(t)} for t in itertools.product(leak_transitions, block_transitions) From 820affd2aaa8e9f0d889a125d43ef0d62936eb8c Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 09:58:54 -0700 Subject: [PATCH 14/55] extend validator set so randomized helpers have more room for operation --- tests/core/pyspec/eth2spec/test/context.py | 5 +++-- .../eth2spec/test/phase0/sanity/test_blocks_random.py | 11 +++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index a6828f7e0..f6f120d55 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -152,12 +152,13 @@ def misc_balances(spec): return balances -def misc_balances_in_default_range(spec): +def misc_balances_in_default_range_with_many_validators(spec): """ Helper method to create a series of balances that includes some misc. balances but none that are below the ``EJECTION_BALANCE``. """ - num_validators = spec.SLOTS_PER_EPOCH * 8 + # Double validators to facilitate randomized testing + num_validators = spec.SLOTS_PER_EPOCH * 8 * 2 floor = spec.config.EJECTION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT balances = [ max(spec.MAX_EFFECTIVE_BALANCE * 2 * i // num_validators, floor) for i in range(num_validators) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index cead514a5..52868c744 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -3,7 +3,11 @@ import warnings from random import Random from tests.core.pyspec.eth2spec.test.helpers.constants import PHASE0, ALTAIR from typing import Callable -from tests.core.pyspec.eth2spec.test.context import misc_balances_in_default_range, with_phases, zero_activation_threshold +from tests.core.pyspec.eth2spec.test.context import ( + misc_balances_in_default_range_with_many_validators, + with_phases, + zero_activation_threshold, +) from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state, ) @@ -323,7 +327,10 @@ def _iter_temporal(spec, callable_or_int): @pytest_generate_tests_adapter @with_phases([PHASE0, ALTAIR]) -@with_custom_state(balances_fn=misc_balances_in_default_range, threshold_fn=zero_activation_threshold) +@with_custom_state( + balances_fn=misc_balances_in_default_range_with_many_validators, + threshold_fn=zero_activation_threshold +) @spec_test @single_phase @always_bls From 270814e20fbc9b80cbe6c34eb1dff5534a4cd52e Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 09:59:28 -0700 Subject: [PATCH 15/55] fix bug with `_epochs_until_leak` helper --- .../eth2spec/test/phase0/sanity/test_blocks_random.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 52868c744..e0043332d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -61,7 +61,11 @@ def _randomize_state(spec, state): ## epochs def _epochs_until_leak(spec): - return spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + """ + State is "leaking" if the current epoch is at least + this value after the last finalized epoch. + """ + return spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 1 def _epochs_for_shard_committee_period(spec): From 993997aca5ddf88d17db341791ac89156adee77b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 10:07:31 -0700 Subject: [PATCH 16/55] ensure no leak on "normal" transitions --- .../test/phase0/sanity/test_blocks_random.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index e0043332d..c3b55e49d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -124,8 +124,19 @@ def _validate_is_leaking(spec, state): return spec.is_in_inactivity_leak(state) +def _validate_is_not_leaking(spec, state): + return not _validate_is_leaking(spec, state) + + # transitions +def _with_validation(transition, validation): + if isinstance(transition, Callable): + transition = transition() + transition["validation"] = validation + return transition + + def _no_op_transition(): return {} @@ -264,8 +275,9 @@ def _generate_randomized_scenarios(): # and preface each block transition with the possible leak transitions # (... either no leak or transition to a leak before applying the block transition) + _transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) leak_transitions = ( - _no_op_transition, + _transition_without_leak, _transition_to_leaking, ) scenarios = [ From f76a29c1f9b2ede7cc2ce371d1e5b94df2fef85f Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 10:52:22 -0700 Subject: [PATCH 17/55] patch state to not be leaking at start --- .../test/phase0/sanity/test_blocks_random.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index c3b55e49d..c379d5815 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -197,10 +197,35 @@ def _randomized_scenario_setup(): state.slot += slots_to_skip return f + def _simulate_honest_execution(spec, state): + """ + Want to start tests not in a leak state; the finality data + may not reflect this condition with prior (arbitrary) mutations, + so this mutator addresses that fact. + """ + state.justification_bits = (True, True, True, True) + previous_epoch = spec.get_previous_epoch(state) + previous_root = spec.get_block_root(state, previous_epoch) + previous_previous_epoch = max(spec.GENESIS_EPOCH, spec.Epoch(previous_epoch - 1)) + previous_previous_root = spec.get_block_root(state, previous_previous_epoch) + state.previous_justified_checkpoint = spec.Checkpoint( + epoch=previous_previous_epoch, + root=previous_previous_root, + ) + state.current_justified_checkpoint = spec.Checkpoint( + epoch=previous_epoch, + root=previous_root, + ) + state.finalized_checkpoint = spec.Checkpoint( + epoch=previous_previous_epoch, + root=previous_previous_root, + ) + return ( # NOTE: the block randomization function assumes at least 1 shard committee period # so advance the state before doing anything else. (_skip_epochs(_epochs_for_shard_committee_period), _no_op_validation), + (_simulate_honest_execution, _no_op_validation), (_randomize_state, ensure_state_has_validators_across_lifecycle), ) From ce471b702e57114e3c66a8cec13f8f14b627ca46 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 10:54:00 -0700 Subject: [PATCH 18/55] code org --- .../pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index c379d5815..93f31a4da 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -160,6 +160,8 @@ def _transition_to_leaking(): } +_transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) + ## block transitions def _transition_with_random_block(epochs=None, slots=None): @@ -300,7 +302,6 @@ def _generate_randomized_scenarios(): # and preface each block transition with the possible leak transitions # (... either no leak or transition to a leak before applying the block transition) - _transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) leak_transitions = ( _transition_without_leak, _transition_to_leaking, From 0c401a3e2a470b8f567f53e03254ffe6536ae0f1 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 12:13:40 -0700 Subject: [PATCH 19/55] filter for exit eligibility in helper --- .../eth2spec/test/helpers/multi_operations.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 2629206e7..54e45b335 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -125,12 +125,24 @@ def prepare_state_and_get_random_deposits(spec, state, rng): return deposits +def _eligible_for_exit(spec, state, index): + validator = state.validators[index] + + not_slashed = not validator.slashed + + current_epoch = spec.get_current_epoch(state) + activation_epoch = validator.activation_epoch + active_for_long_enough = current_epoch >= activation_epoch + spec.config.SHARD_COMMITTEE_PERIOD + + return not_slashed and active_for_long_enough + + def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): num_exits = rng.randrange(spec.MAX_VOLUNTARY_EXITS) active_indices = set(spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy()) indices = set( index for index in active_indices - if not state.validators[index].slashed + if _eligible_for_exit(spec, state, index) ) eligible_indices = indices - to_be_slashed_indices indices_count = min(num_exits, len(eligible_indices)) From 253f927c0a45c4830c54f2fd99163e8191f9b6b3 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 12:14:17 -0700 Subject: [PATCH 20/55] fix randomness seed across randomized test --- .../pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 93f31a4da..8928b9309 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,6 +1,6 @@ import itertools import warnings -from random import Random +import random from tests.core.pyspec.eth2spec.test.helpers.constants import PHASE0, ALTAIR from typing import Callable from tests.core.pyspec.eth2spec.test.context import ( @@ -276,7 +276,7 @@ def _generate_randomized_scenarios(): NOTE: the main block driver builds a block for the **next** slot, so the slot transitions are offset by -1 to target certain boundaries. """ - rng = Random(1336) + rng = random.Random(1336) # go forward 0 or 1 epochs epochs_set = ( @@ -377,6 +377,7 @@ def _iter_temporal(spec, callable_or_int): @single_phase @always_bls def test_harness_for_randomized_blocks(spec, state, test_description): + random.seed(1337) for mutation, validation in test_description["setup"]: mutation(spec, state) validation(spec, state) From 2db01ba6d06bb3290f6d2ac02b59152cee4615c0 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Sun, 22 Aug 2021 13:33:30 -0700 Subject: [PATCH 21/55] use fixed seed for block randomization --- .../eth2spec/test/phase0/sanity/test_blocks_random.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 8928b9309..7279e19d0 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -30,6 +30,8 @@ from eth2spec.test.context import ( misc_balances, ) +rng = random.Random(1337) + def _warn_if_empty_operations(block): if len(block.body.deposits) == 0: warnings.warn(f"deposits missing in block at slot {block.slot}") @@ -101,7 +103,7 @@ def _random_block(spec, state, _signed_blocks): to produce a block over ``BLOCK_ATTEMPTS`` slots in order to find a valid block in the event that the proposer has already been slashed. """ - block = build_random_block_from_state(spec, state) + block = build_random_block_from_state(spec, state, rng) for _ in range(BLOCK_ATTEMPTS): proposer = state.validators[block.proposer_index] if proposer.slashed: @@ -276,8 +278,6 @@ def _generate_randomized_scenarios(): NOTE: the main block driver builds a block for the **next** slot, so the slot transitions are offset by -1 to target certain boundaries. """ - rng = random.Random(1336) - # go forward 0 or 1 epochs epochs_set = ( _epoch_transition(n=0), @@ -377,7 +377,6 @@ def _iter_temporal(spec, callable_or_int): @single_phase @always_bls def test_harness_for_randomized_blocks(spec, state, test_description): - random.seed(1337) for mutation, validation in test_description["setup"]: mutation(spec, state) validation(spec, state) From 361d97c54bf0f97dd1a31142186b0ac02e7be83c Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 09:54:00 -0700 Subject: [PATCH 22/55] fix bug with proposer search --- .../pyspec/eth2spec/test/helpers/multi_operations.py | 4 ++-- .../eth2spec/test/phase0/sanity/test_blocks_random.py | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 54e45b335..c53cc40c7 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -150,7 +150,7 @@ def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): return prepare_signed_exits(spec, state, exit_indices) -def build_random_block_from_state(spec, state, rng=Random(2188)): +def build_random_block_from_state_for_next_slot(spec, state, rng=Random(2188)): # prepare state for deposits before building block deposits = prepare_state_and_get_random_deposits(spec, state, rng) @@ -177,7 +177,7 @@ def run_test_full_random_operations(spec, state, rng=Random(2080)): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - block = build_random_block_from_state(spec, state, rng) + block = build_random_block_from_state_for_next_slot(spec, state, rng) yield 'pre', state diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 7279e19d0..fb7b308f6 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -9,7 +9,7 @@ from tests.core.pyspec.eth2spec.test.context import ( zero_activation_threshold, ) from eth2spec.test.helpers.multi_operations import ( - build_random_block_from_state, + build_random_block_from_state_for_next_slot, ) from eth2spec.test.helpers.state import ( next_epoch, @@ -103,13 +103,16 @@ def _random_block(spec, state, _signed_blocks): to produce a block over ``BLOCK_ATTEMPTS`` slots in order to find a valid block in the event that the proposer has already been slashed. """ - block = build_random_block_from_state(spec, state, rng) + temp_state = state.copy() + next_slot(spec, temp_state) for _ in range(BLOCK_ATTEMPTS): - proposer = state.validators[block.proposer_index] + proposer_index = spec.get_beacon_proposer_index(temp_state) + proposer = state.validators[proposer_index] if proposer.slashed: next_slot(spec, state) - block = build_random_block_from_state(spec, state) + next_slot(spec, temp_state) else: + block = build_random_block_from_state_for_next_slot(spec, state) _warn_if_empty_operations(block) return block else: From 6316c7d364888264b209c6cbd01b9e6373fe6c0b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 10:29:39 -0700 Subject: [PATCH 23/55] ensure at least 1 attester slashing --- tests/core/pyspec/eth2spec/test/helpers/multi_operations.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index c53cc40c7..962ab6404 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -61,7 +61,9 @@ def get_random_proposer_slashings(spec, state, rng): def get_random_attester_slashings(spec, state, rng): - num_slashings = rng.randrange(spec.MAX_ATTESTER_SLASHINGS) + # ensure at least one attester slashing, the max count + # is small so not much room for random inclusion + num_slashings = max(1, rng.randrange(spec.MAX_ATTESTER_SLASHINGS)) active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() indices = [ index for index in active_indices From 16423880aa6d8335125e6c73507848c846289c4a Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 11:00:33 -0700 Subject: [PATCH 24/55] add multiple blocks to each test --- .../test/phase0/sanity/test_blocks_random.py | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index fb7b308f6..4051f9c7d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -52,6 +52,8 @@ def _warn_if_empty_operations(block): # May need to make several attempts to find a block that does not correspond to a slashed # proposer with the randomization helpers... BLOCK_ATTEMPTS = 32 +# Ensure this many blocks are present in *each* randomized scenario +BLOCK_TRANSITIONS_COUNT = 2 # primitives ## state @@ -269,6 +271,15 @@ def _normalize_scenarios(scenarios): transitions[i] = _normalize_transition(transition) +def _flatten(t): + leak_transition = t[0] + result = [leak_transition] + for transition_batch in t[1]: + for transition in transition_batch: + result.append(transition) + return result + + def _generate_randomized_scenarios(): """ Generates a set of randomized testing scenarios. @@ -297,20 +308,24 @@ def _generate_randomized_scenarios(): # the last slot in an epoch (see note in docstring about offsets...) _slot_transition(_penultimate_slot_in_epoch), ) - # build a set of block transitions from combinations of sub-transitions - block_transitions = list( - _transition_with_random_block(epochs=epochs, slots=slots) - for epochs, slots in itertools.product(epochs_set, slots_set) + # and produce a block... + blocks_set = ( + _transition_with_random_block, ) + # build a set of block transitions from combinations of sub-transitions + transitions_generator = ( + itertools.product(epochs_set, slots_set, blocks_set) for + _ in range(BLOCK_TRANSITIONS_COUNT) + ) + block_transitions = zip(*transitions_generator) - # and preface each block transition with the possible leak transitions - # (... either no leak or transition to a leak before applying the block transition) + # and preface each set of block transitions with the possible leak transitions leak_transitions = ( _transition_without_leak, _transition_to_leaking, ) scenarios = [ - {"transitions": list(t)} + {"transitions": _flatten(t)} for t in itertools.product(leak_transitions, block_transitions) ] _normalize_scenarios(scenarios) From 20e3934fa2fd66ca7dcc53b67f75fe088ae93ac2 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 11:12:40 -0700 Subject: [PATCH 25/55] do not exit validators who are already exited --- tests/core/pyspec/eth2spec/test/helpers/multi_operations.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 962ab6404..52234fa97 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -136,7 +136,9 @@ def _eligible_for_exit(spec, state, index): activation_epoch = validator.activation_epoch active_for_long_enough = current_epoch >= activation_epoch + spec.config.SHARD_COMMITTEE_PERIOD - return not_slashed and active_for_long_enough + not_exited = validator.exit_epoch == spec.FAR_FUTURE_EPOCH + + return not_slashed and active_for_long_enough and not_exited def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): From 31d46247ce403651d98dc4a2bcbb41c799a4533e Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 11:48:22 -0700 Subject: [PATCH 26/55] file re-org to re-use for later forks --- .../test/phase0/sanity/test_blocks_random.py | 403 +----------------- .../pyspec/eth2spec/test/utils/__init__.py | 5 + .../core/pyspec/eth2spec/test/utils/random.py | 398 +++++++++++++++++ .../pyspec/eth2spec/test/{ => utils}/utils.py | 0 4 files changed, 412 insertions(+), 394 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/utils/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/utils/random.py rename tests/core/pyspec/eth2spec/test/{ => utils}/utils.py (100%) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 4051f9c7d..6ea793206 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,392 +1,30 @@ -import itertools -import warnings -import random -from tests.core.pyspec.eth2spec.test.helpers.constants import PHASE0, ALTAIR -from typing import Callable +from tests.core.pyspec.eth2spec.test.helpers.constants import PHASE0 from tests.core.pyspec.eth2spec.test.context import ( misc_balances_in_default_range_with_many_validators, with_phases, zero_activation_threshold, ) -from eth2spec.test.helpers.multi_operations import ( - build_random_block_from_state_for_next_slot, -) -from eth2spec.test.helpers.state import ( - next_epoch, - next_slot, - ensure_state_has_validators_across_lifecycle, - state_transition_and_sign_block, -) -from eth2spec.test.helpers.random import ( - randomize_state, -) from eth2spec.test.context import ( - with_all_phases, always_bls, spec_test, with_custom_state, - default_activation_threshold, single_phase, - misc_balances, ) - -rng = random.Random(1337) - -def _warn_if_empty_operations(block): - if len(block.body.deposits) == 0: - warnings.warn(f"deposits missing in block at slot {block.slot}") - - if len(block.body.proposer_slashings) == 0: - warnings.warn(f"proposer slashings missing in block at slot {block.slot}") - - if len(block.body.attester_slashings) == 0: - warnings.warn(f"attester slashings missing in block at slot {block.slot}") - - if len(block.body.attestations) == 0: - warnings.warn(f"attestations missing in block at slot {block.slot}") - - if len(block.body.voluntary_exits) == 0: - warnings.warn(f"voluntary exits missing in block at slot {block.slot}") - - -# May need to make several attempts to find a block that does not correspond to a slashed -# proposer with the randomization helpers... -BLOCK_ATTEMPTS = 32 -# Ensure this many blocks are present in *each* randomized scenario -BLOCK_TRANSITIONS_COUNT = 2 - -# primitives -## state - -def _randomize_state(spec, state): - return randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) - - -## epochs - -def _epochs_until_leak(spec): - """ - State is "leaking" if the current epoch is at least - this value after the last finalized epoch. - """ - return spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 1 - - -def _epochs_for_shard_committee_period(spec): - return spec.config.SHARD_COMMITTEE_PERIOD - - -## slots - -def _last_slot_in_epoch(spec): - return spec.SLOTS_PER_EPOCH - 1 - - -def _random_slot_in_epoch(rng): - def _a_slot_in_epoch(spec): - return rng.randrange(1, spec.SLOTS_PER_EPOCH - 2) - return _a_slot_in_epoch - - -def _penultimate_slot_in_epoch(spec): - return spec.SLOTS_PER_EPOCH - 2 - - -## blocks - -def _no_block(_spec, _pre_state, _signed_blocks): - return None - - -def _random_block(spec, state, _signed_blocks): - """ - Produce a random block. - NOTE: this helper may mutate state, as it will attempt - to produce a block over ``BLOCK_ATTEMPTS`` slots in order - to find a valid block in the event that the proposer has already been slashed. - """ - temp_state = state.copy() - next_slot(spec, temp_state) - for _ in range(BLOCK_ATTEMPTS): - proposer_index = spec.get_beacon_proposer_index(temp_state) - proposer = state.validators[proposer_index] - if proposer.slashed: - next_slot(spec, state) - next_slot(spec, temp_state) - else: - block = build_random_block_from_state_for_next_slot(spec, state) - _warn_if_empty_operations(block) - return block - else: - raise AssertionError("could not find a block with an unslashed proposer, check ``state`` input") - - -## validations - -def _no_op_validation(spec, state): - return True - - -def _validate_is_leaking(spec, state): - return spec.is_in_inactivity_leak(state) - - -def _validate_is_not_leaking(spec, state): - return not _validate_is_leaking(spec, state) - - -# transitions - -def _with_validation(transition, validation): - if isinstance(transition, Callable): - transition = transition() - transition["validation"] = validation - return transition - - -def _no_op_transition(): - return {} - - -def _epoch_transition(n=0): - return { - "epochs_to_skip": n, - } - - -def _slot_transition(n=0): - return { - "slots_to_skip": n, - } - - -def _transition_to_leaking(): - return { - "epochs_to_skip": _epochs_until_leak, - "validation": _validate_is_leaking, - } - - -_transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) - -## block transitions - -def _transition_with_random_block(epochs=None, slots=None): - """ - Build a block transition with randomized data. - Provide optional sub-transitions to advance some - number of epochs or slots before applying the random block. - """ - transition = { - "block_producer": _random_block, - } - if epochs: - transition.update(epochs) - if slots: - transition.update(slots) - return transition - - -# setup and test gen - -def _randomized_scenario_setup(): - """ - Return a sequence of pairs of ("mutator", "validator"), - a function that accepts (spec, state) arguments and performs some change - and a function that accepts (spec, state) arguments and validates some change was made. - """ - def _skip_epochs(epoch_producer): - def f(spec, state): - """ - The unoptimized spec implementation is too slow to advance via ``next_epoch``. - Instead, just overwrite the ``state.slot`` and continue... - """ - epochs_to_skip = epoch_producer(spec) - slots_to_skip = epochs_to_skip * spec.SLOTS_PER_EPOCH - state.slot += slots_to_skip - return f - - def _simulate_honest_execution(spec, state): - """ - Want to start tests not in a leak state; the finality data - may not reflect this condition with prior (arbitrary) mutations, - so this mutator addresses that fact. - """ - state.justification_bits = (True, True, True, True) - previous_epoch = spec.get_previous_epoch(state) - previous_root = spec.get_block_root(state, previous_epoch) - previous_previous_epoch = max(spec.GENESIS_EPOCH, spec.Epoch(previous_epoch - 1)) - previous_previous_root = spec.get_block_root(state, previous_previous_epoch) - state.previous_justified_checkpoint = spec.Checkpoint( - epoch=previous_previous_epoch, - root=previous_previous_root, - ) - state.current_justified_checkpoint = spec.Checkpoint( - epoch=previous_epoch, - root=previous_root, - ) - state.finalized_checkpoint = spec.Checkpoint( - epoch=previous_previous_epoch, - root=previous_previous_root, - ) - - return ( - # NOTE: the block randomization function assumes at least 1 shard committee period - # so advance the state before doing anything else. - (_skip_epochs(_epochs_for_shard_committee_period), _no_op_validation), - (_simulate_honest_execution, _no_op_validation), - (_randomize_state, ensure_state_has_validators_across_lifecycle), - ) - - -def _normalize_transition(transition): - """ - Provide "empty" or "no op" sub-transitions - to a given transition. - """ - if isinstance(transition, Callable): - transition = transition() - if "epochs_to_skip" not in transition: - transition["epochs_to_skip"] = 0 - if "slots_to_skip" not in transition: - transition["slots_to_skip"] = 0 - if "block_producer" not in transition: - transition["block_producer"] = _no_block - if "validation" not in transition: - transition["validation"] = _no_op_validation - return transition - - -def _normalize_scenarios(scenarios): - """ - "Normalize" a "scenario" so that a producer of a test case - does not need to provide every expected key/value. - """ - for scenario in scenarios: - if "setup" not in scenario: - scenario["setup"] = _randomized_scenario_setup() - - transitions = scenario["transitions"] - for i, transition in enumerate(transitions): - transitions[i] = _normalize_transition(transition) - - -def _flatten(t): - leak_transition = t[0] - result = [leak_transition] - for transition_batch in t[1]: - for transition in transition_batch: - result.append(transition) - return result - - -def _generate_randomized_scenarios(): - """ - Generates a set of randomized testing scenarios. - Return a sequence of "scenarios" where each scenario: - 1. Provides some setup - 2. Provides a sequence of transitions that mutate the state in some way, - possibly yielding blocks along the way - NOTE: scenarios are "normalized" with empty/no-op elements before returning - to the test generation to facilitate brevity when writing scenarios by hand. - NOTE: the main block driver builds a block for the **next** slot, so - the slot transitions are offset by -1 to target certain boundaries. - """ - # go forward 0 or 1 epochs - epochs_set = ( - _epoch_transition(n=0), - _epoch_transition(n=1), - ) - # within those epochs, go forward to: - slots_set = ( - # the first slot in an epoch (see note in docstring about offsets...) - _slot_transition(_last_slot_in_epoch), - # the second slot in an epoch - _slot_transition(n=0), - # some random number of slots, but not at epoch boundaries - _slot_transition(_random_slot_in_epoch(rng)), - # the last slot in an epoch (see note in docstring about offsets...) - _slot_transition(_penultimate_slot_in_epoch), - ) - # and produce a block... - blocks_set = ( - _transition_with_random_block, - ) - # build a set of block transitions from combinations of sub-transitions - transitions_generator = ( - itertools.product(epochs_set, slots_set, blocks_set) for - _ in range(BLOCK_TRANSITIONS_COUNT) - ) - block_transitions = zip(*transitions_generator) - - # and preface each set of block transitions with the possible leak transitions - leak_transitions = ( - _transition_without_leak, - _transition_to_leaking, - ) - scenarios = [ - {"transitions": _flatten(t)} - for t in itertools.product(leak_transitions, block_transitions) - ] - _normalize_scenarios(scenarios) - return scenarios - - -def _id_from_scenario(test_description): - """ - Construct a test name for ``pytest`` infra. - """ - def _to_id_part(prefix, x): - suffix = str(x) - if isinstance(x, Callable): - suffix = x.__name__ - return f"{prefix}{suffix}" - - def _id_from_transition(transition): - return ",".join(( - _to_id_part("epochs:", transition["epochs_to_skip"]), - _to_id_part("slots:", transition["slots_to_skip"]), - _to_id_part("with-block:", transition["block_producer"]) - )) - - return "|".join(map(_id_from_transition, test_description["transitions"])) - +from eth2spec.test.utils.random import ( + generate_randomized_tests, + pytest_generate_tests_adapter, + run_generated_randomized_test, +) def pytest_generate_tests(metafunc): """ Pytest hook to generate test cases from dynamically computed data """ - generated_name = "test_description" - generated_values = _generate_randomized_scenarios() - metafunc.parametrize(generated_name, generated_values, ids=_id_from_scenario, scope="module") - - -def pytest_generate_tests_adapter(f): - """ - Adapter decorator to allow dynamic test case generation - while leveraging existing decorators specific to spec tests. - """ - def wrapper(test_description, *args, **kwargs): - kwargs["test_description"] = test_description - f(*args, **kwargs) - return wrapper - - -def _iter_temporal(spec, callable_or_int): - """ - Intended to advance some number of {epochs, slots}. - Caller can provide a constant integer or a callable deriving a number from - the ``spec`` under consideration. - """ - numeric = callable_or_int - if isinstance(callable_or_int, Callable): - numeric = callable_or_int(spec) - for i in range(numeric): - yield i + generate_randomized_tests(metafunc) @pytest_generate_tests_adapter -@with_phases([PHASE0, ALTAIR]) +@with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, threshold_fn=zero_activation_threshold @@ -395,27 +33,4 @@ def _iter_temporal(spec, callable_or_int): @single_phase @always_bls def test_harness_for_randomized_blocks(spec, state, test_description): - for mutation, validation in test_description["setup"]: - mutation(spec, state) - validation(spec, state) - - yield "pre", state - - blocks = [] - for transition in test_description["transitions"]: - epochs_to_skip = _iter_temporal(spec, transition["epochs_to_skip"]) - for _ in epochs_to_skip: - next_epoch(spec, state) - slots_to_skip = _iter_temporal(spec, transition["slots_to_skip"]) - for _ in slots_to_skip: - next_slot(spec, state) - - block = transition["block_producer"](spec, state, blocks) - if block: - signed_block = state_transition_and_sign_block(spec, state, block) - blocks.append(signed_block) - - assert transition["validation"](spec, state) - - yield "blocks", blocks - yield "post", state + yield from run_generated_randomized_test(spec, state, test_description) diff --git a/tests/core/pyspec/eth2spec/test/utils/__init__.py b/tests/core/pyspec/eth2spec/test/utils/__init__.py new file mode 100644 index 000000000..56e4d44ca --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/utils/__init__.py @@ -0,0 +1,5 @@ +from .utils import ( + vector_test, + with_meta_tags, + build_transition_test, +) diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py new file mode 100644 index 000000000..f28f7ff70 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -0,0 +1,398 @@ +""" +Utility code to generate randomized block tests +""" + +import itertools +import random +import warnings +from typing import Callable +from eth2spec.test.helpers.multi_operations import ( + build_random_block_from_state_for_next_slot, +) +from eth2spec.test.helpers.state import ( + next_slot, + next_epoch, + ensure_state_has_validators_across_lifecycle, + state_transition_and_sign_block, +) +from eth2spec.test.helpers.random import ( + randomize_state, +) + +rng = random.Random(1337) + +def _warn_if_empty_operations(block): + if len(block.body.deposits) == 0: + warnings.warn(f"deposits missing in block at slot {block.slot}") + + if len(block.body.proposer_slashings) == 0: + warnings.warn(f"proposer slashings missing in block at slot {block.slot}") + + if len(block.body.attester_slashings) == 0: + warnings.warn(f"attester slashings missing in block at slot {block.slot}") + + if len(block.body.attestations) == 0: + warnings.warn(f"attestations missing in block at slot {block.slot}") + + if len(block.body.voluntary_exits) == 0: + warnings.warn(f"voluntary exits missing in block at slot {block.slot}") + + +# May need to make several attempts to find a block that does not correspond to a slashed +# proposer with the randomization helpers... +BLOCK_ATTEMPTS = 32 +# Ensure this many blocks are present in *each* randomized scenario +BLOCK_TRANSITIONS_COUNT = 2 + +# primitives +## state + +def _randomize_state(spec, state): + return randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) + + +## epochs + +def _epochs_until_leak(spec): + """ + State is "leaking" if the current epoch is at least + this value after the last finalized epoch. + """ + return spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 1 + + +def _epochs_for_shard_committee_period(spec): + return spec.config.SHARD_COMMITTEE_PERIOD + + +## slots + +def _last_slot_in_epoch(spec): + return spec.SLOTS_PER_EPOCH - 1 + + +def _random_slot_in_epoch(rng): + def _a_slot_in_epoch(spec): + return rng.randrange(1, spec.SLOTS_PER_EPOCH - 2) + return _a_slot_in_epoch + + +def _penultimate_slot_in_epoch(spec): + return spec.SLOTS_PER_EPOCH - 2 + + +## blocks + +def _no_block(_spec, _pre_state, _signed_blocks): + return None + + +def _random_block(spec, state, _signed_blocks): + """ + Produce a random block. + NOTE: this helper may mutate state, as it will attempt + to produce a block over ``BLOCK_ATTEMPTS`` slots in order + to find a valid block in the event that the proposer has already been slashed. + """ + temp_state = state.copy() + next_slot(spec, temp_state) + for _ in range(BLOCK_ATTEMPTS): + proposer_index = spec.get_beacon_proposer_index(temp_state) + proposer = state.validators[proposer_index] + if proposer.slashed: + next_slot(spec, state) + next_slot(spec, temp_state) + else: + block = build_random_block_from_state_for_next_slot(spec, state) + _warn_if_empty_operations(block) + return block + else: + raise AssertionError("could not find a block with an unslashed proposer, check ``state`` input") + + +## validations + +def _no_op_validation(spec, state): + return True + + +def _validate_is_leaking(spec, state): + return spec.is_in_inactivity_leak(state) + + +def _validate_is_not_leaking(spec, state): + return not _validate_is_leaking(spec, state) + + +# transitions + +def _with_validation(transition, validation): + if isinstance(transition, Callable): + transition = transition() + transition["validation"] = validation + return transition + + +def _no_op_transition(): + return {} + + +def _epoch_transition(n=0): + return { + "epochs_to_skip": n, + } + + +def _slot_transition(n=0): + return { + "slots_to_skip": n, + } + + +def _transition_to_leaking(): + return { + "epochs_to_skip": _epochs_until_leak, + "validation": _validate_is_leaking, + } + + +_transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) + +## block transitions + +def _transition_with_random_block(block_randomizer): + """ + Build a block transition with randomized data. + Provide optional sub-transitions to advance some + number of epochs or slots before applying the random block. + """ + return { + "block_producer": block_randomizer, + } + + +# setup and test gen + +def _randomized_scenario_setup(state_randomizer): + """ + Return a sequence of pairs of ("mutator", "validator"), + a function that accepts (spec, state) arguments and performs some change + and a function that accepts (spec, state) arguments and validates some change was made. + """ + def _skip_epochs(epoch_producer): + def f(spec, state): + """ + The unoptimized spec implementation is too slow to advance via ``next_epoch``. + Instead, just overwrite the ``state.slot`` and continue... + """ + epochs_to_skip = epoch_producer(spec) + slots_to_skip = epochs_to_skip * spec.SLOTS_PER_EPOCH + state.slot += slots_to_skip + return f + + def _simulate_honest_execution(spec, state): + """ + Want to start tests not in a leak state; the finality data + may not reflect this condition with prior (arbitrary) mutations, + so this mutator addresses that fact. + """ + state.justification_bits = (True, True, True, True) + previous_epoch = spec.get_previous_epoch(state) + previous_root = spec.get_block_root(state, previous_epoch) + previous_previous_epoch = max(spec.GENESIS_EPOCH, spec.Epoch(previous_epoch - 1)) + previous_previous_root = spec.get_block_root(state, previous_previous_epoch) + state.previous_justified_checkpoint = spec.Checkpoint( + epoch=previous_previous_epoch, + root=previous_previous_root, + ) + state.current_justified_checkpoint = spec.Checkpoint( + epoch=previous_epoch, + root=previous_root, + ) + state.finalized_checkpoint = spec.Checkpoint( + epoch=previous_previous_epoch, + root=previous_previous_root, + ) + + return ( + # NOTE: the block randomization function assumes at least 1 shard committee period + # so advance the state before doing anything else. + (_skip_epochs(_epochs_for_shard_committee_period), _no_op_validation), + (_simulate_honest_execution, _no_op_validation), + (state_randomizer, ensure_state_has_validators_across_lifecycle), + ) + + +def _normalize_transition(transition): + """ + Provide "empty" or "no op" sub-transitions + to a given transition. + """ + if isinstance(transition, Callable): + transition = transition() + if "epochs_to_skip" not in transition: + transition["epochs_to_skip"] = 0 + if "slots_to_skip" not in transition: + transition["slots_to_skip"] = 0 + if "block_producer" not in transition: + transition["block_producer"] = _no_block + if "validation" not in transition: + transition["validation"] = _no_op_validation + return transition + + +def _normalize_scenarios(scenarios, state_randomizer): + """ + "Normalize" a "scenario" so that a producer of a test case + does not need to provide every expected key/value. + """ + for scenario in scenarios: + if "setup" not in scenario: + scenario["setup"] = _randomized_scenario_setup(state_randomizer) + + transitions = scenario["transitions"] + for i, transition in enumerate(transitions): + transitions[i] = _normalize_transition(transition) + + +def _flatten(t): + leak_transition = t[0] + result = [leak_transition] + for transition_batch in t[1]: + for transition in transition_batch: + result.append(transition) + return result + + +def _generate_randomized_scenarios(state_randomizer, block_randomizer): + """ + Generates a set of randomized testing scenarios. + Return a sequence of "scenarios" where each scenario: + 1. Provides some setup + 2. Provides a sequence of transitions that mutate the state in some way, + possibly yielding blocks along the way + NOTE: scenarios are "normalized" with empty/no-op elements before returning + to the test generation to facilitate brevity when writing scenarios by hand. + NOTE: the main block driver builds a block for the **next** slot, so + the slot transitions are offset by -1 to target certain boundaries. + """ + # go forward 0 or 1 epochs + epochs_set = ( + _epoch_transition(n=0), + _epoch_transition(n=1), + ) + # within those epochs, go forward to: + slots_set = ( + # the first slot in an epoch (see note in docstring about offsets...) + _slot_transition(_last_slot_in_epoch), + # the second slot in an epoch + _slot_transition(n=0), + # some random number of slots, but not at epoch boundaries + _slot_transition(_random_slot_in_epoch(rng)), + # the last slot in an epoch (see note in docstring about offsets...) + _slot_transition(_penultimate_slot_in_epoch), + ) + # and produce a block... + blocks_set = ( + _transition_with_random_block(block_randomizer), + ) + # build a set of block transitions from combinations of sub-transitions + transitions_generator = ( + itertools.product(epochs_set, slots_set, blocks_set) for + _ in range(BLOCK_TRANSITIONS_COUNT) + ) + block_transitions = zip(*transitions_generator) + + # and preface each set of block transitions with the possible leak transitions + leak_transitions = ( + _transition_without_leak, + _transition_to_leaking, + ) + scenarios = [ + {"transitions": _flatten(t)} + for t in itertools.product(leak_transitions, block_transitions) + ] + _normalize_scenarios(scenarios, state_randomizer) + return scenarios + + +def _id_from_scenario(test_description): + """ + Construct a test name for ``pytest`` infra. + """ + def _to_id_part(prefix, x): + suffix = str(x) + if isinstance(x, Callable): + suffix = x.__name__ + return f"{prefix}{suffix}" + + def _id_from_transition(transition): + return ",".join(( + _to_id_part("epochs:", transition["epochs_to_skip"]), + _to_id_part("slots:", transition["slots_to_skip"]), + _to_id_part("with-block:", transition["block_producer"]) + )) + + return "|".join(map(_id_from_transition, test_description["transitions"])) + +# Generate a series of randomized block tests: + +def generate_randomized_tests(metafunc, state_randomizer=_randomize_state, block_randomizer=_random_block): + """ + Pytest hook to generate test cases from dynamically computed data + """ + generated_name = "test_description" + generated_values = _generate_randomized_scenarios(state_randomizer, block_randomizer) + metafunc.parametrize(generated_name, generated_values, ids=_id_from_scenario, scope="module") + + +def pytest_generate_tests_adapter(f): + """ + Adapter decorator to allow dynamic test case generation + while leveraging existing decorators specific to spec tests. + """ + def wrapper(test_description, *args, **kwargs): + kwargs["test_description"] = test_description + f(*args, **kwargs) + return wrapper + +# Run the generated tests: + +def _iter_temporal(spec, callable_or_int): + """ + Intended to advance some number of {epochs, slots}. + Caller can provide a constant integer or a callable deriving a number from + the ``spec`` under consideration. + """ + numeric = callable_or_int + if isinstance(callable_or_int, Callable): + numeric = callable_or_int(spec) + for i in range(numeric): + yield i + + +def run_generated_randomized_test(spec, state, test_description): + for mutation, validation in test_description["setup"]: + mutation(spec, state) + validation(spec, state) + + yield "pre", state + + blocks = [] + for transition in test_description["transitions"]: + epochs_to_skip = _iter_temporal(spec, transition["epochs_to_skip"]) + for _ in epochs_to_skip: + next_epoch(spec, state) + slots_to_skip = _iter_temporal(spec, transition["slots_to_skip"]) + for _ in slots_to_skip: + next_slot(spec, state) + + block = transition["block_producer"](spec, state, blocks) + if block: + signed_block = state_transition_and_sign_block(spec, state, block) + blocks.append(signed_block) + + assert transition["validation"](spec, state) + + yield "blocks", blocks + yield "post", state diff --git a/tests/core/pyspec/eth2spec/test/utils.py b/tests/core/pyspec/eth2spec/test/utils/utils.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/utils.py rename to tests/core/pyspec/eth2spec/test/utils/utils.py From ff6863e6899a92c89006d985625587ef6da4ac68 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 12:01:05 -0700 Subject: [PATCH 27/55] fix bug with deposit generation code --- tests/core/pyspec/eth2spec/test/helpers/multi_operations.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 52234fa97..32998b3ba 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -103,6 +103,7 @@ def prepare_state_and_get_random_deposits(spec, state, rng): deposits = [] # First build deposit data leaves + root = None for i in range(num_deposits): index = len(state.validators) + i _, root, deposit_data_leaves = build_deposit( @@ -115,7 +116,9 @@ def prepare_state_and_get_random_deposits(spec, state, rng): signed=True, ) - state.eth1_data.deposit_root = root + if root: + # NOTE: if ``num_deposits == 0``, ``root`` is never assigned to + state.eth1_data.deposit_root = root state.eth1_data.deposit_count += num_deposits # Then for that context, build deposits/proofs From 7b9d70fcec86f82a33256c6fa52bcab6e8cfce07 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 12:15:09 -0700 Subject: [PATCH 28/55] allow test customization (for future forks) --- tests/core/pyspec/eth2spec/test/utils/random.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index f28f7ff70..b50a67349 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -16,7 +16,7 @@ from eth2spec.test.helpers.state import ( state_transition_and_sign_block, ) from eth2spec.test.helpers.random import ( - randomize_state, + randomize_state as randomize_state_helper, ) rng = random.Random(1337) @@ -47,8 +47,8 @@ BLOCK_TRANSITIONS_COUNT = 2 # primitives ## state -def _randomize_state(spec, state): - return randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) +def randomize_state(spec, state): + randomize_state_helper(spec, state, exit_fraction=0.1, slash_fraction=0.1) ## epochs @@ -87,7 +87,7 @@ def _no_block(_spec, _pre_state, _signed_blocks): return None -def _random_block(spec, state, _signed_blocks): +def random_block(spec, state, _signed_blocks): """ Produce a random block. NOTE: this helper may mutate state, as it will attempt @@ -337,7 +337,7 @@ def _id_from_scenario(test_description): # Generate a series of randomized block tests: -def generate_randomized_tests(metafunc, state_randomizer=_randomize_state, block_randomizer=_random_block): +def generate_randomized_tests(metafunc, state_randomizer=randomize_state, block_randomizer=random_block): """ Pytest hook to generate test cases from dynamically computed data """ From 58c6f33e8522a176b2065bec9e21aa5fce1ffe6b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 12:15:22 -0700 Subject: [PATCH 29/55] ensure at least one proposer slashing --- tests/core/pyspec/eth2spec/test/helpers/multi_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 32998b3ba..68ca02b91 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -44,7 +44,7 @@ def run_slash_and_exit(spec, state, slash_index, exit_index, valid=True): def get_random_proposer_slashings(spec, state, rng): - num_slashings = rng.randrange(spec.MAX_PROPOSER_SLASHINGS) + num_slashings = max(1, rng.randrange(spec.MAX_PROPOSER_SLASHINGS)) active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() indices = [ index for index in active_indices From cc04da8e795ca9d8774f033434765e5be2edafe6 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 12:30:05 -0700 Subject: [PATCH 30/55] add randomized block tests for altair --- .../test/altair/sanity/test_blocks_random.py | 63 +++++++++++++++++++ .../eth2spec/test/helpers/multi_operations.py | 20 ++++++ .../core/pyspec/eth2spec/test/utils/random.py | 4 +- tests/generators/sanity/main.py | 1 + 4 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py diff --git a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py new file mode 100644 index 000000000..b0c0e86b5 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py @@ -0,0 +1,63 @@ +from tests.core.pyspec.eth2spec.test.helpers.constants import ALTAIR +from tests.core.pyspec.eth2spec.test.context import ( + misc_balances_in_default_range_with_many_validators, + with_phases, + zero_activation_threshold, +) +from eth2spec.test.helpers.multi_operations import ( + get_random_sync_aggregate, +) +from eth2spec.test.helpers.inactivity_scores import ( + randomize_inactivity_scores, +) +from eth2spec.test.context import ( + always_bls, + spec_test, + with_custom_state, + single_phase, +) +from eth2spec.test.utils.random import ( + generate_randomized_tests, + pytest_generate_tests_adapter, + run_generated_randomized_test, + random_block, + randomize_state, +) + +SYNC_AGGREGATE_PARTICIPATION_BUCKETS = 4 + +def _randomize_altair_state(spec, state): + randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) + randomize_inactivity_scores(spec, state) + + +def _randomize_altair_block(spec, state, signed_blocks): + block = random_block(spec, state, signed_blocks) + fraction_missed = len(signed_blocks) / SYNC_AGGREGATE_PARTICIPATION_BUCKETS + fraction_participated = 1.0 - fraction_missed + block.body.sync_aggregate = get_random_sync_aggregate(spec, state, fraction_participated=fraction_participated) + return block + + +def pytest_generate_tests(metafunc): + """ + Pytest hook to generate test cases from dynamically computed data + """ + generate_randomized_tests( + metafunc, + state_randomizer=_randomize_altair_state, + block_randomizer=_randomize_altair_block, + ) + + +@pytest_generate_tests_adapter +@with_phases([ALTAIR]) +@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_harness_for_randomized_blocks(spec, state, test_description): + yield from run_generated_randomized_test(spec, state, test_description) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 68ca02b91..10de14253 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -7,6 +7,10 @@ from eth2spec.test.helpers.state import ( from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.sync_committee import ( + compute_committee_indices, + compute_aggregate_sync_committee_signature, +) from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing_by_indices from eth2spec.test.helpers.attestations import get_valid_attestation @@ -192,3 +196,19 @@ def run_test_full_random_operations(spec, state, rng=Random(2080)): yield 'blocks', [signed_block] yield 'post', state + + +def get_random_sync_aggregate(spec, state, fraction_participated=1.0, rng=Random(2099)): + committee_indices = compute_committee_indices(spec, state, state.current_sync_committee) + participant_count = int(len(committee_indices) * fraction_participated) + participants = rng.sample(committee_indices, participant_count) + signature = compute_aggregate_sync_committee_signature( + spec, + state, + state.slot, + participants, + ) + return spec.SyncAggregate( + sync_committee_bits=[index in participants for index in committee_indices], + sync_committee_signature=signature, + ) diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index b50a67349..5a7067b3f 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -47,8 +47,8 @@ BLOCK_TRANSITIONS_COUNT = 2 # primitives ## state -def randomize_state(spec, state): - randomize_state_helper(spec, state, exit_fraction=0.1, slash_fraction=0.1) +def randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1): + randomize_state_helper(spec, state, exit_fraction=exit_fraction, slash_fraction=slash_fraction) ## epochs diff --git a/tests/generators/sanity/main.py b/tests/generators/sanity/main.py index 63efa3897..89e622f1c 100644 --- a/tests/generators/sanity/main.py +++ b/tests/generators/sanity/main.py @@ -10,6 +10,7 @@ if __name__ == "__main__": ]} altair_mods = {**{key: 'eth2spec.test.altair.sanity.test_' + key for key in [ 'blocks', + 'blocks_random', ]}, **phase_0_mods} # also run the previous phase 0 tests # Altair-specific test cases are ignored, but should be included after the Merge is rebased onto Altair work. From d037c6662acb4329269a848af9106a70e8eacb35 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 12:40:42 -0700 Subject: [PATCH 31/55] lint fix --- .../test/altair/sanity/test_blocks_random.py | 1 + .../test/phase0/sanity/test_blocks_random.py | 1 + .../pyspec/eth2spec/test/utils/__init__.py | 7 +++++++ .../core/pyspec/eth2spec/test/utils/random.py | 18 ++++++++++++------ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py index b0c0e86b5..bc391b1f7 100644 --- a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py @@ -26,6 +26,7 @@ from eth2spec.test.utils.random import ( SYNC_AGGREGATE_PARTICIPATION_BUCKETS = 4 + def _randomize_altair_state(spec, state): randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) randomize_inactivity_scores(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 6ea793206..1244785cd 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -16,6 +16,7 @@ from eth2spec.test.utils.random import ( run_generated_randomized_test, ) + def pytest_generate_tests(metafunc): """ Pytest hook to generate test cases from dynamically computed data diff --git a/tests/core/pyspec/eth2spec/test/utils/__init__.py b/tests/core/pyspec/eth2spec/test/utils/__init__.py index 56e4d44ca..f6b2a8a44 100644 --- a/tests/core/pyspec/eth2spec/test/utils/__init__.py +++ b/tests/core/pyspec/eth2spec/test/utils/__init__.py @@ -3,3 +3,10 @@ from .utils import ( with_meta_tags, build_transition_test, ) + + +__all__ = [ # avoid "unused import" lint error + "vector_test", + "with_meta_tags", + "build_transition_test", +] diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index 5a7067b3f..da8e391e8 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -21,6 +21,7 @@ from eth2spec.test.helpers.random import ( rng = random.Random(1337) + def _warn_if_empty_operations(block): if len(block.body.deposits) == 0: warnings.warn(f"deposits missing in block at slot {block.slot}") @@ -45,13 +46,14 @@ BLOCK_ATTEMPTS = 32 BLOCK_TRANSITIONS_COUNT = 2 # primitives -## state +# state + def randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1): randomize_state_helper(spec, state, exit_fraction=exit_fraction, slash_fraction=slash_fraction) -## epochs +# epochs def _epochs_until_leak(spec): """ @@ -65,7 +67,7 @@ def _epochs_for_shard_committee_period(spec): return spec.config.SHARD_COMMITTEE_PERIOD -## slots +# slots def _last_slot_in_epoch(spec): return spec.SLOTS_PER_EPOCH - 1 @@ -81,7 +83,7 @@ def _penultimate_slot_in_epoch(spec): return spec.SLOTS_PER_EPOCH - 2 -## blocks +# blocks def _no_block(_spec, _pre_state, _signed_blocks): return None @@ -110,7 +112,7 @@ def random_block(spec, state, _signed_blocks): raise AssertionError("could not find a block with an unslashed proposer, check ``state`` input") -## validations +# validations def _no_op_validation(spec, state): return True @@ -158,7 +160,8 @@ def _transition_to_leaking(): _transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) -## block transitions +# block transitions + def _transition_with_random_block(block_randomizer): """ @@ -173,6 +176,7 @@ def _transition_with_random_block(block_randomizer): # setup and test gen + def _randomized_scenario_setup(state_randomizer): """ Return a sequence of pairs of ("mutator", "validator"), @@ -337,6 +341,7 @@ def _id_from_scenario(test_description): # Generate a series of randomized block tests: + def generate_randomized_tests(metafunc, state_randomizer=randomize_state, block_randomizer=random_block): """ Pytest hook to generate test cases from dynamically computed data @@ -358,6 +363,7 @@ def pytest_generate_tests_adapter(f): # Run the generated tests: + def _iter_temporal(spec, callable_or_int): """ Intended to advance some number of {epochs, slots}. From 505bdba8f8aaa7be89591e28b8fb8e7e83780ca1 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 23 Aug 2021 12:49:36 -0700 Subject: [PATCH 32/55] fix imports --- .../pyspec/eth2spec/test/altair/sanity/test_blocks_random.py | 4 ++-- .../pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py index bc391b1f7..d546588d7 100644 --- a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py @@ -1,5 +1,5 @@ -from tests.core.pyspec.eth2spec.test.helpers.constants import ALTAIR -from tests.core.pyspec.eth2spec.test.context import ( +from eth2spec.test.helpers.constants import ALTAIR +from eth2spec.test.context import ( misc_balances_in_default_range_with_many_validators, with_phases, zero_activation_threshold, diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py index 1244785cd..96193c3f9 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py @@ -1,5 +1,5 @@ -from tests.core.pyspec.eth2spec.test.helpers.constants import PHASE0 -from tests.core.pyspec.eth2spec.test.context import ( +from eth2spec.test.helpers.constants import PHASE0 +from eth2spec.test.context import ( misc_balances_in_default_range_with_many_validators, with_phases, zero_activation_threshold, From c27e4d140e444ee3543d3cdd9e1f3a7413c61cfa Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 11:21:14 -0700 Subject: [PATCH 33/55] move to code-gen under new test generator --- .../eth2spec/test/altair/random/__init__.py | 0 .../test/altair/random/test_random.py | 421 ++++++++++++++++++ .../test/altair/sanity/test_blocks_random.py | 64 --- .../eth2spec/test/phase0/random/__init__.py | 0 .../test/phase0/random/test_random.py | 421 ++++++++++++++++++ .../test/phase0/sanity/test_blocks_random.py | 37 -- .../core/pyspec/eth2spec/test/utils/random.py | 273 ++++-------- tests/generators/random/Makefile | 7 + tests/generators/random/README.md | 29 ++ tests/generators/random/generate.py | 243 ++++++++++ tests/generators/random/main.py | 18 + tests/generators/random/requirements.txt | 2 + tests/generators/sanity/main.py | 2 - 13 files changed, 1226 insertions(+), 291 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/altair/random/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/altair/random/test_random.py delete mode 100644 tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py create mode 100644 tests/core/pyspec/eth2spec/test/phase0/random/__init__.py create mode 100644 tests/core/pyspec/eth2spec/test/phase0/random/test_random.py delete mode 100644 tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py create mode 100644 tests/generators/random/Makefile create mode 100644 tests/generators/random/README.md create mode 100644 tests/generators/random/generate.py create mode 100644 tests/generators/random/main.py create mode 100644 tests/generators/random/requirements.txt diff --git a/tests/core/pyspec/eth2spec/test/altair/random/__init__.py b/tests/core/pyspec/eth2spec/test/altair/random/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py new file mode 100644 index 000000000..86f8f97b1 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py @@ -0,0 +1,421 @@ +""" +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 ALTAIR +from eth2spec.test.context import ( + misc_balances_in_default_range_with_many_validators, + with_phases, + zero_activation_threshold, +) +from eth2spec.test.context import ( + always_bls, + spec_test, + with_custom_state, + single_phase, +) +from eth2spec.test.utils.random import ( + run_generated_randomized_test, +) + + +@with_phases([ALTAIR]) +@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:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # epochs:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([ALTAIR]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_block_altair + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) diff --git a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py deleted file mode 100644 index d546588d7..000000000 --- a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks_random.py +++ /dev/null @@ -1,64 +0,0 @@ -from eth2spec.test.helpers.constants import ALTAIR -from eth2spec.test.context import ( - misc_balances_in_default_range_with_many_validators, - with_phases, - zero_activation_threshold, -) -from eth2spec.test.helpers.multi_operations import ( - get_random_sync_aggregate, -) -from eth2spec.test.helpers.inactivity_scores import ( - randomize_inactivity_scores, -) -from eth2spec.test.context import ( - always_bls, - spec_test, - with_custom_state, - single_phase, -) -from eth2spec.test.utils.random import ( - generate_randomized_tests, - pytest_generate_tests_adapter, - run_generated_randomized_test, - random_block, - randomize_state, -) - -SYNC_AGGREGATE_PARTICIPATION_BUCKETS = 4 - - -def _randomize_altair_state(spec, state): - randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) - randomize_inactivity_scores(spec, state) - - -def _randomize_altair_block(spec, state, signed_blocks): - block = random_block(spec, state, signed_blocks) - fraction_missed = len(signed_blocks) / SYNC_AGGREGATE_PARTICIPATION_BUCKETS - fraction_participated = 1.0 - fraction_missed - block.body.sync_aggregate = get_random_sync_aggregate(spec, state, fraction_participated=fraction_participated) - return block - - -def pytest_generate_tests(metafunc): - """ - Pytest hook to generate test cases from dynamically computed data - """ - generate_randomized_tests( - metafunc, - state_randomizer=_randomize_altair_state, - block_randomizer=_randomize_altair_block, - ) - - -@pytest_generate_tests_adapter -@with_phases([ALTAIR]) -@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_harness_for_randomized_blocks(spec, state, test_description): - yield from run_generated_randomized_test(spec, state, test_description) diff --git a/tests/core/pyspec/eth2spec/test/phase0/random/__init__.py b/tests/core/pyspec/eth2spec/test/phase0/random/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py new file mode 100644 index 000000000..bfa93330f --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py @@ -0,0 +1,421 @@ +""" +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 PHASE0 +from eth2spec.test.context import ( + misc_balances_in_default_range_with_many_validators, + with_phases, + zero_activation_threshold, +) +from eth2spec.test.context import ( + always_bls, + spec_test, + with_custom_state, + single_phase, +) +from eth2spec.test.utils.random import ( + run_generated_randomized_test, +) + + +@with_phases([PHASE0]) +@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:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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 + # 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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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 + # 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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:1,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) + + +@with_phases([PHASE0]) +@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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:random_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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + yield from run_generated_randomized_test( + spec, + state, + scenario, + ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py deleted file mode 100644 index 96193c3f9..000000000 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks_random.py +++ /dev/null @@ -1,37 +0,0 @@ -from eth2spec.test.helpers.constants import PHASE0 -from eth2spec.test.context import ( - misc_balances_in_default_range_with_many_validators, - with_phases, - zero_activation_threshold, -) -from eth2spec.test.context import ( - always_bls, - spec_test, - with_custom_state, - single_phase, -) -from eth2spec.test.utils.random import ( - generate_randomized_tests, - pytest_generate_tests_adapter, - run_generated_randomized_test, -) - - -def pytest_generate_tests(metafunc): - """ - Pytest hook to generate test cases from dynamically computed data - """ - generate_randomized_tests(metafunc) - - -@pytest_generate_tests_adapter -@with_phases([PHASE0]) -@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_harness_for_randomized_blocks(spec, state, test_description): - yield from run_generated_randomized_test(spec, state, test_description) diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index da8e391e8..b12fca96b 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -2,12 +2,20 @@ Utility code to generate randomized block tests """ -import itertools -import random +import sys import warnings +from random import Random from typing import Callable + from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state_for_next_slot, + get_random_sync_aggregate, +) +from eth2spec.test.helpers.inactivity_scores import ( + randomize_inactivity_scores, +) +from eth2spec.test.helpers.random import ( + randomize_state as randomize_state_helper, ) from eth2spec.test.helpers.state import ( next_slot, @@ -15,37 +23,8 @@ from eth2spec.test.helpers.state import ( ensure_state_has_validators_across_lifecycle, state_transition_and_sign_block, ) -from eth2spec.test.helpers.random import ( - randomize_state as randomize_state_helper, -) -rng = random.Random(1337) - - -def _warn_if_empty_operations(block): - if len(block.body.deposits) == 0: - warnings.warn(f"deposits missing in block at slot {block.slot}") - - if len(block.body.proposer_slashings) == 0: - warnings.warn(f"proposer slashings missing in block at slot {block.slot}") - - if len(block.body.attester_slashings) == 0: - warnings.warn(f"attester slashings missing in block at slot {block.slot}") - - if len(block.body.attestations) == 0: - warnings.warn(f"attestations missing in block at slot {block.slot}") - - if len(block.body.voluntary_exits) == 0: - warnings.warn(f"voluntary exits missing in block at slot {block.slot}") - - -# May need to make several attempts to find a block that does not correspond to a slashed -# proposer with the randomization helpers... -BLOCK_ATTEMPTS = 32 -# Ensure this many blocks are present in *each* randomized scenario -BLOCK_TRANSITIONS_COUNT = 2 - -# primitives +# primitives: # state @@ -53,6 +32,11 @@ def randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1): randomize_state_helper(spec, state, exit_fraction=exit_fraction, slash_fraction=slash_fraction) +def randomize_state_altair(spec, state): + randomize_state(spec, state, exit_fraction=0.1, slash_fraction=0.1) + randomize_inactivity_scores(spec, state) + + # epochs def _epochs_until_leak(spec): @@ -69,26 +53,46 @@ def _epochs_for_shard_committee_period(spec): # slots -def _last_slot_in_epoch(spec): +def last_slot_in_epoch(spec): return spec.SLOTS_PER_EPOCH - 1 -def _random_slot_in_epoch(rng): - def _a_slot_in_epoch(spec): - return rng.randrange(1, spec.SLOTS_PER_EPOCH - 2) - return _a_slot_in_epoch +def random_slot_in_epoch(spec, rng=Random(1336)): + return rng.randrange(1, spec.SLOTS_PER_EPOCH - 2) -def _penultimate_slot_in_epoch(spec): +def penultimate_slot_in_epoch(spec): return spec.SLOTS_PER_EPOCH - 2 # blocks -def _no_block(_spec, _pre_state, _signed_blocks): +def no_block(_spec, _pre_state, _signed_blocks): return None +# May need to make several attempts to find a block that does not correspond to a slashed +# proposer with the randomization helpers... +BLOCK_ATTEMPTS = 32 + + +def _warn_if_empty_operations(block): + if len(block.body.deposits) == 0: + warnings.warn(f"deposits missing in block at slot {block.slot}") + + if len(block.body.proposer_slashings) == 0: + warnings.warn(f"proposer slashings missing in block at slot {block.slot}") + + if len(block.body.attester_slashings) == 0: + warnings.warn(f"attester slashings missing in block at slot {block.slot}") + + if len(block.body.attestations) == 0: + warnings.warn(f"attestations missing in block at slot {block.slot}") + + if len(block.body.voluntary_exits) == 0: + warnings.warn(f"voluntary exits missing in block at slot {block.slot}") + + def random_block(spec, state, _signed_blocks): """ Produce a random block. @@ -112,9 +116,20 @@ def random_block(spec, state, _signed_blocks): raise AssertionError("could not find a block with an unslashed proposer, check ``state`` input") +SYNC_AGGREGATE_PARTICIPATION_BUCKETS = 4 + + +def random_block_altair(spec, state, signed_blocks): + block = random_block(spec, state, signed_blocks) + fraction_missed = len(signed_blocks) / SYNC_AGGREGATE_PARTICIPATION_BUCKETS + fraction_participated = 1.0 - fraction_missed + block.body.sync_aggregate = get_random_sync_aggregate(spec, state, fraction_participated=fraction_participated) + return block + + # validations -def _no_op_validation(spec, state): +def no_op_validation(spec, state): return True @@ -139,31 +154,31 @@ def _no_op_transition(): return {} -def _epoch_transition(n=0): +def epoch_transition(n=0): return { "epochs_to_skip": n, } -def _slot_transition(n=0): +def slot_transition(n=0): return { "slots_to_skip": n, } -def _transition_to_leaking(): +def transition_to_leaking(): return { "epochs_to_skip": _epochs_until_leak, "validation": _validate_is_leaking, } -_transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) +transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) # block transitions -def _transition_with_random_block(block_randomizer): +def transition_with_random_block(block_randomizer): """ Build a block transition with randomized data. Provide optional sub-transitions to advance some @@ -221,163 +236,43 @@ def _randomized_scenario_setup(state_randomizer): return ( # NOTE: the block randomization function assumes at least 1 shard committee period # so advance the state before doing anything else. - (_skip_epochs(_epochs_for_shard_committee_period), _no_op_validation), - (_simulate_honest_execution, _no_op_validation), + (_skip_epochs(_epochs_for_shard_committee_period), no_op_validation), + (_simulate_honest_execution, no_op_validation), (state_randomizer, ensure_state_has_validators_across_lifecycle), ) - -def _normalize_transition(transition): - """ - Provide "empty" or "no op" sub-transitions - to a given transition. - """ - if isinstance(transition, Callable): - transition = transition() - if "epochs_to_skip" not in transition: - transition["epochs_to_skip"] = 0 - if "slots_to_skip" not in transition: - transition["slots_to_skip"] = 0 - if "block_producer" not in transition: - transition["block_producer"] = _no_block - if "validation" not in transition: - transition["validation"] = _no_op_validation - return transition - - -def _normalize_scenarios(scenarios, state_randomizer): - """ - "Normalize" a "scenario" so that a producer of a test case - does not need to provide every expected key/value. - """ - for scenario in scenarios: - if "setup" not in scenario: - scenario["setup"] = _randomized_scenario_setup(state_randomizer) - - transitions = scenario["transitions"] - for i, transition in enumerate(transitions): - transitions[i] = _normalize_transition(transition) - - -def _flatten(t): - leak_transition = t[0] - result = [leak_transition] - for transition_batch in t[1]: - for transition in transition_batch: - result.append(transition) - return result - - -def _generate_randomized_scenarios(state_randomizer, block_randomizer): - """ - Generates a set of randomized testing scenarios. - Return a sequence of "scenarios" where each scenario: - 1. Provides some setup - 2. Provides a sequence of transitions that mutate the state in some way, - possibly yielding blocks along the way - NOTE: scenarios are "normalized" with empty/no-op elements before returning - to the test generation to facilitate brevity when writing scenarios by hand. - NOTE: the main block driver builds a block for the **next** slot, so - the slot transitions are offset by -1 to target certain boundaries. - """ - # go forward 0 or 1 epochs - epochs_set = ( - _epoch_transition(n=0), - _epoch_transition(n=1), - ) - # within those epochs, go forward to: - slots_set = ( - # the first slot in an epoch (see note in docstring about offsets...) - _slot_transition(_last_slot_in_epoch), - # the second slot in an epoch - _slot_transition(n=0), - # some random number of slots, but not at epoch boundaries - _slot_transition(_random_slot_in_epoch(rng)), - # the last slot in an epoch (see note in docstring about offsets...) - _slot_transition(_penultimate_slot_in_epoch), - ) - # and produce a block... - blocks_set = ( - _transition_with_random_block(block_randomizer), - ) - # build a set of block transitions from combinations of sub-transitions - transitions_generator = ( - itertools.product(epochs_set, slots_set, blocks_set) for - _ in range(BLOCK_TRANSITIONS_COUNT) - ) - block_transitions = zip(*transitions_generator) - - # and preface each set of block transitions with the possible leak transitions - leak_transitions = ( - _transition_without_leak, - _transition_to_leaking, - ) - scenarios = [ - {"transitions": _flatten(t)} - for t in itertools.product(leak_transitions, block_transitions) - ] - _normalize_scenarios(scenarios, state_randomizer) - return scenarios - - -def _id_from_scenario(test_description): - """ - Construct a test name for ``pytest`` infra. - """ - def _to_id_part(prefix, x): - suffix = str(x) - if isinstance(x, Callable): - suffix = x.__name__ - return f"{prefix}{suffix}" - - def _id_from_transition(transition): - return ",".join(( - _to_id_part("epochs:", transition["epochs_to_skip"]), - _to_id_part("slots:", transition["slots_to_skip"]), - _to_id_part("with-block:", transition["block_producer"]) - )) - - return "|".join(map(_id_from_transition, test_description["transitions"])) - -# Generate a series of randomized block tests: - - -def generate_randomized_tests(metafunc, state_randomizer=randomize_state, block_randomizer=random_block): - """ - Pytest hook to generate test cases from dynamically computed data - """ - generated_name = "test_description" - generated_values = _generate_randomized_scenarios(state_randomizer, block_randomizer) - metafunc.parametrize(generated_name, generated_values, ids=_id_from_scenario, scope="module") - - -def pytest_generate_tests_adapter(f): - """ - Adapter decorator to allow dynamic test case generation - while leveraging existing decorators specific to spec tests. - """ - def wrapper(test_description, *args, **kwargs): - kwargs["test_description"] = test_description - f(*args, **kwargs) - return wrapper - # Run the generated tests: -def _iter_temporal(spec, callable_or_int): +# while the test implementation works via code-gen, +# references to helper code in this module are serialized as str names. +# to resolve this references at runtime, we need a reference to this module: +_this_module = sys.modules[__name__] + +def _resolve_ref(ref): + if isinstance(ref, str): + return getattr(_this_module, ref) + return ref + + +def _iter_temporal(spec, description): """ Intended to advance some number of {epochs, slots}. Caller can provide a constant integer or a callable deriving a number from the ``spec`` under consideration. """ - numeric = callable_or_int - if isinstance(callable_or_int, Callable): - numeric = callable_or_int(spec) + numeric = _resolve_ref(description) + if isinstance(numeric, Callable): + numeric = numeric(spec) for i in range(numeric): yield i def run_generated_randomized_test(spec, state, test_description): + if "setup" not in test_description: + state_randomizer = _resolve_ref(test_description.get("state_randomizer", randomize_state)) + test_description["setup"] = _randomized_scenario_setup(state_randomizer) + for mutation, validation in test_description["setup"]: mutation(spec, state) validation(spec, state) @@ -393,12 +288,14 @@ def run_generated_randomized_test(spec, state, test_description): for _ in slots_to_skip: next_slot(spec, state) - block = transition["block_producer"](spec, state, blocks) + block_producer = _resolve_ref(transition["block_producer"]) + block = block_producer(spec, state, blocks) if block: signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) - assert transition["validation"](spec, state) + validation = _resolve_ref(transition["validation"]) + assert validation(spec, state) yield "blocks", blocks yield "post", state diff --git a/tests/generators/random/Makefile b/tests/generators/random/Makefile new file mode 100644 index 000000000..a3c845243 --- /dev/null +++ b/tests/generators/random/Makefile @@ -0,0 +1,7 @@ +all: + . ./venv/bin/activate + pip install -r requirements.txt + rm -f ../../core/pyspec/eth2spec/test/phase0/random/test_random.py + rm -f ../../core/pyspec/eth2spec/test/altair/random/test_random.py + python generate.py phase0 > ../../core/pyspec/eth2spec/test/phase0/random/test_random.py + python generate.py altair > ../../core/pyspec/eth2spec/test/altair/random/test_random.py diff --git a/tests/generators/random/README.md b/tests/generators/random/README.md new file mode 100644 index 000000000..e1942b7f4 --- /dev/null +++ b/tests/generators/random/README.md @@ -0,0 +1,29 @@ +# Randomized tests + +Randomized tests in the format of `sanity` tests, with randomized operations. + +Information on the format of the tests can be found in the [sanity test formats documentation](../../formats/sanity/README.md). + +# To generate test sources + +```bash +$ make +``` + +The necessary commands are in the `Makefile`, as the only target. + +The generated files are committed to the repo so you should not need to do this. + +# To run tests + +Use the usual `pytest` mechanics used elsewhere in this repo. + +# To generate spec tests (from the generated files) + +Run the test generator in the usual way. + +E.g. from the root of this repo, you can run: + +```bash +$ make gen_random +``` diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py new file mode 100644 index 000000000..b31aac6a3 --- /dev/null +++ b/tests/generators/random/generate.py @@ -0,0 +1,243 @@ +""" +This test format currently uses code generation to assemble the tests +as the current test infra does not have a facility to dynamically +generate tests that can be seen by ``pytest``. + +This will likley change in future releases of the testing infra. + +NOTE: To add additional scenarios, add test cases below in ``_generate_randomized_scenarios``. +""" + +import sys +import warnings +from typing import Callable +import itertools + +from eth2spec.test.utils.random import ( + no_block, + no_op_validation, + randomize_state, + randomize_state_altair, + random_block, + random_block_altair, + last_slot_in_epoch, + random_slot_in_epoch, + penultimate_slot_in_epoch, + epoch_transition, + slot_transition, + transition_with_random_block, + transition_to_leaking, + transition_without_leak, +) +from eth2spec.test.helpers.constants import PHASE0, ALTAIR + + +# Ensure this many blocks are present in *each* randomized scenario +BLOCK_TRANSITIONS_COUNT = 2 + + +def _normalize_transition(transition): + """ + Provide "empty" or "no op" sub-transitions + to a given transition. + """ + if isinstance(transition, Callable): + transition = transition() + if "epochs_to_skip" not in transition: + transition["epochs_to_skip"] = 0 + if "slots_to_skip" not in transition: + transition["slots_to_skip"] = 0 + if "block_producer" not in transition: + transition["block_producer"] = no_block + if "validation" not in transition: + transition["validation"] = no_op_validation + return transition + + +def _normalize_scenarios(scenarios): + """ + "Normalize" a "scenario" so that a producer of a test case + does not need to provide every expected key/value. + """ + for scenario in scenarios: + transitions = scenario["transitions"] + for i, transition in enumerate(transitions): + transitions[i] = _normalize_transition(transition) + + +def _flatten(t): + leak_transition = t[0] + result = [leak_transition] + for transition_batch in t[1]: + for transition in transition_batch: + result.append(transition) + return result + + +def _generate_randomized_scenarios(block_randomizer): + """ + Generates a set of randomized testing scenarios. + Return a sequence of "scenarios" where each scenario: + 1. Provides some setup + 2. Provides a sequence of transitions that mutate the state in some way, + possibly yielding blocks along the way + NOTE: scenarios are "normalized" with empty/no-op elements before returning + to the test generation to facilitate brevity when writing scenarios by hand. + NOTE: the main block driver builds a block for the **next** slot, so + the slot transitions are offset by -1 to target certain boundaries. + """ + # go forward 0 or 1 epochs + epochs_set = ( + epoch_transition(n=0), + epoch_transition(n=1), + ) + # within those epochs, go forward to: + slots_set = ( + # the first slot in an epoch (see note in docstring about offsets...) + slot_transition(last_slot_in_epoch), + # the second slot in an epoch + slot_transition(n=0), + # some random number of slots, but not at epoch boundaries + slot_transition(random_slot_in_epoch), + # the last slot in an epoch (see note in docstring about offsets...) + slot_transition(penultimate_slot_in_epoch), + ) + # and produce a block... + blocks_set = ( + transition_with_random_block(block_randomizer), + ) + # build a set of block transitions from combinations of sub-transitions + transitions_generator = ( + itertools.product(epochs_set, slots_set, blocks_set) for + _ in range(BLOCK_TRANSITIONS_COUNT) + ) + block_transitions = zip(*transitions_generator) + + # and preface each set of block transitions with the possible leak transitions + leak_transitions = ( + transition_without_leak, + transition_to_leaking, + ) + scenarios = [ + {"transitions": _flatten(t)} + for t in itertools.product(leak_transitions, block_transitions) + ] + _normalize_scenarios(scenarios) + return scenarios + + +def _id_from_scenario(test_description): + """ + Construct a test name for ``pytest`` infra. + """ + def _to_id_part(prefix, x): + suffix = str(x) + if isinstance(x, Callable): + suffix = x.__name__ + return f"{prefix}{suffix}" + + def _id_from_transition(transition): + return ",".join(( + _to_id_part("epochs:", transition["epochs_to_skip"]), + _to_id_part("slots:", transition["slots_to_skip"]), + _to_id_part("with-block:", transition["block_producer"]) + )) + + return "|".join(map(_id_from_transition, test_description["transitions"])) + + +test_imports_template = """\"\"\" +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 {phase} +from eth2spec.test.context import ( + misc_balances_in_default_range_with_many_validators, + with_phases, + zero_activation_threshold, +) +from eth2spec.test.context import ( + always_bls, + spec_test, + with_custom_state, + single_phase, +) +from eth2spec.test.utils.random import ( + run_generated_randomized_test, +)""" + +test_template = """ +@with_phases([{phase}]) +@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_{index}(spec, state): + # scenario as high-level, informal text: +{name_as_comment} + scenario = {scenario} + yield from run_generated_randomized_test( + spec, + state, + scenario, + )""" + + +def _to_comment(name, indent_level): + parts = name.split("|") + indentation = " " * indent_level + parts = [ + indentation + "# " + part for part in parts + ] + return "\n".join(parts) + + +def run_generate_tests_to_std_out(phase, state_randomizer, block_randomizer): + scenarios = _generate_randomized_scenarios(block_randomizer) + test_content = {"phase": phase.upper()} + test_imports = test_imports_template.format(**test_content) + test_file = [test_imports] + for index, scenario in enumerate(scenarios): + # required for setup phase + scenario["state_randomizer"] = state_randomizer.__name__ + + # need to pass name, rather than function reference... + transitions = scenario["transitions"] + for transition in transitions: + for name, value in transition.items(): + if isinstance(value, Callable): + transition[name] = value.__name__ + + test_content = test_content.copy() + name = _id_from_scenario(scenario) + test_content["name_as_comment"] = _to_comment(name, 1) + test_content["index"] = index + test_content["scenario"] = scenario + test_instance = test_template.format(**test_content) + test_file.append(test_instance) + print("\n\n".join(test_file)) + + +if __name__ == "__main__": + did_generate = False + if PHASE0 in sys.argv: + did_generate = True + run_generate_tests_to_std_out( + PHASE0, + state_randomizer=randomize_state, + block_randomizer=random_block, + ) + if ALTAIR in sys.argv: + did_generate = True + run_generate_tests_to_std_out( + ALTAIR, + state_randomizer=randomize_state_altair, + block_randomizer=random_block_altair, + ) + if not did_generate: + warnings.warn("no phase given for test generation") diff --git a/tests/generators/random/main.py b/tests/generators/random/main.py new file mode 100644 index 000000000..f6f1b1847 --- /dev/null +++ b/tests/generators/random/main.py @@ -0,0 +1,18 @@ +from eth2spec.test.helpers.constants import PHASE0, ALTAIR +from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators + + +if __name__ == "__main__": + phase_0_mods = {key: 'eth2spec.test.phase0.random.test_' + key for key in [ + 'random', + ]} + altair_mods = {key: 'eth2spec.test.altair.random.test_' + key for key in [ + 'random', + ]} + + all_mods = { + PHASE0: phase_0_mods, + ALTAIR: altair_mods, + } + + run_state_test_generators(runner_name="random", all_mods=all_mods) diff --git a/tests/generators/random/requirements.txt b/tests/generators/random/requirements.txt new file mode 100644 index 000000000..182248686 --- /dev/null +++ b/tests/generators/random/requirements.txt @@ -0,0 +1,2 @@ +pytest>=4.4 +../../../[generator] diff --git a/tests/generators/sanity/main.py b/tests/generators/sanity/main.py index 89e622f1c..8caedc8e5 100644 --- a/tests/generators/sanity/main.py +++ b/tests/generators/sanity/main.py @@ -5,12 +5,10 @@ from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators if __name__ == "__main__": phase_0_mods = {key: 'eth2spec.test.phase0.sanity.test_' + key for key in [ 'blocks', - 'blocks_random', 'slots', ]} altair_mods = {**{key: 'eth2spec.test.altair.sanity.test_' + key for key in [ 'blocks', - 'blocks_random', ]}, **phase_0_mods} # also run the previous phase 0 tests # Altair-specific test cases are ignored, but should be included after the Merge is rebased onto Altair work. From d1f3ec59afba70ee39e5c1bcf15e371248c6189c Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 11:56:19 -0700 Subject: [PATCH 34/55] ensure at least 1 operation when making random block --- .../pyspec/eth2spec/test/helpers/multi_operations.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 10de14253..3d941627b 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -87,7 +87,7 @@ def get_random_attester_slashings(spec, state, rng): def get_random_attestations(spec, state, rng): - num_attestations = rng.randrange(spec.MAX_ATTESTATIONS) + num_attestations = max(1, rng.randrange(spec.MAX_ATTESTATIONS)) attestations = [ get_valid_attestation( @@ -101,13 +101,12 @@ def get_random_attestations(spec, state, rng): def prepare_state_and_get_random_deposits(spec, state, rng): - num_deposits = rng.randrange(spec.MAX_DEPOSITS) + num_deposits = max(1, rng.randrange(spec.MAX_DEPOSITS)) deposit_data_leaves = [spec.DepositData() for _ in range(len(state.validators))] deposits = [] # First build deposit data leaves - root = None for i in range(num_deposits): index = len(state.validators) + i _, root, deposit_data_leaves = build_deposit( @@ -120,9 +119,8 @@ def prepare_state_and_get_random_deposits(spec, state, rng): signed=True, ) - if root: - # NOTE: if ``num_deposits == 0``, ``root`` is never assigned to - state.eth1_data.deposit_root = root + # NOTE: if ``num_deposits == 0``, ``root`` is never assigned to + state.eth1_data.deposit_root = root state.eth1_data.deposit_count += num_deposits # Then for that context, build deposits/proofs @@ -149,7 +147,7 @@ def _eligible_for_exit(spec, state, index): def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): - num_exits = rng.randrange(spec.MAX_VOLUNTARY_EXITS) + num_exits = max(1, rng.randrange(spec.MAX_VOLUNTARY_EXITS)) active_indices = set(spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy()) indices = set( index for index in active_indices From 8e5a34c38a909db63a75057bde62d64b07f234a0 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 12:37:28 -0700 Subject: [PATCH 35/55] adjust helper to account for additional slashings --- .../eth2spec/test/helpers/multi_operations.py | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 3d941627b..cfc2c4a0f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -64,20 +64,33 @@ def get_random_proposer_slashings(spec, state, rng): return slashings -def get_random_attester_slashings(spec, state, rng): +def get_random_attester_slashings(spec, state, rng, slashed_indices=[]): + """ + Caller can supply ``slashed_indices`` if they are aware of other indices + that will be slashed by other operations in the same block as the one that + contains the output of this function. + """ # ensure at least one attester slashing, the max count # is small so not much room for random inclusion num_slashings = max(1, rng.randrange(spec.MAX_ATTESTER_SLASHINGS)) active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() indices = [ index for index in active_indices - if not state.validators[index].slashed + if ( + not state.validators[index].slashed + and index not in slashed_indices + ) ] + sample_upper_bound = 4 + max_slashed_count = num_slashings * sample_upper_bound - 1 + if len(indices) < max_slashed_count: + return [] + slot_range = list(range(state.slot - spec.SLOTS_PER_HISTORICAL_ROOT + 1, state.slot)) slashings = [ get_valid_attester_slashing_by_indices( spec, state, - sorted([indices.pop(rng.randrange(len(indices))) for _ in range(rng.randrange(1, 4))]), + sorted([indices.pop(rng.randrange(len(indices))) for _ in range(rng.randrange(1, sample_upper_bound))]), slot=slot_range.pop(rng.randrange(len(slot_range))), signed_1=True, signed_2=True, ) @@ -164,8 +177,13 @@ def build_random_block_from_state_for_next_slot(spec, state, rng=Random(2188)): deposits = prepare_state_and_get_random_deposits(spec, state, rng) block = build_empty_block_for_next_slot(spec, state) - block.body.proposer_slashings = get_random_proposer_slashings(spec, state, rng) - block.body.attester_slashings = get_random_attester_slashings(spec, state, rng) + proposer_slashings = get_random_proposer_slashings(spec, state, rng) + block.body.proposer_slashings = proposer_slashings + slashed_indices = [ + slashing.signed_header_1.message.proposer_index + for slashing in proposer_slashings + ] + block.body.attester_slashings = get_random_attester_slashings(spec, state, rng, slashed_indices) block.body.attestations = get_random_attestations(spec, state, rng) block.body.deposits = deposits From 933c1323dd2b51fa1c24df7737df94b281385196 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 14:46:31 -0700 Subject: [PATCH 36/55] lint updates --- .../test/altair/random/test_random.py | 32 +++++++++---------- .../test/phase0/random/test_random.py | 32 +++++++++---------- .../core/pyspec/eth2spec/test/utils/random.py | 1 + tests/generators/random/generate.py | 2 +- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py index 86f8f97b1..c7780925d 100644 --- a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py @@ -38,7 +38,7 @@ def test_randomized_0(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -63,7 +63,7 @@ def test_randomized_1(spec, state): # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -88,7 +88,7 @@ def test_randomized_2(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -113,7 +113,7 @@ def test_randomized_3(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -138,7 +138,7 @@ def test_randomized_4(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -163,7 +163,7 @@ def test_randomized_5(spec, state): # epochs:1,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -188,7 +188,7 @@ def test_randomized_6(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -213,7 +213,7 @@ def test_randomized_7(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -238,7 +238,7 @@ def test_randomized_8(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -263,7 +263,7 @@ def test_randomized_9(spec, state): # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -288,7 +288,7 @@ def test_randomized_10(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -313,7 +313,7 @@ def test_randomized_11(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -338,7 +338,7 @@ def test_randomized_12(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -363,7 +363,7 @@ def test_randomized_13(spec, state): # epochs:1,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -388,7 +388,7 @@ def test_randomized_14(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -413,7 +413,7 @@ def test_randomized_15(spec, state): # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, diff --git a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py index bfa93330f..95dfeaeaf 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py @@ -38,7 +38,7 @@ def test_randomized_0(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -63,7 +63,7 @@ def test_randomized_1(spec, state): # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -88,7 +88,7 @@ def test_randomized_2(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -113,7 +113,7 @@ def test_randomized_3(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -138,7 +138,7 @@ def test_randomized_4(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -163,7 +163,7 @@ def test_randomized_5(spec, state): # epochs:1,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -188,7 +188,7 @@ def test_randomized_6(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -213,7 +213,7 @@ def test_randomized_7(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -238,7 +238,7 @@ def test_randomized_8(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -263,7 +263,7 @@ def test_randomized_9(spec, state): # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -288,7 +288,7 @@ def test_randomized_10(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -313,7 +313,7 @@ def test_randomized_11(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -338,7 +338,7 @@ def test_randomized_12(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -363,7 +363,7 @@ def test_randomized_13(spec, state): # epochs:1,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -388,7 +388,7 @@ def test_randomized_14(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -413,7 +413,7 @@ def test_randomized_15(spec, state): # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index b12fca96b..2f727e749 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -249,6 +249,7 @@ def _randomized_scenario_setup(state_randomizer): # to resolve this references at runtime, we need a reference to this module: _this_module = sys.modules[__name__] + def _resolve_ref(ref): if isinstance(ref, str): return getattr(_this_module, ref) diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index b31aac6a3..2f6b306d1 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -180,7 +180,7 @@ test_template = """ def test_randomized_{index}(spec, state): # scenario as high-level, informal text: {name_as_comment} - scenario = {scenario} + scenario = {scenario} # noqa: E501 yield from run_generated_randomized_test( spec, state, From f7c0dc36bed1e002c5768459d0cb6b93f1050c55 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 14:57:56 -0700 Subject: [PATCH 37/55] skip running heavy randomized tests in CI --- .../eth2spec/test/altair/random/test_random.py | 17 +++++++++++++++++ tests/core/pyspec/eth2spec/test/context.py | 11 +++++++++++ .../eth2spec/test/phase0/random/test_random.py | 17 +++++++++++++++++ tests/generators/random/generate.py | 2 ++ 4 files changed, 47 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py index c7780925d..d022c2ca1 100644 --- a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py @@ -9,6 +9,7 @@ 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, @@ -21,6 +22,7 @@ from eth2spec.test.utils.random import ( ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -46,6 +48,7 @@ def test_randomized_0(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -71,6 +74,7 @@ def test_randomized_1(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -96,6 +100,7 @@ def test_randomized_2(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -121,6 +126,7 @@ def test_randomized_3(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -146,6 +152,7 @@ def test_randomized_4(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -171,6 +178,7 @@ def test_randomized_5(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -196,6 +204,7 @@ def test_randomized_6(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -221,6 +230,7 @@ def test_randomized_7(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -246,6 +256,7 @@ def test_randomized_8(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -271,6 +282,7 @@ def test_randomized_9(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -296,6 +308,7 @@ def test_randomized_10(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -321,6 +334,7 @@ def test_randomized_11(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -346,6 +360,7 @@ def test_randomized_12(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -371,6 +386,7 @@ def test_randomized_13(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -396,6 +412,7 @@ def test_randomized_14(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([ALTAIR]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index f6f120d55..346cdc8f1 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -456,6 +456,17 @@ with_altair_and_later = with_phases([ALTAIR, MERGE]) with_merge_and_later = with_phases([MERGE]) # TODO: include sharding when spec stabilizes. +def only_generator(reason): + def _decorator(inner): + def _wrapper(*args, **kwargs): + if is_pytest: + dump_skipping_message(reason) + return None + return inner(*args, **kwargs) + return _wrapper + return _decorator + + def fork_transition_test(pre_fork_name, post_fork_name, fork_epoch=None): """ A decorator to construct a "transition" test from one fork of the eth2 spec diff --git a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py index 95dfeaeaf..5bb8c3791 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py @@ -9,6 +9,7 @@ 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, @@ -21,6 +22,7 @@ from eth2spec.test.utils.random import ( ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -46,6 +48,7 @@ def test_randomized_0(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -71,6 +74,7 @@ def test_randomized_1(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -96,6 +100,7 @@ def test_randomized_2(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -121,6 +126,7 @@ def test_randomized_3(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -146,6 +152,7 @@ def test_randomized_4(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -171,6 +178,7 @@ def test_randomized_5(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -196,6 +204,7 @@ def test_randomized_6(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -221,6 +230,7 @@ def test_randomized_7(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -246,6 +256,7 @@ def test_randomized_8(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -271,6 +282,7 @@ def test_randomized_9(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -296,6 +308,7 @@ def test_randomized_10(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -321,6 +334,7 @@ def test_randomized_11(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -346,6 +360,7 @@ def test_randomized_12(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -371,6 +386,7 @@ def test_randomized_13(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, @@ -396,6 +412,7 @@ def test_randomized_14(spec, state): ) +@only_generator("randomized test for broad coverage, not point-to-point CI") @with_phases([PHASE0]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index 2f6b306d1..3f34a6bc0 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -157,6 +157,7 @@ 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, @@ -169,6 +170,7 @@ from eth2spec.test.utils.random import ( )""" test_template = """ +@only_generator(\"randomized test for broad coverage, not point-to-point CI\") @with_phases([{phase}]) @with_custom_state( balances_fn=misc_balances_in_default_range_with_many_validators, From 33c96127dac894f942ed3225400541499fa2ea30 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 16:21:45 -0700 Subject: [PATCH 38/55] fix bug with random sync aggregate helper --- .../pyspec/eth2spec/test/helpers/multi_operations.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index cfc2c4a0f..83494182e 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -217,14 +217,18 @@ def run_test_full_random_operations(spec, state, rng=Random(2080)): def get_random_sync_aggregate(spec, state, fraction_participated=1.0, rng=Random(2099)): committee_indices = compute_committee_indices(spec, state, state.current_sync_committee) participant_count = int(len(committee_indices) * fraction_participated) - participants = rng.sample(committee_indices, participant_count) + participant_indices = rng.sample(range(len(committee_indices)), participant_count) + participants = [ + committee_indices[index] + for index in participant_indices + ] signature = compute_aggregate_sync_committee_signature( spec, state, - state.slot, + state.slot - 1, participants, ) return spec.SyncAggregate( - sync_committee_bits=[index in participants for index in committee_indices], + sync_committee_bits=[index in participant_indices for index in range(len(committee_indices))], sync_committee_signature=signature, ) From 7874e8db881fc0a6812d0af8261925c91a62ac56 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 16:25:25 -0700 Subject: [PATCH 39/55] clean up unnecessary comment --- tests/core/pyspec/eth2spec/test/helpers/multi_operations.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 83494182e..c0a58dbca 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -132,7 +132,6 @@ def prepare_state_and_get_random_deposits(spec, state, rng): signed=True, ) - # NOTE: if ``num_deposits == 0``, ``root`` is never assigned to state.eth1_data.deposit_root = root state.eth1_data.deposit_count += num_deposits From 02bc6541d99770a17a3b1127e36870971713a843 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 24 Aug 2021 16:28:13 -0700 Subject: [PATCH 40/55] extend Makefile --- tests/generators/random/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/generators/random/Makefile b/tests/generators/random/Makefile index a3c845243..799001280 100644 --- a/tests/generators/random/Makefile +++ b/tests/generators/random/Makefile @@ -1,4 +1,5 @@ all: + if ! test -d venv; then python3 -m venv venv; fi; . ./venv/bin/activate pip install -r requirements.txt rm -f ../../core/pyspec/eth2spec/test/phase0/random/test_random.py From 4d4f4e89f48aa4d5c14a41159d6bcb021f8ec1a3 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 10:38:01 -0700 Subject: [PATCH 41/55] be specific about which slot we want a sync committee root for --- .../core/pyspec/eth2spec/test/helpers/multi_operations.py | 4 ++-- tests/core/pyspec/eth2spec/test/utils/random.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index c0a58dbca..075b03aa0 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -213,7 +213,7 @@ def run_test_full_random_operations(spec, state, rng=Random(2080)): yield 'post', state -def get_random_sync_aggregate(spec, state, fraction_participated=1.0, rng=Random(2099)): +def get_random_sync_aggregate(spec, state, slot, fraction_participated=1.0, rng=Random(2099)): committee_indices = compute_committee_indices(spec, state, state.current_sync_committee) participant_count = int(len(committee_indices) * fraction_participated) participant_indices = rng.sample(range(len(committee_indices)), participant_count) @@ -224,7 +224,7 @@ def get_random_sync_aggregate(spec, state, fraction_participated=1.0, rng=Random signature = compute_aggregate_sync_committee_signature( spec, state, - state.slot - 1, + slot, participants, ) return spec.SyncAggregate( diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index 2f727e749..d17a3a9b2 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -123,7 +123,12 @@ def random_block_altair(spec, state, signed_blocks): block = random_block(spec, state, signed_blocks) fraction_missed = len(signed_blocks) / SYNC_AGGREGATE_PARTICIPATION_BUCKETS fraction_participated = 1.0 - fraction_missed - block.body.sync_aggregate = get_random_sync_aggregate(spec, state, fraction_participated=fraction_participated) + block.body.sync_aggregate = get_random_sync_aggregate( + spec, + state, + block.slot - 1, + fraction_participated=fraction_participated, + ) return block From e72edf07f9e1f35fd3cf7f21970ce85848905841 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 10:40:15 -0700 Subject: [PATCH 42/55] consolidate call to `max` into `randrange` --- .../core/pyspec/eth2spec/test/helpers/multi_operations.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 075b03aa0..73ebedfe0 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -48,7 +48,7 @@ def run_slash_and_exit(spec, state, slash_index, exit_index, valid=True): def get_random_proposer_slashings(spec, state, rng): - num_slashings = max(1, rng.randrange(spec.MAX_PROPOSER_SLASHINGS)) + num_slashings = rng.randrange(1, spec.MAX_PROPOSER_SLASHINGS) active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() indices = [ index for index in active_indices @@ -72,7 +72,7 @@ def get_random_attester_slashings(spec, state, rng, slashed_indices=[]): """ # ensure at least one attester slashing, the max count # is small so not much room for random inclusion - num_slashings = max(1, rng.randrange(spec.MAX_ATTESTER_SLASHINGS)) + num_slashings = rng.randrange(1, spec.MAX_ATTESTER_SLASHINGS) active_indices = spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy() indices = [ index for index in active_indices @@ -100,7 +100,7 @@ def get_random_attester_slashings(spec, state, rng, slashed_indices=[]): def get_random_attestations(spec, state, rng): - num_attestations = max(1, rng.randrange(spec.MAX_ATTESTATIONS)) + num_attestations = rng.randrange(1, spec.MAX_ATTESTATIONS) attestations = [ get_valid_attestation( @@ -114,7 +114,7 @@ def get_random_attestations(spec, state, rng): def prepare_state_and_get_random_deposits(spec, state, rng): - num_deposits = max(1, rng.randrange(spec.MAX_DEPOSITS)) + num_deposits = rng.randrange(1, spec.MAX_DEPOSITS) deposit_data_leaves = [spec.DepositData() for _ in range(len(state.validators))] deposits = [] From e575b222be7798ad945669baa9a0b44abd1952a2 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 10:54:55 -0700 Subject: [PATCH 43/55] clarify readme --- tests/generators/random/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/generators/random/README.md b/tests/generators/random/README.md index e1942b7f4..35de22d01 100644 --- a/tests/generators/random/README.md +++ b/tests/generators/random/README.md @@ -1,6 +1,6 @@ # Randomized tests -Randomized tests in the format of `sanity` tests, with randomized operations. +Randomized tests in the format of `sanity` blocks tests, with randomized operations. Information on the format of the tests can be found in the [sanity test formats documentation](../../formats/sanity/README.md). From 81971a89573804d0570fb8ef5cb5fc6d3fd90270 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 11:01:26 -0700 Subject: [PATCH 44/55] update readme for pytest --- tests/generators/random/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/generators/random/README.md b/tests/generators/random/README.md index 35de22d01..fd1728441 100644 --- a/tests/generators/random/README.md +++ b/tests/generators/random/README.md @@ -16,7 +16,9 @@ The generated files are committed to the repo so you should not need to do this. # To run tests -Use the usual `pytest` mechanics used elsewhere in this repo. +Each of the generated test does produce a `pytest` test instance but by default is +currently skipped. Running the test via the generator (see next) will trigger any errors +that would arise during the running of `pytest`. # To generate spec tests (from the generated files) From 0da1fe947dbea4ce6c9272630cc7d19df286bc54 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 11:09:35 -0700 Subject: [PATCH 45/55] clarify how the random block generator works --- tests/core/pyspec/eth2spec/test/utils/random.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/random.py index d17a3a9b2..d0fde4565 100644 --- a/tests/core/pyspec/eth2spec/test/utils/random.py +++ b/tests/core/pyspec/eth2spec/test/utils/random.py @@ -100,6 +100,15 @@ def random_block(spec, state, _signed_blocks): to produce a block over ``BLOCK_ATTEMPTS`` slots in order to find a valid block in the event that the proposer has already been slashed. """ + # NOTE: ``state`` has been "randomized" at this point and so will likely + # contain a large number of slashed validators. This function needs to return + # a valid block so it needs to check that the proposer of the next slot is not + # slashed. + # To do this, generate a ``temp_state`` to use for checking the propser in the next slot. + # This ensures no accidental mutations happen to the ``state`` the caller expects to get back + # after this function returns. + # Using a copy of the state for proposer sampling is also sound as any inputs used for the + # shuffling are fixed a few epochs prior to ``spec.get_current_epoch(state)``. temp_state = state.copy() next_slot(spec, temp_state) for _ in range(BLOCK_ATTEMPTS): From a6f8870e18598431716d69e8eaa199cdea25dded Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 11:15:27 -0700 Subject: [PATCH 46/55] update makefile to use correct python version --- tests/generators/random/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/generators/random/Makefile b/tests/generators/random/Makefile index 799001280..1b518bfde 100644 --- a/tests/generators/random/Makefile +++ b/tests/generators/random/Makefile @@ -1,8 +1,8 @@ all: if ! test -d venv; then python3 -m venv venv; fi; . ./venv/bin/activate - pip install -r requirements.txt + pip3 install -r requirements.txt rm -f ../../core/pyspec/eth2spec/test/phase0/random/test_random.py rm -f ../../core/pyspec/eth2spec/test/altair/random/test_random.py - python generate.py phase0 > ../../core/pyspec/eth2spec/test/phase0/random/test_random.py - python generate.py altair > ../../core/pyspec/eth2spec/test/altair/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 From 14518d4d642d2ca7f94e709dc155256b0c568a81 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 11:15:59 -0700 Subject: [PATCH 47/55] update name of utility module to be more specific --- tests/core/pyspec/eth2spec/test/altair/random/test_random.py | 2 +- tests/core/pyspec/eth2spec/test/phase0/random/test_random.py | 2 +- .../test/utils/{random.py => randomized_block_tests.py} | 0 tests/generators/random/generate.py | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename tests/core/pyspec/eth2spec/test/utils/{random.py => randomized_block_tests.py} (100%) diff --git a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py index d022c2ca1..b581659fe 100644 --- a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py @@ -17,7 +17,7 @@ from eth2spec.test.context import ( with_custom_state, single_phase, ) -from eth2spec.test.utils.random import ( +from eth2spec.test.utils.randomized_block_tests import ( run_generated_randomized_test, ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py index 5bb8c3791..abf74e43f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py @@ -17,7 +17,7 @@ from eth2spec.test.context import ( with_custom_state, single_phase, ) -from eth2spec.test.utils.random import ( +from eth2spec.test.utils.randomized_block_tests import ( run_generated_randomized_test, ) diff --git a/tests/core/pyspec/eth2spec/test/utils/random.py b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py similarity index 100% rename from tests/core/pyspec/eth2spec/test/utils/random.py rename to tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index 3f34a6bc0..d6215bb1f 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -13,7 +13,7 @@ import warnings from typing import Callable import itertools -from eth2spec.test.utils.random import ( +from eth2spec.test.utils.randomized_block_tests import ( no_block, no_op_validation, randomize_state, @@ -165,7 +165,7 @@ from eth2spec.test.context import ( with_custom_state, single_phase, ) -from eth2spec.test.utils.random import ( +from eth2spec.test.utils.randomized_block_tests import ( run_generated_randomized_test, )""" From 377797fd0dfcd7d60ca688760779a2a44be13768 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 11:20:17 -0700 Subject: [PATCH 48/55] code layout change --- .../eth2spec/test/helpers/multi_operations.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index 73ebedfe0..bbfc9ffc6 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -171,6 +171,26 @@ def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): return prepare_signed_exits(spec, state, exit_indices) +def get_random_sync_aggregate(spec, state, slot, fraction_participated=1.0, rng=Random(2099)): + committee_indices = compute_committee_indices(spec, state, state.current_sync_committee) + participant_count = int(len(committee_indices) * fraction_participated) + participant_indices = rng.sample(range(len(committee_indices)), participant_count) + participants = [ + committee_indices[index] + for index in participant_indices + ] + signature = compute_aggregate_sync_committee_signature( + spec, + state, + slot, + participants, + ) + return spec.SyncAggregate( + sync_committee_bits=[index in participant_indices for index in range(len(committee_indices))], + sync_committee_signature=signature, + ) + + def build_random_block_from_state_for_next_slot(spec, state, rng=Random(2188)): # prepare state for deposits before building block deposits = prepare_state_and_get_random_deposits(spec, state, rng) @@ -211,23 +231,3 @@ def run_test_full_random_operations(spec, state, rng=Random(2080)): yield 'blocks', [signed_block] yield 'post', state - - -def get_random_sync_aggregate(spec, state, slot, fraction_participated=1.0, rng=Random(2099)): - committee_indices = compute_committee_indices(spec, state, state.current_sync_committee) - participant_count = int(len(committee_indices) * fraction_participated) - participant_indices = rng.sample(range(len(committee_indices)), participant_count) - participants = [ - committee_indices[index] - for index in participant_indices - ] - signature = compute_aggregate_sync_committee_signature( - spec, - state, - slot, - participants, - ) - return spec.SyncAggregate( - sync_committee_bits=[index in participant_indices for index in range(len(committee_indices))], - sync_committee_signature=signature, - ) From 961953ac15df9246edc3e36c7bf2ad436911b06f Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 13:10:41 -0700 Subject: [PATCH 49/55] update parameter name --- .../eth2spec/test/utils/randomized_block_tests.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 d0fde4565..4b25fb5ac 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -283,19 +283,19 @@ def _iter_temporal(spec, description): yield i -def run_generated_randomized_test(spec, state, test_description): - if "setup" not in test_description: - state_randomizer = _resolve_ref(test_description.get("state_randomizer", randomize_state)) - test_description["setup"] = _randomized_scenario_setup(state_randomizer) +def run_generated_randomized_test(spec, state, scenario): + if "setup" not in scenario: + state_randomizer = _resolve_ref(scenario.get("state_randomizer", randomize_state)) + scenario["setup"] = _randomized_scenario_setup(state_randomizer) - for mutation, validation in test_description["setup"]: + for mutation, validation in scenario["setup"]: mutation(spec, state) validation(spec, state) yield "pre", state blocks = [] - for transition in test_description["transitions"]: + for transition in scenario["transitions"]: epochs_to_skip = _iter_temporal(spec, transition["epochs_to_skip"]) for _ in epochs_to_skip: next_epoch(spec, state) From 047ff5b09910c8b6fec54f56af2e748c1e4348ef Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 14:16:39 -0700 Subject: [PATCH 50/55] unify visibility on names for doc purposes --- .../test/utils/randomized_block_tests.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 4b25fb5ac..63c242782 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -39,7 +39,7 @@ def randomize_state_altair(spec, state): # epochs -def _epochs_until_leak(spec): +def epochs_until_leak(spec): """ State is "leaking" if the current epoch is at least this value after the last finalized epoch. @@ -47,7 +47,7 @@ def _epochs_until_leak(spec): return spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 1 -def _epochs_for_shard_committee_period(spec): +def epochs_for_shard_committee_period(spec): return spec.config.SHARD_COMMITTEE_PERIOD @@ -147,24 +147,24 @@ def no_op_validation(spec, state): return True -def _validate_is_leaking(spec, state): +def validate_is_leaking(spec, state): return spec.is_in_inactivity_leak(state) -def _validate_is_not_leaking(spec, state): - return not _validate_is_leaking(spec, state) +def validate_is_not_leaking(spec, state): + return not validate_is_leaking(spec, state) # transitions -def _with_validation(transition, validation): +def with_validation(transition, validation): if isinstance(transition, Callable): transition = transition() transition["validation"] = validation return transition -def _no_op_transition(): +def no_op_transition(): return {} @@ -182,12 +182,12 @@ def slot_transition(n=0): def transition_to_leaking(): return { - "epochs_to_skip": _epochs_until_leak, - "validation": _validate_is_leaking, + "epochs_to_skip": epochs_until_leak, + "validation": validate_is_leaking, } -transition_without_leak = _with_validation(_no_op_transition, _validate_is_not_leaking) +transition_without_leak = with_validation(no_op_transition, validate_is_not_leaking) # block transitions @@ -250,7 +250,7 @@ def _randomized_scenario_setup(state_randomizer): return ( # NOTE: the block randomization function assumes at least 1 shard committee period # so advance the state before doing anything else. - (_skip_epochs(_epochs_for_shard_committee_period), no_op_validation), + (_skip_epochs(epochs_for_shard_committee_period), no_op_validation), (_simulate_honest_execution, no_op_validation), (state_randomizer, ensure_state_has_validators_across_lifecycle), ) From e2dc9f9ec2f5643c833af500e1edf18e7c31b8de Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 14:42:41 -0700 Subject: [PATCH 51/55] update generation of randomized scenarios for more variability --- .../test/altair/random/test_random.py | 120 +++++++++--------- .../test/phase0/random/test_random.py | 120 +++++++++--------- tests/generators/random/generate.py | 19 ++- 3 files changed, 136 insertions(+), 123 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py index b581659fe..d00da3f9e 100644 --- a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py @@ -35,12 +35,12 @@ 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:last_slot_in_epoch,with-block:no_block - # epochs:0,slots:0,with-block:random_block_altair # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -60,13 +60,13 @@ def test_randomized_0(spec, state): def test_randomized_1(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: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_altair # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -87,12 +87,12 @@ 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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -113,12 +113,12 @@ 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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:penultimate_slot_in_epoch,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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -142,9 +142,9 @@ def test_randomized_4(spec, state): # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair # epochs:1,slots:0,with-block:no_block - # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -164,13 +164,13 @@ def test_randomized_4(spec, state): def test_randomized_5(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:random_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - # epochs:1,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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -191,12 +191,12 @@ 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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - # 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:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -217,12 +217,12 @@ 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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair # 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:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -241,14 +241,14 @@ def test_randomized_7(spec, state): @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: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_altair # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # 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_altair + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -267,14 +267,14 @@ def test_randomized_8(spec, state): @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:0,slots:0,with-block:no_block - # epochs:0,slots:0,with-block:no_block + # 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_altair # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -293,14 +293,14 @@ def test_randomized_9(spec, state): @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: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:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -319,14 +319,14 @@ def test_randomized_10(spec, state): @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: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:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:penultimate_slot_in_epoch,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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -345,14 +345,14 @@ def test_randomized_11(spec, state): @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: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_altair # epochs:1,slots:0,with-block:no_block - # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -371,14 +371,14 @@ def test_randomized_12(spec, state): @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:1,slots:0,with-block:no_block + # 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_altair - # epochs:1,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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -397,14 +397,14 @@ def test_randomized_13(spec, state): @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: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:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - # 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:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -423,14 +423,14 @@ def test_randomized_14(spec, state): @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: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:no_block # epochs:0,slots:0,with-block:random_block_altair # 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:no_block # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, diff --git a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py index abf74e43f..89a457bed 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/random/test_random.py @@ -35,12 +35,12 @@ 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:last_slot_in_epoch,with-block:no_block - # epochs:0,slots:0,with-block:random_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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + # 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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -60,13 +60,13 @@ def test_randomized_0(spec, state): def test_randomized_1(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: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 # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -87,12 +87,12 @@ 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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -113,12 +113,12 @@ 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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:penultimate_slot_in_epoch,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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -142,9 +142,9 @@ def test_randomized_4(spec, state): # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block # epochs:1,slots:0,with-block:no_block - # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -164,13 +164,13 @@ def test_randomized_4(spec, state): def test_randomized_5(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:random_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - # epochs:1,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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -191,12 +191,12 @@ 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:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_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:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -217,12 +217,12 @@ 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:penultimate_slot_in_epoch,with-block:no_block + # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_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:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -241,14 +241,14 @@ def test_randomized_7(spec, state): @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: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 # 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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + # 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 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -267,14 +267,14 @@ def test_randomized_8(spec, state): @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:0,slots:0,with-block:no_block - # epochs:0,slots:0,with-block:no_block + # 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 # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -293,14 +293,14 @@ def test_randomized_9(spec, state): @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: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:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:random_slot_in_epoch,with-block:no_block + # epochs:0,slots:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -319,14 +319,14 @@ def test_randomized_10(spec, state): @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: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:last_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:penultimate_slot_in_epoch,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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -345,14 +345,14 @@ def test_randomized_11(spec, state): @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: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 # epochs:1,slots:0,with-block:no_block - # epochs:0,slots:last_slot_in_epoch,with-block:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -371,14 +371,14 @@ def test_randomized_12(spec, state): @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:1,slots:0,with-block:no_block + # 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 - # epochs:1,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 - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -397,14 +397,14 @@ def test_randomized_13(spec, state): @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: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:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_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:no_block + # epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -423,14 +423,14 @@ def test_randomized_14(spec, state): @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: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:no_block # epochs:0,slots:0,with-block:random_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:no_block # epochs:0,slots:0,with-block:random_block - 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 + 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', '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', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state'} # noqa: E501 yield from run_generated_randomized_test( spec, state, diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index d6215bb1f..7f033f957 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -9,6 +9,7 @@ NOTE: To add additional scenarios, add test cases below in ``_generate_randomize """ import sys +import random import warnings from typing import Callable import itertools @@ -70,7 +71,11 @@ def _flatten(t): result = [leak_transition] for transition_batch in t[1]: for transition in transition_batch: - result.append(transition) + if isinstance(transition, tuple): + for subtransition in transition: + result.append(subtransition) + else: + result.append(transition) return result @@ -106,10 +111,18 @@ def _generate_randomized_scenarios(block_randomizer): blocks_set = ( transition_with_random_block(block_randomizer), ) + + rng = random.Random(1447) + all_skips = list(itertools.product(epochs_set, slots_set)) + randomized_skips = ( + rng.sample(all_skips, len(all_skips)) + for _ in range(BLOCK_TRANSITIONS_COUNT) + ) + # build a set of block transitions from combinations of sub-transitions transitions_generator = ( - itertools.product(epochs_set, slots_set, blocks_set) for - _ in range(BLOCK_TRANSITIONS_COUNT) + itertools.product(prefix, blocks_set) + for prefix in randomized_skips ) block_transitions = zip(*transitions_generator) From c206a2772aba5a0c129995843e705ed0f7090793 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 14:46:17 -0700 Subject: [PATCH 52/55] update docs via PR feedback --- tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 63c242782..338f88b6a 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -208,7 +208,7 @@ def transition_with_random_block(block_randomizer): def _randomized_scenario_setup(state_randomizer): """ - Return a sequence of pairs of ("mutator", "validator"), + Return a sequence of pairs of ("mutation", "validation"), a function that accepts (spec, state) arguments and performs some change and a function that accepts (spec, state) arguments and validates some change was made. """ From 5b0d2627c33b2228c92d7efa82139d09da64a2d4 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 15:13:20 -0700 Subject: [PATCH 53/55] apply pr feedback on randrange --- tests/core/pyspec/eth2spec/test/helpers/multi_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py index bbfc9ffc6..14b281a95 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/multi_operations.py @@ -159,7 +159,7 @@ def _eligible_for_exit(spec, state, index): def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng): - num_exits = max(1, rng.randrange(spec.MAX_VOLUNTARY_EXITS)) + num_exits = rng.randrange(1, spec.MAX_VOLUNTARY_EXITS) active_indices = set(spec.get_active_validator_indices(state, spec.get_current_epoch(state)).copy()) indices = set( index for index in active_indices From 4b3022a76794f9b06e66d319d0163b0f43abb582 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 16:19:46 -0600 Subject: [PATCH 54/55] Update tests/generators/random/generate.py --- tests/generators/random/generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index 7f033f957..825cac128 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -141,7 +141,7 @@ def _generate_randomized_scenarios(block_randomizer): def _id_from_scenario(test_description): """ - Construct a test name for ``pytest`` infra. + Construct a name for the scenario based its data. """ def _to_id_part(prefix, x): suffix = str(x) From 874ea80cb8a3c77a321bb29b1979376cbc52a296 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 25 Aug 2021 17:18:02 -0700 Subject: [PATCH 55/55] use more precise name for altair block randomizer and re-gen tests --- .../test/altair/random/test_random.py | 96 +++++++++---------- .../test/utils/randomized_block_tests.py | 7 +- tests/generators/random/generate.py | 4 +- 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py index d00da3f9e..2250101bd 100644 --- a/tests/core/pyspec/eth2spec/test/altair/random/test_random.py +++ b/tests/core/pyspec/eth2spec/test/altair/random/test_random.py @@ -36,11 +36,11 @@ def test_randomized_0(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -62,11 +62,11 @@ def test_randomized_1(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -88,11 +88,11 @@ def test_randomized_2(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -114,11 +114,11 @@ def test_randomized_3(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -140,11 +140,11 @@ def test_randomized_4(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -166,11 +166,11 @@ def test_randomized_5(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -192,11 +192,11 @@ def test_randomized_6(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -218,11 +218,11 @@ def test_randomized_7(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # epochs:1,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -244,11 +244,11 @@ def test_randomized_8(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -270,11 +270,11 @@ def test_randomized_9(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # epochs:0,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -296,11 +296,11 @@ def test_randomized_10(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -322,11 +322,11 @@ def test_randomized_11(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -348,11 +348,11 @@ def test_randomized_12(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -374,11 +374,11 @@ def test_randomized_13(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -400,11 +400,11 @@ def test_randomized_14(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # 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_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, @@ -426,11 +426,11 @@ def test_randomized_15(spec, state): # 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_altair + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation # epochs:1,slots:0,with-block:no_block # epochs:0,slots:0,with-block:no_block - # epochs:0,slots:0,with-block:random_block_altair - 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_altair', '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_altair', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 + # epochs:0,slots:0,with-block:random_block_altair_with_cycling_sync_committee_participation + 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_altair_with_cycling_sync_committee_participation', '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_altair_with_cycling_sync_committee_participation', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_altair'} # noqa: E501 yield from run_generated_randomized_test( spec, state, 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 338f88b6a..44dab0e0e 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -128,9 +128,12 @@ def random_block(spec, state, _signed_blocks): SYNC_AGGREGATE_PARTICIPATION_BUCKETS = 4 -def random_block_altair(spec, state, signed_blocks): +def random_block_altair_with_cycling_sync_committee_participation(spec, + state, + signed_blocks): block = random_block(spec, state, signed_blocks) - fraction_missed = len(signed_blocks) / SYNC_AGGREGATE_PARTICIPATION_BUCKETS + block_index = len(signed_blocks) % SYNC_AGGREGATE_PARTICIPATION_BUCKETS + fraction_missed = block_index * (1 / SYNC_AGGREGATE_PARTICIPATION_BUCKETS) fraction_participated = 1.0 - fraction_missed block.body.sync_aggregate = get_random_sync_aggregate( spec, diff --git a/tests/generators/random/generate.py b/tests/generators/random/generate.py index 7f033f957..099be5f35 100644 --- a/tests/generators/random/generate.py +++ b/tests/generators/random/generate.py @@ -20,7 +20,7 @@ from eth2spec.test.utils.randomized_block_tests import ( randomize_state, randomize_state_altair, random_block, - random_block_altair, + random_block_altair_with_cycling_sync_committee_participation, last_slot_in_epoch, random_slot_in_epoch, penultimate_slot_in_epoch, @@ -252,7 +252,7 @@ if __name__ == "__main__": run_generate_tests_to_std_out( ALTAIR, state_randomizer=randomize_state_altair, - block_randomizer=random_block_altair, + block_randomizer=random_block_altair_with_cycling_sync_committee_participation, ) if not did_generate: warnings.warn("no phase given for test generation")