Workspace IndexDev Notes › L1 zkEVM — the word doing the work is "optional"

#7PoC

L1 zkEVM — the word doing the work is "optional"

EIP-8025 lets a validator verify a block by checking a proof instead of re-executing it. The number nobody publishes is how many still re-execute once it is cheaper not to.

Not yet scoped — start by proving recent mainnet blocks with an off-the-shelf zkVM on rented GPU and plotting wall-clock proving time against gas used, then check where Glamsterdam's 200M gas target lands relative to the reveal window ePBS opens. Source: EIP-8025 (Optional Execution Proofs), targeted at the Hegotá fork and dependent on Glamsterdam's EIP-7732 and EIP-7928.

Why

Two forks make one machine, and it is worth stating the dependency plainly because the roadmap coverage rarely does. Glamsterdam sets out two chairs: ePBS (EIP-7732) supplies time, because splitting the slot seats the builder as prover and opens an interval between header commitment and payload reveal; BAL (EIP-7928) supplies partition, because a block that declares the state it will touch is a block whose proving work can be sliced across many provers. Neither alone makes a twelve-second proof possible, which is why EIP-8025 sits in Hegotá rather than in Glamsterdam. That much is architecture. The part worth a card is the adjective. These are optional execution proofs, and the option is the whole design: a validator may check a succinct proof of the state transition instead of running the transactions. Proof-checking has to be cheaper than re-execution or nobody takes the option, and if it is cheaper then a rational validator takes it — all of them. At that point the network's ability to notice a prover bug rests entirely on whoever is still paying more to re-execute, which is to say on validators behaving irrationally. Safety that depends on people declining a discount is the same shape this catalogue already recorded in the Aqua card, where quoted depth is real but only for whoever arrives first, and in the note on Tempo, where a single client plus a halt-rather-than-be-wrong posture turns one bug into an outage. The question is not whether the proofs are sound. It is what fraction of the network keeps the capacity to disagree with them.

How it works

Mechanism first, as documented: a validator may verify a block by checking a succinct proof of the state transition rather than re-executing its transactions, with the mainnet state transition function exposed to the execution layer through an EXECUTE precompile in the EIP-8079 draft, and Native Rollups built on the same primitive. Proving is made feasible by the two Glamsterdam pieces above rather than by any change in EIP-8025 itself. Two measurements, both small enough to run without building anything. First, the window. Take a few dozen recent mainnet blocks, prove them with an off-the-shelf zkVM on a rented GPU, and plot wall-clock proving time against gas used. The output is one number and one curve: the largest block that proves inside the interval ePBS opens, and the hardware it took to get there. Set that against Glamsterdam's 200M gas target and the gap either closes or it does not, and if it does not then the option is theoretical and this card's second half is premature. Second, the discount. Price the cost of verifying a proof against the cost of re-executing the same block on a home-spec node. That ratio is the adoption rate, and the adoption rate is the erosion of re-execution coverage, so the interesting output is not the ratio itself but the fraction of stake at which nobody is left to catch a bad prover. One section belongs inside this card rather than beside it: the list. The ePBS card asked which code silently assumes the proposer knows the payload; this one asks the twin question, which code silently assumes somebody actually ran the transactions. Fraud proofs, re-org monitors, block explorers that recompute receipts, and any service that trusts a value because it saw a node produce it are all candidates, and the list is cheap to write now and expensive to write during a testnet.

Update 2026-08-25 — the mechanism, and what the option actually rests on

What a proof asserts. Block execution is one function: newStateRoot = STF(oldStateRoot, block). The proof asserts knowledge of an execution trace carrying the first to the third. Public inputs are the old root, a commitment to the block, and the claimed new root; the witness — full trace, every signature, every storage access — stays inside. Verification is a short function over the public inputs returning true or false in milliseconds.

Why the block hash is not the weak point. The commitment pins which block is under discussion, not what gets checked. The circuit carries a constraint that the hash of the transactions actually executed equals the committed hash, so a prover that ran a different set cannot produce a proof at all. Signature validity, nonce ordering, balance sufficiency and gas accounting all sit inside the state transition function being proven — an invalid transaction cannot be "correctly executed" into a state change.

