Skip to content

chore(l1,l2): bump ZisK to v1.1.0-alpha - #7156

Merged
ilitteri merged 6 commits into
mainfrom
chore/bump-zisk-v1.1.0-alpha
Aug 18, 2026
Merged

chore(l1,l2): bump ZisK to v1.1.0-alpha#7156
ilitteri merged 6 commits into
mainfrom
chore/bump-zisk-v1.1.0-alpha

Conversation

@ilitteri

@ilitteri ilitteri commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Motivation

ZisK v1.1.0-alpha is out. It carries soundness fixes (MemAlign on non-aligned memory operations, narrow unsigned loads leaving high bytes unconstrained, signed-division zero results in the Arith state machine, BLAKE2b message permutation, DMA transpilation under dynamic jumps), a reworked BLAKE2b arithmetization (24 → 8 rows per round), more efficient Main/Binary arithmetization, and a .sbss-aware linker script. Upstream's own upgrade note is explicit that ELFs must be rebuilt against it.

Description

Bumps the ziskos tag in crates/guest-program/Cargo.toml and crates/guest-program/bin/zisk/Cargo.toml, raises ZISK_VERSION in .github/actions/install-zisk, and refreshes the workspace and ZisK-guest lockfiles. The lock churn is larger than a version string because pil2-proofman moved to crates.io and several ZisK crates gained a zisk- prefix (zkvm-interfacezisk-zkvm-interface, lib-czisk-lib-c, precompiles-helperszisk-precomp-helpers, circuitzisk-circuit).

The one non-mechanical part is ZISK_RUST_TOOLCHAIN, re-pinned from zisk-0.5.1 to zisk-3.0.0. That pin exists because ziskup installs whatever toolchain release is newest, and the two versions have to agree on who supplies the guest linker script. v1.1.0-alpha reverses the direction of that dependency: zisk-build now injects its own script (-C link-arg=-T<zisk_linker_script.ld>), so the toolchain must be one that embeds none. On the old pin the link takes both and fails:

rust-lld: error: rustc-riscv64-linkfile.ld:6: region 'rom' already defined
>>>   rom   (xa) : ORIGIN = 0x80000000, LENGTH = 0x10000000

No source changes were needed:

  • zkvm-interface/zkvm_accelerators.h is byte-identical between the two tags, so the hand-written extern "C" bindings in the ZisK crypto provider still match.
  • The cargo-zisk build / execute / prove / verify flags the prover backend drives are unchanged, and ziskos::entrypoint! stayed compatible with a plain fn().
  • zkvm_bls12_g1_msm / zkvm_bls12_g2_msm / zkvm_bls12_pairing now return ZKVM_EFAIL on a zero-length pair list. Unreachable from here — all three levm precompiles reject empty calldata before building the pair vector.

Two things worth flagging for reviewers:

  • The guest ELF changes shape. The new linker script rewrites the RAM layout (stack now at 0xa0000000, .output_data at 0xa0410000 instead of 0xa0020000), so any pinned ZisK verification key has to be regenerated. Nothing on-chain depends on it today — ZiskBackend::prover_type() is still unimplemented!().
  • The stateless-validator guest is out of scope. It reaches ZisK through ere-platform-zisk at a pinned ere rev, which still resolves v1.0.0-alpha. feat: update zisk to v1.1.0-alpha eth-act/ere#404 bumps it upstream but landed after ere v0.15.0, so there is no release (and therefore no ere-compiler-zisk release image) carrying it yet, and moving the shared ERE_REV would also pull in unrelated sp1/openvm changes. Separate change once ere cuts a release.

Also in this PR: the zkevm_bench workspace

tooling/zkevm_bench landed on main after this branch was opened, and it carries its own ZisK coupling. Three things needed doing, none of them optional:

  • Its committed lockfile went stale the moment the ziskos tag moved, because it depends on ethrex-guest-program with the zisk feature. Its lint step runs cargo clippy --locked and then asserts the lock is unmodified, so this was a guaranteed CI failure on the first run after merging main in. That makes three lockfiles this bump has to touch.
  • make zkevm-bench-setup and the tool's README still said v1.0.0-alpha. Bumped, and the Rust toolchain the target installs is now pinned to the same release CI uses — ziskup takes whatever is newest, which for v1.0.0-alpha was already the wrong pairing, so that target could not have linked a guest as written.
  • The tool shells out to ziskemu -X and parses the AIR-cost report, and v1.1.0-alpha reworks emulator statistics. Rather than assume, I ran ziskemu -X from the new toolchain against a guest ELF built from this tree: the only structural change is an added ROM USAGE line. Every label parse_air_cost matches is still emitted unchanged and ROM is not one of them, so it is skipped like any unrecognised label. Noted in docs/ziskemu-output.md.

