proofread and add ToC
This commit is contained in:
parent
2c34a97341
commit
67123a79cb
|
@ -1,10 +1,52 @@
|
|||
# Ethereum 2.0 Phase 0 -- The Beacon Chain
|
||||
|
||||
###### tags: `spec`, `eth2.0`, `casper`, `sharding`, `beacon`
|
||||
**tags: `spec`, `eth2.0`, `casper`, `sharding`, `beacon`**
|
||||
|
||||
**NOTICE**: This document is a work-in-progress for researchers and implementers. It reflects recent spec changes and takes precedence over the [Python proof-of-concept implementation](https://github.com/ethereum/beacon_chain).
|
||||
|
||||
### Introduction
|
||||
## Table of contents
|
||||
* [Ethereum 2.0 Phase 0 -- The Beacon Chain](#ethereum-20-phase-0----the-beacon-chain)
|
||||
* [Table of contents](#table-of-contents)
|
||||
* [Introduction](#introduction)
|
||||
* [Terminology](#terminology)
|
||||
* [Constants](#constants)
|
||||
* [PoW chain registration contract](#pow-chain-registration-contract)
|
||||
* [Data structures](#data-structures)
|
||||
* [Beacon chain blocks](#beacon-chain-blocks)
|
||||
* [Beacon chain state](#beacon-chain-state)
|
||||
* [Beacon chain processing](#beacon-chain-processing)
|
||||
* [Beacon chain fork choice rule](#beacon-chain-fork-choice-rule)
|
||||
* [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
* [Helper functions](#helper-functions)
|
||||
* [PoW chain contract](#pow-chain-contract)
|
||||
* [On startup](#on-startup)
|
||||
* [Routine for adding a validator](#routine-for-adding-a-validator)
|
||||
* [Routine for removing a validator](#routine-for-removing-a-validator)
|
||||
* [Per-block processing](#per-block-processing)
|
||||
* [Verify attestations](#verify-attestations)
|
||||
* [Verify proposer signature](#verify-proposer-signature)
|
||||
* [Verify and process RANDAO reveal](#verify-and-process-randao-reveal)
|
||||
* [Process PoW receipt root](#process-pow-receipt-root)
|
||||
* [Process penalties, logouts and other special objects](#process-penalties-logouts-and-other-special-objects)
|
||||
* [LOGOUT](#logout)
|
||||
* [CASPER_SLASHING](#casper_slashing)
|
||||
* [PROPOSER_SLASHING](#proposer_slashing)
|
||||
* [DEPOSIT_PROOF](#deposit_proof)
|
||||
* [Cycle boundary processing](#cycle-boundary-processing)
|
||||
* [Precomputation](#precomputation)
|
||||
* [Adjust justified slots and crosslink status](#adjust-justified-slots-and-crosslink-status)
|
||||
* [Balance recalculations related to FFG rewards](#balance-recalculations-related-to-ffg-rewards)
|
||||
* [Balance recalculations related to crosslink rewards](#balance-recalculations-related-to-crosslink-rewards)
|
||||
* [PoW chain related rules](#pow-chain-related-rules)
|
||||
* [Validator set change](#validator-set-change)
|
||||
* [If a validator set change does NOT happen](#if-a-validator-set-change-does-not-happen)
|
||||
* [Proposer reshuffling](#proposer-reshuffling)
|
||||
* [Finally...](#finally)
|
||||
* [Appendix](#appendix)
|
||||
* [Appendix A - Hash function](#appendix-a---hash-function)
|
||||
* [Copyright](#copyright)
|
||||
|
||||
## Introduction
|
||||
|
||||
This document represents the specification for Phase 0 of Ethereum 2.0 -- The Beacon Chain.
|
||||
|
||||
|
@ -12,7 +54,8 @@ At the core of Ethereum 2.0 is a system chain called the "beacon chain". The bea
|
|||
|
||||
The primary source of load on the beacon chain are "attestations". Attestations simultaneously attest to a shard block and a corresponding beacon chain 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.
|
||||
|
||||
### Terminology
|
||||
|
||||
## Terminology
|
||||
|
||||
* **Validator** - a participant in the Casper/sharding consensus system. You can become one by depositing 32 ETH into the Casper mechanism.
|
||||
* **Active validator set** - those validators who are currently participating, and which the Casper mechanism looks to produce and attest to blocks, crosslinks and other consensus objects.
|
||||
|
@ -28,7 +71,7 @@ The primary source of load on the beacon chain are "attestations". Attestations
|
|||
* **Withdrawal period** - number of slots between a validator exit and the validator balance being withdrawable
|
||||
* **Genesis time** - the Unix time of the genesis beacon chain block at slot 0
|
||||
|
||||
### Constants
|
||||
## Constants
|
||||
|
||||
| Constant | Value | Unit | Approximation |
|
||||
| --- | --- | :---: | - |
|
||||
|
@ -52,13 +95,13 @@ The primary source of load on the beacon chain are "attestations". Attestations
|
|||
| `COLLECTIVE_PENALTY_CALCULATION_PERIOD` | 2**20 (= 1,048,576) | slots | ~2.4 months |
|
||||
| `POW_RECEIPT_ROOT_VOTING_PERIOD` | 2**10 (= 1,024) | slots | ~1.7 hours |
|
||||
| `SLASHING_WHISTLEBLOWER_REWARD_DENOMINATOR` | 2**9 (= 512) |
|
||||
| `BASE_REWARD_QUOTIENT` | 2**11 (= 2,048) | — |
|
||||
| `INCLUDER_REWARD_SHARE_QUOTIENT` | 2**3 (= 8) | — |
|
||||
| `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — |
|
||||
| `BASE_REWARD_QUOTIENT` | 2**11 (= 2,048) | - |
|
||||
| `INCLUDER_REWARD_SHARE_QUOTIENT` | 2**3 (= 8) | - |
|
||||
| `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | - |
|
||||
| `POW_CONTRACT_MERKLE_TREE_DEPTH` | 2**5 (= 32) | - |
|
||||
| `MAX_ATTESTATION_COUNT` | 2**7 (= 128) | - |
|
||||
| `LOGOUT_MESSAGE` | `"LOGOUT"` | — |
|
||||
| `INITIAL_FORK_VERSION` | 0 | — |
|
||||
|
||||
| `INITIAL_FORK_VERSION` | 0 | - |
|
||||
|
||||
**Notes**
|
||||
|
||||
|
@ -103,7 +146,7 @@ The primary source of load on the beacon chain are "attestations". Attestations
|
|||
| `DOMAIN_PROPOSAL` | `2` |
|
||||
| `DOMAIN_LOGOUT` | `3` |
|
||||
|
||||
### PoW chain registration contract
|
||||
## PoW chain registration contract
|
||||
|
||||
The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to the PoW chain. A registration contract is added to the PoW chain to deposit ETH. This contract has a `registration` function which takes as arguments `pubkey`, `withdrawal_credentials`, `randao_commitment` as defined in a `ValidatorRecord` below. A BLS `proof_of_possession` of types `bytes` is given as a final argument.
|
||||
|
||||
|
@ -333,7 +376,7 @@ A `ProcessedAttestation` object has the following fields:
|
|||
{
|
||||
# Signed data
|
||||
'data': AttestationSignedData,
|
||||
# Attester participation bitfield (2 bits per attester)
|
||||
# Attester participation bitfield
|
||||
'attester_bitfield': 'bytes',
|
||||
# Proof of custody bitfield
|
||||
'poc_bitfield': 'bytes',
|
||||
|
@ -371,7 +414,7 @@ The beacon chain fork choice rule is a hybrid that combines justification and fi
|
|||
* Let `finalized_head` be the finalized block with the highest slot number. (A block `B` is finalized if there is a descendant of `B` in `store` the processing of which sets `B` as finalized.)
|
||||
* Let `justified_head` be the descendant of `finalized_head` with the highest slot number that has been justified for at least `CYCLE_LENGTH` slots. (A block `B` is justified if there is a descendant of `B` in `store` the processing of which sets `B` as justified.) If no such descendant exists set `justified_head` to `finalized_head`.
|
||||
* Let `get_ancestor(store, block, slot)` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as `def get_ancestor(store, block, slot): return block if block.slot == slot else get_ancestor(store, store.get_parent(block), slot)`.
|
||||
* Let `get_latest_attestation(store, validator)` be the attestation with the highest slot number in `store` from `validator`. If several such attestations exist use the one the validator `v` observed first.
|
||||
* Let `get_latest_attestation(store, validator)` be the attestation with the highest slot number in `store` from `validator`. If several such attestations exist, use the one the validator `v` observed first.
|
||||
* Let `get_latest_attestation_target(store, validator)` be the target block in the attestation `get_latest_attestation(store, validator)`.
|
||||
* The head is `lmd_ghost(store, justified_head)` where the function `lmd_ghost` is defined below. Note that the implementation below is suboptimal; there are implementations that compute the head in time logarithmic in slot count.
|
||||
|
||||
|
@ -409,7 +452,7 @@ Below are various helper functions.
|
|||
|
||||
The following is a function that gets active validator indices from the validator list:
|
||||
```python
|
||||
def get_active_validator_indices(validators)
|
||||
def get_active_validator_indices(validators: [ValidatorRecords]) -> List[int]:
|
||||
return [i for i, v in enumerate(validators) if v.status == ACTIVE]
|
||||
```
|
||||
|
||||
|
@ -501,18 +544,18 @@ Now, our combined helper method:
|
|||
def get_new_shuffling(seed: Hash32,
|
||||
validators: List[ValidatorRecord],
|
||||
crosslinking_start_shard: int) -> List[List[ShardAndCommittee]]:
|
||||
active_validators = get_active_validator_indices(validators)
|
||||
active_validator_indices = get_active_validator_indices(validators)
|
||||
|
||||
committees_per_slot = clamp(
|
||||
1,
|
||||
SHARD_COUNT // CYCLE_LENGTH,
|
||||
len(active_validators) // CYCLE_LENGTH // TARGET_COMMITTEE_SIZE,
|
||||
len(active_validator_indices) // CYCLE_LENGTH // TARGET_COMMITTEE_SIZE,
|
||||
)
|
||||
|
||||
output = []
|
||||
|
||||
# Shuffle with seed
|
||||
shuffled_active_validator_indices = shuffle(active_validators, seed)
|
||||
shuffled_active_validator_indices = shuffle(active_validator_indices, seed)
|
||||
|
||||
# Split the shuffled list into cycle_length pieces
|
||||
validators_per_slot = split(shuffled_active_validator_indices, CYCLE_LENGTH)
|
||||
|
@ -1107,7 +1150,7 @@ Repeat the steps in this section while `block.slot - last_state_recalculation_sl
|
|||
|
||||
_Note: `last_state_recalculation_slot` will always be a multiple of `CYCLE_LENGTH`. In the "happy case", this process will trigger, and loop once, every time `block.slot` passes a new exact multiple of `CYCLE_LENGTH`, but if a chain skips more than an entire cycle then the loop may run multiple times, incrementing `last_state_recalculation_slot` by `CYCLE_LENGTH` with each iteration._
|
||||
|
||||
#### Precomputation
|
||||
### Precomputation
|
||||
|
||||
All validators:
|
||||
|
||||
|
@ -1147,7 +1190,7 @@ def adjust_for_inclusion_distance(magnitude: int, dist: int) -> int:
|
|||
|
||||
For any validator `v`, `base_reward(v) = balance_at_stake(v) // reward_quotient`
|
||||
|
||||
#### Adjust justified slots and crosslink status
|
||||
### Adjust justified slots and crosslink status
|
||||
|
||||
* Set `state.justified_slot_bitfield = (state.justified_slot_bitfield * 2) % 2**64`.
|
||||
* If `3 * prev_cycle_boundary_attesting_balance >= 2 * total_balance` then set `state.justified_slot_bitfield &= 2` (ie. flip the second lowest bit to 1) and `new_justification_source = s - CYCLE_LENGTH`.
|
||||
|
@ -1161,7 +1204,7 @@ For every `ShardAndCommittee` object `obj`:
|
|||
|
||||
* If `3 * total_attesting_balance(obj) >= 2 * total_balance(obj)`, set `crosslinks[shard] = CrosslinkRecord(slot=last_state_recalculation_slot + CYCLE_LENGTH, hash=winning_hash(obj))`.
|
||||
|
||||
#### Balance recalculations related to FFG rewards
|
||||
### Balance recalculations related to FFG rewards
|
||||
|
||||
Note: When applying penalties in the following balance recalculations implementers should make sure the `uint64` does not underflow.
|
||||
|
||||
|
@ -1180,21 +1223,21 @@ Case 2: `time_since_finality > 4 * CYCLE_LENGTH`:
|
|||
|
||||
For each `v` in `prev_cycle_boundary_attesters`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(v))` and set `state.validators[proposer_index].balance += base_reward(v) // INCLUDER_REWARD_SHARE_QUOTIENT`.
|
||||
|
||||
#### Balance recalculations related to crosslink rewards
|
||||
### Balance recalculations related to crosslink rewards
|
||||
|
||||
For every `ShardAndCommittee` object `obj` in `shard_and_committee_for_slots[:CYCLE_LENGTH]` (ie. the objects corresponding to the cycle before the current one), for each `v` in `[state.validators[index] for index in obj.committee]`, adjust balances as follows:
|
||||
|
||||
* If `v in attesting_validators(obj)`, `v.balance += adjust_for_inclusion_distance(base_reward(v) * total_attesting_balance(obj) // total_balance(obj)), inclusion_distance(v))`.
|
||||
* If `v not in attesting_validators(obj)`, `v.balance -= base_reward(v)`.
|
||||
|
||||
#### PoW chain related rules
|
||||
### PoW chain related rules
|
||||
|
||||
If `last_state_recalculation_slot % POW_RECEIPT_ROOT_VOTING_PERIOD == 0`, then:
|
||||
|
||||
* If for any `x` in `state.candidate_pow_receipt_root`, `x.votes * 2 >= POW_RECEIPT_ROOT_VOTING_PERIOD` set `state.processed_pow_receipt_root = x.receipt_root`.
|
||||
* Set `state.candidate_pow_receipt_roots = []`.
|
||||
|
||||
#### Validator set change
|
||||
### Validator set change
|
||||
|
||||
A validator set change can happen if all of the following criteria are satisfied:
|
||||
|
||||
|
@ -1212,9 +1255,9 @@ def get_changed_validators(validators: List[ValidatorRecord],
|
|||
Return changed validator set and `deposits_penalized_in_period`, `validator_set_delta_hash_chain`.
|
||||
"""
|
||||
# The active validator set
|
||||
active_validators = get_active_validator_indices(validators)
|
||||
active_validator_indices = get_active_validator_indices(validators)
|
||||
# The total balance of active validators
|
||||
total_balance = sum([balance_at_stake(v) for i, v in enumerate(validators) if i in active_validators])
|
||||
total_balance = sum([balance_at_stake(v) for i, v in enumerate(validators) if i in active_validator_indices])
|
||||
# The maximum total wei that can deposit+withdraw
|
||||
max_allowable_change = max(
|
||||
2 * DEPOSIT_SIZE * GWEI_PER_ETH,
|
||||
|
@ -1296,14 +1339,14 @@ And perform the following updates to the `state`:
|
|||
* Set `state.shard_and_committee_for_slots[CYCLE_LENGTH:] = get_new_shuffling(state.next_shuffling_seed, validators, next_start_shard)`
|
||||
* Set `state.next_shuffling_seed = state.randao_mix`
|
||||
|
||||
#### If a validator set change does NOT happen
|
||||
### If a validator set change does NOT happen
|
||||
|
||||
* Set `state.shard_and_committee_for_slots[:CYCLE_LENGTH] = state.shard_and_committee_for_slots[CYCLE_LENGTH:]`
|
||||
* Let `time_since_finality = block.slot - state.validator_set_change_slot`
|
||||
* Let `start_shard = state.shard_and_committee_for_slots[0][0].shard`
|
||||
* If `time_since_finality * CYCLE_LENGTH <= MIN_VALIDATOR_SET_CHANGE_INTERVAL` or `time_since_finality` is an exact power of 2, set `state.shard_and_committee_for_slots[CYCLE_LENGTH:] = get_new_shuffling(state.next_shuffling_seed, validators, start_shard)` and set `state.next_shuffling_seed = state.randao_mix`. Note that `start_shard` is not changed from last cycle.
|
||||
|
||||
#### Proposer reshuffling
|
||||
### Proposer reshuffling
|
||||
|
||||
Run the following code to update the shard proposer set:
|
||||
|
||||
|
@ -1332,7 +1375,7 @@ while len(state.persistent_committee_reassignments) > 0 and state.persistent_com
|
|||
state.persistent_committees[rec.shard].append(rec.validator_index)
|
||||
```
|
||||
|
||||
#### Finally...
|
||||
### Finally...
|
||||
|
||||
* Remove all attestation records older than slot `s`
|
||||
* For any validator with index `v` with balance less than `MIN_ONLINE_DEPOSIT_SIZE` and status `ACTIVE`, run `exit_validator(v, state, block, penalize=False, current_slot=block.slot)`
|
||||
|
@ -1344,5 +1387,5 @@ while len(state.persistent_committee_reassignments) > 0 and state.persistent_com
|
|||
|
||||
We aim to have a STARK-friendly hash function `hash(x)` for the production launch of the beacon chain. While the standardisation process for a STARK-friendly hash function takes place—led by STARKware, who will produce a detailed report with recommendations—we use `BLAKE2b-512` as a placeholder. Specifically, we set `hash(x) := BLAKE2b-512(x)[0:32]` where the `BLAKE2b-512` algorithm is defined in [RFC 7693](https://tools.ietf.org/html/rfc7693) and the input `x` is of type `bytes`.
|
||||
|
||||
## Copyright
|
||||
# Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
Loading…
Reference in New Issue