mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-02 01:25:16 -05:00
@@ -1 +1 @@
|
||||
0.11.0
|
||||
0.11.1
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user