Deliberately left on v1.0.0-alpha: the tool's test fixtures, its sample report, and the committed fixtures/ziskemu_sample.txt. Those record a real captured run rather than a version we install, so rewriting the strings would misdescribe the capture.

How to Test

No CI job builds the ZisK guest ELF — the prover lint job only runs cargo check/clippy, which do not enable zisk-build-elf — so the toolchain pairing above was verified by hand on an x86_64 Debian 13 box provisioned exactly like install-zisk does it (ziskup v1.1.0-alpha + cargo-zisk toolchain install -t zisk-3.0.0):

# builds and links the guest ELF
cd crates/guest-program
cargo check --release -p ethrex-guest-program --features zisk-build-elf,ci

# what the PR job runs
cargo check -r -p ethrex-prover -F "zisk,ci"
cargo clippy -r -p ethrex-prover --all-targets -F "zisk,ci"

# lockfiles resolve as committed
make check-cargo-lock

All pass. readelf -lW on the produced ELF shows the v1.1.0-alpha memory map, confirming the SDK's script won rather than a stale one from the toolchain. Re-pinning the toolchain back to zisk-0.5.1 and rebuilding reproduces the region 'rom' already defined failure quoted above, so the pin change is load-bearing rather than cosmetic.

Checklist

  • Updated STORE_SCHEMA_VERSION (crates/storage/lib.rs) if the PR includes breaking changes to the Store requiring a re-sync.

… both guest

manifests, raise ZISK_VERSION in the CI install action, and refresh the two
affected lockfiles (pil2-proofman moved to crates.io and several ZisK crates were
renamed with a `zisk-` prefix, so the entries change shape as well as version).

Re-pin ZISK_RUST_TOOLCHAIN from zisk-0.5.1 to zisk-3.0.0. The two pins are coupled
through who supplies the guest linker script, and v1.1.0-alpha reverses that
relationship: `zisk-build` now injects its own script with `-C link-arg=-T`, so the
toolchain has to be one whose riscv64ima-zisk-zkvm-elf target spec embeds none. Kept
on the old pin the link takes both scripts and rust-lld fails with "region 'rom'
already defined".

No source changes are needed. `zkvm-interface/zkvm_accelerators.h` is unchanged, so
the hand-written extern "C" bindings in the ZisK crypto provider still match, and the
`cargo-zisk` build/execute/prove/verify flags the prover backend drives are unchanged
too. The BLS12-381 MSM and pairing accelerators now reject a zero-length pair list,
which the levm precompiles already reject before the call.

The guest ELF changes: the new linker script moves the whole RAM layout (stack now at
0xa0000000, output_data at 0xa0410000), so any pinned ZisK verification key has to be
regenerated.

The stateless-validator guest is not covered here. It reaches ZisK through
`ere-platform-zisk` at a pinned ere rev, which still resolves v1.0.0-alpha; moving it
needs an ere release carrying eth-act/ere#404 and would drag in unrelated sp1/openvm
changes, so it belongs in its own change.
@ilitteri
ilitteri requested a review from a team as a code owner August 18, 2026 14:02
@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

⚠️ Known Issues — intentionally skipped tests

Source: docs/known_issues.md

rpc-compat log-bearing cases excluded

Where: KNOWN_EXCLUDED_TESTS in .github/scripts/check-hive-results.sh counts out
eight hive rpc-compat cases — the four eth_getLogs cases, eth_getBlockReceipts/get-block-receipts-latest,
and three eth_getTransactionReceipt cases. They are exactly the cases whose recorded
response contains at least one log object; every case with an empty log array still runs.
Note this leaves eth_getLogs with no rpc-compat coverage at all, since all four of its
cases are in the set.

Why: ethrex populates blockTimestamp on log objects, as geth, besu, nethermind, reth
and erigon all do. hive's rpc-compat compares responses byte-exactly (jsondiff.FullMatch;
the lenient checkJSONStructure path applies only to cases upstream marks speconly), and
the corpus is pinned to execution-apis d08382ae (2025-02-10), whose recordings predate the
field — it entered the schema in execution-apis#639 and the fixtures in #846 (2026-07-22).
So the extra key cannot match, and this is a property of the pin rather than of the response.

