Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions specs/gloas/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ class ExecutionPayloadBid(Container):
parent_block_hash: Hash32
parent_block_root: Root
block_hash: Hash32
prev_randao: Bytes32
fee_recipient: ExecutionAddress
gas_limit: uint64
builder_index: ValidatorIndex
Expand Down Expand Up @@ -994,6 +995,7 @@ def process_execution_payload_bid(state: BeaconState, block: BeaconBlock) -> Non
# Verify that the bid is for the right parent block
assert bid.parent_block_hash == state.latest_block_hash
assert bid.parent_block_root == block.parent_root
assert bid.prev_randao == get_randao_mix(state, get_current_epoch(state))

# Record the pending payment if there is some payment
if amount > 0:
Expand Down Expand Up @@ -1310,6 +1312,7 @@ def process_execution_payload(
committed_bid = state.latest_execution_payload_bid
assert envelope.builder_index == committed_bid.builder_index
assert committed_bid.blob_kzg_commitments_root == hash_tree_root(envelope.blob_kzg_commitments)
assert committed_bid.prev_randao == payload.prev_randao

# Verify the withdrawals root
assert hash_tree_root(payload.withdrawals) == state.latest_withdrawals_root
Expand All @@ -1320,8 +1323,6 @@ def process_execution_payload(
assert committed_bid.block_hash == payload.block_hash
# Verify consistency of the parent hash with respect to the previous execution payload
assert payload.parent_hash == state.latest_block_hash
# Verify prev_randao
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
# Verify timestamp
assert payload.timestamp == compute_time_at_slot(state, state.slot)
# Verify commitments are under limit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def prepare_execution_payload_envelope(
)


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

if prev_randao is None:
prev_randao = spec.get_randao_mix(state, spec.get_current_epoch(state))

# Create and set the latest execution payload bid
kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]()
bid = spec.ExecutionPayloadBid(
parent_block_hash=state.latest_block_hash,
parent_block_root=state.latest_block_header.hash_tree_root(),
block_hash=spec.Hash32(),
prev_randao=prev_randao,
fee_recipient=spec.ExecutionAddress(),
gas_limit=spec.uint64(60000000),
builder_index=builder_index,
Expand Down Expand Up @@ -837,6 +841,38 @@ def test_process_execution_payload_wrong_prev_randao(spec, state):
yield from run_execution_payload_processing(spec, state, signed_envelope, valid=False)


@with_gloas_and_later
@spec_state_test
@always_bls
def test_process_execution_payload_bid_prev_randao_mismatch(spec, state):
"""
Test that committed_bid.prev_randao must equal payload.prev_randao
"""
proposer_index = spec.get_beacon_proposer_index(state)
# Use a different validator as builder
builder_index = (proposer_index + 1) % len(state.validators)
make_validator_builder(spec, state, builder_index)

# Setup bid with one prev_randao value
bid_prev_randao = spec.Bytes32(b"\x11" * 32)
setup_state_with_payload_bid(
spec, state, builder_index, spec.Gwei(2300000), prev_randao=bid_prev_randao
)

execution_payload = build_empty_execution_payload(spec, state)
execution_payload.block_hash = state.latest_execution_payload_bid.block_hash
execution_payload.gas_limit = state.latest_execution_payload_bid.gas_limit
execution_payload.parent_hash = state.latest_block_hash
# Set payload with a different prev_randao value
execution_payload.prev_randao = spec.Bytes32(b"\x22" * 32)

signed_envelope = prepare_execution_payload_envelope(
spec, state, builder_index=builder_index, execution_payload=execution_payload
)

yield from run_execution_payload_processing(spec, state, signed_envelope, valid=False)


@with_gloas_and_later
@spec_state_test
@always_bls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def prepare_signed_execution_payload_bid(
gas_limit=None,
block_hash=None,
blob_kzg_commitments_root=None,
prev_randao=None,
valid_signature=True,
):
"""
Expand Down Expand Up @@ -88,10 +89,14 @@ def prepare_signed_execution_payload_bid(
kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]()
blob_kzg_commitments_root = kzg_list.hash_tree_root()

if prev_randao is None:
prev_randao = spec.get_randao_mix(state, spec.get_current_epoch(state))

bid = spec.ExecutionPayloadBid(
parent_block_hash=parent_block_hash,
parent_block_root=parent_block_root,
block_hash=block_hash,
prev_randao=prev_randao,
fee_recipient=fee_recipient,
gas_limit=gas_limit,
builder_index=builder_index,
Expand Down Expand Up @@ -821,3 +826,30 @@ def test_process_execution_payload_bid_wrong_parent_block_root(spec, state):
block.body.signed_execution_payload_bid = signed_bid

yield from run_execution_payload_bid_processing(spec, state, block, valid=False)


@with_gloas_and_later
@spec_state_test
def test_process_execution_payload_bid_wrong_prev_randao(spec, state):
"""
Test wrong prev_randao fails (bid.prev_randao != get_randao_mix)
"""
proposer_index = spec.get_beacon_proposer_index(state)

# Create block first to advance slot
block = build_empty_block_for_next_slot(spec, state)

# Create bid with wrong prev_randao
wrong_prev_randao = spec.Bytes32(b"\x42" * 32)
signed_bid = prepare_signed_execution_payload_bid(
spec,
state,
builder_index=proposer_index,
slot=block.slot,
parent_block_root=block.parent_root,
prev_randao=wrong_prev_randao,
)

block.body.signed_execution_payload_bid = signed_bid

yield from run_execution_payload_bid_processing(spec, state, block, valid=False)
9 changes: 6 additions & 3 deletions tests/core/pyspec/eth2spec/test/helpers/execution_payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,12 @@ def build_empty_post_gloas_execution_payload_bid(spec, state):
# to distinguish it from the genesis block hash and have
# is_parent_node_full correctly return False
empty_payload_hash = spec.Hash32(b"\x01" + b"\x00" * 31)
prev_randao = spec.get_randao_mix(state, spec.get_current_epoch(state))
return spec.ExecutionPayloadBid(
parent_block_hash=state.latest_block_hash,
parent_block_root=parent_block_root,
block_hash=empty_payload_hash,
prev_randao=prev_randao,
fee_recipient=spec.ExecutionAddress(),
gas_limit=spec.uint64(0),
builder_index=builder_index,
Expand Down Expand Up @@ -362,15 +364,16 @@ def build_empty_execution_payload(spec, state, randao_mix=None):
if is_post_gloas(spec):
latest = state.latest_execution_payload_bid
parent_hash = latest.parent_block_hash
if randao_mix is None:
randao_mix = state.latest_execution_payload_bid.prev_randao
else:
latest = state.latest_execution_payload_header
parent_hash = latest.block_hash
if randao_mix is None:
randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state))
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=parent_hash,
fee_recipient=spec.ExecutionAddress(),
Expand Down
Loading