What proofs do not cover. Correctness, not completeness or fairness. Inclusion is untouched: omitting a transaction yields a perfectly valid proof, which is FOCIL's problem rather than this one. Ordering is untouched, so MEV survives intact. Data availability sits outside the proof entirely — if the payload is never published, "some set hashing to H executed correctly" is true and useless, since nobody can compute a balance or construct an exit proof. On L1 this is moot because payloads propagate; on a validium it is the entire problem, and it is why a forced-exit guarantee reverts to a promise the moment an operator withholds data.

Who actually re-executes. Four groups, one of them robust. Those who need the state anyway — indexers, explorers, exchanges — re-execute at any discount, because proof verification returns one bit while their product is the state itself. Those who distrust the proof system shrink as incident-free years accumulate, so the thin moment arrives late rather than early. Un-upgraded nodes are real but cannot be designed around. Paid watchdogs do not exist in protocol today.

The trouble is that the robust group cannot reject a block. Influencing consensus requires stake, and stake has the sharpest incentive to take the discount. The group with the most durable reason to keep re-executing holds no veto, and the group holding the veto has the strongest reason to stop. Time compounds it: an indexer noticing a mismatch two hours later is noticing after finality, where reversal is a social problem rather than a technical one. Detection is a far weaker guarantee than rejection, so the measurement must be stake-weighted rather than node-counted.

Proof diversity — why it is the strongest candidate fix. Different zkVMs prove the same sentence. Their internals differ completely while their claims are bound to identical public inputs, so outputs need no reconciliation: the answer is already fixed at one newStateRoot, and each proof independently attests to it. If zkVM A carries a bug in, say, its MULMOD circuit, it can produce a passing proof for a wrong root — but zkVM B, to agree, would have to prove a false statement, which a sound system cannot do. Disagreement therefore surfaces mechanically. In consensus it would read roughly:

required = {A, B, C}
valid = count(S in required where Verify_S(oldRoot, blockCommit, newRoot, proof_S))
block valid  ⟺  valid ≥ N

Note that newRoot is the same variable throughout the loop, so agreement is structural rather than separately adjudicated. Cost stays a few milliseconds.

Where diversity leaks. Three places, and the third is the interesting one. First, the diversity may be surface-only: client diversity worked because implementations were written independently from a spec, whereas zkVMs frequently share proof-system families, hash and curve implementations, and base libraries — a bug beneath the diversity layer produces the same wrong answer three times. Second, requiring N proofs multiplies proving cost and lets the slowest prover set the pace, so a single system's outage becomes a liveness failure. Third and most important, the same discount dynamic reappears one level down: if one zkVM is meaningfully cheaper, provers concentrate on it and the monoculture returns. Ethereum's ongoing client-diversity concern is the live demonstration that a norm is not a rule. Diversity therefore only works if the protocol names the required systems in consensus — which is a real departure from Ethereum's practice of keeping implementation names out of the protocol — and it makes several verifier implementations consensus-critical, adding attack surface at the verification layer to remove it at the proving layer.

And the aggregation irony. Carrying three proofs per block is heavy, so the practical construction is recursive aggregation: one circuit proves that A, B and C all verified, emitting a single small proof. Elegant, and almost certainly where this goes — except the aggregation circuit is shared code again. The efficient implementation of diversity reintroduces a monoculture at the aggregation layer.

What diversity still cannot catch, and the resulting design. Diversity defends against an implementation bug in one prover. It does not defend against a bug shared by all provers, whether through a common dependency or through an ambiguous specification, because every system proves the same statement about the same spec. Only re-execution is grounded in actually running the thing. The two are complementary rather than alternative:

one prover wrong all provers wrong (shared dependency or spec)
Proof diversity caught not caught
Mandatory sampled re-execution caught caught

Sampling a small random subset of validators per slot — the machinery attestation committees already use — keeps cost low while making "nobody re-executes" structurally impossible.

Measurement added to this card. Alongside the window and the discount, a third number: the shared-dependency graph across candidate zkVMs. Diversity is only worth what the independence beneath it is worth, and that overlap is computable today from public dependency manifests. Nobody publishes it.

← All Dev Notes · Workspace Index · Top ↑

L1 zkEVM — 정작 일하는 단어는 '선택적'이다

EIP-8025는 검증자가 재실행 대신 증명을 확인해 블록을 검증하게 합니다. 아무도 발표하지 않는 숫자는, 재실행이 더 비싸진 뒤에도 여전히 재실행하는 노드가 몇이나 남는가입니다.

