Skip to content

EIP-9999: amend EIP-8141 mode check, fix discard + mode-1 binding, spec-consistency fixes#1

Open
soispoke wants to merge 1 commit into
vbuterin:patch-3from
soispoke:fix/eip-9999-spec-consistency
Open

EIP-9999: amend EIP-8141 mode check, fix discard + mode-1 binding, spec-consistency fixes#1
soispoke wants to merge 1 commit into
vbuterin:patch-3from
soispoke:fix/eip-9999-spec-consistency

Conversation

@soispoke

@soispoke soispoke commented Jun 6, 2026

Copy link
Copy Markdown

This PR makes a set of small, text-provable spec fixes to eip-9999.md. It targets the patch-3 branch so the fixes flow into ethereum#11772. Design choices (dependency canonicalization, the wrapper cap model, proof placement, gas accounting, FOCIL binding) are not changed here; they are listed at the end as discussion comments.

Correctness

  1. EIP-8141 mode check. EIP-8141 enforces assert frame.mode < 3, so DEP_VERIFY_FRAME_MODE = 3 frames are rejected and the mechanism cannot validate as written. Amended to < 4. (The one fix without which nothing validates.)
  2. Discard set was dead code. The recursive circuit built discard_hashes as a set of hashes but tested raw dependency triples against it, so no discard ever applied (Test Case 10 could not pass). Now compares triples to a set of triples.
  3. Mode-1 wrapper binding. Mode-0 wrappers verify deps equals the referenced transactions' dependencies; mode-1 did not, so a mode-1 wrapper could carry a valid recursive STARK over deps unrelated to its transactions. Added the same binding to mode 1.

Clarifications

  1. Tx-by-hash wrappers require the node to hold the full transaction bytes before the wrapper can be validated or forwarded (needed to recompute dependencies(tx)).
  2. No-fold forwarding fallback. A node that cannot produce a fresh recursive wrapper before the next interval SHOULD forward the wrappers it already verified, so folding stays an optimization rather than a liveness gate.
  3. AGGREGATED_VK propagation. Stated that AGGREGATED_VK is a protocol constant, never user-chosen, pinned by block validity rule 2 and carried unchanged through every recursion level (which is why a recursive proof's public inputs are [deps_hash, AGGREGATED_VK] while a leaf takes only data_hash); distinguished it from the per-dependency user vks in the Security note.

Editorial

  1. "two new frame modes" → "one new frame mode" (only one is defined).
  2. FRAMEDATASIZE is not an EIP-8141 instruction; use FRAMEPARAM(0x04, i) for length (matches this EIP's own introspection list).
  3. Unified get_dependencies(block) / dependencies(block) to the defined name.

Design comments (out of scope for this PR — flagging for discussion)

These are real but change semantics or the DoS model, so they are not in this bug-fix PR:

  1. Dependency canonicalization. get_deps_hash(filtered_deps) == block_deps_hash cannot hold when a block has a duplicate (scheme, data_hash, vk) triple (the block hash counts it twice, the circuit dedups to one) or when the proof is assembled by recursive union (deps ++ inner_deps order ≠ block-tx order). Likely fix: make dependencies a canonical set (sort by the 96-byte dep_id and dedup) in both block_deps_hash and the circuit. This changes consensus semantics, so flagging rather than patching.
  2. Mode-0 vs mode-1 cap axis. MAX_LEANSTARK_DEPS_PER_WRAPPER = 1 (a Mempool-Level Limit) means a mode-1 mempool wrapper can't aggregate more than one STARK-bearing tx, contradicting "one wrapper containing all currently active transactions". A recursive proof is ~constant size, so leaf count is the wrong axis. Suggest: per-dep caps apply to mode-0 raw wrappers; mode-1 wrappers bounded by serialized size + a tx-reference count.
  3. Per-tx caps not enforced. MAX_SIGS_PER_TX / MAX_STARKS_PER_TX are described in Security as the primary DoS defense, but no validity rule enforces them, and MAX_DEPENDENCIES_PER_FRAME = 256 lets one frame exceed both.
  4. Gas. recursive_stark_gas appears to charge each dependency twice (per-frame + block-level) and bills users via base fee for the builder's work — clarify additive-vs-replacing and the payer. Separately, make the proof-size bound explicit (fixed trace width, 2**24 cycle cap) so flat gas is visibly justified. (Not proposing dynamic gas.)
  5. Proof placement. The header carries the full proof inline; consider committing only to a recursive_stark root + block_deps_hash and carrying the proof bytes in a separate erasure-coded object (ePBS commits the small header first, sends the body later).
  6. FOCIL. FOCIL validation doesn't state attesters must check deps_hash == hash(deps of the FOCIL's txs) and verify against AGGREGATED_VK (the same hole Spelling, Grammar, Initial Structure ethereum/EIPs#3 closes for mempool wrappers); and FOCIL = [transactions, recursive_stark] intentionally exceeds EIP-7805's 8 KiB IL budget — worth one line documenting that accepted tradeoff.
  7. Rationale notes: mention mempool sharding as future work; note that aggregation incentives are a deferred open problem; and reconcile "unlimited-depth recursion" with the depth-2 soundness assumption.

…ec-consistency fixes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant