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/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/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/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 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 6411ecb6a..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, ) @@ -25,7 +25,7 @@ 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): store = initialize_light_client_store(spec, state) @@ -41,7 +41,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 +57,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, ) @@ -72,7 +71,7 @@ def test_process_light_client_update_not_timeout(spec, state): @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): store = initialize_light_client_store(spec, state) @@ -94,7 +93,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 +107,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, ) @@ -123,7 +121,7 @@ def test_process_light_client_update_at_period_boundary(spec, state): @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): store = initialize_light_client_store(spec, state) @@ -145,7 +143,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 +158,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, ) @@ -175,7 +172,7 @@ def test_process_light_client_update_timeout(spec, state): @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): store = initialize_light_client_store(spec, state) @@ -211,7 +208,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 +217,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, ) 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 b35c6c687..7dcad319a 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/light_client.py +++ b/tests/core/pyspec/eth2spec/test/helpers/light_client.py @@ -45,5 +45,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