mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-02 11:35:01 -05:00
add test case for active/exited difference for sync rewards processing
This commit is contained in:
@@ -12,7 +12,6 @@ from eth2spec.test.helpers.constants import (
|
||||
from eth2spec.test.helpers.sync_committee import (
|
||||
compute_aggregate_sync_committee_signature,
|
||||
compute_committee_indices,
|
||||
get_committee_indices,
|
||||
run_sync_committee_processing,
|
||||
run_successful_sync_committee_test,
|
||||
)
|
||||
@@ -28,7 +27,7 @@ from eth2spec.test.context import (
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_bad_domain(spec, state):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.sync_aggregate = spec.SyncAggregate(
|
||||
@@ -48,7 +47,7 @@ def test_invalid_signature_bad_domain(spec, state):
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_missing_participant(spec, state):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
rng = random.Random(2020)
|
||||
random_participant = rng.choice(committee_indices)
|
||||
|
||||
@@ -111,7 +110,7 @@ def test_invalid_signature_infinite_signature_with_single_participant(spec, stat
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_extra_participant(spec, state):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
rng = random.Random(3030)
|
||||
random_participant = rng.choice(committee_indices)
|
||||
|
||||
@@ -134,7 +133,7 @@ def test_invalid_signature_extra_participant(spec, state):
|
||||
@with_presets([MINIMAL], reason="to create nonduplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_nonduplicate_committee(spec, state):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=False)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
committee_size = len(committee_indices)
|
||||
committee_bits = [True] * committee_size
|
||||
active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state)))
|
||||
@@ -150,7 +149,7 @@ def test_sync_committee_rewards_nonduplicate_committee(spec, state):
|
||||
@with_presets([MAINNET], reason="to create duplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_duplicate_committee_no_participation(spec, state):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=True)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
committee_size = len(committee_indices)
|
||||
committee_bits = [False] * committee_size
|
||||
active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state)))
|
||||
@@ -166,7 +165,7 @@ def test_sync_committee_rewards_duplicate_committee_no_participation(spec, state
|
||||
@with_presets([MAINNET], reason="to create duplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_duplicate_committee_half_participation(spec, state):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=True)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
committee_size = len(committee_indices)
|
||||
committee_bits = [True] * (committee_size // 2) + [False] * (committee_size // 2)
|
||||
assert len(committee_bits) == committee_size
|
||||
@@ -183,7 +182,7 @@ def test_sync_committee_rewards_duplicate_committee_half_participation(spec, sta
|
||||
@with_presets([MAINNET], reason="to create duplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_duplicate_committee_full_participation(spec, state):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=True)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
committee_size = len(committee_indices)
|
||||
committee_bits = [True] * committee_size
|
||||
active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state)))
|
||||
@@ -199,7 +198,7 @@ def test_sync_committee_rewards_duplicate_committee_full_participation(spec, sta
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_sync_committee_rewards_not_full_participants(spec, state):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
rng = random.Random(1010)
|
||||
committee_bits = [rng.choice([True, False]) for _ in committee_indices]
|
||||
|
||||
@@ -210,7 +209,7 @@ def test_sync_committee_rewards_not_full_participants(spec, state):
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_sync_committee_rewards_empty_participants(spec, state):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
committee_bits = [False for _ in committee_indices]
|
||||
|
||||
yield from run_successful_sync_committee_test(spec, state, committee_indices, committee_bits)
|
||||
@@ -220,7 +219,7 @@ def test_sync_committee_rewards_empty_participants(spec, state):
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_past_block(spec, state):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
committee_indices = compute_committee_indices(spec, state)
|
||||
|
||||
for _ in range(2):
|
||||
# NOTE: need to transition twice to move beyond the degenerate case at genesis
|
||||
|
||||
@@ -2,10 +2,19 @@ import random
|
||||
from eth2spec.test.helpers.constants import (
|
||||
MAINNET, MINIMAL,
|
||||
)
|
||||
from eth2spec.test.helpers.random import (
|
||||
randomize_state
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
has_active_balance_differential,
|
||||
)
|
||||
from eth2spec.test.helpers.sync_committee import (
|
||||
get_committee_indices,
|
||||
compute_committee_indices,
|
||||
run_successful_sync_committee_test,
|
||||
)
|
||||
from eth2spec.test.helpers.voluntary_exits import (
|
||||
get_unslashed_exited_validators,
|
||||
)
|
||||
from eth2spec.test.context import (
|
||||
with_altair_and_later,
|
||||
spec_state_test,
|
||||
@@ -18,8 +27,8 @@ from eth2spec.test.context import (
|
||||
)
|
||||
|
||||
|
||||
def _test_harness_for_randomized_test_case(spec, state, duplicates=False, participation_fn=None):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=duplicates)
|
||||
def _test_harness_for_randomized_test_case(spec, state, expect_duplicates=False, participation_fn=None):
|
||||
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
|
||||
|
||||
if participation_fn:
|
||||
participating_indices = participation_fn(committee_indices)
|
||||
@@ -28,7 +37,7 @@ def _test_harness_for_randomized_test_case(spec, state, duplicates=False, partic
|
||||
|
||||
committee_bits = [index in participating_indices for index in committee_indices]
|
||||
committee_size = len(committee_indices)
|
||||
if duplicates:
|
||||
if expect_duplicates:
|
||||
assert committee_size > len(set(committee_indices))
|
||||
else:
|
||||
assert committee_size == len(set(committee_indices))
|
||||
@@ -44,7 +53,7 @@ def test_random_only_one_participant_with_duplicates(spec, state):
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
duplicates=True,
|
||||
expect_duplicates=True,
|
||||
participation_fn=lambda comm: [rng.choice(comm)],
|
||||
)
|
||||
|
||||
@@ -57,7 +66,7 @@ def test_random_low_participation_with_duplicates(spec, state):
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
duplicates=True,
|
||||
expect_duplicates=True,
|
||||
participation_fn=lambda comm: rng.sample(comm, int(len(comm) * 0.25)),
|
||||
)
|
||||
|
||||
@@ -70,7 +79,7 @@ def test_random_high_participation_with_duplicates(spec, state):
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
duplicates=True,
|
||||
expect_duplicates=True,
|
||||
participation_fn=lambda comm: rng.sample(comm, int(len(comm) * 0.75)),
|
||||
)
|
||||
|
||||
@@ -83,7 +92,7 @@ def test_random_all_but_one_participating_with_duplicates(spec, state):
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
duplicates=True,
|
||||
expect_duplicates=True,
|
||||
participation_fn=lambda comm: rng.sample(comm, len(comm) - 1),
|
||||
)
|
||||
|
||||
@@ -98,7 +107,25 @@ def test_random_misc_balances_and_half_participation_with_duplicates(spec, state
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
duplicates=True,
|
||||
expect_duplicates=True,
|
||||
participation_fn=lambda comm: rng.sample(comm, len(comm) // 2),
|
||||
)
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_presets([MAINNET], reason="to create duplicate committee")
|
||||
@spec_state_test
|
||||
@single_phase
|
||||
def test_random_with_exits_with_duplicates(spec, state):
|
||||
rng = random.Random(1402)
|
||||
randomize_state(spec, state, rng=rng, exit_fraction=0.1, slash_fraction=0.0)
|
||||
target_validators = get_unslashed_exited_validators(spec, state)
|
||||
assert len(target_validators) != 0
|
||||
assert has_active_balance_differential(spec, state)
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
expect_duplicates=True,
|
||||
participation_fn=lambda comm: rng.sample(comm, len(comm) // 2),
|
||||
)
|
||||
|
||||
@@ -163,3 +190,20 @@ def test_random_misc_balances_and_half_participation_without_duplicates(spec, st
|
||||
state,
|
||||
participation_fn=lambda comm: rng.sample(comm, len(comm) // 2),
|
||||
)
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_presets([MINIMAL], reason="to create nonduplicate committee")
|
||||
@spec_state_test
|
||||
@single_phase
|
||||
def test_random_with_exits_without_duplicates(spec, state):
|
||||
rng = random.Random(1502)
|
||||
randomize_state(spec, state, rng=rng, exit_fraction=0.1, slash_fraction=0.0)
|
||||
target_validators = get_unslashed_exited_validators(spec, state)
|
||||
assert len(target_validators) != 0
|
||||
assert has_active_balance_differential(spec, state)
|
||||
yield from _test_harness_for_randomized_test_case(
|
||||
spec,
|
||||
state,
|
||||
participation_fn=lambda comm: rng.sample(comm, len(comm) // 2),
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ from eth2spec.test.helpers.block import (
|
||||
)
|
||||
from eth2spec.test.helpers.block_processing import run_block_processing_to
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.hash_function import hash
|
||||
|
||||
|
||||
def compute_sync_committee_signature(spec, state, slot, privkey, block_root=None, domain_type=None):
|
||||
@@ -75,10 +74,12 @@ def compute_sync_committee_proposer_reward(spec, state, committee_indices, commi
|
||||
return spec.Gwei(participant_reward * participant_number)
|
||||
|
||||
|
||||
def compute_committee_indices(spec, state, committee):
|
||||
def compute_committee_indices(spec, state, committee=None):
|
||||
"""
|
||||
Given a ``committee``, calculate and return the related indices
|
||||
"""
|
||||
if committee is None:
|
||||
committee = state.current_sync_committee
|
||||
all_pubkeys = [v.pubkey for v in state.validators]
|
||||
return [all_pubkeys.index(pubkey) for pubkey in committee.pubkeys]
|
||||
|
||||
@@ -153,6 +154,7 @@ def _build_block_for_next_slot_with_sync_participation(spec, state, committee_in
|
||||
state,
|
||||
block.slot - 1,
|
||||
[index for index, bit in zip(committee_indices, committee_bits) if bit],
|
||||
block_root=block.parent_root,
|
||||
)
|
||||
)
|
||||
return block
|
||||
@@ -161,23 +163,3 @@ def _build_block_for_next_slot_with_sync_participation(spec, state, committee_in
|
||||
def run_successful_sync_committee_test(spec, state, committee_indices, committee_bits):
|
||||
block = _build_block_for_next_slot_with_sync_participation(spec, state, committee_indices, committee_bits)
|
||||
yield from run_sync_committee_processing(spec, state, block)
|
||||
|
||||
|
||||
def get_committee_indices(spec, state, duplicates=False):
|
||||
"""
|
||||
This utility function allows the caller to ensure there are or are not
|
||||
duplicate validator indices in the returned committee based on
|
||||
the boolean ``duplicates``.
|
||||
"""
|
||||
state = state.copy()
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
randao_index = (current_epoch + 1) % spec.EPOCHS_PER_HISTORICAL_VECTOR
|
||||
while True:
|
||||
committee = spec.get_next_sync_committee_indices(state)
|
||||
if duplicates:
|
||||
if len(committee) != len(set(committee)):
|
||||
return committee
|
||||
else:
|
||||
if len(committee) == len(set(committee)):
|
||||
return committee
|
||||
state.randao_mixes[randao_index] = hash(state.randao_mixes[randao_index])
|
||||
|
||||
Reference in New Issue
Block a user