mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-02 06:54:57 -05:00
Merge pull request #2380 from ethereum/merge-test-vectors
Merge test vectors: enable phase0 tests for Merge + start on new testing
This commit is contained in:
2
setup.py
2
setup.py
@@ -441,7 +441,7 @@ ExecutionState = Any
|
||||
|
||||
|
||||
def get_pow_block(hash: Bytes32) -> PowBlock:
|
||||
pass
|
||||
return PowBlock(block_hash=hash, is_valid=True, is_processed=True, total_difficulty=TRANSITION_TOTAL_DIFFICULTY)
|
||||
|
||||
|
||||
def get_execution_state(execution_state_root: Bytes32) -> ExecutionState:
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
- [Introduction](#introduction)
|
||||
- [Custom types](#custom-types)
|
||||
- [Constants](#constants)
|
||||
- [Transition](#transition)
|
||||
- [Execution](#execution)
|
||||
- [Configuration](#configuration)
|
||||
- [Containers](#containers)
|
||||
- [Extended containers](#extended-containers)
|
||||
- [`BeaconBlockBody`](#beaconblockbody)
|
||||
@@ -24,6 +24,7 @@
|
||||
- [`ExecutionPayloadHeader`](#executionpayloadheader)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc)
|
||||
- [`is_execution_enabled`](#is_execution_enabled)
|
||||
- [`is_transition_completed`](#is_transition_completed)
|
||||
- [`is_transition_block`](#is_transition_block)
|
||||
- [`compute_time_at_slot`](#compute_time_at_slot)
|
||||
@@ -50,12 +51,6 @@ We define the following Python custom types for type hinting and readability:
|
||||
|
||||
## Constants
|
||||
|
||||
### Transition
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `TRANSITION_TOTAL_DIFFICULTY` | **TBD** |
|
||||
|
||||
### Execution
|
||||
|
||||
| Name | Value |
|
||||
@@ -64,6 +59,16 @@ We define the following Python custom types for type hinting and readability:
|
||||
| `MAX_EXECUTION_TRANSACTIONS` | `uint64(2**14)` (= 16,384) |
|
||||
| `BYTES_PER_LOGS_BLOOM` | `uint64(2**8)` (= 256) |
|
||||
|
||||
## Configuration
|
||||
|
||||
Warning: this configuration is not definitive.
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `MERGE_FORK_VERSION` | `Version('0x02000000')` |
|
||||
| `MERGE_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
|
||||
| `TRANSITION_TOTAL_DIFFICULTY` | **TBD** |
|
||||
|
||||
## Containers
|
||||
|
||||
### Extended containers
|
||||
@@ -136,6 +141,13 @@ class ExecutionPayloadHeader(Container):
|
||||
|
||||
### Misc
|
||||
|
||||
#### `is_execution_enabled`
|
||||
|
||||
```python
|
||||
def is_execution_enabled(state: BeaconState, block: BeaconBlock) -> bool:
|
||||
return is_transition_completed(state) or is_transition_block(state, block)
|
||||
```
|
||||
|
||||
#### `is_transition_completed`
|
||||
|
||||
```python
|
||||
@@ -146,8 +158,8 @@ def is_transition_completed(state: BeaconState) -> bool:
|
||||
#### `is_transition_block`
|
||||
|
||||
```python
|
||||
def is_transition_block(state: BeaconState, block_body: BeaconBlockBody) -> bool:
|
||||
return not is_transition_completed(state) and block_body.execution_payload != ExecutionPayload()
|
||||
def is_transition_block(state: BeaconState, block: BeaconBlock) -> bool:
|
||||
return not is_transition_completed(state) and block.body.execution_payload != ExecutionPayload()
|
||||
```
|
||||
|
||||
#### `compute_time_at_slot`
|
||||
@@ -168,7 +180,9 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body)
|
||||
process_execution_payload(state, block.body) # [New in Merge]
|
||||
# Pre-merge, skip execution payload processing
|
||||
if is_execution_enabled(state, block):
|
||||
process_execution_payload(state, block.body.execution_payload) # [New in Merge]
|
||||
```
|
||||
|
||||
#### Execution payload processing
|
||||
@@ -181,16 +195,10 @@ The body of the function is implementation dependent.
|
||||
##### `process_execution_payload`
|
||||
|
||||
```python
|
||||
def process_execution_payload(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
def process_execution_payload(state: BeaconState, execution_payload: ExecutionPayload) -> None:
|
||||
"""
|
||||
Note: This function is designed to be able to be run in parallel with the other `process_block` sub-functions
|
||||
"""
|
||||
# Pre-merge, skip processing
|
||||
if not is_transition_completed(state) and not is_transition_block(state, body):
|
||||
return
|
||||
|
||||
execution_payload = body.execution_payload
|
||||
|
||||
if is_transition_completed(state):
|
||||
assert execution_payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||
assert execution_payload.number == state.latest_execution_payload_header.number + 1
|
||||
|
||||
@@ -75,7 +75,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root
|
||||
|
||||
# [New in Merge]
|
||||
if is_transition_block(pre_state, block.body):
|
||||
if is_transition_block(pre_state, block):
|
||||
# Delay consideration of block until PoW block is processed by the PoW node
|
||||
pow_block = get_pow_block(block.body.execution_payload.parent_hash)
|
||||
assert pow_block.is_processed
|
||||
|
||||
@@ -10,7 +10,6 @@ from eth2spec.test.helpers.state import (
|
||||
next_epoch,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import (
|
||||
PHASE0,
|
||||
MAINNET, MINIMAL,
|
||||
)
|
||||
from eth2spec.test.helpers.sync_committee import (
|
||||
@@ -18,7 +17,7 @@ from eth2spec.test.helpers.sync_committee import (
|
||||
)
|
||||
from eth2spec.test.context import (
|
||||
expect_assertion_error,
|
||||
with_all_phases_except,
|
||||
with_altair_and_later,
|
||||
with_configs,
|
||||
spec_state_test,
|
||||
always_bls,
|
||||
@@ -63,7 +62,7 @@ def get_committee_indices(spec, state, duplicates=False):
|
||||
state.randao_mixes[randao_index] = hash(state.randao_mixes[randao_index])
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_missing_participant(spec, state):
|
||||
@@ -85,7 +84,7 @@ def test_invalid_signature_missing_participant(spec, state):
|
||||
yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_extra_participant(spec, state):
|
||||
@@ -198,7 +197,7 @@ def run_successful_sync_committee_test(spec, state, committee, committee_bits):
|
||||
)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="to create nonduplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_nonduplicate_committee(spec, state):
|
||||
@@ -214,7 +213,7 @@ def test_sync_committee_rewards_nonduplicate_committee(spec, state):
|
||||
yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_configs([MAINNET], reason="to create duplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_duplicate_committee(spec, state):
|
||||
@@ -230,7 +229,7 @@ def test_sync_committee_rewards_duplicate_committee(spec, state):
|
||||
yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_sync_committee_rewards_not_full_participants(spec, state):
|
||||
@@ -241,7 +240,7 @@ def test_sync_committee_rewards_not_full_participants(spec, state):
|
||||
yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_sync_committee_rewards_empty_participants(spec, state):
|
||||
@@ -251,7 +250,7 @@ def test_sync_committee_rewards_empty_participants(spec, state):
|
||||
yield from run_successful_sync_committee_test(spec, state, committee, committee_bits)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_past_block(spec, state):
|
||||
@@ -290,7 +289,7 @@ def test_invalid_signature_past_block(spec, state):
|
||||
yield from run_sync_committee_processing(spec, state, invalid_block, expect_exception=True)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="to produce different committee sets")
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@@ -327,7 +326,7 @@ def test_invalid_signature_previous_committee(spec, state):
|
||||
yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
|
||||
@@ -2,16 +2,13 @@ from eth2spec.test.context import (
|
||||
always_bls,
|
||||
spec_state_test,
|
||||
spec_test,
|
||||
with_all_phases_except,
|
||||
with_altair_and_later,
|
||||
with_configs,
|
||||
with_custom_state,
|
||||
single_phase,
|
||||
misc_balances,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import (
|
||||
PHASE0,
|
||||
MINIMAL,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
from eth2spec.test.helpers.state import transition_to
|
||||
from eth2spec.test.helpers.epoch_processing import (
|
||||
run_epoch_processing_with,
|
||||
@@ -49,7 +46,7 @@ def run_sync_committees_progress_test(spec, state):
|
||||
assert state.next_sync_committee == third_sync_committee
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@@ -60,7 +57,7 @@ def test_sync_committees_progress_genesis(spec, state):
|
||||
yield from run_sync_committees_progress_test(spec, state)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@@ -73,7 +70,7 @@ def test_sync_committees_progress_not_genesis(spec, state):
|
||||
yield from run_sync_committees_progress_test(spec, state)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
|
||||
@@ -11,9 +11,8 @@ from eth2spec.test.helpers.block import (
|
||||
from eth2spec.test.helpers.sync_committee import (
|
||||
compute_aggregate_sync_committee_signature,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import PHASE0
|
||||
from eth2spec.test.context import (
|
||||
with_all_phases_except,
|
||||
with_altair_and_later,
|
||||
spec_state_test,
|
||||
)
|
||||
|
||||
@@ -40,46 +39,46 @@ def run_sync_committee_sanity_test(spec, state, fraction_full=1.0):
|
||||
yield 'post', state
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_full_sync_committee_committee(spec, state):
|
||||
next_epoch(spec, state)
|
||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=1.0)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_half_sync_committee_committee(spec, state):
|
||||
next_epoch(spec, state)
|
||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_empty_sync_committee_committee(spec, state):
|
||||
next_epoch(spec, state)
|
||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.0)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_full_sync_committee_committee_genesis(spec, state):
|
||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=1.0)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_half_sync_committee_committee_genesis(spec, state):
|
||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_empty_sync_committee_committee_genesis(spec, state):
|
||||
yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.0)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
def test_inactivity_scores(spec, state):
|
||||
for _ in range(spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2):
|
||||
|
||||
@@ -7,8 +7,7 @@ from eth2spec.test.helpers.state import transition_to
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.bls import only_with_bls
|
||||
from eth2spec.test.context import (
|
||||
PHASE0,
|
||||
with_all_phases_except,
|
||||
with_altair_and_later,
|
||||
with_state,
|
||||
)
|
||||
|
||||
@@ -25,7 +24,7 @@ def ensure_assignments_in_sync_committee(
|
||||
assert spec.is_assigned_to_sync_committee(state, epoch, validator_index)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_state
|
||||
def test_is_assigned_to_sync_committee(phases, spec, state):
|
||||
epoch = spec.get_current_epoch(state)
|
||||
@@ -91,7 +90,7 @@ def _get_sync_committee_signature(
|
||||
|
||||
|
||||
@only_with_bls()
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_state
|
||||
def test_process_sync_committee_contributions(phases, spec, state):
|
||||
# skip over slots at genesis
|
||||
@@ -144,7 +143,7 @@ def _subnet_for_sync_committee_index(spec, i):
|
||||
return i // (spec.SYNC_COMMITTEE_SIZE // spec.SYNC_COMMITTEE_SUBNET_COUNT)
|
||||
|
||||
|
||||
@with_all_phases_except([PHASE0])
|
||||
@with_altair_and_later
|
||||
@with_state
|
||||
def test_compute_subnets_for_sync_committee(state, spec, phases):
|
||||
some_sync_committee_members = list(
|
||||
|
||||
@@ -7,8 +7,8 @@ from eth2spec.utils import bls
|
||||
|
||||
from .exceptions import SkippedTest
|
||||
from .helpers.constants import (
|
||||
PHASE0, ALTAIR,
|
||||
ALL_PHASES, FORKS_BEFORE_ALTAIR,
|
||||
PHASE0, ALTAIR, MERGE,
|
||||
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_MERGE,
|
||||
)
|
||||
from .helpers.genesis import create_genesis_state
|
||||
from .utils import vector_test, with_meta_tags
|
||||
@@ -312,7 +312,7 @@ def with_phases(phases, other_phases=None):
|
||||
return None
|
||||
run_phases = [phase]
|
||||
|
||||
if PHASE0 not in run_phases and ALTAIR not in run_phases:
|
||||
if PHASE0 not in run_phases and ALTAIR not in run_phases and MERGE not in run_phases:
|
||||
dump_skipping_message("none of the recognized phases are executable, skipping test.")
|
||||
return None
|
||||
|
||||
@@ -330,6 +330,8 @@ def with_phases(phases, other_phases=None):
|
||||
phase_dir[PHASE0] = spec_phase0
|
||||
if ALTAIR in available_phases:
|
||||
phase_dir[ALTAIR] = spec_altair
|
||||
if MERGE in available_phases:
|
||||
phase_dir[MERGE] = spec_merge
|
||||
|
||||
# return is ignored whenever multiple phases are ran.
|
||||
# This return is for test generators to emit python generators (yielding test vector outputs)
|
||||
@@ -337,6 +339,8 @@ def with_phases(phases, other_phases=None):
|
||||
ret = fn(spec=spec_phase0, phases=phase_dir, *args, **kw)
|
||||
if ALTAIR in run_phases:
|
||||
ret = fn(spec=spec_altair, phases=phase_dir, *args, **kw)
|
||||
if MERGE in run_phases:
|
||||
ret = fn(spec=spec_merge, phases=phase_dir, *args, **kw)
|
||||
|
||||
# TODO: merge, sharding, custody_game and das are not executable yet.
|
||||
# Tests that specify these features will not run, and get ignored for these specific phases.
|
||||
@@ -362,6 +366,20 @@ def with_configs(configs, reason=None):
|
||||
|
||||
|
||||
def is_post_altair(spec):
|
||||
if spec.fork == MERGE: # TODO: remove parallel Altair-Merge condition after rebase.
|
||||
return False
|
||||
if spec.fork in FORKS_BEFORE_ALTAIR:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def is_post_merge(spec):
|
||||
if spec.fork == ALTAIR: # TODO: remove parallel Altair-Merge condition after rebase.
|
||||
return False
|
||||
if spec.fork in FORKS_BEFORE_MERGE:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
with_altair_and_later = with_phases([ALTAIR]) # TODO: include Merge, but not until Merge work is rebased.
|
||||
with_merge_and_later = with_phases([MERGE])
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from eth2spec.test.context import is_post_altair
|
||||
from eth2spec.test.context import is_post_altair, is_post_merge
|
||||
from eth2spec.test.helpers.execution_payload import build_empty_execution_payload
|
||||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.bls import only_with_bls
|
||||
@@ -94,6 +95,9 @@ def build_empty_block(spec, state, slot=None):
|
||||
if is_post_altair(spec):
|
||||
empty_block.body.sync_aggregate.sync_committee_signature = spec.G2_POINT_AT_INFINITY
|
||||
|
||||
if is_post_merge(spec):
|
||||
empty_block.body.execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
||||
apply_randao_reveal(spec, state, empty_block)
|
||||
return empty_block
|
||||
|
||||
|
||||
@@ -7,21 +7,24 @@ from .typing import SpecForkName, ConfigName
|
||||
# Some of the Spec module functionality is exposed here to deal with phase-specific changes.
|
||||
PHASE0 = SpecForkName('phase0')
|
||||
ALTAIR = SpecForkName('altair')
|
||||
MERGE = SpecForkName('merge')
|
||||
|
||||
# Experimental phases (not included in default "ALL_PHASES"):
|
||||
MERGE = SpecForkName('merge')
|
||||
SHARDING = SpecForkName('sharding')
|
||||
CUSTODY_GAME = SpecForkName('custody_game')
|
||||
DAS = SpecForkName('das')
|
||||
|
||||
# The forks that pytest runs with.
|
||||
ALL_PHASES = (PHASE0, ALTAIR)
|
||||
ALL_PHASES = (PHASE0, ALTAIR, MERGE)
|
||||
# The forks that output to the test vectors.
|
||||
TESTGEN_FORKS = (PHASE0, ALTAIR)
|
||||
TESTGEN_FORKS = (PHASE0, ALTAIR, MERGE)
|
||||
# TODO: everything runs in parallel to Altair.
|
||||
# After features are rebased on the Altair fork, this can be reduced to just PHASE0.
|
||||
FORKS_BEFORE_ALTAIR = (PHASE0, MERGE, SHARDING, CUSTODY_GAME, DAS)
|
||||
|
||||
# TODO: when rebasing Merge onto Altair, add ALTAIR to this tuple.
|
||||
FORKS_BEFORE_MERGE = (PHASE0,)
|
||||
|
||||
#
|
||||
# Config
|
||||
#
|
||||
|
||||
26
tests/core/pyspec/eth2spec/test/helpers/execution_payload.py
Normal file
26
tests/core/pyspec/eth2spec/test/helpers/execution_payload.py
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
def build_empty_execution_payload(spec, state):
|
||||
"""
|
||||
Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions.
|
||||
"""
|
||||
latest = state.latest_execution_payload_header
|
||||
timestamp = spec.compute_time_at_slot(state, state.slot)
|
||||
empty_txs = spec.List[spec.OpaqueTransaction, spec.MAX_EXECUTION_TRANSACTIONS]()
|
||||
|
||||
payload = spec.ExecutionPayload(
|
||||
block_hash=spec.Hash32(),
|
||||
parent_hash=latest.block_hash,
|
||||
coinbase=spec.Bytes20(),
|
||||
state_root=latest.state_root, # no changes to the state
|
||||
number=latest.number + 1,
|
||||
gas_limit=latest.gas_limit, # retain same limit
|
||||
gas_used=0, # empty block, 0 gas
|
||||
timestamp=timestamp,
|
||||
receipt_root=b"no receipts here" + b"\x00" * 16, # TODO: root of empty MPT may be better.
|
||||
logs_bloom=spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM](), # TODO: zeroed logs bloom for empty logs ok?
|
||||
transactions=empty_txs,
|
||||
)
|
||||
# TODO: real RLP + block hash logic would be nice, requires RLP and keccak256 dependency however.
|
||||
payload.block_hash = spec.Hash32(spec.hash(payload.hash_tree_root() + b"FAKE RLP HASH"))
|
||||
|
||||
return payload
|
||||
@@ -1,6 +1,7 @@
|
||||
from eth2spec.test.helpers.constants import (
|
||||
ALTAIR,
|
||||
FORKS_BEFORE_ALTAIR,
|
||||
MERGE,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
|
||||
@@ -28,6 +29,8 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
|
||||
|
||||
if spec.fork == ALTAIR:
|
||||
current_version = spec.ALTAIR_FORK_VERSION
|
||||
elif spec.fork == MERGE:
|
||||
current_version = spec.MERGE_FORK_VERSION
|
||||
|
||||
state = spec.BeaconState(
|
||||
genesis_time=0,
|
||||
|
||||
0
tests/core/pyspec/eth2spec/test/merge/__init__.py
Normal file
0
tests/core/pyspec/eth2spec/test/merge/__init__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from eth2spec.test.helpers.execution_payload import build_empty_execution_payload
|
||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_merge_and_later
|
||||
from eth2spec.test.helpers.state import next_slot
|
||||
|
||||
|
||||
def run_execution_payload_processing(spec, state, execution_payload, valid=True, execution_valid=True):
|
||||
"""
|
||||
Run ``process_execution_payload``, yielding:
|
||||
- pre-state ('pre')
|
||||
- execution payload ('execution_payload')
|
||||
- execution details, to mock EVM execution ('execution.yml', a dict with 'execution_valid' key and boolean value)
|
||||
- post-state ('post').
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
|
||||
pre_exec_header = state.latest_execution_payload_header.copy()
|
||||
|
||||
yield 'pre', state
|
||||
yield 'execution', {'execution_valid': execution_valid}
|
||||
yield 'execution_payload', execution_payload
|
||||
|
||||
if not valid:
|
||||
expect_assertion_error(lambda: spec.process_execution_payload(state, execution_payload))
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
spec.process_execution_payload(state, execution_payload)
|
||||
|
||||
yield 'post', state
|
||||
|
||||
assert pre_exec_header != state.latest_execution_payload_header
|
||||
# TODO: any more assertions to make?
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_success_first_payload(spec, state):
|
||||
next_slot(spec, state)
|
||||
assert not spec.is_transition_completed(state)
|
||||
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
25
tests/core/pyspec/eth2spec/test/merge/sanity/test_blocks.py
Normal file
25
tests/core/pyspec/eth2spec/test/merge/sanity/test_blocks.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from eth2spec.test.helpers.state import (
|
||||
state_transition_and_sign_block
|
||||
)
|
||||
from eth2spec.test.helpers.block import (
|
||||
build_empty_block_for_next_slot
|
||||
)
|
||||
from eth2spec.test.context import (
|
||||
with_merge_and_later, spec_state_test
|
||||
)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_empty_block_transition(spec, state):
|
||||
yield 'pre', state
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
assert len(block.body.execution_payload.transactions) == 0
|
||||
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
|
||||
yield 'blocks', [signed_block]
|
||||
yield 'post', state
|
||||
|
||||
# TODO: tests with EVM, mock or replacement?
|
||||
@@ -1,7 +1,7 @@
|
||||
from eth2spec.test.context import with_all_phases, spec_state_test
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||
from eth2spec.test.helpers.attestations import get_valid_attestation, sign_attestation
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
from eth2spec.test.helpers.state import transition_to, state_transition_and_sign_block, next_epoch, next_slot
|
||||
from eth2spec.test.helpers.fork_choice import get_genesis_forkchoice_store
|
||||
|
||||
@@ -19,7 +19,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
||||
spec.on_attestation(store, attestation)
|
||||
|
||||
sample_index = indexed_attestation.attesting_indices[0]
|
||||
if spec.fork in (PHASE0, ALTAIR):
|
||||
if spec.fork in (PHASE0, ALTAIR, MERGE):
|
||||
latest_message = spec.LatestMessage(
|
||||
epoch=attestation.data.target.epoch,
|
||||
root=attestation.data.beacon_block_root,
|
||||
|
||||
@@ -33,17 +33,23 @@ This excludes the other parts of the block-transition.
|
||||
|
||||
Operations:
|
||||
|
||||
| *`operation-name`* | *`operation-object`* | *`input name`* | *`processing call`* |
|
||||
|-------------------------|-----------------------|----------------------|-----------------------------------------------------------------|
|
||||
| `attestation` | `Attestation` | `attestation` | `process_attestation(state, attestation)` |
|
||||
| `attester_slashing` | `AttesterSlashing` | `attester_slashing` | `process_attester_slashing(state, attester_slashing)` |
|
||||
| `block_header` | `BeaconBlock` | **`block`** | `process_block_header(state, block)` |
|
||||
| `deposit` | `Deposit` | `deposit` | `process_deposit(state, deposit)` |
|
||||
| `proposer_slashing` | `ProposerSlashing` | `proposer_slashing` | `process_proposer_slashing(state, proposer_slashing)` |
|
||||
| `voluntary_exit` | `SignedVoluntaryExit` | `voluntary_exit` | `process_voluntary_exit(state, voluntary_exit)` |
|
||||
| `sync_aggregate` | `SyncAggregate` | `sync_aggregate` | `process_sync_committee(state, sync_aggregate)` (new in Altair) |
|
||||
| *`operation-name`* | *`operation-object`* | *`input name`* | *`processing call`* |
|
||||
|-------------------------|-----------------------|----------------------|----------------------------------------------------------------------|
|
||||
| `attestation` | `Attestation` | `attestation` | `process_attestation(state, attestation)` |
|
||||
| `attester_slashing` | `AttesterSlashing` | `attester_slashing` | `process_attester_slashing(state, attester_slashing)` |
|
||||
| `block_header` | `BeaconBlock` | **`block`** | `process_block_header(state, block)` |
|
||||
| `deposit` | `Deposit` | `deposit` | `process_deposit(state, deposit)` |
|
||||
| `proposer_slashing` | `ProposerSlashing` | `proposer_slashing` | `process_proposer_slashing(state, proposer_slashing)` |
|
||||
| `voluntary_exit` | `SignedVoluntaryExit` | `voluntary_exit` | `process_voluntary_exit(state, voluntary_exit)` |
|
||||
| `sync_aggregate` | `SyncAggregate` | `sync_aggregate` | `process_sync_committee(state, sync_aggregate)` (new in Altair) |
|
||||
| `execution_payload` | `ExecutionPayload` | `execution_payload` | `process_execution_payload(state, execution_payload)` (new in Merge) |
|
||||
|
||||
Note that `block_header` is not strictly an operation (and is a full `Block`), but processed in the same manner, and hence included here.
|
||||
|
||||
The `execution_payload` processing normally requires a `verify_execution_state_transition(execution_payload)`,
|
||||
a responsibility of an (external) execution engine.
|
||||
During testing this execution is mocked, an `execution.yml` is provided instead:
|
||||
a dict containing an `execution_valid` boolean field with the verification result.
|
||||
|
||||
The resulting state should match the expected `post` state, or if the `post` state is left blank,
|
||||
the handler should reject the input operation as invalid.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -27,6 +28,10 @@ if __name__ == "__main__":
|
||||
**phase_0_mods,
|
||||
} # also run the previous phase 0 tests
|
||||
|
||||
# No epoch-processing changes in Merge and previous testing repeats with new types, so no additional tests required.
|
||||
# TODO: rebase onto Altair testing later.
|
||||
merge_mods = phase_0_mods
|
||||
|
||||
# TODO Custody Game testgen is disabled for now
|
||||
# custody_game_mods = {**{key: 'eth2spec.test.custody_game.epoch_processing.test_process_' + key for key in [
|
||||
# 'reveal_deadlines',
|
||||
@@ -37,6 +42,7 @@ if __name__ == "__main__":
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="epoch_processing", specs=specs, all_mods=all_mods)
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {'finality': 'eth2spec.test.phase0.finality.test_finality'}
|
||||
altair_mods = phase_0_mods # No additional altair specific finality tests
|
||||
altair_mods = phase_0_mods # No additional Altair specific finality tests
|
||||
merge_mods = phase_0_mods # No additional Merge specific finality tests
|
||||
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: spec_merge,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="finality", specs=specs, all_mods=all_mods)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -13,10 +14,13 @@ if __name__ == "__main__":
|
||||
]}
|
||||
# No additional Altair specific finality tests, yet.
|
||||
altair_mods = phase_0_mods
|
||||
# No specific Merge tests yet. TODO: rebase onto Altair testing later.
|
||||
merge_mods = phase_0_mods
|
||||
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="fork_choice", specs=specs, all_mods=all_mods)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -23,6 +24,13 @@ if __name__ == "__main__":
|
||||
**phase_0_mods,
|
||||
} # also run the previous phase 0 tests
|
||||
|
||||
merge_mods = {
|
||||
**{key: 'eth2spec.test.merge.block_processing.test_process_' + key for key in [
|
||||
'execution_payload',
|
||||
]},
|
||||
**phase_0_mods, # TODO: runs phase0 tests. Rebase to include `altair_mods` testing later.
|
||||
}
|
||||
|
||||
# TODO Custody Game testgen is disabled for now
|
||||
# custody_game_mods = {**{key: 'eth2spec.test.custody_game.block_processing.test_process_' + key for key in [
|
||||
# 'attestation',
|
||||
@@ -35,6 +43,7 @@ if __name__ == "__main__":
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="operations", specs=specs, all_mods=all_mods)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -16,9 +17,15 @@ if __name__ == "__main__":
|
||||
# No additional altair specific rewards tests, yet.
|
||||
altair_mods = phase_0_mods
|
||||
|
||||
# No additional merge specific rewards tests, yet.
|
||||
# Note: Block rewards are non-epoch rewards and are tested as part of block processing tests.
|
||||
# Transaction fees are part of the execution-layer.
|
||||
merge_mods = phase_0_mods
|
||||
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="rewards", specs=specs, all_mods=all_mods)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -17,9 +18,15 @@ if __name__ == "__main__":
|
||||
'blocks',
|
||||
]}, **phase_0_mods} # also run the previous phase 0 tests
|
||||
|
||||
# Altair-specific test cases are ignored, but should be included after the Merge is rebased onto Altair work.
|
||||
merge_mods = {**{key: 'eth2spec.test.merge.sanity.test_' + key for key in [
|
||||
'blocks',
|
||||
]}, **phase_0_mods} # TODO: Merge inherits phase0 tests for now.
|
||||
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="sanity", specs=specs, all_mods=all_mods)
|
||||
|
||||
@@ -93,8 +93,7 @@ if __name__ == "__main__":
|
||||
seed += 1
|
||||
settings.append((seed, MAINNET, random_value.RandomizationMode.mode_random, False, 5))
|
||||
seed += 1
|
||||
# TODO: enable testing for the whole merge spec.
|
||||
for fork in TESTGEN_FORKS + (MERGE,):
|
||||
for fork in TESTGEN_FORKS:
|
||||
gen_runner.run_generator("ssz_static", [
|
||||
create_provider(fork, config_name, seed, mode, chaos, cases_if_random)
|
||||
for (seed, config_name, mode, chaos, cases_if_random) in settings
|
||||
|
||||
Reference in New Issue
Block a user