mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-21 14:58:12 +00:00
Remove fork_version
from LightClientUpdate
The `fork_version` field in `LightClientUpdate` can be derived from the `update.signature_slot` value by consulting the locally configured fork schedule. The light client already needs access to the fork schedule to determine the `GeneralizedIndex` values used for merkle proofs, and the memory layouts of the structures (including `LightClientUpdate`). The `fork_version` itself is network dependent and doesn't reveal that info.
This commit is contained in:
parent
8cc008d11c
commit
0b8ab23bd4
@ -28,6 +28,7 @@
|
|||||||
- [Helper functions](#helper-functions)
|
- [Helper functions](#helper-functions)
|
||||||
- [Crypto](#crypto)
|
- [Crypto](#crypto)
|
||||||
- [Misc](#misc-1)
|
- [Misc](#misc-1)
|
||||||
|
- [`compute_fork_version`](#compute_fork_version)
|
||||||
- [`add_flag`](#add_flag)
|
- [`add_flag`](#add_flag)
|
||||||
- [`has_flag`](#has_flag)
|
- [`has_flag`](#has_flag)
|
||||||
- [Beacon state accessors](#beacon-state-accessors)
|
- [Beacon state accessors](#beacon-state-accessors)
|
||||||
@ -226,6 +227,18 @@ the functionality described in those documents.
|
|||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
|
|
||||||
|
#### `compute_fork_version`
|
||||||
|
|
||||||
|
```python
|
||||||
|
def compute_fork_version(epoch: Epoch) -> Version:
|
||||||
|
"""
|
||||||
|
Return the fork version at the given ``epoch``.
|
||||||
|
"""
|
||||||
|
if epoch >= ALTAIR_FORK_EPOCH:
|
||||||
|
return ALTAIR_FORK_VERSION
|
||||||
|
return GENESIS_FORK_VERSION
|
||||||
|
```
|
||||||
|
|
||||||
#### `add_flag`
|
#### `add_flag`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -71,8 +71,6 @@ class LightClientUpdate(Container):
|
|||||||
finality_branch: Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]
|
finality_branch: Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]
|
||||||
# Sync committee aggregate signature
|
# Sync committee aggregate signature
|
||||||
sync_aggregate: SyncAggregate
|
sync_aggregate: SyncAggregate
|
||||||
# Fork version for the aggregate signature
|
|
||||||
fork_version: Version
|
|
||||||
# Slot at which the aggregate signature was created (untrusted)
|
# Slot at which the aggregate signature was created (untrusted)
|
||||||
signature_slot: Slot
|
signature_slot: Slot
|
||||||
```
|
```
|
||||||
@ -211,7 +209,8 @@ def validate_light_client_update(store: LightClientStore,
|
|||||||
pubkey for (bit, pubkey) in zip(sync_aggregate.sync_committee_bits, sync_committee.pubkeys)
|
pubkey for (bit, pubkey) in zip(sync_aggregate.sync_committee_bits, sync_committee.pubkeys)
|
||||||
if bit
|
if bit
|
||||||
]
|
]
|
||||||
domain = compute_domain(DOMAIN_SYNC_COMMITTEE, update.fork_version, genesis_validators_root)
|
fork_version = compute_fork_version(compute_epoch_at_slot(update.signature_slot))
|
||||||
|
domain = compute_domain(DOMAIN_SYNC_COMMITTEE, fork_version, genesis_validators_root)
|
||||||
signing_root = compute_signing_root(update.attested_header, domain)
|
signing_root = compute_signing_root(update.attested_header, domain)
|
||||||
assert bls.FastAggregateVerify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)
|
assert bls.FastAggregateVerify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)
|
||||||
```
|
```
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
- [`is_execution_enabled`](#is_execution_enabled)
|
- [`is_execution_enabled`](#is_execution_enabled)
|
||||||
- [Misc](#misc)
|
- [Misc](#misc)
|
||||||
- [`compute_timestamp_at_slot`](#compute_timestamp_at_slot)
|
- [`compute_timestamp_at_slot`](#compute_timestamp_at_slot)
|
||||||
|
- [Modified `compute_fork_version`](#modified-compute_fork_version)
|
||||||
- [Beacon state accessors](#beacon-state-accessors)
|
- [Beacon state accessors](#beacon-state-accessors)
|
||||||
- [Modified `get_inactivity_penalty_deltas`](#modified-get_inactivity_penalty_deltas)
|
- [Modified `get_inactivity_penalty_deltas`](#modified-get_inactivity_penalty_deltas)
|
||||||
- [Beacon state mutators](#beacon-state-mutators)
|
- [Beacon state mutators](#beacon-state-mutators)
|
||||||
@ -242,6 +243,20 @@ def compute_timestamp_at_slot(state: BeaconState, slot: Slot) -> uint64:
|
|||||||
return uint64(state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT)
|
return uint64(state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Modified `compute_fork_version`
|
||||||
|
|
||||||
|
```python
|
||||||
|
def compute_fork_version(epoch: Epoch) -> Version:
|
||||||
|
"""
|
||||||
|
Return the fork version at the given ``epoch``.
|
||||||
|
"""
|
||||||
|
if epoch >= BELLATRIX_FORK_EPOCH:
|
||||||
|
return BELLATRIX_FORK_VERSION
|
||||||
|
if epoch >= ALTAIR_FORK_EPOCH:
|
||||||
|
return ALTAIR_FORK_VERSION
|
||||||
|
return GENESIS_FORK_VERSION
|
||||||
|
```
|
||||||
|
|
||||||
### Beacon state accessors
|
### Beacon state accessors
|
||||||
|
|
||||||
#### Modified `get_inactivity_penalty_deltas`
|
#### Modified `get_inactivity_penalty_deltas`
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
- [`has_eth1_withdrawal_credential`](#has_eth1_withdrawal_credential)
|
- [`has_eth1_withdrawal_credential`](#has_eth1_withdrawal_credential)
|
||||||
- [`is_fully_withdrawable_validator`](#is_fully_withdrawable_validator)
|
- [`is_fully_withdrawable_validator`](#is_fully_withdrawable_validator)
|
||||||
- [`is_partially_withdrawable_validator`](#is_partially_withdrawable_validator)
|
- [`is_partially_withdrawable_validator`](#is_partially_withdrawable_validator)
|
||||||
|
- [Misc](#misc-1)
|
||||||
|
- [Modified `compute_fork_version`](#modified-compute_fork_version)
|
||||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||||
- [Epoch processing](#epoch-processing)
|
- [Epoch processing](#epoch-processing)
|
||||||
- [Full withdrawals](#full-withdrawals)
|
- [Full withdrawals](#full-withdrawals)
|
||||||
@ -318,6 +320,24 @@ def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) ->
|
|||||||
return has_eth1_withdrawal_credential(validator) and has_max_effective_balance and has_excess_balance
|
return has_eth1_withdrawal_credential(validator) and has_max_effective_balance and has_excess_balance
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
|
||||||
|
#### Modified `compute_fork_version`
|
||||||
|
|
||||||
|
```python
|
||||||
|
def compute_fork_version(epoch: Epoch) -> Version:
|
||||||
|
"""
|
||||||
|
Return the fork version at the given ``epoch``.
|
||||||
|
"""
|
||||||
|
if epoch >= CAPELLA_FORK_EPOCH:
|
||||||
|
return CAPELLA_FORK_VERSION
|
||||||
|
if epoch >= BELLATRIX_FORK_EPOCH:
|
||||||
|
return BELLATRIX_FORK_VERSION
|
||||||
|
if epoch >= ALTAIR_FORK_EPOCH:
|
||||||
|
return ALTAIR_FORK_VERSION
|
||||||
|
return GENESIS_FORK_VERSION
|
||||||
|
```
|
||||||
|
|
||||||
## Beacon chain state transition function
|
## Beacon chain state transition function
|
||||||
|
|
||||||
### Epoch processing
|
### Epoch processing
|
||||||
|
@ -16,6 +16,7 @@ from eth2spec.test.helpers.constants import MINIMAL
|
|||||||
from eth2spec.test.helpers.light_client import (
|
from eth2spec.test.helpers.light_client import (
|
||||||
get_sync_aggregate,
|
get_sync_aggregate,
|
||||||
initialize_light_client_store,
|
initialize_light_client_store,
|
||||||
|
override_config_fork_epochs,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
next_slots,
|
next_slots,
|
||||||
@ -27,6 +28,9 @@ from eth2spec.test.helpers.merkle import build_proof
|
|||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_process_light_client_update_not_timeout(spec, state):
|
def test_process_light_client_update_not_timeout(spec, state):
|
||||||
|
old_config = spec.config
|
||||||
|
override_config_fork_epochs(spec, state)
|
||||||
|
|
||||||
store = initialize_light_client_store(spec, state)
|
store = initialize_light_client_store(spec, state)
|
||||||
|
|
||||||
# Block at slot 1 doesn't increase sync committee period, so it won't force update store.finalized_header
|
# Block at slot 1 doesn't increase sync committee period, so it won't force update store.finalized_header
|
||||||
@ -41,7 +45,7 @@ def test_process_light_client_update_not_timeout(spec, state):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sync committee signing the block_header
|
# Sync committee signing the block_header
|
||||||
sync_aggregate, fork_version, signature_slot = get_sync_aggregate(spec, state, block_header)
|
sync_aggregate, signature_slot = get_sync_aggregate(spec, state, block_header)
|
||||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||||
|
|
||||||
# Ensure that finality checkpoint is genesis
|
# Ensure that finality checkpoint is genesis
|
||||||
@ -57,7 +61,6 @@ def test_process_light_client_update_not_timeout(spec, state):
|
|||||||
finalized_header=finality_header,
|
finalized_header=finality_header,
|
||||||
finality_branch=finality_branch,
|
finality_branch=finality_branch,
|
||||||
sync_aggregate=sync_aggregate,
|
sync_aggregate=sync_aggregate,
|
||||||
fork_version=fork_version,
|
|
||||||
signature_slot=signature_slot,
|
signature_slot=signature_slot,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,11 +73,16 @@ def test_process_light_client_update_not_timeout(spec, state):
|
|||||||
assert store.finalized_header == pre_store.finalized_header
|
assert store.finalized_header == pre_store.finalized_header
|
||||||
assert store.best_valid_update == update
|
assert store.best_valid_update == update
|
||||||
|
|
||||||
|
spec.config = old_config
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
@with_presets([MINIMAL], reason="too slow")
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_process_light_client_update_at_period_boundary(spec, state):
|
def test_process_light_client_update_at_period_boundary(spec, state):
|
||||||
|
old_config = spec.config
|
||||||
|
override_config_fork_epochs(spec, state)
|
||||||
|
|
||||||
store = initialize_light_client_store(spec, state)
|
store = initialize_light_client_store(spec, state)
|
||||||
|
|
||||||
# Forward to slot before next sync committee period so that next block is final one in period
|
# Forward to slot before next sync committee period so that next block is final one in period
|
||||||
@ -94,7 +102,7 @@ def test_process_light_client_update_at_period_boundary(spec, state):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sync committee signing the block_header
|
# Sync committee signing the block_header
|
||||||
sync_aggregate, fork_version, signature_slot = get_sync_aggregate(spec, state, block_header)
|
sync_aggregate, signature_slot = get_sync_aggregate(spec, state, block_header)
|
||||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||||
|
|
||||||
# Finality is unchanged
|
# Finality is unchanged
|
||||||
@ -108,7 +116,6 @@ def test_process_light_client_update_at_period_boundary(spec, state):
|
|||||||
finalized_header=finality_header,
|
finalized_header=finality_header,
|
||||||
finality_branch=finality_branch,
|
finality_branch=finality_branch,
|
||||||
sync_aggregate=sync_aggregate,
|
sync_aggregate=sync_aggregate,
|
||||||
fork_version=fork_version,
|
|
||||||
signature_slot=signature_slot,
|
signature_slot=signature_slot,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,11 +128,16 @@ def test_process_light_client_update_at_period_boundary(spec, state):
|
|||||||
assert store.best_valid_update == update
|
assert store.best_valid_update == update
|
||||||
assert store.finalized_header == pre_store.finalized_header
|
assert store.finalized_header == pre_store.finalized_header
|
||||||
|
|
||||||
|
spec.config = old_config
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
@with_presets([MINIMAL], reason="too slow")
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_process_light_client_update_timeout(spec, state):
|
def test_process_light_client_update_timeout(spec, state):
|
||||||
|
old_config = spec.config
|
||||||
|
override_config_fork_epochs(spec, state)
|
||||||
|
|
||||||
store = initialize_light_client_store(spec, state)
|
store = initialize_light_client_store(spec, state)
|
||||||
|
|
||||||
# Forward to next sync committee period
|
# Forward to next sync committee period
|
||||||
@ -145,7 +157,7 @@ def test_process_light_client_update_timeout(spec, state):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sync committee signing the block_header
|
# Sync committee signing the block_header
|
||||||
sync_aggregate, fork_version, signature_slot = get_sync_aggregate(spec, state, block_header)
|
sync_aggregate, signature_slot = get_sync_aggregate(spec, state, block_header)
|
||||||
|
|
||||||
# Sync committee is updated
|
# Sync committee is updated
|
||||||
next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX)
|
next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX)
|
||||||
@ -160,7 +172,6 @@ def test_process_light_client_update_timeout(spec, state):
|
|||||||
finalized_header=finality_header,
|
finalized_header=finality_header,
|
||||||
finality_branch=finality_branch,
|
finality_branch=finality_branch,
|
||||||
sync_aggregate=sync_aggregate,
|
sync_aggregate=sync_aggregate,
|
||||||
fork_version=fork_version,
|
|
||||||
signature_slot=signature_slot,
|
signature_slot=signature_slot,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -173,11 +184,16 @@ def test_process_light_client_update_timeout(spec, state):
|
|||||||
assert store.best_valid_update == update
|
assert store.best_valid_update == update
|
||||||
assert store.finalized_header == pre_store.finalized_header
|
assert store.finalized_header == pre_store.finalized_header
|
||||||
|
|
||||||
|
spec.config = old_config
|
||||||
|
|
||||||
|
|
||||||
@with_altair_and_later
|
@with_altair_and_later
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
@with_presets([MINIMAL], reason="too slow")
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_process_light_client_update_finality_updated(spec, state):
|
def test_process_light_client_update_finality_updated(spec, state):
|
||||||
|
old_config = spec.config
|
||||||
|
override_config_fork_epochs(spec, state)
|
||||||
|
|
||||||
store = initialize_light_client_store(spec, state)
|
store = initialize_light_client_store(spec, state)
|
||||||
|
|
||||||
# Change finality
|
# Change finality
|
||||||
@ -211,7 +227,7 @@ def test_process_light_client_update_finality_updated(spec, state):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sync committee signing the block_header
|
# Sync committee signing the block_header
|
||||||
sync_aggregate, fork_version, signature_slot = get_sync_aggregate(spec, state, block_header)
|
sync_aggregate, signature_slot = get_sync_aggregate(spec, state, block_header)
|
||||||
|
|
||||||
update = spec.LightClientUpdate(
|
update = spec.LightClientUpdate(
|
||||||
attested_header=block_header,
|
attested_header=block_header,
|
||||||
@ -220,7 +236,6 @@ def test_process_light_client_update_finality_updated(spec, state):
|
|||||||
finalized_header=finalized_block_header,
|
finalized_header=finalized_block_header,
|
||||||
finality_branch=finality_branch,
|
finality_branch=finality_branch,
|
||||||
sync_aggregate=sync_aggregate,
|
sync_aggregate=sync_aggregate,
|
||||||
fork_version=fork_version,
|
|
||||||
signature_slot=signature_slot,
|
signature_slot=signature_slot,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -230,3 +245,5 @@ def test_process_light_client_update_finality_updated(spec, state):
|
|||||||
assert store.optimistic_header == update.attested_header
|
assert store.optimistic_header == update.attested_header
|
||||||
assert store.finalized_header == update.finalized_header
|
assert store.finalized_header == update.finalized_header
|
||||||
assert store.best_valid_update is None
|
assert store.best_valid_update is None
|
||||||
|
|
||||||
|
spec.config = old_config
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
transition_to,
|
transition_to,
|
||||||
)
|
)
|
||||||
@ -7,6 +9,35 @@ from eth2spec.test.helpers.sync_committee import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def override_config_fork_epochs(spec, state):
|
||||||
|
# Test framework adjusts state fork but leaves spec config constants inconsistent
|
||||||
|
config_overrides = {}
|
||||||
|
if state.fork.current_version == spec.config.GENESIS_FORK_VERSION:
|
||||||
|
pass
|
||||||
|
elif state.fork.current_version == spec.config.ALTAIR_FORK_VERSION:
|
||||||
|
config_overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
elif state.fork.current_version == spec.config.BELLATRIX_FORK_VERSION:
|
||||||
|
config_overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
config_overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
elif state.fork.current_version == spec.config.CAPELLA_FORK_VERSION:
|
||||||
|
config_overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
config_overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
config_overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
elif state.fork.current_version == spec.config.SHARDING_FORK_VERSION:
|
||||||
|
config_overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
config_overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
config_overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
config_overrides['SHARDING_FORK_EPOCH'] = spec.GENESIS_EPOCH
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
tmp_config = deepcopy(spec.config._asdict())
|
||||||
|
tmp_config.update(config_overrides)
|
||||||
|
config_types = spec.Configuration.__annotations__
|
||||||
|
test_config = {k: config_types[k](v) for k, v in tmp_config.items()}
|
||||||
|
spec.config = spec.Configuration(**test_config)
|
||||||
|
|
||||||
|
|
||||||
def initialize_light_client_store(spec, state):
|
def initialize_light_client_store(spec, state):
|
||||||
return spec.LightClientStore(
|
return spec.LightClientStore(
|
||||||
finalized_header=spec.BeaconBlockHeader(),
|
finalized_header=spec.BeaconBlockHeader(),
|
||||||
@ -45,5 +76,4 @@ def get_sync_aggregate(spec, state, block_header, signature_slot=None):
|
|||||||
sync_committee_bits=sync_committee_bits,
|
sync_committee_bits=sync_committee_bits,
|
||||||
sync_committee_signature=sync_committee_signature,
|
sync_committee_signature=sync_committee_signature,
|
||||||
)
|
)
|
||||||
fork_version = signature_state.fork.current_version
|
return sync_aggregate, signature_slot
|
||||||
return sync_aggregate, fork_version, signature_slot
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user