Repository navigation
Upgrade EthProofs to Ziren 2.0 and integrate the Fleet app worker - #23
Merged
Merged
Conversation
chore: upgrade ziren to v1.2.3
fix: goat system tx err
The Ziren crates are git dependencies on Ziren's default branch; the lockfiles pinned it at c736a41c (host) and 7c2071ea (guest), both 1.2.5. Move both to the current main (2.0.0), which the provers now run. The precompile forks stay at the locked commits that declare Ziren without a tag, so each lockfile holds one Ziren source.
felicityin
approved these changes
Oct 15, 2026
…syscalls) (#26) * Prepare consecutive EthProofs blocks in parallel * guest: the optimised guest line in the Ziren 2.0 EthProofs worker The Fleet worker (4849354, chore/ziren-v2-stateless + fix/ethproofs-consecutive) forked from the guest optimisation line at 9215aa6 and shipped the older guest: no in-guest JUMPDEST table (the host's revm JumpTable was trusted under a code hash that covers only the code bytes), no zkVM syscalls for 256-bit arithmetic and the curves, no arena tries. This squashes perf/guest-hashed-key-memo (7147f4e: feat/guest-syscalls 4a15fee plus the trie-key memo and the checked logs bloom). Resolution: - bin/eth-proofs, the root Cargo.toml and Cargo.lock: the worker's. The worker keeps the git-locked Ziren 2.0 graph; the opt line's sibling-checkout [patch] section is dropped. - Guest, mpt and the witness RPC db: the opt line's. The worker's 2c0245a (preserve untouched storage roots, remove empty accounts) was already in ArenaState::update; its 41317cd (omitted storage of an absent account or an authenticated empty storage root reads zero, any other missing storage trie is an error) is now ArenaState::storage, with its three tests. a75cb33 (verified bytecode recovery) is the opt line's complete_account_code; the duplicated structured-header decoder is kept once. - bin/guest keeps the opt line's graph (precompile forks); its zkm-zkvm/zkm-lib [patch] points at the sibling Ziren checkout, whose guest-side crates (crates/zkvm, crates/build) are identical to 0dd65a15 and 31f6e8eb. Validation: - cargo test -p mpt: 24 passed (the arena storage rule and the update rule). - host (this tree) fetched and executed 26184581-26184583 natively: 278.70M, 269.57M, 52.72M cycles, block hashes as the chain's. - GPU, one card through Fleet (image e786dd = Ziren 31f6e8eb), guest 941629f6: 53.73/53.40/18.01 s, every proof verified against a 31f6e8eb client, public values identical to the deployed guest's (334b45b8: 73.97/73.64/20.61 s on the same blocks, -24.5% overall). * perf(guest): bind the chain to mainnet, gate the precompile tracker The proof commits only the block hash, so the chain spec and the beneficiary override in the input came from the prover unchecked. The guest now accepts mainnet inputs only, with no custom beneficiary. The cycle-tracker wrapper around every precompile call turned the precompile set into a map probed on each call. It is now behind the precompile-tracking feature, for profiling builds. Measured on the executor (blocks 26184948 / 26184949, same committed hashes): cycles -0.19% / -0.28%, main-trace area -0.11% / -0.16%. * perf(guest): walk the JUMPDEST map in assembly on the zkVM The guest derives every executed code's jump table itself, a walk over ~3 M opcodes per mainnet block. Compiled, the walk is nine instructions per opcode, two of them nops in branch delay slots. jumpdest.s fills the slots (the cursor advance, and the next opcode's load, which reads at most 32 bytes into the code's zero padding): six per opcode. Off the zkVM the Rust walk stays. Checked in the executor against the Rust walk on every code of two mainnet blocks and 2,000 random codes. Measured (blocks 26184948 / 26184949, same committed hashes): cycles -1.39% / -1.79%, main-trace area -0.80% / -1.00%. * perf(guest): revm fork with cheaper dispatch and jumps Moves the guest to the fork's patch-31.0.2-mips32-dispatch branch, which adds to the 32-bit fast paths: static gas charged on the low word of the remaining gas, JUMPDEST folded into the taken jump that lands on it, and PUSH2 + JUMP / JUMPI run as one instruction. Measured on the executor (blocks 26184948 / 26184949, same committed hashes): cycles -3.20% / -3.44%, main-trace area -2.06% / -2.16%. * deps: Ziren from perf/shamir-msm Every Ziren dependency now names the perf/shamir-msm branch (Ziren #562: Shamir's trick in the zkVM lib's two-point MSM, which ECDSA recovery runs per transaction), and the guest's comment says the Ziren checkout next to this repo, which its zkvm crates come from, is to be on that branch. The precompile patches still declare Ziren unbranched, and cargo cannot redirect a git source to another branch of it, so the lockfile also keeps their main-branch zkm-lib, zkm-primitives and zkm-zkvm. Those edges exist only for the zkVM target, where the guest's path patch replaces both with the one checkout. Back to main when #562 lands. Measured on the executor (blocks 26184948 / 26184949, same committed hashes): main-trace area -1.83% / -1.71%, cycles -1.05% / -1.00%. * deps: Ziren from perf/glv-msm, revm compare + PUSH2 + JUMPI fusion Ziren moves to perf/glv-msm (Ziren #563, stacked on #562): the zkVM lib's secp256k1 two-point MSM uses the GLV endomorphism, about half the doublings and two thirds of the additions per signature recovery, each a precompile call. The guest's revm fork moves to 2a9844a0 on patch-31.0.2-mips32-dispatch (ziren-patches/revm#4): ISZERO / EQ / LT / GT + PUSH2 + JUMPI run as one instruction, and the stack pushes in place. The lock also picks up the bn patch's newer branch tip, whose only change is its zkm-lib dependency losing a pinned tag; the guest path-patches zkm-lib, so its code is unchanged. Measured on the executor (blocks 26184948 / 26184949, same committed hashes) against the previous commit: cycles +0.46% / +0.34%, main-trace cells -0.23% / -0.26%. On one GPU, with every proof verified, proving time is -1.4% / -5.6% (GLV alone -2.5% / -5.0%): a secp256k1 precompile call costs about 30 us there, far more than its cells suggest. * deps: Ziren from perf/shamir-msm (Ziren #562) The Ziren optimizations are one pull request now, #562 on perf/shamir-msm, so every Ziren dependency names that branch. The lock stays at 8a9ab4fe, the GLV commit this guest was built and measured with: the branch goes on to change the keccak AIR, which the client must not pick up before the GPU prover does. The guest ELF is unchanged (766ff6ce).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrade the EthProofs host and guest to the matching Ziren 2.0 graph and let Fleet run the complete EthProofs pipeline beside a dedicated local GPU server. This branch is based on
stateless; GOAT changes remain in Fleet's separate compatibility path.0dd65a15, accept structured or RLP-encoded witness headers, preserve untouched storage roots and remove empty accounts. Missing non-empty authenticated storage remains an error. When the execution witness omits bytecode, fetch it at the parent block, verify its hash against the authenticated account, cache it and export it into the guest input.Validation: 11 worker tests passed, including persistence/recovery, bounded concurrency, out-of-order readiness, same-head retry and duplicate verification. Earlier correctness checks passed 15 trie, three guest storage and two RPC format tests. Release packaging and real local GPU proofs passed with the immutable image resolved from
ghcr.io/projectzkm/ziren-gpu:lateston 2026-10-11.Fleet pins source
85a0c17. The validated guest has SHA-256334b45b88d6c60e3354e983a5b26ef39b18feee65da828f277a93e646c78c73b, built fromfd9589c; subsequent worker-only changes retain that guest identity. The matching GPU image digest issha256:d4b8ef78d59935d024c034f11f28c26718a1890181f42be2954f31b74e252655.Production now proves every successive block from its saved cursor with
--block-interval 1 --prepare-concurrency 1 --prefetch-depth 1, without--latest-blockor nonzero lag skipping. After draining 26,166,879, it published 81 consecutive blocks from 26,166,880 through 26,166,960 on four GPUs and 48 CPUs. Their checksums passed, a downloaded production proof matched local bytes, and the outbox was empty. Historical gaps made under the earlier latest-head policy are not backfilled by this change. The legacy EthProofs client and endpoint are stopped; GOAT is unchanged.The initial worker is machine-pinned and does not automatically transfer its state or rewind already-published proofs after deep reorgs. Missing bytecode is recovered with hash verification; other incomplete witness data is retried for the same block and still requires diagnosis if persistent.
Bytecode regression validation: all four RPC DB tests pass, including parent-block lookup, cache/export and rejection of mismatched code. Captured block 26,167,642 now passes host execution, state-root validation and native guest verification with 349 code entries (the original witness supplied 348). The release worker builds with the existing guest ELF and GPU image.
Enable reqwest gzip response decoding in the host RPC provider to reduce execution-witness transfer size. Plain JSON responses remain supported. The locked release worker builds on
ant-5090-2; the actual provider advertises gzip and passes gzip/plain-response transport checks and a live witness decode. The binary embeds the unchanged registered guest ELF byte for byte.