diff --git a/tests/core/pyspec/eth2spec/test/helpers/random.py b/tests/core/pyspec/eth2spec/test/helpers/random.py index 8f095aebb..0bb2a6672 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/random.py +++ b/tests/core/pyspec/eth2spec/test/helpers/random.py @@ -128,3 +128,33 @@ def randomize_state(spec, state, rng=Random(8020), exit_fraction=None, slash_fra exit_random_validators(spec, state, rng, fraction=exit_fraction) slash_random_validators(spec, state, rng, fraction=slash_fraction) randomize_attestation_participation(spec, state, rng) + + +def patch_state_to_non_leaking(spec, state): + """ + This function performs an irregular state transition so that: + 1. the current justified checkpoint references the previous epoch + 2. the previous justified checkpoint references the epoch before previous + 3. the finalized checkpoint matches the previous justified checkpoint + + The effects of this function are intended to offset randomization side effects + performed by other functionality in this module so that if the ``state`` was leaking, + then the ``state`` is not leaking after. + """ + 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, + ) 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 ce99c1053..02a5464f7 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -17,6 +17,7 @@ from eth2spec.test.helpers.inactivity_scores import ( ) from eth2spec.test.helpers.random import ( randomize_state as randomize_state_helper, + patch_state_to_non_leaking, ) from eth2spec.test.helpers.state import ( next_slot, @@ -274,23 +275,7 @@ def _randomized_scenario_setup(state_randomizer): 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, - ) + patch_state_to_non_leaking(spec, state) return ( # NOTE: the block randomization function assumes at least 1 shard committee period