diff --git a/specs/deneb/beacon-chain.md b/specs/deneb/beacon-chain.md index f1fe48e82..7d2f9bdc7 100644 --- a/specs/deneb/beacon-chain.md +++ b/specs/deneb/beacon-chain.md @@ -30,6 +30,8 @@ - [Block processing](#block-processing) - [Execution payload](#execution-payload) - [`process_execution_payload`](#process_execution_payload) + - [Modified `process_operations`](#modified-process_operations) + - [Modified `process_voluntary_exit`](#modified-process_voluntary_exit) - [Blob KZG commitments](#blob-kzg-commitments) - [Testing](#testing) @@ -281,7 +283,8 @@ def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVolu # Verify the validator has been active long enough assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD # Verify signature - domain = compute_domain(DOMAIN_VOLUNTARY_EXIT, CAPELLA_FORK_VERSION, state.genesis_validators_root) # [Modified in Deneb] + # [Modified in Deneb] + domain = compute_domain(DOMAIN_VOLUNTARY_EXIT, CAPELLA_FORK_VERSION, state.genesis_validators_root) signing_root = compute_signing_root(voluntary_exit, domain) assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature) # Initiate exit diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py index f4fcaac68..12b554da5 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py @@ -2,6 +2,12 @@ from eth2spec.test.context import ( spec_state_test, always_bls, with_bellatrix_and_later, + with_phases, +) +from eth2spec.test.helpers.constants import ( + BELLATRIX, + CAPELLA, + DENEB, ) from eth2spec.test.helpers.keys import pubkey_to_privkey from eth2spec.test.helpers.state import ( @@ -12,8 +18,10 @@ from eth2spec.test.helpers.voluntary_exits import ( sign_voluntary_exit, ) +BELLATRIX_AND_CAPELLA = [BELLATRIX, CAPELLA] -def _run_voluntary_exit_processing_test( + +def run_voluntary_exit_processing_test( spec, state, fork_version, @@ -51,7 +59,7 @@ def _run_voluntary_exit_processing_test( @spec_state_test @always_bls def test_invalid_voluntary_exit_with_current_fork_version_is_before_fork_epoch(spec, state): - yield from _run_voluntary_exit_processing_test( + yield from run_voluntary_exit_processing_test( spec, state, fork_version=state.fork.current_version, @@ -60,11 +68,11 @@ def test_invalid_voluntary_exit_with_current_fork_version_is_before_fork_epoch(s ) -@with_bellatrix_and_later +@with_phases(BELLATRIX_AND_CAPELLA) @spec_state_test @always_bls def test_voluntary_exit_with_current_fork_version_not_is_before_fork_epoch(spec, state): - yield from _run_voluntary_exit_processing_test( + yield from run_voluntary_exit_processing_test( spec, state, fork_version=state.fork.current_version, @@ -72,13 +80,13 @@ def test_voluntary_exit_with_current_fork_version_not_is_before_fork_epoch(spec, ) -@with_bellatrix_and_later +@with_phases([BELLATRIX, CAPELLA, DENEB]) @spec_state_test @always_bls def test_voluntary_exit_with_previous_fork_version_is_before_fork_epoch(spec, state): assert state.fork.previous_version != state.fork.current_version - yield from _run_voluntary_exit_processing_test( + yield from run_voluntary_exit_processing_test( spec, state, fork_version=state.fork.previous_version, @@ -86,13 +94,13 @@ def test_voluntary_exit_with_previous_fork_version_is_before_fork_epoch(spec, st ) -@with_bellatrix_and_later +@with_phases(BELLATRIX_AND_CAPELLA) @spec_state_test @always_bls def test_invalid_voluntary_exit_with_previous_fork_version_not_is_before_fork_epoch(spec, state): assert state.fork.previous_version != state.fork.current_version - yield from _run_voluntary_exit_processing_test( + yield from run_voluntary_exit_processing_test( spec, state, fork_version=state.fork.previous_version, @@ -107,7 +115,7 @@ def test_invalid_voluntary_exit_with_previous_fork_version_not_is_before_fork_ep def test_invalid_voluntary_exit_with_genesis_fork_version_is_before_fork_epoch(spec, state): assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version) - yield from _run_voluntary_exit_processing_test( + yield from run_voluntary_exit_processing_test( spec, state, fork_version=spec.config.GENESIS_FORK_VERSION, @@ -122,7 +130,7 @@ def test_invalid_voluntary_exit_with_genesis_fork_version_is_before_fork_epoch(s def test_invalid_voluntary_exit_with_genesis_fork_version_not_is_before_fork_epoch(spec, state): assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version) - yield from _run_voluntary_exit_processing_test( + yield from run_voluntary_exit_processing_test( spec, state, fork_version=spec.config.GENESIS_FORK_VERSION, diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/__init__.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_voluntary_exit.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_voluntary_exit.py new file mode 100644 index 000000000..371fcfed4 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_voluntary_exit.py @@ -0,0 +1,45 @@ +from eth2spec.test.context import ( + always_bls, + spec_state_test, + with_phases, + with_deneb_and_later, +) +from eth2spec.test.helpers.constants import ( + DENEB, +) +from eth2spec.test.bellatrix.block_processing.test_process_voluntary_exit import ( + run_voluntary_exit_processing_test, +) + + +@with_deneb_and_later +@spec_state_test +@always_bls +def test_invalid_voluntary_exit_with_current_fork_version_not_is_before_fork_epoch(spec, state): + """ + Since Deneb, the VoluntaryExit domain is fixed to `CAPELLA_FORK_VERSION` + """ + yield from run_voluntary_exit_processing_test( + spec, + state, + fork_version=state.fork.current_version, + is_before_fork_epoch=False, + valid=False, + ) + + +@with_phases([DENEB]) +@spec_state_test +@always_bls +def test_voluntary_exit_with_previous_fork_version_not_is_before_fork_epoch(spec, state): + """ + Since Deneb, the VoluntaryExit domain is fixed to `CAPELLA_FORK_VERSION` + """ + assert state.fork.previous_version != state.fork.current_version + + yield from run_voluntary_exit_processing_test( + spec, + state, + fork_version=state.fork.previous_version, + is_before_fork_epoch=False, + ) diff --git a/tests/core/pyspec/eth2spec/test/eip6110/block_processing/test_process_voluntary_exit.py b/tests/core/pyspec/eth2spec/test/eip6110/block_processing/test_process_voluntary_exit.py new file mode 100644 index 000000000..4128a1181 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/eip6110/block_processing/test_process_voluntary_exit.py @@ -0,0 +1,44 @@ +from eth2spec.test.context import ( + always_bls, + spec_state_test, + with_eip6110_and_later, +) +from eth2spec.test.bellatrix.block_processing.test_process_voluntary_exit import ( + run_voluntary_exit_processing_test, +) + + +@with_eip6110_and_later +@spec_state_test +@always_bls +def test_invalid_voluntary_exit_with_previous_fork_version_not_is_before_fork_epoch(spec, state): + """ + Since Deneb, the VoluntaryExit domain is fixed to `CAPELLA_FORK_VERSION` + """ + assert state.fork.previous_version != state.fork.current_version + + yield from run_voluntary_exit_processing_test( + spec, + state, + fork_version=state.fork.previous_version, + is_before_fork_epoch=False, + valid=False, + ) + + +@with_eip6110_and_later +@spec_state_test +@always_bls +def test_invalid_voluntary_exit_with_previous_fork_version_is_before_fork_epoch(spec, state): + """ + Since Deneb, the VoluntaryExit domain is fixed to `CAPELLA_FORK_VERSION` + """ + assert state.fork.previous_version != state.fork.current_version + + yield from run_voluntary_exit_processing_test( + spec, + state, + fork_version=state.fork.previous_version, + is_before_fork_epoch=True, + valid=False, + ) diff --git a/tests/core/pyspec/eth2spec/test/helpers/voluntary_exits.py b/tests/core/pyspec/eth2spec/test/helpers/voluntary_exits.py index cac101dff..2e8139db6 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/voluntary_exits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/voluntary_exits.py @@ -1,29 +1,31 @@ from random import Random from eth2spec.utils import bls from eth2spec.test.context import expect_assertion_error +from eth2spec.test.helpers.forks import is_post_deneb from eth2spec.test.helpers.keys import privkeys def prepare_signed_exits(spec, state, indices, fork_version=None): - if fork_version is None: - domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT) - else: - domain = spec.compute_domain(spec.DOMAIN_VOLUNTARY_EXIT, fork_version, state.genesis_validators_root) - def create_signed_exit(index): - exit = spec.VoluntaryExit( + voluntary_exit = spec.VoluntaryExit( epoch=spec.get_current_epoch(state), validator_index=index, ) - signing_root = spec.compute_signing_root(exit, domain) - return spec.SignedVoluntaryExit(message=exit, signature=bls.Sign(privkeys[index], signing_root)) + return sign_voluntary_exit(spec, state, voluntary_exit, privkeys[index], fork_version=fork_version) return [create_signed_exit(index) for index in indices] def sign_voluntary_exit(spec, state, voluntary_exit, privkey, fork_version=None): if fork_version is None: - domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) + if is_post_deneb(spec): + domain = spec.compute_domain( + spec.DOMAIN_VOLUNTARY_EXIT, + spec.config.CAPELLA_FORK_VERSION, + state.genesis_validators_root, + ) + else: + domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) else: domain = spec.compute_domain(spec.DOMAIN_VOLUNTARY_EXIT, fork_version, state.genesis_validators_root) diff --git a/tests/generators/operations/main.py b/tests/generators/operations/main.py index fc2217917..2cff8bdf6 100644 --- a/tests/generators/operations/main.py +++ b/tests/generators/operations/main.py @@ -36,10 +36,14 @@ if __name__ == "__main__": ]} capella_mods = combine_mods(_new_capella_mods, bellatrix_mods) - deneb_mods = capella_mods + _new_deneb_mods = {key: 'eth2spec.test.deneb.block_processing.test_process_' + key for key in [ + 'voluntary_exit', + ]} + deneb_mods = combine_mods(_new_deneb_mods, capella_mods) _new_eip6110_mods = {key: 'eth2spec.test.eip6110.block_processing.test_process_' + key for key in [ 'deposit_receipt', + 'voluntary_exit', ]} eip6110_mods = combine_mods(_new_eip6110_mods, deneb_mods)