Skip to content

EIP-8025 -- The Beacon Chain

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

Table of contents

Introduction

These are the beacon-chain specifications that introduce execution proofs which enable constant time stateless validation of execution payloads.

Execution proofs are non-consensus artifacts. Verifying or storing one does not change beacon-chain state, fork choice, or Gloas payload status.

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

Types

New ProofData

1
2
3
4
class ProofData(ProgressiveList[Byte]):
    """
    The opaque proof bytes of an execution proof.
    """

New ProofType

1
2
3
4
5
class ProofType(Uint8):
    """
    The identifier of the proof system, guest program, and version associated
    with an execution proof.
    """

New VersionedHashes

1
2
3
4
5
6
class VersionedHashes(List[VersionedHash]):
    """
    The versioned hashes for blobs associated with an execution payload.
    """

    LIMIT = MAX_BLOB_COMMITMENTS_PER_BLOCK

Constants

Execution

Note: The execution values are not definitive.

Name Value
MAX_PROOF_SIZE Uint64(4194304) (= 4,096 KiB, 4 MiB)
STATELESS_INPUT_SCHEMA_ID Uint16(0x1501)

STATELESS_INPUT_SCHEMA_ID encodes the Amsterdam protocol fork (0x15) and schema revision (0x01).

Domains

Name Value
DOMAIN_EXECUTION_PROOF DomainType('0x0F000000')

Containers

New SSZNewPayloadRequest

1
2
3
4
5
6
7
class SSZNewPayloadRequest(ProgressiveContainer):
    ACTIVE_FIELDS = active_fields(width=4)

    execution_payload: ExecutionPayload
    versioned_hashes: VersionedHashes
    parent_beacon_block_root: Root
    execution_requests: ExecutionRequests

New PublicInput

1
2
3
4
5
6
7
class PublicInput(ProgressiveContainer):
    ACTIVE_FIELDS = active_fields(width=4)

    new_payload_request_root: Root
    successful_validation: Boolean
    chain_id: Uint64
    schema_id: Uint16

New ExecutionProof

1
2
3
4
class ExecutionProof(Container):
    proof_data: ProofData
    proof_type: ProofType
    public_input: PublicInput

New ExecutionProofEnvelope

1
2
3
4
class ExecutionProofEnvelope(Container):
    proof_data: ProofData
    proof_type: ProofType
    beacon_block_root: Root

New SignedExecutionProofEnvelope

1
2
3
4
class SignedExecutionProofEnvelope(Container):
    message: ExecutionProofEnvelope
    validator_index: ValidatorIndex
    signature: BLSSignature

Helpers

New get_supported_proof_types

Note: The initial proof type assignments are provisional. A ProofType identifies an immutable combination of proof system, guest program, and version. Assignments MUST NOT be reused.

1
2
3
4
5
6
7
8
9
def get_supported_proof_types() -> set[ProofType]:
    """
    Return the supported execution proof types.
    """
    return {
        ProofType(1),
        ProofType(2),
        ProofType(3),
    }

Execution proof verification

New verify_execution_proof_envelope

def verify_execution_proof_envelope(
    state: BeaconState,
    signed_proof_envelope: SignedExecutionProofEnvelope,
    payload_envelope: ExecutionPayloadEnvelope,
) -> None:
    """
    Verify an execution proof envelope against the beacon state and payload.
    The execution proof itself is verified separately by the proof engine.
    """
    proof_envelope = signed_proof_envelope.message
    assert proof_envelope.beacon_block_root == payload_envelope.beacon_block_root
    assert signed_proof_envelope.validator_index < len(state.validators)
    assert 0 < len(proof_envelope.proof_data) <= MAX_PROOF_SIZE
    assert proof_envelope.proof_type in get_supported_proof_types()

    # Verify the prover is an active validator
    validator = state.validators[signed_proof_envelope.validator_index]
    assert is_active_validator(validator, get_current_epoch(state))

    # Verify the prover signature
    domain = get_domain(state, DOMAIN_EXECUTION_PROOF, compute_epoch_at_slot(state.slot))
    signing_root = compute_signing_root(proof_envelope, domain)
    assert bls.Verify(validator.pubkey, signing_root, signed_proof_envelope.signature)

New get_execution_proof

def get_execution_proof(
    state: BeaconState,
    proof_envelope: ExecutionProofEnvelope,
    payload_envelope: ExecutionPayloadEnvelope,
) -> ExecutionProof:
    """
    Construct the ``ExecutionProof`` for submission to the proof engine.
    """
    # Construct the proof-system public input from the accepted execution payload
    bid = state.latest_execution_payload_bid
    new_payload_request = SSZNewPayloadRequest(
        execution_payload=payload_envelope.payload,
        versioned_hashes=VersionedHashes(
            data=[
                kzg_commitment_to_versioned_hash(commitment)
                for commitment in bid.blob_kzg_commitments
            ]
        ),
        parent_beacon_block_root=payload_envelope.parent_beacon_block_root,
        execution_requests=payload_envelope.execution_requests,
    )
    public_input = PublicInput(
        new_payload_request_root=hash_tree_root(new_payload_request),
        successful_validation=Boolean(True),
        chain_id=DEPOSIT_CHAIN_ID,
        schema_id=STATELESS_INPUT_SCHEMA_ID,
    )
    return ExecutionProof(
        proof_data=proof_envelope.proof_data,
        proof_type=proof_envelope.proof_type,
        public_input=public_input,
    )

New process_execution_proof

def process_execution_proof(
    state: BeaconState,
    signed_proof_envelope: SignedExecutionProofEnvelope,
    payload_envelope: ExecutionPayloadEnvelope,
    proof_engine: ProofEngine,
) -> None:
    """
    Authenticate and verify an execution proof envelope.
    """
    verify_execution_proof_envelope(
        state,
        signed_proof_envelope,
        payload_envelope,
    )

    proof = get_execution_proof(
        state,
        signed_proof_envelope.message,
        payload_envelope,
    )
    assert proof_engine.verify_execution_proof(proof)