-
-
owned this note
-
Published
Linked with GitHub
# Phase 0 accompanying resource
[toc]
## Resources
* [Specs](https://github.com/ethereum/eth2.0-specs)
* [beacon chain state transition](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md)
* [fork choice](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_fork-choice.md)
* [validator guide](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/validator/0_beacon-chain-validator.md)
* [design rationale](https://notes.ethereum.org/s/rkhCgQteN#)
* Academic Papers
* [Casper FFG](https://arxiv.org/abs/1710.09437)
* [WIP paper formalizing FFG in PoS chain using LMD GHOST](https://www.overleaf.com/5374235669mhggmhksxpyj)
## High level overview
The beacon chain is the core system-level blockchain for Ethereum 2.0. The name comes from that fact that it serves as a random beacon, but could just as easily be called the "system chain", "spine chain", etc. This chain is where the validators exist, where they are assigned their _duties_, where they perform the _RNG MPC_, where they _vote on the head_ of the chain for the fork choice, where they _finalize checkpoints_, and where they _link back in references to shard chains (crosslinks)_ to serve as the root of each shard chain and to faciliate cross-shard communication. It is both the brains behind the operation and the scaffolding upon which the rest of the sharded system is built.
The beacon chain's state (`BeaconState`) is the core object around which the specification is built. The `BeaconState` encapsulates all of the information pertaining to: who the validators are, in what state each of them is in, which chain in the tree this state belongs to and a hash-reference to the Ethereum 1 chain.
Beginning with the genesis state, the post state of a block is considered valid if it passes all of the guards within the state transition function. Thus, the precondition of a block is recursively defined as being a valid postcondition of running the state transition function on the previous block and its state all the way back to the genesis state.
### Fork Choice Rule
Given a block tree, the fork choice rule provides a single chain (the canonical chain) and resulting state based upon recent messages from validators. The fork choice rule consumes the block-tree along with the set of most recent attestations from the validator set and returns a block as the current head of the chain. LMD GHOST, the fork choice rule of Eth2.0, considers which block the latest attestation from each validator points to and uses this to calculate the total balance that recursively attests to each block in the tree. This is done by setting the weight of a node in the tree to be the sum of the balances of the validators whose latest attestations were for that node or any descendent of that node. The GHOST algorithm then starts at the base of the tree, selecting the child of the current node with the heaviest weight until reaching a leaf node. This leaf node is the head of the chain and recursively defines the canonical chain.
Concretely, validators are given the opportunity to produce a single [attestation](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md#attestation) during an assigned slot at each epoch. The committed to `attestation.data.beacon_block_root` serves as a fork choice vote. A view takes into account all of the most recent of these votes from the current active validator set when computing the fork choice.
### Finality
The fork choice rule allows us to choose a single canonical blockchain through the block tree whereas "finality" provides guarantees that certain blocks will remain within the canonical chain. The beacon chain uses a modified version of Casper FFG for finality. Casper provides "accountable safety" that certain blocks will always remain in the canonical chain unless some threshold of validators burn their staked up capital. This is what we call a "crypto-economic" claim of safety rather than a more traditional safety found in traditional consensus algorithms.
Concretely, validators are given the opportunity to produce a single [attestation](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md#attestation) during an assigned slot at each epoch. The committed to `(attestation.data.source_root, attestation.data.source_epoch)` serves as the FFG source pair discussed in depth in ["Combining GHOST and Casper"](https://www.overleaf.com/5374235669mhggmhksxpyj), while the committed to `(attestation.data.target_root, attestation.data.target_epoch)` serves as the FFG target pair.
### Crosslinks
Crosslinks are references in the beacon chain to the recent state/blocks for each shard chain. These references serve both as the root of the shard chain fork choice as well as a means for asynchronous communication between shards. In the normal case, each shard can be crosslinked into the beacon chain once per epoch (with a low validator count, this is sometimes once every N epochs).
Although shard chains are not added until phase 1, crosslink committees in phase 0 are still assigned to a shard and attempt to form a crosslink each epoch. In phase 0, data roots inside of crosslinks are simply stubbed as `0x00`.
### Validator responsibilities
A detailed discussion of the responsibilities of validators in phase 0 can be found [here](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/validator/0_beacon-chain-validator.md#beacon-chain-responsibilities).
The two primary responsibilities are (1) attesting to the beacon chain at each epoch and (2) infrequently creating beacon blocks when selected. Validators are split into "crosslink committees" at each epoch. Each committee is assigned to a slot and shard. The validator attests to the head of the beacon chain and the recent data of the shard (phase 1) at the assigned slot. At each slot, a single beacon block proposer is selected (via `get_beacon_proposer_index`) from one of the committees assigned to the slot.
Validators gain rewards by regularly attesting to the canonical beacon chain and shard chains and incur penalties if they fail to do so. A validator can be _slashed_ (a more severe penalty) if they violate the Casper FFG rules or if they create two beacon blocks in one epoch. More details on slashing can be found [here](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/validator/0_beacon-chain-validator.md#how-to-avoid-slashing).
## Data structures
### A note on data structures
Data structures and hashes of data structures within the beacon chain are encoded as [Simple SerialiZe (SSZ)](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/simple-serialize.md) objects. One of the benefits of SSZ-hashing is its support for non-homgenous tree depths when merkleizing the underlying data. As a result of this and the rest of SSZ's clever design, the hash tree root of an SSZ object is the same whether the object's sub-objects are represented by the full sub-objects or just their partial merkle root.
### Beacon operations
Beacon operations are datastructures that can be added to a `BeaconBlock` by a block proposer. This is how various messages related to system level validation/construction of the chain are incorporated. They are essentially validator-level transactions to the beacon chain state machine. Each operation has a maximum allowed per block defined in the constants in [max operations per block](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md#max-operations-per-block).
#### `ProposerSlashing`
* Beacon block proposers can be slashed if they signed two different beacon blocks for the same epoch.
* This data structure contains proof that such a slashable offense has occurred.
* `hash_tree_root(block) == hash_tree_root(block_header)` and thus the signature is valid for both data structures. `BeaconBlockHeader` is thus used as proof to reduce message size.
#### `AttesterSlashing`
* Beacon attesters can be slashed if they sign two conflicting attestations where conflicting is defined by [`is_slashable_attestation_data`](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md#is_slashable_attestation_data) which checks for the Casper FFG "double" and "surround" vote conditions.
#### `Attestation`
* Primary message type that validators create for consensus. Although beacon blocks are only created by one validator per slot, _all_ validators have a chance to create an attestation each epoch. In the normal case, all online validators create and have an attestation included into a block at each epoch.
* `AttestationData` is the main component that is signed. The outer datastructure contains the aggregate signature and the participation bitfields requisite for verification of the signature.
* Fields
* `aggregation_bitfield` stores a single bit for each member of the committee with a value of `1` if the validator participated in this aggregate signature
* `data` is the `AttestationData` that was signed by the validator or committee of validators
* `beacon_block_root` - block root of the beacon block seen as the head of the chain at the assigned slot
* `source_epoch` - the most recent justified epoch in the `BeaconState` at the assigned slot
* `source_root` - the most recent justified root in the `BeaconState` at the assigned slot
* `target_epoch` - the epoch attempting to be justified (the current epoch)
* `target_root` - the block root attempting to be justified (the epoch boundary block)
* `crosslink` - the crosslink attemping to be formed for the assigned shard
* `custody_bitfield` represents each participating validator's "proof of custody" bit. In phase 0, this must be set to 0 bits. (proof of custody is to be enabled during phase 1)
* `signature` is the aggregate BLS signature of the data.
* [`AttestationDataAndCustodyBit`](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md#attestationdataandcustodybit) is the actual message signed by validators. For a given `Attestation` there are two potential messages signed -- `AttestationDataAndCustodyBit` with a 0 or 1 custody bit. The `custody_bitfield` allows recovery of the expected signed message (custody_bit 0/1) from each participating validator. In phase 0, all custody bits are 0.
#### `Deposit`
* Represents incoming validator deposits from the eth1 chain deposit contract.
* Fields
* `proof` - the merkle proof against the `BeaconState` current `eth1_data.root`
* `data` - the `DepositData` submit to the deposit contract to be verified using the proof against the deposit root.
* `pubkey` - BLS12-381 pubkey to be used to sign messages by the validator
* `withdrawal_credentials` - the hash of an offline pubkey to be used to withdraw the staked funds after exiting. This key is not used actively in validation and can be kept in cold storage.
* `amount` - amount in Gwei that was deposited
* `signature` - Signature of the `DepositData` using the `privkey` pair of the `pubkey`. This is used as a one-time "proof of custody" required for securely using BLS keys.
#### `VoluntaryExit`
* Message type allows a validator to voluntarily exit validation duties
* Fields
* `epoch` - minimum epoch at which this exit can be included on chain. Helps prevent accidental/nefarious use in chain reorgs/forks.
* `validator_index` - index of validator exiting
* `signature` - signature of the `VoluntaryExit` by the pubkey associated with the `Validator` defined by `validator_index`.
#### `Transfer`
* Allows validators to transfer balances.
* This is primarily a mechanism to allow for liquidity during phase 0 and 1 before state exists on the shard chains.
* Transfers must be included in the precise `slot` specified to avoid replay attacks.
* Active validators cannot transfer eth.
* `MAX_TRANSFERS` is expected to be set to 0 at the initial launch of phase 0 and only to be increased once phase 0 is seen as stable in production.
* Fields
* `sender` - validator index of the sender of funds
* `recipient` - validator index of the recipient of funds
* `amount` - amount in Gwei
* `fee` - fee in Gwei to be paid to the block proposer for including the transfer
* `slot` - the specific slot that this signed `Transfer` can be included on chain. prevents replay attacks
* `pubkey` - the withdrawal `pubkey` of the `sender`. The `hash` of this pubkey must match the `sender`s withdrawal_credentials.
* `signature` - the signature of the `Transfer` signed by the `transfer.pubkey`
### Beacon blocks
* `BeaconBlock`
* This can be thought of as the main container/header for a beacon block.
* Note that `hash_tree_root(BeaconBlock) == hash_tree_root(BeaconBlockHeader)` and so signatures of each are equivalent.
* Fields
* `slot` - the slot for which this block is created. Must be greater than the slot of the block defined by `parent_root`
* `parent_root` - the block root of the parent block forming a block chain
* `state_root` - the hash root of the post state of running the state transition through this block
* `body` - contain all of the aforementioned beacon operations objects as well as a few supplemental fields
* `signature` - signature of the block by the block proposer
* `BeaconBlockBody`
* `randao_reveal` is the signature of the current epoch (by the block proposer) and, when mixed in with the other validators' reveals, consitutes the seed for randomness.
* `Eth1Data` is the pointer from the beacon chain back to the Eth1 chain. It maintains the following fields of note:
* `deposit_root` - the merkle-root of the deposits in the deposit contract.
* `deposit_count` - the number of deposits that have occured thusfar
* `block_hash` - the eth1 block hash that contained the `deposit_root`. This `block_hash` is expected to be used for finilization of the Eth1 chain in the future (similar to how the FFG contract was going to be used to finalize the eth1 chain).
* `graffiti` - This is a space for validators to decorate as they choose. It has no define in-protocol use.
### Beacon state
The `BeaconState` is the resulting state of running the state transition function on a series of blocks starting from the genesis state. It contains the validator registry, information about randomness, information about finality, relevant caches, and data about the eth1 chain.
* Misc
* `slot` -- time is divided into "slots" of fixed length at which actions occur and state transitions happen. This field tracks the slot of the state.
* `genesis_time` -- tracks when genesis event occured. This allows a client to calculate what the slot should be according to wall clock time
* `fork` -- a mechanism for handling forking (upgrading) the beacon chain. The main purpose here is to handle versioning of signatures and handle objects of different signatures across fork boundaries
* Validator registry
* `validator_registry` -- a list of `Validator` records, tracking the current full registry. Each validator contains data relevant to it such as pubkey, effective balance, and status (pending, active, exited, etc)
* `balances` -- a list mapping 1:1 with the `validator_registry`. The granular/frequently changing balances are pulled out to reduce the amount of re-hashing that needs to be performed at each epoch.
* Randomness and committees
* `latest_randao_mixes` -- The randao mix from each epoch. At the start of every epoch, the randao_mix from the previous epoch is copied over as the base of the current epoch. At each block, the `hash` of the `block.randao_reveal` is xor'd into the running mix.
* `latest_start_shard` -- Tracks the "start shard" of the current epoch which is used as the base to calculate assigned shard for each committee in an epoch -- `(latest_shard_shard + committee_offset) % SHARD_COUNT`
* Finality
* `PendingAttestations`
* `Attestations` from blocks are converted to `PendingAttestations` and stored in state for bulk accounting at epoch boundaries. We store two separate lists
* `previous_epoch_attesations` -- List of `PendingAttestations` for slots from the previous epoch. *note*: these are attestations attesting to slots in the previous epoch, not those included in blocks during the previous epoch.
* `current_epoch_attesations` -- List of `PendingAttestations` for slots from the current epoch. Moved to `previous_epoch_attestations` at the end of the current epoch processing.
* `previous_justifed_epoch` -- Most recent justified epoch _during_ the previous epoch.
* `current_justifed_epoch` -- Most recent justified epoch _during_ the current epoch.
* `previous_justified_root` -- Most recent justified block root _during_ the previous epoch.
* `current_justified_root` -- Most recent justified block root _during_ the current epoch.
* `justification_bitfield` -- bits tracking the justified state of the previous 64 epochs. Note that this is not alone sufficient in calculating finality as `source` of the justified epoch must be taken into account.
* `finalized_epoch` -- the latest finalized epoch
* `finalized_root` -- the latest finalized block root
* Recent state
* Crosslinks
* We store previous and current epoch crosslinks because crosslinks must form a chain so an `Attestation` references the crosslink as it was during the creation of the attestation. To validate an crosslink reference within attestation from the previous epoch during the current epoch, we rely upon `previous_crosslinks`.
* `current_crosslinks` -- The list of crosslinks (one per shard) during the current epoch
* `previous_crosslinks` -- The list of crosslinks as they were during the previous epoch
* `latest_block_roots` -- per-slot store of the recent block roots. The block root for a slot is added at the start of the next slot to avoid the circular dependency due to the state root being embedded in the block. For slots that are skipped (no block in the chain for the given slot), the previous available block root is stored.
* `latest_state_roots` -- per-slot store of the recent state roots. The state root for a slot is stored at the start of the next slot.
* `latest_active_index_roots` -- per-epoch store of the hash-root of the active validator registry. This is primarily used to better serve light clients.
* `latest_slashed_balances` -- per-epoch store of the running total of slashed balances for all time. The difference between the current and some previous epoch gives us the "recent slashed balance" is used to calculate the proportion of balance that should be slashed for slashable validators.
* `latest_block_header` -- Store of the latest block header seen. On the slot of the block, the header is stored _without_ the state root. At the start of the next slot, the state root is added to the block header. This is done to eliminate the circular dependency of the state root being embedded in the block header.
* `historical_roots` -- a double batch merkle accumulator of the latest block and state roots to make historic merkle proofs against
* Ethereum 1.0 chain data
* `latest_eth1_data` -- the latest eth1 data that has been come to a consensus on by the eth2 validators. This data is then used to process incoming deposits from the eth1 chain.
* `eth1_data_votes` -- the latest eth1 data votes since the start of the recent eth1 data voting period. Each processed block contains an `Eth1Data` vote. At the end of the voting period, if >50% agree on a single vote, the `Eth1Data` is enshrined in `latest_eth1_data`.
* `deposit_index` -- running counter of the latest deposit processed. Deposits must be processed in order and blocks must contain deposits if `deposit_index < latest_eth1_data.deposit_count`, with a maximum of `MAX_DEPOSITS` per block.
## State Transition
* `state_transition`
* This is the top level function of the state transition. It accepts a pre-state and a beacon block, and outputs a post-state.
* `process_slots`
* The first component of the state transition function. This handles all of the operations that happen at each slot regardless of the block. If there are "skipped" slots in between the state transition input block and its parent, then multiple slots are transitioned during `process_slots` up to the block slot.
* Consensus forming clients must sometimes call this function to transition state through empty slots when attesting or producing blocks.
* `process_slot` is called for each slot.
* `process_epoch` is only called at epoch boundaries. Note that because `state.slot` has not yet been incremented, this occurs at the state transition at `slot` that is the start of `slot % SLOTS_PER_EPOCH == 0`
* `process_slot`
* Some general book-keeping for the previous slot performed at each slot. Note that the `state` has not yet been modified so still represents the post state of the previous slot. Also `state.slot` is still equal to the previous slot (`state.slot += 1` happens after `process_slot` from within `process_slots`).
* The post state root of the previous slot is inserted into state at the next slot to avoid a circular dependency.
* Cache state root
* The state root of the previous slot is cached in state. Note that `hash_tree_root(state) == root_of_previous_state` because the `state` has not yet been modified from the post state of the previous slot.
* Cache latest block header state root
* If the previous slot had a block (was not a skipped slot), then we insert the `previous_state_root` into the cached block header. This block header remains in state through any skipped slots until the next block occurs.
* Cache block root
* We cache the latest block into `latest_block_roots` at each slot. If the slot is skipped, then the block from the latest non-skipped slot is cached.
### Epoch Processing
Epoch processing occurs at the _start_ of the 0th slot (`slot % EPOCH_LENGTH == 0`) of each epoch. Note that `state.slot` is still equal to the previous slot when `process_epoch` is run, only incremented after.
`process_epoch` is the primary container function that calls the rest of the epoch processing sub-functions.
#### Justification and Finilization
* `process_justification_and_finilization`
* Justification is updated first by evaluating how many validators (as weighted by balance) voted for the previous epoch as the target for justification. If more than 2/3 of the active balance attests to the same epoch and that being the previous epoch, update the justification status of the previous epoch. Next, the current epoch is considered, if > 2/3 of the balance attests to that, the current epoch is justified.
* Only the 2nd, 3rd and 4th most recent epochs can be finalized. This is done by checking which epochs are used as the source for the most recent justifications and, most recent justified epoch (within the past 4) that is used as the source for a more recently justified epoch, is finalized. We only consider `k=1` and `k=2` finality rules discussed in [section 5.5 in the draft paper](https://www.overleaf.com/5374235669mhggmhksxpyj).
#### Crosslinks
* `process_crosslinks`
* For each shard, if at least 2/3 of the committee members attest to the the same crosslink, update the shard's most recent crosslink (from the perspective of the beacon chain) to be the winning crosslink. This is checked for both the previous and current epoch in case more attestations have come in for the previous epoch.
* Crosslinks must form a chain via `crosslink.parent_root`. The only crosslinks considered in `get_winning_crosslink_and_attesting_indices` are those that meet this chain criterion.
#### Rewards and Penalties
* `process_rewards_and_penalties`
* All of the rewards and penalties collected over the last epoch are applied to validator balances in this function. Rewards and penalties are collected from `get_crosslink_deltas` and `get_attestation_deltas` which return the rewards and penalties for each validator as tuples of lists. Rewards and penalties are separated to avoid signed integers.
* `get_base_reward`
* All rewards scale with $\frac{1}{\sqrt{TotalBalance}}$. See [the design rationale](https://notes.ethereum.org/s/rkhCgQteN#Base-rewards) for why.
* `get_attestation_deltas`
* Determines how much each validator's balance changes as a function of their attestation behaviour in the previous epoch.
* For each of the active validators:
* Reward for FFG Source, Target & Head - If a validator's source, target, or head attestations match the current source, target, or head of the previous epoch, issue rewards to those validators, else issue a penalty.
* Reward for how quickly attestations were included - Find the attestation that was included the soonest for each validator and give the proposer a small reward for including the attestation and the included validator a reward proportional to how quickly they were included.
* Penalise those are inactive - if finalization is not occuring, penalize everyone, but particularly those who are not participating. Note that if a validator is maximally participating during an inactivity leak, their balance remains unchanged.
* `get_crosslink_deltas`
* Every validator who attested to the winning crosslink (in their committee) recieves a reward and a penalty otherwise.
#### Registry updates
* `process_registry_updates`
* Validators whose balances are sufficient to be activated but have not yet been added to the queue, are added to the activation queue.
* Validators whose balances are too low are "ejected" by being added to the withdrawal queue.
* Validators that in the activation queue are activated within the churn limit.
#### Slashings
* `process_slashings`
* Validators that are slashed are done so in proportion to how many validators are slashed within a recent time period. This occurs occur independently of the order in which validators are slashed. `process_slashings` goes through the recent slashings and penalizes slashed validators proportionately.
#### Final updates
* `process_final_updates`
* This function handles sundry functionality that needs to occur with epoch-frequency, namely:
* Reset eth1 data votes if the start of a new voting period
* Recalculate effective balances (using hysteresis)
* Determine the new stard shard for the next epoch
* Make the active index root reflect the current active indicies
* Update total slashed balances
* Set the resulting randao mix from the current epoch as the base randao mix in the next epoch.
* (Potentially) append state to historical root.
### Block Processing
`process_block` is the main function that calls the sub-functions of block processing. If any asserts or exceptions are thrown in block processing, then the block is seen as invalid and should be discarded.
#### Block Header
`process_block_header` determines whether, at a high level, a block is valid. It does so by verifying that:
* The block is for the correct slot
* The parent block hash is correct
* The signature is that of the approriate block proposer and is valid
`process_block_header` also stores the block header in `state` for later uses in the state transition function.
#### RANDAO
`process_randao` verifies that the block's RANDAO reveal is the valid signature of the current epoch by the proposer and if so, mixes it into the epoch's mix.
#### Eth1 data
`process_eth1_data` adds the block's eth1-data to state's eth1-data-votes. If more than half of the votes in the voting period are for the same eth1-data, update `latest_eth1_data`.
#### Operations
`process_operations` makes sure that the appropriate number of slashings, attestations, depoists, exits and transfers occur as determined by the functions in the following sections. It does so by processing the `ProposerSlashing`, `AttesterSlashing`, `Attestation`, `Deposit`, `VoluntaryExit`, and `Transfer` objects as described above.