cleanup code duplication, and build new context util for state customization
This commit is contained in:
parent
baded82247
commit
e8a3eac55e
|
@ -2,43 +2,62 @@ from eth2spec.phase0 import spec as spec_phase0
|
|||
from eth2spec.phase1 import spec as spec_phase1
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from .helpers.genesis import create_genesis_state, create_genesis_state_misc_balances
|
||||
from .helpers.genesis import create_genesis_state
|
||||
|
||||
from .utils import vector_test, with_meta_tags
|
||||
|
||||
|
||||
def with_state(fn):
|
||||
def entry(*args, **kw):
|
||||
try:
|
||||
kw['state'] = create_genesis_state(spec=kw['spec'], num_validators=spec_phase0.SLOTS_PER_EPOCH * 8,
|
||||
validator_balance=spec_phase0.MAX_EFFECTIVE_BALANCE)
|
||||
except KeyError:
|
||||
raise TypeError('Spec decorator must come within state decorator to inject spec into state.')
|
||||
return fn(*args, **kw)
|
||||
return entry
|
||||
from typing import Any, Callable, Sequence
|
||||
|
||||
|
||||
def with_state_low_balance(fn):
|
||||
def entry(*args, **kw):
|
||||
try:
|
||||
kw['state'] = create_genesis_state(spec=kw['spec'], num_validators=spec_phase0.SLOTS_PER_EPOCH * 8,
|
||||
validator_balance=18 * 10**9)
|
||||
except KeyError:
|
||||
raise TypeError('Spec decorator must come within state decorator to inject spec into state.')
|
||||
return fn(*args, **kw)
|
||||
return entry
|
||||
def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
|
||||
threshold_fn: Callable[[Any], int]):
|
||||
def deco(fn):
|
||||
def entry(*args, **kw):
|
||||
try:
|
||||
spec = kw['spec']
|
||||
|
||||
balances = balances_fn(spec)
|
||||
activation_threshold = threshold_fn(spec)
|
||||
|
||||
kw['state'] = create_genesis_state(spec=spec, validator_balances=balances,
|
||||
activation_threshold=activation_threshold)
|
||||
except KeyError:
|
||||
raise TypeError('Spec decorator must come within state decorator to inject spec into state.')
|
||||
return fn(*args, **kw)
|
||||
return entry
|
||||
return deco
|
||||
|
||||
|
||||
def with_state_misc_balances(fn):
|
||||
def entry(*args, **kw):
|
||||
try:
|
||||
validator_balances = [spec_phase0.MAX_EFFECTIVE_BALANCE] * (spec_phase0.SLOTS_PER_EPOCH * 8) + [
|
||||
spec_phase0.MIN_DEPOSIT_AMOUNT] * spec_phase0.SLOTS_PER_EPOCH
|
||||
kw['state'] = create_genesis_state_misc_balances(spec=kw['spec'], validator_balances=validator_balances)
|
||||
except KeyError:
|
||||
raise TypeError('Spec decorator must come within state decorator to inject spec into state.')
|
||||
return fn(*args, **kw)
|
||||
return entry
|
||||
def default_activation_threshold(spec):
|
||||
return spec.MAX_EFFECTIVE_BALANCE
|
||||
|
||||
|
||||
def default_balances(spec):
|
||||
num_validators = spec.SLOTS_PER_EPOCH * 8
|
||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||
|
||||
|
||||
with_state = with_custom_state(default_balances, default_activation_threshold)
|
||||
|
||||
|
||||
def low_balances(spec):
|
||||
"""
|
||||
Helper method to create a series of low balances. Usage: `@with_validator_balances(low_balances)`
|
||||
"""
|
||||
num_validators = spec.SLOTS_PER_EPOCH * 8
|
||||
# Technically the balances cannot be this low starting from genesis, but it is useful for testing
|
||||
low_balance = 18 * 10 ** 9
|
||||
return [low_balance] * num_validators
|
||||
|
||||
|
||||
def misc_balances(spec):
|
||||
"""
|
||||
Helper method to create a series of balances that includes some misc. balances.
|
||||
Usage: `@with_validator_balances(misc_balances)`
|
||||
"""
|
||||
num_validators = spec.SLOTS_PER_EPOCH * 8
|
||||
num_misc_validators = spec.SLOTS_PER_EPOCH
|
||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators + [spec.MIN_DEPOSIT_AMOUNT] * num_misc_validators
|
||||
|
||||
|
||||
# BLS is turned off by default *for performance purposes during TESTING*.
|
||||
|
@ -65,14 +84,6 @@ def spec_state_test(fn):
|
|||
return spec_test(with_state(fn))
|
||||
|
||||
|
||||
def spec_state_low_balance_test(fn):
|
||||
return spec_test(with_state_low_balance(fn))
|
||||
|
||||
|
||||
def spec_state_misc_balances_test(fn):
|
||||
return spec_test(with_state_misc_balances(fn))
|
||||
|
||||
|
||||
def expect_assertion_error(fn):
|
||||
bad = False
|
||||
try:
|
||||
|
|
|
@ -19,43 +19,7 @@ def build_mock_validator(spec, i: int, balance: int):
|
|||
)
|
||||
|
||||
|
||||
def create_genesis_state(spec, num_validators, validator_balance):
|
||||
deposit_root = b'\x42' * 32
|
||||
|
||||
state = spec.BeaconState(
|
||||
genesis_time=0,
|
||||
eth1_deposit_index=num_validators,
|
||||
eth1_data=spec.Eth1Data(
|
||||
deposit_root=deposit_root,
|
||||
deposit_count=num_validators,
|
||||
block_hash=spec.Hash(),
|
||||
),
|
||||
latest_block_header=spec.BeaconBlockHeader(body_root=spec.hash_tree_root(spec.BeaconBlockBody())),
|
||||
)
|
||||
|
||||
# We "hack" in the initial validators,
|
||||
# as it is much faster than creating and processing genesis deposits for every single test case.
|
||||
state.balances = [validator_balance] * num_validators
|
||||
state.validators = [build_mock_validator(spec, i, state.balances[i]) for i in range(num_validators)]
|
||||
|
||||
# Process genesis activations
|
||||
for validator in state.validators:
|
||||
if validator.effective_balance >= validator_balance:
|
||||
validator.activation_eligibility_epoch = spec.GENESIS_EPOCH
|
||||
validator.activation_epoch = spec.GENESIS_EPOCH
|
||||
|
||||
genesis_active_index_root = hash_tree_root(List[spec.ValidatorIndex, spec.VALIDATOR_REGISTRY_LIMIT](
|
||||
spec.get_active_validator_indices(state, spec.GENESIS_EPOCH)))
|
||||
genesis_compact_committees_root = hash_tree_root(List[spec.ValidatorIndex, spec.VALIDATOR_REGISTRY_LIMIT](
|
||||
spec.get_active_validator_indices(state, spec.GENESIS_EPOCH)))
|
||||
for index in range(spec.EPOCHS_PER_HISTORICAL_VECTOR):
|
||||
state.active_index_roots[index] = genesis_active_index_root
|
||||
state.compact_committees_roots[index] = genesis_compact_committees_root
|
||||
|
||||
return state
|
||||
|
||||
|
||||
def create_genesis_state_misc_balances(spec, validator_balances):
|
||||
def create_genesis_state(spec, validator_balances, activation_threshold):
|
||||
deposit_root = b'\x42' * 32
|
||||
|
||||
state = spec.BeaconState(
|
||||
|
@ -76,7 +40,7 @@ def create_genesis_state_misc_balances(spec, validator_balances):
|
|||
|
||||
# Process genesis activations
|
||||
for validator in state.validators:
|
||||
if validator.effective_balance > spec.EJECTION_BALANCE:
|
||||
if validator.effective_balance >= activation_threshold:
|
||||
validator.activation_eligibility_epoch = spec.GENESIS_EPOCH
|
||||
validator.activation_epoch = spec.GENESIS_EPOCH
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.context import spec_state_test, spec_state_low_balance_test, expect_assertion_error, always_bls, \
|
||||
with_all_phases, with_phases
|
||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, \
|
||||
with_all_phases, with_phases, spec_test, low_balances, with_custom_state
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
get_valid_attestation,
|
||||
sign_aggregate_attestation,
|
||||
|
@ -58,7 +58,8 @@ def test_success(spec, state):
|
|||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_low_balance_test
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
def test_success_multi_proposer_index_iterations(spec, state):
|
||||
state.slot += spec.SLOTS_PER_EPOCH * 2
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from eth2spec.test.context import spec_state_test, spec_state_misc_balances_test, with_all_phases
|
||||
from eth2spec.test.context import spec_state_test, with_all_phases, spec_test, \
|
||||
misc_balances, with_custom_state, default_activation_threshold
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch,
|
||||
next_slot,
|
||||
|
@ -55,9 +56,7 @@ def test_genesis_epoch_full_attestations_no_rewards(spec, state):
|
|||
assert state.balances[index] == pre_state.balances[index]
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_full_attestations(spec, state):
|
||||
def prepare_state_with_full_attestations(spec, state):
|
||||
attestations = []
|
||||
for slot in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
# create an attestation for each slot in epoch
|
||||
|
@ -73,6 +72,14 @@ def test_full_attestations(spec, state):
|
|||
assert spec.compute_epoch_of_slot(state.slot) == spec.GENESIS_EPOCH + 1
|
||||
assert len(state.previous_epoch_attestations) == spec.SLOTS_PER_EPOCH
|
||||
|
||||
return attestations
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_full_attestations(spec, state):
|
||||
attestations = prepare_state_with_full_attestations(spec, state)
|
||||
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
yield from run_process_rewards_and_penalties(spec, state)
|
||||
|
@ -87,22 +94,10 @@ def test_full_attestations(spec, state):
|
|||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_misc_balances_test
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=default_activation_threshold)
|
||||
def test_full_attestations_misc_balances(spec, state):
|
||||
attestations = []
|
||||
for slot in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
# create an attestation for each slot in epoch
|
||||
if slot < spec.SLOTS_PER_EPOCH:
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
attestations.append(attestation)
|
||||
# fill each created slot in state after inclusion delay
|
||||
if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0:
|
||||
include_att = attestations[slot - spec.MIN_ATTESTATION_INCLUSION_DELAY]
|
||||
add_attestations_to_state(spec, state, [include_att], state.slot)
|
||||
next_slot(spec, state)
|
||||
|
||||
assert spec.compute_epoch_of_slot(state.slot) == spec.GENESIS_EPOCH + 1
|
||||
assert len(state.previous_epoch_attestations) == spec.SLOTS_PER_EPOCH
|
||||
attestations = prepare_state_with_full_attestations(spec, state)
|
||||
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
|
|
Loading…
Reference in New Issue