Add test for exited validators during inactivity leak
This commit is contained in:
parent
69205a2aff
commit
2ff143c719
|
@ -3,10 +3,15 @@ from random import Random
|
||||||
from eth2spec.test.context import spec_state_test, with_altair_and_later
|
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.inactivity_scores import randomize_inactivity_scores, zero_inactivity_scores
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
|
next_epoch,
|
||||||
next_epoch_via_block,
|
next_epoch_via_block,
|
||||||
set_full_participation,
|
set_full_participation,
|
||||||
set_empty_participation,
|
set_empty_participation,
|
||||||
)
|
)
|
||||||
|
from eth2spec.test.helpers.voluntary_exits import (
|
||||||
|
exit_validators,
|
||||||
|
get_exited_validators
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.epoch_processing import (
|
from eth2spec.test.helpers.epoch_processing import (
|
||||||
run_epoch_processing_with
|
run_epoch_processing_with
|
||||||
)
|
)
|
||||||
|
@ -266,3 +271,53 @@ def test_some_slashed_full_random_leaking(spec, state):
|
||||||
|
|
||||||
# Check still in leak
|
# Check still in leak
|
||||||
assert spec.is_in_inactivity_leak(state)
|
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 get_exited_validators(spec, state)
|
||||||
|
exited_indices = exit_validators(spec, state, exit_count, rng=rng)
|
||||||
|
assert not 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)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from random import Random
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
from eth2spec.test.helpers.keys import privkeys
|
from eth2spec.test.helpers.keys import privkeys
|
||||||
|
|
||||||
|
@ -23,3 +24,21 @@ def sign_voluntary_exit(spec, state, voluntary_exit, privkey):
|
||||||
message=voluntary_exit,
|
message=voluntary_exit,
|
||||||
signature=bls.Sign(privkey, signing_root)
|
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
|
||||||
|
|
Loading…
Reference in New Issue