Repository navigation
Zilkworm v0.1.0-alpha.4
Pre-releasev0.1.0-alpha.4 - ERE stateless input, stateless new-payload checks and Sepolia
Highlights
This release lets Zilkworm consume the canonical EEST stateless input (tests-zkevm v21.0.1) used by the ERE zkEVM benchmark, so the same guest validates Sepolia blocks inside zkevm-benchmark-workload. The guest now applies the new-payload and witness checks a stateless validator owes the claimed block, and rejects blocks whose execution needs data the witness omits. Releases publish the guest verification key and end with an ERE benchmark run against the published guest.
ERE stateless input (statelessInputBytes -> MFBD)
The host adapter prover/stateless_validator decodes EEST statelessInputBytes and translates it into the MFBD envelope consumed by the guest:
- Decoding via ere-guests
stateless-validator-commonv0.18.0, tracking the tests-zkevm v21.0.1 schema - Witness preimage keys derived from the Block-Level Access Lists (EIP-7928) for post-Amsterdam blocks
- EIP-8282 builder deposit and exit requests folded into
requests_hash - Network selected by chain id:
sepolia(11155111, Amsterdam at 1791294816),glamsterdam-devnet-7,glamsterdam-devnet-8, and chain id 1 for the generated EEST benchmark corpus (Amsterdam from genesis) - Claimed block hash and versioned hashes carried per block as an MFBD engine record (
kBlockFlagEngineRecord) - Expected public values (gas used, pre/post-state root, block hash, chain id) derived on the host for comparison with the guest commitment; a block expected to be invalid commits zeros and the chain id
Rust toolchain bumped to 1.95.0.
Stateless validation
- Engine checks per execution-specs
execute_new_payload_request: claimed block hash and blob versioned hashes (EIP-4844) against the block - Witness headers must each decode as exactly one header, link by parent hash and end at the parent block; host-provided BLOCKHASH entries are checked against them
- Code or block hashes missing from the witness mark the block invalid instead of aborting the guest
- Accounts created and destroyed within the block are proven absent from the parent state trie
- A block rejected at the state-root check no longer leaks its pre-state root into the public values
Validated under SP1 on tests-zkevm v21.0.1: 33,635 / 33,637 output_matched; the 2 failures are BAL fixtures also expected to fail for Reth.
ERE benchmark integration
make ere-binbuilds the guest ELF and derives its SP1 VK (32-byte digest) in the layout expected byere-hosts;ere-bin-linklinks it under the SP1 SDK version of the ere the workload resolvesmake ere-validateruns the guest throughere-hosts --action executeand gates onoutput_matchedmake ere-compareruns--action estimate-costfor Zilkworm and Reth and compares SP1 estimated prover cost (opcode,syscall,systemcomponents)tools/ere-fetch-fixtures.shdownloads and sha256-verifies R2 catalog batches (first,all,latest N), Sepolia by defaulttools/ere_compare.pyandtools/compare_ere_benchmarks.pyread the ere >= v0.17 metrics schema and report legacy cycles and estimated cost separatelytools/scripts/eest_runner.pyreports SP1 cycle and prover-gas distributions- See
docs/ere_integration.mdfor the details about environment and workflow
Validated on the latest Sepolia batch (blocks 11899400..11899499): 100 / 100 output_matched. Estimated prover cost on blocks 11871300..11871399 is 0.500x Reth 0.1.0-rc.4's (Zilkworm cheaper on 98 / 100).
Prover
- SP1 v6.6.0, up from v6.0.2; the prover builds on
erigontech/sp1erigon/patches-v6.6.0(v6.6.0 plusprove_with_cycles) with thecudafeature - C++ witness converter embedded via FFI instead of spawning a binary
- SP1 guest built with wider GCC inlining and loop unrolling (-2.30% cycles); byte swaps expanded inline on rv64im
Performance and Fixes
- Keccak calls memoized;
zeroless_viewuses an aligned u64 stride and branchless compare - Calldata bytes counted once per transaction; no per-transaction copies of calldata and RLP envelopes
- GridMPT copies and patches the branch RLP on fold instead of re-encoding
MphfCollisionEntry::offsetwidened to u64USE_HASH_KEYnode-store account recovery restored (default off)- evmone built without its built-in tracers
- MFBD design and specification document (
docs/mfbd_design_specs.md)
CI
- New
ERE Benchmarkworkflow: builds the guest at the run's ref or downloads a published release guest (sha256-checked againstSHA256SUMS.txt), fetches the latest N R2 batches (default: Sepolia, 1 batch, matching upstreameest-r2-stateless-inputs), and validates; optional cost comparison against Reth - Runs on push to
release/*branches, onworkflow_dispatch, and from the release workflow - Release workflow builds and publishes the guest VK and finishes with an ERE benchmark of the published guest, cost comparison enabled
- EEST jobs reuse the build directory, extract only
blockchain_testsand cache fixtures; unit tests run in thezilkworm-ciimage
ZVM1/EVMone changes
ZVM1 (now corresponds to evmone v0.24.0 plus the Amsterdam picks, up from v0.23.0)
- Code written earlier in the same transaction is served from the transaction's code writes when the witness omits it
- EIP-7702: the delegate's code is read during call target resolution, before a value-transfer failure, as in execution-specs
Transaction::datais a non-owningbytes_view- Keccak calls the zkVM permutation directly and absorbs input with aligned 64-bit loads
- Faster jumpdest analysis on RISC-V
- EVMC hash types word-aligned and passed to the C++ host by reference
- safegcd for 256-bit modular inversion
- Built-in tracers optional (
EVMONE_TRACING) - Upstream fixes: account nonexistence restored when a cold access is reverted, widened blob fee in the affordability check, state-independent CALL costs charged first
- Please check the upstream evmone changelog for the full list of changes
Contributors
| Author | Commits |
|---|---|
| Somnath Banerjee @somnergy | 11 |
| Paweł Bylica @chfast | 3 |
| @canepat | 2 |
Commit Log by Category (16 non-merge commits since v0.1.0-alpha.3)
Witness Format, State & Pre-Trie Validation
7191202mphf: widen MphfCollisionEntry::offset to u64 (#176) (Somnath Banerjee @somnergy)e4bdce4state_zz: re-add USE_HASH_KEY node-store account recovery (default off) (#130) (Somnath Banerjee @somnergy)66f8500Add MFBD design and specifications document (#174) (Somnath Banerjee @somnergy)
Merkle Patricia Trie
e89f3bcgrid_mpt: copy-and-patch the branch RLP on fold instead of re-encoding (#169) (@canepat)
Protocol & Core EVM
af9274bprotocol: count calldata bytes once per tx (#179) (Somnath Banerjee @somnergy)26dc926types/trie: avoid per-tx copies of calldata and RLP envelopes (#178) (Somnath Banerjee @somnergy)3a88e8ccore: memoize keccak calls (#139) (Somnath Banerjee @somnergy)da094a9common: use aligned u64 stride and branchless compare forzeroless_view(#121) (Somnath Banerjee @somnergy)416d457Build evmone without its built-in tracers (#168) (Paweł Bylica @chfast)bf1d76bevmone: point the submodule at the zvm1 oss branch (Somnath Banerjee @somnergy)
Prover & Guest
14e1df3Add ERE stateless-input path and release ERE benchmark (#15) (@canepat)7d73e94prover: embed C++ witness converter via FFI instead of spawning a binary (#137) (Somnath Banerjee @somnergy)52dafacguest: Widen GCC inlining and unroll loops on the SP1 guest (-2.30% cycles) (#164) (Paweł Bylica @chfast)a4a46deguest: Expand byte swaps inline on rv64im (#157) (Paweł Bylica @chfast)
CI/CD & Workflows
0066de2ci: use zilkworm-ci image in unit tests workflow (#33) (Somnath Banerjee @somnergy)dcea126ci: reuse build dir, extract only blockchain_tests, cache fixtures (#135) (Somnath Banerjee @somnergy)
Released by @canepat