clean up and extend sync committee rewards tests

This commit is contained in:
Danny Ryan 2021-03-16 11:18:26 -06:00
parent 27e88a2484
commit b0a9fc8277
No known key found for this signature in database
GPG Key ID: 2765A792E42CE07A
1 changed files with 92 additions and 60 deletions

View File

@ -65,7 +65,8 @@ def get_committee_indices(spec, state, duplicates=False):
@always_bls @always_bls
def test_invalid_signature_missing_participant(spec, state): def test_invalid_signature_missing_participant(spec, state):
committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state)) committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state))
random_participant = random.choice(committee) rng = random.Random(2020)
random_participant = rng.choice(committee)
yield 'pre', state yield 'pre', state
@ -88,7 +89,8 @@ def test_invalid_signature_missing_participant(spec, state):
@always_bls @always_bls
def test_invalid_signature_extra_participant(spec, state): def test_invalid_signature_extra_participant(spec, state):
committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state)) committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state))
random_participant = random.choice(committee) rng = random.Random(3030)
random_participant = rng.choice(committee)
block = build_empty_block_for_next_slot(spec, state) block = build_empty_block_for_next_slot(spec, state)
# Exclude one signature even though the block claims the entire committee participated. # Exclude one signature even though the block claims the entire committee participated.
@ -105,7 +107,7 @@ def test_invalid_signature_extra_participant(spec, state):
yield from run_sync_committee_processing(spec, state, block, expect_exception=True) yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
def compute_sync_committee_participant_reward(spec, state, participant_index, committee, committee_bits): def compute_sync_committee_inclusion_reward(spec, state, participant_index, committee, committee_bits):
total_active_increments = spec.get_total_active_balance(state) // spec.EFFECTIVE_BALANCE_INCREMENT total_active_increments = spec.get_total_active_balance(state) // spec.EFFECTIVE_BALANCE_INCREMENT
total_base_rewards = spec.Gwei(spec.get_base_reward_per_increment(state) * total_active_increments) total_base_rewards = spec.Gwei(spec.get_base_reward_per_increment(state) * total_active_increments)
max_epoch_rewards = spec.Gwei(total_base_rewards * spec.SYNC_REWARD_WEIGHT // spec.WEIGHT_DENOMINATOR) max_epoch_rewards = spec.Gwei(total_base_rewards * spec.SYNC_REWARD_WEIGHT // spec.WEIGHT_DENOMINATOR)
@ -116,9 +118,82 @@ def compute_sync_committee_participant_reward(spec, state, participant_index, co
committee_effective_balance = sum([state.validators[index].effective_balance for index in included_indices]) committee_effective_balance = sum([state.validators[index].effective_balance for index in included_indices])
committee_effective_balance = max(spec.EFFECTIVE_BALANCE_INCREMENT, committee_effective_balance) committee_effective_balance = max(spec.EFFECTIVE_BALANCE_INCREMENT, committee_effective_balance)
effective_balance = state.validators[participant_index].effective_balance effective_balance = state.validators[participant_index].effective_balance
inclusion_reward = spec.Gwei(max_slot_rewards * effective_balance // committee_effective_balance) return spec.Gwei(max_slot_rewards * effective_balance // committee_effective_balance)
def compute_sync_committee_participant_reward(spec, state, participant_index, committee, committee_bits):
included_indices = [index for index, bit in zip(committee, committee_bits) if bit]
multiplicities = Counter(included_indices)
inclusion_reward = compute_sync_committee_inclusion_reward(
spec, state, participant_index, committee, committee_bits,
)
proposer_reward = spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT) proposer_reward = spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT)
return spec.Gwei(inclusion_reward - proposer_reward) return spec.Gwei((inclusion_reward - proposer_reward) * multiplicities[participant_index])
def compute_sync_committee_proposer_reward(spec, state, committee, committee_bits):
proposer_reward = 0
for index, bit in zip(committee, committee_bits):
if not bit:
continue
inclusion_reward = compute_sync_committee_inclusion_reward(
spec, state, index, committee, committee_bits,
)
proposer_reward += spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT)
return proposer_reward
def validate_sync_committee_rewards(spec, pre_state, post_state, committee, committee_bits, proposer_index):
for index in range(len(post_state.validators)):
reward = 0
if index in committee:
reward += compute_sync_committee_participant_reward(
spec,
pre_state,
index,
committee,
committee_bits,
)
if proposer_index == index:
reward += compute_sync_committee_proposer_reward(
spec,
pre_state,
committee,
committee_bits,
)
assert post_state.balances[index] == pre_state.balances[index] + reward
def run_successful_sync_committee_test(spec, state, committee, committee_bits):
yield 'pre', state
pre_state = state.copy()
block = build_empty_block_for_next_slot(spec, state)
block.body.sync_aggregate = spec.SyncAggregate(
sync_committee_bits=committee_bits,
sync_committee_signature=compute_aggregate_sync_committee_signature(
spec,
state,
block.slot - 1,
[index for index, bit in zip(committee, committee_bits) if bit],
)
)
yield from run_sync_committee_processing(spec, state, block)
validate_sync_committee_rewards(
spec,
pre_state,
state,
committee,
committee_bits,
block.proposer_index,
)
@with_all_phases_except([PHASE0, PHASE1]) @with_all_phases_except([PHASE0, PHASE1])
@with_configs([MINIMAL], reason="to create nonduplicate committee") @with_configs([MINIMAL], reason="to create nonduplicate committee")
@ -126,41 +201,25 @@ def compute_sync_committee_participant_reward(spec, state, participant_index, co
def test_sync_committee_rewards_nonduplicate_committee(spec, state): def test_sync_committee_rewards_nonduplicate_committee(spec, state):
committee = get_committee_indices(spec, state, duplicates=False) committee = get_committee_indices(spec, state, duplicates=False)
committee_size = len(committee) committee_size = len(committee)
committee_bits = [True] * committee_size
active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state))) active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state)))
# Preconditions of this test case # Preconditions of this test case
assert active_validator_count >= spec.SYNC_COMMITTEE_SIZE assert active_validator_count >= spec.SYNC_COMMITTEE_SIZE
assert committee_size == len(set(committee)) assert committee_size == len(set(committee))
yield 'pre', state yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
pre_balances = state.balances.copy()
block = build_empty_block_for_next_slot(spec, state) @with_all_phases_except([PHASE0, PHASE1])
committee_bits = [True] * committee_size @spec_state_test
block.body.sync_aggregate = spec.SyncAggregate( @always_bls
sync_committee_bits=committee_bits, def test_sync_committee_rewards_not_full_participants(spec, state):
sync_committee_signature=compute_aggregate_sync_committee_signature( committee = get_committee_indices(spec, state, duplicates=False)
spec, rng = random.Random(1010)
state, committee_bits = [rng.choice([True, False]) for _ in committee]
block.slot - 1,
committee,
)
)
yield from run_sync_committee_processing(spec, state, block) yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
for index in range(len(state.validators)):
if index in committee:
participant_reward = compute_sync_committee_participant_reward(
spec,
state,
index,
committee,
committee_bits,
)
assert state.balances[index] == pre_balances[index] + participant_reward
@with_all_phases_except([PHASE0, PHASE1]) @with_all_phases_except([PHASE0, PHASE1])
@ -169,41 +228,14 @@ def test_sync_committee_rewards_nonduplicate_committee(spec, state):
def test_sync_committee_rewards_duplicate_committee(spec, state): def test_sync_committee_rewards_duplicate_committee(spec, state):
committee = get_committee_indices(spec, state, duplicates=True) committee = get_committee_indices(spec, state, duplicates=True)
committee_size = len(committee) committee_size = len(committee)
committee_bits = [True] * committee_size
active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state))) active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state)))
# Preconditions of this test case # Preconditions of this test case
assert active_validator_count < spec.SYNC_COMMITTEE_SIZE assert active_validator_count < spec.SYNC_COMMITTEE_SIZE
assert committee_size > len(set(committee)) assert committee_size > len(set(committee))
pre_balances = state.balances.copy() yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
block = build_empty_block_for_next_slot(spec, state)
committee_bits = [True] * committee_size
block.body.sync_aggregate = spec.SyncAggregate(
sync_committee_bits=committee_bits,
sync_committee_signature=compute_aggregate_sync_committee_signature(
spec,
state,
block.slot - 1,
committee,
)
)
yield from run_sync_committee_processing(spec, state, block)
multiplicities = Counter(committee)
for index in range(len(state.validators)):
inclusion_rewards = 0
if index in committee:
participant_reward = compute_sync_committee_participant_reward(
spec,
state,
index,
committee,
committee_bits,
)
inclusion_rewards += reward * multiplicities[index]
# assert state.balances[index] == pre_balances[index] + inclusion_rewards
@with_all_phases_except([PHASE0, PHASE1]) @with_all_phases_except([PHASE0, PHASE1])