Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8399512
initial commit
kevaundray Sep 15, 2025
9b78a25
rename to zkevm_proof
kevaundray Sep 15, 2025
abb1360
remove payload header from verify_zkevm_proof
kevaundray Sep 15, 2025
d887390
initial beacon chain commit
kevaundray Sep 16, 2025
882fb04
remove fork epoch and version
kevaundray Sep 16, 2025
833dca3
commit fork.md
kevaundray Sep 16, 2025
81326d4
remove fork.md (ie no fork is needed)
kevaundray Sep 16, 2025
4bd49cc
add SignedExecutionProof
kevaundray Sep 16, 2025
69ebaa3
initial validator.md
kevaundray Sep 16, 2025
bb16ed4
remove MAX_PROF_SYSTEM
kevaundray Sep 16, 2025
6ba4645
raise exception when proofID not found
kevaundray Sep 16, 2025
f9d600c
init p2p-interface.md
kevaundray Sep 16, 2025
93fce96
Merge branch 'master' into kw/zkevm-proof
kevaundray Sep 16, 2025
d890137
ExecutionWitness -> ZkExecutionWitness
kevaundray Sep 16, 2025
4f78959
use SignedExecutionProofs
kevaundray Sep 16, 2025
564e33e
ExecutionWitness -> ZKExecutionWitness
kevaundray Sep 16, 2025
860b277
JT review
kevaundray Sep 16, 2025
fe497a7
EL_PROGRAM -> ProgramSource
kevaundray Sep 16, 2025
15da8bf
remove ProgramSource
kevaundray Sep 16, 2025
fcc6bdf
rm
kevaundray Sep 16, 2025
7ba7640
remove public methods header and ProgramSource
kevaundray Sep 16, 2025
b912057
remove multiple EL programs
kevaundray Sep 16, 2025
21376dd
make lint
kevaundray Sep 16, 2025
998f2aa
make lint
kevaundray Sep 16, 2025
be4509a
Merge branch 'master' into kw/zkevm-proof
kevaundray Sep 16, 2025
780918c
use blockhash and subnet id
kevaundray Sep 16, 2025
feb53be
lint
kevaundray Sep 16, 2025
bd54aae
append proof_id to bytecode
kevaundray Sep 16, 2025
f197c2a
change desc
kevaundray Sep 16, 2025
69b967e
extend description
kevaundray Sep 16, 2025
4027018
multi:
kevaundray Sep 16, 2025
6175bcb
add comments on the constants
kevaundray Sep 16, 2025
187307b
update domain type
kevaundray Sep 16, 2025
605ac53
rename folder: execution_proofs -> optional_execution_proofs
kevaundray Sep 16, 2025
f5d62ad
remove extraneous constants
kevaundray Sep 16, 2025
9b7179c
reduce `MAX_EXECUTION_PROOFS_PER_PAYLOAD` -- its arbitrary
kevaundray Sep 16, 2025
a367540
reduce maximum amount of proofs per payload and make ProgramBytecode …
kevaundray Sep 16, 2025
52010b9
rename folder eip8025
kevaundray Sep 17, 2025
504568d
Fix spec titles & use minlevel=2 for toc
jtraglia Sep 17, 2025
2752875
Fix some nits
jtraglia Sep 17, 2025
5220338
Add eip8025 section to release notes
jtraglia Sep 17, 2025
9adbefa
Fix prereq sentence
jtraglia Sep 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions specs/_features/execution_proofs/beacon-chain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Execution Proofs -- The Beacon Chain

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

## Table of contents

<!-- mdformat-toc start --slug=github --no-anchors --maxlevel=6 --minlevel=1 -->

