Implement execution payload tests

This commit is contained in:
Mikhail Kalinin 2021-05-10 16:12:23 +06:00
parent 2bc2a30887
commit e78e045847
3 changed files with 116 additions and 40 deletions

View File

@ -451,9 +451,9 @@ def get_execution_state(execution_state_root: Bytes32) -> ExecutionState:
def get_pow_chain_head() -> PowBlock:
pass
verify_execution_state_transition_ret_value = True
def verify_execution_state_transition(execution_payload: ExecutionPayload) -> bool:
return True
return verify_execution_state_transition_ret_value
def produce_execution_payload(parent_hash: Hash32, timestamp: uint64) -> ExecutionPayload:

View File

@ -1,4 +1,3 @@
def build_empty_execution_payload(spec, state):
"""
Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions.
@ -24,3 +23,33 @@ def build_empty_execution_payload(spec, state):
payload.block_hash = spec.Hash32(spec.hash(payload.hash_tree_root() + b"FAKE RLP HASH"))
return payload
def get_execution_payload_header(spec, execution_payload):
return spec.ExecutionPayloadHeader(
block_hash=execution_payload.block_hash,
parent_hash=execution_payload.parent_hash,
coinbase=execution_payload.coinbase,
state_root=execution_payload.state_root,
number=execution_payload.number,
gas_limit=execution_payload.gas_limit,
gas_used=execution_payload.gas_used,
timestamp=execution_payload.timestamp,
receipt_root=execution_payload.receipt_root,
logs_bloom=execution_payload.logs_bloom,
transactions_root=spec.hash_tree_root(execution_payload.transactions)
)
def build_state_with_incomplete_transition(spec, state):
return build_state_with_execution_payload_header(spec, state, spec.ExecutionPayloadHeader())
def build_state_with_complete_transition(spec, state):
pre_state_payload = build_empty_execution_payload(spec, state)
payload_header = get_execution_payload_header(spec, pre_state_payload)
return build_state_with_execution_payload_header(spec, state, payload_header)
def build_state_with_execution_payload_header(spec, state, execution_payload_header):
pre_state = state.copy()
pre_state.latest_execution_payload_header = execution_payload_header
return pre_state

View File

@ -1,4 +1,9 @@
from eth2spec.test.helpers.execution_payload import build_empty_execution_payload
from eth2spec.test.helpers.execution_payload import (
build_empty_execution_payload,
get_execution_payload_header,
build_state_with_incomplete_transition,
build_state_with_complete_transition,
)
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_merge_and_later
from eth2spec.test.helpers.state import next_slot
@ -13,31 +18,36 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True,
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
spec.verify_execution_state_transition_ret_value = execution_valid
if not valid:
expect_assertion_error(lambda: spec.process_execution_payload(state, execution_payload))
yield 'post', None
spec.verify_execution_state_transition_ret_value = True
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?
assert state.latest_execution_payload_header == get_execution_payload_header(spec, execution_payload)
spec.verify_execution_state_transition_ret_value = True
@with_merge_and_later
@spec_state_test
def test_success_first_payload(spec, state):
# pre-state
state = build_state_with_incomplete_transition(spec, state)
next_slot(spec, state)
assert not spec.is_transition_completed(state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
yield from run_execution_payload_processing(spec, state, execution_payload)
@ -46,11 +56,12 @@ def test_success_first_payload(spec, state):
@with_merge_and_later
@spec_state_test
def test_success_regular_payload(spec, state):
# TODO: setup state
assert spec.is_transition_completed(state)
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
yield from run_execution_payload_processing(spec, state, execution_payload)
@ -58,12 +69,13 @@ def test_success_regular_payload(spec, state):
@with_merge_and_later
@spec_state_test
def test_success_first_payload_with_gap_slot(spec, state):
# TODO: transition gap slot
# pre-state
state = build_state_with_incomplete_transition(spec, state)
next_slot(spec, state)
next_slot(spec, state)
assert not spec.is_transition_completed(state)
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
yield from run_execution_payload_processing(spec, state, execution_payload)
@ -71,12 +83,13 @@ def test_success_first_payload_with_gap_slot(spec, state):
@with_merge_and_later
@spec_state_test
def test_success_regular_payload_with_gap_slot(spec, state):
# TODO: setup state
assert spec.is_transition_completed(state)
# TODO: transition gap slot
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
next_slot(spec, state)
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
yield from run_execution_payload_processing(spec, state, execution_payload)
@ -86,8 +99,12 @@ def test_success_regular_payload_with_gap_slot(spec, state):
def test_bad_execution_first_payload(spec, state):
# completely valid payload, but execution itself fails (e.g. block exceeds gas limit)
# TODO: execution payload.
execution_payload = spec.ExecutionPayload()
# pre-state
state = build_state_with_incomplete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False)
@ -97,35 +114,55 @@ def test_bad_execution_first_payload(spec, state):
def test_bad_execution_regular_payload(spec, state):
# completely valid payload, but execution itself fails (e.g. block exceeds gas limit)
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False)
@with_merge_and_later
@spec_state_test
def test_bad_parent_hash_first_payload(spec, state):
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
def test_bad_parent_hash_regular_payload(spec, state):
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
execution_payload.parent_hash = spec.Hash32()
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
@with_merge_and_later
@spec_state_test
def test_bad_number_first_payload(spec, state):
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
def test_bad_number_regular_payload(spec, state):
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
execution_payload.number = execution_payload.number + 1
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
@with_merge_and_later
@spec_state_test
def test_bad_everything_first_payload(spec, state):
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
def test_bad_everything_regular_payload(spec, state):
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
execution_payload.parent_hash = spec.Hash32()
execution_payload.number = execution_payload.number + 1
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
@ -133,8 +170,13 @@ def test_bad_everything_first_payload(spec, state):
@with_merge_and_later
@spec_state_test
def test_bad_timestamp_first_payload(spec, state):
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
# pre-state
state = build_state_with_incomplete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
execution_payload.timestamp = execution_payload.timestamp + 1
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
@ -142,7 +184,12 @@ def test_bad_timestamp_first_payload(spec, state):
@with_merge_and_later
@spec_state_test
def test_bad_timestamp_regular_payload(spec, state):
# TODO: execution payload
execution_payload = spec.ExecutionPayload()
# pre-state
state = build_state_with_complete_transition(spec, state)
next_slot(spec, state)
# execution payload
execution_payload = build_empty_execution_payload(spec, state)
execution_payload.timestamp = execution_payload.timestamp + 1
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)