diff --git a/specs/_features/eip8025/beacon-chain.md b/specs/_features/eip8025/beacon-chain.md index b383668f06..5336442a5b 100644 --- a/specs/_features/eip8025/beacon-chain.md +++ b/specs/_features/eip8025/beacon-chain.md @@ -8,43 +8,49 @@ - [Table of contents](#table-of-contents) - [Introduction](#introduction) +- [Types](#types) - [Constants](#constants) - [Execution](#execution) - [Domains](#domains) - [Configuration](#configuration) - [Containers](#containers) - - [New containers](#new-containers) - - [`ExecutionProof`](#executionproof) - - [`SignedExecutionProof`](#signedexecutionproof) - - [Extended containers](#extended-containers) -- [Helpers](#helpers) - - [Execution proof functions](#execution-proof-functions) - - [`verify_execution_proof`](#verify_execution_proof) - - [`verify_execution_proofs`](#verify_execution_proofs) + - [New `PublicInput`](#new-publicinput) + - [New `ExecutionProof`](#new-executionproof) + - [New `SignedExecutionProof`](#new-signedexecutionproof) - [Beacon chain state transition function](#beacon-chain-state-transition-function) - - [Execution payload processing](#execution-payload-processing) - - [Modified `process_execution_payload`](#modified-process_execution_payload) + - [Block processing](#block-processing) + - [Modified `process_block`](#modified-process_block) + - [Execution payload](#execution-payload) + - [New `NewPayloadRequestHeader`](#new-newpayloadrequestheader) + - [Modified `process_execution_payload`](#modified-process_execution_payload) + - [Execution proof](#execution-proof) + - [New `process_execution_proof`](#new-process_execution_proof) ## Introduction -These are the beacon-chain specifications to add EIP-8025. This enables -stateless validation of execution payloads through cryptographic proofs. +These are the beacon-chain specifications to add EIP-8025, enabling stateless +validation of execution payloads through execution proofs. -*Note*: This specification is built upon [Fulu](../../fulu/beacon-chain.md). +*Note*: This specification is built upon [Fulu](../../fulu/beacon-chain.md) and +imports proof types from [proof-engine.md](./proof-engine.md). -*Note*: This specification assumes the reader is familiar with the -[public zkEVM methods exposed](./zkevm.md). +## Types + +| Name | SSZ equivalent | Description | +| ----------- | -------------- | --------------------------------- | +| `ProofType` | `uint8` | The type identifier for the proof | ## Constants ### Execution -| Name | Value | -| ---------------------------------- | -------------------------------------- | -| `MAX_EXECUTION_PROOFS_PER_PAYLOAD` | `uint64(4)` | -| `PROGRAM` | `ProgramBytecode(b"DEFAULT__PROGRAM")` | +*Note*: The execution values are not definitive. + +| Name | Value | +| ---------------- | ------------------- | +| `MAX_PROOF_SIZE` | `307200` (= 300KiB) | ### Domains @@ -56,110 +62,83 @@ stateless validation of execution payloads through cryptographic proofs. *Note*: The configuration values are not definitive. -| Name | Value | -| ------------------------------- | ----------- | -| `MIN_REQUIRED_EXECUTION_PROOFS` | `uint64(1)` | +| Name | Value | +| ------------------------- | ------------- | +| `MAX_WHITELISTED_PROVERS` | `uint64(256)` | ## Containers -### New containers +### New `PublicInput` + +```python +class PublicInput(Container): + new_payload_request_root: Root +``` -#### `ExecutionProof` +### New `ExecutionProof` ```python class ExecutionProof(Container): - beacon_root: Root - zk_proof: ZKEVMProof - validator_index: ValidatorIndex + proof_data: ByteList[MAX_PROOF_SIZE] + proof_type: ProofType + public_input: PublicInput ``` -#### `SignedExecutionProof` +### New `SignedExecutionProof` ```python class SignedExecutionProof(Container): message: ExecutionProof + prover_pubkey: BLSPubkey signature: BLSSignature ``` -### Extended containers - -*Note*: `BeaconState` and `BeaconBlockBody` remain the same. No modifications -are required for execution proofs since they are handled externally. +## Beacon chain state transition function -## Helpers +### Block processing -### Execution proof functions +#### Modified `process_block` -#### `verify_execution_proof` +*Note*: `process_block` is modified in EIP-8025 to pass `PROOF_ENGINE` to +`process_execution_payload`. ```python -def verify_execution_proof( - signed_proof: SignedExecutionProof, - parent_hash: Hash32, - block_hash: Hash32, - state: BeaconState, - el_program: ProgramBytecode, -) -> bool: - """ - Verify an execution proof against a payload header using zkEVM verification. - """ - - # Note: signed_proof.message.beacon_root verification will be done at a higher level - - # Verify the validator signature - proof_message = signed_proof.message - validator = state.validators[proof_message.validator_index] - signing_root = compute_signing_root(proof_message, get_domain(state, DOMAIN_EXECUTION_PROOF)) - if not bls.Verify(validator.pubkey, signing_root, signed_proof.signature): - return False - - # Derive program bytecode from the EL program identifier and proof type - program_bytecode = ProgramBytecode( - el_program + proof_message.zk_proof.proof_type.to_bytes(1, "little") - ) - - return verify_zkevm_proof(proof_message.zk_proof, parent_hash, block_hash, program_bytecode) +def process_block(state: BeaconState, block: BeaconBlock) -> None: + process_block_header(state, block) + process_withdrawals(state, block.body.execution_payload) + # [Modified in EIP8025] + process_execution_payload(state, block.body, EXECUTION_ENGINE, PROOF_ENGINE) + process_randao(state, block.body) + process_eth1_data(state, block.body) + process_operations(state, block.body) + process_sync_aggregate(state, block.body.sync_aggregate) ``` -#### `verify_execution_proofs` +#### Execution payload + +##### New `NewPayloadRequestHeader` ```python -def verify_execution_proofs(parent_hash: Hash32, block_hash: Hash32, state: BeaconState) -> bool: - """ - Verify that execution proofs are available and valid for an execution payload. - """ - # `retrieve_execution_proofs` is implementation and context dependent. - # It returns all execution proofs for the given payload block hash. - signed_execution_proofs = retrieve_execution_proofs(block_hash) - - # Verify there are sufficient proofs - if len(signed_execution_proofs) < MIN_REQUIRED_EXECUTION_PROOFS: - return False - - # Verify all execution proofs - for signed_proof in signed_execution_proofs: - if not verify_execution_proof(signed_proof, parent_hash, block_hash, state, PROGRAM): - return False - - return True +@dataclass +class NewPayloadRequestHeader(object): + execution_payload_header: ExecutionPayloadHeader + versioned_hashes: Sequence[VersionedHash] + parent_beacon_block_root: Root + execution_requests: ExecutionRequests ``` -## Beacon chain state transition function - -### Execution payload processing +##### Modified `process_execution_payload` -#### Modified `process_execution_payload` +*Note*: `process_execution_payload` is modified in EIP-8025 to require both +`ExecutionEngine` and `ProofEngine` for validation. ```python def process_execution_payload( state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine, - stateless_validation: bool = False, + proof_engine: ProofEngine, ) -> None: - """ - Note: This function is modified to support optional stateless validation with execution proofs. - """ payload = body.execution_payload # Verify consistency of the parent hash with respect to the previous execution payload header @@ -174,24 +153,48 @@ def process_execution_payload( <= get_blob_parameters(get_current_epoch(state)).max_blobs_per_block ) - if stateless_validation: - # Stateless validation using execution proofs - assert verify_execution_proofs(payload.parent_hash, payload.block_hash, state) - else: - # Compute list of versioned hashes - versioned_hashes = [ - kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments - ] - - # Verify the execution payload is valid - assert execution_engine.verify_and_notify_new_payload( - NewPayloadRequest( - execution_payload=payload, - versioned_hashes=versioned_hashes, - parent_beacon_block_root=state.latest_block_header.parent_root, - execution_requests=body.execution_requests, - ) + # Compute list of versioned hashes + versioned_hashes = [ + kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments + ] + + # Verify the execution payload is valid via ExecutionEngine + assert execution_engine.verify_and_notify_new_payload( + NewPayloadRequest( + execution_payload=payload, + versioned_hashes=versioned_hashes, + parent_beacon_block_root=state.latest_block_header.parent_root, + execution_requests=body.execution_requests, ) + ) + + # [New in EIP8025] + # Verify via ProofEngine + new_payload_request_header = NewPayloadRequestHeader( + execution_payload_header=ExecutionPayloadHeader( + parent_hash=payload.parent_hash, + fee_recipient=payload.fee_recipient, + state_root=payload.state_root, + receipts_root=payload.receipts_root, + logs_bloom=payload.logs_bloom, + prev_randao=payload.prev_randao, + block_number=payload.block_number, + gas_limit=payload.gas_limit, + gas_used=payload.gas_used, + timestamp=payload.timestamp, + extra_data=payload.extra_data, + base_fee_per_gas=payload.base_fee_per_gas, + block_hash=payload.block_hash, + transactions_root=hash_tree_root(payload.transactions), + withdrawals_root=hash_tree_root(payload.withdrawals), + blob_gas_used=payload.blob_gas_used, + excess_blob_gas=payload.excess_blob_gas, + ), + versioned_hashes=versioned_hashes, + parent_beacon_block_root=state.latest_block_header.parent_root, + execution_requests=body.execution_requests, + ) + assert proof_engine.verify_new_payload_request_header(new_payload_request_header) # Cache execution payload header state.latest_execution_payload_header = ExecutionPayloadHeader( @@ -214,3 +217,30 @@ def process_execution_payload( excess_blob_gas=payload.excess_blob_gas, ) ``` + +### Execution proof + +*Note*: Proof storage is implementation-dependent, managed by the `ProofEngine`. + +#### New `process_execution_proof` + +```python +def process_execution_proof( + state: BeaconState, + signed_proof: SignedExecutionProof, + proof_engine: ProofEngine, +) -> None: + proof_message = signed_proof.message + prover_pubkey = signed_proof.prover_pubkey + + # Verify prover is whitelisted + validator_pubkeys = [v.pubkey for v in state.validators] + assert prover_pubkey in validator_pubkeys + + domain = get_domain(state, DOMAIN_EXECUTION_PROOF, compute_epoch_at_slot(state.slot)) + signing_root = compute_signing_root(proof_message, domain) + assert bls.Verify(prover_pubkey, signing_root, signed_proof.signature) + + # Verify the execution proof + assert proof_engine.verify_execution_proof(proof_message) +``` diff --git a/specs/_features/eip8025/p2p-interface.md b/specs/_features/eip8025/p2p-interface.md index 2898e2873f..c71eee8834 100644 --- a/specs/_features/eip8025/p2p-interface.md +++ b/specs/_features/eip8025/p2p-interface.md @@ -2,21 +2,24 @@ This document contains the networking specifications for EIP-8025. +*Note*: This specification is built upon [Fulu](../../fulu/p2p-interface.md) and +imports proof types from [proof-engine.md](./proof-engine.md). + ## Table of contents - [Table of contents](#table-of-contents) - [Constants](#constants) -- [Containers](#containers) + - [Execution](#execution) - [MetaData](#metadata) - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) - [Topics and messages](#topics-and-messages) - [Global topics](#global-topics) - - [`execution_proof_{subnet_id}`](#execution_proof_subnet_id) + - [`execution_proof`](#execution_proof) - [The Req/Resp domain](#the-reqresp-domain) - [Messages](#messages) - - [ExecutionProofsByHash](#executionproofsbyhash) + - [ExecutionProofsByRoot](#executionproofsbyroot) - [GetMetaData v4](#getmetadata-v4) - [The discovery domain: discv5](#the-discovery-domain-discv5) - [ENR structure](#enr-structure) @@ -26,14 +29,13 @@ This document contains the networking specifications for EIP-8025. ## Constants -*Note*: There are `MAX_EXECUTION_PROOFS_PER_PAYLOAD` (from -[beacon-chain.md](./beacon-chain.md)) execution proof subnets to provide 1-to-1 -mapping with proof systems. Each proof system gets its own dedicated subnet. +### Execution -## Containers +*Note*: The execution values are not definitive. -*Note*: Execution proofs are broadcast directly as `SignedExecutionProof` -containers. No additional message wrapper is needed. +| Name | Value | +| ---------------------------------- | ----------- | +| `MAX_EXECUTION_PROOFS_PER_PAYLOAD` | `uint64(4)` | ## MetaData @@ -65,43 +67,37 @@ Where #### Global topics -##### `execution_proof_{subnet_id}` - -Execution proof subnets are used to propagate execution proofs for specific -proof systems. - -The execution proof subnet for a given `proof_id` is: - -```python -def compute_subnet_for_execution_proof(proof_id: ProofID) -> SubnetID: - assert proof_id < MAX_EXECUTION_PROOFS_PER_PAYLOAD - return SubnetID(proof_id) -``` - -The following validations MUST pass before forwarding the -`signed_execution_proof` on the network: - -- _[IGNORE]_ The proof is the first valid proof received for the tuple - `(signed_execution_proof.message.zk_proof.public_inputs.block_hash, subnet_id)`. -- _[REJECT]_ The `signed_execution_proof.message.validator_index` is within the - known validator registry. -- _[REJECT]_ The `signed_execution_proof.signature` is valid with respect to the - validator's public key. -- _[REJECT]_ The `signed_execution_proof.message.zk_proof.proof_data` is - non-empty. -- _[REJECT]_ The proof system ID matches the subnet: - `signed_execution_proof.message.zk_proof.proof_type == subnet_id`. -- _[REJECT]_ The execution proof is valid as verified by - `verify_execution_proof()` with the appropriate parent and block hashes from - the execution layer. +##### `execution_proof` + +This topic is used to propagate `SignedExecutionProof` messages. + +The following validations MUST pass before forwarding a proof on the network: + +- _[IGNORE]_ The proof's corresponding new payload request (identified by + `proof.message.public_input.new_payload_request_root`) has been seen (via + gossip or non-gossip sources) (a client MAY queue proofs for processing once + the new payload request is retrieved). +- _[IGNORE]_ The proof is the first proof received for the tuple + `(proof.message.public_input.new_payload_request_root, proof.message.proof_type, proof.prover_pubkey)` + -- i.e. the first *valid or invalid* proof for `proof.message.proof_type` from + `proof.prover_pubkey`. +- _[REJECT]_ `proof.prover_pubkey` is associated with an active validator. +- _[REJECT]_ `proof.signature` is valid with respect to the prover's public key. +- _[REJECT]_ `proof.message.proof_data` is non-empty. +- _[REJECT]_ `proof.message.proof_data` is not larger than `MAX_PROOF_SIZE`. +- _[REJECT]_ `proof.message` is a valid execution proof. +- _[IGNORE]_ The proof is the first proof received for the tuple + `(proof.message.public_input.new_payload_request_root, proof.message.proof_type)` + -- i.e. the first *valid* proof for `proof.message.proof_type` from any + prover. ## The Req/Resp domain ### Messages -#### ExecutionProofsByHash +#### ExecutionProofsByRoot -**Protocol ID:** `/eth2/beacon/req/execution_proofs_by_hash/1/` +**Protocol ID:** `/eth2/beacon_chain/req/execution_proofs_by_root/1/` The `` field is calculated as `context = compute_fork_digest(fork_version, genesis_validators_root)`. @@ -110,7 +106,7 @@ Request Content: ``` ( - Hash32 # block_hash + block_root: Root ) ``` @@ -122,17 +118,17 @@ Response Content: ) ``` -Requests execution proofs for the given execution payload `block_hash`. The -response MUST contain all available proofs for the requested block hash, up to +Requests execution proofs for the given `block_root`. The response MUST contain +all available proofs for the requested beacon block, up to `MAX_EXECUTION_PROOFS_PER_PAYLOAD`. The following validations MUST pass: -- _[REJECT]_ The `block_hash` is a 32-byte value. +- _[REJECT]_ The `block_root` is a 32-byte value. The response MUST contain: -- All available execution proofs for the requested block hash. +- All available execution proofs for the requested `block_root`. - The response MUST NOT contain more than `MAX_EXECUTION_PROOFS_PER_PAYLOAD` proofs. diff --git a/specs/_features/eip8025/proof-engine.md b/specs/_features/eip8025/proof-engine.md new file mode 100644 index 0000000000..911c6125dc --- /dev/null +++ b/specs/_features/eip8025/proof-engine.md @@ -0,0 +1,101 @@ +# EIP-8025 -- Proof Engine + +*Note*: This document is a work-in-progress for researchers and implementers. + +## Table of contents + + + +- [Table of contents](#table-of-contents) +- [Introduction](#introduction) +- [Types](#types) +- [Proof engine](#proof-engine) + - [New `verify_execution_proof`](#new-verify_execution_proof) + - [New `verify_new_payload_request_header`](#new-verify_new_payload_request_header) + - [New `ProofAttributes`](#new-proofattributes) + - [New `request_proofs`](#new-request_proofs) + + + +## Introduction + +This document contains the Proof Engine specification. The Proof Engine enables +stateless validation of execution payloads through execution proofs. + +## Types + +| Name | SSZ equivalent | Description | +| ------------ | -------------- | ---------------------------------------- | +| `ProofGenId` | `Bytes8` | Identifier for tracking proof generation | + +## Proof engine + +The implementation-dependent `ProofEngine` protocol encapsulates the proof +sub-system logic via: + +- a state object `self.proof_state` of type `ProofState` containing stored + proofs +- a verification function `self.verify_execution_proof` to verify individual + proofs +- a verification function `self.verify_new_payload_request_header` to verify new + payload request headers using stored proofs +- a generation function `self.request_proofs` to initiate asynchronous proof + generation + +The body of these functions are implementation dependent. The Engine API may be +used to implement this and similarly defined functions via an external proof +engine. + +### New `verify_execution_proof` + +```python +def verify_execution_proof( + self: ProofEngine, + execution_proof: ExecutionProof, +) -> bool: + """ + Verify an execution proof. + Return ``True`` if proof is valid. + """ + ... +``` + +### New `verify_new_payload_request_header` + +```python +def verify_new_payload_request_header( + self: ProofEngine, + new_payload_request_header: NewPayloadRequestHeader, +) -> bool: + """ + Verify the corresponding new payload request execution is valid. + Return ``True`` if proof requirements are satisfied. + """ + ... +``` + +### New `ProofAttributes` + +```python +@dataclass +class ProofAttributes(object): + proof_types: List[ProofType] +``` + +### New `request_proofs` + +```python +def request_proofs( + self: ProofEngine, + new_payload_request: NewPayloadRequest, + proof_attributes: ProofAttributes, +) -> ProofGenId: + """ + Request proof generation for a new payload request with specified proof attributes. + Returns a ``ProofGenId`` to track the generation request. + + Generated proofs are delivered asynchronously via the beacon API endpoint + ``POST /eth/v1/prover/execution_proofs``. + """ + ... +``` diff --git a/specs/_features/eip8025/prover.md b/specs/_features/eip8025/prover.md new file mode 100644 index 0000000000..f4a9fadd93 --- /dev/null +++ b/specs/_features/eip8025/prover.md @@ -0,0 +1,86 @@ +# EIP-8025 -- Honest Prover + +*Note*: This document is a work-in-progress for researchers and implementers. + +## Table of contents + + + +- [Table of contents](#table-of-contents) +- [Introduction](#introduction) +- [Helpers](#helpers) + - [New `get_execution_proof_signature`](#new-get_execution_proof_signature) +- [Constructing `SignedExecutionProof`](#constructing-signedexecutionproof) +- [Honest prover relay](#honest-prover-relay) + + + +## Introduction + +This document represents the prover guide accompanying EIP-8025. Provers are +whitelisted network participants who voluntarily generate and submit execution +proofs without direct protocol-level compensation. They provide a public good by +enabling stateless validation during the optional proof phase. + +*Note*: Provers are a transitional mechanism. In future mandatory proof forks, +builders will be required to produce and gossip execution proofs as part of +their block production duties, and the prover role will be deprecated. + +*Note*: This specification is built upon [Fulu](../../fulu/beacon-chain.md) and +imports proof types from [proof-engine.md](./proof-engine.md). + +## Helpers + +### New `get_execution_proof_signature` + +```python +def get_execution_proof_signature( + state: BeaconState, proof: ExecutionProof, privkey: int +) -> BLSSignature: + domain = get_domain(state, DOMAIN_EXECUTION_PROOF, compute_epoch_at_slot(state.slot)) + signing_root = compute_signing_root(proof, domain) + return bls.Sign(privkey, signing_root) +``` + +## Constructing `SignedExecutionProof` + +An honest prover who has been whitelisted and wants to generate execution proofs +for a `BeaconBlockBody` performs the following steps: + +1. Extract `NewPayloadRequest` from `BeaconBlockBody`: + - `execution_payload = body.execution_payload` + - `versioned_hashes = [kzg_commitment_to_versioned_hash(c) for c in body.blob_kzg_commitments]` + - `parent_beacon_block_root = state.latest_block_header.parent_root` + - `execution_requests = body.execution_requests` +2. Create `ProofAttributes` with desired proof types. +3. Call + `proof_gen_id = proof_engine.request_proofs(new_payload_request, proof_attributes)` + to initiate proof generation. +4. The proof engine generates proofs asynchronously and delivers them to the + prover via `POST /eth/v1/prover/execution_proofs`. Each proof is delivered + with its associated `proof_gen_id` to link it to the original request. +5. Upon receiving each `ExecutionProof` with its `proof_gen_id`: + - Validate the proof matches a pending `proof_gen_id`. + - Set `message` to the `ExecutionProof`. + - Set `prover_pubkey` to the prover's public key. + - Sign the proof using + `get_execution_proof_signature(state, proof, prover_privkey)`. + - Broadcast the `SignedExecutionProof` on the `execution_proof` gossip topic. + +## Honest prover relay + +A prover relay is a trusted intermediary that accepts unsigned execution proofs +from proof engines and signs them for broadcast. The relay's public key MUST be +in the prover whitelist. + +When a prover relay receives an unsigned `ExecutionProof` via +`POST /eth/v1/prover/execution_proofs`: + +1. Validate that `proof_data` is non-empty. +2. Verify the execution proof is valid using + `proof_engine.verify_execution_proof(proof)`. +3. Check the proof is not a duplicate (same `new_payload_request_root`, + `proof_type`). +4. If valid and not a duplicate: + - Create a `SignedExecutionProof` with the relay's public key and signature. + - Broadcast on the `execution_proof` gossip topic. diff --git a/specs/_features/eip8025/validator.md b/specs/_features/eip8025/validator.md deleted file mode 100644 index 1f80bd0ffd..0000000000 --- a/specs/_features/eip8025/validator.md +++ /dev/null @@ -1,92 +0,0 @@ -# EIP-8025 -- Honest Validator - -**Notice**: This document is a work-in-progress for researchers and -implementers. - -## Table of contents - - - -- [Table of contents](#table-of-contents) -- [Introduction](#introduction) -- [Prerequisites](#prerequisites) -- [Configuration](#configuration) -- [Optional execution proof generation](#optional-execution-proof-generation) - - [`generate_execution_proof`](#generate_execution_proof) - - [`broadcast_execution_proof`](#broadcast_execution_proof) - - - -## Introduction - -This document represents optional execution proof generation capabilities that -validators may choose to implement. - -## Prerequisites - -This document is an extension of the -[Fulu -- Honest Validator](../../fulu/validator.md) guide. All behaviors and -definitions defined in this document, and documents it extends, carry over -unless explicitly noted or overridden. - -## Configuration - -| Name | Value | -| ------------------------------------ | ------- | -| `EXECUTION_PROOF_GENERATION_ENABLED` | `False` | - -## Optional execution proof generation - -Validators MAY choose to generate execution proofs for payloads they propose or -receive. - -### `generate_execution_proof` - -```python -def generate_execution_proof( - payload: ExecutionPayload, execution_witness: ZKExecutionWitness, proof_id: ProofID -) -> Optional[SignedExecutionProof]: - """ - Generate an execution proof for the given payload. - """ - if not EXECUTION_PROOF_GENERATION_ENABLED: - return None - - zk_proof = generate_zkevm_proof(payload, execution_witness, PROGRAM, proof_id) - - if zk_proof is None: - return None - - validator_index = get_validator_index() - beacon_root = get_current_beacon_root() - - execution_proof_message = ExecutionProof( - beacon_root=beacon_root, - zk_proof=zk_proof, - validator_index=validator_index, - ) - - signing_root = compute_signing_root( - execution_proof_message, get_domain(get_current_state(), DOMAIN_EXECUTION_PROOF) - ) - signature = bls.Sign(get_validator_private_key(), signing_root) - - return SignedExecutionProof( - message=execution_proof_message, - signature=signature, - ) -``` - -### `broadcast_execution_proof` - -```python -def broadcast_execution_proof(signed_proof: SignedExecutionProof) -> None: - """ - Broadcast an execution proof to the network. - """ - # Broadcast on the appropriate subnet based on proof system - subnet_id = compute_subnet_for_execution_proof(signed_proof.message.zk_proof.proof_type) - topic = f"execution_proof_{subnet_id}" - - broadcast_to_topic(topic, signed_proof) -``` diff --git a/specs/_features/eip8025/zkevm.md b/specs/_features/eip8025/zkevm.md deleted file mode 100644 index 2831ea0fde..0000000000 --- a/specs/_features/eip8025/zkevm.md +++ /dev/null @@ -1,221 +0,0 @@ -# EIP-8025 -- zkEVM - -*Note*: This document is a work-in-progress for researchers and implementers. - - - -- [Introduction](#introduction) -- [Constants](#constants) -- [Types](#types) -- [Cryptographic types](#cryptographic-types) -- [Containers](#containers) - - [`ZKEVMProof`](#zkevmproof) - - [`PrivateInput`](#privateinput) - - [`PublicInput`](#publicinput) -- [Helpers](#helpers) - - [Preprocessing](#preprocessing) - - [`generate_keys`](#generate_keys) - - [Proof verification](#proof-verification) - - [`verify_execution_proof_impl`](#verify_execution_proof_impl) - - [`generate_verification_key`](#generate_verification_key) - - [Proof generation](#proof-generation) - - [`generate_execution_proof_impl`](#generate_execution_proof_impl) - - [`generate_proving_key`](#generate_proving_key) - - [`verify_zkevm_proof`](#verify_zkevm_proof) - - [`generate_zkevm_proof`](#generate_zkevm_proof) - - - -## 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) | - -## 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` - -```python -class ZKEVMProof(Container): - proof_data: ByteList[MAX_PROOF_SIZE] - proof_type: ProofID - public_inputs: PublicInput -``` - -### `PrivateInput` - -```python -class PrivateInput(Container): - execution_payload: ExecutionPayload - execution_witness: ZKExecutionWitness -``` - -### `PublicInput` - -```python -class PublicInput(Container): - block_hash: Hash32 - parent_hash: Hash32 -``` - -## Helpers - -### Preprocessing - -#### `generate_keys` - -```python -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` - -```python -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` - -```python -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` - -```python -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` - -```python -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` - -```python -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` - -```python -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) -```