Merge branch 'dev' into hwwhww/strict-uint64
This commit is contained in:
commit
76840c9178
|
@ -28,13 +28,3 @@ tests/core/pyspec/test-reports
|
|||
tests/core/pyspec/eth2spec/test_results.xml
|
||||
|
||||
*.egg-info
|
||||
|
||||
# flake8 config
|
||||
tox.ini
|
||||
|
||||
# VS code files
|
||||
.vscode
|
||||
*.code-workspace
|
||||
|
||||
# npm (for doctoc)
|
||||
package-lock.json
|
10
Makefile
10
Makefile
|
@ -22,6 +22,9 @@ MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/phase0/*.md) $(wildcard $(SPEC_DIR)/phas
|
|||
COV_HTML_OUT=.htmlcov
|
||||
COV_INDEX_FILE=$(PY_SPEC_DIR)/$(COV_HTML_OUT)/index.html
|
||||
|
||||
CURRENT_DIR = ${CURDIR}
|
||||
LINTER_CONFIG_FILE = $(CURRENT_DIR)/linter.ini
|
||||
|
||||
.PHONY: clean partial_clean all test citest lint generate_tests pyspec install_test open_cov \
|
||||
install_deposit_contract_tester test_deposit_contract install_deposit_contract_compiler \
|
||||
compile_deposit_contract test_compile_deposit_contract check_toc
|
||||
|
@ -101,9 +104,8 @@ codespell:
|
|||
|
||||
lint: pyspec
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
flake8 --ignore=E252,W504,W503 --max-line-length=120 ./eth2spec \
|
||||
&& cd ./eth2spec && mypy --follow-imports=silent --warn-unused-ignores --ignore-missing-imports --check-untyped-defs --disallow-incomplete-defs --disallow-untyped-defs -p phase0 \
|
||||
&& mypy --follow-imports=silent --warn-unused-ignores --ignore-missing-imports --check-untyped-defs --disallow-incomplete-defs --disallow-untyped-defs -p phase1;
|
||||
flake8 --config $(LINTER_CONFIG_FILE) ./eth2spec \
|
||||
&& mypy --config-file $(LINTER_CONFIG_FILE) -p eth2spec.phase0 -p eth2spec.phase1
|
||||
|
||||
install_deposit_contract_tester:
|
||||
cd $(DEPOSIT_CONTRACT_TESTER_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install -r requirements.txt
|
||||
|
@ -123,8 +125,6 @@ test_compile_deposit_contract:
|
|||
cd $(DEPOSIT_CONTRACT_COMPILER_DIR); . venv/bin/activate; \
|
||||
python3.7 -m pytest .
|
||||
|
||||
CURRENT_DIR = ${CURDIR}
|
||||
|
||||
# Runs a generator, identified by param 1
|
||||
define run_generator
|
||||
# Started!
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
[flake8]
|
||||
ignore = E252,W504,W503
|
||||
max-line-length = 120
|
||||
|
||||
[mypy]
|
||||
disallow_incomplete_defs = True
|
||||
disallow_untyped_defs = True
|
||||
|
||||
warn_unused_ignores = True
|
||||
warn_unused_configs = True
|
||||
warn_redundant_casts = True
|
||||
|
||||
ignore_missing_imports = True
|
6
setup.py
6
setup.py
|
@ -189,10 +189,10 @@ get_base_reward = cache_this(
|
|||
lambda state, index: (state.validators.hash_tree_root(), state.slot, index),
|
||||
_get_base_reward, lru_size=2048)
|
||||
|
||||
_get_committee_count_at_slot = get_committee_count_at_slot
|
||||
get_committee_count_at_slot = cache_this(
|
||||
_get_committee_count_per_slot = get_committee_count_per_slot
|
||||
get_committee_count_per_slot = cache_this(
|
||||
lambda state, epoch: (state.validators.hash_tree_root(), epoch),
|
||||
_get_committee_count_at_slot, lru_size=SLOTS_PER_EPOCH * 3)
|
||||
_get_committee_count_per_slot, lru_size=SLOTS_PER_EPOCH * 3)
|
||||
|
||||
_get_active_validator_indices = get_active_validator_indices
|
||||
get_active_validator_indices = cache_this(
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
- [`get_active_validator_indices`](#get_active_validator_indices)
|
||||
- [`get_validator_churn_limit`](#get_validator_churn_limit)
|
||||
- [`get_seed`](#get_seed)
|
||||
- [`get_committee_count_at_slot`](#get_committee_count_at_slot)
|
||||
- [`get_committee_count_per_slot`](#get_committee_count_per_slot)
|
||||
- [`get_beacon_committee`](#get_beacon_committee)
|
||||
- [`get_beacon_proposer_index`](#get_beacon_proposer_index)
|
||||
- [`get_total_balance`](#get_total_balance)
|
||||
|
@ -952,14 +952,13 @@ def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes
|
|||
return hash(domain_type + int_to_bytes(epoch, length=8) + mix)
|
||||
```
|
||||
|
||||
#### `get_committee_count_at_slot`
|
||||
#### `get_committee_count_per_slot`
|
||||
|
||||
```python
|
||||
def get_committee_count_at_slot(state: BeaconState, slot: Slot) -> uint64:
|
||||
def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64:
|
||||
"""
|
||||
Return the number of committees at ``slot``.
|
||||
Return the number of committees in each slot for the given ``epoch``.
|
||||
"""
|
||||
epoch = compute_epoch_at_slot(slot)
|
||||
return max(uint64(1), min(
|
||||
MAX_COMMITTEES_PER_SLOT,
|
||||
uint64(len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE),
|
||||
|
@ -974,7 +973,7 @@ def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex)
|
|||
Return the beacon committee at ``slot`` for ``index``.
|
||||
"""
|
||||
epoch = compute_epoch_at_slot(slot)
|
||||
committees_per_slot = get_committee_count_at_slot(state, slot)
|
||||
committees_per_slot = get_committee_count_per_slot(state, epoch)
|
||||
return compute_committee(
|
||||
indices=get_active_validator_indices(state, epoch),
|
||||
seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER),
|
||||
|
@ -1724,7 +1723,7 @@ def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSla
|
|||
```python
|
||||
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||
data = attestation.data
|
||||
assert data.index < get_committee_count_at_slot(state, data.slot)
|
||||
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
|
||||
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
|
||||
assert data.target.epoch == compute_epoch_at_slot(data.slot)
|
||||
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
|
||||
|
|
|
@ -275,18 +275,22 @@ Additional global topics are used to propagate lower frequency validator message
|
|||
Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `Name`s are:
|
||||
|
||||
- `beacon_attestation_{subnet_id}` - These topics are used to propagate unaggregated attestations to the subnet `subnet_id` (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the subnet.
|
||||
- _[REJECT]_ The attestation is for the correct subnet (i.e. `compute_subnet_for_attestation(state, attestation.data.slot, attestation.data.index) == subnet_id`).
|
||||
- _[REJECT]_ The attestation is for the correct subnet -- i.e. `compute_subnet_for_attestation(committees_per_slot, attestation.data.slot, attestation.data.index) == subnet_id`, where `committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch)`, which may be pre-computed along with the committee information for the signature check.
|
||||
- _[IGNORE]_ `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (within a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. `attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot` (a client MAY queue future attestations for processing at the appropriate slot).
|
||||
- _[REJECT]_ The attestation is unaggregated -- that is, it has exactly one participating validator (`len(get_attesting_indices(state, attestation.data, attestation.aggregation_bits)) == 1`).
|
||||
- _[REJECT]_ The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit in bit attestation.aggregation_bits if bit]) == 1`, i.e. exactly 1 bit is set).
|
||||
- _[IGNORE]_ There has been no other valid attestation seen on an attestation subnet that has an identical `attestation.data.target.epoch` and participating validator index.
|
||||
- _[REJECT]_ The block being voted for (`attestation.data.beacon_block_root`) passes validation.
|
||||
- _[REJECT]_ The signature of `attestation` is valid.
|
||||
|
||||
#### Attestations and Aggregation
|
||||
|
||||
Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The correct subnet for an attestation can be calculated with `compute_subnet_for_attestation`. `beacon_attestation_{subnet_id}` topics, are rotated through throughout the epoch in a similar fashion to rotating through shards in committees in Phase 1.
|
||||
Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`.
|
||||
The correct subnet for an attestation can be calculated with `compute_subnet_for_attestation`.
|
||||
`beacon_attestation_{subnet_id}` topics, are rotated through throughout the epoch in a similar fashion to rotating through shards in committees in Phase 1.
|
||||
The subnets are rotated through with `committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch)` subnets per slot.
|
||||
|
||||
Unaggregated attestations are sent to the subnet topic, `beacon_attestation_{compute_subnet_for_attestation(committees_per_slot, attestation.data.slot, attestation.data.index)}` as `Attestation`s.
|
||||
|
||||
Unaggregated attestations are sent to the subnet topic, `beacon_attestation_{compute_subnet_for_attestation(state, attestation.data.slot, attestation.data.index)}` as `Attestation`s.
|
||||
|
||||
Aggregated attestations are sent to the `beacon_aggregate_and_proof` topic as `AggregateAndProof`s.
|
||||
|
||||
|
|
|
@ -172,8 +172,9 @@ def get_committee_assignment(state: BeaconState,
|
|||
assert epoch <= next_epoch
|
||||
|
||||
start_slot = compute_start_slot_at_epoch(epoch)
|
||||
committee_count_per_slot = get_committee_count_per_slot(state, epoch)
|
||||
for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH):
|
||||
for index in range(get_committee_count_at_slot(state, Slot(slot))):
|
||||
for index in range(committee_count_per_slot):
|
||||
committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index))
|
||||
if validator_index in committee:
|
||||
return committee, CommitteeIndex(index), Slot(slot)
|
||||
|
@ -199,8 +200,10 @@ The beacon chain shufflings are designed to provide a minimum of 1 epoch lookahe
|
|||
|
||||
Specifically a validator should:
|
||||
* Call `get_committee_assignment(state, next_epoch, validator_index)` when checking for next epoch assignments.
|
||||
* Find peers of the pubsub topic `beacon_attestation_{compute_subnet_for_attestation(state, slot, committee_index)}`.
|
||||
* If an _insufficient_ number of current peers are subscribed to the topic, the validator must discover new peers on this topic. Via the discovery protocol, find peers with an ENR containing the `attnets` entry such that `ENR["attnets"][compute_subnet_for_attestation(state, slot, committee_index)] == True`. Then validate that the peers are still persisted on the desired topic by requesting `GetMetaData` and checking the resulting `attnets` field.
|
||||
* Calculate the committees per slot for the next epoch: `committees_per_slot = get_committee_count_per_slot(state, next_epoch)`
|
||||
* Calculate the subnet index: `subnet_id = compute_subnet_for_attestation(committees_per_slot, slot, committee_index)`
|
||||
* Find peers of the pubsub topic `beacon_attestation_{subnet_id}`.
|
||||
* If an _insufficient_ number of current peers are subscribed to the topic, the validator must discover new peers on this topic. Via the discovery protocol, find peers with an ENR containing the `attnets` entry such that `ENR["attnets"][subnet_id] == True`. Then validate that the peers are still persisted on the desired topic by requesting `GetMetaData` and checking the resulting `attnets` field.
|
||||
* If the validator is assigned to be an aggregator for the slot (see `is_aggregator()`), then subscribe to the topic.
|
||||
|
||||
*Note*: If the validator is _not_ assigned to be an aggregator, the validator only needs sufficient number of peers on the topic to be able to publish messages. The validator does not need to _subscribe_ and listen to all messages on the topic.
|
||||
|
@ -425,16 +428,20 @@ def get_attestation_signature(state: BeaconState, attestation_data: AttestationD
|
|||
|
||||
#### Broadcast attestation
|
||||
|
||||
Finally, the validator broadcasts `attestation` to the associated attestation subnet -- the `beacon_attestation_{compute_subnet_for_attestation(state, attestation.data.slot, attestation.data.committee_index)}` pubsub topic.
|
||||
Finally, the validator broadcasts `attestation` to the associated attestation subnet, the `beacon_attestation_{subnet_id}` pubsub topic.
|
||||
|
||||
The `subnet_id` for the `attestation` is calculated with:
|
||||
- Let `committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch)`.
|
||||
- Let `subnet_id = compute_subnet_for_attestation(committees_per_slot, attestation.data.slot, attestation.data.committee_index)`.
|
||||
|
||||
```python
|
||||
def compute_subnet_for_attestation(state: BeaconState, slot: Slot, committee_index: CommitteeIndex) -> uint64:
|
||||
def compute_subnet_for_attestation(committees_per_slot: uint64, slot: Slot, committee_index: CommitteeIndex) -> uint64:
|
||||
"""
|
||||
Compute the correct subnet for an attestation for Phase 0.
|
||||
Note, this mimics expected Phase 1 behavior where attestations will be mapped to their shard subnet.
|
||||
"""
|
||||
slots_since_epoch_start = slot % SLOTS_PER_EPOCH
|
||||
committees_since_epoch_start = get_committee_count_at_slot(state, slot) * slots_since_epoch_start
|
||||
committees_since_epoch_start = committees_per_slot * slots_since_epoch_start
|
||||
|
||||
return uint64((committees_since_epoch_start + committee_index) % ATTESTATION_SUBNET_COUNT)
|
||||
```
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
- [`get_shard_proposer_index`](#get_shard_proposer_index)
|
||||
- [`get_committee_count_delta`](#get_committee_count_delta)
|
||||
- [`get_start_shard`](#get_start_shard)
|
||||
- [`get_shard`](#get_shard)
|
||||
- [`get_latest_slot_for_shard`](#get_latest_slot_for_shard)
|
||||
- [`get_offset_slots`](#get_offset_slots)
|
||||
- [Predicates](#predicates)
|
||||
|
@ -167,6 +166,8 @@ class AttestationData(Container):
|
|||
# FFG vote
|
||||
source: Checkpoint
|
||||
target: Checkpoint
|
||||
# Shard vote
|
||||
shard: Shard
|
||||
# Current-slot shard block root
|
||||
shard_head_root: Root
|
||||
# Shard transition root
|
||||
|
@ -252,7 +253,7 @@ class BeaconBlockBody(Container):
|
|||
deposits: List[Deposit, MAX_DEPOSITS]
|
||||
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
|
||||
# Custody game
|
||||
chunk_challenges: List[CustodyChunkResponse, MAX_CUSTODY_CHUNK_CHALLENGES]
|
||||
chunk_challenges: List[CustodyChunkChallenge, MAX_CUSTODY_CHUNK_CHALLENGES]
|
||||
chunk_challenge_responses: List[CustodyChunkResponse, MAX_CUSTODY_CHUNK_CHALLENGE_RESPONSES]
|
||||
custody_key_reveals: List[CustodyKeyReveal, MAX_CUSTODY_KEY_REVEALS]
|
||||
early_derived_secret_reveals: List[EarlyDerivedSecretReveal, MAX_EARLY_DERIVED_SECRET_REVEALS]
|
||||
|
@ -493,7 +494,7 @@ def compute_offset_slots(start_slot: Slot, end_slot: Slot) -> Sequence[Slot]:
|
|||
#### `compute_updated_gasprice`
|
||||
|
||||
```python
|
||||
def compute_updated_gasprice(prev_gasprice: Gwei, shard_block_length: uint8) -> Gwei:
|
||||
def compute_updated_gasprice(prev_gasprice: Gwei, shard_block_length: uint64) -> Gwei:
|
||||
if shard_block_length > TARGET_SHARD_BLOCK_SIZE:
|
||||
delta = (prev_gasprice * (shard_block_length - TARGET_SHARD_BLOCK_SIZE)
|
||||
// TARGET_SHARD_BLOCK_SIZE // GASPRICE_ADJUSTMENT_COEFFICIENT)
|
||||
|
@ -592,7 +593,10 @@ def get_committee_count_delta(state: BeaconState, start_slot: Slot, stop_slot: S
|
|||
"""
|
||||
Return the sum of committee counts in range ``[start_slot, stop_slot)``.
|
||||
"""
|
||||
return sum(get_committee_count_at_slot(state, Slot(slot)) for slot in range(start_slot, stop_slot))
|
||||
return sum(
|
||||
get_committee_count_per_slot(state, compute_epoch_at_slot(Slot(slot)))
|
||||
for slot in range(start_slot, stop_slot)
|
||||
)
|
||||
```
|
||||
|
||||
#### `get_start_shard`
|
||||
|
@ -621,16 +625,6 @@ def get_start_shard(state: BeaconState, slot: Slot) -> Shard:
|
|||
)
|
||||
```
|
||||
|
||||
#### `get_shard`
|
||||
|
||||
```python
|
||||
def get_shard(state: BeaconState, attestation: Attestation) -> Shard:
|
||||
"""
|
||||
Return the shard that the given ``attestation`` is attesting.
|
||||
"""
|
||||
return compute_shard_from_committee_index(state, attestation.data.index, attestation.data.slot)
|
||||
```
|
||||
|
||||
#### `get_latest_slot_for_shard`
|
||||
|
||||
```python
|
||||
|
@ -757,7 +751,7 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
|||
```python
|
||||
def validate_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||
data = attestation.data
|
||||
assert data.index < get_committee_count_at_slot(state, data.slot)
|
||||
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
|
||||
assert data.index < get_active_shard_count(state)
|
||||
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
|
||||
assert data.target.epoch == compute_epoch_at_slot(data.slot)
|
||||
|
@ -775,6 +769,9 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None:
|
|||
if is_on_time_attestation(state, attestation):
|
||||
# Correct parent block root
|
||||
assert data.beacon_block_root == get_block_root_at_slot(state, compute_previous_slot(state.slot))
|
||||
# Correct shard number
|
||||
shard = compute_shard_from_committee_index(state, attestation.data.index, attestation.data.slot)
|
||||
assert attestation.data.shard == shard
|
||||
# Type 2: no shard transition
|
||||
else:
|
||||
# Ensure delayed attestation
|
||||
|
@ -935,15 +932,18 @@ def process_crosslinks(state: BeaconState,
|
|||
shard_transitions: Sequence[ShardTransition],
|
||||
attestations: Sequence[Attestation]) -> None:
|
||||
on_time_attestation_slot = compute_previous_slot(state.slot)
|
||||
committee_count = get_committee_count_at_slot(state, on_time_attestation_slot)
|
||||
committee_count = get_committee_count_per_slot(state, compute_epoch_at_slot(on_time_attestation_slot))
|
||||
for committee_index in map(CommitteeIndex, range(committee_count)):
|
||||
# All attestations in the block for this committee/shard and current slot
|
||||
shard = compute_shard_from_committee_index(state, committee_index, on_time_attestation_slot)
|
||||
# Since the attestations are validated, all `shard_attestations` satisfy `attestation.data.shard == shard`
|
||||
shard_attestations = [
|
||||
attestation for attestation in attestations
|
||||
if is_on_time_attestation(state, attestation) and attestation.data.index == committee_index
|
||||
]
|
||||
shard = compute_shard_from_committee_index(state, committee_index, on_time_attestation_slot)
|
||||
winning_root = process_crosslink_for_shard(state, committee_index, shard_transitions[shard], shard_attestations)
|
||||
winning_root = process_crosslink_for_shard(
|
||||
state, committee_index, shard_transitions[shard], shard_attestations
|
||||
)
|
||||
if winning_root != Root():
|
||||
# Mark relevant pending attestations as creating a successful crosslink
|
||||
for pending_attestation in state.current_epoch_attestations:
|
||||
|
|
|
@ -302,7 +302,7 @@ def process_custody_game_operations(state: BeaconState, body: BeaconBlockBody) -
|
|||
fn(state, operation)
|
||||
|
||||
for_ops(body.chunk_challenges, process_chunk_challenge)
|
||||
for_ops(body.chunk_challenge_responses, process_chunk_challenge)
|
||||
for_ops(body.chunk_challenge_responses, process_chunk_challenge_response)
|
||||
for_ops(body.custody_key_reveals, process_custody_key_reveal)
|
||||
for_ops(body.early_derived_secret_reveals, process_early_derived_secret_reveal)
|
||||
for_ops(body.custody_slashings, process_custody_slashing)
|
||||
|
|
|
@ -39,7 +39,8 @@ class LatestMessage(object):
|
|||
def update_latest_messages(store: Store, attesting_indices: Sequence[ValidatorIndex], attestation: Attestation) -> None:
|
||||
target = attestation.data.target
|
||||
beacon_block_root = attestation.data.beacon_block_root
|
||||
shard = get_shard(store.block_states[beacon_block_root], attestation)
|
||||
# TODO: separate shard chain vote
|
||||
shard = attestation.data.shard
|
||||
for i in attesting_indices:
|
||||
if i not in store.latest_messages or target.epoch > store.latest_messages[i].epoch:
|
||||
store.latest_messages[i] = LatestMessage(
|
||||
|
|
|
@ -70,8 +70,9 @@ def shard_state_transition(shard_state: ShardState,
|
|||
"""
|
||||
shard_state.slot = block.slot
|
||||
prev_gasprice = shard_state.gasprice
|
||||
shard_state.gasprice = compute_updated_gasprice(prev_gasprice, len(block.body))
|
||||
if len(block.body) == 0:
|
||||
shard_block_length = len(block.body)
|
||||
shard_state.gasprice = compute_updated_gasprice(prev_gasprice, uint64(shard_block_length))
|
||||
if shard_block_length == 0:
|
||||
latest_block_root = shard_state.latest_block_root
|
||||
else:
|
||||
latest_block_root = hash_tree_root(block)
|
||||
|
@ -123,8 +124,7 @@ def is_valid_fraud_proof(beacon_state: BeaconState,
|
|||
# 2. Check if the shard state transition result is wrong between
|
||||
# `transition.shard_states[offset_index - 1]` to `transition.shard_states[offset_index]`.
|
||||
if offset_index == 0:
|
||||
shard = get_shard(beacon_state, attestation)
|
||||
shard_states = beacon_parent_block.body.shard_transitions[shard].shard_states
|
||||
shard_states = beacon_parent_block.body.shard_transitions[attestation.data.shard].shard_states
|
||||
shard_state = shard_states[len(shard_states) - 1]
|
||||
else:
|
||||
shard_state = transition.shard_states[offset_index - 1] # Not doing the actual state updates here.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Ethereum 2.0 Phase 0 -- Honest Validator
|
||||
# Ethereum 2.0 Phase 1 -- Honest Validator
|
||||
|
||||
**Notice**: This document is a work-in-progress for researchers and implementers. This is an accompanying document to [Ethereum 2.0 Phase 1](./), which describes the expected actions of a "validator" participating in the Ethereum 2.0 Phase 1 protocol.
|
||||
|
||||
|
@ -94,12 +94,14 @@ Beacon chain validator assignments to beacon committees and beacon block proposa
|
|||
Lookahead for beacon committee assignments operates in the same manner as Phase 0, but committee members must join a shard block pubsub topic in addition to the committee attestation topic.
|
||||
|
||||
Specifically _after_ finding stable peers of attestation subnets (see Phase 0) a validator should:
|
||||
* Let `shard = compute_shard_from_committee_index(committe_index)`
|
||||
* Let `shard = compute_shard_from_committee_index(state, committee_index, slot)`
|
||||
* Subscribe to the pubsub topic `shard_{shard}_block` (attestation subnet peers should have this topic available).
|
||||
|
||||
TODO: For now, the `state` we pass to `compute_shard_from_committee_index` is the current state without considering `len(state.shard_states)`, i.e., the result from `get_active_shard_count(state)` changes. We should fix it when we have shard count update logic.
|
||||
|
||||
## Beacon chain responsibilities
|
||||
|
||||
A validator has two primary responsibilities to the beacon chain: [proposing blocks](#block-proposal) and [creating attestations](#attestations-1). Proposals happen infrequently, whereas attestations should be created once per epoch.
|
||||
A validator has two primary responsibilities to the beacon chain: [proposing blocks](#block-proposal) and [creating attestations](#attesting). Proposals happen infrequently, whereas attestations should be created once per epoch.
|
||||
|
||||
These responsibilities are largely unchanged from Phase 0, but utilize the updated `SignedBeaconBlock`, `BeaconBlock`, `BeaconBlockBody`, `Attestation`, and `AttestationData` definitions found in Phase 1. Below notes only the additional and modified behavior with respect to Phase 0.
|
||||
|
||||
|
@ -109,7 +111,7 @@ Phase 1 adds light client committees and associated responsibilities, discussed
|
|||
|
||||
#### Preparing for a `BeaconBlock`
|
||||
|
||||
`slot`, `proposer_index`, `parent_root` fields are unchanged.
|
||||
`slot`, `proposer_index`, `parent_root`, `state_root` fields are unchanged.
|
||||
|
||||
#### Constructing the `BeaconBlockBody`
|
||||
|
||||
|
@ -133,10 +135,10 @@ Up to `MAX_EARLY_DERIVED_SECRET_REVEALS`, [`EarlyDerivedSecretReveal`](./custody
|
|||
|
||||
##### Shard transitions
|
||||
|
||||
Exactly `MAX_SHARDS` [`ShardTransition`](./beacon-chain#shardtransition) objects are included in the block. Default each to an empty `ShardTransition()`. Then for each committee assigned to the slot with an associated `committee_index` and `shard`, set `shard_transitions[shard] = full_transitions[winning_root]` if the committee had enough weight to form a crosslink this slot.
|
||||
Exactly `MAX_SHARDS` [`ShardTransition`](./beacon-chain.md#shardtransition) objects are included in the block. Default each to an empty `ShardTransition()`. Then for each committee assigned to the slot with an associated `committee_index` and `shard`, set `shard_transitions[shard] = full_transitions[winning_root]` if the committee had enough weight to form a crosslink this slot.
|
||||
|
||||
Specifically:
|
||||
* Call `shards, winning_roots = get_shard_winning_roots(state, block.slot, block.body.attestations)`
|
||||
* Call `shards, winning_roots = get_shard_winning_roots(state, block.body.attestations)`
|
||||
* Let `full_transitions` be a dictionary mapping from the `shard_transition_root`s found in `attestations` to the corresponding full `ShardTransition`
|
||||
* Then for each `shard` and `winning_root` in `zip(shards, winning_roots)` set `shard_transitions[shard] = full_transitions[winning_root]`
|
||||
|
||||
|
@ -148,15 +150,16 @@ def get_shard_winning_roots(state: BeaconState,
|
|||
shards = []
|
||||
winning_roots = []
|
||||
online_indices = get_online_validator_indices(state)
|
||||
committee_count = get_committee_count_at_slot(state, state.slot)
|
||||
on_time_attestation_slot = compute_previous_slot(state.slot)
|
||||
committee_count = get_committee_count_per_slot(state, compute_epoch_at_slot(on_time_attestation_slot))
|
||||
for committee_index in map(CommitteeIndex, range(committee_count)):
|
||||
shard = compute_shard_from_committee_index(state, committee_index, state.slot)
|
||||
shard = compute_shard_from_committee_index(state, committee_index, on_time_attestation_slot)
|
||||
# All attestations in the block for this committee/shard and are "on time"
|
||||
shard_attestations = [
|
||||
attestation for attestation in attestations
|
||||
if is_on_time_attestation(state, attestation) and attestation.data.index == committee_index
|
||||
]
|
||||
committee = get_beacon_committee(state, state.slot, committee_index)
|
||||
committee = get_beacon_committee(state, on_time_attestation_slot, committee_index)
|
||||
|
||||
# Loop over all shard transition roots, looking for a winning root
|
||||
shard_transition_roots = set([a.data.shard_transition_root for a in shard_attestations])
|
||||
|
@ -184,7 +187,7 @@ def get_shard_winning_roots(state: BeaconState,
|
|||
|
||||
##### Light client fields
|
||||
|
||||
First retrieve `best_aggregate` from `get_best_light_client_aggregate` where `aggregates` is a list of valid aggregated `LightClientVote`s for the previous slot.
|
||||
First retrieve `best_aggregate` from `get_best_light_client_aggregate(block, aggregates)` where `aggregates` is a list of valid aggregated `LightClientVote`s for the previous slot.
|
||||
|
||||
Then:
|
||||
* Set `light_client_bits = best_aggregate.aggregation_bits`
|
||||
|
@ -219,7 +222,7 @@ A validator is expected to create, sign, and broadcast an attestation during eac
|
|||
|
||||
Assignments and the core of this duty are unchanged from Phase 0. There are a few additional fields related to the assigned shard chain.
|
||||
|
||||
The `Attestation` and `AttestationData` defined in the [Phase 1 Beacon Chain spec]() utilizes `shard_transition_root: Root` rather than a full `ShardTransition`. For the purposes of the validator and p2p layer, a modified `FullAttestationData` and containing `FullAttestation` are used to send the accompanying `ShardTransition` in its entirety. Note that due to the properties of SSZ `hash_tree_root`, the root and signatures of `AttestationData` and `FullAttestationData` are equivalent.
|
||||
The `Attestation` and `AttestationData` defined in the [Phase 1 Beacon Chain spec](./beacon-chain.md) utilizes `shard_transition_root: Root` rather than a full `ShardTransition`. For the purposes of the validator and p2p layer, a modified `FullAttestationData` and containing `FullAttestation` are used to send the accompanying `ShardTransition` in its entirety. Note that due to the properties of SSZ `hash_tree_root`, the root and signatures of `AttestationData` and `FullAttestationData` are equivalent.
|
||||
|
||||
#### `FullAttestationData`
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
* **union**: union type containing one of the given subtypes
|
||||
* notation `Union[type_0, type_1, ...]`, e.g. `union[null, uint64]`
|
||||
|
||||
*Note*: Both `Vector[boolean, N]` and `Bitvector[N]` are valid, yet distinct due to their different serialization requirements. Similarly, both `List[boolean, N]` and `Bitlist[N]` are valid, yet distinct. Generally `Bitvector[N]`/`Bitlist[N]` are preferred because of their serialization efficiencies.
|
||||
|
||||
### Variable-size and fixed-size
|
||||
|
||||
We recursively define "variable-size" types to be lists, unions, `Bitlist` and all types that contain a variable-size type. All other types are said to be "fixed-size".
|
||||
|
@ -88,9 +90,9 @@ Assuming a helper function `default(type)` which returns the default value for `
|
|||
| `boolean` | `False` |
|
||||
| `Container` | `[default(type) for type in container]` |
|
||||
| `Vector[type, N]` | `[default(type)] * N` |
|
||||
| `Bitvector[boolean, N]` | `[False] * N` |
|
||||
| `Bitvector[N]` | `[False] * N` |
|
||||
| `List[type, N]` | `[]` |
|
||||
| `Bitlist[boolean, N]` | `[]` |
|
||||
| `Bitlist[N]` | `[]` |
|
||||
| `Union[type_0, type_1, ...]` | `default(type_0)` |
|
||||
|
||||
#### `is_zero`
|
||||
|
|
|
@ -154,7 +154,7 @@ def test_filtered_block_tree(spec, state):
|
|||
attestations = []
|
||||
for i in range(spec.SLOTS_PER_EPOCH):
|
||||
slot = rogue_block.slot + i
|
||||
for index in range(spec.get_committee_count_at_slot(non_viable_state, slot)):
|
||||
for index in range(spec.get_committee_count_per_slot(non_viable_state, spec.compute_epoch_at_slot(slot))):
|
||||
attestation = get_valid_attestation(spec, non_viable_state, slot, index, signed=True)
|
||||
attestations.append(attestation)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
|||
latest_message = spec.LatestMessage(
|
||||
epoch=attestation.data.target.epoch,
|
||||
root=attestation.data.beacon_block_root,
|
||||
shard=spec.get_shard(state, attestation),
|
||||
shard=attestation.data.shard,
|
||||
shard_root=attestation.data.shard_head_root,
|
||||
)
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ def apply_shard_and_beacon(spec, state, store, shard_store, shard_blocks_buffer)
|
|||
shard_transition=shard_transition,
|
||||
signed=False,
|
||||
)
|
||||
assert spec.get_shard(state, attestation) == shard
|
||||
assert attestation.data.shard == shard
|
||||
beacon_block.body.attestations = [attestation]
|
||||
beacon_block.body.shard_transitions = shard_transitions
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ def run_attestation_processing(spec, state, attestation, valid=True):
|
|||
yield 'post', state
|
||||
|
||||
|
||||
def build_attestation_data(spec, state, slot, index, shard_transition=None, on_time=True):
|
||||
def build_attestation_data(spec, state, slot, index, shard=None, shard_transition=None, on_time=True):
|
||||
assert state.slot >= slot
|
||||
|
||||
if slot == state.slot:
|
||||
|
@ -78,13 +78,15 @@ def build_attestation_data(spec, state, slot, index, shard_transition=None, on_t
|
|||
)
|
||||
|
||||
if spec.fork == PHASE1:
|
||||
if shard is None:
|
||||
shard = spec.compute_shard_from_committee_index(state, attestation_data.index, attestation_data.slot)
|
||||
attestation_data.shard = shard
|
||||
|
||||
if shard_transition is not None:
|
||||
lastest_shard_data_root_index = len(shard_transition.shard_data_roots) - 1
|
||||
attestation_data.shard_head_root = shard_transition.shard_data_roots[lastest_shard_data_root_index]
|
||||
attestation_data.shard_transition_root = shard_transition.hash_tree_root()
|
||||
else:
|
||||
# No shard transition -> no shard block
|
||||
shard = spec.get_shard(state, spec.Attestation(data=attestation_data))
|
||||
if on_time:
|
||||
shard_transition = spec.get_shard_transition(state, shard, shard_blocks=[])
|
||||
lastest_shard_data_root_index = len(shard_transition.shard_data_roots) - 1
|
||||
|
@ -257,7 +259,7 @@ def next_epoch_with_attestations(spec,
|
|||
block = build_empty_block_for_next_slot(spec, post_state)
|
||||
if fill_cur_epoch and post_state.slot >= spec.MIN_ATTESTATION_INCLUSION_DELAY:
|
||||
slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1
|
||||
committees_per_slot = spec.get_committee_count_at_slot(state, slot_to_attest)
|
||||
committees_per_slot = spec.get_committee_count_per_slot(state, spec.compute_epoch_at_slot(slot_to_attest))
|
||||
if slot_to_attest >= spec.compute_start_slot_at_epoch(spec.get_current_epoch(post_state)):
|
||||
for index in range(committees_per_slot):
|
||||
if spec.fork == PHASE1:
|
||||
|
@ -275,7 +277,7 @@ def next_epoch_with_attestations(spec,
|
|||
|
||||
if fill_prev_epoch:
|
||||
slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1
|
||||
committees_per_slot = spec.get_committee_count_at_slot(state, slot_to_attest)
|
||||
committees_per_slot = spec.get_committee_count_per_slot(state, spec.compute_epoch_at_slot(slot_to_attest))
|
||||
for index in range(committees_per_slot):
|
||||
prev_attestation = get_valid_attestation(
|
||||
spec, post_state, slot_to_attest, index=index, signed=True, on_time=False)
|
||||
|
@ -304,7 +306,7 @@ def prepare_state_with_attestations(spec, state, participation_fn=None):
|
|||
for _ in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
# create an attestation for each index in each slot in epoch
|
||||
if state.slot < next_epoch_start_slot:
|
||||
for committee_index in range(spec.get_committee_count_at_slot(state, state.slot)):
|
||||
for committee_index in range(spec.get_committee_count_per_slot(state, spec.get_current_epoch(state))):
|
||||
def temp_participants_filter(comm):
|
||||
if participation_fn is None:
|
||||
return comm
|
||||
|
|
|
@ -75,7 +75,7 @@ def get_shard_transitions(spec, parent_beacon_state, shard_blocks):
|
|||
|
||||
def get_committee_index_of_shard(spec, state, slot, shard): # Optional[CommitteeIndex]
|
||||
active_shard_count = spec.get_active_shard_count(state)
|
||||
committee_count = spec.get_committee_count_at_slot(state, slot)
|
||||
committee_count = spec.get_committee_count_per_slot(state, spec.compute_epoch_at_slot(slot))
|
||||
start_shard = spec.get_start_shard(state, slot)
|
||||
for committee_index in range(committee_count):
|
||||
if (start_shard + committee_index) % active_shard_count == shard:
|
||||
|
|
|
@ -139,7 +139,7 @@ def test_wrong_index_for_committee_signature(spec, state):
|
|||
@spec_state_test
|
||||
@never_bls
|
||||
def test_wrong_index_for_slot(spec, state):
|
||||
while spec.get_committee_count_at_slot(state, state.slot) >= spec.MAX_COMMITTEES_PER_SLOT:
|
||||
while spec.get_committee_count_per_slot(state, spec.get_current_epoch(state)) >= spec.MAX_COMMITTEES_PER_SLOT:
|
||||
state.validators = state.validators[:len(state.validators) // 2]
|
||||
state.balances = state.balances[:len(state.balances) // 2]
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import (
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import (
|
||||
run_epoch_processing_with, run_epoch_processing_to
|
||||
)
|
||||
from eth2spec.test.helpers.state import transition_to
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import (
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import (
|
||||
run_epoch_processing_with
|
||||
)
|
||||
from eth2spec.test.helpers.state import transition_to
|
||||
|
@ -27,8 +27,8 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support
|
|||
remaining_balance = int(total_balance * 2 // 3) # can become negative
|
||||
|
||||
start_slot = spec.compute_start_slot_at_epoch(epoch)
|
||||
committees_per_slot = spec.get_committee_count_per_slot(state, epoch)
|
||||
for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH):
|
||||
committees_per_slot = spec.get_committee_count_at_slot(state, slot)
|
||||
for index in range(committees_per_slot):
|
||||
# Check if we already have had sufficient balance. (and undone if we don't want it).
|
||||
# If so, do not create more attestations. (we do not have empty pending attestations normally anyway)
|
|
@ -1,7 +1,7 @@
|
|||
from eth2spec.test.helpers.deposits import mock_deposit
|
||||
from eth2spec.test.helpers.state import next_epoch, next_slots
|
||||
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
|
||||
|
||||
def run_process_registry_updates(spec, state):
|
|
@ -1,4 +1,5 @@
|
|||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
spec_state_test, spec_test,
|
||||
with_all_phases, with_phases, single_phase,
|
||||
with_custom_state,
|
||||
|
@ -16,7 +17,7 @@ from eth2spec.test.helpers.attestations import (
|
|||
)
|
||||
from eth2spec.test.helpers.rewards import leaking
|
||||
from eth2spec.test.helpers.attester_slashings import get_indexed_attestation_participants
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from random import Random
|
||||
|
||||
|
||||
|
@ -24,7 +25,7 @@ def run_process_rewards_and_penalties(spec, state):
|
|||
yield from run_epoch_processing_with(spec, state, 'process_rewards_and_penalties')
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_genesis_epoch_no_attestations_no_penalties(spec, state):
|
||||
pre_state = state.copy()
|
||||
|
@ -37,7 +38,7 @@ def test_genesis_epoch_no_attestations_no_penalties(spec, state):
|
|||
assert state.balances[index] == pre_state.balances[index]
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_genesis_epoch_full_attestations_no_rewards(spec, state):
|
||||
attestations = []
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import (
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import (
|
||||
run_epoch_processing_with, run_epoch_processing_to
|
||||
)
|
||||
from eth2spec.test.helpers.state import next_epoch
|
|
@ -21,8 +21,8 @@ from eth2spec.test.helpers.deposits import prepare_state_and_deposit
|
|||
from eth2spec.test.helpers.shard_transitions import get_shard_transition_of_committee
|
||||
|
||||
from eth2spec.test.context import (
|
||||
PHASE0, PHASE1,
|
||||
spec_state_test, with_all_phases, expect_assertion_error, always_bls, with_phases,
|
||||
PHASE1
|
||||
)
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ def process_and_sign_block_without_header_validations(spec, state, block):
|
|||
return sign_block(spec, state, block)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_proposal_for_genesis_slot(spec, state):
|
||||
assert state.slot == spec.GENESIS_SLOT
|
||||
|
@ -484,7 +484,7 @@ def test_duplicate_attester_slashing(spec, state):
|
|||
|
||||
# All AttesterSlashing tests should be adopted for Phase 1 but helper support is not yet there
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_multiple_attester_slashings_no_overlap(spec, state):
|
||||
# Skip test if config cannot handle multiple AttesterSlashings per block
|
||||
|
@ -525,7 +525,7 @@ def test_multiple_attester_slashings_no_overlap(spec, state):
|
|||
check_attester_slashing_effect(spec, pre_state, state, full_indices)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_multiple_attester_slashings_partial_overlap(spec, state):
|
||||
# Skip test if config cannot handle multiple AttesterSlashings per block
|
||||
|
@ -740,7 +740,7 @@ def prepare_signed_exits(spec, state, indices):
|
|||
# exceeding the minimal-config randao mixes memory size.
|
||||
# Applies to all voluntary-exit sanity block tests.
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_voluntary_exit(spec, state):
|
||||
validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
|
||||
|
@ -768,7 +768,7 @@ def test_voluntary_exit(spec, state):
|
|||
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_double_validator_exit_same_block(spec, state):
|
||||
validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
|
||||
|
@ -789,7 +789,7 @@ def test_double_validator_exit_same_block(spec, state):
|
|||
yield 'post', None
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
def test_multiple_different_validator_exits_same_block(spec, state):
|
||||
validator_indices = [
|
|
@ -1,4 +1,5 @@
|
|||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
with_all_phases_except,
|
||||
spec_state_test,
|
||||
always_bls,
|
||||
|
@ -11,7 +12,7 @@ from eth2spec.test.helpers.attestations import (
|
|||
)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_on_time_success(spec, state):
|
||||
|
@ -22,7 +23,7 @@ def test_on_time_success(spec, state):
|
|||
yield from run_attestation_processing(spec, state, attestation)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_late_success(spec, state):
|
|
@ -8,11 +8,12 @@ from eth2spec.test.helpers.attestations import (
|
|||
)
|
||||
from eth2spec.test.helpers.state import transition_to
|
||||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
with_all_phases_except,
|
||||
spec_state_test,
|
||||
expect_assertion_error,
|
||||
)
|
||||
from eth2spec.test.phase_0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
|
||||
|
||||
def run_chunk_challenge_processing(spec, state, custody_chunk_challenge, valid=True):
|
||||
|
@ -64,7 +65,7 @@ def run_custody_chunk_response_processing(spec, state, custody_response, valid=T
|
|||
yield 'post', state
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_challenge_appended(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
||||
|
@ -85,7 +86,7 @@ def test_challenge_appended(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_challenge_empty_element_replaced(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
||||
|
@ -108,7 +109,7 @@ def test_challenge_empty_element_replaced(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_duplicate_challenge(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
||||
|
@ -131,7 +132,7 @@ def test_duplicate_challenge(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge, valid=False)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_second_challenge(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
||||
|
@ -156,7 +157,7 @@ def test_second_challenge(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge1)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_multiple_epochs_custody(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3)
|
||||
|
@ -178,7 +179,7 @@ def test_multiple_epochs_custody(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_many_epochs_custody(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20)
|
||||
|
@ -200,7 +201,7 @@ def test_many_epochs_custody(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_off_chain_attestation(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
|
@ -218,7 +219,7 @@ def test_off_chain_attestation(spec, state):
|
|||
yield from run_chunk_challenge_processing(spec, state, challenge)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_custody_response(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
|
@ -246,7 +247,7 @@ def test_custody_response(spec, state):
|
|||
yield from run_custody_chunk_response_processing(spec, state, custody_response)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_custody_response_multiple_epochs(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3)
|
||||
|
@ -274,7 +275,7 @@ def test_custody_response_multiple_epochs(spec, state):
|
|||
yield from run_custody_chunk_response_processing(spec, state, custody_response)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_custody_response_many_epochs(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20)
|
|
@ -9,11 +9,12 @@ from eth2spec.test.helpers.attestations import (
|
|||
from eth2spec.utils.ssz.ssz_typing import ByteList
|
||||
from eth2spec.test.helpers.state import get_balance, transition_to
|
||||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
with_all_phases_except,
|
||||
spec_state_test,
|
||||
expect_assertion_error,
|
||||
)
|
||||
from eth2spec.test.phase_0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
|
||||
|
||||
def run_custody_slashing_processing(spec, state, custody_slashing, valid=True, correct=True):
|
||||
|
@ -102,31 +103,31 @@ def run_standard_custody_slashing_test(spec,
|
|||
yield from run_custody_slashing_processing(spec, state, slashing, valid=valid, correct=correct)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_custody_slashing(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_incorrect_custody_slashing(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state, correct=False)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_multiple_epochs_custody(spec, state):
|
||||
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])
|
||||
@spec_state_test
|
||||
def test_many_epochs_custody(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 10)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_invalid_custody_slashing(spec, state):
|
||||
yield from run_standard_custody_slashing_test(
|
|
@ -7,13 +7,14 @@ from eth2spec.test.helpers.attestations import (
|
|||
)
|
||||
from eth2spec.test.helpers.state import transition_to
|
||||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
with_all_phases_except,
|
||||
spec_state_test,
|
||||
)
|
||||
from eth2spec.test.phase_0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
|
||||
from eth2spec.test.phase_1.block_processing.test_process_chunk_challenge import (
|
||||
from eth2spec.test.phase1.block_processing.test_process_chunk_challenge import (
|
||||
run_chunk_challenge_processing,
|
||||
)
|
||||
|
||||
|
@ -22,7 +23,7 @@ def run_process_challenge_deadlines(spec, state):
|
|||
yield from run_epoch_processing_with(spec, state, 'process_challenge_deadlines')
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_slashed_after_chunk_challenge(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
|
@ -1,3 +1,6 @@
|
|||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
)
|
||||
from eth2spec.test.helpers.custody import (
|
||||
get_valid_chunk_challenge,
|
||||
get_valid_custody_chunk_response,
|
||||
|
@ -12,21 +15,21 @@ from eth2spec.test.context import (
|
|||
with_all_phases_except,
|
||||
spec_state_test,
|
||||
)
|
||||
from eth2spec.test.phase_0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
|
||||
from eth2spec.test.phase_1.block_processing.test_process_chunk_challenge import (
|
||||
from eth2spec.test.phase1.block_processing.test_process_chunk_challenge import (
|
||||
run_chunk_challenge_processing,
|
||||
run_custody_chunk_response_processing,
|
||||
)
|
||||
from eth2spec.test.phase_1.block_processing.test_process_custody_key_reveal import run_custody_key_reveal_processing
|
||||
from eth2spec.test.phase1.block_processing.test_process_custody_key_reveal import run_custody_key_reveal_processing
|
||||
|
||||
|
||||
def run_process_custody_final_updates(spec, state):
|
||||
yield from run_epoch_processing_with(spec, state, 'process_custody_final_updates')
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_withdrawal_delay(spec, state):
|
||||
spec.initiate_validator_exit(state, 0)
|
||||
|
@ -37,7 +40,7 @@ def test_validator_withdrawal_delay(spec, state):
|
|||
assert state.validators[0].withdrawable_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_withdrawal_reenable_after_custody_reveal(spec, state):
|
||||
spec.initiate_validator_exit(state, 0)
|
||||
|
@ -60,7 +63,7 @@ def test_validator_withdrawal_reenable_after_custody_reveal(spec, state):
|
|||
assert state.validators[0].withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
||||
|
@ -108,7 +111,7 @@ def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state):
|
|||
assert state.validators[validator_index].withdrawable_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_withdrawal_resume_after_chunk_challenge_response(spec, state):
|
||||
transition_to(spec, state, state.slot + 1)
|
|
@ -3,18 +3,19 @@ from eth2spec.test.helpers.custody import (
|
|||
)
|
||||
from eth2spec.test.helpers.state import transition_to
|
||||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
with_all_phases_except,
|
||||
spec_state_test,
|
||||
)
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from eth2spec.test.phase_1.block_processing.test_process_custody_key_reveal import run_custody_key_reveal_processing
|
||||
from eth2spec.test.phase0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
from eth2spec.test.phase1.block_processing.test_process_custody_key_reveal import run_custody_key_reveal_processing
|
||||
|
||||
|
||||
def run_process_challenge_deadlines(spec, state):
|
||||
yield from run_epoch_processing_with(spec, state, 'process_challenge_deadlines')
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_slashed_after_reveal_deadline(spec, state):
|
||||
assert state.validators[0].slashed == 0
|
||||
|
@ -33,7 +34,7 @@ def test_validator_slashed_after_reveal_deadline(spec, state):
|
|||
assert state.validators[0].slashed == 1
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@with_all_phases_except([PHASE0])
|
||||
@spec_state_test
|
||||
def test_validator_not_slashed_after_reveal(spec, state):
|
||||
transition_to(spec, state, spec.EPOCHS_PER_CUSTODY_PERIOD * spec.SLOTS_PER_EPOCH)
|
|
@ -10,11 +10,16 @@ from eth2spec.test.helpers.state import next_epoch
|
|||
@spec_state_test
|
||||
def test_get_committee_count_delta(spec, state):
|
||||
assert spec.get_committee_count_delta(state, 0, 0) == 0
|
||||
assert spec.get_committee_count_at_slot(state, 0) != 0
|
||||
assert spec.get_committee_count_delta(state, 0, 1) == spec.get_committee_count_at_slot(state, 0)
|
||||
assert spec.get_committee_count_delta(state, 1, 2) == spec.get_committee_count_at_slot(state, 1)
|
||||
assert spec.get_committee_count_delta(state, 0, 2) == (
|
||||
spec.get_committee_count_at_slot(state, 0) + spec.get_committee_count_at_slot(state, 1)
|
||||
assert spec.get_committee_count_per_slot(state, 0) != 0
|
||||
assert spec.get_committee_count_delta(state, 0, 1) == spec.get_committee_count_per_slot(state, 0)
|
||||
assert spec.get_committee_count_delta(state, 1, 2) == spec.get_committee_count_per_slot(state, 0)
|
||||
assert spec.get_committee_count_delta(state, 0, 2) == spec.get_committee_count_per_slot(state, 0) * 2
|
||||
assert spec.get_committee_count_delta(state, 0, spec.SLOTS_PER_EPOCH) == (
|
||||
spec.get_committee_count_per_slot(state, 0) * spec.SLOTS_PER_EPOCH
|
||||
)
|
||||
assert spec.get_committee_count_delta(state, 0, 2 * spec.SLOTS_PER_EPOCH) == (
|
||||
spec.get_committee_count_per_slot(state, 0) * spec.SLOTS_PER_EPOCH
|
||||
+ spec.get_committee_count_per_slot(state, 1) * spec.SLOTS_PER_EPOCH
|
||||
)
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from eth2spec.test.context import spec_state_test, never_bls, with_all_phases, with_phases
|
||||
from eth2spec.test.context import PHASE0, spec_state_test, never_bls, with_all_phases, with_phases
|
||||
from eth2spec.test.helpers.state import next_epoch_via_block
|
||||
from eth2spec.test.helpers.attestations import next_epoch_with_attestations
|
||||
|
||||
|
@ -28,7 +28,7 @@ def check_finality(spec,
|
|||
assert state.finalized_checkpoint == prev_state.finalized_checkpoint
|
||||
|
||||
|
||||
@with_phases(["phase0"])
|
||||
@with_phases([PHASE0])
|
||||
@spec_state_test
|
||||
@never_bls
|
||||
def test_finality_no_updates_at_genesis(spec, state):
|
||||
|
|
|
@ -26,7 +26,7 @@ def run_get_committee_assignment(spec, state, epoch, validator_index, valid=True
|
|||
committee, committee_index, slot = assignment
|
||||
assert spec.compute_epoch_at_slot(slot) == epoch
|
||||
assert committee == spec.get_beacon_committee(state, slot, committee_index)
|
||||
assert committee_index < spec.get_committee_count_at_slot(state, slot)
|
||||
assert committee_index < spec.get_committee_count_per_slot(state, epoch)
|
||||
assert validator_index in committee
|
||||
assert valid
|
||||
except AssertionError:
|
||||
|
@ -359,13 +359,12 @@ def test_get_attestation_signature_phase0(spec, state):
|
|||
def test_compute_subnet_for_attestation(spec, state):
|
||||
for committee_idx in range(spec.MAX_COMMITTEES_PER_SLOT):
|
||||
for slot in range(state.slot, state.slot + spec.SLOTS_PER_EPOCH):
|
||||
actual_subnet_id = spec.compute_subnet_for_attestation(state, slot, committee_idx)
|
||||
committees_per_slot = spec.get_committee_count_per_slot(state, spec.compute_epoch_at_slot(slot))
|
||||
actual_subnet_id = spec.compute_subnet_for_attestation(committees_per_slot, slot, committee_idx)
|
||||
|
||||
slots_since_epoch_start = slot % spec.SLOTS_PER_EPOCH
|
||||
committees_since_epoch_start = spec.get_committee_count_at_slot(
|
||||
state, slot) * slots_since_epoch_start
|
||||
expected_subnet_id = (committees_since_epoch_start +
|
||||
committee_idx) % spec.ATTESTATION_SUBNET_COUNT
|
||||
committees_since_epoch_start = committees_per_slot * slots_since_epoch_start
|
||||
expected_subnet_id = (committees_since_epoch_start + committee_idx) % spec.ATTESTATION_SUBNET_COUNT
|
||||
|
||||
assert actual_subnet_id == expected_subnet_id
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from typing import Iterable
|
|||
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.phase1 import spec as spec_phase1
|
||||
from eth2spec.test.phase_0.epoch_processing import (
|
||||
from eth2spec.test.phase0.epoch_processing import (
|
||||
test_process_final_updates,
|
||||
test_process_justification_and_finalization,
|
||||
test_process_registry_updates,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Iterable
|
||||
|
||||
from eth2spec.test.phase_0.block_processing import (
|
||||
from eth2spec.test.phase0.block_processing import (
|
||||
test_process_attestation,
|
||||
test_process_attester_slashing,
|
||||
test_process_block_header,
|
||||
|
|
|
@ -2,7 +2,7 @@ from typing import Iterable
|
|||
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.phase1 import spec as spec_phase1
|
||||
from eth2spec.test.phase_0.rewards import (
|
||||
from eth2spec.test.phase0.rewards import (
|
||||
test_basic,
|
||||
test_leak,
|
||||
test_random,
|
||||
|
|
|
@ -5,7 +5,7 @@ from gen_base import gen_runner, gen_typing
|
|||
from gen_from_tests.gen import generate_from_tests
|
||||
|
||||
from eth2spec.test.context import PHASE0
|
||||
from eth2spec.test.phase_0.sanity import test_blocks, test_slots
|
||||
from eth2spec.test.phase0.sanity import test_blocks, test_slots
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.phase1 import spec as spec_phase1
|
||||
|
|
Loading…
Reference in New Issue