Merge branch 'dev' into JustinDrake-patch-1
This commit is contained in:
commit
9eb3be5471
|
@ -180,7 +180,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
|
||||||
### Misc
|
### Misc
|
||||||
|
|
||||||
| Name | Value |
|
| Name | Value |
|
||||||
| - | - | :-: |
|
| - | - |
|
||||||
| `SHARD_COUNT` | `2**10` (= 1,024) |
|
| `SHARD_COUNT` | `2**10` (= 1,024) |
|
||||||
| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) |
|
| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) |
|
||||||
| `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) |
|
| `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) |
|
||||||
|
@ -997,6 +997,7 @@ def get_beacon_proposer_index(state: BeaconState,
|
||||||
def merkle_root(values: List[Bytes32]) -> Bytes32:
|
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.
|
||||||
|
Note that the leaves are not hashed.
|
||||||
"""
|
"""
|
||||||
o = [0] * len(values) + values
|
o = [0] * len(values) + values
|
||||||
for i in range(len(values) - 1, 0, -1):
|
for i in range(len(values) - 1, 0, -1):
|
||||||
|
@ -1170,7 +1171,7 @@ def verify_slashable_attestation(state: BeaconState, slashable_attestation: Slas
|
||||||
hash_tree_root(AttestationDataAndCustodyBit(data=slashable_attestation.data, custody_bit=0b1)),
|
hash_tree_root(AttestationDataAndCustodyBit(data=slashable_attestation.data, custody_bit=0b1)),
|
||||||
],
|
],
|
||||||
signature=slashable_attestation.aggregate_signature,
|
signature=slashable_attestation.aggregate_signature,
|
||||||
domain=get_domain(state.fork, slot_to_epoch(vote_data.data.slot), DOMAIN_ATTESTATION),
|
domain=get_domain(state.fork, slot_to_epoch(slashable_attestation.data.slot), DOMAIN_ATTESTATION),
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1347,9 +1348,9 @@ def slash_validator(state: BeaconState, index: ValidatorIndex) -> None:
|
||||||
Slash the validator with index ``index``.
|
Slash the validator with index ``index``.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
assert state.slot < validator.withdrawable_epoch # [TO BE REMOVED IN PHASE 2]
|
|
||||||
exit_validator(state, index)
|
|
||||||
validator = state.validator_registry[index]
|
validator = state.validator_registry[index]
|
||||||
|
assert state.slot < get_epoch_start_slot(validator.withdrawable_epoch) # [TO BE REMOVED IN PHASE 2]
|
||||||
|
exit_validator(state, index)
|
||||||
state.latest_slashed_balances[get_current_epoch(state) % LATEST_SLASHED_EXIT_LENGTH] += get_effective_balance(state, index)
|
state.latest_slashed_balances[get_current_epoch(state) % LATEST_SLASHED_EXIT_LENGTH] += get_effective_balance(state, index)
|
||||||
|
|
||||||
whistleblower_index = get_beacon_proposer_index(state, state.slot)
|
whistleblower_index = get_beacon_proposer_index(state, state.slot)
|
||||||
|
@ -1524,7 +1525,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 parent block with root `block.parent_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.
|
* An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` has been processed and accepted.
|
||||||
* 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.)
|
* The node's Unix time is greater than or equal to `state.genesis_time + (block.slot - GENESIS_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.)
|
||||||
|
|
||||||
If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied.
|
If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied.
|
||||||
|
|
||||||
|
@ -1634,7 +1635,7 @@ Below are the processing steps that happen at every `block`.
|
||||||
|
|
||||||
#### Eth1 data
|
#### Eth1 data
|
||||||
|
|
||||||
* If there exists an `eth1_data_vote` in `states.eth1_data_votes` for which `eth1_data_vote.eth1_data == block.eth1_data` (there will be at most one), set `eth1_data_vote.vote_count += 1`.
|
* If there exists an `eth1_data_vote` in `state.eth1_data_votes` for which `eth1_data_vote.eth1_data == block.eth1_data` (there will be at most one), 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)`.
|
* Otherwise, append to `state.eth1_data_votes` a new `Eth1DataVote(eth1_data=block.eth1_data, vote_count=1)`.
|
||||||
|
|
||||||
#### Transactions
|
#### Transactions
|
||||||
|
@ -2058,7 +2059,7 @@ def process_exit_queue(state: BeaconState) -> None:
|
||||||
|
|
||||||
#### Final updates
|
#### Final updates
|
||||||
|
|
||||||
* Set `state.latest_active_index_roots[(next_epoch + ACTIVATION_EXIT_DELAY) % LATEST_ACTIVE_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, next_epoch + ACTIVATION_EXIT_DELAY))`.
|
* Set `state.latest_active_index_roots[(next_epoch + ACTIVATION_EXIT_DELAY) % LATEST_ACTIVE_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state.validator_registry, next_epoch + ACTIVATION_EXIT_DELAY))`.
|
||||||
* Set `state.latest_slashed_balances[(next_epoch) % LATEST_SLASHED_EXIT_LENGTH] = state.latest_slashed_balances[current_epoch % LATEST_SLASHED_EXIT_LENGTH]`.
|
* Set `state.latest_slashed_balances[(next_epoch) % LATEST_SLASHED_EXIT_LENGTH] = state.latest_slashed_balances[current_epoch % LATEST_SLASHED_EXIT_LENGTH]`.
|
||||||
* Set `state.latest_randao_mixes[next_epoch % LATEST_RANDAO_MIXES_LENGTH] = get_randao_mix(state, current_epoch)`.
|
* Set `state.latest_randao_mixes[next_epoch % LATEST_RANDAO_MIXES_LENGTH] = get_randao_mix(state, current_epoch)`.
|
||||||
* Remove any `attestation` in `state.latest_attestations` such that `slot_to_epoch(attestation.data.slot) < current_epoch`.
|
* Remove any `attestation` in `state.latest_attestations` such that `slot_to_epoch(attestation.data.slot) < current_epoch`.
|
||||||
|
|
|
@ -47,8 +47,8 @@ def get_split_offset(list_size: int, chunks: int, index: int) -> int:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_shuffled_committee(state: BeaconState,
|
def get_shuffled_committee(state: BeaconState,
|
||||||
shard: ShardNumber,
|
shard: Shard,
|
||||||
committee_start_epoch: EpochNumber) -> List[ValidatorIndex]:
|
committee_start_epoch: Epoch) -> List[ValidatorIndex]:
|
||||||
"""
|
"""
|
||||||
Return shuffled committee.
|
Return shuffled committee.
|
||||||
"""
|
"""
|
||||||
|
@ -66,8 +66,8 @@ def get_shuffled_committee(state: BeaconState,
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_persistent_committee(state: BeaconState,
|
def get_persistent_committee(state: BeaconState,
|
||||||
shard: ShardNumber,
|
shard: Shard,
|
||||||
epoch: EpochNumber) -> List[ValidatorIndex]:
|
epoch: Epoch) -> List[ValidatorIndex]:
|
||||||
"""
|
"""
|
||||||
Return the persistent committee for the given ``shard`` at the given ``epoch``.
|
Return the persistent committee for the given ``shard`` at the given ``epoch``.
|
||||||
"""
|
"""
|
||||||
|
@ -94,10 +94,10 @@ def get_persistent_committee(state: BeaconState,
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_shard_proposer_index(state: BeaconState,
|
def get_shard_proposer_index(state: BeaconState,
|
||||||
shard: ShardNumber,
|
shard: Shard,
|
||||||
slot: SlotNumber) -> ValidatorIndex:
|
slot: Slot) -> ValidatorIndex:
|
||||||
seed = hash(
|
seed = hash(
|
||||||
state.current_epoch_seed +
|
state.current_shuffling_seed +
|
||||||
int_to_bytes8(shard) +
|
int_to_bytes8(shard) +
|
||||||
int_to_bytes8(slot)
|
int_to_bytes8(slot)
|
||||||
)
|
)
|
||||||
|
@ -177,8 +177,8 @@ A node should sign a crosslink only if the following conditions hold. **If a nod
|
||||||
First, the conditions must recursively apply to the crosslink referenced in `last_crosslink_root` for the same shard (unless `last_crosslink_root` equals zero, in which case we are at the genesis).
|
First, the conditions must recursively apply to the crosslink referenced in `last_crosslink_root` for the same shard (unless `last_crosslink_root` equals zero, in which case we are at the genesis).
|
||||||
|
|
||||||
Second, we verify the `shard_chain_commitment`.
|
Second, we verify the `shard_chain_commitment`.
|
||||||
* Let `start_slot = state.latest_crosslinks[shard].epoch * EPOCH_LENGTH + EPOCH_LENGTH - CROSSLINK_LOOKBACK`.
|
* Let `start_slot = state.latest_crosslinks[shard].epoch * SLOTS_PER_EPOCH + SLOTS_PER_EPOCH - CROSSLINK_LOOKBACK`.
|
||||||
* Let `end_slot = attestation.data.slot - attestation.data.slot % EPOCH_LENGTH - CROSSLINK_LOOKBACK`.
|
* Let `end_slot = attestation.data.slot - attestation.data.slot % SLOTS_PER_EPOCH - CROSSLINK_LOOKBACK`.
|
||||||
* Let `length = end_slot - start_slot`, `headers[0] .... headers[length-1]` be the serialized block headers in the canonical shard chain from the verifer's point of view (note that this implies that `headers` and `bodies` have been checked for validity).
|
* Let `length = end_slot - start_slot`, `headers[0] .... headers[length-1]` be the serialized block headers in the canonical shard chain from the verifer's point of view (note that this implies that `headers` and `bodies` have been checked for validity).
|
||||||
* Let `bodies[0] ... bodies[length-1]` be the bodies of the blocks.
|
* Let `bodies[0] ... bodies[length-1]` be the bodies of the blocks.
|
||||||
* Note: If there is a missing slot, then the header and body are the same as that of the block at the most recent slot that has a block.
|
* Note: If there is a missing slot, then the header and body are the same as that of the block at the most recent slot that has a block.
|
||||||
|
|
|
@ -29,6 +29,7 @@ deserializing objects and data types.
|
||||||
- [`uint264`..`uintN`, `bytes33`..`bytesN`](#uint264uintn-bytes33bytesn)
|
- [`uint264`..`uintN`, `bytes33`..`bytesN`](#uint264uintn-bytes33bytesn)
|
||||||
- [List/Vectors](#listvectors-2)
|
- [List/Vectors](#listvectors-2)
|
||||||
- [Container](#container-2)
|
- [Container](#container-2)
|
||||||
|
+ [Signed Roots](#signed-roots)
|
||||||
* [Implementations](#implementations)
|
* [Implementations](#implementations)
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
@ -396,6 +397,14 @@ Recursively tree hash the values in the container in the same order as the field
|
||||||
return merkle_hash([hash_tree_root_internal(getattr(x, field)) for field in value.fields])
|
return merkle_hash([hash_tree_root_internal(getattr(x, field)) for field in value.fields])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Signed roots
|
||||||
|
|
||||||
|
Let `field_name` be a field name in an SSZ container `container`. We define `truncate(container, field_name)` to be the `container` with the fields from `field_name` onwards truncated away. That is, `truncate(container, field_name) = [getattr(container, field)) for field in value.fields[:i]]` where `i = value.fields.index(field_name)`.
|
||||||
|
|
||||||
|
When `field_name` maps to a signature (e.g. a BLS12-381 signature of type `Bytes96`) the convention is that the corresponding signed message be `signed_root(container, field_name) = hash_tree_root(truncate(container, field_name))`. For example if `container = {"foo": sub_object_1, "bar": sub_object_2, "signature": bytes96, "baz": sub_object_3}` then `signed_root(container, "signature") = merkle_hash([hash_tree_root(sub_object_1), hash_tree_root(sub_object_2)])`.
|
||||||
|
|
||||||
|
Note that this convention means that fields after the signature are _not_ signed over. If there are multiple signatures in `container` then those are expected to be signing over the fields in the order specified. If multiple signatures of the same value are expected the convention is that the signature field be an array of signatures.
|
||||||
|
|
||||||
## Implementations
|
## Implementations
|
||||||
|
|
||||||
| Language | Implementation | Description |
|
| Language | Implementation | Description |
|
||||||
|
|
|
@ -34,7 +34,7 @@ __NOTICE__: This document is a work-in-progress for researchers and implementers
|
||||||
- [Attester slashings](#attester-slashings)
|
- [Attester slashings](#attester-slashings)
|
||||||
- [Attestations](#attestations)
|
- [Attestations](#attestations)
|
||||||
- [Deposits](#deposits)
|
- [Deposits](#deposits)
|
||||||
- [Exits](#exits)
|
- [Voluntary exits](#voluntary-exits)
|
||||||
- [Attestations](#attestations-1)
|
- [Attestations](#attestations-1)
|
||||||
- [Attestation data](#attestation-data)
|
- [Attestation data](#attestation-data)
|
||||||
- [Slot](#slot-1)
|
- [Slot](#slot-1)
|
||||||
|
@ -118,7 +118,7 @@ Once a validator has been processed and added to the beacon state's `validator_r
|
||||||
|
|
||||||
### Activation
|
### Activation
|
||||||
|
|
||||||
In normal operation, the validator is quickly activated at which point the validator is added to the shuffling and begins validation after an additional `ENTRY_EXIT_DELAY` epochs (25.6 minutes).
|
In normal operation, the validator is quickly activated at which point the validator is added to the shuffling and begins validation after an additional `ACTIVATION_EXIT_DELAY` epochs (25.6 minutes).
|
||||||
|
|
||||||
The function [`is_active_validator`](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#is_active_validator) can be used to check if a validator is active during a given epoch. Usage is as follows:
|
The function [`is_active_validator`](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#is_active_validator) can be used to check if a validator is active during a given epoch. Usage is as follows:
|
||||||
|
|
||||||
|
@ -232,15 +232,15 @@ Up to `MAX_ATTESTATIONS` aggregate attestations can be included in the `block`.
|
||||||
|
|
||||||
Up to `MAX_DEPOSITS` [`Deposit`](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#deposit) objects can be included in the `block`. These deposits are constructed from the `Deposit` logs from the [Eth1.0 deposit contract](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#ethereum-10-deposit-contract) and must be processed in sequential order. The deposits included in the `block` must satisfy the verification conditions found in [deposits processing](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#deposits-1).
|
Up to `MAX_DEPOSITS` [`Deposit`](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#deposit) objects can be included in the `block`. These deposits are constructed from the `Deposit` logs from the [Eth1.0 deposit contract](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#ethereum-10-deposit-contract) and must be processed in sequential order. The deposits included in the `block` must satisfy the verification conditions found in [deposits processing](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#deposits-1).
|
||||||
|
|
||||||
##### Exits
|
##### Voluntary exits
|
||||||
|
|
||||||
Up to `MAX_EXITS` [`Exit`](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#exit) objects can be included in the `block`. The exits must satisfy the verification conditions found in [exits processing](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#exits-1).
|
Up to `MAX_VOLUNTARY_EXITS` [`VoluntaryExit`](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#voluntaryexit) objects can be included in the `block`. The exits must satisfy the verification conditions found in [exits processing](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#exits-1).
|
||||||
|
|
||||||
### Attestations
|
### Attestations
|
||||||
|
|
||||||
A validator is expected to create, sign, and broadcast an attestation during each epoch. The slot during which the validator performs this role is any slot at which `get_crosslink_committees_at_slot(state, slot)` contains a committee that contains `validator_index`.
|
A validator is expected to create, sign, and broadcast an attestation during each epoch. The slot during which the validator performs this role is any slot at which `get_crosslink_committees_at_slot(state, slot)` contains a committee that contains `validator_index`.
|
||||||
|
|
||||||
A validator should create and broadcast the attestation halfway through the `slot` during which the validator is assigned -- that is `SLOT_DURATION * 0.5` seconds after the start of `slot`.
|
A validator should create and broadcast the attestation halfway through the `slot` during which the validator is assigned -- that is `SECONDS_PER_SLOT * 0.5` seconds after the start of `slot`.
|
||||||
|
|
||||||
#### Attestation data
|
#### Attestation data
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is determi
|
||||||
def get_next_epoch_committee_assignment(
|
def get_next_epoch_committee_assignment(
|
||||||
state: BeaconState,
|
state: BeaconState,
|
||||||
validator_index: ValidatorIndex,
|
validator_index: ValidatorIndex,
|
||||||
registry_change: bool) -> Tuple[List[ValidatorIndex], ShardNumber, SlotNumber, bool]:
|
registry_change: bool) -> Tuple[List[ValidatorIndex], Shard, Slot, bool]:
|
||||||
"""
|
"""
|
||||||
Return the committee assignment in the next epoch for ``validator_index`` and ``registry_change``.
|
Return the committee assignment in the next epoch for ``validator_index`` and ``registry_change``.
|
||||||
``assignment`` returned is a tuple of the following form:
|
``assignment`` returned is a tuple of the following form:
|
||||||
|
@ -360,14 +360,14 @@ def get_next_epoch_committee_assignment(
|
||||||
current_epoch = get_current_epoch(state)
|
current_epoch = get_current_epoch(state)
|
||||||
next_epoch = current_epoch + 1
|
next_epoch = current_epoch + 1
|
||||||
next_epoch_start_slot = get_epoch_start_slot(next_epoch)
|
next_epoch_start_slot = get_epoch_start_slot(next_epoch)
|
||||||
for slot in range(next_epoch_start_slot, next_epoch_start_slot + EPOCH_LENGTH):
|
for slot in range(next_epoch_start_slot, next_epoch_start_slot + SLOTS_PER_EPOCH):
|
||||||
crosslink_committees = get_crosslink_committees_at_slot(
|
crosslink_committees = get_crosslink_committees_at_slot(
|
||||||
state,
|
state,
|
||||||
slot,
|
slot,
|
||||||
registry_change=registry_change,
|
registry_change=registry_change,
|
||||||
)
|
)
|
||||||
selected_committees = [
|
selected_committees = [
|
||||||
committee # Tuple[List[ValidatorIndex], ShardNumber]
|
committee # Tuple[List[ValidatorIndex], Shard]
|
||||||
for committee in crosslink_committees
|
for committee in crosslink_committees
|
||||||
if validator_index in committee[0]
|
if validator_index in committee[0]
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue