executable light client patch: beacon-chain.md (#2141)

* Bump remerkleable to 0.1.18

* Disable `sync-protocol.md` for now. Make linter pass

* Enable lightclient tests

* Use *new* `optional_fast_aggregate_verify`

* Fix ToC and codespell

* Do not run phase1 tests with Lightclient patch

* Fix the Eth1Data casting bug. Add a workaround.

* Fix `run_on_attestation` testing helper

* Revert

* Rename `optional_fast_aggregate_verify` to `eth2_fast_aggregate_verify`

* Apply Proto's suggestion

* Apply Danny's suggestion

* Fixing tests

* Fix after rebasing

* Rename `LIGHTCLIENT` -> `LIGHTCLIENT_PATCH`

* New doctoc

* Add lightclient patch configs

* fix gitignore light client patch generator output

* Upgrade state for light client patch

* Add `lightclient-fork.md` to deal the fork boundary and fix
`process_block_header`

* Misc cleanups

1) Add a summary note for every function that is changed.
2) Avoid changing `process_block` (instead only change `process_block_header`).
3) Rename `G2_INFINITY_POINT_SIG` to `G2_POINT_AT_INFINITY` to avoid `SIG` contraction.
4) Misc cleanups

* Update block.py

* Update beacon-chain.md

* Fix typo "minimal" -> "mainnet"

Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>

* Use the new `BeaconBlockHeader` instead of phase 0 version

* Update config files

* Move `sync_committee_bits` and `sync_committee_signature` back to `BeaconBlockBody`

Co-authored-by: protolambda <proto@protolambda.com>
Co-authored-by: Justin <drakefjustin@gmail.com>
Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
This commit is contained in:
Hsiao-Wei Wang 2020-12-15 13:18:20 +08:00 committed by GitHub
parent 1a30ea9da9
commit acfe49e3f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 340 additions and 114 deletions

2
.gitignore vendored
View File

@ -17,7 +17,7 @@ eth2.0-spec-tests/
# Dynamically built from Markdown spec # Dynamically built from Markdown spec
tests/core/pyspec/eth2spec/phase0/ tests/core/pyspec/eth2spec/phase0/
tests/core/pyspec/eth2spec/phase1/ tests/core/pyspec/eth2spec/phase1/
tests/core/pyspec/eth2spec/lightclient/ tests/core/pyspec/eth2spec/lightclient_patch/
# coverage reports # coverage reports
.htmlcov .htmlcov

View File

@ -86,11 +86,11 @@ install_test:
test: pyspec test: pyspec
. venv/bin/activate; cd $(PY_SPEC_DIR); \ . venv/bin/activate; cd $(PY_SPEC_DIR); \
python -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec python -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov=eth2spec.lightclient_patch.spec -cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
find_test: pyspec find_test: pyspec
. venv/bin/activate; cd $(PY_SPEC_DIR); \ . venv/bin/activate; cd $(PY_SPEC_DIR); \
python -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec python -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov=eth2spec.lightclient_patch.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
citest: pyspec citest: pyspec
mkdir -p tests/core/pyspec/test-reports/eth2spec; . venv/bin/activate; cd $(PY_SPEC_DIR); \ mkdir -p tests/core/pyspec/test-reports/eth2spec; . venv/bin/activate; cd $(PY_SPEC_DIR); \
@ -113,7 +113,7 @@ codespell:
lint: pyspec lint: pyspec
. venv/bin/activate; cd $(PY_SPEC_DIR); \ . venv/bin/activate; cd $(PY_SPEC_DIR); \
flake8 --config $(LINTER_CONFIG_FILE) ./eth2spec \ flake8 --config $(LINTER_CONFIG_FILE) ./eth2spec \
&& mypy --config-file $(LINTER_CONFIG_FILE) -p eth2spec.phase0 -p eth2spec.phase1 -p eth2spec.lightclient && mypy --config-file $(LINTER_CONFIG_FILE) -p eth2spec.phase0 -p eth2spec.phase1 -p eth2spec.lightclient_patch
lint_generators: pyspec lint_generators: pyspec
. venv/bin/activate; cd $(TEST_GENERATORS_DIR); \ . venv/bin/activate; cd $(TEST_GENERATORS_DIR); \

View File

@ -0,0 +1,21 @@
# Mainnet preset - lightclient patch
CONFIG_NAME: "mainnet"
# Misc
# ---------------------------------------------------------------
# 2**10 (=1,024)
SYNC_COMMITTEE_SIZE: 1024
# 2**6 (=64)
SYNC_COMMITTEE_PUBKEY_AGGREGATES_SIZE: 64
# Time parameters
# ---------------------------------------------------------------
# 2**8 (= 256)
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 256
# Signature domains
# ---------------------------------------------------------------
DOMAIN_SYNC_COMMITTEE: 0x07000000

View File

@ -0,0 +1,21 @@
# Minimal preset - lightclient patch
CONFIG_NAME: "minimal"
# Misc
# ---------------------------------------------------------------
# [customized]
SYNC_COMMITTEE_SIZE: 64
# [customized]
SYNC_COMMITTEE_PUBKEY_AGGREGATES_SIZE: 16
# Time parameters
# ---------------------------------------------------------------
# 2**8 (= 256)
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 256
# Signature domains
# ---------------------------------------------------------------
DOMAIN_SYNC_COMMITTEE: 0x07000000

View File

