Skip to content

Commit 797e865

Browse files
authored
Fix randao mix processing in Gloas (#4728)
h/t @StefanBratanov for finding this
1 parent 11e1509 commit 797e865

File tree

4 files changed

+78
-6
lines changed

4 files changed

+78
-6
lines changed

specs/gloas/beacon-chain.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ class ExecutionPayloadBid(Container):
191191
parent_block_hash: Hash32
192192
parent_block_root: Root
193193
block_hash: Hash32
194+
prev_randao: Bytes32
194195
fee_recipient: ExecutionAddress
195196
gas_limit: uint64
196197
builder_index: ValidatorIndex
@@ -984,6 +985,7 @@ def process_execution_payload_bid(state: BeaconState, block: BeaconBlock) -> Non
984985
# Verify that the bid is for the right parent block
985986
assert bid.parent_block_hash == state.latest_block_hash
986987
assert bid.parent_block_root == block.parent_root
988+
assert bid.prev_randao == get_randao_mix(state, get_current_epoch(state))
987989

988990
# Record the pending payment if there is some payment
989991
if amount > 0:
@@ -1253,6 +1255,7 @@ def process_execution_payload(
12531255
committed_bid = state.latest_execution_payload_bid
12541256
assert envelope.builder_index == committed_bid.builder_index
12551257
assert committed_bid.blob_kzg_commitments_root == hash_tree_root(envelope.blob_kzg_commitments)
1258+
assert committed_bid.prev_randao == payload.prev_randao
12561259

12571260
# Verify the withdrawals root
12581261
assert hash_tree_root(payload.withdrawals) == state.latest_withdrawals_root
@@ -1263,8 +1266,6 @@ def process_execution_payload(
12631266
assert committed_bid.block_hash == payload.block_hash
12641267
# Verify consistency of the parent hash with respect to the previous execution payload
12651268
assert payload.parent_hash == state.latest_block_hash
1266-
# Verify prev_randao
1267-
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
12681269
# Verify timestamp
12691270
assert payload.timestamp == compute_time_at_slot(state, state.slot)
12701271
# Verify commitments are under limit

tests/core/pyspec/eth2spec/test/gloas/block_processing/test_process_execution_payload.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def prepare_execution_payload_envelope(
169169
)
170170

171171

172-
def setup_state_with_payload_bid(spec, state, builder_index=None, value=None):
172+
def setup_state_with_payload_bid(spec, state, builder_index=None, value=None, prev_randao=None):
173173
"""
174174
Helper to setup state with a committed execution payload bid.
175175
This simulates the state after process_execution_payload_bid has run.
@@ -180,12 +180,16 @@ def setup_state_with_payload_bid(spec, state, builder_index=None, value=None):
180180
if value is None:
181181
value = spec.Gwei(0)
182182

183+
if prev_randao is None:
184+
prev_randao = spec.get_randao_mix(state, spec.get_current_epoch(state))
185+
183186
# Create and set the latest execution payload bid
184187
kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]()
185188
bid = spec.ExecutionPayloadBid(
186189
parent_block_hash=state.latest_block_hash,
187190
parent_block_root=state.latest_block_header.hash_tree_root(),
188191
block_hash=spec.Hash32(),
192+
prev_randao=prev_randao,
189193
fee_recipient=spec.ExecutionAddress(),
190194
gas_limit=spec.uint64(60000000),
191195
builder_index=builder_index,
@@ -837,6 +841,38 @@ def test_process_execution_payload_wrong_prev_randao(spec, state):
837841
yield from run_execution_payload_processing(spec, state, signed_envelope, valid=False)
838842

839843

844+
@with_gloas_and_later
845+
@spec_state_test
846+
@always_bls
847+
def test_process_execution_payload_bid_prev_randao_mismatch(spec, state):
848+
"""
849+
Test that committed_bid.prev_randao must equal payload.prev_randao
850+
"""
851+
proposer_index = spec.get_beacon_proposer_index(state)
852+
# Use a different validator as builder
853+
builder_index = (proposer_index + 1) % len(state.validators)
854+
make_validator_builder(spec, state, builder_index)
855+
856+
# Setup bid with one prev_randao value
857+
bid_prev_randao = spec.Bytes32(b"\x11" * 32)
858+
setup_state_with_payload_bid(
859+
spec, state, builder_index, spec.Gwei(2300000), prev_randao=bid_prev_randao
860+
)
861+
862+
execution_payload = build_empty_execution_payload(spec, state)
863+
execution_payload.block_hash = state.latest_execution_payload_bid.block_hash
864+
execution_payload.gas_limit = state.latest_execution_payload_bid.gas_limit
865+
execution_payload.parent_hash = state.latest_block_hash
866+
# Set payload with a different prev_randao value
867+
execution_payload.prev_randao = spec.Bytes32(b"\x22" * 32)
868+
869+
signed_envelope = prepare_execution_payload_envelope(
870+
spec, state, builder_index=builder_index, execution_payload=execution_payload
871+
)
872+
873+
yield from run_execution_payload_processing(spec, state, signed_envelope, valid=False)
874+
875+
840876
@with_gloas_and_later
841877
@spec_state_test
842878
@always_bls

tests/core/pyspec/eth2spec/test/gloas/block_processing/test_process_execution_payload_bid.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def prepare_signed_execution_payload_bid(
4747
gas_limit=None,
4848
block_hash=None,
4949
blob_kzg_commitments_root=None,
50+
prev_randao=None,
5051
valid_signature=True,
5152
):
5253
"""
@@ -88,10 +89,14 @@ def prepare_signed_execution_payload_bid(
8889
kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]()
8990
blob_kzg_commitments_root = kzg_list.hash_tree_root()
9091

92+
if prev_randao is None:
93+
prev_randao = spec.get_randao_mix(state, spec.get_current_epoch(state))
94+
9195
bid = spec.ExecutionPayloadBid(
9296
parent_block_hash=parent_block_hash,
9397
parent_block_root=parent_block_root,
9498
block_hash=block_hash,
99+
prev_randao=prev_randao,
95100
fee_recipient=fee_recipient,
96101
gas_limit=gas_limit,
97102
builder_index=builder_index,
@@ -821,3 +826,30 @@ def test_process_execution_payload_bid_wrong_parent_block_root(spec, state):
821826
block.body.signed_execution_payload_bid = signed_bid
822827

823828
yield from run_execution_payload_bid_processing(spec, state, block, valid=False)
829+
830+
831+
@with_gloas_and_later
832+
@spec_state_test
833+
def test_process_execution_payload_bid_wrong_prev_randao(spec, state):
834+
"""
835+
Test wrong prev_randao fails (bid.prev_randao != get_randao_mix)
836+
"""
837+
proposer_index = spec.get_beacon_proposer_index(state)
838+
839+
# Create block first to advance slot
840+
block = build_empty_block_for_next_slot(spec, state)
841+
842+
# Create bid with wrong prev_randao
843+
wrong_prev_randao = spec.Bytes32(b"\x42" * 32)
844+
signed_bid = prepare_signed_execution_payload_bid(
845+
spec,
846+
state,
847+
builder_index=proposer_index,
848+
slot=block.slot,
849+
parent_block_root=block.parent_root,
850+
prev_randao=wrong_prev_randao,
851+
)
852+
853+
block.body.signed_execution_payload_bid = signed_bid
854+
855+
yield from run_execution_payload_bid_processing(spec, state, block, valid=False)

tests/core/pyspec/eth2spec/test/helpers/execution_payload.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,12 @@ def build_empty_post_gloas_execution_payload_bid(spec, state):
323323
# to distinguish it from the genesis block hash and have
324324
# is_parent_node_full correctly return False
325325
empty_payload_hash = spec.Hash32(b"\x01" + b"\x00" * 31)
326+
prev_randao = spec.get_randao_mix(state, spec.get_current_epoch(state))
326327
return spec.ExecutionPayloadBid(
327328
parent_block_hash=state.latest_block_hash,
328329
parent_block_root=parent_block_root,
329330
block_hash=empty_payload_hash,
331+
prev_randao=prev_randao,
330332
fee_recipient=spec.ExecutionAddress(),
331333
gas_limit=spec.uint64(0),
332334
builder_index=builder_index,
@@ -362,15 +364,16 @@ def build_empty_execution_payload(spec, state, randao_mix=None):
362364
if is_post_gloas(spec):
363365
latest = state.latest_execution_payload_bid
364366
parent_hash = latest.parent_block_hash
367+
if randao_mix is None:
368+
randao_mix = state.latest_execution_payload_bid.prev_randao
365369
else:
366370
latest = state.latest_execution_payload_header
367371
parent_hash = latest.block_hash
372+
if randao_mix is None:
373+
randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state))
368374
timestamp = spec.compute_time_at_slot(state, state.slot)
369375
empty_txs = spec.List[spec.Transaction, spec.MAX_TRANSACTIONS_PER_PAYLOAD]()
370376

371-
if randao_mix is None:
372-
randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state))
373-
374377
payload = spec.ExecutionPayload(
375378
parent_hash=parent_hash,
376379
fee_recipient=spec.ExecutionAddress(),

0 commit comments

Comments
 (0)