Merge pull request #2737 from ethereum/test_prepare_execution_payload

Fix spec typo and add `test_prepare_execution_payload` unit tests
This commit is contained in:
Danny Ryan 2021-11-23 14:25:48 -07:00 committed by GitHub
commit 32e8ca26a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 99 additions and 1 deletions

View File

@ -125,7 +125,7 @@ def prepare_execution_payload(state: BeaconState,
execution_engine: ExecutionEngine) -> Optional[PayloadId]:
if not is_merge_complete(state):
is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32()
is_activation_epoch_reached = get_current_epoch(state.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
if is_terminal_block_hash_set and not is_activation_epoch_reached:
# Terminal block hash is set but activation epoch is not yet reached, no prepare payload call is needed
return None

View File

@ -1,3 +1,5 @@
from copy import deepcopy
from eth2spec.test.helpers.pow_block import (
prepare_random_pow_chain,
)
@ -62,3 +64,99 @@ def test_get_pow_block_at_terminal_total_difficulty(spec, state):
assert pow_block is None
else:
raise Exception('Something is wrong')
SAMPLE_PAYLOAD_ID = b'\x12' * 8
# ('is_merge_complete', 'is_terminal_block_hash_set', 'is_activation_epoch_reached',
# 'terminal_pow_block_is_none', 'result_payload_id')
prepare_execution_payload_expected_results = [
(False, False, False, False, SAMPLE_PAYLOAD_ID),
(False, False, False, True, None),
(False, False, True, False, SAMPLE_PAYLOAD_ID),
(False, False, True, True, None),
(False, True, False, False, None),
(False, True, False, True, None),
(False, True, True, False, SAMPLE_PAYLOAD_ID),
(False, True, True, True, None),
(True, False, False, False, SAMPLE_PAYLOAD_ID),
(True, False, False, True, SAMPLE_PAYLOAD_ID),
(True, False, True, False, SAMPLE_PAYLOAD_ID),
(True, False, True, True, SAMPLE_PAYLOAD_ID),
(True, True, False, False, SAMPLE_PAYLOAD_ID),
(True, True, False, True, SAMPLE_PAYLOAD_ID),
(True, True, True, False, SAMPLE_PAYLOAD_ID),
(True, True, True, True, SAMPLE_PAYLOAD_ID),
]
@with_merge_and_later
@spec_state_test
def test_prepare_execution_payload(spec, state):
for result in prepare_execution_payload_expected_results:
(
is_merge_complete,
is_terminal_block_hash_set,
is_activation_epoch_reached,
terminal_pow_block_is_none,
result_payload_id,
) = result
# 1. Handle `is_merge_complete`
if is_merge_complete:
state.latest_execution_payload_header = spec.ExecutionPayloadHeader(random=b'\x12' * 32)
else:
state.latest_execution_payload_header = spec.ExecutionPayloadHeader()
# 2. `is_terminal_block_hash_set` and `is_activation_epoch_reached` require mocking configs in runtime
config_overrides = {}
_mock_terminal_block_hash = b'\x34' * 32
if is_terminal_block_hash_set:
config_overrides['TERMINAL_BLOCK_HASH'] = _mock_terminal_block_hash
else:
config_overrides['TERMINAL_BLOCK_HASH'] = spec.Hash32()
# Default `TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH` is too big and too close to overflow
_mock_terminal_block_hash_activation_epoch = 3
config_overrides['TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH'] = _mock_terminal_block_hash_activation_epoch
if is_activation_epoch_reached:
state.slot = _mock_terminal_block_hash_activation_epoch * spec.SLOTS_PER_EPOCH
else:
state.slot = (_mock_terminal_block_hash_activation_epoch - 1) * spec.SLOTS_PER_EPOCH
# Logic from `with_config_overrides`
old_config = spec.config
tmp_config = deepcopy(old_config._asdict())
tmp_config.update(config_overrides)
config_types = spec.Configuration.__annotations__
test_config = {k: config_types[k](v) for k, v in tmp_config.items()}
spec.config = spec.Configuration(**test_config)
# 3. Handle `terminal_pow_block_is_none`
pow_chain = prepare_random_pow_chain(spec, 2)
if terminal_pow_block_is_none:
pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - 1
else:
if is_terminal_block_hash_set:
pow_chain.head().block_hash = _mock_terminal_block_hash
pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
# Dummy arguments
finalized_block_hash = b'\x56' * 32
suggested_fee_recipient = b'\x78' * 20
# Mock execution_engine
class TestEngine(spec.NoopExecutionEngine):
def notify_forkchoice_updated(self, parent_hash, finalized_block_hash, payload_attributes) -> bool:
return SAMPLE_PAYLOAD_ID
payload_id = spec.prepare_execution_payload(
state=state,
pow_chain=pow_chain.to_dict(),
finalized_block_hash=finalized_block_hash,
suggested_fee_recipient=suggested_fee_recipient,
execution_engine=TestEngine(),
)
assert payload_id == result_payload_id
# Restore config
spec.config = old_config