mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-02 14:35:04 -05:00
Some updates
This commit is contained in:
committed by
Danny Ryan
parent
e5544d055b
commit
7fc2830730
@@ -41,28 +41,61 @@ This document describes the shard transition function (data layer only) and the
|
||||
| `ONLINE_PERIOD` | `2**3` (= 8) | epochs | ~51 min |
|
||||
| `LIGHT_CLIENT_COMMITTEE_SIZE` | `2**7` (= 128) |
|
||||
| `LIGHT_CLIENT_COMMITTEE_PERIOD` | `2**8` (= 256) | epochs | ~29 hours |
|
||||
| `SHARD_STATE_ROOT_LENGTH` | `2**7` (= 128) | bytes |
|
||||
| `MAX_SHARD_BLOCK
|
||||
|
||||
## Containers
|
||||
|
||||
### Aliases
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `SHARD_STATE_ROOT` | `BytesN[SHARD_STATE_ROOT_LENGTH]` |
|
||||
|
||||
|
||||
### `AttestationData`
|
||||
|
||||
```python
|
||||
class AttestationData(Container):
|
||||
# Slot
|
||||
slot: Slot
|
||||
index: CommitteeIndex
|
||||
# LMD GHOST vote
|
||||
beacon_block_root: Hash
|
||||
# FFG vote
|
||||
source: Checkpoint
|
||||
target: Checkpoint
|
||||
# Shard data
|
||||
shard_data: AttestationShardData
|
||||
```
|
||||
|
||||
### `AttestationShardData`
|
||||
|
||||
```python
|
||||
class AttestationShardData(Container):
|
||||
# Shard block lengths
|
||||
shard_block_lengths: List[uint8, MAX_CATCHUP_RATIO * MAX_SHARDS]
|
||||
# Shard data roots
|
||||
shard_data_roots: List[Hash, MAX_CATCHUP_RATIO * MAX_SHARDS]
|
||||
# Intermediate state roots
|
||||
shard_state_roots: List[Hash, MAX_CATCHUP_RATIO * MAX_SHARDS]
|
||||
# Index
|
||||
index: uint64
|
||||
shard_state_roots: List[SHARD_STATE_ROOT, MAX_CATCHUP_RATIO * MAX_SHARDS]
|
||||
```
|
||||
|
||||
### `ReducedAttestationData`
|
||||
|
||||
```python
|
||||
class ReducedAttestationData(Container):
|
||||
slot: Slot
|
||||
index: CommitteeIndex
|
||||
# LMD GHOST vote
|
||||
beacon_block_root: Hash
|
||||
# FFG vote
|
||||
source: Checkpoint
|
||||
target: Checkpoint
|
||||
# Shard data root
|
||||
shard_data_root: Hash
|
||||
```
|
||||
|
||||
|
||||
### `Attestation`
|
||||
|
||||
```python
|
||||
@@ -73,6 +106,26 @@ class Attestation(Container):
|
||||
signature: BLSSignature
|
||||
```
|
||||
|
||||
### `ReducedAttestation`
|
||||
|
||||
```python
|
||||
class ReducedAttestation(Container):
|
||||
aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]
|
||||
data: ReducedAttestationData
|
||||
custody_bits: List[Bitlist[MAX_VALIDATORS_PER_COMMITTEE], MAX_CATCHUP_RATIO * MAX_SHARDS]
|
||||
signature: BLSSignature
|
||||
```
|
||||
|
||||
### `IndexedAttestation`
|
||||
|
||||
```python
|
||||
class IndexedAttestation(Container):
|
||||
participants: List[ValidatorIndex, MAX_COMMITTEE_SIZE]
|
||||
data: ReducedAttestationData
|
||||
custody_bits: List[Bitlist[MAX_VALIDATORS_PER_COMMITTEE], MAX_CATCHUP_RATIO * MAX_SHARDS]
|
||||
signature: BLSSignature
|
||||
```
|
||||
|
||||
### `CompactCommittee`
|
||||
|
||||
```python
|
||||
@@ -81,6 +134,15 @@ class CompactCommittee(Container):
|
||||
compact_validators: List[uint64, MAX_VALIDATORS_PER_COMMITTEE]
|
||||
```
|
||||
|
||||
### `AttestationCustodyBitWrapper`
|
||||
|
||||
```
|
||||
class AttestationCustodyBitWrapper(Container):
|
||||
attestation_root: Hash
|
||||
index: uint64
|
||||
bit: bool
|
||||
```
|
||||
|
||||
## Helpers
|
||||
|
||||
### `get_online_validators`
|
||||
@@ -103,16 +165,6 @@ def pack_compact_validator(index: int, slashed: bool, balance_in_increments: int
|
||||
return (index << 16) + (slashed << 15) + balance_in_increments
|
||||
```
|
||||
|
||||
### `unpack_compact_validator`
|
||||
|
||||
```python
|
||||
def unpack_compact_validator(compact_validator: int) -> Tuple[int, bool, int]:
|
||||
"""
|
||||
Returns validator index, slashed, balance // EFFECTIVE_BALANCE_INCREMENT
|
||||
"""
|
||||
return compact_validator >> 16, bool((compact_validator >> 15) % 2), compact_validator & (2**15 - 1)
|
||||
```
|
||||
|
||||
### `committee_to_compact_committee`
|
||||
|
||||
```python
|
||||
@@ -129,6 +181,52 @@ def committee_to_compact_committee(state: BeaconState, committee: Sequence[Valid
|
||||
return CompactCommittee(pubkeys=pubkeys, compact_validators=compact_validators)
|
||||
```
|
||||
|
||||
### `get_light_client_committee`
|
||||
|
||||
```python
|
||||
def get_light_client_committee(beacon_state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
|
||||
assert epoch % LIGHT_CLIENT_COMMITTEE_PERIOD == 0
|
||||
active_validator_indices = get_active_validator_indices(beacon_state, epoch)
|
||||
seed = get_seed(beacon_state, epoch, DOMAIN_SHARD_LIGHT_CLIENT)
|
||||
return compute_committee(active_validator_indices, seed, 0, ACTIVE_SHARDS)[:TARGET_COMMITTEE_SIZE]
|
||||
```
|
||||
|
||||
### `get_indexed_attestation`
|
||||
|
||||
```python
|
||||
def get_indexed_attestation(beacon_state: BeaconState, attestation: Attestation) -> IndexedAttestation:
|
||||
attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
|
||||
return IndexedAttestation(attesting_indices, data, custody_bits, signature)
|
||||
```
|
||||
|
||||
### `is_valid_indexed_attestation`
|
||||
|
||||
``python
|
||||
def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
|
||||
"""
|
||||
Check if ``indexed_attestation`` has valid indices and signature.
|
||||
"""
|
||||
|
||||
# Verify indices are sorted
|
||||
if indexed_attestation.participants != sorted(indexed_attestation.participants):
|
||||
return False
|
||||
|
||||
# Verify aggregate signature
|
||||
all_pubkeys = []
|
||||
all_message_hashes = []
|
||||
for participant, custody_bits in zip(participants, indexed_attestation.custody_bits):
|
||||
for i, bit in enumerate(custody_bits):
|
||||
all_pubkeys.append(state.validators[participant].pubkey)
|
||||
all_message_hashes.append(AttestationCustodyBitWrapper(hash_tree_root(indexed_attestation.data), i, bit))
|
||||
|
||||
return bls_verify_multiple(
|
||||
pubkeys=all_pubkeys,
|
||||
message_hashes=all_message_hashes,
|
||||
signature=indexed_attestation.signature,
|
||||
domain=get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch),
|
||||
)
|
||||
```
|
||||
|
||||
## Beacon Chain Changes
|
||||
|
||||
### New state variables
|
||||
@@ -216,37 +314,37 @@ Check the length of attestations using `len(block.attestations) <= 4 * get_commi
|
||||
### Light client processing
|
||||
|
||||
```python
|
||||
signer_validators = []
|
||||
signer_keys = []
|
||||
for i, bit in enumerate(block.light_client_signature_bitfield):
|
||||
if bit:
|
||||
signer_keys.append(state.current_light_committee.pubkeys[i])
|
||||
index, _, _ = unpack_compact_validator(state.current_light_committee.compact_validators[i])
|
||||
signer_validators.append(index)
|
||||
|
||||
assert bls_verify(
|
||||
pubkey=bls_aggregate_pubkeys(signer_keys),
|
||||
message_hash=get_block_root_at_slot(state, state.slot - 1),
|
||||
signature=block.light_client_signature,
|
||||
domain=DOMAIN_LIGHT_CLIENT
|
||||
)
|
||||
def verify_light_client_signatures(state: BeaconState, block: BeaconBlock):
|
||||
period_start = get_current_epoch(state) - get_current_epoch(state) % LIGHT_CLIENT_COMMITTEE_PERIOD
|
||||
committee = get_light_client_committee(state, period_start - min(period_start, LIGHT_CLIENT_COMMITTEE_PERIOD))
|
||||
signer_validators = []
|
||||
signer_keys = []
|
||||
for i, bit in enumerate(block.light_client_signature_bitfield):
|
||||
if bit:
|
||||
signer_keys.append(state.validators[committee[i]].pubkey)
|
||||
signer_validators.append(committee[i])
|
||||
|
||||
assert bls_verify(
|
||||
pubkey=bls_aggregate_pubkeys(signer_keys),
|
||||
message_hash=get_block_root_at_slot(state, state.slot - 1),
|
||||
signature=block.light_client_signature,
|
||||
domain=DOMAIN_LIGHT_CLIENT
|
||||
)
|
||||
```
|
||||
|
||||
### Epoch transition
|
||||
|
||||
```python
|
||||
# Slowly remove validators from the "online" set if they do not show up
|
||||
for index in range(len(state.validators)):
|
||||
if state.online_countdown[index] != 0:
|
||||
state.online_countdown[index] = state.online_countdown[index] - 1
|
||||
|
||||
# Update light client committees
|
||||
if get_current_epoch(state) % LIGHT_CLIENT_COMMITTEE_PERIOD == 0:
|
||||
state.current_light_committee = state.next_light_committee
|
||||
seed = get_seed(state, get_current_epoch(state), DOMAIN_LIGHT_CLIENT)
|
||||
active_indices = get_active_validator_indices(state, get_current_epoch(state))
|
||||
committee = [active_indices[compute_shuffled_index(ValidatorIndex(i), len(active_indices), seed)] for i in range(LIGHT_CLIENT_COMMITTEE_SIZE)]
|
||||
state.next_light_committee = committee_to_compact_committee(state, committee)
|
||||
def phase_1_epoch_transition(state):
|
||||
# Slowly remove validators from the "online" set if they do not show up
|
||||
for index in range(len(state.validators)):
|
||||
if state.online_countdown[index] != 0:
|
||||
state.online_countdown[index] = state.online_countdown[index] - 1
|
||||
|
||||
# Update light client committees
|
||||
if get_current_epoch(state) % LIGHT_CLIENT_COMMITTEE_PERIOD == 0:
|
||||
state.current_light_committee = state.next_light_committee
|
||||
state.next_light_committee = committee_to_compact_committee(state, get_light_client_committee(state, get_current_epoch(state)))
|
||||
```
|
||||
|
||||
### Fraud proofs
|
||||
|
||||
Reference in New Issue
Block a user