Update 0_beacon-chain.md
* `processed_deposit_root` => `latest_deposit_root` * `receipt_root` => `deposit_root` * `receipt_tree` => `deposit_tree` * Emphasize that deposits are Ethereum 1.0 deposits in text in various places * `Eth1Deposit` => `Deposit` for consistency (Also happy sticking with `Eth1Deposit` and replacing `deposit_` with `eth1_deposit_` everywhere. This may be unnecessary since Ethereum 2.0 deposits can be distinguished with the `shard_` prefix, e.g. `ShardDeposit` and `shard_deposit`.) * Clarify `withdrawal_credentials`. * Clarify that multiple Ethereum 1.0 blocks can have the same deposit root.
This commit is contained in:
parent
3dbee05aa6
commit
9a90803f5c
|
@ -53,7 +53,8 @@
|
|||
- [`ValidatorRegistryDeltaBlock`](#validatorregistrydeltablock)
|
||||
- [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract)
|
||||
- [Deposit arguments](#deposit-arguments)
|
||||
- [`Eth1Deposit` logs](#eth1deposit-logs)
|
||||
- [Withdrawal credentials](#withdrawal-credentials)
|
||||
- [`Deposit` logs](#Deposit-logs)
|
||||
- [`ChainStart` log](#chainstart-log)
|
||||
- [Vyper code](#vyper-code)
|
||||
- [Beacon chain processing](#beacon-chain-processing)
|
||||
|
@ -126,7 +127,7 @@
|
|||
|
||||
This document represents the specification for Phase 0 of Ethereum 2.0 -- The Beacon Chain.
|
||||
|
||||
At the core of Ethereum 2.0 is a system chain called the "beacon chain". The beacon chain stores and manages the registry of [validators](#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 deposit transaction receipts are processed by the beacon chain, the activation balance is reached, and after a queuing process. 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](#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 after a queuing process. 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 availability votes for a shard block, and simultaneously proof of stake votes for a 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.
|
||||
|
||||
|
@ -368,7 +369,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
|
||||
```python
|
||||
{
|
||||
# Deposit parameters
|
||||
# Deposit input
|
||||
'deposit_input': DepositInput,
|
||||
# Value in Gwei
|
||||
'value': 'uint64',
|
||||
|
@ -389,7 +390,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
'randao_commitment': 'hash32',
|
||||
# Initial proof of custody commitment
|
||||
'poc_commitment': 'hash32',
|
||||
# a BLS signature of this ``DepositInput``
|
||||
# A BLS signature of this `DepositInput`
|
||||
'proof_of_possession': ['uint384'],
|
||||
}
|
||||
```
|
||||
|
@ -499,8 +500,8 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
'latest_attestations': [PendingAttestationRecord],
|
||||
'batched_block_roots': ['hash32'],
|
||||
|
||||
# Deposit root
|
||||
'processed_deposit_root': 'hash32',
|
||||
# Ethereum 1.0 deposit root
|
||||
'latest_deposit_root': 'hash32',
|
||||
'deposit_root_votes': [DepositRootVote],
|
||||
}
|
||||
```
|
||||
|
@ -620,28 +621,32 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
|||
|
||||
## Ethereum 1.0 deposit contract
|
||||
|
||||
The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to Ethereum 1.0. A deposit contract at address `DEPOSIT_CONTRACT_ADDRESS` is added to Ethereum 1.0 for deposits of ETH to the beacon chain. Validator balances will be withdrawable to the shards when the EVM2.0 is deployed and the shards have state.
|
||||
The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to Ethereum 1.0. A deposit contract at address `DEPOSIT_CONTRACT_ADDRESS` is added to Ethereum 1.0 for deposits of ETH to the beacon chain. Validator balances will be withdrawable to the shards in phase 2, i.e. when the EVM2.0 is deployed and the shards have state.
|
||||
|
||||
### Deposit arguments
|
||||
|
||||
The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositInput`. One of the `DepositInput` fields is `withdrawal_credentials` which must satisfy:
|
||||
The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositInput`.
|
||||
|
||||
### Withdrawal credentials
|
||||
|
||||
One of the `DepositInput` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawals to shards. The first byte of `withdrawal_credentials` is a version number. As of now the only expected format is as follows:
|
||||
|
||||
* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE`
|
||||
* `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey
|
||||
|
||||
We recommend the private key corresponding to `withdrawal_pubkey` be stored in cold storage until a withdrawal is required.
|
||||
The private key corresponding to `withdrawal_pubkey` will be required to initiate a withdrawal. It can be stored separately until a withdrawal is required, e.g. in cold storage.
|
||||
|
||||
### `Eth1Deposit` logs
|
||||
### `Deposit` logs
|
||||
|
||||
Every deposit, of size between `MIN_DEPOSIT` and `MAX_DEPOSIT`, emits an `Eth1Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract.
|
||||
Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT` and `MAX_DEPOSIT`, emits an `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract.
|
||||
|
||||
### `ChainStart` log
|
||||
|
||||
When sufficiently many full deposits have been made the deposit contract emits the `ChainStart` log. The beacon chain state may then be initialized by calling the `get_initial_beacon_state` function (defined below) where:
|
||||
|
||||
* `genesis_time` equals `time` in the `ChainStart` log
|
||||
* `processed_deposit_root` equals `receipt_root` in the `ChainStart` log
|
||||
* `initial_validator_deposits` is a list of `Deposit` objects built according to the `Eth1Deposit` logs up to the deposit that triggered the `ChainStart` log, processed in the order in which they were emitted (oldest to newest)
|
||||
* `latest_deposit_root` equals `deposit_root` in the `ChainStart` log
|
||||
* `initial_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `ChainStart` log, processed in the order in which they were emitted (oldest to newest)
|
||||
|
||||
### Vyper code
|
||||
|
||||
|
@ -656,10 +661,10 @@ DEPOSIT_CONTRACT_TREE_DEPTH: constant(uint256) = 32
|
|||
TWO_TO_POWER_OF_TREE_DEPTH: constant(uint256) = 4294967296 # 2**32
|
||||
SECONDS_PER_DAY: constant(uint256) = 86400
|
||||
|
||||
Eth1Deposit: event({previous_receipt_root: bytes32, data: bytes[2064], deposit_count: uint256})
|
||||
ChainStart: event({receipt_root: bytes32, time: bytes[8]})
|
||||
Deposit: event({previous_deposit_root: bytes32, data: bytes[2064], deposit_count: uint256})
|
||||
ChainStart: event({deposit_root: bytes32, time: bytes[8]})
|
||||
|
||||
receipt_tree: map(uint256, bytes32)
|
||||
deposit_tree: map(uint256, bytes32)
|
||||
deposit_count: uint256
|
||||
full_deposit_count: uint256
|
||||
|
||||
|
@ -674,13 +679,13 @@ def deposit(deposit_input: bytes[2048]):
|
|||
timestamp_bytes8: bytes[8] = slice(concat("", convert(block.timestamp, bytes32)), start=24, len=8)
|
||||
deposit_data: bytes[2064] = concat(msg_gwei_bytes8, timestamp_bytes8, deposit_input)
|
||||
|
||||
log.Eth1Deposit(self.receipt_tree[1], deposit_data, self.deposit_count)
|
||||
log.Deposit(self.deposit_tree[1], deposit_data, self.deposit_count)
|
||||
|
||||
# add deposit to merkle tree
|
||||
self.receipt_tree[index] = sha3(deposit_data)
|
||||
self.deposit_tree[index] = sha3(deposit_data)
|
||||
for i in range(32): # DEPOSIT_CONTRACT_TREE_DEPTH (range of constant var not yet supported)
|
||||
index /= 2
|
||||
self.receipt_tree[index] = sha3(concat(self.receipt_tree[index * 2], self.receipt_tree[index * 2 + 1]))
|
||||
self.deposit_tree[index] = sha3(concat(self.deposit_tree[index * 2], self.deposit_tree[index * 2 + 1]))
|
||||
|
||||
self.deposit_count += 1
|
||||
if msg.value == as_wei_value(MAX_DEPOSIT, "ether"):
|
||||
|
@ -688,12 +693,12 @@ def deposit(deposit_input: bytes[2048]):
|
|||
if self.full_deposit_count == CHAIN_START_FULL_DEPOSIT_THRESHOLD:
|
||||
timestamp_day_boundary: uint256 = as_unitless_number(block.timestamp) - as_unitless_number(block.timestamp) % SECONDS_PER_DAY + SECONDS_PER_DAY
|
||||
timestamp_day_boundary_bytes8: bytes[8] = slice(concat("", convert(timestamp_day_boundary, bytes32)), start=24, len=8)
|
||||
log.ChainStart(self.receipt_tree[1], timestamp_day_boundary_bytes8)
|
||||
log.ChainStart(self.deposit_tree[1], timestamp_day_boundary_bytes8)
|
||||
|
||||
@public
|
||||
@constant
|
||||
def get_receipt_root() -> bytes32:
|
||||
return self.receipt_tree[1]
|
||||
def get_deposit_root() -> bytes32:
|
||||
return self.deposit_tree[1]
|
||||
|
||||
```
|
||||
|
||||
|
@ -711,7 +716,7 @@ For a beacon chain block, `block`, to be processed by a node, the following cond
|
|||
|
||||
* The parent block with root `block.parent_root` has been processed and accepted.
|
||||
* The node has processed its `state` up to slot, `block.slot - 1`.
|
||||
* The Ethereum 1.0 block pointed to by the `state.processed_deposit_root` has been processed and accepted.
|
||||
* A Ethereum 1.0 block pointed to by the `state.latest_deposit_root` has been processed and accepted.
|
||||
* The node's local clock time is greater than or equal to `state.genesis_time + block.slot * SLOT_DURATION`.
|
||||
|
||||
If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied.
|
||||
|
@ -1161,7 +1166,7 @@ A valid block with slot `INITIAL_SLOT_NUMBER` (a "genesis block") has the follow
|
|||
```python
|
||||
def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
|
||||
genesis_time: int,
|
||||
processed_deposit_root: Hash32) -> BeaconState:
|
||||
latest_deposit_root: Hash32) -> BeaconState:
|
||||
state = BeaconState(
|
||||
# Misc
|
||||
slot=INITIAL_SLOT_NUMBER,
|
||||
|
@ -1201,7 +1206,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
|
|||
batched_block_roots=[],
|
||||
|
||||
# Deposit root
|
||||
processed_deposit_root=processed_deposit_root,
|
||||
latest_deposit_root=latest_deposit_root,
|
||||
deposit_root_votes=[],
|
||||
)
|
||||
|
||||
|
@ -1527,7 +1532,7 @@ Verify that `len(block.body.deposits) <= MAX_DEPOSITS`.
|
|||
For each `deposit` in `block.body.deposits`:
|
||||
|
||||
* Let `serialized_deposit_data` be the serialized form of `deposit.deposit_data`. It should be the `DepositInput` followed by 8 bytes for `deposit_data.value` and 8 bytes for `deposit_data.timestamp`. That is, it should match `deposit_data` in the [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) of which the hash was placed into the Merkle tree.
|
||||
* Use the following procedure to verify `deposit.merkle_branch`, setting `leaf=serialized_deposit_data`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH` and `root=state.processed_deposit_root`:
|
||||
* Use the following procedure to verify `deposit.merkle_branch`, setting `leaf=serialized_deposit_data`, `depth=DEPOSIT_CONTRACT_TREE_DEPTH` and `root=state.latest_deposit_root`:
|
||||
|
||||
```python
|
||||
def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool:
|
||||
|
@ -1624,7 +1629,7 @@ For every `shard_committee` in `state.shard_committees_at_slots`:
|
|||
|
||||
If `state.slot % DEPOSIT_ROOT_VOTING_PERIOD == 0`:
|
||||
|
||||
* Set `state.processed_deposit_root = deposit_root_vote.receipt_root` if `deposit_root_vote.vote_count * 2 > DEPOSIT_ROOT_VOTING_PERIOD` for some `deposit_root_vote` in `state.deposit_root_votes`.
|
||||
* Set `state.latest_deposit_root = deposit_root_vote.deposit_root` if `deposit_root_vote.vote_count * 2 > DEPOSIT_ROOT_VOTING_PERIOD` for some `deposit_root_vote` in `state.deposit_root_votes`.
|
||||
* Set `state.deposit_root_votes = []`.
|
||||
|
||||
### Justification
|
||||
|
|
Loading…
Reference in New Issue