extend inactivity updates tests
This commit is contained in:
parent
153e1b34dd
commit
48382ce09c
|
@ -1,26 +1,20 @@
|
||||||
from random import Random
|
from random import Random
|
||||||
|
|
||||||
from eth2spec.test.context import spec_state_test, with_altair_and_later
|
from eth2spec.test.context import spec_state_test, with_altair_and_later
|
||||||
from eth2spec.test.helpers.inactivity_scores import randomize_inactivity_scores
|
from eth2spec.test.helpers.inactivity_scores import randomize_inactivity_scores, zero_inactivity_scores
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
next_epoch_via_block,
|
next_epoch_via_block,
|
||||||
|
set_full_participation, set_full_participation_previous_epoch,
|
||||||
|
set_empty_participation,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.epoch_processing import (
|
from eth2spec.test.helpers.epoch_processing import (
|
||||||
run_epoch_processing_with
|
run_epoch_processing_with
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.random import (
|
from eth2spec.test.helpers.random import (
|
||||||
randomize_attestation_participation,
|
randomize_attestation_participation,
|
||||||
|
randomize_previous_epoch_participation,
|
||||||
)
|
)
|
||||||
|
from eth2spec.test.helpers.rewards import leaking
|
||||||
|
|
||||||
def set_full_participation(spec, state):
|
|
||||||
full_flags = spec.ParticipationFlags(0)
|
|
||||||
for flag_index in range(len(spec.PARTICIPATION_FLAG_WEIGHTS)):
|
|
||||||
full_flags = spec.add_flag(full_flags, flag_index)
|
|
||||||
|
|
||||||
for index in range(len(state.validators)):
|
|
||||||
state.current_epoch_participation[index] = full_flags
|
|
||||||
state.previous_epoch_participation[index] = full_flags
|
|
||||||
|
|
||||||
|
|
||||||
def run_process_inactivity_updates(spec, state):
|
def run_process_inactivity_updates(spec, state):
|
||||||
|
@ -33,58 +27,169 @@ def test_genesis(spec, state):
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
yield from run_process_inactivity_updates(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_genesis_random_scores(spec, state):
|
||||||
|
rng = Random(10102)
|
||||||
|
state.inactivity_scores = [rng.randint(0, 100) for _ in state.inactivity_scores]
|
||||||
|
pre_scores = state.inactivity_scores.copy()
|
||||||
|
|
||||||
|
yield from run_process_inactivity_updates(spec, state)
|
||||||
|
|
||||||
|
assert state.inactivity_scores == pre_scores
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Genesis epoch processing is skipped
|
# Genesis epoch processing is skipped
|
||||||
# Thus all of following tests all go past genesis epoch to test core functionality
|
# Thus all of following tests all go past genesis epoch to test core functionality
|
||||||
#
|
#
|
||||||
|
|
||||||
|
def run_inactivity_scores_test(spec, state, participation_fn=None, inactivity_scores_fn=None, rng=Random(10101)):
|
||||||
|
next_epoch_via_block(spec, state)
|
||||||
|
if participation_fn is not None:
|
||||||
|
participation_fn(spec, state, rng=rng)
|
||||||
|
if inactivity_scores_fn is not None:
|
||||||
|
inactivity_scores_fn(spec, state, rng=rng)
|
||||||
|
yield from run_process_inactivity_updates(spec, state)
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_all_zero_inactivity_scores_empty_participation(spec, state):
|
def test_all_zero_inactivity_scores_empty_participation(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
yield from run_inactivity_scores_test(spec, state, set_empty_participation, zero_inactivity_scores)
|
||||||
state.inactivity_scores = [0] * len(state.validators)
|
assert set(state.inactivity_scores) == set([0])
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_all_zero_inactivity_scores_empty_participation_leaking(spec, state):
|
||||||
|
yield from run_inactivity_scores_test(spec, state, set_empty_participation, zero_inactivity_scores)
|
||||||
|
|
||||||
|
# Should still in be leak
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
for score in state.inactivity_scores:
|
||||||
|
assert score > 0
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_all_zero_inactivity_scores_random_participation(spec, state):
|
def test_all_zero_inactivity_scores_random_participation(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
yield from run_inactivity_scores_test(
|
||||||
state.inactivity_scores = [0] * len(state.validators)
|
spec, state,
|
||||||
randomize_attestation_participation(spec, state, rng=Random(5555))
|
randomize_attestation_participation, zero_inactivity_scores, rng=Random(5555),
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
)
|
||||||
|
assert set(state.inactivity_scores) == set([0])
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_all_zero_inactivity_scores_random_participation_leaking(spec, state):
|
||||||
|
# Only randompize participation in previous epoch to remain in leak
|
||||||
|
yield from run_inactivity_scores_test(
|
||||||
|
spec, state,
|
||||||
|
randomize_previous_epoch_participation, zero_inactivity_scores, rng=Random(5555),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check still in leak
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
assert 0 in state.inactivity_scores
|
||||||
|
assert len(set(state.inactivity_scores)) > 1
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_all_zero_inactivity_scores_full_participation(spec, state):
|
def test_all_zero_inactivity_scores_full_participation(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
yield from run_inactivity_scores_test(
|
||||||
set_full_participation(spec, state)
|
spec, state,
|
||||||
state.inactivity_scores = [0] * len(state.validators)
|
set_full_participation, zero_inactivity_scores,
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
)
|
||||||
|
|
||||||
|
assert set(state.inactivity_scores) == set([0])
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_all_zero_inactivity_scores_full_participation_leaking(spec, state):
|
||||||
|
# Only set full participation in previous epoch to remain in leak
|
||||||
|
yield from run_inactivity_scores_test(
|
||||||
|
spec, state,
|
||||||
|
set_full_participation_previous_epoch, zero_inactivity_scores,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check still in leak
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
assert set(state.inactivity_scores) == set([0])
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_random_inactivity_scores_empty_participation(spec, state):
|
def test_random_inactivity_scores_empty_participation(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
yield from run_inactivity_scores_test(
|
||||||
randomize_inactivity_scores(spec, state, rng=Random(9999))
|
spec, state,
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
set_empty_participation, randomize_inactivity_scores, Random(9999),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_random_inactivity_scores_empty_participation_leaking(spec, state):
|
||||||
|
yield from run_inactivity_scores_test(
|
||||||
|
spec, state,
|
||||||
|
set_empty_participation, randomize_inactivity_scores, Random(9999),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check still in leak
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_random_inactivity_scores_random_participation(spec, state):
|
def test_random_inactivity_scores_random_participation(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
yield from run_inactivity_scores_test(
|
||||||
randomize_attestation_participation(spec, state, rng=Random(22222))
|
spec, state,
|
||||||
randomize_inactivity_scores(spec, state, rng=Random(22222))
|
randomize_attestation_participation, randomize_inactivity_scores, Random(22222),
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_random_inactivity_scores_random_participation_leaking(spec, state):
|
||||||
|
# Only randompize participation in previous epoch to remain in leak
|
||||||
|
yield from run_inactivity_scores_test(
|
||||||
|
spec, state,
|
||||||
|
randomize_previous_epoch_participation, randomize_inactivity_scores, Random(22222),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check still in leak
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_random_inactivity_scores_full_participation(spec, state):
|
def test_random_inactivity_scores_full_participation(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
yield from run_inactivity_scores_test(
|
||||||
set_full_participation(spec, state)
|
spec, state,
|
||||||
randomize_inactivity_scores(spec, state, rng=Random(33333))
|
set_full_participation, randomize_inactivity_scores, Random(33333),
|
||||||
yield from run_process_inactivity_updates(spec, state)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_random_inactivity_scores_full_participation_leaking(spec, state):
|
||||||
|
# Only set full participation in previous epoch to remain in leak
|
||||||
|
yield from run_inactivity_scores_test(
|
||||||
|
spec, state,
|
||||||
|
set_full_participation_previous_epoch, randomize_inactivity_scores, Random(33333),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check still in leak
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
|
@ -112,7 +112,7 @@ def test_random_high_inactivity_scores_leaking(spec, state):
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
@leaking(epochs=5)
|
@leaking(epochs=8)
|
||||||
def test_random_high_inactivity_scores_leaking_5_epochs(spec, state):
|
def test_random_high_inactivity_scores_leaking_8_epochs(spec, state):
|
||||||
randomize_inactivity_scores(spec, state, minimum=500000, maximum=5000000, rng=Random(9998))
|
randomize_inactivity_scores(spec, state, minimum=500000, maximum=5000000, rng=Random(9998))
|
||||||
yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(9998))
|
yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(9998))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import random
|
from random import Random
|
||||||
|
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
state_transition_and_sign_block,
|
state_transition_and_sign_block,
|
||||||
next_epoch,
|
next_epoch,
|
||||||
next_epoch_via_block,
|
set_full_participation_previous_epoch,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.block import (
|
from eth2spec.test.helpers.block import (
|
||||||
build_empty_block_for_next_slot,
|
build_empty_block_for_next_slot,
|
||||||
|
@ -15,12 +16,14 @@ from eth2spec.test.context import (
|
||||||
with_altair_and_later,
|
with_altair_and_later,
|
||||||
spec_state_test,
|
spec_state_test,
|
||||||
)
|
)
|
||||||
|
from eth2spec.test.helpers.rewards import leaking
|
||||||
|
from eth2spec.test.helpers.inactivity_scores import randomize_inactivity_scores
|
||||||
|
|
||||||
|
|
||||||
def run_sync_committee_sanity_test(spec, state, fraction_full=1.0):
|
def run_sync_committee_sanity_test(spec, state, fraction_full=1.0, rng=Random(454545)):
|
||||||
all_pubkeys = [v.pubkey for v in state.validators]
|
all_pubkeys = [v.pubkey for v in state.validators]
|
||||||
committee = [all_pubkeys.index(pubkey) for pubkey in state.current_sync_committee.pubkeys]
|
committee = [all_pubkeys.index(pubkey) for pubkey in state.current_sync_committee.pubkeys]
|
||||||
participants = random.sample(committee, int(len(committee) * fraction_full))
|
participants = rng.sample(committee, int(len(committee) * fraction_full))
|
||||||
|
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ def test_full_sync_committee_committee(spec, state):
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_half_sync_committee_committee(spec, state):
|
def test_half_sync_committee_committee(spec, state):
|
||||||
next_epoch(spec, state)
|
next_epoch(spec, state)
|
||||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5)
|
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5, rng=Random(1212))
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
|
@ -70,7 +73,7 @@ def test_full_sync_committee_committee_genesis(spec, state):
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_half_sync_committee_committee_genesis(spec, state):
|
def test_half_sync_committee_committee_genesis(spec, state):
|
||||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5)
|
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5, rng=Random(2323))
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
|
@ -81,11 +84,13 @@ def test_empty_sync_committee_committee_genesis(spec, state):
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_inactivity_scores(spec, state):
|
@leaking()
|
||||||
for _ in range(spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2):
|
def test_inactivity_scores_leaking(spec, state):
|
||||||
next_epoch_via_block(spec, state)
|
|
||||||
|
|
||||||
assert spec.is_in_inactivity_leak(state)
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
randomize_inactivity_scores(spec, state, rng=Random(5252))
|
||||||
|
assert len(set(state.inactivity_scores)) > 1
|
||||||
|
|
||||||
previous_inactivity_scores = state.inactivity_scores.copy()
|
previous_inactivity_scores = state.inactivity_scores.copy()
|
||||||
|
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
@ -97,5 +102,36 @@ def test_inactivity_scores(spec, state):
|
||||||
yield 'blocks', [signed_block]
|
yield 'blocks', [signed_block]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
|
# No particiaption during a leak so all scores should increase
|
||||||
for pre, post in zip(previous_inactivity_scores, state.inactivity_scores):
|
for pre, post in zip(previous_inactivity_scores, state.inactivity_scores):
|
||||||
assert post == pre + spec.config.INACTIVITY_SCORE_BIAS
|
assert post == pre + spec.config.INACTIVITY_SCORE_BIAS
|
||||||
|
|
||||||
|
|
||||||
|
@with_altair_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@leaking()
|
||||||
|
def test_inactivity_scores_full_participation_leaking(spec, state):
|
||||||
|
randomize_inactivity_scores(spec, state, rng=Random(5252))
|
||||||
|
assert len(set(state.inactivity_scores)) > 1
|
||||||
|
|
||||||
|
# Only set full participation for previous epoch to remain in leak
|
||||||
|
set_full_participation_previous_epoch(spec, state)
|
||||||
|
|
||||||
|
previous_inactivity_scores = state.inactivity_scores.copy()
|
||||||
|
|
||||||
|
yield 'pre', state
|
||||||
|
|
||||||
|
# Block transition to next epoch
|
||||||
|
block = build_empty_block(spec, state, slot=state.slot + spec.SLOTS_PER_EPOCH)
|
||||||
|
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
assert spec.is_in_inactivity_leak(state)
|
||||||
|
|
||||||
|
yield 'blocks', [signed_block]
|
||||||
|
yield 'post', state
|
||||||
|
|
||||||
|
# Full particiaption during a leak so all scores should decrease by 1
|
||||||
|
print(previous_inactivity_scores)
|
||||||
|
print(state.inactivity_scores)
|
||||||
|
for pre, post in zip(previous_inactivity_scores, state.inactivity_scores):
|
||||||
|
assert post == pre - 1
|
||||||
|
|
|
@ -3,3 +3,7 @@ from random import Random
|
||||||
|
|
||||||
def randomize_inactivity_scores(spec, state, minimum=0, maximum=50000, rng=Random(4242)):
|
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))]
|
state.inactivity_scores = [rng.randint(minimum, maximum) for _ in range(len(state.validators))]
|
||||||
|
|
||||||
|
|
||||||
|
def zero_inactivity_scores(spec, state, rng=None):
|
||||||
|
state.inactivity_scores = [0] * len(state.validators)
|
||||||
|
|
|
@ -100,6 +100,13 @@ def randomize_epoch_participation(spec, state, epoch, rng):
|
||||||
epoch_participation[index] = flags
|
epoch_participation[index] = flags
|
||||||
|
|
||||||
|
|
||||||
|
def randomize_previous_epoch_participation(spec, state, rng=Random(8020)):
|
||||||
|
cached_prepare_state_with_attestations(spec, state)
|
||||||
|
randomize_epoch_participation(spec, state, spec.get_previous_epoch(state), rng)
|
||||||
|
if not is_post_altair(spec):
|
||||||
|
state.current_epoch_attestations = []
|
||||||
|
|
||||||
|
|
||||||
def randomize_attestation_participation(spec, state, rng=Random(8020)):
|
def randomize_attestation_participation(spec, state, rng=Random(8020)):
|
||||||
cached_prepare_state_with_attestations(spec, state)
|
cached_prepare_state_with_attestations(spec, state)
|
||||||
randomize_epoch_participation(spec, state, spec.get_previous_epoch(state), rng)
|
randomize_epoch_participation(spec, state, spec.get_previous_epoch(state), rng)
|
||||||
|
|
|
@ -260,9 +260,9 @@ def run_get_inactivity_penalty_deltas(spec, state):
|
||||||
|
|
||||||
def transition_state_to_leak(spec, state, epochs=None):
|
def transition_state_to_leak(spec, state, epochs=None):
|
||||||
if epochs is None:
|
if epochs is None:
|
||||||
# +1 to trigger inactivity_score transitions
|
# +2 because finality delay is based on previous_epoch and must be more than `MIN_EPOCHS_TO_INACTIVITY_PENALTY`
|
||||||
epochs = spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 1
|
epochs = spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2
|
||||||
assert epochs >= spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY
|
assert epochs > spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY
|
||||||
|
|
||||||
for _ in range(epochs):
|
for _ in range(epochs):
|
||||||
next_epoch(spec, state)
|
next_epoch(spec, state)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from eth2spec.test.context import expect_assertion_error
|
from eth2spec.test.context import expect_assertion_error, is_post_altair
|
||||||
from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block
|
from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,3 +92,44 @@ def state_transition_and_sign_block(spec, state, block, expect_fail=False):
|
||||||
transition_unsigned_block(spec, state, block)
|
transition_unsigned_block(spec, state, block)
|
||||||
block.state_root = state.hash_tree_root()
|
block.state_root = state.hash_tree_root()
|
||||||
return sign_block(spec, state, block)
|
return sign_block(spec, state, block)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# WARNING: The following functions can only be used post-altair due to the manipulation of participation flags directly
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def _set_full_participation(spec, state, current=True, previous=True):
|
||||||
|
assert is_post_altair(spec)
|
||||||
|
|
||||||
|
full_flags = spec.ParticipationFlags(0)
|
||||||
|
for flag_index in range(len(spec.PARTICIPATION_FLAG_WEIGHTS)):
|
||||||
|
full_flags = spec.add_flag(full_flags, flag_index)
|
||||||
|
|
||||||
|
for index in range(len(state.validators)):
|
||||||
|
if current:
|
||||||
|
state.current_epoch_participation[index] = full_flags.copy()
|
||||||
|
if previous:
|
||||||
|
state.previous_epoch_participation[index] = full_flags.copy()
|
||||||
|
|
||||||
|
|
||||||
|
def set_full_participation(spec, state, rng=None):
|
||||||
|
_set_full_participation(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
def set_full_participation_previous_epoch(spec, state, rng=None):
|
||||||
|
_set_full_participation(spec, state, current=False, previous=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_empty_participation(spec, state, current=True, previous=True):
|
||||||
|
assert is_post_altair(spec)
|
||||||
|
|
||||||
|
for index in range(len(state.validators)):
|
||||||
|
if current:
|
||||||
|
state.current_epoch_participation[index] = spec.ParticipationFlags(0)
|
||||||
|
if previous:
|
||||||
|
state.previous_epoch_participation[index] = spec.ParticipationFlags(0)
|
||||||
|
|
||||||
|
|
||||||
|
def set_empty_participation(spec, state, rng=None):
|
||||||
|
_set_empty_participation(spec, state)
|
||||||
|
|
Loading…
Reference in New Issue