diff --git a/scripts/build_spec.py b/scripts/build_spec.py
index 1f5fe1ee6..fe66a72d5 100644
--- a/scripts/build_spec.py
+++ b/scripts/build_spec.py
@@ -12,7 +12,7 @@ from typing import (
PHASE0_IMPORTS = '''from typing import (
- Any, Callable, Dict, Set, Sequence, Tuple,
+ Any, Dict, Set, Sequence, Tuple,
)
from dataclasses import (
@@ -37,7 +37,7 @@ from eth2spec.utils.bls import (
from eth2spec.utils.hash_function import hash
'''
PHASE1_IMPORTS = '''from typing import (
- Any, Callable, Dict, Optional, Set, Sequence, MutableSequence, Tuple,
+ Any, Dict, Optional, Set, Sequence, MutableSequence, Tuple,
)
from dataclasses import (
diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md
index 3930988b1..68915177c 100644
--- a/specs/core/0_beacon-chain.md
+++ b/specs/core/0_beacon-chain.md
@@ -9,7 +9,6 @@
- [Table of contents](#table-of-contents)
- [Introduction](#introduction)
- [Notation](#notation)
- - [Terminology](#terminology)
- [Custom types](#custom-types)
- [Constants](#constants)
- [Configuration](#configuration)
@@ -49,49 +48,54 @@
- [Beacon state](#beacon-state)
- [`BeaconState`](#beaconstate)
- [Helper functions](#helper-functions)
- - [`xor`](#xor)
- - [`hash`](#hash)
- - [`hash_tree_root`](#hash_tree_root)
- - [`signing_root`](#signing_root)
- - [`bls_domain`](#bls_domain)
- - [`slot_to_epoch`](#slot_to_epoch)
- - [`get_previous_epoch`](#get_previous_epoch)
- - [`get_current_epoch`](#get_current_epoch)
- - [`get_epoch_start_slot`](#get_epoch_start_slot)
- - [`is_active_validator`](#is_active_validator)
- - [`is_slashable_validator`](#is_slashable_validator)
- - [`get_active_validator_indices`](#get_active_validator_indices)
- - [`increase_balance`](#increase_balance)
- - [`decrease_balance`](#decrease_balance)
- - [`get_epoch_committee_count`](#get_epoch_committee_count)
- - [`get_shard_delta`](#get_shard_delta)
- - [`get_epoch_start_shard`](#get_epoch_start_shard)
- - [`get_attestation_data_slot`](#get_attestation_data_slot)
- - [`get_block_root_at_slot`](#get_block_root_at_slot)
- - [`get_block_root`](#get_block_root)
- - [`get_randao_mix`](#get_randao_mix)
- - [`get_compact_committees_root`](#get_compact_committees_root)
- - [`generate_seed`](#generate_seed)
- - [`get_beacon_proposer_index`](#get_beacon_proposer_index)
- - [`verify_merkle_branch`](#verify_merkle_branch)
- - [`get_shuffled_index`](#get_shuffled_index)
- - [`compute_committee`](#compute_committee)
- - [`get_crosslink_committee`](#get_crosslink_committee)
- - [`get_attesting_indices`](#get_attesting_indices)
- - [`int_to_bytes`](#int_to_bytes)
- - [`bytes_to_int`](#bytes_to_int)
- - [`get_total_balance`](#get_total_balance)
- - [`get_domain`](#get_domain)
- - [`convert_to_indexed`](#convert_to_indexed)
- - [`validate_indexed_attestation`](#validate_indexed_attestation)
- - [`is_slashable_attestation_data`](#is_slashable_attestation_data)
- - [`integer_squareroot`](#integer_squareroot)
- - [`get_delayed_activation_exit_epoch`](#get_delayed_activation_exit_epoch)
- - [`get_churn_limit`](#get_churn_limit)
- - [`bls_verify`](#bls_verify)
- - [`bls_verify_multiple`](#bls_verify_multiple)
- - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys)
- - [Routines for updating validator status](#routines-for-updating-validator-status)
+ - [Math](#math)
+ - [`integer_squareroot`](#integer_squareroot)
+ - [`xor`](#xor)
+ - [`int_to_bytes`](#int_to_bytes)
+ - [`bytes_to_int`](#bytes_to_int)
+ - [Crypto](#crypto)
+ - [`hash`](#hash)
+ - [`hash_tree_root`](#hash_tree_root)
+ - [`signing_root`](#signing_root)
+ - [`bls_verify`](#bls_verify)
+ - [`bls_verify_multiple`](#bls_verify_multiple)
+ - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys)
+ - [Predicates](#predicates)
+ - [`is_active_validator`](#is_active_validator)
+ - [`is_slashable_validator`](#is_slashable_validator)
+ - [`is_slashable_attestation_data`](#is_slashable_attestation_data)
+ - [`is_valid_merkle_branch`](#is_valid_merkle_branch)
+ - [Misc](#misc)
+ - [`shuffle_index`](#shuffle_index)
+ - [`compute_committee`](#compute_committee)
+ - [`validate_indexed_attestation`](#validate_indexed_attestation)
+ - [`slot_to_epoch`](#slot_to_epoch)
+ - [`epoch_start_slot`](#epoch_start_slot)
+ - [`compute_activation_exit_epoch`](#compute_activation_exit_epoch)
+ - [`bls_domain`](#bls_domain)
+ - [Beacon state accessors](#beacon-state-accessors)
+ - [`get_current_epoch`](#get_current_epoch)
+ - [`get_previous_epoch`](#get_previous_epoch)
+ - [`get_block_root`](#get_block_root)
+ - [`get_block_root_at_slot`](#get_block_root_at_slot)
+ - [`get_randao_mix`](#get_randao_mix)
+ - [`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_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_compact_committees_root`](#get_compact_committees_root)
+ - [`get_total_balance`](#get_total_balance)
+ - [`get_domain`](#get_domain)
+ - [`get_indexed_attestation`](#get_indexed_attestation)
+ - [`get_attesting_indices`](#get_attesting_indices)
+ - [Beacon state mutators](#beacon-state-mutators)
+ - [`increase_balance`](#increase_balance)
+ - [`decrease_balance`](#decrease_balance)
- [`initiate_validator_exit`](#initiate_validator_exit)
- [`slash_validator`](#slash_validator)
- [Genesis](#genesis)
@@ -124,29 +128,12 @@
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](#dfn-validator). In the initial deployment phases of Ethereum 2.0, the only mechanism to become a [validator](#dfn-validator) is to make a one-way ETH transaction to a deposit contract on Ethereum 1.0. Activation as a [validator](#dfn-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.
+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.
## Notation
-Code snippets appearing in `this style` are to be interpreted as Python code.
-
-## Terminology
-
-* **Validator**—a registered participant in the beacon chain. You can become one by sending ether into the Ethereum 1.0 deposit contract.
-* **Active validator**—an active participant in the Ethereum 2.0 consensus invited to, among other things, propose and attest to blocks and vote for crosslinks.
-* **Committee**—a (pseudo-) randomly sampled subset of [active validators](#dfn-active-validator). When a committee is referred to collectively, as in "this committee attests to X", this is assumed to mean "some subset of that committee that contains enough [validators](#dfn-validator) that the protocol recognizes it as representing the committee".
-* **Proposer**—the [validator](#dfn-validator) that creates a beacon chain block.
-* **Attester**—a [validator](#dfn-validator) that is part of a committee that needs to sign off on a beacon chain block while simultaneously creating a link (crosslink) to a recent shard block on a particular shard chain.
-* **Beacon chain**—the central proof-of-stake chain that is the base of the sharding system.
-* **Shard chain**—one of the chains on which user transactions take place and account data is stored.
-* **Block root**—a 32-byte Merkle root of a beacon chain block or shard chain block. Previously called "block hash".
-* **Crosslink**—a set of signatures from a committee attesting to a block in a shard chain that can be included into the beacon chain. Crosslinks are the main means by which the beacon chain "learns about" the updated state of shard chains.
-* **Slot**—a period during which one proposer has the ability to create a beacon chain block and some attesters have the ability to make attestations.
-* **Epoch**—an aligned span of slots during which all [validators](#dfn-validator) get exactly one chance to make an attestation.
-* **Finalized**, **justified**—see the [Casper FFG paper](https://arxiv.org/abs/1710.09437).
-* **Withdrawal period**—the number of slots between a [validator](#dfn-validator) exit and the [validator](#dfn-validator) balance being withdrawable.
-* **Genesis time**—the Unix time of the genesis beacon chain block at slot 0.
+Code snippets appearing in `this style` are to be interpreted as Python 3 code.
## Custom types
@@ -160,7 +147,7 @@ We define the following Python custom types for type hinting and readability:
| `ValidatorIndex` | `uint64` | a validator registry index |
| `Gwei` | `uint64` | an amount in Gwei |
| `Version` | `Bytes4` | a fork version number |
-| `Hash` | `Bytes32` | a hashed result |
+| `Hash` | `Bytes32` | a hash |
| `BLSPubkey` | `Bytes48` | a BLS12-381 public key |
| `BLSSignature` | `Bytes96` | a BLS12-381 signature |
@@ -171,7 +158,6 @@ The following values are (non-configurable) constants used throughout the specif
| Name | Value |
| - | - |
| `FAR_FUTURE_EPOCH` | `Epoch(2**64 - 1)` |
-| `ZERO_HASH` | `Hash(b'\x00' * 32)` |
| `BASE_REWARDS_PER_EPOCH` | `5` |
| `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) |
| `SECONDS_PER_DAY` | `86400` |
@@ -193,6 +179,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) |
| `JUSTIFICATION_BITS_LENGTH` | `4` |
+| `ENDIANNESS` | `'little'` |
* 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.)
@@ -249,7 +236,7 @@ The following values are (non-configurable) constants used throughout the specif
| `INACTIVITY_PENALTY_QUOTIENT` | `2**25` (= 33,554,432) |
| `MIN_SLASHING_PENALTY_QUOTIENT` | `2**5` (= 32) |
-* The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**12 epochs` (about 18 days) is the time it takes the inactivity penalty to reduce the balance of non-participating [validators](#dfn-validator) to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline [validators](#dfn-validator) after `n` epochs is about `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)`; so after `INVERSE_SQRT_E_DROP_TIME` epochs, it is roughly `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`.
+* The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**12 epochs` (about 18 days) is the time it takes the inactivity penalty to reduce the balance of non-participating validators to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline validators after `n` epochs is about `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)`; so after `INVERSE_SQRT_E_DROP_TIME` epochs, it is roughly `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`.
### Max operations per block
@@ -547,80 +534,82 @@ class BeaconState(Container):
*Note*: The definitions below are for specification purposes and are not necessarily optimal implementations.
-### `xor`
+### Math
+
+#### `int_to_bytes`
+
+#### `integer_squareroot`
+
+```python
+def integer_squareroot(n: uint64) -> int:
+ """
+ Return the largest integer ``x`` such that ``x**2 <= n``.
+ """
+ x = n
+ y = (x + 1) // 2
+ while y < x:
+ x = y
+ y = (x + n // x) // 2
+ return x
+```
+
+#### `xor`
```python
def xor(bytes1: Bytes32, bytes2: Bytes32) -> Bytes32:
+ """
+ Return the exclusive-or of two 32-byte strings.
+ """
return Bytes32(a ^ b for a, b in zip(bytes1, bytes2))
```
-### `hash`
-
-The `hash` function is SHA256.
-
-*Note*: We aim to migrate to a S[T/N]ARK-friendly hash function in a future Ethereum 2.0 deployment phase.
-
-### `hash_tree_root`
-
-`def hash_tree_root(object: SSZSerializable) -> Hash` is a function for hashing objects into a single root by utilizing a hash tree structure, as defined in the [SimpleSerialize spec](../simple-serialize.md#merkleization).
-
-### `signing_root`
-
-`def signing_root(object: Container) -> Hash` is a function for computing signing messages, as defined in the [SimpleSerialize spec](../simple-serialize.md#self-signed-containers).
-
-### `bls_domain`
-
```python
-def bls_domain(domain_type: int, fork_version: bytes=b'\x00\x00\x00\x00') -> int:
+def int_to_bytes(integer: uint64, length: uint64) -> bytes:
"""
- Return the bls domain given by the ``domain_type`` and optional 4 byte ``fork_version`` (defaults to zero).
+ Return the ``length``-byte serialization of ``integer``.
"""
- return bytes_to_int(int_to_bytes(domain_type, length=4) + fork_version)
+ return integer.to_bytes(length, ENDIANNESS)
```
-### `slot_to_epoch`
+#### `bytes_to_int`
```python
-def slot_to_epoch(slot: Slot) -> Epoch:
+def bytes_to_int(data: bytes) -> int:
"""
- Return the epoch number of the given ``slot``.
+ Return the integer deserialization of ``data``.
"""
- return Epoch(slot // SLOTS_PER_EPOCH)
+ return int.from_bytes(data, ENDIANNESS)
```
-### `get_previous_epoch`
+### Crypto
-```python
-def get_previous_epoch(state: BeaconState) -> Epoch:
- """`
- Return the previous epoch of the given ``state``.
- Return the current epoch if it's genesis epoch.
- """
- current_epoch = get_current_epoch(state)
- return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
-```
+#### `hash`
-### `get_current_epoch`
+`def hash(data: bytes) -> Hash` is SHA256.
-```python
-def get_current_epoch(state: BeaconState) -> Epoch:
- """
- Return the current epoch of the given ``state``.
- """
- return slot_to_epoch(state.slot)
-```
+#### `hash_tree_root`
-### `get_epoch_start_slot`
+`def hash_tree_root(object: SSZSerializable) -> Hash` is a function for hashing objects into a single root by utilizing a hash tree structure, as defined in the [SSZ spec](../simple-serialize.md#merkleization).
-```python
-def get_epoch_start_slot(epoch: Epoch) -> Slot:
- """
- Return the starting slot of the given ``epoch``.
- """
- return Slot(epoch * SLOTS_PER_EPOCH)
-```
+#### `signing_root`
-### `is_active_validator`
+`def signing_root(object: Container) -> Hash` is a function for computing signing messages, as defined in the [SSZ spec](../simple-serialize.md#self-signed-containers).
+
+#### `bls_verify`
+
+`bls_verify` is a function for verifying a BLS signature, as defined in the [BLS Signature spec](../bls_signature.md#bls_verify).
+
+#### `bls_verify_multiple`
+
+`bls_verify_multiple` is a function for verifying a BLS signature constructed from multiple messages, as defined in the [BLS Signature spec](../bls_signature.md#bls_verify_multiple).
+
+#### `bls_aggregate_pubkeys`
+
+`bls_aggregate_pubkeys` is a function for aggregating multiple BLS public keys into a single aggregate key, as defined in the [BLS Signature spec](../bls_signature.md#bls_aggregate_pubkeys).
+
+### Predicates
+
+#### `is_active_validator`
```python
def is_active_validator(validator: Validator, epoch: Epoch) -> bool:
@@ -630,7 +619,7 @@ def is_active_validator(validator: Validator, epoch: Epoch) -> bool:
return validator.activation_epoch <= epoch < validator.exit_epoch
```
-### `is_slashable_validator`
+#### `is_slashable_validator`
```python
def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool:
@@ -640,204 +629,43 @@ def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool:
return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch)
```
-### `get_active_validator_indices`
+#### `is_slashable_attestation_data`
```python
-def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
+def is_slashable_attestation_data(data_1: AttestationData, data_2: AttestationData) -> bool:
"""
- Get active validator indices at ``epoch``.
+ Check if ``data_1`` and ``data_2`` are slashable according to Casper FFG rules.
"""
- return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
-```
-
-### `increase_balance`
-
-```python
-def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
- """
- Increase validator balance by ``delta``.
- """
- state.balances[index] += delta
-```
-
-### `decrease_balance`
-
-```python
-def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
- """
- Decrease validator balance by ``delta`` with underflow protection.
- """
- state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta
-```
-
-### `get_epoch_committee_count`
-
-```python
-def get_epoch_committee_count(state: BeaconState, epoch: Epoch) -> int:
- """
- Return the number of committees at ``epoch``.
- """
- active_validator_indices = get_active_validator_indices(state, epoch)
- return max(
- 1,
- min(
- SHARD_COUNT // SLOTS_PER_EPOCH,
- len(active_validator_indices) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
- )
- ) * SLOTS_PER_EPOCH
-```
-
-### `get_shard_delta`
-
-```python
-def get_shard_delta(state: BeaconState, epoch: Epoch) -> int:
- """
- Return the number of shards to increment ``state.start_shard`` during ``epoch``.
- """
- return min(get_epoch_committee_count(state, epoch), SHARD_COUNT - SHARD_COUNT // SLOTS_PER_EPOCH)
-```
-
-### `get_epoch_start_shard`
-
-```python
-def get_epoch_start_shard(state: BeaconState, epoch: Epoch) -> Shard:
- """
- Return the start shard of the 0th committee in an 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_attestation_data_slot`
-
-```python
-def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot:
- committee_count = get_epoch_committee_count(state, data.target.epoch)
- offset = (data.crosslink.shard + SHARD_COUNT - get_epoch_start_shard(state, data.target.epoch)) % SHARD_COUNT
- return Slot(get_epoch_start_slot(data.target.epoch) + offset // (committee_count // SLOTS_PER_EPOCH))
-```
-
-### `get_block_root_at_slot`
-
-```python
-def get_block_root_at_slot(state: BeaconState,
- slot: Slot) -> Hash:
- """
- Return the block root at a recent ``slot``.
- """
- assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
- return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
-```
-
-### `get_block_root`
-
-```python
-def get_block_root(state: BeaconState,
- epoch: Epoch) -> Hash:
- """
- Return the block root at a recent ``epoch``.
- """
- return get_block_root_at_slot(state, get_epoch_start_slot(epoch))
-```
-
-### `get_randao_mix`
-
-```python
-def get_randao_mix(state: BeaconState,
- epoch: Epoch) -> Hash:
- """
- Return the randao mix at a recent ``epoch``.
- ``epoch`` expected to be between (current_epoch - EPOCHS_PER_HISTORICAL_VECTOR, current_epoch].
- """
- return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
-```
-
-### `get_compact_committees_root`
-
-```python
-def get_compact_committees_root(state: BeaconState, epoch: Epoch) -> Hash:
- """
- Return the compact committee root for the current epoch.
- """
- committees = [CompactCommittee() for _ in range(SHARD_COUNT)]
- start_shard = get_epoch_start_shard(state, epoch)
- for committee_number in range(get_epoch_committee_count(state, epoch)):
- shard = Shard((start_shard + committee_number) % SHARD_COUNT)
- for index in get_crosslink_committee(state, epoch, shard):
- validator = state.validators[index]
- committees[shard].pubkeys.append(validator.pubkey)
- compact_balance = validator.effective_balance // EFFECTIVE_BALANCE_INCREMENT
- # `index` (top 6 bytes) + `slashed` (16th bit) + `compact_balance` (bottom 15 bits)
- compact_validator = uint64((index << 16) + (validator.slashed << 15) + compact_balance)
- committees[shard].compact_validators.append(compact_validator)
- return hash_tree_root(Vector[CompactCommittee, SHARD_COUNT](committees))
-```
-
-### `generate_seed`
-
-```python
-def generate_seed(state: BeaconState,
- epoch: Epoch) -> Hash:
- """
- Generate a seed for the given ``epoch``.
- """
- return hash(
- get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD)) + # Avoid underflow
- hash_tree_root(List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, epoch))) +
- int_to_bytes(epoch, length=32)
+ return (
+ # Double vote
+ (data_1 != data_2 and data_1.target.epoch == data_2.target.epoch) or
+ # Surround vote
+ (data_1.source.epoch < data_2.source.epoch and data_2.target.epoch < data_1.target.epoch)
)
```
-### `get_beacon_proposer_index`
+#### `is_valid_merkle_branch`
```python
-def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
+def is_valid_merkle_branch(leaf: Hash, branch: Sequence[Hash], depth: uint64, index: uint64, root: Hash) -> bool:
"""
- Return the current beacon proposer index.
- """
- epoch = get_current_epoch(state)
- committees_per_slot = get_epoch_committee_count(state, epoch) // SLOTS_PER_EPOCH
- offset = committees_per_slot * (state.slot % SLOTS_PER_EPOCH)
- shard = Shard((get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT)
- first_committee = get_crosslink_committee(state, epoch, shard)
- MAX_RANDOM_BYTE = 2**8 - 1
- seed = generate_seed(state, epoch)
- i = 0
- while True:
- candidate_index = first_committee[(epoch + i) % len(first_committee)]
- random_byte = hash(seed + int_to_bytes(i // 32, length=8))[i % 32]
- effective_balance = state.validators[candidate_index].effective_balance
- if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
- return ValidatorIndex(candidate_index)
- i += 1
-```
-
-### `verify_merkle_branch`
-
-```python
-def verify_merkle_branch(leaf: Hash, proof: Sequence[Hash], depth: int, index: int, root: Hash) -> bool:
- """
- Verify that the given ``leaf`` is on the merkle branch ``proof``
- starting with the given ``root``.
+ Check if ``leaf`` at ``index`` verifies against the Merkle ``root`` and ``branch``.
"""
value = leaf
for i in range(depth):
if index // (2**i) % 2:
- value = hash(proof[i] + value)
+ value = hash(branch[i] + value)
else:
- value = hash(value + proof[i])
+ value = hash(value + branch[i])
return value == root
```
-### `get_shuffled_index`
+### Misc
+
+#### `shuffle_index`
```python
-def get_shuffled_index(index: ValidatorIndex, index_count: int, seed: Hash) -> ValidatorIndex:
+def shuffle_index(index: ValidatorIndex, index_count: uint64, seed: Hash) -> ValidatorIndex:
"""
Return the shuffled validator index corresponding to ``seed`` (and ``index_count``).
"""
@@ -850,10 +678,7 @@ def get_shuffled_index(index: ValidatorIndex, index_count: int, seed: Hash) -> V
pivot = bytes_to_int(hash(seed + int_to_bytes(current_round, length=1))[0:8]) % index_count
flip = ValidatorIndex((pivot + index_count - index) % index_count)
position = max(index, flip)
- source = hash(
- seed + int_to_bytes(current_round, length=1) +
- int_to_bytes(position // 256, length=4)
- )
+ source = hash(seed + int_to_bytes(current_round, length=1) + int_to_bytes(position // 256, length=4))
byte = source[(position % 256) // 8]
bit = (byte >> (position % 8)) % 2
index = flip if bit else index
@@ -861,100 +686,22 @@ def get_shuffled_index(index: ValidatorIndex, index_count: int, seed: Hash) -> V
return ValidatorIndex(index)
```
-### `compute_committee`
+#### `compute_committee`
```python
def compute_committee(indices: Sequence[ValidatorIndex],
- seed: Hash, index: int, count: int) -> Sequence[ValidatorIndex]:
+ seed: Hash,
+ index: uint64,
+ count: uint64) -> Sequence[ValidatorIndex]:
+ """
+ Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``.
+ """
start = (len(indices) * index) // count
end = (len(indices) * (index + 1)) // count
- return [indices[get_shuffled_index(ValidatorIndex(i), len(indices), seed)] for i in range(start, end)]
+ return [indices[shuffle_index(ValidatorIndex(i), len(indices), seed)] for i in range(start, end)]
```
-### `get_crosslink_committee`
-
-```python
-def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> Sequence[ValidatorIndex]:
- return compute_committee(
- indices=get_active_validator_indices(state, epoch),
- seed=generate_seed(state, epoch),
- index=(shard + SHARD_COUNT - get_epoch_start_shard(state, epoch)) % SHARD_COUNT,
- count=get_epoch_committee_count(state, epoch),
- )
-```
-
-### `get_attesting_indices`
-
-```python
-def get_attesting_indices(state: BeaconState,
- data: AttestationData,
- bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]) -> Set[ValidatorIndex]:
- """
- Return the set of attesting indices corresponding to ``data`` and ``bitfield``.
- """
- committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
- return set(index for i, index in enumerate(committee) if bits[i])
-```
-
-### `int_to_bytes`
-
-```python
-def int_to_bytes(integer: int, length: int) -> bytes:
- return integer.to_bytes(length, 'little')
-```
-
-### `bytes_to_int`
-
-```python
-def bytes_to_int(data: bytes) -> int:
- return int.from_bytes(data, 'little')
-```
-
-### `get_total_balance`
-
-```python
-def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
- """
- Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.)
- """
- return Gwei(max(sum([state.validators[index].effective_balance for index in indices]), 1))
-```
-
-### `get_domain`
-
-```python
-def get_domain(state: BeaconState,
- domain_type: int,
- message_epoch: Epoch=None) -> int:
- """
- Return the signature domain (fork version concatenated with domain type) of a message.
- """
- epoch = get_current_epoch(state) if message_epoch is None else message_epoch
- fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
- return bls_domain(domain_type, fork_version)
-```
-
-### `convert_to_indexed`
-
-```python
-def convert_to_indexed(state: BeaconState, attestation: Attestation) -> IndexedAttestation:
- """
- Convert ``attestation`` to (almost) indexed-verifiable form.
- """
- attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
- custody_bit_1_indices = get_attesting_indices(state, attestation.data, attestation.custody_bits)
- assert custody_bit_1_indices.issubset(attesting_indices)
- custody_bit_0_indices = attesting_indices.difference(custody_bit_1_indices)
-
- return IndexedAttestation(
- custody_bit_0_indices=sorted(custody_bit_0_indices),
- custody_bit_1_indices=sorted(custody_bit_1_indices),
- data=attestation.data,
- signature=attestation.signature,
- )
-```
-
-### `validate_indexed_attestation`
+#### `validate_indexed_attestation`
```python
def validate_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> None:
@@ -987,82 +734,339 @@ def validate_indexed_attestation(state: BeaconState, indexed_attestation: Indexe
)
```
-### `is_slashable_attestation_data`
+#### `slot_to_epoch`
```python
-def is_slashable_attestation_data(data_1: AttestationData, data_2: AttestationData) -> bool:
+def slot_to_epoch(slot: Slot) -> Epoch:
"""
- Check if ``data_1`` and ``data_2`` are slashable according to Casper FFG rules.
+ Return the epoch number of ``slot``.
"""
- return (
- # Double vote
- (data_1 != data_2 and data_1.target.epoch == data_2.target.epoch) or
- # Surround vote
- (data_1.source.epoch < data_2.source.epoch and data_2.target.epoch < data_1.target.epoch)
- )
+ return Epoch(slot // SLOTS_PER_EPOCH)
```
-### `integer_squareroot`
+#### `epoch_start_slot`
```python
-def integer_squareroot(n: int) -> int:
+def epoch_start_slot(epoch: Epoch) -> Slot:
"""
- The largest integer ``x`` such that ``x**2`` is less than or equal to ``n``.
+ Return the start slot of ``epoch``.
"""
- assert n >= 0
- x = n
- y = (x + 1) // 2
- while y < x:
- x = y
- y = (x + n // x) // 2
- return x
+ return Slot(epoch * SLOTS_PER_EPOCH)
```
-### `get_delayed_activation_exit_epoch`
+#### `compute_activation_exit_epoch`
```python
-def get_delayed_activation_exit_epoch(epoch: Epoch) -> Epoch:
+def compute_activation_exit_epoch(epoch: Epoch) -> Epoch:
"""
- Return the epoch at which an activation or exit triggered in ``epoch`` takes effect.
+ Return the epoch during which validator activations and exits initiated in ``epoch`` take effect.
"""
return Epoch(epoch + 1 + ACTIVATION_EXIT_DELAY)
```
-### `get_churn_limit`
+#### `bls_domain`
```python
-def get_churn_limit(state: BeaconState) -> int:
+def bls_domain(domain_type: uint64, fork_version: bytes=b'\x00' * 4) -> int:
"""
- Return the churn limit based on the active validator count.
+ Return the BLS domain for the ``domain_type`` and ``fork_version``.
"""
- return max(
- MIN_PER_EPOCH_CHURN_LIMIT,
- len(get_active_validator_indices(state, get_current_epoch(state))) // CHURN_LIMIT_QUOTIENT
+ return bytes_to_int(int_to_bytes(domain_type, length=4) + fork_version)
+```
+
+### Beacon state accessors
+
+#### `get_current_epoch`
+
+```python
+def get_current_epoch(state: BeaconState) -> Epoch:
+ """
+ Return the current epoch.
+ """
+ return slot_to_epoch(state.slot)
+```
+
+#### `get_previous_epoch`
+
+```python
+def get_previous_epoch(state: BeaconState) -> Epoch:
+ """`
+ Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
+ """
+ current_epoch = get_current_epoch(state)
+ return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
+```
+
+#### `get_block_root`
+
+```python
+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, epoch_start_slot(epoch))
+```
+
+#### `get_block_root_at_slot`
+
+```python
+def get_block_root_at_slot(state: BeaconState, slot: Slot) -> Hash:
+ """
+ Return the block root at a recent ``slot``.
+ """
+ assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
+ return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
+```
+
+#### `get_randao_mix`
+
+```python
+def get_randao_mix(state: BeaconState, epoch: Epoch) -> Hash:
+ """
+ Return the randao mix at a recent ``epoch``.
+ """
+ return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
+```
+
+#### `get_active_validator_indices`
+
+```python
+def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
+ """
+ Return the sequence of active validator indices at ``epoch``.
+ """
+ return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
+```
+
+#### `get_validator_churn_limit`
+
+```python
+def get_validator_churn_limit(state: BeaconState) -> int:
+ """
+ Return the validator churn limit for the current epoch.
+ """
+ active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
+ return max(MIN_PER_EPOCH_CHURN_LIMIT, len(active_validator_indices) // CHURN_LIMIT_QUOTIENT)
+```
+
+#### `get_seed`
+
+```python
+def get_seed(state: BeaconState, epoch: Epoch) -> Hash:
+ """
+ Return the seed at ``epoch``.
+ """
+ mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD)) # Avoid underflow
+ active_indices = get_active_validator_indices(state, epoch)
+ active_indices_root = hash_tree_root(List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](active_indices))
+ return hash(mix + active_indices_root + int_to_bytes(epoch, length=32))
+```
+
+#### `get_committee_count`
+
+```python
+def get_committee_count(state: BeaconState, epoch: Epoch) -> int:
+ """
+ Return the number of committees at ``epoch``.
+ """
+ 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
+```
+
+#### `get_crosslink_committee`
+
+```python
+def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> Sequence[ValidatorIndex]:
+ """
+ Return the crosslink committee at ``epoch`` for ``shard``.
+ """
+ return compute_committee(
+ indices=get_active_validator_indices(state, epoch),
+ seed=get_seed(state, epoch),
+ index=(shard + SHARD_COUNT - get_start_shard(state, epoch)) % SHARD_COUNT,
+ count=get_committee_count(state, epoch),
)
```
-### `bls_verify`
+#### `get_start_shard`
-`bls_verify` is a function for verifying a BLS signature, as defined in the [BLS Signature spec](../bls_signature.md#bls_verify).
+```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
+```
-### `bls_verify_multiple`
+#### `get_shard_delta`
-`bls_verify_multiple` is a function for verifying a BLS signature constructed from multiple messages, as defined in the [BLS Signature spec](../bls_signature.md#bls_verify_multiple).
+```python
+def get_shard_delta(state: BeaconState, epoch: Epoch) -> int:
+ """
+ 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)
+```
-### `bls_aggregate_pubkeys`
+#### `get_beacon_proposer_index`
-`bls_aggregate_pubkeys` is a function for aggregating multiple BLS public keys into a single aggregate key, as defined in the [BLS Signature spec](../bls_signature.md#bls_aggregate_pubkeys).
+```python
+def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
+ """
+ Return the beacon proposer index at the current slot.
+ """
+ epoch = get_current_epoch(state)
+ committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH
+ offset = committees_per_slot * (state.slot % SLOTS_PER_EPOCH)
+ shard = Shard((get_start_shard(state, epoch) + offset) % SHARD_COUNT)
+ first_committee = get_crosslink_committee(state, epoch, shard)
+ MAX_RANDOM_BYTE = 2**8 - 1
+ seed = get_seed(state, epoch)
+ i = 0
+ while True:
+ candidate_index = first_committee[(epoch + i) % len(first_committee)]
+ random_byte = hash(seed + int_to_bytes(i // 32, length=8))[i % 32]
+ effective_balance = state.validators[candidate_index].effective_balance
+ if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
+ return ValidatorIndex(candidate_index)
+ i += 1
+```
-### Routines for updating validator status
+#### `get_attestation_data_slot`
-*Note*: All functions in this section mutate `state`.
+```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(epoch_start_slot(data.target.epoch) + offset // (committee_count // SLOTS_PER_EPOCH))
+```
+
+#### `get_compact_committees_root`
+
+```python
+def get_compact_committees_root(state: BeaconState, epoch: Epoch) -> Hash:
+ """
+ Return the compact committee root at ``epoch``.
+ """
+ committees = [CompactCommittee() for _ in range(SHARD_COUNT)]
+ start_shard = get_start_shard(state, epoch)
+ for committee_number in range(get_committee_count(state, epoch)):
+ shard = Shard((start_shard + committee_number) % SHARD_COUNT)
+ for index in get_crosslink_committee(state, epoch, shard):
+ validator = state.validators[index]
+ committees[shard].pubkeys.append(validator.pubkey)
+ compact_balance = validator.effective_balance // EFFECTIVE_BALANCE_INCREMENT
+ # `index` (top 6 bytes) + `slashed` (16th bit) + `compact_balance` (bottom 15 bits)
+ compact_validator = uint64((index << 16) + (validator.slashed << 15) + compact_balance)
+ committees[shard].compact_validators.append(compact_validator)
+ return hash_tree_root(Vector[CompactCommittee, SHARD_COUNT](committees))
+```
+
+#### `get_total_balance`
+
+```python
+def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
+ """
+ Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.)
+ """
+ return Gwei(max(sum([state.validators[index].effective_balance for index in indices]), 1))
+```
+
+#### `get_total_active_balance`
+
+```python
+def get_total_active_balance(state: BeaconState) -> Gwei:
+ """
+ Return the combined effective balance of the active validators.
+ """
+ return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
+```
+
+#### `get_domain`
+
+```python
+def get_domain(state: BeaconState, domain_type: uint64, message_epoch: Epoch=None) -> int:
+ """
+ Return the signature domain (fork version concatenated with domain type) of a message.
+ """
+ epoch = get_current_epoch(state) if message_epoch is None else message_epoch
+ fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
+ return bls_domain(domain_type, fork_version)
+```
+
+#### `get_indexed_attestation`
+
+```python
+def get_indexed_attestation(state: BeaconState, attestation: Attestation) -> IndexedAttestation:
+ """
+ Return the indexed attestation corresponding to ``attestation``.
+ """
+ attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
+ custody_bit_1_indices = get_attesting_indices(state, attestation.data, attestation.custody_bits)
+ assert custody_bit_1_indices.issubset(attesting_indices)
+ custody_bit_0_indices = attesting_indices.difference(custody_bit_1_indices)
+
+ return IndexedAttestation(
+ custody_bit_0_indices=sorted(custody_bit_0_indices),
+ custody_bit_1_indices=sorted(custody_bit_1_indices),
+ data=attestation.data,
+ signature=attestation.signature,
+ )
+```
+
+#### `get_attesting_indices`
+
+```python
+def get_attesting_indices(state: BeaconState,
+ data: AttestationData,
+ bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]) -> Set[ValidatorIndex]:
+ """
+ Return the set of attesting indices corresponding to ``data`` and ``bits``.
+ """
+ committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
+ return set(index for i, index in enumerate(committee) if bits[i])
+```
+
+### Beacon state mutators
+
+#### `increase_balance`
+
+```python
+def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
+ """
+ Increase the validator balance at index ``index`` by ``delta``.
+ """
+ state.balances[index] += delta
+```
+
+#### `decrease_balance`
+
+```python
+def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
+ """
+ Decrease the validator balance at index ``index`` by ``delta``, with underflow protection.
+ """
+ state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta
+```
#### `initiate_validator_exit`
```python
def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
"""
- Initiate the exit of the validator of the given ``index``.
+ Initiate the exit of the validator with index ``index``.
"""
# Return if validator already initiated exit
validator = state.validators[index]
@@ -1071,9 +1075,9 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
# Compute exit queue epoch
exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH]
- exit_queue_epoch = max(exit_epochs + [get_delayed_activation_exit_epoch(get_current_epoch(state))])
+ exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))])
exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch])
- if exit_queue_churn >= get_churn_limit(state):
+ if exit_queue_churn >= get_validator_churn_limit(state):
exit_queue_epoch += Epoch(1)
# Set validator exit epoch and withdrawable epoch
@@ -1110,22 +1114,12 @@ def slash_validator(state: BeaconState,
## Genesis
-### Genesis state
-
-Before the Ethereum 2.0 genesis has been triggered, and for every Ethereum 1.0 block, call `initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)` where:
+Before the Ethereum 2.0 genesis has been triggered, and for every Ethereum 1.0 block, let `candidate_state = initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)` where:
* `eth1_block_hash` is the hash of the Ethereum 1.0 block
* `eth1_timestamp` is the Unix timestamp corresponding to `eth1_block_hash`
* `deposits` is the sequence of all deposits, ordered chronologically, up to the block with hash `eth1_block_hash`
-The genesis state `genesis_state` is the return value of calling `initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)` only if `is_valid_genesis_state(genesis_state) is True`.
-
-Implementations can choose to support different (more optimized) variations of the below initialization approach:
- - Build the `genesis_state` from a stream of deposits by incrementally updating the `state.eth1_data.deposit_root`.
- - Compute deposit proofs for the final `state.eth1_data.deposit_root`, and process as a pre-determined collection.
-
-*Note*: The two constants `MIN_GENESIS_TIME` and `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` have yet to be agreed upon by the community, and can be updated as necessary.
-
```python
def initialize_beacon_state_from_eth1(eth1_block_hash: Hash,
eth1_timestamp: uint64,
@@ -1139,9 +1133,8 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash,
# Process deposits
leaves = list(map(lambda deposit: deposit.data, deposits))
for index, deposit in enumerate(deposits):
- state.eth1_data.deposit_root = hash_tree_root(
- List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
- )
+ deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
+ state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
process_deposit(state, deposit)
# Process activations
@@ -1151,22 +1144,27 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash,
validator.activation_epoch = GENESIS_EPOCH
# Populate compact_committees_roots
- genesis_committee_root = get_compact_committees_root(state, GENESIS_EPOCH)
+ committee_root = get_compact_committees_root(state, GENESIS_EPOCH)
for index in range(EPOCHS_PER_HISTORICAL_VECTOR):
- state.compact_committees_roots[index] = genesis_committee_root
+ state.compact_committees_roots[index] = committee_root
return state
```
+### Genesis state
+
+Let `genesis_state = candidate_state` whenever `is_valid_genesis_state(candidate_state) is True` for the first time.
+
```python
def is_valid_genesis_state(state: BeaconState) -> bool:
if state.genesis_time < MIN_GENESIS_TIME:
return False
- elif len(get_active_validator_indices(state, GENESIS_EPOCH)) < MIN_GENESIS_ACTIVE_VALIDATOR_COUNT:
+ if len(get_active_validator_indices(state, GENESIS_EPOCH)) < MIN_GENESIS_ACTIVE_VALIDATOR_COUNT:
return False
- else:
- return True
+ return True
```
+*Note*: The `is_valid_genesis_state` function (including `MIN_GENESIS_TIME` and `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT`) is a placeholder for testing. It has yet to be finalized by the community, and can be updated as necessary.
+
### Genesis block
Let `genesis_block = BeaconBlock(state_root=hash_tree_root(genesis_state))`.
@@ -1193,7 +1191,7 @@ def process_slots(state: BeaconState, slot: Slot) -> None:
assert state.slot <= slot
while state.slot < slot:
process_slot(state)
- # Process epoch on the first slot of the next epoch
+ # Process epoch on the start slot of the next epoch
if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
process_epoch(state)
state.slot += Slot(1)
@@ -1204,11 +1202,9 @@ def process_slot(state: BeaconState) -> None:
# Cache state root
previous_state_root = hash_tree_root(state)
state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root
-
# Cache latest block header state root
- if state.latest_block_header.state_root == ZERO_HASH:
+ if state.latest_block_header.state_root == Hash():
state.latest_block_header.state_root = previous_state_root
-
# Cache block root
previous_block_root = signing_root(state.latest_block_header)
state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
@@ -1233,11 +1229,6 @@ def process_epoch(state: BeaconState) -> None:
#### Helper functions
-```python
-def get_total_active_balance(state: BeaconState) -> Gwei:
- return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
-```
-
```python
def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
assert epoch in (get_previous_epoch(state), get_current_epoch(state))
@@ -1340,8 +1331,8 @@ def process_justification_and_finalization(state: BeaconState) -> None:
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_epoch_committee_count(state, epoch)):
- shard = Shard((get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT)
+ 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):
@@ -1413,8 +1404,8 @@ def get_crosslink_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[G
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_epoch_committee_count(state, epoch)):
- shard = Shard((get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT)
+ 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)
@@ -1459,13 +1450,13 @@ def process_registry_updates(state: BeaconState) -> None:
activation_queue = sorted([
index for index, validator in enumerate(state.validators) if
validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH and
- validator.activation_epoch >= get_delayed_activation_exit_epoch(state.finalized_checkpoint.epoch)
+ validator.activation_epoch >= compute_activation_exit_epoch(state.finalized_checkpoint.epoch)
], key=lambda index: state.validators[index].activation_eligibility_epoch)
# Dequeued validators for activation up to churn limit (without resetting activation epoch)
- for index in activation_queue[:get_churn_limit(state)]:
+ for index in activation_queue[:get_validator_churn_limit(state)]:
validator = state.validators[index]
if validator.activation_epoch == FAR_FUTURE_EPOCH:
- validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
+ validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state))
```
#### Slashings
@@ -1506,10 +1497,7 @@ def process_final_updates(state: BeaconState) -> None:
state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch)
# Set historical root accumulator
if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
- historical_batch = HistoricalBatch(
- block_roots=state.block_roots,
- state_roots=state.state_roots,
- )
+ historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
state.historical_roots.append(hash_tree_root(historical_batch))
# Rotate current/previous epoch attestations
state.previous_epoch_attestations = state.current_epoch_attestations
@@ -1538,7 +1526,7 @@ def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
state.latest_block_header = BeaconBlockHeader(
slot=block.slot,
parent_root=block.parent_root,
- state_root=ZERO_HASH, # Overwritten in next `process_slot` call
+ state_root=Hash(), # Overwritten in the next `process_slot` call
body_root=hash_tree_root(block.body),
)
# Verify proposer is not slashed
@@ -1579,15 +1567,14 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
# Verify that there are no duplicate transfers
assert len(body.transfers) == len(set(body.transfers))
- all_operations = (
+ for operations, function in (
(body.proposer_slashings, process_proposer_slashing),
(body.attester_slashings, process_attester_slashing),
(body.attestations, process_attestation),
(body.deposits, process_deposit),
(body.voluntary_exits, process_voluntary_exit),
(body.transfers, process_transfer),
- ) # type: Sequence[Tuple[List, Callable]]
- for operations, function in all_operations:
+ ):
for operation in operations:
function(state, operation)
```
@@ -1596,9 +1583,6 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
```python
def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSlashing) -> None:
- """
- Process ``ProposerSlashing`` operation.
- """
proposer = state.validators[proposer_slashing.proposer_index]
# Verify that the epoch is the same
assert slot_to_epoch(proposer_slashing.header_1.slot) == slot_to_epoch(proposer_slashing.header_2.slot)
@@ -1618,9 +1602,6 @@ def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSla
```python
def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSlashing) -> None:
- """
- Process ``AttesterSlashing`` operation.
- """
attestation_1 = attester_slashing.attestation_1
attestation_2 = attester_slashing.attestation_2
assert is_slashable_attestation_data(attestation_1.data, attestation_2.data)
@@ -1641,9 +1622,6 @@ def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSla
```python
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
- """
- Process ``Attestation`` operation.
- """
data = attestation.data
assert data.crosslink.shard < SHARD_COUNT
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
@@ -1671,23 +1649,20 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
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 == ZERO_HASH # [to be removed in phase 1]
+ assert data.crosslink.data_root == Hash() # [to be removed in phase 1]
# Check signature
- validate_indexed_attestation(state, convert_to_indexed(state, attestation))
+ validate_indexed_attestation(state, get_indexed_attestation(state, attestation))
```
##### Deposits
```python
def process_deposit(state: BeaconState, deposit: Deposit) -> None:
- """
- Process an Eth1 deposit, registering a validator or increasing its balance.
- """
# Verify the Merkle branch
- assert verify_merkle_branch(
+ assert is_valid_merkle_branch(
leaf=hash_tree_root(deposit.data),
- proof=deposit.proof,
+ branch=deposit.proof,
depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1, # Add 1 for the `List` length mix-in
index=state.eth1_deposit_index,
root=state.eth1_data.deposit_root,
@@ -1700,13 +1675,10 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
amount = deposit.data.amount
validator_pubkeys = [v.pubkey for v in state.validators]
if pubkey not in validator_pubkeys:
- # Verify the deposit signature (proof of possession).
- # Invalid signatures are allowed by the deposit contract,
- # and hence included on-chain, but must not be processed.
+ # Verify the deposit signature (proof of possession) for new validators.
+ # Note: The deposit contract does not check signatures.
# Note: Deposits are valid across forks, hence the deposit domain is retrieved directly from `bls_domain`
- if not bls_verify(
- pubkey, signing_root(deposit.data), deposit.data.signature, bls_domain(DOMAIN_DEPOSIT)
- ):
+ if not bls_verify(pubkey, signing_root(deposit.data), deposit.data.signature, bls_domain(DOMAIN_DEPOSIT)):
return
# Add validator and balance entries
@@ -1730,9 +1702,6 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
```python
def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
- """
- Process ``VoluntaryExit`` operation.
- """
validator = state.validators[exit.validator_index]
# Verify the validator is active
assert is_active_validator(validator, get_current_epoch(state))
@@ -1753,21 +1722,18 @@ def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
```python
def process_transfer(state: BeaconState, transfer: Transfer) -> None:
- """
- Process ``Transfer`` operation.
- """
# Verify the balance the covers amount and fee (with overflow protection)
assert state.balances[transfer.sender] >= max(transfer.amount + transfer.fee, transfer.amount, transfer.fee)
# A transfer is valid in only one slot
assert state.slot == transfer.slot
- # Sender must satisfy at least one of the following conditions in the parenthesis:
+ # Sender must satisfy at least one of the following:
assert (
- # * Has not been activated
+ # 1) Never have been eligible for activation
state.validators[transfer.sender].activation_eligibility_epoch == FAR_FUTURE_EPOCH or
- # * Is withdrawable
+ # 2) Be withdrawable
get_current_epoch(state) >= state.validators[transfer.sender].withdrawable_epoch or
- # * Balance after transfer is more than the effective balance threshold
- transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <= state.balances[transfer.sender]
+ # 3) Have a balance of at least MAX_EFFECTIVE_BALANCE after the transfer
+ state.balances[transfer.sender] >= transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE
)
# Verify that the pubkey is valid
assert (
diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md
index c54824f3b..a45d79fbe 100644
--- a/specs/core/0_fork-choice.md
+++ b/specs/core/0_fork-choice.md
@@ -69,7 +69,7 @@ class LatestMessage(object):
```python
@dataclass
class Store(object):
- time: int
+ time: uint64
justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
blocks: Dict[Hash, BeaconBlock] = field(default_factory=dict)
@@ -124,7 +124,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 = get_epoch_start_slot(store.justified_checkpoint.epoch)
+ justified_slot = epoch_start_slot(store.justified_checkpoint.epoch)
while True:
children = [
root for root in store.blocks.keys()
@@ -141,7 +141,7 @@ def get_head(store: Store) -> Hash:
#### `on_tick`
```python
-def on_tick(store: Store, time: int) -> None:
+def on_tick(store: Store, time: uint64) -> None:
store.time = time
```
@@ -162,7 +162,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 > get_epoch_start_slot(store.finalized_checkpoint.epoch)
+ assert block.slot > epoch_start_slot(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
@@ -190,11 +190,11 @@ def on_attestation(store: Store, attestation: Attestation) -> None:
# Attestations cannot be from future epochs. If they are, delay consideration until the epoch arrivesr
base_state = store.block_states[target.root].copy()
- assert store.time >= base_state.genesis_time + get_epoch_start_slot(target.epoch) * SECONDS_PER_SLOT
+ assert store.time >= base_state.genesis_time + epoch_start_slot(target.epoch) * SECONDS_PER_SLOT
# Store target checkpoint state if not yet seen
if target not in store.checkpoint_states:
- process_slots(base_state, get_epoch_start_slot(target.epoch))
+ process_slots(base_state, epoch_start_slot(target.epoch))
store.checkpoint_states[target] = base_state
target_state = store.checkpoint_states[target]
@@ -204,7 +204,7 @@ def on_attestation(store: Store, attestation: Attestation) -> None:
assert store.time >= (attestation_slot + 1) * SECONDS_PER_SLOT
# Get state at the `target` to validate attestation and calculate the committees
- indexed_attestation = convert_to_indexed(target_state, attestation)
+ indexed_attestation = get_indexed_attestation(target_state, attestation)
validate_indexed_attestation(target_state, indexed_attestation)
# Update latest messages
diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md
index 24076fef6..54a1ca34b 100644
--- a/specs/core/1_custody-game.md
+++ b/specs/core/1_custody-game.md
@@ -259,7 +259,7 @@ class BeaconBlockBody(Container):
### `ceillog2`
```python
-def ceillog2(x: int) -> int:
+def ceillog2(x: uint64) -> int:
return x.bit_length()
```
@@ -275,7 +275,7 @@ def get_custody_chunk_count(crosslink: Crosslink) -> int:
### `get_bit`
```python
-def get_bit(serialization: bytes, i: int) -> int:
+def get_bit(serialization: bytes, i: uint64) -> int:
"""
Extract the bit in ``serialization`` at position ``i``.
"""
@@ -304,7 +304,7 @@ def get_chunk_bits_root(chunk_bits: bytes) -> Bytes32:
### `get_randao_epoch_for_custody_period`
```python
-def get_randao_epoch_for_custody_period(period: int, validator_index: ValidatorIndex) -> Epoch:
+def get_randao_epoch_for_custody_period(period: uint64, validator_index: ValidatorIndex) -> Epoch:
next_period_start = (period + 1) * EPOCHS_PER_CUSTODY_PERIOD - validator_index % EPOCHS_PER_CUSTODY_PERIOD
return Epoch(next_period_start + CUSTODY_PERIOD_TO_RANDAO_PADDING)
```
@@ -473,7 +473,7 @@ For each `challenge` in `block.body.custody_chunk_challenges`, run the following
```python
def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge) -> None:
# Verify the attestation
- validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation))
+ validate_indexed_attestation(state, get_indexed_attestation(state, challenge.attestation))
# Verify it is not too late to challenge
assert slot_to_epoch(challenge.attestation.data.slot) >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
responder = state.validators[challenge.responder_index]
@@ -526,7 +526,7 @@ def process_bit_challenge(state: BeaconState, challenge: CustodyBitChallenge) ->
# Verify challenger is slashable
assert is_slashable_validator(challenger, get_current_epoch(state))
# Verify attestation
- validate_indexed_attestation(state, convert_to_indexed(state, attestation))
+ validate_indexed_attestation(state, get_indexed_attestation(state, attestation))
# Verify attestation is eligible for challenging
responder = state.validators[challenge.responder_index]
assert epoch + responder.max_reveal_lateness <= get_reveal_period(state, challenge.responder_index)
@@ -595,13 +595,13 @@ def process_chunk_challenge_response(state: BeaconState,
# Verify chunk index
assert response.chunk_index == challenge.chunk_index
# Verify bit challenge data is null
- assert response.chunk_bits_branch == [] and response.chunk_bits_leaf == ZERO_HASH
+ assert response.chunk_bits_branch == [] and response.chunk_bits_leaf == Hash()
# Verify minimum delay
assert get_current_epoch(state) >= challenge.inclusion_epoch + ACTIVATION_EXIT_DELAY
# Verify the chunk matches the crosslink data root
- assert verify_merkle_branch(
+ assert is_valid_merkle_branch(
leaf=hash_tree_root(response.chunk),
- proof=response.data_branch,
+ branch=response.data_branch,
depth=challenge.depth,
index=response.chunk_index,
root=challenge.data_root,
@@ -624,17 +624,17 @@ def process_bit_challenge_response(state: BeaconState,
responder = state.validators[challenge.responder_index]
assert not responder.slashed
# Verify the chunk matches the crosslink data root
- assert verify_merkle_branch(
+ assert is_valid_merkle_branch(
leaf=hash_tree_root(response.chunk),
- proof=response.data_branch,
+ branch=response.data_branch,
depth=ceillog2(challenge.chunk_count),
index=response.chunk_index,
root=challenge.data_root,
)
# Verify the chunk bit leaf matches the challenge data
- assert verify_merkle_branch(
+ assert is_valid_merkle_branch(
leaf=response.chunk_bits_leaf,
- proof=response.chunk_bits_branch,
+ branch=response.chunk_bits_branch,
depth=ceillog2(challenge.chunk_count) >> 8,
index=response.chunk_index // 256,
root=challenge.chunk_bits_merkle_root
diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md
index 432820b7c..fd0e41b4f 100644
--- a/specs/core/1_shard-data-chains.md
+++ b/specs/core/1_shard-data-chains.md
@@ -132,14 +132,14 @@ class ShardBlockHeader(Container):
def get_period_committee(state: BeaconState,
epoch: Epoch,
shard: Shard,
- index: int,
- count: int) -> Sequence[ValidatorIndex]:
+ index: uint64,
+ count: uint64) -> Sequence[ValidatorIndex]:
"""
Return committee for a period. Used to construct persistent committees.
"""
return compute_committee(
indices=get_active_validator_indices(state, epoch),
- seed=generate_seed(state, epoch),
+ seed=get_seed(state, epoch),
index=shard * count + index,
count=SHARD_COUNT * count,
)
@@ -150,7 +150,7 @@ def get_period_committee(state: BeaconState,
```python
def get_switchover_epoch(state: BeaconState, epoch: Epoch, index: ValidatorIndex) -> int:
earlier_start_epoch = Epoch(epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2)
- return (bytes_to_int(hash(generate_seed(state, earlier_start_epoch) + int_to_bytes(index, length=3)[0:8]))
+ return (bytes_to_int(hash(get_seed(state, earlier_start_epoch) + int_to_bytes(index, length=3)[0:8]))
% PERSISTENT_COMMITTEE_PERIOD)
```
@@ -248,7 +248,7 @@ def verify_shard_attestation_signature(state: BeaconState,
```python
def compute_crosslink_data_root(blocks: Sequence[ShardBlock]) -> Bytes32:
- def is_power_of_two(value: int) -> bool:
+ def is_power_of_two(value: uint64) -> bool:
return (value > 0) and (value & (value - 1) == 0)
def pad_to_power_of_2(values: MutableSequence[bytes]) -> Sequence[bytes]:
@@ -259,7 +259,7 @@ def compute_crosslink_data_root(blocks: Sequence[ShardBlock]) -> Bytes32:
def hash_tree_root_of_bytes(data: bytes) -> bytes:
return hash_tree_root([data[i:i + 32] for i in range(0, len(data), 32)])
- def zpad(data: bytes, length: int) -> bytes:
+ def zpad(data: bytes, length: uint64) -> bytes:
return data + b'\x00' * (length - len(data))
return hash(
@@ -309,11 +309,11 @@ def is_valid_shard_block(beacon_blocks: Sequence[BeaconBlock],
assert beacon_block.slot <= candidate.slot
# Check state root
- assert candidate.state_root == ZERO_HASH # [to be removed in phase 2]
+ assert candidate.state_root == Hash() # [to be removed in phase 2]
# Check parent block
if candidate.slot == PHASE_1_FORK_SLOT:
- assert candidate.parent_root == ZERO_HASH
+ assert candidate.parent_root == Hash()
else:
parent_block = next(
(block for block in valid_shard_blocks if signing_root(block) == candidate.parent_root),
@@ -395,7 +395,7 @@ def is_valid_beacon_attestation(shard: Shard,
# Check previous attestation
if candidate.data.previous_crosslink.epoch <= PHASE_1_FORK_EPOCH:
- assert candidate.data.previous_crosslink.data_root == ZERO_HASH
+ assert candidate.data.previous_crosslink.data_root == Hash()
else:
previous_attestation = next(
(attestation for attestation in valid_attestations if
diff --git a/specs/light_client/sync_protocol.md b/specs/light_client/sync_protocol.md
index 9a089720b..2b1703f21 100644
--- a/specs/light_client/sync_protocol.md
+++ b/specs/light_client/sync_protocol.md
@@ -84,7 +84,7 @@ def get_period_data(block: ExtendedBeaconBlock, shard_id: Shard, later: bool) ->
indices = get_period_committee(block.state, shard_id, period_start, 0, committee_count)
return PeriodData(
validator_count,
- generate_seed(block.state, period_start),
+ get_seed(block.state, period_start),
[block.state.validators[i] for i in indices],
)
```
diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md
index 1b103b218..0b6857a72 100644
--- a/specs/validator/0_beacon-chain-validator.md
+++ b/specs/validator/0_beacon-chain-validator.md
@@ -145,11 +145,11 @@ def get_committee_assignment(
next_epoch = get_current_epoch(state) + 1
assert epoch <= next_epoch
- committees_per_slot = get_epoch_committee_count(state, epoch) // SLOTS_PER_EPOCH
- epoch_start_slot = get_epoch_start_slot(epoch)
- for slot in range(epoch_start_slot, epoch_start_slot + SLOTS_PER_EPOCH):
+ committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH
+ start_slot = epoch_start_slot(epoch)
+ for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH):
offset = committees_per_slot * (slot % SLOTS_PER_EPOCH)
- slot_start_shard = (get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT
+ slot_start_shard = (get_start_shard(state, epoch) + offset) % SHARD_COUNT
for i in range(committees_per_slot):
shard = (slot_start_shard + i) % SHARD_COUNT
committee = get_crosslink_committee(state, epoch, shard)
@@ -223,7 +223,7 @@ epoch_signature = bls_sign(
The `block.eth1_data` field is for block proposers to vote on recent Eth 1.0 data. This recent data contains an Eth 1.0 block hash as well as the associated deposit root (as calculated by the `get_hash_tree_root()` method of the deposit contract) and deposit count after execution of the corresponding Eth 1.0 block. If over half of the block proposers in the current Eth 1.0 voting period vote for the same `eth1_data` then `state.eth1_data` updates at the end of the voting period. Each deposit in `block.body.deposits` must verify against `state.eth1_data.eth1_deposit_root`.
-Let `get_eth1_data(distance: int) -> Eth1Data` be the (subjective) function that returns the Eth 1.0 data at distance `distance` relative to the Eth 1.0 head at the start of the current Eth 1.0 voting period. Let `previous_eth1_distance` be the distance relative to the Eth 1.0 block corresponding to `state.eth1_data.block_hash` at the start of the current Eth 1.0 voting period. An honest block proposer sets `block.eth1_data = get_eth1_vote(state, previous_eth1_distance)` where:
+Let `get_eth1_data(distance: uint64) -> Eth1Data` be the (subjective) function that returns the Eth 1.0 data at distance `distance` relative to the Eth 1.0 head at the start of the current Eth 1.0 voting period. Let `previous_eth1_distance` be the distance relative to the Eth 1.0 block corresponding to `state.eth1_data.block_hash` at the start of the current Eth 1.0 voting period. An honest block proposer sets `block.eth1_data = get_eth1_vote(state, previous_eth1_distance)` where:
```python
def get_eth1_vote(state: BeaconState, previous_eth1_distance: uint64) -> Eth1Data:
@@ -307,8 +307,8 @@ Set `attestation_data.beacon_block_root = signing_root(head_block)`.
* Set `attestation_data.target_root = epoch_boundary_block_root` where `epoch_boundary_block_root` is the root of block at the most recent epoch boundary.
*Note*: `epoch_boundary_block_root` can be looked up in the state using:
-* Let `epoch_start_slot = get_epoch_start_slot(get_current_epoch(head_state))`.
-* Let `epoch_boundary_block_root = signing_root(head_block) if epoch_start_slot == head_state.slot else get_block_root(state, epoch_start_slot)`.
+* Let `start_slot = epoch_start_slot(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
diff --git a/test_generators/shuffling/main.py b/test_generators/shuffling/main.py
index 7e7b3f94b..9afadfee4 100644
--- a/test_generators/shuffling/main.py
+++ b/test_generators/shuffling/main.py
@@ -10,7 +10,7 @@ from preset_loader import loader
def shuffling_case(seed, count):
yield 'seed', '0x' + seed.hex()
yield 'count', count
- yield 'shuffled', [int(spec.get_shuffled_index(i, count, seed)) for i in range(count)]
+ yield 'shuffled', [int(spec.shuffled_index(i, count, seed)) for i in range(count)]
@to_tuple
diff --git a/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py b/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py
index 5adb022a6..400675888 100644
--- a/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py
+++ b/test_libs/pyspec/eth2spec/test/fork_choice/test_on_attestation.py
@@ -14,7 +14,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
else:
assert False
- indexed_attestation = spec.convert_to_indexed(state, attestation)
+ indexed_attestation = spec.get_indexed_attestation(state, attestation)
spec.on_attestation(store, attestation)
assert (
store.latest_messages[indexed_attestation.custody_bit_0_indices[0]] ==
diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py
index ffd8d1afa..92c4b843d 100644
--- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py
@@ -15,7 +15,7 @@ def build_attestation_data(spec, state, slot, shard):
else:
block_root = spec.get_block_root_at_slot(state, slot)
- current_epoch_start_slot = spec.get_epoch_start_slot(spec.get_current_epoch(state))
+ current_epoch_start_slot = spec.epoch_start_slot(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:
@@ -43,7 +43,7 @@ def build_attestation_data(spec, state, slot, shard):
shard=shard,
start_epoch=parent_crosslink.end_epoch,
end_epoch=min(spec.slot_to_epoch(slot), parent_crosslink.end_epoch + spec.MAX_EPOCHS_PER_CROSSLINK),
- data_root=spec.ZERO_HASH,
+ data_root=spec.Hash(),
parent_root=hash_tree_root(parent_crosslink),
),
)
@@ -54,8 +54,8 @@ def get_valid_attestation(spec, state, slot=None, signed=False):
slot = state.slot
epoch = spec.slot_to_epoch(slot)
- epoch_start_shard = spec.get_epoch_start_shard(state, epoch)
- committees_per_slot = spec.get_epoch_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH
+ 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)
diff --git a/test_libs/pyspec/eth2spec/test/helpers/attester_slashings.py b/test_libs/pyspec/eth2spec/test/helpers/attester_slashings.py
index 9c68b7bbe..20abcacfb 100644
--- a/test_libs/pyspec/eth2spec/test/helpers/attester_slashings.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/attester_slashings.py
@@ -13,6 +13,6 @@ def get_valid_attester_slashing(spec, state, signed_1=False, signed_2=False):
sign_attestation(spec, state, attestation_2)
return spec.AttesterSlashing(
- attestation_1=spec.convert_to_indexed(state, attestation_1),
- attestation_2=spec.convert_to_indexed(state, attestation_2),
+ attestation_1=spec.get_indexed_attestation(state, attestation_1),
+ attestation_2=spec.get_indexed_attestation(state, attestation_2),
)
diff --git a/test_libs/pyspec/eth2spec/test/helpers/block.py b/test_libs/pyspec/eth2spec/test/helpers/block.py
index 16249fe93..fdbc5ef55 100644
--- a/test_libs/pyspec/eth2spec/test/helpers/block.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/block.py
@@ -59,7 +59,7 @@ def build_empty_block(spec, state, slot=None, signed=False):
empty_block.slot = slot
empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index
previous_block_header = deepcopy(state.latest_block_header)
- if previous_block_header.state_root == spec.ZERO_HASH:
+ if previous_block_header.state_root == spec.Hash():
previous_block_header.state_root = state.hash_tree_root()
empty_block.parent_root = signing_root(previous_block_header)
diff --git a/test_libs/pyspec/eth2spec/test/helpers/deposits.py b/test_libs/pyspec/eth2spec/test/helpers/deposits.py
index b46363e62..4f099be9d 100644
--- a/test_libs/pyspec/eth2spec/test/helpers/deposits.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/deposits.py
@@ -49,7 +49,7 @@ def build_deposit(spec,
tree = calc_merkle_tree_from_leaves(tuple([d.hash_tree_root() for d in deposit_data_list]))
proof = list(get_merkle_proof(tree, item_index=index)) + [(index + 1).to_bytes(32, 'little')]
leaf = deposit_data.hash_tree_root()
- assert spec.verify_merkle_branch(leaf, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH + 1, index, root)
+ assert spec.is_valid_merkle_branch(leaf, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH + 1, index, root)
deposit = spec.Deposit(proof=proof, data=deposit_data)
return deposit, root, deposit_data_list
diff --git a/test_libs/pyspec/eth2spec/test/helpers/genesis.py b/test_libs/pyspec/eth2spec/test/helpers/genesis.py
index 7ffacd7d0..a5a816977 100644
--- a/test_libs/pyspec/eth2spec/test/helpers/genesis.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/genesis.py
@@ -27,7 +27,7 @@ def create_genesis_state(spec, num_validators):
eth1_data=spec.Eth1Data(
deposit_root=deposit_root,
deposit_count=num_validators,
- block_hash=spec.ZERO_HASH,
+ block_hash=spec.Hash(),
),
latest_block_header=spec.BeaconBlockHeader(body_root=spec.hash_tree_root(spec.BeaconBlockBody())),
)
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py
index 685eb6ebb..54a284a6e 100644
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py
@@ -195,7 +195,7 @@ def test_bad_merkle_proof(spec, state):
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
# mess up merkle branch
- deposit.proof[5] = spec.ZERO_HASH
+ deposit.proof[5] = spec.Hash()
sign_deposit_data(spec, deposit.data, privkeys[validator_index], state=state)
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py
index 6903f0666..f079ff578 100644
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py
@@ -360,7 +360,7 @@ def test_non_existent_recipient(spec, state):
@spec_state_test
def test_invalid_pubkey(spec, state):
transfer = get_valid_transfer(spec, state, signed=True)
- state.validators[transfer.sender].withdrawal_credentials = spec.ZERO_HASH
+ state.validators[transfer.sender].withdrawal_credentials = spec.Hash()
# un-activate so validator can transfer
state.validators[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py
index 33cacc4e2..6c9298ecc 100644
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py
@@ -71,7 +71,7 @@ def test_success_exit_queue(spec, state):
current_epoch = spec.get_current_epoch(state)
# exit `MAX_EXITS_PER_EPOCH`
- initial_indices = spec.get_active_validator_indices(state, current_epoch)[:spec.get_churn_limit(state)]
+ initial_indices = spec.get_active_validator_indices(state, current_epoch)[:spec.get_validator_churn_limit(state)]
# Prepare a bunch of exits, based on the current state
exit_queue = []
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
index 59d47f0ad..41d784c50 100644
--- 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
@@ -83,7 +83,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, state):
@with_all_phases
@spec_state_test
def test_double_late_crosslink(spec, state):
- if spec.get_epoch_committee_count(state, spec.get_current_epoch(state)) < spec.SHARD_COUNT:
+ 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
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 1744d388c..f59da1fc5 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
@@ -10,8 +10,8 @@ def run_process_just_and_fin(spec, state):
def get_shards_for_slot(spec, state, slot):
epoch = spec.slot_to_epoch(slot)
- epoch_start_shard = spec.get_epoch_start_shard(state, epoch)
- committees_per_slot = spec.get_epoch_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH
+ 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)]
@@ -33,8 +33,8 @@ 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
- epoch_start_slot = spec.get_epoch_start_slot(epoch)
- for slot in range(epoch_start_slot, epoch_start_slot + spec.SLOTS_PER_EPOCH):
+ start_slot = spec.epoch_start_slot(epoch)
+ for slot in range(start_slot, start_slot + spec.SLOTS_PER_EPOCH):
for shard in get_shards_for_slot(spec, state, 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)
@@ -80,7 +80,7 @@ def get_checkpoints(spec, epoch):
def put_checkpoints_in_block_roots(spec, state, checkpoints):
for c in checkpoints:
- state.block_roots[spec.get_epoch_start_slot(c.epoch) % spec.SLOTS_PER_HISTORICAL_ROOT] = c.root
+ state.block_roots[spec.epoch_start_slot(c.epoch) % spec.SLOTS_PER_HISTORICAL_ROOT] = c.root
def finalize_on_234(spec, state, epoch, sufficient_support):
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py
index 19500d4ab..ab6a74a70 100644
--- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py
@@ -45,7 +45,7 @@ def test_activation_queue_sorting(spec, state):
state.validators[mock_activations - 1].activation_eligibility_epoch = epoch
# make sure we are hitting the churn
- churn_limit = spec.get_churn_limit(state)
+ churn_limit = spec.get_validator_churn_limit(state)
assert mock_activations > churn_limit
yield from run_process_registry_updates(spec, state)
diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py
index b2eb19244..b6f0ecba2 100644
--- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py
+++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py
@@ -63,7 +63,7 @@ def test_empty_block_transition(spec, state):
assert len(state.eth1_data_votes) == pre_eth1_votes + 1
assert spec.get_block_root_at_slot(state, pre_slot) == block.parent_root
- assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.ZERO_HASH
+ assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.Hash()
@with_all_phases
@@ -98,7 +98,7 @@ def test_skipped_slots(spec, state):
yield 'post', state
assert state.slot == block.slot
- assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.ZERO_HASH
+ assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.Hash()
for slot in range(pre_slot, state.slot):
assert spec.get_block_root_at_slot(state, slot) == block.parent_root
diff --git a/test_libs/pyspec/eth2spec/test/test_finality.py b/test_libs/pyspec/eth2spec/test/test_finality.py
index 2d86ef523..5ff0ed1ef 100644
--- a/test_libs/pyspec/eth2spec/test/test_finality.py
+++ b/test_libs/pyspec/eth2spec/test/test_finality.py
@@ -43,7 +43,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
- if slot_to_attest >= spec.get_epoch_start_slot(spec.get_current_epoch(post_state)):
+ if slot_to_attest >= spec.epoch_start_slot(spec.get_current_epoch(post_state)):
cur_attestation = get_valid_attestation(spec, post_state, slot_to_attest)
block.body.attestations.append(cur_attestation)