Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-7732 current fork spectests #3854

Open
wants to merge 65 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
714db1e
refactor genesis state for eip7732
potuz Jul 15, 2024
0ae49b0
Revert "Disable eip7732 tests like whisk-style"
potuz Jul 4, 2024
2be168c
Fixes some more python tests
potuz Aug 21, 2024
7e092f6
deal with new get_head reply
potuz Jul 4, 2024
800b27f
skip electra tests with a payload
potuz Jul 5, 2024
f45e829
run_execution_payload_processing post eip-7732
potuz Jul 5, 2024
de7bf8d
construct the header correctly
potuz Jul 5, 2024
5bb0dd8
get sample sidecars for eip 7732
potuz Jul 8, 2024
62f4cd2
use right sidecar proofs in tests
potuz Jul 8, 2024
0731099
fixed gindex
potuz Jul 8, 2024
ebeed79
keep deprecated kzg
potuz Jul 8, 2024
fa5cc0a
fix merkle proof tester
potuz Jul 8, 2024
4ee4805
fix validate_merge_block
potuz Jul 8, 2024
b9644a6
fix test_config_invariants
potuz Jul 8, 2024
8caa39e
use full latest block for genesis
potuz Jul 8, 2024
789322f
fix test_process_execution_payload
potuz Jul 8, 2024
43e9f2d
skip invalid withdrawal tests
potuz Jul 9, 2024
f5d61ce
skip invalid bellatrix tests
potuz Jul 9, 2024
5b22ff3
skip more invalid tests
potuz Jul 9, 2024
7f52e6d
skip some more tests and fix bellatrix execution_payload
potuz Jul 9, 2024
ab221ff
skip several more tests
potuz Aug 21, 2024
3de46b7
fix deneb process_execution_payload
potuz Jul 9, 2024
f7d7e1a
fix get_head
potuz Jul 9, 2024
e94a337
Fix execution payload testing in 7732
potuz Jul 15, 2024
f3238a0
Use full nodes
potuz Jul 15, 2024
ba8bb95
some forkchoice fixes
potuz Jul 15, 2024
7c84a5d
linter
potuz Jul 15, 2024
34a21f4
fix test_networking
potuz Jul 16, 2024
6c5f1cb
fix test_discard_equivocations_on_attester_slashing
potuz Jul 16, 2024
936a3d6
test_on_block_finalized_skip_slots
potuz Jul 16, 2024
6c50e26
fix test_discard_equivocations_slashed_validator_censoring
potuz Jul 16, 2024
ef4659b
bad state in test_filtered_block_tree
potuz Jul 16, 2024
3906e58
more head checks
potuz Jul 16, 2024
81009f6
skip honest reorg tests
potuz Jul 17, 2024
341da17
fix test_invalid_parent_from_same_slot
potuz Jul 17, 2024
d698023
fix payload transitions in test_reorg.py
potuz Jul 17, 2024
f9408f5
fix payload transition in test_voting_source_beyond_two_epoch
potuz Jul 17, 2024
54b9f10
Remove state from payload_state_transition
potuz Jul 22, 2024
04eae5b
fix test_on_block
potuz Jul 22, 2024
5aae7f2
add more fixes to test_on_block.py
potuz Jul 22, 2024
c7e2b5c
fix test_justification_withholding_reverse_order
potuz Jul 22, 2024
35a1a34
more payload transition additions
potuz Jul 22, 2024
5889859
fix test_justified_update_monotonic
potuz Jul 22, 2024
5e353b6
fix test_justified_update_not_realized_finality
potuz Jul 22, 2024
7c74ab2
fix test_filtered_block_tree
potuz Jul 22, 2024
49e68f2
fix attestation helpers
potuz Jul 22, 2024
9a923c2
get_store_full_state helper
potuz Jul 22, 2024
7df5538
fix test_proposer_boost_is_first_block
potuz Jul 22, 2024
2855395
fix test_justification_withholding_reverse_order
potuz Jul 22, 2024
8df692e
fix test_proposer_boost
potuz Jul 22, 2024
89d2764
fix test_justification_withholding
potuz Jul 23, 2024
3330025
fix test_on_block_checkpoints
potuz Jul 23, 2024
6e1797e
fix _run_include_votes_of_another_empty_chain
potuz Jul 23, 2024
eeb7097
Fix test_simple_attempted_reorg_without_enough_ffg_votes
potuz Jul 23, 2024
b315909
some small fixes
potuz Jul 23, 2024
ed33cbe
fix test_withholding_attack_unviable_honest_chain
potuz Jul 24, 2024
f31f5a2
fix test_withholding_attack
potuz Jul 24, 2024
3046c99
fix previous forks tests
potuz Jul 24, 2024
97f309c
doctoc
potuz Jul 24, 2024
4acbaca
fix some capella and bellatrix tests
potuz Jul 24, 2024
89a79cc
fix deneb tests
potuz Jul 24, 2024
e482735
fix electra tests
potuz Jul 24, 2024
2f3db22
fix linter
potuz Jul 24, 2024
6408770
enable 7732 in circleci
potuz Jul 24, 2024
9df37db
Update CircleCI image to Python3.12.4
hwwhww Aug 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,19 @@ jobs:
command: make citest fork=eip7594
- store_test_results:
path: tests/core/pyspec/test-reports
test-eip7732:
docker:
- image: cimg/python:3.12.4
working_directory: ~/specs-repo
steps:
- restore_cache:
key: v3-specs-repo-{{ .Branch }}-{{ .Revision }}
- restore_pyspec_cached_venv
- run:
name: Run py-tests
command: make citest fork=eip7732
- store_test_results:
path: tests/core/pyspec/test-reports
table_of_contents:
docker:
- image: circleci/node:10.16.3
Expand Down Expand Up @@ -323,6 +336,9 @@ workflows:
- test-eip7594:
requires:
- install_pyspec_test
- test-eip7732:
requires:
- install_pyspec_test
- table_of_contents
- codespell
- lint:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
needs: [lint,codespell,table_of_contents]
strategy:
matrix:
version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "whisk", "eip7594"]
version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "whisk", "eip7594", "eip7732"]
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down
80 changes: 80 additions & 0 deletions specs/_features/eip7732/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
- [New `verify_execution_payload_envelope_signature`](#new-verify_execution_payload_envelope_signature)
- [Modified `is_merge_transition_complete`](#modified-is_merge_transition_complete)
- [Modified `validate_merge_block`](#modified-validate_merge_block)
- [Testing](#testing)
- [Modified `initialize_beacon_state_from_eth1`](#modified-initialize_beacon_state_from_eth1)
- [Modified `is_merge_transition_complete`](#modified-is_merge_transition_complete-1)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
Expand Down Expand Up @@ -714,3 +717,80 @@ def validate_merge_block(block: BeaconBlock) -> None:
# Check if `pow_block` is a valid terminal PoW block
assert is_valid_terminal_pow_block(pow_block, pow_parent)
```

## Testing

### Modified `initialize_beacon_state_from_eth1`

*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP-7732 testing only.
Modifications include:
1. Use `EIP7732_FORK_VERSION` as the previous and current fork version.

```python
def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
eth1_timestamp: uint64,
deposits: Sequence[Deposit],
execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader()
) -> BeaconState:
fork = Fork(
previous_version=EIP7732_FORK_VERSION, # [Modified in EIP-7732]
current_version=EIP7732_FORK_VERSION, # [Modified in EIP-7732]
epoch=GENESIS_EPOCH,
)
state = BeaconState(
genesis_time=eth1_timestamp + GENESIS_DELAY,
fork=fork,
eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
deposit_requests_start_index=UNSET_DEPOSIT_REQUESTS_START_INDEX, # [New in Electra:EIP6110]
)

# Process deposits
leaves = list(map(lambda deposit: deposit.data, deposits))
for index, deposit in enumerate(deposits):
deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
process_deposit(state, deposit)

# Process deposit balance updates
for deposit in state.pending_balance_deposits:
increase_balance(state, deposit.index, deposit.amount)
state.pending_balance_deposits = []

# Process activations
for index, validator in enumerate(state.validators):
balance = state.balances[index]
# [Modified in Electra:EIP7251]
validator.effective_balance = min(
balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_validator_max_effective_balance(validator))
if validator.effective_balance >= MIN_ACTIVATION_BALANCE:
validator.activation_eligibility_epoch = GENESIS_EPOCH
validator.activation_epoch = GENESIS_EPOCH

# Set genesis validators root for domain separation and chain versioning
state.genesis_validators_root = hash_tree_root(state.validators)

# Fill in sync committees
# Note: A duplicate committee is assigned for the current and next committee at genesis
state.current_sync_committee = get_next_sync_committee(state)
state.next_sync_committee = get_next_sync_committee(state)

# Initialize the execution payload header
state.latest_execution_payload_header = execution_payload_header

return state
```

### Modified `is_merge_transition_complete`

The function `is_merge_transition_complete` is modified for test purposes only to include the hash tree root of the empty KZG commitment list

```python
def is_merge_transition_complete(state: BeaconState) -> bool:
header = ExecutionPayloadHeader()
kzgs = List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]()
header.blob_kzg_commitments_root = kzgs.hash_tree_root()

return state.latest_execution_payload_header != header
```
32 changes: 32 additions & 0 deletions specs/_features/eip7732/fork-choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
- [`seconds_into_slot`](#seconds_into_slot)
- [Modified `on_tick_per_slot`](#modified-on_tick_per_slot)
- [`on_payload_attestation_message`](#on_payload_attestation_message)
- [Modified `validate_merge_block`](#modified-validate_merge_block)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
Expand Down Expand Up @@ -561,3 +562,34 @@ def on_payload_attestation_message(
store.payload_withhold_boost_root = block.parent_root
store.payload_withhold_boost_full = is_parent_node_full(store, block)
```

### Modified `validate_merge_block`

The function `validate_merge_block` is modified for test purposes

```python
def validate_merge_block(block: BeaconBlock) -> None:
"""
Check the parent PoW block of execution payload is a valid terminal PoW block.

Note: Unavailable PoW block(s) may later become available,
and a client software MAY delay a call to ``validate_merge_block``
until the PoW block(s) become available.
"""
if TERMINAL_BLOCK_HASH != Hash32():
# If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
assert block.body.signed_execution_payload_header.message.parent_block_hash == TERMINAL_BLOCK_HASH
return

pow_block = get_pow_block(block.body.signed_execution_payload_header.message.parent_block_hash)
# Check if `pow_block` is available
assert pow_block is not None
pow_parent = get_pow_block(pow_block.parent_hash)
# Check if `pow_parent` is available
assert pow_parent is not None
# Check if `pow_block` is a valid terminal PoW block
assert is_valid_terminal_pow_block(pow_block, pow_parent)



Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
expect_assertion_error,
spec_state_test,
with_bellatrix_and_later,
with_bellatrix_until_eip7732,
with_phases,
)
from eth2spec.test.helpers.keys import privkeys
from eth2spec.test.helpers.state import next_slot
from eth2spec.test.helpers.forks import is_post_eip7732


def run_execution_payload_processing(spec, state, execution_payload, valid=True, execution_valid=True):
Expand All @@ -28,34 +31,68 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True,
If ``valid == False``, run expecting ``AssertionError``
"""
# Before Deneb, only `body.execution_payload` matters. `BeaconBlockBody` is just a wrapper.
body = spec.BeaconBlockBody(execution_payload=execution_payload)
# after EIP-7732 the execution payload is no longer in the body
if is_post_eip7732(spec):
envelope = spec.ExecutionPayloadEnvelope(
payload=execution_payload,
beacon_block_root=state.latest_block_header.hash_tree_root(),
payload_withheld=False,
)
post_state = state.copy()
post_state.latest_block_hash = execution_payload.block_hash
post_state.latest_full_slot = state.slot
envelope.state_root = post_state.hash_tree_root()
privkey = privkeys[0]
signature = spec.get_execution_payload_envelope_signature(
state,
envelope,
privkey,
)
signed_envelope = spec.SignedExecutionPayloadEnvelope(
message=envelope,
signature=signature,
)
else:
body = spec.BeaconBlockBody(execution_payload=execution_payload)

yield 'pre', state
yield 'execution', {'execution_valid': execution_valid}
yield 'body', body
if not is_post_eip7732(spec):
yield 'body', body

called_new_block = False

class TestEngine(spec.NoopExecutionEngine):
def verify_and_notify_new_payload(self, new_payload_request) -> bool:
nonlocal called_new_block, execution_valid
called_new_block = True
assert new_payload_request.execution_payload == body.execution_payload
assert new_payload_request.execution_payload == execution_payload
return execution_valid

if not valid:
expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine()))
if is_post_eip7732(spec):
expect_assertion_error(lambda: spec.process_execution_payload(state, signed_envelope, TestEngine()))
else:
expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine()))
yield 'post', None
return

spec.process_execution_payload(state, body, TestEngine())
if is_post_eip7732(spec):
spec.process_execution_payload(state, signed_envelope, TestEngine())
else:
spec.process_execution_payload(state, body, TestEngine())

# Make sure we called the engine
assert called_new_block

yield 'post', state

assert state.latest_execution_payload_header == get_execution_payload_header(spec, body.execution_payload)
if is_post_eip7732(spec):
assert state.latest_full_slot == state.slot
assert state.latest_block_hash == execution_payload.block_hash
else:
assert state.latest_execution_payload_header == get_execution_payload_header(
spec, state, body.execution_payload)


def run_success_test(spec, state):
Expand All @@ -65,15 +102,15 @@ def run_success_test(spec, state):
yield from run_execution_payload_processing(spec, state, execution_payload)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_success_first_payload(spec, state):
state = build_state_with_incomplete_transition(spec, state)

yield from run_success_test(spec, state)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_success_regular_payload(spec, state):
state = build_state_with_complete_transition(spec, state)
Expand All @@ -89,14 +126,14 @@ def run_gap_slot_test(spec, state):
yield from run_execution_payload_processing(spec, state, execution_payload)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_success_first_payload_with_gap_slot(spec, state):
state = build_state_with_incomplete_transition(spec, state)
yield from run_gap_slot_test(spec, state)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_success_regular_payload_with_gap_slot(spec, state):
state = build_state_with_complete_transition(spec, state)
Expand All @@ -111,14 +148,14 @@ def run_bad_execution_test(spec, state):
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_invalid_bad_execution_first_payload(spec, state):
state = build_state_with_incomplete_transition(spec, state)
yield from run_bad_execution_test(spec, state)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_invalid_bad_execution_regular_payload(spec, state):
state = build_state_with_complete_transition(spec, state)
Expand Down Expand Up @@ -255,14 +292,14 @@ def run_non_empty_extra_data_test(spec, state):
assert state.latest_execution_payload_header.extra_data == execution_payload.extra_data


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_non_empty_extra_data_first_payload(spec, state):
state = build_state_with_incomplete_transition(spec, state)
yield from run_non_empty_extra_data_test(spec, state)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_non_empty_extra_data_regular_payload(spec, state):
state = build_state_with_complete_transition(spec, state)
Expand All @@ -284,14 +321,14 @@ def run_non_empty_transactions_test(spec, state):
assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root()


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_non_empty_transactions_first_payload(spec, state):
state = build_state_with_incomplete_transition(spec, state)
yield from run_non_empty_extra_data_test(spec, state)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_non_empty_transactions_regular_payload(spec, state):
state = build_state_with_complete_transition(spec, state)
Expand All @@ -310,14 +347,14 @@ def run_zero_length_transaction_test(spec, state):
assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root()


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_zero_length_transaction_first_payload(spec, state):
state = build_state_with_incomplete_transition(spec, state)
yield from run_zero_length_transaction_test(spec, state)


@with_bellatrix_and_later
@with_bellatrix_until_eip7732
@spec_state_test
def test_zero_length_transaction_regular_payload(spec, state):
state = build_state_with_complete_transition(spec, state)
Expand All @@ -328,6 +365,11 @@ def run_randomized_non_validated_execution_fields_test(spec, state, rng, executi
next_slot(spec, state)
execution_payload = build_randomized_execution_payload(spec, state, rng)

if is_post_eip7732(spec):
state.latest_execution_payload_header.block_hash = execution_payload.block_hash
state.latest_execution_payload_header.gas_limit = execution_payload.gas_limit
state.latest_block_hash = execution_payload.parent_hash

yield from run_execution_payload_processing(
spec, state,
execution_payload,
Expand Down
Loading