Skip to content
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
112 changes: 112 additions & 0 deletions tests/core/pyspec/eth2spec/test/deneb/transition/test_transition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from eth2spec.test.context import (
ForkMeta,
with_fork_metas,
with_presets,
)
from eth2spec.test.helpers.constants import (
AFTER_DENEB_PRE_POST_FORKS,
MINIMAL,
)
from eth2spec.test.helpers.keys import pubkeys
from eth2spec.test.helpers.fork_transition import (
do_fork,
transition_to_next_epoch_and_append_blocks,
transition_until_fork,
)


def mock_activated_validators(spec, state, mock_activations):
validator_count = len(state.validators)
for i in range(mock_activations):
index = validator_count + i
validator = spec.Validator(
pubkey=pubkeys[index],
withdrawal_credentials=spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + b'\x56' * 20,
activation_eligibility_epoch=0,
activation_epoch=spec.FAR_FUTURE_EPOCH,
exit_epoch=spec.FAR_FUTURE_EPOCH,
withdrawable_epoch=spec.FAR_FUTURE_EPOCH,
effective_balance=spec.MAX_EFFECTIVE_BALANCE,
)
state.validators.append(validator)
state.balances.append(spec.MAX_EFFECTIVE_BALANCE)
state.previous_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
state.current_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
state.inactivity_scores.append(0)
state.validators[index].activation_epoch = spec.get_current_epoch(state)


@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2)
for pre, post in AFTER_DENEB_PRE_POST_FORKS])
@with_presets([MINIMAL], reason="churn limit update needs enough validators")
def test_higher_churn_limit_to_lower(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Test if churn limit goes from high to low due to EIP-7514.
"""
# Create high churn limit
mock_activations = post_spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT * spec.config.CHURN_LIMIT_QUOTIENT
mock_activated_validators(spec, state, mock_activations)

transition_until_fork(spec, state, fork_epoch)

churn_limit_0 = spec.get_validator_churn_limit(state)
assert churn_limit_0 > post_spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT

# check pre state
assert spec.get_current_epoch(state) < fork_epoch

yield "pre", state

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

# check post state
assert spec.get_current_epoch(state) == fork_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)

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

churn_limit_1 = post_spec.get_validator_activation_churn_limit(state)
assert churn_limit_1 == post_spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
assert churn_limit_1 < churn_limit_0


@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2)
for pre, post in AFTER_DENEB_PRE_POST_FORKS])
@with_presets([MINIMAL], reason="churn limit update needs enough validators")
def test_higher_churn_limit_to_lower__without_block(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
"""
Test if churn limit goes from high to low due to EIP-7514.
"""
# Create high churn limit
mock_activations = post_spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT * spec.config.CHURN_LIMIT_QUOTIENT
mock_activated_validators(spec, state, mock_activations)

transition_until_fork(spec, state, fork_epoch)

churn_limit_0 = spec.get_validator_churn_limit(state)
assert churn_limit_0 > post_spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT

# check pre state
assert spec.get_current_epoch(state) < fork_epoch

yield "pre", state

# irregular state transition to handle fork
# set with_block=False here
state, _ = do_fork(state, spec, post_spec, fork_epoch, with_block=False)

# check post state
assert spec.get_current_epoch(state) == fork_epoch

yield "blocks", []
yield "post", state
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test format does not support this, see https://github.com/ethereum/consensus-specs/blob/dev/tests/formats/transition/README.md

post is "A SSZ-snappy encoded BeaconState according to the specification of the post fork, the state after running the block transitions"

Therefore, you need to add a block, as post is the last applied block's immediate post-state.

I guess the easiest fix is to add some more empty slots and then just add 1 more block to ensure that everything was processed correctly.


churn_limit_1 = post_spec.get_validator_activation_churn_limit(state)
assert churn_limit_1 == post_spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
assert churn_limit_1 < churn_limit_0
2 changes: 2 additions & 0 deletions tests/generators/transition/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
)
from eth2spec.test.deneb.transition import (
test_operations as test_deneb_operations,
test_transition as test_deneb_transition,
)


Expand Down Expand Up @@ -47,6 +48,7 @@ def cases_fn() -> Iterable[gen_typing.TestCase]:
test_altair_slashing,
test_altair_operations,
test_deneb_operations,
test_deneb_transition,
)
for transition_test_module in all_tests:
for pre_fork, post_fork in ALL_PRE_POST_FORKS:
Expand Down