Merge branch 'master' into honest-validator
This commit is contained in:
commit
f204a81e04
|
@ -12,6 +12,11 @@ Core specifications for eth2.0 client validation can be found in [specs/core](sp
|
||||||
* [Phase 0 -- The Beacon Chain](specs/core/0_beacon-chain.md)
|
* [Phase 0 -- The Beacon Chain](specs/core/0_beacon-chain.md)
|
||||||
* [Phase 1 -- Shard Data Chains](specs/core/1_shard-data-chains.md)
|
* [Phase 1 -- Shard Data Chains](specs/core/1_shard-data-chains.md)
|
||||||
|
|
||||||
|
Accompanying documents can be found in [specs](specs) and include
|
||||||
|
* [SimpleSerialize (SSZ) spec](specs/simple-serialize.md)
|
||||||
|
* [BLS signature verification](specs/bls_signature.md)
|
||||||
|
* [General test format](specs/test-format.md)
|
||||||
|
|
||||||
## Design goals
|
## Design goals
|
||||||
The following are the broad design goals for Ethereum 2.0:
|
The following are the broad design goals for Ethereum 2.0:
|
||||||
* to minimize complexity, even at the cost of some losses in efficiency
|
* to minimize complexity, even at the cost of some losses in efficiency
|
||||||
|
|
|
@ -106,11 +106,11 @@ def modular_squareroot(value: int) -> int:
|
||||||
|
|
||||||
### `bls_aggregate_pubkeys`
|
### `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.
|
Let `bls_aggregate_pubkeys(pubkeys: List[Bytes48]) -> Bytes48` return `pubkeys[0] + .... + pubkeys[len(pubkeys)-1]`, where `+` is the elliptic curve addition operation over the G1 curve.
|
||||||
|
|
||||||
### `bls_aggregate_signatures`
|
### `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.
|
Let `bls_aggregate_signatures(signatures: List[Bytes96]) -> Bytes96` return `signatures[0] + .... + signatures[len(signatures)-1]`, where `+` is the elliptic curve addition operation over the G2 curve.
|
||||||
|
|
||||||
## Signature verification
|
## Signature verification
|
||||||
|
|
||||||
|
@ -119,12 +119,12 @@ In the following `e` is the pairing function and `g` is the G1 generator with th
|
||||||
```python
|
```python
|
||||||
g_x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
|
g_x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
|
||||||
g_y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
|
g_y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
|
||||||
g = Fq2(g_x, g_y)
|
g = Fq2([g_x, g_y])
|
||||||
```
|
```
|
||||||
|
|
||||||
### `bls_verify`
|
### `bls_verify`
|
||||||
|
|
||||||
Let `bls_verify(pubkey: uint384, message: bytes32, signature: [uint384], domain: uint64) -> bool`:
|
Let `bls_verify(pubkey: Bytes48, message: Bytes32, signature: Bytes96, domain: uint64) -> bool`:
|
||||||
|
|
||||||
* Verify that `pubkey` is a valid G1 point.
|
* Verify that `pubkey` is a valid G1 point.
|
||||||
* Verify that `signature` is a valid G2 point.
|
* Verify that `signature` is a valid G2 point.
|
||||||
|
@ -132,7 +132,7 @@ Let `bls_verify(pubkey: uint384, message: bytes32, signature: [uint384], domain:
|
||||||
|
|
||||||
### `bls_verify_multiple`
|
### `bls_verify_multiple`
|
||||||
|
|
||||||
Let `bls_verify_multiple(pubkeys: [uint384], messages: [bytes32], signature: [uint384], domain: uint64) -> bool`:
|
Let `bls_verify_multiple(pubkeys: List[Bytes48], messages: List[Bytes32], signature: Bytes96, domain: uint64) -> bool`:
|
||||||
|
|
||||||
* Verify that each `pubkey` in `pubkeys` is a valid G1 point.
|
* Verify that each `pubkey` in `pubkeys` is a valid G1 point.
|
||||||
* Verify that `signature` is a valid G2 point.
|
* Verify that `signature` is a valid G2 point.
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
- [`get_beacon_proposer_index`](#get_beacon_proposer_index)
|
- [`get_beacon_proposer_index`](#get_beacon_proposer_index)
|
||||||
- [`merkle_root`](#merkle_root)
|
- [`merkle_root`](#merkle_root)
|
||||||
- [`get_attestation_participants`](#get_attestation_participants)
|
- [`get_attestation_participants`](#get_attestation_participants)
|
||||||
- [`bytes1`, `bytes2`, ...](#bytes1-bytes2-)
|
- [`int_to_bytes1`, `int_to_bytes2`, ...](#int_to_bytes1-int_to_bytes2-)
|
||||||
- [`get_effective_balance`](#get_effective_balance)
|
- [`get_effective_balance`](#get_effective_balance)
|
||||||
- [`get_fork_version`](#get_fork_version)
|
- [`get_fork_version`](#get_fork_version)
|
||||||
- [`get_domain`](#get_domain)
|
- [`get_domain`](#get_domain)
|
||||||
|
@ -190,9 +190,9 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
| `GENESIS_SLOT` | `0` |
|
| `GENESIS_SLOT` | `0` |
|
||||||
| `GENESIS_START_SHARD` | `0` |
|
| `GENESIS_START_SHARD` | `0` |
|
||||||
| `FAR_FUTURE_SLOT` | `2**64 - 1` |
|
| `FAR_FUTURE_SLOT` | `2**64 - 1` |
|
||||||
| `ZERO_HASH` | `bytes32(0)` |
|
| `ZERO_HASH` | `int_to_bytes32(0)` |
|
||||||
| `EMPTY_SIGNATURE` | `[bytes48(0), bytes48(0)]` |
|
| `EMPTY_SIGNATURE` | `int_to_bytes96(0)` |
|
||||||
| `BLS_WITHDRAWAL_PREFIX_BYTE` | `bytes1(0)` |
|
| `BLS_WITHDRAWAL_PREFIX_BYTE` | `int_to_bytes1(0)` |
|
||||||
|
|
||||||
### Time parameters
|
### Time parameters
|
||||||
|
|
||||||
|
@ -266,11 +266,11 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# First proposal data
|
# First proposal data
|
||||||
'proposal_data_1': ProposalSignedData,
|
'proposal_data_1': ProposalSignedData,
|
||||||
# First proposal signature
|
# First proposal signature
|
||||||
'proposal_signature_1': '[uint384]',
|
'proposal_signature_1': 'bytes96',
|
||||||
# Second proposal data
|
# Second proposal data
|
||||||
'proposal_data_2': ProposalSignedData,
|
'proposal_data_2': ProposalSignedData,
|
||||||
# Second proposal signature
|
# Second proposal signature
|
||||||
'proposal_signature_2': '[uint384]',
|
'proposal_signature_2': 'bytes96',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# Attestation data
|
# Attestation data
|
||||||
'data': AttestationData,
|
'data': AttestationData,
|
||||||
# Aggregate signature
|
# Aggregate signature
|
||||||
'aggregate_signature': ['uint384'],
|
'aggregate_signature': 'bytes96',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# Custody bitfield
|
# Custody bitfield
|
||||||
'custody_bitfield': 'bytes',
|
'custody_bitfield': 'bytes',
|
||||||
# BLS aggregate signature
|
# BLS aggregate signature
|
||||||
'aggregate_signature': ['uint384'],
|
'aggregate_signature': 'bytes96',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -328,17 +328,17 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# Shard number
|
# Shard number
|
||||||
'shard': 'uint64',
|
'shard': 'uint64',
|
||||||
# Hash of root of the signed beacon block
|
# Hash of root of the signed beacon block
|
||||||
'beacon_block_root': 'hash32',
|
'beacon_block_root': 'bytes32',
|
||||||
# Hash of root of the ancestor at the epoch boundary
|
# Hash of root of the ancestor at the epoch boundary
|
||||||
'epoch_boundary_root': 'hash32',
|
'epoch_boundary_root': 'bytes32',
|
||||||
# Shard block's hash of root
|
# Shard block's hash of root
|
||||||
'shard_block_root': 'hash32',
|
'shard_block_root': 'bytes32',
|
||||||
# Last crosslink's hash of root
|
# Last crosslink's hash of root
|
||||||
'latest_crosslink_root': 'hash32',
|
'latest_crosslink_root': 'bytes32',
|
||||||
# Slot of the last justified beacon block
|
# Slot of the last justified beacon block
|
||||||
'justified_slot': 'uint64',
|
'justified_slot': 'uint64',
|
||||||
# Hash of the last justified beacon block
|
# Hash of the last justified beacon block
|
||||||
'justified_block_root': 'hash32',
|
'justified_block_root': 'bytes32',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
# Branch in the deposit tree
|
# Branch in the deposit tree
|
||||||
'branch': '[hash32]',
|
'branch': ['bytes32'],
|
||||||
# Index in the deposit tree
|
# Index in the deposit tree
|
||||||
'index': 'uint64',
|
'index': 'uint64',
|
||||||
# Data
|
# Data
|
||||||
|
@ -386,15 +386,15 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
# BLS pubkey
|
# BLS pubkey
|
||||||
'pubkey': 'uint384',
|
'pubkey': 'bytes48',
|
||||||
# Withdrawal credentials
|
# Withdrawal credentials
|
||||||
'withdrawal_credentials': 'hash32',
|
'withdrawal_credentials': 'bytes32',
|
||||||
# Initial RANDAO commitment
|
# Initial RANDAO commitment
|
||||||
'randao_commitment': 'hash32',
|
'randao_commitment': 'bytes32',
|
||||||
# Initial custody commitment
|
# Initial custody commitment
|
||||||
'custody_commitment': 'hash32',
|
'custody_commitment': 'bytes32',
|
||||||
# A BLS signature of this `DepositInput`
|
# A BLS signature of this `DepositInput`
|
||||||
'proof_of_possession': ['uint384'],
|
'proof_of_possession': 'bytes96',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# Index of the exiting validator
|
# Index of the exiting validator
|
||||||
'validator_index': 'uint24',
|
'validator_index': 'uint24',
|
||||||
# Validator signature
|
# Validator signature
|
||||||
'signature': '[uint384]',
|
'signature': 'bytes96',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -421,11 +421,11 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
{
|
{
|
||||||
## Header ##
|
## Header ##
|
||||||
'slot': 'uint64',
|
'slot': 'uint64',
|
||||||
'parent_root': 'hash32',
|
'parent_root': 'bytes32',
|
||||||
'state_root': 'hash32',
|
'state_root': 'bytes32',
|
||||||
'randao_reveal': 'hash32',
|
'randao_reveal': 'bytes32',
|
||||||
'eth1_data': Eth1Data,
|
'eth1_data': Eth1Data,
|
||||||
'signature': ['uint384'],
|
'signature': 'bytes96',
|
||||||
|
|
||||||
## Body ##
|
## Body ##
|
||||||
'body': BeaconBlockBody,
|
'body': BeaconBlockBody,
|
||||||
|
@ -458,7 +458,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# 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's hash of root
|
||||||
'block_root': 'hash32',
|
'block_root': 'bytes32',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -478,17 +478,17 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
'validator_balances': ['uint64'],
|
'validator_balances': ['uint64'],
|
||||||
'validator_registry_update_slot': 'uint64',
|
'validator_registry_update_slot': 'uint64',
|
||||||
'validator_registry_exit_count': 'uint64',
|
'validator_registry_exit_count': 'uint64',
|
||||||
'validator_registry_delta_chain_tip': 'hash32', # For light clients to track deltas
|
'validator_registry_delta_chain_tip': 'bytes32', # For light clients to track deltas
|
||||||
|
|
||||||
# Randomness and committees
|
# Randomness and committees
|
||||||
'latest_randao_mixes': ['hash32'],
|
'latest_randao_mixes': ['bytes32'],
|
||||||
'latest_vdf_outputs': ['hash32'],
|
'latest_vdf_outputs': ['bytes32'],
|
||||||
'previous_epoch_start_shard': 'uint64',
|
'previous_epoch_start_shard': 'uint64',
|
||||||
'current_epoch_start_shard': 'uint64',
|
'current_epoch_start_shard': 'uint64',
|
||||||
'previous_epoch_calculation_slot': 'uint64',
|
'previous_epoch_calculation_slot': 'uint64',
|
||||||
'current_epoch_calculation_slot': 'uint64',
|
'current_epoch_calculation_slot': 'uint64',
|
||||||
'previous_epoch_randao_mix': 'hash32',
|
'previous_epoch_randao_mix': 'bytes32',
|
||||||
'current_epoch_randao_mix': 'hash32',
|
'current_epoch_randao_mix': 'bytes32',
|
||||||
|
|
||||||
# Custody challenges
|
# Custody challenges
|
||||||
'custody_challenges': [CustodyChallenge],
|
'custody_challenges': [CustodyChallenge],
|
||||||
|
@ -501,10 +501,10 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
|
|
||||||
# Recent state
|
# Recent state
|
||||||
'latest_crosslinks': [Crosslink],
|
'latest_crosslinks': [Crosslink],
|
||||||
'latest_block_roots': ['hash32'], # Needed to process attestations, older to newer
|
'latest_block_roots': ['bytes32'], # Needed to process attestations, older to newer
|
||||||
'latest_penalized_balances': ['uint64'], # Balances penalized at every withdrawal period
|
'latest_penalized_balances': ['uint64'], # Balances penalized at every withdrawal period
|
||||||
'latest_attestations': [PendingAttestation],
|
'latest_attestations': [PendingAttestation],
|
||||||
'batched_block_roots': ['hash32'],
|
'batched_block_roots': ['bytes32'],
|
||||||
|
|
||||||
# Ethereum 1.0 chain data
|
# Ethereum 1.0 chain data
|
||||||
'latest_eth1_data': Eth1Data,
|
'latest_eth1_data': Eth1Data,
|
||||||
|
@ -517,11 +517,11 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
# BLS public key
|
# BLS public key
|
||||||
'pubkey': 'uint384',
|
'pubkey': 'bytes48',
|
||||||
# Withdrawal credentials
|
# Withdrawal credentials
|
||||||
'withdrawal_credentials': 'hash32',
|
'withdrawal_credentials': 'bytes32',
|
||||||
# RANDAO commitment
|
# RANDAO commitment
|
||||||
'randao_commitment': 'hash32',
|
'randao_commitment': 'bytes32',
|
||||||
# Slots the proposer has skipped (i.e. layers of RANDAO expected)
|
# Slots the proposer has skipped (i.e. layers of RANDAO expected)
|
||||||
'randao_layers': 'uint64',
|
'randao_layers': 'uint64',
|
||||||
# Slot when validator activated
|
# Slot when validator activated
|
||||||
|
@ -537,7 +537,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# Status flags
|
# Status flags
|
||||||
'status_flags': 'uint64',
|
'status_flags': 'uint64',
|
||||||
# Custody commitment
|
# Custody commitment
|
||||||
'custody_commitment': 'hash32',
|
'custody_commitment': 'bytes32',
|
||||||
# Slot of latest custody reseed
|
# Slot of latest custody reseed
|
||||||
'latest_custody_reseed_slot': 'uint64',
|
'latest_custody_reseed_slot': 'uint64',
|
||||||
# Slot of second-latest custody reseed
|
# Slot of second-latest custody reseed
|
||||||
|
@ -552,7 +552,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
# Slot number
|
# Slot number
|
||||||
'slot': 'uint64',
|
'slot': 'uint64',
|
||||||
# Shard block root
|
# Shard block root
|
||||||
'shard_block_root': 'hash32',
|
'shard_block_root': 'bytes32',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -588,9 +588,9 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted
|
||||||
|
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
'latest_registry_delta_root': 'hash32',
|
'latest_registry_delta_root': 'bytes32',
|
||||||
'validator_index': 'uint24',
|
'validator_index': 'uint24',
|
||||||
'pubkey': 'uint384',
|
'pubkey': 'bytes48',
|
||||||
'slot': 'uint64',
|
'slot': 'uint64',
|
||||||
'flag': 'uint64',
|
'flag': 'uint64',
|
||||||
}
|
}
|
||||||
|
@ -808,7 +808,7 @@ def get_active_validator_indices(validators: [Validator], slot: int) -> List[int
|
||||||
#### `shuffle`
|
#### `shuffle`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def shuffle(values: List[Any], seed: Hash32) -> List[Any]:
|
def shuffle(values: List[Any], seed: Bytes32) -> List[Any]:
|
||||||
"""
|
"""
|
||||||
Returns the shuffled ``values`` with ``seed`` as entropy.
|
Returns the shuffled ``values`` with ``seed`` as entropy.
|
||||||
"""
|
"""
|
||||||
|
@ -888,7 +888,7 @@ def get_committee_count_per_slot(active_validator_count: int) -> int:
|
||||||
#### `get_shuffling`
|
#### `get_shuffling`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_shuffling(seed: Hash32,
|
def get_shuffling(seed: Bytes32,
|
||||||
validators: List[Validator],
|
validators: List[Validator],
|
||||||
slot: int) -> List[List[int]]
|
slot: int) -> List[List[int]]
|
||||||
"""
|
"""
|
||||||
|
@ -905,7 +905,7 @@ def get_shuffling(seed: Hash32,
|
||||||
committees_per_slot = get_committee_count_per_slot(len(active_validator_indices))
|
committees_per_slot = get_committee_count_per_slot(len(active_validator_indices))
|
||||||
|
|
||||||
# Shuffle
|
# Shuffle
|
||||||
seed = xor(seed, bytes32(slot))
|
seed = xor(seed, int_to_bytes32(slot))
|
||||||
shuffled_active_validator_indices = shuffle(active_validator_indices, seed)
|
shuffled_active_validator_indices = shuffle(active_validator_indices, seed)
|
||||||
|
|
||||||
# Split the shuffled list into epoch_length * committees_per_slot pieces
|
# Split the shuffled list into epoch_length * committees_per_slot pieces
|
||||||
|
@ -946,11 +946,12 @@ def get_crosslink_committees_at_slot(state: BeaconState,
|
||||||
"""
|
"""
|
||||||
Returns the list of ``(committee, shard)`` tuples for the ``slot``.
|
Returns the list of ``(committee, shard)`` tuples for the ``slot``.
|
||||||
"""
|
"""
|
||||||
earliest_slot = state.slot - (state.slot % EPOCH_LENGTH) - EPOCH_LENGTH
|
state_epoch_slot = state.slot - (state.slot % EPOCH_LENGTH)
|
||||||
assert earliest_slot <= slot < earliest_slot + EPOCH_LENGTH * 2
|
assert state_epoch_slot <= slot + EPOCH_LENGTH
|
||||||
|
assert slot < state_epoch_slot + EPOCH_LENGTH
|
||||||
offset = slot % EPOCH_LENGTH
|
offset = slot % EPOCH_LENGTH
|
||||||
|
|
||||||
if slot < earliest_slot + EPOCH_LENGTH:
|
if slot < state_epoch_slot:
|
||||||
committees_per_slot = get_previous_epoch_committee_count_per_slot(state)
|
committees_per_slot = get_previous_epoch_committee_count_per_slot(state)
|
||||||
shuffling = get_shuffling(
|
shuffling = get_shuffling(
|
||||||
state.previous_epoch_randao_mix,
|
state.previous_epoch_randao_mix,
|
||||||
|
@ -982,7 +983,7 @@ def get_crosslink_committees_at_slot(state: BeaconState,
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_block_root(state: BeaconState,
|
def get_block_root(state: BeaconState,
|
||||||
slot: int) -> Hash32:
|
slot: int) -> Bytes32:
|
||||||
"""
|
"""
|
||||||
Returns the block root at a recent ``slot``.
|
Returns the block root at a recent ``slot``.
|
||||||
"""
|
"""
|
||||||
|
@ -997,7 +998,7 @@ def get_block_root(state: BeaconState,
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_randao_mix(state: BeaconState,
|
def get_randao_mix(state: BeaconState,
|
||||||
slot: int) -> Hash32:
|
slot: int) -> Bytes32:
|
||||||
"""
|
"""
|
||||||
Returns the randao mix at a recent ``slot``.
|
Returns the randao mix at a recent ``slot``.
|
||||||
"""
|
"""
|
||||||
|
@ -1021,7 +1022,7 @@ def get_beacon_proposer_index(state: BeaconState,
|
||||||
#### `merkle_root`
|
#### `merkle_root`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def merkle_root(values: List[Hash32]) -> Hash32:
|
def merkle_root(values: List[Bytes32]) -> Bytes32:
|
||||||
"""
|
"""
|
||||||
Merkleize ``values`` (where ``len(values)`` is a power of two) and return the Merkle root.
|
Merkleize ``values`` (where ``len(values)`` is a power of two) and return the Merkle root.
|
||||||
"""
|
"""
|
||||||
|
@ -1057,9 +1058,9 @@ def get_attestation_participants(state: BeaconState,
|
||||||
return participants
|
return participants
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `bytes1`, `bytes2`, ...
|
#### `int_to_bytes1`, `int_to_bytes2`, ...
|
||||||
|
|
||||||
`bytes1(x): return x.to_bytes(1, 'big')`, `bytes2(x): return x.to_bytes(2, 'big')`, and so on for all integers, particularly 1, 2, 3, 4, 8, 32.
|
`int_to_bytes1(x): return x.to_bytes(1, 'big')`, `int_to_bytes2(x): return x.to_bytes(2, 'big')`, and so on for all integers, particularly 1, 2, 3, 4, 8, 32, 48, 96.
|
||||||
|
|
||||||
#### `get_effective_balance`
|
#### `get_effective_balance`
|
||||||
|
|
||||||
|
@ -1113,7 +1114,7 @@ def verify_slashable_vote_data(state: BeaconState, vote_data: SlashableVoteData)
|
||||||
signature=vote_data.aggregate_signature,
|
signature=vote_data.aggregate_signature,
|
||||||
domain=get_domain(
|
domain=get_domain(
|
||||||
state.fork,
|
state.fork,
|
||||||
state.slot,
|
vote_data.data.slot,
|
||||||
DOMAIN_ATTESTATION,
|
DOMAIN_ATTESTATION,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -1293,11 +1294,11 @@ First, a helper function:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def validate_proof_of_possession(state: BeaconState,
|
def validate_proof_of_possession(state: BeaconState,
|
||||||
pubkey: int,
|
pubkey: Bytes48,
|
||||||
proof_of_possession: bytes,
|
proof_of_possession: Bytes96,
|
||||||
withdrawal_credentials: Hash32,
|
withdrawal_credentials: Bytes32,
|
||||||
randao_commitment: Hash32,
|
randao_commitment: Bytes32,
|
||||||
custody_commitment: Hash32) -> bool:
|
custody_commitment: Bytes32) -> bool:
|
||||||
proof_of_possession_data = DepositInput(
|
proof_of_possession_data = DepositInput(
|
||||||
pubkey=pubkey,
|
pubkey=pubkey,
|
||||||
withdrawal_credentials=withdrawal_credentials,
|
withdrawal_credentials=withdrawal_credentials,
|
||||||
|
@ -1322,12 +1323,12 @@ Now, to add a [validator](#dfn-validator) or top up an existing [validator](#dfn
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def process_deposit(state: BeaconState,
|
def process_deposit(state: BeaconState,
|
||||||
pubkey: int,
|
pubkey: Bytes48,
|
||||||
amount: int,
|
amount: int,
|
||||||
proof_of_possession: bytes,
|
proof_of_possession: Bytes96,
|
||||||
withdrawal_credentials: Hash32,
|
withdrawal_credentials: Bytes32,
|
||||||
randao_commitment: Hash32,
|
randao_commitment: Bytes32,
|
||||||
custody_commitment: Hash32) -> None:
|
custody_commitment: Bytes32) -> None:
|
||||||
"""
|
"""
|
||||||
Process a deposit from Ethereum 1.0.
|
Process a deposit from Ethereum 1.0.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
|
@ -1362,8 +1363,7 @@ def process_deposit(state: BeaconState,
|
||||||
penultimate_custody_reseed_slot=GENESIS_SLOT,
|
penultimate_custody_reseed_slot=GENESIS_SLOT,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Note: In phase 2 registry indices that has been withdrawn for a long time will be recycled.
|
# Note: In phase 2 registry indices that have been withdrawn for a long time will be recycled.
|
||||||
index = len(state.validator_registry)
|
|
||||||
state.validator_registry.append(validator)
|
state.validator_registry.append(validator)
|
||||||
state.validator_balances.append(amount)
|
state.validator_balances.append(amount)
|
||||||
else:
|
else:
|
||||||
|
@ -1551,7 +1551,7 @@ For each `deposit` in `block.body.deposits`:
|
||||||
* 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`.
|
* 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
|
```python
|
||||||
def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool:
|
def verify_merkle_branch(leaf: Bytes32, branch: [Bytes32], depth: int, index: int, root: Bytes32) -> bool:
|
||||||
value = leaf
|
value = leaf
|
||||||
for i in range(depth):
|
for i in range(depth):
|
||||||
if index // (2**i) % 2:
|
if index // (2**i) % 2:
|
||||||
|
@ -1584,7 +1584,8 @@ For each `exit` in `block.body.exits`:
|
||||||
* Let `validator = state.validator_registry[exit.validator_index]`.
|
* Let `validator = state.validator_registry[exit.validator_index]`.
|
||||||
* Verify that `validator.exit_slot > state.slot + ENTRY_EXIT_DELAY`.
|
* Verify that `validator.exit_slot > state.slot + ENTRY_EXIT_DELAY`.
|
||||||
* Verify that `state.slot >= exit.slot`.
|
* Verify that `state.slot >= exit.slot`.
|
||||||
* Verify that `bls_verify(pubkey=validator.pubkey, message=ZERO_HASH, signature=exit.signature, domain=get_domain(state.fork, exit.slot, DOMAIN_EXIT))`.
|
* Let `exit_message = hash_tree_root(Exit(slot=exit.slot, validator_index=exit.validator_index, signature=EMPTY_SIGNATURE))`.
|
||||||
|
* Verify that `bls_verify(pubkey=validator.pubkey, message=exit_message, signature=exit.signature, domain=get_domain(state.fork, exit.slot, DOMAIN_EXIT))`.
|
||||||
* Run `initiate_validator_exit(state, exit.validator_index)`.
|
* Run `initiate_validator_exit(state, exit.validator_index)`.
|
||||||
|
|
||||||
#### Custody
|
#### Custody
|
||||||
|
@ -1606,34 +1607,34 @@ All [validators](#dfn-validator):
|
||||||
|
|
||||||
* Let `current_epoch_attestations = [a for a in state.latest_attestations if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]`. (Note: this is the set of attestations of slots in the epoch `state.slot-EPOCH_LENGTH...state.slot-1`, _not_ attestations that got included in the chain during the epoch `state.slot-EPOCH_LENGTH...state.slot-1`.)
|
* Let `current_epoch_attestations = [a for a in state.latest_attestations if state.slot - EPOCH_LENGTH <= a.data.slot < state.slot]`. (Note: this is the set of attestations of slots in the epoch `state.slot-EPOCH_LENGTH...state.slot-1`, _not_ attestations that got included in the chain during the epoch `state.slot-EPOCH_LENGTH...state.slot-1`.)
|
||||||
* Validators justifying the epoch boundary block at the start of the current epoch:
|
* Validators justifying the epoch boundary block at the start of the current epoch:
|
||||||
* Let `current_epoch_boundary_attestations = [a for a in current_epoch_attestations if a.data.epoch_boundary_root == get_block_root(state, state.slot-EPOCH_LENGTH) and a.justified_slot == state.justified_slot]`.
|
* Let `current_epoch_boundary_attestations = [a for a in current_epoch_attestations if a.data.epoch_boundary_root == get_block_root(state, state.slot-EPOCH_LENGTH) and a.data.justified_slot == state.justified_slot]`.
|
||||||
* Let `current_epoch_boundary_attester_indices` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_boundary_attestations]`.
|
* Let `current_epoch_boundary_attester_indices` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_boundary_attestations]`.
|
||||||
* Let `current_epoch_boundary_attesting_balance = sum([get_effective_balance(state, i) for i in current_epoch_boundary_attester_indices])`.
|
* Let `current_epoch_boundary_attesting_balance = sum([get_effective_balance(state, i) for i in current_epoch_boundary_attester_indices])`.
|
||||||
|
|
||||||
[Validators](#dfn-Validator) attesting during the previous epoch:
|
[Validators](#dfn-Validator) attesting during the previous epoch:
|
||||||
|
|
||||||
* Validators that made an attestation during the previous epoch:
|
* Validators that made an attestation during the previous epoch:
|
||||||
* Let `previous_epoch_attestations = [a for a in state.latest_attestations if state.slot - 2 * EPOCH_LENGTH <= a.slot < state.slot - EPOCH_LENGTH]`.
|
* Let `previous_epoch_attestations = [a for a in state.latest_attestations if state.slot - 2 * EPOCH_LENGTH <= a.data.slot < state.slot - EPOCH_LENGTH]`.
|
||||||
* Let `previous_epoch_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_attestations]`.
|
* Let `previous_epoch_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_attestations]`.
|
||||||
* Validators targeting the previous justified slot:
|
* Validators targeting the previous justified slot:
|
||||||
* Let `previous_epoch_justified_attestations = [a for a in current_epoch_attestations + previous_epoch_attestations if a.justified_slot == state.previous_justified_slot]`.
|
* Let `previous_epoch_justified_attestations = [a for a in current_epoch_attestations + previous_epoch_attestations if a.data.justified_slot == state.previous_justified_slot]`.
|
||||||
* Let `previous_epoch_justified_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_justified_attestations]`.
|
* Let `previous_epoch_justified_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_justified_attestations]`.
|
||||||
* Let `previous_epoch_justified_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_justified_attester_indices])`.
|
* Let `previous_epoch_justified_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_justified_attester_indices])`.
|
||||||
* Validators justifying the epoch boundary block at the start of the previous epoch:
|
* Validators justifying the epoch boundary block at the start of the previous epoch:
|
||||||
* Let `previous_epoch_boundary_attestations = [a for a in previous_epoch_justified_attestations if a.epoch_boundary_root == get_block_root(state, state.slot - 2 * EPOCH_LENGTH)]`.
|
* Let `previous_epoch_boundary_attestations = [a for a in previous_epoch_justified_attestations if a.data.epoch_boundary_root == get_block_root(state, state.slot - 2 * EPOCH_LENGTH)]`.
|
||||||
* Let `previous_epoch_boundary_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_boundary_attestations]`.
|
* Let `previous_epoch_boundary_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_boundary_attestations]`.
|
||||||
* Let `previous_epoch_boundary_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_boundary_attester_indices])`.
|
* Let `previous_epoch_boundary_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_boundary_attester_indices])`.
|
||||||
* Validators attesting to the expected beacon chain head during the previous epoch:
|
* Validators attesting to the expected beacon chain head during the previous epoch:
|
||||||
* Let `previous_epoch_head_attestations = [a for a in previous_epoch_attestations if a.beacon_block_root == get_block_root(state, a.slot)]`.
|
* Let `previous_epoch_head_attestations = [a for a in previous_epoch_attestations if a.data.beacon_block_root == get_block_root(state, a.data.slot)]`.
|
||||||
* Let `previous_epoch_head_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_head_attestations]`.
|
* Let `previous_epoch_head_attester_indices` be the union of the validator index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in previous_epoch_head_attestations]`.
|
||||||
* Let `previous_epoch_head_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_head_attester_indices])`.
|
* Let `previous_epoch_head_attesting_balance = sum([get_effective_balance(state, i) for i in previous_epoch_head_attester_indices])`.
|
||||||
|
|
||||||
**Note**: `previous_epoch_boundary_attesting_balance` balance might be marginally different than `current_epoch_boundary_attesting_balance` during the previous epoch transition. Due to the tight bound on validator churn each epoch and small per-epoch rewards/penalties, the potential balance difference is very low and only marginally affects consensus safety.
|
**Note**: `previous_epoch_boundary_attesting_balance` balance might be marginally different than `current_epoch_boundary_attesting_balance` during the previous epoch transition. Due to the tight bound on validator churn each epoch and small per-epoch rewards/penalties, the potential balance difference is very low and only marginally affects consensus safety.
|
||||||
|
|
||||||
For every `slot in range(state.slot - 2 * EPOCH_LENGTH, state.slot)`, let `crosslink_committee_at_slot = get_crosslink_committees_at_slot(slot)`. For every `(crosslink_committee, shard)` in `crosslink_committee_at_slot`, compute:
|
For every `slot in range(state.slot - 2 * EPOCH_LENGTH, state.slot)`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute:
|
||||||
|
|
||||||
* Let `shard_block_root` be `state.latest_crosslinks[shard].shard_block_root`
|
* Let `shard_block_root` be `state.latest_crosslinks[shard].shard_block_root`
|
||||||
* Let `attesting_validator_indices(crosslink_committee, shard_block_root)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_attestations + previous_epoch_attestations if a.shard == shard and a.shard_block_root == shard_block_root]`.
|
* Let `attesting_validator_indices(crosslink_committee, shard_block_root)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_attestations + previous_epoch_attestations if a.data.shard == shard and a.data.shard_block_root == shard_block_root]`.
|
||||||
* Let `winning_root(crosslink_committee)` be equal to the value of `shard_block_root` such that `sum([get_effective_balance(state, i) for i in attesting_validator_indices(crosslink_committee, shard_block_root)])` is maximized (ties broken by favoring lower `shard_block_root` values).
|
* Let `winning_root(crosslink_committee)` be equal to the value of `shard_block_root` such that `sum([get_effective_balance(state, i) for i in attesting_validator_indices(crosslink_committee, shard_block_root)])` is maximized (ties broken by favoring lower `shard_block_root` values).
|
||||||
* Let `attesting_validators(crosslink_committee)` be equal to `attesting_validator_indices(crosslink_committee, winning_root(crosslink_committee))` for convenience.
|
* Let `attesting_validators(crosslink_committee)` be equal to `attesting_validator_indices(crosslink_committee, winning_root(crosslink_committee))` for convenience.
|
||||||
* Let `total_attesting_balance(crosslink_committee) = sum([get_effective_balance(state, i) for i in attesting_validators(crosslink_committee)])`.
|
* Let `total_attesting_balance(crosslink_committee) = sum([get_effective_balance(state, i) for i in attesting_validators(crosslink_committee)])`.
|
||||||
|
@ -1666,7 +1667,7 @@ Set `state.finalized_slot = state.previous_justified_slot` if any of the followi
|
||||||
|
|
||||||
### Crosslinks
|
### Crosslinks
|
||||||
|
|
||||||
For every `slot in range(state.slot - 2 * EPOCH_LENGTH, state.slot)`, let `crosslink_committee_at_slot = get_crosslink_committees_at_slot(slot)`. For every `(crosslink_committee, shard)` in `crosslink_committee_at_slot`, compute:
|
For every `slot in range(state.slot - 2 * EPOCH_LENGTH, state.slot)`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute:
|
||||||
|
|
||||||
* Set `state.latest_crosslinks[shard] = Crosslink(slot=state.slot, shard_block_root=winning_root(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * total_balance(crosslink_committee)`.
|
* Set `state.latest_crosslinks[shard] = Crosslink(slot=state.slot, shard_block_root=winning_root(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * total_balance(crosslink_committee)`.
|
||||||
|
|
||||||
|
@ -1712,7 +1713,7 @@ For each `index` in `previous_epoch_attester_indices`, we determine the proposer
|
||||||
|
|
||||||
#### Crosslinks
|
#### Crosslinks
|
||||||
|
|
||||||
For every `i in range(state.slot - 2 * EPOCH_LENGTH, state.slot - EPOCH_LENGTH)`, let `crosslink_committee_at_slot, start_shard = get_crosslink_committees_at_slot(i)`. For every `j in range(len(crosslink_committee_at_slot))`, let `crosslink_committee = crosslink_committee_at_slot[j]`, `shard = (start_shard + j) % SHARD_COUNT`, and compute:
|
For every `slot in range(state.slot - 2 * EPOCH_LENGTH, state.slot - EPOCH_LENGTH)`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute:
|
||||||
|
|
||||||
* If `index in attesting_validators(crosslink_committee)`, `state.validator_balances[index] += base_reward(state, index) * total_attesting_balance(crosslink_committee) // total_balance(crosslink_committee))`.
|
* If `index in attesting_validators(crosslink_committee)`, `state.validator_balances[index] += base_reward(state, index) * total_attesting_balance(crosslink_committee) // total_balance(crosslink_committee))`.
|
||||||
* If `index not in attesting_validators(crosslink_committee)`, `state.validator_balances[index] -= base_reward(state, index)`.
|
* If `index not in attesting_validators(crosslink_committee)`, `state.validator_balances[index] -= base_reward(state, index)`.
|
||||||
|
|
|
@ -70,7 +70,7 @@ To validate a block header on shard `shard_id`, compute as follows:
|
||||||
* Verify that `beacon_chain_ref` is the hash of a block in the beacon chain with slot less than or equal to `slot`. Verify that `beacon_chain_ref` is equal to or a descendant of the `beacon_chain_ref` specified in the `ShardBlock` pointed to by `parent_root`.
|
* Verify that `beacon_chain_ref` is the hash of a block in the beacon chain with slot less than or equal to `slot`. Verify that `beacon_chain_ref` is equal to or a descendant of the `beacon_chain_ref` specified in the `ShardBlock` pointed to by `parent_root`.
|
||||||
* Let `state` be the state of the beacon chain block referred to by `beacon_chain_ref`. Let `validators` be `[validators[i] for i in state.current_persistent_committees[shard_id]]`.
|
* Let `state` be the state of the beacon chain block referred to by `beacon_chain_ref`. Let `validators` be `[validators[i] for i in state.current_persistent_committees[shard_id]]`.
|
||||||
* Assert `len(participation_bitfield) == ceil_div8(len(validators))`
|
* Assert `len(participation_bitfield) == ceil_div8(len(validators))`
|
||||||
* Let `proposer_index = hash(state.randao_mix + bytes8(shard_id) + bytes8(slot)) % len(validators)`. Let `msg` be the block but with the `block.signature` set to `[0, 0]`. Verify that `BLSVerify(pub=validators[proposer_index].pubkey, msg=hash(msg), sig=block.signature, domain=get_domain(state, slot, SHARD_PROPOSER_DOMAIN))` passes.
|
* Let `proposer_index = hash(state.randao_mix + int_to_bytes8(shard_id) + int_to_bytes8(slot)) % len(validators)`. Let `msg` be the block but with the `block.signature` set to `[0, 0]`. Verify that `BLSVerify(pub=validators[proposer_index].pubkey, msg=hash(msg), sig=block.signature, domain=get_domain(state, slot, SHARD_PROPOSER_DOMAIN))` passes.
|
||||||
* Generate the `group_public_key` by adding the public keys of all the validators for whom the corresponding position in the bitfield is set to 1. Verify that `BLSVerify(pub=group_public_key, msg=parent_root, sig=block.aggregate_signature, domain=get_domain(state, slot, SHARD_ATTESTER_DOMAIN))` passes.
|
* Generate the `group_public_key` by adding the public keys of all the validators for whom the corresponding position in the bitfield is set to 1. Verify that `BLSVerify(pub=group_public_key, msg=parent_root, sig=block.aggregate_signature, domain=get_domain(state, slot, SHARD_ATTESTER_DOMAIN))` passes.
|
||||||
|
|
||||||
### Block Merklization helper
|
### Block Merklization helper
|
||||||
|
|
Loading…
Reference in New Issue