Make altair transition tests support merge forks
This commit is contained in:
parent
7d411a2acd
commit
0b0fe15c75
|
@ -1,12 +1,15 @@
|
||||||
import random
|
import random
|
||||||
from eth2spec.test.context import (
|
from eth2spec.test.context import (
|
||||||
MINIMAL,
|
ForkMeta,
|
||||||
fork_transition_test,
|
|
||||||
with_presets,
|
with_presets,
|
||||||
|
with_fork_metas,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.constants import (
|
||||||
|
ALL_FORKS,
|
||||||
|
MINIMAL,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
|
||||||
from eth2spec.test.helpers.fork_transition import (
|
from eth2spec.test.helpers.fork_transition import (
|
||||||
do_altair_fork,
|
do_fork,
|
||||||
transition_until_fork,
|
transition_until_fork,
|
||||||
transition_to_next_epoch_and_append_blocks,
|
transition_to_next_epoch_and_append_blocks,
|
||||||
)
|
)
|
||||||
|
@ -21,7 +24,7 @@ from eth2spec.test.helpers.random import (
|
||||||
# Exit
|
# Exit
|
||||||
#
|
#
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
@with_presets([MINIMAL],
|
@with_presets([MINIMAL],
|
||||||
reason="only test with enough validators such that at least one exited index is not in sync committee")
|
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,
|
def test_transition_with_one_fourth_exiting_validators_exit_post_fork(state,
|
||||||
|
@ -59,7 +62,7 @@ def test_transition_with_one_fourth_exiting_validators_exit_post_fork(state,
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
blocks = []
|
blocks = []
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# ensure that some of the current sync committee members are exiting
|
# ensure that some of the current sync committee members are exiting
|
||||||
|
@ -81,7 +84,7 @@ def test_transition_with_one_fourth_exiting_validators_exit_post_fork(state,
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_one_fourth_exiting_validators_exit_at_fork(state,
|
def test_transition_with_one_fourth_exiting_validators_exit_at_fork(state,
|
||||||
fork_epoch,
|
fork_epoch,
|
||||||
spec,
|
spec,
|
||||||
|
@ -117,7 +120,7 @@ def test_transition_with_one_fourth_exiting_validators_exit_at_fork(state,
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
blocks = []
|
blocks = []
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# check post transition state
|
# check post transition state
|
||||||
|
@ -127,10 +130,6 @@ def test_transition_with_one_fourth_exiting_validators_exit_at_fork(state,
|
||||||
assert not post_spec.is_active_validator(validator, post_spec.get_current_epoch(state))
|
assert not post_spec.is_active_validator(validator, post_spec.get_current_epoch(state))
|
||||||
assert not post_spec.is_in_inactivity_leak(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
|
# 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)
|
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks, only_last_block=True)
|
||||||
|
|
||||||
|
@ -143,7 +142,7 @@ def test_transition_with_one_fourth_exiting_validators_exit_at_fork(state,
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_non_empty_activation_queue(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_non_empty_activation_queue(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Create some deposits before the transition
|
Create some deposits before the transition
|
||||||
|
@ -161,7 +160,7 @@ def test_transition_with_non_empty_activation_queue(state, fork_epoch, spec, pos
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
blocks = []
|
blocks = []
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
|
@ -171,7 +170,7 @@ def test_transition_with_non_empty_activation_queue(state, fork_epoch, spec, pos
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_activation_at_fork_epoch(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_activation_at_fork_epoch(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Create some deposits before the transition
|
Create some deposits before the transition
|
||||||
|
@ -191,7 +190,7 @@ def test_transition_with_activation_at_fork_epoch(state, fork_epoch, spec, post_
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
blocks = []
|
blocks = []
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
from eth2spec.test.context import fork_transition_test
|
from eth2spec.test.context import (
|
||||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
ForkMeta,
|
||||||
|
with_fork_metas,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.constants import (
|
||||||
|
ALL_FORKS,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.fork_transition import (
|
from eth2spec.test.helpers.fork_transition import (
|
||||||
do_altair_fork,
|
do_fork,
|
||||||
transition_until_fork,
|
transition_until_fork,
|
||||||
transition_to_next_epoch_and_append_blocks,
|
transition_to_next_epoch_and_append_blocks,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=7)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=7) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_leaking_pre_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
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).
|
Leaking starts at epoch 6 (MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2).
|
||||||
|
@ -22,7 +27,7 @@ def test_transition_with_leaking_pre_fork(state, fork_epoch, spec, post_spec, pr
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
blocks = []
|
blocks = []
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# check post transition state
|
# check post transition state
|
||||||
|
@ -35,7 +40,7 @@ def test_transition_with_leaking_pre_fork(state, fork_epoch, spec, post_spec, pr
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=6)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=6) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_leaking_at_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
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).
|
Leaking starts at epoch 6 (MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2).
|
||||||
|
@ -50,7 +55,7 @@ def test_transition_with_leaking_at_fork(state, fork_epoch, spec, post_spec, pre
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
blocks = []
|
blocks = []
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# check post transition state
|
# check post transition state
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
from eth2spec.test.context import (
|
from eth2spec.test.context import (
|
||||||
|
ForkMeta,
|
||||||
always_bls,
|
always_bls,
|
||||||
fork_transition_test,
|
with_fork_metas,
|
||||||
|
with_presets,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.constants import (
|
||||||
|
ALL_FORKS,
|
||||||
|
MINIMAL,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
|
||||||
from eth2spec.test.helpers.fork_transition import (
|
from eth2spec.test.helpers.fork_transition import (
|
||||||
OperationType,
|
OperationType,
|
||||||
run_transition_with_operation,
|
run_transition_with_operation,
|
||||||
|
@ -13,7 +18,7 @@ from eth2spec.test.helpers.fork_transition import (
|
||||||
# PROPOSER_SLASHING
|
# PROPOSER_SLASHING
|
||||||
#
|
#
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
@always_bls
|
@always_bls
|
||||||
def test_transition_with_proposer_slashing_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_proposer_slashing_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
|
@ -31,7 +36,7 @@ def test_transition_with_proposer_slashing_right_after_fork(state, fork_epoch, s
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
@always_bls
|
@always_bls
|
||||||
def test_transition_with_proposer_slashing_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_proposer_slashing_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
|
@ -54,7 +59,7 @@ def test_transition_with_proposer_slashing_right_before_fork(state, fork_epoch,
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
@always_bls
|
@always_bls
|
||||||
def test_transition_with_attester_slashing_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_attester_slashing_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
|
@ -72,7 +77,7 @@ def test_transition_with_attester_slashing_right_after_fork(state, fork_epoch, s
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
@always_bls
|
@always_bls
|
||||||
def test_transition_with_attester_slashing_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_attester_slashing_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
|
@ -95,7 +100,7 @@ def test_transition_with_attester_slashing_right_before_fork(state, fork_epoch,
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_deposit_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_deposit_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Create a deposit right *after* the transition
|
Create a deposit right *after* the transition
|
||||||
|
@ -112,7 +117,7 @@ def test_transition_with_deposit_right_after_fork(state, fork_epoch, spec, post_
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_deposit_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_deposit_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Create a deposit right *before* the transition
|
Create a deposit right *before* the transition
|
||||||
|
@ -134,11 +139,12 @@ def test_transition_with_deposit_right_before_fork(state, fork_epoch, spec, post
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=260)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=66) for pre, post in ALL_FORKS.items()])
|
||||||
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_transition_with_voluntary_exit_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_voluntary_exit_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Create a voluntary exit right *after* the transition.
|
Create a voluntary exit right *after* the transition.
|
||||||
fork_epoch=260 because mainnet `SHARD_COMMITTEE_PERIOD` is 256 epochs.
|
fork_epoch=66 because minimal preset `SHARD_COMMITTEE_PERIOD` is 64 epochs.
|
||||||
"""
|
"""
|
||||||
# Fast forward to the future epoch so that validator can do voluntary exit
|
# Fast forward to the future epoch so that validator can do voluntary exit
|
||||||
state.slot = spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
state.slot = spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||||
|
@ -155,11 +161,12 @@ def test_transition_with_voluntary_exit_right_after_fork(state, fork_epoch, spec
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=260)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=66) for pre, post in ALL_FORKS.items()])
|
||||||
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_transition_with_voluntary_exit_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_voluntary_exit_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Create a voluntary exit right *before* the transition.
|
Create a voluntary exit right *before* the transition.
|
||||||
fork_epoch=260 because mainnet `SHARD_COMMITTEE_PERIOD` is 256 epochs.
|
fork_epoch=66 because minimal preset `SHARD_COMMITTEE_PERIOD` is 64 epochs.
|
||||||
"""
|
"""
|
||||||
# Fast forward to the future epoch so that validator can do voluntary exit
|
# Fast forward to the future epoch so that validator can do voluntary exit
|
||||||
state.slot = spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
state.slot = spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import random
|
import random
|
||||||
from eth2spec.test.context import (
|
from eth2spec.test.context import (
|
||||||
MINIMAL,
|
ForkMeta,
|
||||||
fork_transition_test,
|
with_fork_metas,
|
||||||
with_presets,
|
with_presets,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
from eth2spec.test.helpers.constants import (
|
||||||
|
ALL_FORKS,
|
||||||
|
MINIMAL,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.fork_transition import (
|
from eth2spec.test.helpers.fork_transition import (
|
||||||
do_altair_fork,
|
do_fork,
|
||||||
transition_to_next_epoch_and_append_blocks,
|
transition_to_next_epoch_and_append_blocks,
|
||||||
transition_until_fork,
|
transition_until_fork,
|
||||||
)
|
)
|
||||||
|
@ -15,7 +18,7 @@ from eth2spec.test.helpers.random import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=1)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=1) for pre, post in ALL_FORKS.items()])
|
||||||
@with_presets([MINIMAL],
|
@with_presets([MINIMAL],
|
||||||
reason="only test with enough validators such that at least one exited index is not in sync committee")
|
reason="only test with enough validators such that at least one exited index is not in sync committee")
|
||||||
def test_transition_with_one_fourth_slashed_active_validators_pre_fork(state,
|
def test_transition_with_one_fourth_slashed_active_validators_pre_fork(state,
|
||||||
|
@ -45,7 +48,7 @@ def test_transition_with_one_fourth_slashed_active_validators_pre_fork(state,
|
||||||
yield "pre", state
|
yield "pre", state
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, _ = do_altair_fork(state, spec, post_spec, fork_epoch, with_block=False)
|
state, _ = do_fork(state, spec, post_spec, fork_epoch, with_block=False)
|
||||||
|
|
||||||
# ensure that some of the current sync committee members are slashed
|
# ensure that some of the current sync committee members are slashed
|
||||||
slashed_pubkeys = [state.validators[index].pubkey for index in slashed_indices]
|
slashed_pubkeys = [state.validators[index].pubkey for index in slashed_indices]
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
import random
|
import random
|
||||||
from eth2spec.test.context import fork_transition_test
|
from eth2spec.test.context import (
|
||||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
ForkMeta,
|
||||||
|
with_fork_metas,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.constants import (
|
||||||
|
ALL_FORKS,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
next_epoch_via_signed_block,
|
next_epoch_via_signed_block,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.attestations import next_slots_with_attestations
|
from eth2spec.test.helpers.attestations import next_slots_with_attestations
|
||||||
from eth2spec.test.helpers.fork_transition import (
|
from eth2spec.test.helpers.fork_transition import (
|
||||||
do_altair_fork,
|
do_fork,
|
||||||
no_blocks,
|
no_blocks,
|
||||||
only_at,
|
only_at,
|
||||||
skip_slots,
|
skip_slots,
|
||||||
|
@ -15,7 +20,7 @@ from eth2spec.test.helpers.fork_transition import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_normal_transition(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_normal_transition(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
||||||
|
@ -34,7 +39,7 @@ def test_normal_transition(state, fork_epoch, spec, post_spec, pre_tag, post_tag
|
||||||
])
|
])
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
|
@ -51,7 +56,7 @@ def test_normal_transition(state, fork_epoch, spec, post_spec, pre_tag, post_tag
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_missing_first_post_block(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_missing_first_post_block(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
||||||
|
@ -71,7 +76,7 @@ def test_transition_missing_first_post_block(state, fork_epoch, spec, post_spec,
|
||||||
])
|
])
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, _ = do_altair_fork(state, spec, post_spec, fork_epoch, with_block=False)
|
state, _ = do_fork(state, spec, post_spec, fork_epoch, with_block=False)
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks)
|
transition_to_next_epoch_and_append_blocks(post_spec, state, post_tag, blocks)
|
||||||
|
@ -88,7 +93,7 @@ def test_transition_missing_first_post_block(state, fork_epoch, spec, post_spec,
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_missing_last_pre_fork_block(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_missing_last_pre_fork_block(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
||||||
|
@ -109,7 +114,7 @@ def test_transition_missing_last_pre_fork_block(state, fork_epoch, spec, post_sp
|
||||||
])
|
])
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
|
@ -127,7 +132,7 @@ def test_transition_missing_last_pre_fork_block(state, fork_epoch, spec, post_sp
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_only_blocks_post_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_only_blocks_post_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
||||||
|
@ -148,7 +153,7 @@ def test_transition_only_blocks_post_fork(state, fork_epoch, spec, post_spec, pr
|
||||||
])
|
])
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, _ = do_altair_fork(state, spec, post_spec, fork_epoch, with_block=False)
|
state, _ = do_fork(state, spec, post_spec, fork_epoch, with_block=False)
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||||
|
@ -215,7 +220,7 @@ def _run_transition_test_with_attestations(state,
|
||||||
assert (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0
|
assert (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# continue regular state transition with new spec into next epoch
|
# continue regular state transition with new spec into next epoch
|
||||||
|
@ -253,7 +258,7 @@ def _run_transition_test_with_attestations(state,
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=3) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_finality(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_finality(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
||||||
|
@ -262,7 +267,7 @@ def test_transition_with_finality(state, fork_epoch, spec, post_spec, pre_tag, p
|
||||||
yield from _run_transition_test_with_attestations(state, fork_epoch, spec, post_spec, pre_tag, post_tag)
|
yield from _run_transition_test_with_attestations(state, fork_epoch, spec, post_spec, pre_tag, post_tag)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=3) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_random_three_quarters_participation(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_random_three_quarters_participation(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
Transition from the initial ``state`` to the epoch after the ``fork_epoch``,
|
||||||
|
@ -289,7 +294,7 @@ def test_transition_with_random_three_quarters_participation(state, fork_epoch,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=3) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_random_half_participation(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_random_half_participation(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
rng = random.Random(2020)
|
rng = random.Random(2020)
|
||||||
|
|
||||||
|
@ -313,7 +318,7 @@ def test_transition_with_random_half_participation(state, fork_epoch, spec, post
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=3) for pre, post in ALL_FORKS.items()])
|
||||||
def test_transition_with_no_attestations_until_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
def test_transition_with_no_attestations_until_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
"""
|
"""
|
||||||
Transition from the initial ``state`` to the ``fork_epoch`` with no attestations,
|
Transition from the initial ``state`` to the ``fork_epoch`` with no attestations,
|
||||||
|
@ -332,7 +337,7 @@ def test_transition_with_no_attestations_until_after_fork(state, fork_epoch, spe
|
||||||
])
|
])
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch)
|
state, block = do_fork(state, spec, post_spec, fork_epoch)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
# continue regular state transition but add attestations
|
# continue regular state transition but add attestations
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from eth2spec.phase0 import mainnet as spec_phase0_mainnet, minimal as spec_phase0_minimal
|
from eth2spec.phase0 import mainnet as spec_phase0_mainnet, minimal as spec_phase0_minimal
|
||||||
from eth2spec.altair import mainnet as spec_altair_mainnet, minimal as spec_altair_minimal
|
from eth2spec.altair import mainnet as spec_altair_mainnet, minimal as spec_altair_minimal
|
||||||
from eth2spec.merge import mainnet as spec_merge_mainnet, minimal as spec_merge_minimal
|
from eth2spec.merge import mainnet as spec_merge_mainnet, minimal as spec_merge_minimal
|
||||||
|
@ -7,12 +9,16 @@ from eth2spec.utils import bls
|
||||||
|
|
||||||
from .exceptions import SkippedTest
|
from .exceptions import SkippedTest
|
||||||
from .helpers.constants import (
|
from .helpers.constants import (
|
||||||
SpecForkName, PresetBaseName,
|
|
||||||
PHASE0, ALTAIR, MERGE, MINIMAL, MAINNET,
|
PHASE0, ALTAIR, MERGE, MINIMAL, MAINNET,
|
||||||
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_MERGE,
|
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_MERGE,
|
||||||
|
ALL_FORKS,
|
||||||
)
|
)
|
||||||
|
from .helpers.typing import SpecForkName, PresetBaseName
|
||||||
from .helpers.genesis import create_genesis_state
|
from .helpers.genesis import create_genesis_state
|
||||||
from .utils import vector_test, with_meta_tags, build_transition_test
|
from .utils import (
|
||||||
|
vector_test,
|
||||||
|
with_meta_tags,
|
||||||
|
)
|
||||||
|
|
||||||
from random import Random
|
from random import Random
|
||||||
from typing import Any, Callable, Sequence, TypedDict, Protocol, Dict
|
from typing import Any, Callable, Sequence, TypedDict, Protocol, Dict
|
||||||
|
@ -50,6 +56,13 @@ class SpecMerge(Spec):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ForkMeta:
|
||||||
|
pre_fork_name: str
|
||||||
|
post_fork_name: str
|
||||||
|
fork_epoch: int
|
||||||
|
|
||||||
|
|
||||||
spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
||||||
MINIMAL: {
|
MINIMAL: {
|
||||||
PHASE0: spec_phase0_minimal,
|
PHASE0: spec_phase0_minimal,
|
||||||
|
@ -86,7 +99,6 @@ _custom_state_cache_dict = LRU(size=10)
|
||||||
def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
|
def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
|
||||||
threshold_fn: Callable[[Any], int]):
|
threshold_fn: Callable[[Any], int]):
|
||||||
def deco(fn):
|
def deco(fn):
|
||||||
|
|
||||||
def entry(*args, spec: Spec, phases: SpecForks, **kw):
|
def entry(*args, spec: Spec, phases: SpecForks, **kw):
|
||||||
# make a key for the state, unique to the fork + config (incl preset choice) and balances/activations
|
# make a key for the state, unique to the fork + config (incl preset choice) and balances/activations
|
||||||
key = (spec.fork, spec.config.__hash__(), spec.__file__, balances_fn, threshold_fn)
|
key = (spec.fork, spec.config.__hash__(), spec.__file__, balances_fn, threshold_fn)
|
||||||
|
@ -104,7 +116,7 @@ def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
|
||||||
return deco
|
return deco
|
||||||
|
|
||||||
|
|
||||||
def default_activation_threshold(spec):
|
def default_activation_threshold(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to use the default balance activation threshold for state creation for tests.
|
Helper method to use the default balance activation threshold for state creation for tests.
|
||||||
Usage: `@with_custom_state(threshold_fn=default_activation_threshold, ...)`
|
Usage: `@with_custom_state(threshold_fn=default_activation_threshold, ...)`
|
||||||
|
@ -112,7 +124,7 @@ def default_activation_threshold(spec):
|
||||||
return spec.MAX_EFFECTIVE_BALANCE
|
return spec.MAX_EFFECTIVE_BALANCE
|
||||||
|
|
||||||
|
|
||||||
def zero_activation_threshold(spec):
|
def zero_activation_threshold(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to use 0 gwei as the activation threshold for state creation for tests.
|
Helper method to use 0 gwei as the activation threshold for state creation for tests.
|
||||||
Usage: `@with_custom_state(threshold_fn=zero_activation_threshold, ...)`
|
Usage: `@with_custom_state(threshold_fn=zero_activation_threshold, ...)`
|
||||||
|
@ -120,7 +132,7 @@ def zero_activation_threshold(spec):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def default_balances(spec):
|
def default_balances(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create a series of default balances.
|
Helper method to create a series of default balances.
|
||||||
Usage: `@with_custom_state(balances_fn=default_balances, ...)`
|
Usage: `@with_custom_state(balances_fn=default_balances, ...)`
|
||||||
|
@ -129,7 +141,7 @@ def default_balances(spec):
|
||||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||||
|
|
||||||
|
|
||||||
def scaled_churn_balances(spec):
|
def scaled_churn_balances(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create enough validators to scale the churn limit.
|
Helper method to create enough validators to scale the churn limit.
|
||||||
(This is *firmly* over the churn limit -- thus the +2 instead of just +1)
|
(This is *firmly* over the churn limit -- thus the +2 instead of just +1)
|
||||||
|
@ -143,7 +155,7 @@ def scaled_churn_balances(spec):
|
||||||
with_state = with_custom_state(default_balances, default_activation_threshold)
|
with_state = with_custom_state(default_balances, default_activation_threshold)
|
||||||
|
|
||||||
|
|
||||||
def low_balances(spec):
|
def low_balances(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create a series of low balances.
|
Helper method to create a series of low balances.
|
||||||
Usage: `@with_custom_state(balances_fn=low_balances, ...)`
|
Usage: `@with_custom_state(balances_fn=low_balances, ...)`
|
||||||
|
@ -154,7 +166,7 @@ def low_balances(spec):
|
||||||
return [low_balance] * num_validators
|
return [low_balance] * num_validators
|
||||||
|
|
||||||
|
|
||||||
def misc_balances(spec):
|
def misc_balances(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create a series of balances that includes some misc. balances.
|
Helper method to create a series of balances that includes some misc. balances.
|
||||||
Usage: `@with_custom_state(balances_fn=misc_balances, ...)`
|
Usage: `@with_custom_state(balances_fn=misc_balances, ...)`
|
||||||
|
@ -166,7 +178,7 @@ def misc_balances(spec):
|
||||||
return balances
|
return balances
|
||||||
|
|
||||||
|
|
||||||
def misc_balances_in_default_range_with_many_validators(spec):
|
def misc_balances_in_default_range_with_many_validators(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create a series of balances that includes some misc. balances but
|
Helper method to create a series of balances that includes some misc. balances but
|
||||||
none that are below the ``EJECTION_BALANCE``.
|
none that are below the ``EJECTION_BALANCE``.
|
||||||
|
@ -182,7 +194,7 @@ def misc_balances_in_default_range_with_many_validators(spec):
|
||||||
return balances
|
return balances
|
||||||
|
|
||||||
|
|
||||||
def low_single_balance(spec):
|
def low_single_balance(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create a single of balance of 1 Gwei.
|
Helper method to create a single of balance of 1 Gwei.
|
||||||
Usage: `@with_custom_state(balances_fn=low_single_balance, ...)`
|
Usage: `@with_custom_state(balances_fn=low_single_balance, ...)`
|
||||||
|
@ -190,7 +202,7 @@ def low_single_balance(spec):
|
||||||
return [1]
|
return [1]
|
||||||
|
|
||||||
|
|
||||||
def large_validator_set(spec):
|
def large_validator_set(spec: Spec):
|
||||||
"""
|
"""
|
||||||
Helper method to create a large series of default balances.
|
Helper method to create a large series of default balances.
|
||||||
Usage: `@with_custom_state(balances_fn=default_balances, ...)`
|
Usage: `@with_custom_state(balances_fn=default_balances, ...)`
|
||||||
|
@ -347,6 +359,66 @@ def with_all_phases_except(exclusion_phases):
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def _get_preset_targets(kw):
|
||||||
|
preset_name = DEFAULT_TEST_PRESET
|
||||||
|
if 'preset' in kw:
|
||||||
|
preset_name = kw.pop('preset')
|
||||||
|
return spec_targets[preset_name]
|
||||||
|
|
||||||
|
|
||||||
|
def _get_run_phases(phases, kw):
|
||||||
|
"""
|
||||||
|
Return the fork names for the base `spec` in test cases
|
||||||
|
"""
|
||||||
|
if 'phase' in kw:
|
||||||
|
# Limit phases if one explicitly specified
|
||||||
|
phase = kw.pop('phase')
|
||||||
|
if phase not in phases:
|
||||||
|
dump_skipping_message(f"doesn't support this fork: {phase}")
|
||||||
|
return None
|
||||||
|
run_phases = [phase]
|
||||||
|
else:
|
||||||
|
# If pytest `--fork` flag is set, filter out the rest forks
|
||||||
|
run_phases = set(phases).intersection(DEFAULT_PYTEST_FORKS)
|
||||||
|
|
||||||
|
return run_phases
|
||||||
|
|
||||||
|
|
||||||
|
def _get_available_phases(run_phases, other_phases):
|
||||||
|
"""
|
||||||
|
The return the available fork names for multi-phase tests
|
||||||
|
"""
|
||||||
|
available_phases = set(run_phases)
|
||||||
|
if other_phases is not None:
|
||||||
|
available_phases |= set(other_phases)
|
||||||
|
return available_phases
|
||||||
|
|
||||||
|
|
||||||
|
def _run_test_case_with_phases(fn, phases, other_phases, kw, args, is_fork_transition=False):
|
||||||
|
run_phases = _get_run_phases(phases, kw)
|
||||||
|
|
||||||
|
if len(run_phases) == 0:
|
||||||
|
if not is_fork_transition:
|
||||||
|
dump_skipping_message("none of the recognized phases are executable, skipping test.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
available_phases = _get_available_phases(run_phases, other_phases)
|
||||||
|
|
||||||
|
targets = _get_preset_targets(kw)
|
||||||
|
|
||||||
|
# Populate all phases for multi-phase tests
|
||||||
|
phase_dir = {}
|
||||||
|
for phase in available_phases:
|
||||||
|
phase_dir[phase] = targets[phase]
|
||||||
|
|
||||||
|
# Return is ignored whenever multiple phases are ran.
|
||||||
|
# This return is for test generators to emit python generators (yielding test vector outputs)
|
||||||
|
for phase in run_phases:
|
||||||
|
ret = fn(spec=targets[phase], phases=phase_dir, *args, **kw)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def with_phases(phases, other_phases=None):
|
def with_phases(phases, other_phases=None):
|
||||||
"""
|
"""
|
||||||
Decorator factory that returns a decorator that runs a test for the appropriate phases.
|
Decorator factory that returns a decorator that runs a test for the appropriate phases.
|
||||||
|
@ -354,49 +426,24 @@ def with_phases(phases, other_phases=None):
|
||||||
"""
|
"""
|
||||||
def decorator(fn):
|
def decorator(fn):
|
||||||
def wrapper(*args, **kw):
|
def wrapper(*args, **kw):
|
||||||
run_phases = set(phases).intersection(DEFAULT_PYTEST_FORKS)
|
if 'fork_metas' in kw:
|
||||||
|
fork_metas = kw.pop('fork_metas')
|
||||||
# limit phases if one explicitly specified
|
if 'phase' in kw:
|
||||||
if 'phase' in kw:
|
# When running test generator, it sets specific `phase`
|
||||||
phase = kw.pop('phase')
|
phase = kw['phase']
|
||||||
if phase not in phases:
|
_phases = [phase]
|
||||||
dump_skipping_message(f"doesn't support this fork: {phase}")
|
_other_phases = [ALL_FORKS[phase]]
|
||||||
return None
|
ret = _run_test_case_with_phases(fn, _phases, _other_phases, kw, args, is_fork_transition=True)
|
||||||
run_phases = [phase]
|
else:
|
||||||
|
# When running pytest, go through `fork_metas`
|
||||||
if PHASE0 not in run_phases and ALTAIR not in run_phases and MERGE not in run_phases:
|
for fork_meta in fork_metas:
|
||||||
dump_skipping_message("none of the recognized phases are executable, skipping test.")
|
pre_fork_name = fork_meta.pre_fork_name
|
||||||
return None
|
post_fork_name = fork_meta.post_fork_name
|
||||||
|
_phases = [pre_fork_name]
|
||||||
available_phases = set(run_phases)
|
_other_phases = [post_fork_name]
|
||||||
if other_phases is not None:
|
ret = _run_test_case_with_phases(fn, _phases, _other_phases, kw, args, is_fork_transition=True)
|
||||||
available_phases |= set(other_phases)
|
else:
|
||||||
|
ret = _run_test_case_with_phases(fn, phases, other_phases, kw, args)
|
||||||
preset_name = DEFAULT_TEST_PRESET
|
|
||||||
if 'preset' in kw:
|
|
||||||
preset_name = kw.pop('preset')
|
|
||||||
targets = spec_targets[preset_name]
|
|
||||||
|
|
||||||
# Populate all phases for multi-phase tests
|
|
||||||
phase_dir = {}
|
|
||||||
if PHASE0 in available_phases:
|
|
||||||
phase_dir[PHASE0] = targets[PHASE0]
|
|
||||||
if ALTAIR in available_phases:
|
|
||||||
phase_dir[ALTAIR] = targets[ALTAIR]
|
|
||||||
if MERGE in available_phases:
|
|
||||||
phase_dir[MERGE] = targets[MERGE]
|
|
||||||
|
|
||||||
# return is ignored whenever multiple phases are ran.
|
|
||||||
# This return is for test generators to emit python generators (yielding test vector outputs)
|
|
||||||
if PHASE0 in run_phases:
|
|
||||||
ret = fn(spec=targets[PHASE0], phases=phase_dir, *args, **kw)
|
|
||||||
if ALTAIR in run_phases:
|
|
||||||
ret = fn(spec=targets[ALTAIR], phases=phase_dir, *args, **kw)
|
|
||||||
if MERGE in run_phases:
|
|
||||||
ret = fn(spec=targets[MERGE], phases=phase_dir, *args, **kw)
|
|
||||||
|
|
||||||
# TODO: merge, sharding, custody_game and das are not executable yet.
|
|
||||||
# Tests that specify these features will not run, and get ignored for these specific phases.
|
|
||||||
return ret
|
return ret
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -481,10 +528,25 @@ def only_generator(reason):
|
||||||
return _decorator
|
return _decorator
|
||||||
|
|
||||||
|
|
||||||
def fork_transition_test(pre_fork_name, post_fork_name, fork_epoch=None):
|
#
|
||||||
|
# Fork transition state tests
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def set_fork_metas(fork_metas: Sequence[ForkMeta]):
|
||||||
|
def decorator(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
return fn(*args, fork_metas=fork_metas, **kwargs)
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def with_fork_metas(fork_metas: Sequence[ForkMeta]):
|
||||||
"""
|
"""
|
||||||
A decorator to construct a "transition" test from one fork of the eth2 spec
|
A decorator to construct a "transition" test from one fork to another.
|
||||||
to another.
|
|
||||||
|
Decorator takes a list of `ForkMeta` and each item defines `pre_fork_name`,
|
||||||
|
`post_fork_name`, and `fork_epoch`.
|
||||||
|
|
||||||
Decorator assumes a transition from the `pre_fork_name` fork to the
|
Decorator assumes a transition from the `pre_fork_name` fork to the
|
||||||
`post_fork_name` fork. The user can supply a `fork_epoch` at which the
|
`post_fork_name` fork. The user can supply a `fork_epoch` at which the
|
||||||
|
@ -502,15 +564,62 @@ def fork_transition_test(pre_fork_name, post_fork_name, fork_epoch=None):
|
||||||
`post_tag`: a function to tag data as belonging to `post_fork_name` fork.
|
`post_tag`: a function to tag data as belonging to `post_fork_name` fork.
|
||||||
Used to discriminate data during consumption of the generated spec tests.
|
Used to discriminate data during consumption of the generated spec tests.
|
||||||
"""
|
"""
|
||||||
def _wrapper(fn):
|
run_yield_fork_meta = yield_fork_meta(fork_metas)
|
||||||
@with_phases([pre_fork_name], other_phases=[post_fork_name])
|
run_with_phases = with_phases(ALL_PHASES)
|
||||||
@spec_test
|
run_set_fork_metas = set_fork_metas(fork_metas)
|
||||||
@with_state
|
|
||||||
def _adapter(*args, **kwargs):
|
def decorator(fn):
|
||||||
wrapped = build_transition_test(fn,
|
return run_set_fork_metas(run_with_phases(spec_test(with_state(run_yield_fork_meta(fn)))))
|
||||||
pre_fork_name,
|
return decorator
|
||||||
post_fork_name,
|
|
||||||
fork_epoch=fork_epoch)
|
|
||||||
return wrapped(*args, **kwargs)
|
def yield_fork_meta(fork_metas: Sequence[ForkMeta]):
|
||||||
return _adapter
|
"""
|
||||||
return _wrapper
|
Yield meta fields to `meta.yaml` and pass post spec and meta fields to `fn`.
|
||||||
|
"""
|
||||||
|
def decorator(fn):
|
||||||
|
def wrapper(*args, **kw):
|
||||||
|
phases = kw.pop('phases')
|
||||||
|
spec = kw["spec"]
|
||||||
|
fork_meta = [m for m in fork_metas if m.pre_fork_name == spec.fork][0]
|
||||||
|
fork_meta = next(filter(lambda m: m.pre_fork_name == spec.fork, fork_metas))
|
||||||
|
post_spec = phases[fork_meta.post_fork_name]
|
||||||
|
|
||||||
|
# Reset counter
|
||||||
|
pre_fork_counter = 0
|
||||||
|
|
||||||
|
def pre_tag(obj):
|
||||||
|
nonlocal pre_fork_counter
|
||||||
|
pre_fork_counter += 1
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def post_tag(obj):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
yield "post_fork", "meta", fork_meta.post_fork_name
|
||||||
|
|
||||||
|
has_fork_epoch = False
|
||||||
|
if fork_meta.fork_epoch:
|
||||||
|
kw["fork_epoch"] = fork_meta.fork_epoch
|
||||||
|
has_fork_epoch = True
|
||||||
|
yield "fork_epoch", "meta", fork_meta.fork_epoch
|
||||||
|
|
||||||
|
result = fn(
|
||||||
|
*args,
|
||||||
|
post_spec=post_spec,
|
||||||
|
pre_tag=pre_tag,
|
||||||
|
post_tag=post_tag,
|
||||||
|
**kw,
|
||||||
|
)
|
||||||
|
if result is not None:
|
||||||
|
for part in result:
|
||||||
|
if part[0] == "fork_epoch":
|
||||||
|
has_fork_epoch = True
|
||||||
|
yield part
|
||||||
|
assert has_fork_epoch
|
||||||
|
|
||||||
|
if pre_fork_counter > 0:
|
||||||
|
yield "fork_block", "meta", pre_fork_counter - 1
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
|
|
|
@ -21,6 +21,11 @@ TESTGEN_FORKS = (PHASE0, ALTAIR, MERGE)
|
||||||
|
|
||||||
FORKS_BEFORE_ALTAIR = (PHASE0,)
|
FORKS_BEFORE_ALTAIR = (PHASE0,)
|
||||||
FORKS_BEFORE_MERGE = (PHASE0, ALTAIR)
|
FORKS_BEFORE_MERGE = (PHASE0, ALTAIR)
|
||||||
|
ALL_FORKS = {
|
||||||
|
# pre_fork_name: post_fork_name
|
||||||
|
PHASE0: ALTAIR,
|
||||||
|
ALTAIR: MERGE,
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Config
|
# Config
|
||||||
|
|
|
@ -9,6 +9,10 @@ from eth2spec.test.helpers.block import (
|
||||||
build_empty_block,
|
build_empty_block,
|
||||||
sign_block,
|
sign_block,
|
||||||
)
|
)
|
||||||
|
from eth2spec.test.helpers.constants import (
|
||||||
|
ALTAIR,
|
||||||
|
MERGE,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.deposits import (
|
from eth2spec.test.helpers.deposits import (
|
||||||
prepare_state_and_deposit,
|
prepare_state_and_deposit,
|
||||||
)
|
)
|
||||||
|
@ -133,17 +137,25 @@ def state_transition_across_slots_with_ignoring_proposers(spec,
|
||||||
next_slot(spec, state)
|
next_slot(spec, state)
|
||||||
|
|
||||||
|
|
||||||
def do_altair_fork(state, spec, post_spec, fork_epoch, with_block=True, operation_dict=None):
|
def do_fork(state, spec, post_spec, fork_epoch, with_block=True, operation_dict=None):
|
||||||
spec.process_slots(state, state.slot + 1)
|
spec.process_slots(state, state.slot + 1)
|
||||||
|
|
||||||
assert state.slot % spec.SLOTS_PER_EPOCH == 0
|
assert state.slot % spec.SLOTS_PER_EPOCH == 0
|
||||||
assert spec.get_current_epoch(state) == fork_epoch
|
assert spec.get_current_epoch(state) == fork_epoch
|
||||||
|
|
||||||
state = post_spec.upgrade_to_altair(state)
|
if post_spec.fork == ALTAIR:
|
||||||
|
state = post_spec.upgrade_to_altair(state)
|
||||||
|
elif post_spec.fork == MERGE:
|
||||||
|
state = post_spec.upgrade_to_merge(state)
|
||||||
|
|
||||||
assert state.fork.epoch == fork_epoch
|
assert state.fork.epoch == fork_epoch
|
||||||
assert state.fork.previous_version == post_spec.config.GENESIS_FORK_VERSION
|
|
||||||
assert state.fork.current_version == post_spec.config.ALTAIR_FORK_VERSION
|
if post_spec.fork == ALTAIR:
|
||||||
|
assert state.fork.previous_version == post_spec.config.GENESIS_FORK_VERSION
|
||||||
|
assert state.fork.current_version == post_spec.config.ALTAIR_FORK_VERSION
|
||||||
|
elif post_spec.fork == MERGE:
|
||||||
|
assert state.fork.previous_version == post_spec.config.ALTAIR_FORK_VERSION
|
||||||
|
assert state.fork.current_version == post_spec.config.MERGE_FORK_VERSION
|
||||||
|
|
||||||
if with_block:
|
if with_block:
|
||||||
return state, _state_transition_and_sign_block_at_slot(post_spec, state, operation_dict=operation_dict)
|
return state, _state_transition_and_sign_block_at_slot(post_spec, state, operation_dict=operation_dict)
|
||||||
|
@ -280,7 +292,7 @@ def run_transition_with_operation(state,
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
# irregular state transition to handle fork:
|
||||||
_operation_at_slot = operation_dict if is_at_fork else None
|
_operation_at_slot = operation_dict if is_at_fork else None
|
||||||
state, block = do_altair_fork(state, spec, post_spec, fork_epoch, operation_dict=_operation_at_slot)
|
state, block = do_fork(state, spec, post_spec, fork_epoch, operation_dict=_operation_at_slot)
|
||||||
blocks.append(post_tag(block))
|
blocks.append(post_tag(block))
|
||||||
|
|
||||||
if is_at_fork:
|
if is_at_fork:
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
from .utils import (
|
from .utils import (
|
||||||
vector_test,
|
vector_test,
|
||||||
with_meta_tags,
|
with_meta_tags,
|
||||||
build_transition_test,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [ # avoid "unused import" lint error
|
__all__ = [ # avoid "unused import" lint error
|
||||||
"vector_test",
|
"vector_test",
|
||||||
"with_meta_tags",
|
"with_meta_tags",
|
||||||
"build_transition_test",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import inspect
|
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from eth2spec.utils.ssz.ssz_typing import View
|
from eth2spec.utils.ssz.ssz_typing import View
|
||||||
from eth2spec.utils.ssz.ssz_impl import serialize
|
from eth2spec.utils.ssz.ssz_impl import serialize
|
||||||
|
@ -94,50 +93,3 @@ def with_meta_tags(tags: Dict[str, Any]):
|
||||||
yield k, 'meta', v
|
yield k, 'meta', v
|
||||||
return entry
|
return entry
|
||||||
return runner
|
return runner
|
||||||
|
|
||||||
|
|
||||||
def build_transition_test(fn, pre_fork_name, post_fork_name, fork_epoch=None):
|
|
||||||
"""
|
|
||||||
Handles the inner plumbing to generate `transition_test`s.
|
|
||||||
See that decorator in `context.py` for more information.
|
|
||||||
"""
|
|
||||||
def _adapter(*args, **kwargs):
|
|
||||||
post_spec = kwargs["phases"][post_fork_name]
|
|
||||||
|
|
||||||
pre_fork_counter = 0
|
|
||||||
|
|
||||||
def pre_tag(obj):
|
|
||||||
nonlocal pre_fork_counter
|
|
||||||
pre_fork_counter += 1
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def post_tag(obj):
|
|
||||||
return obj
|
|
||||||
|
|
||||||
yield "post_fork", "meta", post_fork_name
|
|
||||||
|
|
||||||
has_fork_epoch = False
|
|
||||||
if fork_epoch:
|
|
||||||
kwargs["fork_epoch"] = fork_epoch
|
|
||||||
has_fork_epoch = True
|
|
||||||
yield "fork_epoch", "meta", fork_epoch
|
|
||||||
|
|
||||||
# massage args to handle an optional custom state using
|
|
||||||
# `with_custom_state` decorator
|
|
||||||
expected_args = inspect.getfullargspec(fn)
|
|
||||||
if "phases" not in expected_args.kwonlyargs:
|
|
||||||
kwargs.pop("phases", None)
|
|
||||||
|
|
||||||
for part in fn(*args,
|
|
||||||
post_spec=post_spec,
|
|
||||||
pre_tag=pre_tag,
|
|
||||||
post_tag=post_tag,
|
|
||||||
**kwargs):
|
|
||||||
if part[0] == "fork_epoch":
|
|
||||||
has_fork_epoch = True
|
|
||||||
yield part
|
|
||||||
assert has_fork_epoch
|
|
||||||
|
|
||||||
if pre_fork_counter > 0:
|
|
||||||
yield "fork_block", "meta", pre_fork_counter - 1
|
|
||||||
return _adapter
|
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from eth2spec.test.helpers.constants import ALTAIR, MINIMAL, MAINNET, PHASE0
|
from eth2spec.test.helpers.constants import (
|
||||||
|
MINIMAL,
|
||||||
|
MAINNET,
|
||||||
|
ALL_FORKS,
|
||||||
|
)
|
||||||
|
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
|
||||||
|
from eth2spec.gen_helpers.gen_from_tests.gen import (
|
||||||
|
generate_from_tests,
|
||||||
|
)
|
||||||
from eth2spec.test.altair.transition import (
|
from eth2spec.test.altair.transition import (
|
||||||
test_transition as test_altair_transition,
|
test_transition as test_altair_transition,
|
||||||
test_activations_and_exits as test_altair_activations_and_exits,
|
test_activations_and_exits as test_altair_activations_and_exits,
|
||||||
|
@ -9,9 +17,6 @@ from eth2spec.test.altair.transition import (
|
||||||
test_operations as test_altair_operations,
|
test_operations as test_altair_operations,
|
||||||
)
|
)
|
||||||
|
|
||||||
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
|
|
||||||
from eth2spec.gen_helpers.gen_from_tests.gen import generate_from_tests
|
|
||||||
|
|
||||||
|
|
||||||
def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_name: str) -> gen_typing.TestProvider:
|
def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_name: str) -> gen_typing.TestProvider:
|
||||||
|
|
||||||
|
@ -31,18 +36,17 @@ def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_n
|
||||||
return gen_typing.TestProvider(prepare=prepare_fn, make_cases=cases_fn)
|
return gen_typing.TestProvider(prepare=prepare_fn, make_cases=cases_fn)
|
||||||
|
|
||||||
|
|
||||||
TRANSITION_TESTS = (
|
|
||||||
(PHASE0, ALTAIR, test_altair_transition),
|
|
||||||
(PHASE0, ALTAIR, test_altair_activations_and_exits),
|
|
||||||
(PHASE0, ALTAIR, test_altair_leaking),
|
|
||||||
(PHASE0, ALTAIR, test_altair_slashing),
|
|
||||||
(PHASE0, ALTAIR, test_altair_operations),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
for pre_fork, post_fork, transition_test_module in TRANSITION_TESTS:
|
altair_tests = (
|
||||||
gen_runner.run_generator("transition", [
|
test_altair_transition,
|
||||||
create_provider(transition_test_module, MINIMAL, pre_fork, post_fork),
|
test_altair_activations_and_exits,
|
||||||
create_provider(transition_test_module, MAINNET, pre_fork, post_fork),
|
test_altair_leaking,
|
||||||
])
|
test_altair_slashing,
|
||||||
|
test_altair_operations,
|
||||||
|
)
|
||||||
|
for transition_test_module in altair_tests:
|
||||||
|
for pre_fork, post_fork in ALL_FORKS.items():
|
||||||
|
gen_runner.run_generator("transition", [
|
||||||
|
create_provider(transition_test_module, MINIMAL, pre_fork, post_fork),
|
||||||
|
create_provider(transition_test_module, MAINNET, pre_fork, post_fork),
|
||||||
|
])
|
||||||
|
|
Loading…
Reference in New Issue