From 0b8ab23bd4fdb38a1bc38e0f242fc892cee71663 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 27 Apr 2022 09:50:27 +0200 Subject: [PATCH 1/3] 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. --- specs/altair/beacon-chain.md | 13 +++++++ specs/altair/sync-protocol.md | 5 ++- specs/bellatrix/beacon-chain.md | 15 ++++++++ specs/capella/beacon-chain.md | 20 +++++++++++ .../altair/unittests/test_sync_protocol.py | 33 +++++++++++++----- .../eth2spec/test/helpers/light_client.py | 34 +++++++++++++++++-- 6 files changed, 107 insertions(+), 13 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index a14ddb4f6..fadce93ef 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -28,6 +28,7 @@ - [Helper functions](#helper-functions) - [Crypto](#crypto) - [Misc](#misc-1) + - [`compute_fork_version`](#compute_fork_version) - [`add_flag`](#add_flag) - [`has_flag`](#has_flag) - [Beacon state accessors](#beacon-state-accessors) @@ -226,6 +227,18 @@ the functionality described in those documents. ### 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` ```python diff --git a/specs/altair/sync-protocol.md b/specs/altair/sync-protocol.md index 1aa9316d3..a3b10efa2 100644 --- a/specs/altair/sync-protocol.md +++ b/specs/altair/sync-protocol.md @@ -71,8 +71,6 @@ class LightClientUpdate(Container): finality_branch: Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)] # Sync committee aggregate signature sync_aggregate: SyncAggregate - # Fork version for the aggregate signature - fork_version: Version # Slot at which the aggregate signature was created (untrusted) 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) 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) assert bls.FastAggregateVerify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature) ``` diff --git a/specs/bellatrix/beacon-chain.md b/specs/bellatrix/beacon-chain.md index b37a8ab71..f92c4cbf5 100644 --- a/specs/bellatrix/beacon-chain.md +++ b/specs/bellatrix/beacon-chain.md @@ -29,6 +29,7 @@ - [`is_execution_enabled`](#is_execution_enabled) - [Misc](#misc) - [`compute_timestamp_at_slot`](#compute_timestamp_at_slot) + - [Modified `compute_fork_version`](#modified-compute_fork_version) - [Beacon state accessors](#beacon-state-accessors) - [Modified `get_inactivity_penalty_deltas`](#modified-get_inactivity_penalty_deltas) - [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) ``` +#### 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 #### Modified `get_inactivity_penalty_deltas` diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index da67a8fcb..e2b47dd1f 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -34,6 +34,8 @@ - [`has_eth1_withdrawal_credential`](#has_eth1_withdrawal_credential) - [`is_fully_withdrawable_validator`](#is_fully_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) - [Epoch processing](#epoch-processing) - [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 ``` +### 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 ### Epoch processing diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py index 6411ecb6a..4acfa6424 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py @@ -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 diff --git a/tests/core/pyspec/eth2spec/test/helpers/light_client.py b/tests/core/pyspec/eth2spec/test/helpers/light_client.py index b35c6c687..6868cad86 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/light_client.py +++ b/tests/core/pyspec/eth2spec/test/helpers/light_client.py @@ -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 From 840733ffd2994d2ef361175fe98b9cff4e7403e5 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 23 Jun 2022 20:55:18 +0200 Subject: [PATCH 2/3] Move `compute_fork_version` to `fork.md` --- specs/altair/beacon-chain.md | 13 ------------- specs/altair/fork.md | 19 +++++++++++++++++++ specs/bellatrix/beacon-chain.md | 15 --------------- specs/bellatrix/fork.md | 21 +++++++++++++++++++++ specs/capella/beacon-chain.md | 20 -------------------- specs/capella/fork.md | 23 +++++++++++++++++++++++ 6 files changed, 63 insertions(+), 48 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index fadce93ef..a14ddb4f6 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -28,7 +28,6 @@ - [Helper functions](#helper-functions) - [Crypto](#crypto) - [Misc](#misc-1) - - [`compute_fork_version`](#compute_fork_version) - [`add_flag`](#add_flag) - [`has_flag`](#has_flag) - [Beacon state accessors](#beacon-state-accessors) @@ -227,18 +226,6 @@ the functionality described in those documents. ### 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` ```python diff --git a/specs/altair/fork.md b/specs/altair/fork.md index 6228022b8..bf8499a21 100644 --- a/specs/altair/fork.md +++ b/specs/altair/fork.md @@ -7,6 +7,9 @@ - [Introduction](#introduction) - [Configuration](#configuration) +- [Helper functions](#helper-functions) + - [Misc](#misc) + - [`compute_fork_version`](#compute_fork_version) - [Fork to Altair](#fork-to-altair) - [Fork trigger](#fork-trigger) - [Upgrading the state](#upgrading-the-state) @@ -26,6 +29,22 @@ Warning: this configuration is not definitive. | `ALTAIR_FORK_VERSION` | `Version('0x01000000')` | | `ALTAIR_FORK_EPOCH` | `Epoch(74240)` (Oct 27, 2021, 10:56:23am UTC) | +## Helper functions + +### 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 +``` + ## Fork to Altair ### Fork trigger diff --git a/specs/bellatrix/beacon-chain.md b/specs/bellatrix/beacon-chain.md index f92c4cbf5..b37a8ab71 100644 --- a/specs/bellatrix/beacon-chain.md +++ b/specs/bellatrix/beacon-chain.md @@ -29,7 +29,6 @@ - [`is_execution_enabled`](#is_execution_enabled) - [Misc](#misc) - [`compute_timestamp_at_slot`](#compute_timestamp_at_slot) - - [Modified `compute_fork_version`](#modified-compute_fork_version) - [Beacon state accessors](#beacon-state-accessors) - [Modified `get_inactivity_penalty_deltas`](#modified-get_inactivity_penalty_deltas) - [Beacon state mutators](#beacon-state-mutators) @@ -243,20 +242,6 @@ def compute_timestamp_at_slot(state: BeaconState, slot: Slot) -> uint64: 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 #### Modified `get_inactivity_penalty_deltas` diff --git a/specs/bellatrix/fork.md b/specs/bellatrix/fork.md index 8cb34099b..5c0e174da 100644 --- a/specs/bellatrix/fork.md +++ b/specs/bellatrix/fork.md @@ -9,6 +9,9 @@ - [Introduction](#introduction) - [Configuration](#configuration) +- [Helper functions](#helper-functions) + - [Misc](#misc) + - [Modified `compute_fork_version`](#modified-compute_fork_version) - [Fork to Bellatrix](#fork-to-bellatrix) - [Fork trigger](#fork-trigger) - [Upgrading the state](#upgrading-the-state) @@ -28,6 +31,24 @@ Warning: this configuration is not definitive. | `BELLATRIX_FORK_VERSION` | `Version('0x02000000')` | | `BELLATRIX_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | +## Helper functions + +### Misc + +#### 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 +``` + ## Fork to Bellatrix ### Fork trigger diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index e2b47dd1f..da67a8fcb 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -34,8 +34,6 @@ - [`has_eth1_withdrawal_credential`](#has_eth1_withdrawal_credential) - [`is_fully_withdrawable_validator`](#is_fully_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) - [Epoch processing](#epoch-processing) - [Full withdrawals](#full-withdrawals) @@ -320,24 +318,6 @@ def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) -> 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 ### Epoch processing diff --git a/specs/capella/fork.md b/specs/capella/fork.md index 0d8283e56..c22387ee7 100644 --- a/specs/capella/fork.md +++ b/specs/capella/fork.md @@ -7,6 +7,9 @@ - [Introduction](#introduction) - [Configuration](#configuration) +- [Helper functions](#helper-functions) + - [Misc](#misc) + - [Modified `compute_fork_version`](#modified-compute_fork_version) - [Fork to Capella](#fork-to-capella) - [Fork trigger](#fork-trigger) - [Upgrading the state](#upgrading-the-state) @@ -27,6 +30,26 @@ Warning: this configuration is not definitive. | `CAPELLA_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** | +## Helper functions + +### 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 +``` + ## Fork to Capella ### Fork trigger From 9a253e437d4991e3ca7e8aa3cf4adf095d424321 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 24 Jun 2022 01:05:11 +0200 Subject: [PATCH 3/3] create decorator for tests with matching config --- .../altair/unittests/test_config_override.py | 32 +++++++++++++++++- .../altair/unittests/test_sync_protocol.py | 31 +++-------------- tests/core/pyspec/eth2spec/test/context.py | 33 +++++++++++++++++++ .../eth2spec/test/helpers/light_client.py | 31 ----------------- 4 files changed, 69 insertions(+), 58 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py index f1503c39f..5c940eafc 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py @@ -1,4 +1,9 @@ -from eth2spec.test.context import spec_configured_state_test, with_phases +from eth2spec.test.context import ( + spec_configured_state_test, + spec_state_test_with_matching_config, + with_all_phases, + with_phases +) from eth2spec.test.helpers.constants import ALTAIR @@ -17,3 +22,28 @@ def test_config_override(spec, state): # TODO: it would be nice if the create_genesis_state actually outputs a state # for the fork with a slot that matches at least the fork boundary. # assert spec.get_current_epoch(state) >= 4 + + +@with_all_phases +@spec_state_test_with_matching_config +def test_override_config_fork_epoch(spec, state): + if state.fork.current_version == spec.config.GENESIS_FORK_VERSION: + return + + assert spec.config.ALTAIR_FORK_EPOCH == spec.GENESIS_EPOCH + if state.fork.current_version == spec.config.ALTAIR_FORK_VERSION: + return + + assert spec.config.BELLATRIX_FORK_EPOCH == spec.GENESIS_EPOCH + if state.fork.current_version == spec.config.BELLATRIX_FORK_VERSION: + return + + assert spec.config.CAPELLA_FORK_EPOCH == spec.GENESIS_EPOCH + if state.fork.current_version == spec.config.CAPELLA_FORK_VERSION: + return + + assert spec.config.SHARDING_FORK_EPOCH == spec.GENESIS_EPOCH + if state.fork.current_version == spec.config.SHARDING_FORK_VERSION: + return + + assert False # Fork is missing diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py index 4acfa6424..69d9db0f2 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py @@ -1,7 +1,7 @@ from copy import deepcopy from eth2spec.test.context import ( - spec_state_test, + spec_state_test_with_matching_config, with_presets, with_altair_and_later, ) @@ -16,7 +16,6 @@ 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, @@ -26,11 +25,8 @@ from eth2spec.test.helpers.merkle import build_proof @with_altair_and_later -@spec_state_test +@spec_state_test_with_matching_config 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 @@ -73,16 +69,11 @@ 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 +@spec_state_test_with_matching_config @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 @@ -128,16 +119,11 @@ 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 +@spec_state_test_with_matching_config @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 @@ -184,16 +170,11 @@ 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 +@spec_state_test_with_matching_config @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 @@ -245,5 +226,3 @@ 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 diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 35e4f1bcb..06313c195 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -277,6 +277,39 @@ def spec_configured_state_test(conf): return decorator +def config_fork_epoch_overrides(spec, state): + overrides = {} + if state.fork.current_version == spec.config.GENESIS_FORK_VERSION: + pass + elif state.fork.current_version == spec.config.ALTAIR_FORK_VERSION: + overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH + elif state.fork.current_version == spec.config.BELLATRIX_FORK_VERSION: + overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH + overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH + elif state.fork.current_version == spec.config.CAPELLA_FORK_VERSION: + overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH + overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH + overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH + elif state.fork.current_version == spec.config.SHARDING_FORK_VERSION: + overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH + overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH + overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH + overrides['SHARDING_FORK_EPOCH'] = spec.GENESIS_EPOCH + else: + assert False # Fork is missing + return overrides + + +def spec_state_test_with_matching_config(fn): + def decorator(fn): + def wrapper(*args, spec: Spec, **kw): + conf = config_fork_epoch_overrides(spec, kw['state']) + overrides = with_config_overrides(conf) + return overrides(fn)(*args, spec=spec, **kw) + return wrapper + return spec_test(with_state(decorator(single_phase(fn)))) + + def expect_assertion_error(fn): bad = False try: diff --git a/tests/core/pyspec/eth2spec/test/helpers/light_client.py b/tests/core/pyspec/eth2spec/test/helpers/light_client.py index 6868cad86..7dcad319a 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/light_client.py +++ b/tests/core/pyspec/eth2spec/test/helpers/light_client.py @@ -1,5 +1,3 @@ -from copy import deepcopy - from eth2spec.test.helpers.state import ( transition_to, ) @@ -9,35 +7,6 @@ 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(),