Merge branch 'master' into vbuterin-patch-15

This commit is contained in:
vbuterin 2018-12-17 10:41:23 -05:00 committed by GitHub
commit 2fa7d254dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 53 deletions

View File

@ -2,6 +2,8 @@
[![Join the chat at https://gitter.im/ethereum/sharding](https://badges.gitter.im/ethereum/sharding.svg)](https://gitter.im/ethereum/sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
To learn more about sharding and eth2.0/Serenity, see the [sharding FAQ](https://github.com/ethereum/wiki/wiki/Sharding-FAQs) and the [research compendium](https://notes.ethereum.org/s/H1PGqDhpm).
This repo hosts the current eth2.0 specifications. Discussions about design rationale and proposed changes can be brought up and discussed as issues. Solidified, agreed upon changes to spec can be made through pull requests.
# Specs

View File

@ -99,6 +99,16 @@ def modular_squareroot(value: int) -> int:
return None
```
## Operations involving asignature aggregation
### `bls_aggregate_pubkeys`
Let `bls_aggregate_pubkeys(pubkeys: [uint384]) -> uint384` return `pubkeys[0] + .... + pubkeys[len(pubkeys)-1]`, where `+` is the elliptic curve addition operation over the G1 curve.
### `bls_aggregate_signatures`
Let `bls_aggregate_signatures(signatures: [[uint384]]) -> [uint384]` return `signatures[0] + .... + signatures[len(signatures)-1]`, where `+` is the elliptic curve addition operation over the G2 curve.
## Signature verification
In the following `e` is the pairing function and `g` is the G1 generator with the following coordinates (see [here](https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#g1)):

View File

@ -49,6 +49,7 @@
- [`CandidatePoWReceiptRootRecord`](#candidatepowreceiptrootrecord)
- [`PendingAttestationRecord`](#pendingattestationrecord)
- [`ForkData`](#forkdata)
- [`ValidatorRegistryDeltaBlock`](#validatorregistrydeltablock)
- [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract)
- [Deposit arguments](#deposit-arguments)
- [`Eth1Deposit` logs](#eth1deposit-logs)
@ -59,11 +60,11 @@
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
- [Helper functions](#helper-functions)
- [`hash`](#hash)
- [`hash_tree_root`](#hash_tree_root)
- [`is_active_validator`](#is_active_validator)
- [`get_active_validator_indices`](#get_active_validator_indices)
- [`shuffle`](#shuffle)
- [`split`](#split)
- [`clamp`](#clamp)
- [`get_new_shuffling`](#get_new_shuffling)
- [`get_shard_committees_at_slot`](#get_shard_committees_at_slot)
- [`get_block_root`](#get_block_root)
@ -75,11 +76,13 @@
- [`get_new_validator_registry_delta_chain_tip`](#get_new_validator_registry_delta_chain_tip)
- [`get_fork_version`](#get_fork_version)
- [`get_domain`](#get_domain)
- [`hash_tree_root`](#hash_tree_root)
- [`verify_slashable_vote_data`](#verify_slashable_vote_data)
- [`is_double_vote`](#is_double_vote)
- [`is_surround_vote`](#is_surround_vote)
- [`integer_squareroot`](#integer_squareroot)
- [`bls_verify`](#bls_verify)
- [`bls_verify_multiple`](#bls_verify_multiple)
- [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys)
- [On startup](#on-startup)
- [Routine for processing deposits](#routine-for-processing-deposits)
- [Routine for updating validator status](#routine-for-updating-validator-status)
@ -140,6 +143,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
* **Attester** - a [validator](#dfn-validator) that is part of a committee that needs to sign off on a beacon chain block while simultaneously creating a link (crosslink) to a recent shard block on a particular shard chain.
* **Beacon chain** - the central PoS chain that is the base of the sharding system.
* **Shard chain** - one of the chains on which user transactions take place and account data is stored.
* **Block root** - a 32-byte Merkle root of a beacon chain block or shard chain block. Previously called "block hash".
* **Crosslink** - a set of signatures from a committee attesting to a block in a shard chain, which can be included into the beacon chain. Crosslinks are the main means by which the beacon chain "learns about" the updated state of shard chains.
* **Slot** - a period of `SLOT_DURATION` seconds, during which one proposer has the ability to create a beacon chain block and some attesters have the ability to make attestations
* **Epoch** - an aligned span of slots during which all [validators](#dfn-validator) get exactly one chance to make an attestation
@ -162,6 +166,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
| `BLS_WITHDRAWAL_PREFIX_BYTE` | `0x00` | - |
| `MAX_CASPER_VOTES` | `2**10` (= 1,024) | votes |
| `LATEST_BLOCK_ROOTS_LENGTH` | `2**13` (= 8,192) | block roots |
| `EMPTY_SIGNATURE` | `[bytes48(0), bytes48(0)]` | - |
* For the safety of crosslinks a minimum committee size of 111 is [recommended](https://vitalik.ca/files/Ithaca201807_Sharding.pdf). (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) The shuffling algorithm generally ensures (assuming sufficient validators) committee sizes at least `TARGET_COMMITTEE_SIZE // 2`.
@ -368,12 +373,12 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
{
# BLS pubkey
'pubkey': 'uint384',
# BLS proof of possession (a BLS signature)
'proof_of_possession': ['uint384'],
# Withdrawal credentials
'withdrawal_credentials': 'hash32',
# Initial RANDAO commitment
'randao_commitment': 'hash32',
# a BLS signature of this ``DepositInput``
'proof_of_possession': ['uint384'],
}
```
@ -507,7 +512,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
{
# Slot number
'slot': 'uint64',
# Shard block hash
# Shard block root
'shard_block_root': 'hash32',
}
```
@ -577,6 +582,17 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
}
```
#### `ValidatorRegistryDeltaBlock`
```python
{
latest_registry_delta_root: 'hash32',
validator_index: 'uint24',
pubkey: 'uint384',
flag: 'uint64',
}
```
## 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.
@ -726,6 +742,10 @@ The hash function is denoted by `hash`. In Phase 0 the beacon chain is deployed
Note: We aim to migrate to a S[T/N]ARK-friendly hash function in a future Ethereum 2.0 deployment phase.
#### `hash_tree_root`
`hash_tree_root` 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).
#### `is_active_validator`
```python
def is_active_validator(validator: ValidatorRecord) -> bool:
@ -812,21 +832,6 @@ def split(values: List[Any], split_count: int) -> List[Any]:
]
```
#### `clamp`
```python
def clamp(minval: int, maxval: int, x: int) -> int:
"""
Clamps ``x`` between ``minval`` and ``maxval``.
"""
if x <= minval:
return minval
elif x >= maxval:
return maxval
else:
return x
```
#### `get_new_shuffling`
```python
@ -838,10 +843,12 @@ def get_new_shuffling(seed: Hash32,
"""
active_validator_indices = get_active_validator_indices(validators)
committees_per_slot = clamp(
committees_per_slot = max(
1,
SHARD_COUNT // EPOCH_LENGTH,
len(active_validator_indices) // EPOCH_LENGTH // TARGET_COMMITTEE_SIZE,
min(
SHARD_COUNT // EPOCH_LENGTH,
len(active_validator_indices) // EPOCH_LENGTH // TARGET_COMMITTEE_SIZE,
)
)
# Shuffle with seed
@ -893,7 +900,7 @@ def get_shard_committees_at_slot(state: BeaconState,
def get_block_root(state: BeaconState,
slot: int) -> Hash32:
"""
Returns the block hash at a recent ``slot``.
Returns the block root at a recent ``slot``.
"""
earliest_slot_in_array = state.slot - len(state.latest_block_roots)
assert earliest_slot_in_array <= slot < state.slot
@ -966,17 +973,19 @@ def get_effective_balance(state: State, index: int) -> int:
```python
def get_new_validator_registry_delta_chain_tip(current_validator_registry_delta_chain_tip: Hash32,
index: int,
validator_index: int,
pubkey: int,
flag: int) -> Hash32:
"""
Compute the next hash in the validator registry delta hash chain.
Compute the next root in the validator registry delta chain.
"""
return hash(
current_validator_registry_delta_chain_tip +
bytes1(flag) +
bytes3(index) +
bytes48(pubkey)
return hash_tree_root(
ValidatorRegistryDeltaBlock(
validator_registry_delta_chain_tip=current_validator_registry_delta_chain_tip,
validator_index=validator_index,
pubkey=pubkey,
flag=flag,
)
)
```
@ -1003,10 +1012,6 @@ def get_domain(fork_data: ForkData,
) * 2**32 + domain_type
```
#### `hash_tree_root`
`hash_tree_root` 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).
#### `verify_slashable_vote_data`
```python
@ -1035,6 +1040,38 @@ def verify_slashable_vote_data(state: BeaconState, vote_data: SlashableVoteData)
)
```
#### `is_double_vote`
```python
def is_double_vote(attestation_data_1: AttestationData,
attestation_data_2: AttestationData) -> bool
"""
Assumes ``attestation_data_1`` is distinct from ``attestation_data_2``.
Returns True if the provided ``AttestationData`` are slashable
due to a 'double vote'.
"""
return attestation_data_1.slot == attestation_data_2.slot
```
#### `is_surround_vote`
```python
def is_surround_vote(attestation_data_1: AttestationData,
attestation_data_2: AttestationData) -> bool
"""
Assumes ``attestation_data_1`` is distinct from ``attestation_data_2``.
Returns True if the provided ``AttestationData`` are slashable
due to a 'surround vote'.
Note: parameter order matters as this function only checks
that ``attestation_data_1`` surrounds ``attestation_data_2``.
"""
return (
(attestation_data_1.justified_slot < attestation_data_2.justified_slot) and
(attestat_data_2.justified_slot + 1 == attestation_data_2.slot) and
(attestation_data_2.slot < attestation_data_1.slot)
)
```
#### `integer_squareroot`
```python
@ -1052,11 +1089,15 @@ def integer_squareroot(n: int) -> int:
#### `bls_verify`
`bls_verify` is a function for verifying a BLS12-381 signature, defined in the [BLS Verification spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_verify.md#bls_verify).
`bls_verify` is a function for verifying a BLS12-381 signature, defined in the [BLS Signature spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_signature.md#bls_verify).
#### `bls_verify_multiple`
`bls_verify_multiple` is a function for verifying a BLS12-381 signature constructed from multiple messages, defined in the [BLS Verification spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_verify.md#bls_verify_multiple).
`bls_verify_multiple` is a function for verifying a BLS12-381 signature constructed from multiple messages, defined in the [BLS Signature spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/bls_signature.md#bls_verify_multiple).
#### `bls_aggregate_pubkeys`
`bls_aggregate_pubkeys` is a function for aggregating a BLS12-381 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).
### On startup
@ -1069,7 +1110,7 @@ A valid block with slot `INITIAL_SLOT_NUMBER` (a "genesis block") has the follow
state_root=STARTUP_STATE_ROOT,
randao_reveal=ZERO_HASH,
candidate_pow_receipt_root=ZERO_HASH,
proposer_signature=[0, 0],
proposer_signature=EMPTY_SIGNATURE,
'body': BeaconBlockBody(
proposer_slashings=[],
casper_slashings=[],
@ -1080,7 +1121,7 @@ A valid block with slot `INITIAL_SLOT_NUMBER` (a "genesis block") has the follow
}
```
`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 `ChainStart` log has been emitted, `get_initial_beacon_state` will execute to compute the `ssz_tree_hash` of `BeaconState`.
`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 `ChainStart` log has been emitted, `get_initial_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`.
```python
def get_initial_beacon_state(initial_validator_deposits: List[Deposit],
@ -1174,15 +1215,21 @@ def process_deposit(state: BeaconState,
deposit: int,
proof_of_possession: bytes,
withdrawal_credentials: Hash32,
randao_commitment: Hash32,
status: int) -> int:
randao_commitment: Hash32) -> int:
"""
Process a deposit from Ethereum 1.0.
Note that this function mutates ``state``.
"""
proof_of_possession_data = DepositInput(
pubkey=pubkey,
withdrawal_credentials=withdrawal_credentials,
randao_commitment=randao_commitment,
proof_of_possession=EMPTY_SIGNATURE,
)
assert bls_verify(
pubkey=pubkey,
message=hash(bytes32(pubkey) + withdrawal_credentials + randao_commitment),
message=hash_tree_root(proof_of_possession_data),
signature=proof_of_possession,
domain=get_domain(
state.fork_data,
@ -1259,7 +1306,7 @@ def activate_validator(state: BeaconState,
validator.latest_status_change_slot = state.slot
state.validator_registry_delta_chain_tip = get_new_validator_registry_delta_chain_tip(
validator_registry_delta_chain_tip=state.validator_registry_delta_chain_tip,
index=index,
validator_index=index,
pubkey=validator.pubkey,
flag=ACTIVATION,
)
@ -1314,7 +1361,7 @@ def exit_validator(state: BeaconState,
validator.exit_count = state.validator_registry_exit_count
state.validator_registry_delta_chain_tip = get_new_validator_registry_delta_chain_tip(
validator_registry_delta_chain_tip=state.validator_registry_delta_chain_tip,
index=index,
validator_index=index,
pubkey=validator.pubkey,
flag=EXIT
)
@ -1352,7 +1399,7 @@ Below are the processing steps that happen at every `block`.
### Proposer signature
* Let `block_without_signature_root` be the `hash_tree_root` of `block` where `block.signature` is set to `[0, 0]`.
* Let `block_without_signature_root` be the `hash_tree_root` of `block` where `block.signature` is set to `EMPTY_SIGNATURE`.
* Let `proposal_root = hash_tree_root(ProposalSignedData(state.slot, BEACON_CHAIN_SHARD_NUMBER, block_without_signature_root))`.
* Verify that `bls_verify(pubkey=state.validator_registry[get_beacon_proposer_index(state, state.slot)].pubkey, data=proposal_root, signature=block.signature, domain=get_domain(state.fork_data, state.slot, DOMAIN_PROPOSAL))`.
@ -1393,13 +1440,15 @@ Verify that `len(block.body.casper_slashings) <= MAX_CASPER_SLASHINGS`.
For each `casper_slashing` in `block.body.casper_slashings`:
* Verify that `casper_slashing.slashable_vote_data_1.data != casper_slashing.slashable_vote_data_2.data`.
* Let `indices(vote) = vote.aggregate_signature_poc_0_indices + vote.aggregate_signature_poc_1_indices`.
* Let `intersection = [x for x in indices(casper_slashing.slashable_vote_data_1) if x in indices(casper_slashing.slashable_vote_data_2)]`.
* Let `slashable_vote_data_1 = casper_slashing.slashable_vote_data_1`.
* Let `slashable_vote_data_2 = casper_slashing.slashable_vote_data_2`.
* Let `indices(slashable_vote_data) = slashable_vote_data.aggregate_signature_poc_0_indices + slashable_vote_data.aggregate_signature_poc_1_indices`.
* Let `intersection = [x for x in indices(slashable_vote_data_1) if x in indices(slashable_vote_data_2)]`.
* Verify that `len(intersection) >= 1`.
* Verify that `casper_slashing.slashable_vote_data_1.data.justified_slot + 1 < casper_slashing.slashable_vote_data_2.data.justified_slot + 1 == casper_slashing.slashable_vote_data_2.data.slot < casper_slashing.slashable_vote_data_1.data.slot` or `casper_slashing.slashable_vote_data_1.data.slot == casper_slashing.slashable_vote_data_2.data.slot`.
* Verify that `verify_slashable_vote_data(state, casper_slashing.slashable_vote_data_1)`.
* Verify that `verify_slashable_vote_data(state, casper_slashing.slashable_vote_data_2)`.
* Verify that `slashable_vote_data_1.data != slashable_vote_data_2.data`.
* Verify that `is_double_vote(slashable_vote_data_1.data, slashable_vote_data_2.data)` or `is_surround_vote(slashable_vote_data_1.data, slashable_vote_data_2.data)`.
* Verify that `verify_slashable_vote_data(state, slashable_vote_data_1)`.
* Verify that `verify_slashable_vote_data(state, slashable_vote_data_2)`.
* For each [validator](#dfn-validator) index `i` in `intersection`, if `state.validator_registry[i].status` does not equal `EXITED_WITH_PENALTY`, then run `update_validator_status(state, i, new_status=EXITED_WITH_PENALTY)`
#### Attestations
@ -1415,7 +1464,7 @@ For each `attestation` in `block.body.attestations`:
* Verify that either `attestation.data.latest_crosslink_root` or `attestation.data.shard_block_root` equals `state.latest_crosslinks[shard].shard_block_root`.
* `aggregate_signature` verification:
* Let `participants = get_attestation_participants(state, attestation.data, attestation.participation_bitfield)`.
* Let `group_public_key = BLSAddPubkeys([state.validator_registry[v].pubkey for v in participants])`.
* Let `group_public_key = bls_aggregate_pubkeys([state.validator_registry[v].pubkey for v in participants])`.
* Verify that `bls_verify(pubkey=group_public_key, message=hash_tree_root(attestation.data) + bytes1(0), signature=attestation.aggregate_signature, domain=get_domain(state.fork_data, attestation.data.slot, DOMAIN_ATTESTATION))`.
* [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.shard_block_root == ZERO_HASH`.
* Append `PendingAttestationRecord(data=attestation.data, participation_bitfield=attestation.participation_bitfield, custody_bitfield=attestation.custody_bitfield, slot_included=state.slot)` to `state.latest_attestations`.