The pin cannot move, and this is not temporary. The pin sits one commit before
execution-apis#627, which moved the test chain to a pre-merge genesis: the current corpus has
~36 proof-of-work blocks before its terminal total difficulty. ethrex does not support
pre-merge chains and will not, so importing that chain.rlp fails at block 1 —
validate_block_header has no pre-London base-fee path. Every revision carrying
blockTimestamp in its fixtures also carries that chain, so there is no revision that
satisfies both. Nor can the corpus be patched locally: rpc-compat's Dockerfile clones
ethereum/execution-apis by hard-coded URL, so the branch buildarg cannot point at a fork.

Coverage: the field itself is pinned by
block_timestamp_is_on_the_log_and_not_on_the_receipt in
crates/networking/rpc/types/receipt.rs, which asserts it is present on each log and absent
from the receipt level.

Removal: delete the entries if ethrex ever gains pre-merge chain import, or if upstream
marks these cases speconly so they are type-checked instead of compared byte-for-byte.


The stateless schema id does not identify the encoding

Where: STATELESS_INPUT_SCHEMA_ID in crates/common/types/stateless_ssz.rs.

Upstream keeps the stateless input schema id at 0x1501
(fork_index 0x15 << 8 | revision 0x01) across incompatible body changes. Three
encodings have now shipped under it: tests-zkevm@v0.6.2, then #3248 + #3278,
then #3356, which moved state, codes and public_keys from SszList to
ProgressiveList. ethrex speaks the last one.

The consequence is that the 2-byte prefix cannot be used to detect a stale or
mismatched bundle. A wrong-dialect input is accepted by the id check and then
fails later — in SSZ decode, or on a root that does not match — rather than being
rejected up front for what it is. only_amsterdam_schema_id_decodes therefore
proves less than its name suggests.

Worth raising upstream: a revision field that does not move across a body change
provides no version negotiation at all.


ZisK guest program hash changes with the unsync_cell gate

Where: crates/common/types/block.rs, transaction.rs.

The gate on the single-threaded unsync_cell::OnceCell moved from
all(feature = "eip-8025", target_arch = "riscv64") to
all(feature = "zisk", target_arch = "riscv64") when the eip-8025 feature was removed.

The guest ELFs were previously built --features "<zkvm>-build-elf,ci", which never enabled
eip-8025, so they compiled the atomic once_cell variant. bin/zisk/Cargo.toml does enable
ethrex-common/zisk, so the ZisK guest now compiles the unsafe impl Sync cell instead.
That changes the ELF bytes and therefore the program hash and verification key.

This is intended (the guest is single-threaded, so the unsync cell is sound and cheaper), but it
is a VK change rather than a no-op refactor, and the diffstat presents it as a file rename
(eip8025_cell.rsunsync_cell.rs). Anyone pinning a ZisK VK across this change must
re-register it. The stateless-validator crate now forwards ethrex-common/zisk from its own
zisk feature so the two ZisK guests do not disagree on the cell type.


Release signing key is an unprotected repository secret

Where: .github/workflows/tag_release.yaml.

MINISIGN_SECRET_KEY is a plain repository secret. There is no environment: on
finalize-release or dry-run-release-assets, and gh api repos/lambdaclass/ethrex/rulesets
shows only branch-targeted rulesets, so the github.ref_type == 'tag' condition is a workflow
check rather than an enforced boundary: anyone who can push a tag can reach the signing key.

This is a repository-settings change, not a code change, so it is recorded here rather than
fixed in the tree. Recommended:

  1. Move MINISIGN_SECRET_KEY / MINISIGN_PASSWORD into a GitHub Environment with required
    reviewers, and add environment: to the two jobs that sign.
  2. Add a ruleset targeting refs/tags/v* restricting who may create release tags.

Until then, the compromise of that key is silent and durable: signatures would still verify
against the committed .github/minisign.pub.

@github-actions github-actions Bot added L1 Ethereum client L2 Rollup client labels Aug 18, 2026
@github-actions

Copy link
Copy Markdown

🤖 Kimi Code Review

Overall, this is a well-structured dependency upgrade PR for the Zisk zkVM integration. The changes are consistent across workspace and guest binary configurations, and the documentation accurately explains the toolchain/SDK version coupling.

Critical Build Configuration.github/actions/install-zisk/action.yml

The updated comment (lines 16-28) correctly documents the inverted dependency relationship between SDK and toolchain regarding linker scripts. This is a critical detail:

  • v1.1.0-alpha SDK: Supplies its own linker script via zisk-build
  • zisk-3.0.0 toolchain: Must not embed a linker script (removed in v1.0.0+)

If these versions drift, linking will fail with "region 'rom' already defined" errors. The comment explicitly warns about this, which is excellent defensive documentation.

Dependency Source Migration

