Merge pull request #3615 from ethereum/init-electra

Init Electra (EIP6110 + EIP7002)
This commit is contained in:
Hsiao-Wei Wang 2024-04-09 12:43:05 +09:00 committed by GitHub
commit aba6345776
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 211 additions and 510 deletions

View File

@ -155,7 +155,7 @@ jobs:
command: make citest fork=deneb
- store_test_results:
path: tests/core/pyspec/test-reports
test-eip6110:
test-electra:
docker:
- image: circleci/python:3.9
working_directory: ~/specs-repo
@ -165,20 +165,7 @@ jobs:
- restore_pyspec_cached_venv
- run:
name: Run py-tests
command: make citest fork=eip6110
- store_test_results:
path: tests/core/pyspec/test-reports
test-eip7002:
docker:
- image: circleci/python:3.9
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=eip7002
command: make citest fork=electra
- store_test_results:
path: tests/core/pyspec/test-reports
test-eip7549:
@ -340,10 +327,7 @@ workflows:
- test-deneb:
requires:
- install_pyspec_test
- test-eip6110:
requires:
- install_pyspec_test
- test-eip7002:
- test-electra:
requires:
- install_pyspec_test
- test-eip7549:

View File

@ -71,7 +71,7 @@ jobs:
needs: [preclear,lint,codespell,table_of_contents]
strategy:
matrix:
version: ["phase0", "altair", "bellatrix", "capella", "deneb", "eip6110", "eip7002", "eip7549", "whisk", "eip7594"]
version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "eip7549", "whisk", "eip7594"]
steps:
- name: Checkout this repo
uses: actions/checkout@v3.2.0

3
.gitignore vendored
View File

@ -21,8 +21,7 @@ tests/core/pyspec/eth2spec/altair/
tests/core/pyspec/eth2spec/bellatrix/
tests/core/pyspec/eth2spec/capella/
tests/core/pyspec/eth2spec/deneb/
tests/core/pyspec/eth2spec/eip6110/
tests/core/pyspec/eth2spec/eip7002/
tests/core/pyspec/eth2spec/electra/
tests/core/pyspec/eth2spec/eip7549/
tests/core/pyspec/eth2spec/whisk/
tests/core/pyspec/eth2spec/eip7251/

View File

