PR feedback and add two more test cases
This commit is contained in:
parent
240209915c
commit
d04ecf16b1
|
@ -1,7 +1,7 @@
|
||||||
import random
|
import random
|
||||||
from eth2spec.test.context import fork_transition_test
|
from eth2spec.test.context import fork_transition_test
|
||||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||||
from eth2spec.test.helpers.state import state_transition_and_sign_block, next_slot
|
from eth2spec.test.helpers.state import state_transition_and_sign_block, next_slot, next_epoch_via_block
|
||||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block
|
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block
|
||||||
from eth2spec.test.helpers.attestations import next_slots_with_attestations
|
from eth2spec.test.helpers.attestations import next_slots_with_attestations
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ def _do_altair_fork(state, spec, post_spec, fork_epoch, with_block=True):
|
||||||
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.compute_epoch_at_slot(state.slot) == fork_epoch
|
assert spec.get_current_epoch(state) == fork_epoch
|
||||||
|
|
||||||
state = post_spec.upgrade_to_altair(state)
|
state = post_spec.upgrade_to_altair(state)
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ def test_normal_transition(state, fork_epoch, spec, post_spec, pre_tag, post_tag
|
||||||
])
|
])
|
||||||
|
|
||||||
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
||||||
assert post_spec.compute_epoch_at_slot(state.slot) == fork_epoch + 1
|
assert post_spec.get_current_epoch(state) == fork_epoch + 1
|
||||||
|
|
||||||
slots_with_blocks = [block.message.slot for block in blocks]
|
slots_with_blocks = [block.message.slot for block in blocks]
|
||||||
assert len(set(slots_with_blocks)) == len(slots_with_blocks)
|
assert len(set(slots_with_blocks)) == len(slots_with_blocks)
|
||||||
|
@ -150,7 +150,7 @@ def test_transition_missing_first_post_block(state, fork_epoch, spec, post_spec,
|
||||||
])
|
])
|
||||||
|
|
||||||
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
||||||
assert post_spec.compute_epoch_at_slot(state.slot) == fork_epoch + 1
|
assert post_spec.get_current_epoch(state) == fork_epoch + 1
|
||||||
|
|
||||||
slots_with_blocks = [block.message.slot for block in blocks]
|
slots_with_blocks = [block.message.slot for block in blocks]
|
||||||
assert len(set(slots_with_blocks)) == len(slots_with_blocks)
|
assert len(set(slots_with_blocks)) == len(slots_with_blocks)
|
||||||
|
@ -193,7 +193,7 @@ def test_transition_missing_last_pre_fork_block(state, fork_epoch, spec, post_sp
|
||||||
])
|
])
|
||||||
|
|
||||||
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
||||||
assert post_spec.compute_epoch_at_slot(state.slot) == fork_epoch + 1
|
assert post_spec.get_current_epoch(state) == fork_epoch + 1
|
||||||
|
|
||||||
slots_with_blocks = [block.message.slot for block in blocks]
|
slots_with_blocks = [block.message.slot for block in blocks]
|
||||||
assert len(set(slots_with_blocks)) == len(slots_with_blocks)
|
assert len(set(slots_with_blocks)) == len(slots_with_blocks)
|
||||||
|
@ -236,7 +236,7 @@ def test_transition_only_blocks_post_fork(state, fork_epoch, spec, post_spec, pr
|
||||||
])
|
])
|
||||||
|
|
||||||
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
||||||
assert post_spec.compute_epoch_at_slot(state.slot) == fork_epoch + 1
|
assert post_spec.get_current_epoch(state) == fork_epoch + 1
|
||||||
|
|
||||||
slots_with_blocks = [block.message.slot for block in blocks]
|
slots_with_blocks = [block.message.slot for block in blocks]
|
||||||
assert len(slots_with_blocks) == 1
|
assert len(slots_with_blocks) == 1
|
||||||
|
@ -246,82 +246,101 @@ def test_transition_only_blocks_post_fork(state, fork_epoch, spec, post_spec, pr
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
|
def _run_transition_test_with_attestations(state,
|
||||||
|
fork_epoch,
|
||||||
|
spec,
|
||||||
|
post_spec,
|
||||||
|
pre_tag,
|
||||||
|
post_tag,
|
||||||
|
participation_fn=None,
|
||||||
|
expect_finality=True):
|
||||||
|
yield "pre", state
|
||||||
|
|
||||||
|
current_epoch = spec.get_current_epoch(state)
|
||||||
|
assert current_epoch < fork_epoch
|
||||||
|
assert current_epoch == spec.GENESIS_EPOCH
|
||||||
|
|
||||||
|
# skip genesis epoch to avoid dealing with some edge cases...
|
||||||
|
block = next_epoch_via_block(spec, state)
|
||||||
|
|
||||||
|
# regular state transition until fork:
|
||||||
|
fill_cur_epoch = False
|
||||||
|
fill_prev_epoch = True
|
||||||
|
blocks = [pre_tag(sign_block(spec, state, block))]
|
||||||
|
current_epoch = spec.get_current_epoch(state)
|
||||||
|
for _ in range(current_epoch, fork_epoch - 1):
|
||||||
|
_, blocks_in_epoch, state = next_slots_with_attestations(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
spec.SLOTS_PER_EPOCH,
|
||||||
|
fill_cur_epoch,
|
||||||
|
fill_prev_epoch,
|
||||||
|
participation_fn=participation_fn,
|
||||||
|
)
|
||||||
|
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
||||||
|
|
||||||
|
_, blocks_in_epoch, state = next_slots_with_attestations(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
spec.SLOTS_PER_EPOCH - 1,
|
||||||
|
fill_cur_epoch,
|
||||||
|
fill_prev_epoch,
|
||||||
|
participation_fn=participation_fn,
|
||||||
|
)
|
||||||
|
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
||||||
|
assert spec.get_current_epoch(state) == fork_epoch - 1
|
||||||
|
assert (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0
|
||||||
|
|
||||||
|
# irregular state transition to handle fork:
|
||||||
|
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
|
||||||
|
for _ in range(4):
|
||||||
|
_, blocks_in_epoch, state = next_slots_with_attestations(
|
||||||
|
post_spec,
|
||||||
|
state,
|
||||||
|
post_spec.SLOTS_PER_EPOCH,
|
||||||
|
fill_cur_epoch,
|
||||||
|
fill_prev_epoch,
|
||||||
|
participation_fn=participation_fn,
|
||||||
|
)
|
||||||
|
blocks.extend([post_tag(block) for block in blocks_in_epoch])
|
||||||
|
|
||||||
|
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
||||||
|
assert post_spec.get_current_epoch(state) == fork_epoch + 4
|
||||||
|
|
||||||
|
if expect_finality:
|
||||||
|
assert state.current_justified_checkpoint.epoch == fork_epoch + 2
|
||||||
|
assert state.finalized_checkpoint.epoch == fork_epoch
|
||||||
|
else:
|
||||||
|
assert state.current_justified_checkpoint.epoch == spec.GENESIS_EPOCH
|
||||||
|
assert state.finalized_checkpoint.epoch == spec.GENESIS_EPOCH
|
||||||
|
|
||||||
|
assert len(blocks) == (fork_epoch + 3) * post_spec.SLOTS_PER_EPOCH + 1
|
||||||
|
assert len(blocks) == len(set(blocks))
|
||||||
|
|
||||||
|
blocks_without_attestations = [block for block in blocks if len(block.message.body.attestations) == 0]
|
||||||
|
assert len(blocks_without_attestations) == 2
|
||||||
|
slots_without_attestations = [b.message.slot for b in blocks_without_attestations]
|
||||||
|
|
||||||
|
assert set(slots_without_attestations) == set([spec.SLOTS_PER_EPOCH, fork_epoch * spec.SLOTS_PER_EPOCH])
|
||||||
|
|
||||||
|
yield "blocks", blocks
|
||||||
|
yield "post", state
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
||||||
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``,
|
||||||
including attestations so as to produce finality through the fork boundary.
|
including attestations so as to produce finality through the fork boundary.
|
||||||
"""
|
"""
|
||||||
yield "pre", state
|
yield from _run_transition_test_with_attestations(state, fork_epoch, spec, post_spec, pre_tag, post_tag)
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
|
||||||
assert current_epoch < fork_epoch
|
|
||||||
assert current_epoch == spec.GENESIS_EPOCH
|
|
||||||
|
|
||||||
# regular state transition until fork:
|
|
||||||
fill_cur_epoch = False
|
|
||||||
fill_prev_epoch = True
|
|
||||||
blocks = []
|
|
||||||
for _ in range(current_epoch, fork_epoch - 1):
|
|
||||||
if current_epoch == spec.GENESIS_EPOCH:
|
|
||||||
fill_cur_epoch = True
|
|
||||||
fill_prev_epoch = False
|
|
||||||
|
|
||||||
_, blocks_in_epoch, state = next_slots_with_attestations(spec,
|
|
||||||
state,
|
|
||||||
spec.SLOTS_PER_EPOCH,
|
|
||||||
fill_cur_epoch,
|
|
||||||
fill_prev_epoch)
|
|
||||||
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
|
||||||
if current_epoch == spec.GENESIS_EPOCH:
|
|
||||||
fill_cur_epoch = False
|
|
||||||
fill_prev_epoch = True
|
|
||||||
|
|
||||||
_, blocks_in_epoch, state = next_slots_with_attestations(spec,
|
|
||||||
state,
|
|
||||||
spec.SLOTS_PER_EPOCH - 1,
|
|
||||||
fill_cur_epoch,
|
|
||||||
fill_prev_epoch)
|
|
||||||
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
|
||||||
assert spec.get_current_epoch(state) == fork_epoch - 1
|
|
||||||
assert (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0
|
|
||||||
|
|
||||||
# irregular state transition to handle fork:
|
|
||||||
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
|
|
||||||
for _ in range(4):
|
|
||||||
_, blocks_in_epoch, state = next_slots_with_attestations(post_spec,
|
|
||||||
state,
|
|
||||||
post_spec.SLOTS_PER_EPOCH,
|
|
||||||
fill_cur_epoch,
|
|
||||||
fill_prev_epoch)
|
|
||||||
blocks.extend([post_tag(block) for block in blocks_in_epoch])
|
|
||||||
|
|
||||||
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
|
||||||
assert post_spec.compute_epoch_at_slot(state.slot) == fork_epoch + 4
|
|
||||||
|
|
||||||
assert state.current_justified_checkpoint.epoch == fork_epoch + 2
|
|
||||||
assert state.finalized_checkpoint.epoch == fork_epoch
|
|
||||||
|
|
||||||
assert len(blocks) == (fork_epoch + 4) * post_spec.SLOTS_PER_EPOCH
|
|
||||||
assert len(blocks) == len(set(blocks))
|
|
||||||
|
|
||||||
blocks_without_attestations = [block for block in blocks if len(block.message.body.attestations) == 0]
|
|
||||||
# A boundary condition of ``next_slots_with_attestations`` skips
|
|
||||||
# over the block with ``slot == 1``.
|
|
||||||
# And the fork upgrade helper currently does not construct any attestations.
|
|
||||||
assert len(blocks_without_attestations) == 2
|
|
||||||
slots_without_attestations = [b.message.slot for b in blocks_without_attestations]
|
|
||||||
assert set(slots_without_attestations) == set([1, fork_epoch * spec.SLOTS_PER_EPOCH])
|
|
||||||
|
|
||||||
yield "blocks", blocks
|
|
||||||
yield "post", state
|
|
||||||
|
|
||||||
|
|
||||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
||||||
def test_transition_with_random_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``,
|
||||||
including attestations so as to produce finality through the fork boundary.
|
including attestations so as to produce finality through the fork boundary.
|
||||||
|
@ -332,76 +351,86 @@ def test_transition_with_random_participation(state, fork_epoch, spec, post_spec
|
||||||
# still finalize, but drop some attestations
|
# still finalize, but drop some attestations
|
||||||
committee_len = len(indices)
|
committee_len = len(indices)
|
||||||
assert committee_len >= 4
|
assert committee_len >= 4
|
||||||
one_quarter_len = committee_len // 4
|
filter_len = committee_len // 4
|
||||||
participant_count = committee_len - one_quarter_len
|
participant_count = committee_len - filter_len
|
||||||
return rng.sample(indices, participant_count)
|
return rng.sample(indices, participant_count)
|
||||||
|
|
||||||
|
yield from _run_transition_test_with_attestations(
|
||||||
|
state,
|
||||||
|
fork_epoch,
|
||||||
|
spec,
|
||||||
|
post_spec,
|
||||||
|
pre_tag,
|
||||||
|
post_tag,
|
||||||
|
participation_fn=_drop_random_quarter
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=3)
|
||||||
|
def test_transition_with_random_half_participation(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||||
|
rng = random.Random(2020)
|
||||||
|
|
||||||
|
def _drop_random_half(_slot, _index, indices):
|
||||||
|
# still finalize, but drop some attestations
|
||||||
|
committee_len = len(indices)
|
||||||
|
assert committee_len >= 2
|
||||||
|
filter_len = committee_len // 2
|
||||||
|
participant_count = committee_len - filter_len
|
||||||
|
return rng.sample(indices, participant_count)
|
||||||
|
|
||||||
|
yield from _run_transition_test_with_attestations(
|
||||||
|
state,
|
||||||
|
fork_epoch,
|
||||||
|
spec,
|
||||||
|
post_spec,
|
||||||
|
pre_tag,
|
||||||
|
post_tag,
|
||||||
|
participation_fn=_drop_random_half,
|
||||||
|
expect_finality=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
||||||
|
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,
|
||||||
|
then transition forward with enough attestations to finalize the fork epoch.
|
||||||
|
"""
|
||||||
yield "pre", state
|
yield "pre", state
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
assert spec.get_current_epoch(state) < fork_epoch
|
||||||
assert current_epoch < fork_epoch
|
|
||||||
assert current_epoch == spec.GENESIS_EPOCH
|
|
||||||
|
|
||||||
# regular state transition until fork:
|
# regular state transition until fork:
|
||||||
fill_cur_epoch = False
|
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||||
fill_prev_epoch = True
|
|
||||||
blocks = []
|
blocks = []
|
||||||
for _ in range(current_epoch, fork_epoch - 1):
|
blocks.extend([
|
||||||
if current_epoch == spec.GENESIS_EPOCH:
|
pre_tag(block) for block in
|
||||||
fill_cur_epoch = True
|
_state_transition_across_slots(spec, state, to_slot)
|
||||||
fill_prev_epoch = False
|
])
|
||||||
|
|
||||||
_, blocks_in_epoch, state = next_slots_with_attestations(spec,
|
|
||||||
state,
|
|
||||||
spec.SLOTS_PER_EPOCH,
|
|
||||||
fill_cur_epoch,
|
|
||||||
fill_prev_epoch,
|
|
||||||
participation_fn=_drop_random_quarter)
|
|
||||||
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
|
||||||
if current_epoch == spec.GENESIS_EPOCH:
|
|
||||||
fill_cur_epoch = False
|
|
||||||
fill_prev_epoch = True
|
|
||||||
|
|
||||||
_, blocks_in_epoch, state = next_slots_with_attestations(spec,
|
|
||||||
state,
|
|
||||||
spec.SLOTS_PER_EPOCH - 1,
|
|
||||||
fill_cur_epoch,
|
|
||||||
fill_prev_epoch,
|
|
||||||
participation_fn=_drop_random_quarter)
|
|
||||||
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
|
||||||
assert spec.get_current_epoch(state) == fork_epoch - 1
|
|
||||||
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_altair_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 but add attestations
|
||||||
|
# for enough epochs to finalize the ``fork_epoch``
|
||||||
|
block = next_epoch_via_block(post_spec, state)
|
||||||
|
blocks.append(post_tag(sign_block(post_spec, state, block)))
|
||||||
for _ in range(4):
|
for _ in range(4):
|
||||||
_, blocks_in_epoch, state = next_slots_with_attestations(post_spec,
|
_, blocks_in_epoch, state = next_slots_with_attestations(
|
||||||
state,
|
post_spec,
|
||||||
post_spec.SLOTS_PER_EPOCH,
|
state,
|
||||||
fill_cur_epoch,
|
post_spec.SLOTS_PER_EPOCH,
|
||||||
fill_prev_epoch,
|
False,
|
||||||
participation_fn=_drop_random_quarter)
|
True,
|
||||||
|
)
|
||||||
blocks.extend([post_tag(block) for block in blocks_in_epoch])
|
blocks.extend([post_tag(block) for block in blocks_in_epoch])
|
||||||
|
|
||||||
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
assert state.slot % post_spec.SLOTS_PER_EPOCH == 0
|
||||||
assert post_spec.compute_epoch_at_slot(state.slot) == fork_epoch + 4
|
assert post_spec.get_current_epoch(state) == fork_epoch + 5
|
||||||
|
|
||||||
assert state.current_justified_checkpoint.epoch == fork_epoch + 2
|
assert state.current_justified_checkpoint.epoch == fork_epoch + 3
|
||||||
assert state.finalized_checkpoint.epoch == fork_epoch
|
assert state.finalized_checkpoint.epoch == fork_epoch + 1
|
||||||
|
|
||||||
assert len(blocks) == (fork_epoch + 4) * post_spec.SLOTS_PER_EPOCH
|
|
||||||
assert len(blocks) == len(set(blocks))
|
|
||||||
|
|
||||||
blocks_without_attestations = [block for block in blocks if len(block.message.body.attestations) == 0]
|
|
||||||
# A boundary condition of ``next_slots_with_attestations`` skips
|
|
||||||
# over the block with ``slot == 1``.
|
|
||||||
# And the fork upgrade helper currently does not construct any attestations.
|
|
||||||
assert len(blocks_without_attestations) == 2
|
|
||||||
slots_without_attestations = [b.message.slot for b in blocks_without_attestations]
|
|
||||||
assert set(slots_without_attestations) == set([1, fork_epoch * spec.SLOTS_PER_EPOCH])
|
|
||||||
|
|
||||||
yield "blocks", blocks
|
yield "blocks", blocks
|
||||||
yield "post", state
|
yield "post", state
|
||||||
|
|
Loading…
Reference in New Issue