Skip to content

EIP-8025 -- zkEVM

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

Introduction

This document specifies the cryptographic operations for zkEVM based execution proofs enabling stateless validation of execution payloads.

Note: This specification provides placeholder implementations. Production implementations should use established zkEVM systems.

Constants

All of the constants below are subject to change and one should not overindex on them. MAX_PROOF_SIZE, MAX_PROVING_KEY_SIZE, and MAX_VERIFICATION_KEY_SIZE are all arbitrary. MAX_WITNESS_SIZE is the worst case witness size for the MPT for a payload with a maximum gas limit of 30M gas.

Name Value
MAX_PROOF_SIZE 307200 (= 300KiB)
MAX_PROVING_KEY_SIZE 2**28 (= 256MiB)
MAX_VERIFICATION_KEY_SIZE 2**20 (= 1MiB)
MAX_WITNESS_SIZE 314572800 (= 300MiB)

Custom types

Name SSZ equivalent Description
ZKEVMProof Container Proof of execution of a program

Cryptographic types

Note: ProgramBytecode represents the bytecode for a particular execution layer client. The size depends on the client; 16 is a placeholder.

Name SSZ equivalent Description
ProgramBytecode ByteList[16] Execution layer program bytecode
ProofID uint8 Identifier for proof system
ProvingKey ByteList[MAX_PROVING_KEY_SIZE] Key used for proof generation
VerificationKey ByteList[MAX_VERIFICATION_KEY_SIZE] Key used for proof verification
ZKExecutionWitness ByteList[MAX_WITNESS_SIZE] zkEVM execution witness data for stateless program execution
PrivateInput Container Private inputs for execution proof generation
PublicInput Container Public inputs for execution proof generation and verification

Containers

ZKEVMProof

1
2
3
4
class ZKEVMProof(Container):
    proof_data: ByteList[MAX_PROOF_SIZE]
    proof_type: ProofID
    public_inputs: PublicInput

PrivateInput

1
2
3
class PrivateInput(Container):
    execution_payload: ExecutionPayload
    execution_witness: ZKExecutionWitness

PublicInput

1
2
3
class PublicInput(Container):
    block_hash: Hash32
    parent_hash: Hash32

Helper functions

Preprocessing

generate_keys

def generate_keys(
    program_bytecode: ProgramBytecode, proof_id: ProofID
) -> tuple[ProvingKey, VerificationKey]:
    """
    Generate proving and verification keys for the given program bytecode and proof system.
    """
    proving_key = generate_proving_key(program_bytecode, proof_id)
    verification_key = generate_verification_key(program_bytecode, proof_id)

    return (proving_key, verification_key)

Proof verification

verify_execution_proof_impl

1
2
3
4
5
6
7
8
def verify_execution_proof_impl(proof: ZKEVMProof, verification_key: VerificationKey) -> bool:
    """
    Verify a zkEVM execution proof using the verification key.
    """
    if len(proof.proof_data) > MAX_PROOF_SIZE:
        return False

    return True

generate_verification_key

1
2
3
4
5
6
7
8
def generate_verification_key(
    program_bytecode: ProgramBytecode, proof_id: ProofID
) -> VerificationKey:
    """
    Generate a verification key for the given program bytecode and proof system.
    """
    verification_key = VerificationKey(program_bytecode + proof_id.to_bytes(1, "little"))
    return verification_key

Proof generation

generate_execution_proof_impl

def generate_execution_proof_impl(
    private_input: PrivateInput,
    proving_key: ProvingKey,
    proof_id: ProofID,
    public_inputs: PublicInput,
) -> ZKEVMProof:
    """
    Generate a zkEVM execution proof using the proving key, private inputs and public inputs
    """
    proof_data = hash(
        public_inputs.block_hash + public_inputs.parent_hash + proof_id.to_bytes(1, "little")
    )

    return ZKEVMProof(
        proof_data=ByteList(proof_data), proof_type=proof_id, public_inputs=public_inputs
    )

generate_proving_key

1
2
3
4
5
def generate_proving_key(program_bytecode: ProgramBytecode, proof_id: ProofID) -> ProvingKey:
    """
    Generate a proving key for the given program bytecode and proof system.
    """
    return ProvingKey(program_bytecode + proof_id.to_bytes(1, "little"))

verify_zkevm_proof

def verify_zkevm_proof(
    zk_proof: ZKEVMProof, parent_hash: Hash32, block_hash: Hash32, program_bytecode: ProgramBytecode
) -> bool:
    """
    Public method to verify a zkEVM execution proof against block hashes.
    """
    # Validate that public inputs match the provided parent and current block hash
    if zk_proof.public_inputs.block_hash != block_hash:
        return False
    if zk_proof.public_inputs.parent_hash != parent_hash:
        return False

    _, verification_key = generate_keys(program_bytecode, zk_proof.proof_type)

    return verify_execution_proof_impl(zk_proof, verification_key)

generate_zkevm_proof

def generate_zkevm_proof(
    execution_payload: ExecutionPayload,
    execution_witness: ZKExecutionWitness,
    program_bytecode: ProgramBytecode,
    proof_id: ProofID,
) -> Optional[ZKEVMProof]:
    """
    Public method to generate an execution proof for a payload.
    """
    proving_key, _ = generate_keys(program_bytecode, proof_id)

    public_inputs = PublicInput(
        block_hash=execution_payload.block_hash, parent_hash=execution_payload.parent_hash
    )
    private_input = PrivateInput(
        execution_payload=execution_payload, execution_witness=execution_witness
    )

    return generate_execution_proof_impl(private_input, proving_key, proof_id, public_inputs)