Merge pull request #2630 from ethereum/tests/merge-clean-up
#2598 + cleanups
This commit is contained in:
commit
d34b79f4de
|
@ -5,8 +5,8 @@ PRESET_BASE: 'mainnet'
|
|||
|
||||
# Transition
|
||||
# ---------------------------------------------------------------
|
||||
# TBD, 2**256-1 is a placeholder
|
||||
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129639935
|
||||
# TBD, 2**256-2**10 is a placeholder
|
||||
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129638912
|
||||
|
||||
|
||||
# Genesis
|
||||
|
|
|
@ -5,8 +5,8 @@ PRESET_BASE: 'minimal'
|
|||
|
||||
# Transition
|
||||
# ---------------------------------------------------------------
|
||||
# TBD, 2**256-1 is a placeholder
|
||||
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129639935
|
||||
# TBD, 2**256-2**10 is a placeholder
|
||||
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129638912
|
||||
|
||||
|
||||
# Genesis
|
||||
|
|
|
@ -55,8 +55,7 @@ def notify_forkchoice_updated(self: ExecutionEngine, head_block_hash: Hash32, fi
|
|||
### `PowBlock`
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class PowBlock(object):
|
||||
class PowBlock(Container):
|
||||
block_hash: Hash32
|
||||
parent_hash: Hash32
|
||||
total_difficulty: uint256
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
class SkippedTest(Exception):
|
||||
...
|
||||
|
||||
|
||||
class BlockNotFoundException(Exception):
|
||||
...
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from random import Random
|
||||
from eth_utils import encode_hex
|
||||
from eth2spec.test.exceptions import BlockNotFoundException
|
||||
from eth2spec.utils.ssz.ssz_typing import uint256
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
next_epoch_with_attestations,
|
||||
next_slots_with_attestations,
|
||||
|
@ -22,15 +25,22 @@ def add_block_to_store(spec, store, signed_block):
|
|||
spec.on_block(store, signed_block)
|
||||
|
||||
|
||||
def tick_and_add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_attestations=False):
|
||||
def tick_and_add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_attestations=False,
|
||||
merge_block=False, block_not_found=False):
|
||||
pre_state = store.block_states[signed_block.message.parent_root]
|
||||
block_time = pre_state.genesis_time + signed_block.message.slot * spec.config.SECONDS_PER_SLOT
|
||||
if merge_block:
|
||||
assert spec.is_merge_block(pre_state, signed_block.message.body)
|
||||
|
||||
if store.time < block_time:
|
||||
on_tick_and_append_step(spec, store, block_time, test_steps)
|
||||
|
||||
post_state = yield from add_block(
|
||||
spec, store, signed_block, test_steps, valid=valid, allow_invalid_attestations=allow_invalid_attestations)
|
||||
spec, store, signed_block, test_steps,
|
||||
valid=valid,
|
||||
allow_invalid_attestations=allow_invalid_attestations,
|
||||
block_not_found=block_not_found,
|
||||
)
|
||||
|
||||
return post_state
|
||||
|
||||
|
@ -118,7 +128,13 @@ def run_on_block(spec, store, signed_block, valid=True):
|
|||
assert store.blocks[signed_block.message.hash_tree_root()] == signed_block.message
|
||||
|
||||
|
||||
def add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_attestations=False):
|
||||
def add_block(spec,
|
||||
store,
|
||||
signed_block,
|
||||
test_steps,
|
||||
valid=True,
|
||||
allow_invalid_attestations=False,
|
||||
block_not_found=False):
|
||||
"""
|
||||
Run on_block and on_attestation
|
||||
"""
|
||||
|
@ -127,7 +143,9 @@ def add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_a
|
|||
if not valid:
|
||||
try:
|
||||
run_on_block(spec, store, signed_block, valid=True)
|
||||
except AssertionError:
|
||||
except (AssertionError, BlockNotFoundException) as e:
|
||||
if isinstance(e, BlockNotFoundException) and not block_not_found:
|
||||
assert False
|
||||
test_steps.append({
|
||||
'block': get_block_file_name(signed_block),
|
||||
'valid': False,
|
||||
|
@ -227,3 +245,21 @@ def apply_next_slots_with_attestations(spec,
|
|||
assert store.block_states[block_root].hash_tree_root() == post_state.hash_tree_root()
|
||||
|
||||
return post_state, store, last_signed_block
|
||||
|
||||
|
||||
def prepare_empty_pow_block(spec, rng=Random(3131)):
|
||||
return spec.PowBlock(
|
||||
block_hash=spec.Hash32(spec.hash(bytearray(rng.getrandbits(8) for _ in range(32)))),
|
||||
parent_hash=spec.Hash32(spec.hash(bytearray(rng.getrandbits(8) for _ in range(32)))),
|
||||
total_difficulty=uint256(0),
|
||||
difficulty=uint256(0)
|
||||
)
|
||||
|
||||
|
||||
def get_pow_block_file_name(pow_block):
|
||||
return f"pow_block_{encode_hex(pow_block.block_hash)}"
|
||||
|
||||
|
||||
def add_pow_block(spec, store, pow_block, test_steps):
|
||||
yield get_pow_block_file_name(pow_block), pow_block
|
||||
test_steps.append({'pow_block': get_pow_block_file_name(pow_block)})
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from eth2spec.utils.ssz.ssz_typing import uint64
|
||||
from eth2spec.test.helpers.execution_payload import (
|
||||
build_empty_execution_payload,
|
||||
get_execution_payload_header,
|
||||
|
@ -227,3 +228,157 @@ def test_bad_timestamp_regular_payload(spec, state):
|
|||
execution_payload.timestamp = execution_payload.timestamp + 1
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_zero_first_payload(spec, state):
|
||||
# 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.gas_limit = uint64(0)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_max_first_payload(spec, state):
|
||||
# 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.gas_limit = uint64(2**64 - 1)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_upper_plus_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.gas_limit = (
|
||||
execution_payload.gas_limit +
|
||||
execution_payload.gas_limit // spec.GAS_LIMIT_DENOMINATOR
|
||||
)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_upper_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.gas_limit = (
|
||||
execution_payload.gas_limit +
|
||||
execution_payload.gas_limit // spec.GAS_LIMIT_DENOMINATOR - uint64(1)
|
||||
)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_lower_minus_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.gas_limit = (
|
||||
execution_payload.gas_limit -
|
||||
execution_payload.gas_limit // spec.GAS_LIMIT_DENOMINATOR
|
||||
)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_lower_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.gas_limit = (
|
||||
execution_payload.gas_limit -
|
||||
execution_payload.gas_limit // spec.GAS_LIMIT_DENOMINATOR + uint64(1)
|
||||
)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_minimum_regular_payload(spec, state):
|
||||
# pre-state
|
||||
state = build_state_with_complete_transition(spec, state)
|
||||
next_slot(spec, state)
|
||||
state.latest_execution_payload_header.gas_limit = spec.MIN_GAS_LIMIT
|
||||
|
||||
# execution payload
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
execution_payload.gas_limit = execution_payload.gas_limit
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gaslimit_minimum_minus_regular_payload(spec, state):
|
||||
# pre-state
|
||||
state = build_state_with_complete_transition(spec, state)
|
||||
next_slot(spec, state)
|
||||
state.latest_execution_payload_header.gas_limit = spec.MIN_GAS_LIMIT
|
||||
|
||||
# execution payload
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
execution_payload.gas_limit = execution_payload.gas_limit - uint64(1)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gasused_gaslimit_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.gas_used = execution_payload.gas_limit
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_gasused_gaslimit_plus_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.gas_used = execution_payload.gas_limit + uint64(1)
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
from eth2spec.utils.ssz.ssz_typing import uint256
|
||||
from eth2spec.test.exceptions import BlockNotFoundException
|
||||
from eth2spec.test.context import spec_state_test, with_phases, MERGE
|
||||
from eth2spec.test.helpers.block import (
|
||||
build_empty_block_for_next_slot,
|
||||
)
|
||||
from eth2spec.test.helpers.fork_choice import (
|
||||
get_genesis_forkchoice_store_and_block,
|
||||
on_tick_and_append_step,
|
||||
tick_and_add_block,
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
state_transition_and_sign_block,
|
||||
)
|
||||
from eth2spec.test.helpers.fork_choice import (
|
||||
prepare_empty_pow_block,
|
||||
add_pow_block,
|
||||
)
|
||||
from eth2spec.test.helpers.execution_payload import (
|
||||
build_state_with_incomplete_transition,
|
||||
)
|
||||
|
||||
|
||||
def with_pow_block_patch(spec, blocks, func):
|
||||
def get_pow_block(hash: spec.Bytes32) -> spec.PowBlock:
|
||||
for block in blocks:
|
||||
if block.block_hash == hash:
|
||||
return block
|
||||
raise BlockNotFoundException()
|
||||
get_pow_block_backup = spec.get_pow_block
|
||||
spec.get_pow_block = get_pow_block
|
||||
|
||||
class AtomicBoolean():
|
||||
value = False
|
||||
is_called = AtomicBoolean()
|
||||
|
||||
def wrap(flag: AtomicBoolean):
|
||||
yield from func()
|
||||
flag.value = True
|
||||
|
||||
try:
|
||||
yield from wrap(is_called)
|
||||
finally:
|
||||
spec.get_pow_block = get_pow_block_backup
|
||||
assert is_called.value
|
||||
|
||||
|
||||
@with_phases([MERGE])
|
||||
@spec_state_test
|
||||
def test_all_valid(spec, state):
|
||||
test_steps = []
|
||||
# Initialization
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
|
||||
yield 'anchor_state', state
|
||||
yield 'anchor_block', anchor_block
|
||||
current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
|
||||
on_tick_and_append_step(spec, store, current_time, test_steps)
|
||||
assert store.time == current_time
|
||||
|
||||
pow_block_parent = prepare_empty_pow_block(spec)
|
||||
pow_block_parent.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
pow_block = prepare_empty_pow_block(spec)
|
||||
pow_block.parent_hash = pow_block_parent.block_hash
|
||||
pow_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
pow_blocks = [pow_block, pow_block_parent]
|
||||
for pb in pow_blocks:
|
||||
yield from add_pow_block(spec, store, pb, test_steps)
|
||||
|
||||
def run_func():
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.execution_payload.parent_hash = pow_block.block_hash
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
yield from tick_and_add_block(spec, store, signed_block, test_steps, merge_block=True)
|
||||
# valid
|
||||
assert spec.get_head(store) == signed_block.message.hash_tree_root()
|
||||
|
||||
yield from with_pow_block_patch(spec, pow_blocks, run_func)
|
||||
yield 'steps', test_steps
|
||||
|
||||
|
||||
@with_phases([MERGE])
|
||||
@spec_state_test
|
||||
def test_block_lookup_failed(spec, state):
|
||||
test_steps = []
|
||||
# Initialization
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
|
||||
yield 'anchor_state', state
|
||||
yield 'anchor_block', anchor_block
|
||||
current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
|
||||
on_tick_and_append_step(spec, store, current_time, test_steps)
|
||||
assert store.time == current_time
|
||||
|
||||
pow_block = prepare_empty_pow_block(spec)
|
||||
pow_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
pow_blocks = [pow_block]
|
||||
for pb in pow_blocks:
|
||||
yield from add_pow_block(spec, store, pb, test_steps)
|
||||
|
||||
def run_func():
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.execution_payload.parent_hash = pow_block.block_hash
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
yield from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True,
|
||||
block_not_found=True)
|
||||
|
||||
yield from with_pow_block_patch(spec, pow_blocks, run_func)
|
||||
yield 'steps', test_steps
|
||||
|
||||
|
||||
@with_phases([MERGE])
|
||||
@spec_state_test
|
||||
def test_too_early_for_merge(spec, state):
|
||||
test_steps = []
|
||||
# Initialization
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
|
||||
yield 'anchor_state', state
|
||||
yield 'anchor_block', anchor_block
|
||||
current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
|
||||
on_tick_and_append_step(spec, store, current_time, test_steps)
|
||||
assert store.time == current_time
|
||||
|
||||
pow_block_parent = prepare_empty_pow_block(spec)
|
||||
pow_block_parent.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(2)
|
||||
pow_block = prepare_empty_pow_block(spec)
|
||||
pow_block.parent_hash = pow_block_parent.block_hash
|
||||
pow_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
pow_blocks = [pow_block, pow_block_parent]
|
||||
for pb in pow_blocks:
|
||||
yield from add_pow_block(spec, store, pb, test_steps)
|
||||
|
||||
def run_func():
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.execution_payload.parent_hash = pow_block.block_hash
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
yield from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True)
|
||||
|
||||
yield from with_pow_block_patch(spec, pow_blocks, run_func)
|
||||
yield 'steps', test_steps
|
||||
|
||||
|
||||
@with_phases([MERGE])
|
||||
@spec_state_test
|
||||
def test_too_late_for_merge(spec, state):
|
||||
test_steps = []
|
||||
# Initialization
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
|
||||
yield 'anchor_state', state
|
||||
yield 'anchor_block', anchor_block
|
||||
current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
|
||||
on_tick_and_append_step(spec, store, current_time, test_steps)
|
||||
assert store.time == current_time
|
||||
|
||||
pow_block_parent = prepare_empty_pow_block(spec)
|
||||
pow_block_parent.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
pow_block = prepare_empty_pow_block(spec)
|
||||
pow_block.parent_hash = pow_block_parent.block_hash
|
||||
pow_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + uint256(1)
|
||||
pow_blocks = [pow_block, pow_block_parent]
|
||||
for pb in pow_blocks:
|
||||
yield from add_pow_block(spec, store, pb, test_steps)
|
||||
|
||||
def run_func():
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.execution_payload.parent_hash = pow_block.block_hash
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
yield from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True)
|
||||
|
||||
yield from with_pow_block_patch(spec, pow_blocks, run_func)
|
||||
yield 'steps', test_steps
|
|
@ -0,0 +1,143 @@
|
|||
from eth2spec.test.exceptions import BlockNotFoundException
|
||||
from eth2spec.utils.ssz.ssz_typing import uint256
|
||||
from eth2spec.test.helpers.fork_choice import (
|
||||
prepare_empty_pow_block,
|
||||
)
|
||||
from eth2spec.test.context import spec_state_test, with_merge_and_later
|
||||
|
||||
|
||||
# Copy of conditional merge part of `on_block(store: Store, signed_block: SignedBeaconBlock)` handler
|
||||
def validate_transition_execution_payload(spec, execution_payload):
|
||||
pow_block = spec.get_pow_block(execution_payload.parent_hash)
|
||||
pow_parent = spec.get_pow_block(pow_block.parent_hash)
|
||||
assert spec.is_valid_terminal_pow_block(pow_block, pow_parent)
|
||||
|
||||
|
||||
def run_validate_transition_execution_payload(spec, block, parent_block, payload,
|
||||
valid=True, block_lookup_success=True):
|
||||
"""
|
||||
Run ``validate_transition_execution_payload``
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
If ``block_lookup_success == False``, run expecting ``BlockNotFoundException``
|
||||
"""
|
||||
|
||||
def get_pow_block(hash: spec.Bytes32) -> spec.PowBlock:
|
||||
if hash == block.block_hash:
|
||||
return block
|
||||
elif hash == parent_block.block_hash:
|
||||
return parent_block
|
||||
else:
|
||||
raise BlockNotFoundException()
|
||||
save_pow_block = spec.get_pow_block
|
||||
|
||||
# Guido authorized everyone to do this
|
||||
spec.get_pow_block = get_pow_block
|
||||
exception_caught = False
|
||||
block_not_found_exception_caught = False
|
||||
try:
|
||||
validate_transition_execution_payload(spec, payload)
|
||||
except BlockNotFoundException:
|
||||
block_not_found_exception_caught = True
|
||||
except AssertionError:
|
||||
exception_caught = True
|
||||
except Exception as e:
|
||||
spec.get_pow_block = save_pow_block
|
||||
raise e
|
||||
spec.get_pow_block = save_pow_block
|
||||
|
||||
if block_lookup_success:
|
||||
assert not block_not_found_exception_caught
|
||||
else:
|
||||
assert block_not_found_exception_caught
|
||||
if valid:
|
||||
assert not exception_caught
|
||||
else:
|
||||
assert exception_caught
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_valid_terminal_pow_block_success_valid(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.parent_hash = parent_block.block_hash
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
|
||||
assert spec.is_valid_terminal_pow_block(block, parent_block)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_valid_terminal_pow_block_fail_before_terminal(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(2)
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.parent_hash = parent_block.block_hash
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
|
||||
assert not spec.is_valid_terminal_pow_block(block, parent_block)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_valid_terminal_pow_block_fail_just_after_terminal(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.parent_hash = parent_block.block_hash
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + uint256(1)
|
||||
|
||||
assert not spec.is_valid_terminal_pow_block(block, parent_block)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_validate_transition_execution_payload_success(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.parent_hash = parent_block.block_hash
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
payload = spec.ExecutionPayload()
|
||||
payload.parent_hash = block.block_hash
|
||||
run_validate_transition_execution_payload(spec, block, parent_block, payload)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_validate_transition_execution_payload_fail_block_lookup(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.parent_hash = parent_block.block_hash
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
payload = spec.ExecutionPayload()
|
||||
run_validate_transition_execution_payload(spec, block, parent_block, payload,
|
||||
block_lookup_success=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_validate_transition_execution_payload_fail_parent_block_lookup(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1)
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
payload = spec.ExecutionPayload()
|
||||
payload.parent_hash = block.block_hash
|
||||
run_validate_transition_execution_payload(spec, block, parent_block, payload,
|
||||
block_lookup_success=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_validate_transition_execution_payload_fail_after_terminal(spec, state):
|
||||
parent_block = prepare_empty_pow_block(spec)
|
||||
parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||
block = prepare_empty_pow_block(spec)
|
||||
block.parent_hash = parent_block.block_hash
|
||||
block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + 1
|
||||
payload = spec.ExecutionPayload()
|
||||
payload.parent_hash = block.block_hash
|
||||
run_validate_transition_execution_payload(spec, block, parent_block, payload, valid=False)
|
|
@ -0,0 +1,55 @@
|
|||
from eth2spec.test.helpers.execution_payload import (
|
||||
build_empty_execution_payload,
|
||||
build_state_with_incomplete_transition,
|
||||
build_state_with_complete_transition,
|
||||
)
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_merge_and_later
|
||||
)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_fail_merge_complete(spec, state):
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
assert not spec.is_merge_complete(state)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_success_merge_complete(spec, state):
|
||||
state = build_state_with_complete_transition(spec, state)
|
||||
assert spec.is_merge_complete(state)
|
||||
|
||||
|
||||
# with_complete_transition', 'with_execution_payload', 'is_merge_block', 'is_execution_enabled'
|
||||
expected_results = [
|
||||
(True, True, False, True),
|
||||
(True, False, False, True),
|
||||
(False, True, True, True),
|
||||
(False, False, False, False)
|
||||
]
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_is_merge_block_and_is_execution_enabled(spec, state):
|
||||
for result in expected_results:
|
||||
(
|
||||
with_complete_transition,
|
||||
with_execution_payload,
|
||||
is_merge_block,
|
||||
is_execution_enabled
|
||||
) = result
|
||||
if with_complete_transition:
|
||||
state = build_state_with_complete_transition(spec, state)
|
||||
else:
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
|
||||
body = spec.BeaconBlockBody()
|
||||
if with_execution_payload:
|
||||
body.execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
||||
assert spec.is_merge_block(state, body) == is_merge_block
|
||||
assert spec.is_execution_enabled(state, body) == is_execution_enabled
|
|
@ -69,6 +69,18 @@ The file is located in the same folder (see below).
|
|||
|
||||
After this step, the `store` object may have been updated.
|
||||
|
||||
#### `on_merge_block` execution
|
||||
|
||||
Adds `PowBlock` data which is required for executing `on_block(store, block)`.
|
||||
```yaml
|
||||
{
|
||||
pow_block: string -- the name of the `pow_block_<32-byte-root>.ssz_snappy` file.
|
||||
To be used in `get_pow_block` lookup
|
||||
}
|
||||
```
|
||||
The file is located in the same folder (see below).
|
||||
PowBlocks should be used as return values for `get_pow_block(hash: Hash32) -> PowBlock` function if hashes match.
|
||||
|
||||
#### Checks step
|
||||
|
||||
The checks to verify the current status of `store`.
|
||||
|
|
|
@ -9,8 +9,14 @@ if __name__ == "__main__":
|
|||
]}
|
||||
# No additional Altair specific finality tests, yet.
|
||||
altair_mods = phase_0_mods
|
||||
# No specific Merge tests yet.
|
||||
merge_mods = altair_mods
|
||||
# For merge `on_merge_block` test kind added with `pow_block_N.ssz` files with several
|
||||
# PowBlock's which should be resolved by `get_pow_block(hash: Hash32) -> PowBlock` function
|
||||
merge_mods = {
|
||||
**{key: 'eth2spec.test.merge.fork_choice.test_' + key for key in [
|
||||
'on_merge_block',
|
||||
]},
|
||||
**altair_mods,
|
||||
}
|
||||
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -8,9 +8,12 @@ if __name__ == "__main__":
|
|||
'validity',
|
||||
]}
|
||||
altair_mods = phase_0_mods
|
||||
# we have new unconditional lines in `initialize_beacon_state_from_eth1` and we want to test it
|
||||
merge_mods = altair_mods
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="genesis", all_mods=all_mods)
|
||||
|
|
Loading…
Reference in New Issue