The migration of proofman-* crates from Git to crates.io (registry) in Cargo.lock (lines 10118-10143) improves supply chain security. Published crate versions are immutable, whereas Git tags can be force-pushed. Consider ensuring the zisk-* crates also migrate to registry releases when available.

Version Consistency

All version pins are consistent:

  1. ZISK_VERSION: "1.1.0-alpha" in action.yml (line 29)
  2. tag = "v1.1.0-alpha" in crates/guest-program/Cargo.toml (line 44)
  3. tag = "v1.1.0-alpha" in crates/guest-program/bin/zisk/Cargo.toml (line 17)

Minor Suggestion

In crates/guest-program/bin/zisk/Cargo.toml, consider explicitly disabling default features for ziskos to match the workspace configuration:

ziskos = { git = "https://github.com/0xPolygonHermez/zisk.git", tag = "v1.1.0-alpha", default-features = false }

This ensures the guest binary doesn't accidentally enable host-side features that could break the zkVM guest environment.

Security Note

Both versions are alpha releases. Ensure the 9a5a1ac594b9b6e527fc6f54ff4313f75c4acf93 commit referenced in the lockfile has been reviewed for critical zkVM soundness issues, as this code handles proof generation/verification.

The PR is ready to merge after considering the default-features suggestion.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

No hardcoded memory-map assumptions in the ethrex-side code that the new ELF layout would break.