@ -173,7 +173,7 @@ from lru import LRU
from eth2spec.utils.ssz.ssz_impl import hash_tree_root, copy, uint_to_bytes from eth2spec.utils.ssz.ssz_impl import hash_tree_root, copy, uint_to_bytes
from eth2spec.utils.ssz.ssz_typing import ( from eth2spec.utils.ssz.ssz_typing import (
View, boolean, Container, List, Vector, uint8, uint32, uint64, View, boolean, Container, List, Vector, uint8, uint32, uint64,
Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
) )
from eth2spec.utils import bls from eth2spec.utils import bls
@ -386,7 +386,7 @@ def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:
fork_imports = { fork_imports = {
'phase0': PHASE0_IMPORTS, 'phase0': PHASE0_IMPORTS,
'phase1': PHASE1_IMPORTS, 'phase1': PHASE1_IMPORTS,
'lightclient': LIGHTCLIENT_IMPORT, 'lightclient_patch': LIGHTCLIENT_IMPORT,
} }
@ -453,15 +453,16 @@ class PySpecCommand(Command):
specs/phase1/shard-fork-choice.md specs/phase1/shard-fork-choice.md
specs/phase1/validator.md specs/phase1/validator.md
""" """
elif self.spec_fork == "lightclient": elif self.spec_fork == "lightclient_patch":
self.md_doc_paths = """ self.md_doc_paths = """
specs/phase0/beacon-chain.md specs/phase0/beacon-chain.md
specs/phase0/fork-choice.md specs/phase0/fork-choice.md
specs/phase0/validator.md specs/phase0/validator.md
specs/phase0/weak-subjectivity.md specs/phase0/weak-subjectivity.md
specs/lightclient/beacon-chain.md specs/lightclient/beacon-chain.md
specs/lightclient/sync-protocol.md specs/lightclient/lightclient-fork.md
""" """
# TODO: add specs/lightclient/sync-protocol.md back when the GeneralizedIndex helpers are included.
else: else:
raise Exception('no markdown files specified, and spec fork "%s" is unknown', self.spec_fork) raise Exception('no markdown files specified, and spec fork "%s" is unknown', self.spec_fork)
@ -584,7 +585,7 @@ setup(
"py_ecc==5.0.0", "py_ecc==5.0.0",
"milagro_bls_binding==1.5.0", "milagro_bls_binding==1.5.0",
"dataclasses==0.6", "dataclasses==0.6",
"remerkleable==0.1.17", "remerkleable==0.1.18",
"ruamel.yaml==0.16.5", "ruamel.yaml==0.16.5",
"lru-dict==1.1.6" "lru-dict==1.1.6"
] ]

View File

@ -6,10 +6,10 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- 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)
- [Constants](#constants) - [Constants](#constants)
- [Configuration](#configuration) - [Configuration](#configuration)
- [Constants](#constants-1)
- [Misc](#misc) - [Misc](#misc)
- [Time parameters](#time-parameters) - [Time parameters](#time-parameters)
- [Domain types](#domain-types) - [Domain types](#domain-types)
@ -20,12 +20,15 @@
- [New containers](#new-containers) - [New containers](#new-containers)
- [`SyncCommittee`](#synccommittee) - [`SyncCommittee`](#synccommittee)
- [Helper functions](#helper-functions) - [Helper functions](#helper-functions)
- [`Predicates`](#predicates)
- [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify)
- [Beacon state accessors](#beacon-state-accessors) - [Beacon state accessors](#beacon-state-accessors)
- [`get_sync_committee_indices`](#get_sync_committee_indices) - [`get_sync_committee_indices`](#get_sync_committee_indices)
- [`get_sync_committee`](#get_sync_committee) - [`get_sync_committee`](#get_sync_committee)
- [Block processing](#block-processing) - [Block processing](#block-processing)
- [Sync committee processing](#sync-committee-processing) - [Sync committee processing](#sync-committee-processing)
- [Epoch processing](#epoch-processing) - [Epoch processing](#epoch-processing)
- [Components of attestation deltas](#components-of-attestation-deltas)
- [Final updates](#final-updates) - [Final updates](#final-updates)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@ -43,6 +46,12 @@ This is a standalone beacon chain patch adding light client support via sync com
## Configuration ## Configuration
### Constants
| Name | Value |
| - | - |
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
### Misc ### Misc
| Name | Value | | Name | Value |
@ -69,25 +78,15 @@ This is a standalone beacon chain patch adding light client support via sync com
*Note*: Extended SSZ containers inherit all fields from the parent in the original *Note*: Extended SSZ containers inherit all fields from the parent in the original
order and append any additional fields to the end. order and append any additional fields to the end.
#### `BeaconBlock` #### `BeaconBlockBody`
```python ```python
class BeaconBlock(phase0.BeaconBlock): class BeaconBlockBody(phase0.BeaconBlockBody):
# Sync committee aggregate signature # Sync committee aggregate signature
sync_committee_bits: Bitvector[SYNC_COMMITTEE_SIZE] sync_committee_bits: Bitvector[SYNC_COMMITTEE_SIZE]
sync_committee_signature: BLSSignature sync_committee_signature: BLSSignature
``` ```
#### `BeaconBlockHeader`
```python
class BeaconBlockHeader(phase0.BeaconBlockHeader):
# Sync committee aggregate signature
sync_committee_bits: Bitvector[SYNC_COMMITTEE_SIZE]
sync_committee_signature: BLSSignature
```
#### `BeaconState` #### `BeaconState`
```python ```python
@ -109,6 +108,20 @@ class SyncCommittee(Container):
## Helper functions ## Helper functions
### `Predicates`
#### `eth2_fast_aggregate_verify`
```python
def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool:
"""
Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty.
"""
if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY:
return True
return bls.FastAggregateVerify(pubkeys, message, signature)
```
### Beacon state accessors ### Beacon state accessors
#### `get_sync_committee_indices` #### `get_sync_committee_indices`
@ -117,13 +130,14 @@ class SyncCommittee(Container):
def get_sync_committee_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]: def get_sync_committee_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
""" """
Return the sync committee indices for a given state and epoch. Return the sync committee indices for a given state and epoch.
""" """
MAX_RANDOM_BYTE = 2**8 - 1 MAX_RANDOM_BYTE = 2**8 - 1
base_epoch = Epoch((max(epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD, 1) - 1) * EPOCHS_PER_SYNC_COMMITTEE_PERIOD) base_epoch = Epoch((max(epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD, 1) - 1) * EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
active_validator_indices = get_active_validator_indices(state, base_epoch) active_validator_indices = get_active_validator_indices(state, base_epoch)
active_validator_count = uint64(len(active_validator_indices)) active_validator_count = uint64(len(active_validator_indices))
seed = get_seed(state, base_epoch, DOMAIN_SYNC_COMMITTEE) seed = get_seed(state, base_epoch, DOMAIN_SYNC_COMMITTEE)
i, sync_committee_indices = 0, [] i = 0
sync_committee_indices: List[ValidatorIndex] = []
while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE:
shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed) shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed)
candidate_index = active_validator_indices[shuffled_index] candidate_index = active_validator_indices[shuffled_index]
@ -156,41 +170,74 @@ def get_sync_committee(state: BeaconState, epoch: Epoch) -> SyncCommittee:
```python ```python
def process_block(state: BeaconState, block: BeaconBlock) -> None: def process_block(state: BeaconState, block: BeaconBlock) -> None:
phase0.process_block(state, block) process_block_header(state, block)
process_sync_committee(state, block) process_randao(state, block.body)
process_eth1_data(state, block.body)
process_operations(state, block.body)
# Light client support
process_sync_committee(state, block.body)
``` ```
#### Sync committee processing #### Sync committee processing
```python ```python
def process_sync_committee(state: BeaconState, block: BeaconBlock) -> None: def process_sync_committee(state: BeaconState, body: BeaconBlockBody) -> None:
# Verify sync committee aggregate signature signing over the previous slot block root # Verify sync committee aggregate signature signing over the previous slot block root
previous_slot = Slot(max(state.slot, 1) - 1) previous_slot = Slot(max(int(state.slot), 1) - 1)
committee_indices = get_sync_committee_indices(state, get_current_epoch(state)) committee_indices = get_sync_committee_indices(state, get_current_epoch(state))
participant_indices = [index for index, bit in zip(committee_indices, body.sync_committee_bits) if bit] participant_indices = [index for index, bit in zip(committee_indices, body.sync_committee_bits) if bit]
committee_pubkeys = state.current_sync_committee.pubkeys committee_pubkeys = state.current_sync_committee.pubkeys
participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, body.sync_committee_bits) if bit] participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, body.sync_committee_bits) if bit]
domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot)) domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot))
signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain) signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain)
assert bls.FastAggregateVerify(participant_pubkeys, signing_root, block.sync_committee_signature) assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, body.sync_committee_signature)
# Reward sync committee participants # Reward sync committee participants
participant_rewards = Gwei(0) proposer_reward = Gwei(0)
active_validator_count = uint64(len(get_active_validator_indices(state, get_current_epoch(state)))) active_validator_count = uint64(len(get_active_validator_indices(state, get_current_epoch(state))))
for participant_index in participant_indices: for participant_index in participant_indices:
base_reward = get_base_reward(state, participant_index) base_reward = get_base_reward(state, participant_index)
reward = Gwei(base_reward * active_validator_count // len(committee_indices) // SLOTS_PER_EPOCH) max_participant_reward = base_reward - base_reward // PROPOSER_REWARD_QUOTIENT
reward = Gwei(max_participant_reward * active_validator_count // len(committee_indices) // SLOTS_PER_EPOCH)
increase_balance(state, participant_index, reward) increase_balance(state, participant_index, reward)
participant_rewards += reward proposer_reward += base_reward // PROPOSER_REWARD_QUOTIENT
# Reward beacon proposer # Reward beacon proposer
increase_balance(state, get_beacon_proposer_index(state), Gwei(participant_rewards // PROPOSER_REWARD_QUOTIENT)) increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
``` ```
### Epoch processing ### Epoch processing
#### Components of attestation deltas
*Note*: The function `get_inactivity_penalty_deltas` is modified with `BASE_REWARDS_PER_EPOCH` replaced by `BASE_REWARDS_PER_EPOCH - 1`.
```python
def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
"""
Return inactivity reward/penalty deltas for each validator.
"""
penalties = [Gwei(0) for _ in range(len(state.validators))]
if is_in_inactivity_leak(state):
matching_target_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
matching_target_attesting_indices = get_unslashed_attesting_indices(state, matching_target_attestations)
for index in get_eligible_validator_indices(state):
# Penalize validator so that optimal attestation performance is rewarded with one base reward per epoch
base_reward = get_base_reward(state, index)
penalties[index] += Gwei((BASE_REWARDS_PER_EPOCH - 1) * base_reward - get_proposer_reward(state, index))
if index not in matching_target_attesting_indices:
effective_balance = state.validators[index].effective_balance
penalties[index] += Gwei(effective_balance * get_finality_delay(state) // INACTIVITY_PENALTY_QUOTIENT)
# No rewards associated with inactivity penalties
rewards = [Gwei(0) for _ in range(len(state.validators))]
return rewards, penalties
```
#### Final updates #### Final updates
*Note*: The function `process_final_updates` is modified to handle sync committee updates.
```python ```python
def process_final_updates(state: BeaconState) -> None: def process_final_updates(state: BeaconState) -> None:
phase0.process_final_updates(state) phase0.process_final_updates(state)

View File

@ -0,0 +1,83 @@
# Ethereum 2.0 Light Client Support -- From Phase 0 to Light Client Patch
**Notice**: This document is a work-in-progress for researchers and implementers.
## Table of contents
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Introduction](#introduction)
- [Configuration](#configuration)
- [Fork to Light-client patch](#fork-to-light-client-patch)
- [Fork trigger](#fork-trigger)
- [Upgrading the state](#upgrading-the-state)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Introduction
This document describes the process of moving from Phase 0 to Phase 1 of Ethereum 2.0.
## Configuration
Warning: this configuration is not definitive.
| Name | Value |
| - | - |
| `LIGHTCLIENT_PATCH_FORK_VERSION` | `Version('0x01000000')` |
| `LIGHTCLIENT_PATCH_FORK_SLOT` | `Slot(0)` **TBD** |
## Fork to Light-client patch
### Fork trigger
TBD. Social consensus, along with state conditions such as epoch boundary, finality, deposits, active validator count, etc. may be part of the decision process to trigger the fork. For now we assume the condition will be triggered at slot `LIGHTCLIENT_PATCH_FORK_SLOT`, where `LIGHTCLIENT_PATCH_FORK_SLOT % SLOTS_PER_EPOCH == 0`.
### Upgrading the state
After `process_slots` of Phase 0 finishes, if `state.slot == LIGHTCLIENT_PATCH_FORK_SLOT`, an irregular state change is made to upgrade to light-client patch.
```python
def upgrade_to_lightclient_patch(pre: phase0.BeaconState) -> BeaconState:
epoch = get_current_epoch(pre)
post = BeaconState(
genesis_time=pre.genesis_time,
slot=pre.slot,
fork=Fork(
previous_version=pre.fork.current_version,
current_version=LIGHTCLIENT_PATCH_FORK_VERSION,
epoch=epoch,
),
# History
latest_block_header=pre.latest_block_header,
block_roots=pre.block_roots,
state_roots=pre.state_roots,
historical_roots=pre.historical_roots,
# Eth1
eth1_data=pre.eth1_data,
eth1_data_votes=pre.eth1_data_votes,
eth1_deposit_index=pre.eth1_deposit_index,
# Registry
validators=pre.validators,
balances=pre.balances,
# Randomness
randao_mixes=pre.randao_mixes,
# Slashings
slashings=pre.slashings,
# Attestations
# previous_epoch_attestations is cleared on upgrade.
previous_epoch_attestations=List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH](),
# empty in pre state, since the upgrade is performed just after an epoch boundary.
current_epoch_attestations=List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH](),
# Finality
justification_bits=pre.justification_bits,
previous_justified_checkpoint=pre.previous_justified_checkpoint,
current_justified_checkpoint=pre.current_justified_checkpoint,
finalized_checkpoint=pre.finalized_checkpoint,
# Light-client
current_sync_committee=SyncCommittee(),
next_sync_committee=SyncCommittee(),
)
return post
```

View File

@ -8,7 +8,6 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- 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)
- [Constants](#constants) - [Constants](#constants)
- [Configuration](#configuration) - [Configuration](#configuration)
@ -100,7 +99,7 @@ class LightClientStore(Container):
## Light client state updates ## Light client state updates
A light client maintains its state in a `store` object of type `LightClientStore` and receives `update` objects of type `LightClientUpdate`. Every `update` triggers `process_light_client_update(store, update, current_slot)` where `current_slot` is the currect slot based on some local clock. A light client maintains its state in a `store` object of type `LightClientStore` and receives `update` objects of type `LightClientUpdate`. Every `update` triggers `process_light_client_update(store, update, current_slot)` where `current_slot` is the current slot based on some local clock.
#### `is_valid_light_client_update` #### `is_valid_light_client_update`

View File

@ -327,7 +327,9 @@ def get_eth1_vote(state: BeaconState, eth1_chain: Sequence[Eth1Block]) -> Eth1Da
valid_votes = [vote for vote in state.eth1_data_votes if vote in votes_to_consider] valid_votes = [vote for vote in state.eth1_data_votes if vote in votes_to_consider]
# Default vote on latest eth1 block data in the period range unless eth1 chain is not live # Default vote on latest eth1 block data in the period range unless eth1 chain is not live
default_vote = votes_to_consider[len(votes_to_consider) - 1] if any(votes_to_consider) else state.eth1_data # Non-substantive casting for linter
state_eth1_data: Eth1Data = state.eth1_data
default_vote = votes_to_consider[len(votes_to_consider) - 1] if any(votes_to_consider) else state_eth1_data
return max( return max(
valid_votes, valid_votes,

View File

@ -2,6 +2,7 @@ import pytest
from eth2spec.phase0 import spec as spec_phase0 from eth2spec.phase0 import spec as spec_phase0
from eth2spec.phase1 import spec as spec_phase1 from eth2spec.phase1 import spec as spec_phase1
from eth2spec.lightclient_patch import spec as spec_lightclient_patch
from eth2spec.utils import bls from eth2spec.utils import bls
from .exceptions import SkippedTest from .exceptions import SkippedTest
@ -19,6 +20,7 @@ from importlib import reload
def reload_specs(): def reload_specs():
reload(spec_phase0) reload(spec_phase0)
reload(spec_phase1) reload(spec_phase1)
reload(spec_lightclient_patch)
# Some of the Spec module functionality is exposed here to deal with phase-specific changes. # Some of the Spec module functionality is exposed here to deal with phase-specific changes.
@ -28,7 +30,9 @@ ConfigName = NewType("ConfigName", str)
PHASE0 = SpecForkName('phase0') PHASE0 = SpecForkName('phase0')
PHASE1 = SpecForkName('phase1') PHASE1 = SpecForkName('phase1')
ALL_PHASES = (PHASE0, PHASE1) LIGHTCLIENT_PATCH = SpecForkName('lightclient_patch')
ALL_PHASES = (PHASE0, PHASE1, LIGHTCLIENT_PATCH)
MAINNET = ConfigName('mainnet') MAINNET = ConfigName('mainnet')
MINIMAL = ConfigName('minimal') MINIMAL = ConfigName('minimal')
@ -47,14 +51,18 @@ class SpecPhase0(Spec):
class SpecPhase1(Spec): class SpecPhase1(Spec):
def upgrade_to_phase1(self, state: spec_phase0.BeaconState) -> spec_phase1.BeaconState: ...
...
class SpecLightclient(Spec):
...
# add transfer, bridge, etc. as the spec evolves # add transfer, bridge, etc. as the spec evolves
class SpecForks(TypedDict, total=False): class SpecForks(TypedDict, total=False):
PHASE0: SpecPhase0 PHASE0: SpecPhase0
PHASE1: SpecPhase1 PHASE1: SpecPhase1
LIGHTCLIENT_PATCH: SpecLightclient
def _prepare_state(balances_fn: Callable[[Any], Sequence[int]], threshold_fn: Callable[[Any], int], def _prepare_state(balances_fn: Callable[[Any], Sequence[int]], threshold_fn: Callable[[Any], int],
@ -70,6 +78,8 @@ def _prepare_state(balances_fn: Callable[[Any], Sequence[int]], threshold_fn: Ca
# TODO: instead of upgrading a test phase0 genesis state we can also write a phase1 state helper. # TODO: instead of upgrading a test phase0 genesis state we can also write a phase1 state helper.
# Decide based on performance/consistency results later. # Decide based on performance/consistency results later.
state = phases[PHASE1].upgrade_to_phase1(state) state = phases[PHASE1].upgrade_to_phase1(state)
elif spec.fork == LIGHTCLIENT_PATCH: # not generalizing this just yet, unclear final spec fork/patch order.
state = phases[LIGHTCLIENT_PATCH].upgrade_to_lightclient_patch(state)
return state return state
@ -337,12 +347,16 @@ def with_phases(phases, other_phases=None):
phase_dir[PHASE0] = spec_phase0 phase_dir[PHASE0] = spec_phase0
if PHASE1 in available_phases: if PHASE1 in available_phases:
phase_dir[PHASE1] = spec_phase1 phase_dir[PHASE1] = spec_phase1
if LIGHTCLIENT_PATCH in available_phases:
phase_dir[LIGHTCLIENT_PATCH] = spec_lightclient_patch
# return is ignored whenever multiple phases are ran. If # return is ignored whenever multiple phases are ran. If
if PHASE0 in run_phases: if PHASE0 in run_phases:
ret = fn(spec=spec_phase0, phases=phase_dir, *args, **kw) ret = fn(spec=spec_phase0, phases=phase_dir, *args, **kw)
if PHASE1 in run_phases: if PHASE1 in run_phases:
ret = fn(spec=spec_phase1, phases=phase_dir, *args, **kw) ret = fn(spec=spec_phase1, phases=phase_dir, *args, **kw)
if LIGHTCLIENT_PATCH in run_phases:
ret = fn(spec=spec_lightclient_patch, phases=phase_dir, *args, **kw)
return ret return ret
return wrapper return wrapper
return decorator return decorator

View File

@ -1,3 +1,4 @@
from eth2spec.test.context import LIGHTCLIENT_PATCH
from eth2spec.test.helpers.keys import privkeys from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils import bls from eth2spec.utils import bls
from eth2spec.utils.bls import only_with_bls from eth2spec.utils.bls import only_with_bls
@ -89,6 +90,10 @@ def build_empty_block(spec, state, slot=None):
empty_block.proposer_index = spec.get_beacon_proposer_index(state) empty_block.proposer_index = spec.get_beacon_proposer_index(state)
empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index
empty_block.parent_root = parent_block_root empty_block.parent_root = parent_block_root
if spec.fork == LIGHTCLIENT_PATCH:
empty_block.body.sync_committee_signature = spec.G2_POINT_AT_INFINITY
apply_randao_reveal(spec, state, empty_block) apply_randao_reveal(spec, state, empty_block)
return empty_block return empty_block

View File

@ -2,6 +2,7 @@ from random import Random
from lru import LRU from lru import LRU
from eth2spec.phase0 import spec as spec_phase0 from eth2spec.phase0 import spec as spec_phase0
from eth2spec.test.context import 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
@ -159,8 +160,12 @@ def run_get_inactivity_penalty_deltas(spec, state):
continue continue
if spec.is_in_inactivity_leak(state): if spec.is_in_inactivity_leak(state):
if spec.fork == LIGHTCLIENT_PATCH:
cancel_base_rewards_per_epoch = spec.BASE_REWARDS_PER_EPOCH - 1
else:
cancel_base_rewards_per_epoch = spec.BASE_REWARDS_PER_EPOCH
base_reward = spec.get_base_reward(state, index) base_reward = spec.get_base_reward(state, index)
base_penalty = spec.BASE_REWARDS_PER_EPOCH * base_reward - spec.get_proposer_reward(state, index) base_penalty = cancel_base_rewards_per_epoch * base_reward - spec.get_proposer_reward(state, index)
if not has_enough_for_reward(spec, state, index): if not has_enough_for_reward(spec, state, index):
assert penalties[index] == 0 assert penalties[index] == 0
elif index in matching_attesting_indices: elif index in matching_attesting_indices:

View File

@ -1,4 +1,5 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
LIGHTCLIENT_PATCH,
spec_state_test, spec_test, spec_state_test, spec_test,
with_all_phases, single_phase, with_all_phases, single_phase,
with_phases, PHASE0, with_phases, PHASE0,
@ -162,6 +163,9 @@ def run_with_participation(spec, state, participation_fn):
pre_state = state.copy() pre_state = state.copy()
if spec.fork == LIGHTCLIENT_PATCH:
sync_committee_indices = spec.get_sync_committee_indices(state, spec.get_current_epoch(state))
yield from run_process_rewards_and_penalties(spec, state) yield from run_process_rewards_and_penalties(spec, state)
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations) attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
@ -172,9 +176,13 @@ def run_with_participation(spec, state, participation_fn):
# Proposers can still make money during a leak # Proposers can still make money during a leak
if index in proposer_indices and index in participated: if index in proposer_indices and index in participated:
assert state.balances[index] > pre_state.balances[index] assert state.balances[index] > pre_state.balances[index]
# If not proposer but participated optimally, should have exactly neutral balance
elif index in attesting_indices: elif index in attesting_indices:
assert state.balances[index] == pre_state.balances[index] if spec.fork == LIGHTCLIENT_PATCH and index in sync_committee_indices:
# The sync committee reward has not been canceled, so the sync committee participants still earn it
assert state.balances[index] >= pre_state.balances[index]
else:
# If not proposer but participated optimally, should have exactly neutral balance
assert state.balances[index] == pre_state.balances[index]
else: else:
assert state.balances[index] < pre_state.balances[index] assert state.balances[index] < pre_state.balances[index]
else: else:

View File

@ -1,4 +1,4 @@
from eth2spec.test.context import PHASE0, with_all_phases, spec_state_test from eth2spec.test.context import PHASE0, PHASE1, LIGHTCLIENT_PATCH, with_all_phases, spec_state_test
from eth2spec.test.helpers.block import build_empty_block_for_next_slot from eth2spec.test.helpers.block import build_empty_block_for_next_slot
from eth2spec.test.helpers.attestations import get_valid_attestation, sign_attestation from eth2spec.test.helpers.attestations import get_valid_attestation, sign_attestation
from eth2spec.test.helpers.state import transition_to, state_transition_and_sign_block, next_epoch, next_slot from eth2spec.test.helpers.state import transition_to, state_transition_and_sign_block, next_epoch, next_slot
@ -18,12 +18,12 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
spec.on_attestation(store, attestation) spec.on_attestation(store, attestation)
sample_index = indexed_attestation.attesting_indices[0] sample_index = indexed_attestation.attesting_indices[0]
if spec.fork == PHASE0: if spec.fork in (PHASE0, LIGHTCLIENT_PATCH):
latest_message = spec.LatestMessage( latest_message = spec.LatestMessage(
epoch=attestation.data.target.epoch, epoch=attestation.data.target.epoch,
root=attestation.data.beacon_block_root, root=attestation.data.beacon_block_root,
) )
else: elif spec.fork == PHASE1:
latest_message = spec.LatestMessage( latest_message = spec.LatestMessage(
epoch=attestation.data.target.epoch, epoch=attestation.data.target.epoch,
root=attestation.data.beacon_block_root, root=attestation.data.beacon_block_root,

View File

@ -1,5 +1,6 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
with_all_phases_except, with_all_phases_except,
spec_state_test, spec_state_test,
always_bls, always_bls,
@ -12,7 +13,7 @@ from eth2spec.test.helpers.attestations import (
) )
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_on_time_success(spec, state): def test_on_time_success(spec, state):
@ -23,7 +24,7 @@ def test_on_time_success(spec, state):
yield from run_attestation_processing(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_late_success(spec, state): def test_late_success(spec, state):

View File

@ -9,6 +9,7 @@ from eth2spec.test.helpers.attestations import (
from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
MINIMAL, MINIMAL,
expect_assertion_error, expect_assertion_error,
disable_process_reveal_deadlines, disable_process_reveal_deadlines,
@ -68,7 +69,7 @@ def run_custody_chunk_response_processing(spec, state, custody_response, valid=T
yield 'post', state yield 'post', state
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@ -92,7 +93,7 @@ def test_challenge_appended(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge) yield from run_chunk_challenge_processing(spec, state, challenge)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -118,7 +119,7 @@ def test_challenge_empty_element_replaced(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge) yield from run_chunk_challenge_processing(spec, state, challenge)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -144,7 +145,7 @@ def test_duplicate_challenge(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge, valid=False) yield from run_chunk_challenge_processing(spec, state, challenge, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -172,7 +173,7 @@ def test_second_challenge(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge1) yield from run_chunk_challenge_processing(spec, state, challenge1)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -197,7 +198,7 @@ def test_multiple_epochs_custody(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge) yield from run_chunk_challenge_processing(spec, state, challenge)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -222,7 +223,7 @@ def test_many_epochs_custody(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge) yield from run_chunk_challenge_processing(spec, state, challenge)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -243,7 +244,7 @@ def test_off_chain_attestation(spec, state):
yield from run_chunk_challenge_processing(spec, state, challenge) yield from run_chunk_challenge_processing(spec, state, challenge)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -275,7 +276,7 @@ def test_custody_response(spec, state):
yield from run_custody_chunk_response_processing(spec, state, custody_response) yield from run_custody_chunk_response_processing(spec, state, custody_response)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -306,7 +307,7 @@ def test_custody_response_chunk_index_2(spec, state):
yield from run_custody_chunk_response_processing(spec, state, custody_response) yield from run_custody_chunk_response_processing(spec, state, custody_response)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -338,7 +339,7 @@ def test_custody_response_multiple_epochs(spec, state):
yield from run_custody_chunk_response_processing(spec, state, custody_response) yield from run_custody_chunk_response_processing(spec, state, custody_response)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")

View File

@ -1,6 +1,7 @@
from eth2spec.test.helpers.custody import get_valid_custody_key_reveal from eth2spec.test.helpers.custody import get_valid_custody_key_reveal
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
with_all_phases_except, with_all_phases_except,
spec_state_test, spec_state_test,
expect_assertion_error, expect_assertion_error,
@ -39,7 +40,7 @@ def run_custody_key_reveal_processing(spec, state, custody_key_reveal, valid=Tru
yield 'post', state yield 'post', state
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_success(spec, state): def test_success(spec, state):
@ -49,7 +50,7 @@ def test_success(spec, state):
yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal) yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_reveal_too_early(spec, state): def test_reveal_too_early(spec, state):
@ -58,7 +59,7 @@ def test_reveal_too_early(spec, state):
yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal, False) yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal, False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_wrong_period(spec, state): def test_wrong_period(spec, state):
@ -67,7 +68,7 @@ def test_wrong_period(spec, state):
yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal, False) yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal, False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_late_reveal(spec, state): def test_late_reveal(spec, state):
@ -77,7 +78,7 @@ def test_late_reveal(spec, state):
yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal) yield from run_custody_key_reveal_processing(spec, state, custody_key_reveal)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_double_reveal(spec, state): def test_double_reveal(spec, state):

View File

@ -11,6 +11,7 @@ from eth2spec.test.helpers.state import get_balance, transition_to
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
MINIMAL, MINIMAL,
LIGHTCLIENT_PATCH,
with_all_phases_except, with_all_phases_except,
spec_state_test, spec_state_test,
expect_assertion_error, expect_assertion_error,
@ -112,7 +113,7 @@ def run_standard_custody_slashing_test(spec,
yield from run_custody_slashing_processing(spec, state, slashing, valid=valid, correct=correct) yield from run_custody_slashing_processing(spec, state, slashing, valid=valid, correct=correct)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -120,7 +121,7 @@ def test_custody_slashing(spec, state):
yield from run_standard_custody_slashing_test(spec, state) yield from run_standard_custody_slashing_test(spec, state)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -128,7 +129,7 @@ def test_incorrect_custody_slashing(spec, state):
yield from run_standard_custody_slashing_test(spec, state, correct=False) yield from run_standard_custody_slashing_test(spec, state, correct=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -136,7 +137,7 @@ def test_multiple_epochs_custody(spec, state):
yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 3) yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 3)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
@ -144,7 +145,7 @@ def test_many_epochs_custody(spec, state):
yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 5) yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 5)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@disable_process_reveal_deadlines @disable_process_reveal_deadlines
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")

View File

@ -2,6 +2,7 @@ from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal
from eth2spec.test.helpers.state import next_epoch_via_block, get_balance from eth2spec.test.helpers.state import next_epoch_via_block, get_balance
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
with_all_phases_except, with_all_phases_except,
spec_state_test, spec_state_test,
expect_assertion_error, expect_assertion_error,
@ -41,7 +42,7 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v
yield 'post', state yield 'post', state
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_success(spec, state): def test_success(spec, state):
@ -50,7 +51,7 @@ def test_success(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@never_bls @never_bls
def test_reveal_from_current_epoch(spec, state): def test_reveal_from_current_epoch(spec, state):
@ -59,7 +60,7 @@ def test_reveal_from_current_epoch(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@never_bls @never_bls
def test_reveal_from_past_epoch(spec, state): def test_reveal_from_past_epoch(spec, state):
@ -69,7 +70,7 @@ def test_reveal_from_past_epoch(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_reveal_with_custody_padding(spec, state): def test_reveal_with_custody_padding(spec, state):
@ -81,7 +82,7 @@ def test_reveal_with_custody_padding(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_reveal_with_custody_padding_minus_one(spec, state): def test_reveal_with_custody_padding_minus_one(spec, state):
@ -93,7 +94,7 @@ def test_reveal_with_custody_padding_minus_one(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@never_bls @never_bls
def test_double_reveal(spec, state): def test_double_reveal(spec, state):
@ -114,7 +115,7 @@ def test_double_reveal(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal2, False) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal2, False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@never_bls @never_bls
def test_revealer_is_slashed(spec, state): def test_revealer_is_slashed(spec, state):
@ -124,7 +125,7 @@ def test_revealer_is_slashed(spec, state):
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@never_bls @never_bls
def test_far_future_epoch(spec, state): def test_far_future_epoch(spec, state):

View File

@ -1,5 +1,6 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
with_all_phases_except, with_all_phases_except,
only_full_crosslink, only_full_crosslink,
spec_state_test, spec_state_test,
@ -90,21 +91,21 @@ def run_successful_crosslink_tests(spec, state, target_len_offset_slot):
assert bool(pending_attestation.crosslink_success) is True assert bool(pending_attestation.crosslink_success) is True
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_basic_crosslinks(spec, state): def test_basic_crosslinks(spec, state):
yield from run_successful_crosslink_tests(spec, state, target_len_offset_slot=1) yield from run_successful_crosslink_tests(spec, state, target_len_offset_slot=1)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_multiple_offset_slots(spec, state): def test_multiple_offset_slots(spec, state):
yield from run_successful_crosslink_tests(spec, state, target_len_offset_slot=2) yield from run_successful_crosslink_tests(spec, state, target_len_offset_slot=2)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_no_winning_root(spec, state): def test_no_winning_root(spec, state):
@ -152,7 +153,7 @@ def test_no_winning_root(spec, state):
assert state.shard_states == pre_shard_states assert state.shard_states == pre_shard_states
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_wrong_shard_transition_root(spec, state): def test_wrong_shard_transition_root(spec, state):

View File

@ -8,6 +8,7 @@ from eth2spec.test.helpers.attestations import (
from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
MINIMAL, MINIMAL,
spec_state_test, spec_state_test,
with_all_phases_except, with_all_phases_except,
@ -25,7 +26,7 @@ def run_process_challenge_deadlines(spec, state):
yield from run_epoch_processing_with(spec, state, 'process_challenge_deadlines') yield from run_epoch_processing_with(spec, state, 'process_challenge_deadlines')
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
def test_validator_slashed_after_chunk_challenge(spec, state): def test_validator_slashed_after_chunk_challenge(spec, state):

View File

@ -1,5 +1,6 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
) )
from eth2spec.test.helpers.custody import ( from eth2spec.test.helpers.custody import (
get_valid_chunk_challenge, get_valid_chunk_challenge,
@ -29,7 +30,7 @@ def run_process_custody_final_updates(spec, state):
yield from run_epoch_processing_with(spec, state, 'process_custody_final_updates') yield from run_epoch_processing_with(spec, state, 'process_custody_final_updates')
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_validator_withdrawal_delay(spec, state): def test_validator_withdrawal_delay(spec, state):
transition_to_valid_shard_slot(spec, state) transition_to_valid_shard_slot(spec, state)
@ -42,7 +43,7 @@ def test_validator_withdrawal_delay(spec, state):
assert state.validators[0].withdrawable_epoch == spec.FAR_FUTURE_EPOCH assert state.validators[0].withdrawable_epoch == spec.FAR_FUTURE_EPOCH
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_validator_withdrawal_reenable_after_custody_reveal(spec, state): def test_validator_withdrawal_reenable_after_custody_reveal(spec, state):
transition_to_valid_shard_slot(spec, state) transition_to_valid_shard_slot(spec, state)
@ -67,7 +68,7 @@ def test_validator_withdrawal_reenable_after_custody_reveal(spec, state):
assert state.validators[0].withdrawable_epoch < spec.FAR_FUTURE_EPOCH assert state.validators[0].withdrawable_epoch < spec.FAR_FUTURE_EPOCH
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state): def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state):
transition_to_valid_shard_slot(spec, state) transition_to_valid_shard_slot(spec, state)
@ -116,7 +117,7 @@ def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state):
assert state.validators[validator_index].withdrawable_epoch == spec.FAR_FUTURE_EPOCH assert state.validators[validator_index].withdrawable_epoch == spec.FAR_FUTURE_EPOCH
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_validator_withdrawal_resume_after_chunk_challenge_response(spec, state): def test_validator_withdrawal_resume_after_chunk_challenge_response(spec, state):
transition_to_valid_shard_slot(spec, state) transition_to_valid_shard_slot(spec, state)

View File

@ -4,6 +4,7 @@ from eth2spec.test.helpers.custody import (
from eth2spec.test.helpers.state import transition_to from eth2spec.test.helpers.state import transition_to
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
MINIMAL, MINIMAL,
with_all_phases_except, with_all_phases_except,
with_configs, with_configs,
@ -17,7 +18,7 @@ def run_process_challenge_deadlines(spec, state):
yield from run_epoch_processing_with(spec, state, 'process_challenge_deadlines') yield from run_epoch_processing_with(spec, state, 'process_challenge_deadlines')
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
def test_validator_slashed_after_reveal_deadline(spec, state): def test_validator_slashed_after_reveal_deadline(spec, state):
@ -37,7 +38,7 @@ def test_validator_slashed_after_reveal_deadline(spec, state):
assert state.validators[0].slashed == 1 assert state.validators[0].slashed == 1
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@with_configs([MINIMAL], reason="too slow") @with_configs([MINIMAL], reason="too slow")
def test_validator_not_slashed_after_reveal(spec, state): def test_validator_not_slashed_after_reveal(spec, state):

View File

@ -1,7 +1,9 @@
from typing import Dict, Sequence from typing import Dict, Sequence
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, MINIMAL, PHASE0,
LIGHTCLIENT_PATCH,
MINIMAL,
with_all_phases_except, with_all_phases_except,
spec_state_test, spec_state_test,
only_full_crosslink, only_full_crosslink,
@ -98,7 +100,7 @@ def run_beacon_block_with_shard_blocks(spec, state, target_len_offset_slot, comm
assert post_shard_state.gasprice > pre_gasprice assert post_shard_state.gasprice > pre_gasprice
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_process_beacon_block_with_normal_shard_transition(spec, state): def test_process_beacon_block_with_normal_shard_transition(spec, state):
@ -112,7 +114,7 @@ def test_process_beacon_block_with_normal_shard_transition(spec, state):
yield from run_beacon_block_with_shard_blocks(spec, state, target_len_offset_slot, committee_index, shard) yield from run_beacon_block_with_shard_blocks(spec, state, target_len_offset_slot, committee_index, shard)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_process_beacon_block_with_empty_proposal_transition(spec, state): def test_process_beacon_block_with_empty_proposal_transition(spec, state):
@ -131,7 +133,7 @@ def test_process_beacon_block_with_empty_proposal_transition(spec, state):
# #
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_with_shard_transition_with_custody_challenge_and_response(spec, state): def test_with_shard_transition_with_custody_challenge_and_response(spec, state):
@ -165,7 +167,7 @@ def test_with_shard_transition_with_custody_challenge_and_response(spec, state):
yield from run_beacon_block(spec, state, block) yield from run_beacon_block(spec, state, block)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@with_configs([MINIMAL]) @with_configs([MINIMAL])
def test_custody_key_reveal(spec, state): def test_custody_key_reveal(spec, state):
@ -179,7 +181,7 @@ def test_custody_key_reveal(spec, state):
yield from run_beacon_block(spec, state, block) yield from run_beacon_block(spec, state, block)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_early_derived_secret_reveal(spec, state): def test_early_derived_secret_reveal(spec, state):
transition_to_valid_shard_slot(spec, state) transition_to_valid_shard_slot(spec, state)
@ -190,7 +192,7 @@ def test_early_derived_secret_reveal(spec, state):
yield from run_beacon_block(spec, state, block) yield from run_beacon_block(spec, state, block)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_custody_slashing(spec, state): def test_custody_slashing(spec, state):

View File

@ -1,5 +1,6 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
always_bls, always_bls,
expect_assertion_error, expect_assertion_error,
spec_state_test, spec_state_test,
@ -43,7 +44,7 @@ def run_shard_blocks(spec, shard_state, signed_shard_block, beacon_parent_state,
shard_state.latest_block_root == pre_shard_state.latest_block_root shard_state.latest_block_root == pre_shard_state.latest_block_root
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink
@ -63,7 +64,7 @@ def test_valid_shard_block(spec, state):
# #
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_invalid_shard_parent_root(spec, state): def test_invalid_shard_parent_root(spec, state):
@ -79,7 +80,7 @@ def test_invalid_shard_parent_root(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_invalid_beacon_parent_root(spec, state): def test_invalid_beacon_parent_root(spec, state):
@ -94,7 +95,7 @@ def test_invalid_beacon_parent_root(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_invalid_slot(spec, state): def test_invalid_slot(spec, state):
@ -110,7 +111,7 @@ def test_invalid_slot(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_invalid_proposer_index(spec, state): def test_invalid_proposer_index(spec, state):
@ -130,7 +131,7 @@ def test_invalid_proposer_index(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink
@ -151,7 +152,7 @@ def test_out_of_bound_offset(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink
@ -170,7 +171,7 @@ def test_invalid_offset(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state, valid=False)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink
@ -189,7 +190,7 @@ def test_empty_block_body(spec, state):
# #
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink
@ -208,7 +209,7 @@ def test_invalid_signature(spec, state):
# #
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink
@ -225,7 +226,7 @@ def test_max_offset(spec, state):
yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state)
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@always_bls @always_bls
@only_full_crosslink @only_full_crosslink

View File

@ -1,6 +1,13 @@
from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.utils.ssz.ssz_impl import hash_tree_root
from eth2spec.test.context import PHASE0, spec_state_test, with_all_phases_except, never_bls, only_full_crosslink from eth2spec.test.context import (
PHASE0,
LIGHTCLIENT_PATCH,
spec_state_test,
with_all_phases_except,
never_bls,
only_full_crosslink,
)
from eth2spec.test.helpers.attestations import get_valid_on_time_attestation from eth2spec.test.helpers.attestations import get_valid_on_time_attestation
from eth2spec.test.helpers.shard_block import ( from eth2spec.test.helpers.shard_block import (
build_shard_block, build_shard_block,
@ -145,7 +152,7 @@ def create_and_apply_beacon_and_shard_blocks(spec, state, store, shard, shard_bl
return has_shard_committee return has_shard_committee
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@never_bls # Set to never_bls for testing `check_pending_shard_blocks` @never_bls # Set to never_bls for testing `check_pending_shard_blocks`
def test_basic(spec, state): def test_basic(spec, state):
@ -206,7 +213,7 @@ def create_simple_fork(spec, state, store, shard):
return head_block, forking_block return head_block, forking_block
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_shard_simple_fork(spec, state): def test_shard_simple_fork(spec, state):
@ -231,7 +238,7 @@ def test_shard_simple_fork(spec, state):
assert spec.get_shard_head(store, shard) == forking_block.message.hash_tree_root() assert spec.get_shard_head(store, shard) == forking_block.message.hash_tree_root()
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
@only_full_crosslink @only_full_crosslink
def test_shard_latest_messages_for_different_shards(spec, state): def test_shard_latest_messages_for_different_shards(spec, state):

View File

@ -1,12 +1,13 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
PHASE0, PHASE0,
LIGHTCLIENT_PATCH,
with_all_phases_except, with_all_phases_except,
spec_state_test, spec_state_test,
) )
from eth2spec.test.helpers.state import next_epoch from eth2spec.test.helpers.state import next_epoch
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_get_committee_count_delta(spec, state): def test_get_committee_count_delta(spec, state):
assert spec.get_committee_count_delta(state, 0, 0) == 0 assert spec.get_committee_count_delta(state, 0, 0) == 0
@ -23,7 +24,7 @@ def test_get_committee_count_delta(spec, state):
) )
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_get_start_shard_current_epoch_start(spec, state): def test_get_start_shard_current_epoch_start(spec, state):
assert state.current_epoch_start_shard == 0 assert state.current_epoch_start_shard == 0
@ -39,7 +40,7 @@ def test_get_start_shard_current_epoch_start(spec, state):
assert start_shard == state.current_epoch_start_shard assert start_shard == state.current_epoch_start_shard
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_get_start_shard_next_slot(spec, state): def test_get_start_shard_next_slot(spec, state):
next_epoch(spec, state) next_epoch(spec, state)
@ -57,7 +58,7 @@ def test_get_start_shard_next_slot(spec, state):
assert start_shard == expected_start_shard assert start_shard == expected_start_shard
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_get_start_shard_previous_slot(spec, state): def test_get_start_shard_previous_slot(spec, state):
next_epoch(spec, state) next_epoch(spec, state)
@ -76,7 +77,7 @@ def test_get_start_shard_previous_slot(spec, state):
assert start_shard == expected_start_shard assert start_shard == expected_start_shard
@with_all_phases_except([PHASE0]) @with_all_phases_except([PHASE0, LIGHTCLIENT_PATCH])
@spec_state_test @spec_state_test
def test_get_start_shard_far_past_epoch(spec, state): def test_get_start_shard_far_past_epoch(spec, state):
initial_epoch = spec.get_current_epoch(state) initial_epoch = spec.get_current_epoch(state)