Skip to content

EIP-8025 -- Fork Choice

Note: This document is a work-in-progress for researchers and implementers.

Table of contents

Introduction

This document contains the fork-choice modifications for EIP-8025.

Note: This specification is built upon Gloas and imports proof types from proof-engine.md.

Execution payload envelope

Modified verify_execution_payload_envelope

Note: verify_execution_payload_envelope is modified in EIP-8025 to require both ExecutionEngine and ProofEngine, and to notify the ProofEngine of the new payload alongside the ExecutionEngine.

def verify_execution_payload_envelope(
    state: BeaconState,
    signed_envelope: SignedExecutionPayloadEnvelope,
    execution_engine: ExecutionEngine,
    proof_engine: ProofEngine,
) -> None:
    envelope = signed_envelope.message
    payload = envelope.payload

    # Verify signature
    assert verify_execution_payload_envelope_signature(state, signed_envelope)

    # Verify consistency with the beacon block
    header = copy(state.latest_block_header)
    header.state_root = hash_tree_root(state)
    assert envelope.beacon_block_root == hash_tree_root(header)
    assert envelope.parent_beacon_block_root == state.latest_block_header.parent_root

    # Verify consistency with the committed bid
    bid = state.latest_execution_payload_bid
    assert envelope.builder_index == bid.builder_index
    assert payload.prev_randao == bid.prev_randao
    assert payload.gas_limit == bid.gas_limit
    assert payload.block_hash == bid.block_hash
    assert hash_tree_root(envelope.execution_requests) == bid.execution_requests_root

    # Verify the execution payload is valid
    assert payload.slot_number == state.slot
    assert payload.parent_hash == state.latest_block_hash
    assert payload.timestamp == compute_time_at_slot(state, state.slot)
    assert hash_tree_root(payload.withdrawals) == hash_tree_root(state.payload_expected_withdrawals)

    new_payload_request = NewPayloadRequest(
        execution_payload=payload,
        versioned_hashes=[
            kzg_commitment_to_versioned_hash(commitment) for commitment in bid.blob_kzg_commitments
        ],
        parent_beacon_block_root=envelope.parent_beacon_block_root,
        execution_requests=envelope.execution_requests,
    )

    # Verify the execution payload is valid via ExecutionEngine
    assert execution_engine.verify_and_notify_new_payload(new_payload_request)

    # [New in EIP8025]
    # Notify ProofEngine of the new execution payload
    proof_engine.notify_new_payload(new_payload_request)

Modified on_execution_payload_envelope

Note: on_execution_payload_envelope is modified in EIP-8025 to pass PROOF_ENGINE alongside EXECUTION_ENGINE to verify_execution_payload_envelope.

def on_execution_payload_envelope(
    store: Store, signed_envelope: SignedExecutionPayloadEnvelope
) -> None:
    """
    Run ``on_execution_payload_envelope`` upon receiving a new execution payload envelope.
    """
    envelope = signed_envelope.message
    # The corresponding beacon block root needs to be known
    assert envelope.beacon_block_root in store.block_states

    # Check if blob data is available
    # If not, this payload MAY be queued and subsequently considered when blob data becomes available
    assert is_data_available(envelope.beacon_block_root)

    state = store.block_states[envelope.beacon_block_root]

    # Verify the execution payload envelope
    # [Modified in EIP8025]
    verify_execution_payload_envelope(state, signed_envelope, EXECUTION_ENGINE, PROOF_ENGINE)

    # Add execution payload envelope to the store
    store.payloads[envelope.beacon_block_root] = envelope