아직 범위 미정 — 최근 메인넷 블록들을 기성 zkVM으로(대여 GPU) 증명해 실시간 증명 소요 대 가스 사용량 곡선을 그리고, Glamsterdam의 200M 가스 목표가 ePBS가 열어주는 공개 창 대비 어디에 떨어지는지 확인하는 것부터. 출처: EIP-8025(Optional Execution Proofs), Hegotá 포크 대상이며 Glamsterdam의 EIP-7732·EIP-7928에 의존.

두 포크가 합쳐져 하나의 기계가 됩니다. 로드맵 기사들이 잘 짚지 않으니 의존 관계를 분명히 적어둘 값어치가 있습니다. Glamsterdam은 의자 둘을 놓습니다 — ePBS(EIP-7732)가 시간을 주고(슬롯이 쪼개지며 빌더가 증명자 자리에 앉고, 헤더 커밋과 페이로드 공개 사이에 구간이 생깁니다), BAL(EIP-7928)이 분할을 줍니다(건드릴 상태를 미리 선언한 블록은 증명 작업을 여러 증명자에게 쪼개 줄 수 있습니다). 둘 중 하나만으로는 12초 안의 증명이 성립하지 않고, 그래서 EIP-8025가 Glamsterdam이 아니라 Hegotá에 있습니다. 여기까지는 아키텍처입니다. 카드가 될 값어치는 형용사 하나에 있습니다. 이것은 선택적(optional) 실행 증명이고, 그 선택이 설계의 전부입니다 — 검증자는 트랜잭션을 돌리는 대신 상태전이의 간결한 증명을 확인해도 됩니다. 증명 확인이 재실행보다 싸야만 아무도 그 선택을 하지 않을 이유가 없고, 싸다면 합리적인 검증자는 전부 그쪽을 고릅니다. 그 순간 네트워크가 증명자 버그를 알아챌 능력은 여전히 더 비싼 재실행을 하고 있는 쪽, 즉 비합리적으로 행동하는 검증자들에게만 남습니다. 안전이 "모두가 할인을 받지는 않는다"에 기대는 구조 — 이 카탈로그가 이미 두 번 기록한 형태입니다. Aqua 카드에서 호가된 깊이는 실재하지만 먼저 도착한 사람에게만 실재했고, Tempo 메모에서는 단일 클라이언트에 "틀리느니 멈춘다"가 겹쳐 버그 하나가 곧 중단이 됐습니다. 질문은 증명이 건전한가가 아닙니다. 네트워크의 몇 퍼센트가 그 증명에 이의를 제기할 능력을 유지하는가입니다.

동작 방식

먼저 문서화된 동작 방식: 검증자는 트랜잭션을 재실행하는 대신 상태전이의 간결한 증명을 확인해 블록을 검증할 수 있고, 메인넷 상태전이함수는 EIP-8079 초안의 EXECUTE 프리컴파일로 실행 계층에 노출되며 Native Rollups도 같은 원시 기능 위에 섭니다. 증명이 가능해지는 것은 EIP-8025 자체의 변경이 아니라 위의 Glamsterdam 두 조각 덕분입니다. 측정은 둘이고, 둘 다 아무것도 만들지 않고 돌릴 만큼 작습니다. 첫째, 창(window). 최근 메인넷 블록 수십 개를 대여 GPU 위 기성 zkVM으로 증명하고, 실시간 증명 소요를 가스 사용량에 대해 그립니다. 산출물은 숫자 하나와 곡선 하나입니다 — ePBS가 여는 구간 안에 증명이 끝나는 최대 블록, 그리고 거기까지 든 하드웨어. 그것을 Glamsterdam의 200M 가스 목표에 대보면 간격이 닫히거나 닫히지 않고, 닫히지 않으면 그 선택지는 아직 이론이며 이 카드의 후반부는 시기상조입니다. 둘째, 할인율. 같은 블록을 가정용 사양 노드에서 재실행하는 비용과 증명을 검증하는 비용을 견줍니다. 그 비율이 곧 채택률이고, 채택률이 곧 재실행 커버리지의 침식이라, 흥미로운 산출물은 비율 자체가 아니라 나쁜 증명자를 잡을 사람이 아무도 남지 않게 되는 지분 비율입니다. 한 섹션은 옆에 두지 말고 이 카드 안에 넣습니다: 목록. ePBS 편이 "어떤 코드가 제안자가 페이로드를 안다고 암묵 가정하는가"를 물었다면, 이 편은 그 쌍둥이 질문을 묻습니다 — 어떤 코드가 누군가 실제로 트랜잭션을 돌렸다고 암묵 가정하는가. 사기 증명, 리오그 감시, 영수증을 재계산하는 익스플로러, 그리고 어떤 값을 "노드가 만들어내는 것을 봤으니" 믿는 모든 서비스가 후보이고, 이 목록은 지금 쓰면 싸고 테스트넷 도중에 쓰면 비쌉니다.

