Update 0_beacon-chain.md

This commit is contained in:
Justin 2019-02-15 00:23:03 +00:00 committed by GitHub
parent 81e8f53ab9
commit ab140c2f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 62 additions and 89 deletions

View File

@ -43,7 +43,8 @@
- [Beacon chain blocks](#beacon-chain-blocks) - [Beacon chain blocks](#beacon-chain-blocks)
- [`BeaconBlock`](#beaconblock) - [`BeaconBlock`](#beaconblock)
- [`BeaconBlockBody`](#beaconblockbody) - [`BeaconBlockBody`](#beaconblockbody)
- [`ProposalSignedData`](#proposalsigneddata) - [`Proposal`](#proposal)
- [`RandaoReveal`](#randaoreveal)
- [Beacon chain state](#beacon-chain-state) - [Beacon chain state](#beacon-chain-state)
- [`BeaconState`](#beaconstate) - [`BeaconState`](#beaconstate)
- [`Validator`](#validator) - [`Validator`](#validator)
@ -94,7 +95,6 @@
- [`bls_verify`](#bls_verify) - [`bls_verify`](#bls_verify)
- [`bls_verify_multiple`](#bls_verify_multiple) - [`bls_verify_multiple`](#bls_verify_multiple)
- [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys) - [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys)
- [`validate_proof_of_possession`](#validate_proof_of_possession)
- [`process_deposit`](#process_deposit) - [`process_deposit`](#process_deposit)
- [Routines for updating validator status](#routines-for-updating-validator-status) - [Routines for updating validator status](#routines-for-updating-validator-status)
- [`activate_validator`](#activate_validator) - [`activate_validator`](#activate_validator)
@ -117,7 +117,7 @@
- [Block roots](#block-roots) - [Block roots](#block-roots)
- [Per-block processing](#per-block-processing) - [Per-block processing](#per-block-processing)
- [Slot](#slot-1) - [Slot](#slot-1)
- [Proposer signature](#proposer-signature) - [Block signature](#block-signature)
- [RANDAO](#randao) - [RANDAO](#randao)
- [Eth1 data](#eth1-data) - [Eth1 data](#eth1-data)
- [Transactions](#transactions) - [Transactions](#transactions)
@ -299,14 +299,10 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
{ {
# Proposer index # Proposer index
'proposer_index': 'uint64', 'proposer_index': 'uint64',
# First proposal data # First proposal
'proposal_data_1': ProposalSignedData, 'proposal_1': Proposal,
# First proposal signature # Second proposal
'proposal_signature_1': 'bytes96', 'proposal_2': Proposal,
# Second proposal data
'proposal_data_2': ProposalSignedData,
# Second proposal signature
'proposal_signature_2': 'bytes96',
} }
``` ```
@ -363,9 +359,9 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
'slot': 'uint64', 'slot': 'uint64',
# Shard number # Shard number
'shard': 'uint64', 'shard': 'uint64',
# Hash of root of the signed beacon block # Root of the signed beacon block
'beacon_block_root': 'bytes32', 'beacon_block_root': 'bytes32',
# Hash of root of the ancestor at the epoch boundary # Root of the ancestor at the epoch boundary
'epoch_boundary_root': 'bytes32', 'epoch_boundary_root': 'bytes32',
# Shard block's hash of root # Shard block's hash of root
'shard_block_root': 'bytes32', 'shard_block_root': 'bytes32',
@ -474,16 +470,17 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
```python ```python
{ {
## Header ## # Header
'slot': 'uint64', 'slot': Slot,
'parent_root': 'bytes32', 'parent_root': 'bytes32',
'state_root': 'bytes32', 'state_root': 'bytes32',
'randao_reveal': 'bytes96', 'randao_reveal': 'bytes96',
'eth1_data': Eth1Data, 'eth1_data': Eth1Data,
'signature': 'bytes96',
## Body ## # Body
'body': BeaconBlockBody, 'body': BeaconBlockBody,
# Signature
'signature': 'bytes96',
} }
``` ```
@ -500,7 +497,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
} }
``` ```
#### `ProposalSignedData` #### `Proposal`
```python ```python
{ {
@ -508,8 +505,21 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
'slot': 'uint64', 'slot': 'uint64',
# Shard number (`BEACON_CHAIN_SHARD_NUMBER` for beacon chain) # Shard number (`BEACON_CHAIN_SHARD_NUMBER` for beacon chain)
'shard': 'uint64', 'shard': 'uint64',
# Block's hash of root # Block root
'block_root': 'bytes32', 'block_root': 'bytes32',
# Signature
'signature': 'bytes96',
}
```
#### `RandaoReveal`
```python
{
# Epoch number
'epoch': 'uint64',
# RANDAO reveal
'randao_reveal': 'bytes96',
} }
``` ```
@ -670,6 +680,10 @@ Note: We aim to migrate to a S[T/N]ARK-friendly hash function in a future Ethere
`def hash_tree_root(object: SSZSerializable) -> Bytes32` is a function for hashing objects into a single root utilizing a hash tree structure. `hash_tree_root` is defined in the [SimpleSerialize spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/simple-serialize.md#tree-hash). `def hash_tree_root(object: SSZSerializable) -> Bytes32` is a function for hashing objects into a single root utilizing a hash tree structure. `hash_tree_root` is defined in the [SimpleSerialize spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/simple-serialize.md#tree-hash).
### `signed_root`
`def signed_root(object: SSZContainer) -> Bytes32` is a function defined in the [SimpleSerialize spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/simple-serialize.md#signed-roots) to compute signed messages.
### `slot_to_epoch` ### `slot_to_epoch`
```python ```python
@ -1240,60 +1254,33 @@ def get_entry_exit_effect_epoch(epoch: Epoch) -> Epoch:
`bls_aggregate_pubkeys` is a function for aggregating multiple BLS public keys into a single aggregate key, defined in the [BLS Signature spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_signature.md#bls_aggregate_pubkeys). `bls_aggregate_pubkeys` is a function for aggregating multiple BLS public keys into a single aggregate key, defined in the [BLS Signature spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_signature.md#bls_aggregate_pubkeys).
### `validate_proof_of_possession` ### `process_deposit`
Used to add a [validator](#dfn-validator) or top up an existing [validator](#dfn-validator)'s balance by some `deposit` amount:
```python ```python
def validate_proof_of_possession(state: BeaconState, def process_deposit(state: BeaconState, deposit: Deposit) -> None:
pubkey: BLSPubkey,
proof_of_possession: BLSSignature,
withdrawal_credentials: Bytes32) -> bool:
""" """
Verify the given ``proof_of_possession``. Process a deposit from Ethereum 1.0.
Note that this function mutates ``state``.
""" """
proof_of_possession_data = DepositInput( deposit_input = deposit.deposit_data.deposit_input
pubkey=pubkey,
withdrawal_credentials=withdrawal_credentials,
proof_of_possession=EMPTY_SIGNATURE,
)
return bls_verify( assert bls_verify(
pubkey=pubkey, pubkey=deposit_input.pubkey,
message_hash=hash_tree_root(proof_of_possession_data), message_hash=signed_root(deposit_input, "proof_of_possession"),
signature=proof_of_possession, signature=deposit_input.proof_of_possession,
domain=get_domain( domain=get_domain(
state.fork, state.fork,
get_current_epoch(state), get_current_epoch(state),
DOMAIN_DEPOSIT, DOMAIN_DEPOSIT,
) )
) )
```
### `process_deposit`
Used to add a [validator](#dfn-validator) or top up an existing [validator](#dfn-validator)'s balance by some `deposit` amount:
```python
def process_deposit(state: BeaconState,
pubkey: BLSPubkey,
amount: Gwei,
proof_of_possession: BLSSignature,
withdrawal_credentials: Bytes32) -> None:
"""
Process a deposit from Ethereum 1.0.
Note that this function mutates ``state``.
"""
# Validate the given `proof_of_possession`
proof_is_valid = validate_proof_of_possession(
state,
pubkey,
proof_of_possession,
withdrawal_credentials,
)
if not proof_is_valid:
return
validator_pubkeys = [v.pubkey for v in state.validator_registry] validator_pubkeys = [v.pubkey for v in state.validator_registry]
pubkey = deposit_input.pubkey
amount = deposit.deposit_data.amount
withdrawal_credentials = deposit_input.withdrawal_credentials
if pubkey not in validator_pubkeys: if pubkey not in validator_pubkeys:
# Add new validator # Add new validator
@ -1520,13 +1507,7 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
# Process genesis deposits # Process genesis deposits
for deposit in genesis_validator_deposits: for deposit in genesis_validator_deposits:
process_deposit( process_deposit(state, deposit)
state=state,
pubkey=deposit.deposit_data.deposit_input.pubkey,
amount=deposit.deposit_data.amount,
proof_of_possession=deposit.deposit_data.deposit_input.proof_of_possession,
withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials,
)
# Process genesis activations # Process genesis activations
for validator_index, _ in enumerate(state.validator_registry): for validator_index, _ in enumerate(state.validator_registry):
@ -1652,16 +1633,16 @@ Below are the processing steps that happen at every `block`.
* Verify that `block.slot == state.slot`. * Verify that `block.slot == state.slot`.
#### Proposer signature #### Block signature
* Let `block_without_signature_root` be the `hash_tree_root` of `block` where `block.signature` is set to `EMPTY_SIGNATURE`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`.
* Let `proposal_root = hash_tree_root(ProposalSignedData(state.slot, BEACON_CHAIN_SHARD_NUMBER, block_without_signature_root))`. * Let `proposal = Proposal(block.slot, BEACON_CHAIN_SHARD_NUMBER, signed_root(block, "signature"), block.signature)`.
* Verify that `bls_verify(pubkey=state.validator_registry[get_beacon_proposer_index(state, state.slot)].pubkey, message_hash=proposal_root, signature=block.signature, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_PROPOSAL))`. * Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=signed_root(proposal, "signature"), signature=proposal.signature, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_PROPOSAL))`.
#### RANDAO #### RANDAO
* Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. * Let `randao_reveal = RandaoReveal(epoch=get_current_epoch(state), randao_reveal=block.randao_reveal)`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=int_to_bytes32(get_current_epoch(state)), signature=block.randao_reveal, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO))`. * Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=signed_root(randao_reveal, "randao_reveal"), signature=randao_reveal.randao_reveal, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO))`.
* Set `state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = xor(get_randao_mix(state, get_current_epoch(state)), hash(block.randao_reveal))`. * Set `state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = xor(get_randao_mix(state, get_current_epoch(state)), hash(block.randao_reveal))`.
#### Eth1 data #### Eth1 data
@ -1678,12 +1659,12 @@ Verify that `len(block.body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS`.
For each `proposer_slashing` in `block.body.proposer_slashings`: For each `proposer_slashing` in `block.body.proposer_slashings`:
* Let `proposer = state.validator_registry[proposer_slashing.proposer_index]`. * Let `proposer = state.validator_registry[proposer_slashing.proposer_index]`.
* Verify that `proposer_slashing.proposal_data_1.slot == proposer_slashing.proposal_data_2.slot`. * Verify that `proposer_slashing.proposal_1.slot == proposer_slashing.proposal_2.slot`.
* Verify that `proposer_slashing.proposal_data_1.shard == proposer_slashing.proposal_data_2.shard`. * Verify that `proposer_slashing.proposal_1.shard == proposer_slashing.proposal_2.shard`.
* Verify that `proposer_slashing.proposal_data_1.block_root != proposer_slashing.proposal_data_2.block_root`. * Verify that `proposer_slashing.proposal_1.block_root != proposer_slashing.proposal_2.block_root`.
* Verify that `proposer.slashed_epoch > get_current_epoch(state)`. * 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=signed_root(proposer_slashing.proposal_1, "signature"), signature=proposer_slashing.proposal_1.signature, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_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))`. * Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=signed_root(proposer_slashing.proposal_2, "signature"), signature=proposer_slashing.proposal_2.signature, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_2.slot), DOMAIN_PROPOSAL))`.
* Run `slash_validator(state, proposer_slashing.proposer_index)`. * Run `slash_validator(state, proposer_slashing.proposer_index)`.
##### Attester slashings ##### Attester slashings
@ -1777,13 +1758,7 @@ def verify_merkle_branch(leaf: Bytes32, branch: List[Bytes32], depth: int, index
* Run the following: * Run the following:
```python ```python
process_deposit( process_deposit(state, deposit)
state=state,
pubkey=deposit.deposit_data.deposit_input.pubkey,
amount=deposit.deposit_data.amount,
proof_of_possession=deposit.deposit_data.deposit_input.proof_of_possession,
withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials,
)
``` ```
* Set `state.deposit_index += 1`. * Set `state.deposit_index += 1`.
@ -1797,8 +1772,7 @@ For each `exit` in `block.body.voluntary_exits`:
* Let `validator = state.validator_registry[exit.validator_index]`. * Let `validator = state.validator_registry[exit.validator_index]`.
* Verify that `validator.exit_epoch > get_entry_exit_effect_epoch(get_current_epoch(state))`. * Verify that `validator.exit_epoch > get_entry_exit_effect_epoch(get_current_epoch(state))`.
* Verify that `get_current_epoch(state) >= exit.epoch`. * Verify that `get_current_epoch(state) >= exit.epoch`.
* Let `exit_message = hash_tree_root(Exit(epoch=exit.epoch, validator_index=exit.validator_index, signature=EMPTY_SIGNATURE))`. * Verify that `bls_verify(pubkey=validator.pubkey, message_hash=signed_root(exit, "signature"), signature=exit.signature, domain=get_domain(state.fork, exit.epoch, DOMAIN_EXIT))`.
* Verify that `bls_verify(pubkey=validator.pubkey, message_hash=exit_message, signature=exit.signature, domain=get_domain(state.fork, exit.epoch, DOMAIN_EXIT))`.
* Run `initiate_validator_exit(state, exit.validator_index)`. * Run `initiate_validator_exit(state, exit.validator_index)`.
##### Transfers ##### Transfers
@ -1815,8 +1789,7 @@ For each `transfer` in `block.body.transfers`:
* Verify that `state.slot == transfer.slot`. * Verify that `state.slot == transfer.slot`.
* Verify that `get_current_epoch(state) >= state.validator_registry[transfer.from].withdrawable_epoch`. * Verify that `get_current_epoch(state) >= state.validator_registry[transfer.from].withdrawable_epoch`.
* Verify that `state.validator_registry[transfer.from].withdrawal_credentials == BLS_WITHDRAWAL_PREFIX_BYTE + hash(transfer.pubkey)[1:]`. * Verify that `state.validator_registry[transfer.from].withdrawal_credentials == BLS_WITHDRAWAL_PREFIX_BYTE + hash(transfer.pubkey)[1:]`.
* Let `transfer_message = hash_tree_root(Transfer(from=transfer.from, to=transfer.to, amount=transfer.amount, fee=transfer.fee, slot=transfer.slot, signature=EMPTY_SIGNATURE))`. * Verify that `bls_verify(pubkey=transfer.pubkey, message_hash=signed_root(transfer, "signature"), signature=transfer.signature, domain=get_domain(state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER))`.
* Verify that `bls_verify(pubkey=transfer.pubkey, message_hash=transfer_message, signature=transfer.signature, domain=get_domain(state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER))`.
* Set `state.validator_balances[transfer.from] -= transfer.amount + transfer.fee`. * Set `state.validator_balances[transfer.from] -= transfer.amount + transfer.fee`.
* Set `state.validator_balances[transfer.to] += transfer.amount`. * Set `state.validator_balances[transfer.to] += transfer.amount`.
* Set `state.validator_balances[get_beacon_proposer_index(state, state.slot)] += transfer.fee`. * Set `state.validator_balances[get_beacon_proposer_index(state, state.slot)] += transfer.fee`.