Conversation
* fix: enhance fallback mechanism for incomplete witness data * fix: include bytecode retrieval in RPC fallback logic * chore: clean up redundant lines in fallback address proof logic * update Cargo.lock
…builds the host zkm-build v1.2.7 runs the guest's cargo with the environment of the host's build script, into which cargo exports the host compiler as RUSTC and rustup exports the workspace toolchain (rust-toolchain.toml, nightly). That toolchain has no mipsel-zkm-zkvm-elf target, so a plain cargo build failed with "could not find specification for target" unless the whole build was run with cargo +zkm. The two build scripts now select the zkm toolchain for the nested build, overridable through ZKM_GUEST_TOOLCHAIN, and drop the inherited RUSTC and RUSTC_WRAPPER, the way the current zkm-build does itself. The README states the requirement.
The header listed accrue_logs_bloom_cycles_count, but the guest no longer profiles that stage (the logs bloom comes precomputed in the client input) and write_record never pushed a value for it, so the header had 79 fields and every record 78. The csv writer rejects that whenever the report file is created fresh, and the host exited with a CSV error right after a successful execution. The column goes; the only reader of the report, the cycle-count diff test, never used it.
Both sides moved to Ziren v1.2.7 and touched the lock files; the locks are rebuilt from the merged manifests, with main's tagged precompile forks.
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.
What this branch is
The GOAT stateless block verifier on top of
main: GOAT osaka hardfork, slot-level state-transition verification (ClientExecutor::execute(input, storage_info); the shipped guest passes an empty list, so the check is a library hook), the GOATdebug_executionWitnesssource (JSON headers), handling of witnesses that lack a storage trie or carry precompile addresses, and an RPC fallback for incomplete witnesses. The GOAT execution rules themselves (zero-gas system transactions, fee split to the foundation and locking contracts, requests derived from logs) live in theziren-patches/rethfork, branchpatch-1.9.3. On testnet 48816 the post-execution validation skips the receipts-root/bloom check (receipt encoding differs between the testnet geth and mainnet geth).Verified against GOAT testnet3
Chain id 48816 (
rpc-legacy.testnet3.goat.network, GOAT geth v0.1.12,debug_executionWitnessserved). Stateless execution of five recent blocks — three empty ones, one with a user transaction (40,213 gas, secp256k1 recovery), one with a zero-gas GOAT system transaction — all executed and verified against the header state root.Fixes in the last two commits
cargo build --release --bin host --features execution-witnessfailed withcould not find specification for target "mipsel-zkm-zkvm-elf": rustup exports the workspace toolchain (nightly, fromrust-toolchain.toml) and cargo exports the hostrustcpath asRUSTCinto build scripts, and zkm-build v1.2.7 sets neither for the nested guest build.bin/host/build.rsandbin/eth-proofs/build.rsnow select the guest toolchain (ZKM_GUEST_TOOLCHAIN, defaultzkm) and dropRUSTC/RUSTC_WRAPPERbefore calling zkm-build (RUSTC_WORKSPACE_WRAPPERstays: zkm-build uses it to skip the guest under clippy). README gained the one-line requirement. The Ziren pin is unchanged.accrue_logs_bloom_cycles_countcolumn the CSV record never carried. The first run into a freshreport.csvfailed after a successful execution withCSV error: found record with 78 fields, but the previous record has 79 fields(persist_report_hook.rs):write_headeremitted a columnwrite_recordnever pushed (the guest has no such profile label; the bloom is precomputed in the client input, and the only reader does not use the column). Header and record are both 78 fields now.Checked: clean-target build with no
RUSTUP_TOOLCHAINin the environment produces the MIPS guest; the CSV failure reproduced on the previous binary and is gone (fresh file plus appends, three GOAT blocks, exit 0);cargo fmt --checkand clippy clean on the touched files. Thehost-executorintegration tests needRPC_1/RPC_10/RPC_59144/RPC_11155111archive endpoints and are unchanged.Performance (GOAT testnet3, execution only, 914fbfc)
Of the last 3,000 testnet3 blocks (17238616-17241615), 2,749 are empty, 251 carry transactions (at most 2), 51 of those only zero-gas system transactions; the busiest block in the window used 271,265 gas. The busiest six plus two median blocks, executed stateless in the Ziren executor (instructions = the proving-relevant count; "tracked" = the host's cycle-tracker total; shares are of tracked cycles):
An empty block costs 3,851,300 instructions; a block with one zero-gas system transaction 4,333,336. Witnesses are 16-42 KB (44-99 trie nodes); the only precompile seen is sha256; sender recovery is ~47k cycles per transaction over the secp256k1 syscalls. The block-execution phase alone is 4-6 cycles per gas on the busiest blocks, in line with mainnet (~7.5 cycles/gas end to end on 30 M-gas blocks); the per-block figure of 22-112 instructions per gas is fixed cost, the blocks being 100-700x smaller than mainnet's.
The dominant fixed cost is ~3.1 M instructions per block (51-70% of every block, 81% of an empty one) outside every cycle-tracker span:
verify_blockbuilds the chain spec frominput.genesis, and forGenesis::GoatTestnetthat isserde_json::from_str::<alloy_genesis::Genesis>over the embedded 162 KB genesis JSON (15 contract accounts, 75 KB of code hex, 63 storage slots) on every block; mainnet uses the built-inChainSpecand never pays it. A pre-decoded GOAT chain spec (parsed at build time, or a built-in spec) would roughly halve the busiest blocks and cut empty ones five-fold. Second tier: witness-db initialisation and state-root computation (keccak-bound, ~40% of tracked cycles together) and input deserialisation (~13%).Proving on the current GPU prover (branch
feat/goat-ziren-main, this branch moved to Zirenmain)The GOAT guest on Ziren
main(af27773) executes the same blocks with 15-18% fewer cycles (17241345: 6,089,011 → 4,976,938; empty block 3,851,300 → 3,266,069) and proves on the production GPU prover, shadow instance, warm second run, compressed proof 280,657 bytes:A GOAT block is one or two core shards, so the time is the fixed pipeline floor (shard, leaf, compose, root with the compress-schedule grinds); two cards take the root's grinds in parallel, a third and fourth card add nothing at this size.