mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-21 14:58:12 +00:00
Add EIP-7251 to Electra fork
This commit is contained in:
parent
77ec547cc7
commit
ce3931653d
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,7 +23,6 @@ tests/core/pyspec/eth2spec/capella/
|
||||
tests/core/pyspec/eth2spec/deneb/
|
||||
tests/core/pyspec/eth2spec/electra/
|
||||
tests/core/pyspec/eth2spec/whisk/
|
||||
tests/core/pyspec/eth2spec/eip7251/
|
||||
tests/core/pyspec/eth2spec/eip7594/
|
||||
|
||||
# coverage reports
|
||||
|
@ -53,9 +53,6 @@ DENEB_FORK_EPOCH: 269568 # March 13, 2024, 01:55:35pm UTC
|
||||
# Electra
|
||||
ELECTRA_FORK_VERSION: 0x05000000
|
||||
ELECTRA_FORK_EPOCH: 18446744073709551615
|
||||
# EIP7251
|
||||
EIP7251_FORK_VERSION: 0x06000000 # temporary stub
|
||||
EIP7251_FORK_EPOCH: 18446744073709551615
|
||||
# WHISK
|
||||
WHISK_FORK_VERSION: 0x08000000 # temporary stub
|
||||
WHISK_FORK_EPOCH: 18446744073709551615
|
||||
@ -163,6 +160,6 @@ NUMBER_OF_COLUMNS: 128
|
||||
DATA_COLUMN_SIDECAR_SUBNET_COUNT: 32
|
||||
MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384
|
||||
|
||||
# [New in EIP7251]
|
||||
MIN_PER_EPOCH_CHURN_LIMIT_EIP7251: 128000000000 # 2**7 * 10**9 (= 128,000,000,000)
|
||||
# [New in Electra:EIP7251]
|
||||
MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000 # 2**7 * 10**9 (= 128,000,000,000)
|
||||
MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000 # 2**8 * 10**9 (= 256,000,000,000)
|
||||
|
@ -52,9 +52,6 @@ DENEB_FORK_EPOCH: 18446744073709551615
|
||||
# Electra
|
||||
ELECTRA_FORK_VERSION: 0x05000001
|
||||
ELECTRA_FORK_EPOCH: 18446744073709551615
|
||||
# EIP7251
|
||||
EIP7251_FORK_VERSION: 0x06000001 # temporary stub
|
||||
EIP7251_FORK_EPOCH: 18446744073709551615
|
||||
# WHISK
|
||||
WHISK_FORK_VERSION: 0x08000001
|
||||
WHISK_FORK_EPOCH: 18446744073709551615
|
||||
@ -161,6 +158,6 @@ NUMBER_OF_COLUMNS: 128
|
||||
DATA_COLUMN_SIDECAR_SUBNET_COUNT: 32
|
||||
MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384
|
||||
|
||||
# [New in EIP7251]
|
||||
MIN_PER_EPOCH_CHURN_LIMIT_EIP7251: 64000000000 # 2**6 * 10**9 (= 64,000,000,000)
|
||||
# [New in Electra:EIP7251]
|
||||
MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 64000000000 # 2**6 * 10**9 (= 64,000,000,000)
|
||||
MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 128000000000 # 2**7 * 10**9 (= 128,000,000,000)
|
||||
|
@ -1,28 +0,0 @@
|
||||
# Mainnet preset - EIP7251
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MIN_ACTIVATION_BALANCE: 32000000000
|
||||
# 2**11 * 10**9 (= 2,048,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE_EIP7251: 2048000000000
|
||||
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
|
||||
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 134217728
|
||||
PENDING_CONSOLIDATIONS_LIMIT: 262144
|
||||
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_EIP7251: 4096
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT_EIP7251: 4096
|
||||
|
||||
# Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
MAX_CONSOLIDATIONS: 1
|
||||
|
||||
# Execution
|
||||
# ---------------------------------------------------------------
|
||||
# 2**3 (= 8) partial withdrawals
|
||||
MAX_PARTIAL_WITHDRAWALS_PER_PAYLOAD: 8
|
@ -1,11 +1,30 @@
|
||||
# Mainnet preset - Electra
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MIN_ACTIVATION_BALANCE: 32000000000
|
||||
# 2**11 * 10**9 (= 2,048,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000
|
||||
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
|
||||
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 134217728
|
||||
PENDING_CONSOLIDATIONS_LIMIT: 262144
|
||||
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: 4096
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: 4096
|
||||
|
||||
# # Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
# `uint64(2**0)` (= 1)
|
||||
MAX_ATTESTER_SLASHINGS_ELECTRA: 1
|
||||
# `uint64(2 * 3)` (= 8)
|
||||
MAX_ATTESTATIONS_ELECTRA: 8
|
||||
MAX_CONSOLIDATIONS: 1
|
||||
|
||||
# Execution
|
||||
# ---------------------------------------------------------------
|
||||
@ -13,3 +32,5 @@ MAX_ATTESTATIONS_ELECTRA: 8
|
||||
MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: 8192
|
||||
# 2**4 (= 16) exits
|
||||
MAX_EXECUTION_LAYER_EXITS: 16
|
||||
# 2**3 (= 8) partial withdrawals
|
||||
MAX_PARTIAL_WITHDRAWALS_PER_PAYLOAD: 8
|
||||
|
@ -1,30 +0,0 @@
|
||||
# Minimal preset - EIP7251
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MIN_ACTIVATION_BALANCE: 32000000000
|
||||
# 2**11 * 10**9 (= 2,048,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE_EIP7251: 2048000000000
|
||||
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
|
||||
# [customized] smaller queue
|
||||
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 64
|
||||
# [customized] smaller queue
|
||||
PENDING_CONSOLIDATIONS_LIMIT: 64
|
||||
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_EIP7251: 4096
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT_EIP7251: 4096
|
||||
|
||||
# Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
MAX_CONSOLIDATIONS: 1
|
||||
|
||||
# Execution
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] 2**1 (= 2)
|
||||
MAX_PARTIAL_WITHDRAWALS_PER_PAYLOAD: 2
|
@ -1,11 +1,32 @@
|
||||
# Minimal preset - Electra
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MIN_ACTIVATION_BALANCE: 32000000000
|
||||
# 2**11 * 10**9 (= 2,048,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000
|
||||
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
PENDING_BALANCE_DEPOSITS_LIMIT: 134217728
|
||||
# [customized] smaller queue
|
||||
PENDING_PARTIAL_WITHDRAWALS_LIMIT: 64
|
||||
# [customized] smaller queue
|
||||
PENDING_CONSOLIDATIONS_LIMIT: 64
|
||||
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: 4096
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: 4096
|
||||
|
||||
# # Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
# `uint64(2**0)` (= 1)
|
||||
MAX_ATTESTER_SLASHINGS_ELECTRA: 1
|
||||
# `uint64(2 * 3)` (= 8)
|
||||
MAX_ATTESTATIONS_ELECTRA: 8
|
||||
MAX_CONSOLIDATIONS: 1
|
||||
|
||||
# Execution
|
||||
# ---------------------------------------------------------------
|
||||
@ -13,3 +34,5 @@ MAX_ATTESTATIONS_ELECTRA: 8
|
||||
MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: 4
|
||||
# 2**4 (= 16) exits
|
||||
MAX_EXECUTION_LAYER_EXITS: 16
|
||||
# [customized] 2**1 (= 2)
|
||||
MAX_PARTIAL_WITHDRAWALS_PER_PAYLOAD: 2
|
||||
|
@ -6,7 +6,6 @@ CAPELLA = 'capella'
|
||||
DENEB = 'deneb'
|
||||
ELECTRA = 'electra'
|
||||
EIP7594 = 'eip7594'
|
||||
EIP7251 = 'eip7251'
|
||||
WHISK = 'whisk'
|
||||
|
||||
|
||||
|
@ -9,7 +9,6 @@ from .constants import (
|
||||
ELECTRA,
|
||||
WHISK,
|
||||
EIP7594,
|
||||
EIP7251,
|
||||
)
|
||||
|
||||
|
||||
@ -21,7 +20,6 @@ PREVIOUS_FORK_OF = {
|
||||
DENEB: CAPELLA,
|
||||
ELECTRA: DENEB,
|
||||
WHISK: CAPELLA,
|
||||
EIP7251: DENEB,
|
||||
EIP7594: DENEB,
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ from .capella import CapellaSpecBuilder
|
||||
from .deneb import DenebSpecBuilder
|
||||
from .electra import ElectraSpecBuilder
|
||||
from .whisk import WhiskSpecBuilder
|
||||
from .eip7251 import EIP7251SpecBuilder
|
||||
from .eip7594 import EIP7594SpecBuilder
|
||||
|
||||
|
||||
@ -13,6 +12,6 @@ spec_builders = {
|
||||
builder.fork: builder
|
||||
for builder in (
|
||||
Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder, DenebSpecBuilder,
|
||||
ElectraSpecBuilder, WhiskSpecBuilder, EIP7594SpecBuilder, EIP7251SpecBuilder,
|
||||
ElectraSpecBuilder, WhiskSpecBuilder, EIP7594SpecBuilder,
|
||||
)
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
from typing import Dict
|
||||
|
||||
from .base import BaseSpecBuilder
|
||||
from ..constants import EIP7251
|
||||
|
||||
|
||||
class EIP7251SpecBuilder(BaseSpecBuilder):
|
||||
fork: str = EIP7251
|
||||
|
||||
@classmethod
|
||||
def imports(cls, preset_name: str):
|
||||
return super().imports(preset_name) + f'''
|
||||
from eth2spec.deneb import {preset_name} as deneb
|
||||
'''
|
||||
|
||||
## TODO: deal with changed gindices
|
||||
|
||||
@classmethod
|
||||
def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]:
|
||||
return {
|
||||
'FINALIZED_ROOT_GINDEX': 'GeneralizedIndex(169)',
|
||||
'CURRENT_SYNC_COMMITTEE_GINDEX': 'GeneralizedIndex(86)',
|
||||
'NEXT_SYNC_COMMITTEE_GINDEX': 'GeneralizedIndex(87)',
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
from typing import Dict
|
||||
from .base import BaseSpecBuilder
|
||||
from ..constants import ELECTRA
|
||||
|
||||
@ -10,3 +11,13 @@ class ElectraSpecBuilder(BaseSpecBuilder):
|
||||
return f'''
|
||||
from eth2spec.deneb import {preset_name} as deneb
|
||||
'''
|
||||
|
||||
## TODO: deal with changed gindices
|
||||
|
||||
@classmethod
|
||||
def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]:
|
||||
return {
|
||||
'FINALIZED_ROOT_GINDEX': 'GeneralizedIndex(169)',
|
||||
'CURRENT_SYNC_COMMITTEE_GINDEX': 'GeneralizedIndex(86)',
|
||||
'NEXT_SYNC_COMMITTEE_GINDEX': 'GeneralizedIndex(87)',
|
||||
}
|
||||
|
@ -1,137 +0,0 @@
|
||||
# EIP7251 -- Fork Logic
|
||||
|
||||
**Notice**: This document is a work-in-progress for researchers and implementers.
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- 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)
|
||||
- [Configuration](#configuration)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc)
|
||||
- [Modified `compute_fork_version`](#modified-compute_fork_version)
|
||||
- [Fork to EIP7251](#fork-to-eip7251)
|
||||
- [Fork trigger](#fork-trigger)
|
||||
- [Upgrading the state](#upgrading-the-state)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This document describes the process of the EIP7251 upgrade.
|
||||
|
||||
## Configuration
|
||||
|
||||
Warning: this configuration is not definitive.
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `EIP7251_FORK_VERSION` | `Version('0x06000000')` |
|
||||
| `EIP7251_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 >= EIP7251_FORK_EPOCH:
|
||||
return EIP7251_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 EIP7251
|
||||
|
||||
### 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 `EIP7251_FORK_EPOCH`.
|
||||
|
||||
Note that for the pure EIP7251 networks, we don't apply `upgrade_to_eip7251` since it starts with EIP7251 version logic.
|
||||
|
||||
### Upgrading the state
|
||||
|
||||
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == EIP7251_FORK_EPOCH`,
|
||||
an irregular state change is made to upgrade to EIP7251.
|
||||
|
||||
```python
|
||||
def upgrade_to_eip7251(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=EIP7251_FORK_VERSION,
|
||||
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,
|
||||
# [New in EIP7251]
|
||||
deposit_balance_to_consume=0,
|
||||
exit_balance_to_consume=get_activation_exit_churn_limit(pre),
|
||||
earliest_exit_epoch=max([v.exit_epoch for v in pre.validators if v.exit_epoch != FAR_FUTURE_EPOCH]) + 1,
|
||||
consolidation_balance_to_consume=get_consolidation_churn_limit(pre),
|
||||
earliest_consolidation_epoch=compute_activation_exit_epoch(get_current_epoch(pre)),
|
||||
pending_balance_deposits=[],
|
||||
pending_partial_withdrawals=[],
|
||||
pending_consolidations=[],
|
||||
)
|
||||
|
||||
# Ensure early adopters of compounding credentials go through the activation churn
|
||||
for index, validator in enumerate(post.validators):
|
||||
if has_compounding_withdrawal_credential(validator):
|
||||
queue_excess_active_balance(post, ValidatorIndex(index))
|
||||
|
||||
return post
|
||||
```
|
@ -1,73 +0,0 @@
|
||||
# EIP-7251 -- Honest Validator
|
||||
|
||||
## 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)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Beacon chain responsibilities](#beacon-chain-responsibilities)
|
||||
- [Block and sidecar proposal](#block-and-sidecar-proposal)
|
||||
- [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody)
|
||||
- [ExecutionPayload](#executionpayload)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This document represents the changes to be made in the code of an "honest validator".
|
||||
|
||||
## 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-7251](./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.
|
||||
|
||||
## Beacon chain responsibilities
|
||||
|
||||
All validator responsibilities remain unchanged other than those noted below.
|
||||
|
||||
### Block and sidecar proposal
|
||||
|
||||
#### Constructing the `BeaconBlockBody`
|
||||
|
||||
##### ExecutionPayload
|
||||
|
||||
`prepare_execution_payload` is updated from the Deneb specs.
|
||||
|
||||
*Note*: In this section, `state` is the state of the slot for the block proposal _without_ the block yet applied.
|
||||
That is, `state` is the `previous_state` processed through any empty slots up to the assigned slot using `process_slots(previous_state, slot)`.
|
||||
|
||||
*Note*: The only change to `prepare_execution_payload` is the new definition of `get_expected_withdrawals`.
|
||||
|
||||
```python
|
||||
def prepare_execution_payload(state: BeaconState,
|
||||
safe_block_hash: Hash32,
|
||||
finalized_block_hash: Hash32,
|
||||
suggested_fee_recipient: ExecutionAddress,
|
||||
execution_engine: ExecutionEngine) -> Optional[PayloadId]:
|
||||
# Verify consistency of the parent hash with respect to the previous execution payload header
|
||||
parent_hash = state.latest_execution_payload_header.block_hash
|
||||
|
||||
# Set the forkchoice head and initiate the payload build process
|
||||
withdrawals, _ = get_expected_withdrawals(state) # [Modified in EIP-7251]
|
||||
|
||||
payload_attributes = PayloadAttributes(
|
||||
timestamp=compute_timestamp_at_slot(state, state.slot),
|
||||
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
||||
suggested_fee_recipient=suggested_fee_recipient,
|
||||
withdrawals=withdrawals,
|
||||
parent_beacon_block_root=hash_tree_root(state.latest_block_header),
|
||||
)
|
||||
return execution_engine.notify_forkchoice_updated(
|
||||
head_block_hash=parent_hash,
|
||||
safe_block_hash=safe_block_hash,
|
||||
finalized_block_hash=finalized_block_hash,
|
||||
payload_attributes=payload_attributes,
|
||||
)
|
||||
```
|
File diff suppressed because it is too large
Load Diff
@ -139,9 +139,24 @@ def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState:
|
||||
next_withdrawal_validator_index=pre.next_withdrawal_validator_index,
|
||||
# Deep history valid from Capella onwards
|
||||
historical_summaries=pre.historical_summaries,
|
||||
# EIP6110
|
||||
deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX, # [New in Electra:EIP6110]
|
||||
# [New in Electra:EIP6110]
|
||||
deposit_receipts_start_index=UNSET_DEPOSIT_RECEIPTS_START_INDEX,
|
||||
# [New in Electra:EIP7251]
|
||||
deposit_balance_to_consume=0,
|
||||
exit_balance_to_consume=get_activation_exit_churn_limit(pre),
|
||||
earliest_exit_epoch=max([v.exit_epoch for v in pre.validators if v.exit_epoch != FAR_FUTURE_EPOCH]) + 1,
|
||||
consolidation_balance_to_consume=get_consolidation_churn_limit(pre),
|
||||
earliest_consolidation_epoch=compute_activation_exit_epoch(get_current_epoch(pre)),
|
||||
pending_balance_deposits=[],
|
||||
pending_partial_withdrawals=[],
|
||||
pending_consolidations=[],
|
||||
)
|
||||
|
||||
# [New in Electra:EIP7251]
|
||||
# Ensure early adopters of compounding credentials go through the activation churn
|
||||
for index, validator in enumerate(post.validators):
|
||||
if has_compounding_withdrawal_credential(validator):
|
||||
queue_excess_active_balance(post, ValidatorIndex(index))
|
||||
|
||||
return post
|
||||
```
|
||||
|
@ -13,6 +13,7 @@
|
||||
- [Attester slashings](#attester-slashings)
|
||||
- [Attestations](#attestations)
|
||||
- [Deposits](#deposits)
|
||||
- [Execution payload](#execution-payload)
|
||||
- [Attesting](#attesting)
|
||||
- [Construct attestation](#construct-attestation)
|
||||
- [Attestation aggregation](#attestation-aggregation)
|
||||
@ -81,6 +82,42 @@ def get_eth1_pending_deposit_count(state: BeaconState) -> uint64:
|
||||
return uint64(0)
|
||||
```
|
||||
|
||||
#### Execution payload
|
||||
|
||||
`prepare_execution_payload` is updated from the Deneb specs.
|
||||
|
||||
*Note*: In this section, `state` is the state of the slot for the block proposal _without_ the block yet applied.
|
||||
That is, `state` is the `previous_state` processed through any empty slots up to the assigned slot using `process_slots(previous_state, slot)`.
|
||||
|
||||
*Note*: The only change to `prepare_execution_payload` is the new definition of `get_expected_withdrawals`.
|
||||
|
||||
```python
|
||||
def prepare_execution_payload(state: BeaconState,
|
||||
safe_block_hash: Hash32,
|
||||
finalized_block_hash: Hash32,
|
||||
suggested_fee_recipient: ExecutionAddress,
|
||||
execution_engine: ExecutionEngine) -> Optional[PayloadId]:
|
||||
# Verify consistency of the parent hash with respect to the previous execution payload header
|
||||
parent_hash = state.latest_execution_payload_header.block_hash
|
||||
|
||||
# Set the forkchoice head and initiate the payload build process
|
||||
withdrawals, _ = get_expected_withdrawals(state) # [Modified in EIP-7251]
|
||||
|
||||
payload_attributes = PayloadAttributes(
|
||||
timestamp=compute_timestamp_at_slot(state, state.slot),
|
||||
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
||||
suggested_fee_recipient=suggested_fee_recipient,
|
||||
withdrawals=withdrawals,
|
||||
parent_beacon_block_root=hash_tree_root(state.latest_block_header),
|
||||
)
|
||||
return execution_engine.notify_forkchoice_updated(
|
||||
head_block_hash=parent_hash,
|
||||
safe_block_hash=safe_block_hash,
|
||||
finalized_block_hash=finalized_block_hash,
|
||||
payload_attributes=payload_attributes,
|
||||
)
|
||||
```
|
||||
|
||||
## Attesting
|
||||
|
||||
### Construct attestation
|
||||
|
@ -8,7 +8,6 @@ from eth2spec.utils import bls
|
||||
from .exceptions import SkippedTest
|
||||
from .helpers.constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA,
|
||||
EIP7251,
|
||||
EIP7594,
|
||||
WHISK,
|
||||
MINIMAL,
|
||||
@ -523,7 +522,6 @@ with_deneb_and_later = with_all_phases_from(DENEB)
|
||||
with_electra_and_later = with_all_phases_from(ELECTRA)
|
||||
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)
|
||||
with_eip7251_and_later = with_all_phases_from(EIP7251, all_phases=ALLOWED_TEST_RUNNER_FORKS)
|
||||
|
||||
|
||||
class quoted_str(str):
|
||||
|
@ -1,7 +1,7 @@
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_eip7251_and_later,
|
||||
with_electra_and_later,
|
||||
with_presets,
|
||||
always_bls,
|
||||
spec_test,
|
||||
@ -25,7 +25,7 @@ from eth2spec.test.helpers.withdrawals import (
|
||||
# ***********************
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -73,7 +73,7 @@ def test_basic_consolidation_in_current_consolidation_epoch(spec, state):
|
||||
assert state.validators[0].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -262,7 +262,7 @@ def test_basic_consolidation_with_compounding_credential(spec, state):
|
||||
assert state.validators[0].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -310,7 +310,7 @@ def test_consolidation_churn_limit_balance(spec, state):
|
||||
assert state.validators[0].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -357,7 +357,7 @@ def test_consolidation_balance_larger_than_churn_limit(spec, state):
|
||||
assert state.validators[0].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -404,7 +404,7 @@ def test_consolidation_balance_through_two_churn_epochs(spec, state):
|
||||
assert state.consolidation_balance_to_consume == expected_balance
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -461,7 +461,7 @@ def test_multiple_consolidations_below_churn(spec, state):
|
||||
assert state.validators[2 * i].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -515,7 +515,7 @@ def test_multiple_consolidations_equal_churn(spec, state):
|
||||
assert state.validators[2 * i].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -593,7 +593,7 @@ def test_multiple_consolidations_above_churn(spec, state):
|
||||
assert state.validators[2 * i].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL], "need sufficient consolidation churn limit")
|
||||
@with_custom_state(
|
||||
balances_fn=scaled_churn_balances_exceed_activation_exit_churn_limit,
|
||||
@ -651,8 +651,7 @@ def test_multiple_consolidations_equal_twice_churn(spec, state):
|
||||
|
||||
# Failing tests
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_source_equals_target(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -678,7 +677,7 @@ def test_invalid_source_equals_target(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_exceed_pending_consolidations_limit(spec, state):
|
||||
state.pending_consolidations = [
|
||||
@ -727,7 +726,7 @@ def test_invalid_not_enough_consolidation_churn_available(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_exited_source(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -749,7 +748,7 @@ def test_invalid_exited_source(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_exited_target(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -772,7 +771,7 @@ def test_invalid_exited_target(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_inactive_source(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -794,7 +793,7 @@ def test_invalid_inactive_source(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_inactive_target(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -817,7 +816,7 @@ def test_invalid_inactive_target(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_no_execution_withdrawal_credential(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -835,7 +834,7 @@ def test_invalid_no_execution_withdrawal_credential(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_different_credentials(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -856,7 +855,7 @@ def test_invalid_different_credentials(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_source_signature(spec, state):
|
||||
@ -880,7 +879,7 @@ def test_invalid_source_signature(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_target_signature(spec, state):
|
||||
@ -904,7 +903,7 @@ def test_invalid_target_signature(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_before_specified_epoch(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
@ -0,0 +1,284 @@
|
||||
from eth2spec.test.helpers.deposits import (
|
||||
build_deposit,
|
||||
prepare_state_and_deposit,
|
||||
run_deposit_processing_electra,
|
||||
run_deposit_processing_electra_with_specific_fork_version,
|
||||
sign_deposit_data,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
||||
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_electra_and_later,
|
||||
always_bls,
|
||||
)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_new_deposit_under_min_activation_balance(spec, state):
|
||||
# fresh deposit = next validator index = validator appended to registry
|
||||
validator_index = len(state.validators)
|
||||
# effective balance will be 1 EFFECTIVE_BALANCE_INCREMENT smaller because of this small decrement.
|
||||
amount = spec.MIN_ACTIVATION_BALANCE - 1
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_new_deposit_min(spec, state):
|
||||
# fresh deposit = next validator index = validator appended to registry
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MIN_DEPOSIT_AMOUNT
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_new_deposit_between_min_and_max(spec, state):
|
||||
# fresh deposit = next validator index = validator appended to registry
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE_electra // 2
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_new_deposit_max(spec, state):
|
||||
# fresh deposit = next validator index = validator appended to registry
|
||||
validator_index = len(state.validators)
|
||||
# effective balance will be exactly the same as balance.
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE_electra
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_new_deposit_over_max(spec, state):
|
||||
# fresh deposit = next validator index = validator appended to registry
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE_electra + 1
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
# @with_electra_and_later
|
||||
# @spec_state_test
|
||||
# def test_top_up__max_effective_balance(spec, state):
|
||||
# validator_index = 0
|
||||
# amount = spec.MAX_EFFECTIVE_BALANCE_electra // 4
|
||||
# deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
# state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE_electra
|
||||
# state.validators[validator_index].effective_balance = spec.MAX_EFFECTIVE_BALANCE_electra
|
||||
|
||||
# yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
# assert state.balances[validator_index] == spec.MAX_EFFECTIVE_BALANCE_electra + amount
|
||||
# assert state.validators[validator_index].effective_balance == spec.MAX_EFFECTIVE_BALANCE_electra
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_correct_sig_but_forked_state(spec, state):
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||
# deposits will always be valid, regardless of the current fork
|
||||
state.fork.current_version = spec.Version('0x1234abcd')
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_incorrect_sig_new_deposit(spec, state):
|
||||
# fresh deposit = next validator index = validator appended to registry
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MIN_ACTIVATION_BALANCE
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index, effective=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_top_up__max_effective_balance(spec, state):
|
||||
validator_index = 0
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
state.balances[validator_index] = spec.MAX_EFFECTIVE_BALANCE
|
||||
state.validators[validator_index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
assert state.validators[validator_index].effective_balance == spec.MAX_EFFECTIVE_BALANCE
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_top_up__less_effective_balance(spec, state):
|
||||
validator_index = 0
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
initial_balance = spec.MAX_EFFECTIVE_BALANCE - 1000
|
||||
initial_effective_balance = spec.MAX_EFFECTIVE_BALANCE - spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
state.balances[validator_index] = initial_balance
|
||||
state.validators[validator_index].effective_balance = initial_effective_balance
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
# unchanged effective balance
|
||||
assert state.validators[validator_index].effective_balance == initial_effective_balance
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_top_up__zero_balance(spec, state):
|
||||
validator_index = 0
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
initial_balance = 0
|
||||
initial_effective_balance = 0
|
||||
state.balances[validator_index] = initial_balance
|
||||
state.validators[validator_index].effective_balance = initial_effective_balance
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
# unchanged effective balance
|
||||
assert state.validators[validator_index].effective_balance == initial_effective_balance
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_incorrect_sig_top_up(spec, state):
|
||||
validator_index = 0
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||
|
||||
# invalid signatures, in top-ups, are allowed!
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_incorrect_withdrawal_credentials_top_up(spec, state):
|
||||
validator_index = 0
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(b"junk")[1:]
|
||||
deposit = prepare_state_and_deposit(
|
||||
spec,
|
||||
state,
|
||||
validator_index,
|
||||
amount,
|
||||
withdrawal_credentials=withdrawal_credentials
|
||||
)
|
||||
|
||||
# inconsistent withdrawal credentials, in top-ups, are allowed!
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_wrong_deposit_for_deposit_count(spec, state):
|
||||
deposit_data_leaves = [spec.DepositData() for _ in range(len(state.validators))]
|
||||
|
||||
# build root for deposit_1
|
||||
index_1 = len(deposit_data_leaves)
|
||||
pubkey_1 = pubkeys[index_1]
|
||||
privkey_1 = privkeys[index_1]
|
||||
_, _, deposit_data_leaves = build_deposit(
|
||||
spec,
|
||||
deposit_data_leaves,
|
||||
pubkey_1,
|
||||
privkey_1,
|
||||
spec.MAX_EFFECTIVE_BALANCE,
|
||||
withdrawal_credentials=b'\x00' * 32,
|
||||
signed=True,
|
||||
)
|
||||
deposit_count_1 = len(deposit_data_leaves)
|
||||
|
||||
# build root for deposit_2
|
||||
index_2 = len(deposit_data_leaves)
|
||||
pubkey_2 = pubkeys[index_2]
|
||||
privkey_2 = privkeys[index_2]
|
||||
deposit_2, root_2, deposit_data_leaves = build_deposit(
|
||||
spec,
|
||||
deposit_data_leaves,
|
||||
pubkey_2,
|
||||
privkey_2,
|
||||
spec.MAX_EFFECTIVE_BALANCE,
|
||||
withdrawal_credentials=b'\x00' * 32,
|
||||
signed=True,
|
||||
)
|
||||
|
||||
# state has root for deposit_2 but is at deposit_count for deposit_1
|
||||
state.eth1_data.deposit_root = root_2
|
||||
state.eth1_data.deposit_count = deposit_count_1
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit_2, index_2, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_bad_merkle_proof(spec, state):
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||
|
||||
# mess up merkle branch
|
||||
deposit.proof[5] = spec.Bytes32()
|
||||
|
||||
sign_deposit_data(spec, deposit.data, privkeys[validator_index])
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_key_validate_invalid_subgroup(spec, state):
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||
|
||||
# All-zero pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception.
|
||||
pubkey = b'\x00' * 48
|
||||
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, pubkey=pubkey, signed=True)
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_key_validate_invalid_decompression(spec, state):
|
||||
validator_index = len(state.validators)
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||
|
||||
# `deserialization_fails_infinity_with_true_b_flag` BLS G1 deserialization test case.
|
||||
# This pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception.
|
||||
pubkey_hex = 'c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||
pubkey = bytes.fromhex(pubkey_hex)
|
||||
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, pubkey=pubkey, signed=True)
|
||||
|
||||
yield from run_deposit_processing_electra(spec, state, deposit, validator_index)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_ineffective_deposit_with_bad_fork_version(spec, state):
|
||||
yield from run_deposit_processing_electra_with_specific_fork_version(
|
||||
spec,
|
||||
state,
|
||||
fork_version=spec.Version('0xAaBbCcDd'),
|
||||
effective=False,
|
||||
)
|
@ -1,7 +1,7 @@
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
expect_assertion_error,
|
||||
with_eip7251_and_later,
|
||||
with_electra_and_later,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
@ -20,8 +20,7 @@ from eth2spec.test.helpers.withdrawals import (
|
||||
|
||||
# Modified tests from 7002. Just testing EL-triggered exits, not partial withdrawals
|
||||
|
||||
|
||||
@with_eip7251_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
|
||||
@ -104,7 +103,7 @@ def test_basic_exit_with_full_partial_withdrawal_queue(spec, state):
|
||||
# Invalid tests
|
||||
|
||||
|
||||
@with_eip7251_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
|
||||
@ -129,7 +128,7 @@ def test_incorrect_source_address(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_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
|
||||
@ -158,7 +157,7 @@ def test_incorrect_withdrawal_credential_prefix(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_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
|
||||
@ -184,7 +183,7 @@ def test_on_exit_initiated_validator(spec, state):
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_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)
|
||||
@ -212,8 +211,7 @@ def test_activation_epoch_less_than_shard_committee_period(spec, state):
|
||||
|
||||
# Partial withdrawals tests
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MINIMAL])
|
||||
def test_basic_partial_withdrawal_request(spec, state):
|
||||
|
@ -0,0 +1,441 @@
|
||||
from eth2spec.test.helpers.constants import (MINIMAL, MAINNET)
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_electra_and_later,
|
||||
with_presets,
|
||||
always_bls,
|
||||
spec_test, single_phase,
|
||||
with_custom_state,
|
||||
scaled_churn_balances_min_churn_limit,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import pubkey_to_privkey
|
||||
from eth2spec.test.helpers.voluntary_exits import (
|
||||
run_voluntary_exit_processing,
|
||||
sign_voluntary_exit,
|
||||
)
|
||||
# ********************
|
||||
# * EXIT QUEUE TESTS *
|
||||
# ********************
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_min_balance_exit(spec, state):
|
||||
# This state has 64 validators each with 32 ETH
|
||||
expected_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
# Set the balance to consume equal to churn limit
|
||||
state.exit_balance_to_consume = churn_limit
|
||||
|
||||
yield "pre", state
|
||||
# Exit validators, all which fit in the churn limit
|
||||
spec.initiate_validator_exit(state, 0)
|
||||
yield "post", state
|
||||
|
||||
# Check exit queue churn is set
|
||||
assert state.exit_balance_to_consume == churn_limit - spec.MIN_ACTIVATION_BALANCE
|
||||
# Check exit epoch
|
||||
assert state.validators[0].exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_min_balance_exits_up_to_churn(spec, state):
|
||||
# This state has 64 validators each with 32 ETH
|
||||
single_validator_balance = spec.MIN_ACTIVATION_BALANCE
|
||||
expected_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
# Set the balance to consume equal to churn limit
|
||||
state.exit_balance_to_consume = churn_limit
|
||||
|
||||
yield "pre", state
|
||||
# Exit validators, all which fit in the churn limit
|
||||
for i in range(churn_limit // spec.MIN_ACTIVATION_BALANCE):
|
||||
validator_index = i
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
yield f"post{i}", state
|
||||
# Check exit queue churn is set
|
||||
assert state.exit_balance_to_consume == churn_limit - single_validator_balance * (i + 1)
|
||||
# Check exit epoch
|
||||
assert state.validators[validator_index].exit_epoch == expected_exit_epoch
|
||||
yield "post", state
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_min_balance_exits_above_churn(spec, state):
|
||||
# This state has 64 validators each with 32 ETH
|
||||
single_validator_balance = spec.MIN_ACTIVATION_BALANCE
|
||||
expected_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
# Set the balance to consume equal to churn limit
|
||||
state.exit_balance_to_consume = churn_limit
|
||||
|
||||
yield "pre", state
|
||||
# Exit validators, all which fit in the churn limit
|
||||
for i in range(churn_limit // spec.MIN_ACTIVATION_BALANCE):
|
||||
validator_index = i
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
# Check exit queue churn is set
|
||||
assert state.exit_balance_to_consume == churn_limit - single_validator_balance * (i + 1)
|
||||
# Check exit epoch
|
||||
assert state.validators[validator_index].exit_epoch == expected_exit_epoch
|
||||
|
||||
# Exit balance has been fully consumed
|
||||
assert state.exit_balance_to_consume == 0
|
||||
|
||||
# Exit an additional validator, doesn't fit in the churn limit, so exit
|
||||
# epoch is incremented
|
||||
validator_index = churn_limit // spec.MIN_ACTIVATION_BALANCE
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
|
||||
yield "post", state
|
||||
# Check exit epoch
|
||||
assert state.validators[validator_index].exit_epoch == expected_exit_epoch + 1
|
||||
# Check exit balance to consume is set
|
||||
assert state.exit_balance_to_consume == churn_limit - single_validator_balance
|
||||
|
||||
|
||||
# @with_electra_and_later
|
||||
# @spec_state_test
|
||||
# def test_exit_balance_to_consume_large_validator(spec, state):
|
||||
# # Set 0th validator effective balance to 2048 ETH
|
||||
# state.validators[0].effective_balance = spec.MAX_EFFECTIVE_BALANCE_electra
|
||||
# churn_limit = spec.get_validator_churn_limit(state)
|
||||
# expected_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
# expected_exit_epoch += spec.MAX_EFFECTIVE_BALANCE_electra // churn_limit
|
||||
|
||||
# validator_index = 0
|
||||
# spec.initiate_validator_exit(state, validator_index)
|
||||
# # Check exit epoch
|
||||
# assert state.validators[validator_index].exit_epoch == expected_exit_epoch
|
||||
# # Check exit_balance_to_consume
|
||||
# assert state.exit_balance_to_consume == churn_limit - (spec.MAX_EFFECTIVE_BALANCE_electra % churn_limit)
|
||||
# # Check earliest_exit_epoch
|
||||
# assert state.earliest_exit_epoch == expected_exit_epoch
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MAINNET], "With CHURN_LIMIT_QUOTIENT=32, can't change validator balance without changing churn_limit")
|
||||
def test_max_balance_exit(spec, state):
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
assert churn_limit == spec.MIN_ACTIVATION_BALANCE * spec.config.MIN_PER_EPOCH_CHURN_LIMIT
|
||||
|
||||
# Set 0th validator effective balance to 2048 ETH
|
||||
state.validators[0].effective_balance = spec.MAX_EFFECTIVE_BALANCE_electra
|
||||
yield 'pre', state
|
||||
|
||||
expected_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
# Validator consumes exit churn for 16 epochs, exits at the 17th one
|
||||
expected_exit_epoch += (spec.MAX_EFFECTIVE_BALANCE_electra // churn_limit)
|
||||
|
||||
validator_index = 0
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
yield 'post', state
|
||||
# Check exit epoch
|
||||
assert state.validators[validator_index].exit_epoch == expected_exit_epoch
|
||||
# Check exit_balance_to_consume
|
||||
assert state.exit_balance_to_consume == churn_limit
|
||||
# Check earliest_exit_epoch
|
||||
assert state.earliest_exit_epoch == expected_exit_epoch
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MAINNET], "With CHURN_LIMIT_QUOTIENT=32, can't change validator balance without changing churn_limit")
|
||||
def test_exit_with_balance_equal_to_churn_limit(spec, state):
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
|
||||
# Set 0th validator effective balance to churn_limit
|
||||
state.validators[0].effective_balance = churn_limit
|
||||
yield 'pre', state
|
||||
|
||||
validator_index = 0
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
|
||||
yield 'post', state
|
||||
# Validator consumes churn limit fully in the current epoch
|
||||
assert (state.validators[validator_index].exit_epoch ==
|
||||
spec.compute_activation_exit_epoch(spec.get_current_epoch(state)))
|
||||
# Check exit_balance_to_consume
|
||||
assert state.exit_balance_to_consume == 0
|
||||
# Check earliest_exit_epoch
|
||||
assert state.earliest_exit_epoch == state.validators[validator_index].exit_epoch
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MAINNET], "With CHURN_LIMIT_QUOTIENT=32, can't change validator balance without changing churn_limit")
|
||||
def test_exit_churn_limit_balance_existing_churn_(spec, state):
|
||||
cl = spec.get_activation_exit_churn_limit(state)
|
||||
|
||||
# set exit epoch to the first available one and set exit balance to consume to full churn limit
|
||||
state.earliest_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
state.exit_balance_to_consume = cl
|
||||
# consume some churn in exit epoch
|
||||
state.exit_balance_to_consume -= 1000000000
|
||||
|
||||
# Set 0th validator effective balance to the churn limit
|
||||
state.validators[0].effective_balance = cl
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
# The existing 1 ETH churn will push an extra epoch
|
||||
expected_exit_epoch = state.earliest_exit_epoch + 1
|
||||
|
||||
yield 'post', state
|
||||
validator_index = 0
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
# Check exit epoch
|
||||
assert state.validators[validator_index].exit_epoch == expected_exit_epoch
|
||||
# Check balance consumed in exit epoch is the remainder 1 ETH
|
||||
assert state.exit_balance_to_consume == cl - 1000000000
|
||||
# check earliest exit epoch
|
||||
assert expected_exit_epoch == state.earliest_exit_epoch
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@with_presets([MAINNET], "With CHURN_LIMIT_QUOTIENT=32, can't change validator balance without changing churn_limit")
|
||||
def test_multi_epoch_exit_existing_churn(spec, state):
|
||||
cl = spec.get_activation_exit_churn_limit(state)
|
||||
|
||||
# set exit epoch to the first available one and set exit balance to consume to full churn limit
|
||||
state.earliest_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
state.exit_balance_to_consume = cl
|
||||
# consume some churn in exit epoch
|
||||
state.exit_balance_to_consume -= 1000000000
|
||||
|
||||
# Set 0th validator effective balance to 2x the churn limit
|
||||
state.validators[0].effective_balance = 2 * cl
|
||||
|
||||
yield 'pre', state
|
||||
# Two extra epochs will be necessary
|
||||
expected_exit_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state)) + 2
|
||||
|
||||
validator_index = 0
|
||||
spec.initiate_validator_exit(state, validator_index)
|
||||
yield 'post', state
|
||||
# Check exit epoch
|
||||
assert state.validators[validator_index].exit_epoch == expected_exit_epoch
|
||||
# Check balance consumed in exit epoch is the remainder 1 ETH
|
||||
assert state.exit_balance_to_consume == cl - 1000000000
|
||||
# check earliest exit epoch
|
||||
assert expected_exit_epoch == state.earliest_exit_epoch
|
||||
|
||||
|
||||
# Repurposed from phase0 voluntary exit tests, should disable the phase0 ones
|
||||
|
||||
def run_test_success_exit_queue(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
# exit `MAX_EXITS_PER_EPOCH`
|
||||
max_exits = churn_limit // spec.MIN_ACTIVATION_BALANCE
|
||||
initial_indices = spec.get_active_validator_indices(state, current_epoch)[:max_exits]
|
||||
|
||||
# Prepare a bunch of exits, based on the current state
|
||||
exit_queue = []
|
||||
for index in initial_indices:
|
||||
privkey = pubkey_to_privkey[state.validators[index].pubkey]
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=index), privkey)
|
||||
|
||||
exit_queue.append(signed_voluntary_exit)
|
||||
|
||||
# Now run all the exits
|
||||
for voluntary_exit in exit_queue:
|
||||
# the function yields data, but we are just interested in running it here, ignore yields.
|
||||
for _ in run_voluntary_exit_processing(spec, state, voluntary_exit):
|
||||
continue
|
||||
|
||||
# exit an additional validator
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey)
|
||||
|
||||
# This is the interesting part of the test: on a pre-state with a full exit queue,
|
||||
# when processing an additional exit, it results in an exit in a later epoch
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit)
|
||||
|
||||
for index in initial_indices:
|
||||
assert (
|
||||
state.validators[validator_index].exit_epoch ==
|
||||
state.validators[index].exit_epoch + 1
|
||||
)
|
||||
assert state.earliest_exit_epoch == state.validators[validator_index].exit_epoch
|
||||
consumed_churn = spec.MIN_ACTIVATION_BALANCE * (max_exits + 1)
|
||||
assert state.exit_balance_to_consume == churn_limit - (consumed_churn % churn_limit)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_success_exit_queue__min_churn(spec, state):
|
||||
yield from run_test_success_exit_queue(spec, state)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_min_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_success_exit_queue__scaled_churn(spec, state):
|
||||
churn_limit = spec.get_activation_exit_churn_limit(state)
|
||||
assert churn_limit > spec.config.MIN_PER_EPOCH_CHURN_LIMIT
|
||||
yield from run_test_success_exit_queue(spec, state)
|
||||
|
||||
|
||||
# After here no modifications were made, can just leave them in phase0 as is
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_basic(spec, state):
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit)
|
||||
|
||||
assert state.validators[validator_index].exit_epoch == spec.compute_activation_exit_epoch(current_epoch)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_incorrect_signature(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
|
||||
voluntary_exit = spec.VoluntaryExit(
|
||||
epoch=current_epoch,
|
||||
validator_index=validator_index,
|
||||
)
|
||||
signed_voluntary_exit = sign_voluntary_exit(spec, state, voluntary_exit, 12345)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_default_exit_epoch_subsequent_exit(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey)
|
||||
|
||||
# Exit one validator prior to this new one
|
||||
exited_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
||||
state.validators[exited_index].exit_epoch = current_epoch - 1
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit)
|
||||
|
||||
assert state.validators[validator_index].exit_epoch == spec.compute_activation_exit_epoch(current_epoch)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_validator_exit_in_future(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
voluntary_exit = spec.VoluntaryExit(
|
||||
epoch=current_epoch + 1,
|
||||
validator_index=validator_index,
|
||||
)
|
||||
signed_voluntary_exit = sign_voluntary_exit(spec, state, voluntary_exit, privkey)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_validator_incorrect_validator_index(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
voluntary_exit = spec.VoluntaryExit(
|
||||
epoch=current_epoch,
|
||||
validator_index=len(state.validators),
|
||||
)
|
||||
signed_voluntary_exit = sign_voluntary_exit(spec, state, voluntary_exit, privkey)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_validator_not_active(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
state.validators[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_validator_already_exited(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow validator able to exit
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
# but validator already has exited
|
||||
state.validators[validator_index].exit_epoch = current_epoch + 2
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False)
|
||||
|
||||
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_validator_not_active_long_enough(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||
|
||||
signed_voluntary_exit = sign_voluntary_exit(
|
||||
spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey)
|
||||
|
||||
assert (
|
||||
current_epoch - state.validators[validator_index].activation_epoch <
|
||||
spec.config.SHARD_COMMITTEE_PERIOD
|
||||
)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False)
|
@ -1,11 +1,11 @@
|
||||
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_eip7251_and_later,
|
||||
with_electra_and_later,
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_deposit_min_activation_balance(spec, state):
|
||||
index = 0
|
||||
@ -23,7 +23,7 @@ def test_pending_deposit_min_activation_balance(spec, state):
|
||||
assert state.pending_balance_deposits == []
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_deposit_balance_equal_churn(spec, state):
|
||||
index = 0
|
||||
@ -40,7 +40,7 @@ def test_pending_deposit_balance_equal_churn(spec, state):
|
||||
assert state.pending_balance_deposits == []
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_deposit_balance_above_churn(spec, state):
|
||||
index = 0
|
||||
@ -64,7 +64,7 @@ def test_pending_deposit_balance_above_churn(spec, state):
|
||||
]
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_pending_deposit_preexisting_churn(spec, state):
|
||||
index = 0
|
||||
@ -85,7 +85,7 @@ def test_pending_deposit_preexisting_churn(spec, state):
|
||||
assert state.pending_balance_deposits == []
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_multiple_pending_deposits_below_churn(spec, state):
|
||||
amount = 10**9
|
||||
@ -106,7 +106,7 @@ def test_multiple_pending_deposits_below_churn(spec, state):
|
||||
assert state.pending_balance_deposits == []
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_multiple_pending_deposits_above_churn(spec, state):
|
||||
# set third deposit to be over the churn
|
||||
|
@ -1,7 +1,7 @@
|
||||
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_eip7251_and_later,
|
||||
with_electra_and_later,
|
||||
)
|
||||
|
||||
# ***********************
|
||||
@ -9,7 +9,7 @@ from eth2spec.test.context import (
|
||||
# ***********************
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_basic_pending_consolidation(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
@ -78,7 +78,7 @@ def test_consolidation_not_yet_withdrawable_validator(spec, state):
|
||||
assert state.pending_consolidations == pre_pending_consolidations
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_state_test
|
||||
def test_skip_consolidation_when_source_slashed(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
@ -1,11 +1,11 @@
|
||||
from eth2spec.test.context import (
|
||||
single_phase,
|
||||
spec_test,
|
||||
with_eip7251_and_later,
|
||||
with_electra_and_later,
|
||||
)
|
||||
|
||||
|
||||
@with_eip7251_and_later
|
||||
@with_electra_and_later
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_withdrawals(spec):
|
||||
|
@ -19,7 +19,6 @@ CUSTODY_GAME = SpecForkName('custody_game')
|
||||
DAS = SpecForkName('das')
|
||||
ELECTRA = SpecForkName('electra')
|
||||
WHISK = SpecForkName('whisk')
|
||||
EIP7251 = SpecForkName('eip7251')
|
||||
EIP7594 = SpecForkName('eip7594')
|
||||
|
||||
#
|
||||
@ -38,7 +37,6 @@ ALL_PHASES = (
|
||||
DENEB,
|
||||
ELECTRA,
|
||||
# Experimental patches
|
||||
EIP7251,
|
||||
EIP7594,
|
||||
)
|
||||
# The forks that have light client specs
|
||||
@ -59,7 +57,6 @@ PREVIOUS_FORK_OF = {
|
||||
ELECTRA: DENEB,
|
||||
# Experimental patches
|
||||
WHISK: CAPELLA,
|
||||
EIP7251: DENEB,
|
||||
EIP7594: DENEB,
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from .constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
|
||||
ELECTRA, WHISK, EIP7251,
|
||||
ELECTRA, WHISK,
|
||||
PREVIOUS_FORK_OF,
|
||||
)
|
||||
|
||||
@ -41,10 +41,6 @@ def is_post_electra(spec):
|
||||
return is_post_fork(spec.fork, ELECTRA)
|
||||
|
||||
|
||||
def is_post_eip7251(spec):
|
||||
return is_post_fork(spec.fork, EIP7251)
|
||||
|
||||
|
||||
def is_post_whisk(spec):
|
||||
return is_post_fork(spec.fork, WHISK)
|
||||
|
||||
|
@ -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_electra, is_post_whisk, is_post_eip7251,
|
||||
is_post_altair, is_post_bellatrix, is_post_capella, is_post_electra, is_post_whisk,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
from eth2spec.test.helpers.whisk import compute_whisk_initial_tracker_cached, compute_whisk_initial_k_commitment_cached
|
||||
@ -148,7 +148,7 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
|
||||
for i in range(spec.WHISK_PROPOSER_TRACKERS_COUNT):
|
||||
state.whisk_proposer_trackers[i] = compute_whisk_initial_tracker_cached(i % vc)
|
||||
|
||||
if is_post_eip7251(spec):
|
||||
if is_post_electra(spec):
|
||||
state.deposit_balance_to_consume = 0
|
||||
state.exit_balance_to_consume = 0
|
||||
state.earliest_exit_epoch = spec.GENESIS_EPOCH
|
||||
|
@ -4,7 +4,7 @@ from eth2spec.test.context import (
|
||||
)
|
||||
from eth2spec.test.helpers.constants import UINT64_MAX
|
||||
from eth2spec.test.helpers.forks import (
|
||||
is_post_altair, is_post_bellatrix, is_post_eip7251,
|
||||
is_post_altair, is_post_bellatrix, is_post_electra,
|
||||
)
|
||||
|
||||
|
||||
@ -58,8 +58,8 @@ def test_incentives(spec, state):
|
||||
assert spec.MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX <= spec.WHISTLEBLOWER_REWARD_QUOTIENT
|
||||
elif is_post_altair(spec):
|
||||
assert spec.MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR <= spec.WHISTLEBLOWER_REWARD_QUOTIENT
|
||||
elif is_post_eip7251(spec):
|
||||
assert spec.MIN_SLASHING_PENALTY_QUOTIENT_EIP7251 <= spec.WHISTLEBLOWER_REWARD_QUOTIENT_EIP7251
|
||||
elif is_post_electra(spec):
|
||||
assert spec.MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA <= spec.WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA
|
||||
else:
|
||||
assert spec.MIN_SLASHING_PENALTY_QUOTIENT <= spec.WHISTLEBLOWER_REWARD_QUOTIENT
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user