Update 0_beacon-chain.md

This commit is contained in:
Justin 2019-02-12 12:24:19 +00:00 committed by GitHub
parent 8445d06b8f
commit de7263c838
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 53 additions and 45 deletions

View File

@ -19,10 +19,10 @@
- [State list lengths](#state-list-lengths)
- [Reward and penalty quotients](#reward-and-penalty-quotients)
- [Status flags](#status-flags)
- [Max operations per block](#max-operations-per-block)
- [Max transactions per block](#max-transactions-per-block)
- [Signature domains](#signature-domains)
- [Data structures](#data-structures)
- [Beacon chain operations](#beacon-chain-operations)
- [Beacon chain transactions](#beacon-chain-transactions)
- [Proposer slashings](#proposer-slashings)
- [`ProposerSlashing`](#proposerslashing)
- [Attester slashings](#attester-slashings)
@ -36,8 +36,8 @@
- [`Deposit`](#deposit)
- [`DepositData`](#depositdata)
- [`DepositInput`](#depositinput)
- [Exits](#exits)
- [`Exit`](#exit)
- [Voluntary exits](#voluntary-exits)
- [`VoluntaryExit`](#voluntaryexit)
- [Beacon chain blocks](#beacon-chain-blocks)
- [`BeaconBlock`](#beaconblock)
- [`BeaconBlockBody`](#beaconblockbody)
@ -98,15 +98,15 @@
- [`activate_validator`](#activate_validator)
- [`initiate_validator_exit`](#initiate_validator_exit)
- [`exit_validator`](#exit_validator)
- [`penalize_validator`](#penalize_validator)
- [`slash_validator`](#slash_validator)
- [`prepare_validator_for_withdrawal`](#prepare_validator_for_withdrawal)
- [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract)
- [Deposit arguments](#deposit-arguments)
- [Withdrawal credentials](#withdrawal-credentials)
- [`Deposit` logs](#deposit-logs)
- [`Eth2Genesis` log](#chainstart-log)
- [`Eth2Genesis` log](#eth2genesis-log)
- [Vyper code](#vyper-code)
- [On startup](#on-startup)
- [On genesis](#on-genesis)
- [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)
@ -118,12 +118,12 @@
- [Proposer signature](#proposer-signature)
- [RANDAO](#randao)
- [Eth1 data](#eth1-data)
- [Operations](#operations)
- [Transactions](#transactions)
- [Proposer slashings](#proposer-slashings-1)
- [Attester slashings](#attester-slashings-1)
- [Attestations](#attestations-1)
- [Deposits](#deposits-1)
- [Exits](#exits-1)
- [Voluntary exits](#voluntary-exits-1)
- [Per-epoch processing](#per-epoch-processing)
- [Helper variables](#helper-variables)
- [Eth1 data](#eth1-data-1)
@ -247,7 +247,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
| - | - |
| `BASE_REWARD_QUOTIENT` | `2**5` (= 32) |
| `WHISTLEBLOWER_REWARD_QUOTIENT` | `2**9` (= 512) |
| `INCLUDER_REWARD_QUOTIENT` | `2**3` (= 8) |
| `ATTESTATION_INCLUSION_REWARD_QUOTIENT` | `2**3` (= 8) |
| `INACTIVITY_PENALTY_QUOTIENT` | `2**24` (= 16,777,216) |
* The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It corresponds to ~2.54% annual interest assuming 10 million participating ETH in every epoch.
@ -260,7 +260,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
| `INITIATED_EXIT` | `2**0` (= 1) |
| `WITHDRAWABLE` | `2**1` (= 2) |
### Max operations per block
### Max transactions per block
| Name | Value |
| - | - |
@ -268,7 +268,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
| `MAX_ATTESTER_SLASHINGS` | `2**0` (= 1) |
| `MAX_ATTESTATIONS` | `2**7` (= 128) |
| `MAX_DEPOSITS` | `2**4` (= 16) |
| `MAX_EXITS` | `2**4` (= 16) |
| `MAX_VOLUNTARY_EXITS` | `2**4` (= 16) |
### Signature domains
@ -284,7 +284,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
The following data structures are defined as [SimpleSerialize (SSZ)](https://github.com/ethereum/eth2.0-specs/blob/master/specs/simple-serialize.md) objects.
### Beacon chain operations
### Beacon chain transactions
#### Proposer slashings
@ -425,9 +425,9 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
}
```
#### Exits
#### Voluntary exits
##### `Exit`
##### `VoluntaryExit`
```python
{
@ -467,7 +467,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
'attester_slashings': [AttesterSlashing],
'attestations': [Attestation],
'deposits': [Deposit],
'exits': [Exit],
'voluntary_exits': [VoluntaryExit],
}
```
@ -621,7 +621,7 @@ We define the following Python custom types for type hinting and readability:
| `Slot` | `uint64` | a slot number |
| `Epoch` | `uint64` | an epoch number |
| `Shard` | `uint64` | a shard number |
| `ValidatorIndex` | `uint64` | an index in the validator registry |
| `ValidatorIndex` | `uint64` | a validator registry index |
| `Gwei` | `uint64` | an amount in Gwei |
| `Bytes32` | `bytes32` | 32 bytes of binary data |
| `BLSPubkey` | `bytes48` | a BLS12-381 public key |
@ -654,7 +654,7 @@ def slot_to_epoch(slot: Slot) -> Epoch:
### `get_previous_epoch`
```python
def get_previous_epoch(state: BeaconState) -> EpochNumber:
def get_previous_epoch(state: BeaconState) -> Epoch:
"""`
Return the previous epoch of the given ``state``.
If the current epoch is ``GENESIS_EPOCH``, return ``GENESIS_EPOCH``.
@ -1335,12 +1335,12 @@ def exit_validator(state: BeaconState, index: ValidatorIndex) -> None:
validator.exit_epoch = get_entry_exit_effect_epoch(get_current_epoch(state))
```
#### `penalize_validator`
#### `slash_validator`
```python
def penalize_validator(state: BeaconState, index: ValidatorIndex) -> None:
def slash_validator(state: BeaconState, index: ValidatorIndex) -> None:
"""
Penalize the validator of the given ``index``.
Slash the validator with index ``index``.
Note that this function mutates ``state``.
"""
exit_validator(state, index)
@ -1389,11 +1389,12 @@ Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSI
### `Eth2Genesis` log
When sufficiently many full deposits have been made the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_initial_beacon_state` function (defined below) where:
When sufficiently many full deposits have been made the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_genesis_beacon_state` function (defined below) where:
* `genesis_time` equals `time` in the `Eth2Genesis` log
* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log, and `latest_eth1_data.block_hash` equals the hash of the block that included the log
* `initial_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest)
* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log
* `latest_eth1_data.block_hash` equals the hash of the block that included the log
* `genesis_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest)
### Vyper code
@ -1407,7 +1408,7 @@ For convenience, we provide the interface to the contract here:
* `get_deposit_root() -> bytes32`: returns the current root of the deposit tree
* `deposit(bytes[512])`: adds a deposit instance to the deposit tree, incorporating the input argument and the value transferred in the given call. Note: the amount of value transferred *must* be within `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSIT_AMOUNT`, inclusive. Each of these constants are specified in units of Gwei.
## On startup
## On genesis
A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following values. Other validity rules (e.g. requiring a signature) do not apply.
@ -1415,7 +1416,7 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val
{
slot=GENESIS_SLOT,
parent_root=ZERO_HASH,
state_root=STARTUP_STATE_ROOT,
state_root=GENESIS_STATE_ROOT,
randao_reveal=EMPTY_SIGNATURE,
eth1_data=Eth1Data(
deposit_root=ZERO_HASH,
@ -1432,14 +1433,14 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val
}
```
`STARTUP_STATE_ROOT` (in the above "genesis block") is generated from the `get_initial_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `Eth2Genesis` log has been emitted, `get_initial_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`.
`GENESIS_STATE_ROOT` (in the above "genesis block") is generated from the `get_genesis_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `Eth2Genesis` log has been emitted, `get_genesis_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`.
```python
def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
genesis_time: int,
latest_eth1_data: Eth1Data) -> BeaconState:
"""
Get the initial ``BeaconState``.
Get the genesis ``BeaconState``.
"""
state = BeaconState(
# Misc
@ -1482,11 +1483,11 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
# Ethereum 1.0 chain data
latest_eth1_data=latest_eth1_data,
eth1_data_votes=[],
deposit_index=len(initial_validator_deposits)
deposit_index=len(genesis_validator_deposits)
)
# Process initial deposits
for deposit in initial_validator_deposits:
# Process genesis deposits
for deposit in genesis_validator_deposits:
process_deposit(
state=state,
pubkey=deposit.deposit_data.deposit_input.pubkey,
@ -1495,7 +1496,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials,
)
# Process initial activations
# Process genesis activations
for validator_index, _ in enumerate(state.validator_registry):
if get_effective_balance(state, validator_index) >= MAX_DEPOSIT_AMOUNT:
activate_validator(state, validator_index, is_genesis=True)
@ -1636,7 +1637,7 @@ Below are the processing steps that happen at every `block`.
* If there exists an `eth1_data_vote` in `states.eth1_data_votes` for which `eth1_data_vote.eth1_data == block.eth1_data` (there will be at most one), set `eth1_data_vote.vote_count += 1`.
* Otherwise, append to `state.eth1_data_votes` a new `Eth1DataVote(eth1_data=block.eth1_data, vote_count=1)`.
#### Operations
#### Transactions
##### Proposer slashings
@ -1651,7 +1652,7 @@ For each `proposer_slashing` in `block.body.proposer_slashings`:
* Verify that `proposer.slashed_epoch > get_current_epoch(state)`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=hash_tree_root(proposer_slashing.proposal_data_1), signature=proposer_slashing.proposal_signature_1, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_data_1.slot), DOMAIN_PROPOSAL))`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=hash_tree_root(proposer_slashing.proposal_data_2), signature=proposer_slashing.proposal_signature_2, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_data_2.slot), DOMAIN_PROPOSAL))`.
* Run `penalize_validator(state, proposer_slashing.proposer_index)`.
* Run `slash_validator(state, proposer_slashing.proposer_index)`.
##### Attester slashings
@ -1667,7 +1668,7 @@ For each `attester_slashing` in `block.body.attester_slashings`:
* Verify that `verify_slashable_attestation(state, slashable_attestation_2)`.
* Let `slashable_indices = [index for index in slashable_attestation_1.validator_indices if index in slashable_attestation_2.validator_indices and state.validator_registry[index].slashed_epoch > get_current_epoch(state)]`.
* Verify that `len(slashable_indices) >= 1`.
* Run `penalize_validator(state, index)` for each `index` in `slashable_indices`.
* Run `slash_validator(state, index)` for each `index` in `slashable_indices`.
##### Attestations
@ -1755,11 +1756,11 @@ process_deposit(
* Set `state.deposit_index += 1`.
##### Exits
##### Voluntary exits
Verify that `len(block.body.exits) <= MAX_EXITS`.
Verify that `len(block.body.voluntary_exits) <= MAX_VOLUNTARY_EXITS`.
For each `exit` in `block.body.exits`:
For each `exit` in `block.body.voluntary_exits`:
* Let `validator = state.validator_registry[exit.validator_index]`.
* Verify that `validator.exit_epoch > get_entry_exit_effect_epoch(get_current_epoch(state))`.
@ -1893,7 +1894,7 @@ Case 2: `epochs_since_finality > 4`:
##### Attestation inclusion
For each `index` in `previous_epoch_attester_indices`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(state, index))` and set `state.validator_balances[proposer_index] += base_reward(state, index) // INCLUDER_REWARD_QUOTIENT`.
For each `index` in `previous_epoch_attester_indices`, we determine the proposer `proposer_index = get_beacon_proposer_index(state, inclusion_slot(state, index))` and set `state.validator_balances[proposer_index] += base_reward(state, index) // ATTESTATION_INCLUSION_REWARD_QUOTIENT`.
##### Crosslinks
@ -1995,18 +1996,16 @@ If a validator registry update does _not_ happen do the following:
**Invariant**: the active index root that is hashed into the shuffling seed actually is the `hash_tree_root` of the validator set that is used for that epoch.
Regardless of whether or not a validator set change happens, run the following:
Regardless of whether or not a validator set change happens run `process_slashings(state)` and `process_withdrawals(state):
```python
def process_penalties_and_exits(state: BeaconState) -> None:
def process_slashings(state: BeaconState) -> None:
"""
Process the penalties and prepare the validators who are eligible to withdrawal.
Process the slashings.
Note that this function mutates ``state``.
"""
current_epoch = get_current_epoch(state)
# The active validators
active_validator_indices = get_active_validator_indices(state.validator_registry, current_epoch)
# The total effective balance of active validators
total_balance = sum(get_effective_balance(state, i) for i in active_validator_indices)
for index, validator in enumerate(state.validator_registry):
@ -2017,6 +2016,15 @@ def process_penalties_and_exits(state: BeaconState) -> None:
total_penalties = total_at_end - total_at_start
penalty = get_effective_balance(state, index) * min(total_penalties * 3, total_balance) // total_balance
state.validator_balances[index] -= penalty
```
```python
def process_withdrawals(state: BeaconState) -> None:
"""
Process the withdrawals.
Note that this function mutates ``state``.
"""
current_epoch = get_current_epoch(state)
def eligible(index):
validator = state.validator_registry[index]