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:
Etan Kissling
2022-04-27 09:50:27 +02:00
parent 8cc008d11c
commit 0b8ab23bd4
6 changed files with 107 additions and 13 deletions

View File

@@ -16,6 +16,7 @@ from eth2spec.test.helpers.constants import MINIMAL
from eth2spec.test.helpers.light_client import (
get_sync_aggregate,
initialize_light_client_store,
override_config_fork_epochs,
)
from eth2spec.test.helpers.state import (
next_slots,
@@ -27,6 +28,9 @@ from eth2spec.test.helpers.merkle import build_proof
@with_altair_and_later
@spec_state_test
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)
# 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_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))]
# Ensure that finality checkpoint is genesis
@@ -57,7 +61,6 @@ def test_process_light_client_update_not_timeout(spec, state):
finalized_header=finality_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
fork_version=fork_version,
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.best_valid_update == update
spec.config = old_config
@with_altair_and_later
@spec_state_test
@with_presets([MINIMAL], reason="too slow")
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)
# 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_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))]
# Finality is unchanged
@@ -108,7 +116,6 @@ def test_process_light_client_update_at_period_boundary(spec, state):
finalized_header=finality_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
fork_version=fork_version,
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.finalized_header == pre_store.finalized_header
spec.config = old_config
@with_altair_and_later
@spec_state_test
@with_presets([MINIMAL], reason="too slow")
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)
# 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_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
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,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
fork_version=fork_version,
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.finalized_header == pre_store.finalized_header
spec.config = old_config
@with_altair_and_later
@spec_state_test
@with_presets([MINIMAL], reason="too slow")
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)
# Change finality
@@ -211,7 +227,7 @@ def test_process_light_client_update_finality_updated(spec, state):
)
# 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(
attested_header=block_header,
@@ -220,7 +236,6 @@ def test_process_light_client_update_finality_updated(spec, state):
finalized_header=finalized_block_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
fork_version=fork_version,
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.finalized_header == update.finalized_header
assert store.best_valid_update is None
spec.config = old_config

View File

@@ -1,3 +1,5 @@
from copy import deepcopy
from eth2spec.test.helpers.state import (
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):
return spec.LightClientStore(
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_signature=sync_committee_signature,
)
fork_version = signature_state.fork.current_version
return sync_aggregate, fork_version, signature_slot
return sync_aggregate, signature_slot