[WIP] Add new transition tests
This commit is contained in:
parent
aa592b008c
commit
4dd8b7c98a
|
@ -1,7 +1,11 @@
|
|||
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,
|
||||
slash_some_validators_for_inactivity_scores_test,
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch,
|
||||
next_epoch_via_block,
|
||||
|
@ -201,20 +205,6 @@ def test_random_inactivity_scores_full_participation_leaking(spec, state):
|
|||
assert spec.is_in_inactivity_leak(state)
|
||||
|
||||
|
||||
def slash_some_validators_for_inactivity_scores_test(spec, state, rng=Random(40404040)):
|
||||
# ``run_inactivity_scores_test`` runs at the next epoch from `state`.
|
||||
# We retrieve the proposer of this future state to avoid
|
||||
# accidentally slashing that validator
|
||||
future_state = state.copy()
|
||||
next_epoch_via_block(spec, future_state)
|
||||
|
||||
proposer_index = spec.get_beacon_proposer_index(future_state)
|
||||
# Slash ~1/4 of validaors
|
||||
for validator_index in range(len(state.validators)):
|
||||
if rng.choice(range(4)) == 0 and validator_index != proposer_index:
|
||||
spec.slash_validator(state, validator_index)
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_some_slashed_zero_scores_full_participation(spec, state):
|
||||
|
|
|
@ -1,12 +1,24 @@
|
|||
import random
|
||||
from eth2spec.test.context import fork_transition_test
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.test.helpers.state import state_transition_and_sign_block, next_slot, next_epoch_via_signed_block
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch_via_signed_block,
|
||||
next_slot,
|
||||
state_transition_and_sign_block,
|
||||
transition_to,
|
||||
)
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block
|
||||
from eth2spec.test.helpers.deposits import (
|
||||
prepare_state_and_deposit,
|
||||
)
|
||||
from eth2spec.test.helpers.attestations import next_slots_with_attestations
|
||||
from eth2spec.test.helpers.random import set_some_new_deposits
|
||||
from eth2spec.test.helpers.inactivity_scores import (
|
||||
slash_some_validators_for_inactivity_scores_test,
|
||||
)
|
||||
|
||||
|
||||
def _state_transition_and_sign_block_at_slot(spec, state):
|
||||
def _state_transition_and_sign_block_at_slot(spec, state, deposits=None):
|
||||
"""
|
||||
Cribbed from ``transition_unsigned_block`` helper
|
||||
where the early parts of the state transition have already
|
||||
|
@ -15,6 +27,9 @@ def _state_transition_and_sign_block_at_slot(spec, state):
|
|||
Used to produce a block during an irregular state transition.
|
||||
"""
|
||||
block = build_empty_block(spec, state)
|
||||
# FIXME: not just passing `deposits`
|
||||
if deposits is not None:
|
||||
block.body.deposits = deposits
|
||||
|
||||
assert state.latest_block_header.slot < block.slot
|
||||
assert state.slot == block.slot
|
||||
|
@ -62,7 +77,29 @@ def _state_transition_across_slots(spec, state, to_slot, block_filter=_all_block
|
|||
next_slot(spec, state)
|
||||
|
||||
|
||||
def _do_altair_fork(state, spec, post_spec, fork_epoch, with_block=True):
|
||||
def _state_transition_across_slots_with_ignoring_proposers(spec, state, to_slot, ignoring_proposers):
|
||||
"""
|
||||
The slashed validators can't be proposers. Here we ignore the given `ignoring_proposers`
|
||||
and ensure that the result state was computed with a block with slot >= to_slot.
|
||||
"""
|
||||
assert state.slot < to_slot
|
||||
|
||||
found_valid = False
|
||||
while state.slot < to_slot or not found_valid:
|
||||
future_state = state.copy()
|
||||
next_slot(spec, future_state)
|
||||
proposer_index = spec.get_beacon_proposer_index(future_state)
|
||||
if proposer_index not in ignoring_proposers:
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
yield signed_block
|
||||
if state.slot >= to_slot:
|
||||
found_valid = True
|
||||
else:
|
||||
next_slot(spec, state)
|
||||
|
||||
|
||||
def _do_altair_fork(state, spec, post_spec, fork_epoch, with_block=True, deposits=None):
|
||||
spec.process_slots(state, state.slot + 1)
|
||||
|
||||
assert state.slot % spec.SLOTS_PER_EPOCH == 0
|
||||
|
@ -75,11 +112,25 @@ def _do_altair_fork(state, spec, post_spec, fork_epoch, with_block=True):
|
|||
assert state.fork.current_version == post_spec.config.ALTAIR_FORK_VERSION
|
||||
|
||||
if with_block:
|
||||
return state, _state_transition_and_sign_block_at_slot(post_spec, state)
|
||||
return state, _state_transition_and_sign_block_at_slot(post_spec, state, deposits=deposits)
|
||||
else:
|
||||
return state, None
|
||||
|
||||
|
||||
def _set_validators_exit_epoch(spec, state, exit_epoch, rng=random.Random(40404040), fraction=0.25):
|
||||
"""
|
||||
Set some valdiators' exit_epoch.
|
||||
"""
|
||||
selected_count = int(len(state.validators) * fraction)
|
||||
selected_indices = rng.sample(range(len(state.validators)), selected_count)
|
||||
for validator_index in selected_indices:
|
||||
state.validators[validator_index].exit_epoch = exit_epoch
|
||||
state.validators[validator_index].withdrawable_epoch = (
|
||||
exit_epoch + spec.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
||||
)
|
||||
return selected_indices
|
||||
|
||||
|
||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=2)
|
||||
def test_normal_transition(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
|
@ -434,3 +485,353 @@ def test_transition_with_no_attestations_until_after_fork(state, fork_epoch, spe
|
|||
|
||||
yield "blocks", blocks
|
||||
yield "post", state
|
||||
|
||||
|
||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=1)
|
||||
def test_transition_with_one_fourth_slashed_active_validators_pre_fork(
|
||||
state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
1/4 validators are slashed but still active at the fork transition.
|
||||
"""
|
||||
# slash 1/4 validators
|
||||
selected_indices = slash_some_validators_for_inactivity_scores_test(
|
||||
spec, state, rng=random.Random(5566), fraction=0.25)
|
||||
assert len(selected_indices) > 0
|
||||
|
||||
# check if some validators are slashed but still active
|
||||
for validator_index in selected_indices:
|
||||
validator = state.validators[validator_index]
|
||||
assert validator.slashed
|
||||
assert spec.is_active_validator(validator, spec.get_current_epoch(state))
|
||||
assert not spec.is_in_inactivity_leak(state)
|
||||
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
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))
|
||||
|
||||
# continue regular state transition with new spec into next epoch
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
# since the proposer might have been slashed, here we only create blocks with non-slashed proposers
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots_with_ignoring_proposers(post_spec, state, to_slot, selected_indices)
|
||||
])
|
||||
|
||||
# check post state
|
||||
for validator in state.validators:
|
||||
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_post_fork(
|
||||
state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
1/4 exiting but still active validators at the fork transition.
|
||||
"""
|
||||
exited_indices = _set_validators_exit_epoch(spec, state, exit_epoch=10, rng=random.Random(5566), fraction=0.25)
|
||||
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
# 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)))
|
||||
|
||||
# continue regular state transition with new spec into next epoch
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
# 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 exiting but still active validators at the fork transition.
|
||||
"""
|
||||
exited_indices = _set_validators_exit_epoch(spec, state, exit_epoch=2, rng=random.Random(5566), fraction=0.25)
|
||||
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
# 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
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
yield "blocks", blocks
|
||||
yield "post", state
|
||||
|
||||
|
||||
@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.
|
||||
"""
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
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
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
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.
|
||||
"""
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
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
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
yield "blocks", blocks
|
||||
yield "post", state
|
||||
|
||||
|
||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=5)
|
||||
def test_transition_with_leaking_post_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 after the fork transition in this case.
|
||||
"""
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
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 not spec.is_in_inactivity_leak(state)
|
||||
|
||||
# continue regular state transition with new spec into next epoch
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
# check state again
|
||||
assert spec.is_in_inactivity_leak(state)
|
||||
|
||||
yield "blocks", blocks
|
||||
yield "post", state
|
||||
|
||||
|
||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=10)
|
||||
def test_transition_with_non_empty_activation_queue(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
Create some deposits before the transition
|
||||
"""
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
_, queuing_indices = set_some_new_deposits(spec, state, rng=random.Random(5566))
|
||||
|
||||
assert spec.get_current_epoch(state) < fork_epoch
|
||||
assert len(queuing_indices) > 0
|
||||
for validator_index in queuing_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
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
yield "blocks", blocks
|
||||
yield "post", state
|
||||
|
||||
|
||||
@fork_transition_test(PHASE0, ALTAIR, fork_epoch=10)
|
||||
def test_transition_with_deposit_at_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
Create a deposit at the transition
|
||||
"""
|
||||
# regular state transition until fork:
|
||||
to_slot = fork_epoch * spec.SLOTS_PER_EPOCH - 1
|
||||
transition_to(spec, state, to_slot)
|
||||
|
||||
yield "pre", state
|
||||
|
||||
# create a new deposit
|
||||
validator_index = len(state.validators)
|
||||
amount = post_spec.MAX_EFFECTIVE_BALANCE
|
||||
deposit = prepare_state_and_deposit(post_spec, state, validator_index, amount, signed=True)
|
||||
|
||||
# irregular state transition to handle fork:
|
||||
state, block = _do_altair_fork(state, spec, post_spec, fork_epoch, deposits=[deposit])
|
||||
blocks = []
|
||||
blocks.append(post_tag(block))
|
||||
|
||||
assert not post_spec.is_active_validator(state.validators[validator_index], post_spec.get_current_epoch(state))
|
||||
|
||||
# continue regular state transition with new spec into next epoch
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
# finalize activation_eligibility_epoch
|
||||
_, blocks_in_epoch, state = next_slots_with_attestations(
|
||||
post_spec,
|
||||
state,
|
||||
spec.SLOTS_PER_EPOCH * 2,
|
||||
fill_cur_epoch=True,
|
||||
fill_prev_epoch=True,
|
||||
)
|
||||
blocks.extend([pre_tag(block) for block in blocks_in_epoch])
|
||||
assert state.finalized_checkpoint.epoch == state.validators[validator_index].activation_eligibility_epoch
|
||||
|
||||
# continue regular state transition with new spec into next epoch
|
||||
to_slot = post_spec.SLOTS_PER_EPOCH + state.slot
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
|
||||
assert state.validators[validator_index].activation_epoch < post_spec.FAR_FUTURE_EPOCH
|
||||
|
||||
to_slot = state.validators[validator_index].activation_epoch * post_spec.SLOTS_PER_EPOCH
|
||||
blocks.extend([
|
||||
post_tag(block) for block in
|
||||
_state_transition_across_slots(post_spec, state, to_slot)
|
||||
])
|
||||
assert post_spec.is_active_validator(state.validators[validator_index], post_spec.get_current_epoch(state))
|
||||
|
||||
yield "blocks", blocks
|
||||
yield "post", state
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
from random import Random
|
||||
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch_via_block,
|
||||
)
|
||||
|
||||
|
||||
def randomize_inactivity_scores(spec, state, minimum=0, maximum=50000, rng=Random(4242)):
|
||||
state.inactivity_scores = [rng.randint(minimum, maximum) for _ in range(len(state.validators))]
|
||||
|
@ -7,3 +11,22 @@ def randomize_inactivity_scores(spec, state, minimum=0, maximum=50000, rng=Rando
|
|||
|
||||
def zero_inactivity_scores(spec, state, rng=None):
|
||||
state.inactivity_scores = [0] * len(state.validators)
|
||||
|
||||
|
||||
def slash_some_validators_for_inactivity_scores_test(spec, state, rng=Random(40404040), fraction=0.25):
|
||||
"""
|
||||
``run_inactivity_scores_test`` runs at the next epoch from `state`.
|
||||
# We retrieve the proposer of this future state to avoid
|
||||
# accidentally slashing that validator
|
||||
"""
|
||||
future_state = state.copy()
|
||||
next_epoch_via_block(spec, future_state)
|
||||
proposer_index = spec.get_beacon_proposer_index(future_state)
|
||||
selected_count = int(len(state.validators) * fraction)
|
||||
selected_indices = rng.sample(range(len(state.validators)), selected_count)
|
||||
if proposer_index in selected_indices:
|
||||
selected_indices.remove(proposer_index)
|
||||
for validator_index in selected_indices:
|
||||
spec.slash_validator(state, validator_index)
|
||||
|
||||
return selected_indices
|
||||
|
|
|
@ -7,6 +7,7 @@ from eth2spec.test.helpers.state import next_epoch
|
|||
|
||||
|
||||
def set_some_new_deposits(spec, state, rng):
|
||||
eligible_indices = queuing_indices = []
|
||||
num_validators = len(state.validators)
|
||||
# Set ~1/10 to just recently deposited
|
||||
for index in range(num_validators):
|
||||
|
@ -18,6 +19,10 @@ def set_some_new_deposits(spec, state, rng):
|
|||
# Set ~half of selected to eligible for activation
|
||||
if rng.choice([True, False]):
|
||||
state.validators[index].activation_eligibility_epoch = spec.get_current_epoch(state)
|
||||
eligible_indices.append(index)
|
||||
else:
|
||||
queuing_indices.append(index)
|
||||
return eligible_indices, queuing_indices
|
||||
|
||||
|
||||
def exit_random_validators(spec, state, rng, fraction=None):
|
||||
|
|
Loading…
Reference in New Issue