Skip to content

Commit 1845088

Browse files
authored
Merge pull request #982 from ethereum/JustinDrake-patch-20
Split off fork choice rule and deposit contract
2 parents 06965f2 + f7f8ecb commit 1845088

File tree

5 files changed

+193
-136
lines changed

5 files changed

+193
-136
lines changed

README.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,22 @@ This repo hosts the current eth2.0 specifications. Discussions about design rati
1010
## Specs
1111

1212
Core specifications for eth2.0 client validation can be found in [specs/core](specs/core). These are divided into phases. Each subsequent phase depends upon the prior. The current phases specified are:
13-
* [Phase 0 -- The Beacon Chain](specs/core/0_beacon-chain.md)
14-
* [Phase 1 -- Custody Game](specs/core/1_custody-game.md)
15-
* [Phase 1 -- Shard Data Chains](specs/core/1_shard-data-chains.md)
1613

17-
Accompanying documents can be found in [specs](specs) and include:
14+
### Phase 0
15+
* [The Beacon Chain](specs/core/0_beacon-chain.md)
16+
* [Fork Choice](specs/core/0_fork-choice.md)
17+
* [Deposit Contract](specs/core/0_deposit-contract.md)
18+
* [Honest validator implementation doc](specs/validator/0_beacon-chain-validator.md)
19+
20+
### Phase 1
21+
* [Custody Game](specs/core/1_custody-game.md)
22+
* [Shard Data Chains](specs/core/1_shard-data-chains.md)
23+
24+
### Accompanying documents can be found in [specs](specs) and include:
25+
1826
* [SimpleSerialize (SSZ) spec](specs/simple-serialize.md)
1927
* [BLS signature verification](specs/bls_signature.md)
2028
* [General test format](specs/test_formats/README.md)
21-
* [Honest validator implementation doc](specs/validator/0_beacon-chain-validator.md)
2229
* [Merkle proof formats](specs/light_client/merkle_proofs.md)
2330
* [Light client syncing protocol](specs/light_client/sync_protocol.md)
2431

specs/core/0_beacon-chain.md

Lines changed: 1 addition & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Ethereum 2.0 Phase 0 -- The Beacon Chain
22

