Some initial changes

This commit is contained in:
Vitalik Buterin 2019-11-06 14:19:00 -08:00 committed by Danny Ryan
parent b6680d28bb
commit 8f34a0788d
No known key found for this signature in database
GPG Key ID: 2765A792E42CE07A
1 changed files with 29 additions and 22 deletions

View File

@ -13,7 +13,7 @@
- [Misc](#misc) - [Misc](#misc)
- [Containers](#containers) - [Containers](#containers)
- [`ShardBlockWrapper`](#shardblockwrapper) - [`ShardBlockWrapper`](#shardblockwrapper)
- [`ShardSignedHeader`](#shardsignedheader) - [`ShardSignableHeader`](#shardsignedheader)
- [`ShardState`](#shardstate) - [`ShardState`](#shardstate)
- [`AttestationData`](#attestationdata) - [`AttestationData`](#attestationdata)
- [`ShardTransition`](#shardtransition) - [`ShardTransition`](#shardtransition)
@ -28,7 +28,7 @@
- [`committee_to_compact_committee`](#committee_to_compact_committee) - [`committee_to_compact_committee`](#committee_to_compact_committee)
- [`get_light_client_committee`](#get_light_client_committee) - [`get_light_client_committee`](#get_light_client_committee)
- [`get_indexed_attestation`](#get_indexed_attestation) - [`get_indexed_attestation`](#get_indexed_attestation)
- [`update_gasprice`](#update_gasprice) - [`get_updated_gasprice`](#get_updated_gasprice)
- [`is_valid_indexed_attestation`](#is_valid_indexed_attestation) - [`is_valid_indexed_attestation`](#is_valid_indexed_attestation)
- [`get_attestation_shard`](#get_attestation_shard) - [`get_attestation_shard`](#get_attestation_shard)
- [Beacon Chain Changes](#beacon-chain-changes) - [Beacon Chain Changes](#beacon-chain-changes)
@ -77,6 +77,8 @@ This document describes the shard transition function (data layer only) and the
### `ShardBlockWrapper` ### `ShardBlockWrapper`
_Wrapper for being broadcasted over the network._
```python ```python
class ShardBlockWrapper(Container): class ShardBlockWrapper(Container):
shard_parent_root: Hash shard_parent_root: Hash
@ -86,10 +88,10 @@ class ShardBlockWrapper(Container):
signature: BLSSignature signature: BLSSignature
``` ```
### `ShardSignedHeader` ### `ShardSignableHeader`
```python ```python
class ShardSignedHeader(Container): class ShardSignableHeader(Container):
shard_parent_root: Hash shard_parent_root: Hash
beacon_parent_root: Hash beacon_parent_root: Hash
slot: Slot slot: Slot
@ -102,7 +104,7 @@ class ShardSignedHeader(Container):
class ShardState(Container): class ShardState(Container):
slot: Slot slot: Slot
gasprice: Gwei gasprice: Gwei
root: Hash data: Hash
latest_block_hash: Hash latest_block_hash: Hash
``` ```
@ -131,7 +133,7 @@ class ShardTransition(Container):
shard_block_lengths: List[uint64, MAX_SHARD_BLOCKS_PER_ATTESTATION] shard_block_lengths: List[uint64, MAX_SHARD_BLOCKS_PER_ATTESTATION]
# Shard data roots # Shard data roots
shard_data_roots: List[List[Hash, MAX_SHARD_BLOCK_CHUNKS], MAX_SHARD_BLOCKS_PER_ATTESTATION] shard_data_roots: List[List[Hash, MAX_SHARD_BLOCK_CHUNKS], MAX_SHARD_BLOCKS_PER_ATTESTATION]
# Intermediate state roots # Intermediate shard states
shard_states: List[ShardState, MAX_SHARD_BLOCKS_PER_ATTESTATION] shard_states: List[ShardState, MAX_SHARD_BLOCKS_PER_ATTESTATION]
# Proposer signature aggregate # Proposer signature aggregate
proposer_signature_aggregate: BLSSignature proposer_signature_aggregate: BLSSignature
@ -241,10 +243,10 @@ def get_indexed_attestation(beacon_state: BeaconState, attestation: Attestation)
return IndexedAttestation(committee, attestation) return IndexedAttestation(committee, attestation)
``` ```
### `update_gasprice` ### `get_updated_gasprice`
```python ```python
def update_gasprice(prev_gasprice: Gwei, length: uint8) -> Gwei: def get_updated_gasprice(prev_gasprice: Gwei, length: uint8) -> Gwei:
if length > BLOCK_SIZE_TARGET: if length > BLOCK_SIZE_TARGET:
delta = prev_gasprice * (length - BLOCK_SIZE_TARGET) // BLOCK_SIZE_TARGET // GASPRICE_ADJUSTMENT_COEFFICIENT delta = prev_gasprice * (length - BLOCK_SIZE_TARGET) // BLOCK_SIZE_TARGET // GASPRICE_ADJUSTMENT_COEFFICIENT
return min(prev_gasprice + delta, MAX_GASPRICE) return min(prev_gasprice + delta, MAX_GASPRICE)
@ -289,13 +291,20 @@ def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: Indexe
) )
``` ```
### `get_attestation_shard` ### `get_shard`
```python ```python
def get_shard(state: BeaconState, attestation: Attestation) -> Shard: def get_shard(state: BeaconState, attestation: Attestation) -> Shard:
return Shard((attestation.data.index + get_start_shard(state, data.slot)) % ACTIVE_SHARDS) return Shard((attestation.data.index + get_start_shard(state, data.slot)) % ACTIVE_SHARDS)
``` ```
### `get_offset_slots`
```python
def get_offset_slots(state: BeaconState, start_slot: Slot) -> Sequence[Slot]:
return [start_slot + x for x in SHARD_BLOCK_OFFSETS if start_slot + x < state.slot]
```
## Beacon Chain Changes ## Beacon Chain Changes
### New beacon state fields ### New beacon state fields
@ -333,16 +342,13 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None:
# Correct slot # Correct slot
assert data.slot == state.slot assert data.slot == state.slot
# Correct data root count # Correct data root count
start_slot = state.shard_next_slots[shard] assert len(attestation.custody_bits) == len(get_offset_slots(state, state.shard_next_slots[shard]))
offset_slots = [start_slot + x for x in SHARD_BLOCK_OFFSETS if start_slot + x < state.slot]
assert len(attestation.custody_bits) == len(offset_slots)
# Correct parent block root # Correct parent block root
assert data.beacon_block_root == get_block_root_at_slot(state, state.slot - 1) assert data.beacon_block_root == get_block_root_at_slot(state, state.slot - 1)
# Type 2: delayed attestations # Type 2: delayed attestations
else: else:
assert state.slot < data.slot + SLOTS_PER_EPOCH assert state.slot < data.slot + SLOTS_PER_EPOCH
assert data.shard_transition_root == Hash() assert data.shard_transition_root == Hash()
assert len(attestation.custody_bits) == 0
``` ```
#### `apply_shard_transition` #### `apply_shard_transition`
@ -353,7 +359,7 @@ def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTr
start_slot = state.shard_next_slots[shard] start_slot = state.shard_next_slots[shard]
# Correct data root count # Correct data root count
offset_slots = [start_slot + x for x in SHARD_BLOCK_OFFSETS if start_slot + x < state.slot] offset_slots = get_offset_slots(state, start_slot)
assert len(transition.shard_data_roots) == len(transition.shard_states) == len(transition.shard_block_lengths) == len(offset_slots) assert len(transition.shard_data_roots) == len(transition.shard_states) == len(transition.shard_block_lengths) == len(offset_slots)
assert transition.start_slot == start_slot assert transition.start_slot == start_slot
@ -366,7 +372,7 @@ def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTr
shard_parent_root = state.shard_states[shard].latest_block_hash shard_parent_root = state.shard_states[shard].latest_block_hash
for i in range(len(offset_slots)): for i in range(len(offset_slots)):
if any(transition.shard_data_roots): if any(transition.shard_data_roots):
headers.append(ShardSignedHeader( headers.append(ShardSignableHeader(
shard_parent_root=shard_parent_root, shard_parent_root=shard_parent_root,
parent_hash=get_block_root_at_slot(state, state.slot-1), parent_hash=get_block_root_at_slot(state, state.slot-1),
slot=offset_slots[i], slot=offset_slots[i],
@ -379,7 +385,7 @@ def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTr
prev_gasprice = state.shard_states[shard].gasprice prev_gasprice = state.shard_states[shard].gasprice
for i in range(len(offset_slots)): for i in range(len(offset_slots)):
shard_state, block_length, chunks = transition.shard_states[i], transition.shard_block_lengths[i], transition.shard_data_roots[i] shard_state, block_length, chunks = transition.shard_states[i], transition.shard_block_lengths[i], transition.shard_data_roots[i]
assert shard_state.gasprice == update_gasprice(prev_gasprice, block_length) assert shard_state.gasprice == get_updated_gasprice(prev_gasprice, block_length)
assert shard_state.slot == offset_slots[i] assert shard_state.slot == offset_slots[i]
assert len(chunks) == block_length // SHARD_BLOCK_CHUNK_SIZE assert len(chunks) == block_length // SHARD_BLOCK_CHUNK_SIZE
prev_gasprice = shard_state.gasprice prev_gasprice = shard_state.gasprice
@ -462,9 +468,6 @@ def misc_block_post_process(state: BeaconState, block: BeaconBlock) -> None:
for shard in range(MAX_SHARDS): for shard in range(MAX_SHARDS):
if state.shard_states[shard].slot != state.slot - 1: if state.shard_states[shard].slot != state.slot - 1:
assert block.shard_transition[shard] == ShardTransition() assert block.shard_transition[shard] == ShardTransition()
for pending_attestation in state.current_epoch_attestations + state.previous_epoch_attestations:
for index in get_attesting_indices(state, pending_attestation.data, pending_attestation.aggregation_bits):
state.online_countdown[index] = ONLINE_PERIOD
``` ```
### Light client processing ### Light client processing
@ -505,6 +508,11 @@ def phase_1_epoch_transition(state: BeaconState) -> None:
state.current_light_committee = state.next_light_committee state.current_light_committee = state.next_light_committee
new_committee = get_light_client_committee(state, get_current_epoch(state) + LIGHT_CLIENT_COMMITTEE_PERIOD) new_committee = get_light_client_committee(state, get_current_epoch(state) + LIGHT_CLIENT_COMMITTEE_PERIOD)
state.next_light_committee = committee_to_compact_committee(state, new_committee) state.next_light_committee = committee_to_compact_committee(state, new_committee)
# Process pending attestations
for pending_attestation in state.current_epoch_attestations + state.previous_epoch_attestations:
for index in get_attesting_indices(state, pending_attestation.data, pending_attestation.aggregation_bits):
state.online_countdown[index] = ONLINE_PERIOD
``` ```
## Fraud proofs ## Fraud proofs
@ -520,7 +528,7 @@ TODO. The intent is to have a single universal fraud proof type, which contains
The proof verifies that one of the two conditions is false: The proof verifies that one of the two conditions is false:
1. `custody_bits[i][j] != generate_custody_bit(subkey, block_contents)` for any `j` 1. `custody_bits[i][j] != generate_custody_bit(subkey, block_contents)` for any `j`
2. `execute_state_transition(shard, slot, transition.shard_states[i-1].root, hash_tree_root(parent), get_shard_proposer(state, shard, slot), block_contents) != transition.shard_states[i].root` (if `i=0` then instead use `parent.shard_states[shard][-1].root`) 2. `execute_state_transition(shard, slot, transition.shard_states[i-1].data, hash_tree_root(parent), get_shard_proposer(state, shard, slot), block_contents) != transition.shard_states[i].data` (if `i=0` then instead use `parent.shard_states[shard][-1].data`)
## Shard state transition function ## Shard state transition function
@ -535,8 +543,7 @@ def shard_state_transition(shard: Shard, slot: Slot, pre_state: Hash, previous_b
Suppose you are a committee member on shard `shard` at slot `current_slot`. Let `state` be the head beacon state you are building on. Three seconds into slot `slot`, run the following procedure: Suppose you are a committee member on shard `shard` at slot `current_slot`. Let `state` be the head beacon state you are building on. Three seconds into slot `slot`, run the following procedure:
* Initialize `proposals = []`, `shard_states = []`, `shard_state = state.shard_states[shard][-1]`, `start_slot = shard_state.slot`. * Initialize `proposals = []`, `shard_states = []`, `shard_state = state.shard_states[shard][-1]`, `start_slot = shard_state.slot`.
* Let `offset_slots = [start_slot + x for x in SHARD_BLOCK_OFFSETS if start_slot + x < state.slot]` * For `slot in get_offset_slots(state, start_slot)`, do the following:
* For `slot in offset_slots`, do the following:
* Look for all valid proposals for `slot`; that is, a Bytes `proposal` where `shard_state_transition(shard, slot, shard_state, get_block_root_at_slot(state, state.slot - 1), get_shard_proposer(state, shard, slot), proposal)` returns a result and does not throw an exception. Let `choices` be the set of non-empty valid proposals you discover. * Look for all valid proposals for `slot`; that is, a Bytes `proposal` where `shard_state_transition(shard, slot, shard_state, get_block_root_at_slot(state, state.slot - 1), get_shard_proposer(state, shard, slot), proposal)` returns a result and does not throw an exception. Let `choices` be the set of non-empty valid proposals you discover.
* If `len(choices) == 0`, do `proposals.append(make_empty_proposal(shard_state, slot))` * If `len(choices) == 0`, do `proposals.append(make_empty_proposal(shard_state, slot))`
* If `len(choices) == 1`, do `proposals.append(choices[0])` * If `len(choices) == 1`, do `proposals.append(choices[0])`