- [Execution Proofs -- The Beacon Chain](#execution-proofs----the-beacon-chain)
- [Table of contents](#table-of-contents)
- [Introduction](#introduction)
- [Constants](#constants)
- [Execution](#execution)
- [Domain types](#domain-types)
- [Configuration](#configuration)
- [Containers](#containers)
- [New containers](#new-containers)
- [`ExecutionProof`](#executionproof)
- [`SignedExecutionProof`](#signedexecutionproof)
- [Extended Containers](#extended-containers)
- [Helper functions](#helper-functions)
- [Execution proof functions](#execution-proof-functions)
- [`verify_execution_proof`](#verify_execution_proof)
- [`verify_execution_proofs`](#verify_execution_proofs)
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
- [Execution payload processing](#execution-payload-processing)
- [Modified `process_execution_payload`](#modified-process_execution_payload)

<!-- mdformat-toc end -->

## Introduction

This document contains the consensus specs for Execution Proofs. This enables stateless validation of execution payloads through cryptographic proofs.

*Note*: This specification assumes the reader is familiar with the [zkEVM cryptographic operations](./zkevm.md).

## Constants

### Execution

| Name | Value |
| --------------------------------------- | ----------------- |
| `MAX_EXECUTION_PROOFS_PER_PAYLOAD` | `uint64(8)` |
| `PROGRAM` | `ProgramSource(b"PROG_V1" + b"\x00" * 25)` |

### Domain types

| Name | Value |
| -------------------------- | -------------------------- |
| `DOMAIN_EXECUTION_PROOF` | `DomainType('0x0A000000')` |

## Configuration

*Note*: The configuration values are not definitive.

| Name | Value |
| -------------------------------- | ------------------------------- |
| `MIN_REQUIRED_EXECUTION_PROOFS` | `uint64(1)` |

## Containers

### New containers

#### `ExecutionProof`

```python
class ExecutionProof(Container):
beacon_root: Root
zk_proof: ZKProof
validator_index: ValidatorIndex
```

#### `SignedExecutionProof`

```python
class SignedExecutionProof(Container):
message: ExecutionProof
signature: BLSSignature
```

### Extended Containers

*Note*: `BeaconState` and `BeaconBlockBody` remain the same as Fulu. No modifications are required for execution proofs since they are handled externally.

## Helper functions

### Execution proof functions

#### `verify_execution_proof`

```python
def verify_execution_proof(signed_proof: SignedExecutionProof, parent_hash: Hash32, block_hash: Hash32, state: BeaconState, el_program: ProgramSource) -> bool:
"""
Verify an execution proof against a payload header using zkEVM verification.
"""

# Note: signed_proof.message.beacon_root verification would 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)
```

#### `verify_execution_proofs`

```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 the execution proofs for the given payload block hash
signed_execution_proofs = retrieve_execution_proofs(block_hash)

# Verify we have 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
```

## Beacon chain state transition function

### Execution payload processing

#### Modified `process_execution_payload`

```python
def process_execution_payload(
state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine, stateless_validation: bool = False

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main change is additional stateless_validation parameter. When set to false, nothing changes from the fork it was built upon

) -> 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
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
# Verify prev_randao
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
# Verify timestamp
assert payload.timestamp == compute_time_at_slot(state, state.slot)
# Verify commitments are under limit
assert (
len(body.blob_kzg_commitments)
<= 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:
# Traditional validation - execute the payload
versioned_hashes = [
kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments
]
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,
)
)

# Cache execution payload header
state.latest_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,
)
```
89 changes: 89 additions & 0 deletions specs/_features/execution_proofs/p2p-interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Execution Proofs -- Networking

This document contains the networking specification for Execution Proofs.

## Table of contents

<!-- mdformat-toc start --slug=github --no-anchors --maxlevel=6 --minlevel=1 -->

- [Execution Proofs -- Networking](#execution-proofs----networking)
- [Table of contents](#table-of-contents)
- [Constants](#constants)
- [Containers](#containers)
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
- [Topics and messages](#topics-and-messages)
- [Global topics](#global-topics)
- [`execution_proof`](#execution_proof)
- [The Req/Resp domain](#the-reqresp-domain)
- [Messages](#messages)
- [ExecutionProofsByHash](#executionproofsbyHash)

<!-- mdformat-toc end -->

## Constants

*Note*: Execution proof subnets use `MAX_EXECUTION_PROOFS_PER_PAYLOAD` (from [beacon-chain.md](./beacon-chain.md)) to provide 1-to-1 mapping with proof systems. Each proof system gets its own dedicated subnet.

## Containers

*Note*: Execution proofs are broadcast directly as `SignedExecutionProof` containers. No additional message wrapper is needed.

## The gossip domain: gossipsub

### Topics and messages

#### 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.beacon_root, signed_execution_proof.message.validator_index)`.
- _[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`.

Subnet topics follow the pattern: `/eth2/execution_proof_{subnet_id}/ssz_snappy`

## The Req/Resp domain

### Messages

#### ExecutionProofsByHash

**Protocol ID:** `/eth2/beacon/req/execution_proofs_by_hash/1/`

The `<context-bytes>` field is calculated as `context = compute_fork_digest(fork_version, genesis_validators_root)`.

Request Content:
```
(
Hash32 # block_hash
)
```

Response Content:
```
(
List[SignedExecutionProof, MAX_EXECUTION_PROOFS_PER_PAYLOAD]
)
```

Requests execution proofs for the given execution payload `block_hash`. The response MUST contain all available proofs for the requested block hash, up to `MAX_EXECUTION_PROOFS_PER_PAYLOAD`.

The following validations MUST pass:
- _[REJECT]_ The `block_hash` is a 32-byte value.

The response MUST contain:
- All available execution proofs for the requested block hash
- The response MUST NOT contain more than `MAX_EXECUTION_PROOFS_PER_PAYLOAD` proofs
83 changes: 83 additions & 0 deletions specs/_features/execution_proofs/validator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Execution Proofs -- Validator

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

## Table of contents

<!-- mdformat-toc start --slug=github --no-anchors --maxlevel=6 --minlevel=1 -->

- [Execution Proofs -- Validator](#execution-proofs----validator)
- [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)

<!-- mdformat-toc end -->

## Introduction

This document represents optional execution proof generation capabilities that validators may choose to implement.

## Prerequisites

This document is an extension of the [Fulu -- Validator](../../fulu/validator.md) guide.

## 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)
```
Loading
Loading