From 332ad4cb576c35dbc8e37a9a9999048562b8f450 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sun, 30 Oct 2022 12:50:56 +0100 Subject: [PATCH 01/11] Move `is_post_xxx` functions to new module Moving the `is_post_xxx` functions to a separate module allows `genesis` to also use them (cyclic import from `context` prevented this before). This allows removing `FORKS_BEFORE_ALTAIR` and `FORKS_BEFORE_BELLATRIX` constants and adding a more general `is_post_fork` function that needs less maintenance. This then allows definition of `with_all_phases_from` to streamline the implementation of the `with_xxx_and_later` decorators. --- .../altair/unittests/test_config_override.py | 5 ++- tests/core/pyspec/eth2spec/test/context.py | 40 ++++++++----------- .../eth2spec/test/helpers/attestations.py | 3 +- .../pyspec/eth2spec/test/helpers/block.py | 2 +- .../pyspec/eth2spec/test/helpers/constants.py | 5 +-- .../pyspec/eth2spec/test/helpers/deposits.py | 6 +-- .../eth2spec/test/helpers/epoch_processing.py | 2 +- .../test/helpers/execution_payload.py | 2 +- .../pyspec/eth2spec/test/helpers/genesis.py | 10 +++-- .../pyspec/eth2spec/test/helpers/phases.py | 33 +++++++++++++++ .../test/helpers/proposer_slashings.py | 2 +- .../pyspec/eth2spec/test/helpers/random.py | 2 +- .../pyspec/eth2spec/test/helpers/rewards.py | 2 +- .../pyspec/eth2spec/test/helpers/state.py | 3 +- ..._process_justification_and_finalization.py | 3 +- .../test_process_rewards_and_penalties.py | 2 + .../test_process_slashings.py | 3 +- .../test/phase0/fork_choice/test_get_head.py | 4 +- .../phase0/genesis/test_initialization.py | 4 +- .../test/phase0/genesis/test_validity.py | 4 +- .../test/phase0/sanity/test_blocks.py | 3 +- .../unittests/test_config_invariants.py | 4 +- 22 files changed, 91 insertions(+), 53 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/helpers/phases.py 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 b7df49790..e3836d3c9 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,12 +1,13 @@ from eth2spec.test.context import ( - is_post_capella, - is_post_eip4844, spec_configured_state_test, spec_state_test_with_matching_config, with_all_phases, with_phases, ) from eth2spec.test.helpers.constants import ALTAIR +from eth2spec.test.helpers.phases import ( + is_post_capella, is_post_eip4844, +) @with_phases([ALTAIR]) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index bc04c05f2..7684e74be 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -13,9 +13,10 @@ from .exceptions import SkippedTest from .helpers.constants import ( PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844, SHARDING, MINIMAL, MAINNET, - ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_BELLATRIX, + ALL_PHASES, ALL_FORK_UPGRADES, ) +from .helpers.phases import is_post_fork from .helpers.typing import SpecForkName, PresetBaseName from .helpers.genesis import create_genesis_state from .utils import ( @@ -408,6 +409,15 @@ def with_all_phases(fn): return with_phases(ALL_PHASES)(fn) +def with_all_phases_from(earliest_phase): + """ + A decorator factory for running a tests with every phase except the ones listed + """ + def decorator(fn): + return with_phases([phase for phase in ALL_PHASES if is_post_fork(phase, earliest_phase)])(fn) + return decorator + + def with_all_phases_except(exclusion_phases): """ A decorator factory for running a tests with every phase except the ones listed @@ -417,6 +427,12 @@ def with_all_phases_except(exclusion_phases): return decorator +with_altair_and_later = with_all_phases_from(ALTAIR) +with_bellatrix_and_later = with_all_phases_from(BELLATRIX) +with_capella_and_later = with_all_phases_from(CAPELLA) +with_eip4844_and_later = with_all_phases_from(EIP4844) + + def _get_preset_targets(kw): preset_name = DEFAULT_TEST_PRESET if 'preset' in kw: @@ -587,28 +603,6 @@ def with_config_overrides(config_overrides): return decorator -def is_post_altair(spec): - return spec.fork not in FORKS_BEFORE_ALTAIR - - -def is_post_bellatrix(spec): - return spec.fork not in FORKS_BEFORE_BELLATRIX - - -def is_post_capella(spec): - return spec.fork == CAPELLA - - -def is_post_eip4844(spec): - return spec.fork == EIP4844 - - -with_altair_and_later = with_all_phases_except([PHASE0]) -with_bellatrix_and_later = with_all_phases_except([PHASE0, ALTAIR]) -with_capella_and_later = with_all_phases_except([PHASE0, ALTAIR, BELLATRIX, EIP4844]) -with_eip4844_and_later = with_all_phases_except([PHASE0, ALTAIR, BELLATRIX, CAPELLA]) - - def only_generator(reason): def _decorator(inner): def _wrapper(*args, **kwargs): diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index 854dbf59a..c3db16675 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -2,10 +2,11 @@ from lru import LRU from typing import List -from eth2spec.test.context import expect_assertion_error, is_post_altair +from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.state import state_transition_and_sign_block, next_epoch, next_slot from eth2spec.test.helpers.block import build_empty_block_for_next_slot from eth2spec.test.helpers.keys import privkeys +from eth2spec.test.helpers.phases import is_post_altair from eth2spec.utils import bls from eth2spec.utils.ssz.ssz_typing import Bitlist diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index facaa48b6..24bc68e60 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -1,6 +1,6 @@ -from eth2spec.test.context import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.execution_payload import build_empty_execution_payload from eth2spec.test.helpers.keys import privkeys +from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.utils import bls from eth2spec.utils.bls import only_with_bls from eth2spec.utils.ssz.ssz_impl import hash_tree_root diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py index 0763c42cc..598b189ef 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/constants.py +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -26,9 +26,6 @@ ALL_PHASES = ( # The forks that output to the test vectors. TESTGEN_FORKS = (PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844) -FORKS_BEFORE_ALTAIR = (PHASE0,) -FORKS_BEFORE_BELLATRIX = (PHASE0, ALTAIR) - # TODO: no EIP4844 fork tests now. Should add when we figure out the content of Capella. ALL_FORK_UPGRADES = { # pre_fork_name: post_fork_name @@ -37,7 +34,7 @@ ALL_FORK_UPGRADES = { BELLATRIX: CAPELLA, } ALL_PRE_POST_FORKS = ALL_FORK_UPGRADES.items() -AFTER_BELLATRIX_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key not in FORKS_BEFORE_ALTAIR} +AFTER_BELLATRIX_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key != PHASE0} AFTER_BELLATRIX_PRE_POST_FORKS = AFTER_BELLATRIX_UPGRADES.items() # diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index 4639b22dc..f013fdc7e 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -1,10 +1,8 @@ from random import Random -from eth2spec.test.context import ( - is_post_altair, - expect_assertion_error, -) +from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.keys import pubkeys, privkeys +from eth2spec.test.helpers.phases import is_post_altair from eth2spec.test.helpers.state import get_balance from eth2spec.utils import bls from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof diff --git a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py index e18c239f1..ebfce5cad 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py +++ b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py @@ -1,5 +1,5 @@ -from eth2spec.test.context import is_post_altair +from eth2spec.test.helpers.phases import is_post_altair def get_process_calls(spec): diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 83162e1c2..f2dd15e39 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -1,5 +1,5 @@ from eth2spec.debug.random_value import get_random_bytes_list -from eth2spec.test.context import is_post_capella +from eth2spec.test.helpers.phases import is_post_capella def build_empty_execution_payload(spec, state, randao_mix=None): diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index e497a0ce2..bd4f0e421 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -1,6 +1,8 @@ from eth2spec.test.helpers.constants import ( ALTAIR, BELLATRIX, CAPELLA, EIP4844, - FORKS_BEFORE_ALTAIR, FORKS_BEFORE_BELLATRIX, +) +from eth2spec.test.helpers.phases import ( + is_post_altair, is_post_bellatrix, ) from eth2spec.test.helpers.keys import pubkeys @@ -88,7 +90,7 @@ def create_genesis_state(spec, validator_balances, activation_threshold): if validator.effective_balance >= activation_threshold: validator.activation_eligibility_epoch = spec.GENESIS_EPOCH validator.activation_epoch = spec.GENESIS_EPOCH - if spec.fork not in FORKS_BEFORE_ALTAIR: + if is_post_altair(spec): state.previous_epoch_participation.append(spec.ParticipationFlags(0b0000_0000)) state.current_epoch_participation.append(spec.ParticipationFlags(0b0000_0000)) state.inactivity_scores.append(spec.uint64(0)) @@ -96,13 +98,13 @@ def create_genesis_state(spec, validator_balances, activation_threshold): # Set genesis validators root for domain separation and chain versioning state.genesis_validators_root = spec.hash_tree_root(state.validators) - if spec.fork not in FORKS_BEFORE_ALTAIR: + if is_post_altair(spec): # Fill in sync committees # Note: A duplicate committee is assigned for the current and next committee at genesis state.current_sync_committee = spec.get_next_sync_committee(state) state.next_sync_committee = spec.get_next_sync_committee(state) - if spec.fork not in FORKS_BEFORE_BELLATRIX: + if is_post_bellatrix(spec): # Initialize the execution payload header (with block number and genesis time set to 0) state.latest_execution_payload_header = get_sample_genesis_execution_payload_header( spec, diff --git a/tests/core/pyspec/eth2spec/test/helpers/phases.py b/tests/core/pyspec/eth2spec/test/helpers/phases.py new file mode 100644 index 000000000..4bb75413d --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/helpers/phases.py @@ -0,0 +1,33 @@ +from .constants import ( + PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844, +) + + +def is_post_fork(a, b): + if a == EIP4844: + return b in [PHASE0, ALTAIR, BELLATRIX, EIP4844] + if a == CAPELLA: + return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA] + if a == BELLATRIX: + return b in [PHASE0, ALTAIR, BELLATRIX] + if a == ALTAIR: + return b in [PHASE0, ALTAIR] + if a == PHASE0: + return b in [PHASE0] + assert False # Fork is missing + + +def is_post_altair(spec): + return is_post_fork(spec.fork, ALTAIR) + + +def is_post_bellatrix(spec): + return is_post_fork(spec.fork, BELLATRIX) + + +def is_post_capella(spec): + return is_post_fork(spec.fork, CAPELLA) + + +def is_post_eip4844(spec): + return is_post_fork(spec.fork, EIP4844) diff --git a/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py b/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py index 517190869..abb8bd62a 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py +++ b/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py @@ -1,6 +1,6 @@ -from eth2spec.test.context import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.block_header import sign_block_header from eth2spec.test.helpers.keys import pubkey_to_privkey +from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.state import get_balance from eth2spec.test.helpers.sync_committee import ( compute_committee_indices, diff --git a/tests/core/pyspec/eth2spec/test/helpers/random.py b/tests/core/pyspec/eth2spec/test/helpers/random.py index 0dc446d19..1b093fb41 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/random.py +++ b/tests/core/pyspec/eth2spec/test/helpers/random.py @@ -1,8 +1,8 @@ from random import Random from eth2spec.test.helpers.attestations import cached_prepare_state_with_attestations -from eth2spec.test.context import is_post_altair from eth2spec.test.helpers.deposits import mock_deposit +from eth2spec.test.helpers.phases import is_post_altair from eth2spec.test.helpers.state import next_epoch diff --git a/tests/core/pyspec/eth2spec/test/helpers/rewards.py b/tests/core/pyspec/eth2spec/test/helpers/rewards.py index ec7ff25e3..c3a5cf2a9 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/rewards.py +++ b/tests/core/pyspec/eth2spec/test/helpers/rewards.py @@ -2,7 +2,7 @@ from random import Random from lru import LRU from eth2spec.phase0.mainnet import VALIDATOR_REGISTRY_LIMIT # equal everywhere, fine to import -from eth2spec.test.context import is_post_altair, is_post_bellatrix +from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.state import ( next_epoch, ) diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 6f1923e54..2190f1759 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -1,5 +1,6 @@ -from eth2spec.test.context import expect_assertion_error, is_post_altair +from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block +from eth2spec.test.helpers.phases import is_post_altair from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py index 1d3197ba6..c94d3e757 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py @@ -1,8 +1,9 @@ from random import Random -from eth2spec.test.context import is_post_altair, spec_state_test, with_all_phases +from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, ) +from eth2spec.test.helpers.phases import is_post_altair from eth2spec.test.helpers.state import transition_to, next_epoch_via_block, next_slot from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py index 2bb297498..443aa0c3c 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py @@ -5,6 +5,8 @@ from eth2spec.test.context import ( with_custom_state, zero_activation_threshold, misc_balances, low_single_balance, +) +from eth2spec.test.helpers.phases import ( is_post_altair, ) from eth2spec.test.helpers.state import ( diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py index e7ae96ecb..7ad487fae 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py @@ -1,9 +1,10 @@ from random import Random -from eth2spec.test.context import spec_state_test, with_all_phases, is_post_altair, is_post_bellatrix +from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, run_epoch_processing_to ) from eth2spec.test.helpers.random import randomize_state +from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.state import has_active_balance_differential from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators from eth2spec.test.helpers.state import next_epoch diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index e8c2dc268..286bd06e5 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -2,7 +2,6 @@ import random from eth_utils import encode_hex from eth2spec.test.context import ( - is_post_altair, spec_state_test, with_all_phases, with_presets, @@ -24,6 +23,9 @@ from eth2spec.test.helpers.fork_choice import ( tick_and_run_on_attestation, tick_and_add_block, ) +from eth2spec.test.helpers.phases import ( + is_post_altair, +) from eth2spec.test.helpers.state import ( next_slots, next_epoch, diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py index 53dd3760a..f311ec127 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py @@ -1,5 +1,4 @@ from eth2spec.test.context import ( - is_post_altair, single_phase, spec_test, with_presets, @@ -10,6 +9,9 @@ from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, prepare_random_genesis_deposits, ) +from eth2spec.test.helpers.phases import ( + is_post_altair, +) def get_post_altair_description(spec): diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py index e17e72a4e..e0e64875d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py @@ -1,5 +1,4 @@ from eth2spec.test.context import ( - is_post_altair, spec_test, single_phase, with_presets, @@ -9,6 +8,9 @@ from eth2spec.test.helpers.constants import MINIMAL from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, ) +from eth2spec.test.helpers.phases import ( + is_post_altair, +) def get_post_altair_description(spec): diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index a09c02b9a..57ae90093 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -30,6 +30,7 @@ from eth2spec.test.helpers.sync_committee import ( compute_sync_committee_participant_reward_and_penalty, ) from eth2spec.test.helpers.constants import PHASE0, MINIMAL +from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.test.context import ( spec_test, spec_state_test, dump_skipping_message, with_phases, with_all_phases, single_phase, @@ -37,8 +38,6 @@ from eth2spec.test.context import ( with_presets, with_custom_state, large_validator_set, - is_post_altair, - is_post_bellatrix, ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py index 7f0fd5d73..f33a2802b 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py @@ -1,9 +1,11 @@ from eth2spec.test.context import ( spec_state_test, with_all_phases, - is_post_altair, is_post_bellatrix, ) from eth2spec.test.helpers.constants import MAX_UINT_64 +from eth2spec.test.helpers.phases import ( + is_post_altair, is_post_bellatrix, +) def check_bound(value, lower_bound, upper_bound): From 8bb1751f4664bb319adc4d34f95b4450e64a85aa Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 7 Nov 2022 15:22:26 -0700 Subject: [PATCH 02/11] Add note to Capella validator guide about BLS to execution change --- specs/capella/validator.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/specs/capella/validator.md b/specs/capella/validator.md index 90176e035..9bbc8d8db 100644 --- a/specs/capella/validator.md +++ b/specs/capella/validator.md @@ -19,6 +19,8 @@ - [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody) - [ExecutionPayload](#executionpayload) - [BLS to execution changes](#bls-to-execution-changes) +- [Enabling validator withdrawals](#enabling-validator-withdrawals) + - [Changing from BLS to execution withdrawal credentials](#changing-from-bls-to-execution-withdrawal-credentials) @@ -111,3 +113,38 @@ def prepare_execution_payload(state: BeaconState, ##### BLS to execution changes Up to `MAX_BLS_TO_EXECUTION_CHANGES`, [`BLSToExecutionChange`](./beacon-chain.md#blstoexecutionchange) objects can be included in the `block`. The BLS to execution changes must satisfy the verification conditions found in [BLS to execution change processing](./beacon-chain.md#new-process_bls_to_execution_change). + +## Enabling validator withdrawals + +Stake belonging to validators that can safely be withdrawn from the beacon chain happens via an automatic process. + +There is one prerequisite task to perform before a validator can particpate in this automatic process: +ensuring the withdrawal credentials are for the execution layer, i.e. having an `ETH1_ADDRESS_WITHDRAWAL_PREFIX`. + +If a validator has a `BLS_WITHDRAWAL_PREFIX` withdrawal credential prefix, Capella adds the ability for a validator +to make a one-time message that changes their withdrawal credential from the version authenticated with a BLS key to the +version compatible with the execution layer. + +Validators who wish to enable withdrawals **MUST** assemble, sign, and broadcast this message so that it is accepted +on the beacon chain. Validators who do not want to enable withdrawals and have the `BLS_WITHDRAWAL_PREFIX` version of +withdrawal credentials can simply wait until they are ready to create this message and will not particpate in the +automatic withdrawal process. + +### Changing from BLS to execution withdrawal credentials + +First, the validator must construct a valid [`BLSToExecutionChange`](./beacon-chain.md#blstoexecutionchange) `message`. +This `message` contains the `validator_index` for the validator who wishes to change their credentials, the `from_bls_pubkey` containing the BLS public key corresponding to the **withdrawal BLS secret key** used to form the `BLS_WITHDRAWAL_PREFIX` withdrawal credential, and the `to_execution_address` specifying where the validator wants stake to be withdrawn to on the execution layer. + +**NOTE**: The withdrawal key pair used to construct the `BLS_WITHDRAWAL_PREFIX` withdrawal credential should be distinct from the signing key pair used to operate the validator under typical circumstances. Consult your validator deposit tooling documentation for further details if you are not aware of the difference. + +The `from_bls_pubkey` is compared against the existing withdrawal credential on-chain for the given `validator_index` so +it is unlikely a validator will incorrectly specify this data; however, this message can only be issued once and is currently +irreversible once on-chain so take care with the `to_execution_address`. + +Next, the validator signs the assembled `BLSToExecutionChange` `message` with the **withdrawal BLS secret key** and this +`signature` is placed into a `SignedBLSToExecutionChange` message along with the inner `BLSToExecutionChange` `message`. +Note that the `SignedBLSToExecutionChange` message should pass all of the validations in [`process_bls_to_execution_change`](./beacon-chain.md#new-process_bls_to_execution_change). + +The complete `SignedBLSToExecutionChange` message can be submitted to the consensus layer network. Once included on-chain, +the withdrawal credential change takes effect. No further action is required for a validator to enter into the automated +withdrawal process. From 91de8a09f3be6b15f7b86547ffb010f4ac22ac51 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Tue, 8 Nov 2022 17:06:07 +1100 Subject: [PATCH 03/11] Fix slot checks in light client p2p spec --- specs/altair/light-client/p2p-interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/altair/light-client/p2p-interface.md b/specs/altair/light-client/p2p-interface.md index f7575cf53..09065d8d4 100644 --- a/specs/altair/light-client/p2p-interface.md +++ b/specs/altair/light-client/p2p-interface.md @@ -59,7 +59,7 @@ New global topics are added to provide light clients with the latest updates. This topic is used to propagate the latest `LightClientFinalityUpdate` to light clients, allowing them to keep track of the latest `finalized_header`. The following validations MUST pass before forwarding the `finality_update` on the network. -- _[IGNORE]_ No other `finality_update` with a lower or equal `finalized_header.slot` was already forwarded on the network +- _[IGNORE]_ The `finalized_head.slot` is greater than the `slot` of all previously forwarded finality updates - _[IGNORE]_ The `finality_update` is received after the block at `signature_slot` was given enough time to propagate through the network -- i.e. validate that one-third of `finality_update.signature_slot` has transpired (`SECONDS_PER_SLOT / INTERVALS_PER_SLOT` seconds after the start of the slot, with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) For full nodes, the following validations MUST additionally pass before forwarding the `finality_update` on the network. @@ -87,7 +87,7 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: This topic is used to propagate the latest `LightClientOptimisticUpdate` to light clients, allowing them to keep track of the latest `optimistic_header`. The following validations MUST pass before forwarding the `optimistic_update` on the network. -- _[IGNORE]_ No other `optimistic_update` with a lower or equal `attested_header.slot` was already forwarded on the network +- _[IGNORE]_ The `attester_header.slot` is greater than the `slot` of all previously forwarded optimistic updates - _[IGNORE]_ The `optimistic_update` is received after the block at `signature_slot` was given enough time to propagate through the network -- i.e. validate that one-third of `optimistic_update.signature_slot` has transpired (`SECONDS_PER_SLOT / INTERVALS_PER_SLOT` seconds after the start of the slot, with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) For full nodes, the following validations MUST additionally pass before forwarding the `optimistic_update` on the network. From dae10111943426ec89641f6cf7729bf10ae64040 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 9 Nov 2022 09:41:21 +1100 Subject: [PATCH 04/11] Fix typos Co-authored-by: Alex Stokes --- specs/altair/light-client/p2p-interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/altair/light-client/p2p-interface.md b/specs/altair/light-client/p2p-interface.md index 09065d8d4..9ee6f89a5 100644 --- a/specs/altair/light-client/p2p-interface.md +++ b/specs/altair/light-client/p2p-interface.md @@ -59,7 +59,7 @@ New global topics are added to provide light clients with the latest updates. This topic is used to propagate the latest `LightClientFinalityUpdate` to light clients, allowing them to keep track of the latest `finalized_header`. The following validations MUST pass before forwarding the `finality_update` on the network. -- _[IGNORE]_ The `finalized_head.slot` is greater than the `slot` of all previously forwarded finality updates +- _[IGNORE]_ The `finalized_header.slot` is greater than the `slot` of all previously forwarded finality updates - _[IGNORE]_ The `finality_update` is received after the block at `signature_slot` was given enough time to propagate through the network -- i.e. validate that one-third of `finality_update.signature_slot` has transpired (`SECONDS_PER_SLOT / INTERVALS_PER_SLOT` seconds after the start of the slot, with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) For full nodes, the following validations MUST additionally pass before forwarding the `finality_update` on the network. @@ -87,7 +87,7 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: This topic is used to propagate the latest `LightClientOptimisticUpdate` to light clients, allowing them to keep track of the latest `optimistic_header`. The following validations MUST pass before forwarding the `optimistic_update` on the network. -- _[IGNORE]_ The `attester_header.slot` is greater than the `slot` of all previously forwarded optimistic updates +- _[IGNORE]_ The `attested_header.slot` is greater than the `slot` of all previously forwarded optimistic updates - _[IGNORE]_ The `optimistic_update` is received after the block at `signature_slot` was given enough time to propagate through the network -- i.e. validate that one-third of `optimistic_update.signature_slot` has transpired (`SECONDS_PER_SLOT / INTERVALS_PER_SLOT` seconds after the start of the slot, with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) For full nodes, the following validations MUST additionally pass before forwarding the `optimistic_update` on the network. From 579f8fd1d26c310aa223494a478976ea117019cf Mon Sep 17 00:00:00 2001 From: terencechain Date: Wed, 9 Nov 2022 15:06:58 -0800 Subject: [PATCH 05/11] EIP4844: Explicitly mention old gossip validations for block --- specs/eip4844/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/eip4844/p2p-interface.md b/specs/eip4844/p2p-interface.md index 1576fe96f..5d175ac2c 100644 --- a/specs/eip4844/p2p-interface.md +++ b/specs/eip4844/p2p-interface.md @@ -85,7 +85,7 @@ EIP4844 introduces a new global topic for beacon block and blobs-sidecars. This topic is used to propagate new signed and coupled beacon blocks and blobs sidecars to all nodes on the networks. -The following validations MUST pass before forwarding the `signed_beacon_block_and_blobs_sidecar` on the network. +In addition to the gossip validations for `beacon_block` topic from prior specifications, the following validations MUST pass before forwarding the `signed_beacon_block_and_blobs_sidecar` on the network. Alias `signed_beacon_block = signed_beacon_block_and_blobs_sidecar.beacon_block`, `block = signed_beacon_block.message`, `execution_payload = block.body.execution_payload`. - _[REJECT]_ The KZG commitments of the blobs are all correctly encoded compressed BLS G1 Points. -- i.e. `all(bls.KeyValidate(commitment) for commitment in block.body.blob_kzg_commitments)` From 76157f91d75d967ae215a292fe419b5a05350d87 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 10 Nov 2022 13:26:00 +0100 Subject: [PATCH 06/11] Rename `phases.py` to `forks.py`; add `ValueError` check Co-authored-by: Hsiao-Wei Wang --- .../eth2spec/test/altair/unittests/test_config_override.py | 2 +- tests/core/pyspec/eth2spec/test/context.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/attestations.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/block.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/deposits.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/execution_payload.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/{phases.py => forks.py} | 2 +- tests/core/pyspec/eth2spec/test/helpers/genesis.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/random.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/rewards.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/state.py | 2 +- .../test_process_justification_and_finalization.py | 2 +- .../epoch_processing/test_process_rewards_and_penalties.py | 2 +- .../test/phase0/epoch_processing/test_process_slashings.py | 2 +- .../pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py | 2 +- .../pyspec/eth2spec/test/phase0/genesis/test_initialization.py | 2 +- tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py | 2 +- tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py | 2 +- .../eth2spec/test/phase0/unittests/test_config_invariants.py | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) rename tests/core/pyspec/eth2spec/test/helpers/{phases.py => forks.py} (93%) 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 e3836d3c9..5448781ec 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 @@ -5,7 +5,7 @@ from eth2spec.test.context import ( with_phases, ) from eth2spec.test.helpers.constants import ALTAIR -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_capella, is_post_eip4844, ) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 7684e74be..920b97f31 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -16,7 +16,7 @@ from .helpers.constants import ( ALL_PHASES, ALL_FORK_UPGRADES, ) -from .helpers.phases import is_post_fork +from .helpers.forks import is_post_fork from .helpers.typing import SpecForkName, PresetBaseName from .helpers.genesis import create_genesis_state from .utils import ( diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index c3db16675..a636adace 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -5,8 +5,8 @@ from typing import List from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.state import state_transition_and_sign_block, next_epoch, next_slot from eth2spec.test.helpers.block import build_empty_block_for_next_slot +from eth2spec.test.helpers.forks import is_post_altair from eth2spec.test.helpers.keys import privkeys -from eth2spec.test.helpers.phases import is_post_altair from eth2spec.utils import bls from eth2spec.utils.ssz.ssz_typing import Bitlist diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index 24bc68e60..270bc4be1 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -1,6 +1,6 @@ from eth2spec.test.helpers.execution_payload import build_empty_execution_payload +from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.keys import privkeys -from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.utils import bls from eth2spec.utils.bls import only_with_bls from eth2spec.utils.ssz.ssz_impl import hash_tree_root diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index f013fdc7e..f8ab75e85 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -1,8 +1,8 @@ from random import Random from eth2spec.test.context import expect_assertion_error +from eth2spec.test.helpers.forks import is_post_altair from eth2spec.test.helpers.keys import pubkeys, privkeys -from eth2spec.test.helpers.phases import is_post_altair from eth2spec.test.helpers.state import get_balance from eth2spec.utils import bls from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof diff --git a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py index ebfce5cad..ed61f8bdb 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py +++ b/tests/core/pyspec/eth2spec/test/helpers/epoch_processing.py @@ -1,5 +1,5 @@ -from eth2spec.test.helpers.phases import is_post_altair +from eth2spec.test.helpers.forks import is_post_altair def get_process_calls(spec): diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index f2dd15e39..b745d80c8 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -1,5 +1,5 @@ from eth2spec.debug.random_value import get_random_bytes_list -from eth2spec.test.helpers.phases import is_post_capella +from eth2spec.test.helpers.forks import is_post_capella def build_empty_execution_payload(spec, state, randao_mix=None): diff --git a/tests/core/pyspec/eth2spec/test/helpers/phases.py b/tests/core/pyspec/eth2spec/test/helpers/forks.py similarity index 93% rename from tests/core/pyspec/eth2spec/test/helpers/phases.py rename to tests/core/pyspec/eth2spec/test/helpers/forks.py index 4bb75413d..d6d88876a 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/phases.py +++ b/tests/core/pyspec/eth2spec/test/helpers/forks.py @@ -14,7 +14,7 @@ def is_post_fork(a, b): return b in [PHASE0, ALTAIR] if a == PHASE0: return b in [PHASE0] - assert False # Fork is missing + raise ValueError("Unknown fork name %s" % a) def is_post_altair(spec): diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index bd4f0e421..ee3068788 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -1,7 +1,7 @@ from eth2spec.test.helpers.constants import ( ALTAIR, BELLATRIX, CAPELLA, EIP4844, ) -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_altair, is_post_bellatrix, ) from eth2spec.test.helpers.keys import pubkeys diff --git a/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py b/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py index abb8bd62a..329188829 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py +++ b/tests/core/pyspec/eth2spec/test/helpers/proposer_slashings.py @@ -1,6 +1,6 @@ from eth2spec.test.helpers.block_header import sign_block_header +from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.keys import pubkey_to_privkey -from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.state import get_balance from eth2spec.test.helpers.sync_committee import ( compute_committee_indices, diff --git a/tests/core/pyspec/eth2spec/test/helpers/random.py b/tests/core/pyspec/eth2spec/test/helpers/random.py index 1b093fb41..eb280076f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/random.py +++ b/tests/core/pyspec/eth2spec/test/helpers/random.py @@ -2,7 +2,7 @@ from random import Random from eth2spec.test.helpers.attestations import cached_prepare_state_with_attestations from eth2spec.test.helpers.deposits import mock_deposit -from eth2spec.test.helpers.phases import is_post_altair +from eth2spec.test.helpers.forks import is_post_altair from eth2spec.test.helpers.state import next_epoch diff --git a/tests/core/pyspec/eth2spec/test/helpers/rewards.py b/tests/core/pyspec/eth2spec/test/helpers/rewards.py index c3a5cf2a9..4168c2490 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/rewards.py +++ b/tests/core/pyspec/eth2spec/test/helpers/rewards.py @@ -2,7 +2,7 @@ from random import Random from lru import LRU from eth2spec.phase0.mainnet import VALIDATOR_REGISTRY_LIMIT # equal everywhere, fine to import -from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix +from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.state import ( next_epoch, ) diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 2190f1759..0dc17b00f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -1,6 +1,6 @@ from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block -from eth2spec.test.helpers.phases import is_post_altair +from eth2spec.test.helpers.forks import is_post_altair from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py index c94d3e757..dba0442cb 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_justification_and_finalization.py @@ -3,7 +3,7 @@ from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, ) -from eth2spec.test.helpers.phases import is_post_altair +from eth2spec.test.helpers.forks import is_post_altair from eth2spec.test.helpers.state import transition_to, next_epoch_via_block, next_slot from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py index 443aa0c3c..e3c01f263 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py @@ -6,7 +6,7 @@ from eth2spec.test.context import ( zero_activation_threshold, misc_balances, low_single_balance, ) -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_altair, ) from eth2spec.test.helpers.state import ( diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py index 7ad487fae..172243077 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_slashings.py @@ -3,8 +3,8 @@ from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.helpers.epoch_processing import ( run_epoch_processing_with, run_epoch_processing_to ) +from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.random import randomize_state -from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix from eth2spec.test.helpers.state import has_active_balance_differential from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators from eth2spec.test.helpers.state import next_epoch diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 286bd06e5..990c42031 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -23,7 +23,7 @@ from eth2spec.test.helpers.fork_choice import ( tick_and_run_on_attestation, tick_and_add_block, ) -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_altair, ) from eth2spec.test.helpers.state import ( diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py index f311ec127..4c7c5f28c 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py @@ -9,7 +9,7 @@ from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, prepare_random_genesis_deposits, ) -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_altair, ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py index e0e64875d..aecc96077 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py @@ -8,7 +8,7 @@ from eth2spec.test.helpers.constants import MINIMAL from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, ) -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_altair, ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index 57ae90093..b94a01f7f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -30,7 +30,7 @@ from eth2spec.test.helpers.sync_committee import ( compute_sync_committee_participant_reward_and_penalty, ) from eth2spec.test.helpers.constants import PHASE0, MINIMAL -from eth2spec.test.helpers.phases import is_post_altair, is_post_bellatrix +from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix from eth2spec.test.context import ( spec_test, spec_state_test, dump_skipping_message, with_phases, with_all_phases, single_phase, diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py index f33a2802b..9b27d1deb 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py @@ -3,7 +3,7 @@ from eth2spec.test.context import ( with_all_phases, ) from eth2spec.test.helpers.constants import MAX_UINT_64 -from eth2spec.test.helpers.phases import ( +from eth2spec.test.helpers.forks import ( is_post_altair, is_post_bellatrix, ) From be098b60c0403ab4412afbe3b9f8181f5514e6af Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 10 Nov 2022 09:10:01 -0500 Subject: [PATCH 07/11] Update specs/eip4844/p2p-interface.md --- specs/eip4844/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/eip4844/p2p-interface.md b/specs/eip4844/p2p-interface.md index 5d175ac2c..03363e1b8 100644 --- a/specs/eip4844/p2p-interface.md +++ b/specs/eip4844/p2p-interface.md @@ -85,7 +85,7 @@ EIP4844 introduces a new global topic for beacon block and blobs-sidecars. This topic is used to propagate new signed and coupled beacon blocks and blobs sidecars to all nodes on the networks. -In addition to the gossip validations for `beacon_block` topic from prior specifications, the following validations MUST pass before forwarding the `signed_beacon_block_and_blobs_sidecar` on the network. +In addition to the gossip validations for the `beacon_block` topic from prior specifications, the following validations MUST pass before forwarding the `signed_beacon_block_and_blobs_sidecar` on the network. Alias `signed_beacon_block = signed_beacon_block_and_blobs_sidecar.beacon_block`, `block = signed_beacon_block.message`, `execution_payload = block.body.execution_payload`. - _[REJECT]_ The KZG commitments of the blobs are all correctly encoded compressed BLS G1 Points. -- i.e. `all(bls.KeyValidate(commitment) for commitment in block.body.blob_kzg_commitments)` From 0f93e9aad8ae70cd6a0bdaa9779665a670182553 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 10 Nov 2022 09:12:10 -0500 Subject: [PATCH 08/11] Update specs/capella/validator.md Co-authored-by: Hsiao-Wei Wang --- specs/capella/validator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/capella/validator.md b/specs/capella/validator.md index 9bbc8d8db..32e26bca6 100644 --- a/specs/capella/validator.md +++ b/specs/capella/validator.md @@ -118,7 +118,7 @@ Up to `MAX_BLS_TO_EXECUTION_CHANGES`, [`BLSToExecutionChange`](./beacon-chain.md Stake belonging to validators that can safely be withdrawn from the beacon chain happens via an automatic process. -There is one prerequisite task to perform before a validator can particpate in this automatic process: +There is one prerequisite task to perform before a validator can participate in this automatic process: ensuring the withdrawal credentials are for the execution layer, i.e. having an `ETH1_ADDRESS_WITHDRAWAL_PREFIX`. If a validator has a `BLS_WITHDRAWAL_PREFIX` withdrawal credential prefix, Capella adds the ability for a validator From be85e9356a6029287e6b9b3c02c11447b1a7e3c8 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 10 Nov 2022 09:12:35 -0500 Subject: [PATCH 09/11] Update specs/capella/validator.md Co-authored-by: Hsiao-Wei Wang --- specs/capella/validator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/capella/validator.md b/specs/capella/validator.md index 32e26bca6..0853d052e 100644 --- a/specs/capella/validator.md +++ b/specs/capella/validator.md @@ -141,7 +141,7 @@ The `from_bls_pubkey` is compared against the existing withdrawal credential on- it is unlikely a validator will incorrectly specify this data; however, this message can only be issued once and is currently irreversible once on-chain so take care with the `to_execution_address`. -Next, the validator signs the assembled `BLSToExecutionChange` `message` with the **withdrawal BLS secret key** and this +Next, the validator signs the assembled `message: BLSToExecutionChange` with the **withdrawal BLS secret key** and this `signature` is placed into a `SignedBLSToExecutionChange` message along with the inner `BLSToExecutionChange` `message`. Note that the `SignedBLSToExecutionChange` message should pass all of the validations in [`process_bls_to_execution_change`](./beacon-chain.md#new-process_bls_to_execution_change). From 0e7d3555ead28fdf1f0970f1ea900938d9f7a007 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 10 Nov 2022 11:12:33 -0700 Subject: [PATCH 10/11] minor copy edits --- specs/capella/validator.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/specs/capella/validator.md b/specs/capella/validator.md index 0853d052e..74bad7e6d 100644 --- a/specs/capella/validator.md +++ b/specs/capella/validator.md @@ -116,35 +116,36 @@ Up to `MAX_BLS_TO_EXECUTION_CHANGES`, [`BLSToExecutionChange`](./beacon-chain.md ## Enabling validator withdrawals -Stake belonging to validators that can safely be withdrawn from the beacon chain happens via an automatic process. +Validator balances are fully or partially withdrawn via an automatic process. -There is one prerequisite task to perform before a validator can participate in this automatic process: -ensuring the withdrawal credentials are for the execution layer, i.e. having an `ETH1_ADDRESS_WITHDRAWAL_PREFIX`. +For validators, there is one prerequisite for this automated process: +withdrawal credentials pointing to an execution layer address, i.e. having an `ETH1_ADDRESS_WITHDRAWAL_PREFIX`. -If a validator has a `BLS_WITHDRAWAL_PREFIX` withdrawal credential prefix, Capella adds the ability for a validator -to make a one-time message that changes their withdrawal credential from the version authenticated with a BLS key to the -version compatible with the execution layer. +If a validator has a `BLS_WITHDRAWAL_PREFIX` withdrawal credential prefix, to participate in withdrawals the validator must +create a one-time message to change their withdrawal credential from the version authenticated with a BLS key to the +version compatible with the execution layer. This message -- a `BLSToExecutionChange` -- is available starting in Capella Validators who wish to enable withdrawals **MUST** assemble, sign, and broadcast this message so that it is accepted on the beacon chain. Validators who do not want to enable withdrawals and have the `BLS_WITHDRAWAL_PREFIX` version of -withdrawal credentials can simply wait until they are ready to create this message and will not particpate in the -automatic withdrawal process. +withdrawal credentials can delay creating this message until they are ready to enable withdrawals. ### Changing from BLS to execution withdrawal credentials First, the validator must construct a valid [`BLSToExecutionChange`](./beacon-chain.md#blstoexecutionchange) `message`. -This `message` contains the `validator_index` for the validator who wishes to change their credentials, the `from_bls_pubkey` containing the BLS public key corresponding to the **withdrawal BLS secret key** used to form the `BLS_WITHDRAWAL_PREFIX` withdrawal credential, and the `to_execution_address` specifying where the validator wants stake to be withdrawn to on the execution layer. +This `message` contains the `validator_index` for the validator who wishes to change their credentials, the `from_bls_pubkey` -- the BLS public key corresponding to the **withdrawal BLS secret key** used to form the `BLS_WITHDRAWAL_PREFIX` withdrawal credential, and the `to_execution_address` specifying the execution layer address to which the validator's balances will be withdrawn. -**NOTE**: The withdrawal key pair used to construct the `BLS_WITHDRAWAL_PREFIX` withdrawal credential should be distinct from the signing key pair used to operate the validator under typical circumstances. Consult your validator deposit tooling documentation for further details if you are not aware of the difference. +*Note*: The withdrawal key pair used to construct the `BLS_WITHDRAWAL_PREFIX` withdrawal credential should be distinct from the signing key pair used to operate the validator under typical circumstances. Consult your validator deposit tooling documentation for further details if you are not aware of the difference. -The `from_bls_pubkey` is compared against the existing withdrawal credential on-chain for the given `validator_index` so -it is unlikely a validator will incorrectly specify this data; however, this message can only be issued once and is currently -irreversible once on-chain so take care with the `to_execution_address`. +*Warning*: This message can only be included on-chain once and is +irreversible so ensure the correctness and accessibility to `to_execution_address`. Next, the validator signs the assembled `message: BLSToExecutionChange` with the **withdrawal BLS secret key** and this `signature` is placed into a `SignedBLSToExecutionChange` message along with the inner `BLSToExecutionChange` `message`. Note that the `SignedBLSToExecutionChange` message should pass all of the validations in [`process_bls_to_execution_change`](./beacon-chain.md#new-process_bls_to_execution_change). -The complete `SignedBLSToExecutionChange` message can be submitted to the consensus layer network. Once included on-chain, +The `SignedBLSToExecutionChange` message should then be submitted to the consensus layer network. Once included on-chain, the withdrawal credential change takes effect. No further action is required for a validator to enter into the automated withdrawal process. + +*Note*: A node *should* prioritize locally received `BLSToExecutionChange` operations to ensure these changes make it on-chain +through self published blocks even if the rest of the network censors. From 897b97990fff3d25718de8130915a9166224568f Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Fri, 11 Nov 2022 22:09:33 +1100 Subject: [PATCH 11/11] Further clarify light client slot checks --- specs/altair/light-client/p2p-interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/altair/light-client/p2p-interface.md b/specs/altair/light-client/p2p-interface.md index 9ee6f89a5..3997a2d09 100644 --- a/specs/altair/light-client/p2p-interface.md +++ b/specs/altair/light-client/p2p-interface.md @@ -59,7 +59,7 @@ New global topics are added to provide light clients with the latest updates. This topic is used to propagate the latest `LightClientFinalityUpdate` to light clients, allowing them to keep track of the latest `finalized_header`. The following validations MUST pass before forwarding the `finality_update` on the network. -- _[IGNORE]_ The `finalized_header.slot` is greater than the `slot` of all previously forwarded finality updates +- _[IGNORE]_ The `finalized_header.slot` is greater than that of all previously forwarded `finality_update`s - _[IGNORE]_ The `finality_update` is received after the block at `signature_slot` was given enough time to propagate through the network -- i.e. validate that one-third of `finality_update.signature_slot` has transpired (`SECONDS_PER_SLOT / INTERVALS_PER_SLOT` seconds after the start of the slot, with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) For full nodes, the following validations MUST additionally pass before forwarding the `finality_update` on the network. @@ -87,7 +87,7 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: This topic is used to propagate the latest `LightClientOptimisticUpdate` to light clients, allowing them to keep track of the latest `optimistic_header`. The following validations MUST pass before forwarding the `optimistic_update` on the network. -- _[IGNORE]_ The `attested_header.slot` is greater than the `slot` of all previously forwarded optimistic updates +- _[IGNORE]_ The `attested_header.slot` is greater than that of all previously forwarded `optimistic_update`s - _[IGNORE]_ The `optimistic_update` is received after the block at `signature_slot` was given enough time to propagate through the network -- i.e. validate that one-third of `optimistic_update.signature_slot` has transpired (`SECONDS_PER_SLOT / INTERVALS_PER_SLOT` seconds after the start of the slot, with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) For full nodes, the following validations MUST additionally pass before forwarding the `optimistic_update` on the network.