Merge pull request #2193 from ethereum/accounting-reform-tests
fix and extend accounting reform tests
This commit is contained in:
commit
ddbd3483cf
|
@ -7,8 +7,9 @@
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
|
- [Custom types](#custom-types)
|
||||||
- [Constants](#constants)
|
- [Constants](#constants)
|
||||||
- [Participation flags](#participation-flags)
|
- [Validator action flags](#validator-action-flags)
|
||||||
- [Participation rewards](#participation-rewards)
|
- [Participation rewards](#participation-rewards)
|
||||||
- [Misc](#misc)
|
- [Misc](#misc)
|
||||||
- [Configuration](#configuration)
|
- [Configuration](#configuration)
|
||||||
|
@ -55,15 +56,27 @@ This is a patch implementing the first hard fork to the beacon chain, tentativel
|
||||||
and [TODO] reducing the cost of processing chains that have very little or zero participation for a long span of epochs
|
and [TODO] reducing the cost of processing chains that have very little or zero participation for a long span of epochs
|
||||||
* Fork choice rule changes to address weaknesses recently discovered in the existing fork choice
|
* Fork choice rule changes to address weaknesses recently discovered in the existing fork choice
|
||||||
|
|
||||||
|
## Custom types
|
||||||
|
|
||||||
|
| Name | SSZ equivalent | Description |
|
||||||
|
| - | - | - |
|
||||||
|
| `ValidatorFlag` | `uint8` | Bitflags to track validator actions with |
|
||||||
|
|
||||||
## Constants
|
## Constants
|
||||||
|
|
||||||
### Participation flags
|
### Validator action flags
|
||||||
|
|
||||||
|
This is formatted as an enum, with values `2**i` that can be combined as bit-flags.
|
||||||
|
The `0` value is reserved as default. Remaining bits in `ValidatorFlag` may be used in future hardforks.
|
||||||
|
|
||||||
|
**Note**: Unlike Phase0, a `TIMELY_TARGET_FLAG` does not necessarily imply a `TIMELY_SOURCE_FLAG`
|
||||||
|
due to the varying slot delay requirements of each.
|
||||||
|
|
||||||
| Name | Value |
|
| Name | Value |
|
||||||
| - | - |
|
| - | - |
|
||||||
| `TIMELY_HEAD_FLAG` | `0` |
|
| `TIMELY_HEAD_FLAG` | `ValidatorFlag(2**0)` (= 1) |
|
||||||
| `TIMELY_SOURCE_FLAG` | `1` |
|
| `TIMELY_SOURCE_FLAG` | `ValidatorFlag(2**1)` (= 2) |
|
||||||
| `TIMELY_TARGET_FLAG` | `2` |
|
| `TIMELY_TARGET_FLAG` | `ValidatorFlag(2**2)` (= 4) |
|
||||||
|
|
||||||
### Participation rewards
|
### Participation rewards
|
||||||
|
|
||||||
|
@ -80,7 +93,6 @@ The reward fractions add up to 7/8, leaving the remaining 1/8 for proposer rewar
|
||||||
|
|
||||||
| Name | Value |
|
| Name | Value |
|
||||||
| - | - |
|
| - | - |
|
||||||
| `PARTICIPATION_FLAGS_LENGTH` | `8` |
|
|
||||||
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
|
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -146,8 +158,8 @@ class BeaconState(Container):
|
||||||
# Slashings
|
# Slashings
|
||||||
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances
|
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances
|
||||||
# Participation
|
# Participation
|
||||||
previous_epoch_participation: List[Bitvector[PARTICIPATION_FLAGS_LENGTH], VALIDATOR_REGISTRY_LIMIT]
|
previous_epoch_participation: List[ValidatorFlag, VALIDATOR_REGISTRY_LIMIT]
|
||||||
current_epoch_participation: List[Bitvector[PARTICIPATION_FLAGS_LENGTH], VALIDATOR_REGISTRY_LIMIT]
|
current_epoch_participation: List[ValidatorFlag, VALIDATOR_REGISTRY_LIMIT]
|
||||||
# Finality
|
# Finality
|
||||||
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch
|
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch
|
||||||
previous_justified_checkpoint: Checkpoint
|
previous_justified_checkpoint: Checkpoint
|
||||||
|
@ -189,7 +201,7 @@ def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, s
|
||||||
#### `flags_and_numerators`
|
#### `flags_and_numerators`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_flags_and_numerators() -> Sequence[Tuple[int, int]]:
|
def get_flags_and_numerators() -> Sequence[Tuple[ValidatorFlag, int]]:
|
||||||
return (
|
return (
|
||||||
(TIMELY_HEAD_FLAG, TIMELY_HEAD_NUMERATOR),
|
(TIMELY_HEAD_FLAG, TIMELY_HEAD_NUMERATOR),
|
||||||
(TIMELY_SOURCE_FLAG, TIMELY_SOURCE_NUMERATOR),
|
(TIMELY_SOURCE_FLAG, TIMELY_SOURCE_NUMERATOR),
|
||||||
|
@ -197,7 +209,15 @@ def get_flags_and_numerators() -> Sequence[Tuple[int, int]]:
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def add_validator_flags(flags: ValidatorFlag, add: ValidatorFlag) -> ValidatorFlag:
|
||||||
|
return flags | add
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def has_validator_flags(flags: ValidatorFlag, has: ValidatorFlag) -> bool:
|
||||||
|
return flags & has == has
|
||||||
|
```
|
||||||
|
|
||||||
### Beacon state accessors
|
### Beacon state accessors
|
||||||
|
|
||||||
|
@ -257,7 +277,10 @@ def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
||||||
#### `get_unslashed_participating_indices`
|
#### `get_unslashed_participating_indices`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_unslashed_participating_indices(state: BeaconState, flag: uint8, epoch: Epoch) -> Set[ValidatorIndex]:
|
def get_unslashed_participating_indices(state: BeaconState, flags: ValidatorFlag, epoch: Epoch) -> Set[ValidatorIndex]:
|
||||||
|
"""
|
||||||
|
Retrieve the active validator indices of the given epoch, which are not slashed, and have all of the given flags.
|
||||||
|
"""
|
||||||
assert epoch in (get_previous_epoch(state), get_current_epoch(state))
|
assert epoch in (get_previous_epoch(state), get_current_epoch(state))
|
||||||
if epoch == get_current_epoch(state):
|
if epoch == get_current_epoch(state):
|
||||||
epoch_participation = state.current_epoch_participation
|
epoch_participation = state.current_epoch_participation
|
||||||
|
@ -265,7 +288,7 @@ def get_unslashed_participating_indices(state: BeaconState, flag: uint8, epoch:
|
||||||
epoch_participation = state.previous_epoch_participation
|
epoch_participation = state.previous_epoch_participation
|
||||||
participating_indices = [
|
participating_indices = [
|
||||||
index for index in get_active_validator_indices(state, epoch)
|
index for index in get_active_validator_indices(state, epoch)
|
||||||
if epoch_participation[index][flag]
|
if has_validator_flags(epoch_participation[index], flags)
|
||||||
]
|
]
|
||||||
return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
|
return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
|
||||||
```
|
```
|
||||||
|
@ -273,9 +296,11 @@ def get_unslashed_participating_indices(state: BeaconState, flag: uint8, epoch:
|
||||||
#### `get_flag_deltas`
|
#### `get_flag_deltas`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_flag_deltas(state: BeaconState, flag: uint8, numerator: uint64) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_flag_deltas(state: BeaconState,
|
||||||
|
flag: ValidatorFlag,
|
||||||
|
numerator: uint64) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
"""
|
"""
|
||||||
Computes the rewards and penalties associated with a particular duty, by scanning through the participation
|
Compute the rewards and penalties associated with a particular duty, by scanning through the participation
|
||||||
flags to determine who participated and who did not and assigning them the appropriate rewards and penalties.
|
flags to determine who participated and who did not and assigning them the appropriate rewards and penalties.
|
||||||
"""
|
"""
|
||||||
rewards = [Gwei(0)] * len(state.validators)
|
rewards = [Gwei(0)] * len(state.validators)
|
||||||
|
@ -374,7 +399,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||||
|
|
||||||
# Participation flags
|
# Participation flags
|
||||||
participation_flags = []
|
participation_flags = []
|
||||||
if is_matching_head and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY:
|
if is_matching_head and is_matching_target and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY:
|
||||||
participation_flags.append(TIMELY_HEAD_FLAG)
|
participation_flags.append(TIMELY_HEAD_FLAG)
|
||||||
if is_matching_source and state.slot <= data.slot + integer_squareroot(SLOTS_PER_EPOCH):
|
if is_matching_source and state.slot <= data.slot + integer_squareroot(SLOTS_PER_EPOCH):
|
||||||
participation_flags.append(TIMELY_SOURCE_FLAG)
|
participation_flags.append(TIMELY_SOURCE_FLAG)
|
||||||
|
@ -385,8 +410,8 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||||
proposer_reward_numerator = 0
|
proposer_reward_numerator = 0
|
||||||
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
||||||
for flag, numerator in get_flags_and_numerators():
|
for flag, numerator in get_flags_and_numerators():
|
||||||
if flag in participation_flags and not epoch_participation[index][flag]:
|
if flag in participation_flags and not has_validator_flags(epoch_participation[index], flag):
|
||||||
epoch_participation[index][flag] = True
|
epoch_participation[index] = add_validator_flags(epoch_participation[index], flag)
|
||||||
proposer_reward_numerator += get_base_reward(state, index) * numerator
|
proposer_reward_numerator += get_base_reward(state, index) * numerator
|
||||||
|
|
||||||
# Reward proposer
|
# Reward proposer
|
||||||
|
@ -432,8 +457,8 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
||||||
state.validators.append(get_validator_from_deposit(state, deposit))
|
state.validators.append(get_validator_from_deposit(state, deposit))
|
||||||
state.balances.append(amount)
|
state.balances.append(amount)
|
||||||
# [Added in hf-1] Initialize empty participation flags for new validator
|
# [Added in hf-1] Initialize empty participation flags for new validator
|
||||||
state.previous_epoch_participation.append(Bitvector[PARTICIPATION_FLAGS_LENGTH]())
|
state.previous_epoch_participation.append(ValidatorFlag(0))
|
||||||
state.current_epoch_participation.append(Bitvector[PARTICIPATION_FLAGS_LENGTH]())
|
state.current_epoch_participation.append(ValidatorFlag(0))
|
||||||
else:
|
else:
|
||||||
# Increase balance by deposit amount
|
# Increase balance by deposit amount
|
||||||
index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
||||||
|
@ -572,5 +597,5 @@ def process_participation_flag_updates(state: BeaconState) -> None:
|
||||||
Call to ``process_participation_flag_updates`` added to ``process_epoch`` in HF1
|
Call to ``process_participation_flag_updates`` added to ``process_epoch`` in HF1
|
||||||
"""
|
"""
|
||||||
state.previous_epoch_participation = state.current_epoch_participation
|
state.previous_epoch_participation = state.current_epoch_participation
|
||||||
state.current_epoch_participation = [Bitvector[PARTICIPATION_FLAGS_LENGTH]() for _ in range(len(state.validators))]
|
state.current_epoch_participation = [ValidatorFlag(0) for _ in range(len(state.validators))]
|
||||||
```
|
```
|
||||||
|
|
|
@ -67,8 +67,8 @@ def upgrade_to_lightclient_patch(pre: phase0.BeaconState) -> BeaconState:
|
||||||
# Slashings
|
# Slashings
|
||||||
slashings=pre.slashings,
|
slashings=pre.slashings,
|
||||||
# Attestations
|
# Attestations
|
||||||
previous_epoch_participation=[Bitvector[PARTICIPATION_FLAGS_LENGTH]() for _ in range(len(pre.validators))],
|
previous_epoch_participation=[ValidatorFlag(0) for _ in range(len(pre.validators))],
|
||||||
current_epoch_participation=[Bitvector[PARTICIPATION_FLAGS_LENGTH]() for _ in range(len(pre.validators))],
|
current_epoch_participation=[ValidatorFlag(0) for _ in range(len(pre.validators))],
|
||||||
# Finality
|
# Finality
|
||||||
justification_bits=pre.justification_bits,
|
justification_bits=pre.justification_bits,
|
||||||
previous_justified_checkpoint=pre.previous_justified_checkpoint,
|
previous_justified_checkpoint=pre.previous_justified_checkpoint,
|
||||||
|
|
|
@ -44,11 +44,8 @@ def run_attestation_processing(spec, state, attestation, valid=True):
|
||||||
else:
|
else:
|
||||||
assert len(state.previous_epoch_attestations) == previous_epoch_count + 1
|
assert len(state.previous_epoch_attestations) == previous_epoch_count + 1
|
||||||
else:
|
else:
|
||||||
for index in spec.get_attesting_indices(state, attestation.data, attestation.aggregation_bits):
|
# After accounting reform, there are cases when processing an attestation does not result in any flag updates
|
||||||
if attestation.data.target.epoch == spec.get_current_epoch(state):
|
pass
|
||||||
assert state.current_epoch_participation[index][spec.TIMELY_TARGET_FLAG]
|
|
||||||
else:
|
|
||||||
assert state.previous_epoch_participation[index][spec.TIMELY_TARGET_FLAG]
|
|
||||||
|
|
||||||
# yield post-state
|
# yield post-state
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
|
@ -6,7 +6,7 @@ from eth2spec.test.context import is_post_lightclient_patch
|
||||||
from eth2spec.test.helpers.attestations import cached_prepare_state_with_attestations
|
from eth2spec.test.helpers.attestations import cached_prepare_state_with_attestations
|
||||||
from eth2spec.test.helpers.deposits import mock_deposit
|
from eth2spec.test.helpers.deposits import mock_deposit
|
||||||
from eth2spec.test.helpers.state import next_epoch
|
from eth2spec.test.helpers.state import next_epoch
|
||||||
from eth2spec.utils.ssz.ssz_typing import Container, uint64, List, Bitvector
|
from eth2spec.utils.ssz.ssz_typing import Container, uint64, List
|
||||||
|
|
||||||
|
|
||||||
class Deltas(Container):
|
class Deltas(Container):
|
||||||
|
@ -314,7 +314,7 @@ def run_test_full_but_partial_participation(spec, state, rng=Random(5522)):
|
||||||
else:
|
else:
|
||||||
for index in range(len(state.validators)):
|
for index in range(len(state.validators)):
|
||||||
if rng.choice([True, False]):
|
if rng.choice([True, False]):
|
||||||
state.previous_epoch_participation[index] = Bitvector[spec.PARTICIPATION_FLAGS_LENGTH]()
|
state.previous_epoch_participation[index] = spec.ValidatorFlag(0)
|
||||||
|
|
||||||
yield from run_deltas(spec, state)
|
yield from run_deltas(spec, state)
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ def run_test_partial(spec, state, fraction_filled):
|
||||||
state.previous_epoch_attestations = state.previous_epoch_attestations[:num_attestations]
|
state.previous_epoch_attestations = state.previous_epoch_attestations[:num_attestations]
|
||||||
else:
|
else:
|
||||||
for index in range(int(len(state.validators) * fraction_filled)):
|
for index in range(int(len(state.validators) * fraction_filled)):
|
||||||
state.previous_epoch_participation[index] = Bitvector[spec.PARTICIPATION_FLAGS_LENGTH]()
|
state.previous_epoch_participation[index] = spec.ValidatorFlag(0)
|
||||||
|
|
||||||
yield from run_deltas(spec, state)
|
yield from run_deltas(spec, state)
|
||||||
|
|
||||||
|
@ -394,7 +394,7 @@ def run_test_some_very_low_effective_balances_that_did_not_attest(spec, state):
|
||||||
else:
|
else:
|
||||||
index = 0
|
index = 0
|
||||||
state.validators[index].effective_balance = 1
|
state.validators[index].effective_balance = 1
|
||||||
state.previous_epoch_participation[index] = Bitvector[spec.PARTICIPATION_FLAGS_LENGTH]()
|
state.previous_epoch_participation[index] = spec.ValidatorFlag(0)
|
||||||
|
|
||||||
yield from run_deltas(spec, state)
|
yield from run_deltas(spec, state)
|
||||||
|
|
||||||
|
@ -517,11 +517,27 @@ def run_test_full_random(spec, state, rng=Random(8020)):
|
||||||
pending_attestation.inclusion_delay = rng.randint(1, spec.SLOTS_PER_EPOCH)
|
pending_attestation.inclusion_delay = rng.randint(1, spec.SLOTS_PER_EPOCH)
|
||||||
else:
|
else:
|
||||||
for index in range(len(state.validators)):
|
for index in range(len(state.validators)):
|
||||||
# ~1/3 have bad target
|
# ~1/3 have bad head or bad target or not timely enough
|
||||||
state.previous_epoch_participation[index][spec.TIMELY_TARGET_FLAG] = rng.randint(0, 2) != 0
|
is_timely_correct_head = rng.randint(0, 2) != 0
|
||||||
# ~1/3 have bad head
|
flags = state.previous_epoch_participation[index]
|
||||||
state.previous_epoch_participation[index][spec.TIMELY_HEAD_FLAG] = rng.randint(0, 2) != 0
|
|
||||||
# ~50% participation
|
|
||||||
state.previous_epoch_participation[index][spec.TIMELY_SOURCE_FLAG] = rng.choice([True, False])
|
|
||||||
|
|
||||||
|
def set_flag(f, v):
|
||||||
|
nonlocal flags
|
||||||
|
if v:
|
||||||
|
flags |= f
|
||||||
|
else:
|
||||||
|
flags &= 0xff ^ f
|
||||||
|
|
||||||
|
set_flag(spec.TIMELY_HEAD_FLAG, is_timely_correct_head)
|
||||||
|
if is_timely_correct_head:
|
||||||
|
# If timely head, then must be timely target
|
||||||
|
set_flag(spec.TIMELY_TARGET_FLAG, True)
|
||||||
|
# If timely head, then must be timely source
|
||||||
|
set_flag(spec.TIMELY_SOURCE_FLAG, True)
|
||||||
|
else:
|
||||||
|
# ~50% of remaining have bad target or not timely enough
|
||||||
|
set_flag(spec.TIMELY_TARGET_FLAG, rng.choice([True, False]))
|
||||||
|
# ~50% of remaining have bad source or not timely enough
|
||||||
|
set_flag(spec.TIMELY_SOURCE_FLAG, rng.choice([True, False]))
|
||||||
|
state.previous_epoch_participation[index] = flags
|
||||||
yield from run_deltas(spec, state)
|
yield from run_deltas(spec, state)
|
||||||
|
|
|
@ -18,6 +18,7 @@ from eth2spec.test.context import (
|
||||||
with_all_phases_except,
|
with_all_phases_except,
|
||||||
with_configs,
|
with_configs,
|
||||||
spec_state_test,
|
spec_state_test,
|
||||||
|
always_bls,
|
||||||
)
|
)
|
||||||
from eth2spec.utils.hash_function import hash
|
from eth2spec.utils.hash_function import hash
|
||||||
|
|
||||||
|
@ -196,6 +197,7 @@ def test_sync_committee_rewards_duplicate_committee(spec, state):
|
||||||
|
|
||||||
@with_all_phases_except([PHASE0, PHASE1])
|
@with_all_phases_except([PHASE0, PHASE1])
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
def test_invalid_signature_past_block(spec, state):
|
def test_invalid_signature_past_block(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))
|
||||||
|
|
||||||
|
@ -237,6 +239,7 @@ def test_invalid_signature_past_block(spec, state):
|
||||||
@with_all_phases_except([PHASE0, PHASE1])
|
@with_all_phases_except([PHASE0, PHASE1])
|
||||||
@with_configs([MINIMAL], reason="to produce different committee sets")
|
@with_configs([MINIMAL], reason="to produce different committee sets")
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
def test_invalid_signature_previous_committee(spec, state):
|
def test_invalid_signature_previous_committee(spec, state):
|
||||||
# NOTE: the `state` provided is at genesis and the process to select
|
# NOTE: the `state` provided is at genesis and the process to select
|
||||||
# sync committees currently returns the same committee for the first and second
|
# sync committees currently returns the same committee for the first and second
|
||||||
|
|
|
@ -2,10 +2,13 @@ from eth2spec.test.context import (
|
||||||
spec_state_test,
|
spec_state_test,
|
||||||
always_bls, never_bls,
|
always_bls, never_bls,
|
||||||
with_all_phases,
|
with_all_phases,
|
||||||
|
with_all_phases_except,
|
||||||
spec_test,
|
spec_test,
|
||||||
low_balances,
|
low_balances,
|
||||||
with_custom_state,
|
with_custom_state,
|
||||||
single_phase)
|
single_phase,
|
||||||
|
PHASE1,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.attestations import (
|
from eth2spec.test.helpers.attestations import (
|
||||||
run_attestation_processing,
|
run_attestation_processing,
|
||||||
get_valid_attestation,
|
get_valid_attestation,
|
||||||
|
@ -329,3 +332,212 @@ def test_too_few_aggregation_bits(spec, state):
|
||||||
attestation.aggregation_bits = attestation.aggregation_bits[:-1]
|
attestation.aggregation_bits = attestation.aggregation_bits[:-1]
|
||||||
|
|
||||||
yield from run_attestation_processing(spec, state, attestation, False)
|
yield from run_attestation_processing(spec, state, attestation, False)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Full correct atttestation contents at different slot inclusions
|
||||||
|
#
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_correct_min_inclusion_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=True)
|
||||||
|
next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_correct_sqrt_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=True, on_time=False)
|
||||||
|
next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH))
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_correct_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=True, on_time=False)
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_correct_after_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=True, on_time=False)
|
||||||
|
|
||||||
|
# increment past latest inclusion slot
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation, False)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Incorrect head but correct source/target at different slot inclusions
|
||||||
|
#
|
||||||
|
|
||||||
|
@with_all_phases_except([PHASE1])
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_min_inclusion_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False)
|
||||||
|
next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_sqrt_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH))
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH)
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_after_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
|
||||||
|
# increment past latest inclusion slot
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1)
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation, False)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Incorrect head and target but correct source at different slot inclusions
|
||||||
|
#
|
||||||
|
|
||||||
|
# Note: current phase 1 spec checks
|
||||||
|
# `assert data.beacon_block_root == get_block_root_at_slot(state, compute_previous_slot(state.slot))`
|
||||||
|
# so this test can't pass that until phase 1 refactor is merged
|
||||||
|
@with_all_phases_except([PHASE1])
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_and_target_min_inclusion_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False)
|
||||||
|
next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_and_target_sqrt_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH))
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_and_target_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH)
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_head_and_target_after_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
# increment past latest inclusion slot
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1)
|
||||||
|
|
||||||
|
attestation.data.beacon_block_root = b'\x42' * 32
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation, False)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Correct head and source but incorrect target at different slot inclusions
|
||||||
|
#
|
||||||
|
|
||||||
|
@with_all_phases_except([PHASE1])
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_target_min_inclusion_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False)
|
||||||
|
next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||||
|
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_target_sqrt_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH))
|
||||||
|
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_target_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH)
|
||||||
|
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_incorrect_target_after_epoch_delay(spec, state):
|
||||||
|
attestation = get_valid_attestation(spec, state, signed=False, on_time=False)
|
||||||
|
# increment past latest inclusion slot
|
||||||
|
next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1)
|
||||||
|
|
||||||
|
attestation.data.target.root = b'\x42' * 32
|
||||||
|
sign_attestation(spec, state, attestation)
|
||||||
|
|
||||||
|
yield from run_attestation_processing(spec, state, attestation, False)
|
||||||
|
|
|
@ -78,10 +78,10 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support
|
||||||
else:
|
else:
|
||||||
for i, index in enumerate(committee):
|
for i, index in enumerate(committee):
|
||||||
if aggregation_bits[i]:
|
if aggregation_bits[i]:
|
||||||
epoch_participation[index][spec.TIMELY_HEAD_FLAG] = True
|
epoch_participation[index] |= spec.TIMELY_HEAD_FLAG
|
||||||
epoch_participation[index][spec.TIMELY_SOURCE_FLAG] = True
|
epoch_participation[index] |= spec.TIMELY_SOURCE_FLAG
|
||||||
if not messed_up_target:
|
if not messed_up_target:
|
||||||
epoch_participation[index][spec.TIMELY_TARGET_FLAG] = True
|
epoch_participation[index] |= spec.TIMELY_TARGET_FLAG
|
||||||
|
|
||||||
|
|
||||||
def get_checkpoints(spec, epoch):
|
def get_checkpoints(spec, epoch):
|
||||||
|
|
|
@ -29,6 +29,12 @@ def test_full_random_2(spec, state):
|
||||||
yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(3030))
|
yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(3030))
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_full_random_3(spec, state):
|
||||||
|
yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(4040))
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||||
@spec_test
|
@spec_test
|
||||||
|
|
|
@ -806,7 +806,7 @@ def test_attestation(spec, state):
|
||||||
assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root
|
assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root
|
||||||
else:
|
else:
|
||||||
for index in range(len(state.validators)):
|
for index in range(len(state.validators)):
|
||||||
assert state.current_epoch_participation[index] == spec.Bitvector[spec.PARTICIPATION_FLAGS_LENGTH]()
|
assert state.current_epoch_participation[index] == 0
|
||||||
assert spec.hash_tree_root(state.previous_epoch_participation) == pre_current_epoch_participation_root
|
assert spec.hash_tree_root(state.previous_epoch_participation) == pre_current_epoch_participation_root
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue