diff --git a/specs/merge/beacon-chain.md b/specs/merge/beacon-chain.md index 47e69e918..7823a664d 100644 --- a/specs/merge/beacon-chain.md +++ b/specs/merge/beacon-chain.md @@ -191,25 +191,22 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: process_eth1_data(state, block.body) process_operations(state, block.body) if is_execution_enabled(state, block.body): - # [New in Merge] - randao_mix = get_randao_mix(state, get_current_epoch(state)) - process_execution_payload(state, block.body.execution_payload, randao_mix, EXECUTION_ENGINE) + process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [New in Merge] ``` ### Execution payload processing #### `process_execution_payload` +*Note:* This function depends on `process_randao` function call as it retrieves the most recent randao mix from the `state`. Implementations that are considering parallel processing of execution payload with respect to beacon chain state transition function should work around this dependency. + ```python -def process_execution_payload(state: BeaconState, - payload: ExecutionPayload, - randao_mix: Bytes32, - execution_engine: ExecutionEngine) -> None: +def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None: # Verify consistency of the parent hash, block number and random if is_merge_complete(state): assert payload.parent_hash == state.latest_execution_payload_header.block_hash assert payload.block_number == state.latest_execution_payload_header.block_number + uint64(1) - assert payload.random == randao_mix + assert payload.random == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp assert payload.timestamp == compute_timestamp_at_slot(state, state.slot) # Verify the execution payload is valid @@ -241,7 +238,6 @@ def process_execution_payload(state: BeaconState, def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32, eth1_timestamp: uint64, deposits: Sequence[Deposit]) -> BeaconState: - randao_seed = eth1_block_hash fork = Fork( previous_version=GENESIS_FORK_VERSION, current_version=MERGE_FORK_VERSION, # [Modified in Merge] @@ -252,7 +248,7 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32, 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=[randao_seed] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy + randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy ) # Process deposits @@ -276,7 +272,7 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32, # [New in Merge] Initialize the execution payload header (with block number set to 0) state.latest_execution_payload_header.block_hash = eth1_block_hash state.latest_execution_payload_header.timestamp = eth1_timestamp - state.latest_execution_payload_header.random = randao_seed + state.latest_execution_payload_header.random = eth1_block_hash return state ``` diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 41fa3117d..1ef63eaaf 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -1,8 +1,4 @@ -def build_empty_execution_payload_with_zeroed_random(spec, state): - return build_empty_execution_payload(spec, state, spec.Bytes32()) - - -def build_empty_execution_payload(spec, state, random): +def build_empty_execution_payload(spec, state, randao_mix=None): """ Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions. """ @@ -10,6 +6,9 @@ def build_empty_execution_payload(spec, state, random): timestamp = spec.compute_time_at_slot(state, state.slot) empty_txs = spec.List[spec.Transaction, spec.MAX_TRANSACTIONS_PER_PAYLOAD]() + if randao_mix is None: + randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state)) + payload = spec.ExecutionPayload( parent_hash=latest.block_hash, coinbase=spec.Bytes20(), @@ -17,7 +16,7 @@ def build_empty_execution_payload(spec, state, random): 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? block_number=latest.block_number + 1, - random=random, + random=randao_mix, gas_limit=latest.gas_limit, # retain same limit gas_used=0, # empty block, 0 gas timestamp=timestamp, diff --git a/tests/core/pyspec/eth2spec/test/merge/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/merge/block_processing/test_process_execution_payload.py index 4f6c98705..15c69f2dd 100644 --- a/tests/core/pyspec/eth2spec/test/merge/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/merge/block_processing/test_process_execution_payload.py @@ -1,5 +1,5 @@ from eth2spec.test.helpers.execution_payload import ( - build_empty_execution_payload_with_zeroed_random, + build_empty_execution_payload, get_execution_payload_header, build_state_with_incomplete_transition, build_state_with_complete_transition, @@ -22,7 +22,6 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True, yield 'execution', {'execution_valid': execution_valid} yield 'execution_payload', execution_payload - randao_mix = spec.Bytes32() called_new_block = False class TestEngine(spec.NoopExecutionEngine): @@ -34,11 +33,11 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True, if not valid: expect_assertion_error( - lambda: spec.process_execution_payload(state, execution_payload, randao_mix, TestEngine())) + lambda: spec.process_execution_payload(state, execution_payload, TestEngine())) yield 'post', None return - spec.process_execution_payload(state, execution_payload, randao_mix, TestEngine()) + spec.process_execution_payload(state, execution_payload, TestEngine()) # Make sure we called the engine assert called_new_block @@ -56,7 +55,7 @@ def test_success_first_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload) @@ -69,7 +68,7 @@ def test_success_regular_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload) @@ -83,7 +82,7 @@ def test_success_first_payload_with_gap_slot(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload) @@ -97,7 +96,7 @@ def test_success_regular_payload_with_gap_slot(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload) @@ -112,7 +111,7 @@ def test_bad_execution_first_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False) @@ -127,7 +126,7 @@ def test_bad_execution_regular_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False) @@ -140,7 +139,7 @@ def test_bad_parent_hash_regular_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + 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) @@ -154,7 +153,7 @@ def test_bad_number_regular_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) execution_payload.block_number = execution_payload.block_number + 1 yield from run_execution_payload_processing(spec, state, execution_payload, valid=False) @@ -168,7 +167,7 @@ def test_bad_everything_regular_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + execution_payload = build_empty_execution_payload(spec, state) execution_payload.parent_hash = spec.Hash32() execution_payload.block_number = execution_payload.block_number + 1 @@ -183,7 +182,7 @@ def test_bad_timestamp_first_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + 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) @@ -197,7 +196,7 @@ def test_bad_timestamp_regular_payload(spec, state): next_slot(spec, state) # execution payload - execution_payload = build_empty_execution_payload_with_zeroed_random(spec, state) + 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)