From dfdf3ab5cf256cb2ab4933493844fc5c7174004f Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 11:48:34 +0900 Subject: [PATCH 01/23] initial removal and cleanup of shard/crosslink from phase 0 --- specs/core/0_beacon-chain.md | 154 +++----------------- specs/core/0_fork-choice.md | 2 +- specs/validator/0_beacon-chain-validator.md | 31 ++-- 3 files changed, 30 insertions(+), 157 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 681d82457..838d9d681 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -25,7 +25,6 @@ - [`Fork`](#fork) - [`Checkpoint`](#checkpoint) - [`Validator`](#validator) - - [`Crosslink`](#crosslink) - [`AttestationData`](#attestationdata) - [`AttestationDataAndCustodyBit`](#attestationdataandcustodybit) - [`IndexedAttestation`](#indexedattestation) @@ -84,8 +83,6 @@ - [`get_seed`](#get_seed) - [`get_committee_count`](#get_committee_count) - [`get_crosslink_committee`](#get_crosslink_committee) - - [`get_start_shard`](#get_start_shard) - - [`get_shard_delta`](#get_shard_delta) - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - [`get_attestation_data_slot`](#get_attestation_data_slot) - [`get_total_balance`](#get_total_balance) @@ -105,7 +102,6 @@ - [Epoch processing](#epoch-processing) - [Helper functions](#helper-functions-1) - [Justification and finalization](#justification-and-finalization) - - [Crosslinks](#crosslinks) - [Rewards and penalties](#rewards-and-penalties-1) - [Registry updates](#registry-updates) - [Slashings](#slashings) @@ -174,6 +170,7 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | +| `COMMITTEES_PER_SLOT` | `2**5` (= 32) | | `SHARD_COUNT` | `2**10` (= 1,024) | | `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | | `MAX_VALIDATORS_PER_COMMITTEE` | `2**12` (= 4,096) | @@ -305,29 +302,18 @@ class Validator(Container): withdrawable_epoch: Epoch # When validator can withdraw or transfer funds ``` -#### `Crosslink` - -```python -class Crosslink(Container): - shard: Shard - parent_root: Hash - # Crosslinking data - start_epoch: Epoch - end_epoch: Epoch - data_root: Hash -``` - #### `AttestationData` ```python class AttestationData(Container): + slot: Slot # LMD GHOST vote beacon_block_root: Hash # FFG vote source: Checkpoint target: Checkpoint - # Crosslink vote - crosslink: Crosslink + # Index -- Maybe remove + index: uint64 ``` #### `AttestationDataAndCustodyBit` @@ -507,16 +493,12 @@ class BeaconState(Container): validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] # Shuffling - start_shard: Shard randao_mixes: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Slashings slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances # Attestations previous_epoch_attestations: List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH] current_epoch_attestations: List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH] - # Crosslinks - previous_crosslinks: Vector[Crosslink, SHARD_COUNT] # Previous epoch snapshot - current_crosslinks: Vector[Crosslink, SHARD_COUNT] # Finality justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch previous_justified_checkpoint: Checkpoint # Previous epoch snapshot @@ -885,54 +867,32 @@ def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: """ Return the number of committees at ``epoch``. """ + # Consider not hard coding but just return committees per slot for now + """ committees_per_slot = max(1, min( SHARD_COUNT // SLOTS_PER_EPOCH, len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, )) return committees_per_slot * SLOTS_PER_EPOCH + """ + return COMMITTEES_PER_SLOT ``` #### `get_crosslink_committee` ```python -def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> Sequence[ValidatorIndex]: +def get_crosslink_committee(state: BeaconState, epoch: Epoch, index: uint64) -> Sequence[ValidatorIndex]: """ - Return the crosslink committee at ``epoch`` for ``shard``. + Return the crosslink committee at ``epoch`` for ``index``. """ return compute_committee( indices=get_active_validator_indices(state, epoch), seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), - index=(shard + SHARD_COUNT - get_start_shard(state, epoch)) % SHARD_COUNT, + index=index, count=get_committee_count(state, epoch), ) ``` -#### `get_start_shard` - -```python -def get_start_shard(state: BeaconState, epoch: Epoch) -> Shard: - """ - Return the start shard of the 0th committee at ``epoch``. - """ - assert epoch <= get_current_epoch(state) + 1 - check_epoch = Epoch(get_current_epoch(state) + 1) - shard = Shard((state.start_shard + get_shard_delta(state, get_current_epoch(state))) % SHARD_COUNT) - while check_epoch > epoch: - check_epoch -= Epoch(1) - shard = Shard((shard + SHARD_COUNT - get_shard_delta(state, check_epoch)) % SHARD_COUNT) - return shard -``` - -#### `get_shard_delta` - -```python -def get_shard_delta(state: BeaconState, epoch: Epoch) -> uint64: - """ - Return the number of shards to increment ``state.start_shard`` at ``epoch``. - """ - return min(get_committee_count(state, epoch), SHARD_COUNT - SHARD_COUNT // SLOTS_PER_EPOCH) -``` - #### `get_beacon_proposer_index` ```python @@ -946,18 +906,6 @@ def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex: return compute_proposer_index(state, indices, seed) ``` -#### `get_attestation_data_slot` - -```python -def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot: - """ - Return the slot corresponding to the attestation ``data``. - """ - committee_count = get_committee_count(state, data.target.epoch) - offset = (data.crosslink.shard + SHARD_COUNT - get_start_shard(state, data.target.epoch)) % SHARD_COUNT - return Slot(compute_start_slot_of_epoch(data.target.epoch) + offset // (committee_count // SLOTS_PER_EPOCH)) -``` - #### `get_total_balance` ```python @@ -1019,7 +967,7 @@ def get_attesting_indices(state: BeaconState, """ Return the set of attesting indices corresponding to ``data`` and ``bits``. """ - committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard) + committee = get_crosslink_committee(state, data.target.epoch, data.index) return set(index for i, index in enumerate(committee) if bits[i]) ``` @@ -1199,7 +1147,6 @@ def process_slot(state: BeaconState) -> None: ```python def process_epoch(state: BeaconState) -> None: process_justification_and_finalization(state) - process_crosslinks(state) process_rewards_and_penalties(state) process_registry_updates(state) # @process_reveal_deadlines @@ -1230,7 +1177,7 @@ def get_matching_target_attestations(state: BeaconState, epoch: Epoch) -> Sequen def get_matching_head_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]: return [ a for a in get_matching_source_attestations(state, epoch) - if a.data.beacon_block_root == get_block_root_at_slot(state, get_attestation_data_slot(state, a.data)) + if a.data.beacon_block_root == get_block_root_at_slot(state, a.data.slot) ] ``` @@ -1248,23 +1195,6 @@ def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAtte return get_total_balance(state, get_unslashed_attesting_indices(state, attestations)) ``` -```python -def get_winning_crosslink_and_attesting_indices(state: BeaconState, - epoch: Epoch, - shard: Shard) -> Tuple[Crosslink, Set[ValidatorIndex]]: - attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] - crosslinks = filter( - lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_root, hash_tree_root(c)), - [a.data.crosslink for a in attestations] - ) - # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) - winning_crosslink = max(crosslinks, key=lambda c: ( - get_attesting_balance(state, [a for a in attestations if a.data.crosslink == c]), c.data_root - ), default=Crosslink()) - winning_attestations = [a for a in attestations if a.data.crosslink == winning_crosslink] - return winning_crosslink, get_unslashed_attesting_indices(state, winning_attestations) -``` - #### Justification and finalization ```python @@ -1308,20 +1238,6 @@ def process_justification_and_finalization(state: BeaconState) -> None: state.finalized_checkpoint = old_current_justified_checkpoint ``` -#### Crosslinks - -```python -def process_crosslinks(state: BeaconState) -> None: - state.previous_crosslinks = [c for c in state.current_crosslinks] - for epoch in (get_previous_epoch(state), get_current_epoch(state)): - for offset in range(get_committee_count(state, epoch)): - shard = Shard((get_start_shard(state, epoch) + offset) % SHARD_COUNT) - crosslink_committee = set(get_crosslink_committee(state, epoch, shard)) - winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(state, epoch, shard) - if 3 * get_total_balance(state, attesting_indices) >= 2 * get_total_balance(state, crosslink_committee): - state.current_crosslinks[shard] = winning_crosslink -``` - #### Rewards and penalties ```python @@ -1384,36 +1300,15 @@ def get_attestation_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence return rewards, penalties ``` -```python -def get_crosslink_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]: - rewards = [Gwei(0) for _ in range(len(state.validators))] - penalties = [Gwei(0) for _ in range(len(state.validators))] - epoch = get_previous_epoch(state) - for offset in range(get_committee_count(state, epoch)): - shard = Shard((get_start_shard(state, epoch) + offset) % SHARD_COUNT) - crosslink_committee = set(get_crosslink_committee(state, epoch, shard)) - winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(state, epoch, shard) - attesting_balance = get_total_balance(state, attesting_indices) - committee_balance = get_total_balance(state, crosslink_committee) - for index in crosslink_committee: - base_reward = get_base_reward(state, index) - if index in attesting_indices: - rewards[index] += base_reward * attesting_balance // committee_balance - else: - penalties[index] += base_reward - return rewards, penalties -``` - ```python def process_rewards_and_penalties(state: BeaconState) -> None: if get_current_epoch(state) == GENESIS_EPOCH: return rewards1, penalties1 = get_attestation_deltas(state) - rewards2, penalties2 = get_crosslink_deltas(state) for index in range(len(state.validators)): - increase_balance(state, ValidatorIndex(index), rewards1[index] + rewards2[index]) - decrease_balance(state, ValidatorIndex(index), penalties1[index] + penalties2[index]) + increase_balance(state, ValidatorIndex(index), rewards1[index]) + decrease_balance(state, ValidatorIndex(index), penalties1[index]) ``` #### Registry updates @@ -1481,8 +1376,6 @@ def process_final_updates(state: BeaconState) -> None: if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0: historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots) state.historical_roots.append(hash_tree_root(historical_batch)) - # Update start shard - state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT) # Rotate current/previous epoch attestations state.previous_epoch_attestations = state.current_epoch_attestations state.current_epoch_attestations = [] @@ -1609,37 +1502,28 @@ def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSla ```python def process_attestation(state: BeaconState, attestation: Attestation) -> None: data = attestation.data - assert data.crosslink.shard < SHARD_COUNT + assert data.index < COMMITTEES_PER_SLOT assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) - attestation_slot = get_attestation_data_slot(state, data) - assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH + assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH - committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard) + committee = get_crosslink_committee(state, data.target.epoch, data.index) assert len(attestation.aggregation_bits) == len(attestation.custody_bits) == len(committee) pending_attestation = PendingAttestation( data=data, aggregation_bits=attestation.aggregation_bits, - inclusion_delay=state.slot - attestation_slot, + inclusion_delay=state.slot - data.slot, proposer_index=get_beacon_proposer_index(state), ) if data.target.epoch == get_current_epoch(state): assert data.source == state.current_justified_checkpoint - parent_crosslink = state.current_crosslinks[data.crosslink.shard] state.current_epoch_attestations.append(pending_attestation) else: assert data.source == state.previous_justified_checkpoint - parent_crosslink = state.previous_crosslinks[data.crosslink.shard] state.previous_epoch_attestations.append(pending_attestation) - # Check crosslink against expected parent crosslink - assert data.crosslink.parent_root == hash_tree_root(parent_crosslink) - assert data.crosslink.start_epoch == parent_crosslink.end_epoch - assert data.crosslink.end_epoch == min(data.target.epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK) - assert data.crosslink.data_root == Bytes32() # [to be removed in phase 1] - # Check signature assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation)) ``` diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index ad0590685..8e25fe8f3 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -192,7 +192,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None: # Attestations can only affect the fork choice of subsequent slots. # Delay consideration in the fork choice until their slot is in the past. - attestation_slot = get_attestation_data_slot(target_state, attestation.data) + attestation_slot = attestation.data.slot assert store.time >= (attestation_slot + 1) * SECONDS_PER_SLOT # Get state at the `target` to validate attestation and calculate the committees diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 8a9cf1b5d..d43200463 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -41,7 +41,6 @@ - [Attestation data](#attestation-data) - [LMD GHOST vote](#lmd-ghost-vote) - [FFG vote](#ffg-vote) - - [Crosslink vote](#crosslink-vote) - [Construct attestation](#construct-attestation) - [Data](#data) - [Aggregation bits](#aggregation-bits) @@ -135,28 +134,25 @@ A validator can get committee assignments for a given epoch using the following ```python def get_committee_assignment(state: BeaconState, epoch: Epoch, - validator_index: ValidatorIndex) -> Optional[Tuple[Sequence[ValidatorIndex], Shard, Slot]]: + validator_index: ValidatorIndex + ) -> Optional[Tuple[Sequence[ValidatorIndex], uint64, Slot]]: """ Return the committee assignment in the ``epoch`` for ``validator_index``. ``assignment`` returned is a tuple of the following form: * ``assignment[0]`` is the list of validators in the committee - * ``assignment[1]`` is the shard to which the committee is assigned + * ``assignment[1]`` is the index to which the committee is assigned * ``assignment[2]`` is the slot at which the committee is assigned Return None if no assignment. """ next_epoch = get_current_epoch(state) + 1 assert epoch <= next_epoch - committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): - offset = committees_per_slot * (slot % SLOTS_PER_EPOCH) - slot_start_shard = (get_start_shard(state, epoch) + offset) % SHARD_COUNT - for i in range(committees_per_slot): - shard = Shard((slot_start_shard + i) % SHARD_COUNT) - committee = get_crosslink_committee(state, epoch, shard) + for index in range(COMMITTEES_PER_SLOT): + committee = get_crosslink_committee(state, epoch, index) if validator_index in committee: - return committee, shard, Slot(slot) + return committee, index, Slot(slot) return None ``` @@ -176,7 +172,7 @@ def is_proposer(state: BeaconState, The beacon chain shufflings are designed to provide a minimum of 1 epoch lookahead on the validator's upcoming committee assignments for attesting dictated by the shuffling and slot. Note that this lookahead does not apply to proposing, which must be checked during the epoch in question. -`get_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (`current_epoch + 1`). A validator should plan for future assignments by noting at which future slot they will have to attest and also which shard they should begin syncing (in Phase 1+). +`get_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (`current_epoch + 1`). A validator should plan for future assignments by noting at which future slot they will have to attest. Specifically, a validator should call `get_committee_assignment(state, next_epoch, validator_index)` when checking for next epoch assignments. @@ -278,7 +274,7 @@ Up to `MAX_VOLUNTARY_EXITS`, [`VoluntaryExit`](../core/0_beacon-chain.md#volunta ### Attestations -A validator is expected to create, sign, and broadcast an attestation during each epoch. The `committee`, assigned `shard`, and assigned `slot` for which the validator performs this role during an epoch are defined by `get_committee_assignment(state, epoch, validator_index)`. +A validator is expected to create, sign, and broadcast an attestation during each epoch. The `committee`, assigned `index`, and assigned `slot` for which the validator performs this role during an epoch are defined by `get_committee_assignment(state, epoch, validator_index)`. A validator should create and broadcast the attestation halfway through the `slot` during which the validator is assigned―that is, `SECONDS_PER_SLOT * 0.5` seconds after the start of `slot`. @@ -303,16 +299,9 @@ Set `attestation_data.beacon_block_root = signing_root(head_block)`. - Let `start_slot = compute_start_slot_of_epoch(get_current_epoch(head_state))`. - Let `epoch_boundary_block_root = signing_root(head_block) if start_slot == head_state.slot else get_block_root(state, start_slot)`. -##### Crosslink vote +##### Index -Construct `attestation_data.crosslink` via the following. - -- Set `attestation_data.crosslink.shard = shard` where `shard` is the shard associated with the validator's committee. -- Let `parent_crosslink = head_state.current_crosslinks[shard]`. -- Set `attestation_data.crosslink.start_epoch = parent_crosslink.end_epoch`. -- Set `attestation_data.crosslink.end_epoch = min(attestation_data.target.epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)`. -- Set `attestation_data.crosslink.parent_root = hash_tree_root(head_state.current_crosslinks[shard])`. -- Set `attestation_data.crosslink.data_root = ZERO_HASH`. *Note*: This is a stub for Phase 0. +Set `attestation_data.index = index` where `index` is the index associated with the validator's committee. #### Construct attestation From b3b9b434b49e3f7e5264ef310a0c9f7485d47513 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 12:16:13 +0900 Subject: [PATCH 02/23] working through phase 0 tests after crosslink/shard removal --- specs/core/0_beacon-chain.md | 1 - specs/core/1_shard-data-chains.md | 9 ++ .../eth2spec/test/helpers/attestations.py | 32 ++-- .../test_process_attestation.py | 143 ++---------------- .../test_process_crosslinks.py | 132 ---------------- 5 files changed, 27 insertions(+), 290 deletions(-) delete mode 100644 test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 838d9d681..b57aa7ff4 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -84,7 +84,6 @@ - [`get_committee_count`](#get_committee_count) - [`get_crosslink_committee`](#get_crosslink_committee) - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - - [`get_attestation_data_slot`](#get_attestation_data_slot) - [`get_total_balance`](#get_total_balance) - [`get_total_active_balance`](#get_total_active_balance) - [`get_domain`](#get_domain) diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 69962b6fe..9bd9c70ee 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -53,6 +53,7 @@ This document describes the shard transition function (data layer only) and the | Name | SSZ equivalent | Description | | - | - | - | +| `Shard` | `uint64` | a shard number | | `ShardSlot` | `uint64` | a shard slot number | ## Configuration @@ -101,6 +102,14 @@ This document describes the shard transition function (data layer only) and the ## Containers +### `Crosslink` + +```python +class Crosslink(Container): + # STUB: placeholder data structure while reworking phase 0 + shard: Shard +``` + ### `ShardBlock` ```python diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index 23d1a8f8f..00c25b340 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -3,11 +3,10 @@ from typing import List from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block from eth2spec.test.helpers.keys import privkeys from eth2spec.utils.bls import bls_sign, bls_aggregate_signatures -from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.utils.ssz.ssz_typing import Bitlist -def build_attestation_data(spec, state, slot, shard): +def build_attestation_data(spec, state, slot, index): assert state.slot >= slot if slot == state.slot: @@ -30,40 +29,27 @@ def build_attestation_data(spec, state, slot, shard): source_epoch = state.current_justified_checkpoint.epoch source_root = state.current_justified_checkpoint.root - if spec.compute_epoch_of_slot(slot) == spec.get_current_epoch(state): - parent_crosslink = state.current_crosslinks[shard] - else: - parent_crosslink = state.previous_crosslinks[shard] - return spec.AttestationData( + slot=slot, beacon_block_root=block_root, source=spec.Checkpoint(epoch=source_epoch, root=source_root), target=spec.Checkpoint(epoch=spec.compute_epoch_of_slot(slot), root=epoch_boundary_root), - crosslink=spec.Crosslink( - shard=shard, - start_epoch=parent_crosslink.end_epoch, - end_epoch=min(spec.compute_epoch_of_slot(slot), parent_crosslink.end_epoch + spec.MAX_EPOCHS_PER_CROSSLINK), - data_root=spec.Hash(), - parent_root=hash_tree_root(parent_crosslink), - ), + index=index, ) -def get_valid_attestation(spec, state, slot=None, signed=False): +def get_valid_attestation(spec, state, slot=None, index=None, signed=False): if slot is None: slot = state.slot + if index is None: + index = 0 - epoch = spec.compute_epoch_of_slot(slot) - epoch_start_shard = spec.get_start_shard(state, epoch) - committees_per_slot = spec.get_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH - shard = (epoch_start_shard + committees_per_slot * (slot % spec.SLOTS_PER_EPOCH)) % spec.SHARD_COUNT - - attestation_data = build_attestation_data(spec, state, slot, shard) + attestation_data = build_attestation_data(spec, state, slot, index) crosslink_committee = spec.get_crosslink_committee( state, attestation_data.target.epoch, - attestation_data.crosslink.shard, + attestation_data.index, ) committee_size = len(crosslink_committee) @@ -132,7 +118,7 @@ def fill_aggregate_attestation(spec, state, attestation): crosslink_committee = spec.get_crosslink_committee( state, attestation.data.target.epoch, - attestation.data.crosslink.shard, + attestation.data.index, ) for i in range(len(crosslink_committee)): attestation.aggregation_bits[i] = True diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index 8ae45788f..b3952b7ea 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -1,4 +1,9 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phases +from eth2spec.test.context import ( + spec_state_test, + expect_assertion_error, + always_bls, never_bls, + with_all_phases, with_phases, +) from eth2spec.test.helpers.attestations import ( get_valid_attestation, sign_aggregate_attestation, @@ -6,7 +11,6 @@ from eth2spec.test.helpers.attestations import ( ) from eth2spec.test.helpers.state import ( next_epoch, - next_slot, ) from eth2spec.test.helpers.block import apply_empty_block from eth2spec.utils.ssz.ssz_typing import Bitlist @@ -67,54 +71,6 @@ def test_success_previous_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_all_phases -@spec_state_test -def test_success_since_max_epochs_per_crosslink(spec, state): - # Do not run mainnet (64 epochs), that would mean the equivalent of ~7 hours chain simulation. - if spec.MAX_EPOCHS_PER_CROSSLINK > 4: - return - for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2): - next_epoch(spec, state) - apply_empty_block(spec, state) - - attestation = get_valid_attestation(spec, state, signed=True) - data = attestation.data - # test logic sanity check: make sure the attestation only includes MAX_EPOCHS_PER_CROSSLINK epochs - assert data.crosslink.end_epoch - data.crosslink.start_epoch == spec.MAX_EPOCHS_PER_CROSSLINK - - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - next_slot(spec, state) - apply_empty_block(spec, state) - - yield from run_attestation_processing(spec, state, attestation) - - -@with_all_phases -@spec_state_test -def test_wrong_end_epoch_with_max_epochs_per_crosslink(spec, state): - # Do not run mainnet (64 epochs), that would mean the equivalent of ~7 hours chain simulation. - if spec.MAX_EPOCHS_PER_CROSSLINK > 4: - return - for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2): - next_epoch(spec, state) - apply_empty_block(spec, state) - - attestation = get_valid_attestation(spec, state) - data = attestation.data - # test logic sanity check: make sure the attestation only includes MAX_EPOCHS_PER_CROSSLINK epochs - assert data.crosslink.end_epoch - data.crosslink.start_epoch == spec.MAX_EPOCHS_PER_CROSSLINK - # Now change it to be different - data.crosslink.end_epoch += 1 - - sign_attestation(spec, state, attestation) - - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - next_slot(spec, state) - apply_empty_block(spec, state) - - yield from run_attestation_processing(spec, state, attestation, False) - - @with_all_phases @spec_state_test @always_bls @@ -168,27 +124,13 @@ def test_old_source_epoch(spec, state): @with_all_phases @spec_state_test -def test_wrong_shard(spec, state): - attestation = get_valid_attestation(spec, state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.data.crosslink.shard += 1 - - sign_attestation(spec, state, attestation) - - yield from run_attestation_processing(spec, state, attestation, False) - - -@with_all_phases -@spec_state_test -def test_invalid_shard(spec, state): +@never_bls +def test_invalid_index(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY # off by one (with respect to valid range) on purpose - attestation.data.crosslink.shard = spec.SHARD_COUNT - - sign_attestation(spec, state, attestation) + attestation.data.index = spec.COMMITTEES_PER_SLOT yield from run_attestation_processing(spec, state, attestation, False) @@ -290,73 +232,6 @@ def test_bad_source_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0']) -@spec_state_test -def test_non_zero_crosslink_data_root(spec, state): - attestation = get_valid_attestation(spec, state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.data.crosslink.data_root = b'\x42' * 32 - - sign_attestation(spec, state, attestation) - - yield from run_attestation_processing(spec, state, attestation, False) - - -@with_all_phases -@spec_state_test -def test_bad_parent_crosslink(spec, state): - state.slot = spec.SLOTS_PER_EPOCH - 1 - next_epoch(spec, state) - apply_empty_block(spec, state) - - attestation = get_valid_attestation(spec, state, signed=False) - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - next_slot(spec, state) - apply_empty_block(spec, state) - - attestation.data.crosslink.parent_root = b'\x27' * 32 - sign_attestation(spec, state, attestation) - - yield from run_attestation_processing(spec, state, attestation, False) - - -@with_all_phases -@spec_state_test -def test_bad_crosslink_start_epoch(spec, state): - state.slot = spec.SLOTS_PER_EPOCH - 1 - next_epoch(spec, state) - apply_empty_block(spec, state) - - attestation = get_valid_attestation(spec, state, signed=False) - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - next_slot(spec, state) - apply_empty_block(spec, state) - - attestation.data.crosslink.start_epoch += 1 - sign_attestation(spec, state, attestation) - - yield from run_attestation_processing(spec, state, attestation, False) - - -@with_all_phases -@spec_state_test -def test_bad_crosslink_end_epoch(spec, state): - state.slot = spec.SLOTS_PER_EPOCH - 1 - next_epoch(spec, state) - apply_empty_block(spec, state) - - attestation = get_valid_attestation(spec, state, signed=False) - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - next_slot(spec, state) - apply_empty_block(spec, state) - - attestation.data.crosslink.end_epoch += 1 - sign_attestation(spec, state, attestation) - - yield from run_attestation_processing(spec, state, attestation, False) - - @with_all_phases @spec_state_test def test_inconsistent_bits(spec, state): diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py deleted file mode 100644 index 41d784c50..000000000 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py +++ /dev/null @@ -1,132 +0,0 @@ -from copy import deepcopy - -from eth2spec.test.context import spec_state_test, with_all_phases -from eth2spec.test.helpers.state import ( - next_epoch, - next_slot -) -from eth2spec.test.helpers.block import apply_empty_block -from eth2spec.test.helpers.attestations import ( - add_attestation_to_state, - fill_aggregate_attestation, - get_valid_attestation, - sign_attestation, -) -from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with - - -def run_process_crosslinks(spec, state): - yield from run_epoch_processing_with(spec, state, 'process_crosslinks') - - -@with_all_phases -@spec_state_test -def test_no_attestations(spec, state): - yield from run_process_crosslinks(spec, state) - - for shard in range(spec.SHARD_COUNT): - assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] - - -@with_all_phases -@spec_state_test -def test_single_crosslink_update_from_current_epoch(spec, state): - next_epoch(spec, state) - - attestation = get_valid_attestation(spec, state, signed=True) - - fill_aggregate_attestation(spec, state, attestation) - add_attestation_to_state(spec, state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) - - assert len(state.current_epoch_attestations) == 1 - - shard = attestation.data.crosslink.shard - pre_crosslink = deepcopy(state.current_crosslinks[shard]) - - yield from run_process_crosslinks(spec, state) - - assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] - assert pre_crosslink != state.current_crosslinks[shard] - - -@with_all_phases -@spec_state_test -def test_single_crosslink_update_from_previous_epoch(spec, state): - next_epoch(spec, state) - - attestation = get_valid_attestation(spec, state, signed=True) - - fill_aggregate_attestation(spec, state, attestation) - add_attestation_to_state(spec, state, attestation, state.slot + spec.SLOTS_PER_EPOCH) - - assert len(state.previous_epoch_attestations) == 1 - - shard = attestation.data.crosslink.shard - pre_crosslink = deepcopy(state.current_crosslinks[shard]) - - crosslink_deltas = spec.get_crosslink_deltas(state) - - yield from run_process_crosslinks(spec, state) - - assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] - assert pre_crosslink != state.current_crosslinks[shard] - - # ensure rewarded - for index in spec.get_crosslink_committee( - state, - attestation.data.target.epoch, - attestation.data.crosslink.shard): - assert crosslink_deltas[0][index] > 0 - assert crosslink_deltas[1][index] == 0 - - -@with_all_phases -@spec_state_test -def test_double_late_crosslink(spec, state): - if spec.get_committee_count(state, spec.get_current_epoch(state)) < spec.SHARD_COUNT: - print("warning: ignoring test, test-assumptions are incompatible with configuration") - return - - next_epoch(spec, state) - state.slot += 4 - - attestation_1 = get_valid_attestation(spec, state, signed=True) - fill_aggregate_attestation(spec, state, attestation_1) - - # add attestation_1 to next epoch - next_epoch(spec, state) - add_attestation_to_state(spec, state, attestation_1, state.slot + 1) - - for _ in range(spec.SLOTS_PER_EPOCH): - attestation_2 = get_valid_attestation(spec, state) - if attestation_2.data.crosslink.shard == attestation_1.data.crosslink.shard: - sign_attestation(spec, state, attestation_2) - break - next_slot(spec, state) - apply_empty_block(spec, state) - - fill_aggregate_attestation(spec, state, attestation_2) - - # add attestation_2 in the next epoch after attestation_1 has - # already updated the relevant crosslink - next_epoch(spec, state) - add_attestation_to_state(spec, state, attestation_2, state.slot + 1) - - assert len(state.previous_epoch_attestations) == 1 - assert len(state.current_epoch_attestations) == 0 - - crosslink_deltas = spec.get_crosslink_deltas(state) - - yield from run_process_crosslinks(spec, state) - - shard = attestation_2.data.crosslink.shard - - # ensure that the current crosslinks were not updated by the second attestation - assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] - # ensure no reward, only penalties for the failed crosslink - for index in spec.get_crosslink_committee( - state, - attestation_2.data.target.epoch, - attestation_2.data.crosslink.shard): - assert crosslink_deltas[0][index] == 0 - assert crosslink_deltas[1][index] > 0 From d98cabf7e7c2a1e79a39ba50dd798a29f61236ec Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 13:06:52 +0900 Subject: [PATCH 03/23] fix get crosslink committee and finalitytests --- configs/minimal.yaml | 4 ++-- specs/core/0_beacon-chain.md | 11 ++++++----- specs/validator/0_beacon-chain-validator.md | 2 +- .../pyspec/eth2spec/test/helpers/attestations.py | 4 ++-- test_libs/pyspec/eth2spec/test/helpers/custody.py | 2 +- test_libs/pyspec/eth2spec/test/helpers/state.py | 10 ++++++---- .../test_process_justification_and_finalization.py | 2 +- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/configs/minimal.yaml b/configs/minimal.yaml index 4c32eae4d..dfed19426 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -4,8 +4,8 @@ # Misc # --------------------------------------------------------------- -# [customized] Just 8 shards for testing purposes -SHARD_COUNT: 8 +# [customized] Just 2 committees for slot for testing purposes +COMMITTEES_PER_SLOT: 2 # [customized] unsecure, but fast TARGET_COMMITTEE_SIZE: 4 # 2**12 (= 4,096) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index b57aa7ff4..a371df628 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -880,15 +880,16 @@ def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: #### `get_crosslink_committee` ```python -def get_crosslink_committee(state: BeaconState, epoch: Epoch, index: uint64) -> Sequence[ValidatorIndex]: +def get_crosslink_committee(state: BeaconState, slot: Slot, index: uint64) -> Sequence[ValidatorIndex]: """ Return the crosslink committee at ``epoch`` for ``index``. """ + epoch = compute_epoch_of_slot(slot) return compute_committee( indices=get_active_validator_indices(state, epoch), seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), - index=index, - count=get_committee_count(state, epoch), + index=(slot % SLOTS_PER_EPOCH) * COMMITTEES_PER_SLOT + index, + count=COMMITTEES_PER_SLOT * SLOTS_PER_EPOCH, ) ``` @@ -966,7 +967,7 @@ def get_attesting_indices(state: BeaconState, """ Return the set of attesting indices corresponding to ``data`` and ``bits``. """ - committee = get_crosslink_committee(state, data.target.epoch, data.index) + committee = get_crosslink_committee(state, data.slot, data.index) return set(index for i, index in enumerate(committee) if bits[i]) ``` @@ -1506,7 +1507,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH - committee = get_crosslink_committee(state, data.target.epoch, data.index) + committee = get_crosslink_committee(state, data.slot, data.index) assert len(attestation.aggregation_bits) == len(attestation.custody_bits) == len(committee) pending_attestation = PendingAttestation( diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index d43200463..1efdadb35 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -150,7 +150,7 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): for index in range(COMMITTEES_PER_SLOT): - committee = get_crosslink_committee(state, epoch, index) + committee = get_crosslink_committee(state, Slot(slot), index) if validator_index in committee: return committee, index, Slot(slot) return None diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index 00c25b340..afd51b0bd 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -48,7 +48,7 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False): crosslink_committee = spec.get_crosslink_committee( state, - attestation_data.target.epoch, + attestation_data.slot, attestation_data.index, ) @@ -117,7 +117,7 @@ def get_attestation_signature(spec, state, attestation_data, privkey, custody_bi def fill_aggregate_attestation(spec, state, attestation): crosslink_committee = spec.get_crosslink_committee( state, - attestation.data.target.epoch, + attestation.data.slot, attestation.data.index, ) for i in range(len(crosslink_committee)): diff --git a/test_libs/pyspec/eth2spec/test/helpers/custody.py b/test_libs/pyspec/eth2spec/test/helpers/custody.py index 4b7c8c97b..98659ee8e 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/custody.py +++ b/test_libs/pyspec/eth2spec/test/helpers/custody.py @@ -82,7 +82,7 @@ def bitlist_from_int(max_len, num_bits, n): def get_valid_bit_challenge(spec, state, attestation, invalid_custody_bit=False): crosslink_committee = spec.get_crosslink_committee( state, - attestation.data.target.epoch, + attestation.data.slot, attestation.data.crosslink.shard, ) responder_index = crosslink_committee[0] diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py index e88fc6ade..5a2f72ff3 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/state.py +++ b/test_libs/pyspec/eth2spec/test/helpers/state.py @@ -53,13 +53,15 @@ def next_epoch_with_attestations(spec, 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 if slot_to_attest >= spec.compute_start_slot_of_epoch(spec.get_current_epoch(post_state)): - cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest) - block.body.attestations.append(cur_attestation) + for index in range(spec.COMMITTEES_PER_SLOT): + cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) + block.body.attestations.append(cur_attestation) if fill_prev_epoch: slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1 - prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest) - block.body.attestations.append(prev_attestation) + for index in range(spec.COMMITTEES_PER_SLOT): + prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) + block.body.attestations.append(prev_attestation) state_transition_and_sign_block(spec, post_state, block) blocks.append(block) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 7dcdb42a4..6d1762ecb 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -41,7 +41,7 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support if remaining_balance < 0: return - committee = spec.get_crosslink_committee(state, spec.compute_epoch_of_slot(slot), shard) + committee = spec.get_crosslink_committee(state, slot, shard) # Create a bitfield filled with the given count per attestation, # exactly on the right-most part of the committee field. From 667bf67d7178b5b7f30ebd1b4146df8cf2b09390 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 13:24:17 +0900 Subject: [PATCH 04/23] temporarily disable phase 1 tests --- test_libs/pyspec/eth2spec/test/context.py | 6 ++++-- .../epoch_processing/run_epoch_process_base.py | 1 - ...test_process_justification_and_finalization.py | 15 ++++----------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index 80edaba9b..3bb8f1153 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -1,5 +1,5 @@ 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.utils import bls from .helpers.genesis import create_genesis_state @@ -137,7 +137,9 @@ def with_phases(phases): if 'phase0' in run_phases: ret = run_with_spec_version(spec_phase0, *args, **kw) if 'phase1' in run_phases: - ret = run_with_spec_version(spec_phase1, *args, **kw) + # temporarily disable phase 1 tests + return + # ret = run_with_spec_version(spec_phase1, *args, **kw) return ret return wrapper return decorator diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/run_epoch_process_base.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/run_epoch_process_base.py index 5b2a2ece4..af4587a2a 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/run_epoch_process_base.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/run_epoch_process_base.py @@ -1,7 +1,6 @@ process_calls = [ 'process_justification_and_finalization', - 'process_crosslinks', 'process_rewards_and_penalties', 'process_registry_updates', 'process_reveal_deadlines', diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 6d1762ecb..4e0085076 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -8,14 +8,6 @@ def run_process_just_and_fin(spec, state): yield from run_epoch_processing_with(spec, state, 'process_justification_and_finalization') -def get_shards_for_slot(spec, state, slot): - epoch = spec.compute_epoch_of_slot(slot) - epoch_start_shard = spec.get_start_shard(state, epoch) - committees_per_slot = spec.get_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH - shard = (epoch_start_shard + committees_per_slot * (slot % spec.SLOTS_PER_EPOCH)) % spec.SHARD_COUNT - return [shard + i for i in range(committees_per_slot)] - - def add_mock_attestations(spec, state, epoch, source, target, sufficient_support=False): # we must be at the end of the epoch assert (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0 @@ -35,13 +27,13 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support start_slot = spec.compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH): - for shard in get_shards_for_slot(spec, state, slot): + for index in range(spec.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) if remaining_balance < 0: return - committee = spec.get_crosslink_committee(state, slot, shard) + committee = spec.get_crosslink_committee(state, slot, index) # Create a bitfield filled with the given count per attestation, # exactly on the right-most part of the committee field. @@ -60,10 +52,11 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support attestations.append(spec.PendingAttestation( aggregation_bits=aggregation_bits, data=spec.AttestationData( + slot=slot, beacon_block_root=b'\xff' * 32, # irrelevant to testing source=source, target=target, - crosslink=spec.Crosslink(shard=shard) + index=index, ), inclusion_delay=1, )) From b3a0a03f85c20a66df6984b64fbef3a17f2a9c55 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 13:32:46 +0900 Subject: [PATCH 05/23] remove some legacy code --- specs/core/0_beacon-chain.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index a371df628..4bd839b88 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -311,7 +311,7 @@ class AttestationData(Container): # FFG vote source: Checkpoint target: Checkpoint - # Index -- Maybe remove + # Committee Index index: uint64 ``` @@ -866,14 +866,6 @@ def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: """ Return the number of committees at ``epoch``. """ - # Consider not hard coding but just return committees per slot for now - """ - committees_per_slot = max(1, min( - SHARD_COUNT // SLOTS_PER_EPOCH, - len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, - )) - return committees_per_slot * SLOTS_PER_EPOCH - """ return COMMITTEES_PER_SLOT ``` From 5ccac7c206237e0fe89b00e6984e0eec5346f41a Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 13:36:05 +0900 Subject: [PATCH 06/23] remove get_committee_count --- specs/core/0_beacon-chain.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 4bd839b88..efad5fff2 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -81,7 +81,6 @@ - [`get_active_validator_indices`](#get_active_validator_indices) - [`get_validator_churn_limit`](#get_validator_churn_limit) - [`get_seed`](#get_seed) - - [`get_committee_count`](#get_committee_count) - [`get_crosslink_committee`](#get_crosslink_committee) - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - [`get_total_balance`](#get_total_balance) @@ -859,16 +858,6 @@ def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Hash: return hash(domain_type + int_to_bytes(epoch, length=8) + mix) ``` -#### `get_committee_count` - -```python -def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: - """ - Return the number of committees at ``epoch``. - """ - return COMMITTEES_PER_SLOT -``` - #### `get_crosslink_committee` ```python From 1fbf7f8e0da8f93f5b3e486dc69292cad56b1ba5 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 13:54:51 +0900 Subject: [PATCH 07/23] fix config files --- configs/mainnet.yaml | 6 ++---- configs/minimal.yaml | 2 -- specs/core/0_beacon-chain.md | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index c11f1e54c..68c5052c2 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -5,8 +5,8 @@ # Misc # --------------------------------------------------------------- -# 2**10 (= 1,024) -SHARD_COUNT: 1024 +# 2**5 (= 32) +COMMITTEES_PER_SLOT: 32 # 2**7 (= 128) TARGET_COMMITTEE_SIZE: 128 # 2**12 (= 4,096) @@ -69,8 +69,6 @@ SLOTS_PER_HISTORICAL_ROOT: 8192 MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 # 2**11 (= 2,048) epochs 9 days PERSISTENT_COMMITTEE_PERIOD: 2048 -# 2**6 (= 64) epochs ~7 hours -MAX_EPOCHS_PER_CROSSLINK: 64 # 2**2 (= 4) epochs 25.6 minutes MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 # 2**14 (= 16,384) epochs ~73 days diff --git a/configs/minimal.yaml b/configs/minimal.yaml index dfed19426..8f7beebc7 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -68,8 +68,6 @@ SLOTS_PER_HISTORICAL_ROOT: 64 MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 # 2**11 (= 2,048) epochs PERSISTENT_COMMITTEE_PERIOD: 2048 -# [customized] fast catchup crosslinks -MAX_EPOCHS_PER_CROSSLINK: 4 # 2**2 (= 4) epochs MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 # [customized] 2**12 (= 4,096) epochs diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index efad5fff2..2ceae488e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -210,7 +210,6 @@ The following values are (non-configurable) constants used throughout the specif | `SLOTS_PER_HISTORICAL_ROOT` | `2**13` (= 8,192) | slots | ~13 hours | | `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `2**8` (= 256) | epochs | ~27 hours | | `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | 9 days | -| `MAX_EPOCHS_PER_CROSSLINK` | `2**6` (= 64) | epochs | ~7 hours | | `MIN_EPOCHS_TO_INACTIVITY_PENALTY` | `2**2` (= 4) | epochs | 25.6 minutes | ### State list lengths From c392db3b9b61065cc1c8af5d65f1230bc5862da5 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sat, 12 Oct 2019 14:44:53 +0900 Subject: [PATCH 08/23] fix max epochs var --- configs/mainnet.yaml | 2 ++ configs/minimal.yaml | 2 ++ specs/core/1_beacon-chain-misc.md | 1 + specs/core/1_custody-game.md | 1 + 4 files changed, 6 insertions(+) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 68c5052c2..a45e965d2 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -69,6 +69,8 @@ SLOTS_PER_HISTORICAL_ROOT: 8192 MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 # 2**11 (= 2,048) epochs 9 days PERSISTENT_COMMITTEE_PERIOD: 2048 +# 2**6 (= 64) epochs ~7 hours +MAX_EPOCHS_PER_CROSSLINK: 64 # 2**2 (= 4) epochs 25.6 minutes MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 # 2**14 (= 16,384) epochs ~73 days diff --git a/configs/minimal.yaml b/configs/minimal.yaml index 8f7beebc7..dfed19426 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -68,6 +68,8 @@ SLOTS_PER_HISTORICAL_ROOT: 64 MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 # 2**11 (= 2,048) epochs PERSISTENT_COMMITTEE_PERIOD: 2048 +# [customized] fast catchup crosslinks +MAX_EPOCHS_PER_CROSSLINK: 4 # 2**2 (= 4) epochs MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 # [customized] 2**12 (= 4,096) epochs diff --git a/specs/core/1_beacon-chain-misc.md b/specs/core/1_beacon-chain-misc.md index 6dd6e19c3..9f7a4d2d7 100644 --- a/specs/core/1_beacon-chain-misc.md +++ b/specs/core/1_beacon-chain-misc.md @@ -31,6 +31,7 @@ | Name | Value | Unit | Duration | - | - | - | - | +| `MAX_EPOCHS_PER_CROSSLINK` | `2**6` (= 64) | epochs | ~7 hours | | `MAX_SHARD_RECEIPT_PROOFS` | `2**0` (= 1) | - | - | | `PERIOD_COMMITTEE_ROOT_LENGTH` | `2**8` (= 256) | periods | ~9 months | | `MINOR_REWARD_QUOTIENT` | `2**8` (=256) | - | - | diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 158d575e2..2fc4904ce 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -81,6 +81,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether | - | - | | `BLS12_381_Q` | `4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787` | | `MINOR_REWARD_QUOTIENT` | `2**8` (= 256) | +| `MAX_EPOCHS_PER_CROSSLINK` | `2**6` (= 64) | epochs | ~7 hours | ### Custody game parameters From d8431f847648041dd3efd4d55abc92ce2a872f44 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 13 Oct 2019 13:53:43 +0900 Subject: [PATCH 09/23] add start index back in --- configs/mainnet.yaml | 2 +- configs/minimal.yaml | 2 +- specs/core/0_beacon-chain.md | 72 +++++++++++++++++-- specs/validator/0_beacon-chain-validator.md | 4 +- .../eth2spec/test/helpers/attestations.py | 5 +- .../pyspec/eth2spec/test/helpers/state.py | 10 ++- .../test_process_attestation.py | 8 ++- ..._process_justification_and_finalization.py | 5 +- 8 files changed, 96 insertions(+), 12 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index a45e965d2..1210d8076 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -6,7 +6,7 @@ # Misc # --------------------------------------------------------------- # 2**5 (= 32) -COMMITTEES_PER_SLOT: 32 +MAX_COMMITTEES_PER_SLOT: 32 # 2**7 (= 128) TARGET_COMMITTEE_SIZE: 128 # 2**12 (= 4,096) diff --git a/configs/minimal.yaml b/configs/minimal.yaml index dfed19426..a6040b3a3 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -5,7 +5,7 @@ # --------------------------------------------------------------- # [customized] Just 2 committees for slot for testing purposes -COMMITTEES_PER_SLOT: 2 +MAX_COMMITTEES_PER_SLOT: 2 # [customized] unsecure, but fast TARGET_COMMITTEE_SIZE: 4 # 2**12 (= 4,096) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 2ceae488e..7b6b876de 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -168,8 +168,8 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | -| `COMMITTEES_PER_SLOT` | `2**5` (= 32) | | `SHARD_COUNT` | `2**10` (= 1,024) | +| `MAX_COMMITTEES_PER_SLOT` | `2**5` (= 32) | | `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | | `MAX_VALIDATORS_PER_COMMITTEE` | `2**12` (= 4,096) | | `MIN_PER_EPOCH_CHURN_LIMIT` | `2**2` (= 4) | @@ -490,6 +490,7 @@ class BeaconState(Container): validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] # Shuffling + start_index: uint64 randao_mixes: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Slashings slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances @@ -857,6 +858,21 @@ def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Hash: return hash(domain_type + int_to_bytes(epoch, length=8) + mix) ``` + +#### `get_committee_count` + +```python +def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: + """ + Return the number of committees at ``epoch``. + """ + committees_per_slot = max(1, min( + MAX_COMMITTEES_PER_SLOT, + len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, + )) + return committees_per_slot * SLOTS_PER_EPOCH +``` + #### `get_crosslink_committee` ```python @@ -865,14 +881,60 @@ def get_crosslink_committee(state: BeaconState, slot: Slot, index: uint64) -> Se Return the crosslink committee at ``epoch`` for ``index``. """ epoch = compute_epoch_of_slot(slot) + committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH + slot_start_index = get_slot_start_index(state, slot) + slot_offset = (index + MAX_COMMITTEES_PER_SLOT - slot_start_index) % MAX_COMMITTEES_PER_SLOT + epoch_offset = slot_offset + (slot % SLOTS_PER_EPOCH) * committees_per_slot + print(epoch_offset) + return compute_committee( indices=get_active_validator_indices(state, epoch), seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), - index=(slot % SLOTS_PER_EPOCH) * COMMITTEES_PER_SLOT + index, - count=COMMITTEES_PER_SLOT * SLOTS_PER_EPOCH, + index=epoch_offset, + count=get_committee_count(state, epoch), ) ``` +#### `get_slot_start_index` + +```python +def get_slot_start_index(state: BeaconState, slot: Slot) -> uint64: + """ + Return the start index of the 0th committee at ``slot``. + """ + epoch = compute_epoch_of_slot(slot) + committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH + slot_start_index = ((slot % SLOTS_PER_EPOCH) * committees_per_slot + get_start_index(state, epoch)) % MAX_COMMITTEES_PER_SLOT + return slot_start_index +``` + +#### `get_start_index` + +```python +def get_start_index(state: BeaconState, epoch: Epoch) -> uint64: + """ + Return the start index of the 0th committee at ``epoch``. + """ + assert epoch <= get_current_epoch(state) + 1 + check_epoch = Epoch(get_current_epoch(state) + 1) + index = (state.start_index + get_index_delta(state, get_current_epoch(state))) % MAX_COMMITTEES_PER_SLOT + MAX_COMMITTEES_PER_EPOCH = MAX_COMMITTEES_PER_SLOT * SLOTS_PER_EPOCH + while check_epoch > epoch: + check_epoch -= Epoch(1) + index = (index + MAX_COMMITTEES_PER_EPOCH - get_index_delta(state, check_epoch)) % MAX_COMMITTEES_PER_SLOT + return index +``` + +#### `get_index_delta` + +```python +def get_index_delta(state: BeaconState, epoch: Epoch) -> uint64: + """ + Return the amount to increase ``state.start_index`` at ``epoch``. + """ + return get_committee_count(state, epoch) +``` + #### `get_beacon_proposer_index` ```python @@ -1356,6 +1418,8 @@ def process_final_updates(state: BeaconState) -> None: if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0: historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots) state.historical_roots.append(hash_tree_root(historical_batch)) + # Update start shard + state.start_index = (state.start_index + get_index_delta(state, current_epoch)) % MAX_COMMITTEES_PER_SLOT # Rotate current/previous epoch attestations state.previous_epoch_attestations = state.current_epoch_attestations state.current_epoch_attestations = [] @@ -1482,7 +1546,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 < COMMITTEES_PER_SLOT + assert data.index < MAX_COMMITTEES_PER_SLOT assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 1efdadb35..774837ced 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -149,7 +149,9 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): - for index in range(COMMITTEES_PER_SLOT): + slot_start_index = get_slot_start_index(state, Slot(slot)) + for i in range(get_committee_count(state, epoch) // SLOTS_PER_EPOCH): + index = (slot_start_index + i) % MAX_COMMITTEES_PER_SLOT committee = get_crosslink_committee(state, Slot(slot), index) if validator_index in committee: return committee, index, Slot(slot) diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index afd51b0bd..49d6b6ad7 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -42,7 +42,10 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False): if slot is None: slot = state.slot if index is None: - index = 0 + index = spec.get_slot_start_index(state, slot) + print(slot) + print(index) + print(spec.get_committee_count(state, spec.compute_epoch_of_slot(slot))) attestation_data = build_attestation_data(spec, state, slot, index) diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py index 5a2f72ff3..6ae845f69 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/state.py +++ b/test_libs/pyspec/eth2spec/test/helpers/state.py @@ -51,15 +51,21 @@ def next_epoch_with_attestations(spec, for _ in range(spec.SLOTS_PER_EPOCH): block = build_empty_block_for_next_slot(spec, post_state) if fill_cur_epoch and post_state.slot >= spec.MIN_ATTESTATION_INCLUSION_DELAY: + committees_per_slot = spec.get_committee_count(state, spec.get_current_epoch(state)) // spec.SLOTS_PER_EPOCH slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 if slot_to_attest >= spec.compute_start_slot_of_epoch(spec.get_current_epoch(post_state)): - for index in range(spec.COMMITTEES_PER_SLOT): + slot_start_index = spec.get_slot_start_index(state, slot_to_attest) + for i in range(committees_per_slot): + index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_SLOT cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) block.body.attestations.append(cur_attestation) if fill_prev_epoch: + committees_per_slot = spec.get_committee_count(state, spec.get_previous_epoch(state)) // spec.SLOTS_PER_EPOCH slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1 - for index in range(spec.COMMITTEES_PER_SLOT): + slot_start_index = spec.get_slot_start_index(state, slot_to_attest) + for i in range(committees_per_slot): + index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_SLOT prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) block.body.attestations.append(prev_attestation) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index b3952b7ea..87024a21d 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -122,6 +122,12 @@ def test_old_source_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) +@with_all_phases +@spec_state_test +def test_wrong_index(spec, state): + pass + + @with_all_phases @spec_state_test @never_bls @@ -130,7 +136,7 @@ def test_invalid_index(spec, state): state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY # off by one (with respect to valid range) on purpose - attestation.data.index = spec.COMMITTEES_PER_SLOT + attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT yield from run_attestation_processing(spec, state, attestation, False) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 4e0085076..abd8f2c17 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -26,8 +26,11 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support remaining_balance = total_balance * 2 // 3 start_slot = spec.compute_start_slot_of_epoch(epoch) + committees_per_slot = spec.get_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH): - for index in range(spec.COMMITTEES_PER_SLOT): + slot_start_index = spec.get_slot_start_index(state, slot) + for i in range(committees_per_slot): + index = (slot_start_index + i) % spec.MAX_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) if remaining_balance < 0: From 6208e74d3f9ff9b975fd625aaf89c31ea88d0838 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 13 Oct 2019 21:52:58 +0900 Subject: [PATCH 10/23] get crosslink committees by slot --- configs/minimal.yaml | 2 +- specs/core/0_beacon-chain.md | 31 +++++++++++-------- specs/validator/0_beacon-chain-validator.md | 2 +- .../eth2spec/test/helpers/attestations.py | 3 -- .../pyspec/eth2spec/test/helpers/state.py | 4 +-- .../test_process_attestation.py | 27 ++++++++++++++-- ..._process_justification_and_finalization.py | 2 +- 7 files changed, 48 insertions(+), 23 deletions(-) diff --git a/configs/minimal.yaml b/configs/minimal.yaml index a6040b3a3..1cf35ca90 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -5,7 +5,7 @@ # --------------------------------------------------------------- # [customized] Just 2 committees for slot for testing purposes -MAX_COMMITTEES_PER_SLOT: 2 +MAX_COMMITTEES_PER_SLOT: 4 # [customized] unsecure, but fast TARGET_COMMITTEE_SIZE: 4 # 2**12 (= 4,096) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 7b6b876de..72cc4edb8 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -858,19 +858,18 @@ def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Hash: return hash(domain_type + int_to_bytes(epoch, length=8) + mix) ``` - -#### `get_committee_count` +#### `get_committees_per_slot` ```python -def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: +def get_committees_per_slot(state: BeaconState, slot: Slot) -> uint64: """ - Return the number of committees at ``epoch``. + Return the number of committees at ``slot``. """ - committees_per_slot = max(1, min( + epoch = compute_epoch_of_slot(slot) + return max(1, min( MAX_COMMITTEES_PER_SLOT, len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, )) - return committees_per_slot * SLOTS_PER_EPOCH ``` #### `get_crosslink_committee` @@ -878,20 +877,19 @@ def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64: ```python def get_crosslink_committee(state: BeaconState, slot: Slot, index: uint64) -> Sequence[ValidatorIndex]: """ - Return the crosslink committee at ``epoch`` for ``index``. + Return the crosslink committee at ``slot`` for ``index``. """ epoch = compute_epoch_of_slot(slot) - committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH + committees_per_slot = get_committees_per_slot(state, slot) slot_start_index = get_slot_start_index(state, slot) slot_offset = (index + MAX_COMMITTEES_PER_SLOT - slot_start_index) % MAX_COMMITTEES_PER_SLOT epoch_offset = slot_offset + (slot % SLOTS_PER_EPOCH) * committees_per_slot - print(epoch_offset) return compute_committee( indices=get_active_validator_indices(state, epoch), seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), index=epoch_offset, - count=get_committee_count(state, epoch), + count=committees_per_slot * SLOTS_PER_EPOCH, ) ``` @@ -903,8 +901,9 @@ def get_slot_start_index(state: BeaconState, slot: Slot) -> uint64: Return the start index of the 0th committee at ``slot``. """ epoch = compute_epoch_of_slot(slot) - committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH - slot_start_index = ((slot % SLOTS_PER_EPOCH) * committees_per_slot + get_start_index(state, epoch)) % MAX_COMMITTEES_PER_SLOT + committees_per_slot = get_committees_per_slot(state, slot) + start_index = get_start_index(state, epoch) + slot_start_index = ((slot % SLOTS_PER_EPOCH) * committees_per_slot + start_index) % MAX_COMMITTEES_PER_SLOT return slot_start_index ``` @@ -932,7 +931,7 @@ def get_index_delta(state: BeaconState, epoch: Epoch) -> uint64: """ Return the amount to increase ``state.start_index`` at ``epoch``. """ - return get_committee_count(state, epoch) + return get_committees_per_slot(state, compute_start_slot_of_epoch(epoch)) * SLOTS_PER_EPOCH ``` #### `get_beacon_proposer_index` @@ -1547,6 +1546,12 @@ def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSla def process_attestation(state: BeaconState, attestation: Attestation) -> None: data = attestation.data assert data.index < MAX_COMMITTEES_PER_SLOT + slot_start_index = get_slot_start_index(state, data.slot) + if data.index < slot_start_index: + test_index = data.index + MAX_COMMITTEES_PER_SLOT + else: + test_index = data.index + assert slot_start_index <= test_index < slot_start_index + get_committees_per_slot(state, data.slot) assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 774837ced..b0e64d6c9 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -150,7 +150,7 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): slot_start_index = get_slot_start_index(state, Slot(slot)) - for i in range(get_committee_count(state, epoch) // SLOTS_PER_EPOCH): + for i in range(get_committees_per_slot(state, Slot(slot))): index = (slot_start_index + i) % MAX_COMMITTEES_PER_SLOT committee = get_crosslink_committee(state, Slot(slot), index) if validator_index in committee: diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index 49d6b6ad7..879d878ac 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -43,9 +43,6 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False): slot = state.slot if index is None: index = spec.get_slot_start_index(state, slot) - print(slot) - print(index) - print(spec.get_committee_count(state, spec.compute_epoch_of_slot(slot))) attestation_data = build_attestation_data(spec, state, slot, index) diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py index 6ae845f69..ffa59fafd 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/state.py +++ b/test_libs/pyspec/eth2spec/test/helpers/state.py @@ -51,8 +51,8 @@ def next_epoch_with_attestations(spec, for _ in range(spec.SLOTS_PER_EPOCH): block = build_empty_block_for_next_slot(spec, post_state) if fill_cur_epoch and post_state.slot >= spec.MIN_ATTESTATION_INCLUSION_DELAY: - committees_per_slot = spec.get_committee_count(state, spec.get_current_epoch(state)) // spec.SLOTS_PER_EPOCH slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 + committees_per_slot = spec.get_committees_per_slot(state, slot_to_attest) if slot_to_attest >= spec.compute_start_slot_of_epoch(spec.get_current_epoch(post_state)): slot_start_index = spec.get_slot_start_index(state, slot_to_attest) for i in range(committees_per_slot): @@ -61,8 +61,8 @@ def next_epoch_with_attestations(spec, block.body.attestations.append(cur_attestation) if fill_prev_epoch: - committees_per_slot = spec.get_committee_count(state, spec.get_previous_epoch(state)) // spec.SLOTS_PER_EPOCH slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1 + committees_per_slot = spec.get_committees_per_slot(state, slot_to_attest) slot_start_index = spec.get_slot_start_index(state, slot_to_attest) for i in range(committees_per_slot): index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_SLOT diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index 87024a21d..229eb85b3 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -124,8 +124,31 @@ def test_old_source_epoch(spec, state): @with_all_phases @spec_state_test -def test_wrong_index(spec, state): - pass +@always_bls +def test_wrong_index_for_committee_signature(spec, state): + attestation = get_valid_attestation(spec, state) + state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY + + attestation.data.index += 1 + + yield from run_attestation_processing(spec, state, attestation, False) + + +@with_all_phases +@spec_state_test +@never_bls +def test_wrong_index_for_slot(spec, state): + committees_per_slot = spec.get_committees_per_slot(state, state.slot) + assert committees_per_slot < spec.MAX_COMMITTEES_PER_SLOT + slot_start_index = spec.get_slot_start_index(state, state.slot) + index = slot_start_index + committees_per_slot + + attestation = get_valid_attestation(spec, state) + state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY + + attestation.data.index = index + + yield from run_attestation_processing(spec, state, attestation, False) @with_all_phases diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index abd8f2c17..25d8c083f 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -26,8 +26,8 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support remaining_balance = total_balance * 2 // 3 start_slot = spec.compute_start_slot_of_epoch(epoch) - committees_per_slot = spec.get_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH): + committees_per_slot = spec.get_committees_per_slot(state, slot) slot_start_index = spec.get_slot_start_index(state, slot) for i in range(committees_per_slot): index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_SLOT From bd1c71b82ed905321781f1be8452535c60d56d7c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 16 Oct 2019 18:47:19 +0900 Subject: [PATCH 11/23] simplify index --- specs/core/0_beacon-chain.md | 57 +------------------ specs/validator/0_beacon-chain-validator.md | 4 +- .../eth2spec/test/helpers/attestations.py | 2 +- .../pyspec/eth2spec/test/helpers/state.py | 8 +-- .../test_process_attestation.py | 3 +- ..._process_justification_and_finalization.py | 4 +- 6 files changed, 8 insertions(+), 70 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 72cc4edb8..e0d6c108b 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -490,7 +490,6 @@ class BeaconState(Container): validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] # Shuffling - start_index: uint64 randao_mixes: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Slashings slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances @@ -881,9 +880,7 @@ def get_crosslink_committee(state: BeaconState, slot: Slot, index: uint64) -> Se """ epoch = compute_epoch_of_slot(slot) committees_per_slot = get_committees_per_slot(state, slot) - slot_start_index = get_slot_start_index(state, slot) - slot_offset = (index + MAX_COMMITTEES_PER_SLOT - slot_start_index) % MAX_COMMITTEES_PER_SLOT - epoch_offset = slot_offset + (slot % SLOTS_PER_EPOCH) * committees_per_slot + epoch_offset = index + (slot % SLOTS_PER_EPOCH) * committees_per_slot return compute_committee( indices=get_active_validator_indices(state, epoch), @@ -893,47 +890,6 @@ def get_crosslink_committee(state: BeaconState, slot: Slot, index: uint64) -> Se ) ``` -#### `get_slot_start_index` - -```python -def get_slot_start_index(state: BeaconState, slot: Slot) -> uint64: - """ - Return the start index of the 0th committee at ``slot``. - """ - epoch = compute_epoch_of_slot(slot) - committees_per_slot = get_committees_per_slot(state, slot) - start_index = get_start_index(state, epoch) - slot_start_index = ((slot % SLOTS_PER_EPOCH) * committees_per_slot + start_index) % MAX_COMMITTEES_PER_SLOT - return slot_start_index -``` - -#### `get_start_index` - -```python -def get_start_index(state: BeaconState, epoch: Epoch) -> uint64: - """ - Return the start index of the 0th committee at ``epoch``. - """ - assert epoch <= get_current_epoch(state) + 1 - check_epoch = Epoch(get_current_epoch(state) + 1) - index = (state.start_index + get_index_delta(state, get_current_epoch(state))) % MAX_COMMITTEES_PER_SLOT - MAX_COMMITTEES_PER_EPOCH = MAX_COMMITTEES_PER_SLOT * SLOTS_PER_EPOCH - while check_epoch > epoch: - check_epoch -= Epoch(1) - index = (index + MAX_COMMITTEES_PER_EPOCH - get_index_delta(state, check_epoch)) % MAX_COMMITTEES_PER_SLOT - return index -``` - -#### `get_index_delta` - -```python -def get_index_delta(state: BeaconState, epoch: Epoch) -> uint64: - """ - Return the amount to increase ``state.start_index`` at ``epoch``. - """ - return get_committees_per_slot(state, compute_start_slot_of_epoch(epoch)) * SLOTS_PER_EPOCH -``` - #### `get_beacon_proposer_index` ```python @@ -1417,8 +1373,6 @@ def process_final_updates(state: BeaconState) -> None: if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0: historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots) state.historical_roots.append(hash_tree_root(historical_batch)) - # Update start shard - state.start_index = (state.start_index + get_index_delta(state, current_epoch)) % MAX_COMMITTEES_PER_SLOT # Rotate current/previous epoch attestations state.previous_epoch_attestations = state.current_epoch_attestations state.current_epoch_attestations = [] @@ -1545,15 +1499,8 @@ def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSla ```python def process_attestation(state: BeaconState, attestation: Attestation) -> None: data = attestation.data - assert data.index < MAX_COMMITTEES_PER_SLOT - slot_start_index = get_slot_start_index(state, data.slot) - if data.index < slot_start_index: - test_index = data.index + MAX_COMMITTEES_PER_SLOT - else: - test_index = data.index - assert slot_start_index <= test_index < slot_start_index + get_committees_per_slot(state, data.slot) + assert data.index < get_committees_per_slot(state, data.slot) assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) - assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH committee = get_crosslink_committee(state, data.slot, data.index) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index b0e64d6c9..51f560243 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -149,9 +149,7 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): - slot_start_index = get_slot_start_index(state, Slot(slot)) - for i in range(get_committees_per_slot(state, Slot(slot))): - index = (slot_start_index + i) % MAX_COMMITTEES_PER_SLOT + for index in range(get_committees_per_slot(state, Slot(slot))): committee = get_crosslink_committee(state, Slot(slot), index) if validator_index in committee: return committee, index, Slot(slot) diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index 879d878ac..afd51b0bd 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -42,7 +42,7 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False): if slot is None: slot = state.slot if index is None: - index = spec.get_slot_start_index(state, slot) + index = 0 attestation_data = build_attestation_data(spec, state, slot, index) diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py index ffa59fafd..68b8283bc 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/state.py +++ b/test_libs/pyspec/eth2spec/test/helpers/state.py @@ -54,18 +54,14 @@ def next_epoch_with_attestations(spec, slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 committees_per_slot = spec.get_committees_per_slot(state, slot_to_attest) if slot_to_attest >= spec.compute_start_slot_of_epoch(spec.get_current_epoch(post_state)): - slot_start_index = spec.get_slot_start_index(state, slot_to_attest) - for i in range(committees_per_slot): - index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_SLOT + for index in range(committees_per_slot): cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) block.body.attestations.append(cur_attestation) if fill_prev_epoch: slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1 committees_per_slot = spec.get_committees_per_slot(state, slot_to_attest) - slot_start_index = spec.get_slot_start_index(state, slot_to_attest) - for i in range(committees_per_slot): - index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_SLOT + for index in range(committees_per_slot): prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) block.body.attestations.append(prev_attestation) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index 229eb85b3..e3ccb5d9f 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -140,8 +140,7 @@ def test_wrong_index_for_committee_signature(spec, state): def test_wrong_index_for_slot(spec, state): committees_per_slot = spec.get_committees_per_slot(state, state.slot) assert committees_per_slot < spec.MAX_COMMITTEES_PER_SLOT - slot_start_index = spec.get_slot_start_index(state, state.slot) - index = slot_start_index + committees_per_slot + index = committees_per_slot attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 25d8c083f..8fc3f9866 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -28,9 +28,7 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support start_slot = spec.compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH): committees_per_slot = spec.get_committees_per_slot(state, slot) - slot_start_index = spec.get_slot_start_index(state, slot) - for i in range(committees_per_slot): - index = (slot_start_index + i) % spec.MAX_COMMITTEES_PER_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) if remaining_balance < 0: From 219084a08a679997425522336b84476c2724e73f Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 16 Oct 2019 18:53:36 +0900 Subject: [PATCH 12/23] add CommitteeIndex type --- specs/core/0_beacon-chain.md | 5 +++-- specs/validator/0_beacon-chain-validator.md | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index e0d6c108b..19712a7d9 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -137,6 +137,7 @@ We define the following Python custom types for type hinting and readability: | - | - | - | | `Slot` | `uint64` | a slot number | | `Epoch` | `uint64` | an epoch number | +| `CommitteeIndex` | `uint64` | an index for a committee within a slot | | `Shard` | `uint64` | a shard number | | `ValidatorIndex` | `uint64` | a validator registry index | | `Gwei` | `uint64` | an amount in Gwei | @@ -310,7 +311,7 @@ class AttestationData(Container): source: Checkpoint target: Checkpoint # Committee Index - index: uint64 + index: CommitteeIndex ``` #### `AttestationDataAndCustodyBit` @@ -874,7 +875,7 @@ def get_committees_per_slot(state: BeaconState, slot: Slot) -> uint64: #### `get_crosslink_committee` ```python -def get_crosslink_committee(state: BeaconState, slot: Slot, index: uint64) -> Sequence[ValidatorIndex]: +def get_crosslink_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]: """ Return the crosslink committee at ``slot`` for ``index``. """ diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 51f560243..15edc1e28 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -135,7 +135,7 @@ A validator can get committee assignments for a given epoch using the following def get_committee_assignment(state: BeaconState, epoch: Epoch, validator_index: ValidatorIndex - ) -> Optional[Tuple[Sequence[ValidatorIndex], uint64, Slot]]: + ) -> Optional[Tuple[Sequence[ValidatorIndex], CommitteeIndex, Slot]]: """ Return the committee assignment in the ``epoch`` for ``validator_index``. ``assignment`` returned is a tuple of the following form: @@ -150,9 +150,9 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): for index in range(get_committees_per_slot(state, Slot(slot))): - committee = get_crosslink_committee(state, Slot(slot), index) + committee = get_crosslink_committee(state, Slot(slot), CommitteeIndex(index)) if validator_index in committee: - return committee, index, Slot(slot) + return committee, CommitteeIndex(index), Slot(slot) return None ``` From c239ce0b5eb1b350c80fde7617ecc194a26dbad1 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 17 Oct 2019 10:45:07 +0900 Subject: [PATCH 13/23] crosslink committee -> beacon committee --- specs/core/0_beacon-chain.md | 10 +++++----- specs/core/1_custody-game.md | 2 +- specs/core/1_shard-data-chains.md | 1 + specs/validator/0_beacon-chain-validator.md | 4 ++-- test_libs/pyspec/eth2spec/test/helpers/attestations.py | 8 ++++---- test_libs/pyspec/eth2spec/test/helpers/custody.py | 6 +++--- .../test_process_justification_and_finalization.py | 2 +- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 19712a7d9..bf941eabd 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -81,7 +81,7 @@ - [`get_active_validator_indices`](#get_active_validator_indices) - [`get_validator_churn_limit`](#get_validator_churn_limit) - [`get_seed`](#get_seed) - - [`get_crosslink_committee`](#get_crosslink_committee) + - [`get_beacon_committee`](#get_beacon_committee) - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - [`get_total_balance`](#get_total_balance) - [`get_total_active_balance`](#get_total_active_balance) @@ -872,10 +872,10 @@ def get_committees_per_slot(state: BeaconState, slot: Slot) -> uint64: )) ``` -#### `get_crosslink_committee` +#### `get_beacon_committee` ```python -def get_crosslink_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]: +def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]: """ Return the crosslink committee at ``slot`` for ``index``. """ @@ -965,7 +965,7 @@ def get_attesting_indices(state: BeaconState, """ Return the set of attesting indices corresponding to ``data`` and ``bits``. """ - committee = get_crosslink_committee(state, data.slot, data.index) + committee = get_beacon_committee(state, data.slot, data.index) return set(index for i, index in enumerate(committee) if bits[i]) ``` @@ -1504,7 +1504,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH - committee = get_crosslink_committee(state, data.slot, data.index) + committee = get_beacon_committee(state, data.slot, data.index) assert len(attestation.aggregation_bits) == len(attestation.custody_bits) == len(committee) pending_attestation = PendingAttestation( diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 2fc4904ce..80a42cc14 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -624,7 +624,7 @@ def process_bit_challenge(state: BeaconState, challenge: CustodyBitChallenge) -> chunk_count = get_custody_chunk_count(attestation.data.crosslink) assert chunk_count == len(challenge.chunk_bits) # Verify custody bit is incorrect - committee = get_crosslink_committee(state, epoch, shard) + committee = get_beacon_committee(state, epoch, shard) custody_bit = attestation.custody_bits[committee.index(challenge.responder_index)] assert custody_bit != get_chunk_bits_root(challenge.chunk_bits) # Add new bit challenge record diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 9bd9c70ee..477dce44f 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -62,6 +62,7 @@ This document describes the shard transition function (data layer only) and the | Name | Value | | - | - | +| `SHARD_COUNT` | `2**10` (= 1,024) | | `MIN_BLOCK_BODY_PRICE` | `2**0` (= 1) | | `MAX_PERIOD_COMMITTEE_SIZE` | `2**7` (= 128) | | `SHARD_HEADER_SIZE` | `2**10` (= 1024) | diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 15edc1e28..454b99a41 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -150,7 +150,7 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): for index in range(get_committees_per_slot(state, Slot(slot))): - committee = get_crosslink_committee(state, Slot(slot), CommitteeIndex(index)) + committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index)) if validator_index in committee: return committee, CommitteeIndex(index), Slot(slot) return None @@ -166,7 +166,7 @@ def is_proposer(state: BeaconState, *Note*: To see if a validator is assigned to propose during the slot, the beacon state must be in the epoch in question. At the epoch boundaries, the validator must run an epoch transition into the epoch to successfully check the proposal assignment of the first slot. -*Note*: `BeaconBlock` proposal is distinct from crosslink committee assignment, and in a given epoch each responsibility might occur at different a different slot. +*Note*: `BeaconBlock` proposal is distinct from beacon committee assignment, and in a given epoch each responsibility might occur at different a different slot. ### Lookahead diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index afd51b0bd..e4540738a 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -46,13 +46,13 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False): attestation_data = build_attestation_data(spec, state, slot, index) - crosslink_committee = spec.get_crosslink_committee( + beacon_committee = spec.get_beacon_committee( state, attestation_data.slot, attestation_data.index, ) - committee_size = len(crosslink_committee) + committee_size = len(beacon_committee) aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](*([0] * committee_size)) custody_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](*([0] * committee_size)) attestation = spec.Attestation( @@ -115,12 +115,12 @@ def get_attestation_signature(spec, state, attestation_data, privkey, custody_bi def fill_aggregate_attestation(spec, state, attestation): - crosslink_committee = spec.get_crosslink_committee( + beacon_committee = spec.get_beacon_committee( state, attestation.data.slot, attestation.data.index, ) - for i in range(len(crosslink_committee)): + for i in range(len(beacon_committee)): attestation.aggregation_bits[i] = True diff --git a/test_libs/pyspec/eth2spec/test/helpers/custody.py b/test_libs/pyspec/eth2spec/test/helpers/custody.py index 98659ee8e..205a335f4 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/custody.py +++ b/test_libs/pyspec/eth2spec/test/helpers/custody.py @@ -80,13 +80,13 @@ def bitlist_from_int(max_len, num_bits, n): def get_valid_bit_challenge(spec, state, attestation, invalid_custody_bit=False): - crosslink_committee = spec.get_crosslink_committee( + beacon_committee = spec.get_beacon_committee( state, attestation.data.slot, attestation.data.crosslink.shard, ) - responder_index = crosslink_committee[0] - challenger_index = crosslink_committee[-1] + responder_index = beacon_committee[0] + challenger_index = beacon_committee[-1] epoch = spec.get_randao_epoch_for_custody_period(attestation.data.target.epoch, responder_index) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 8fc3f9866..88470eb93 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -34,7 +34,7 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support if remaining_balance < 0: return - committee = spec.get_crosslink_committee(state, slot, index) + committee = spec.get_beacon_committee(state, slot, index) # Create a bitfield filled with the given count per attestation, # exactly on the right-most part of the committee field. From 7af2c232708425a7574d509fa028f50e2b3c1cb3 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 17 Oct 2019 10:47:39 +0900 Subject: [PATCH 14/23] remove refs to crosslinks --- specs/core/0_beacon-chain.md | 9 ++++----- specs/test_formats/epoch_processing/README.md | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index bf941eabd..fd52b69f1 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -123,7 +123,7 @@ This document represents the specification for Phase 0 of Ethereum 2.0 -- The Beacon Chain. At the core of Ethereum 2.0 is a system chain called the "beacon chain". The beacon chain stores and manages the registry of validators. In the initial deployment phases of Ethereum 2.0, the only mechanism to become a validator is to make a one-way ETH transaction to a deposit contract on Ethereum 1.0. Activation as a validator happens when Ethereum 1.0 deposit receipts are processed by the beacon chain, the activation balance is reached, and a queuing process is completed. Exit is either voluntary or done forcibly as a penalty for misbehavior. -The primary source of load on the beacon chain is "attestations". Attestations are simultaneously availability votes for a shard block and proof-of-stake votes for a beacon block. A sufficient number of attestations for the same shard block create a "crosslink", confirming the shard segment up to that shard block into the beacon chain. Crosslinks also serve as infrastructure for asynchronous cross-shard communication. +The primary source of load on the beacon chain is "attestations". Attestations are simultaneously availability votes for a shard block (Phase 1) and proof-of-stake votes for a beacon block (Phase 0). ## Notation @@ -169,7 +169,6 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | -| `SHARD_COUNT` | `2**10` (= 1,024) | | `MAX_COMMITTEES_PER_SLOT` | `2**5` (= 32) | | `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | | `MAX_VALIDATORS_PER_COMMITTEE` | `2**12` (= 4,096) | @@ -179,7 +178,7 @@ The following values are (non-configurable) constants used throughout the specif | `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` | `2**16` (= 65,536) | | `MIN_GENESIS_TIME` | `1578009600` (Jan 3, 2020) | -- For the safety of crosslinks, `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) +- For the safety of committees, `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) ### Gwei values @@ -319,7 +318,7 @@ class AttestationData(Container): ```python class AttestationDataAndCustodyBit(Container): data: AttestationData - custody_bit: bit # Challengeable bit (SSZ-bool, 1 byte) for the custody of crosslink data + custody_bit: bit # Challengeable bit (SSZ-bool, 1 byte) for the custody of shard data ``` #### `IndexedAttestation` @@ -877,7 +876,7 @@ def get_committees_per_slot(state: BeaconState, slot: Slot) -> uint64: ```python def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]: """ - Return the crosslink committee at ``slot`` for ``index``. + Return the beacon committee at ``slot`` for ``index``. """ epoch = compute_epoch_of_slot(slot) committees_per_slot = get_committees_per_slot(state, slot) diff --git a/specs/test_formats/epoch_processing/README.md b/specs/test_formats/epoch_processing/README.md index d5b5e2c6d..7c5e2dc70 100644 --- a/specs/test_formats/epoch_processing/README.md +++ b/specs/test_formats/epoch_processing/README.md @@ -38,7 +38,6 @@ The provided pre-state is already transitioned to just before the specific sub-t Sub-transitions: - `justification_and_finalization` -- `crosslinks` - *`rewards_and_penalties` - planned testing extension* - `registry_updates` - `slashings` From 283a8cbf0d67e00950d2a1800c9e8803b447643b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 17 Oct 2019 10:49:49 +0900 Subject: [PATCH 15/23] remove refs to crosslinks --- test_generators/epoch_processing/main.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test_generators/epoch_processing/main.py b/test_generators/epoch_processing/main.py index f0505ee94..52581d8c3 100644 --- a/test_generators/epoch_processing/main.py +++ b/test_generators/epoch_processing/main.py @@ -3,7 +3,6 @@ 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 ( - test_process_crosslinks, test_process_final_updates, test_process_justification_and_finalization, test_process_registry_updates, @@ -35,8 +34,6 @@ def create_provider(handler_name: str, tests_src, config_name: str) -> gen_typin if __name__ == "__main__": gen_runner.run_generator("epoch_processing", [ - create_provider('crosslinks', test_process_crosslinks, 'minimal'), - create_provider('crosslinks', test_process_crosslinks, 'mainnet'), create_provider('final_updates', test_process_final_updates, 'minimal'), create_provider('final_updates', test_process_final_updates, 'mainnet'), create_provider('justification_and_finalization', test_process_justification_and_finalization, 'minimal'), From 437a65d3e121f8ff887a1fb20c0568e467ad686b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 17 Oct 2019 17:47:51 +0900 Subject: [PATCH 16/23] cleanup wrt Justin's comments --- configs/mainnet.yaml | 8 ++--- configs/minimal.yaml | 6 ++-- scripts/build_spec.py | 2 +- specs/core/0_beacon-chain.md | 36 +++++++++---------- specs/core/1_custody-game.md | 2 +- specs/validator/0_beacon-chain-validator.md | 10 +++--- .../eth2spec/test/helpers/attestations.py | 4 +-- .../pyspec/eth2spec/test/helpers/state.py | 4 +-- .../test_process_attestation.py | 2 +- ..._process_justification_and_finalization.py | 2 +- 10 files changed, 37 insertions(+), 39 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 1210d8076..1a65084e2 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -5,12 +5,12 @@ # Misc # --------------------------------------------------------------- -# 2**5 (= 32) -MAX_COMMITTEES_PER_SLOT: 32 +# 2**6 (= 64) +MAX_COMMITTEES_PER_SLOT: 64 # 2**7 (= 128) TARGET_COMMITTEE_SIZE: 128 -# 2**12 (= 4,096) -MAX_VALIDATORS_PER_COMMITTEE: 4096 +# 2**10 (= 1,024) +MAX_VALIDATORS_PER_COMMITTEE: 1024 # 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4 # 2**16 (= 65,536) diff --git a/configs/minimal.yaml b/configs/minimal.yaml index 1cf35ca90..f9eb5c4fe 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -4,12 +4,12 @@ # Misc # --------------------------------------------------------------- -# [customized] Just 2 committees for slot for testing purposes +# [customized] Just 4 committees for slot for testing purposes MAX_COMMITTEES_PER_SLOT: 4 # [customized] unsecure, but fast TARGET_COMMITTEE_SIZE: 4 -# 2**12 (= 4,096) -MAX_VALIDATORS_PER_COMMITTEE: 4096 +# 2**10 (= 1,024) +MAX_VALIDATORS_PER_COMMITTEE: 1024 # 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4 # 2**16 (= 65,536) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index f35332e64..c47249fe4 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -118,7 +118,7 @@ def apply_constants_preset(preset: Dict[str, Any]) -> None: global_vars[k] = v # Deal with derived constants - global_vars['GENESIS_EPOCH'] = compute_epoch_of_slot(GENESIS_SLOT) + global_vars['GENESIS_EPOCH'] = compute_epoch_at_slot(GENESIS_SLOT) # Initialize SSZ types again, to account for changed lengths init_SSZ_types() diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fd52b69f1..dced36a1b 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -68,7 +68,7 @@ - [`compute_shuffled_index`](#compute_shuffled_index) - [`compute_proposer_index`](#compute_proposer_index) - [`compute_committee`](#compute_committee) - - [`compute_epoch_of_slot`](#compute_epoch_of_slot) + - [`compute_epoch_at_slot`](#compute_epoch_at_slot) - [`compute_start_slot_of_epoch`](#compute_start_slot_of_epoch) - [`compute_activation_exit_epoch`](#compute_activation_exit_epoch) - [`compute_domain`](#compute_domain) @@ -137,8 +137,7 @@ We define the following Python custom types for type hinting and readability: | - | - | - | | `Slot` | `uint64` | a slot number | | `Epoch` | `uint64` | an epoch number | -| `CommitteeIndex` | `uint64` | an index for a committee within a slot | -| `Shard` | `uint64` | a shard number | +| `CommitteeIndex` | `uint64` | a committee index at a slot | | `ValidatorIndex` | `uint64` | a validator registry index | | `Gwei` | `uint64` | an amount in Gwei | | `Hash` | `Bytes32` | a hash | @@ -169,9 +168,9 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | -| `MAX_COMMITTEES_PER_SLOT` | `2**5` (= 32) | +| `MAX_COMMITTEES_PER_SLOT` | `2**6` (= 64) | | `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | -| `MAX_VALIDATORS_PER_COMMITTEE` | `2**12` (= 4,096) | +| `MAX_VALIDATORS_PER_COMMITTEE` | `2**10` (= 1,024) | | `MIN_PER_EPOCH_CHURN_LIMIT` | `2**2` (= 4) | | `CHURN_LIMIT_QUOTIENT` | `2**16` (= 65,536) | | `SHUFFLE_ROUND_COUNT` | `90` | @@ -304,13 +303,12 @@ class Validator(Container): ```python class AttestationData(Container): slot: Slot + index: CommitteeIndex # LMD GHOST vote beacon_block_root: Hash # FFG vote source: Checkpoint target: Checkpoint - # Committee Index - index: CommitteeIndex ``` #### `AttestationDataAndCustodyBit` @@ -489,7 +487,7 @@ class BeaconState(Container): # Registry validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - # Shuffling + # Randomness randao_mixes: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Slashings slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances @@ -731,12 +729,12 @@ def compute_committee(indices: Sequence[ValidatorIndex], return [indices[compute_shuffled_index(ValidatorIndex(i), len(indices), seed)] for i in range(start, end)] ``` -#### `compute_epoch_of_slot` +#### `compute_epoch_at_slot` ```python -def compute_epoch_of_slot(slot: Slot) -> Epoch: +def compute_epoch_at_slot(slot: Slot) -> Epoch: """ - Return the epoch number of ``slot``. + Return the epoch number at ``slot``. """ return Epoch(slot // SLOTS_PER_EPOCH) ``` @@ -780,7 +778,7 @@ def get_current_epoch(state: BeaconState) -> Epoch: """ Return the current epoch. """ - return compute_epoch_of_slot(state.slot) + return compute_epoch_at_slot(state.slot) ``` #### `get_previous_epoch` @@ -857,14 +855,14 @@ def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Hash: return hash(domain_type + int_to_bytes(epoch, length=8) + mix) ``` -#### `get_committees_per_slot` +#### `get_committee_count_at_slot` ```python -def get_committees_per_slot(state: BeaconState, slot: Slot) -> uint64: +def get_committee_count_at_slot(state: BeaconState, slot: Slot) -> uint64: """ Return the number of committees at ``slot``. """ - epoch = compute_epoch_of_slot(slot) + epoch = compute_epoch_at_slot(slot) return max(1, min( MAX_COMMITTEES_PER_SLOT, len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, @@ -878,8 +876,8 @@ def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) """ Return the beacon committee at ``slot`` for ``index``. """ - epoch = compute_epoch_of_slot(slot) - committees_per_slot = get_committees_per_slot(state, slot) + epoch = compute_epoch_at_slot(slot) + committees_per_slot = get_committee_count_at_slot(state, slot) epoch_offset = index + (slot % SLOTS_PER_EPOCH) * committees_per_slot return compute_committee( @@ -1468,7 +1466,7 @@ def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSla assert is_slashable_validator(proposer, get_current_epoch(state)) # Signatures are valid for header in (proposer_slashing.header_1, proposer_slashing.header_2): - domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_of_slot(header.slot)) + domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(header.slot)) assert bls_verify(proposer.pubkey, signing_root(header), header.signature, domain) slash_validator(state, proposer_slashing.proposer_index) @@ -1499,7 +1497,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_committees_per_slot(state, data.slot) + assert data.index < get_committee_count_at_slot(state, data.slot) assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 80a42cc14..224dfd5f2 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -547,7 +547,7 @@ def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge # Verify the attestation assert is_valid_indexed_attestation(state, get_indexed_attestation(state, challenge.attestation)) # Verify it is not too late to challenge - assert (compute_epoch_of_slot(challenge.attestation.data.slot) + assert (compute_epoch_at_slot(challenge.attestation.data.slot) >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY) responder = state.validators[challenge.responder_index] assert responder.exit_epoch >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 454b99a41..331184699 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -149,7 +149,7 @@ def get_committee_assignment(state: BeaconState, start_slot = compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): - for index in range(get_committees_per_slot(state, Slot(slot))): + for index in range(get_committee_count_at_slot(state, Slot(slot))): committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index)) if validator_index in committee: return committee, CommitteeIndex(index), Slot(slot) @@ -210,8 +210,8 @@ Set `block.randao_reveal = epoch_signature` where `epoch_signature` is obtained ```python def get_epoch_signature(state: BeaconState, block: BeaconBlock, privkey: int) -> BLSSignature: - domain = get_domain(state, DOMAIN_RANDAO, compute_epoch_of_slot(block.slot)) - return bls_sign(privkey, hash_tree_root(compute_epoch_of_slot(block.slot)), domain) + domain = get_domain(state, DOMAIN_RANDAO, compute_epoch_at_slot(block.slot)) + return bls_sign(privkey, hash_tree_root(compute_epoch_at_slot(block.slot)), domain) ``` ##### Eth1 Data @@ -244,7 +244,7 @@ Set `header.signature = block_signature` where `block_signature` is obtained fro ```python def get_block_signature(state: BeaconState, header: BeaconBlockHeader, privkey: int) -> BLSSignature: - domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_of_slot(header.slot)) + domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(header.slot)) return bls_sign(privkey, signing_root(header), domain) ``` @@ -352,7 +352,7 @@ To avoid "proposer slashings", a validator must not sign two conflicting [`Beaco Specifically, when signing a `BeaconBlock`, a validator should perform the following steps in the following order: -1. Save a record to hard disk that a beacon block has been signed for the `epoch=compute_epoch_of_slot(block.slot)`. +1. Save a record to hard disk that a beacon block has been signed for the `epoch=compute_epoch_at_slot(block.slot)`. 2. Generate and broadcast the block. If the software crashes at some point within this routine, then when the validator comes back online, the hard disk has the record of the *potentially* signed/broadcast block and can effectively avoid slashing. diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index e4540738a..5e5073441 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -31,10 +31,10 @@ def build_attestation_data(spec, state, slot, index): return spec.AttestationData( slot=slot, + index=index, beacon_block_root=block_root, source=spec.Checkpoint(epoch=source_epoch, root=source_root), - target=spec.Checkpoint(epoch=spec.compute_epoch_of_slot(slot), root=epoch_boundary_root), - index=index, + target=spec.Checkpoint(epoch=spec.compute_epoch_at_slot(slot), root=epoch_boundary_root), ) diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py index 68b8283bc..c5a9bd4ce 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/state.py +++ b/test_libs/pyspec/eth2spec/test/helpers/state.py @@ -52,7 +52,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_committees_per_slot(state, slot_to_attest) + committees_per_slot = spec.get_committee_count_at_slot(state, slot_to_attest) if slot_to_attest >= spec.compute_start_slot_of_epoch(spec.get_current_epoch(post_state)): for index in range(committees_per_slot): cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) @@ -60,7 +60,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_committees_per_slot(state, slot_to_attest) + committees_per_slot = spec.get_committee_count_at_slot(state, slot_to_attest) for index in range(committees_per_slot): prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) block.body.attestations.append(prev_attestation) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index e3ccb5d9f..13faed3f4 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -138,7 +138,7 @@ def test_wrong_index_for_committee_signature(spec, state): @spec_state_test @never_bls def test_wrong_index_for_slot(spec, state): - committees_per_slot = spec.get_committees_per_slot(state, state.slot) + committees_per_slot = spec.get_committee_count_at_slot(state, state.slot) assert committees_per_slot < spec.MAX_COMMITTEES_PER_SLOT index = committees_per_slot diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 88470eb93..81f761a72 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -27,7 +27,7 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support start_slot = spec.compute_start_slot_of_epoch(epoch) for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH): - committees_per_slot = spec.get_committees_per_slot(state, slot) + 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) From fbcc2a4870f230a9744456702ca6ef5d48ff4e50 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 18 Oct 2019 12:05:43 +0900 Subject: [PATCH 17/23] fix comment re: proto --- specs/core/1_shard-data-chains.md | 2 +- test_libs/pyspec/eth2spec/test/helpers/block.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 477dce44f..6edc5daba 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -106,8 +106,8 @@ This document describes the shard transition function (data layer only) and the ### `Crosslink` ```python +# Crosslink is a placeholder to appease the build script until phase 1 is reworked class Crosslink(Container): - # STUB: placeholder data structure while reworking phase 0 shard: Shard ``` diff --git a/test_libs/pyspec/eth2spec/test/helpers/block.py b/test_libs/pyspec/eth2spec/test/helpers/block.py index 2682a0c82..779f2e1cf 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/block.py +++ b/test_libs/pyspec/eth2spec/test/helpers/block.py @@ -14,7 +14,7 @@ def sign_block(spec, state, block, proposer_index=None): if block.slot == state.slot: proposer_index = spec.get_beacon_proposer_index(state) else: - if spec.compute_epoch_of_slot(state.slot) + 1 > spec.compute_epoch_of_slot(block.slot): + if spec.compute_epoch_at_slot(state.slot) + 1 > spec.compute_epoch_at_slot(block.slot): print("warning: block slot far away, and no proposer index manually given." " Signing block is slow due to transition for proposer index calculation.") # use stub state to get proposer index of future slot @@ -26,10 +26,10 @@ def sign_block(spec, state, block, proposer_index=None): block.body.randao_reveal = bls_sign( privkey=privkey, - message_hash=hash_tree_root(spec.compute_epoch_of_slot(block.slot)), + message_hash=hash_tree_root(spec.compute_epoch_at_slot(block.slot)), domain=spec.get_domain( state, - message_epoch=spec.compute_epoch_of_slot(block.slot), + message_epoch=spec.compute_epoch_at_slot(block.slot), domain_type=spec.DOMAIN_RANDAO, ) ) @@ -39,7 +39,7 @@ def sign_block(spec, state, block, proposer_index=None): domain=spec.get_domain( state, spec.DOMAIN_BEACON_PROPOSER, - spec.compute_epoch_of_slot(block.slot))) + spec.compute_epoch_at_slot(block.slot))) def apply_empty_block(spec, state): From 58c28349de46c34fe36997725201485c43fbc566 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 18 Oct 2019 12:10:36 +0900 Subject: [PATCH 18/23] proto pr feedback --- specs/core/0_fork-choice.md | 3 +-- specs/validator/0_beacon-chain-validator.md | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 8e25fe8f3..552a3cb02 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -192,8 +192,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None: # Attestations can only affect the fork choice of subsequent slots. # Delay consideration in the fork choice until their slot is in the past. - attestation_slot = attestation.data.slot - assert store.time >= (attestation_slot + 1) * SECONDS_PER_SLOT + assert store.time >= (attestation.data.slot + 1) * SECONDS_PER_SLOT # Get state at the `target` to validate attestation and calculate the committees indexed_attestation = get_indexed_attestation(target_state, attestation) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 331184699..1be028df4 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -285,6 +285,11 @@ First, the validator should construct `attestation_data`, an [`AttestationData`] - Let `head_block` be the result of running the fork choice during the assigned slot. - Let `head_state` be the state of `head_block` processed through any empty slots up to the assigned slot using `process_slots(state, slot)`. +##### General + +* Set `attestation_data.slot = slot` where `slot` is the assigned slot. +* Set `attestation_data.index = index` where `index` is the index associated with the validator's committee. + ##### LMD GHOST vote Set `attestation_data.beacon_block_root = signing_root(head_block)`. @@ -299,10 +304,6 @@ Set `attestation_data.beacon_block_root = signing_root(head_block)`. - Let `start_slot = compute_start_slot_of_epoch(get_current_epoch(head_state))`. - Let `epoch_boundary_block_root = signing_root(head_block) if start_slot == head_state.slot else get_block_root(state, start_slot)`. -##### Index - -Set `attestation_data.index = index` where `index` is the index associated with the validator's committee. - #### Construct attestation Next, the validator creates `attestation`, an [`Attestation`](../core/0_beacon-chain.md#attestation) object. From d5a2535f98b48d9ef80d66ba684f16745ef787e2 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 18 Oct 2019 12:17:46 +0900 Subject: [PATCH 19/23] minor comments resolved from hww --- specs/core/0_beacon-chain.md | 10 ++++------ specs/core/1_beacon-chain-misc.md | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index dced36a1b..ca968713d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -878,12 +878,10 @@ def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) """ epoch = compute_epoch_at_slot(slot) committees_per_slot = get_committee_count_at_slot(state, slot) - epoch_offset = index + (slot % SLOTS_PER_EPOCH) * committees_per_slot - return compute_committee( indices=get_active_validator_indices(state, epoch), seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), - index=epoch_offset, + index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index, count=committees_per_slot * SLOTS_PER_EPOCH, ) ``` @@ -1300,10 +1298,10 @@ def process_rewards_and_penalties(state: BeaconState) -> None: if get_current_epoch(state) == GENESIS_EPOCH: return - rewards1, penalties1 = get_attestation_deltas(state) + rewards, penalties = get_attestation_deltas(state) for index in range(len(state.validators)): - increase_balance(state, ValidatorIndex(index), rewards1[index]) - decrease_balance(state, ValidatorIndex(index), penalties1[index]) + increase_balance(state, ValidatorIndex(index), rewards[index]) + decrease_balance(state, ValidatorIndex(index), penalties[index]) ``` #### Registry updates diff --git a/specs/core/1_beacon-chain-misc.md b/specs/core/1_beacon-chain-misc.md index 9f7a4d2d7..6dd6e19c3 100644 --- a/specs/core/1_beacon-chain-misc.md +++ b/specs/core/1_beacon-chain-misc.md @@ -31,7 +31,6 @@ | Name | Value | Unit | Duration | - | - | - | - | -| `MAX_EPOCHS_PER_CROSSLINK` | `2**6` (= 64) | epochs | ~7 hours | | `MAX_SHARD_RECEIPT_PROOFS` | `2**0` (= 1) | - | - | | `PERIOD_COMMITTEE_ROOT_LENGTH` | `2**8` (= 256) | periods | ~9 months | | `MINOR_REWARD_QUOTIENT` | `2**8` (=256) | - | - | From a11b01296bc1d19deba3c01c26de82d5f88d474d Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 20 Oct 2019 12:38:00 +0800 Subject: [PATCH 20/23] update constants for phase 0 simplification --- configs/mainnet.yaml | 12 ++++++------ configs/minimal.yaml | 6 +++--- specs/core/0_beacon-chain.md | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 1a65084e2..1a2e1ea83 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -9,8 +9,8 @@ MAX_COMMITTEES_PER_SLOT: 64 # 2**7 (= 128) TARGET_COMMITTEE_SIZE: 128 -# 2**10 (= 1,024) -MAX_VALIDATORS_PER_COMMITTEE: 1024 +# 2**11 (= 2,048) +MAX_VALIDATORS_PER_COMMITTEE: 2048 # 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4 # 2**16 (= 65,536) @@ -51,12 +51,12 @@ BLS_WITHDRAWAL_PREFIX: 0x00 # Time parameters # --------------------------------------------------------------- -# 6 seconds 6 seconds -SECONDS_PER_SLOT: 6 +# 12 seconds +SECONDS_PER_SLOT: 12 # 2**0 (= 1) slots 6 seconds MIN_ATTESTATION_INCLUSION_DELAY: 1 -# 2**6 (= 64) slots 6.4 minutes -SLOTS_PER_EPOCH: 64 +# 2**6 (= 32) slots 6.4 minutes +SLOTS_PER_EPOCH: 32 # 2**0 (= 1) epochs 6.4 minutes MIN_SEED_LOOKAHEAD: 1 # 2**2 (= 4) epochs 25.6 minutes diff --git a/configs/minimal.yaml b/configs/minimal.yaml index f9eb5c4fe..75b93f66a 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -8,8 +8,8 @@ MAX_COMMITTEES_PER_SLOT: 4 # [customized] unsecure, but fast TARGET_COMMITTEE_SIZE: 4 -# 2**10 (= 1,024) -MAX_VALIDATORS_PER_COMMITTEE: 1024 +# 2**11 (= 2,048) +MAX_VALIDATORS_PER_COMMITTEE: 2048 # 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4 # 2**16 (= 65,536) @@ -50,7 +50,7 @@ BLS_WITHDRAWAL_PREFIX: 0x00 # Time parameters # --------------------------------------------------------------- -# 6 seconds 6 seconds +# [customized] Faster for testing purposes SECONDS_PER_SLOT: 6 # 2**0 (= 1) slots 6 seconds MIN_ATTESTATION_INCLUSION_DELAY: 1 diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index ca968713d..9be1f07d8 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -154,7 +154,7 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | | - | - | | `FAR_FUTURE_EPOCH` | `Epoch(2**64 - 1)` | -| `BASE_REWARDS_PER_EPOCH` | `5` | +| `BASE_REWARDS_PER_EPOCH` | `4` | | `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) | | `SECONDS_PER_DAY` | `86400` | | `JUSTIFICATION_BITS_LENGTH` | `4` | @@ -170,7 +170,7 @@ The following values are (non-configurable) constants used throughout the specif | - | - | | `MAX_COMMITTEES_PER_SLOT` | `2**6` (= 64) | | `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | -| `MAX_VALIDATORS_PER_COMMITTEE` | `2**10` (= 1,024) | +| `MAX_VALIDATORS_PER_COMMITTEE` | `2**11` (= 2,048) | | `MIN_PER_EPOCH_CHURN_LIMIT` | `2**2` (= 4) | | `CHURN_LIMIT_QUOTIENT` | `2**16` (= 65,536) | | `SHUFFLE_ROUND_COUNT` | `90` | @@ -200,9 +200,9 @@ The following values are (non-configurable) constants used throughout the specif | Name | Value | Unit | Duration | | - | - | :-: | :-: | -| `SECONDS_PER_SLOT` | `6` | seconds | 6 seconds | -| `MIN_ATTESTATION_INCLUSION_DELAY` | `2**0` (= 1) | slots | 6 seconds | -| `SLOTS_PER_EPOCH` | `2**6` (= 64) | slots | 6.4 minutes | +| `SECONDS_PER_SLOT` | `12` | seconds | 12 seconds | +| `MIN_ATTESTATION_INCLUSION_DELAY` | `2**0` (= 1) | slots | 12 seconds | +| `SLOTS_PER_EPOCH` | `2**5` (= 32) | slots | 6.4 minutes | | `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | | `MAX_SEED_LOOKAHEAD` | `2**2` (= 4) | epochs | 25.6 minutes | | `SLOTS_PER_ETH1_VOTING_PERIOD` | `2**10` (= 1,024) | slots | ~1.7 hours | From e86ff1ead7db5e3c87eefe4ace3d401521a4523e Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 20 Oct 2019 00:43:36 -0500 Subject: [PATCH 21/23] minor fix to mainnet config comments Co-Authored-By: Cayman --- configs/mainnet.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 1a2e1ea83..45d5b6894 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -55,7 +55,7 @@ BLS_WITHDRAWAL_PREFIX: 0x00 SECONDS_PER_SLOT: 12 # 2**0 (= 1) slots 6 seconds MIN_ATTESTATION_INCLUSION_DELAY: 1 -# 2**6 (= 32) slots 6.4 minutes +# 2**5 (= 32) slots 6.4 minutes SLOTS_PER_EPOCH: 32 # 2**0 (= 1) epochs 6.4 minutes MIN_SEED_LOOKAHEAD: 1 From f809b21241cedeeb6d287c921c0880feb3efebdc Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 23 Oct 2019 09:37:15 +0900 Subject: [PATCH 22/23] minor pr review --- specs/core/0_beacon-chain.md | 8 ++++---- specs/core/0_fork-choice.md | 8 ++++---- specs/core/1_beacon-chain-misc.md | 2 +- specs/light_client/sync_protocol.md | 4 ++-- specs/validator/0_beacon-chain-validator.md | 4 ++-- test_libs/pyspec/eth2spec/test/helpers/attestations.py | 2 +- test_libs/pyspec/eth2spec/test/helpers/state.py | 2 +- .../test_process_justification_and_finalization.py | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 9be1f07d8..8d8fd2c15 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -69,7 +69,7 @@ - [`compute_proposer_index`](#compute_proposer_index) - [`compute_committee`](#compute_committee) - [`compute_epoch_at_slot`](#compute_epoch_at_slot) - - [`compute_start_slot_of_epoch`](#compute_start_slot_of_epoch) + - [`compute_start_slot_at_epoch`](#compute_start_slot_at_epoch) - [`compute_activation_exit_epoch`](#compute_activation_exit_epoch) - [`compute_domain`](#compute_domain) - [Beacon state accessors](#beacon-state-accessors) @@ -739,10 +739,10 @@ def compute_epoch_at_slot(slot: Slot) -> Epoch: return Epoch(slot // SLOTS_PER_EPOCH) ``` -#### `compute_start_slot_of_epoch` +#### `compute_start_slot_at_epoch` ```python -def compute_start_slot_of_epoch(epoch: Epoch) -> Slot: +def compute_start_slot_at_epoch(epoch: Epoch) -> Slot: """ Return the start slot of ``epoch``. """ @@ -799,7 +799,7 @@ def get_block_root(state: BeaconState, epoch: Epoch) -> Hash: """ Return the block root at the start of a recent ``epoch``. """ - return get_block_root_at_slot(state, compute_start_slot_of_epoch(epoch)) + return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch)) ``` #### `get_block_root_at_slot` diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 552a3cb02..88edceaa0 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -118,7 +118,7 @@ def get_latest_attesting_balance(store: Store, root: Hash) -> Gwei: def get_head(store: Store) -> Hash: # Execute the LMD-GHOST fork choice head = store.justified_checkpoint.root - justified_slot = compute_start_slot_of_epoch(store.justified_checkpoint.epoch) + justified_slot = compute_start_slot_at_epoch(store.justified_checkpoint.epoch) while True: children = [ root for root in store.blocks.keys() @@ -156,7 +156,7 @@ def on_block(store: Store, block: BeaconBlock) -> None: store.finalized_checkpoint.root ) # Check that block is later than the finalized epoch slot - assert block.slot > compute_start_slot_of_epoch(store.finalized_checkpoint.epoch) + assert block.slot > compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) # Check the block is valid and compute the post-state state = state_transition(pre_state, block) # Add new state for this block to the store @@ -182,11 +182,11 @@ def on_attestation(store: Store, attestation: Attestation) -> None: # Attestations cannot be from future epochs. If they are, delay consideration until the epoch arrives base_state = store.block_states[target.root].copy() - assert store.time >= base_state.genesis_time + compute_start_slot_of_epoch(target.epoch) * SECONDS_PER_SLOT + assert store.time >= base_state.genesis_time + compute_start_slot_at_epoch(target.epoch) * SECONDS_PER_SLOT # Store target checkpoint state if not yet seen if target not in store.checkpoint_states: - process_slots(base_state, compute_start_slot_of_epoch(target.epoch)) + process_slots(base_state, compute_start_slot_at_epoch(target.epoch)) store.checkpoint_states[target] = base_state target_state = store.checkpoint_states[target] diff --git a/specs/core/1_beacon-chain-misc.md b/specs/core/1_beacon-chain-misc.md index 6dd6e19c3..6a8d06d4a 100644 --- a/specs/core/1_beacon-chain-misc.md +++ b/specs/core/1_beacon-chain-misc.md @@ -203,7 +203,7 @@ class BeaconState(Container): ``` `period_committee_roots` values are initialized to `Bytes32()` (empty bytes value). -`next_shard_receipt_period` values are initialized to `compute_epoch_of_slot(PHASE_1_FORK_SLOT) // EPOCHS_PER_SHARD_PERIOD`. +`next_shard_receipt_period` values are initialized to `compute_epoch_at_slot(PHASE_1_FORK_SLOT) // EPOCHS_PER_SHARD_PERIOD`. #### `BeaconBlockBody` diff --git a/specs/light_client/sync_protocol.md b/specs/light_client/sync_protocol.md index c3b035270..ef9e2b7bc 100644 --- a/specs/light_client/sync_protocol.md +++ b/specs/light_client/sync_protocol.md @@ -84,7 +84,7 @@ def get_persistent_committee_pubkeys_and_balances(memory: LightClientMemory, """ Return pubkeys and balances for the persistent committee at ``epoch``. """ - current_period = compute_epoch_of_slot(memory.header.slot) // EPOCHS_PER_SHARD_PERIOD + current_period = compute_epoch_at_slot(memory.header.slot) // EPOCHS_PER_SHARD_PERIOD next_period = epoch // EPOCHS_PER_SHARD_PERIOD assert next_period in (current_period, current_period + 1) if next_period == current_period: @@ -114,7 +114,7 @@ The state of a light client is stored in a `memory` object of type `LightClientM ```python def update_memory(memory: LightClientMemory, update: LightClientUpdate) -> None: # Verify the update does not skip a period - current_period = compute_epoch_of_slot(memory.header.slot) // EPOCHS_PER_SHARD_PERIOD + current_period = compute_epoch_at_slot(memory.header.slot) // EPOCHS_PER_SHARD_PERIOD next_epoch = compute_epoch_of_shard_slot(update.header.slot) next_period = next_epoch // EPOCHS_PER_SHARD_PERIOD assert next_period in (current_period, current_period + 1) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 1be028df4..13c688468 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -147,7 +147,7 @@ def get_committee_assignment(state: BeaconState, next_epoch = get_current_epoch(state) + 1 assert epoch <= next_epoch - start_slot = compute_start_slot_of_epoch(epoch) + start_slot = compute_start_slot_at_epoch(epoch) for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH): for index in range(get_committee_count_at_slot(state, Slot(slot))): committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index)) @@ -301,7 +301,7 @@ Set `attestation_data.beacon_block_root = signing_root(head_block)`. *Note*: `epoch_boundary_block_root` can be looked up in the state using: -- Let `start_slot = compute_start_slot_of_epoch(get_current_epoch(head_state))`. +- Let `start_slot = compute_start_slot_at_epoch(get_current_epoch(head_state))`. - Let `epoch_boundary_block_root = signing_root(head_block) if start_slot == head_state.slot else get_block_root(state, start_slot)`. #### Construct attestation diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index 5e5073441..f3454fe4c 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -14,7 +14,7 @@ def build_attestation_data(spec, state, slot, index): else: block_root = spec.get_block_root_at_slot(state, slot) - current_epoch_start_slot = spec.compute_start_slot_of_epoch(spec.get_current_epoch(state)) + current_epoch_start_slot = spec.compute_start_slot_at_epoch(spec.get_current_epoch(state)) if slot < current_epoch_start_slot: epoch_boundary_root = spec.get_block_root(state, spec.get_previous_epoch(state)) elif slot == current_epoch_start_slot: diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py index c5a9bd4ce..27e946cbb 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/state.py +++ b/test_libs/pyspec/eth2spec/test/helpers/state.py @@ -53,7 +53,7 @@ def next_epoch_with_attestations(spec, 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) - if slot_to_attest >= spec.compute_start_slot_of_epoch(spec.get_current_epoch(post_state)): + if slot_to_attest >= spec.compute_start_slot_at_epoch(spec.get_current_epoch(post_state)): for index in range(committees_per_slot): cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest, index=index) block.body.attestations.append(cur_attestation) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py index 81f761a72..002d3b169 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_justification_and_finalization.py @@ -25,7 +25,7 @@ def add_mock_attestations(spec, state, epoch, source, target, sufficient_support total_balance = spec.get_total_active_balance(state) remaining_balance = total_balance * 2 // 3 - start_slot = spec.compute_start_slot_of_epoch(epoch) + start_slot = spec.compute_start_slot_at_epoch(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): @@ -74,7 +74,7 @@ def get_checkpoints(spec, epoch): def put_checkpoints_in_block_roots(spec, state, checkpoints): for c in checkpoints: - state.block_roots[spec.compute_start_slot_of_epoch(c.epoch) % spec.SLOTS_PER_HISTORICAL_ROOT] = c.root + state.block_roots[spec.compute_start_slot_at_epoch(c.epoch) % spec.SLOTS_PER_HISTORICAL_ROOT] = c.root def finalize_on_234(spec, state, epoch, sufficient_support): From 13c3d9c6e9fbee8706e3cbbff131a630f86070c6 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Wed, 23 Oct 2019 12:10:43 +0800 Subject: [PATCH 23/23] Update ToCs --- specs/core/0_beacon-chain.md | 1 + specs/core/1_beacon-chain-misc.md | 1 + specs/core/1_custody-game.md | 2 +- specs/core/1_shard-data-chains.md | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 8d8fd2c15..24f944136 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -81,6 +81,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_beacon_committee`](#get_beacon_committee) - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - [`get_total_balance`](#get_total_balance) diff --git a/specs/core/1_beacon-chain-misc.md b/specs/core/1_beacon-chain-misc.md index 6a8d06d4a..3fdafe3ea 100644 --- a/specs/core/1_beacon-chain-misc.md +++ b/specs/core/1_beacon-chain-misc.md @@ -9,6 +9,7 @@ - [Configuration](#configuration) - [Containers](#containers) - [`CompactCommittee`](#compactcommittee) + - [`ShardReceiptDelta`](#shardreceiptdelta) - [`ShardReceiptProof`](#shardreceiptproof) - [Helper functions](#helper-functions) - [`pack_compact_validator`](#pack_compact_validator) diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 224dfd5f2..67e12a08c 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -336,7 +336,7 @@ def legendre_bit(a: int, q: int) -> int: return 0 ``` -### ```custody_subchunkify``` +### `custody_subchunkify` Given one proof of custody chunk, returns the proof of custody subchunks of the correct sizes. diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 6edc5daba..d9c88e72b 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -18,10 +18,11 @@ - [Rewards and penalties](#rewards-and-penalties) - [Signature domain types](#signature-domain-types) - [Containers](#containers) + - [`Crosslink`](#crosslink) - [`ShardBlock`](#shardblock) - [`ShardBlockHeader`](#shardblockheader) - [`ShardState`](#shardstate) - - [`ShardAttestationData`](#ShardAttestationData) + - [`ShardAttestationData`](#shardattestationdata) - [Helper functions](#helper-functions) - [Misc](#misc-1) - [`compute_epoch_of_shard_slot`](#compute_epoch_of_shard_slot)