start testing of merge functionality
This commit is contained in:
parent
521cffc3e9
commit
25d0d673a9
|
@ -8,7 +8,7 @@ from eth2spec.utils import bls
|
||||||
from .exceptions import SkippedTest
|
from .exceptions import SkippedTest
|
||||||
from .helpers.constants import (
|
from .helpers.constants import (
|
||||||
PHASE0, ALTAIR,
|
PHASE0, ALTAIR,
|
||||||
ALL_PHASES, FORKS_BEFORE_ALTAIR,
|
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_MERGE,
|
||||||
)
|
)
|
||||||
from .helpers.genesis import create_genesis_state
|
from .helpers.genesis import create_genesis_state
|
||||||
from .utils import vector_test, with_meta_tags
|
from .utils import vector_test, with_meta_tags
|
||||||
|
@ -365,3 +365,9 @@ def is_post_altair(spec):
|
||||||
if spec.fork in FORKS_BEFORE_ALTAIR:
|
if spec.fork in FORKS_BEFORE_ALTAIR:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_post_merge(spec):
|
||||||
|
if spec.fork in FORKS_BEFORE_MERGE:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
|
@ -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.test.helpers.keys import privkeys
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
from eth2spec.utils.bls import only_with_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):
|
if is_post_altair(spec):
|
||||||
empty_block.body.sync_aggregate.sync_committee_signature = spec.G2_POINT_AT_INFINITY
|
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)
|
apply_randao_reveal(spec, state, empty_block)
|
||||||
return empty_block
|
return empty_block
|
||||||
|
|
||||||
|
|
|
@ -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_root=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
|
|
@ -0,0 +1,147 @@
|
||||||
|
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||||
|
from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases_except
|
||||||
|
|
||||||
|
with_merge_and_later = with_all_phases_except([PHASE0, ALTAIR])
|
||||||
|
|
||||||
|
|
||||||
|
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``
|
||||||
|
"""
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# TODO: any assertions to make?
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_success_first_payload(spec, state):
|
||||||
|
assert not spec.is_transition_completed(state)
|
||||||
|
|
||||||
|
# TODO: execution payload
|
||||||
|
execution_payload = spec.ExecutionPayload()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_success_regular_payload(spec, state):
|
||||||
|
# TODO: setup state
|
||||||
|
assert spec.is_transition_completed(state)
|
||||||
|
|
||||||
|
# TODO: execution payload
|
||||||
|
execution_payload = spec.ExecutionPayload()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_success_first_payload_with_gap_slot(spec, state):
|
||||||
|
# TODO: transition gap slot
|
||||||
|
|
||||||
|
assert not spec.is_transition_completed(state)
|
||||||
|
|
||||||
|
# TODO: execution payload
|
||||||
|
execution_payload = spec.ExecutionPayload()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||||
|
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
# TODO: execution payload
|
||||||
|
execution_payload = spec.ExecutionPayload()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
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()
|
||||||
|
|
||||||
|
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_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()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_bad_timestamp_first_payload(spec, state):
|
||||||
|
# TODO: execution payload
|
||||||
|
execution_payload = spec.ExecutionPayload()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_bad_timestamp_regular_payload(spec, state):
|
||||||
|
# TODO: execution payload
|
||||||
|
execution_payload = spec.ExecutionPayload()
|
||||||
|
|
||||||
|
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||||
|
|
|
@ -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_all_phases, spec_state_test
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@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?
|
Loading…
Reference in New Issue