Skip to content

Refactor EIP8025 proof engine and p2p interface#5055

Open
frisitano wants to merge 2 commits intoethereum:masterfrom
frisitano:feat/eip8025-refactor
Open

Refactor EIP8025 proof engine and p2p interface#5055
frisitano wants to merge 2 commits intoethereum:masterfrom
frisitano:feat/eip8025-refactor

Conversation

@frisitano
Copy link
Copy Markdown
Contributor

EIP-8025 specification refactor

This PR refactors the EIP-8025 specification across several dimensions: simplifying the proof engine interface, tightening gossip validation rules, improving sync protocol expressiveness, and replacing the prover relay model with a validator-driven proof re-signing flow.

Changes

beacon-chain.md

  • Remove the bespoke NewPayloadRequestHeader container in favour of reusing the existing NewPayloadRequest type already passed to the execution engine. We can introduce NewPayloadRequestHeader when we actually use it in the BiB protocol.
  • Replace assert proof_engine.verify_new_payload_request_header(...) with a fire-and-forget proof_engine.notify_new_payload(...) — the proof engine is informed of the new payload but consensus is not gated on its response.

proof-engine.md

  • Rename verify_new_payload_request_headernotify_new_payload, reflecting that this is a notification rather than a synchronous verification step.

p2p-interface.md

  • Add two new gossip IGNORE rules for the execution_proof topic: deduplication by hash_tree_root(proof), and ignoring proofs from validators whose public key has previously produced an invalid proof.
  • Add proof_types to ExecutionProofStatus as a dynamic capability advertisement, so peers can communicate which proof types they support without requiring a hard fork or new client release. This enables new proof types to be rolled out and adopted incrementally.
  • Add proof_filters: List[ProofByRootIdentifier, ...] to ExecutionProofsByRange so callers can request specific proof types for specific block roots within a range, rather than fetching all proofs for all blocks. @nalepae had previously flagged this, and upon reflection, I think his proposal was correct.

prover.md

  • Replace the callback-based prover relay model with an SSE-driven flow: the prover subscribes to beacon node Block events and proof engine completion events, tracks requests by new_payload_request_root, and constructs SignedExecutionProof on completion.

validator.md (new)

  • Introduce a validator guide for EIP-8025.
  • Document proof re-signing: validators that receive a valid SignedExecutionProof MAY re-sign and re-gossip it under their own key to ensure availability for peers that may have blacklisted the original signer due to a prior invalid proof submission.

parent_beacon_block_root=state.latest_block_header.parent_root,
execution_requests=body.execution_requests,
)
)
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.

The proof engine call is deliberately non-asserting. Consensus correctness does not depend on the proof engine's state — notify_new_payload is a best-effort notification to allow the engine to begin proof verification or caching ahead of receiving gossip proofs.

new_payload_request_header: NewPayloadRequestHeader,
) -> bool:
new_payload_request: NewPayloadRequest,
) -> None:
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.

Return type is None — the proof engine is not expected to return a result synchronously. Proof outcomes are delivered asynchronously via SSE events and the verify_execution_proof path.

Comment on lines +80 to +81
- _[IGNORE]_ The proof has not already been processed -- i.e.
`hash_tree_root(proof)` has not been seen before.
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.

Placed first as the cheapest deduplication check — avoids redundant signature verification and state lookups for proofs we have already processed.

Comment on lines +93 to +95
- _[IGNORE]_ The validator has not previously sent an invalid proof -- i.e. no
*invalid* proof from the public key associated with
`signed_execution_proof.validator_index` has been received.
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.

Keyed on public key rather than validator_index because validator indices are epoch-dependent and can be reused after exits. Blacklisting by public key is stable across the validator lifecycle.

@github-actions github-actions bot added the eip8025 Optional Execution Proofs label Mar 28, 2026
(
block_root: Root
slot: Slot
proof_types: List[ProofType, MAX_EXECUTION_PROOFS_PER_PAYLOAD]
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.

proof_types is a dynamic capability advertisement rather than a protocol constant. A client advertises the proof types it currently supports at the point of request, allowing peers to make informed decisions during sync and peer selection. Critically, this means new proof types can be rolled out and adopted by clients without requiring a hard fork or coordinated client release — a client that understands a new proof type simply starts advertising it.

Copy link
Copy Markdown
Contributor Author

@frisitano frisitano Mar 28, 2026

Choose a reason for hiding this comment

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

This may be problematic regarding consensus so I would encourage discussion on this.

(
start_slot: Slot
count: uint64
proof_filters: List[ProofByRootIdentifier, MAX_REQUEST_BLOCKS_DENEB]
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.

Mirrors the ProofByRootIdentifier filtering already present in ExecutionProofsByRoot. Useful when a client has partially synced proofs for a range and only needs specific missing proof types for specific blocks, avoiding redundant data transfer.


## Beacon chain responsibilities

### Proof re-signing
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.

A validator that previously sent an invalid proof to some peers will be ignored by those peers for all future proofs. Re-signing by a different validator re-introduces the proof under a clean public key, preventing liveness issues where a subset of the network never sees a valid proof for a given block.

@frisitano frisitano changed the title refactor: eip8025 refactor Refactor EIP8025 proof engine and p2p interface Mar 28, 2026
@jtraglia jtraglia requested a review from jihoonsong March 28, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

eip8025 Optional Execution Proofs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant