Skip to content

Commit

Permalink
Merge pull request #2542 from ralexstokes/add-inactivity-updates-test…
Browse files Browse the repository at this point in the history
…-with-exited-validator

Add test for exited validators during inactivity leak
  • Loading branch information
djrtwo authored Aug 6, 2021
2 parents 94e7d13 + 170d7dc commit b184fa2
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
from eth2spec.test.context import spec_state_test, with_altair_and_later
from eth2spec.test.helpers.inactivity_scores import randomize_inactivity_scores, zero_inactivity_scores
from eth2spec.test.helpers.state import (
next_epoch,
next_epoch_via_block,
set_full_participation,
set_empty_participation,
)
from eth2spec.test.helpers.voluntary_exits import (
exit_validators,
get_exited_validators
)
from eth2spec.test.helpers.epoch_processing import (
run_epoch_processing_with
)
Expand Down Expand Up @@ -266,3 +271,53 @@ def test_some_slashed_full_random_leaking(spec, state):

# Check still in leak
assert spec.is_in_inactivity_leak(state)


@with_altair_and_later
@spec_state_test
@leaking()
def test_some_exited_full_random_leaking(spec, state):
rng = Random(1102233)

exit_count = 3

# randomize ahead of time to check exited validators do not have
# mutations applied to their inactivity scores
randomize_inactivity_scores(spec, state, rng=rng)

assert not any(get_exited_validators(spec, state))
exited_indices = exit_validators(spec, state, exit_count, rng=rng)
assert not any(get_exited_validators(spec, state))

# advance the state to effect the exits
target_epoch = max(state.validators[index].exit_epoch for index in exited_indices)
# validators that have exited in the previous epoch or earlier will not
# have their inactivity scores modified, the test advances the state past this point
# to confirm this invariant:
previous_epoch = spec.get_previous_epoch(state)
for _ in range(target_epoch - previous_epoch):
next_epoch(spec, state)
assert len(get_exited_validators(spec, state)) == exit_count

previous_scores = state.inactivity_scores.copy()

yield from run_inactivity_scores_test(
spec, state,
randomize_previous_epoch_participation, rng=rng,
)

# ensure exited validators have their score "frozen" at exit
# but otherwise there was a change
some_changed = False
for index in range(len(state.validators)):
if index in exited_indices:
assert previous_scores[index] == state.inactivity_scores[index]
else:
previous_score = previous_scores[index]
current_score = state.inactivity_scores[index]
if previous_score != current_score:
some_changed = True
assert some_changed

# Check still in leak
assert spec.is_in_inactivity_leak(state)
19 changes: 19 additions & 0 deletions tests/core/pyspec/eth2spec/test/helpers/voluntary_exits.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from random import Random
from eth2spec.utils import bls
from eth2spec.test.helpers.keys import privkeys

Expand All @@ -23,3 +24,21 @@ def sign_voluntary_exit(spec, state, voluntary_exit, privkey):
message=voluntary_exit,
signature=bls.Sign(privkey, signing_root)
)


#
# Helpers for applying effects of a voluntary exit
#
def get_exited_validators(spec, state):
current_epoch = spec.get_current_epoch(state)
return [index for (index, validator) in enumerate(state.validators) if validator.exit_epoch <= current_epoch]


def exit_validators(spec, state, validator_count, rng=None):
if rng is None:
rng = Random(1337)

indices = rng.sample(range(len(state.validators)), validator_count)
for index in indices:
spec.initiate_validator_exit(state, index)
return indices

0 comments on commit b184fa2

Please sign in to comment.