From ec4bdae2d449b3ac5769be24a4be4ad26bbe3fea Mon Sep 17 00:00:00 2001 From: djrtwo Date: Wed, 14 Jun 2023 10:51:10 -0600 Subject: [PATCH] build EIP 7045 into Deneb fork --- .circleci/config.yml | 17 -- Makefile | 2 +- configs/mainnet.yaml | 3 - configs/minimal.yaml | 5 - setup.py | 16 +- specs/_features/eip7045/beacon-chain.md | 167 ------------------ specs/_features/eip7045/fork.md | 123 ------------- specs/_features/eip7045/p2p-interface.md | 72 -------- specs/deneb/beacon-chain.md | 81 ++++++++- specs/deneb/fork.md | 2 +- specs/deneb/p2p-interface.md | 48 ++++- specs/phase0/p2p-interface.md | 2 +- tests/core/pyspec/eth2spec/test/context.py | 8 +- .../test_process_voluntary_exit.py | 1 - .../eth2spec/test/helpers/attestations.py | 4 +- .../pyspec/eth2spec/test/helpers/constants.py | 3 +- .../eth2spec/test/helpers/fork_transition.py | 6 - .../pyspec/eth2spec/test/helpers/forks.py | 8 +- .../pyspec/eth2spec/test/helpers/genesis.py | 5 +- 19 files changed, 136 insertions(+), 437 deletions(-) delete mode 100644 specs/_features/eip7045/beacon-chain.md delete mode 100644 specs/_features/eip7045/fork.md delete mode 100644 specs/_features/eip7045/p2p-interface.md diff --git a/.circleci/config.yml b/.circleci/config.yml index 966eec4c3..157c56ca5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -168,20 +168,6 @@ jobs: command: make citest fork=eip6110 - store_test_results: path: tests/core/pyspec/test-reports - test-eip7045: - docker: - - image: circleci/python:3.8 - working_directory: ~/specs-repo - steps: - - restore_cache: - key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} - - restore_pyspec_cached_venv - - run: - name: Run py-tests - command: make citest fork=eip7045 - - store_test_results: - path: tests/core/pyspec/test-reports - table_of_contents: docker: - image: circleci/node:10.16.3 @@ -305,9 +291,6 @@ workflows: - test-eip6110: requires: - install_pyspec_test - - test-eip7045: - requires: - - install_pyspec_test - table_of_contents - codespell - lint: diff --git a/Makefile b/Makefile index 0dd091e32..6c852a1e9 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/*/*.md) \ $(wildcard $(SPEC_DIR)/_features/*/*/*.md) \ $(wildcard $(SSZ_DIR)/*.md) -ALL_EXECUTABLE_SPECS = phase0 altair bellatrix capella deneb eip6110 eip7045 whisk +ALL_EXECUTABLE_SPECS = phase0 altair bellatrix capella deneb eip6110 whisk # The parameters for commands. Use `foreach` to avoid listing specs again. COVERAGE_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPECS), --cov=eth2spec.$S.$(TEST_PRESET_TYPE)) PYLINT_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPECS), ./eth2spec/$S) diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 12f32d699..365bc1136 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -53,9 +53,6 @@ DENEB_FORK_EPOCH: 18446744073709551615 # EIP6110 EIP6110_FORK_VERSION: 0x05000000 # temporary stub EIP6110_FORK_EPOCH: 18446744073709551615 -# EIP7045 -EIP7045_FORK_VERSION: 0x05000000 # temporary stub -EIP7045_FORK_EPOCH: 18446744073709551615 # Time parameters diff --git a/configs/minimal.yaml b/configs/minimal.yaml index 870bc5438..b22a7165e 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -52,11 +52,6 @@ DENEB_FORK_EPOCH: 18446744073709551615 # EIP6110 EIP6110_FORK_VERSION: 0x05000001 EIP6110_FORK_EPOCH: 18446744073709551615 -# EIP7045 -EIP7045_FORK_VERSION: 0x05000001 -EIP7045_FORK_EPOCH: 18446744073709551615 - - # Time parameters diff --git a/setup.py b/setup.py index c2b06d8aa..90ac744e6 100644 --- a/setup.py +++ b/setup.py @@ -48,7 +48,6 @@ BELLATRIX = 'bellatrix' CAPELLA = 'capella' DENEB = 'deneb' EIP6110 = 'eip6110' -EIP7045= 'eip7045' WHISK = 'whisk' PREVIOUS_FORK_OF = { @@ -58,7 +57,6 @@ PREVIOUS_FORK_OF = { CAPELLA: BELLATRIX, DENEB: CAPELLA, EIP6110: DENEB, - EIP7045: DENEB, WHISK: CAPELLA, } @@ -778,18 +776,6 @@ class EIP6110SpecBuilder(DenebSpecBuilder): from eth2spec.deneb import {preset_name} as deneb ''' -# -# EIP7045SpecBuilder -# -class EIP7045SpecBuilder(DenebSpecBuilder): - fork: str = EIP7045 - - @classmethod - def imports(cls, preset_name: str): - return super().imports(preset_name) + f''' -from eth2spec.deneb import {preset_name} as deneb -''' - # # WhiskSpecBuilder # @@ -816,7 +802,7 @@ spec_builders = { builder.fork: builder for builder in ( Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder, DenebSpecBuilder, - EIP6110SpecBuilder, EIP7045SpecBuilder, WhiskSpecBuilder, + EIP6110SpecBuilder, WhiskSpecBuilder, ) } diff --git a/specs/_features/eip7045/beacon-chain.md b/specs/_features/eip7045/beacon-chain.md deleted file mode 100644 index 9429b102e..000000000 --- a/specs/_features/eip7045/beacon-chain.md +++ /dev/null @@ -1,167 +0,0 @@ -# Deneb -- The Beacon Chain - -**Notice**: This document is a work-in-progress for researchers and implementers. - -## Table of contents - - - - - -- [Introduction](#introduction) -- [Preset](#preset) -- [Configuration](#configuration) -- [Containers](#containers) -- [Helpers](#helpers) - - [Modified `get_attestation_participation_flag_indicies`](#modified-get_attestation_participation_flag_indicies) -- [Beacon chain state transition function](#beacon-chain-state-transition-function) - - [Block processing](#block-processing) - - [Modified `process_attestation`](#modified-process_attestation) -- [Testing](#testing) - - - - -## Introduction - -This feature allows for inclusion of attestations created during epoch `N` to be included in slots from epoch `N` as well as all slots in epoch `N+1` rather than the current `SLOTS_PER_EPOCH` slot restricted range. This is an extension of the Deneb upgrade. - -## Preset - -## Configuration - -## Containers - -## Helpers - -### Modified `get_attestation_participation_flag_indicies` - -*Note:* The function `get_attestation_participation_flag_indicies` is modified to set the `TIMELY_TARGET_FLAG` for any correct target attestation, regardless of `inclusion_delay` as a baseline reward for any speed of inclusion of an attestation that contributes to justification of the contained chain. - -```python -def get_attestation_participation_flag_indices(state: BeaconState, - data: AttestationData, - inclusion_delay: uint64) -> Sequence[int]: - """ - Return the flag indices that are satisfied by an attestation. - """ - if data.target.epoch == get_current_epoch(state): - justified_checkpoint = state.current_justified_checkpoint - else: - justified_checkpoint = state.previous_justified_checkpoint - - # Matching roots - is_matching_source = data.source == justified_checkpoint - is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch) - is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot) - assert is_matching_source - - participation_flag_indices = [] - if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH): - participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX) - if is_matching_target: # [Modified in EIP7045] - participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX) - if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY: - participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX) - - return participation_flag_indices -``` - -## Beacon chain state transition function - -### Block processing - -#### Modified `process_attestation` - -*Note*: The function `process_attestation` is modified to expand valid slots for inclusion to those in both `target.epoch` epoch and `target.epoch + 1` epoch. Additionally, it utilizes an updated version of `get_attestation_participation_flag_indices` to ensure rewards are available for the extended attestation inclusion range. - -```python -def process_attestation(state: BeaconState, attestation: Attestation) -> None: - data = attestation.data - assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) - assert data.target.epoch == compute_epoch_at_slot(data.slot) - assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot # [Modified in EIP7045] - assert data.index < get_committee_count_per_slot(state, data.target.epoch) - - committee = get_beacon_committee(state, data.slot, data.index) - assert len(attestation.aggregation_bits) == len(committee) - - # Participation flag indices - participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot) - - # Verify signature - assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation)) - - # Update epoch participation flags - if data.target.epoch == get_current_epoch(state): - epoch_participation = state.current_epoch_participation - else: - epoch_participation = state.previous_epoch_participation - - proposer_reward_numerator = 0 - for index in get_attesting_indices(state, data, attestation.aggregation_bits): - for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS): - if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index): - epoch_participation[index] = add_flag(epoch_participation[index], flag_index) - proposer_reward_numerator += get_base_reward(state, index) * weight - - # Reward proposer - proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT - proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator) - increase_balance(state, get_beacon_proposer_index(state), proposer_reward) -``` - -## Testing - -*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP7045 testing only. -Modifications include: -1. Use `EIP7045_FORK_VERSION` as the previous and current fork version. - -```python -def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, - eth1_timestamp: uint64, - deposits: Sequence[Deposit], - execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader() - ) -> BeaconState: - fork = Fork( - previous_version=EIP7045_FORK_VERSION, # [Modified in EIP7045] for testing only - current_version=EIP7045_FORK_VERSION, # [Modified in EIP7045] - epoch=GENESIS_EPOCH, - ) - state = BeaconState( - genesis_time=eth1_timestamp + GENESIS_DELAY, - fork=fork, - eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))), - latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())), - randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy - ) - - # Process deposits - leaves = list(map(lambda deposit: deposit.data, deposits)) - for index, deposit in enumerate(deposits): - deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1]) - state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) - process_deposit(state, deposit) - - # Process activations - for index, validator in enumerate(state.validators): - balance = state.balances[index] - validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) - if validator.effective_balance == MAX_EFFECTIVE_BALANCE: - validator.activation_eligibility_epoch = GENESIS_EPOCH - validator.activation_epoch = GENESIS_EPOCH - - # Set genesis validators root for domain separation and chain versioning - state.genesis_validators_root = hash_tree_root(state.validators) - - # Fill in sync committees - # Note: A duplicate committee is assigned for the current and next committee at genesis - state.current_sync_committee = get_next_sync_committee(state) - state.next_sync_committee = get_next_sync_committee(state) - - # Initialize the execution payload header - state.latest_execution_payload_header = execution_payload_header - - return state -``` - diff --git a/specs/_features/eip7045/fork.md b/specs/_features/eip7045/fork.md deleted file mode 100644 index 152d09f62..000000000 --- a/specs/_features/eip7045/fork.md +++ /dev/null @@ -1,123 +0,0 @@ -# Att-Slot-Range -- Fork Logic - -**Notice**: This document is a work-in-progress for researchers and implementers. - -## Table of contents - - - - -- [Introduction](#introduction) -- [Configuration](#configuration) -- [Helper functions](#helper-functions) - - [Misc](#misc) - - [Modified `compute_fork_version`](#modified-compute_fork_version) -- [Fork to EIP7045](#fork-to-eip7045) - - [Fork trigger](#fork-trigger) - - [Upgrading the state](#upgrading-the-state) - - - -## Introduction - -This document describes the process of Att-Slot-Range upgrade. - -## Configuration - -Warning: this configuration is not definitive. - -| Name | Value | -| - | - | -| `EIP7045_FORK_VERSION` | `Version('0x05000000')` | -| `EIP7045_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 >= EIP7045_FORK_EPOCH: - return EIP7045_FORK_VERSION - if epoch >= DENEB_FORK_EPOCH: - return DENEB_FORK_VERSION - 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 EIP7045 - -### Fork trigger - -TBD. This fork is defined for testing purposes, the EIP may be combined with other consensus-layer upgrade. -For now, we assume the condition will be triggered at epoch `EIP7045_FORK_EPOCH`. - -Note that for the pure EIP7045 networks, we don't apply `upgrade_to_eip7045` since it starts with EIP7045 version logic. - -### Upgrading the state - -If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == EIP7045_FORK_EPOCH`, -an irregular state change is made to upgrade to EIP7045. - -```python -def upgrade_to_eip7045(pre: deneb.BeaconState) -> BeaconState: - post = BeaconState( - # Versioning - genesis_time=pre.genesis_time, - genesis_validators_root=pre.genesis_validators_root, - slot=pre.slot, - fork=Fork( - previous_version=pre.fork.current_version, - current_version=EIP7045_FORK_VERSION, # [Modified in Att-Slot-Range] - epoch=deneb.get_current_epoch(pre), - ), - # History - latest_block_header=pre.latest_block_header, - block_roots=pre.block_roots, - state_roots=pre.state_roots, - historical_roots=pre.historical_roots, - # Eth1 - eth1_data=pre.eth1_data, - eth1_data_votes=pre.eth1_data_votes, - eth1_deposit_index=pre.eth1_deposit_index, - # Registry - validators=pre.validators, - balances=pre.balances, - # Randomness - randao_mixes=pre.randao_mixes, - # Slashings - slashings=pre.slashings, - # Participation - previous_epoch_participation=pre.previous_epoch_participation, - current_epoch_participation=pre.current_epoch_participation, - # Finality - justification_bits=pre.justification_bits, - previous_justified_checkpoint=pre.previous_justified_checkpoint, - current_justified_checkpoint=pre.current_justified_checkpoint, - finalized_checkpoint=pre.finalized_checkpoint, - # Inactivity - inactivity_scores=pre.inactivity_scores, - # Sync - current_sync_committee=pre.current_sync_committee, - next_sync_committee=pre.next_sync_committee, - # Execution-layer - latest_execution_payload_header=pre.latest_execution_payload_header, - # Withdrawals - next_withdrawal_index=pre.next_withdrawal_index, - next_withdrawal_validator_index=pre.next_withdrawal_validator_index, - # Deep history valid from Capella onwards - historical_summaries=pre.historical_summaries, - ) - - return post -``` diff --git a/specs/_features/eip7045/p2p-interface.md b/specs/_features/eip7045/p2p-interface.md deleted file mode 100644 index 8e263bcee..000000000 --- a/specs/_features/eip7045/p2p-interface.md +++ /dev/null @@ -1,72 +0,0 @@ -# EIP7045 -- Networking - -This document contains the consensus-layer networking specification for EIP7045. - -The specification of these changes continues in the same format as the network specifications of previous upgrades, and assumes them as pre-requisite. - -## Table of contents - - - - - -- [Modifications in EIP7045](#modifications-in-eip7045) - - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) - - [Topics and messages](#topics-and-messages) - - [Global topics](#global-topics) - - [`beacon_aggregate_and_proof`](#beacon_aggregate_and_proof) - - [Attestation subnets](#attestation-subnets) - - [`beacon_attestation_{subnet_id}](#beacon_attestation_subnet_id) - - - - -## Modifications in EIP7045 - -### The gossip domain: gossipsub - -#### Topics and messages - -Topics follow the same specification as in prior upgrades. - -The `beacon_aggregate_and_proof` and `beacon_attestation_{subnet_id}` topics are modified to support the gossip of attestations created in epoch `N` to be gossiped through the entire range of slots in epoch `N+1` rather than only through one epoch of slots. - -Otherwise, the specification around the creation, validation, and dissemination of messages has not changed from the Deneb document unless explicitly noted here. - -The derivation of the `message-id` remains stable. - -##### Global topics - -Deneb introduces new global topics for blob sidecars. - -###### `beacon_aggregate_and_proof` - -The following validation is removed: -* _[IGNORE]_ `aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- - i.e. `aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate.data.slot` - (a client MAY queue future aggregates for processing at the appropriate slot). - -The following validations are added in its place: -* _[IGNORE]_ `aggregate.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- - i.e. `aggregate.data.slot <= current_slot` - (a client MAY queue future aggregates for processing at the appropriate slot). -* _[IGNORE]_ the epoch of `aggregate.data.slot` is either the current or previous epoch - (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- - i.e. `compute_epoch_at_slot(aggregate.data.slot) in (get_previous_epoch(state), get_current_epoch(state))` - -#### Attestation subnets - -##### `beacon_attestation_{subnet_id} - -The following validation is removed: -* _[IGNORE]_ `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- - i.e. `attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot` - (a client MAY queue future attestations for processing at the appropriate slot). - -The following validations are added in its place: -* _[IGNORE]_ `attestation.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- - i.e. `attestation.data.slot <= current_slot` - (a client MAY queue future attestation for processing at the appropriate slot). -* _[IGNORE]_ the epoch of `attestation.data.slot` is either the current or previous epoch - (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- - i.e. `compute_epoch_at_slot(attestation.data.slot) in (get_previous_epoch(state), get_current_epoch(state))` diff --git a/specs/deneb/beacon-chain.md b/specs/deneb/beacon-chain.md index 3189ee190..8901b35f6 100644 --- a/specs/deneb/beacon-chain.md +++ b/specs/deneb/beacon-chain.md @@ -24,6 +24,7 @@ - [Helper functions](#helper-functions) - [Misc](#misc) - [`kzg_commitment_to_versioned_hash`](#kzg_commitment_to_versioned_hash) + - [Modified `get_attestation_participation_flag_indicies`](#modified-get_attestation_participation_flag_indicies) - [Beacon chain state transition function](#beacon-chain-state-transition-function) - [Execution engine](#execution-engine) - [Request data](#request-data) @@ -32,6 +33,7 @@ - [`is_valid_versioned_hashes`](#is_valid_versioned_hashes) - [Modified `verify_and_notify_new_payload`](#modified-verify_and_notify_new_payload) - [Block processing](#block-processing) + - [Modified `process_attestation`](#modified-process_attestation) - [Execution payload](#execution-payload) - [Modified `process_execution_payload`](#modified-process_execution_payload) - [Modified `process_voluntary_exit`](#modified-process_voluntary_exit) @@ -45,6 +47,7 @@ Deneb is a consensus-layer upgrade containing a number of features. Including: * [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844): Shard Blob Transactions scale data-availability of Ethereum in a simple, forwards-compatible manner * [EIP-7044](https://github.com/ethereum/EIPs/pull/7044): Perpetually Valid Signed Voluntary Exits +* [EIP-7045](https://eips.ethereum.org/EIPS/eip-7045): Increase Max Attestation Inclusion Slot ## Custom types @@ -170,6 +173,40 @@ def kzg_commitment_to_versioned_hash(kzg_commitment: KZGCommitment) -> Versioned return VERSIONED_HASH_VERSION_KZG + hash(kzg_commitment)[1:] ``` +### Modified `get_attestation_participation_flag_indicies` + +*Note:* The function `get_attestation_participation_flag_indicies` is modified to set the `TIMELY_TARGET_FLAG` for any correct target attestation, regardless of `inclusion_delay` as a baseline reward for any speed of inclusion of an attestation that contributes to justification of the contained chain for EIP-7045. + +```python +def get_attestation_participation_flag_indices(state: BeaconState, + data: AttestationData, + inclusion_delay: uint64) -> Sequence[int]: + """ + Return the flag indices that are satisfied by an attestation. + """ + if data.target.epoch == get_current_epoch(state): + justified_checkpoint = state.current_justified_checkpoint + else: + justified_checkpoint = state.previous_justified_checkpoint + + # Matching roots + is_matching_source = data.source == justified_checkpoint + is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch) + is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot) + assert is_matching_source + + participation_flag_indices = [] + if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH): + participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX) + if is_matching_target: # [Modified in Deneb:EIP7045] + participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX) + if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY: + participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX) + + return participation_flag_indices +``` + + ## Beacon chain state transition function ### Execution engine @@ -221,10 +258,52 @@ def verify_and_notify_new_payload(self: ExecutionEngine, ### Block processing +#### Modified `process_attestation` + +*Note*: The function `process_attestation` is modified to expand valid slots for inclusion to those in both `target.epoch` epoch and `target.epoch + 1` epoch for EIP-7045. Additionally, it utilizes an updated version of `get_attestation_participation_flag_indices` to ensure rewards are available for the extended attestation inclusion range for EIP-7045. + +```python +def process_attestation(state: BeaconState, attestation: Attestation) -> None: + data = attestation.data + assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) + assert data.target.epoch == compute_epoch_at_slot(data.slot) + assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot # [Modified in Deneb:EIP7045] + assert data.index < get_committee_count_per_slot(state, data.target.epoch) + + committee = get_beacon_committee(state, data.slot, data.index) + assert len(attestation.aggregation_bits) == len(committee) + + # Participation flag indices + participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot) + + # Verify signature + assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation)) + + # Update epoch participation flags + if data.target.epoch == get_current_epoch(state): + epoch_participation = state.current_epoch_participation + else: + epoch_participation = state.previous_epoch_participation + + proposer_reward_numerator = 0 + for index in get_attesting_indices(state, data, attestation.aggregation_bits): + for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS): + if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index): + epoch_participation[index] = add_flag(epoch_participation[index], flag_index) + proposer_reward_numerator += get_base_reward(state, index) * weight + + # Reward proposer + proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT + proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator) + increase_balance(state, get_beacon_proposer_index(state), proposer_reward) +``` + #### Execution payload ##### Modified `process_execution_payload` +*Note*: The function `process_execution_payload` is modified to pass `versioned_hashes` into `execution_engine.verify_and_notify_new_payload` and to assign the new fields in `ExecutionPayloadHeader` for EIP-4844. + ```python def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None: payload = body.execution_payload @@ -270,7 +349,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi #### Modified `process_voluntary_exit` -*Note*: The function `process_voluntary_exit` is modified to use the a fixed fork version -- `CAPELLA_FORK_VERSION` -- for EIP-7044 +*Note*: The function `process_voluntary_exit` is modified to use the a fixed fork version -- `CAPELLA_FORK_VERSION` -- for EIP-7044. ```python def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None: diff --git a/specs/deneb/fork.md b/specs/deneb/fork.md index ffced6a59..08af2fd35 100644 --- a/specs/deneb/fork.md +++ b/specs/deneb/fork.md @@ -57,7 +57,7 @@ def compute_fork_version(epoch: Epoch) -> Version: ### Fork trigger -TBD. This fork is defined for testing purposes, the EIP may be combined with other consensus-layer upgrade. +TBD. This fork is defined for testing purposes. For now, we assume the condition will be triggered at epoch `DENEB_FORK_EPOCH`. Note that for the pure Deneb networks, we don't apply `upgrade_to_deneb` since it starts with Deneb version logic. diff --git a/specs/deneb/p2p-interface.md b/specs/deneb/p2p-interface.md index 809e405a6..f073b50f5 100644 --- a/specs/deneb/p2p-interface.md +++ b/specs/deneb/p2p-interface.md @@ -23,6 +23,9 @@ The specification of these changes continues in the same format as the network s - [Global topics](#global-topics) - [`beacon_block`](#beacon_block) - [`blob_sidecar_{subnet_id}`](#blob_sidecar_subnet_id) + - [`beacon_aggregate_and_proof`](#beacon_aggregate_and_proof) + - [Attestation subnets](#attestation-subnets) + - [`beacon_attestation_{subnet_id}](#beacon_attestation_subnet_id) - [Transitioning the gossip](#transitioning-the-gossip) - [The Req/Resp domain](#the-reqresp-domain) - [Messages](#messages) @@ -106,7 +109,11 @@ Some gossip meshes are upgraded in the fork of Deneb to support upgraded types. Topics follow the same specification as in prior upgrades. -The `beacon_block` topic is modified to also support deneb blocks and new topics are added per table below. All other topics remain stable. +The `beacon_block` topic is modified to also support Deneb blocks and new topics are added per table below. + +The `voluntary_exit` topic is implicitly modified due to the lock-in use of `CAPELLA_FORK_VERSION` for this message signature validation for EIP-7044. + +The `beacon_aggregate_and_proof` and `beacon_attestation_{subnet_id}` topics are modified to support the gossip of attestations created in epoch `N` to be gossiped through the entire range of slots in epoch `N+1` rather than only through one epoch of slots for EIP-7045. The specification around the creation, validation, and dissemination of messages has not changed from the Capella document unless explicitly noted here. @@ -124,7 +131,9 @@ Deneb introduces new global topics for blob sidecars. ###### `beacon_block` -The *type* of the payload of this topic changes to the (modified) `SignedBeaconBlock` found in deneb. +The *type* of the payload of this topic changes to the (modified) `SignedBeaconBlock` found in Deneb. + +*[Modified in Deneb:EIP4844]* New validation: @@ -150,6 +159,41 @@ The following validations MUST pass before forwarding the `signed_blob_sidecar` - _[REJECT]_ The sidecar is proposed by the expected `proposer_index` for the block's slot in the context of the current shuffling (defined by `block_parent_root`/`slot`). If the `proposer_index` cannot immediately be verified against the expected shuffling, the sidecar MAY be queued for later processing while proposers for the block's branch are calculated -- in such a case _do not_ `REJECT`, instead `IGNORE` this message. +###### `beacon_aggregate_and_proof` + +*[Modified in Deneb:EIP7045]* + +The following validation is removed: +* _[IGNORE]_ `aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- + i.e. `aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate.data.slot` + (a client MAY queue future aggregates for processing at the appropriate slot). + +The following validations are added in its place: +* _[IGNORE]_ `aggregate.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- + i.e. `aggregate.data.slot <= current_slot` + (a client MAY queue future aggregates for processing at the appropriate slot). +* _[IGNORE]_ the epoch of `aggregate.data.slot` is either the current or previous epoch + (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- + i.e. `compute_epoch_at_slot(aggregate.data.slot) in (get_previous_epoch(state), get_current_epoch(state))` + +##### Attestation subnets + +###### `beacon_attestation_{subnet_id} + +*[Modified in Deneb:EIP7045]* + +The following validation is removed: +* _[IGNORE]_ `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- + i.e. `attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot` + (a client MAY queue future attestations for processing at the appropriate slot). + +The following validations are added in its place: +* _[IGNORE]_ `attestation.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- + i.e. `attestation.data.slot <= current_slot` + (a client MAY queue future attestation for processing at the appropriate slot). +* _[IGNORE]_ the epoch of `attestation.data.slot` is either the current or previous epoch + (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- + i.e. `compute_epoch_at_slot(attestation.data.slot) in (get_previous_epoch(state), get_current_epoch(state))` #### Transitioning the gossip diff --git a/specs/phase0/p2p-interface.md b/specs/phase0/p2p-interface.md index c0d18b08f..14427c79c 100644 --- a/specs/phase0/p2p-interface.md +++ b/specs/phase0/p2p-interface.md @@ -1002,7 +1002,7 @@ Clients MAY connect to peers with the same `fork_digest` but a different `next_f Unless `ENRForkID` is manually updated to matching prior to the earlier `next_fork_epoch` of the two clients, these connecting clients will be unable to successfully interact starting at the earlier `next_fork_epoch`. -### Attestation subnet subcription +### Attestation subnet subscription Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`beacon_attestation_{subnet_id}`). To provide this stability, each beacon node should: diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 88b252649..48f6857f6 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -9,13 +9,12 @@ from eth2spec.bellatrix import mainnet as spec_bellatrix_mainnet, minimal as spe from eth2spec.capella import mainnet as spec_capella_mainnet, minimal as spec_capella_minimal from eth2spec.deneb import mainnet as spec_deneb_mainnet, minimal as spec_deneb_minimal from eth2spec.eip6110 import mainnet as spec_eip6110_mainnet, minimal as spec_eip6110_minimal -from eth2spec.eip7045 import mainnet as spec_eip7045_mainnet, minimal as spec_eip7045_minimal from eth2spec.utils import bls from .exceptions import SkippedTest from .helpers.constants import ( PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, - EIP6110, EIP7045, + EIP6110, MINIMAL, MAINNET, ALL_PHASES, ALL_FORK_UPGRADES, @@ -84,7 +83,6 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = { CAPELLA: spec_capella_minimal, DENEB: spec_deneb_minimal, EIP6110: spec_eip6110_minimal, - EIP7045: spec_eip7045_minimal, }, MAINNET: { PHASE0: spec_phase0_mainnet, @@ -93,7 +91,6 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = { CAPELLA: spec_capella_mainnet, DENEB: spec_deneb_mainnet, EIP6110: spec_eip6110_mainnet, - EIP7045: spec_eip7045_mainnet, }, } @@ -544,9 +541,6 @@ with_bellatrix_and_later = with_all_phases_from(BELLATRIX) with_capella_and_later = with_all_phases_from(CAPELLA) with_deneb_and_later = with_all_phases_from(DENEB) with_eip6110_and_later = with_all_phases_from(EIP6110) -with_eip7045_and_later = with_all_phases_from(EIP7045) - -with_all_phases_except_eip7045 = with_all_phases_except(EIP7045) class quoted_str(str): 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 index 711d27eb9..b01eaab0e 100644 --- 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 @@ -1,7 +1,6 @@ from eth2spec.test.context import ( always_bls, spec_state_test, - with_phases, with_deneb_and_later, ) from eth2spec.test.helpers.constants import ( diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index b1f60feb4..4899e6224 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -5,7 +5,7 @@ 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, is_post_eip7045 +from eth2spec.test.helpers.forks import is_post_altair, is_post_deneb from eth2spec.test.helpers.keys import privkeys from eth2spec.utils import bls from eth2spec.utils.ssz.ssz_typing import Bitlist @@ -159,7 +159,7 @@ def get_attestation_signature(spec, state, attestation_data, privkey): def compute_max_inclusion_slot(spec, attestation): - if is_post_eip7045(spec): + if is_post_deneb(spec): next_epoch = spec.compute_epoch_at_slot(attestation.data.slot) + 1 end_of_next_epoch = spec.compute_start_slot_at_epoch(next_epoch + 1) - 1 return end_of_next_epoch diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py index 0f1aeb561..049c354ca 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/constants.py +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -17,7 +17,6 @@ SHARDING = SpecForkName('sharding') CUSTODY_GAME = SpecForkName('custody_game') DAS = SpecForkName('das') EIP6110 = SpecForkName('eip6110') -EIP7045 = SpecForkName('eip7045') # # SpecFork settings @@ -32,7 +31,7 @@ ALL_PHASES = ( *MAINNET_FORKS, DENEB, # Experimental patches - EIP6110, EIP7045, + EIP6110, ) # The forks that have light client specs LIGHT_CLIENT_TESTING_FORKS = (*[item for item in MAINNET_FORKS if item != PHASE0], DENEB) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py b/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py index cf7aeb93a..68444c472 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py @@ -16,7 +16,6 @@ from eth2spec.test.helpers.constants import ( CAPELLA, DENEB, EIP6110, - EIP7045, ) from eth2spec.test.helpers.deposits import ( prepare_state_and_deposit, @@ -162,8 +161,6 @@ def do_fork(state, spec, post_spec, fork_epoch, with_block=True, sync_aggregate= state = post_spec.upgrade_to_deneb(state) elif post_spec.fork == EIP6110: state = post_spec.upgrade_to_eip6110(state) - elif post_spec.fork == EIP7045: - state = post_spec.upgrade_to_eip7045(state) assert state.fork.epoch == fork_epoch @@ -182,9 +179,6 @@ def do_fork(state, spec, post_spec, fork_epoch, with_block=True, sync_aggregate= elif post_spec.fork == EIP6110: assert state.fork.previous_version == post_spec.config.DENEB_FORK_VERSION assert state.fork.current_version == post_spec.config.EIP6110_FORK_VERSION - elif post_spec.fork == EIP7045: - assert state.fork.previous_version == post_spec.config.DENEB_FORK_VERSION - assert state.fork.current_version == post_spec.config.EIP7045_FORK_VERSION if with_block: return state, _state_transition_and_sign_block_at_slot( diff --git a/tests/core/pyspec/eth2spec/test/helpers/forks.py b/tests/core/pyspec/eth2spec/test/helpers/forks.py index ddd3b795b..5e97522db 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/forks.py +++ b/tests/core/pyspec/eth2spec/test/helpers/forks.py @@ -1,12 +1,10 @@ from .constants import ( PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, - EIP6110, EIP7045, + EIP6110, ) def is_post_fork(a, b): - if a == EIP7045: - return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP7045] if a == EIP6110: return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110] if a == DENEB: @@ -40,7 +38,3 @@ def is_post_deneb(spec): def is_post_eip6110(spec): return is_post_fork(spec.fork, EIP6110) - - -def is_post_eip7045(spec): - return is_post_fork(spec.fork, EIP7045) diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index eab4abec8..fea259013 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -1,5 +1,5 @@ from eth2spec.test.helpers.constants import ( - ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110, EIP7045, + ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110, ) from eth2spec.test.helpers.execution_payload import ( compute_el_header_block_hash, @@ -86,9 +86,6 @@ def create_genesis_state(spec, validator_balances, activation_threshold): elif spec.fork == EIP6110: previous_version = spec.config.DENEB_FORK_VERSION current_version = spec.config.EIP6110_FORK_VERSION - elif spec.fork == EIP7045: - previous_version = spec.config.DENEB_FORK_VERSION - current_version = spec.config.EIP7045_FORK_VERSION state = spec.BeaconState( genesis_time=0,