Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Altair transition tests #2664

Merged
merged 17 commits into from
Oct 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from random import Random

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,
)
hwwhww marked this conversation as resolved.
Show resolved Hide resolved
from eth2spec.test.helpers.state import (
next_epoch,
next_epoch_via_block,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import random
from eth2spec.test.context import (
MINIMAL,
fork_transition_test,
with_presets,
)
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
from eth2spec.test.helpers.fork_transition import (
do_altair_fork,
transition_until_fork,
transition_to_next_epoch_and_append_blocks,
)
from eth2spec.test.helpers.random import (
exit_random_validators,
set_some_activations,
set_some_new_deposits,
)


#
# Exit
#

@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
@with_presets([MINIMAL],
reason="only test with enough validators such that at least one exited index is not in sync committee")
def test_transition_with_one_fourth_exiting_validators_exit_post_fork(state,
fork_epoch,
spec,
post_spec,
pre_tag,
post_tag):
"""
1/4 validators initiated voluntary exit before the fork,
and are exiting but still active *after* the fork transition.
"""
exited_indices = exit_random_validators(
spec,
state,
rng=random.Random(5566),
fraction=0.25,
exit_epoch=10,
from_epoch=spec.get_current_epoch(state),
)

transition_until_fork(spec, state, fork_epoch)

# check pre state
assert len(exited_indices) > 0
for index in exited_indices:
validator = state.validators[index]
assert not validator.slashed
assert fork_epoch < validator.exit_epoch < spec.FAR_FUTURE_EPOCH
assert spec.is_active_validator(validator, spec.get_current_epoch(state))
assert not spec.is_in_inactivity_leak(state)
assert spec.get_current_epoch(state) < fork_epoch

yield "pre", state

# irregular state transition to handle fork:
blocks = []
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
blocks.append(post_tag(block))

# ensure that some of the current sync committee members are exiting
exited_pubkeys = [state.validators[index].pubkey for index in exited_indices]
assert any(set(exited_pubkeys).intersection(list(state.current_sync_committee.pubkeys)))
assert any(set(exited_pubkeys).difference(list(state.current_sync_committee.pubkeys)))
hwwhww marked this conversation as resolved.
Show resolved Hide resolved

# continue regular state transition with new spec into next epoch
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)

# check state
for index in exited_indices:
validator = state.validators[index]
assert not validator.slashed
assert post_spec.is_active_validator(validator, post_spec.get_current_epoch(state))
assert not post_spec.is_in_inactivity_leak(state)

yield "blocks", blocks
yield "post", state


@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
def test_transition_with_one_fourth_exiting_validators_exit_at_fork(state,
fork_epoch,
spec,
post_spec,
pre_tag,
post_tag):
"""
1/4 validators initiated voluntary exit before the fork,
and being exited and inactive *right after* the fork transition.
"""
exited_indices = exit_random_validators(
spec,
state,
rng=random.Random(5566),
fraction=0.25,
exit_epoch=fork_epoch,
from_epoch=spec.get_current_epoch(state),
)

transition_until_fork(spec, state, fork_epoch)

# check pre state
assert len(exited_indices) > 0
for index in exited_indices:
validator = state.validators[index]
assert not validator.slashed
assert fork_epoch == validator.exit_epoch < spec.FAR_FUTURE_EPOCH
assert spec.is_active_validator(validator, spec.get_current_epoch(state))
assert not spec.is_in_inactivity_leak(state)
assert spec.get_current_epoch(state) < fork_epoch

yield "pre", state

# irregular state transition to handle fork:
blocks = []
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
blocks.append(post_tag(block))

# check post transition state
for index in exited_indices:
validator = state.validators[index]
assert not validator.slashed
assert not post_spec.is_active_validator(validator, post_spec.get_current_epoch(state))
assert not post_spec.is_in_inactivity_leak(state)

# ensure that none of the current sync committee members are exited validators
exited_pubkeys = [state.validators[index].pubkey for index in exited_indices]
assert not any(set(exited_pubkeys).intersection(list(state.current_sync_committee.pubkeys)))

# continue regular state transition with new spec into next epoch
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)

yield "blocks", blocks
yield "post", state


#
# Activation
#


@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
def test_transition_with_non_empty_activation_queue(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Create some deposits before the transition
"""
transition_until_fork(spec, state, fork_epoch)

deposited_indices = set_some_new_deposits(spec, state, rng=random.Random(5566))

assert spec.get_current_epoch(state) < fork_epoch
assert len(deposited_indices) > 0
for validator_index in deposited_indices:
assert not spec.is_active_validator(state.validators[validator_index], spec.get_current_epoch(state))

yield "pre", state

# irregular state transition to handle fork:
blocks = []
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
blocks.append(post_tag(block))

# continue regular state transition with new spec into next epoch
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)

yield "blocks", blocks
yield "post", state


@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
def test_transition_with_activation_at_fork_epoch(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Create some deposits before the transition
"""
transition_until_fork(spec, state, fork_epoch)

selected_indices = set_some_activations(spec, state, rng=random.Random(5566), activation_epoch=fork_epoch)

assert spec.get_current_epoch(state) < fork_epoch
assert len(selected_indices) > 0
for validator_index in selected_indices:
validator = state.validators[validator_index]
assert not spec.is_active_validator(validator, spec.get_current_epoch(state))
assert validator.activation_epoch == fork_epoch

yield "pre", state

# irregular state transition to handle fork:
blocks = []
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
blocks.append(post_tag(block))

# continue regular state transition with new spec into next epoch
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)

# now they are active
for validator_index in selected_indices:
validator = state.validators[validator_index]
assert post_spec.is_active_validator(validator, post_spec.get_current_epoch(state))

yield "blocks", blocks
yield "post", state
63 changes: 63 additions & 0 deletions tests/core/pyspec/eth2spec/test/altair/transition/test_leaking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from eth2spec.test.context import fork_transition_test
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
from eth2spec.test.helpers.fork_transition import (
do_altair_fork,
transition_until_fork,
transition_to_next_epoch_and_append_blocks,
)


@fork_transition_test(PHASE0, ALTAIR, fork_epoch=7)
def test_transition_with_leaking_pre_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Leaking starts at epoch 6 (MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2).
The leaking starts before the fork transition in this case.
"""
transition_until_fork(spec, state, fork_epoch)

assert spec.is_in_inactivity_leak(state)
assert spec.get_current_epoch(state) < fork_epoch

yield "pre", state

# irregular state transition to handle fork:
blocks = []
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
blocks.append(post_tag(block))

# check post transition state
assert spec.is_in_inactivity_leak(state)

# continue regular state transition with new spec into next epoch
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)

yield "blocks", blocks
yield "post", state


@fork_transition_test(PHASE0, ALTAIR, fork_epoch=6)
def test_transition_with_leaking_at_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Leaking starts at epoch 6 (MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2).
The leaking starts at the fork transition in this case.
"""
transition_until_fork(spec, state, fork_epoch)

assert not spec.is_in_inactivity_leak(state)
assert spec.get_current_epoch(state) < fork_epoch

yield "pre", state

# irregular state transition to handle fork:
blocks = []
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
blocks.append(post_tag(block))

# check post transition state
assert spec.is_in_inactivity_leak(state)

# continue regular state transition with new spec into next epoch
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)

yield "blocks", blocks
yield "post", state
Loading