mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-01-20 07:29:02 +00:00
Second pass
This commit is contained in:
parent
d02a6422e3
commit
f75ea377d5
@ -37,6 +37,7 @@ We define the following Python custom types for type hinting and readability:
|
||||
| `MAX_SHARDS` | `uint64(2**10)` (= 1024) | Theoretical max shard count (used to determine data structure sizes) |
|
||||
| `INITIAL_ACTIVE_SHARDS` | `uint64(2**6)` (= 64) | Initial shard count |
|
||||
| `GASPRICE_ADJUSTMENT_COEFFICIENT` | `uint64(2**3)` (= 2) | Gasprice may decrease/increase by at most exp(1 / this value) *per epoch* |
|
||||
| `MAX_SHARD_HEADERS` | `MAX_SHARDS * 4` | |
|
||||
|
||||
### Shard block configs
|
||||
|
||||
@ -50,6 +51,7 @@ We define the following Python custom types for type hinting and readability:
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `G2_ONE` | The G2 generator |
|
||||
| `SIZE_CHECK_POINTS` | Type `List[G2, MAX_SAMPLES_PER_BLOCK + 1]`; TO BE COMPUTED |
|
||||
|
||||
These points are the G2-side Kate commitments to `product[a in i...MAX_SAMPLES_PER_BLOCK] (X - w ** revbit(a))` for each `i` in `[0...MAX_SAMPLES_PER_BLOCK]`, where `w` is the root of unity and `revbit` is the reverse-bit-order function. They are used to verify block size proofs. They can be computed with a one-time O(N^2/log(N)) calculation using fast-linear-combinations in G2.
|
||||
@ -92,6 +94,13 @@ class AttestationData(Container):
|
||||
shard_header_root: Root
|
||||
```
|
||||
|
||||
### `BeaconBlock`
|
||||
|
||||
```python
|
||||
class BeaconBlock(phase0.BeaconBlock):
|
||||
shard_headers: List[Signed[ShardHeader], MAX_SHARD_HEADERS]
|
||||
```
|
||||
|
||||
### `BeaconState`
|
||||
|
||||
```python
|
||||
@ -100,6 +109,7 @@ class BeaconState(phase0.BeaconState):
|
||||
previous_epoch_pending_headers: List[PendingHeader, MAX_PENDING_HEADERS * SLOTS_PER_EPOCH]
|
||||
confirmed_header_root: Root
|
||||
shard_gasprice: uint64
|
||||
current_epoch_start_shard: Shard
|
||||
```
|
||||
|
||||
## New containers
|
||||
@ -201,7 +211,7 @@ def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64:
|
||||
Return the number of committees in each slot for the given ``epoch``.
|
||||
"""
|
||||
return max(uint64(1), min(
|
||||
get_active_shard_count(state),
|
||||
get_active_shard_count(state, epoch),
|
||||
uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
|
||||
))
|
||||
```
|
||||
@ -209,7 +219,7 @@ def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64:
|
||||
#### `get_active_shard_count`
|
||||
|
||||
```python
|
||||
def get_active_shard_count(state: BeaconState) -> uint64:
|
||||
def get_active_shard_count(state: BeaconState, epoch: Epoch) -> uint64:
|
||||
"""
|
||||
Return the number of active shards.
|
||||
Note that this puts an upper bound on the number of committees per slot.
|
||||
@ -231,7 +241,7 @@ def get_shard_committee(beacon_state: BeaconState, epoch: Epoch, shard: Shard) -
|
||||
indices=active_validator_indices,
|
||||
seed=seed,
|
||||
index=shard,
|
||||
count=get_active_shard_count(beacon_state),
|
||||
count=get_active_shard_count(beacon_state, epoch),
|
||||
)
|
||||
```
|
||||
|
||||
@ -245,21 +255,7 @@ def get_shard_proposer_index(beacon_state: BeaconState, slot: Slot, shard: Shard
|
||||
epoch = compute_epoch_at_slot(slot)
|
||||
committee = get_shard_committee(beacon_state, epoch, shard)
|
||||
seed = hash(get_seed(beacon_state, epoch, DOMAIN_SHARD_COMMITTEE) + uint_to_bytes(slot))
|
||||
r = bytes_to_uint64(seed[:8])
|
||||
return committee[r % len(committee)]
|
||||
```
|
||||
|
||||
#### `get_committee_count_delta`
|
||||
|
||||
```python
|
||||
def get_committee_count_delta(state: BeaconState, start_slot: Slot, stop_slot: Slot) -> uint64:
|
||||
"""
|
||||
Return the sum of committee counts in range ``[start_slot, stop_slot)``.
|
||||
"""
|
||||
return uint64(sum(
|
||||
get_committee_count_per_slot(state, compute_epoch_at_slot(Slot(slot)))
|
||||
for slot in range(start_slot, stop_slot)
|
||||
))
|
||||
return compute_proposer_index(state, committee, seed)
|
||||
```
|
||||
|
||||
#### `get_start_shard`
|
||||
@ -270,26 +266,24 @@ def get_start_shard(state: BeaconState, slot: Slot) -> Shard:
|
||||
Return the start shard at ``slot``.
|
||||
"""
|
||||
current_epoch_start_slot = compute_start_slot_at_epoch(get_current_epoch(state))
|
||||
active_shard_count = get_active_shard_count(state)
|
||||
if current_epoch_start_slot == slot:
|
||||
return state.current_epoch_start_shard
|
||||
elif slot > current_epoch_start_slot:
|
||||
shard = state.current_epoch_start_shard
|
||||
if slot > current_epoch_start_slot:
|
||||
# Current epoch or the next epoch lookahead
|
||||
shard_delta = get_committee_count_delta(state, start_slot=current_epoch_start_slot, stop_slot=slot)
|
||||
return Shard((state.current_epoch_start_shard + shard_delta) % active_shard_count)
|
||||
else:
|
||||
for _slot in range(current_epoch_start_slot, slot):
|
||||
committee_count = get_committee_count_per_slot(state, compute_epoch_at_slot(Slot(_slot)))
|
||||
active_shard_count = get_active_shard_count(state, compute_epoch_at_slot(Slot(_slot)))
|
||||
shard = (shard + committee_count) % active_shard_count
|
||||
return Shard(shard)
|
||||
elif slot < current_epoch_start_slot:
|
||||
# Previous epoch
|
||||
shard_delta = get_committee_count_delta(state, start_slot=slot, stop_slot=current_epoch_start_slot)
|
||||
max_committees_per_slot = active_shard_count
|
||||
max_committees_in_span = max_committees_per_slot * (current_epoch_start_slot - slot)
|
||||
return Shard(
|
||||
for _slot in list(range(slot, current_epoch_start_slot))[::-1]:
|
||||
committee_count = get_committee_count_per_slot(state, compute_epoch_at_slot(Slot(_slot)))
|
||||
active_shard_count = get_active_shard_count(state, compute_epoch_at_slot(Slot(_slot)))
|
||||
# Ensure positive
|
||||
(state.current_epoch_start_shard + max_committees_in_span - shard_delta)
|
||||
% active_shard_count
|
||||
)
|
||||
shard = (shard + active_shard_count - committee_count) % active_shard_count
|
||||
return Shard(shard)
|
||||
```
|
||||
|
||||
|
||||
### Predicates
|
||||
|
||||
### Block processing
|
||||
@ -320,6 +314,9 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
for_ops(body.attestations, process_attestation)
|
||||
for_ops(body.deposits, process_deposit)
|
||||
for_ops(body.voluntary_exits, process_voluntary_exit)
|
||||
# Limit is dynamic based on active shard count
|
||||
assert len(body.shard_headers) <= 4 * get_active_shard_count(state, get_current_epoch(state))
|
||||
for_ops(body.shard_headers, process_shard_header)
|
||||
|
||||
# See custody game spec.
|
||||
process_custody_game_operations(state, body)
|
||||
@ -349,18 +346,16 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||
```python
|
||||
def update_pending_votes(state: BeaconState,
|
||||
attestation: Attestation) -> None:
|
||||
if slot_to_epoch(slot) == get_current_epoch(state):
|
||||
if compute_epoch_at_slot(slot) == get_current_epoch(state):
|
||||
pending_headers = state.current_epoch_pending_headers
|
||||
else:
|
||||
pending_headers = state.previous_epoch_pending_headers
|
||||
# Create or update the PendingShardHeader object
|
||||
pending_header_index = None
|
||||
for index, header in enumerate(pending_headers):
|
||||
pending_header = None
|
||||
for header in pending_headers:
|
||||
if header.root == attestation.data.shard_header_root:
|
||||
pending_header_index = index
|
||||
break
|
||||
assert pending_header_index is not None
|
||||
pending_header = pending_headers[pending_header_index]
|
||||
pending_header = header
|
||||
assert pending_header is not None
|
||||
assert pending_header.slot == attestation.data.slot + 1
|
||||
assert pending_header.shard == compute_shard_from_committee_index(
|
||||
state,
|
||||
@ -388,11 +383,11 @@ def update_pending_votes(state: BeaconState,
|
||||
pending_header.confirmed = True
|
||||
```
|
||||
|
||||
#### `process_shard_data_commitment`
|
||||
#### `process_shard_header`
|
||||
|
||||
```python
|
||||
def process_shard_data_commitment(state: BeaconState,
|
||||
signed_header: Signed[ShardDataHeader]) -> None:
|
||||
def process_shard_header(state: BeaconState,
|
||||
signed_header: Signed[ShardDataHeader]) -> None:
|
||||
header = signed_header.message
|
||||
header_root = hash_tree_root(header)
|
||||
# Verify signature
|
||||
@ -408,7 +403,7 @@ def process_shard_data_commitment(state: BeaconState,
|
||||
bls.Pairing(header.commitment, G2_ONE)
|
||||
)
|
||||
# Get the correct pending header list
|
||||
if slot_to_epoch(header.slot) == get_current_epoch(state):
|
||||
if compute_epoch_at_slot(header.slot) == get_current_epoch(state):
|
||||
pending_headers = state.current_epoch_pending_headers
|
||||
else:
|
||||
pending_headers = state.previous_epoch_pending_headers
|
||||
@ -431,31 +426,6 @@ def process_shard_data_commitment(state: BeaconState,
|
||||
|
||||
### Shard transition processing
|
||||
|
||||
|
||||
##### New default validator for deposits
|
||||
|
||||
```python
|
||||
def get_validator_from_deposit(state: BeaconState, deposit: Deposit) -> Validator:
|
||||
amount = deposit.data.amount
|
||||
effective_balance = min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||
next_custody_secret_to_reveal = get_custody_period_for_validator(
|
||||
ValidatorIndex(len(state.validators)),
|
||||
get_current_epoch(state),
|
||||
)
|
||||
|
||||
return Validator(
|
||||
pubkey=deposit.data.pubkey,
|
||||
withdrawal_credentials=deposit.data.withdrawal_credentials,
|
||||
activation_eligibility_epoch=FAR_FUTURE_EPOCH,
|
||||
activation_epoch=FAR_FUTURE_EPOCH,
|
||||
exit_epoch=FAR_FUTURE_EPOCH,
|
||||
withdrawable_epoch=FAR_FUTURE_EPOCH,
|
||||
effective_balance=effective_balance,
|
||||
next_custody_secret_to_reveal=next_custody_secret_to_reveal,
|
||||
all_custody_secrets_revealed_epoch=FAR_FUTURE_EPOCH,
|
||||
)
|
||||
```
|
||||
|
||||
### Epoch transition
|
||||
|
||||
This epoch transition overrides the phase0 epoch transition:
|
||||
|
Loading…
x
Reference in New Issue
Block a user