Fix tests

This commit is contained in:
Hsiao-Wei Wang 2021-06-02 01:21:03 +08:00
parent c115fa9a86
commit 67809e76e1
No known key found for this signature in database
GPG Key ID: 1111A8A81778319E
4 changed files with 109 additions and 44 deletions

View File

@ -1,4 +1,3 @@
from collections import Counter
import random import random
from eth2spec.test.helpers.block import ( from eth2spec.test.helpers.block import (
build_empty_block_for_next_slot, build_empty_block_for_next_slot,
@ -13,6 +12,9 @@ from eth2spec.test.helpers.constants import (
) )
from eth2spec.test.helpers.sync_committee import ( from eth2spec.test.helpers.sync_committee import (
compute_aggregate_sync_committee_signature, compute_aggregate_sync_committee_signature,
compute_sync_committee_participant_reward_and_penalty,
compute_sync_committee_proposer_reward,
compute_committee_indices,
) )
from eth2spec.test.context import ( from eth2spec.test.context import (
expect_assertion_error, expect_assertion_error,
@ -61,15 +63,6 @@ def get_committee_indices(spec, state, duplicates=False):
state.randao_mixes[randao_index] = hash(state.randao_mixes[randao_index]) state.randao_mixes[randao_index] = hash(state.randao_mixes[randao_index])
def compute_committee_indices(spec, state, committee):
"""
Given a ``committee``, calculate and return the related indices
"""
all_pubkeys = [v.pubkey for v in state.validators]
committee_indices = [all_pubkeys.index(pubkey) for pubkey in committee.pubkeys]
return committee_indices
@with_altair_and_later @with_altair_and_later
@spec_state_test @spec_state_test
@always_bls @always_bls
@ -115,41 +108,20 @@ 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_inclusion_reward(spec, state):
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)
max_participant_rewards = spec.Gwei(total_base_rewards * spec.SYNC_REWARD_WEIGHT //
spec.WEIGHT_DENOMINATOR // spec.SLOTS_PER_EPOCH)
return spec.Gwei(max_participant_rewards // spec.SYNC_COMMITTEE_SIZE)
def compute_sync_committee_participant_reward(spec, state, participant_index, committee_indices, committee_bits):
included_indices = [index for index, bit in zip(committee_indices, committee_bits) if bit]
multiplicities = Counter(included_indices)
inclusion_reward = compute_sync_committee_inclusion_reward(spec, state)
return spec.Gwei(inclusion_reward * multiplicities[participant_index])
def compute_sync_committee_proposer_reward(spec, state, committee_indices, committee_bits):
proposer_reward_denominator = spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT
inclusion_reward = compute_sync_committee_inclusion_reward(spec, state)
participant_number = committee_bits.count(True)
participant_reward = inclusion_reward * spec.PROPOSER_WEIGHT // proposer_reward_denominator
return spec.Gwei(participant_reward * participant_number)
def validate_sync_committee_rewards(spec, pre_state, post_state, committee_indices, committee_bits, proposer_index): def validate_sync_committee_rewards(spec, pre_state, post_state, committee_indices, committee_bits, proposer_index):
for index in range(len(post_state.validators)): for index in range(len(post_state.validators)):
reward = 0 reward = 0
penalty = 0
if index in committee_indices: if index in committee_indices:
reward += compute_sync_committee_participant_reward( _reward, _penalty = compute_sync_committee_participant_reward_and_penalty(
spec, spec,
pre_state, pre_state,
index, index,
committee_indices, committee_indices,
committee_bits, committee_bits,
) )
reward += _reward
penalty += _penalty
if proposer_index == index: if proposer_index == index:
reward += compute_sync_committee_proposer_reward( reward += compute_sync_committee_proposer_reward(
@ -159,7 +131,7 @@ def validate_sync_committee_rewards(spec, pre_state, post_state, committee_indic
committee_bits, committee_bits,
) )
assert post_state.balances[index] == pre_state.balances[index] + reward assert post_state.balances[index] == pre_state.balances[index] + reward - penalty
def run_successful_sync_committee_test(spec, state, committee_indices, committee_bits): def run_successful_sync_committee_test(spec, state, committee_indices, committee_bits):

View File

@ -2,6 +2,10 @@ from eth2spec.test.context import is_post_altair
from eth2spec.test.helpers.block_header import sign_block_header from eth2spec.test.helpers.block_header import sign_block_header
from eth2spec.test.helpers.keys import pubkey_to_privkey from eth2spec.test.helpers.keys import pubkey_to_privkey
from eth2spec.test.helpers.state import get_balance from eth2spec.test.helpers.state import get_balance
from eth2spec.test.helpers.sync_committee import (
compute_committee_indices,
compute_sync_committee_participant_reward_and_penalty,
)
def get_min_slashing_penalty_quotient(spec): def get_min_slashing_penalty_quotient(spec):
@ -11,7 +15,7 @@ def get_min_slashing_penalty_quotient(spec):
return spec.MIN_SLASHING_PENALTY_QUOTIENT return spec.MIN_SLASHING_PENALTY_QUOTIENT
def check_proposer_slashing_effect(spec, pre_state, state, slashed_index): def check_proposer_slashing_effect(spec, pre_state, state, slashed_index, block=None):
slashed_validator = state.validators[slashed_index] slashed_validator = state.validators[slashed_index]
assert slashed_validator.slashed assert slashed_validator.slashed
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
@ -20,24 +24,51 @@ def check_proposer_slashing_effect(spec, pre_state, state, slashed_index):
proposer_index = spec.get_beacon_proposer_index(state) proposer_index = spec.get_beacon_proposer_index(state)
slash_penalty = state.validators[slashed_index].effective_balance // get_min_slashing_penalty_quotient(spec) slash_penalty = state.validators[slashed_index].effective_balance // get_min_slashing_penalty_quotient(spec)
whistleblower_reward = state.validators[slashed_index].effective_balance // spec.WHISTLEBLOWER_REWARD_QUOTIENT whistleblower_reward = state.validators[slashed_index].effective_balance // spec.WHISTLEBLOWER_REWARD_QUOTIENT
# Altair introduces sync committee (SC) reward and penalty
sc_reward_for_slashed = sc_penalty_for_slashed = sc_reward_for_proposer = sc_penalty_for_proposer = 0
if is_post_altair(spec) and block is not None:
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
committee_bits = block.body.sync_aggregate.sync_committee_bits
sc_reward_for_slashed, sc_penalty_for_slashed = compute_sync_committee_participant_reward_and_penalty(
spec,
pre_state,
slashed_index,
committee_indices,
committee_bits,
)
sc_reward_for_proposer, sc_penalty_for_proposer = compute_sync_committee_participant_reward_and_penalty(
spec,
pre_state,
proposer_index,
committee_indices,
committee_bits,
)
if proposer_index != slashed_index: if proposer_index != slashed_index:
# slashed validator lost initial slash penalty # slashed validator lost initial slash penalty
assert ( assert (
get_balance(state, slashed_index) get_balance(state, slashed_index)
== get_balance(pre_state, slashed_index) - slash_penalty == get_balance(pre_state, slashed_index) - slash_penalty + sc_reward_for_slashed - sc_penalty_for_slashed
) )
# block proposer gained whistleblower reward # block proposer gained whistleblower reward
# >= because proposer could have reported multiple # >= because proposer could have reported multiple
assert ( assert (
get_balance(state, proposer_index) get_balance(state, proposer_index)
>= get_balance(pre_state, proposer_index) + whistleblower_reward >= (
get_balance(pre_state, proposer_index) + whistleblower_reward
+ sc_reward_for_proposer - sc_penalty_for_proposer
)
) )
else: else:
# proposer reported themself so get penalty and reward # proposer reported themself so get penalty and reward
# >= because proposer could have reported multiple # >= because proposer could have reported multiple
assert ( assert (
get_balance(state, slashed_index) get_balance(state, slashed_index)
>= get_balance(pre_state, slashed_index) - slash_penalty + whistleblower_reward >= (
get_balance(pre_state, slashed_index) - slash_penalty + whistleblower_reward
+ sc_reward_for_slashed - sc_penalty_for_slashed
)
) )

View File

@ -1,3 +1,5 @@
from collections import Counter
from eth2spec.test.helpers.keys import privkeys from eth2spec.test.helpers.keys import privkeys
from eth2spec.test.helpers.block import ( from eth2spec.test.helpers.block import (
build_empty_block_for_next_slot, build_empty_block_for_next_slot,
@ -33,3 +35,42 @@ def compute_aggregate_sync_committee_signature(spec, state, slot, participants,
) )
) )
return bls.Aggregate(signatures) return bls.Aggregate(signatures)
def compute_sync_committee_inclusion_reward(spec, state):
total_active_increments = spec.get_total_active_balance(state) // spec.EFFECTIVE_BALANCE_INCREMENT
total_base_rewards = spec.get_base_reward_per_increment(state) * total_active_increments
max_participant_rewards = (total_base_rewards * spec.SYNC_REWARD_WEIGHT
// spec.WEIGHT_DENOMINATOR // spec.SLOTS_PER_EPOCH)
return max_participant_rewards // spec.SYNC_COMMITTEE_SIZE
def compute_sync_committee_participant_reward_and_penalty(
spec, state, participant_index, committee_indices, committee_bits):
inclusion_reward = compute_sync_committee_inclusion_reward(spec, state)
included_indices = [index for index, bit in zip(committee_indices, committee_bits) if bit]
not_included_indices = [index for index, bit in zip(committee_indices, committee_bits) if not bit]
included_multiplicities = Counter(included_indices)
not_included_multiplicities = Counter(not_included_indices)
return (
spec.Gwei(inclusion_reward * included_multiplicities[participant_index]),
spec.Gwei(inclusion_reward * not_included_multiplicities[participant_index])
)
def compute_sync_committee_proposer_reward(spec, state, committee_indices, committee_bits):
proposer_reward_denominator = spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT
inclusion_reward = compute_sync_committee_inclusion_reward(spec, state)
participant_number = committee_bits.count(True)
participant_reward = inclusion_reward * spec.PROPOSER_WEIGHT // proposer_reward_denominator
return spec.Gwei(participant_reward * participant_number)
def compute_committee_indices(spec, state, committee):
"""
Given a ``committee``, calculate and return the related indices
"""
all_pubkeys = [v.pubkey for v in state.validators]
committee_indices = [all_pubkeys.index(pubkey) for pubkey in committee.pubkeys]
return committee_indices

View File

@ -24,6 +24,10 @@ from eth2spec.test.helpers.multi_operations import (
run_slash_and_exit, run_slash_and_exit,
run_test_full_random_operations, run_test_full_random_operations,
) )
from eth2spec.test.helpers.sync_committee import (
compute_committee_indices,
compute_sync_committee_participant_reward_and_penalty,
)
from eth2spec.test.helpers.constants import PHASE0, MINIMAL from eth2spec.test.helpers.constants import PHASE0, MINIMAL
from eth2spec.test.context import ( from eth2spec.test.context import (
spec_test, spec_state_test, dump_skipping_message, spec_test, spec_state_test, dump_skipping_message,
@ -416,7 +420,7 @@ def test_proposer_slashing(spec, state):
yield 'blocks', [signed_block] yield 'blocks', [signed_block]
yield 'post', state yield 'post', state
check_proposer_slashing_effect(spec, pre_state, state, slashed_index) check_proposer_slashing_effect(spec, pre_state, state, slashed_index, block)
@with_all_phases @with_all_phases
@ -491,7 +495,7 @@ def test_multiple_different_proposer_slashings_same_block(spec, state):
for proposer_slashing in proposer_slashings: for proposer_slashing in proposer_slashings:
slashed_index = proposer_slashing.signed_header_1.message.proposer_index slashed_index = proposer_slashing.signed_header_1.message.proposer_index
check_proposer_slashing_effect(spec, pre_state, state, slashed_index) check_proposer_slashing_effect(spec, pre_state, state, slashed_index, block)
def check_attester_slashing_effect(spec, pre_state, state, slashed_indices): def check_attester_slashing_effect(spec, pre_state, state, slashed_indices):
@ -743,7 +747,8 @@ def test_deposit_top_up(spec, state):
initial_balances_len = len(state.balances) initial_balances_len = len(state.balances)
validator_pre_balance = get_balance(state, validator_index) validator_pre_balance = get_balance(state, validator_index)
yield 'pre', state pre_state = state.copy()
yield 'pre', pre_state
block = build_empty_block_for_next_slot(spec, state) block = build_empty_block_for_next_slot(spec, state)
block.body.deposits.append(deposit) block.body.deposits.append(deposit)
@ -755,7 +760,23 @@ def test_deposit_top_up(spec, state):
assert len(state.validators) == initial_registry_len assert len(state.validators) == initial_registry_len
assert len(state.balances) == initial_balances_len assert len(state.balances) == initial_balances_len
assert get_balance(state, validator_index) == validator_pre_balance + amount
# Altair introduces sync committee (sm) reward and penalty
sync_committee_reward = sync_committee_penalty = 0
if is_post_altair(spec):
committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
committee_bits = block.body.sync_aggregate.sync_committee_bits
sync_committee_reward, sync_committee_penalty = compute_sync_committee_participant_reward_and_penalty(
spec,
pre_state,
validator_index,
committee_indices,
committee_bits,
)
assert get_balance(state, validator_index) == (
validator_pre_balance + amount + sync_committee_reward - sync_committee_penalty
)
@with_all_phases @with_all_phases