@ -35,7 +35,7 @@ MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/*/*.md) \
$(wildcard $(SPEC_DIR)/_features/*/*/*.md) \
$(wildcard $(SSZ_DIR)/*.md)
ALL_EXECUTABLE_SPEC_NAMES = phase0 altair bellatrix capella deneb eip6110 eip7002 eip7549 whisk
ALL_EXECUTABLE_SPEC_NAMES = phase0 altair bellatrix capella deneb electra eip7549 whisk
# The parameters for commands. Use `foreach` to avoid listing specs again.
COVERAGE_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPEC_NAMES), --cov=eth2spec.$S.$(TEST_PRESET_TYPE))
PYLINT_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPEC_NAMES), ./eth2spec/$S)

View File

@ -26,10 +26,10 @@ Features are researched and developed in parallel, and then consolidated into se
### In-development Specifications
| Code Name or Topic | Specs | Notes |
| - | - | - |
| Electra | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/electra/beacon-chain.md)</li><li>[EIP-6110 fork](specs/electra/fork.md)</li></ul><li>Additions</li><ul><li>[Honest validator guide changes](specs/electra/validator.md)</li></ul></ul> |
| Sharding (outdated) | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/_features/sharding/beacon-chain.md)</li></ul><li>Additions</li><ul><li>[P2P networking](specs/_features/sharding/p2p-interface.md)</li></ul></ul> |
| Custody Game (outdated) | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/_features/custody_game/beacon-chain.md)</li></ul><li>Additions</li><ul><li>[Honest validator guide changes](specs/_features/custody_game/validator.md)</li></ul></ul> | Dependent on sharding |
| Data Availability Sampling (outdated) | <ul><li>Core</li><ul><li>[Core types and functions](specs/_features/das/das-core.md)</li><li>[Fork choice changes](specs/_features/das/fork-choice.md)</li></ul><li>Additions</li><ul><li>[P2P Networking](specs/_features/das/p2p-interface.md)</li><li>[Sampling process](specs/_features/das/sampling.md)</li></ul></ul> | <ul><li> Dependent on sharding</li><li>[Technical explainer](https://hackmd.io/@HWeNw8hNRimMm2m2GH56Cw/B1YJPGkpD)</li></ul> |
| EIP-6110 | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/_features/eip6110//beacon-chain.md)</li><li>[EIP-6110 fork](specs/_features/eip6110/fork.md)</li></ul><li>Additions</li><ul><li>[Honest validator guide changes](specs/_features/eip6110/validator.md)</li></ul></ul> |
### Accompanying documents can be found in [specs](specs) and include:

View File

@ -53,12 +53,6 @@ DENEB_FORK_EPOCH: 269568 # March 13, 2024, 01:55:35pm UTC
# Electra
ELECTRA_FORK_VERSION: 0x05000000
ELECTRA_FORK_EPOCH: 18446744073709551615
# EIP6110
EIP6110_FORK_VERSION: 0x06000000 # temporary stub
EIP6110_FORK_EPOCH: 18446744073709551615
# EIP7002
EIP7002_FORK_VERSION: 0x07000000 # temporary stub
EIP7002_FORK_EPOCH: 18446744073709551615
# EIP7251
EIP7251_FORK_VERSION: 0x06000000 # temporary stub
EIP7251_FORK_EPOCH: 18446744073709551615

View File

@ -52,12 +52,6 @@ DENEB_FORK_EPOCH: 18446744073709551615
# Electra
ELECTRA_FORK_VERSION: 0x05000001
ELECTRA_FORK_EPOCH: 18446744073709551615
# EIP6110
EIP6110_FORK_VERSION: 0x06000001
EIP6110_FORK_EPOCH: 18446744073709551615
# EIP7002
EIP7002_FORK_VERSION: 0x07000001
EIP7002_FORK_EPOCH: 18446744073709551615
# EIP7251
EIP7251_FORK_VERSION: 0x06000001 # temporary stub
EIP7251_FORK_EPOCH: 18446744073709551615

View File

@ -1,6 +1,8 @@
# Mainnet preset - EIP6110
# Mainnet preset - Electra
# Execution
# ---------------------------------------------------------------
# 2**13 (= 8192) receipts
MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: 8192
# 2**4 (= 16) exits
MAX_EXECUTION_LAYER_EXITS: 16

View File

@ -1,6 +1,8 @@
# Minimal preset - EIP6110
# Minimal preset - Electra
# Execution
# ---------------------------------------------------------------
# [customized]
MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: 4
# 2**4 (= 16) exits
MAX_EXECUTION_LAYER_EXITS: 16

View File

@ -4,8 +4,7 @@ ALTAIR = 'altair'
BELLATRIX = 'bellatrix'
CAPELLA = 'capella'
DENEB = 'deneb'
EIP6110 = 'eip6110'
EIP7002 = 'eip7002'
ELECTRA = 'electra'
EIP7251 = 'eip7251'
EIP7549 = 'eip7549'
WHISK = 'whisk'

View File

@ -6,8 +6,7 @@ from .constants import (
BELLATRIX,
CAPELLA,
DENEB,
EIP6110,
EIP7002,
ELECTRA,
EIP7251,
EIP7549,
WHISK,
@ -21,10 +20,9 @@ PREVIOUS_FORK_OF = {
BELLATRIX: ALTAIR,
CAPELLA: BELLATRIX,
DENEB: CAPELLA,
EIP6110: DENEB,
ELECTRA: DENEB,
EIP7549: DENEB,
WHISK: CAPELLA,
EIP7002: CAPELLA,
EIP7251: DENEB,
EIP7594: DENEB,
}

View File

@ -3,8 +3,7 @@ from .altair import AltairSpecBuilder
from .bellatrix import BellatrixSpecBuilder
from .capella import CapellaSpecBuilder
from .deneb import DenebSpecBuilder
from .eip6110 import EIP6110SpecBuilder
from .eip7002 import EIP7002SpecBuilder
from .electra import ElectraSpecBuilder
from .eip7549 import EIP7549SpecBuilder
from .whisk import WhiskSpecBuilder
from .eip7251 import EIP7251SpecBuilder
@ -15,7 +14,7 @@ spec_builders = {
builder.fork: builder
for builder in (
Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder, DenebSpecBuilder,
EIP6110SpecBuilder, EIP7002SpecBuilder, EIP7549SpecBuilder, WhiskSpecBuilder, EIP7251SpecBuilder,
ElectraSpecBuilder, EIP7549SpecBuilder, WhiskSpecBuilder, EIP7251SpecBuilder,
EIP7594SpecBuilder,
)
}

View File

@ -1,12 +0,0 @@
from .base import BaseSpecBuilder
from ..constants import EIP7002
class EIP7002SpecBuilder(BaseSpecBuilder):
fork: str = EIP7002
@classmethod
def imports(cls, preset_name: str):
return super().imports(preset_name) + f'''
from eth2spec.capella import {preset_name} as capella
'''

View File

@ -1,9 +1,9 @@
from .base import BaseSpecBuilder
from ..constants import EIP6110
from ..constants import ELECTRA
class EIP6110SpecBuilder(BaseSpecBuilder):
fork: str = EIP6110
class ElectraSpecBuilder(BaseSpecBuilder):
fork: str = ELECTRA
@classmethod
def imports(cls, preset_name: str):

View File

@ -10,7 +10,7 @@
# Set variables
ALL_EXECUTABLE_SPECS=("phase0" "altair" "bellatrix" "capella" "deneb" "eip6110" "whisk")
ALL_EXECUTABLE_SPECS=("phase0" "altair" "bellatrix" "capella" "deneb" "electra" "whisk")
TEST_PRESET_TYPE=minimal
FORK_TO_TEST=phase0
NUMBER_OF_CORES=4

View File

@ -1,304 +0,0 @@
# EIP-7002 -- The Beacon Chain
## Table of contents
<!-- TOC -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Introduction](#introduction)
- [Preset](#preset)
- [Max operations per block](#max-operations-per-block)
- [Containers](#containers)
- [New containers](#new-containers)
- [`ExecutionLayerExit`](#executionlayerexit)
- [Extended Containers](#extended-containers)
- [`ExecutionPayload`](#executionpayload)
- [`ExecutionPayloadHeader`](#executionpayloadheader)
- [`BeaconState`](#beaconstate)
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
- [Block processing](#block-processing)
- [Execution payload](#execution-payload)
- [Modified `process_execution_payload`](#modified-process_execution_payload)
- [Operations](#operations)
- [Modified `process_operations`](#modified-process_operations)
- [New `process_execution_layer_exit`](#new-process_execution_layer_exit)
- [Testing](#testing)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
## Introduction
This is the beacon chain specification of the execution layer triggerable exits feature.
This mechanism relies on the changes proposed by [EIP-7002](http://eips.ethereum.org/EIPS/eip-7002).
*Note:* This specification is built upon [Capella](../../capella/beacon-chain.md) and is under active development.
## Preset
### Max operations per block
| Name | Value |
| - | - |
| `MAX_EXECUTION_LAYER_EXITS` | `2**4` (= 16) |
## Containers
### New containers
#### `ExecutionLayerExit`
```python
class ExecutionLayerExit(Container):
source_address: ExecutionAddress
validator_pubkey: BLSPubkey
```
### Extended Containers
#### `ExecutionPayload`
```python
class ExecutionPayload(Container):
# Execution block header fields
parent_hash: Hash32
fee_recipient: ExecutionAddress
state_root: Bytes32
receipts_root: Bytes32
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
prev_randao: Bytes32
block_number: uint64
gas_limit: uint64
gas_used: uint64
timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256
# Extra payload fields
block_hash: Hash32
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
exits: List[ExecutionLayerExit, MAX_EXECUTION_LAYER_EXITS] # [New in EIP7002]
```
#### `ExecutionPayloadHeader`
```python
class ExecutionPayloadHeader(Container):
# Execution block header fields
parent_hash: Hash32
fee_recipient: ExecutionAddress
state_root: Bytes32
receipts_root: Bytes32
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
prev_randao: Bytes32
block_number: uint64
gas_limit: uint64
gas_used: uint64
timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256
# Extra payload fields
block_hash: Hash32
transactions_root: Root
withdrawals_root: Root
exits_root: Root # [New in EIP7002]
```
#### `BeaconState`
```python
class BeaconState(Container):
# Versioning
genesis_time: uint64
genesis_validators_root: Root
slot: Slot
fork: Fork
# History
latest_block_header: BeaconBlockHeader
block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
# Eth1
eth1_data: Eth1Data
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
eth1_deposit_index: uint64
# Registry
validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
# Slashings
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances
# Participation
previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
# Finality
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch
previous_justified_checkpoint: Checkpoint
current_justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
# Inactivity
inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT]
# Sync
current_sync_committee: SyncCommittee
next_sync_committee: SyncCommittee
# Execution
latest_execution_payload_header: ExecutionPayloadHeader # [Modified in EIP7002]
# Withdrawals
next_withdrawal_index: WithdrawalIndex
next_withdrawal_validator_index: ValidatorIndex
# Deep history valid from Capella onwards
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
```
## Beacon chain state transition function
### Block processing
#### Execution payload
##### Modified `process_execution_payload`
```python
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
payload = body.execution_payload
# Verify consistency of the parent hash with respect to the previous execution payload header
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
# Verify prev_randao
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
# Verify timestamp
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
# Verify the execution payload is valid
assert execution_engine.verify_and_notify_new_payload(NewPayloadRequest(execution_payload=payload))
# Cache execution payload header
state.latest_execution_payload_header = ExecutionPayloadHeader(
parent_hash=payload.parent_hash,
fee_recipient=payload.fee_recipient,
state_root=payload.state_root,
receipts_root=payload.receipts_root,
logs_bloom=payload.logs_bloom,
prev_randao=payload.prev_randao,
block_number=payload.block_number,
gas_limit=payload.gas_limit,
gas_used=payload.gas_used,
timestamp=payload.timestamp,
extra_data=payload.extra_data,
base_fee_per_gas=payload.base_fee_per_gas,
block_hash=payload.block_hash,
transactions_root=hash_tree_root(payload.transactions),
withdrawals_root=hash_tree_root(payload.withdrawals),
exits_root=hash_tree_root(payload.exits), # [New in EIP7002]
)
```
#### Operations
##### Modified `process_operations`
*Note*: The function `process_operations` is modified to process `ExecutionLayerExit` operations included in the block.
```python
def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
# Verify that outstanding deposits are processed up to the maximum number of deposits
assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None:
for operation in operations:
fn(state, operation)
for_ops(body.proposer_slashings, process_proposer_slashing)
for_ops(body.attester_slashings, process_attester_slashing)
for_ops(body.attestations, process_attestation)
for_ops(body.deposits, process_deposit)
for_ops(body.voluntary_exits, process_voluntary_exit)
for_ops(body.execution_payload.exits, process_execution_layer_exit) # [New in EIP7002]
for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
```
##### New `process_execution_layer_exit`
```python
def process_execution_layer_exit(state: BeaconState, execution_layer_exit: ExecutionLayerExit) -> None:
validator_pubkeys = [v.pubkey for v in state.validators]
# Verify pubkey exists
pubkey_to_exit = execution_layer_exit.validator_pubkey
if pubkey_to_exit not in validator_pubkeys:
return
validator_index = ValidatorIndex(validator_pubkeys.index(pubkey_to_exit))
validator = state.validators[validator_index]
# Verify withdrawal credentials
is_execution_address = validator.withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX
is_correct_source_address = validator.withdrawal_credentials[12:] == execution_layer_exit.source_address
if not (is_execution_address and is_correct_source_address):
return
# Verify the validator is active
if not is_active_validator(validator, get_current_epoch(state)):
return
# Verify exit has not been initiated
if validator.exit_epoch != FAR_FUTURE_EPOCH:
return
# Verify the validator has been active long enough
if get_current_epoch(state) < validator.activation_epoch + SHARD_COMMITTEE_PERIOD:
return
# Initiate exit
initiate_validator_exit(state, validator_index)
```
## Testing
*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP-7002 testing only.
Modifications include:
1. Use `EIP7002_FORK_VERSION` as the previous and current fork version.
2. Utilize the EIP-7002 `BeaconBlockBody` when constructing the initial `latest_block_header`.
```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=EIP7002_FORK_VERSION, # [Modified in EIP7002] for testing only
current_version=EIP7002_FORK_VERSION, # [Modified in EIP7002]
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
```

View File

@ -1,4 +1,6 @@
# EIP-6110 -- The Beacon Chain
# Electra -- The Beacon Chain
**Notice**: This document is a work-in-progress for researchers and implementers.
## Table of contents
@ -14,6 +16,7 @@
- [Containers](#containers)
- [New containers](#new-containers)
- [`DepositReceipt`](#depositreceipt)
- [`ExecutionLayerExit`](#executionlayerexit)
- [Extended Containers](#extended-containers)
- [`ExecutionPayload`](#executionpayload)
- [`ExecutionPayloadHeader`](#executionpayloadheader)
@ -22,6 +25,7 @@
- [Block processing](#block-processing)
- [Modified `process_operations`](#modified-process_operations)
- [New `process_deposit_receipt`](#new-process_deposit_receipt)
- [New `process_execution_layer_exit`](#new-process_execution_layer_exit)
- [Modified `process_execution_payload`](#modified-process_execution_payload)
- [Testing](#testing)
@ -30,10 +34,9 @@
## Introduction
This is the beacon chain specification of in-protocol deposits processing mechanism.
This mechanism relies on the changes proposed by [EIP-6110](http://eips.ethereum.org/EIPS/eip-6110).
*Note:* This specification is built upon [Deneb](../../deneb/beacon-chain.md) and is under active development.
Electra is a consensus-layer upgrade containing a number of features. Including:
* [EIP-6110](https://eips.ethereum.org/EIPS/eip-6110): Supply validator deposits on chain
* [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002): Execution layer triggerable exits
## Constants
@ -41,9 +44,9 @@ The following values are (non-configurable) constants used throughout the specif
### Misc
| Name | Value |
| - | - |
| `UNSET_DEPOSIT_RECEIPTS_START_INDEX` | `uint64(2**64 - 1)` |
| Name | Value | Description |
| - | - | - |
| `UNSET_DEPOSIT_RECEIPTS_START_INDEX` | `uint64(2**64 - 1)` | *[New in Electra:EIP6110]* |
## Preset
@ -51,7 +54,8 @@ The following values are (non-configurable) constants used throughout the specif
| Name | Value | Description |
| - | - | - |
| `MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD` | `uint64(2**13)` (= 8,192) | Maximum number of deposit receipts allowed in each payload |
| `MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD` | `uint64(2**13)` (= 8,192) | *[New in Electra:EIP6110]* Maximum number of deposit receipts allowed in each payload |
| `MAX_EXECUTION_LAYER_EXITS` | `2**4` (= 16) | *[New in Electra:EIP7002]* |
## Containers
@ -59,6 +63,8 @@ The following values are (non-configurable) constants used throughout the specif
#### `DepositReceipt`
*Note*: The container is new in EIP6110.
```python
class DepositReceipt(Container):
pubkey: BLSPubkey
@ -68,6 +74,16 @@ class DepositReceipt(Container):
index: uint64
```
#### `ExecutionLayerExit`
*Note*: The container is new in EIP7002.
```python
class ExecutionLayerExit(Container):
source_address: ExecutionAddress
validator_pubkey: BLSPubkey
```
### Extended Containers
#### `ExecutionPayload`
@ -93,7 +109,8 @@ class ExecutionPayload(Container):
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
blob_gas_used: uint64
excess_blob_gas: uint64
deposit_receipts: List[DepositReceipt, MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD] # [New in EIP6110]
deposit_receipts: List[DepositReceipt, MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD] # [New in Electra:EIP6110]
exits: List[ExecutionLayerExit, MAX_EXECUTION_LAYER_EXITS] # [New in Electra:EIP7002]
```
#### `ExecutionPayloadHeader`
@ -119,7 +136,8 @@ class ExecutionPayloadHeader(Container):
withdrawals_root: Root
blob_gas_used: uint64
excess_blob_gas: uint64
deposit_receipts_root: Root # [New in EIP6110]
deposit_receipts_root: Root # [New in Electra:EIP6110]
exits_root: Root # [New in Electra:EIP7002]
```
#### `BeaconState`
@ -161,13 +179,13 @@ class BeaconState(Container):
current_sync_committee: SyncCommittee
next_sync_committee: SyncCommittee
# Execution
latest_execution_payload_header: ExecutionPayloadHeader # [Modified in EIP6110]
latest_execution_payload_header: ExecutionPayloadHeader # [Modified in Electra:EIP6110:EIP7002]
# Withdrawals
next_withdrawal_index: WithdrawalIndex
next_withdrawal_validator_index: ValidatorIndex
# Deep history valid from Capella onwards
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
# [New in EIP6110]
# [New in Electra:EIP6110]
deposit_receipts_start_index: uint64
```
@ -179,20 +197,20 @@ class BeaconState(Container):
def process_block(state: BeaconState, block: BeaconBlock) -> None:
process_block_header(state, block)
process_withdrawals(state, block.body.execution_payload)
process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in EIP6110]
process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Electra:EIP6110]
process_randao(state, block.body)
process_eth1_data(state, block.body)
process_operations(state, block.body) # [Modified in EIP6110]
process_operations(state, block.body) # [Modified in Electra:EIP6110:EIP7002]
process_sync_aggregate(state, block.body.sync_aggregate)
```
#### Modified `process_operations`
*Note*: The function `process_operations` is modified to process `DepositReceipt` operations included in the payload.
*Note*: The function `process_operations` is modified to process `DepositReceipt` and `ExecutionLayerExit` operations included in the payload.
```python
def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
# [Modified in EIP6110]
# [Modified in Electra:EIP6110]
# Disable former deposit mechanism once all prior deposits are processed
eth1_deposit_index_limit = min(state.eth1_data.deposit_count, state.deposit_receipts_start_index)
if state.eth1_deposit_index < eth1_deposit_index_limit:
@ -209,6 +227,7 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
for_ops(body.attestations, process_attestation)
for_ops(body.deposits, process_deposit)
for_ops(body.voluntary_exits, process_voluntary_exit)
for_ops(body.execution_payload.exits, process_execution_layer_exit) # [New in Electra:EIP7002]
for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
# [New in EIP6110]
@ -217,6 +236,8 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
#### New `process_deposit_receipt`
*Note*: This function is new in Electra:EIP6110.
```python
def process_deposit_receipt(state: BeaconState, deposit_receipt: DepositReceipt) -> None:
# Set deposit receipt start index
@ -232,6 +253,39 @@ def process_deposit_receipt(state: BeaconState, deposit_receipt: DepositReceipt)
)
```
#### New `process_execution_layer_exit`
*Note*: This function is new in Electra:EIP7002.
```python
def process_execution_layer_exit(state: BeaconState, execution_layer_exit: ExecutionLayerExit) -> None:
validator_pubkeys = [v.pubkey for v in state.validators]
# Verify pubkey exists
pubkey_to_exit = execution_layer_exit.validator_pubkey
if pubkey_to_exit not in validator_pubkeys:
return
validator_index = ValidatorIndex(validator_pubkeys.index(pubkey_to_exit))
validator = state.validators[validator_index]
# Verify withdrawal credentials
is_execution_address = validator.withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX
is_correct_source_address = validator.withdrawal_credentials[12:] == execution_layer_exit.source_address
if not (is_execution_address and is_correct_source_address):
return
# Verify the validator is active
if not is_active_validator(validator, get_current_epoch(state)):
return
# Verify exit has not been initiated
if validator.exit_epoch != FAR_FUTURE_EPOCH:
return
# Verify the validator has been active long enough
if get_current_epoch(state) < validator.activation_epoch + SHARD_COMMITTEE_PERIOD:
return
# Initiate exit
initiate_validator_exit(state, validator_index)
```
#### Modified `process_execution_payload`
*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type.
@ -276,17 +330,18 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi
withdrawals_root=hash_tree_root(payload.withdrawals),
blob_gas_used=payload.blob_gas_used,
excess_blob_gas=payload.excess_blob_gas,
deposit_receipts_root=hash_tree_root(payload.deposit_receipts), # [New in EIP6110]
deposit_receipts_root=hash_tree_root(payload.deposit_receipts), # [New in Electra:EIP6110]
exits_root=hash_tree_root(payload.exits), # [New in Electra:EIP7002]
)
```
## Testing
*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP-6110 testing only.
*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure Electra testing only.
Modifications include:
1. Use `EIP6110_FORK_VERSION` as the previous and current fork version.
2. Utilize the EIP-6110 `BeaconBlockBody` when constructing the initial `latest_block_header`.
3. Add `deposit_receipts_start_index` variable to the genesis state initialization.
1. Use `ELECTRA_FORK_VERSION` as the previous and current fork version.
2. Utilize the Electra `BeaconBlockBody` when constructing the initial `latest_block_header`.
3. *[New in Electra:EIP6110]* Add `deposit_receipts_start_index` variable to the genesis state initialization.
```python
def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
@ -295,8 +350,8 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader()
) -> BeaconState:
fork = Fork(
previous_version=EIP6110_FORK_VERSION, # [Modified in EIP6110] for testing only
current_version=EIP6110_FORK_VERSION, # [Modified in EIP6110]
previous_version=ELECTRA_FORK_VERSION, # [Modified in Electra:EIP6110] for testing only
current_version=ELECTRA_FORK_VERSION, # [Modified in Electra:EIP6110]
epoch=GENESIS_EPOCH,
)
state = BeaconState(
@ -305,7 +360,7 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
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
deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX, # [New in EIP6110]
deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX, # [New in Electra:EIP6110]
)
# Process deposits

View File

@ -1,4 +1,4 @@
# EIP-6110 -- Fork Logic
# Electra -- Fork Logic
**Notice**: This document is a work-in-progress for researchers and implementers.
@ -12,7 +12,7 @@
- [Helper functions](#helper-functions)
- [Misc](#misc)
- [Modified `compute_fork_version`](#modified-compute_fork_version)
- [Fork to EIP-6110](#fork-to-eip-6110)
- [Fork to Electra](#fork-to-electra)
- [Fork trigger](#fork-trigger)
- [Upgrading the state](#upgrading-the-state)
@ -28,8 +28,8 @@ Warning: this configuration is not definitive.
| Name | Value |
| - | - |
| `EIP6110_FORK_VERSION` | `Version('0x06000000')` |
| `EIP6110_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
| `ELECTRA_FORK_VERSION` | `Version('0x05000000')` |
| `ELECTRA_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
## Helper functions
@ -42,8 +42,8 @@ def compute_fork_version(epoch: Epoch) -> Version:
"""
Return the fork version at the given ``epoch``.
"""
if epoch >= EIP6110_FORK_EPOCH:
return EIP6110_FORK_VERSION
if epoch >= ELECTRA_FORK_EPOCH:
return ELECTRA_FORK_VERSION
if epoch >= DENEB_FORK_EPOCH:
return DENEB_FORK_VERSION
if epoch >= CAPELLA_FORK_EPOCH:
@ -55,22 +55,22 @@ def compute_fork_version(epoch: Epoch) -> Version:
return GENESIS_FORK_VERSION
```
## Fork to EIP-6110
## Fork to Electra
### 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 `EIP6110_FORK_EPOCH`.
For now, we assume the condition will be triggered at epoch `ELECTRA_FORK_EPOCH`.
Note that for the pure EIP-6110 networks, we don't apply `upgrade_to_eip6110` since it starts with EIP-6110 version logic.
Note that for the pure Electra networks, we don't apply `upgrade_to_electra` since it starts with Electra version logic.
### Upgrading the state
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == EIP6110_FORK_EPOCH`,
an irregular state change is made to upgrade to EIP-6110.
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == ELECTRA_FORK_EPOCH`,
an irregular state change is made to upgrade to Electra.
```python
def upgrade_to_eip6110(pre: deneb.BeaconState) -> BeaconState:
def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState:
epoch = deneb.get_current_epoch(pre)
latest_execution_payload_header = ExecutionPayloadHeader(
parent_hash=pre.latest_execution_payload_header.parent_hash,
@ -90,7 +90,8 @@ def upgrade_to_eip6110(pre: deneb.BeaconState) -> BeaconState:
withdrawals_root=pre.latest_execution_payload_header.withdrawals_root,
blob_gas_used=uint64(0),
excess_blob_gas=uint64(0),
deposit_receipts_root=Root(), # [New in EIP-6110]
deposit_receipts_root=Root(), # [New in Electra:EIP6110]
exits_root=Root(), # [New in Electra:EIP-7002],
)
post = BeaconState(
# Versioning
@ -99,7 +100,7 @@ def upgrade_to_eip6110(pre: deneb.BeaconState) -> BeaconState:
slot=pre.slot,
fork=Fork(
previous_version=pre.fork.current_version,
current_version=EIP6110_FORK_VERSION, # [Modified in EIP-6110]
current_version=ELECTRA_FORK_VERSION, # [Modified in Electra:EIP6110]
epoch=epoch,
),
# History
@ -132,14 +133,14 @@ def upgrade_to_eip6110(pre: deneb.BeaconState) -> BeaconState:
current_sync_committee=pre.current_sync_committee,
next_sync_committee=pre.next_sync_committee,
# Execution-layer
latest_execution_payload_header=latest_execution_payload_header, # [Modified in EIP-6110]
latest_execution_payload_header=latest_execution_payload_header, # [Modified in Electra:EIP6110:EIP7002]
# 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,
# EIP-6110
deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX, # [New in EIP-6110]
# EIP6110
deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX, # [New in Electra:EIP6110]
)
return post

View File

@ -1,4 +1,4 @@
# EIP-6110 -- Honest Validator
# Electra -- Honest Validator
## Table of contents
@ -16,21 +16,21 @@
## Introduction
This document represents the changes to be made in the code of an "honest validator" to implement EIP-6110.
This document represents the changes to be made in the code of an "honest validator" to implement Electra.
## Prerequisites
This document is an extension of the [Deneb -- Honest Validator](../../deneb/validator.md) guide.
All behaviors and definitions defined in this document, and documents it extends, carry over unless explicitly noted or overridden.
All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of [EIP-6110](./beacon-chain.md) are requisite for this document and used throughout.
All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of [Electra](./beacon-chain.md) are requisite for this document and used throughout.
Please see related Beacon Chain doc before continuing and use them as a reference throughout.
## Block proposal
### Deposits
The expected number of deposits MUST be changed from `min(MAX_DEPOSITS, eth1_data.deposit_count - state.eth1_deposit_index)` to the result of the following function:
*[New in Electra:EIP6110* The expected number of deposits MUST be changed from `min(MAX_DEPOSITS, eth1_data.deposit_count - state.eth1_deposit_index)` to the result of the following function:
```python
def get_eth1_pending_deposit_count(state: BeaconState) -> uint64:

View File

@ -7,8 +7,8 @@ from eth2spec.utils import bls
from .exceptions import SkippedTest
from .helpers.constants import (
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
EIP6110, EIP7002, EIP7251, EIP7549, EIP7594,
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA,
EIP7251, EIP7549, EIP7594,
WHISK,
MINIMAL,
ALL_PHASES,
@ -519,8 +519,7 @@ 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_deneb_and_later = with_all_phases_from(DENEB)
with_eip6110_and_later = with_all_phases_from(EIP6110)
with_eip7002_and_later = with_all_phases_from(EIP7002)
with_electra_and_later = with_all_phases_from(ELECTRA)
with_eip7549_and_later = with_all_phases_from(EIP7549)
with_whisk_and_later = with_all_phases_from(WHISK, all_phases=ALLOWED_TEST_RUNNER_FORKS)
with_eip7594_and_later = with_all_phases_from(EIP7594, all_phases=ALLOWED_TEST_RUNNER_FORKS)

View File

@ -1,4 +1,4 @@
from eth2spec.test.context import spec_state_test, always_bls, with_eip6110_and_later
from eth2spec.test.context import spec_state_test, always_bls, with_electra_and_later
from eth2spec.test.helpers.deposits import (
prepare_deposit_receipt,
run_deposit_receipt_processing,
@ -8,7 +8,7 @@ from eth2spec.test.helpers.state import next_epoch_via_block
from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_new_deposit_under_max(spec, state):
# fresh deposit = next validator index = validator appended to registry
@ -20,7 +20,7 @@ def test_new_deposit_under_max(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_new_deposit_max(spec, state):
# fresh deposit = next validator index = validator appended to registry
@ -32,7 +32,7 @@ def test_new_deposit_max(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_new_deposit_over_max(spec, state):
# fresh deposit = next validator index = validator appended to registry
@ -44,7 +44,7 @@ def test_new_deposit_over_max(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_new_deposit_eth1_withdrawal_credentials(spec, state):
# fresh deposit = next validator index = validator appended to registry
@ -66,7 +66,7 @@ def test_new_deposit_eth1_withdrawal_credentials(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_new_deposit_non_versioned_withdrawal_credentials(spec, state):
# fresh deposit = next validator index = validator appended to registry
@ -87,7 +87,7 @@ def test_new_deposit_non_versioned_withdrawal_credentials(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
@always_bls
def test_correct_sig_but_forked_state(spec, state):
@ -99,7 +99,7 @@ def test_correct_sig_but_forked_state(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
@always_bls
def test_incorrect_sig_new_deposit(spec, state):
@ -110,7 +110,7 @@ def test_incorrect_sig_new_deposit(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index, effective=False)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_top_up__max_effective_balance(spec, state):
validator_index = 0
@ -126,7 +126,7 @@ def test_top_up__max_effective_balance(spec, state):
assert state.validators[validator_index].effective_balance == spec.MAX_EFFECTIVE_BALANCE
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_top_up__less_effective_balance(spec, state):
validator_index = 0
@ -145,7 +145,7 @@ def test_top_up__less_effective_balance(spec, state):
assert state.validators[validator_index].effective_balance == initial_effective_balance
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_top_up__zero_balance(spec, state):
validator_index = 0
@ -164,7 +164,7 @@ def test_top_up__zero_balance(spec, state):
assert state.validators[validator_index].effective_balance == initial_effective_balance
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
@always_bls
def test_incorrect_sig_top_up(spec, state):
@ -176,7 +176,7 @@ def test_incorrect_sig_top_up(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_incorrect_withdrawal_credentials_top_up(spec, state):
validator_index = 0
@ -193,7 +193,7 @@ def test_incorrect_withdrawal_credentials_top_up(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_key_validate_invalid_subgroup(spec, state):
validator_index = len(state.validators)
@ -207,7 +207,7 @@ def test_key_validate_invalid_subgroup(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_key_validate_invalid_decompression(spec, state):
validator_index = len(state.validators)
@ -223,7 +223,7 @@ def test_key_validate_invalid_decompression(spec, state):
yield from run_deposit_receipt_processing(spec, state, deposit_receipt, validator_index)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
@always_bls
def test_ineffective_deposit_with_previous_fork_version(spec, state):
@ -240,7 +240,7 @@ def test_ineffective_deposit_with_previous_fork_version(spec, state):
)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
@always_bls
def test_effective_deposit_with_genesis_fork_version(spec, state):
@ -253,7 +253,7 @@ def test_effective_deposit_with_genesis_fork_version(spec, state):
)
@with_eip6110_and_later
@with_electra_and_later
@spec_state_test
def test_success_top_up_to_withdrawn_validator(spec, state):
validator_index = 0

View File

@ -1,9 +1,9 @@
from eth2spec.test.context import spec_state_test, with_eip7002_and_later
from eth2spec.test.context import spec_state_test, with_electra_and_later
from eth2spec.test.helpers.execution_layer_exits import run_execution_layer_exit_processing
from eth2spec.test.helpers.withdrawals import set_eth1_withdrawal_credential_with_balance
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_basic_exit(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -22,7 +22,7 @@ def test_basic_exit(spec, state):
yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit)
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_incorrect_source_address(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -42,7 +42,7 @@ def test_incorrect_source_address(spec, state):
yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False)
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_incorrect_withdrawal_credential_prefix(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -66,7 +66,7 @@ def test_incorrect_withdrawal_credential_prefix(spec, state):
yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False)
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_on_exit_initiated_validator(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -87,7 +87,7 @@ def test_on_exit_initiated_validator(spec, state):
yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False)
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_activation_epoch_less_than_shard_committee_period(spec, state):
current_epoch = spec.get_current_epoch(state)

View File

@ -3,7 +3,7 @@ from eth2spec.test.helpers.block import (
)
from eth2spec.test.context import (
spec_state_test,
with_eip7002_and_later,
with_electra_and_later,
)
from eth2spec.test.helpers.bls_to_execution_changes import (
get_signed_address_change,
@ -22,7 +22,7 @@ from eth2spec.test.helpers.withdrawals import (
)
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_basic_el_exit(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -51,7 +51,7 @@ def test_basic_el_exit(spec, state):
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_basic_btec_and_el_exit_in_same_block(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -94,7 +94,7 @@ def test_basic_btec_and_el_exit_in_same_block(spec, state):
assert is_execution_address and is_correct_source_address
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_basic_btec_before_el_exit(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
@ -141,7 +141,7 @@ def test_basic_btec_before_el_exit(spec, state):
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
@with_eip7002_and_later
@with_electra_and_later
@spec_state_test
def test_cl_exit_and_el_exit_in_same_block(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit

View File

@ -4,7 +4,7 @@ from eth2spec.test.helpers.block import (
from eth2spec.test.context import (
spec_state_test,
with_phases,
EIP6110,
ELECTRA,
)
from eth2spec.test.helpers.deposits import (
build_deposit_data,
@ -108,7 +108,7 @@ def prepare_state_and_block(spec,
return state, block
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__start_index_is_set(spec, state):
# 0 deposits, 2 deposit receipts, unset deposit_receipts_start_index
@ -123,7 +123,7 @@ def test_deposit_transition__start_index_is_set(spec, state):
assert state.deposit_receipts_start_index == block.body.execution_payload.deposit_receipts[0].index
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__process_eth1_deposits(spec, state):
# 3 deposits, 1 deposit receipt, state.eth1_data.deposit_count < state.deposit_receipts_start_index
@ -136,7 +136,7 @@ def test_deposit_transition__process_eth1_deposits(spec, state):
yield from run_deposit_transition_block(spec, state, block)
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__process_max_eth1_deposits(spec, state):
# spec.MAX_DEPOSITS deposits, 1 deposit receipt, state.eth1_data.deposit_count > state.deposit_receipts_start_index
@ -151,7 +151,7 @@ def test_deposit_transition__process_max_eth1_deposits(spec, state):
yield from run_deposit_transition_block(spec, state, block)
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__process_eth1_deposits_up_to_start_index(spec, state):
# 3 deposits, 1 deposit receipt, state.eth1_data.deposit_count == state.deposit_receipts_start_index
@ -164,7 +164,7 @@ def test_deposit_transition__process_eth1_deposits_up_to_start_index(spec, state
yield from run_deposit_transition_block(spec, state, block)
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__invalid_not_enough_eth1_deposits(spec, state):
# 3 deposits, 1 deposit receipt, state.eth1_data.deposit_count < state.deposit_receipts_start_index
@ -178,7 +178,7 @@ def test_deposit_transition__invalid_not_enough_eth1_deposits(spec, state):
yield from run_deposit_transition_block(spec, state, block, valid=False)
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__invalid_too_many_eth1_deposits(spec, state):
# 3 deposits, 1 deposit receipt, state.eth1_data.deposit_count < state.eth1_data_index
@ -192,7 +192,7 @@ def test_deposit_transition__invalid_too_many_eth1_deposits(spec, state):
yield from run_deposit_transition_block(spec, state, block, valid=False)
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__invalid_eth1_deposits_overlap_in_protocol_deposits(spec, state):
# spec.MAX_DEPOSITS deposits, 1 deposit receipt, state.eth1_data.deposit_count > state.deposit_receipts_start_index
@ -207,7 +207,7 @@ def test_deposit_transition__invalid_eth1_deposits_overlap_in_protocol_deposits(
yield from run_deposit_transition_block(spec, state, block, valid=False)
@with_phases([EIP6110])
@with_phases([ELECTRA])
@spec_state_test
def test_deposit_transition__deposit_and_top_up_same_block(spec, state):
# 1 deposit, 1 deposit receipt that top ups deposited validator

View File

@ -11,13 +11,12 @@ ALTAIR = SpecForkName('altair')
BELLATRIX = SpecForkName('bellatrix')
CAPELLA = SpecForkName('capella')
DENEB = SpecForkName('deneb')
ELECTRA = SpecForkName('electra')
# Experimental phases (not included in default "ALL_PHASES"):
SHARDING = SpecForkName('sharding')
CUSTODY_GAME = SpecForkName('custody_game')
DAS = SpecForkName('das')
EIP6110 = SpecForkName('eip6110')
EIP7002 = SpecForkName('eip7002')
EIP7549 = SpecForkName('eip7549')
WHISK = SpecForkName('whisk')
EIP7251 = SpecForkName('eip7251')
@ -37,9 +36,8 @@ ALL_PHASES = (
# Formal forks
*MAINNET_FORKS,
DENEB,
ELECTRA,
# Experimental patches
EIP6110,
EIP7002,
EIP7251,
EIP7549,
EIP7594,
@ -47,7 +45,7 @@ ALL_PHASES = (
# The forks that have light client specs
LIGHT_CLIENT_TESTING_FORKS = (*[item for item in MAINNET_FORKS if item != PHASE0], DENEB)
# The forks that output to the test vectors.
TESTGEN_FORKS = (*MAINNET_FORKS, DENEB, EIP6110, WHISK)
TESTGEN_FORKS = (*MAINNET_FORKS, DENEB, ELECTRA, WHISK)
# Forks allowed in the test runner `--fork` flag, to fail fast in case of typos
ALLOWED_TEST_RUNNER_FORKS = (*ALL_PHASES, WHISK)
@ -59,10 +57,9 @@ PREVIOUS_FORK_OF = {
BELLATRIX: ALTAIR,
CAPELLA: BELLATRIX,
DENEB: CAPELLA,
ELECTRA: DENEB,
# Experimental patches
EIP6110: DENEB,
WHISK: CAPELLA,
EIP7002: CAPELLA,
EIP7549: DENEB,
EIP7251: DENEB,
EIP7594: DENEB,
@ -75,7 +72,7 @@ POST_FORK_OF = {
ALTAIR: BELLATRIX,
BELLATRIX: CAPELLA,
CAPELLA: DENEB,
DENEB: EIP6110,
DENEB: ELECTRA,
}
ALL_PRE_POST_FORKS = POST_FORK_OF.items()

View File

@ -7,8 +7,7 @@ from eth2spec.debug.random_value import get_random_bytes_list
from eth2spec.test.helpers.forks import (
is_post_capella,
is_post_deneb,
is_post_eip6110,
is_post_eip7002,
is_post_electra,
)
@ -34,9 +33,8 @@ def get_execution_payload_header(spec, execution_payload):
if is_post_deneb(spec):
payload_header.blob_gas_used = execution_payload.blob_gas_used
payload_header.excess_blob_gas = execution_payload.excess_blob_gas
if is_post_eip6110(spec):
if is_post_electra(spec):
payload_header.deposit_receipts_root = spec.hash_tree_root(execution_payload.deposit_receipts)
if is_post_eip7002(spec):
payload_header.exits_root = spec.hash_tree_root(execution_payload.exits)
return payload_header
@ -105,11 +103,10 @@ def compute_el_header_block_hash(spec,
# excess_blob_gas
execution_payload_header_rlp.append((big_endian_int, payload_header.blob_gas_used))
execution_payload_header_rlp.append((big_endian_int, payload_header.excess_blob_gas))
if is_post_eip6110(spec):
if is_post_electra(spec):
# deposit_receipts_root
assert deposit_receipts_trie_root is not None
execution_payload_header_rlp.append((Binary(32, 32), deposit_receipts_trie_root))
if is_post_eip7002(spec):
# exits_trie_root
execution_payload_header_rlp.append((Binary(32, 32), exits_trie_root))
@ -181,10 +178,9 @@ def compute_el_block_hash(spec, payload):
if is_post_capella(spec):
withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals]
withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded)
if is_post_eip6110(spec):
if is_post_electra(spec):
deposit_receipts_encoded = [get_deposit_receipt_rlp(spec, receipt) for receipt in payload.deposit_receipts]
deposit_receipts_trie_root = compute_trie_root_from_indexed_data(deposit_receipts_encoded)
if is_post_eip7002(spec):
exits_encoded = [get_exit_rlp(exit) for exit in payload.exits]
exits_trie_root = compute_trie_root_from_indexed_data(exits_encoded)
@ -231,7 +227,7 @@ def build_empty_execution_payload(spec, state, randao_mix=None):
if is_post_deneb(spec):
payload.blob_gas_used = 0
payload.excess_blob_gas = 0
if is_post_eip6110(spec):
if is_post_electra(spec):
# just to be clear
payload.deposit_receipts = []

View File

@ -1,6 +1,7 @@
from .constants import (
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
EIP6110, EIP7002, EIP7251, EIP7549, WHISK,
ELECTRA,
EIP7251, EIP7549, WHISK,
PREVIOUS_FORK_OF,
)
@ -37,12 +38,8 @@ def is_post_deneb(spec):
return is_post_fork(spec.fork, DENEB)
def is_post_eip6110(spec):
return is_post_fork(spec.fork, EIP6110)
def is_post_eip7002(spec):
return is_post_fork(spec.fork, EIP7002)
def is_post_electra(spec):
return is_post_fork(spec.fork, ELECTRA)
def is_post_eip7251(spec):

View File

@ -6,7 +6,7 @@ from eth2spec.test.helpers.execution_payload import (
compute_el_header_block_hash,
)
from eth2spec.test.helpers.forks import (
is_post_altair, is_post_bellatrix, is_post_capella, is_post_eip6110, is_post_eip7002, is_post_whisk, is_post_eip7251
is_post_altair, is_post_bellatrix, is_post_capella, is_post_electra, is_post_whisk, is_post_eip7251
)
from eth2spec.test.helpers.keys import pubkeys
from eth2spec.test.helpers.whisk import compute_whisk_initial_tracker_cached, compute_whisk_initial_k_commitment_cached
@ -55,9 +55,8 @@ def get_sample_genesis_execution_payload_header(spec,
if is_post_capella(spec):
withdrawals_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
if is_post_eip6110(spec):
if is_post_electra(spec):
deposit_receipts_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
if is_post_eip7002(spec):
exits_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
payload_header.block_hash = compute_el_header_block_hash(
@ -134,7 +133,7 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
eth1_block_hash=eth1_block_hash,
)
if is_post_eip6110(spec):
if is_post_electra(spec):
state.deposit_receipts_start_index = spec.UNSET_DEPOSIT_RECEIPTS_START_INDEX
if is_post_whisk(spec):

View File

@ -45,7 +45,8 @@ Operations:
| `execution_payload` | `BeaconBlockBody` | **`body`** | `process_execution_payload(state, body)` (new in Bellatrix) |
| `withdrawals` | `ExecutionPayload` | `execution_payload` | `process_withdrawals(state, execution_payload)` (new in Capella) |
| `bls_to_execution_change` | `SignedBLSToExecutionChange` | `address_change` | `process_bls_to_execution_change(state, address_change)` (new in Capella) |
| `deposit_receipt` | `DepositReceipt` | `deposit_receipt` | `process_deposit_receipt(state, deposit_receipt)` (new in EIP6110) |
| `deposit_receipt` | `DepositReceipt` | `deposit_receipt` | `process_deposit_receipt(state, deposit_receipt)` (new in Electra) |
| `exits` | `ExecutionLayerExit` | `execution_layer_exit` | `process_execution_layer_exit(state, execution_layer_exit)` (new in Electra) |
Note that `block_header` is not strictly an operation (and is a full `Block`), but processed in the same manner, and hence included here.

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -37,7 +37,7 @@ if __name__ == "__main__":
]}
deneb_mods = combine_mods(_new_deneb_mods, capella_mods)
eip6110_mods = deneb_mods
electra_mods = deneb_mods
# TODO Custody Game testgen is disabled for now
# custody_game_mods = {**{key: 'eth2spec.test.custody_game.epoch_processing.test_process_' + key for key in [
@ -52,7 +52,7 @@ if __name__ == "__main__":
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="epoch_processing", all_mods=all_mods)

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -8,7 +8,7 @@ if __name__ == "__main__":
bellatrix_mods = altair_mods # No additional Bellatrix specific finality tests
capella_mods = bellatrix_mods # No additional Capella specific finality tests
deneb_mods = capella_mods # No additional Deneb specific finality tests
eip6110_mods = deneb_mods # No additional EIP6110 specific finality tests
electra_mods = deneb_mods # No additional Electra specific finality tests
all_mods = {
PHASE0: phase_0_mods,
@ -16,7 +16,7 @@ if __name__ == "__main__":
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="finality", all_mods=all_mods)

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -28,14 +28,14 @@ if __name__ == "__main__":
]}
deneb_mods = combine_mods(_new_deneb_mods, capella_mods)
eip6110_mods = deneb_mods # No additional EIP6110 specific fork choice tests
electra_mods = deneb_mods # No additional Electra specific fork choice tests
all_mods = {
ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="fork_choice", all_mods=all_mods)

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -17,14 +17,14 @@ if __name__ == "__main__":
bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods)
capella_mods = bellatrix_mods # No additional Capella specific genesis tests
deneb_mods = capella_mods # No additional Deneb specific genesis tests
eip6110_mods = deneb_mods # No additional EIP6110 specific genesis tests
electra_mods = deneb_mods # No additional Electra specific genesis tests
all_mods = {
PHASE0: phase_0_mods,
ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="genesis", all_mods=all_mods)

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -43,10 +43,11 @@ if __name__ == "__main__":
]}
deneb_mods = combine_mods(_new_deneb_mods, capella_mods)
_new_eip6110_mods = {key: 'eth2spec.test.eip6110.block_processing.test_process_' + key for key in [
_new_electra_mods = {key: 'eth2spec.test.electra.block_processing.test_process_' + key for key in [
'deposit_receipt',
'execution_layer_exit',
]}
eip6110_mods = combine_mods(_new_eip6110_mods, deneb_mods)
electra_mods = combine_mods(_new_electra_mods, deneb_mods)
# TODO Custody Game testgen is disabled for now
# _new_custody_game_mods = {key: 'eth2spec.test.custody_game.block_processing.test_process_' + key for key in [
@ -64,7 +65,7 @@ if __name__ == "__main__":
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="operations", all_mods=all_mods)

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -17,7 +17,7 @@ if __name__ == "__main__":
bellatrix_mods = altair_mods
capella_mods = bellatrix_mods
deneb_mods = capella_mods
eip6110_mods = deneb_mods
electra_mods = deneb_mods
all_mods = {
PHASE0: phase_0_mods,
@ -25,7 +25,7 @@ if __name__ == "__main__":
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="rewards", all_mods=all_mods)

View File

@ -1,4 +1,4 @@
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
@ -28,10 +28,10 @@ if __name__ == "__main__":
]}
deneb_mods = combine_mods(_new_deneb_mods, capella_mods)
_new_eip6110_mods = {key: 'eth2spec.test.eip6110.sanity.' + key for key in [
_new_electra_mods = {key: 'eth2spec.test.electra.sanity.' + key for key in [
'blocks',
]}
eip6110_mods = combine_mods(_new_eip6110_mods, deneb_mods)
electra_mods = combine_mods(_new_electra_mods, deneb_mods)
all_mods = {
PHASE0: phase_0_mods,
@ -39,7 +39,7 @@ if __name__ == "__main__":
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="sanity", all_mods=all_mods)

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
from eth2spec.test.helpers.constants import BELLATRIX, CAPELLA, DENEB, EIP6110
from eth2spec.test.helpers.constants import BELLATRIX, CAPELLA, DENEB, ELECTRA
if __name__ == "__main__":
@ -8,13 +8,13 @@ if __name__ == "__main__":
]}
capella_mods = bellatrix_mods
deneb_mods = capella_mods
eip6110_mods = deneb_mods
electra_mods = deneb_mods
all_mods = {
BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods,
DENEB: deneb_mods,
EIP6110: eip6110_mods,
ELECTRA: electra_mods,
}
run_state_test_generators(runner_name="sync", all_mods=all_mods)