Review: chore(l1,l2): bump ZisK to v1.1.0-alpha (lambdaclass/ethrex#7156)

This is a mechanical dependency-version bump with no application logic changes — the diff is limited to ziskos git tags, the ZISK_VERSION/ZISK_RUST_TOOLCHAIN pins in the install action, lockfile churn from upstream's crate renames/registry move, and a README version string.

Overall assessment: looks good. The PR description does the hard part correctly — it identifies the load-bearing change (the toolchain re-pin) and explains why it's load-bearing (who supplies the guest linker script flips direction between the old and new SDK), which is exactly the kind of change that's easy to get subtly wrong in a "just bump the version" PR.

Things checked and confirmed sound

  1. Toolchain/SDK linker-script pairing (.github/actions/install-zisk/action.yml:16-32). The comment explains the dependency correctly and the reasoning is falsifiable — the PR description states the failure mode was reproduced by reverting the pin. Good practice for a change like this, since CI doesn't actually build the guest ELF (per the "How to Test" section) and a broken pin would silently ship.
  2. No stale version references left behind. I grepped for v1.0.0-alpha/zisk-0.5.1 across the repo — the remaining hits (crates/prover/src/backend/zisk.rs:22, crates/guest-program/src/crypto/zisk.rs:4, docs/eip-8025.md:182) are either "and later"-style compatibility notes that don't need updating, or the intentionally-out-of-scope stateless-validator pin, which the PR body explains is tracked separately behind an upstream ere release.
  3. Lockfile renames are consistent. Both Cargo.lock and crates/guest-program/bin/zisk/Cargo.lock reflect the same rename set (zkvm-interfacezisk-zkvm-interface, lib-czisk-lib-c, precompiles-helperszisk-precomp-helpers, circuitzisk-circuit, fields/proofman-verifier moving from the pil2-proofman git source to crates.io as proofman-fields/proofman-verifier), so the two lockfiles didn't drift apart.
  4. No hardcoded assumptions about the guest memory layout in crates/prover/src/backend/zisk.rs or the ELF-loading code — the backend treats the ELF as an opaque blob, so the RAM-layout shift the PR calls out (stack/.output_data addresses) doesn't need a corresponding source change here.
  5. ZiskBackend::prover_type() still unimplemented!(), so the "any pinned verification key must be regenerated" caveat in the description is correctly scoped — nothing on-chain currently depends on a ZisK VK.

Minor notes (non-blocking)

  • The commit reasoning about zkvm_bls12_g1_msm/g2_msm/pairing now returning ZKVM_EFAIL on empty pair lists, and it being unreachable because levm precompiles reject empty calldata first — this is asserted in the PR body but I didn't see a corresponding code comment near the precompile call sites in crates/guest-program/src/crypto/zisk.rs tying the two together. Since this is exactly the kind of implicit cross-repo invariant that silently breaks on the next bump, consider adding a one-line comment there referencing why an empty-list EFAIL is unreachable, so a future reviewer bumping ZisK again doesn't have to re-derive it.
  • Nothing else to flag — this is as clean as a dependency-bump PR gets given the amount of due diligence already documented in the PR body.

Automated review by Claude (Anthropic) · sonnet · custom prompt

@github-actions

Copy link
Copy Markdown

🤖 Codex Code Review

No findings in the PR diff.

The change is a dependency/toolchain bump only, and the in-repo version sync points are consistent: .github/actions/install-zisk/action.yml:15-32, crates/guest-program/Cargo.toml:43-44, crates/guest-program/bin/zisk/Cargo.toml:16-17, and crates/guest-program/README.md:147-150 all move together to ZisK v1.1.0-alpha / toolchain zisk-3.0.0. I don’t see any direct impact on EVM correctness, gas accounting, consensus logic, trie behavior, or RLP handling because none of that code changed.

Residual risk: I could not run a local cargo check in this environment because rustup attempted to write under a read-only /home/runner/.rustup, so I did not verify the new ZisK SDK/toolchain pair at build time here.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

@ilitteri

Copy link
Copy Markdown
Collaborator Author

Follow-up for the stateless-validator half tracked in #7157.

@github-project-automation github-project-automation Bot moved this to In Review in ethrex_l1 Aug 18, 2026
ilitteri and others added 5 commits August 18, 2026 12:44
…nch was

opened and carries its own ZisK pins.

`tooling/zkevm_bench` is a standalone workspace depending on `ethrex-guest-program`
with the `zisk` feature, so its committed lockfile went stale the moment the `ziskos`
tag moved. Its lint job runs `cargo clippy --locked` and then asserts the lock is
unmodified, so this would have failed CI on the first run after merging main in.

Also moves `zkevm-bench-setup` and the tool's README from v1.0.0-alpha to
v1.1.0-alpha, and pins the Rust toolchain the target installs. ziskup takes whatever
release is newest, which for v1.0.0-alpha was already the wrong pairing — that target
could not have linked a guest as written. Pinning it to the version CI uses keeps the
local path and CI on the same footing.

Left alone on purpose: the v1.0.0-alpha strings in the tool's test fixtures, its
sample report, and docs/ziskemu-output.md. Those record a real captured `ziskemu -X`
run rather than a version we install, and rewriting them would misdescribe the
capture.
The bump moves the emulator the zkEVM benchmark shells out to, and v1.1.0-alpha's
release notes rework emulator statistics, so the AIR-cost parser needed checking
rather than assuming. Ran `ziskemu -X` from the v1.1.0-alpha toolchain against a guest
ELF built from this tree: the only structural change is a new `ROM USAGE` line after
`RAM USAGE`. Every label `parse_air_cost` matches is still emitted unchanged, and
`ROM` is not one of them, so it is skipped like any other unrecognised label.

The committed fixture stays on its v1.0.0-alpha capture — it records a real run.
@ilitteri

Copy link
Copy Markdown
Collaborator Author

Heads up that the scope grew after the approval, since main moved underneath this branch.

tooling/zkevm_bench landed on main and brings its own ZisK coupling, so three additions were needed:

  • A third lockfile. It is a standalone workspace depending on ethrex-guest-program with the zisk feature, so its committed lock went stale as soon as the ziskos tag moved. Its lint step runs cargo clippy --locked and then asserts the lock is unmodified — this was a guaranteed failure on the first run after merging main in.
  • make zkevm-bench-setup and the tool's README still installed v1.0.0-alpha. Bumped, and the Rust toolchain that target installs is now pinned to the release CI uses. Worth noting it was already wrong: ziskup takes whatever toolchain is newest, which paired with v1.0.0-alpha could not have linked a guest.
  • The ziskemu -X parser. v1.1.0-alpha reworks emulator statistics, so I ran ziskemu -X from the new toolchain against a guest ELF built from this tree instead of assuming. The only structural change is an added ROM USAGE line; every label parse_air_cost matches is emitted unchanged and ROM is not one of them, so it is skipped like any unrecognised label. Recorded in docs/ziskemu-output.md.

Left on v1.0.0-alpha on purpose: the tool's test fixtures, its sample report, and fixtures/ziskemu_sample.txt — those record a real captured run, not a version we install.

Lint zisk backend (which now includes the zkevm_bench clippy and lock check) and Check Cargo.lock both pass on the current head. The PR description has been updated to match.

@ilitteri
ilitteri added this pull request to the merge queue Aug 18, 2026
Merged via the queue into main with commit 8d19edd Aug 18, 2026
63 checks passed
@ilitteri
ilitteri deleted the chore/bump-zisk-v1.1.0-alpha branch August 18, 2026 21:59
@github-project-automation github-project-automation Bot moved this from In Review to Done in ethrex_l1 Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client L2 Rollup client

Projects

Status: Done
Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants