Skip to content

Commit fe73d4e

Browse files
authored
EIP-7732 current fork spectests (#3854)
1 parent 95c3fba commit fe73d4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+981
-316
lines changed

.circleci/config.yml

+16
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,19 @@ jobs:
181181
command: make test fork=eip7441
182182
- store_test_results:
183183
path: tests/core/pyspec/test-reports
184+
test-eip7732:
185+
docker:
186+
- image: cimg/python:3.12-node
187+
working_directory: ~/specs-repo
188+
steps:
189+
- restore_cache:
190+
key: v3-specs-repo-{{ .Branch }}-{{ .Revision }}
191+
- restore_pyspec_cached_venv
192+
- run:
193+
name: Run py-tests
194+
command: make test fork=eip7732
195+
- store_test_results:
196+
path: tests/core/pyspec/test-reports
184197
lint:
185198
docker:
186199
- image: cimg/python:3.12-node
@@ -227,6 +240,9 @@ workflows:
227240
- test-eip7441:
228241
requires:
229242
- install_pyspec_test
243+
- test-eip7732:
244+
requires:
245+
- install_pyspec_test
230246
- lint:
231247
requires:
232248
- install_pyspec_test

.github/workflows/run-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
needs: [lint]
6262
strategy:
6363
matrix:
64-
version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "fulu", "eip7441"]
64+
version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "fulu", "eip7441", "eip7732"]
6565
steps:
6666
- name: Checkout repository
6767
uses: actions/checkout@v4

presets/minimal/eip-7732.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
PTC_SIZE: 2
77
# 2**2 (= 4)
88
MAX_PAYLOAD_ATTESTATIONS: 4
9-
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH_EIP7732: 13
9+
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH_EIP7732: 14

specs/_features/eip7732/beacon-chain.md

+19-3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
- [Execution payload processing](#execution-payload-processing)
5858
- [New `verify_execution_payload_envelope_signature`](#new-verify_execution_payload_envelope_signature)
5959
- [New `process_execution_payload`](#new-process_execution_payload)
60+
- [Testing](#testing)
61+
- [Modified `is_merge_transition_complete`](#modified-is_merge_transition_complete-1)
6062

6163
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
6264
<!-- /TOC -->
@@ -716,9 +718,9 @@ def process_execution_payload(state: BeaconState,
716718
for operation in operations:
717719
fn(state, operation)
718720

719-
for_ops(requests.deposit_requests, process_deposit_request)
720-
for_ops(requests.withdrawal_requests, process_withdrawal_request)
721-
for_ops(requests.consolidation_requests, process_consolidation_request)
721+
for_ops(requests.deposits, process_deposit_request)
722+
for_ops(requests.withdrawals, process_withdrawal_request)
723+
for_ops(requests.consolidations, process_consolidation_request)
722724

723725
# Cache the execution payload header and proposer
724726
state.latest_block_hash = payload.block_hash
@@ -728,3 +730,17 @@ def process_execution_payload(state: BeaconState,
728730
if verify:
729731
assert envelope.state_root == hash_tree_root(state)
730732
```
733+
734+
## Testing
735+
736+
### Modified `is_merge_transition_complete`
737+
738+
The function `is_merge_transition_complete` is modified for test purposes only to include the hash tree root of the empty KZG commitment list
739+
740+
```python
741+
def is_merge_transition_complete(state: BeaconState) -> bool:
742+
header = ExecutionPayloadHeader()
743+
kzgs = List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]()
744+
header.blob_kzg_commitments_root = kzgs.hash_tree_root()
745+
746+
return state.latest_execution_payload_header != header

specs/_features/eip7732/fork-choice.md

+32
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
- [`seconds_into_slot`](#seconds_into_slot)
3636
- [Modified `on_tick_per_slot`](#modified-on_tick_per_slot)
3737
- [`on_payload_attestation_message`](#on_payload_attestation_message)
38+
- [Modified `validate_merge_block`](#modified-validate_merge_block)
3839

3940
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
4041
<!-- /TOC -->
@@ -573,3 +574,34 @@ def on_payload_attestation_message(
573574
store.payload_withhold_boost_root = block.parent_root
574575
store.payload_withhold_boost_full = is_parent_node_full(store, block)
575576
```
577+
578+
### Modified `validate_merge_block`
579+
580+
The function `validate_merge_block` is modified for test purposes
581+
582+
```python
583+
def validate_merge_block(block: BeaconBlock) -> None:
584+
"""
585+
Check the parent PoW block of execution payload is a valid terminal PoW block.
586+
587+
Note: Unavailable PoW block(s) may later become available,
588+
and a client software MAY delay a call to ``validate_merge_block``
589+
until the PoW block(s) become available.
590+
"""
591+
if TERMINAL_BLOCK_HASH != Hash32():
592+
# If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
593+
assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
594+
assert block.body.signed_execution_payload_header.message.parent_block_hash == TERMINAL_BLOCK_HASH
595+
return
596+
597+
pow_block = get_pow_block(block.body.signed_execution_payload_header.message.parent_block_hash)
598+
# Check if `pow_block` is available
599+
assert pow_block is not None
600+
pow_parent = get_pow_block(pow_block.parent_hash)
601+
# Check if `pow_parent` is available
602+
assert pow_parent is not None
603+
# Check if `pow_block` is a valid terminal PoW block
604+
assert is_valid_terminal_pow_block(pow_block, pow_parent)
605+
606+
607+

tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py

+64-22
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
expect_assertion_error,
1414
spec_state_test,
1515
with_bellatrix_and_later,
16+
with_bellatrix_until_eip7732,
1617
with_phases,
1718
)
19+
from eth2spec.test.helpers.keys import privkeys
1820
from eth2spec.test.helpers.state import next_slot
21+
from eth2spec.test.helpers.forks import is_post_eip7732
1922

2023

2124
def run_execution_payload_processing(spec, state, execution_payload, valid=True, execution_valid=True):
@@ -28,34 +31,68 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True,
2831
If ``valid == False``, run expecting ``AssertionError``
2932
"""
3033
# Before Deneb, only `body.execution_payload` matters. `BeaconBlockBody` is just a wrapper.
31-
body = spec.BeaconBlockBody(execution_payload=execution_payload)
34+
# after EIP-7732 the execution payload is no longer in the body
35+
if is_post_eip7732(spec):
36+
envelope = spec.ExecutionPayloadEnvelope(
37+
payload=execution_payload,
38+
beacon_block_root=state.latest_block_header.hash_tree_root(),
39+
payload_withheld=False,
40+
)
41+
post_state = state.copy()
42+
post_state.latest_block_hash = execution_payload.block_hash
43+
post_state.latest_full_slot = state.slot
44+
envelope.state_root = post_state.hash_tree_root()
45+
privkey = privkeys[envelope.builder_index]
46+
signature = spec.get_execution_payload_envelope_signature(
47+
state,
48+
envelope,
49+
privkey,
50+
)
51+
signed_envelope = spec.SignedExecutionPayloadEnvelope(
52+
message=envelope,
53+
signature=signature,
54+
)
55+
else:
56+
body = spec.BeaconBlockBody(execution_payload=execution_payload)
3257

3358
yield 'pre', state
3459
yield 'execution', {'execution_valid': execution_valid}
35-
yield 'body', body
60+
if not is_post_eip7732(spec):
61+
yield 'body', body
3662

3763
called_new_block = False
3864

3965
class TestEngine(spec.NoopExecutionEngine):
4066
def verify_and_notify_new_payload(self, new_payload_request) -> bool:
4167
nonlocal called_new_block, execution_valid
4268
called_new_block = True
43-
assert new_payload_request.execution_payload == body.execution_payload
69+
assert new_payload_request.execution_payload == execution_payload
4470
return execution_valid
4571

4672
if not valid:
47-
expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine()))
73+
if is_post_eip7732(spec):
74+
expect_assertion_error(lambda: spec.process_execution_payload(state, signed_envelope, TestEngine()))
75+
else:
76+
expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine()))
4877
yield 'post', None
4978
return
5079

51-
spec.process_execution_payload(state, body, TestEngine())
80+
if is_post_eip7732(spec):
81+
spec.process_execution_payload(state, signed_envelope, TestEngine())
82+
else:
83+
spec.process_execution_payload(state, body, TestEngine())
5284

5385
# Make sure we called the engine
5486
assert called_new_block
5587

5688
yield 'post', state
5789

58-
assert state.latest_execution_payload_header == get_execution_payload_header(spec, body.execution_payload)
90+
if is_post_eip7732(spec):
91+
assert state.latest_full_slot == state.slot
92+
assert state.latest_block_hash == execution_payload.block_hash
93+
else:
94+
assert state.latest_execution_payload_header == get_execution_payload_header(
95+
spec, state, body.execution_payload)
5996

6097

6198
def run_success_test(spec, state):
@@ -65,15 +102,15 @@ def run_success_test(spec, state):
65102
yield from run_execution_payload_processing(spec, state, execution_payload)
66103

67104

68-
@with_bellatrix_and_later
105+
@with_bellatrix_until_eip7732
69106
@spec_state_test
70107
def test_success_first_payload(spec, state):
71108
state = build_state_with_incomplete_transition(spec, state)
72109

73110
yield from run_success_test(spec, state)
74111

75112

76-
@with_bellatrix_and_later
113+
@with_bellatrix_until_eip7732
77114
@spec_state_test
78115
def test_success_regular_payload(spec, state):
79116
state = build_state_with_complete_transition(spec, state)
@@ -89,14 +126,14 @@ def run_gap_slot_test(spec, state):
89126
yield from run_execution_payload_processing(spec, state, execution_payload)
90127

91128

92-
@with_bellatrix_and_later
129+
@with_bellatrix_until_eip7732
93130
@spec_state_test
94131
def test_success_first_payload_with_gap_slot(spec, state):
95132
state = build_state_with_incomplete_transition(spec, state)
96133
yield from run_gap_slot_test(spec, state)
97134

98135

99-
@with_bellatrix_and_later
136+
@with_bellatrix_until_eip7732
100137
@spec_state_test
101138
def test_success_regular_payload_with_gap_slot(spec, state):
102139
state = build_state_with_complete_transition(spec, state)
@@ -111,14 +148,14 @@ def run_bad_execution_test(spec, state):
111148
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False)
112149

113150

114-
@with_bellatrix_and_later
151+
@with_bellatrix_until_eip7732
115152
@spec_state_test
116153
def test_invalid_bad_execution_first_payload(spec, state):
117154
state = build_state_with_incomplete_transition(spec, state)
118155
yield from run_bad_execution_test(spec, state)
119156

120157

121-
@with_bellatrix_and_later
158+
@with_bellatrix_until_eip7732
122159
@spec_state_test
123160
def test_invalid_bad_execution_regular_payload(spec, state):
124161
state = build_state_with_complete_transition(spec, state)
@@ -255,14 +292,14 @@ def run_non_empty_extra_data_test(spec, state):
255292
assert state.latest_execution_payload_header.extra_data == execution_payload.extra_data
256293

257294

258-
@with_bellatrix_and_later
295+
@with_bellatrix_until_eip7732
259296
@spec_state_test
260297
def test_non_empty_extra_data_first_payload(spec, state):
261298
state = build_state_with_incomplete_transition(spec, state)
262299
yield from run_non_empty_extra_data_test(spec, state)
263300

264301

265-
@with_bellatrix_and_later
302+
@with_bellatrix_until_eip7732
266303
@spec_state_test
267304
def test_non_empty_extra_data_regular_payload(spec, state):
268305
state = build_state_with_complete_transition(spec, state)
@@ -284,14 +321,14 @@ def run_non_empty_transactions_test(spec, state):
284321
assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root()
285322

286323

287-
@with_bellatrix_and_later
324+
@with_bellatrix_until_eip7732
288325
@spec_state_test
289326
def test_non_empty_transactions_first_payload(spec, state):
290327
state = build_state_with_incomplete_transition(spec, state)
291328
yield from run_non_empty_extra_data_test(spec, state)
292329

293330

294-
@with_bellatrix_and_later
331+
@with_bellatrix_until_eip7732
295332
@spec_state_test
296333
def test_non_empty_transactions_regular_payload(spec, state):
297334
state = build_state_with_complete_transition(spec, state)
@@ -310,14 +347,14 @@ def run_zero_length_transaction_test(spec, state):
310347
assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root()
311348

312349

313-
@with_bellatrix_and_later
350+
@with_bellatrix_until_eip7732
314351
@spec_state_test
315352
def test_zero_length_transaction_first_payload(spec, state):
316353
state = build_state_with_incomplete_transition(spec, state)
317354
yield from run_zero_length_transaction_test(spec, state)
318355

319356

320-
@with_bellatrix_and_later
357+
@with_bellatrix_until_eip7732
321358
@spec_state_test
322359
def test_zero_length_transaction_regular_payload(spec, state):
323360
state = build_state_with_complete_transition(spec, state)
@@ -328,38 +365,43 @@ def run_randomized_non_validated_execution_fields_test(spec, state, rng, executi
328365
next_slot(spec, state)
329366
execution_payload = build_randomized_execution_payload(spec, state, rng)
330367

368+
if is_post_eip7732(spec):
369+
state.latest_execution_payload_header.block_hash = execution_payload.block_hash
370+
state.latest_execution_payload_header.gas_limit = execution_payload.gas_limit
371+
state.latest_block_hash = execution_payload.parent_hash
372+
331373
yield from run_execution_payload_processing(
332374
spec, state,
333375
execution_payload,
334376
valid=execution_valid, execution_valid=execution_valid
335377
)
336378

337379

338-
@with_bellatrix_and_later
380+
@with_bellatrix_until_eip7732
339381
@spec_state_test
340382
def test_randomized_non_validated_execution_fields_first_payload__execution_valid(spec, state):
341383
rng = Random(1111)
342384
state = build_state_with_incomplete_transition(spec, state)
343385
yield from run_randomized_non_validated_execution_fields_test(spec, state, rng)
344386

345387

346-
@with_bellatrix_and_later
388+
@with_bellatrix_until_eip7732
347389
@spec_state_test
348390
def test_randomized_non_validated_execution_fields_regular_payload__execution_valid(spec, state):
349391
rng = Random(2222)
350392
state = build_state_with_complete_transition(spec, state)
351393
yield from run_randomized_non_validated_execution_fields_test(spec, state, rng)
352394

353395

354-
@with_bellatrix_and_later
396+
@with_bellatrix_until_eip7732
355397
@spec_state_test
356398
def test_invalid_randomized_non_validated_execution_fields_first_payload__execution_invalid(spec, state):
357399
rng = Random(3333)
358400
state = build_state_with_incomplete_transition(spec, state)
359401
yield from run_randomized_non_validated_execution_fields_test(spec, state, rng, execution_valid=False)
360402

361403

362-
@with_bellatrix_and_later
404+
@with_bellatrix_until_eip7732
363405
@spec_state_test
364406
def test_invalid_randomized_non_validated_execution_fields_regular_payload__execution_invalid(spec, state):
365407
rng = Random(4444)

tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_should_override_forkchoice_update.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from eth2spec.test.context import (
22
spec_state_test,
3-
with_bellatrix_and_later,
3+
with_bellatrix_until_eip7732,
44
with_presets,
55
)
66
from eth2spec.test.helpers.constants import (
@@ -28,7 +28,7 @@
2828
)
2929

3030

31-
@with_bellatrix_and_later
31+
@with_bellatrix_until_eip7732
3232
@spec_state_test
3333
@with_presets([MINIMAL], reason="too slow")
3434
def test_should_override_forkchoice_update__false(spec, state):
@@ -73,7 +73,7 @@ def test_should_override_forkchoice_update__false(spec, state):
7373
yield 'steps', test_steps
7474

7575

76-
@with_bellatrix_and_later
76+
@with_bellatrix_until_eip7732
7777
@spec_state_test
7878
def test_should_override_forkchoice_update__true(spec, state):
7979
test_steps = []

0 commit comments

Comments
 (0)