Merge pull request #1692 from ethereum/master

Backport v0.11.1 to dev
This commit is contained in:
Danny Ryan
2020-03-29 16:38:50 -06:00
committed by GitHub
10 changed files with 218 additions and 48 deletions

View File

@@ -1 +1 @@
0.11.0
0.11.1

View File

@@ -6,6 +6,7 @@ from .helpers.genesis import create_genesis_state
from .utils import vector_test, with_meta_tags
from random import Random
from typing import Any, Callable, Sequence, TypedDict, Protocol
from importlib import reload
@@ -71,6 +72,14 @@ def default_activation_threshold(spec):
return spec.MAX_EFFECTIVE_BALANCE
def zero_activation_threshold(spec):
"""
Helper method to use 0 gwei as the activation threshold for state creation for tests.
Usage: `@with_custom_state(threshold_fn=zero_activation_threshold, ...)`
"""
return 0
def default_balances(spec):
"""
Helper method to create a series of default balances.
@@ -100,8 +109,18 @@ def misc_balances(spec):
Usage: `@with_custom_state(balances_fn=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
balances = [spec.MAX_EFFECTIVE_BALANCE * 2 * i // num_validators for i in range(num_validators)]
rng = Random(1234)
rng.shuffle(balances)
return balances
def low_single_balance(spec):
"""
Helper method to create a single of balance of 1 Gwei.
Usage: `@with_custom_state(balances_fn=low_single_balance, ...)`
"""
return [1]
def single_phase(fn):

View File

@@ -39,7 +39,7 @@ def build_attestation_data(spec, state, slot, index):
)
def get_valid_attestation(spec, state, slot=None, index=None, signed=False):
def get_valid_attestation(spec, state, slot=None, index=None, empty=False, signed=False):
if slot is None:
slot = state.slot
if index is None:
@@ -59,7 +59,8 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False):
aggregation_bits=aggregation_bits,
data=attestation_data,
)
fill_aggregate_attestation(spec, state, attestation)
if not empty:
fill_aggregate_attestation(spec, state, attestation)
if signed:
sign_attestation(spec, state, attestation)
return attestation

View File

@@ -292,14 +292,12 @@ def test_bad_source_root(spec, state):
@with_all_phases
@spec_state_test
def test_empty_aggregation_bits(spec, state):
attestation = get_valid_attestation(spec, state)
attestation = get_valid_attestation(spec, state, empty=True)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
attestation.aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](
assert attestation.aggregation_bits == Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](
*([0b0] * len(attestation.aggregation_bits)))
sign_attestation(spec, state, attestation)
yield from run_attestation_processing(spec, state, attestation)

View File

@@ -1,8 +1,7 @@
from copy import deepcopy
from eth2spec.test.context import (
spec_state_test, with_all_phases, spec_test,
misc_balances, with_custom_state, default_activation_threshold,
misc_balances, with_custom_state,
low_single_balance, zero_activation_threshold,
single_phase,
)
from eth2spec.test.helpers.state import (
@@ -24,7 +23,7 @@ def run_process_rewards_and_penalties(spec, state):
@with_all_phases
@spec_state_test
def test_genesis_epoch_no_attestations_no_penalties(spec, state):
pre_state = deepcopy(state)
pre_state = state.copy()
assert spec.compute_epoch_at_slot(state.slot) == spec.GENESIS_EPOCH
@@ -52,7 +51,7 @@ def test_genesis_epoch_full_attestations_no_rewards(spec, state):
# ensure has not cross the epoch boundary
assert spec.compute_epoch_at_slot(state.slot) == spec.GENESIS_EPOCH
pre_state = deepcopy(state)
pre_state = state.copy()
yield from run_process_rewards_and_penalties(spec, state)
@@ -60,12 +59,12 @@ def test_genesis_epoch_full_attestations_no_rewards(spec, state):
assert state.balances[index] == pre_state.balances[index]
def prepare_state_with_full_attestations(spec, state):
def prepare_state_with_full_attestations(spec, state, empty=False):
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)
attestation = get_valid_attestation(spec, state, empty=empty, signed=True)
attestations.append(attestation)
# fill each created slot in state after inclusion delay
if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0:
@@ -84,7 +83,7 @@ def prepare_state_with_full_attestations(spec, state):
def test_full_attestations(spec, state):
attestations = prepare_state_with_full_attestations(spec, state)
pre_state = deepcopy(state)
pre_state = state.copy()
yield from run_process_rewards_and_penalties(spec, state)
@@ -122,18 +121,19 @@ def test_full_attestations_random_incorrect_fields(spec, state):
@with_all_phases
@spec_test
@with_custom_state(balances_fn=misc_balances, threshold_fn=default_activation_threshold)
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.MAX_EFFECTIVE_BALANCE // 2)
@single_phase
def test_full_attestations_misc_balances(spec, state):
attestations = prepare_state_with_full_attestations(spec, state)
pre_state = deepcopy(state)
pre_state = state.copy()
yield from run_process_rewards_and_penalties(spec, state)
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
assert len(attesting_indices) > 0
assert len(attesting_indices) != len(pre_state.validators)
assert any(v.effective_balance != spec.MAX_EFFECTIVE_BALANCE for v in state.validators)
for index in range(len(pre_state.validators)):
if index in attesting_indices:
assert state.balances[index] > pre_state.balances[index]
@@ -141,13 +141,35 @@ def test_full_attestations_misc_balances(spec, state):
assert state.balances[index] < pre_state.balances[index]
else:
assert state.balances[index] == pre_state.balances[index]
# Check if base rewards are consistent with effective balance.
brs = {}
for index in attesting_indices:
br = spec.get_base_reward(state, index)
if br in brs:
assert brs[br] == state.validators[index].effective_balance
else:
brs[br] = state.validators[index].effective_balance
@with_all_phases
@spec_test
@with_custom_state(balances_fn=low_single_balance, threshold_fn=zero_activation_threshold)
@single_phase
def test_full_attestations_one_validaor_one_gwei(spec, state):
attestations = prepare_state_with_full_attestations(spec, state)
yield from run_process_rewards_and_penalties(spec, state)
# Few assertions. Mainly to check that this extreme case can run without exception
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
assert len(attesting_indices) == 1
@with_all_phases
@spec_state_test
def test_no_attestations_all_penalties(spec, state):
next_epoch(spec, state)
pre_state = deepcopy(state)
pre_state = state.copy()
assert spec.compute_epoch_at_slot(state.slot) == spec.GENESIS_EPOCH + 1
@@ -157,6 +179,22 @@ def test_no_attestations_all_penalties(spec, state):
assert state.balances[index] < pre_state.balances[index]
@with_all_phases
@spec_state_test
def test_empty_attestations(spec, state):
attestations = prepare_state_with_full_attestations(spec, state, empty=True)
pre_state = state.copy()
yield from run_process_rewards_and_penalties(spec, state)
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
assert len(attesting_indices) == 0
for index in range(len(pre_state.validators)):
assert state.balances[index] < pre_state.balances[index]
@with_all_phases
@spec_state_test
def test_duplicate_attestation(spec, state):
@@ -173,8 +211,8 @@ def test_duplicate_attestation(spec, state):
assert len(participants) > 0
single_state = deepcopy(state)
dup_state = deepcopy(state)
single_state = state.copy()
dup_state = state.copy()
inclusion_slot = state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY
add_attestations_to_state(spec, single_state, [attestation], inclusion_slot)
@@ -220,7 +258,7 @@ def test_attestations_some_slashed(spec, state):
assert spec.compute_epoch_at_slot(state.slot) == spec.GENESIS_EPOCH + 1
assert len(state.previous_epoch_attestations) == spec.SLOTS_PER_EPOCH
pre_state = deepcopy(state)
pre_state = state.copy()
yield from run_process_rewards_and_penalties(spec, state)