2026-08-25 보강 — 메커니즘, 그리고 '선택'이 실제로 무엇에 기대는가

증명이 주장하는 것. 블록 실행은 함수 하나입니다: newStateRoot = STF(oldStateRoot, block). 증명은 첫 값에서 셋째 값으로 가는 실행 과정을 알고 있음을 주장합니다. 공개 입력은 이전 상태 루트 · 블록 커밋먼트 · 주장하는 새 상태 루트 셋뿐이고, 증인(witness) — 전체 실행 트레이스, 모든 서명, 모든 스토리지 접근 — 은 안에 남습니다. 검증은 공개 입력에 대한 짧은 함수이고 수 밀리초에 참/거짓을 냅니다.

블록 해시는 약점이 아닙니다. 커밋먼트는 어느 블록 얘기인지를 고정할 뿐 검사 범위를 줄이지 않습니다. 회로 안에 "내가 실행한 트랜잭션들의 해시 == 커밋된 해시" 제약이 들어 있어서, 다른 트랜잭션을 돌린 증명자는 증명 자체를 만들지 못합니다. 서명 유효성·논스 순서·잔고 충분성·가스 회계는 전부 증명 대상인 상태전이함수 안에 있습니다 — 유효하지 않은 트랜잭션은 애초에 "올바르게 실행되어" 상태를 바꿀 수가 없습니다.

증명이 보장하지 않는 것. 보장하는 것은 정확성이지 완결성이나 공정성이 아닙니다. 포함(inclusion)은 무관합니다 — 트랜잭션을 빼도 증명은 완벽히 유효하고, 그건 FOCIL의 문제지 이 EIP의 문제가 아닙니다. 순서도 무관해서 MEV는 그대로 살아남습니다. 그리고 데이터 가용성은 증명 밖에 있습니다 — 페이로드가 공개되지 않으면 "해시가 H인 어떤 집합이 올바르게 실행됐다" 는 참이면서 쓸모가 없습니다. 잔고도 못 구하고 출금 증명도 못 만드니까요. L1에서는 페이로드가 전파되므로 문제가 안 되지만, validium에서는 이게 문제의 전부이고, 운영자가 데이터를 감추는 순간 강제 출금 보장이 다시 약속으로 되돌아가는 이유이기도 합니다.

실제로 재실행하는 쪽은 넷인데, 튼튼한 것은 하나입니다.어차피 상태가 필요한 쪽(인덱서·익스플로러·거래소)은 할인이 아무리 커도 재실행합니다 — 증명 검증은 한 비트를 주는데 이들의 제품은 상태 자체니까요. ② 증명 시스템을 못 믿는 쪽은 무사고 연차가 쌓일수록 줄어들어서, 얇아지는 시점이 초기가 아니라 후기입니다. ③ 안 올린 노드는 실재하지만 설계에 넣을 수 없습니다. ④ 돈 받는 감시자는 현재 프로토콜에 없습니다.

문제는 가장 튼튼한 집단이 블록을 거부할 수 없다는 것입니다. 합의에 영향을 주려면 지분이 필요하고, 지분이야말로 할인을 취할 유인이 가장 날카롭습니다. 재실행을 계속할 이유가 가장 튼튼한 집단에는 거부권이 없고, 거부권을 가진 집단에는 그만둘 이유가 가장 큽니다. 시간이 한 겹 더 얹힙니다 — 인덱서가 두 시간 뒤 불일치를 발견하는 것은 파이널리티 이후의 발견이고, 그 지점에서 되돌리기는 기술 문제가 아니라 정치 문제입니다. 발견은 거부보다 훨씬 약한 보장이므로, 재는 숫자도 노드 개수가 아니라 지분이어야 합니다.

