Skip to content

Make ExecutionEngine highly recommended but optional#5151

Open
barnabasbusa wants to merge 4 commits intoethereum:masterfrom
barnabasbusa:bbusa/eip8025-optional-execution-engine
Open

Make ExecutionEngine highly recommended but optional#5151
barnabasbusa wants to merge 4 commits intoethereum:masterfrom
barnabasbusa:bbusa/eip8025-optional-execution-engine

Conversation

@barnabasbusa
Copy link
Copy Markdown
Member

Summary

This PR extends the fire-and-forget pattern used for the ProofEngine (introduced in #5055) to the ExecutionEngine in EIP-8025, while adding a validator-level rule that preserves the missed-attestation penalty signal for validators that opt out of running a local EL.

This was originally opened as frisitano#3 against the feat/eip8025-refactor branch. Since #5055 is now merged upstream, this PR re-targets ethereum/consensus-specs:master. See the original thread for prior review discussion from @frisitano and @mkalinin — summarized in the "Prior review" section below.

Proposal

Two changes:

  1. Drop the assert on execution_engine.verify_and_notify_new_payload in process_execution_payload, matching the fire-and-forget ProofEngine treatment. A node that chooses not to run a local execution engine (e.g. a stateless client consuming proofs) should not be forced to by the consensus spec.
  2. Add an attestation execution-validity gating rule to a new validator.md (SHOULD-level): a validator SHOULD NOT attest to a block whose execution_payload has not been independently validated — either by a local EL returning VALID, or by a verified SignedExecutionProof whose public_input.new_payload_request_root matches the block's NewPayloadRequest, received by the attestation deadline. If neither signal is available, the validator SHOULD withhold attestation.

Why both changes are needed

Removing the consensus-level assert alone would be unsafe during the optional-proof phase:

  • proof_engine.notify_new_payload is fire-and-forget; it performs no verification.
  • process_execution_proof (which does verify proofs) is only invoked via execution_proof gossip validation — it is not part of block state-transition.
  • Proofs are explicitly optional, arrive asynchronously, and may not be available before the 4-second attestation deadline.
  • Without a gating rule, validators with no EL and no proof-in-hand would still happily attest to invalid blocks, and there would be no missed-attestation penalty to self-correct the behavior.

Change (2) restores the penalty signal. Validators that opt out of the EL and also fail to receive a valid proof in time simply miss their attestation and pay the standard inactivity penalty — making the opt-out economically self-regulating rather than a silent safety risk.

What changed

  • specs/_features/eip8025/beacon-chain.md
    • Removed assert wrapper on execution_engine.verify_and_notify_new_payload(...).
    • Updated the *Note* above process_execution_payload to describe both engines as fire-and-forget notifications and to be explicit that execution-validity verification becomes out-of-band.
    • Updated the inline comment next to the EL call to match.
  • specs/_features/eip8025/validator.md (new file)
    • New section Attestation execution-validity gating under Beacon chain responsibilities encoding the SHOULD-rule described above, plus non-normative notes clarifying (a) follower/non-attesting nodes are unaffected and (b) validators running an EL see no behavioral change in practice.

Why "highly recommended" rather than "removed"

Running an execution engine remains the right default for defense-in-depth: independent check against proof-engine bugs/malicious provers, needed for local block building and fast attesting, useful fallback while proof availability/latency matures. Validators who want to opt out now pay the cost of either running a proof subscription or missing attestations — which seems like the right incentive shape for an optional-proof phase.

Prior review on frisitano#3

Not repeated here verbatim — please read the linked thread for full context — but the main discussion points were:

  • @frisitano (comment): wording tightening — "accepts execution payloads" should acknowledge NOT_VALIDATED / optimistic import semantics.
  • @frisitano (comment): alternative approach — instead of removing the assert, modify verify_and_notify_new_payload to return NOT_VALIDATED when no EL is configured.
  • @mkalinin (comment): SHOULD NOT → MUST NOT, on the grounds that SHOULD leaves clients technically spec-compliant if they attest without either signal.
  • @mkalinin (comment): proposed alternative architecture — keep the assertion, change verify_and_notify_new_payload to return True only when EL returned VALID or a VALID proof has been received from p2p; let Optimistic Sync handle the pending-proof state (analogous to how SYNCING/ACCEPTED is handled today).

Happy to iterate on these in this PR.

Open questions for discussion

  • Do we want to go further and rename/repoint the call to a pure execution_engine.notify_new_payload (returning None) to match the proof engine signature exactly? That is more invasive since verify_and_notify_new_payload is defined up the fork hierarchy (Bellatrix onwards), so I kept this PR to the minimal semantic change.
  • Should the SHOULD-rule be strengthened to a MUST during the transitional phase (per @mkalinin's suggestion), or is SHOULD the right level given it's guidance for honest validators and we cannot punish deviation on-chain?
  • Any need for a fork-choice-level rule in addition to the attestation rule, or is the attestation penalty signal sufficient?
  • @mkalinin's "keep the assert, route through Optimistic Sync" approach vs. the approach taken here — worth comparing explicitly.

Test plan

  • Rendered markdown reads correctly on GitHub (ToC, section anchors).
  • Spec builder still parses eip8025/beacon-chain.md (verified locally — Python blocks AST-parse cleanly; only change is assert removal).
  • Review of the new validator.md section for correctness of the proof-matching condition (public_input.new_payload_request_root against hash_tree_root(new_payload_request)).
  • Discussion with reviewers on SHOULD vs MUST level and on any interaction with fork choice.

Mirror the fire-and-forget pattern used for ProofEngine by dropping the
assert on `execution_engine.verify_and_notify_new_payload`. With EIP-8025
execution proofs, consensus correctness is established via the proof
engine path, so gating consensus on the execution engine's response is no
longer strictly required. Running an execution engine remains highly
recommended for defense-in-depth.
…ted by proofs

The previous phrasing "consensus correctness is established via the proof
engine path" was misleading -- `process_execution_proof` runs during gossip
validation, not as part of block state-transition, and proofs are explicitly
optional in this EIP. With the execution-engine assert removed, consensus no
longer verifies execution validity at all; validity becomes an out-of-band
concern handled by a locally-run execution engine and/or by asynchronously
gossiped execution proofs. State this explicitly so the trade-off is visible
to readers.
Introduce a validator SHOULD-rule that gates attestation on having an
independent execution-validity signal: either a local ExecutionEngine VALID
response or a verified SignedExecutionProof for the corresponding
NewPayloadRequest. This restores the missed-attestation penalty signal for
validators that opt out of running a local execution engine, so that
opt-out validators who also fail to verify a proof before the attestation
deadline self-correct via standard inactivity penalties rather than silently
attesting to invalid blocks.

Addresses reviewer concern that merely removing the consensus-level assert
left validators free to attest to any syntactically valid block without
any execution-validity verification.
@jtraglia jtraglia changed the title EIP-8025: make ExecutionEngine highly recommended but optional Make ExecutionEngine highly recommended but optional Apr 24, 2026
@frisitano
Copy link
Copy Markdown
Contributor

frisitano commented Apr 24, 2026

I've opened #5161 as a draft alternative that handles the optional-engine aspect of EIP-8025 entirely in sync/optimistic.md, with no function-signature changes, no modification to beacon-chain.md pseudocode, and no new validator.md. Single file, 28 insertions.

Short version of the rationale:

  • Keep ExecutionEngine and ProofEngine strictly disjoint at the function level — don't couple them inside verify_and_notify_new_payload per @mkalinin's sketch. Two orthogonal validity sources stay orthogonal.
  • Engine-absence (treated as NOT_VALIDATED) and ProofEngine as a parallel VALID signal source both live in sync/optimistic.md as prose — the idiomatic home for NOT_VALIDATED semantics and signal-driven transitions.
  • Existing optimistic-sync attestation rules already cover honest-validator behaviour; new validator.md becomes redundant.

@mkalinin — thanks for the Optimistic Sync routing suggestion on frisitano#3. I've taken that direction in #5161 but kept EE and PE disjoint rather than coupling them inside verify_and_notify_new_payload — happy to discuss the tradeoff.

I don't have strong conviction on what the best approach is; wanted to provide this as a potential direction for our discussions.

@mkalinin
Copy link
Copy Markdown
Contributor

  • Keep ExecutionEngine and ProofEngine strictly disjoint at the function level — don't couple them inside verify_and_notify_new_payload per @mkalinin's sketch. Two orthogonal validity sources stay orthogonal.

Agreed. But then I would prefer to have a maybe abstract but explicit definition of the second source of payload validity in the spec, i.e. ProofEngine there can also be an abstract function get_payload_proofs() which returns all payload proofs received by a node.

@frisitano
Copy link
Copy Markdown
Contributor

  • Keep ExecutionEngine and ProofEngine strictly disjoint at the function level — don't couple them inside verify_and_notify_new_payload per @mkalinin's sketch. Two orthogonal validity sources stay orthogonal.

Agreed. But then I would prefer to have a maybe abstract but explicit definition of the second source of payload validity in the spec, i.e. ProofEngine there can also be an abstract function get_payload_proofs() which returns all payload proofs received by a node.

Currently, the ProofEngine is defined here https://github.com/ethereum/consensus-specs/blob/master/specs/_features/eip8025/proof-engine.md. It is designed to mirror the interface for the execution engine. I would consider the proof engine and the execution engine to be "execution payload validity oracles". However, it lacks the get_payload_proofs method you mention, so that would need to be added.

frisitano added a commit to frisitano/consensus-specs that referenced this pull request Apr 24, 2026
Adds prose to sync/optimistic.md covering two EIP-8025-specific cases
without changing any function signatures or pseudocode in beacon-chain.md:

1. Engine absence: when a consensus engine is not configured with an
   ExecutionEngine (or ProofEngine), the corresponding signal is treated
   as NOT_VALIDATED for the purposes of optimistic import. A block is
   non-optimistic only after at least one signal source returns VALID.

2. ProofEngine as parallel VALID signal source: when the ProofEngine
   returns VALID for a SignedExecutionProof whose
   public_input.new_payload_request_root matches a block's
   NewPayloadRequest, the consensus engine transitions the block from
   NOT_VALIDATED -> VALID in the same manner as an ExecutionEngine VALID
   response.

This keeps ExecutionEngine and ProofEngine strictly disjoint at the
function level, with unification at the fork-choice / optimistic-sync
layer. No changes to beacon-chain.md pseudocode, no Optional[] cascade
through the fork hierarchy, no new validator.md file. Existing
optimistic-sync attestation rules cover honest-validator behaviour.

Alternative direction to ethereum#5151.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

3 participants