Merge branch 'dev' into sf-epochoverrides

This commit is contained in:
Etan Kissling 2022-11-19 12:11:04 +01:00
commit c3000ed996
No known key found for this signature in database
GPG Key ID: B21DA824C5A3D03D
48 changed files with 1401 additions and 223 deletions

View File

@ -618,14 +618,13 @@ from eth2spec.bellatrix import {preset_name} as bellatrix
# #
# EIP4844SpecBuilder # EIP4844SpecBuilder
# #
class EIP4844SpecBuilder(BellatrixSpecBuilder): class EIP4844SpecBuilder(CapellaSpecBuilder):
fork: str = EIP4844 fork: str = EIP4844
@classmethod @classmethod
def imports(cls, preset_name: str): def imports(cls, preset_name: str):
return super().imports(preset_name) + f''' return super().imports(preset_name) + f'''
from eth2spec.utils import kzg from eth2spec.capella import {preset_name} as capella
from eth2spec.bellatrix import {preset_name} as bellatrix
''' '''
@ -638,19 +637,31 @@ T = TypeVar('T') # For generic function
@classmethod @classmethod
def sundry_functions(cls) -> str: def sundry_functions(cls) -> str:
return super().sundry_functions() + '\n\n' + ''' return super().sundry_functions() + '\n\n' + '''
# TODO: for mainnet, load pre-generated trusted setup file to reduce building time. #
# TESTING_FIELD_ELEMENTS_PER_BLOB is hardcoded copy from minimal presets # Temporarily disable Withdrawals functions for EIP4844 testnets
TESTING_FIELD_ELEMENTS_PER_BLOB = 4 #
TESTING_SECRET = 1337
TESTING_KZG_SETUP_G1 = kzg.generate_setup(bls.G1, TESTING_SECRET, TESTING_FIELD_ELEMENTS_PER_BLOB)
TESTING_KZG_SETUP_G2 = kzg.generate_setup(bls.G2, TESTING_SECRET, TESTING_FIELD_ELEMENTS_PER_BLOB)
TESTING_KZG_SETUP_LAGRANGE = kzg.get_lagrange(TESTING_KZG_SETUP_G1)
KZG_SETUP_G1 = [bls.G1_to_bytes48(p) for p in TESTING_KZG_SETUP_G1]
KZG_SETUP_G2 = [bls.G2_to_bytes96(p) for p in TESTING_KZG_SETUP_G2]
KZG_SETUP_LAGRANGE = TESTING_KZG_SETUP_LAGRANGE
ROOTS_OF_UNITY = kzg.compute_roots_of_unity(TESTING_FIELD_ELEMENTS_PER_BLOB)
def no_op(fn): # type: ignore
def wrapper(*args, **kw): # type: ignore
return None
return wrapper
def get_empty_list_result(fn): # type: ignore
def wrapper(*args, **kw): # type: ignore
return []
return wrapper
process_withdrawals = no_op(process_withdrawals)
process_bls_to_execution_change = no_op(process_bls_to_execution_change)
get_expected_withdrawals = get_empty_list_result(get_expected_withdrawals)
#
# End
#
def retrieve_blobs_sidecar(slot: Slot, beacon_block_root: Root) -> Optional[BlobsSidecar]: def retrieve_blobs_sidecar(slot: Slot, beacon_block_root: Root) -> Optional[BlobsSidecar]:
return "TEST"''' return "TEST"'''
@ -1002,7 +1013,7 @@ class PySpecCommand(Command):
specs/bellatrix/p2p-interface.md specs/bellatrix/p2p-interface.md
sync/optimistic.md sync/optimistic.md
""" """
if self.spec_fork == CAPELLA: if self.spec_fork in (CAPELLA, EIP4844):
self.md_doc_paths += """ self.md_doc_paths += """
specs/capella/beacon-chain.md specs/capella/beacon-chain.md
specs/capella/fork.md specs/capella/fork.md

View File

@ -33,13 +33,14 @@
- [`process_execution_payload`](#process_execution_payload) - [`process_execution_payload`](#process_execution_payload)
- [Blob KZG commitments](#blob-kzg-commitments) - [Blob KZG commitments](#blob-kzg-commitments)
- [Testing](#testing) - [Testing](#testing)
- [Disabling Withdrawals](#disabling-withdrawals)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC --> <!-- /TOC -->
## Introduction ## Introduction
This upgrade adds blobs to the beacon chain as part of EIP-4844. This upgrade adds blobs to the beacon chain as part of EIP-4844. This is an extension of the Capella upgrade.
## Custom types ## Custom types
@ -88,7 +89,8 @@ class BeaconBlockBody(Container):
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
sync_aggregate: SyncAggregate sync_aggregate: SyncAggregate
# Execution # Execution
execution_payload: ExecutionPayload execution_payload: ExecutionPayload # [Modified in EIP-4844]
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
blob_kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] # [New in EIP-4844] blob_kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] # [New in EIP-4844]
``` ```
@ -109,10 +111,11 @@ class ExecutionPayload(Container):
timestamp: uint64 timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES] extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256 base_fee_per_gas: uint256
excess_blobs: uint64 # [New in EIP-4844] excess_data_gas: uint256 # [New in EIP-4844]
# Extra payload fields # Extra payload fields
block_hash: Hash32 # Hash of execution block block_hash: Hash32 # Hash of execution block
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
``` ```
#### `ExecutionPayloadHeader` #### `ExecutionPayloadHeader`
@ -132,10 +135,11 @@ class ExecutionPayloadHeader(Container):
timestamp: uint64 timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES] extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256 base_fee_per_gas: uint256
excess_blobs: uint64 # [New in EIP-4844] excess_data_gas: uint256 # [New in EIP-4844]
# Extra payload fields # Extra payload fields
block_hash: Hash32 # Hash of execution block block_hash: Hash32 # Hash of execution block
transactions_root: Root transactions_root: Root
withdrawals_root: Root
``` ```
## Helper functions ## Helper functions
@ -227,7 +231,8 @@ def verify_kzg_commitments_against_transactions(transactions: Sequence[Transacti
def process_block(state: BeaconState, block: BeaconBlock) -> None: def process_block(state: BeaconState, block: BeaconBlock) -> None:
process_block_header(state, block) process_block_header(state, block)
if is_execution_enabled(state, block.body): if is_execution_enabled(state, block.body):
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) process_withdrawals(state, block.body.execution_payload)
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [Modified in EIP-4844]
process_randao(state, block.body) process_randao(state, block.body)
process_eth1_data(state, block.body) process_eth1_data(state, block.body)
process_operations(state, block.body) process_operations(state, block.body)
@ -253,6 +258,7 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot) assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
# Verify the execution payload is valid # Verify the execution payload is valid
assert execution_engine.notify_new_payload(payload) assert execution_engine.notify_new_payload(payload)
# Cache execution payload header # Cache execution payload header
state.latest_execution_payload_header = ExecutionPayloadHeader( state.latest_execution_payload_header = ExecutionPayloadHeader(
parent_hash=payload.parent_hash, parent_hash=payload.parent_hash,
@ -267,9 +273,10 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
timestamp=payload.timestamp, timestamp=payload.timestamp,
extra_data=payload.extra_data, extra_data=payload.extra_data,
base_fee_per_gas=payload.base_fee_per_gas, base_fee_per_gas=payload.base_fee_per_gas,
excess_blobs=payload.excess_blobs, # [New in EIP-4844] excess_data_gas=payload.excess_data_gas, # [New in EIP-4844]
block_hash=payload.block_hash, block_hash=payload.block_hash,
transactions_root=hash_tree_root(payload.transactions), transactions_root=hash_tree_root(payload.transactions),
withdrawals_root=hash_tree_root(payload.withdrawals),
) )
``` ```
@ -335,3 +342,10 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
return state return state
``` ```
### Disabling Withdrawals
During testing we avoid Capella-specific updates to the state transition. We do this by replacing the following functions with a no-op implementation:
- `process_withdrawals`
- `process_bls_to_execution_change`
The `get_expected_withdrawals` function is also modified to return an empty withdrawals list. As such, the PayloadAttributes used to update forkchoice does not contain withdrawals.

View File

@ -44,6 +44,8 @@ def compute_fork_version(epoch: Epoch) -> Version:
""" """
if epoch >= EIP4844_FORK_EPOCH: if epoch >= EIP4844_FORK_EPOCH:
return EIP4844_FORK_VERSION return EIP4844_FORK_VERSION
if epoch >= CAPELLA_FORK_EPOCH:
return CAPELLA_FORK_VERSION
if epoch >= BELLATRIX_FORK_EPOCH: if epoch >= BELLATRIX_FORK_EPOCH:
return BELLATRIX_FORK_VERSION return BELLATRIX_FORK_VERSION
if epoch >= ALTAIR_FORK_EPOCH: if epoch >= ALTAIR_FORK_EPOCH:
@ -62,12 +64,29 @@ Note that for the pure EIP-4844 networks, we don't apply `upgrade_to_eip4844` si
### Upgrading the state ### Upgrading the state
Since the `eip4844.BeaconState` format is equal to the `bellatrix.BeaconState` format, we only have to update `BeaconState.fork`. Since the `eip4844.BeaconState` format is equal to the `capella.BeaconState` format, we only have to update `BeaconState.fork`.
```python ```python
def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState: def upgrade_to_eip4844(pre: capella.BeaconState) -> BeaconState:
# TODO: if Capella gets scheduled, add sync it with Capella.BeaconState epoch = capella.get_current_epoch(pre)
epoch = bellatrix.get_current_epoch(pre) latest_execution_payload_header = ExecutionPayloadHeader(
parent_hash=pre.latest_execution_payload_header.parent_hash,
fee_recipient=pre.latest_execution_payload_header.fee_recipient,
state_root=pre.latest_execution_payload_header.state_root,
receipts_root=pre.latest_execution_payload_header.receipts_root,
logs_bloom=pre.latest_execution_payload_header.logs_bloom,
prev_randao=pre.latest_execution_payload_header.prev_randao,
block_number=pre.latest_execution_payload_header.block_number,
gas_limit=pre.latest_execution_payload_header.gas_limit,
gas_used=pre.latest_execution_payload_header.gas_used,
timestamp=pre.latest_execution_payload_header.timestamp,
extra_data=pre.latest_execution_payload_header.extra_data,
base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas,
excess_data_gas=uint256(0), # [New in EIP-4844]
block_hash=pre.latest_execution_payload_header.block_hash,
transactions_root=pre.latest_execution_payload_header.transactions_root,
withdrawals_root=pre.latest_execution_payload_header.withdrawals_root,
)
post = BeaconState( post = BeaconState(
# Versioning # Versioning
genesis_time=pre.genesis_time, genesis_time=pre.genesis_time,
@ -108,7 +127,10 @@ def upgrade_to_eip4844(pre: bellatrix.BeaconState) -> BeaconState:
current_sync_committee=pre.current_sync_committee, current_sync_committee=pre.current_sync_committee,
next_sync_committee=pre.next_sync_committee, next_sync_committee=pre.next_sync_committee,
# Execution-layer # Execution-layer
latest_execution_payload_header=pre.latest_execution_payload_header, latest_execution_payload_header=latest_execution_payload_header, # [Modified in EIP4844]
# Withdrawals
next_withdrawal_index=pre.next_withdrawal_index,
next_withdrawal_validator_index=pre.next_withdrawal_validator_index,
) )
return post return post

View File

@ -17,12 +17,14 @@ The specification of these changes continues in the same format as the network s
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
- [Topics and messages](#topics-and-messages) - [Topics and messages](#topics-and-messages)
- [Global topics](#global-topics) - [Global topics](#global-topics)
- [`beacon_block`](#beacon_block)
- [`beacon_block_and_blobs_sidecar`](#beacon_block_and_blobs_sidecar) - [`beacon_block_and_blobs_sidecar`](#beacon_block_and_blobs_sidecar)
- [Transitioning the gossip](#transitioning-the-gossip) - [Transitioning the gossip](#transitioning-the-gossip)
- [The Req/Resp domain](#the-reqresp-domain) - [The Req/Resp domain](#the-reqresp-domain)
- [Messages](#messages) - [Messages](#messages)
- [BeaconBlocksByRange v2](#beaconblocksbyrange-v2) - [BeaconBlocksByRange v2](#beaconblocksbyrange-v2)
- [BeaconBlocksByRoot v2](#beaconblocksbyroot-v2) - [BeaconBlocksByRoot v2](#beaconblocksbyroot-v2)
- [BeaconBlockAndBlobsSidecarByRoot v1](#beaconblockandblobssidecarbyroot-v1)
- [BlobsSidecarsByRange v1](#blobssidecarsbyrange-v1) - [BlobsSidecarsByRange v1](#blobssidecarsbyrange-v1)
- [Design decision rationale](#design-decision-rationale) - [Design decision rationale](#design-decision-rationale)
- [Why are blobs relayed as a sidecar, separate from beacon blocks?](#why-are-blobs-relayed-as-a-sidecar-separate-from-beacon-blocks) - [Why are blobs relayed as a sidecar, separate from beacon blocks?](#why-are-blobs-relayed-as-a-sidecar-separate-from-beacon-blocks)
@ -64,9 +66,9 @@ Some gossip meshes are upgraded in the fork of EIP4844 to support upgraded types
### Topics and messages ### Topics and messages
Topics follow the same specification as in prior upgrades. Topics follow the same specification as in prior upgrades.
All topics remain stable except the beacon block topic which is updated with the modified type. The `beacon_block` topic is deprecated and replaced by the `beacon_block_and_blobs_sidecar` topic. All other topics remain stable.
The specification around the creation, validation, and dissemination of messages has not changed from the Bellatrix document unless explicitly noted here. The specification around the creation, validation, and dissemination of messages has not changed from the Capella document unless explicitly noted here.
The derivation of the `message-id` remains stable. The derivation of the `message-id` remains stable.
@ -81,11 +83,19 @@ The new topics along with the type of the `data` field of a gossipsub message ar
EIP4844 introduces a new global topic for beacon block and blobs-sidecars. EIP4844 introduces a new global topic for beacon block and blobs-sidecars.
##### `beacon_block`
This topic is deprecated and clients **MUST NOT** expose in their topic set to any peer. Implementers do not need to do
anything beyond simply skip implementation, and it is explicitly called out as it is a departure from previous versioning
of this topic.
Refer to [the section below](#transitioning-the-gossip) for details on how to transition the gossip.
##### `beacon_block_and_blobs_sidecar` ##### `beacon_block_and_blobs_sidecar`
This topic is used to propagate new signed and coupled beacon blocks and blobs sidecars to all nodes on the networks. This topic is used to propagate new signed and coupled beacon blocks and blobs sidecars to all nodes on the networks.
In addition to the gossip validations for the `beacon_block` topic from prior specifications, the following validations MUST pass before forwarding the `signed_beacon_block_and_blobs_sidecar` on the network. In addition to the gossip validations for the `beacon_block` topic from prior specifications, the following validations MUST pass before forwarding the `signed_beacon_block_and_blobs_sidecar` on the network.
Alias `signed_beacon_block = signed_beacon_block_and_blobs_sidecar.beacon_block`, `block = signed_beacon_block.message`, `execution_payload = block.body.execution_payload`. Alias `signed_beacon_block = signed_beacon_block_and_blobs_sidecar.beacon_block`, `block = signed_beacon_block.message`, `execution_payload = block.body.execution_payload`.
- _[REJECT]_ The KZG commitments of the blobs are all correctly encoded compressed BLS G1 Points. - _[REJECT]_ The KZG commitments of the blobs are all correctly encoded compressed BLS G1 Points.
-- i.e. `all(bls.KeyValidate(commitment) for commitment in block.body.blob_kzg_commitments)` -- i.e. `all(bls.KeyValidate(commitment) for commitment in block.body.blob_kzg_commitments)`
@ -96,8 +106,8 @@ Alias `sidecar = signed_beacon_block_and_blobs_sidecar.blobs_sidecar`.
- _[IGNORE]_ the `sidecar.beacon_block_slot` is for the current slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. `sidecar.beacon_block_slot == block.slot`. - _[IGNORE]_ the `sidecar.beacon_block_slot` is for the current slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. `sidecar.beacon_block_slot == block.slot`.
- _[REJECT]_ the `sidecar.blobs` are all well formatted, i.e. the `BLSFieldElement` in valid range (`x < BLS_MODULUS`). - _[REJECT]_ the `sidecar.blobs` are all well formatted, i.e. the `BLSFieldElement` in valid range (`x < BLS_MODULUS`).
- _[REJECT]_ The KZG proof is a correctly encoded compressed BLS G1 Point -- i.e. `bls.KeyValidate(blobs_sidecar.kzg_aggregated_proof)` - _[REJECT]_ The KZG proof is a correctly encoded compressed BLS G1 Point -- i.e. `bls.KeyValidate(blobs_sidecar.kzg_aggregated_proof)`
- _[REJECT]_ The KZG commitments in the block are valid against the provided blobs sidecar.
Once the sidecar and beacon block are received together, `validate_blobs_sidecar` can unlock the data-availability fork-choice dependency. -- i.e. `validate_blobs_sidecar(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments, sidecar)`
### Transitioning the gossip ### Transitioning the gossip
@ -123,13 +133,15 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
| `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` | | `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` |
| `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` | | `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` |
| `BELLATRIX_FORK_VERSION` | `bellatrix.SignedBeaconBlock` | | `BELLATRIX_FORK_VERSION` | `bellatrix.SignedBeaconBlock` |
| `CAPELLA_FORK_VERSION` | `capella.SignedBeaconBlock` |
| `EIP4844_FORK_VERSION` | `eip4844.SignedBeaconBlock` | | `EIP4844_FORK_VERSION` | `eip4844.SignedBeaconBlock` |
#### BeaconBlocksByRoot v2 #### BeaconBlocksByRoot v2
**Protocol ID:** `/eth2/beacon_chain/req/beacon_blocks_by_root/2/` **Protocol ID:** `/eth2/beacon_chain/req/beacon_blocks_by_root/2/`
The EIP-4844 fork-digest is introduced to the `context` enum to specify EIP-4844 beacon block type. After `EIP4844_FORK_EPOCH`, `BeaconBlocksByRootV2` is replaced by `BeaconBlockAndBlobsSidecarByRootV1`
clients MUST support requesting blocks by root for pre-fork-epoch blocks.
Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
@ -140,7 +152,43 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
| `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` | | `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` |
| `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` | | `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` |
| `BELLATRIX_FORK_VERSION` | `bellatrix.SignedBeaconBlock` | | `BELLATRIX_FORK_VERSION` | `bellatrix.SignedBeaconBlock` |
| `EIP4844_FORK_VERSION` | `eip4844.SignedBeaconBlock` | | `CAPELLA_FORK_VERSION` | `capella.SignedBeaconBlock` |
#### BeaconBlockAndBlobsSidecarByRoot v1
**Protocol ID:** `/eth2/beacon_chain/req/beacon_block_and_blobs_sidecar_by_root/1/`
Request Content:
```
(
List[Root, MAX_REQUEST_BLOCKS]
)
```
Response Content:
```
(
List[SignedBeaconBlockAndBlobsSidecar, MAX_REQUEST_BLOCKS]
)
```
Requests blocks by block root (= `hash_tree_root(SignedBeaconBlockAndBlobsSidecar.beacon_block.message)`).
The response is a list of `SignedBeaconBlockAndBlobsSidecar` whose length is less than or equal to the number of requests.
It may be less in the case that the responding peer is missing blocks and sidecars.
No more than `MAX_REQUEST_BLOCKS` may be requested at a time.
`BeaconBlockAndBlobsSidecarByRoot` is primarily used to recover recent blocks and sidecars (e.g. when receiving a block or attestation whose parent is unknown).
The response MUST consist of zero or more `response_chunk`.
Each _successful_ `response_chunk` MUST contain a single `SignedBeaconBlockAndBlobsSidecar` payload.
Clients MUST support requesting blocks and sidecars since the latest finalized epoch.
Clients MUST respond with at least one block and sidecar, if they have it.
Clients MAY limit the number of blocks and sidecars in the response.
#### BlobsSidecarsByRange v1 #### BlobsSidecarsByRange v1

View File

@ -32,6 +32,7 @@
- [KZG](#kzg) - [KZG](#kzg)
- [`blob_to_kzg_commitment`](#blob_to_kzg_commitment) - [`blob_to_kzg_commitment`](#blob_to_kzg_commitment)
- [`verify_kzg_proof`](#verify_kzg_proof) - [`verify_kzg_proof`](#verify_kzg_proof)
- [`verify_kzg_proof_impl`](#verify_kzg_proof_impl)
- [`compute_kzg_proof`](#compute_kzg_proof) - [`compute_kzg_proof`](#compute_kzg_proof)
- [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment) - [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment)
- [`compute_aggregate_kzg_proof`](#compute_aggregate_kzg_proof) - [`compute_aggregate_kzg_proof`](#compute_aggregate_kzg_proof)
@ -45,6 +46,8 @@
This document specifies basic polynomial operations and KZG polynomial commitment operations as they are needed for the EIP-4844 specification. The implementations are not optimized for performance, but readability. All practical implementations should optimize the polynomial operations. This document specifies basic polynomial operations and KZG polynomial commitment operations as they are needed for the EIP-4844 specification. The implementations are not optimized for performance, but readability. All practical implementations should optimize the polynomial operations.
Functions flagged as "Public method" MUST be provided by the underlying KZG library as public functions. All other functions are private functions used internally by the KZG library.
## Custom types ## Custom types
| Name | SSZ equivalent | Description | | Name | SSZ equivalent | Description |
@ -276,7 +279,7 @@ def evaluate_polynomial_in_evaluation_form(polynomial: Polynomial,
result = 0 result = 0
for i in range(width): for i in range(width):
result += div(int(polynomial[i]) * int(roots_of_unity_brp[i]), (int(z) - roots_of_unity_brp[i])) result += div(int(polynomial[i]) * int(roots_of_unity_brp[i]), (int(z) - int(roots_of_unity_brp[i])))
result = result * (pow(z, width, BLS_MODULUS) - 1) * inverse_width % BLS_MODULUS result = result * (pow(z, width, BLS_MODULUS) - 1) * inverse_width % BLS_MODULUS
return result return result
``` ```
@ -289,6 +292,9 @@ KZG core functions. These are also defined in EIP-4844 execution specs.
```python ```python
def blob_to_kzg_commitment(blob: Blob) -> KZGCommitment: def blob_to_kzg_commitment(blob: Blob) -> KZGCommitment:
"""
Public method.
"""
return g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), blob_to_polynomial(blob)) return g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), blob_to_polynomial(blob))
``` ```
@ -296,11 +302,27 @@ def blob_to_kzg_commitment(blob: Blob) -> KZGCommitment:
```python ```python
def verify_kzg_proof(polynomial_kzg: KZGCommitment, def verify_kzg_proof(polynomial_kzg: KZGCommitment,
z: BLSFieldElement, z: Bytes32,
y: BLSFieldElement, y: Bytes32,
kzg_proof: KZGProof) -> bool: kzg_proof: KZGProof) -> bool:
""" """
Verify KZG proof that ``p(z) == y`` where ``p(z)`` is the polynomial represented by ``polynomial_kzg``. Verify KZG proof that ``p(z) == y`` where ``p(z)`` is the polynomial represented by ``polynomial_kzg``.
Receives inputs as bytes.
Public method.
"""
return verify_kzg_proof_impl(polynomial_kzg, bytes_to_bls_field(z), bytes_to_bls_field(y), kzg_proof)
```
#### `verify_kzg_proof_impl`
```python
def verify_kzg_proof_impl(polynomial_kzg: KZGCommitment,
z: BLSFieldElement,
y: BLSFieldElement,
kzg_proof: KZGProof) -> bool:
"""
Verify KZG proof that ``p(z) == y`` where ``p(z)`` is the polynomial represented by ``polynomial_kzg``.
""" """
# Verify: P - y = Q * (X - z) # Verify: P - y = Q * (X - z)
X_minus_z = bls.add(bls.bytes96_to_G2(KZG_SETUP_G2[1]), bls.multiply(bls.G2, BLS_MODULUS - z)) X_minus_z = bls.add(bls.bytes96_to_G2(KZG_SETUP_G2[1]), bls.multiply(bls.G2, BLS_MODULUS - z))
@ -367,6 +389,9 @@ def compute_aggregated_poly_and_commitment(
```python ```python
def compute_aggregate_kzg_proof(blobs: Sequence[Blob]) -> KZGProof: def compute_aggregate_kzg_proof(blobs: Sequence[Blob]) -> KZGProof:
"""
Public method.
"""
commitments = [blob_to_kzg_commitment(blob) for blob in blobs] commitments = [blob_to_kzg_commitment(blob) for blob in blobs]
aggregated_poly, aggregated_poly_commitment, evaluation_challenge = compute_aggregated_poly_and_commitment( aggregated_poly, aggregated_poly_commitment, evaluation_challenge = compute_aggregated_poly_and_commitment(
blobs, blobs,
@ -381,6 +406,9 @@ def compute_aggregate_kzg_proof(blobs: Sequence[Blob]) -> KZGProof:
def verify_aggregate_kzg_proof(blobs: Sequence[Blob], def verify_aggregate_kzg_proof(blobs: Sequence[Blob],
expected_kzg_commitments: Sequence[KZGCommitment], expected_kzg_commitments: Sequence[KZGCommitment],
kzg_aggregated_proof: KZGCommitment) -> bool: kzg_aggregated_proof: KZGCommitment) -> bool:
"""
Public method.
"""
aggregated_poly, aggregated_poly_commitment, evaluation_challenge = compute_aggregated_poly_and_commitment( aggregated_poly, aggregated_poly_commitment, evaluation_challenge = compute_aggregated_poly_and_commitment(
blobs, blobs,
expected_kzg_commitments, expected_kzg_commitments,
@ -390,5 +418,5 @@ def verify_aggregate_kzg_proof(blobs: Sequence[Blob],
y = evaluate_polynomial_in_evaluation_form(aggregated_poly, evaluation_challenge) y = evaluate_polynomial_in_evaluation_form(aggregated_poly, evaluation_challenge)
# Verify aggregated proof # Verify aggregated proof
return verify_kzg_proof(aggregated_poly_commitment, evaluation_challenge, y, kzg_aggregated_proof) return verify_kzg_proof_impl(aggregated_poly_commitment, evaluation_challenge, y, kzg_aggregated_proof)
``` ```

View File

@ -29,7 +29,7 @@ This document represents the changes to be made in the code of an "honest valida
## Prerequisites ## Prerequisites
This document is an extension of the [Bellatrix -- Honest Validator](../bellatrix/validator.md) guide. This document is an extension of the [Capella -- Honest Validator](../capella/validator.md) guide.
All behaviors and definitions defined in this document, and documents it extends, carry over unless explicitly noted or overridden. 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 EIP4844](./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 EIP4844](./beacon-chain.md) are requisite for this document and used throughout.
@ -60,7 +60,7 @@ Namely, the blob handling and the addition of `SignedBeaconBlockAndBlobsSidecar`
##### Blob KZG commitments ##### Blob KZG commitments
1. After retrieving the execution payload from the execution engine as specified in Bellatrix, 1. After retrieving the execution payload from the execution engine as specified in Capella,
use the `payload_id` to retrieve `blobs` and `blob_kzg_commitments` via `get_blobs_and_kzg_commitments(payload_id)`. use the `payload_id` to retrieve `blobs` and `blob_kzg_commitments` via `get_blobs_and_kzg_commitments(payload_id)`.
2. Validate `blobs` and `blob_kzg_commitments`: 2. Validate `blobs` and `blob_kzg_commitments`:

View File

@ -1 +1 @@
1.3.0-alpha.0 1.3.0-alpha.1

View File

@ -4,7 +4,6 @@ import time
import shutil import shutil
import argparse import argparse
from pathlib import Path from pathlib import Path
from filelock import FileLock
import sys import sys
import json import json
from typing import Iterable, AnyStr, Any, Callable from typing import Iterable, AnyStr, Any, Callable
@ -13,6 +12,7 @@ from ruamel.yaml import (
YAML, YAML,
) )
from filelock import FileLock
from snappy import compress from snappy import compress
from eth2spec.test import context from eth2spec.test import context
@ -141,6 +141,10 @@ def run_generator(generator_name, test_providers: Iterable[TestProvider]):
tprov.prepare() tprov.prepare()
for test_case in tprov.make_cases(): for test_case in tprov.make_cases():
# If preset list is assigned, filter by presets.
if len(presets) != 0 and test_case.preset_name not in presets:
continue
case_dir = ( case_dir = (
Path(output_dir) / Path(test_case.preset_name) / Path(test_case.fork_name) Path(output_dir) / Path(test_case.preset_name) / Path(test_case.fork_name)
/ Path(test_case.runner_name) / Path(test_case.handler_name) / Path(test_case.runner_name) / Path(test_case.handler_name)
@ -179,7 +183,16 @@ def run_generator(generator_name, test_providers: Iterable[TestProvider]):
try: try:
fn(case_dir) fn(case_dir)
except IOError as e: except IOError as e:
sys.exit(f'Error when dumping test "{case_dir}", part "{name}", kind "{out_kind}": {e}') error_message = (
f'[Error] error when dumping test "{case_dir}", part "{name}", kind "{out_kind}": {e}'
)
# Write to error log file
with log_file.open("a+") as f:
f.write(error_message)
traceback.print_exc(file=f)
f.write('\n')
sys.exit(error_message)
meta = dict() meta = dict()
@ -210,13 +223,13 @@ def run_generator(generator_name, test_providers: Iterable[TestProvider]):
if not written_part: if not written_part:
print(f"test case {case_dir} did not produce any test case parts") print(f"test case {case_dir} did not produce any test case parts")
except Exception as e: except Exception as e:
print(f"ERROR: failed to generate vector(s) for test {case_dir}: {e}") error_message = f"[ERROR] failed to generate vector(s) for test {case_dir}: {e}"
traceback.print_exc() # Write to error log file
# Write to log file
with log_file.open("a+") as f: with log_file.open("a+") as f:
f.write(f"ERROR: failed to generate vector(s) for test {case_dir}: {e}") f.write(error_message)
traceback.print_exc(file=f) traceback.print_exc(file=f)
f.write('\n') f.write('\n')
traceback.print_exc()
else: else:
# If no written_part, the only file was incomplete_tag_file. Clear the existing case_dir folder. # If no written_part, the only file was incomplete_tag_file. Clear the existing case_dir folder.
if not written_part: if not written_part:

View File

@ -49,7 +49,7 @@ def generate_from_tests(runner_name: str, handler_name: str, src: Any,
preset_name=preset_name, preset_name=preset_name,
runner_name=runner_name, runner_name=runner_name,
handler_name=handler_name, handler_name=handler_name,
suite_name='pyspec_tests', suite_name=getattr(tfn, 'suite_name', 'pyspec_tests'),
case_name=case_name, case_name=case_name,
# TODO: with_all_phases and other per-phase tooling, should be replaced with per-fork equivalent. # TODO: with_all_phases and other per-phase tooling, should be replaced with per-fork equivalent.
case_fn=lambda: tfn(generator_mode=True, phase=phase, preset=preset_name, bls_active=bls_active) case_fn=lambda: tfn(generator_mode=True, phase=phase, preset=preset_name, bls_active=bls_active)

View File

@ -1,14 +1,17 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
spec_state_test, spec_state_test,
with_altair_and_later, with_altair_and_later,
with_test_suite_name,
) )
@with_test_suite_name("BeaconState")
@with_altair_and_later @with_altair_and_later
@spec_state_test @spec_state_test
def test_current_sync_committee_merkle_proof(spec, state): def test_current_sync_committee_merkle_proof(spec, state):
yield "state", state yield "object", state
current_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX) current_sync_committee_branch = \
spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX)
yield "proof", { yield "proof", {
"leaf": "0x" + state.current_sync_committee.hash_tree_root().hex(), "leaf": "0x" + state.current_sync_committee.hash_tree_root().hex(),
"leaf_index": spec.CURRENT_SYNC_COMMITTEE_INDEX, "leaf_index": spec.CURRENT_SYNC_COMMITTEE_INDEX,
@ -23,11 +26,13 @@ def test_current_sync_committee_merkle_proof(spec, state):
) )
@with_test_suite_name("BeaconState")
@with_altair_and_later @with_altair_and_later
@spec_state_test @spec_state_test
def test_next_sync_committee_merkle_proof(spec, state): def test_next_sync_committee_merkle_proof(spec, state):
yield "state", state yield "object", state
next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX) next_sync_committee_branch = \
spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX)
yield "proof", { yield "proof", {
"leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(), "leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(),
"leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX, "leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX,
@ -42,11 +47,13 @@ def test_next_sync_committee_merkle_proof(spec, state):
) )
@with_test_suite_name("BeaconState")
@with_altair_and_later @with_altair_and_later
@spec_state_test @spec_state_test
def test_finality_root_merkle_proof(spec, state): def test_finality_root_merkle_proof(spec, state):
yield "state", state yield "object", state
finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX) finality_branch = \
spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX)
yield "proof", { yield "proof", {
"leaf": "0x" + state.finalized_checkpoint.root.hex(), "leaf": "0x" + state.finalized_checkpoint.root.hex(),
"leaf_index": spec.FINALIZED_ROOT_INDEX, "leaf_index": spec.FINALIZED_ROOT_INDEX,

View File

@ -1,7 +1,8 @@
from eth2spec.test.helpers.constants import CAPELLA
from eth2spec.test.helpers.keys import pubkeys from eth2spec.test.helpers.keys import pubkeys
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_capella_and_later, always_bls from eth2spec.test.context import spec_state_test, expect_assertion_error, with_phases, always_bls
def run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=True): def run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=True):
@ -37,14 +38,14 @@ def run_bls_to_execution_change_processing(spec, state, signed_address_change, v
yield 'post', state yield 'post', state
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success(spec, state): def test_success(spec, state):
signed_address_change = get_signed_address_change(spec, state) signed_address_change = get_signed_address_change(spec, state)
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change) yield from run_bls_to_execution_change_processing(spec, state, signed_address_change)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_not_activated(spec, state): def test_success_not_activated(spec, state):
validator_index = 3 validator_index = 3
@ -62,7 +63,7 @@ def test_success_not_activated(spec, state):
assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state)) assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_in_activation_queue(spec, state): def test_success_in_activation_queue(spec, state):
validator_index = 3 validator_index = 3
@ -80,7 +81,7 @@ def test_success_in_activation_queue(spec, state):
assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state)) assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_in_exit_queue(spec, state): def test_success_in_exit_queue(spec, state):
validator_index = 3 validator_index = 3
@ -93,7 +94,7 @@ def test_success_in_exit_queue(spec, state):
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change) yield from run_bls_to_execution_change_processing(spec, state, signed_address_change)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_exited(spec, state): def test_success_exited(spec, state):
validator_index = 4 validator_index = 4
@ -110,7 +111,7 @@ def test_success_exited(spec, state):
assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state)) assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_withdrawable(spec, state): def test_success_withdrawable(spec, state):
validator_index = 4 validator_index = 4
@ -128,7 +129,7 @@ def test_success_withdrawable(spec, state):
assert spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state)) assert spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_val_index_out_of_range(spec, state): def test_fail_val_index_out_of_range(spec, state):
# Create for one validator beyond the validator list length # Create for one validator beyond the validator list length
@ -137,7 +138,7 @@ def test_fail_val_index_out_of_range(spec, state):
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False) yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_already_0x01(spec, state): def test_fail_already_0x01(spec, state):
# Create for one validator beyond the validator list length # Create for one validator beyond the validator list length
@ -149,7 +150,7 @@ def test_fail_already_0x01(spec, state):
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False) yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_incorrect_from_bls_pubkey(spec, state): def test_fail_incorrect_from_bls_pubkey(spec, state):
# Create for one validator beyond the validator list length # Create for one validator beyond the validator list length
@ -163,7 +164,7 @@ def test_fail_incorrect_from_bls_pubkey(spec, state):
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False) yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
@always_bls @always_bls
def test_fail_bad_signature(spec, state): def test_fail_bad_signature(spec, state):

View File

@ -1,7 +1,8 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
spec_state_test, spec_state_test,
with_capella_and_later, with_phases,
) )
from eth2spec.test.helpers.constants import CAPELLA
from eth2spec.test.helpers.state import next_epoch_via_block from eth2spec.test.helpers.state import next_epoch_via_block
from eth2spec.test.helpers.deposits import ( from eth2spec.test.helpers.deposits import (
prepare_state_and_deposit, prepare_state_and_deposit,
@ -10,7 +11,7 @@ from eth2spec.test.helpers.deposits import (
from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_top_up_to_withdrawn_validator(spec, state): def test_success_top_up_to_withdrawn_validator(spec, state):
validator_index = 0 validator_index = 0

View File

@ -3,10 +3,10 @@ import random
from eth2spec.test.context import ( from eth2spec.test.context import (
spec_state_test, spec_state_test,
expect_assertion_error, expect_assertion_error,
with_capella_and_later,
with_presets, with_presets,
with_phases,
) )
from eth2spec.test.helpers.constants import MINIMAL from eth2spec.test.helpers.constants import MINIMAL, CAPELLA
from eth2spec.test.helpers.execution_payload import ( from eth2spec.test.helpers.execution_payload import (
build_empty_execution_payload, build_empty_execution_payload,
) )
@ -87,7 +87,7 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with
return expected_withdrawals return expected_withdrawals
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_zero_expected_withdrawals(spec, state): def test_success_zero_expected_withdrawals(spec, state):
assert len(spec.get_expected_withdrawals(state)) == 0 assert len(spec.get_expected_withdrawals(state)) == 0
@ -98,7 +98,7 @@ def test_success_zero_expected_withdrawals(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_full_withdrawal(spec, state): def test_success_one_full_withdrawal(spec, state):
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
@ -115,7 +115,7 @@ def test_success_one_full_withdrawal(spec, state):
partial_withdrawals_indices=partial_withdrawals_indices) partial_withdrawals_indices=partial_withdrawals_indices)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_partial_withdrawal(spec, state): def test_success_one_partial_withdrawal(spec, state):
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
@ -135,7 +135,7 @@ def test_success_one_partial_withdrawal(spec, state):
) )
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_max_per_slot(spec, state): def test_success_max_per_slot(spec, state):
num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 2 num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 2
@ -153,7 +153,7 @@ def test_success_max_per_slot(spec, state):
partial_withdrawals_indices=partial_withdrawals_indices) partial_withdrawals_indices=partial_withdrawals_indices)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_all_fully_withdrawable(spec, state): def test_success_all_fully_withdrawable(spec, state):
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
@ -168,7 +168,7 @@ def test_success_all_fully_withdrawable(spec, state):
partial_withdrawals_indices=partial_withdrawals_indices) partial_withdrawals_indices=partial_withdrawals_indices)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_all_partially_withdrawable(spec, state): def test_success_all_partially_withdrawable(spec, state):
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
@ -187,7 +187,7 @@ def test_success_all_partially_withdrawable(spec, state):
# Failure cases in which the number of withdrawals in the execution_payload is incorrect # Failure cases in which the number of withdrawals in the execution_payload is incorrect
# #
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_non_withdrawable_non_empty_withdrawals(spec, state): def test_fail_non_withdrawable_non_empty_withdrawals(spec, state):
next_slot(spec, state) next_slot(spec, state)
@ -203,7 +203,7 @@ def test_fail_non_withdrawable_non_empty_withdrawals(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state): def test_fail_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
@ -215,7 +215,7 @@ def test_fail_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, state): def test_fail_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1)
@ -227,7 +227,7 @@ def test_fail_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, stat
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, state): def test_fail_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=2) prepare_expected_withdrawals(spec, state, num_full_withdrawals=2)
@ -239,7 +239,7 @@ def test_fail_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, st
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, state): def test_fail_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=2) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=2)
@ -251,7 +251,7 @@ def test_fail_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec,
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, state): def test_fail_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD) prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD)
@ -263,7 +263,7 @@ def test_fail_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, st
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, state): def test_fail_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD)
@ -275,7 +275,7 @@ def test_fail_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec,
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state): def test_fail_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
@ -287,7 +287,7 @@ def test_fail_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state): def test_fail_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
@ -299,7 +299,7 @@ def test_fail_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state): def test_fail_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4, prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4,
@ -316,7 +316,7 @@ def test_fail_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, sta
# Failure cases in which the withdrawals in the execution_payload are incorrect # Failure cases in which the withdrawals in the execution_payload are incorrect
# #
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_incorrect_withdrawal_index(spec, state): def test_fail_incorrect_withdrawal_index(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
@ -328,7 +328,7 @@ def test_fail_incorrect_withdrawal_index(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_incorrect_address_full(spec, state): def test_fail_incorrect_address_full(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
@ -340,7 +340,7 @@ def test_fail_incorrect_address_full(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_incorrect_address_partial(spec, state): def test_fail_incorrect_address_partial(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1)
@ -352,7 +352,7 @@ def test_fail_incorrect_address_partial(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_incorrect_amount_full(spec, state): def test_fail_incorrect_amount_full(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
@ -364,7 +364,7 @@ def test_fail_incorrect_amount_full(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_incorrect_amount_partial(spec, state): def test_fail_incorrect_amount_partial(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
@ -376,7 +376,7 @@ def test_fail_incorrect_amount_partial(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_one_of_many_incorrectly_full(spec, state): def test_fail_one_of_many_incorrectly_full(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
@ -394,7 +394,7 @@ def test_fail_one_of_many_incorrectly_full(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_one_of_many_incorrectly_partial(spec, state): def test_fail_one_of_many_incorrectly_partial(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
@ -412,7 +412,7 @@ def test_fail_one_of_many_incorrectly_partial(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_many_incorrectly_full(spec, state): def test_fail_many_incorrectly_full(spec, state):
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
@ -430,7 +430,7 @@ def test_fail_many_incorrectly_full(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_fail_many_incorrectly_partial(spec, state): def test_fail_many_incorrectly_partial(spec, state):
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
@ -452,7 +452,7 @@ def test_fail_many_incorrectly_partial(spec, state):
# More full withdrawal cases # More full withdrawal cases
# #
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_withdrawable_epoch_but_0_balance(spec, state): def test_withdrawable_epoch_but_0_balance(spec, state):
current_epoch = spec.get_current_epoch(state) current_epoch = spec.get_current_epoch(state)
@ -466,7 +466,7 @@ def test_withdrawable_epoch_but_0_balance(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state): def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state):
current_epoch = spec.get_current_epoch(state) current_epoch = spec.get_current_epoch(state)
@ -480,7 +480,7 @@ def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state): def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state):
current_epoch = spec.get_current_epoch(state) current_epoch = spec.get_current_epoch(state)
@ -494,7 +494,7 @@ def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state)
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_no_withdrawals_but_some_next_epoch(spec, state): def test_no_withdrawals_but_some_next_epoch(spec, state):
current_epoch = spec.get_current_epoch(state) current_epoch = spec.get_current_epoch(state)
@ -508,7 +508,7 @@ def test_no_withdrawals_but_some_next_epoch(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_all_withdrawal(spec, state): def test_all_withdrawal(spec, state):
# Make all validators withdrawable # Make all validators withdrawable
@ -544,25 +544,25 @@ def run_random_full_withdrawals_test(spec, state, rng):
yield from run_withdrawals_processing(spec, state, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_full_withdrawals_0(spec, state): def test_random_full_withdrawals_0(spec, state):
yield from run_random_full_withdrawals_test(spec, state, random.Random(444)) yield from run_random_full_withdrawals_test(spec, state, random.Random(444))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_full_withdrawals_1(spec, state): def test_random_full_withdrawals_1(spec, state):
yield from run_random_full_withdrawals_test(spec, state, random.Random(420)) yield from run_random_full_withdrawals_test(spec, state, random.Random(420))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_full_withdrawals_2(spec, state): def test_random_full_withdrawals_2(spec, state):
yield from run_random_full_withdrawals_test(spec, state, random.Random(200)) yield from run_random_full_withdrawals_test(spec, state, random.Random(200))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_full_withdrawals_3(spec, state): def test_random_full_withdrawals_3(spec, state):
yield from run_random_full_withdrawals_test(spec, state, random.Random(2000000)) yield from run_random_full_withdrawals_test(spec, state, random.Random(2000000))
@ -572,7 +572,7 @@ def test_random_full_withdrawals_3(spec, state):
# More partial withdrawal cases # More partial withdrawal cases
# #
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_no_max_effective_balance(spec, state): def test_success_no_max_effective_balance(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -588,7 +588,7 @@ def test_success_no_max_effective_balance(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_no_excess_balance(spec, state): def test_success_no_excess_balance(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -604,7 +604,7 @@ def test_success_no_excess_balance(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_excess_balance_but_no_max_effective_balance(spec, state): def test_success_excess_balance_but_no_max_effective_balance(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -621,7 +621,7 @@ def test_success_excess_balance_but_no_max_effective_balance(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_partial_withdrawable_not_yet_active(spec, state): def test_success_one_partial_withdrawable_not_yet_active(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -635,7 +635,7 @@ def test_success_one_partial_withdrawable_not_yet_active(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_partial_withdrawable_in_exit_queue(spec, state): def test_success_one_partial_withdrawable_in_exit_queue(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -650,7 +650,7 @@ def test_success_one_partial_withdrawable_in_exit_queue(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_partial_withdrawable_exited(spec, state): def test_success_one_partial_withdrawable_exited(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -664,7 +664,7 @@ def test_success_one_partial_withdrawable_exited(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_partial_withdrawable_active_and_slashed(spec, state): def test_success_one_partial_withdrawable_active_and_slashed(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -678,7 +678,7 @@ def test_success_one_partial_withdrawable_active_and_slashed(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_one_partial_withdrawable_exited_and_slashed(spec, state): def test_success_one_partial_withdrawable_exited_and_slashed(spec, state):
validator_index = len(state.validators) // 2 validator_index = len(state.validators) // 2
@ -693,7 +693,7 @@ def test_success_one_partial_withdrawable_exited_and_slashed(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_two_partial_withdrawable(spec, state): def test_success_two_partial_withdrawable(spec, state):
set_validator_partially_withdrawable(spec, state, 0) set_validator_partially_withdrawable(spec, state, 0)
@ -704,7 +704,7 @@ def test_success_two_partial_withdrawable(spec, state):
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=2) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=2)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_success_max_partial_withdrawable(spec, state): def test_success_max_partial_withdrawable(spec, state):
# Sanity check that this test works for this state # Sanity check that this test works for this state
@ -719,7 +719,7 @@ def test_success_max_partial_withdrawable(spec, state):
spec, state, execution_payload, num_expected_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD) spec, state, execution_payload, num_expected_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD)
@with_capella_and_later @with_phases([CAPELLA])
@with_presets([MINIMAL], reason="not enough validators with mainnet config") @with_presets([MINIMAL], reason="not enough validators with mainnet config")
@spec_state_test @spec_state_test
def test_success_max_plus_one_withdrawable(spec, state): def test_success_max_plus_one_withdrawable(spec, state):
@ -758,37 +758,37 @@ def run_random_partial_withdrawals_test(spec, state, rng):
yield from run_withdrawals_processing(spec, state, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload)
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_0(spec, state): def test_random_0(spec, state):
yield from run_random_partial_withdrawals_test(spec, state, random.Random(0)) yield from run_random_partial_withdrawals_test(spec, state, random.Random(0))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_partial_withdrawals_1(spec, state): def test_random_partial_withdrawals_1(spec, state):
yield from run_random_partial_withdrawals_test(spec, state, random.Random(1)) yield from run_random_partial_withdrawals_test(spec, state, random.Random(1))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_partial_withdrawals_2(spec, state): def test_random_partial_withdrawals_2(spec, state):
yield from run_random_partial_withdrawals_test(spec, state, random.Random(2)) yield from run_random_partial_withdrawals_test(spec, state, random.Random(2))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_partial_withdrawals_3(spec, state): def test_random_partial_withdrawals_3(spec, state):
yield from run_random_partial_withdrawals_test(spec, state, random.Random(3)) yield from run_random_partial_withdrawals_test(spec, state, random.Random(3))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_partial_withdrawals_4(spec, state): def test_random_partial_withdrawals_4(spec, state):
yield from run_random_partial_withdrawals_test(spec, state, random.Random(4)) yield from run_random_partial_withdrawals_test(spec, state, random.Random(4))
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_random_partial_withdrawals_5(spec, state): def test_random_partial_withdrawals_5(spec, state):
yield from run_random_partial_withdrawals_test(spec, state, random.Random(5)) yield from run_random_partial_withdrawals_test(spec, state, random.Random(5))

View File

@ -0,0 +1,84 @@
from random import Random
from eth2spec.test.context import (
with_phases,
with_custom_state,
with_presets,
spec_test, with_state,
low_balances, misc_balances, large_validator_set,
)
from eth2spec.test.utils import with_meta_tags
from eth2spec.test.helpers.constants import (
BELLATRIX, CAPELLA,
MINIMAL,
)
from eth2spec.test.helpers.capella.fork import (
CAPELLA_FORK_TEST_META_TAGS,
run_fork_test,
)
from eth2spec.test.helpers.random import randomize_state
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@spec_test
@with_state
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_0(spec, phases, state):
randomize_state(spec, state, rng=Random(1010))
yield from run_fork_test(phases[CAPELLA], state)
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@spec_test
@with_state
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_1(spec, phases, state):
randomize_state(spec, state, rng=Random(2020))
yield from run_fork_test(phases[CAPELLA], state)
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@spec_test
@with_state
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_2(spec, phases, state):
randomize_state(spec, state, rng=Random(3030))
yield from run_fork_test(phases[CAPELLA], state)
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@spec_test
@with_state
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_3(spec, phases, state):
randomize_state(spec, state, rng=Random(4040))
yield from run_fork_test(phases[CAPELLA], state)
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@spec_test
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_low_balances(spec, phases, state):
randomize_state(spec, state, rng=Random(5050))
yield from run_fork_test(phases[CAPELLA], state)
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@spec_test
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_misc_balances(spec, phases, state):
randomize_state(spec, state, rng=Random(6060))
yield from run_fork_test(phases[CAPELLA], state)
@with_phases(phases=[BELLATRIX], other_phases=[CAPELLA])
@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=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@with_meta_tags(CAPELLA_FORK_TEST_META_TAGS)
def test_capella_fork_random_large_validator_set(spec, phases, state):
randomize_state(spec, state, rng=Random(7070))
yield from run_fork_test(phases[CAPELLA], state)

View File

@ -1,7 +1,7 @@
from eth2spec.test.context import ( from eth2spec.test.context import (
with_capella_and_later, spec_state_test with_phases, spec_state_test
) )
from eth2spec.test.helpers.constants import CAPELLA
from eth2spec.test.helpers.state import ( from eth2spec.test.helpers.state import (
state_transition_and_sign_block, state_transition_and_sign_block,
) )
@ -21,9 +21,13 @@ from eth2spec.test.helpers.withdrawals import (
from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
@with_capella_and_later #
# BLSToExecutionChange
#
@with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_successful_bls_change(spec, state): def test_success_bls_change(spec, state):
index = 0 index = 0
signed_address_change = get_signed_address_change(spec, state, validator_index=index) signed_address_change = get_signed_address_change(spec, state, validator_index=index)
pre_credentials = state.validators[index].withdrawal_credentials pre_credentials = state.validators[index].withdrawal_credentials
@ -44,77 +48,9 @@ def test_successful_bls_change(spec, state):
assert post_credentials[12:] == signed_address_change.message.to_execution_address assert post_credentials[12:] == signed_address_change.message.to_execution_address
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_full_withdrawal_in_epoch_transition(spec, state): def test_success_exit_and_bls_change(spec, state):
index = 0
current_epoch = spec.get_current_epoch(state)
set_validator_fully_withdrawable(spec, state, index, current_epoch)
assert len(spec.get_expected_withdrawals(state)) == 1
yield 'pre', state
# trigger epoch transition
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
assert state.balances[index] == 0
assert len(spec.get_expected_withdrawals(state)) == 0
@with_capella_and_later
@spec_state_test
def test_partial_withdrawal_in_epoch_transition(spec, state):
index = state.next_withdrawal_index
set_validator_partially_withdrawable(spec, state, index, excess_balance=1000000000000)
pre_balance = state.balances[index]
assert len(spec.get_expected_withdrawals(state)) == 1
yield 'pre', state
# trigger epoch transition
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
assert state.balances[index] < pre_balance
# Potentially less than due to sync committee penalty
assert state.balances[index] <= spec.MAX_EFFECTIVE_BALANCE
assert len(spec.get_expected_withdrawals(state)) == 0
@with_capella_and_later
@spec_state_test
def test_many_partial_withdrawals_in_epoch_transition(spec, state):
assert len(state.validators) > spec.MAX_WITHDRAWALS_PER_PAYLOAD
for i in range(spec.MAX_WITHDRAWALS_PER_PAYLOAD + 1):
index = (i + state.next_withdrawal_index) % len(state.validators)
set_validator_partially_withdrawable(spec, state, index, excess_balance=1000000000000)
assert len(spec.get_expected_withdrawals(state)) == spec.MAX_WITHDRAWALS_PER_PAYLOAD
yield 'pre', state
# trigger epoch transition
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
assert len(spec.get_expected_withdrawals(state)) == 1
@with_capella_and_later
@spec_state_test
def test_exit_and_bls_change(spec, state):
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
@ -141,6 +77,121 @@ def test_exit_and_bls_change(spec, state):
assert spec.is_fully_withdrawable_validator(validator, balance, validator.withdrawable_epoch) assert spec.is_fully_withdrawable_validator(validator, balance, validator.withdrawable_epoch)
@with_phases([CAPELLA])
@spec_state_test
def test_invalid_duplicate_bls_changes_same_block(spec, state):
index = 0
signed_address_change = get_signed_address_change(spec, state, validator_index=index)
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
# Double BLSToExecutionChange of the same validator
for _ in range(2):
block.body.bls_to_execution_changes.append(signed_address_change)
signed_block = state_transition_and_sign_block(spec, state, block, expect_fail=True)
yield 'blocks', [signed_block]
yield 'post', None
@with_phases([CAPELLA])
@spec_state_test
def test_invalid_two_bls_changes_of_different_addresses_same_validator_same_block(spec, state):
index = 0
signed_address_change_1 = get_signed_address_change(spec, state, validator_index=index,
to_execution_address=b'\x12' * 20)
signed_address_change_2 = get_signed_address_change(spec, state, validator_index=index,
to_execution_address=b'\x34' * 20)
assert signed_address_change_1 != signed_address_change_2
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
block.body.bls_to_execution_changes.append(signed_address_change_1)
block.body.bls_to_execution_changes.append(signed_address_change_2)
signed_block = state_transition_and_sign_block(spec, state, block, expect_fail=True)
yield 'blocks', [signed_block]
yield 'post', None
#
# Withdrawals
#
@with_phases([CAPELLA])
@spec_state_test
def test_full_withdrawal_in_epoch_transition(spec, state):
index = 0
current_epoch = spec.get_current_epoch(state)
set_validator_fully_withdrawable(spec, state, index, current_epoch)
assert len(spec.get_expected_withdrawals(state)) == 1
yield 'pre', state
# trigger epoch transition
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
assert state.balances[index] == 0
assert len(spec.get_expected_withdrawals(state)) == 0
@with_phases([CAPELLA])
@spec_state_test
def test_partial_withdrawal_in_epoch_transition(spec, state):
index = state.next_withdrawal_index
set_validator_partially_withdrawable(spec, state, index, excess_balance=1000000000000)
pre_balance = state.balances[index]
assert len(spec.get_expected_withdrawals(state)) == 1
yield 'pre', state
# trigger epoch transition
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
assert state.balances[index] < pre_balance
# Potentially less than due to sync committee penalty
assert state.balances[index] <= spec.MAX_EFFECTIVE_BALANCE
assert len(spec.get_expected_withdrawals(state)) == 0
@with_phases([CAPELLA])
@spec_state_test
def test_many_partial_withdrawals_in_epoch_transition(spec, state):
assert len(state.validators) > spec.MAX_WITHDRAWALS_PER_PAYLOAD
for i in range(spec.MAX_WITHDRAWALS_PER_PAYLOAD + 1):
index = (i + state.next_withdrawal_index) % len(state.validators)
set_validator_partially_withdrawable(spec, state, index, excess_balance=1000000000000)
assert len(spec.get_expected_withdrawals(state)) == spec.MAX_WITHDRAWALS_PER_PAYLOAD
yield 'pre', state
# trigger epoch transition
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_block = state_transition_and_sign_block(spec, state, block)
yield 'blocks', [signed_block]
yield 'post', state
assert len(spec.get_expected_withdrawals(state)) == 1
def _perform_valid_withdrawal(spec, state): def _perform_valid_withdrawal(spec, state):
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4, spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4,
@ -170,7 +221,7 @@ def _perform_valid_withdrawal(spec, state):
return pre_state, signed_block_1, pre_next_withdrawal_index return pre_state, signed_block_1, pre_next_withdrawal_index
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_withdrawal_success_two_blocks(spec, state): def test_withdrawal_success_two_blocks(spec, state):
pre_state, signed_block_1, pre_next_withdrawal_index = _perform_valid_withdrawal(spec, state) pre_state, signed_block_1, pre_next_withdrawal_index = _perform_valid_withdrawal(spec, state)
@ -187,7 +238,7 @@ def test_withdrawal_success_two_blocks(spec, state):
yield 'post', state yield 'post', state
@with_capella_and_later @with_phases([CAPELLA])
@spec_state_test @spec_state_test
def test_withdrawal_fail_second_block_payload_isnt_compatible(spec, state): def test_withdrawal_fail_second_block_payload_isnt_compatible(spec, state):
_perform_valid_withdrawal(spec, state) _perform_valid_withdrawal(spec, state)

View File

@ -600,6 +600,13 @@ def only_generator(reason):
return _decorator return _decorator
def with_test_suite_name(suite_name: str):
def _decorator(inner):
inner.suite_name = suite_name
return inner
return _decorator
# #
# Fork transition state tests # Fork transition state tests
# #

View File

@ -0,0 +1,40 @@
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_eip4844_and_later
def run_bls_to_execution_change_processing_no_op(spec, state, signed_address_change, valid=True):
"""
Run ``process_bls_to_execution_change``, yielding:
- pre-state ('pre')
- address-change ('address_change')
- post-state ('post').
If ``valid == False``, run expecting ``AssertionError``
"""
pre_state = state.copy()
# yield pre-state
yield 'pre', state
yield 'address_change', signed_address_change
# If the address_change is invalid, processing is aborted, and there is no post-state.
if not valid:
expect_assertion_error(lambda: spec.process_bls_to_execution_change(state, signed_address_change))
yield 'post', None
return
# process address change
spec.process_bls_to_execution_change(state, signed_address_change)
# yield post-state
yield 'post', state
# Make sure state has NOT been changed
assert state == pre_state
@with_eip4844_and_later
@spec_state_test
def test_no_op(spec, state):
signed_address_change = get_signed_address_change(spec, state)
yield from run_bls_to_execution_change_processing_no_op(spec, state, signed_address_change)

View File

@ -0,0 +1,41 @@
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_eip4844_and_later
from eth2spec.test.helpers.execution_payload import (
build_empty_execution_payload,
)
from eth2spec.test.helpers.state import next_slot
def run_withdrawals_processing(spec, state, execution_payload, valid=True):
"""
Run ``process_execution_payload``, yielding:
- pre-state ('pre')
- execution payload ('execution_payload')
- post-state ('post').
If ``valid == False``, run expecting ``AssertionError``
"""
pre_state = state.copy()
yield 'pre', state
yield 'execution_payload', execution_payload
if not valid:
expect_assertion_error(lambda: spec.process_withdrawals(state, execution_payload))
yield 'post', None
return
spec.process_withdrawals(state, execution_payload)
yield 'post', state
# Make sure state has NOT been changed
assert state == pre_state
@with_eip4844_and_later
@spec_state_test
def test_no_op(spec, state):
next_slot(spec, state)
execution_payload = build_empty_execution_payload(spec, state)
yield from run_withdrawals_processing(spec, state, execution_payload)

View File

@ -0,0 +1,82 @@
from eth2spec.test.context import (
with_phases,
with_custom_state,
with_presets,
spec_test, with_state,
low_balances, misc_balances, large_validator_set,
)
from eth2spec.test.utils import with_meta_tags
from eth2spec.test.helpers.constants import (
CAPELLA, EIP4844,
MINIMAL,
)
from eth2spec.test.helpers.state import (
next_epoch,
next_epoch_via_block,
)
from eth2spec.test.helpers.eip4844.fork import (
EIP4844_FORK_TEST_META_TAGS,
run_fork_test,
)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_base_state(spec, phases, state):
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_next_epoch(spec, phases, state):
next_epoch(spec, state)
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_next_epoch_with_block(spec, phases, state):
next_epoch_via_block(spec, state)
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_many_next_epoch(spec, phases, state):
for _ in range(3):
next_epoch(spec, state)
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@spec_test
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_random_low_balances(spec, phases, state):
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@spec_test
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_random_misc_balances(spec, phases, state):
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@with_presets([MINIMAL],
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@spec_test
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_fork_random_large_validator_set(spec, phases, state):
yield from run_fork_test(phases[EIP4844], state)

View File

@ -0,0 +1,84 @@
from random import Random
from eth2spec.test.context import (
with_phases,
with_custom_state,
with_presets,
spec_test, with_state,
low_balances, misc_balances, large_validator_set,
)
from eth2spec.test.utils import with_meta_tags
from eth2spec.test.helpers.constants import (
CAPELLA, EIP4844,
MINIMAL,
)
from eth2spec.test.helpers.eip4844.fork import (
EIP4844_FORK_TEST_META_TAGS,
run_fork_test,
)
from eth2spec.test.helpers.random import randomize_state
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_0(spec, phases, state):
randomize_state(spec, state, rng=Random(1010))
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_1(spec, phases, state):
randomize_state(spec, state, rng=Random(2020))
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_2(spec, phases, state):
randomize_state(spec, state, rng=Random(3030))
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_state
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_3(spec, phases, state):
randomize_state(spec, state, rng=Random(4040))
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_low_balances(spec, phases, state):
randomize_state(spec, state, rng=Random(5050))
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@spec_test
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_misc_balances(spec, phases, state):
randomize_state(spec, state, rng=Random(6060))
yield from run_fork_test(phases[EIP4844], state)
@with_phases(phases=[CAPELLA], other_phases=[EIP4844])
@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=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
@with_meta_tags(EIP4844_FORK_TEST_META_TAGS)
def test_eip4844_fork_random_large_validator_set(spec, phases, state):
randomize_state(spec, state, rng=Random(7070))
yield from run_fork_test(phases[EIP4844], state)

View File

@ -0,0 +1,438 @@
"""
This module is generated from the ``random`` test generator.
Please do not edit this file manually.
See the README for that generator for more information.
"""
from eth2spec.test.helpers.constants import EIP4844
from eth2spec.test.context import (
misc_balances_in_default_range_with_many_validators,
with_phases,
zero_activation_threshold,
only_generator,
)
from eth2spec.test.context import (
always_bls,
spec_test,
with_custom_state,
single_phase,
)
from eth2spec.test.utils.randomized_block_tests import (
run_generated_randomized_test,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_0(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_1(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_2(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_3(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_4(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_5(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_6(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_7(spec, state):
# scenario as high-level, informal text:
# epochs:0,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'validation': 'validate_is_not_leaking', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_8(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_9(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_10(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_11(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_12(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:last_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'last_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_13(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:random_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'random_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_14(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:penultimate_slot_in_epoch,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 0, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 'penultimate_slot_in_epoch', 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)
@only_generator("randomized test for broad coverage, not point-to-point CI")
@with_phases([EIP4844])
@with_custom_state(
balances_fn=misc_balances_in_default_range_with_many_validators,
threshold_fn=zero_activation_threshold
)
@spec_test
@single_phase
@always_bls
def test_randomized_15(spec, state):
# scenario as high-level, informal text:
# epochs:epochs_until_leak,slots:0,with-block:no_block
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
# epochs:1,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:no_block
# epochs:0,slots:0,with-block:random_block_eip4844
scenario = {'transitions': [{'epochs_to_skip': 'epochs_until_leak', 'validation': 'validate_is_leaking', 'slots_to_skip': 0, 'block_producer': 'no_block'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}, {'epochs_to_skip': 1, 'slots_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'slots_to_skip': 0, 'epochs_to_skip': 0, 'block_producer': 'no_block', 'validation': 'no_op_validation'}, {'block_producer': 'random_block_eip4844', 'epochs_to_skip': 0, 'slots_to_skip': 0, 'validation': 'no_op_validation'}], 'state_randomizer': 'randomize_state_eip4844'} # noqa: E501
yield from run_generated_randomized_test(
spec,
state,
scenario,
)

View File

@ -17,4 +17,4 @@ def test_verify_kzg_proof(spec, state):
proof = spec.compute_kzg_proof(polynomial, x) proof = spec.compute_kzg_proof(polynomial, x)
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, x) y = spec.evaluate_polynomial_in_evaluation_form(polynomial, x)
assert spec.verify_kzg_proof(commitment, x, y, proof) assert spec.verify_kzg_proof_impl(commitment, x, y, proof)

View File

@ -2,7 +2,7 @@ from eth2spec.utils import bls
from eth2spec.test.helpers.keys import pubkeys, privkeys, pubkey_to_privkey from eth2spec.test.helpers.keys import pubkeys, privkeys, pubkey_to_privkey
def get_signed_address_change(spec, state, validator_index=None, withdrawal_pubkey=None): def get_signed_address_change(spec, state, validator_index=None, withdrawal_pubkey=None, to_execution_address=None):
if validator_index is None: if validator_index is None:
validator_index = 0 validator_index = 0
@ -13,11 +13,14 @@ def get_signed_address_change(spec, state, validator_index=None, withdrawal_pubk
else: else:
withdrawal_privkey = pubkey_to_privkey[withdrawal_pubkey] withdrawal_privkey = pubkey_to_privkey[withdrawal_pubkey]
if to_execution_address is None:
to_execution_address = b'\x42' * 20
domain = spec.get_domain(state, spec.DOMAIN_BLS_TO_EXECUTION_CHANGE) domain = spec.get_domain(state, spec.DOMAIN_BLS_TO_EXECUTION_CHANGE)
address_change = spec.BLSToExecutionChange( address_change = spec.BLSToExecutionChange(
validator_index=validator_index, validator_index=validator_index,
from_bls_pubkey=withdrawal_pubkey, from_bls_pubkey=withdrawal_pubkey,
to_execution_address=b'\x42' * 20, to_execution_address=to_execution_address,
) )
signing_root = spec.compute_signing_root(address_change, domain) signing_root = spec.compute_signing_root(address_change, domain)

View File

@ -32,6 +32,7 @@ ALL_FORK_UPGRADES = {
PHASE0: ALTAIR, PHASE0: ALTAIR,
ALTAIR: BELLATRIX, ALTAIR: BELLATRIX,
BELLATRIX: CAPELLA, BELLATRIX: CAPELLA,
CAPELLA: EIP4844,
} }
ALL_PRE_POST_FORKS = ALL_FORK_UPGRADES.items() ALL_PRE_POST_FORKS = ALL_FORK_UPGRADES.items()
AFTER_BELLATRIX_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key != PHASE0} AFTER_BELLATRIX_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key != PHASE0}

View File

@ -0,0 +1,63 @@
from eth2spec.test.helpers.constants import (
EIP4844,
)
EIP4844_FORK_TEST_META_TAGS = {
'fork': EIP4844,
}
def run_fork_test(post_spec, pre_state):
yield 'pre', pre_state
post_state = post_spec.upgrade_to_eip4844(pre_state)
# Stable fields
stable_fields = [
'genesis_time', 'genesis_validators_root', 'slot',
# History
'latest_block_header', 'block_roots', 'state_roots', 'historical_roots',
# Eth1
'eth1_data', 'eth1_data_votes', 'eth1_deposit_index',
# Registry
'validators', 'balances',
# Randomness
'randao_mixes',
# Slashings
'slashings',
# Participation
'previous_epoch_participation', 'current_epoch_participation',
# Finality
'justification_bits', 'previous_justified_checkpoint', 'current_justified_checkpoint', 'finalized_checkpoint',
# Inactivity
'inactivity_scores',
# Sync
'current_sync_committee', 'next_sync_committee',
# Withdrawals
'next_withdrawal_index', 'next_withdrawal_validator_index',
]
for field in stable_fields:
assert getattr(pre_state, field) == getattr(post_state, field)
# Modified fields
modified_fields = ['fork', 'latest_execution_payload_header']
for field in modified_fields:
assert getattr(pre_state, field) != getattr(post_state, field)
assert len(pre_state.validators) == len(post_state.validators)
for pre_validator, post_validator in zip(pre_state.validators, post_state.validators):
stable_validator_fields = [
'pubkey', 'withdrawal_credentials',
'effective_balance',
'slashed',
'activation_eligibility_epoch', 'activation_epoch', 'exit_epoch', 'withdrawable_epoch',
]
for field in stable_validator_fields:
assert getattr(pre_validator, field) == getattr(post_validator, field)
assert pre_state.fork.current_version == post_state.fork.previous_version
assert post_state.fork.current_version == post_spec.config.EIP4844_FORK_VERSION
assert post_state.fork.epoch == post_spec.get_current_epoch(post_state)
yield 'post', post_state

View File

@ -5,7 +5,7 @@ from .constants import (
def is_post_fork(a, b): def is_post_fork(a, b):
if a == EIP4844: if a == EIP4844:
return b in [PHASE0, ALTAIR, BELLATRIX, EIP4844] return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844]
if a == CAPELLA: if a == CAPELLA:
return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA] return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA]
if a == BELLATRIX: if a == BELLATRIX:

View File

@ -433,7 +433,7 @@ def test_proposer_slashing(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
def test_double_same_proposer_slashings_same_block(spec, state): def test_invalid_duplicate_proposer_slashings_same_block(spec, state):
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
slashed_index = proposer_slashing.signed_header_1.message.proposer_index slashed_index = proposer_slashing.signed_header_1.message.proposer_index
assert not state.validators[slashed_index].slashed assert not state.validators[slashed_index].slashed
@ -450,7 +450,7 @@ def test_double_same_proposer_slashings_same_block(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
def test_double_similar_proposer_slashings_same_block(spec, state): def test_invalid_similar_proposer_slashings_same_block(spec, state):
slashed_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] slashed_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
# Same validator, but different slashable offences in the same block # Same validator, but different slashable offences in the same block
@ -549,7 +549,7 @@ def test_attester_slashing(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
def test_duplicate_attester_slashing(spec, state): def test_invalid_duplicate_attester_slashing_same_block(spec, state):
if spec.MAX_ATTESTER_SLASHINGS < 2: if spec.MAX_ATTESTER_SLASHINGS < 2:
return dump_skipping_message("Skip test if config cannot handle multiple AttesterSlashings per block") return dump_skipping_message("Skip test if config cannot handle multiple AttesterSlashings per block")
@ -744,6 +744,27 @@ def test_deposit_in_block(spec, state):
assert state.validators[validator_index].pubkey == pubkeys[validator_index] assert state.validators[validator_index].pubkey == pubkeys[validator_index]
@with_all_phases
@spec_state_test
def test_invalid_duplicate_deposit_same_block(spec, state):
validator_index = len(state.validators)
amount = spec.MAX_EFFECTIVE_BALANCE
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
# The same deposit of the same validator
for _ in range(2):
block.body.deposits.append(deposit)
signed_block = state_transition_and_sign_block(spec, state, block, expect_fail=True)
yield 'blocks', [signed_block]
yield 'post', None
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
def test_deposit_top_up(spec, state): def test_deposit_top_up(spec, state):
@ -831,6 +852,49 @@ def test_attestation(spec, state):
assert spec.hash_tree_root(state.previous_epoch_participation) == pre_current_epoch_participation_root assert spec.hash_tree_root(state.previous_epoch_participation) == pre_current_epoch_participation_root
@with_all_phases
@spec_state_test
def test_duplicate_attestation_same_block(spec, state):
next_epoch(spec, state)
yield 'pre', state
attestation_block = build_empty_block(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
index = 0
attestation = get_valid_attestation(spec, state, index=index, signed=True)
if not is_post_altair(spec):
pre_current_attestations_len = len(state.current_epoch_attestations)
# Add to state via block transition
for _ in range(2):
attestation_block.body.attestations.append(attestation)
signed_attestation_block = state_transition_and_sign_block(spec, state, attestation_block)
if not is_post_altair(spec):
assert len(state.current_epoch_attestations) == pre_current_attestations_len + 2
# Epoch transition should move to previous_epoch_attestations
pre_current_attestations_root = spec.hash_tree_root(state.current_epoch_attestations)
else:
pre_current_epoch_participation_root = spec.hash_tree_root(state.current_epoch_participation)
epoch_block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
signed_epoch_block = state_transition_and_sign_block(spec, state, epoch_block)
yield 'blocks', [signed_attestation_block, signed_epoch_block]
yield 'post', state
if not is_post_altair(spec):
assert len(state.current_epoch_attestations) == 0
assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root
else:
for index in range(len(state.validators)):
assert state.current_epoch_participation[index] == spec.ParticipationFlags(0b0000_0000)
assert spec.hash_tree_root(state.previous_epoch_participation) == pre_current_epoch_participation_root
# After SHARDING is enabled, a committee is computed for SHARD_COMMITTEE_PERIOD slots ago, # After SHARDING is enabled, a committee is computed for SHARD_COMMITTEE_PERIOD slots ago,
# exceeding the minimal-config randao mixes memory size. # exceeding the minimal-config randao mixes memory size.
# Applies to all voluntary-exit sanity block tests. # Applies to all voluntary-exit sanity block tests.
@ -866,7 +930,7 @@ def test_voluntary_exit(spec, state):
@with_all_phases @with_all_phases
@spec_state_test @spec_state_test
def test_double_validator_exit_same_block(spec, state): def test_invalid_duplicate_validator_exit_same_block(spec, state):
validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit

View File

@ -20,6 +20,9 @@ from eth2spec.test.helpers.random import (
randomize_state as randomize_state_helper, randomize_state as randomize_state_helper,
patch_state_to_non_leaking, patch_state_to_non_leaking,
) )
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
)
from eth2spec.test.helpers.state import ( from eth2spec.test.helpers.state import (
next_slot, next_slot,
next_epoch, next_epoch,
@ -78,6 +81,17 @@ def randomize_state_capella(spec, state, stats, exit_fraction=0.1, slash_fractio
stats, stats,
exit_fraction=exit_fraction, exit_fraction=exit_fraction,
slash_fraction=slash_fraction) slash_fraction=slash_fraction)
# TODO: randomize withdrawals
return scenario_state
def randomize_state_eip4844(spec, state, stats, exit_fraction=0.1, slash_fraction=0.1):
scenario_state = randomize_state_capella(spec,
state,
stats,
exit_fraction=exit_fraction,
slash_fraction=slash_fraction)
# TODO: randomize execution payload
return scenario_state return scenario_state
@ -215,6 +229,16 @@ def random_block_capella(spec, state, signed_blocks, scenario_state, rng=Random(
return block return block
def random_block_eip4844(spec, state, signed_blocks, scenario_state, rng=Random(3456)):
block = random_block_capella(spec, state, signed_blocks, scenario_state)
# TODO: more commitments. blob_kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK]
opaque_tx, _, blob_kzg_commitments = get_sample_opaque_tx(spec, blob_count=1)
block.body.execution_payload.transactions = [opaque_tx]
block.body.blob_kzg_commitments = blob_kzg_commitments
return block
# validations # validations
def no_op_validation(_spec, _state): def no_op_validation(_spec, _state):

View File

@ -5,24 +5,26 @@ generation and verification of merkle proofs based on static data.
## Test case format ## Test case format
### `state.ssz_snappy` Tests for each individual SSZ type are grouped into a `suite` indicating the SSZ type name.
An SSZ-snappy encoded `BeaconState` object from which other data is generated. ### `object.yaml`
A SSZ-snappy encoded object from which other data is generated. The SSZ type can be determined from the test `suite` name.
### `proof.yaml` ### `proof.yaml`
A proof of the leaf value (a merkle root) at generalized-index `leaf_index` in the given `state`. A proof of the leaf value (a merkle root) at generalized-index `leaf_index` in the given `object`.
```yaml ```yaml
leaf: Bytes32 # string, hex encoded, with 0x prefix leaf: Bytes32 # string, hex encoded, with 0x prefix
leaf_index: int # integer, decimal leaf_index: int # integer, decimal
branch: list of Bytes32 # list, each element is a string, hex encoded, with 0x prefix branch: list of Bytes32 # list, each element is a string, hex encoded, with 0x prefix
``` ```
## Condition ## Condition
A test-runner can implement the following assertions: A test-runner can implement the following assertions:
- Check that `is_valid_merkle_branch` confirms `leaf` at `leaf_index` to verify - Check that `is_valid_merkle_branch` confirms `leaf` at `leaf_index` to verify
against `has_tree_root(state)` and `proof`. against `hash_tree_root(object)` and `branch`.
- If the implementation supports generating merkle proofs, check that the - If the implementation supports generating merkle proofs, check that the
self-generated proof matches the `proof` provided with the test. self-generated proof matches the `branch` provided with the test.

View File

@ -186,7 +186,7 @@ if __name__ == "__main__":
ALTAIR: altair_mods, ALTAIR: altair_mods,
} }
run_state_test_generators(runner_name="sanity", specs=specs, all_mods=all_mods) run_state_test_generators(runner_name="sanity", all_mods=all_mods)
``` ```
Here multiple phases load the configuration, and the stream of test cases is derived from a pytest file using the `eth2spec.gen_helpers.gen_from_tests.gen.run_state_test_generators` utility. Note that this helper generates all available tests of `TESTGEN_FORKS` forks of `ALL_CONFIGS` configs of the given runner. Here multiple phases load the configuration, and the stream of test cases is derived from a pytest file using the `eth2spec.gen_helpers.gen_from_tests.gen.run_state_test_generators` utility. Note that this helper generates all available tests of `TESTGEN_FORKS` forks of `ALL_CONFIGS` configs of the given runner.
@ -210,7 +210,7 @@ To add a new test generator that builds `New Tests`:
with any dependencies it may need. Leave it empty if your generator has none. with any dependencies it may need. Leave it empty if your generator has none.
3. Your generator is assumed to have a `main.py` file in its root. 3. Your generator is assumed to have a `main.py` file in its root.
By adding the base generator to your requirements, you can make a generator really easily. See docs below. By adding the base generator to your requirements, you can make a generator really easily. See docs below.
4. Your generator is called with `-o some/file/path/for_testing/can/be_anything -c some/other/path/to_configs/`. 4. Your generator is called with `-o some/file/path/for_testing/can/be_anything --preset-list mainnet minimal`.
The base generator helps you handle this; you only have to define test case providers. The base generator helps you handle this; you only have to define test case providers.
5. Finally, add any linting or testing commands to the 5. Finally, add any linting or testing commands to the
[circleci config file](../../.circleci/config.yml) if desired to increase code quality. [circleci config file](../../.circleci/config.yml) if desired to increase code quality.

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods 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 from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -31,6 +31,10 @@ if __name__ == "__main__":
# so no additional tests required. # so no additional tests required.
capella_mods = bellatrix_mods capella_mods = bellatrix_mods
# No epoch-processing changes in EIP4844 and previous testing repeats with new types,
# so no additional tests required.
eip4844_mods = capella_mods
# TODO Custody Game testgen is disabled for now # TODO Custody Game testgen is disabled for now
# custody_game_mods = {**{key: 'eth2spec.test.custody_game.epoch_processing.test_process_' + key for key in [ # custody_game_mods = {**{key: 'eth2spec.test.custody_game.epoch_processing.test_process_' + key for key in [
# 'reveal_deadlines', # 'reveal_deadlines',
@ -43,6 +47,7 @@ if __name__ == "__main__":
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="epoch_processing", all_mods=all_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.gen_helpers.gen_from_tests.gen import run_state_test_generators
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -7,12 +7,14 @@ if __name__ == "__main__":
altair_mods = phase_0_mods # No additional Altair specific finality tests altair_mods = phase_0_mods # No additional Altair specific finality tests
bellatrix_mods = altair_mods # No additional Bellatrix specific finality tests bellatrix_mods = altair_mods # No additional Bellatrix specific finality tests
capella_mods = bellatrix_mods # No additional Capella specific finality tests capella_mods = bellatrix_mods # No additional Capella specific finality tests
eip4844_mods = capella_mods # No additional EIP4844 specific finality tests
all_mods = { all_mods = {
PHASE0: phase_0_mods, PHASE0: phase_0_mods,
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="finality", all_mods=all_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.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -18,11 +18,14 @@ if __name__ == "__main__":
]} ]}
bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods)
capella_mods = bellatrix_mods # No additional Capella specific fork choice tests capella_mods = bellatrix_mods # No additional Capella specific fork choice tests
eip4844_mods = capella_mods # No additional Capella specific fork choice tests
all_mods = { all_mods = {
PHASE0: phase_0_mods, PHASE0: phase_0_mods,
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="fork_choice", all_mods=all_mods) run_state_test_generators(runner_name="fork_choice", all_mods=all_mods)

View File

@ -1,13 +1,14 @@
from typing import Iterable from typing import Iterable
from eth2spec.test.helpers.constants import ( from eth2spec.test.helpers.constants import (
PHASE0, ALTAIR, BELLATRIX, CAPELLA, PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844,
MINIMAL, MAINNET, MINIMAL, MAINNET,
) )
from eth2spec.test.helpers.typing import SpecForkName, PresetBaseName from eth2spec.test.helpers.typing import SpecForkName, PresetBaseName
from eth2spec.test.altair.fork import test_altair_fork_basic, test_altair_fork_random from eth2spec.test.altair.fork import test_altair_fork_basic, test_altair_fork_random
from eth2spec.test.bellatrix.fork import test_bellatrix_fork_basic, test_bellatrix_fork_random from eth2spec.test.bellatrix.fork import test_bellatrix_fork_basic, test_bellatrix_fork_random
from eth2spec.test.capella.fork import test_capella_fork_basic, test_capella_fork_random from eth2spec.test.capella.fork import test_capella_fork_basic, test_capella_fork_random
from eth2spec.test.eip4844.fork import test_eip4844_fork_basic, test_eip4844_fork_random
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
from eth2spec.gen_helpers.gen_from_tests.gen import generate_from_tests from eth2spec.gen_helpers.gen_from_tests.gen import generate_from_tests
@ -39,6 +40,8 @@ def _get_fork_tests_providers():
yield create_provider(test_bellatrix_fork_random, preset, ALTAIR, BELLATRIX) yield create_provider(test_bellatrix_fork_random, preset, ALTAIR, BELLATRIX)
yield create_provider(test_capella_fork_basic, preset, BELLATRIX, CAPELLA) yield create_provider(test_capella_fork_basic, preset, BELLATRIX, CAPELLA)
yield create_provider(test_capella_fork_random, preset, BELLATRIX, CAPELLA) yield create_provider(test_capella_fork_random, preset, BELLATRIX, CAPELLA)
yield create_provider(test_eip4844_fork_basic, preset, CAPELLA, EIP4844)
yield create_provider(test_eip4844_fork_random, preset, CAPELLA, EIP4844)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,5 +1,5 @@
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods 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 from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -16,11 +16,13 @@ if __name__ == "__main__":
]} ]}
bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods)
capella_mods = bellatrix_mods # No additional Capella specific genesis tests capella_mods = bellatrix_mods # No additional Capella specific genesis tests
eip4844_mods = capella_mods # No additional EIP4844 specific genesis tests
all_mods = { all_mods = {
PHASE0: phase_0_mods, PHASE0: phase_0_mods,
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="genesis", all_mods=all_mods) run_state_test_generators(runner_name="genesis", all_mods=all_mods)

View File

@ -1,4 +1,4 @@
from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX, CAPELLA, EIP4844
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
@ -10,11 +10,13 @@ if __name__ == "__main__":
]} ]}
bellatrix_mods = altair_mods bellatrix_mods = altair_mods
capella_mods = bellatrix_mods capella_mods = bellatrix_mods
eip4844_mods = capella_mods
all_mods = { all_mods = {
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="light_client", all_mods=all_mods) run_state_test_generators(runner_name="light_client", 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.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -31,6 +31,12 @@ if __name__ == "__main__":
]} ]}
capella_mods = combine_mods(_new_capella_mods, bellatrix_mods) capella_mods = combine_mods(_new_capella_mods, bellatrix_mods)
_new_eip4844_mods = {key: 'eth2spec.test.eip4844.block_processing.test_process_' + key for key in [
'bls_to_execution_change',
'withdrawals',
]}
eip4844_mods = combine_mods(_new_eip4844_mods, capella_mods)
# TODO Custody Game testgen is disabled for now # 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 [ # _new_custody_game_mods = {key: 'eth2spec.test.custody_game.block_processing.test_process_' + key for key in [
# 'attestation', # 'attestation',
@ -46,6 +52,7 @@ if __name__ == "__main__":
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="operations", all_mods=all_mods) run_state_test_generators(runner_name="operations", all_mods=all_mods)

View File

@ -6,7 +6,9 @@ all:
rm -f ../../core/pyspec/eth2spec/test/altair/random/test_random.py rm -f ../../core/pyspec/eth2spec/test/altair/random/test_random.py
rm -f ../../core/pyspec/eth2spec/test/bellatrix/random/test_random.py rm -f ../../core/pyspec/eth2spec/test/bellatrix/random/test_random.py
rm -f ../../core/pyspec/eth2spec/test/capella/random/test_random.py rm -f ../../core/pyspec/eth2spec/test/capella/random/test_random.py
rm -f ../../core/pyspec/eth2spec/test/eip4844/random/test_random.py
python3 generate.py phase0 > ../../core/pyspec/eth2spec/test/phase0/random/test_random.py python3 generate.py phase0 > ../../core/pyspec/eth2spec/test/phase0/random/test_random.py
python3 generate.py altair > ../../core/pyspec/eth2spec/test/altair/random/test_random.py python3 generate.py altair > ../../core/pyspec/eth2spec/test/altair/random/test_random.py
python3 generate.py bellatrix > ../../core/pyspec/eth2spec/test/bellatrix/random/test_random.py python3 generate.py bellatrix > ../../core/pyspec/eth2spec/test/bellatrix/random/test_random.py
python3 generate.py capella > ../../core/pyspec/eth2spec/test/capella/random/test_random.py python3 generate.py capella > ../../core/pyspec/eth2spec/test/capella/random/test_random.py
python3 generate.py eip4844 > ../../core/pyspec/eth2spec/test/eip4844/random/test_random.py

View File

@ -21,10 +21,12 @@ from eth2spec.test.utils.randomized_block_tests import (
randomize_state_altair, randomize_state_altair,
randomize_state_bellatrix, randomize_state_bellatrix,
randomize_state_capella, randomize_state_capella,
randomize_state_eip4844,
random_block, random_block,
random_block_altair_with_cycling_sync_committee_participation, random_block_altair_with_cycling_sync_committee_participation,
random_block_bellatrix, random_block_bellatrix,
random_block_capella, random_block_capella,
random_block_eip4844,
last_slot_in_epoch, last_slot_in_epoch,
random_slot_in_epoch, random_slot_in_epoch,
penultimate_slot_in_epoch, penultimate_slot_in_epoch,
@ -34,7 +36,7 @@ from eth2spec.test.utils.randomized_block_tests import (
transition_to_leaking, transition_to_leaking,
transition_without_leak, transition_without_leak,
) )
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
# Ensure this many blocks are present in *each* randomized scenario # Ensure this many blocks are present in *each* randomized scenario
@ -272,5 +274,12 @@ if __name__ == "__main__":
state_randomizer=randomize_state_capella, state_randomizer=randomize_state_capella,
block_randomizer=random_block_capella, block_randomizer=random_block_capella,
) )
if EIP4844 in sys.argv:
did_generate = True
run_generate_tests_to_std_out(
EIP4844,
state_randomizer=randomize_state_eip4844,
block_randomizer=random_block_eip4844,
)
if not did_generate: if not did_generate:
warnings.warn("no phase given for test generation") warnings.warn("no phase given for test generation")

View File

@ -1,4 +1,4 @@
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
@ -15,12 +15,16 @@ if __name__ == "__main__":
capella_mods = {key: 'eth2spec.test.capella.random.test_' + key for key in [ capella_mods = {key: 'eth2spec.test.capella.random.test_' + key for key in [
'random', 'random',
]} ]}
eip4844_mods = {key: 'eth2spec.test.eip4844.random.test_' + key for key in [
'random',
]}
all_mods = { all_mods = {
PHASE0: phase_0_mods, PHASE0: phase_0_mods,
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="random", all_mods=all_mods) run_state_test_generators(runner_name="random", 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.gen_helpers.gen_from_tests.gen import run_state_test_generators
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -16,12 +16,14 @@ if __name__ == "__main__":
# Transaction fees are part of the execution-layer. # Transaction fees are part of the execution-layer.
bellatrix_mods = altair_mods bellatrix_mods = altair_mods
capella_mods = bellatrix_mods capella_mods = bellatrix_mods
eip4844_mods = capella_mods
all_mods = { all_mods = {
PHASE0: phase_0_mods, PHASE0: phase_0_mods,
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="rewards", all_mods=all_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 from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators, combine_mods
@ -23,11 +23,17 @@ if __name__ == "__main__":
]} ]}
capella_mods = combine_mods(_new_capella_mods, bellatrix_mods) capella_mods = combine_mods(_new_capella_mods, bellatrix_mods)
_new_eip4844_mods = {key: 'eth2spec.test.eip4844.sanity.test_' + key for key in [
'blocks',
]}
eip4844_mods = combine_mods(_new_eip4844_mods, capella_mods)
all_mods = { all_mods = {
PHASE0: phase_0_mods, PHASE0: phase_0_mods,
ALTAIR: altair_mods, ALTAIR: altair_mods,
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="sanity", all_mods=all_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.gen_helpers.gen_from_tests.gen import run_state_test_generators
from eth2spec.test.helpers.constants import BELLATRIX, CAPELLA from eth2spec.test.helpers.constants import BELLATRIX, CAPELLA, EIP4844
if __name__ == "__main__": if __name__ == "__main__":
@ -7,10 +7,12 @@ if __name__ == "__main__":
'optimistic', 'optimistic',
]} ]}
capella_mods = bellatrix_mods capella_mods = bellatrix_mods
eip4844_mods = capella_mods
all_mods = { all_mods = {
BELLATRIX: bellatrix_mods, BELLATRIX: bellatrix_mods,
CAPELLA: capella_mods, CAPELLA: capella_mods,
EIP4844: eip4844_mods,
} }
run_state_test_generators(runner_name="sync", all_mods=all_mods) run_state_test_generators(runner_name="sync", all_mods=all_mods)