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
| class ProofData(ProgressiveList[Byte]):
"""
The opaque proof bytes of an execution proof.
"""
|
New ProofType
| class ProofType(Uint8):
"""
The identifier of the proof system, guest program, and version associated
with an execution proof.
"""
|
New VersionedHashes
| 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
| class SSZNewPayloadRequest(ProgressiveContainer):
ACTIVE_FIELDS = active_fields(width=4)
execution_payload: ExecutionPayload
versioned_hashes: VersionedHashes
parent_beacon_block_root: Root
execution_requests: ExecutionRequests
|
| 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
| class ExecutionProof(Container):
proof_data: ProofData
proof_type: ProofType
public_input: PublicInput
|
New ExecutionProofEnvelope
| class ExecutionProofEnvelope(Container):
proof_data: ProofData
proof_type: ProofType
beacon_block_root: Root
|
New SignedExecutionProofEnvelope
| 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.
| 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)
|