From 7686702c29799364e0b4fc15a032bb4287322e13 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Thu, 17 Jan 2019 05:43:47 -0600 Subject: [PATCH] Vote for block hash along with deposit root (#448) --- specs/core/0_beacon-chain.md | 93 +++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 76474a1da..0ba9b5bcc 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -45,10 +45,11 @@ - [`BeaconState`](#beaconstate) - [`Validator`](#validator) - [`Crosslink`](#crosslink) - - [`DepositRootVote`](#depositrootvote) - [`PendingAttestation`](#pendingattestation) - [`Fork`](#fork) - [`ValidatorRegistryDeltaBlock`](#validatorregistrydeltablock) + - [`Eth1Data`](#eth1data) + - [`Eth1DataVote`](#eth1datavote) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - [Deposit arguments](#deposit-arguments) - [Withdrawal credentials](#withdrawal-credentials) @@ -96,7 +97,7 @@ - [Slot](#slot) - [Proposer signature](#proposer-signature) - [RANDAO](#randao) - - [Deposit root](#deposit-root) + - [Eth1 data](#eth1-data) - [Operations](#operations) - [Proposer slashings](#proposer-slashings-1) - [Casper slashings](#casper-slashings-1) @@ -106,7 +107,7 @@ - [Custody](#custody) - [Per-epoch processing](#per-epoch-processing) - [Helpers](#helpers) - - [Deposit roots](#deposit-roots) + - [Eth1 data](#eth1-data-1) - [Justification](#justification) - [Crosslinks](#crosslinks) - [Rewards and penalties](#rewards-and-penalties) @@ -202,7 +203,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `EPOCH_LENGTH` | `2**6` (= 64) | slots | 6.4 minutes | | `SEED_LOOKAHEAD` | `2**6` (= 64) | slots | 6.4 minutes | | `ENTRY_EXIT_DELAY` | `2**8` (= 256) | slots | 25.6 minutes | -| `DEPOSIT_ROOT_VOTING_PERIOD` | `2**10` (= 1,024) | slots | ~1.7 hours | +| `ETH1_DATA_VOTING_PERIOD` | `2**10` (= 1,024) | slots | ~1.7 hours | | `MIN_VALIDATOR_WITHDRAWAL_TIME` | `2**14` (= 16,384) | slots | ~27 hours | ### Reward and penalty quotients @@ -423,7 +424,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted 'parent_root': 'hash32', 'state_root': 'hash32', 'randao_reveal': 'hash32', - 'deposit_root': 'hash32', + 'eth1_data': Eth1Data, 'signature': ['uint384'], ## Body ## @@ -505,9 +506,9 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted 'latest_attestations': [PendingAttestation], 'batched_block_roots': ['hash32'], - # Ethereum 1.0 deposit root - 'latest_deposit_root': 'hash32', - 'deposit_root_votes': [DepositRootVote], + # Ethereum 1.0 chain data + 'latest_eth1_data': Eth1Data, + 'eth1_data_votes': [Eth1DataVote], } ``` @@ -555,17 +556,6 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted } ``` -#### `DepositRootVote` - -```python -{ - # Deposit root - 'deposit_root': 'hash32', - # Vote count - 'vote_count': 'uint64', -} -``` - #### `PendingAttestation` ```python @@ -598,11 +588,33 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted ```python { - latest_registry_delta_root: 'hash32', - validator_index: 'uint24', - pubkey: 'uint384', - slot: 'uint64', - flag: 'uint64', + 'latest_registry_delta_root': 'hash32', + 'validator_index': 'uint24', + 'pubkey': 'uint384', + 'slot': 'uint64', + 'flag': 'uint64', +} +``` + +#### `Eth1Data` + +```python +{ + # Root of the deposit tree + 'deposit_root': 'hash32', + # Block hash + 'block_hash': 'hash32', +} +``` + +#### `Eth1DataVote` + +```python +{ + # Data being voted for + 'eth1_data': Eth1Data, + # Vote count + 'vote_count': 'uint64', } ``` @@ -632,7 +644,7 @@ Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSI 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 -* `latest_deposit_root` equals `deposit_root` in the `ChainStart` log +* `latest_eth1_data.deposit_root` equals `deposit_root` in the `ChainStart` 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 `ChainStart` log, processed in the order in which they were emitted (oldest to newest) ### Vyper code @@ -713,7 +725,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`. -* An Ethereum 1.0 block pointed to by the `state.latest_deposit_root` has been processed and accepted. +* An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` 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. @@ -1183,7 +1195,10 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val parent_root=ZERO_HASH, state_root=STARTUP_STATE_ROOT, randao_reveal=ZERO_HASH, - deposit_root=ZERO_HASH, + eth1_data=Eth1Data( + deposit_root=ZERO_HASH, + block_hash=ZERO_HASH + ), signature=EMPTY_SIGNATURE, body=BeaconBlockBody( proposer_slashings=[], @@ -1203,7 +1218,7 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val ```python def get_initial_beacon_state(initial_validator_deposits: List[Deposit], genesis_time: int, - latest_deposit_root: Hash32) -> BeaconState: + latest_eth1_data: Eth1Data) -> BeaconState: state = BeaconState( # Misc slot=GENESIS_SLOT, @@ -1247,9 +1262,9 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], latest_attestations=[], batched_block_roots=[], - # Deposit root - latest_deposit_root=latest_deposit_root, - deposit_root_votes=[], + # Ethereum 1.0 chain data + latest_eth1_data=latest_eth1_data, + eth1_data_votes=[], ) # Process initial deposits @@ -1466,10 +1481,10 @@ Below are the processing steps that happen at every `block`. * Set `proposer.randao_commitment = block.randao_reveal`. * Set `proposer.randao_layers = 0`. -### Deposit root +### Eth1 data -* If `block.deposit_root` is `deposit_root_vote.deposit_root` for some `deposit_root_vote` in `state.deposit_root_votes`, set `deposit_root_vote.vote_count += 1`. -* Otherwise, append to `state.deposit_root_votes` a new `DepositRootVote(deposit_root=block.deposit_root, vote_count=1)`. +* If `block.eth1_data` equals `eth1_data_vote.eth1_data` for some `eth1_data_vote` in `state.eth1_data_votes`, 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 @@ -1533,7 +1548,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 8 bytes for `deposit_data.amount` followed by 8 bytes for `deposit_data.timestamp` and then the `DepositInput` bytes. 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. -* Verify that `verify_merkle_branch(hash(serialized_deposit_data), deposit.branch, DEPOSIT_CONTRACT_TREE_DEPTH, deposit.index, state.latest_deposit_root)` is `True`. +* Verify that `verify_merkle_branch(hash(serialized_deposit_data), deposit.branch, DEPOSIT_CONTRACT_TREE_DEPTH, deposit.index, state.latest_eth1_data.deposit_root)` is `True`. ```python def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool: @@ -1629,12 +1644,12 @@ Define the following helpers to process attestation inclusion rewards and inclus * Let `inclusion_slot(state, index) = a.slot_included` for the attestation `a` where `index` is in `get_attestation_participants(state, a.data, a.aggregation_bitfield)`. * Let `inclusion_distance(state, index) = a.slot_included - a.data.slot` where `a` is the above attestation. -### Deposit roots +### Eth1 data -If `state.slot % DEPOSIT_ROOT_VOTING_PERIOD == 0`: +If `state.slot % ETH1_DATA_VOTING_PERIOD == 0`: -* 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 = []`. +* Set `state.latest_eth1_data = eth1_data_vote.data` if `eth1_data_vote.vote_count * 2 > ETH1_DATA_VOTING_PERIOD` for some `eth1_data_vote` in `state.eth1_data_votes`. +* Set `state.eth1_data_votes = []`. ### Justification