3-
**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 [[python-poc]](https://github.com/ethereum/beacon_chain).
3+
**NOTICE**: This document is a work in progress for researchers and implementers.
44

55
## Table of contents
66
<!-- TOC -->
@@ -94,15 +94,7 @@
9494
- [Routines for updating validator status](#routines-for-updating-validator-status)
9595
- [`initiate_validator_exit`](#initiate_validator_exit)
9696
- [`slash_validator`](#slash_validator)
97-
- [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract)
98-
- [Deposit arguments](#deposit-arguments)
99-
- [Withdrawal credentials](#withdrawal-credentials)
100-
- [`Deposit` logs](#deposit-logs)
101-
- [`Eth2Genesis` log](#eth2genesis-log)
102-
- [Vyper code](#vyper-code)
10397
- [On genesis](#on-genesis)
104-
- [Beacon chain processing](#beacon-chain-processing)
105-
- [Beacon chain fork choice rule](#beacon-chain-fork-choice-rule)
10698
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
10799
- [State caching](#state-caching)
108100
- [Per-epoch processing](#per-epoch-processing)
@@ -182,7 +174,6 @@ These configurations are updated for releases, but may be out of sync during `de
182174

183175
| Name | Value |
184176
| - | - |
185-
| `DEPOSIT_CONTRACT_ADDRESS` | **TBD** |
186177
| `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) |
187178

188179
### Gwei values
@@ -208,7 +199,6 @@ These configurations are updated for releases, but may be out of sync during `de
208199

209200
| Name | Value | Unit | Duration |
210201
| - | - | :-: | :-: |
211-
| `SECONDS_PER_SLOT` | `6` | seconds | 6 seconds |
212202
| `MIN_ATTESTATION_INCLUSION_DELAY` | `2**2` (= 4) | slots | 24 seconds |
213203
| `SLOTS_PER_EPOCH` | `2**6` (= 64) | slots | 6.4 minutes |
214204
| `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes |
@@ -1233,49 +1223,6 @@ def slash_validator(state: BeaconState, slashed_index: ValidatorIndex, whistlebl
12331223
decrease_balance(state, slashed_index, whistleblowing_reward)
12341224
```
12351225

1236-
## Ethereum 1.0 deposit contract
1237-
1238-
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.
1239-
1240-
### Deposit arguments
1241-
1242-
The deposit contract has a single `deposit` function which takes as argument the `DepositData` elements.
1243-
1244-
### Withdrawal credentials
1245-
1246-
One of the `DepositData` 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:
1247-
1248-
* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE`
1249-
* `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey
1250-
1251-
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.
1252-
1253-
### `Deposit` logs
1254-
1255-
Every Ethereum 1.0 deposit, of size at least `MIN_DEPOSIT_AMOUNT`, emits a `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.
1256-
1257-
### `Eth2Genesis` log
1258-
1259-
When a sufficient amount of 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:
1260-
1261-
* `genesis_time` equals `time` in the `Eth2Genesis` log
1262-
* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log
1263-
* `latest_eth1_data.deposit_count` equals `deposit_count` in the `Eth2Genesis` log
1264-
* `latest_eth1_data.block_hash` equals the hash of the block that included the log
1265-
* `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)
1266-
1267-
### Vyper code
1268-
1269-
The source for the Vyper contract lives in a [separate repository](https://github.com/ethereum/deposit_contract) at [https://github.com/ethereum/deposit_contract/blob/master/deposit_contract/contracts/validator_registration.v.py](https://github.com/ethereum/deposit_contract/blob/master/deposit_contract/contracts/validator_registration.v.py).
1270-
1271-
Note: to save ~10x on gas this contract uses a somewhat unintuitive progressive Merkle root calculation algo that requires only O(log(n)) storage. See https://github.com/ethereum/research/blob/master/beacon_chain_impl/progressive_merkle_tree.py for an implementation of the same algo in python tested for correctness.
1272-
1273-
For convenience, we provide the interface to the contract here:
1274-
1275-
* `__init__()`: initializes the contract
1276-
* `get_deposit_root() -> bytes32`: returns the current root of the deposit tree
1277-
* `deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])`: adds a deposit instance to the deposit tree, incorporating the input arguments and the value transferred in the given call. Note: the amount of value transferred *must* be at least `MIN_DEPOSIT_AMOUNT`. Each of these constants are specified in units of Gwei.
1278-
12791226
## On genesis
12801227

12811228
When enough full deposits have been made to the deposit contract, an `Eth2Genesis` log is emitted. Construct a corresponding `genesis_state` and `genesis_block` as follows:
@@ -1315,80 +1262,6 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
13151262
return state
13161263
```
13171264

1318-
## Beacon chain processing
1319-
1320-
The beacon chain is the system chain for Ethereum 2.0. The main responsibilities of the beacon chain are as follows:
1321-
1322-
* Store and maintain the registry of [validators](#dfn-validator)
1323-
* Process crosslinks (see above)
1324-
* Process its per-block consensus, as well as the finality gadget
1325-
1326-
Processing the beacon chain is similar to processing the Ethereum 1.0 chain. Clients download and process blocks and maintain a view of what is the current "canonical chain", terminating at the current "head". However, because of the beacon chain's relationship with Ethereum 1.0, and because it is a proof-of-stake chain, there are differences.
1327-
1328-
For a beacon chain block, `block`, to be processed by a node, the following conditions must be met:
1329-
1330-
* The parent block with root `block.previous_block_root` has been processed and accepted.
1331-
* An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` has been processed and accepted.
1332-
* The node's Unix time is greater than or equal to `state.genesis_time + block.slot * SECONDS_PER_SLOT`. (Note that leap seconds mean that slots will occasionally last `SECONDS_PER_SLOT + 1` or `SECONDS_PER_SLOT - 1` seconds, possibly several times a year.)
1333-
1334-
If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied.
1335-
1336-
Beacon block production is significantly different because of the proof-of-stake mechanism. A client simply checks what it thinks is the canonical chain when it should create a block and looks up what its slot number is; when the slot arrives, it either proposes or attests to a block as required. Note that this requires each node to have a clock that is roughly (i.e. within `SECONDS_PER_SLOT` seconds) synchronized with the other nodes.
1337-
1338-
### Beacon chain fork choice rule
1339-
1340-
The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a [validator](#dfn-validator) `v` subjectively calculates the beacon chain head as follows.
1341-
1342-
* Abstractly define `Store` as the type of storage object for the chain data and `store` be the set of attestations and blocks that the [validator](#dfn-validator) `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not yet included in any chain are still included in `store`.
1343-
* Let `finalized_head` be the finalized block with the highest epoch. (A block `B` is finalized if there is a descendant of `B` in `store` the processing of which sets `B` as finalized.)
1344-
* Let `justified_head` be the descendant of `finalized_head` with the highest epoch that has been justified for at least 1 epoch. (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`.
1345-
* Let `get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as:
1346-
1347-
```python
1348-
def get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock:
1349-
"""
1350-
Get the ancestor of ``block`` with slot number ``slot``; return ``None`` if not found.
1351-
"""
1352-
if block.slot == slot:
1353-
return block
1354-
elif block.slot < slot:
1355-
return None
1356-
else:
1357-
return get_ancestor(store, store.get_parent(block), slot)
1358-
```
1359-
1360-
* Let `get_latest_attestation(store: Store, index: ValidatorIndex) -> Attestation` be the attestation with the highest slot number in `store` from the validator with the given `index`. If several such attestations exist, use the one the [validator](#dfn-validator) `v` observed first.
1361-
* Let `get_latest_attestation_target(store: Store, index: ValidatorIndex) -> BeaconBlock` be the target block in the attestation `get_latest_attestation(store, index)`.
1362-
* Let `get_children(store: Store, block: BeaconBlock) -> List[BeaconBlock]` returns the child blocks of the given `block`.
1363-
* Let `justified_head_state` be the resulting `BeaconState` object from processing the chain up to the `justified_head`.
1364-
* The `head` is `lmd_ghost(store, justified_head_state, 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.
1365-
1366-
```python
1367-
def lmd_ghost(store: Store, start_state: BeaconState, start_block: BeaconBlock) -> BeaconBlock:
1368-
"""
1369-
Execute the LMD-GHOST algorithm to find the head ``BeaconBlock``.
1370-
"""
1371-
validators = start_state.validator_registry
1372-
active_validator_indices = get_active_validator_indices(validators, slot_to_epoch(start_state.slot))
1373-
attestation_targets = [(i, get_latest_attestation_target(store, i)) for i in active_validator_indices]
1374-
1375-
# Use the effective balance for fork choice voting to reduce recomputations and save bandwidth
1376-
def get_vote_count(block: BeaconBlock) -> int:
1377-
return sum(
1378-
start_state.validator_registry[validator_index].effective_balance
1379-
for validator_index, target in attestation_targets
1380-
if get_ancestor(store, target, block.slot) == block
1381-
)
1382-
1383-
head = start_block
1384-
while 1:
1385-
children = get_children(store, head)
1386-
if len(children) == 0:
1387-
return head
1388-
# Ties broken by favoring block with lexicographically higher root
1389-
head = max(children, key=lambda x: (get_vote_count(x), hash_tree_root(x)))
1390-
```
1391-
13921265
## Beacon chain state transition function
13931266

13941267
We now define the state transition function. At a high level, the state transition is made up of four parts:

specs/core/0_deposit-contract.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Ethereum 2.0 Phase 0 -- Deposit Contract
2+
3+
**NOTICE**: This document is a work in progress for researchers and implementers.
4+
5+
## Table of contents
6+
<!-- TOC -->
7+
8+
- [Ethereum 2.0 Phase 0 -- Deposit Contract](#ethereum-20-phase-0----deposit-contract)
9+
- [Table of contents](#table-of-contents)
10+
- [Introduction](#introduction)
11+
- [Constants](#constants)
12+
- [Deposit contract](#time-parameters)
13+
- [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract)
14+
- [Deposit arguments](#deposit-arguments)
15+
- [Withdrawal credentials](#withdrawal-credentials)
16+
- [`Deposit` logs](#deposit-logs)
17+
- [`Eth2Genesis` log](#eth2genesis-log)
18+
- [Vyper code](#vyper-code)
19+
20+
<!-- /TOC -->
21+
22+
## Introduction
23+
24+
This document represents is the specification for the beacon chain deposit contract, part of Ethereum 2.0 phase 0.
25+
26+
## Constants
27+
28+
### Deposit contract
29+
30+
| Name | Value |
31+
| - | - |
32+
| `DEPOSIT_CONTRACT_ADDRESS` | **TBD** |
33+
| `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) |
34+
35+
## Ethereum 1.0 deposit contract
36+
37+
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.
38+
39+
### Deposit arguments
40+
41+
The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositData`.
42+
43+
### Withdrawal credentials
44+
45+
One of the `DepositData` 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:
46+
47+
* `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE`
48+
* `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey
49+
50+
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.
51+
52+
### `Deposit` logs
53+
54+
Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSIT_AMOUNT`, emits a `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 signature) is not verified by the deposit contract.
55+
56+
### `Eth2Genesis` log
57+
58+
When a sufficient amount of 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:
59+
60+
* `genesis_time` equals `time` in the `Eth2Genesis` log
61+
* `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log
62+
* `latest_eth1_data.deposit_count` equals `deposit_count` in the `Eth2Genesis` log
63+
* `latest_eth1_data.block_hash` equals the hash of the block that included the log
64+
* `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)
65+
66+
### Vyper code
67+
68+
The source for the Vyper contract lives in a [separate repository](https://github.com/ethereum/deposit_contract) at [https://github.com/ethereum/deposit_contract/blob/master/deposit_contract/contracts/validator_registration.v.py](https://github.com/ethereum/deposit_contract/blob/master/deposit_contract/contracts/validator_registration.v.py).
69+
70+
Note: to save ~10x on gas this contract uses a somewhat unintuitive progressive Merkle root calculation algo that requires only O(log(n)) storage. See https://github.com/ethereum/research/blob/master/beacon_chain_impl/progressive_merkle_tree.py for an implementation of the same algo in python tested for correctness.
71+
72+
For convenience, we provide the interface to the contract here:
73+
74+
* `__init__()`: initializes the contract
75+
* `get_deposit_root() -> bytes32`: returns the current root of the deposit tree
76+
* `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.

0 commit comments

Comments
 (0)