증명 다양성이 가장 유력한 해법인 이유. 서로 다른 zkVM은 같은 문장을 증명합니다. 내부는 완전히 다른데 주장은 동일한 공개 입력에 묶여 있어서, 출력을 서로 조율할 필요가 없습니다 — 답은 이미 newStateRoot 하나로 고정돼 있고 각 증명은 그 값에 독립적으로 서명하는 셈입니다. zkVM A의 MULMOD 회로에 버그가 있으면 A는 틀린 루트에 대해서도 통과하는 증명을 만들 수 있습니다. 그런데 B가 거기에 동의하려면 거짓 명제를 증명해야 하고, 건전한 시스템은 그걸 못 합니다. 그래서 불일치가 기계적으로 드러납니다. 합의 규칙으로 쓰면 대략:

required = {A, B, C}
valid = count(S in required where Verify_S(oldRoot, blockCommit, newRoot, proof_S))
블록 유효  ⟺  valid ≥ N

루프 내내 newRoot가 같은 변수라는 점이 중요합니다 — 일치를 따로 판정할 필요 없이 구조적으로 강제됩니다. 비용은 여전히 수 밀리초입니다.

다양성이 새는 곳 셋, 그리고 셋째가 진짜입니다.표면만 다양할 수 있습니다 — 클라이언트 다양성이 작동한 이유는 명세를 보고 독립적으로 구현했기 때문인데, zkVM들은 증명 시스템 계열·해시와 곡선 구현·기반 라이브러리를 자주 공유합니다. 다양성 층 아래의 버그 하나는 셋이 같은 틀린 답을 내게 만듭니다. ② N개를 요구하면 증명 비용이 곱해지고 가장 느린 증명자가 속도를 정하며, 한 시스템의 장애가 곧 라이브니스 실패가 됩니다. ③ 그리고 가장 중요한 것 — 같은 할인 동학이 한 층 아래에서 그대로 재현됩니다. 한 zkVM이 뚜렷하게 싸면 증명자들이 그리로 몰리고 단일 문화가 돌아옵니다. 이더리움의 클라이언트 다양성 문제가 바로 그 살아 있는 증거입니다 — 규범은 규칙이 아닙니다. 그래서 다양성이 작동하려면 프로토콜이 요구 시스템을 합의에 명시해야 하는데, 이는 구현 이름을 프로토콜 밖에 두어 온 이더리움 관행에서 실질적으로 벗어나는 일이고, 동시에 검증자 구현 여러 개를 합의 임계 코드로 만들어 증명 계층의 공격 표면을 검증 계층으로 옮기는 결과가 됩니다.

그리고 집계의 아이러니. 블록마다 증명 셋을 싣는 건 무거우니 실무적 구성은 재귀 집계입니다 — 회로 하나가 "A·B·C가 모두 검증됐다" 를 증명해 작은 증명 하나로 압축합니다. 우아하고 거의 확실히 그리로 갈 텐데, 그 집계 회로가 다시 공유 코드입니다. 다양성의 효율적 구현이 집계 계층에서 단일 문화를 재도입합니다.

다양성으로도 못 잡는 것, 그리고 그 결과의 설계. 다양성은 한 증명자의 구현 버그를 막습니다. 모든 증명자가 함께 틀리는 경우 — 공유 의존성 때문이든 명세가 모호해서든 — 는 못 막습니다. 모두가 같은 명세에 대한 같은 문장을 증명하니까요. 실제로 돌려본다는 근거를 갖는 것은 재실행뿐입니다. 둘은 대체재가 아니라 보완재입니다:

증명자 하나가 틀림 전부 함께 틀림(공유 의존성·명세)
증명 다양성 잡음 못 잡음
강제 표본 재실행 잡음 잡음

매 슬롯 무작위 소수 검증자에게만 재실행 의무를 지우면 — 증명 위원회가 이미 쓰는 기계입니다 — 비용은 거의 안 늘면서 "아무도 안 돌리는 상태"가 구조적으로 불가능해집니다.

이 카드에 추가되는 측정. 창(window)과 할인율에 더해 셋째 숫자: 후보 zkVM들 사이의 공유 의존성 그래프. 다양성의 값어치는 그 아래 독립성의 값어치를 넘지 못하고, 그 겹침은 공개된 의존성 목록으로 오늘 당장 계산할 수 있습니다. 그리고 아무도 발표하지 않습니다.

← 전체 개발 노트 · 워크스페이스 인덱스 · 맨 위 ↑