diff --git a/.gitignore b/.gitignore index 8fd34cc2d5..24c0cf6e2e 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ target zkvm-prover/*.json .work/ rollup/tests.test +local-secrets.md +tmp/ diff --git a/AGENTS.md b/AGENTS.md index 449aecbdc8..35ace727ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,6 +20,60 @@ Follow the structured testing guide in [`docs/testing/openvm-upgrade-testing-gui 4. End-to-end proving 5. Docker image builds +## Shadow Coordinator + Prover Testing (Production Task Replay) + +For testing proof generation against **real mainnet production tasks** without interfering with the live system, use the **Shadow Coordinator** approach. This is significantly faster than a full shadow fork. There are two test modes, each in its own directory under `tests/shadow-testing/`: + +- **Follow mode (primary/default)** — `cd tests/shadow-testing/follow && make follow` forks the ETH mainnet state `FOLLOW_FORK_HOURS_BACK` hours in the past (default 5h; `0` = current tip), catches up the resulting backlog, then follows mainnet bundle production in real time (poll-sync → prove → finalize, default 48h window). This is the default acceptance test for prover/guest upgrades. Operations: `make follow-status`, `make follow-report`, `make follow-stop`, `make re-fork`. +- **Snapshot replay mode (specialized)** — `cd tests/shadow-testing/snapshot`: fork a historical block, import a fixed bundle range, prove & finalize ~N bundles (`make all` / `make docker-all` / `make sepolia-all`). Use for incident reproduction, single-bundle debugging, Sepolia testing, targeted codec-migration checks. + +Shared details: + +- **Architecture**: Local coordinator (`:8390`) + local prover (GPU), fed by imported production task data. Scripts shared by both modes live in `tests/shadow-testing/lib/`; runtime state is shared at `tests/shadow-testing/.work/`. +- **Docs**: [`tests/shadow-testing/follow/GUIDE.md`](tests/shadow-testing/follow/GUIDE.md) and [`tests/shadow-testing/snapshot/GUIDE.md`](tests/shadow-testing/snapshot/GUIDE.md) — per-mode setup guides, troubleshooting, config reference. +- **Quick Start**: [`tests/shadow-testing/README.md`](tests/shadow-testing/README.md) (mode chooser) +- **Automation**: `tests/shadow-testing/{follow,snapshot}/Makefile` — per-mode Makefile targets; the root `tests/shadow-testing/Makefile` is a thin dispatcher (`make follow-up`, `make snapshot-all ...`). + +Key hard-won rules: +- **L2 RPC for coordinator task generation** (must support `debug_executionWitness`): + - ✅ **Primary**: `https://l2geth-rpc-proxy.mainnet.aws.scroll.io/` (internal/debug-enabled, supports `debug_executionWitness`) + - ⚠️ **Fallback**: `https://mainnet-rpc.scroll.io` (public RPC, may not support `debug_executionWitness` for chunk task generation) + - ❌ **Avoid**: `https://rpc.scroll.io` (does not work) +- **Alchemy API for Anvil fork** (must use Alchemy, others hit rate limits): + - ✅ **Primary**: `https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY` + - 📋 **Credential source**: Check `local-secrets.md`, `.env`, or `.pgpass` first. If not found, **ask a human** — do not guess or invent keys. +- **S3 circuit URLs**: v0.9.0 uses `releases/v0.9.0/` prefix. (v0.8.0 historically used `v0.8.0/` without `/releases/`.) +- **l2_block table**: Coordinator needs this for block hash lookups. Must be populated and linked via `chunk_hash`. +- **Blocks**: Must be post-fork (GalileoV2 / codec V10 = blocks ≥ 33,750,000 on mainnet). +- **L1 messages**: If chunks contain L1 messages, prover needs `scroll_getL1MessagesInBlock` RPC support. Most chunks at current mainnet height do NOT contain L1 messages, so this is usually non-blocking. +- **Anvil MUST fork Ethereum L1, NOT Scroll L2**: The ScrollChain proxy address `0xa13BAF47339d63B743e7Da8741db5456DAc1E556` is on **Ethereum mainnet** (chainId=1), not Scroll mainnet (chainId=534352). If you accidentally point Anvil at a Scroll L2 RPC (e.g., `scroll-mainnet.g.alchemy.com`), the proxy address will have no code or wrong code, and all contract interactions will fail. Always verify `eth_chainId` returns `1` after forking. + +### Follow Mode — Additional Rules + +For continuously proving mainnet bundles in real time (poll-syncing the mainnet DB into the shadow DB), three silent starvation traps apply — see `tests/shadow-testing/follow/TROUBLESHOOTING.md` Trap 22/23: +- Poll sync must also maintain `l2_block.chunk_hash` links (UPDATE, not INSERT) and `chunk.batch_hash`/`batch.bundle_hash` parent links, or tasks become invisible to the coordinator with no ERROR logged. +- `sweep-stale-proving.sh` must reset `total_attempts`, not just `proving_status` — the coordinator skips tasks with `total_attempts >= 5`. +- Bundles popping L1 messages enqueued after the Anvil fork block fail with `VerificationFailed(0x439cc0cd)`: the queue-hash sync (`tests/shadow-testing/lib/sync-queue-hashes.py`) runs inside the `sync-mainnet-db.py` poll loop every cycle to mirror `messageRollingHashes` + `nextCrossDomainMessageIndex` from mainnet onto the fork. +- Never run a poll sync against an empty/reset DB: watermark=0 makes it backfill all of mainnet history (Trap 25). Baseline first (handled by `10-follow-up.sh`), and stop daemons with `11-follow-stop.sh` which kills whole process groups — an orphaned python sync is invisible to pidfile checks. + +Daemons: poll-sync (with integrated queue-hash sync), the sweeper, and the hourly monitor all run as plain background processes with pidfiles in `.work/`, started by `follow/scripts/10-follow-up.sh` (the sweeper loops every 10 min) — **no agent/session cron is required**. Fork recovery: `make re-fork` (re-fork, redeploy wrapper, re-fund EOAs, re-mirror queue hashes, restart relayer). + +### Sepolia Shadow Fork — Additional Rules + +| Dimension | Mainnet | Sepolia | Trap | +|-----------|---------|---------|------| +| **DB port** | `localhost:5433` (shadow) / `15432` (RDS tunnel) | `localhost:25432` (RDS tunnel) | Wrong port = connecting to mainnet data | +| **L2 RPC** | `l2geth-rpc-proxy.mainnet.aws.scroll.io` | `l2geth-rpc-proxy.sepolia.aws.scroll.io` | Public Sepolia RPC (`sepolia-rpc.scroll.io`) rejects `debug_executionWitness` | +| **Verifier** | Mainnet has `latestVerifier[10] = 0x0dE1...` (can `anvil_setCode`) | Production proofs + production MVRV may already match | Re-using old proofs → check MVRV first. Testing **new guest** → MUST deploy fresh verifier | +| **`committedBatches`** | Sparse, but fork block usually covers target batches | Sparse; **every bundle end batch must exist** | Missing entry → `ErrorIncorrectBatchHash(0x2a1c1442)` | +| **`L1MessageQueueV2`** | Reset `nextUnfinalizedQueueIndex = 0` sufficient | Set to `MIN(total_l1_messages_popped_before)` of first target batch; **slot 104** (verify with `forge inspect`) | Wrong slot/value → `ErrorFinalizedIndexTooLarge(0x16465978)` | +| **Anvil gas estimation** | Same as mainnet | `eth_estimateGas` fails with fee caps present (`Gas=0`) | Patch `estimategas.go` or use `--min-codec-version` workaround | +| **Sender balance** | Persisted across restarts | **Resets to 0** after Anvil restart | Must re-fund EOAs before each relayer start | +| **Relayer flags** | Standard | Requires `--config ` AND `--min-codec-version 10` | Missing flags = wrong config or immediate exit | +| **DB scope** | Imported limited range | Full production snapshot (batches 128080+) | Relayer batch committer floods logs with commit retries | +| **Blob version** | Usually V0 | Anvil 1.0.0 cannot decode BlobSidecar V1 | Set `fusaka_timestamp: 2000000000` in relayer config | +| **Proofs in DB** | May already be v0.9.0 | Old proofs are v0.7.3 | Must reset `proving_status = 1` to regenerate with v0.9.0 | + ## Useful Commands ```bash @@ -64,6 +118,28 @@ make coordinator_setup | `zkvm-prover/` | Build scripts and runtime config for the prover binary | | `build/dockerfiles/` | Dockerfiles for production images | +## Troubleshooting: Verifier Wrapper Deployment on Shadow Forks + +### `anvil_setCode` Does NOT Reset Immutables +- **Problem**: Copying a mainnet verifier wrapper (e.g., `ZkEvmVerifierPostFeynman`) to Anvil via `anvil_setCode` preserves the **original immutables** (`verifierDigest1`, `verifierDigest2`, `protocolVersion`). These digests are bound to the mainnet plonk verifier VK and will **never** match locally-generated proofs. +- **Symptom**: `VerificationFailed` (selector `0x439cc0cd`) even when the plonk verifier binary, public input hash, and proof are all individually correct. +- **Root cause**: The wrapper assembles its own `instances` array from immutables + `keccak256(protocolVersion || publicInput)`. Wrong immutables = wrong instances = plonk verifier rejects the proof. +- **Solution**: **Always recompile and redeploy** the wrapper with immutables extracted from the *local* proof's `instances` array (bytes 384–416 and 416–448 for digest1/digest2). + +### Do Not "Fix" Production Solidity Without Evidence +- **Problem**: When `VerificationFailed` appears, it's tempting to blame the assembly loop in the wrapper (`sub(0x5a0, i)` vs `add(0x1c0, i)`). +- **Reality**: The production wrapper (`ZkEvmVerifierPostFeynman.sol`) has used `sub(0x5a0, i)` since deployment and has finalized thousands of bundles on mainnet. The loop direction maps hash bytes in **reverse order** to instance words, which matches the verifier circuit's expectation. +- **Symptom of wrong patch**: Changing the loop to `add(0x1c0, i)` inverts the hash-word layout, producing a different set of instances that also fail verification. +- **Correct diagnosis flow**: + 1. Verify the plonk verifier binary matches the deployed contract runtime code. + 2. Verify `keccak256(abi.encodePacked(protocolVersion, publicInput))` matches the proof metadata `bundle_pi_hash`. + 3. Verify the wrapper's immutables match the local proof's digest words. + 4. Only after (1–3) pass should you look at Solidity logic — and even then, production code is almost certainly correct. + +### Access Control on `finalizeBundlePostEuclidV2` +- `ScrollChain.finalizeBundlePostEuclidV2` has `OnlyProver` modifier. +- On shadow fork, impersonate the registered prover EOA before sending the transaction: `cast rpc anvil_impersonateAccount `. + ## Troubleshooting Common E2E Test Issues ### Port Conflicts (Shared Servers) @@ -97,18 +173,42 @@ make coordinator_setup ### S3 Asset URLs - The prover config `base_url` must match the actual S3 object path. Verify with `curl -sI` before running. -- The coordinator downloads **verifier** assets from `v0.X.X/verifier/`; the prover downloads **circuit** assets from `///`. -- If you see HTTP 403 from S3, check whether the URL contains a `releases/` segment that shouldn't be there. +- For v0.9.0, both coordinator **verifier** assets and prover **circuit** assets are under `scroll-zkvm/releases/v0.9.0/`. Earlier v0.8.0 assets used `scroll-zkvm/v0.X.X/` for verifier assets and `scroll-zkvm/galileov2/` for prover circuits. +- If you see HTTP 403 from S3, check whether the URL uses the correct `releases/` prefix for the target version. ### Multiple Coordinator Instances - Running `make coordinator_setup` rebuilds the binary but does not stop running instances. If the old instance holds port 8390, the new one fails with `bind: address already in use`. - Always check with `ss -tlnp | grep 8390` before launching. +## Agent Discipline: Research Before Experimentation + +> **Rule**: When encountering a problem that is **non-trivial**, **time-consuming**, or **has failed more than once**, the agent **must** search existing documentation before attempting new fixes. +> +> 1. Read all relevant markdown files in the task directory (e.g., `tests/shadow-testing/docs/*.md`). +> 2. Search for similar error messages, selectors, or symptoms in the codebase and docs. +> 3. Only after confirming the issue is **not documented** should you design a new experiment. +> +> **Why**: This repository has extensive documentation of past pitfalls. Blind experimentation wastes time and repeats mistakes that are already solved in writing. + ## Coordination with Humans - **Code / logic issues**: agents should reason independently and propose fixes. - **Environment / secrets issues** (database passwords, RPC endpoints, cloud credentials, sudo access): ask the human and wait for a response. Do not time out and make unilateral decisions. +## Secrets & Credentials Reference + +**All sensitive endpoints, keys, and passwords for local development are documented in [`local-secrets.md`](local-secrets.md)** (git-ignored). + +| Category | What's Inside | Why It Matters | +|----------|---------------|----------------| +| **RPC Endpoints** | ETH L1 (Alchemy mainnet/sepolia), Scroll L2 (public/internal) | Anvil must fork **ETH L1**, not Scroll L2. Coordinator needs debug-enabled L2 RPC. | +| **Database DSNs** | Local shadow DB (port 5433), Sepolia shadow DB (port 5442), Mainnet RDS (port 15432 via tunnel) | Wrong DSN = wrong chain data = wasted proving hours. | +| **Contract Addresses** | ScrollChain proxy, L1MessageQueueV2, RollupVerifier, MockVerifier | These change per network (mainnet vs sepolia). Hard-coding without checking = `ErrorIncorrectBatchHash`. | +| **Sender Keys** | Commit/finalize EOA private keys for shadow fork | Anvil-funded accounts; never use production keys in shadow tests. | +| **S3 URLs** | Circuit asset base URLs | v0.9.0 uses the `releases/v0.9.0/` prefix. Wrong URL = 403. | + +> **Agent Rule**: Before starting any shadow fork or E2E test, always cross-reference `local-secrets.md`. If a required secret is missing, ask the human — do not invent URLs or credentials. + ## Documentation Index | Document | What It Covers | @@ -116,4 +216,9 @@ make coordinator_setup | [`docs/prover-coordinator-overview.md`](docs/prover-coordinator-overview.md) | Architecture, data flow, component relationships, common operations | | [`docs/testing/openvm-upgrade-testing-guide.md`](docs/testing/openvm-upgrade-testing-guide.md) | Step-by-step testing checklist after OpenVM / zkvm-prover upgrades | | [`docs/testing/docker-compose-e2e-guide.md`](docs/testing/docker-compose-e2e-guide.md) | Production-like E2E testing with Docker Compose + Coordinator Proxy | +| [`tests/shadow-testing/follow/GUIDE.md`](tests/shadow-testing/follow/GUIDE.md) | Follow mode: shadow coordinator + local prover following live mainnet (primary acceptance test) | +| [`tests/shadow-testing/snapshot/GUIDE.md`](tests/shadow-testing/snapshot/GUIDE.md) | Snapshot replay mode: historical fork + fixed bundle range (incident reproduction, Sepolia) | +| [`tests/shadow-testing/docs/COMMON-TROUBLESHOOTING.md`](tests/shadow-testing/docs/COMMON-TROUBLESHOOTING.md) | Mode-independent pitfalls and agent checklists for shadow testing; per-mode traps live in `tests/shadow-testing/follow/TROUBLESHOOTING.md` and `tests/shadow-testing/snapshot/TROUBLESHOOTING.md` | +| [`tests/shadow-testing/README.md`](tests/shadow-testing/README.md) | Quick reference for common shadow testing commands | | [`docs/testing_reports/openvm-v1.6.0-guest-v0.8.0-May19.md`](docs/testing_reports/openvm-v1.6.0-guest-v0.8.0-May19.md) | Test report for PR #1783 (OpenVM 1.6.0, guest v0.8.0) | +| [`docs/testing/single-chunk-reproving.md`](docs/testing/single-chunk-reproving.md) | Re-proving one specific mainnet chunk using shadow DB + local coordinator/prover | diff --git a/Cargo.lock b/Cargo.lock index a397bc5f7d..1631932da3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,7 +135,7 @@ checksum = "9f5bedd6a59a2bd3a2f1cb7ff488549a2004302edca4df4d578bf0a814888615" dependencies = [ "alloy-consensus", "alloy-core", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-provider", @@ -163,10 +163,10 @@ version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9b151e38e42f1586a01369ec52a6934702731d07e8509a7307331b09f6c46dc" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "alloy-trie 0.9.5", "alloy-tx-macros", "auto_impl", @@ -190,10 +190,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2d5e8668ef6215efdb7dcca6f22277b4e483a5650e05f5de22b2350971f4b8" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "serde", ] @@ -260,26 +260,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "alloy-eips" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609515c1955b33af3d78d26357540f68c5551a90ef58fd53def04f2aa074ec43" -dependencies = [ - "alloy-eip2124", - "alloy-eip2930", - "alloy-eip7702", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.14.0", - "auto_impl", - "c-kzg", - "derive_more 2.1.1", - "either", - "serde", - "sha2 0.10.9", -] - [[package]] name = "alloy-eips" version = "1.8.3" @@ -292,7 +272,7 @@ dependencies = [ "alloy-eip7928", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "auto_impl", "borsh", "c-kzg", @@ -312,7 +292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08e9e656d58027542447c1ca5aa4ca96293f09e6920c4651953b7451a7c35e4e" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-hardforks", "alloy-primitives", "alloy-rpc-types-engine", @@ -333,9 +313,9 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbf9480307b09d22876efb67d30cadd9013134c21f3a17ec9f93fd7536d38024" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", - "alloy-serde 1.8.3", + "alloy-serde", "alloy-trie 0.9.5", "borsh", "serde", @@ -391,13 +371,13 @@ checksum = "8eaf2ae05219e73e0979cb2cf55612aafbab191d130f203079805eaf881cca58" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-json-rpc", "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-any", "alloy-rpc-types-eth", - "alloy-serde 1.8.3", + "alloy-serde", "alloy-signer", "alloy-sol-types", "async-trait", @@ -416,9 +396,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e58f4f345cef483eab7374f2b6056973c7419ffe8ad35e994b7a7f5d8e0c7ba4" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", - "alloy-serde 1.8.3", + "alloy-serde", "serde", ] @@ -445,7 +425,7 @@ dependencies = [ "rapidhash", "rkyv", "ruint", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "serde", "sha3", "tiny-keccak", @@ -459,7 +439,7 @@ checksum = "de2597751539b1cc8fe4204e5325f9a9ed83fcacfb212018dfcfa7877e76de21" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-network-primitives", @@ -492,9 +472,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" +checksum = "24671b1f62edcf0f9b62994c7bf72cd621a04a4b99f5020ece1a647b40e2f103" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -503,13 +483,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" +checksum = "9d4311c03125e8a18296504560b9de3d75ecbd0dcda7f71e6cf2a196d57e6fba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -543,7 +523,7 @@ checksum = "fbde0801a32d21c5f111f037bee7e22874836fba7add34ed4a6919932dd7cf23" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", - "alloy-serde 1.8.3", + "alloy-serde", ] [[package]] @@ -565,10 +545,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "605ec375d91073851f566a3082548af69a28dca831b27a8be7c1b4c49f5c6ca2" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "derive_more 2.1.1", "ethereum_ssz", "ethereum_ssz_derive", @@ -584,11 +564,11 @@ checksum = "361cd87ead4ba7659bda8127902eda92d17fa7ceb18aba1676f7be10f7222487" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-network-primitives", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "alloy-sol-types", "itertools 0.14.0", "serde", @@ -597,17 +577,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "alloy-serde" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4dba6ff08916bc0a9cbba121ce21f67c0b554c39cf174bc7b9df6c651bd3c3b" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - [[package]] name = "alloy-serde" version = "1.8.3" @@ -645,7 +614,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -662,7 +631,7 @@ dependencies = [ "proc-macro2", "quote", "sha3", - "syn 2.0.117", + "syn 2.0.118", "syn-solidity", ] @@ -678,7 +647,7 @@ dependencies = [ "macro-string", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "syn-solidity", ] @@ -784,7 +753,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -857,15 +826,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "ar_archive_writer" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +checksum = "4087686b4b0a3427190bae57a1d9a478dbb2d40c5dc1bd6e2b6d797913bdd348" dependencies = [ "object", ] @@ -973,6 +942,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7a806ac6c8307b929df4645776290a50ee2aac754ad09d8bdf73391309e43af" +dependencies = [ + "ark-ff-asm 0.6.0", + "ark-ff-macros 0.6.0", + "ark-serialize 0.6.0", + "ark-std 0.6.0", + "digest 0.10.7", + "educe", + "num-bigint", + "num-traits", + "zeroize", +] + [[package]] name = "ark-ff-asm" version = "0.3.0" @@ -1000,7 +986,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", +] + +[[package]] +name = "ark-ff-asm" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1479009684adc073dff49a1025d3a7065b317a9ead25aaaca38cdc70058ba8a2" +dependencies = [ + "quote", + "syn 2.0.118", ] [[package]] @@ -1038,7 +1034,20 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", +] + +[[package]] +name = "ark-ff-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0691ed21ef00ef89c1e9bda832eba493dda3ec2f8d892fb25b705f73f06bb8" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.118", ] [[package]] @@ -1112,13 +1121,26 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ - "ark-serialize-derive", + "ark-serialize-derive 0.5.0", "ark-std 0.5.0", "arrayvec", "digest 0.10.7", "num-bigint", ] +[[package]] +name = "ark-serialize" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a74dd304fd536fb95d0a328e72be759209cc496a9da094c5bc56e5fea4f9e86b" +dependencies = [ + "ark-serialize-derive 0.6.0", + "ark-std 0.6.0", + "digest 0.10.7", + "num-bigint", + "serde_with", +] + [[package]] name = "ark-serialize-derive" version = "0.5.0" @@ -1127,7 +1149,18 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f153690697a2b91e5e1251ff98411ee5371500a111a0fd317a70e588eb300f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", ] [[package]] @@ -1161,6 +1194,16 @@ dependencies = [ "rand 0.8.6", ] +[[package]] +name = "ark-std" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367c9c827ed431bff6868b7aa926e05b16eb46603cc8b6e768e4a5553fa1d155" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -1169,9 +1212,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" dependencies = [ "serde", ] @@ -1219,7 +1262,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1230,7 +1273,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1257,14 +1300,14 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "axum" @@ -1387,16 +1430,16 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cexpr", "clang-sys", "itertools 0.13.0", "proc-macro2", "quote", "regex", - "rustc-hash 2.1.2", - "shlex", - "syn 2.0.117", + "rustc-hash 2.1.3", + "shlex 1.3.0", + "syn 2.0.118", ] [[package]] @@ -1420,38 +1463,45 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6ed1b54d8dc333e7be604d00fa9262f4635485ffea923647b6521a5fff045d" dependencies = [ - "arrayvec", - "bitcode_derive", "bytemuck", - "glam", "serde", ] [[package]] -name = "bitcode_derive" -version = "0.6.9" +name = "bitcoin-consensus-encoding" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238b90427dfad9da4a9abd60f3ec1cdee6b80454bde49ed37f1781dd8e9dc7f9" +checksum = "b2d6094e2a1ba3c93b5a596fe5a10d1a10c3c6e06785cde89f693a044c01aa40" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "bitcoin-internals", +] + +[[package]] +name = "bitcoin-internals" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64" +dependencies = [ + "hex-conservative 0.3.2", ] [[package]] name = "bitcoin-io" -version = "0.1.4" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" +checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78" +dependencies = [ + "bitcoin-consensus-encoding", +] [[package]] name = "bitcoin_hashes" -version = "0.14.1" +version = "0.14.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "bitcoin-io", - "hex-conservative", + "hex-conservative 0.2.2", ] [[package]] @@ -1462,9 +1512,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -1477,9 +1527,9 @@ checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" [[package]] name = "bitvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", @@ -1508,20 +1558,6 @@ dependencies = [ "constant_time_eq", ] -[[package]] -name = "blake3" -version = "1.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", - "cpufeatures 0.3.0", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -1592,9 +1628,9 @@ dependencies = [ [[package]] name = "bon" -version = "3.9.1" +version = "3.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47dbe92550676ee653353c310dfb9cf6ba17ee70396e1f7cf0a2020ad49b2fe" +checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561" dependencies = [ "bon-macros", "rustversion", @@ -1602,9 +1638,9 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.9.1" +version = "3.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519bd3116aeeb42d5372c29d982d16d0170d3d4a5ed85fc7dd91642ffff3c67c" +checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f" dependencies = [ "darling 0.23.0", "ident_case", @@ -1612,14 +1648,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "borsh" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +checksum = "2f3f6da4992df95bbcd9af42a6c7dcb994498fc9048230405f3b36ff7cd3f145" dependencies = [ "borsh-derive", "bytes", @@ -1628,15 +1664,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +checksum = "3ae8fb4fb5740e4b2c4884ff95f5f32f5e8479db1e8fd8eb49ddbe09eb09bb7c" dependencies = [ "once_cell", "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1650,9 +1686,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byte-slice-cast" @@ -1680,14 +1716,14 @@ checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "bytemuck" -version = "1.25.0" +version = "1.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" [[package]] name = "byteorder" @@ -1697,18 +1733,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" dependencies = [ "serde", ] [[package]] name = "bytesize" -version = "2.3.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3" +checksum = "3d7c8918969267b2932ffd5655509bbbea0833823058c378876953217f5fc50e" [[package]] name = "bzip2-sys" @@ -1722,9 +1758,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "2.1.7" +version = "2.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" +checksum = "38d04308254695569fdb9bfe3bacc1c91837a670d0806605eb82d63748fbd3a6" dependencies = [ "blst", "cc", @@ -1737,9 +1773,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" dependencies = [ "serde_core", ] @@ -1769,14 +1805,14 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.62" +version = "1.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 2.0.1", ] [[package]] @@ -1800,11 +1836,22 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "num-traits", @@ -1865,7 +1912,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1874,6 +1921,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "color-eyre" version = "0.6.5" @@ -1936,9 +1992,9 @@ checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" [[package]] name = "const-hex" -version = "1.19.0" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20d9a563d167a9cce0f94153382b33cb6eded6dfabff03c69ad65a28ea1514e0" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" dependencies = [ "cfg-if", "cpufeatures 0.2.17", @@ -2101,18 +2157,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -2120,27 +2176,27 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crunchy" @@ -2187,7 +2243,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2215,24 +2271,6 @@ dependencies = [ "cipher", ] -[[package]] -name = "cuda-config" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee74643f7430213a1a78320f88649de309b20b80818325575e393f848f79f5d" -dependencies = [ - "glob", -] - -[[package]] -name = "cuda-runtime-sys" -version = "0.3.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d070b301187fee3c611e75a425cf12247b7c75c09729dbdef95cb9cb64e8c39" -dependencies = [ - "cuda-config", -] - [[package]] name = "cudarc" version = "0.9.15" @@ -2280,7 +2318,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2295,7 +2333,7 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2308,7 +2346,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2319,7 +2357,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2330,7 +2368,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2341,7 +2379,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2375,7 +2413,6 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -2398,7 +2435,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2409,7 +2446,7 @@ checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2420,7 +2457,7 @@ checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2449,7 +2486,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "unicode-xid", ] @@ -2463,7 +2500,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.117", + "syn 2.0.118", "unicode-xid", ] @@ -2490,13 +2527,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2575,14 +2612,14 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" dependencies = [ "serde", ] @@ -2613,6 +2650,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encoder-standard" version = "0.1.0" @@ -2638,34 +2687,22 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enum-ordinalize" -version = "4.3.2" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +checksum = "07f808d588c10e464ea6f7d3eaed500049eff30aaac103460f61828c2d65b3eb" dependencies = [ "enum-ordinalize-derive", ] [[package]] name = "enum-ordinalize-derive" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "enum_dispatch" -version = "0.3.13" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +checksum = "42e528e2d34ba8a67a1a650b86beae8ef69fc5fdb638016f386b973226590432" dependencies = [ - "once_cell", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2676,7 +2713,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2745,9 +2782,9 @@ dependencies = [ [[package]] name = "ethereum_serde_utils" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dc1355dbb41fbbd34ec28d4fb2a57d9a70c67ac3c19f6a5ca4d4a176b9e997a" +checksum = "38df44a7a271ab43835678f9215b53cc2523e4714a215da6643d83dc110245da" dependencies = [ "alloy-primitives", "hex", @@ -2780,7 +2817,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3011,7 +3048,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3098,36 +3135,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", - "wasip2", - "wasip3", + "rand_core 0.10.1", + "wasm-bindgen", ] [[package]] name = "getset" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +checksum = "6cf442baaabe4213ce7d1239afc26c039180b6456da2cededa316ae2c8a77a77" dependencies = [ - "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3162,15 +3197,9 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] -[[package]] -name = "glam" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" - [[package]] name = "glob" version = "0.3.3" @@ -3214,9 +3243,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -3242,9 +3271,8 @@ dependencies = [ [[package]] name = "halo2-axiom" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aee3f8178b78275038e5ea0e2577140056d2c4c87fccaf6777dc0a8eebe455a" +version = "0.5.2" +source = "git+https://github.com/axiom-crypto/halo2.git?tag=v0.5.2#1eed471495b64ec1edf22f0661bbc65d0e4381d5" dependencies = [ "blake2b_simd", "crossbeam", @@ -3264,9 +3292,8 @@ dependencies = [ [[package]] name = "halo2-base" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678cf3adc0a39d7b4d9b82315a655201aa24a430dd1902b162c508047f56ac69" +version = "0.5.4" +source = "git+https://github.com/axiom-crypto/halo2-lib.git?tag=v0.5.4#a69fdee77f41bdd48ad658b69673dea5a0815db4" dependencies = [ "getset", "halo2-axiom", @@ -3285,9 +3312,8 @@ dependencies = [ [[package]] name = "halo2-ecc" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c00681fdd1febaf552d8814e9f5a6a142d81a1514102190da07039588b366" +version = "0.5.4" +source = "git+https://github.com/axiom-crypto/halo2-lib.git?tag=v0.5.4#a69fdee77f41bdd48ad658b69673dea5a0815db4" dependencies = [ "halo2-base", "itertools 0.11.0", @@ -3451,12 +3477,27 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hex-conservative" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hex-literal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" + [[package]] name = "hkdf" version = "0.12.4" @@ -3477,9 +3518,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -3522,18 +3563,18 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] [[package]] name = "hyper" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -3714,12 +3755,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -3782,7 +3817,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3891,23 +3926,22 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.98" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -3943,12 +3977,12 @@ dependencies = [ [[package]] name = "k256" version = "0.13.4" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "ecdsa", "elliptic-curve", "ff 0.13.1", - "hex-literal", + "hex-literal 1.1.0", "num-bigint", "once_cell", "openvm", @@ -3970,9 +4004,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1766b89733097006f3a1388a02849865d6bc98c89273cb622e29fdd209922183" +checksum = "dd5dc2c0d691cbf7595cde551ced329cca99c2387c2cbc97754c5d0cd045d3ee" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -4028,12 +4062,6 @@ dependencies = [ "spin 0.9.8", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" version = "0.2.186" @@ -4129,9 +4157,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.28" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" +checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" dependencies = [ "cc", "pkg-config", @@ -4148,6 +4176,8 @@ dependencies = [ "c-kzg", "eyre", "git-version", + "openvm-sdk", + "openvm-stark-sdk", "regex", "sbv-core", "sbv-primitives", @@ -4199,9 +4229,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" @@ -4245,7 +4275,7 @@ checksum = "59a9dbbfc75d2688ed057456ce8a3ee3f48d12eec09229f560f3643b9f275653" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4263,6 +4293,16 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "maybe-rayon" version = "0.1.1" @@ -4275,15 +4315,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -4364,9 +4404,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "wasi", @@ -4411,7 +4451,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4431,6 +4471,21 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ndarray" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", +] + [[package]] name = "nibble_vec" version = "0.1.0" @@ -4475,9 +4530,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", @@ -4511,11 +4566,10 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -4606,7 +4660,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4618,12 +4672,21 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] -name = "nybbles" -version = "0.3.4" +name = "nvtx" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad2e855e8019f99e4b94ac33670eb4e4f570a2e044f3749a0b2c7f83b841e52c" +dependencies = [ + "cc", +] + +[[package]] +name = "nybbles" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" dependencies = [ @@ -4680,10 +4743,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a501241474c3118833d6195312ae7eb7cc90bbb0d5f524cbb0b06619e49ff67" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "derive_more 2.1.1", "serde", "serde_with", @@ -4697,7 +4760,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726da827358a547be9f1e37c2a756b9e3729cb0350f43408164794b370cad8ae" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", "derive_more 2.1.1", @@ -4711,7 +4774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8f24b8cb66e4b33e6c9e508bf46b8ecafc92eadd0b93fedd306c0accb477657" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-engine", @@ -4767,11 +4830,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.80" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "foreign-types", "libc", @@ -4787,7 +4850,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4798,9 +4861,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.116" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -4810,8 +4873,8 @@ dependencies = [ [[package]] name = "openvm" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "bytemuck", "getrandom 0.2.17", @@ -4825,8 +4888,8 @@ dependencies = [ [[package]] name = "openvm-algebra-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "blstrs", "cfg-if", @@ -4836,13 +4899,14 @@ dependencies = [ "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", "num-bigint", "num-traits", + "once_cell", "openvm-algebra-transpiler", "openvm-circuit", "openvm-circuit-derive", "openvm-circuit-primitives", "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", - "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", "openvm-mod-circuit-builder", @@ -4858,18 +4922,18 @@ dependencies = [ [[package]] name = "openvm-algebra-complex-macros" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-macros-common", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "openvm-algebra-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", "num-bigint", @@ -4884,20 +4948,20 @@ dependencies = [ [[package]] name = "openvm-algebra-moduli-macros" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "num-bigint", "num-prime", "openvm-macros-common", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "openvm-algebra-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-algebra-guest", "openvm-instructions", @@ -4910,8 +4974,8 @@ dependencies = [ [[package]] name = "openvm-bigint-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "cfg-if", "derive-new 0.6.0", @@ -4921,6 +4985,7 @@ dependencies = [ "openvm-circuit-derive", "openvm-circuit-primitives", "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-builder", "openvm-cuda-common", @@ -4936,8 +5001,8 @@ dependencies = [ [[package]] name = "openvm-bigint-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-platform", "strum_macros 0.26.4", @@ -4945,8 +5010,8 @@ dependencies = [ [[package]] name = "openvm-bigint-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-bigint-guest", "openvm-instructions", @@ -4960,8 +5025,8 @@ dependencies = [ [[package]] name = "openvm-build" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "cargo_metadata", "eyre", @@ -4972,17 +5037,16 @@ dependencies = [ [[package]] name = "openvm-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "abi_stable", "backtrace", + "bytesize", "cfg-if", "dashmap", - "derivative", "derive-new 0.6.0", "derive_more 1.0.0", - "enum_dispatch", "eyre", "getset", "itertools 0.14.0", @@ -4991,6 +5055,7 @@ dependencies = [ "openvm-circuit-derive", "openvm-circuit-primitives", "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-builder", "openvm-cuda-common", @@ -5001,7 +5066,7 @@ dependencies = [ "p3-baby-bear", "p3-field", "rand 0.9.4", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "serde", "serde-big-array", "static_assertions", @@ -5011,95 +5076,144 @@ dependencies = [ [[package]] name = "openvm-circuit-derive" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "openvm-circuit-primitives" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "derive-new 0.6.0", "itertools 0.14.0", "num-bigint", "num-traits", "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-builder", "openvm-cuda-common", "openvm-stark-backend", "rand 0.9.4", + "struct-reflection", "tracing", ] [[package]] name = "openvm-circuit-primitives-derive" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "itertools 0.14.0", + "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", +] + +[[package]] +name = "openvm-codec-derive" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.118", ] [[package]] name = "openvm-continuations" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ + "cfg-if", "derivative", + "derive-new 0.6.0", + "eyre", + "hex", + "itertools 0.14.0", + "num-bigint", "openvm-circuit", - "openvm-native-compiler", - "openvm-native-recursion", + "openvm-circuit-primitives", + "openvm-cpu-backend", + "openvm-cuda-backend", + "openvm-cuda-common", + "openvm-poseidon2-air", + "openvm-recursion-circuit", + "openvm-recursion-circuit-derive", "openvm-stark-backend", "openvm-stark-sdk", + "openvm-verify-stark-host", + "p3-air", "p3-bn254", + "p3-field", + "p3-matrix", "serde", - "static_assertions", + "tracing", +] + +[[package]] +name = "openvm-cpu-backend" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +dependencies = [ + "cfg-if", + "derive-new 0.7.0", + "getset", + "itertools 0.14.0", + "openvm-stark-backend", + "p3-air", + "p3-baby-bear", + "p3-dft", + "p3-field", + "p3-interpolation", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "rayon", + "rustc-hash 2.1.3", + "serde", + "thiserror 1.0.69", + "tracing", ] [[package]] name = "openvm-cuda-backend" -version = "1.4.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.4.0#2d4c6da0c84f43b15fcdac84ce13fd2325148c66" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" dependencies = [ - "bincode 2.0.1", - "bincode_derive", - "derivative", "derive-new 0.7.0", + "getset", + "glob", "itertools 0.14.0", - "lazy_static", - "metrics", "openvm-cuda-builder", "openvm-cuda-common", "openvm-stark-backend", "openvm-stark-sdk", "p3-baby-bear", - "p3-commit", + "p3-bn254", "p3-dft", "p3-field", - "p3-fri", - "p3-matrix", - "p3-merkle-tree", "p3-symmetric", "p3-util", - "rustc-hash 2.1.2", + "rand 0.9.4", + "rustc-hash 2.1.3", "serde", - "serde_json", "thiserror 1.0.69", "tracing", + "zkhash-axiom", ] [[package]] name = "openvm-cuda-builder" -version = "1.4.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.4.0#2d4c6da0c84f43b15fcdac84ce13fd2325148c66" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" dependencies = [ "cc", "glob", @@ -5107,8 +5221,8 @@ dependencies = [ [[package]] name = "openvm-cuda-common" -version = "1.4.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.4.0#2d4c6da0c84f43b15fcdac84ce13fd2325148c66" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" dependencies = [ "bytesize", "ctor 0.5.0", @@ -5122,24 +5236,79 @@ dependencies = [ [[package]] name = "openvm-custom-insn" version = "0.1.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", +] + +[[package]] +name = "openvm-deferral-circuit" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "cfg-if", + "dashmap", + "derive-new 0.6.0", + "derive_more 1.0.0", + "itertools 0.14.0", + "openvm-circuit", + "openvm-circuit-derive", + "openvm-circuit-primitives", + "openvm-circuit-primitives-derive", + "openvm-cpu-backend", + "openvm-cuda-backend", + "openvm-cuda-builder", + "openvm-cuda-common", + "openvm-deferral-transpiler", + "openvm-instructions", + "openvm-poseidon2-air", + "openvm-rv32im-circuit", + "openvm-stark-backend", + "openvm-stark-sdk", + "p3-field", + "rand 0.9.4", + "rustc-hash 2.1.3", + "serde", +] + +[[package]] +name = "openvm-deferral-guest" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "openvm-custom-insn", + "strum_macros 0.26.4", +] + +[[package]] +name = "openvm-deferral-transpiler" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "eyre", + "openvm-deferral-guest", + "openvm-instructions", + "openvm-instructions-derive", + "openvm-transpiler", + "p3-field", + "rrs-lib", + "serde", + "strum 0.26.3", ] [[package]] name = "openvm-ecc-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "blstrs", "cfg-if", "derive-new 0.6.0", "derive_more 1.0.0", "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", - "hex-literal", + "hex-literal 1.1.0", "lazy_static", "num-bigint", "num-traits", @@ -5148,6 +5317,7 @@ dependencies = [ "openvm-circuit", "openvm-circuit-derive", "openvm-circuit-primitives", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-common", "openvm-ecc-transpiler", @@ -5164,8 +5334,8 @@ dependencies = [ [[package]] name = "openvm-ecc-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "ecdsa", "elliptic-curve", @@ -5183,18 +5353,18 @@ dependencies = [ [[package]] name = "openvm-ecc-sw-macros" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-macros-common", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "openvm-ecc-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-ecc-guest", "openvm-instructions", @@ -5207,8 +5377,8 @@ dependencies = [ [[package]] name = "openvm-instructions" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "backtrace", "derive-new 0.6.0", @@ -5224,19 +5394,18 @@ dependencies = [ [[package]] name = "openvm-instructions-derive" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "openvm-keccak256-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ - "cfg-if", "derive-new 0.6.0", "derive_more 1.0.0", "itertools 0.14.0", @@ -5244,6 +5413,7 @@ dependencies = [ "openvm-circuit-derive", "openvm-circuit-primitives", "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-builder", "openvm-cuda-common", @@ -5261,16 +5431,16 @@ dependencies = [ [[package]] name = "openvm-keccak256-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-platform", ] [[package]] name = "openvm-keccak256-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-instructions", "openvm-instructions-derive", @@ -5283,26 +5453,22 @@ dependencies = [ [[package]] name = "openvm-macros-common" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "openvm-mod-circuit-builder" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ - "cuda-runtime-sys", "itertools 0.14.0", "num-bigint", "num-traits", "openvm-circuit", "openvm-circuit-primitives", - "openvm-cuda-backend", - "openvm-cuda-builder", - "openvm-cuda-common", "openvm-instructions", "openvm-stark-backend", "openvm-stark-sdk", @@ -5311,115 +5477,14 @@ dependencies = [ "tracing", ] -[[package]] -name = "openvm-native-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" -dependencies = [ - "cfg-if", - "derive-new 0.6.0", - "derive_more 1.0.0", - "eyre", - "itertools 0.14.0", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-cuda-backend", - "openvm-cuda-builder", - "openvm-cuda-common", - "openvm-instructions", - "openvm-native-compiler", - "openvm-poseidon2-air", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-field", - "rand 0.9.4", - "serde", - "static_assertions", - "strum 0.26.3", -] - -[[package]] -name = "openvm-native-compiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" -dependencies = [ - "backtrace", - "itertools 0.14.0", - "num-bigint", - "num-integer", - "openvm-circuit", - "openvm-instructions", - "openvm-instructions-derive", - "openvm-native-compiler-derive", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "serde", - "snark-verifier-sdk", - "strum 0.26.3", - "strum_macros 0.26.4", - "zkhash", -] - -[[package]] -name = "openvm-native-compiler-derive" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "openvm-native-recursion" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" -dependencies = [ - "cfg-if", - "itertools 0.14.0", - "lazy_static", - "once_cell", - "openvm-circuit", - "openvm-native-circuit", - "openvm-native-compiler", - "openvm-native-compiler-derive", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-dft", - "p3-fri", - "p3-merkle-tree", - "p3-symmetric", - "rand 0.8.6", - "rand 0.9.4", - "serde", - "serde_json", - "serde_with", - "snark-verifier-sdk", - "tracing", -] - -[[package]] -name = "openvm-native-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" -dependencies = [ - "openvm-instructions", - "openvm-transpiler", - "p3-field", -] - [[package]] name = "openvm-pairing" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "group 0.13.0", "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", - "hex-literal", + "hex-literal 1.1.0", "itertools 0.14.0", "num-bigint", "num-traits", @@ -5438,8 +5503,8 @@ dependencies = [ [[package]] name = "openvm-pairing-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "cfg-if", "derive-new 0.6.0", @@ -5452,6 +5517,7 @@ dependencies = [ "openvm-circuit", "openvm-circuit-derive", "openvm-circuit-primitives", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-ecc-circuit", "openvm-ecc-guest", @@ -5469,12 +5535,12 @@ dependencies = [ [[package]] name = "openvm-pairing-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "blstrs", "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", - "hex-literal", + "hex-literal 1.1.0", "itertools 0.14.0", "lazy_static", "num-bigint", @@ -5490,8 +5556,8 @@ dependencies = [ [[package]] name = "openvm-pairing-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-instructions", "openvm-pairing-guest", @@ -5503,8 +5569,8 @@ dependencies = [ [[package]] name = "openvm-platform" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "libm", "openvm-custom-insn", @@ -5513,11 +5579,12 @@ dependencies = [ [[package]] name = "openvm-poseidon2-air" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "derivative", "lazy_static", + "openvm-circuit-primitives", "openvm-cuda-builder", "openvm-stark-backend", "openvm-stark-sdk", @@ -5525,13 +5592,50 @@ dependencies = [ "p3-poseidon2-air", "p3-symmetric", "rand 0.9.4", - "zkhash", + "zkhash-axiom", +] + +[[package]] +name = "openvm-recursion-circuit" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "derive-new 0.6.0", + "itertools 0.14.0", + "openvm-circuit", + "openvm-circuit-primitives", + "openvm-cpu-backend", + "openvm-cuda-backend", + "openvm-cuda-builder", + "openvm-cuda-common", + "openvm-poseidon2-air", + "openvm-recursion-circuit-derive", + "openvm-stark-backend", + "openvm-stark-sdk", + "p3-air", + "p3-baby-bear", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-symmetric", + "strum 0.26.3", + "strum_macros 0.26.4", + "tracing", +] + +[[package]] +name = "openvm-recursion-circuit-derive" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "quote", + "syn 2.0.118", ] [[package]] name = "openvm-rv32-adapters" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "derive-new 0.6.0", "itertools 0.14.0", @@ -5547,8 +5651,8 @@ dependencies = [ [[package]] name = "openvm-rv32im-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "cfg-if", "derive-new 0.6.0", @@ -5560,6 +5664,7 @@ dependencies = [ "openvm-circuit-derive", "openvm-circuit-primitives", "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-builder", "openvm-cuda-common", @@ -5570,22 +5675,22 @@ dependencies = [ "rand 0.9.4", "serde", "strum 0.26.3", + "tracing", ] [[package]] name = "openvm-rv32im-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-custom-insn", - "p3-field", "strum_macros 0.26.4", ] [[package]] name = "openvm-rv32im-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-instructions", "openvm-instructions-derive", @@ -5600,124 +5705,147 @@ dependencies = [ [[package]] name = "openvm-sdk" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ + "alloy-sol-types", "bitcode", - "bon", "cfg-if", "clap", "derivative", + "derive-new 0.6.0", "derive_more 1.0.0", "eyre", "getset", + "halo2-base", "hex", "itertools 0.14.0", - "metrics", - "num-bigint", "openvm", + "openvm-build", + "openvm-circuit", + "openvm-continuations", + "openvm-cuda-backend", + "openvm-deferral-circuit", + "openvm-recursion-circuit", + "openvm-sdk-config", + "openvm-stark-backend", + "openvm-stark-sdk", + "openvm-static-verifier", + "openvm-transpiler", + "openvm-verify-stark-circuit", + "openvm-verify-stark-host", + "serde", + "serde_json", + "serde_with", + "tempfile", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "openvm-sdk-config" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "bon", + "cfg-if", + "derive_more 1.0.0", "openvm-algebra-circuit", "openvm-algebra-transpiler", "openvm-bigint-circuit", "openvm-bigint-transpiler", - "openvm-build", "openvm-circuit", "openvm-continuations", + "openvm-cpu-backend", "openvm-cuda-backend", + "openvm-deferral-circuit", + "openvm-deferral-transpiler", "openvm-ecc-circuit", "openvm-ecc-transpiler", "openvm-keccak256-circuit", "openvm-keccak256-transpiler", - "openvm-native-circuit", - "openvm-native-compiler", - "openvm-native-recursion", - "openvm-native-transpiler", "openvm-pairing-circuit", "openvm-pairing-transpiler", "openvm-rv32im-circuit", "openvm-rv32im-transpiler", - "openvm-sha256-circuit", - "openvm-sha256-transpiler", + "openvm-sha2-circuit", + "openvm-sha2-transpiler", "openvm-stark-backend", "openvm-stark-sdk", "openvm-transpiler", - "p3-bn254", - "p3-fri", - "rand 0.9.4", - "rrs-lib", + "openvm-verify-stark-circuit", "serde", - "serde_json", - "serde_with", - "snark-verifier", - "snark-verifier-sdk", - "tempfile", - "thiserror 1.0.69", "toml", - "tracing", ] [[package]] name = "openvm-sha2" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ - "openvm-sha256-guest", + "openvm-sha2-guest", "sha2 0.10.9", ] [[package]] -name = "openvm-sha256-air" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +name = "openvm-sha2-air" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ + "ndarray", + "num_enum 0.7.6", "openvm-circuit-primitives", + "openvm-circuit-primitives-derive", "openvm-stark-backend", "rand 0.9.4", "sha2 0.10.9", ] [[package]] -name = "openvm-sha256-circuit" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +name = "openvm-sha2-circuit" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "cfg-if", "derive-new 0.6.0", "derive_more 1.0.0", + "itertools 0.14.0", + "ndarray", "openvm-circuit", "openvm-circuit-derive", "openvm-circuit-primitives", + "openvm-circuit-primitives-derive", + "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", "openvm-rv32im-circuit", - "openvm-sha256-air", - "openvm-sha256-transpiler", + "openvm-sha2-air", + "openvm-sha2-transpiler", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", "serde", "sha2 0.10.9", - "strum 0.26.3", ] [[package]] -name = "openvm-sha256-guest" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +name = "openvm-sha2-guest" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-platform", ] [[package]] -name = "openvm-sha256-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +name = "openvm-sha2-transpiler" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "openvm-instructions", "openvm-instructions-derive", - "openvm-sha256-guest", + "openvm-sha2-guest", "openvm-stark-backend", "openvm-transpiler", "rrs-lib", @@ -5726,72 +5854,97 @@ dependencies = [ [[package]] name = "openvm-stark-backend" -version = "1.4.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.4.0#2d4c6da0c84f43b15fcdac84ce13fd2325148c66" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" dependencies = [ - "bitcode", "cfg-if", "derivative", "derive-new 0.7.0", "eyre", + "getset", + "hex-literal 1.1.0", "itertools 0.14.0", + "metrics", + "num-bigint", + "openvm-codec-derive", "p3-air", "p3-challenger", - "p3-commit", + "p3-dft", "p3-field", + "p3-interpolation", "p3-matrix", "p3-maybe-rayon", + "p3-symmetric", "p3-util", + "postcard", "rayon", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "serde", "serde_json", "thiserror 1.0.69", + "tikv-jemallocator", "tracing", ] [[package]] name = "openvm-stark-sdk" -version = "1.4.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.4.0#2d4c6da0c84f43b15fcdac84ce13fd2325148c66" +version = "2.0.0" +source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" dependencies = [ "dashmap", - "derivative", - "derive_more 1.0.0", - "ff 0.13.1", + "derive-new 0.7.0", + "eyre", + "hex-literal 1.1.0", "itertools 0.14.0", "metrics", "metrics-tracing-context", "metrics-util", "num-bigint", + "nvtx", + "openvm-cpu-backend", "openvm-stark-backend", "p3-baby-bear", - "p3-blake3", "p3-bn254", - "p3-dft", - "p3-fri", - "p3-goldilocks", - "p3-keccak", - "p3-koala-bear", - "p3-merkle-tree", - "p3-poseidon", + "p3-field", "p3-poseidon2", - "p3-symmetric", "rand 0.9.4", "serde", "serde_json", "static_assertions", - "toml", "tracing", "tracing-forest", "tracing-subscriber 0.3.23", - "zkhash", + "zkhash-axiom", +] + +[[package]] +name = "openvm-static-verifier" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "halo2-base", + "itertools 0.14.0", + "num-bigint", + "num-integer", + "once_cell", + "openvm-continuations", + "openvm-cpu-backend", + "openvm-cuda-backend", + "openvm-recursion-circuit", + "openvm-stark-sdk", + "openvm-verify-stark-host", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "serde_with", + "snark-verifier-sdk", + "tracing", ] [[package]] name = "openvm-transpiler" -version = "1.6.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "elf", "eyre", @@ -5802,6 +5955,54 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "openvm-verify-stark-circuit" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "bitcode", + "cfg-if", + "derive-new 0.6.0", + "eyre", + "itertools 0.14.0", + "openvm-circuit", + "openvm-circuit-primitives", + "openvm-continuations", + "openvm-cpu-backend", + "openvm-cuda-backend", + "openvm-cuda-common", + "openvm-deferral-circuit", + "openvm-poseidon2-air", + "openvm-recursion-circuit", + "openvm-recursion-circuit-derive", + "openvm-stark-backend", + "openvm-stark-sdk", + "openvm-verify-stark-host", + "p3-air", + "p3-field", + "p3-matrix", + "serde", + "tracing", +] + +[[package]] +name = "openvm-verify-stark-host" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +dependencies = [ + "bitcode", + "eyre", + "openvm-circuit", + "openvm-circuit-primitives", + "openvm-recursion-circuit-derive", + "openvm-stark-backend", + "openvm-stark-sdk", + "p3-field", + "serde", + "thiserror 1.0.69", + "zstd", +] + [[package]] name = "ordered-float" version = "4.6.0" @@ -5832,12 +6033,12 @@ dependencies = [ [[package]] name = "p256" version = "0.13.2" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.6.0#eda5bf031a6bd0960adb1dcf59b9a0a951eacb20" +source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" dependencies = [ "ecdsa", "elliptic-curve", "ff 0.13.1", - "hex-literal", + "hex-literal 1.1.0", "num-bigint", "openvm", "openvm-algebra-guest", @@ -5872,17 +6073,6 @@ dependencies = [ "rand 0.9.4", ] -[[package]] -name = "p3-blake3" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8f97fd783752532861bf29bac344b7c226a0d1e2151148834c43c651a5d401" -dependencies = [ - "blake3", - "p3-symmetric", - "p3-util", -] - [[package]] name = "p3-bn254" version = "0.4.3" @@ -5913,21 +6103,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "p3-commit" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf6d7dcb58a8f21f0e1325dc7f7699ad749878ccbe7e286e61f9d46bde2bfa88" -dependencies = [ - "itertools 0.14.0", - "p3-challenger", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-util", - "serde", -] - [[package]] name = "p3-dft" version = "0.4.3" @@ -5959,46 +6134,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "p3-fri" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ca6a795cfc4180425fbf16dfdb4c9c2bfa85971dd55b5930d97b513e0835df" -dependencies = [ - "itertools 0.14.0", - "p3-challenger", - "p3-commit", - "p3-dft", - "p3-field", - "p3-interpolation", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "rand 0.9.4", - "serde", - "thiserror 2.0.18", - "tracing", -] - -[[package]] -name = "p3-goldilocks" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c47d5c650bbeb25941b9a1fa9bfaf59b3cd202a438ea2c20892489af001399" -dependencies = [ - "num-bigint", - "p3-challenger", - "p3-dft", - "p3-field", - "p3-mds", - "p3-poseidon2", - "p3-symmetric", - "p3-util", - "paste", - "rand 0.9.4", - "serde", -] - [[package]] name = "p3-interpolation" version = "0.4.3" @@ -6011,18 +6146,6 @@ dependencies = [ "p3-util", ] -[[package]] -name = "p3-keccak" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a61b090fb42152d1fcb2f82227b8619b1b022f9cd4a123123dccc9c2ab75d5de" -dependencies = [ - "p3-field", - "p3-symmetric", - "p3-util", - "tiny-keccak", -] - [[package]] name = "p3-keccak-air" version = "0.4.3" @@ -6038,20 +6161,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "p3-koala-bear" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb02789fca0950e246123d652bd78e75a76e3b90a651fd88dbb215cd3e81f5a" -dependencies = [ - "p3-challenger", - "p3-field", - "p3-monty-31", - "p3-poseidon2", - "p3-symmetric", - "rand 0.9.4", -] - [[package]] name = "p3-matrix" version = "0.4.3" @@ -6089,25 +6198,6 @@ dependencies = [ "rand 0.9.4", ] -[[package]] -name = "p3-merkle-tree" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e20f61ea816e94f83ed7b8134a5e98d0cad7bd6dff226bc1da17a5143c63cb" -dependencies = [ - "itertools 0.14.0", - "p3-commit", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-symmetric", - "p3-util", - "rand 0.9.4", - "serde", - "thiserror 2.0.18", - "tracing", -] - [[package]] name = "p3-monty-31" version = "0.4.3" @@ -6131,18 +6221,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "p3-poseidon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "548af7ff569975882bc411f653aba7d89a6d85813ca58ef922fd0b1ecb6b5866" -dependencies = [ - "p3-field", - "p3-mds", - "p3-symmetric", - "rand 0.9.4", -] - [[package]] name = "p3-poseidon2" version = "0.4.3" @@ -6235,7 +6313,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6330,9 +6408,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.6" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ "memchr", "ucd-trie", @@ -6346,6 +6424,7 @@ checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros 0.11.3", "phf_shared 0.11.3", + "serde", ] [[package]] @@ -6389,7 +6468,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6402,7 +6481,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6440,7 +6519,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6488,6 +6567,15 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + [[package]] name = "poseidon-primitives" version = "0.2.0" @@ -6503,6 +6591,18 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -6534,7 +6634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6576,7 +6676,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -6598,7 +6698,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6618,7 +6718,7 @@ checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.11.1", + "bitflags 2.13.0", "num-traits", "rand 0.9.4", "rand_chacha 0.9.0", @@ -6645,6 +6745,12 @@ dependencies = [ "http", "libzkp", "once_cell", + "openvm-circuit", + "openvm-continuations", + "openvm-sdk", + "openvm-stark-sdk", + "openvm-verify-stark-circuit", + "openvm-verify-stark-host", "rand 0.8.6", "reqwest", "scroll-proving-sdk", @@ -6686,7 +6792,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -6712,16 +6818,16 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "rustls", "socket2", "thiserror 2.0.18", @@ -6732,16 +6838,17 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "bytes", - "getrandom 0.3.4", + "getrandom 0.4.3", "lru-slab", - "rand 0.9.4", + "rand 0.10.2", + "rand_pcg", "ring", - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", "rustls", "rustls-pki-types", "slab", @@ -6753,23 +6860,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -6804,9 +6911,9 @@ dependencies = [ [[package]] name = "rancor" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" +checksum = "daff8b7b3ccf5f7ba270b3e7a0a4d4c701c5797e38dec27c7e2c3dbb830fed1c" dependencies = [ "ptr_meta", ] @@ -6834,6 +6941,17 @@ dependencies = [ "serde", ] +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -6873,6 +6991,21 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rand_xorshift" version = "0.3.0" @@ -6893,9 +7026,9 @@ dependencies = [ [[package]] name = "rapidhash" -version = "4.4.1" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +checksum = "5da7e78a036ce858e8d55b7e7dc8ba3a88b78350fd2155d3591bbd966b58589e" dependencies = [ "rustversion", ] @@ -6906,9 +7039,15 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.12.0" @@ -6944,7 +7083,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -6964,14 +7103,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", @@ -6981,9 +7120,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -6992,15 +7131,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rend" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" +checksum = "663ba70707f96e871406fe10d68128412e619b06d1d47cb91c3a4c6501176240" dependencies = [ "bytecheck", ] @@ -7105,7 +7244,7 @@ source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186d dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-genesis", "alloy-primitives", @@ -7124,7 +7263,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-genesis", "alloy-primitives", "alloy-trie 0.9.5", @@ -7143,7 +7282,7 @@ source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186d dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -7165,7 +7304,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "reth-chainspec", "reth-consensus", "reth-primitives-traits", @@ -7176,7 +7315,7 @@ name = "reth-db-models" version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "reth-primitives-traits", ] @@ -7198,7 +7337,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "reth-chainspec", "reth-consensus", @@ -7226,11 +7365,11 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-eth", - "alloy-serde 1.8.3", + "alloy-serde", "reth-codecs", "reth-primitives-traits", "serde", @@ -7243,7 +7382,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-primitives", "auto_impl", @@ -7265,7 +7404,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-primitives", "alloy-rpc-types-engine", @@ -7298,7 +7437,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-primitives", "derive_more 2.1.1", @@ -7339,7 +7478,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-genesis", "alloy-primitives", "alloy-rlp", @@ -7390,10 +7529,10 @@ source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186d dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-genesis", "alloy-primitives", - "alloy-serde 1.8.3", + "alloy-serde", "auto_impl", "derive_more 2.1.1", "once_cell", @@ -7414,7 +7553,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-primitives", "alloy-rpc-types-engine", @@ -7458,7 +7597,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", "bytes", @@ -7521,7 +7660,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "auto_impl", @@ -7542,7 +7681,7 @@ name = "reth-storage-errors" version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", "derive_more 2.1.1", @@ -7559,7 +7698,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-trie 0.9.5", @@ -7626,21 +7765,21 @@ dependencies = [ [[package]] name = "revm" -version = "22.0.1" +version = "27.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5378e95ffe5c8377002dafeb6f7d370a55517cef7d6d6c16fc552253af3b123" +checksum = "5e6bf82101a1ad8a2b637363a37aef27f88b4efc8a6e24c72bf5f64923dc5532" dependencies = [ - "revm-bytecode 3.0.0", - "revm-context 3.0.1", - "revm-context-interface 3.0.0", - "revm-database 3.0.0", - "revm-database-interface 3.0.0", - "revm-handler 3.0.1", - "revm-inspector 3.0.1", - "revm-interpreter 18.0.0", - "revm-precompile 19.0.0", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "revm-bytecode 6.2.2", + "revm-context 8.0.4", + "revm-context-interface 9.0.0", + "revm-database 7.0.5", + "revm-database-interface 7.0.5", + "revm-handler 8.1.0", + "revm-inspector 8.1.0", + "revm-interpreter 24.0.0", + "revm-precompile 25.0.0", + "revm-primitives 20.2.1", + "revm-state 7.0.5", ] [[package]] @@ -7682,13 +7821,13 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "3.0.0" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63e138d520c5c5bc25ecc82506e9e4e6e85a811809fc5251c594378dccabfc6" +checksum = "66c52031b73cae95d84cd1b07725808b5fd1500da3e5e24574a3b2dc13d9f16d" dependencies = [ "bitvec", "phf 0.11.3", - "revm-primitives 18.0.0", + "revm-primitives 20.2.1", "serde", ] @@ -7717,17 +7856,17 @@ dependencies = [ [[package]] name = "revm-context" -version = "3.0.1" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9765628dfea4f3686aa8f2a72471c52801e6b38b601939ac16965f49bac66580" +checksum = "9cd508416a35a4d8a9feaf5ccd06ac6d6661cd31ee2dc0252f9f7316455d71f9" dependencies = [ "cfg-if", "derive-where", - "revm-bytecode 3.0.0", - "revm-context-interface 3.0.0", - "revm-database-interface 3.0.0", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "revm-bytecode 6.2.2", + "revm-context-interface 9.0.0", + "revm-database-interface 7.0.5", + "revm-primitives 20.2.1", + "revm-state 7.0.5", "serde", ] @@ -7766,16 +7905,17 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "3.0.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d74335aa1f14222cc4d3be1f62a029cc7dc03819cc8d080ff17b7e1d76375f" +checksum = "dc90302642d21c8f93e0876e201f3c5f7913c4fcb66fb465b0fd7b707dfe1c79" dependencies = [ "alloy-eip2930", "alloy-eip7702", "auto_impl", - "revm-database-interface 3.0.0", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "either", + "revm-database-interface 7.0.5", + "revm-primitives 20.2.1", + "revm-state 7.0.5", "serde", ] @@ -7812,15 +7952,15 @@ dependencies = [ [[package]] name = "revm-database" -version = "3.0.0" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5c80c5a2fd605f2119ee32a63fb3be941fb6a81ced8cdb3397abca28317224" +checksum = "39a276ed142b4718dcf64bc9624f474373ed82ef20611025045c3fb23edbef9c" dependencies = [ - "alloy-eips 0.14.0", - "revm-bytecode 3.0.0", - "revm-database-interface 3.0.0", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "alloy-eips", + "revm-bytecode 6.2.2", + "revm-database-interface 7.0.5", + "revm-primitives 20.2.1", + "revm-state 7.0.5", "serde", ] @@ -7829,7 +7969,7 @@ name = "revm-database" version = "9.0.1" source = "git+https://github.com/scroll-tech/revm?tag=scroll-v91#10e11b985ed28bd383e624539868bcc3f613d77c" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", "revm-bytecode 7.0.1", "revm-database-interface 8.0.2", "revm-primitives 21.0.1", @@ -7843,7 +7983,7 @@ version = "9.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "980d8d6bba78c5dd35b83abbb6585b0b902eb25ea4448ed7bfba6283b0337191" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", "revm-bytecode 7.1.1", "revm-database-interface 8.0.5", "revm-primitives 21.0.2", @@ -7853,13 +7993,14 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "3.0.0" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0e4dfbc734b1ea67b5e8f8b3c7dc4283e2210d978cdaf6c7a45e97be5ea53b3" +checksum = "8c523c77e74eeedbac5d6f7c092e3851dbe9c7fec6f418b85992bd79229db361" dependencies = [ "auto_impl", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "either", + "revm-primitives 20.2.1", + "revm-state 7.0.5", "serde", ] @@ -7890,19 +8031,20 @@ dependencies = [ [[package]] name = "revm-handler" -version = "3.0.1" +version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8676379521c7bf179c31b685c5126ce7800eab5844122aef3231b97026d41a10" +checksum = "1529c8050e663be64010e80ec92bf480315d21b1f2dbf65540028653a621b27d" dependencies = [ "auto_impl", - "revm-bytecode 3.0.0", - "revm-context 3.0.1", - "revm-context-interface 3.0.0", - "revm-database-interface 3.0.0", - "revm-interpreter 18.0.0", - "revm-precompile 19.0.0", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "derive-where", + "revm-bytecode 6.2.2", + "revm-context 8.0.4", + "revm-context-interface 9.0.0", + "revm-database-interface 7.0.5", + "revm-interpreter 24.0.0", + "revm-precompile 25.0.0", + "revm-primitives 20.2.1", + "revm-state 7.0.5", "serde", ] @@ -7945,17 +8087,18 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "3.0.1" +version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfed4ecf999a3f6ae776ae2d160478c5dca986a8c2d02168e04066b1e34c789e" +checksum = "f78db140e332489094ef314eaeb0bd1849d6d01172c113ab0eb6ea8ab9372926" dependencies = [ "auto_impl", - "revm-context 3.0.1", - "revm-database-interface 3.0.0", - "revm-handler 3.0.1", - "revm-interpreter 18.0.0", - "revm-primitives 18.0.0", - "revm-state 3.0.0", + "either", + "revm-context 8.0.4", + "revm-database-interface 7.0.5", + "revm-handler 8.1.0", + "revm-interpreter 24.0.0", + "revm-primitives 20.2.1", + "revm-state 7.0.5", "serde", "serde_json", ] @@ -7997,13 +8140,13 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "18.0.0" +version = "24.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb20260342003cfb791536e678ef5bbea1bfd1f8178b170e8885ff821985473" +checksum = "ff9d7d9d71e8a33740b277b602165b6e3d25fff091ba3d7b5a8d373bf55f28a7" dependencies = [ - "revm-bytecode 3.0.0", - "revm-context-interface 3.0.0", - "revm-primitives 18.0.0", + "revm-bytecode 6.2.2", + "revm-context-interface 9.0.0", + "revm-primitives 20.2.1", "serde", ] @@ -8034,15 +8177,16 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "19.0.0" +version = "25.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418e95eba68c9806c74f3e36cd5d2259170b61e90ac608b17ff8c435038ddace" +checksum = "4cee3f336b83621294b4cfe84d817e3eef6f3d0fce00951973364cc7f860424d" dependencies = [ "ark-bls12-381", "ark-bn254", "ark-ec", "ark-ff 0.5.0", "ark-serialize 0.5.0", + "arrayref", "aurora-engine-modexp", "blst", "c-kzg", @@ -8051,9 +8195,10 @@ dependencies = [ "libsecp256k1", "once_cell", "p256 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "revm-primitives 18.0.0", + "revm-primitives 20.2.1", "ripemd", - "secp256k1 0.30.0", + "rug", + "secp256k1 0.31.1", "sha2 0.10.9", ] @@ -8082,12 +8227,13 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "18.0.0" +version = "20.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc2283ff87358ec7501956c5dd8724a6c2be959c619c4861395ae5e0054575f" +checksum = "5aa29d9da06fe03b249b6419b33968ecdf92ad6428e2f012dc57bcd619b5d94e" dependencies = [ "alloy-primitives", - "enumn", + "num_enum 0.7.6", + "once_cell", "serde", ] @@ -8130,13 +8276,13 @@ dependencies = [ [[package]] name = "revm-state" -version = "3.0.0" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dd121f6e66d75ab111fb51b4712f129511569bc3e41e6067ae760861418bd8" +checksum = "1f64fbacb86008394aaebd3454f9643b7d5a782bd251135e17c5b33da592d84d" dependencies = [ - "bitflags 2.11.1", - "revm-bytecode 3.0.0", - "revm-primitives 18.0.0", + "bitflags 2.13.0", + "revm-bytecode 6.2.2", + "revm-primitives 20.2.1", "serde", ] @@ -8145,7 +8291,7 @@ name = "revm-state" version = "8.0.1" source = "git+https://github.com/scroll-tech/revm?tag=scroll-v91#10e11b985ed28bd383e624539868bcc3f613d77c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "revm-bytecode 7.0.1", "revm-primitives 21.0.1", "serde", @@ -8157,7 +8303,7 @@ version = "8.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8be953b7e374dbdea0773cf360debed8df394ea8d82a8b240a6b5da37592fc" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "revm-bytecode 7.1.1", "revm-primitives 21.0.2", "serde", @@ -8213,9 +8359,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" +checksum = "815cc8a37159a463064825246cadb07961e25cd9885908606f6d08a98d8f8874" dependencies = [ "bytecheck", "bytes", @@ -8232,13 +8378,13 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2ed0b54125315fb36bd021e82d314d1c126548f871634b483f46b31d13cac6" +checksum = "c0ed1a78a1b19d184b0daa629dd9a024573173ec7d485b287cb369fb3607cc1c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -8297,14 +8443,15 @@ dependencies = [ [[package]] name = "ruint" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" +checksum = "45caf26f647c19115bf9c453c70ffe4a4a3a6390dceebd942610584f99b8ddce" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", "ark-ff 0.5.0", + "ark-ff 0.6.0", "bytes", "fastrlp 0.3.1", "fastrlp 0.4.0", @@ -8332,9 +8479,9 @@ checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rustc-demangle" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" [[package]] name = "rustc-hash" @@ -8344,9 +8491,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc-hex" @@ -8378,7 +8525,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", @@ -8387,9 +8534,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.40" +version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "once_cell", "ring", @@ -8401,9 +8548,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -8422,9 +8569,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "rusty-fork" @@ -8474,13 +8621,13 @@ version = "2.0.0" source = "git+https://github.com/scroll-tech/stateless-block-verifier?tag=scroll-v91.2#3a32848c9438432125751eae8837757f6b87562e" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-network", "alloy-primitives", "alloy-rpc-types-debug", "alloy-rpc-types-eth", - "alloy-serde 1.8.3", + "alloy-serde", "reth-chainspec", "reth-ethereum-forks", "reth-evm", @@ -8552,7 +8699,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -8600,10 +8747,10 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.8.3", + "alloy-serde", "derive_more 2.1.1", "reth-codecs", "serde", @@ -8616,7 +8763,7 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-evm", "alloy-primitives", "auto_impl", @@ -8659,11 +8806,11 @@ version = "1.8.2" source = "git+https://github.com/scroll-tech/reth?tag=scroll-v91.2#11d0a3f73186dee7a1ba0d51ea5416dc8fef3e46" dependencies = [ "alloy-consensus", - "alloy-eips 1.8.3", + "alloy-eips", "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 1.8.3", + "alloy-serde", "derive_more 2.1.1", "scroll-alloy-consensus", "serde", @@ -8703,8 +8850,8 @@ dependencies = [ [[package]] name = "scroll-zkvm-prover" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "base64", "bincode 1.3.3", @@ -8713,10 +8860,17 @@ dependencies = [ "git-version", "hex", "openvm-circuit", - "openvm-native-circuit", - "openvm-native-recursion", + "openvm-continuations", + "openvm-cuda-backend", + "openvm-deferral-circuit", + "openvm-recursion-circuit", "openvm-sdk", + "openvm-sdk-config", + "openvm-stark-backend", "openvm-stark-sdk", + "openvm-static-verifier", + "openvm-verify-stark-circuit", + "openvm-verify-stark-host", "scroll-zkvm-types", "scroll-zkvm-verifier", "serde", @@ -8729,8 +8883,8 @@ dependencies = [ [[package]] name = "scroll-zkvm-types" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "alloy-primitives", "base64", @@ -8738,9 +8892,11 @@ dependencies = [ "eyre", "hex", "once_cell", - "openvm-native-recursion", + "openvm-circuit", "openvm-sdk", "openvm-stark-sdk", + "openvm-static-verifier", + "openvm-verify-stark-host", "sbv-primitives", "scroll-zkvm-types-base", "scroll-zkvm-types-batch", @@ -8753,11 +8909,11 @@ dependencies = [ [[package]] name = "scroll-zkvm-types-base" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "alloy-primitives", - "alloy-serde 1.8.3", + "alloy-serde", "serde", "sha2 0.10.9", "sha3", @@ -8765,8 +8921,8 @@ dependencies = [ [[package]] name = "scroll-zkvm-types-batch" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "alloy-primitives", "c-kzg", @@ -8786,8 +8942,8 @@ dependencies = [ [[package]] name = "scroll-zkvm-types-bundle" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "scroll-zkvm-types-base", "serde", @@ -8795,20 +8951,20 @@ dependencies = [ [[package]] name = "scroll-zkvm-types-chunk" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "alloy-consensus", "alloy-primitives", "alloy-sol-types", "ecies", - "hex-literal", + "hex-literal 0.4.1", "itertools 0.14.0", - "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?tag=v1.6.0)", + "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?tag=v2.0.0)", "openvm-ecc-guest", "openvm-pairing", "openvm-sha2", - "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?tag=v1.6.0)", + "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?tag=v2.0.0)", "sbv-core", "sbv-helpers", "sbv-primitives", @@ -8820,15 +8976,18 @@ dependencies = [ [[package]] name = "scroll-zkvm-verifier" -version = "0.8.0" -source = "git+https://github.com/scroll-tech/zkvm-prover?rev=ed3b964#ed3b964c8d0e93856b089d880ad2eda7e08fb7b4" +version = "0.9.0" +source = "git+https://github.com/scroll-tech/zkvm-prover?tag=v0.9.0#bf8494e57828bc449e9582ca6f97b53bd9b6eaf1" dependencies = [ "bincode 1.3.3", "eyre", "once_cell", + "openvm-circuit", "openvm-continuations", - "openvm-native-recursion", "openvm-sdk", + "openvm-stark-sdk", + "openvm-static-verifier", + "openvm-verify-stark-host", "scroll-zkvm-types", "serde", "serde_json", @@ -8899,7 +9058,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -8999,14 +9158,14 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "indexmap 2.14.0", "itoa", @@ -9024,7 +9183,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9061,9 +9220,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ "base64", "bs58", @@ -9081,14 +9240,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9150,9 +9309,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3f15d4e239ebe08413eed880e0f9b5af4b40ee0472543320efa91d488e96a7" +checksum = "a6287fd675f713484342a89cbf0a386abef5f15919cfad607e5e1f19e1e15331" dependencies = [ "cc", "cfg-if", @@ -9173,6 +9332,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "signature" version = "2.2.0" @@ -9231,9 +9396,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" dependencies = [ "serde", ] @@ -9246,9 +9411,8 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "snark-verifier" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d798d8ce8e29b8820ecc1028ac44cc4fc0f0296728af6fe6a0c4db05782c0a4" +version = "0.2.6" +source = "git+https://github.com/axiom-crypto/snark-verifier.git?tag=v0.2.6#364e82654c746b063aff528d8cb660890908278a" dependencies = [ "halo2-base", "halo2-ecc", @@ -9260,7 +9424,7 @@ dependencies = [ "num-traits", "pairing 0.23.0", "rand 0.8.6", - "revm 22.0.1", + "revm 27.1.0", "ruint", "serde", "sha3", @@ -9268,9 +9432,8 @@ dependencies = [ [[package]] name = "snark-verifier-sdk" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338d065044702bf751e87cf353daac63e2fc4c53a3e323cbcd98c603ee6e66c" +version = "0.2.6" +source = "git+https://github.com/axiom-crypto/snark-verifier.git?tag=v0.2.6#364e82654c746b063aff528d8cb660890908278a" dependencies = [ "ark-std 0.3.0", "bincode 1.3.3", @@ -9292,9 +9455,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", "windows-sys 0.61.2", @@ -9362,6 +9525,26 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "struct-reflection" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "701b671d1ad68e250e05718f95dae3014a17f4e69cbe51842531c30495ff3301" +dependencies = [ + "struct-reflection-derive", +] + +[[package]] +name = "struct-reflection-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ab74230a0592602e361bd63c645413fa8cbe4500d10274e849179e5c72548f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "strum" version = "0.24.1" @@ -9418,7 +9601,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9431,7 +9614,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9443,7 +9626,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9465,9 +9648,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -9483,7 +9666,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9503,7 +9686,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9512,7 +9695,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -9540,7 +9723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", @@ -9564,7 +9747,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9575,7 +9758,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "test-case-core", ] @@ -9605,7 +9788,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9616,14 +9799,14 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] @@ -9637,14 +9820,33 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + [[package]] name = "time" -version = "0.3.47" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde_core", @@ -9654,15 +9856,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -9689,9 +9891,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -9725,7 +9927,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -9830,9 +10032,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.11+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", @@ -9877,7 +10079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytes", "futures-core", "futures-util", @@ -9924,7 +10126,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -10037,9 +10239,9 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "typewit" @@ -10079,9 +10281,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-xid" @@ -10148,9 +10350,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "js-sys", "wasm-bindgen", @@ -10219,27 +10421,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -10250,9 +10443,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.71" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -10260,9 +10453,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -10270,48 +10463,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.14.0", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.4.2" @@ -10340,18 +10511,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.15.5", - "indexmap 2.14.0", - "semver 1.0.28", -] - [[package]] name = "wasmtimer" version = "0.4.3" @@ -10368,9 +10527,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.98" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -10388,9 +10547,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" dependencies = [ "rustls-pki-types", ] @@ -10438,7 +10597,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -10449,7 +10608,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -10493,7 +10652,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -10502,16 +10661,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -10529,31 +10679,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -10562,96 +10695,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.5.40" @@ -10679,100 +10764,12 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck 0.5.0", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck 0.5.0", - "indexmap 2.14.0", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.1", - "indexmap 2.14.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.14.0", - "log", - "semver 1.0.28", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -10790,9 +10787,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -10807,28 +10804,28 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -10848,28 +10845,28 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -10902,13 +10899,14 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] -name = "zkhash" +name = "zkhash-axiom" version = "0.2.0" -source = "git+https://github.com/HorizenLabs/poseidon2.git?rev=bb476b9#bb476b9ca38198cf5092487283c8b8c5d4317c4e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d038a7895d0e3ab0a352f53e7eb4f1f829f88fce2fb3cff93d665a8a0e01af6" dependencies = [ "ark-ff 0.4.2", "ark-std 0.4.0", diff --git a/Cargo.toml b/Cargo.toml index 3bd50a362a..0775ab855b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,9 @@ repository = "https://github.com/scroll-tech/scroll" version = "4.7.12" [workspace.dependencies] -scroll-zkvm-prover = { git = "https://github.com/scroll-tech/zkvm-prover", rev = "ed3b964" } -scroll-zkvm-verifier = { git = "https://github.com/scroll-tech/zkvm-prover", rev = "ed3b964" } -scroll-zkvm-types = { git = "https://github.com/scroll-tech/zkvm-prover", rev = "ed3b964" } +scroll-zkvm-prover = { git = "https://github.com/scroll-tech/zkvm-prover", tag = "v0.9.0" } +scroll-zkvm-verifier = { git = "https://github.com/scroll-tech/zkvm-prover", tag = "v0.9.0" } +scroll-zkvm-types = { git = "https://github.com/scroll-tech/zkvm-prover", tag = "v0.9.0" } sbv-primitives = { git = "https://github.com/scroll-tech/stateless-block-verifier", tag = "scroll-v91.2", features = ["scroll", "rkyv"] } sbv-utils = { git = "https://github.com/scroll-tech/stateless-block-verifier", tag = "scroll-v91.2" } diff --git a/common/types/message/message.go b/common/types/message/message.go index 7b35d362d8..a9b52f2809 100644 --- a/common/types/message/message.go +++ b/common/types/message/message.go @@ -165,9 +165,18 @@ type OpenVMProofStat struct { // Proof for flatten VM proof type OpenVMProof struct { - Proof []byte `json:"proofs"` - PublicValues []byte `json:"public_values"` - Stat *OpenVMProofStat `json:"stat,omitempty"` + Proof []byte `json:"proofs"` + PublicValues []byte `json:"public_values"` +} + +// Proof for flatten VM stark proof (v0.9.0+). +// Mirrors scroll_zkvm_types::proof::StarkProof used by the OpenVM v2 prover. +type OpenVMStarkProof struct { + Proof []byte `json:"proof"` + UserPvsProof []byte `json:"user_pvs_proof"` + Baseline []byte `json:"baseline,omitempty"` + DeferralMerkleProofs []byte `json:"deferral_merkle_proofs,omitempty"` + Stat *OpenVMProofStat `json:"stat,omitempty"` } // Proof for flatten EVM proof @@ -183,13 +192,13 @@ type OpenVMChunkProof struct { TotalGasUsed uint64 `json:"chunk_total_gas"` } `json:"metadata"` - VmProof *OpenVMProof `json:"proof"` - Vk []byte `json:"vk,omitempty"` - GitVersion string `json:"git_version,omitempty"` + StarkProof *OpenVMStarkProof `json:"proof"` + Vk []byte `json:"vk,omitempty"` + GitVersion string `json:"git_version,omitempty"` } func (p *OpenVMChunkProof) Proof() []byte { - proofJson, err := json.Marshal(p.VmProof) + proofJson, err := json.Marshal(p.StarkProof) if err != nil { panic(fmt.Sprint("marshaling error", err)) } @@ -217,13 +226,13 @@ type OpenVMBatchProof struct { BatchHash common.Hash `json:"batch_hash"` } `json:"metadata"` - VmProof *OpenVMProof `json:"proof"` - Vk []byte `json:"vk,omitempty"` - GitVersion string `json:"git_version,omitempty"` + StarkProof *OpenVMStarkProof `json:"proof"` + Vk []byte `json:"vk,omitempty"` + GitVersion string `json:"git_version,omitempty"` } func (p *OpenVMBatchProof) Proof() []byte { - proofJson, err := json.Marshal(p.VmProof) + proofJson, err := json.Marshal(p.StarkProof) if err != nil { panic(fmt.Sprint("marshaling error", err)) } @@ -240,17 +249,17 @@ func (ap *OpenVMBatchProof) SanityCheck() error { return errors.New("batch info not ready") } - if ap.VmProof == nil { + if ap.StarkProof == nil { return errors.New("proof not ready") } else { if len(ap.Vk) == 0 { return errors.New("vk not ready") } - pf := ap.VmProof - if pf.Proof == nil { + pf := ap.StarkProof + if len(pf.Proof) == 0 { return errors.New("proof data not ready") } - if len(pf.PublicValues) == 0 { + if len(pf.UserPvsProof) == 0 { return errors.New("proof public value not ready") } } diff --git a/coordinator/internal/controller/api/get_task.go b/coordinator/internal/controller/api/get_task.go index c430f45ee3..b8eb0a07a8 100644 --- a/coordinator/internal/controller/api/get_task.go +++ b/coordinator/internal/controller/api/get_task.go @@ -3,7 +3,7 @@ package api import ( "errors" "fmt" - "math/rand" + "sort" "github.com/gin-gonic/gin" "github.com/prometheus/client_golang/prometheus" @@ -79,7 +79,9 @@ func (ptc *GetTaskController) incGetTaskAccessCounter(ctx *gin.Context) error { return nil } -// GetTasks get assigned chunk/batch task +// GetTasks get assigned chunk/batch/bundle task, trying proof types in priority +// order: Bundle > Batch > Chunk. This lets the pipeline finalize the earliest +// ready bundle before proving unrelated chunks/batches further ahead. func (ptc *GetTaskController) GetTasks(ctx *gin.Context) { var getTaskParameter coordinatorType.GetTaskParameter if err := ctx.ShouldBind(&getTaskParameter); err != nil { @@ -99,35 +101,36 @@ func (ptc *GetTaskController) GetTasks(ctx *gin.Context) { } } - proofType := ptc.proofType(&getTaskParameter) - proverTask, isExist := ptc.proverTasks[proofType] - if !isExist { - nerr := fmt.Errorf("parameter wrong proof type:%v", proofType) - types.RenderFailure(ctx, types.ErrCoordinatorParameterInvalidNo, nerr) - return - } + proofTypes := ptc.prioritizedProofTypes(&getTaskParameter) if err := ptc.incGetTaskAccessCounter(ctx); err != nil { log.Warn("get_task access counter inc failed", "error", err.Error()) } - result, err := proverTask.Assign(ctx, &getTaskParameter) - if err != nil { - nerr := fmt.Errorf("return prover task err:%w", err) - types.RenderFailure(ctx, types.ErrCoordinatorGetTaskFailure, nerr) - return - } + for _, proofType := range proofTypes { + proverTask, isExist := ptc.proverTasks[proofType] + if !isExist { + continue + } - if result == nil { - nerr := errors.New("get empty prover task") - types.RenderFailure(ctx, types.ErrCoordinatorEmptyProofData, nerr) - return + result, err := proverTask.Assign(ctx, &getTaskParameter) + if err != nil { + nerr := fmt.Errorf("return prover task err:%w", err) + types.RenderFailure(ctx, types.ErrCoordinatorGetTaskFailure, nerr) + return + } + + if result != nil { + types.RenderSuccess(ctx, result) + return + } } - types.RenderSuccess(ctx, result) + nerr := errors.New("get empty prover task") + types.RenderFailure(ctx, types.ErrCoordinatorEmptyProofData, nerr) } -func (ptc *GetTaskController) proofType(para *coordinatorType.GetTaskParameter) message.ProofType { +func (ptc *GetTaskController) prioritizedProofTypes(para *coordinatorType.GetTaskParameter) []message.ProofType { var proofTypes []message.ProofType for _, proofType := range para.TaskTypes { proofTypes = append(proofTypes, message.ProofType(proofType)) @@ -141,8 +144,9 @@ func (ptc *GetTaskController) proofType(para *coordinatorType.GetTaskParameter) } } - rand.Shuffle(len(proofTypes), func(i, j int) { - proofTypes[i], proofTypes[j] = proofTypes[j], proofTypes[i] + // Bundle (3) > Batch (2) > Chunk (1) + sort.Slice(proofTypes, func(i, j int) bool { + return proofTypes[i] > proofTypes[j] }) - return proofTypes[0] + return proofTypes } diff --git a/coordinator/internal/logic/provertask/batch_prover_task.go b/coordinator/internal/logic/provertask/batch_prover_task.go index 964dba2618..90608cedff 100644 --- a/coordinator/internal/logic/provertask/batch_prover_task.go +++ b/coordinator/internal/logic/provertask/batch_prover_task.go @@ -199,7 +199,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato taskMsg, err := bp.formatProverTask(ctx.Copy(), proverTask, batchTask, hardForkName) if err != nil { - bp.recoverActiveAttempts(ctx, batchTask) + bp.recoverAttempts(ctx, taskCtx, batchTask) log.Error("format prover task failure", "task_id", batchTask.Hash, "err", err) return nil, ErrCoordinatorInternalFailure } @@ -208,7 +208,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato taskMsg, metadata, err = bp.applyUniversal(taskMsg) if err != nil { - bp.recoverActiveAttempts(ctx, batchTask) + bp.recoverAttempts(ctx, taskCtx, batchTask) log.Error("Generate universal prover task failure", "task_id", batchTask.Hash, "type", "batch", "err", err) return nil, ErrCoordinatorInternalFailure } @@ -217,7 +217,8 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato if isCompatibilityFixingVersion(taskCtx.ProverVersion) { log.Info("Apply compatibility fixing for prover", "version", taskCtx.ProverVersion) if err := fixCompatibility(taskMsg); err != nil { - log.Error("apply compatibility failure", "err", err) + bp.recoverAttempts(ctx, taskCtx, batchTask) + log.Error("apply compatibility failure", "task_id", batchTask.Hash, "err", err) return nil, ErrCoordinatorInternalFailure } } @@ -226,7 +227,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato // Store session info. if taskCtx.hasAssignedTask == nil { if err = bp.proverTaskOrm.InsertProverTask(ctx.Copy(), proverTask); err != nil { - bp.recoverActiveAttempts(ctx, batchTask) + bp.recoverAttempts(ctx, taskCtx, batchTask) log.Error("insert batch prover task info fail", "task_id", batchTask.Hash, "publicKey", taskCtx.PublicKey, "err", err) return nil, ErrCoordinatorInternalFailure } @@ -288,7 +289,17 @@ func (bp *BatchProverTask) formatProverTask(ctx context.Context, task *orm.Prove return taskMsg, nil } -func (bp *BatchProverTask) recoverActiveAttempts(ctx *gin.Context, batchTask *orm.Batch) { +// recoverAttempts rolls back the attempt charged by UpdateBatchAttempts when the coordinator +// fails to dispatch a freshly assigned task (hasAssignedTask == nil): both counters are refunded +// and proving_status is reset to unassigned. For a re-poll of an already assigned task nothing +// was charged in this call, so only active_attempts is decremented as before. +func (bp *BatchProverTask) recoverAttempts(ctx *gin.Context, taskCtx *proverTaskContext, batchTask *orm.Batch) { + if taskCtx.hasAssignedTask == nil { + if err := bp.batchOrm.RefundAttemptsByHash(ctx.Copy(), batchTask.Hash); err != nil { + log.Error("failed to refund batch attempts", "hash", batchTask.Hash, "error", err) + } + return + } if err := bp.batchOrm.DecreaseActiveAttemptsByHash(ctx.Copy(), batchTask.Hash); err != nil { log.Error("failed to recover batch active attempts", "hash", batchTask.Hash, "error", err) } diff --git a/coordinator/internal/logic/provertask/bundle_prover_task.go b/coordinator/internal/logic/provertask/bundle_prover_task.go index 81fddfd702..37ed669d5e 100644 --- a/coordinator/internal/logic/provertask/bundle_prover_task.go +++ b/coordinator/internal/logic/provertask/bundle_prover_task.go @@ -196,7 +196,7 @@ func (bp *BundleProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinat taskMsg, err := bp.formatProverTask(ctx.Copy(), proverTask, hardForkName) if err != nil { - bp.recoverActiveAttempts(ctx, bundleTask) + bp.recoverAttempts(ctx, taskCtx, bundleTask) log.Error("format bundle prover task failure", "task_id", bundleTask.Hash, "err", err) return nil, ErrCoordinatorInternalFailure } @@ -204,7 +204,7 @@ func (bp *BundleProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinat var metadata []byte taskMsg, metadata, err = bp.applyUniversal(taskMsg) if err != nil { - bp.recoverActiveAttempts(ctx, bundleTask) + bp.recoverAttempts(ctx, taskCtx, bundleTask) log.Error("Generate universal prover task failure", "task_id", bundleTask.Hash, "type", "bundle", "err", err) return nil, ErrCoordinatorInternalFailure } @@ -215,7 +215,8 @@ func (bp *BundleProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinat if isCompatibilityFixingVersion(taskCtx.ProverVersion) { log.Info("Apply compatibility fixing for prover", "version", taskCtx.ProverVersion) if err := fixCompatibility(taskMsg); err != nil { - log.Error("apply compatibility failure", "err", err) + bp.recoverAttempts(ctx, taskCtx, bundleTask) + log.Error("apply compatibility failure", "task_id", bundleTask.Hash, "err", err) return nil, ErrCoordinatorInternalFailure } } @@ -224,7 +225,7 @@ func (bp *BundleProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinat // Store session info. if taskCtx.hasAssignedTask == nil { if err = bp.proverTaskOrm.InsertProverTask(ctx.Copy(), proverTask); err != nil { - bp.recoverActiveAttempts(ctx, bundleTask) + bp.recoverAttempts(ctx, taskCtx, bundleTask) log.Error("insert bundle prover task info fail", "task_id", bundleTask.Hash, "publicKey", taskCtx.PublicKey, "err", err) return nil, ErrCoordinatorInternalFailure } @@ -313,7 +314,17 @@ func (bp *BundleProverTask) formatProverTask(ctx context.Context, task *orm.Prov return taskMsg, nil } -func (bp *BundleProverTask) recoverActiveAttempts(ctx *gin.Context, bundleTask *orm.Bundle) { +// recoverAttempts rolls back the attempt charged by UpdateBundleAttempts when the coordinator +// fails to dispatch a freshly assigned task (hasAssignedTask == nil): both counters are refunded +// and proving_status is reset to unassigned. For a re-poll of an already assigned task nothing +// was charged in this call, so only active_attempts is decremented as before. +func (bp *BundleProverTask) recoverAttempts(ctx *gin.Context, taskCtx *proverTaskContext, bundleTask *orm.Bundle) { + if taskCtx.hasAssignedTask == nil { + if err := bp.bundleOrm.RefundAttemptsByHash(ctx.Copy(), bundleTask.Hash); err != nil { + log.Error("failed to refund bundle attempts", "hash", bundleTask.Hash, "error", err) + } + return + } if err := bp.bundleOrm.DecreaseActiveAttemptsByHash(ctx.Copy(), bundleTask.Hash); err != nil { log.Error("failed to recover bundle active attempts", "hash", bundleTask.Hash, "error", err) } diff --git a/coordinator/internal/logic/provertask/chunk_prover_task.go b/coordinator/internal/logic/provertask/chunk_prover_task.go index 6492c10a10..0987c0517b 100644 --- a/coordinator/internal/logic/provertask/chunk_prover_task.go +++ b/coordinator/internal/logic/provertask/chunk_prover_task.go @@ -194,7 +194,7 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato taskMsg, err := cp.formatProverTask(ctx.Copy(), proverTask, chunkTask, hardForkName) if err != nil { - cp.recoverActiveAttempts(ctx, chunkTask) + cp.recoverAttempts(ctx, taskCtx, chunkTask) log.Error("format prover task failure", "task_id", chunkTask.Hash, "err", err) return nil, ErrCoordinatorInternalFailure } @@ -203,7 +203,7 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato var metadata []byte taskMsg, metadata, err = cp.applyUniversal(taskMsg) if err != nil { - cp.recoverActiveAttempts(ctx, chunkTask) + cp.recoverAttempts(ctx, taskCtx, chunkTask) log.Error("Generate universal prover task failure", "task_id", chunkTask.Hash, "type", "chunk", "err", err) return nil, ErrCoordinatorInternalFailure } @@ -212,7 +212,7 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato if taskCtx.hasAssignedTask == nil { if err = cp.proverTaskOrm.InsertProverTask(ctx.Copy(), proverTask); err != nil { - cp.recoverActiveAttempts(ctx, chunkTask) + cp.recoverAttempts(ctx, taskCtx, chunkTask) log.Error("insert chunk prover task fail", "task_id", chunkTask.Hash, "publicKey", taskCtx.PublicKey, "err", err) return nil, ErrCoordinatorInternalFailure } @@ -269,7 +269,17 @@ func (cp *ChunkProverTask) formatProverTask(ctx context.Context, task *orm.Prove return proverTaskSchema, nil } -func (cp *ChunkProverTask) recoverActiveAttempts(ctx *gin.Context, chunkTask *orm.Chunk) { +// recoverAttempts rolls back the attempt charged by UpdateChunkAttempts when the coordinator +// fails to dispatch a freshly assigned task (hasAssignedTask == nil): both counters are refunded +// and proving_status is reset to unassigned. For a re-poll of an already assigned task nothing +// was charged in this call, so only active_attempts is decremented as before. +func (cp *ChunkProverTask) recoverAttempts(ctx *gin.Context, taskCtx *proverTaskContext, chunkTask *orm.Chunk) { + if taskCtx.hasAssignedTask == nil { + if err := cp.chunkOrm.RefundAttemptsByHash(ctx, chunkTask.Hash); err != nil { + log.Error("failed to refund chunk attempts", "hash", chunkTask.Hash, "error", err) + } + return + } if err := cp.chunkOrm.DecreaseActiveAttemptsByHash(ctx, chunkTask.Hash); err != nil { log.Error("failed to recover chunk active attempts", "hash", chunkTask.Hash, "error", err) } diff --git a/coordinator/internal/logic/submitproof/proof_receiver.go b/coordinator/internal/logic/submitproof/proof_receiver.go index e9d4c5abe5..5c4b51d03f 100644 --- a/coordinator/internal/logic/submitproof/proof_receiver.go +++ b/coordinator/internal/logic/submitproof/proof_receiver.go @@ -232,7 +232,7 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor return unmarshalErr } success, verifyErr = m.verifier.VerifyChunkProof(chunkProof, hardForkName) - if stat := chunkProof.VmProof.Stat; stat != nil { + if stat := chunkProof.StarkProof.Stat; stat != nil { if g, _ := m.proverSpeed.GetMetricWithLabelValues("chunk", "exec"); g != nil && stat.ExecutionTimeMills > 0 { g.Set(float64(stat.TotalCycle) / float64(stat.ExecutionTimeMills*1000)) } @@ -252,7 +252,7 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor return unmarshalErr } success, verifyErr = m.verifier.VerifyBatchProof(batchProof, hardForkName) - if stat := batchProof.VmProof.Stat; stat != nil { + if stat := batchProof.StarkProof.Stat; stat != nil { if g, _ := m.proverSpeed.GetMetricWithLabelValues("batch", "exec"); g != nil && stat.ExecutionTimeMills > 0 { g.Set(float64(stat.TotalCycle) / float64(stat.ExecutionTimeMills*1000)) } diff --git a/coordinator/internal/logic/verifier/mock.go b/coordinator/internal/logic/verifier/mock.go index a79ed8d8fc..9e602aa44f 100644 --- a/coordinator/internal/logic/verifier/mock.go +++ b/coordinator/internal/logic/verifier/mock.go @@ -21,7 +21,7 @@ func NewVerifier(cfg *config.VerifierConfig, _ bool) (*Verifier, error) { // VerifyChunkProof return a mock verification result for a ChunkProof. func (v *Verifier) VerifyChunkProof(proof *message.OpenVMChunkProof, forkName string) (bool, error) { - if proof.VmProof != nil && string(proof.VmProof.Proof) == InvalidTestProof { + if proof.StarkProof != nil && string(proof.StarkProof.Proof) == InvalidTestProof { return false, nil } return true, nil @@ -29,7 +29,7 @@ func (v *Verifier) VerifyChunkProof(proof *message.OpenVMChunkProof, forkName st // VerifyBatchProof return a mock verification result for a BatchProof. func (v *Verifier) VerifyBatchProof(proof *message.OpenVMBatchProof, forkName string) (bool, error) { - if proof.VmProof != nil && string(proof.VmProof.Proof) == InvalidTestProof { + if proof.StarkProof != nil && string(proof.StarkProof.Proof) == InvalidTestProof { return false, nil } return true, nil diff --git a/coordinator/internal/orm/batch.go b/coordinator/internal/orm/batch.go index 51e904a016..72bdae6d2c 100644 --- a/coordinator/internal/orm/batch.go +++ b/coordinator/internal/orm/batch.go @@ -211,13 +211,25 @@ func (o *Batch) GetAttemptsByHash(ctx context.Context, hash string) (int16, int1 func (o *Batch) CheckIfBundleBatchProofsAreReady(ctx context.Context, bundleHash string) (bool, error) { db := o.db.WithContext(ctx) db = db.Model(&Batch{}) + db = db.Where("bundle_hash = ?", bundleHash) + + var totalCount int64 + if err := db.Count(&totalCount).Error; err != nil { + return false, fmt.Errorf("Batch.CheckIfBundleBatchProofsAreReady error: %w, bundle hash: %v", err, bundleHash) + } + if totalCount == 0 { + return false, nil + } + + db = o.db.WithContext(ctx) + db = db.Model(&Batch{}) db = db.Where("bundle_hash = ? AND proving_status != ?", bundleHash, types.ProvingTaskVerified) - var count int64 - if err := db.Count(&count).Error; err != nil { - return false, fmt.Errorf("Chunk.CheckIfBundleBatchProofsAreReady error: %w, bundle hash: %v", err, bundleHash) + var unreadyCount int64 + if err := db.Count(&unreadyCount).Error; err != nil { + return false, fmt.Errorf("Batch.CheckIfBundleBatchProofsAreReady error: %w, bundle hash: %v", err, bundleHash) } - return count == 0, nil + return unreadyCount == 0, nil } // GetBatchByHash retrieves the given batch. @@ -459,3 +471,32 @@ func (o *Batch) DecreaseActiveAttemptsByHash(ctx context.Context, batchHash stri } return nil } + +// RefundAttemptsByHash refunds a full assignment attempt of a batch given its hash: +// it decrements both total_attempts and active_attempts and resets proving_status to unassigned. +// It is used to roll back UpdateBatchAttempts when the coordinator fails to dispatch the task +// (e.g. task formatting or prover task insertion failure), so the attempt is not burned permanently. +func (o *Batch) RefundAttemptsByHash(ctx context.Context, batchHash string, dbTX ...*gorm.DB) error { + db := o.db + if len(dbTX) > 0 && dbTX[0] != nil { + db = dbTX[0] + } + db = db.WithContext(ctx) + db = db.Model(&Batch{}) + db = db.Where("hash = ?", batchHash) + db = db.Where("total_attempts > ?", 0) + db = db.Where("active_attempts > ?", 0) + db = db.Where("proving_status != ?", int(types.ProvingTaskVerified)) + result := db.Updates(map[string]interface{}{ + "total_attempts": gorm.Expr("total_attempts - 1"), + "active_attempts": gorm.Expr("active_attempts - 1"), + "proving_status": int(types.ProvingTaskUnassigned), + }) + if result.Error != nil { + return fmt.Errorf("Batch.RefundAttemptsByHash error: %w, batch hash: %v", result.Error, batchHash) + } + if result.RowsAffected == 0 { + log.Warn("No rows were affected in RefundAttemptsByHash", "batch hash", batchHash) + } + return nil +} diff --git a/coordinator/internal/orm/bundle.go b/coordinator/internal/orm/bundle.go index 4e4e22ea17..acd6793ec3 100644 --- a/coordinator/internal/orm/bundle.go +++ b/coordinator/internal/orm/bundle.go @@ -243,3 +243,32 @@ func (o *Bundle) DecreaseActiveAttemptsByHash(ctx context.Context, bundleHash st } return nil } + +// RefundAttemptsByHash refunds a full assignment attempt of a bundle given its hash: +// it decrements both total_attempts and active_attempts and resets proving_status to unassigned. +// It is used to roll back UpdateBundleAttempts when the coordinator fails to dispatch the task +// (e.g. task formatting or prover task insertion failure), so the attempt is not burned permanently. +func (o *Bundle) RefundAttemptsByHash(ctx context.Context, bundleHash string, dbTX ...*gorm.DB) error { + db := o.db + if len(dbTX) > 0 && dbTX[0] != nil { + db = dbTX[0] + } + db = db.WithContext(ctx) + db = db.Model(&Bundle{}) + db = db.Where("hash = ?", bundleHash) + db = db.Where("total_attempts > ?", 0) + db = db.Where("active_attempts > ?", 0) + db = db.Where("proving_status != ?", int(types.ProvingTaskVerified)) + result := db.Updates(map[string]interface{}{ + "total_attempts": gorm.Expr("total_attempts - 1"), + "active_attempts": gorm.Expr("active_attempts - 1"), + "proving_status": int(types.ProvingTaskUnassigned), + }) + if result.Error != nil { + return fmt.Errorf("Bundle.RefundAttemptsByHash error: %w, bundle hash: %v", result.Error, bundleHash) + } + if result.RowsAffected == 0 { + log.Warn("No rows were affected in RefundAttemptsByHash", "bundle hash", bundleHash) + } + return nil +} diff --git a/coordinator/internal/orm/chunk.go b/coordinator/internal/orm/chunk.go index cfefa2ea6c..6faa552887 100644 --- a/coordinator/internal/orm/chunk.go +++ b/coordinator/internal/orm/chunk.go @@ -171,13 +171,25 @@ func (o *Chunk) GetProvingStatusByHash(ctx context.Context, hash string) (types. func (o *Chunk) CheckIfBatchChunkProofsAreReady(ctx context.Context, batchHash string) (bool, error) { db := o.db.WithContext(ctx) db = db.Model(&Chunk{}) + db = db.Where("batch_hash = ?", batchHash) + + var totalCount int64 + if err := db.Count(&totalCount).Error; err != nil { + return false, fmt.Errorf("Chunk.CheckIfBatchChunkProofsAreReady error: %w, batch hash: %v", err, batchHash) + } + if totalCount == 0 { + return false, nil + } + + db = o.db.WithContext(ctx) + db = db.Model(&Chunk{}) db = db.Where("batch_hash = ? AND proving_status != ?", batchHash, types.ProvingTaskVerified) - var count int64 - if err := db.Count(&count).Error; err != nil { + var unreadyCount int64 + if err := db.Count(&unreadyCount).Error; err != nil { return false, fmt.Errorf("Chunk.CheckIfBatchChunkProofsAreReady error: %w, batch hash: %v", err, batchHash) } - return count == 0, nil + return unreadyCount == 0, nil } // GetChunkByHash retrieves the given chunk. @@ -410,3 +422,32 @@ func (o *Chunk) DecreaseActiveAttemptsByHash(ctx context.Context, chunkHash stri } return nil } + +// RefundAttemptsByHash refunds a full assignment attempt of a chunk given its hash: +// it decrements both total_attempts and active_attempts and resets proving_status to unassigned. +// It is used to roll back UpdateChunkAttempts when the coordinator fails to dispatch the task +// (e.g. task formatting or prover task insertion failure), so the attempt is not burned permanently. +func (o *Chunk) RefundAttemptsByHash(ctx context.Context, chunkHash string, dbTX ...*gorm.DB) error { + db := o.db + if len(dbTX) > 0 && dbTX[0] != nil { + db = dbTX[0] + } + db = db.WithContext(ctx) + db = db.Model(&Chunk{}) + db = db.Where("hash = ?", chunkHash) + db = db.Where("total_attempts > ?", 0) + db = db.Where("active_attempts > ?", 0) + db = db.Where("proving_status != ?", int(types.ProvingTaskVerified)) + result := db.Updates(map[string]interface{}{ + "total_attempts": gorm.Expr("total_attempts - 1"), + "active_attempts": gorm.Expr("active_attempts - 1"), + "proving_status": int(types.ProvingTaskUnassigned), + }) + if result.Error != nil { + return fmt.Errorf("Chunk.RefundAttemptsByHash error: %w, chunk hash: %v", result.Error, chunkHash) + } + if result.RowsAffected == 0 { + log.Warn("No rows were affected in RefundAttemptsByHash", "chunk hash", chunkHash) + } + return nil +} diff --git a/coordinator/internal/orm/orm_test.go b/coordinator/internal/orm/orm_test.go index a653237edf..b63668f03b 100644 --- a/coordinator/internal/orm/orm_test.go +++ b/coordinator/internal/orm/orm_test.go @@ -121,3 +121,183 @@ func TestProverTaskOrmUint256(t *testing.T) { assert.Equal(t, resultRewardUint256, rewardUint256) assert.Equal(t, resultRewardUint256.String(), "115792089237316195423570985008687907853269984665640564039457584007913129639935") } + +func TestChunkRefundAttemptsByHash(t *testing.T) { + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + + chunkOrm := NewChunk(db) + insertChunk := func(index uint64, hash string, provingStatus, totalAttempts, activeAttempts int16) { + execErr := db.Exec(`INSERT INTO chunk (index, hash, start_block_number, start_block_hash, end_block_number, end_block_hash, + total_l1_messages_popped_before, total_l1_messages_popped_in_chunk, start_block_time, parent_chunk_hash, state_root, + parent_chunk_state_root, withdraw_root, total_l2_tx_gas, total_l2_tx_num, total_l1_commit_calldata_size, total_l1_commit_gas, + proving_status, total_attempts, active_attempts) + VALUES (?, ?, 1, '0x1', 2, '0x2', 0, 0, 0, '0x0', '0x3', '0x0', '0x4', 0, 0, 0, 0, ?, ?, ?)`, + index, hash, provingStatus, totalAttempts, activeAttempts).Error + assert.NoError(t, execErr) + } + + // (a) charge via UpdateChunkAttempts then refund -> both counters back to 0, status back to unassigned + insertChunk(1, "0xchunk-a", int16(types.ProvingTaskUnassigned), 0, 0) + rowsAffected, err := chunkOrm.UpdateChunkAttempts(context.Background(), 1, 0, 0) + assert.NoError(t, err) + assert.Equal(t, int64(1), rowsAffected) + active, total, err := chunkOrm.GetAttemptsByHash(context.Background(), "0xchunk-a") + assert.NoError(t, err) + assert.Equal(t, int16(1), active) + assert.Equal(t, int16(1), total) + status, err := chunkOrm.GetProvingStatusByHash(context.Background(), "0xchunk-a") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskAssigned, status) + + assert.NoError(t, chunkOrm.RefundAttemptsByHash(context.Background(), "0xchunk-a")) + active, total, err = chunkOrm.GetAttemptsByHash(context.Background(), "0xchunk-a") + assert.NoError(t, err) + assert.Equal(t, int16(0), active) + assert.Equal(t, int16(0), total) + status, err = chunkOrm.GetProvingStatusByHash(context.Background(), "0xchunk-a") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskUnassigned, status) + + // (b) refund on a verified row -> no-op + insertChunk(2, "0xchunk-b", int16(types.ProvingTaskVerified), 1, 1) + assert.NoError(t, chunkOrm.RefundAttemptsByHash(context.Background(), "0xchunk-b")) + active, total, err = chunkOrm.GetAttemptsByHash(context.Background(), "0xchunk-b") + assert.NoError(t, err) + assert.Equal(t, int16(1), active) + assert.Equal(t, int16(1), total) + status, err = chunkOrm.GetProvingStatusByHash(context.Background(), "0xchunk-b") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskVerified, status) + + // (c) refund when attempts are already 0 -> no underflow, row unchanged + insertChunk(3, "0xchunk-c", int16(types.ProvingTaskAssigned), 0, 0) + assert.NoError(t, chunkOrm.RefundAttemptsByHash(context.Background(), "0xchunk-c")) + active, total, err = chunkOrm.GetAttemptsByHash(context.Background(), "0xchunk-c") + assert.NoError(t, err) + assert.Equal(t, int16(0), active) + assert.Equal(t, int16(0), total) + status, err = chunkOrm.GetProvingStatusByHash(context.Background(), "0xchunk-c") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskAssigned, status) +} + +func TestBatchRefundAttemptsByHash(t *testing.T) { + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + + batchOrm := NewBatch(db) + insertBatch := func(index uint64, hash string, provingStatus, totalAttempts, activeAttempts int16) { + execErr := db.Exec(`INSERT INTO batch (index, hash, start_chunk_index, start_chunk_hash, end_chunk_index, end_chunk_hash, + state_root, withdraw_root, parent_batch_hash, batch_header, proving_status, total_attempts, active_attempts) + VALUES (?, ?, 1, '0x1', 2, '0x2', '0x3', '0x4', '0x0', ?, ?, ?, ?)`, + index, hash, []byte{0}, provingStatus, totalAttempts, activeAttempts).Error + assert.NoError(t, execErr) + } + + // (a) charge via UpdateBatchAttempts then refund -> both counters back to 0, status back to unassigned + insertBatch(1, "0xbatch-a", int16(types.ProvingTaskUnassigned), 0, 0) + rowsAffected, err := batchOrm.UpdateBatchAttempts(context.Background(), 1, 0, 0) + assert.NoError(t, err) + assert.Equal(t, int64(1), rowsAffected) + active, total, err := batchOrm.GetAttemptsByHash(context.Background(), "0xbatch-a") + assert.NoError(t, err) + assert.Equal(t, int16(1), active) + assert.Equal(t, int16(1), total) + status, err := batchOrm.GetProvingStatusByHash(context.Background(), "0xbatch-a") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskAssigned, status) + + assert.NoError(t, batchOrm.RefundAttemptsByHash(context.Background(), "0xbatch-a")) + active, total, err = batchOrm.GetAttemptsByHash(context.Background(), "0xbatch-a") + assert.NoError(t, err) + assert.Equal(t, int16(0), active) + assert.Equal(t, int16(0), total) + status, err = batchOrm.GetProvingStatusByHash(context.Background(), "0xbatch-a") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskUnassigned, status) + + // (b) refund on a verified row -> no-op + insertBatch(2, "0xbatch-b", int16(types.ProvingTaskVerified), 1, 1) + assert.NoError(t, batchOrm.RefundAttemptsByHash(context.Background(), "0xbatch-b")) + active, total, err = batchOrm.GetAttemptsByHash(context.Background(), "0xbatch-b") + assert.NoError(t, err) + assert.Equal(t, int16(1), active) + assert.Equal(t, int16(1), total) + status, err = batchOrm.GetProvingStatusByHash(context.Background(), "0xbatch-b") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskVerified, status) + + // (c) refund when attempts are already 0 -> no underflow, row unchanged + insertBatch(3, "0xbatch-c", int16(types.ProvingTaskAssigned), 0, 0) + assert.NoError(t, batchOrm.RefundAttemptsByHash(context.Background(), "0xbatch-c")) + active, total, err = batchOrm.GetAttemptsByHash(context.Background(), "0xbatch-c") + assert.NoError(t, err) + assert.Equal(t, int16(0), active) + assert.Equal(t, int16(0), total) + status, err = batchOrm.GetProvingStatusByHash(context.Background(), "0xbatch-c") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskAssigned, status) +} + +func TestBundleRefundAttemptsByHash(t *testing.T) { + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + + bundleOrm := NewBundle(db) + insertBundle := func(hash string, provingStatus, totalAttempts, activeAttempts int16) { + execErr := db.Exec(`INSERT INTO bundle (hash, start_batch_index, end_batch_index, start_batch_hash, end_batch_hash, + codec_version, proving_status, total_attempts, active_attempts) + VALUES (?, 1, 2, '0x1', '0x2', 10, ?, ?, ?)`, + hash, provingStatus, totalAttempts, activeAttempts).Error + assert.NoError(t, execErr) + } + getAttempts := func(hash string) (int16, int16) { + bundle, getErr := bundleOrm.GetBundleByHash(context.Background(), hash) + assert.NoError(t, getErr) + return bundle.ActiveAttempts, bundle.TotalAttempts + } + + // (a) charge via UpdateBundleAttempts then refund -> both counters back to 0, status back to unassigned + insertBundle("0xbundle-a", int16(types.ProvingTaskUnassigned), 0, 0) + rowsAffected, err := bundleOrm.UpdateBundleAttempts(context.Background(), "0xbundle-a", 0, 0) + assert.NoError(t, err) + assert.Equal(t, int64(1), rowsAffected) + active, total := getAttempts("0xbundle-a") + assert.Equal(t, int16(1), active) + assert.Equal(t, int16(1), total) + status, err := bundleOrm.GetProvingStatusByHash(context.Background(), "0xbundle-a") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskAssigned, status) + + assert.NoError(t, bundleOrm.RefundAttemptsByHash(context.Background(), "0xbundle-a")) + active, total = getAttempts("0xbundle-a") + assert.Equal(t, int16(0), active) + assert.Equal(t, int16(0), total) + status, err = bundleOrm.GetProvingStatusByHash(context.Background(), "0xbundle-a") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskUnassigned, status) + + // (b) refund on a verified row -> no-op + insertBundle("0xbundle-b", int16(types.ProvingTaskVerified), 1, 1) + assert.NoError(t, bundleOrm.RefundAttemptsByHash(context.Background(), "0xbundle-b")) + active, total = getAttempts("0xbundle-b") + assert.Equal(t, int16(1), active) + assert.Equal(t, int16(1), total) + status, err = bundleOrm.GetProvingStatusByHash(context.Background(), "0xbundle-b") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskVerified, status) + + // (c) refund when attempts are already 0 -> no underflow, row unchanged + insertBundle("0xbundle-c", int16(types.ProvingTaskAssigned), 0, 0) + assert.NoError(t, bundleOrm.RefundAttemptsByHash(context.Background(), "0xbundle-c")) + active, total = getAttempts("0xbundle-c") + assert.Equal(t, int16(0), active) + assert.Equal(t, int16(0), total) + status, err = bundleOrm.GetProvingStatusByHash(context.Background(), "0xbundle-c") + assert.NoError(t, err) + assert.Equal(t, types.ProvingTaskAssigned, status) +} diff --git a/coordinator/test/api_test.go b/coordinator/test/api_test.go index 9fc303d760..68ad38f392 100644 --- a/coordinator/test/api_test.go +++ b/coordinator/test/api_test.go @@ -687,7 +687,7 @@ func testTimeoutProof(t *testing.T) { assert.NoError(t, err) err = chunkOrm.UpdateBatchHashInRange(context.Background(), 0, 100, batch.Hash) assert.NoError(t, err) - encodeData, err := json.Marshal(message.OpenVMChunkProof{VmProof: &message.OpenVMProof{}, MetaData: struct { + encodeData, err := json.Marshal(message.OpenVMChunkProof{StarkProof: &message.OpenVMStarkProof{}, MetaData: struct { ChunkInfo *message.ChunkInfo `json:"chunk_info"` TotalGasUsed uint64 `json:"chunk_total_gas"` }{ChunkInfo: &message.ChunkInfo{}}}) diff --git a/coordinator/test/mock_prover.go b/coordinator/test/mock_prover.go index 913344e856..d2c29946ec 100644 --- a/coordinator/test/mock_prover.go +++ b/coordinator/test/mock_prover.go @@ -229,7 +229,7 @@ func (r *mockProver) submitProof(t *testing.T, proverTaskSchema *types.GetTaskSc case message.ProofTypeChunk: fallthrough case message.ProofTypeBatch: - encodeData, err := json.Marshal(&message.OpenVMProof{}) + encodeData, err := json.Marshal(&message.OpenVMStarkProof{}) assert.NoError(t, err) assert.NotEmpty(t, encodeData) proof = encodeData @@ -245,7 +245,7 @@ func (r *mockProver) submitProof(t *testing.T, proverTaskSchema *types.GetTaskSc case message.ProofTypeChunk: fallthrough case message.ProofTypeBatch: - encodeData, err := json.Marshal(&message.OpenVMProof{Proof: []byte(verifier.InvalidTestProof)}) + encodeData, err := json.Marshal(&message.OpenVMStarkProof{Proof: []byte(verifier.InvalidTestProof), UserPvsProof: []byte{0x01}}) assert.NoError(t, err) assert.NotEmpty(t, encodeData) proof = encodeData diff --git a/crates/libzkp/Cargo.toml b/crates/libzkp/Cargo.toml index d673efc9f0..abafd17a2b 100644 --- a/crates/libzkp/Cargo.toml +++ b/crates/libzkp/Cargo.toml @@ -7,6 +7,8 @@ edition.workspace = true [dependencies] scroll-zkvm-types = { workspace = true, features = ["scroll"] } scroll-zkvm-verifier.workspace = true +openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } +openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v2.0.0" } alloy-primitives.workspace = true #depress the effect of "native-keccak" sbv-primitives = {workspace = true, features = ["scroll-compress-info", "scroll"]} diff --git a/crates/libzkp/src/lib.rs b/crates/libzkp/src/lib.rs index f808cf7cad..8351b8723a 100644 --- a/crates/libzkp/src/lib.rs +++ b/crates/libzkp/src/lib.rs @@ -55,43 +55,8 @@ pub fn checkout_chunk_task( /// Convert the universal task json into compatible form for old prover pub fn univ_task_compatibility_fix(task_json: &str) -> eyre::Result { - use scroll_zkvm_types::proof::VmInternalStarkProof; - - let task: tasks::ProvingTask = serde_json::from_str(task_json)?; - let aggregated_proofs: Vec = task - .aggregated_proofs - .into_iter() - .map(|proof| VmInternalStarkProof { - proofs: proof.proofs, - public_values: proof.public_values, - }) - .collect(); - - #[derive(Serialize)] - struct CompatibleProvingTask { - /// seralized witness which should be written into stdin first - pub serialized_witness: Vec>, - /// aggregated proof carried by babybear fields, should be written into stdin - /// followed `serialized_witness` - pub aggregated_proofs: Vec, - /// Fork name specify - pub fork_name: String, - /// The vk of app which is expcted to prove this task - pub vk: Vec, - /// An identifier assigned by coordinator, it should be kept identify for the - /// same task (for example, using chunk, batch and bundle hashes) - pub identifier: String, - } - - let compatible_u_task = CompatibleProvingTask { - serialized_witness: task.serialized_witness, - aggregated_proofs, - fork_name: task.fork_name, - vk: task.vk, - identifier: task.identifier, - }; - - Ok(serde_json::to_string(&compatible_u_task)?) + // v0.9.0+ provers consume the new ProvingTask format directly; no translation needed. + Ok(task_json.to_string()) } /// Generate required staff for proving tasks diff --git a/crates/libzkp/src/tasks/batch.rs b/crates/libzkp/src/tasks/batch.rs index 9d36d1f01f..46ba7cd516 100644 --- a/crates/libzkp/src/tasks/batch.rs +++ b/crates/libzkp/src/tasks/batch.rs @@ -131,6 +131,7 @@ impl BatchProvingTask { .collect(), serialized_witness: vec![serialized_witness], vk: Vec::new(), + input_commits: Vec::new(), }; Ok((proving_task, metadata, batch_pi_hash)) diff --git a/crates/libzkp/src/tasks/bundle.rs b/crates/libzkp/src/tasks/bundle.rs index e1b9aca6a0..abd75aef11 100644 --- a/crates/libzkp/src/tasks/bundle.rs +++ b/crates/libzkp/src/tasks/bundle.rs @@ -38,6 +38,7 @@ impl BundleProvingTask { .collect(), serialized_witness: vec![serialized_witness], vk: Vec::new(), + input_commits: Vec::new(), }; Ok((proving_task, bundle_info, bundle_pi_hash)) diff --git a/crates/libzkp/src/tasks/chunk.rs b/crates/libzkp/src/tasks/chunk.rs index 863f080bef..5cf8059403 100644 --- a/crates/libzkp/src/tasks/chunk.rs +++ b/crates/libzkp/src/tasks/chunk.rs @@ -124,6 +124,7 @@ impl ChunkProvingTask { aggregated_proofs: Vec::new(), serialized_witness: vec![serialized_witness], vk: Vec::new(), + input_commits: Vec::new(), }; Ok((proving_task, chunk_info, chunk_pi_hash)) diff --git a/crates/libzkp/src/verifier/universal.rs b/crates/libzkp/src/verifier/universal.rs index e50fe16f40..b9e8c0c9f6 100644 --- a/crates/libzkp/src/verifier/universal.rs +++ b/crates/libzkp/src/verifier/universal.rs @@ -6,12 +6,16 @@ use crate::{ proofs::{AsRootProof, BatchProof, BundleProof, ChunkProof, IntoEvmProof}, utils::panic_catch, }; +use openvm_sdk::SC; use scroll_zkvm_types::version::Version; use scroll_zkvm_verifier::verifier::UniversalVerifier; use std::path::Path; pub struct Verifier { verifier: UniversalVerifier, + /// Deferral-enabled root verifier VK for batch proofs (v0.9.0+). + /// Loaded from `batch_root_verifier_vk` if present in the assets directory. + batch_mvk: Option>, version: Version, } @@ -19,8 +23,22 @@ impl Verifier { pub fn new(assets_dir: &str, ver_n: u8) -> Self { let verifier_bin = Path::new(assets_dir); + let verifier = + UniversalVerifier::setup(verifier_bin).expect("Setting up universal verifier"); + + let batch_mvk_path = verifier_bin.join("batch_root_verifier_vk"); + let batch_mvk = if batch_mvk_path.exists() { + Some( + openvm_sdk::fs::read_object_from_file(&batch_mvk_path) + .expect("Reading batch root verifier vk"), + ) + } else { + None + }; + Self { - verifier: UniversalVerifier::setup(verifier_bin).expect("Setting up chunk verifier"), + verifier, + batch_mvk, version: Version::from(ver_n), } } @@ -39,16 +57,23 @@ impl ProofVerifier for Verifier { TaskType::Batch => { let proof = serde_json::from_slice::(proof).unwrap(); assert!(proof.pi_hash_check(self.version)); - self.verifier - .verify_stark_proof(proof.as_root_proof(), &proof.vk) - .unwrap() + let mvk = self + .batch_mvk + .as_ref() + .expect("batch_root_verifier_vk missing from assets"); + UniversalVerifier::verify_stark_proof_with_vk( + mvk, + proof.as_root_proof(), + &proof.vk, + ) + .unwrap() } TaskType::Bundle => { let proof = serde_json::from_slice::(proof).unwrap(); assert!(proof.pi_hash_check(self.version)); let vk = proof.vk.clone(); let evm_proof = proof.into_evm_proof(); - self.verifier.verify_evm_proof(&evm_proof, &vk).unwrap() + self.verifier.verify_evm_proof(&evm_proof, &vk).unwrap(); } }) .map(|_| true) diff --git a/crates/prover-bin/Cargo.toml b/crates/prover-bin/Cargo.toml index 6fd6d94a65..dbeef08880 100644 --- a/crates/prover-bin/Cargo.toml +++ b/crates/prover-bin/Cargo.toml @@ -23,6 +23,14 @@ futures-util = "0.3" reqwest = { version = "0.12", features = ["gzip", "stream"] } hex = "0.4.3" +# OpenVM v2+ deferred STARK verification helpers for batch/bundle proving. +openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } +openvm-continuations = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } +openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } +openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v2.0.0" } +openvm-verify-stark-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } +openvm-verify-stark-host = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } + rand = "0.8.5" tokio = "1.37.0" async-trait = "0.1" diff --git a/crates/prover-bin/src/deferral.rs b/crates/prover-bin/src/deferral.rs new file mode 100644 index 0000000000..a0aa1fc4ef --- /dev/null +++ b/crates/prover-bin/src/deferral.rs @@ -0,0 +1,110 @@ +use eyre::Result; +use openvm_circuit::system::memory::merkle::public_values::UserPublicValuesProof; +use openvm_sdk::SC; +use openvm_stark_sdk::openvm_stark_backend::{codec::Decode, proof::Proof}; +use openvm_verify_stark_host::{ + deferral::DeferralMerkleProofs, + vk::{VerificationBaseline, VmStarkVerifyingKey}, + VmStarkProof, +}; +use openvm_sdk::DeferralInput; +use scroll_zkvm_types::proof::StarkProof; +use std::io::Cursor; + +/// Compute deferred STARK verification data required by OpenVM v2+ aggregation circuits. +/// +/// For batch/bundle proving the guest reads `input_commits` from stdin and the host must +/// additionally supply `DeferralInput`s and `DeferralState`s to the SDK prover. This function +/// derives all three from the child STARK proofs, the child aggregation VK and the parent's +/// deferral cached commit. +pub fn compute_deferral_data( + child_agg_vk: &openvm_stark_sdk::openvm_stark_backend::keygen::types::MultiStarkVerifyingKey, + parent_deferral_cached_commit: openvm_continuations::CommitBytes, + proofs: &[&StarkProof], +) -> Result<(Vec<[u8; 32]>, Vec, Vec)> { + let mvk = (*child_agg_vk).clone(); + + let (vm_proofs, baselines): (Vec, Vec) = proofs + .iter() + .map(|p| decode_stark_proof(p)) + .collect::>>()? + .into_iter() + .unzip(); + + let baseline = baselines + .first() + .cloned() + .ok_or_else(|| eyre::eyre!("no child proofs to compute deferral data"))?; + for (i, b) in baselines.iter().enumerate().skip(1) { + if b.app_exe_commit != baseline.app_exe_commit || b.app_vk_commit != baseline.app_vk_commit + { + eyre::bail!( + "child proof {i} has a different verification baseline; all child proofs must use the same app exe/vk commitment" + ); + } + } + + let vk = VmStarkVerifyingKey { mvk, baseline }; + + let cached_commit: openvm_stark_sdk::config::baby_bear_poseidon2::Digest = + parent_deferral_cached_commit.into(); + + let raw_results = openvm_verify_stark_circuit::extension::get_raw_deferral_results( + &vk, + &vm_proofs, + cached_commit, + ) + .map_err(|e| eyre::eyre!("get_raw_deferral_results failed: {e}"))?; + + let input_commits: Vec<[u8; 32]> = raw_results + .iter() + .map(|r| { + r.input + .as_slice() + .try_into() + .expect("input commit must be 32 bytes") + }) + .collect(); + + let deferral_inputs = vec![DeferralInput::from_inputs(&vm_proofs)]; + + let deferral_state = openvm_verify_stark_circuit::extension::get_deferral_state( + &vk, + &vm_proofs, + cached_commit, + 0, + ) + .map_err(|e| eyre::eyre!("get_deferral_state failed: {e}"))?; + + Ok((input_commits, deferral_inputs, vec![deferral_state])) +} + +fn decode_stark_proof(proof: &StarkProof) -> Result<(VmStarkProof, VerificationBaseline)> { + let inner = Proof::::decode_from_bytes(&proof.proof) + .map_err(|e| eyre::eyre!("decode proof failed: {e}"))?; + let user_pvs_proof = + UserPublicValuesProof::decode::(&mut Cursor::new(&proof.user_pvs_proof)) + .map_err(|e| eyre::eyre!("decode user_pvs_proof failed: {e}"))?; + let deferral_merkle_proofs = if proof.deferral_merkle_proofs.is_empty() { + None + } else { + Some( + DeferralMerkleProofs::decode(&mut Cursor::new(&proof.deferral_merkle_proofs)) + .map_err(|e| eyre::eyre!("decode deferral_merkle_proofs failed: {e}"))?, + ) + }; + let baseline = if proof.baseline.is_empty() { + eyre::bail!("stark proof missing verification baseline"); + } else { + serde_json::from_slice(&proof.baseline) + .map_err(|e| eyre::eyre!("decode baseline failed: {e}"))? + }; + Ok(( + VmStarkProof { + inner, + user_pvs_proof, + deferral_merkle_proofs, + }, + baseline, + )) +} diff --git a/crates/prover-bin/src/dumper.rs b/crates/prover-bin/src/dumper.rs index c8360384c0..0bc0c6e796 100644 --- a/crates/prover-bin/src/dumper.rs +++ b/crates/prover-bin/src/dumper.rs @@ -39,7 +39,7 @@ impl Dumper { let mut agg_writer = std::io::BufWriter::new(agg_file); for proof in &task.aggregated_proofs { let sz = bincode::serde::encode_into_std_write( - &proof.proofs, + &proof.proof, &mut agg_writer, bincode::config::standard(), )?; diff --git a/crates/prover-bin/src/main.rs b/crates/prover-bin/src/main.rs index 05fac1ec1a..88e99d1542 100644 --- a/crates/prover-bin/src/main.rs +++ b/crates/prover-bin/src/main.rs @@ -1,4 +1,5 @@ mod dumper; +mod deferral; mod prover; mod types; mod zk_circuits_handler; diff --git a/crates/prover-bin/src/prover.rs b/crates/prover-bin/src/prover.rs index 7fac8419f6..0c01a201ab 100644 --- a/crates/prover-bin/src/prover.rs +++ b/crates/prover-bin/src/prover.rs @@ -1,4 +1,4 @@ -use crate::zk_circuits_handler::{universal::UniversalHandler, CircuitsHandler}; +use crate::zk_circuits_handler::universal::UniversalHandler; use async_trait::async_trait; use eyre::Result; use scroll_proving_sdk::{ @@ -12,7 +12,7 @@ use scroll_proving_sdk::{ ProvingService, }, }; -use scroll_zkvm_types::ProvingTask; +use scroll_zkvm_types::{proof::StarkProof, ProvingTask}; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, @@ -191,6 +191,10 @@ pub struct CircuitConfig { /// cached vk value to save some initial cost, for debugging only #[serde(default)] pub vks: HashMap, + /// Child circuit VKs used to enable OpenVM deferral for aggregation tasks. + /// Required for batch (child=chunk) and bundle (child=batch) proving in v0.9.0+. + #[serde(default)] + pub child_circuit_vks: HashMap, } pub struct LocalProver { @@ -198,7 +202,7 @@ pub struct LocalProver { next_task_id: u64, current_task: Option>>, - handlers: HashMap>, + handlers: HashMap>>, } #[async_trait] @@ -323,41 +327,82 @@ impl LocalProver { if prover_task.use_openvm_13 { eyre::bail!("prover do not support snark params base on openvm 13"); } - let prover_task: ProvingTask = prover_task.into(); + let mut prover_task: ProvingTask = prover_task.into(); let vk = hex::encode(&prover_task.vk); - let handler = if let Some(handler) = self.handlers.get(&vk) { - handler.clone() - } else { - let base_config = self - .config - .circuits - .get(&req.hard_fork_name) - .ok_or_else(|| { - eyre::eyre!( - "coordinator sent unexpected forkname {}", - req.hard_fork_name - ) - })?; - let url_base = if let Some(url) = base_config.location_data.asset_detours.get(&vk) { - url.clone() - } else { - base_config - .location_data - .gen_asset_url(&vk, req.proof_type)? - }; - let asset_path = base_config - .location_data - .get_asset(&vk, &url_base, &base_config.workspace_path) - .await?; - let circuits_handler = Arc::new(Mutex::new(UniversalHandler::new(&asset_path)?)); - self.handlers.insert(vk, circuits_handler.clone()); - circuits_handler + + let parent_handler = self + .get_or_load_handler(&req.hard_fork_name, req.proof_type, &vk) + .await?; + + // OpenVM v2+ aggregation circuits (batch/bundle) need deferral enabled + // using their immediate child circuit's prover, plus input commits/defersal + // inputs derived from the child proofs. + let deferral = match req.proof_type { + ProofType::Batch | ProofType::Bundle => { + let child_type = match req.proof_type { + ProofType::Batch => ProofType::Chunk, + ProofType::Bundle => ProofType::Batch, + _ => unreachable!(), + }; + let child_vk = self + .config + .circuits + .get(&req.hard_fork_name) + .and_then(|c| c.child_circuit_vks.get(&child_type)) + .ok_or_else(|| { + eyre::eyre!( + "missing child circuit vk for {:?} in fork {}", + child_type, + req.hard_fork_name + ) + })? + .clone(); + let child_handler = self + .get_or_load_handler(&req.hard_fork_name, child_type, &child_vk) + .await?; + let mut parent_guard = parent_handler.lock().await; + let child_guard = child_handler.lock().await; + parent_guard.enable_deferral(&*child_guard)?; + + let child_agg_vk = child_guard + .agg_vk() + .map_err(|e| eyre::eyre!("failed to get child agg vk: {e}"))?; + let cached_commit = parent_guard + .deferral_cached_commit() + .map_err(|e| eyre::eyre!("failed to get parent deferral cached commit: {e}"))?; + + let child_proofs: Vec<&StarkProof> = prover_task.aggregated_proofs.iter().collect(); + let (input_commits, def_inputs, def_states) = + crate::deferral::compute_deferral_data( + &child_agg_vk, + cached_commit, + &child_proofs, + )?; + prover_task.input_commits = input_commits; + + // locks are released here + Some((def_inputs, def_states)) + } + _ => None, }; let handle = Handle::current(); let is_evm = req.proof_type == ProofType::Bundle; let task_handle = tokio::task::spawn_blocking(move || { - handle.block_on(handler.get_proof_data(&prover_task, is_evm)) + handle.block_on(async { + let mut guard = parent_handler.lock().await; + match deferral { + Some((def_inputs, def_states)) => { + guard.get_proof_data_with_deferral( + &prover_task, + is_evm, + &def_inputs, + &def_states, + ) + } + None => guard.get_proof_data(&prover_task, is_evm), + } + }) }); self.current_task = Some(task_handle); @@ -372,4 +417,34 @@ impl LocalProver { ..Default::default() }) } + + /// Load a handler for the given fork/proof-type/vk, reusing a cached one if available. + async fn get_or_load_handler( + &mut self, + fork_name: &str, + proof_type: ProofType, + vk: &str, + ) -> Result>> { + if let Some(handler) = self.handlers.get(vk) { + return Ok(handler.clone()); + } + + let base_config = self + .config + .circuits + .get(fork_name) + .ok_or_else(|| eyre::eyre!("coordinator sent unexpected forkname {}", fork_name))?; + let url_base = if let Some(url) = base_config.location_data.asset_detours.get(vk) { + url.clone() + } else { + base_config.location_data.gen_asset_url(vk, proof_type)? + }; + let asset_path = base_config + .location_data + .get_asset(vk, &url_base, &base_config.workspace_path) + .await?; + let handler = Arc::new(Mutex::new(UniversalHandler::new(&asset_path)?)); + self.handlers.insert(vk.to_string(), handler.clone()); + Ok(handler) + } } diff --git a/crates/prover-bin/src/zk_circuits_handler.rs b/crates/prover-bin/src/zk_circuits_handler.rs index f6b9f0086c..a64d745c67 100644 --- a/crates/prover-bin/src/zk_circuits_handler.rs +++ b/crates/prover-bin/src/zk_circuits_handler.rs @@ -2,12 +2,3 @@ #[allow(non_snake_case)] pub mod universal; - -use async_trait::async_trait; -use eyre::Result; -use scroll_zkvm_types::ProvingTask; - -#[async_trait] -pub trait CircuitsHandler: Sync + Send { - async fn get_proof_data(&self, u_task: &ProvingTask, need_snark: bool) -> Result; -} diff --git a/crates/prover-bin/src/zk_circuits_handler/universal.rs b/crates/prover-bin/src/zk_circuits_handler/universal.rs index e332092a8f..37bf96b2d5 100644 --- a/crates/prover-bin/src/zk_circuits_handler/universal.rs +++ b/crates/prover-bin/src/zk_circuits_handler/universal.rs @@ -1,12 +1,11 @@ use std::path::Path; -use super::CircuitsHandler; -use async_trait::async_trait; use eyre::Result; use libzkp::ProvingTaskExt; -use scroll_zkvm_prover::{Prover, ProverConfig}; +use openvm_circuit::arch::deferral::DeferralState; +use openvm_sdk::DeferralInput; +use scroll_zkvm_prover::{task::ProvingTask as ProvingTaskTrait, Prover, ProverConfig}; use scroll_zkvm_types::ProvingTask; -use tokio::sync::Mutex; pub struct UniversalHandler { prover: Prover, } @@ -19,36 +18,77 @@ impl UniversalHandler { pub fn new(workspace_path: impl AsRef) -> Result { let path_app_exe = workspace_path.as_ref().join("app.vmexe"); let path_app_config = workspace_path.as_ref().join("openvm.toml"); - let segment_len = Some((1 << 22) - 100); let config = ProverConfig { path_app_config, path_app_exe, - segment_len, }; let prover = Prover::setup(config, None)?; Ok(Self { prover }) } - /// get_prover get the inner prover, later we would replace chunk/batch/bundle_prover with - /// universal prover, before that, use bundle_prover as the represent one - pub fn get_prover(&mut self) -> &mut Prover { - &mut self.prover + /// Enable OpenVM deferral using `child_prover` as the child circuit prover. + /// Required for batch (child=chunk) and bundle (child=batch) aggregation proofs. + pub fn enable_deferral(&mut self, child: &UniversalHandler) -> Result<()> { + self.prover + .enable_deferral(&child.prover) + .map_err(|e| eyre::eyre!("failed to enable deferral: {}", e))?; + Ok(()) + } + + /// Return the child aggregation VK needed to build deferral data. + pub fn agg_vk(&self) -> Result> { + let sdk = self.prover.sdk().map_err(|e| eyre::eyre!("failed to get sdk: {e}"))?; + Ok(sdk.agg_vk().as_ref().clone()) + } + + /// Return the cached commit of the verify-stark deferral circuit (def_idx 0). + pub fn deferral_cached_commit(&self) -> Result { + let sdk = self.prover.sdk().map_err(|e| eyre::eyre!("failed to get sdk: {e}"))?; + let mut commits = sdk + .deferral_circuit_cached_commits(0) + .map_err(|e| eyre::eyre!("failed to get deferral cached commits: {e}"))?; + eyre::ensure!( + commits.len() == 1, + "expected one deferral circuit, got {}", + commits.len() + ); + Ok(commits.pop().unwrap()) } pub fn get_task_from_input(input: &str) -> Result { Ok(serde_json::from_str(input)?) } -} -#[async_trait] -impl CircuitsHandler for Mutex { - async fn get_proof_data(&self, u_task: &ProvingTask, need_snark: bool) -> Result { - let mut handler_self = self.lock().await; + /// Generate a proof for `u_task`. + pub fn get_proof_data(&mut self, u_task: &ProvingTask, need_snark: bool) -> Result { + let proof = self.prover.gen_proof_universal(u_task, need_snark)?; + Ok(serde_json::to_string(&proof)?) + } - let proof = handler_self - .get_prover() - .gen_proof_universal(u_task, need_snark)?; + /// Generate a proof for `u_task` using deferred STARK verification data. + /// + /// For batch/bundle tasks this writes `input_commits` into stdin, attaches the deferral + /// states and passes the deferral inputs to the SDK prover. + pub fn get_proof_data_with_deferral( + &mut self, + u_task: &ProvingTask, + need_snark: bool, + def_inputs: &[DeferralInput], + def_states: &[DeferralState], + ) -> Result { + let mut stdin = u_task.build_guest_input(); + stdin.deferrals = def_states.to_vec(); + + let proof = if need_snark { + scroll_zkvm_types::proof::ProofEnum::from(scroll_zkvm_types::proof::EvmProof::from( + self.prover.gen_proof_snark(stdin, def_inputs)?, + )) + } else { + scroll_zkvm_types::proof::ProofEnum::from(self.prover.gen_proof_stark( + stdin, def_inputs, + )?) + }; Ok(serde_json::to_string(&proof)?) } diff --git a/docs/testing/single-chunk-reproving.md b/docs/testing/single-chunk-reproving.md new file mode 100644 index 0000000000..317f6b0e61 --- /dev/null +++ b/docs/testing/single-chunk-reproving.md @@ -0,0 +1,260 @@ +# Re-proving a Single Mainnet Chunk + +This guide describes how to re-prove one specific chunk that already exists in the mainnet production database, without running a full shadow fork or replaying an entire chain segment. + +Typical use cases: + +- A chunk was proven with an old guest / circuit version and the existing proof no longer validates against current verifier assets. +- You want to reproduce a mainnet chunk proof locally for debugging or verification. + +## High-level idea + +The mainnet DB user available to agents is **read-only**, so a local coordinator cannot update `proving_status` or insert `prover_task` records against mainnet RDS directly. The workaround is: + +1. Export the target `chunk` row and its `l2_block` rows from mainnet RDS. +2. Import them into the local **shadow DB** (`localhost:5433/shadow_rollup`), which is writable. +3. Run a temporary coordinator against the shadow DB but with **mainnet L2 RPC** and the production verifier assets. +4. Run the prover in `handle` mode pointing at that coordinator and request exactly the chunk hash. +5. Extract the new proof from the shadow DB, verify it independently, and save it. + +## Prerequisites + +- `psql` and access to both: + - Mainnet RDS via the local tunnel (`localhost:15432/mainnet_rollup`) + - Shadow Postgres (`localhost:5433/shadow_rollup`, writable) +- Built coordinator binary: `coordinator/build/bin/coordinator_api` +- Built prover binary: `target/release/prover` +- Verifier assets matching the current circuit version, e.g. `coordinator/build/bin/assets_v2` +- Cached circuit assets for the prover (the S3 `circuit-release` bucket may return 403 from this environment). Look for an existing `.work/galileo//` directory and copy it into the prover workspace. +- Mainnet genesis file, e.g. `tests/prover-e2e/mainnet-galileoV2/genesis.json` + +## Step-by-step + +### 1. Export the chunk and its blocks from mainnet + +Use `enable_seqscan = off` when querying `l2_block`; the table is huge and a plain `BETWEEN` scan can time out even with a partial index. + +```bash +EXPORT_DIR=/tmp/chunk-6641451-export +mkdir -p $EXPORT_DIR + +# chunk row +PGPASSWORD='' psql -h localhost -p 15432 \ + -U mainnet_infra_team_read_only -d mainnet_rollup -Atq \ + -c "COPY (SELECT * FROM chunk WHERE index = 6641451) TO STDOUT WITH CSV HEADER;" \ + > $EXPORT_DIR/chunk.csv + +# l2_block rows for the chunk's block range +PGPASSWORD='' psql -h localhost -p 15432 \ + -U mainnet_infra_team_read_only -d mainnet_rollup -Atq \ + -c " + SET enable_seqscan = off; + COPY ( + SELECT * FROM l2_block + WHERE number BETWEEN 34180693 AND 34180761 + AND deleted_at IS NULL + ) TO STDOUT WITH CSV HEADER; + " > $EXPORT_DIR/l2_blocks.csv +``` + +### 2. Import into the shadow DB + +```bash +PGPASSWORD='shadow_pass' psql -h localhost -p 5433 \ + -U postgres -d shadow_rollup \ + -f /dev/stdin < $EXPORT_DIR/handle-set.json <<'EOF' +{ + "chunks": [ + "0x90861ddc4e0effb030f59644b03c8bd80e0b2ca8632c8c3500a25029fe4f4081" + ], + "batches": [], + "bundles": [] +} +EOF +``` + +### 6. Configure the prover + +Key settings: + +- `coordinator.base_url`: `http://localhost:8390` +- `circuits.galileoV2.workspace_path`: directory containing the cached circuit assets +- `circuits.galileoV2.debug_mode`: `true` to skip S3 preflight / download (S3 may 403) +- `sdk_config.db_path`: separate from other prover runs + +Example: + +```json +{ + "sdk_config": { + "prover_name_prefix": "mainnet-reprove-chunk-6641451", + "keys_dir": "/tmp/chunk-6641451-export/prover-keys", + "coordinator": { + "base_url": "http://localhost:8390", + "retry_count": 10, + "retry_wait_time_sec": 10, + "connection_timeout_sec": 1800 + }, + "prover": { + "supported_proof_types": [1], + "circuit_version": "v0.13.1" + }, + "health_listener_addr": "127.0.0.1:10080", + "db_path": "/tmp/chunk-6641451-export/prover-db" + }, + "circuits": { + "galileoV2": { + "base_url": "https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/releases/v0.9.0/", + "workspace_path": "/tmp/prover-multi-gpu/gpu0/.work/galileo", + "debug_mode": true + } + } +} +``` + +If circuit assets are not already in the workspace, copy them from an existing cache: + +```bash +mkdir -p /tmp/prover-multi-gpu/gpu0/.work/galileo +cp -r /home/scroll/zzhang/scroll/.work/galileo/64cf16439a284e4449666c479a3ae42b568fea5e88610777ff6b5f2cda19d91182a47957139d0d1c1c3fbb28b9579c23f2823c0c6ff05669fe71ad4a0c92620e \ + /tmp/prover-multi-gpu/gpu0/.work/galileo/ +``` + +### 7. Run the prover + +OpenVM proving can overflow the default Rust thread stack, so set `RUST_MIN_STACK`. Run with no timeout: + +```bash +cd /home/scroll/zzhang/scroll +RUST_MIN_STACK=33554432 ./target/release/prover \ + --config /tmp/chunk-6641451-export/prover-config.json \ + handle /tmp/chunk-6641451-export/handle-set.json +``` + +For a chunk of ~70 blocks, expect roughly 10–15 minutes on GPU. + +### 8. Extract, verify, and save the proof + +After the coordinator logs `proof verified and valid`, extract the proof from the shadow DB: + +```bash +PGPASSWORD='shadow_pass' psql -h localhost -p 5433 \ + -U postgres -d shadow_rollup -Atq \ + -c "SELECT encode(proof, 'hex') FROM chunk WHERE index = 6641451;" \ + > /tmp/chunk-6641451-export/new-proof.hex + +xxd -r -p /tmp/chunk-6641451-export/new-proof.hex > /tmp/chunk-6641451-export/new-proof.json + +# independent verification +cd coordinator/build/bin +LD_LIBRARY_PATH=../internal/logic/libzkp/lib:$LD_LIBRARY_PATH \ + ./coordinator_tool verify chunk /tmp/chunk-6641451-export/new-proof.json +``` + +Save the final proof to a clear location: + +```bash +cp /tmp/chunk-6641451-export/new-proof.json \ + /tmp/chunk-6641451/chunk_6641451_proof.json +``` + +## Common pitfalls + +| Symptom | Cause | Fix | +|---------|-------|-----| +| `cannot execute UPDATE in a read-only transaction` | Coordinator connected to mainnet RDS with read-only user | Use shadow DB for coordinator writes | +| `server closed the connection unexpectedly` on `localhost:15432` | Mainnet RDS tunnel (stunnel) is down or broken | Retry later or ask ops to restart the tunnel | +| `record not found, uuid:...` during proof submission | Coordinator was restarted/killed after assigning the task; `prover_task` record was lost or not committed | Keep coordinator alive for the entire proving session; use `disable_timeout=true` | +| Prover aborts with stack overflow | Default Rust thread stack too small for OpenVM | `RUST_MIN_STACK=33554432` | +| S3 403 on circuit asset URLs | Directory listings are blocked or bucket is not public | Copy cached circuit assets into the prover workspace and set `debug_mode: true` | +| Query on `l2_block` times out | Table is huge; planner may seq-scan | `SET enable_seqscan = off;` and include `deleted_at IS NULL` | + +## Cleanup + +Stop the temporary coordinator when done. The shadow DB still contains the imported mainnet chunk; delete it if you no longer need it: + +```bash +PGPASSWORD='shadow_pass' psql -h localhost -p 5433 \ + -U postgres -d shadow_rollup -Atq -c " + DELETE FROM l2_block WHERE number BETWEEN 34180693 AND 34180761; + DELETE FROM chunk WHERE index = 6641451; + " +``` diff --git a/rollup/cmd/rollup_relayer/app/app.go b/rollup/cmd/rollup_relayer/app/app.go index dc36f91c2a..e2c4da1cc6 100644 --- a/rollup/cmd/rollup_relayer/app/app.go +++ b/rollup/cmd/rollup_relayer/app/app.go @@ -148,15 +148,19 @@ func action(ctx *cli.Context) error { } // Watcher loop to fetch missing blocks - go utils.LoopWithContext(subCtx, 2*time.Second, func(ctx context.Context) { - number, loopErr := rutils.GetLatestConfirmedBlockNumber(ctx, l2ethClient, cfg.L2Config.Confirmations) - if loopErr != nil { - log.Error("failed to get block number", "err", loopErr) - return - } - // errors are logged in the try method as well - _ = l2watcher.TryFetchRunningMissingBlocks(number) - }) + if cfg.L2Config.DisableL2Watcher { + log.Info("L2 watcher is disabled (disable_l2_watcher=true), skipping missing-blocks fetch loop") + } else { + go utils.LoopWithContext(subCtx, 2*time.Second, func(ctx context.Context) { + number, loopErr := rutils.GetLatestConfirmedBlockNumber(ctx, l2ethClient, cfg.L2Config.Confirmations) + if loopErr != nil { + log.Error("failed to get block number", "err", loopErr) + return + } + // errors are logged in the try method as well + _ = l2watcher.TryFetchRunningMissingBlocks(number) + }) + } go utils.Loop(subCtx, time.Duration(cfg.L2Config.ChunkProposerConfig.ProposeIntervalMilliseconds)*time.Millisecond, chunkProposer.TryProposeChunk) diff --git a/rollup/internal/config/l2.go b/rollup/internal/config/l2.go index 91ea322cd0..5616aa6106 100644 --- a/rollup/internal/config/l2.go +++ b/rollup/internal/config/l2.go @@ -16,6 +16,10 @@ type L2Config struct { L2MessageQueueAddress common.Address `json:"l2_message_queue_address"` // The WithdrawTrieRootSlot in L2MessageQueue contract. WithdrawTrieRootSlot common.Hash `json:"withdraw_trie_root_slot,omitempty"` + // DisableL2Watcher disables the L2 watcher loop that fetches missing blocks. + // Useful for shadow-fork testing where the l2_block table is imported/empty and a + // genesis crawl is undesirable. Defaults to false (watcher enabled). + DisableL2Watcher bool `json:"disable_l2_watcher"` // The relayer config RelayerConfig *RelayerConfig `json:"relayer_config"` // The chunk_proposer config @@ -34,6 +38,7 @@ type ChunkProposerConfig struct { MaxL2GasPerChunk uint64 `json:"max_l2_gas_per_chunk"` ChunkTimeoutSec uint64 `json:"chunk_timeout_sec"` MaxUncompressedBatchBytesSize uint64 `json:"max_uncompressed_batch_bytes_size"` + Disable bool `json:"disable"` } // BatchProposerConfig loads batch_proposer configuration items. @@ -42,12 +47,15 @@ type BatchProposerConfig struct { BatchTimeoutSec uint64 `json:"batch_timeout_sec"` MaxChunksPerBatch int `json:"max_chunks_per_batch"` MaxUncompressedBatchBytesSize uint64 `json:"max_uncompressed_batch_bytes_size"` + Disable bool `json:"disable"` } // BundleProposerConfig loads bundle_proposer configuration items. type BundleProposerConfig struct { - MaxBatchNumPerBundle uint64 `json:"max_batch_num_per_bundle"` - BundleTimeoutSec uint64 `json:"bundle_timeout_sec"` + MaxBatchNumPerBundle uint64 `json:"max_batch_num_per_bundle"` + BundleTimeoutSec uint64 `json:"bundle_timeout_sec"` + BundleProposeCooldownSec uint64 `json:"bundle_propose_cooldown_sec"` + Disable bool `json:"disable"` } // BlobUploaderConfig loads blob_uploader configuration items. diff --git a/rollup/internal/config/relayer.go b/rollup/internal/config/relayer.go index 2e50969ada..cb9a228d24 100644 --- a/rollup/internal/config/relayer.go +++ b/rollup/internal/config/relayer.go @@ -37,6 +37,11 @@ type SenderConfig struct { MaxPendingBlobTxs int64 `json:"max_pending_blob_txs"` // The timestamp of the Ethereum Fusaka upgrade in seconds since epoch. FusakaTimestamp uint64 `json:"fusaka_timestamp"` + // ChainNonceOnly initializes the sender nonce from the chain pending nonce only, + // ignoring stale pending_transaction rows in the database. + // Useful for shadow-fork testing against a DB imported from production. + // Defaults to false (nonce = max(db nonce + 1, chain pending nonce)). + ChainNonceOnly bool `json:"chain_nonce_only"` } type BatchSubmission struct { diff --git a/rollup/internal/controller/relayer/l2_relayer.go b/rollup/internal/controller/relayer/l2_relayer.go index e57b6ca73f..4c3a60ef00 100644 --- a/rollup/internal/controller/relayer/l2_relayer.go +++ b/rollup/internal/controller/relayer/l2_relayer.go @@ -536,6 +536,11 @@ func (r *Layer2Relayer) ProcessPendingBatches() { "end hash", lastBatch.Hash, "RollupContractAddress", r.cfg.RollupContractAddress, "err", err, + ) + log.Debug( + "Failed to send commitBatch tx to layer1, calldata dump", + "start index", firstBatch.Index, + "end index", lastBatch.Index, "calldata", common.Bytes2Hex(calldata), ) return @@ -768,7 +773,8 @@ func (r *Layer2Relayer) finalizeBundle(bundle *orm.Bundle, withProof bool) error if err != nil { log.Error("finalizeBundle in layer1 failed", "with proof", withProof, "index", bundle.Index, "start batch index", bundle.StartBatchIndex, "end batch index", bundle.EndBatchIndex, - "RollupContractAddress", r.cfg.RollupContractAddress, "err", err, "calldata", common.Bytes2Hex(calldata)) + "RollupContractAddress", r.cfg.RollupContractAddress, "err", err) + log.Debug("finalizeBundle in layer1 failed, calldata dump", "index", bundle.Index, "calldata", common.Bytes2Hex(calldata)) return err } @@ -906,6 +912,16 @@ func (r *Layer2Relayer) handleConfirmation(cfm *sender.Confirmation) { status = types.RollupFinalizeFailed r.metrics.rollupL2BundlesFinalizedConfirmedFailedTotal.Inc() log.Warn("FinalizeBundleTxType transaction confirmed but failed in layer1", "confirmation", cfm) + // Status RollupFinalizeFailed (7) is NOT picked up again by ProcessPendingBundles + // (GetFirstPendingBundle only queries rollup_status = RollupPending); the bundle is + // stranded until rollup_status is manually reset to 1. + bundleIndex := uint64(0) + bundles, queryErr := r.bundleOrm.GetBundles(r.ctx, map[string]interface{}{"hash": bundleHash}, nil, 1) + if queryErr == nil && len(bundles) > 0 { + bundleIndex = bundles[0].Index + } + log.Error("Bundle is now STRANDED with rollup_status=RollupFinalizeFailed(7): it will NOT be retried by ProcessPendingBundles, manual intervention required (reset rollup_status to 1)", + "bundle index", bundleIndex, "bundle hash", bundleHash, "tx hash", cfm.TxHash.String(), "query err", queryErr) } err := r.db.Transaction(func(dbTX *gorm.DB) error { diff --git a/rollup/internal/controller/sender/estimategas.go b/rollup/internal/controller/sender/estimategas.go index 20d66beefa..f0711f1b01 100644 --- a/rollup/internal/controller/sender/estimategas.go +++ b/rollup/internal/controller/sender/estimategas.go @@ -101,10 +101,19 @@ func (s *Sender) estimateBlobGas(to *common.Address, data []byte, sidecar *types return feeData, nil } +const ( + // estimateGasCap is an explicit non-zero gas limit for the eth_estimateGas CallMsg. + // Some nodes (e.g. Anvil) reject estimation requests that carry fee caps but leave + // Gas at the go-ethereum default of 0. go-ethereum's EstimateGas only uses this as + // the upper bound of its binary search, so a generous cap does not affect the result. + estimateGasCap = 30_000_000 +) + func (s *Sender) estimateGasLimit(to *common.Address, data []byte, sidecar *types.BlobTxSidecar, gasPrice, gasTipCap, gasFeeCap, blobGasFeeCap *big.Int) (uint64, *types.AccessList, error) { msg := ethereum.CallMsg{ From: s.transactionSigner.GetAddr(), To: to, + Gas: estimateGasCap, GasPrice: gasPrice, GasTipCap: gasTipCap, GasFeeCap: gasFeeCap, diff --git a/rollup/internal/controller/sender/sender.go b/rollup/internal/controller/sender/sender.go index 5b37473596..d355a19e83 100644 --- a/rollup/internal/controller/sender/sender.go +++ b/rollup/internal/controller/sender/sender.go @@ -450,19 +450,26 @@ func (s *Sender) createTx(feeData *FeeData, target *common.Address, data []byte, } // initializeNonce initializes the nonce by taking the maximum of database nonce and pending nonce. +// When ChainNonceOnly is enabled, the database is ignored and the chain pending nonce is used +// directly (useful for shadow-fork testing with stale pending_transaction rows). func (s *Sender) initializeNonce() (uint64, error) { - // Get maximum nonce from database - dbNonce, err := s.pendingTransactionOrm.GetMaxNonceBySenderAddress(s.ctx, s.transactionSigner.GetAddr().Hex()) - if err != nil { - return 0, fmt.Errorf("failed to get max nonce from database for address %s, err: %w", s.transactionSigner.GetAddr().Hex(), err) - } - // Get pending nonce from the client pendingNonce, err := s.client.PendingNonceAt(s.ctx, s.transactionSigner.GetAddr()) if err != nil { return 0, fmt.Errorf("failed to get pending nonce for address %s, err: %w", s.transactionSigner.GetAddr().Hex(), err) } + if s.config.ChainNonceOnly { + log.Info("nonce initialization (chain_nonce_only mode, ignoring database pending transactions)", "address", s.transactionSigner.GetAddr().Hex(), "pendingNonce", pendingNonce, "finalNonce", pendingNonce) + return pendingNonce, nil + } + + // Get maximum nonce from database + dbNonce, err := s.pendingTransactionOrm.GetMaxNonceBySenderAddress(s.ctx, s.transactionSigner.GetAddr().Hex()) + if err != nil { + return 0, fmt.Errorf("failed to get max nonce from database for address %s, err: %w", s.transactionSigner.GetAddr().Hex(), err) + } + // Take the maximum of pending nonce and (db nonce + 1) // Database stores the used nonce, so the next available nonce should be dbNonce + 1 // When dbNonce is -1 (no records), dbNonce + 1 = 0, which is correct diff --git a/rollup/internal/controller/watcher/batch_proposer.go b/rollup/internal/controller/watcher/batch_proposer.go index 522ce07cb7..eccbb1a2fc 100644 --- a/rollup/internal/controller/watcher/batch_proposer.go +++ b/rollup/internal/controller/watcher/batch_proposer.go @@ -133,6 +133,9 @@ func (p *BatchProposer) SetReplayDB(replayDB *gorm.DB) { // TryProposeBatch tries to propose a new batches. func (p *BatchProposer) TryProposeBatch() { p.batchProposerCircleTotal.Inc() + if p.cfg.Disable { + return + } if err := p.proposeBatch(); err != nil { p.proposeBatchFailureTotal.Inc() log.Error("proposeBatchChunks failed", "err", err) diff --git a/rollup/internal/controller/watcher/bundle_proposer.go b/rollup/internal/controller/watcher/bundle_proposer.go index 388355e6b8..572d3bc5fa 100644 --- a/rollup/internal/controller/watcher/bundle_proposer.go +++ b/rollup/internal/controller/watcher/bundle_proposer.go @@ -29,6 +29,12 @@ type BundleProposer struct { cfg *config.BundleProposerConfig + // lastBundleCreatedAt is used to enforce a wall-clock cooldown between + // consecutive bundle proposals. This is useful in shadow-fork scenarios + // where L2 block timestamps are historical, so the normal bundle timeout + // would otherwise fire immediately. + lastBundleCreatedAt time.Time + minCodecVersion encoding.CodecVersion chainCfg *params.ChainConfig @@ -52,6 +58,7 @@ func NewBundleProposer(ctx context.Context, cfg *config.BundleProposerConfig, mi batchOrm: orm.NewBatch(db), bundleOrm: orm.NewBundle(db), cfg: cfg, + lastBundleCreatedAt: time.Now(), minCodecVersion: minCodecVersion, chainCfg: chainCfg, @@ -91,6 +98,18 @@ func NewBundleProposer(ctx context.Context, cfg *config.BundleProposerConfig, mi // TryProposeBundle tries to propose a new bundle. func (p *BundleProposer) TryProposeBundle() { p.bundleProposerCircleTotal.Inc() + + if p.cfg.Disable { + return + } + + if p.cfg.BundleProposeCooldownSec > 0 { + if elapsed := time.Since(p.lastBundleCreatedAt).Seconds(); elapsed < float64(p.cfg.BundleProposeCooldownSec) { + log.Debug("bundle proposal cooldown has not elapsed", "elapsed", elapsed, "cooldown", p.cfg.BundleProposeCooldownSec) + return + } + } + if err := p.proposeBundle(); err != nil { p.proposeBundleFailureTotal.Inc() log.Error("propose new bundle failed", "err", err) @@ -121,6 +140,8 @@ func (p *BundleProposer) UpdateDBBundleInfo(batches []*orm.Batch, codecVersion e log.Error("update chunk info in orm failed", "err", err) return err } + + p.lastBundleCreatedAt = time.Now() return nil } diff --git a/rollup/internal/controller/watcher/chunk_proposer.go b/rollup/internal/controller/watcher/chunk_proposer.go index 843abaf542..bba9df1eb0 100644 --- a/rollup/internal/controller/watcher/chunk_proposer.go +++ b/rollup/internal/controller/watcher/chunk_proposer.go @@ -141,6 +141,9 @@ func (p *ChunkProposer) SetReplayDB(replayDB *gorm.DB) { // TryProposeChunk tries to propose a new chunk. func (p *ChunkProposer) TryProposeChunk() { p.chunkProposerCircleTotal.Inc() + if p.cfg.Disable { + return + } if err := p.ProposeChunk(); err != nil { p.proposeChunkFailureTotal.Inc() log.Error("propose new chunk failed", "err", err) diff --git a/rust-toolchain b/rust-toolchain index c17a78fd9e..fd7eda1132 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-08-18" +channel = "nightly-2025-11-20" targets = ["riscv32im-unknown-none-elf", "x86_64-unknown-linux-gnu"] -components = ["llvm-tools", "rustc-dev"] \ No newline at end of file +components = ["llvm-tools", "rust-src"] \ No newline at end of file diff --git a/tests/prover-e2e/cloak-galileoV2/.make.env b/tests/prover-e2e/cloak-galileoV2/.make.env index 75ffd1e544..adb4711f97 100644 --- a/tests/prover-e2e/cloak-galileoV2/.make.env +++ b/tests/prover-e2e/cloak-galileoV2/.make.env @@ -1,4 +1,4 @@ BEGIN_BLOCK?=33750000 END_BLOCK?=33750005 SCROLL_FORK_NAME=galileoV2 -SCROLL_ZKVM_VERSION?=v0.8.0 \ No newline at end of file +SCROLL_ZKVM_VERSION?=releases/v0.9.0 \ No newline at end of file diff --git a/tests/prover-e2e/docker-e2e/conf/prover.json b/tests/prover-e2e/docker-e2e/conf/prover.json index 241b61adc1..2f9be1ef95 100644 --- a/tests/prover-e2e/docker-e2e/conf/prover.json +++ b/tests/prover-e2e/docker-e2e/conf/prover.json @@ -17,7 +17,7 @@ }, "circuits": { "galileoV2": { - "base_url": "https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/galileov2/", + "base_url": "https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/releases/v0.9.0/", "workspace_path": ".work/galileo" } } diff --git a/tests/prover-e2e/mainnet-galileoV2/.make.env b/tests/prover-e2e/mainnet-galileoV2/.make.env index c7f03a5a33..525b337cb5 100644 --- a/tests/prover-e2e/mainnet-galileoV2/.make.env +++ b/tests/prover-e2e/mainnet-galileoV2/.make.env @@ -5,4 +5,4 @@ BEGIN_BLOCK?=33750000 END_BLOCK?=33750005 SCROLL_FORK_NAME=galileoV2 -SCROLL_ZKVM_VERSION?=v0.8.0 +SCROLL_ZKVM_VERSION?=releases/v0.9.0 diff --git a/tests/shadow-testing/.env.example b/tests/shadow-testing/.env.example new file mode 100644 index 0000000000..3a44df2cc2 --- /dev/null +++ b/tests/shadow-testing/.env.example @@ -0,0 +1,57 @@ +# Shadow Coordinator + Prover Environment Variables +# Copy this file to .env and fill in real values + +# ============================================================================ +# PRODUCTION RDS (read-only, via IDC port-forward) +# ============================================================================ +PROD_DB_HOST=localhost +PROD_DB_PORT=15432 +PROD_DB_NAME=rollup +PROD_DB_USER=YOUR_PROD_USER_HERE +PROD_DB_PASSWORD=YOUR_PROD_PASSWORD_HERE + +# Full DSN (constructed from above, or override directly) +# PROD_DB=postgresql://YOUR_PROD_USER_HERE:YOUR_PROD_PASSWORD_HERE@localhost:15432/rollup + +# ============================================================================ +# SHADOW DATABASE (local PostgreSQL in Docker) +# ============================================================================ +SHADOW_DB_HOST=localhost +SHADOW_DB_PORT=5433 +SHADOW_DB_NAME=shadow_rollup +SHADOW_DB_USER=postgres +SHADOW_DB_PASSWORD=YOUR_SHADOW_PASSWORD_HERE + +# Full DSN (constructed from above, or override directly) +# SHADOW_DB=postgresql://postgres:YOUR_SHADOW_PASSWORD_HERE@localhost:5433/shadow_rollup + +# ============================================================================ +# COORDINATOR AUTH +# ============================================================================ +# JWT secret for prover login challenge-response. +# MUST match between coordinator config and prover expectations. +COORDINATOR_AUTH_SECRET=YOUR_RANDOM_SECRET_HERE + +# ============================================================================ +# DOCKER IMAGE TAG +# ============================================================================ +IMAGE_TAG=v4.7.13-openvm16 + +# ============================================================================ +# L2 RPC ENDPOINT +# Must support debug_executionWitness and debug_dbGet. +# https://mainnet-rpc.scroll.io works; https://rpc.scroll.io does NOT. +# ============================================================================ +L2_RPC=https://mainnet-rpc.scroll.io + +# ============================================================================ +# VERIFIER ASSETS PATH +# Directory containing subdirectories: openvm-0.5.6, openvm-v0.7.1, openvm-v0.8.0 +# ============================================================================ +VERIFIER_DIR=/tmp/shadow-verifier-assets + +# ============================================================================ +# DATA IMPORT LIMITS +# ============================================================================ +BATCH_LIMIT=50 +BUNDLE_LIMIT=20000 diff --git a/tests/shadow-testing/.gitignore b/tests/shadow-testing/.gitignore new file mode 100644 index 0000000000..badc900a42 --- /dev/null +++ b/tests/shadow-testing/.gitignore @@ -0,0 +1,23 @@ +# Work directory (logs, pid files, generated configs) +.work/ + +# Anvil state files (large, environment-specific) +states/*.json + +# Generated configs (from templates) +.work/*.json + +# Prover work directories +.work/prover-*/ + +# Relayer logs +.work/relayer-*.log + +# Coordinator logs +.work/coordinator-*.log + +# Actual config files with secrets (use .template files instead) +configs/*.json +follow/configs/*.json +snapshot/configs/*.json +__pycache__/ diff --git a/tests/shadow-testing/Makefile b/tests/shadow-testing/Makefile new file mode 100644 index 0000000000..7b8f6d998d --- /dev/null +++ b/tests/shadow-testing/Makefile @@ -0,0 +1,109 @@ +# Shadow Testing Makefile — thin dispatcher. +# +# The two test modes live in their own directories, each with its own +# Makefile, scripts, configs and GUIDE: +# +# follow/ Follow mode (primary): fork the current mainnet tip and follow +# mainnet bundle production in real time. Default acceptance test +# for prover/guest upgrades. +# snapshot/ Snapshot replay mode: fork a historical block and prove/finalize +# a fixed bundle range. Incident reproduction, single-bundle +# debugging, Sepolia testing, codec-migration checks. +# +# Shared scripts and the relayer config template live in lib/. +# .work/ (logs, pidfiles, anvil state) is shared by both modes and stays here. + +CONFIG ?= mainnet +BUNDLE_RANGE ?= 17297:17301 + +# --- Follow mode ------------------------------------------------------------- +.PHONY: follow-up follow-stop follow-status follow-report re-fork + +follow-up: + $(MAKE) -C follow follow + +follow-stop: + $(MAKE) -C follow follow-stop + +follow-status: + $(MAKE) -C follow follow-status + +follow-report: + $(MAKE) -C follow follow-report + +re-fork: + $(MAKE) -C follow re-fork + +# --- Snapshot replay mode ---------------------------------------------------- +.PHONY: snapshot-all snapshot-env snapshot-prove snapshot-finalize \ + snapshot-sepolia-all snapshot-status snapshot-verify \ + snapshot-docker-all snapshot-docker-env snapshot-docker-prove \ + snapshot-docker-finalize snapshot-docker-stop snapshot-stop snapshot-clean + +snapshot-all: + $(MAKE) -C snapshot all CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-env: + $(MAKE) -C snapshot env CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-prove: + $(MAKE) -C snapshot prove CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-finalize: + $(MAKE) -C snapshot finalize CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-sepolia-all: + $(MAKE) -C snapshot sepolia-all CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-status: + $(MAKE) -C snapshot status CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-verify: + $(MAKE) -C snapshot verify CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-docker-all: + $(MAKE) -C snapshot docker-all CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-docker-env: + $(MAKE) -C snapshot docker-env CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-docker-prove: + $(MAKE) -C snapshot docker-prove CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-docker-finalize: + $(MAKE) -C snapshot docker-finalize CONFIG=$(CONFIG) BUNDLE_RANGE=$(BUNDLE_RANGE) + +snapshot-docker-stop: + $(MAKE) -C snapshot docker-stop CONFIG=$(CONFIG) + +snapshot-stop: + $(MAKE) -C snapshot stop CONFIG=$(CONFIG) + +snapshot-clean: + $(MAKE) -C snapshot clean CONFIG=$(CONFIG) + +# --- Help -------------------------------------------------------------------- +.PHONY: help + +help: + @echo "Shadow Testing — two modes, each with its own directory:" + @echo "" + @echo "Follow Mode (primary — fork current mainnet tip, follow indefinitely):" + @echo " make follow-up Bring up the full follow-mode stack" + @echo " make follow-status Latest monitor snapshot + finalize lag" + @echo " make follow-report Throughput report for the current run" + @echo " make re-fork Re-fork Anvil at latest block (recovery)" + @echo " make follow-stop Stop the follow-mode stack" + @echo " (or: make -C follow ; guide: follow/GUIDE.md)" + @echo "" + @echo "Snapshot Replay Mode (historical fork, fixed bundle range):" + @echo " make snapshot-all CONFIG= BUNDLE_RANGE= Full pipeline" + @echo " make snapshot-env CONFIG= BUNDLE_RANGE= Setup Anvil + DB" + @echo " make snapshot-prove CONFIG= BUNDLE_RANGE= Prove bundles" + @echo " make snapshot-finalize CONFIG= BUNDLE_RANGE= Finalize bundles" + @echo " make snapshot-status CONFIG= BUNDLE_RANGE= Check status" + @echo " make snapshot-verify CONFIG= BUNDLE_RANGE= Verify on-chain" + @echo " make snapshot-sepolia-all CONFIG=sepolia BUNDLE_RANGE= Sepolia pipeline" + @echo " make snapshot-docker-{all,env,prove,finalize,stop} Docker pipeline" + @echo " make snapshot-stop / snapshot-clean Stop / cleanup" + @echo " (or: make -C snapshot ; guide: snapshot/GUIDE.md)" diff --git a/tests/shadow-testing/README.md b/tests/shadow-testing/README.md new file mode 100644 index 0000000000..4414348a97 --- /dev/null +++ b/tests/shadow-testing/README.md @@ -0,0 +1,64 @@ +# Shadow Testing Toolkit + +Toolkit for running Scroll shadow fork tests against Anvil: a local coordinator + local prover fed by production task data, without interfering with the live system. There are two test modes, each in its own directory with its own Makefile, scripts, configs and guide. + +## Choose a Mode + +| Mode | What It Does | When To Use | +|------|--------------|-------------| +| **[Follow mode](follow/)** (primary) | Fork the **current** ETH mainnet state, baseline-sync the shadow DB, then follow mainnet indefinitely — poll-syncing new chunk/batch/bundle rows, proving them locally, finalizing on the fork — until a preset duration (default 48h) or a failure | **Default acceptance test** for prover/guest upgrades | +| **[Snapshot replay mode](snapshot/)** | Fork a historical block, import a fixed bundle range, prove & finalize ~N bundles | Reproducing a specific incident, debugging one bundle, Sepolia testing, targeted codec-migration checks | + +## Quick Start + +```bash +# Follow mode (primary acceptance test) +cd tests/shadow-testing/follow +make follow # one-shot bring-up of the full follow-mode stack +make follow-status # latest monitor snapshot + lag summary +make follow-report # final report, windowed to this run (SHADOW_REPORT_START) +make follow-stop # tear down (script supports --keep-anvil) + +# Snapshot replay mode (fixed bundle range) +cd tests/shadow-testing/snapshot +make docker-all CONFIG=mainnet BUNDLE_RANGE=17302:17305 # Docker (recommended) +make all CONFIG=mainnet BUNDLE_RANGE=17297:17301 # bare-metal +``` + +The root `Makefile` is a thin dispatcher (`make follow-up`, `make snapshot-all ...`, `make help`). `lib/` holds scripts shared by both modes (`01-setup-anvil.sh`, `03-deploy-verifier.sh`, `04-prover-up.sh`, `06-run-relayer.sh`, `anvil-utils.sh`, `sync-queue-hashes.py`, `configs/relayer.json.template`). Runtime state (`.work/` — logs, pidfiles, Anvil state, `follow-run.env`) is shared by both modes at `tests/shadow-testing/.work`. + +## Documentation + +| Document | What It Covers | +|----------|----------------| +| [`follow/GUIDE.md`](follow/GUIDE.md) | Follow mode — bring-up, daemons, steady state, recovery, acceptance criteria | +| [`snapshot/GUIDE.md`](snapshot/GUIDE.md) | Snapshot replay mode — step-by-step manual setup, architecture, configuration, verifier deployment, relayer dry-run | +| [`docs/COMMON-TROUBLESHOOTING.md`](docs/COMMON-TROUBLESHOOTING.md) | Mode-independent pitfalls, traps, and agent checklists | +| [`follow/TROUBLESHOOTING.md`](follow/TROUBLESHOOTING.md) | Follow-mode-specific traps (poll sync, starvation, live finalization) | +| [`snapshot/TROUBLESHOOTING.md`](snapshot/TROUBLESHOOTING.md) | Snapshot-replay-mode-specific traps (historical fork, fixed bundle range, Sepolia) | +| [`docs/contract-addresses.md`](docs/contract-addresses.md) | L1 contract addresses per network | + +## Prerequisites + +- [Foundry](https://book.getfoundry.sh/) (`cast`, `forge`) +- `jq` +- `docker compose` (for Docker mode) +- PostgreSQL client (`psql`) +- Access to production RDS (via IDC port-forward) + +## Configurations + +Each mode has its own `configs/`; copy templates and fill in secrets: + +```bash +cp follow/configs/mainnet.json.template follow/configs/mainnet.json +cp follow/configs/coordinator.json.template follow/configs/coordinator.json +cp snapshot/configs/sepolia.json.template snapshot/configs/sepolia.json +# Edit the files and replace placeholders: +# - YOUR_ALCHEMY_API_KEY (in mainnet.json / sepolia.json fork.url) +# - YOUR_SHADOW_DB_PASSWORD (in mainnet.json / sepolia.json db.dsn) +``` + +## Contributing + +When you discover a new trap or workaround, add it to `docs/COMMON-TROUBLESHOOTING.md` (mode-independent) or the per-mode `follow/TROUBLESHOOTING.md` / `snapshot/TROUBLESHOOTING.md` (structured). diff --git a/tests/shadow-testing/contracts/IZkEvmVerifier.sol b/tests/shadow-testing/contracts/IZkEvmVerifier.sol new file mode 100644 index 0000000000..244b0deebe --- /dev/null +++ b/tests/shadow-testing/contracts/IZkEvmVerifier.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.24; + +interface IZkEvmVerifierV1 { + /// @notice Verify aggregate zk proof. + /// @param aggrProof The aggregated proof. + /// @param publicInputHash The public input hash. + function verify(bytes calldata aggrProof, bytes32 publicInputHash) external view; +} + +interface IZkEvmVerifierV2 { + /// @notice Verify bundle zk proof. + /// @param bundleProof The bundle recursion proof. + /// @param publicInput The public input. + function verify(bytes calldata bundleProof, bytes calldata publicInput) external view; +} diff --git a/tests/shadow-testing/contracts/ZkEvmVerifierPostFeynman.sol b/tests/shadow-testing/contracts/ZkEvmVerifierPostFeynman.sol new file mode 100644 index 0000000000..d2e8dd2e2c --- /dev/null +++ b/tests/shadow-testing/contracts/ZkEvmVerifierPostFeynman.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT + +pragma solidity =0.8.24; + +import {IZkEvmVerifierV2} from "./IZkEvmVerifier.sol"; + +// solhint-disable no-inline-assembly + +/// @notice Wrapper around the OpenVM Halo2 plonk verifier for GalileoV2 (post-Feynman) proofs. +/// +/// @dev Identical to ZkEvmVerifierPostEuclid, except the public input hash is computed as +/// keccak256(abi.encodePacked(protocolVersion, publicInput)). The protocol version is +/// stored as an immutable and corresponds to the batch version (10 for GalileoV2). +contract ZkEvmVerifierPostFeynman is IZkEvmVerifierV2 { + /********** + * Errors * + **********/ + + /// @dev Thrown when bundle recursion zk proof verification is failed. + error VerificationFailed(); + + /************* + * Constants * + *************/ + + /// @notice The address of highly optimized plonk verifier contract. + address public immutable plonkVerifier; + + /// @notice A predetermined digest for the `plonkVerifier`. + bytes32 public immutable verifierDigest1; + + /// @notice A predetermined digest for the `plonkVerifier`. + bytes32 public immutable verifierDigest2; + + /// @notice The protocol version prepended to the public input before hashing. + uint256 public immutable protocolVersion; + + /*************** + * Constructor * + ***************/ + + constructor( + address _verifier, + bytes32 _verifierDigest1, + bytes32 _verifierDigest2, + uint256 _protocolVersion + ) { + plonkVerifier = _verifier; + verifierDigest1 = _verifierDigest1; + verifierDigest2 = _verifierDigest2; + protocolVersion = _protocolVersion; + } + + /************************* + * Public View Functions * + *************************/ + + /// @inheritdoc IZkEvmVerifierV2 + /// + /// @dev Encoding for `publicInput` (v0.9.0 / GalileoV2 bundle proofs): + /// ```text + /// | layer2ChainId | messageQueueHash | numBatches | prevStateRoot | prevBatchHash | postStateRoot | batchHash | withdrawRoot | + /// | 8 bytes | 32 bytes | 4 bytes | 32 bytes | 32 bytes | 32 bytes | 32 bytes | 32 bytes | + /// ``` + /// The hash passed to the plonk verifier is `keccak256(abi.encodePacked(protocolVersion, publicInput))`. + function verify(bytes calldata bundleProof, bytes calldata publicInput) external view override { + address _verifier = plonkVerifier; + bytes32 _verifierDigest1 = verifierDigest1; + bytes32 _verifierDigest2 = verifierDigest2; + bytes32 publicInputHash = keccak256(abi.encodePacked(protocolVersion, publicInput)); + bool success; + + // 1. the first 12 * 32 (0x180) bytes of `bundleProof` is `accumulator` + // 2. the rest bytes of `bundleProof` is the actual `bundle_proof` + // 3. Inserted between `accumulator` and `bundle_proof` are + // 32 * 34 (0x440) bytes, such that: + // | start | end | field | + // |---------------|---------------|-------------------------| + // | 0x00 | 0x180 | bundleProof[0x00:0x180] | + // | 0x180 | 0x180 + 0x20 | verifierDigest1 | + // | 0x180 + 0x20 | 0x180 + 0x40 | verifierDigest2 | + // | 0x180 + 0x40 | 0x180 + 0x60 | publicInputHash[0] | + // | 0x180 + 0x60 | 0x180 + 0x80 | publicInputHash[1] | + // ... + // | 0x180 + 0x420 | 0x180 + 0x440 | publicInputHash[31] | + // | 0x180 + 0x440 | dynamic | bundleProof[0x180:] | + assembly { + let p := mload(0x40) + // 1. copy the accumulator's 0x180 bytes + calldatacopy(p, bundleProof.offset, 0x180) + // 2. insert the public input's 0x440 bytes + mstore(add(p, 0x180), _verifierDigest1) // verifierDigest1 + mstore(add(p, 0x1a0), _verifierDigest2) // verifierDigest2 + for { + let i := 0 + } lt(i, 0x400) { + i := add(i, 0x20) + } { + mstore(add(p, sub(0x5a0, i)), and(publicInputHash, 0xff)) + publicInputHash := shr(8, publicInputHash) + } + // 3. copy all remaining bytes from bundleProof + calldatacopy(add(p, 0x5c0), add(bundleProof.offset, 0x180), sub(bundleProof.length, 0x180)) + // 4. call plonk verifier + success := staticcall(gas(), _verifier, p, add(bundleProof.length, 0x440), 0x00, 0x00) + } + if (!success) { + revert VerificationFailed(); + } + } +} diff --git a/tests/shadow-testing/docker-compose.yml b/tests/shadow-testing/docker-compose.yml new file mode 100644 index 0000000000..e39f5afd05 --- /dev/null +++ b/tests/shadow-testing/docker-compose.yml @@ -0,0 +1,213 @@ +version: "3.8" + +services: + # ─── PostgreSQL (Shadow DB) ──────────────────────────────────────────────── + postgres: + image: postgres:15-alpine + container_name: shadow-postgres + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: shadow_pass + POSTGRES_DB: shadow_rollup + ports: + - "5433:5432" + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 + networks: + - shadow-net + + # ─── Coordinator API ─────────────────────────────────────────────────────── + coordinator: + image: scrolltech/coordinator-api:e2e-test + container_name: shadow-coordinator + profiles: ["coordinator"] + command: + - "--config" + - "/app/conf/config.json" + - "--http" + - "--http.addr" + - "0.0.0.0" + - "--http.port" + - "8390" + ports: + - "8390:8390" + volumes: + - ./follow/configs/coordinator.json:/app/conf/config.json:ro + - ../../coordinator/build/bin/assets_v2:/app/assets:ro + - ../../tests/prover-e2e/mainnet-galileoV2/genesis.json:/app/conf/genesis.json:ro + depends_on: + postgres: + condition: service_healthy + networks: + - shadow-net + restart: unless-stopped + + # ─── Relayer ─────────────────────────────────────────────────────────────── + relayer: + image: ubuntu:22.04 + container_name: shadow-relayer + profiles: ["relayer"] + entrypoint: ["/app/rollup_relayer"] + command: + - "--config" + - "/app/config.json" + - "--genesis" + - "/app/conf/genesis.json" + - "--min-codec-version" + - "7" + - "--verbosity" + - "3" + volumes: + - ./.work/relayer-${CONFIG:-mainnet}.json:/app/config.json:ro + - ../../tests/prover-e2e/mainnet-galileoV2/genesis.json:/app/conf/genesis.json:ro + - ../../rollup/build/bin/rollup_relayer:/app/rollup_relayer:ro + depends_on: + - postgres + networks: + - shadow-net + restart: unless-stopped + + # ─── Anvil (optional — usually started by script for fork flexibility) ───── + anvil: + image: ghcr.io/foundry-rs/foundry:latest + container_name: shadow-anvil + profiles: ["anvil"] + entrypoint: ["anvil"] + command: + - "--fork-url" + - "${FORK_URL:-https://eth-mainnet.g.alchemy.com/v2/demo}" + - "--fork-block-number" + - "${FORK_BLOCK:-25202217}" + - "--block-time" + - "12" + - "--port" + - "8545" + - "--state" + - "/data/anvil.state.json" + ports: + - "18545:8545" + volumes: + - ./states:/data + networks: + - shadow-net + restart: unless-stopped + + # ─── Prover GPU-0 ────────────────────────────────────────────────────────── + prover-gpu-0: + image: scrolltech/prover:${PROVER_VERSION:-e2e-test} + container_name: shadow-prover-gpu-0 + profiles: ["prover"] + ports: + - "10080:10080" + environment: + - RUST_MIN_STACK=16777216 + - CUDA_VISIBLE_DEVICES=0 + volumes: + - ./.work/prover-0.json:/prover/conf/config.json:ro + - ./.work/prover-0:/prover/.work + - ~/.openvm/params:/root/.openvm/params:ro + deploy: + resources: + reservations: + devices: + - driver: nvidia + device_ids: ['0'] + capabilities: [gpu] + depends_on: + - coordinator + networks: + - shadow-net + restart: unless-stopped + + # ─── Prover GPU-1 ────────────────────────────────────────────────────────── + prover-gpu-1: + image: scrolltech/prover:${PROVER_VERSION:-e2e-test} + container_name: shadow-prover-gpu-1 + profiles: ["prover"] + ports: + - "10081:10080" + environment: + - RUST_MIN_STACK=16777216 + - CUDA_VISIBLE_DEVICES=0 + volumes: + - ./.work/prover-1.json:/prover/conf/config.json:ro + - ./.work/prover-1:/prover/.work + - ~/.openvm/params:/root/.openvm/params:ro + deploy: + resources: + reservations: + devices: + - driver: nvidia + device_ids: ['1'] + capabilities: [gpu] + depends_on: + - coordinator + networks: + - shadow-net + restart: unless-stopped + + # ─── Prover GPU-2 ────────────────────────────────────────────────────────── + prover-gpu-2: + image: scrolltech/prover:${PROVER_VERSION:-e2e-test} + container_name: shadow-prover-gpu-2 + profiles: ["prover"] + ports: + - "10082:10080" + environment: + - RUST_MIN_STACK=16777216 + - CUDA_VISIBLE_DEVICES=0 + volumes: + - ./.work/prover-2.json:/prover/conf/config.json:ro + - ./.work/prover-2:/prover/.work + - ~/.openvm/params:/root/.openvm/params:ro + deploy: + resources: + reservations: + devices: + - driver: nvidia + device_ids: ['2'] + capabilities: [gpu] + depends_on: + - coordinator + networks: + - shadow-net + restart: unless-stopped + + # ─── Prover GPU-3 ────────────────────────────────────────────────────────── + prover-gpu-3: + image: scrolltech/prover:${PROVER_VERSION:-e2e-test} + container_name: shadow-prover-gpu-3 + profiles: ["prover"] + ports: + - "10083:10080" + environment: + - RUST_MIN_STACK=16777216 + - CUDA_VISIBLE_DEVICES=0 + volumes: + - ./.work/prover-3.json:/prover/conf/config.json:ro + - ./.work/prover-3:/prover/.work + - ~/.openvm/params:/root/.openvm/params:ro + deploy: + resources: + reservations: + devices: + - driver: nvidia + device_ids: ['3'] + capabilities: [gpu] + depends_on: + - coordinator + networks: + - shadow-net + restart: unless-stopped + +volumes: + postgres-data: + +networks: + shadow-net: + driver: bridge diff --git a/tests/shadow-testing/docs/COMMON-TROUBLESHOOTING.md b/tests/shadow-testing/docs/COMMON-TROUBLESHOOTING.md new file mode 100644 index 0000000000..8faa2bbf4b --- /dev/null +++ b/tests/shadow-testing/docs/COMMON-TROUBLESHOOTING.md @@ -0,0 +1,404 @@ +# Common Troubleshooting & Pitfalls (Mode-Independent) + +> **Read this file first** before starting any shadow fork or shadow coordinator test. +> This file covers pitfalls that apply regardless of mode. Mode-specific traps live in +> [`../follow/TROUBLESHOOTING.md`](../follow/TROUBLESHOOTING.md) (follow mode) and +> [`../snapshot/TROUBLESHOOTING.md`](../snapshot/TROUBLESHOOTING.md) (snapshot replay mode). +> Trap numbers are stable across all three files — "Trap 22" refers to the same trap everywhere. +> This directory contains hard-won knowledge from multiple debugging sessions. Blind experimentation will repeat documented mistakes. + +## Pre-Flight Ritual (Mandatory) + +Before executing a single command: + +1. [ ] **Read root `AGENTS.md`** — refresh the trap list. +2. [ ] **Read this file plus the per-mode `TROUBLESHOOTING.md`** (`follow/TROUBLESHOOTING.md` or `snapshot/TROUBLESHOOTING.md`) — check if your planned task matches any documented failure mode. +3. [ ] **Read the per-mode `GUIDE.md`** (`follow/GUIDE.md` or `snapshot/GUIDE.md`) — verify the specific section matching your task (e.g., "Real Verifier Deployment", "Multi-Bundle Relayer Finalize Test"). +4. [ ] **Verify network** — confirm you are testing **Mainnet** or **Sepolia**, and all configs/ports/RPCs match that network. +5. [ ] **Verify target bundle range** — query the DB to confirm: + - Bundles exist and have `proving_status = 4` (or will be regenerated) + - Parent batch of the first target batch exists in the DB + - All bundle end batches have `committedBatches` entries on Anvil (or will be seeded) + +## Mainnet vs Sepolia — Decision Table + +| Check | Mainnet | Sepolia | Verification Command | +|-------|---------|---------|---------------------| +| DB port | `5433` or `15432` | `25432` | `psql -h localhost -p -c "SELECT version();"` | +| L2 RPC | `l2geth-rpc-proxy.mainnet.aws.scroll.io` | `l2geth-rpc-proxy.sepolia.aws.scroll.io` | `curl -X POST -d '{"method":"debug_executionWitness","params":["latest"],"id":1}'` | +| Anvil fork URL | `eth-mainnet.g.alchemy.com` | `eth-sepolia.g.alchemy.com` | `cast block-number --rpc-url ` | +| ScrollChain proxy | `0xa13BAF47339d63B743e7Da8741db5456DAc1E556` | `0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0` | `cast call "lastFinalizedBatchIndex()(uint256)"` | +| MVRV | `0x4CEA3E866e7c57fD75CB0CA3E9F5f1151D4Ead3F` | `0x8A360c7F6fca548507017DdeD732bFe7E078F963` | `cast call "latestVerifier(uint256)" 10` | +| L1MessageQueueV2 | `0x56971da63A3C0205184FEF096E9ddFc7A8C2D18a` | `0xA0673eC0A48aa924f067F1274EcD281A10c5f19F` | `cast call "nextUnfinalizedQueueIndex()(uint256)"` | +| Verifier | Copy from mainnet (`anvil_setCode`) | Check MVRV first; may already match | `cast call "getVerifier(uint256,uint256)" 10 ` | + +## Critical Traps (Do Not Skip) + +### Trap 1: Wrong Verifier Contract or Wrong Digest Form +- **Symptom**: `VerificationFailed(0x439cc0cd)` even with correct digests. +- **Cause A**: Deployed `ZkEvmVerifierPostEuclid` instead of `ZkEvmVerifierPostFeynman`. +- **Cause B**: Used digests in the wrong form. For v0.9.0 the S3 `digest_1.hex` / `digest_2.hex` files are published in **canonical form**, but if you are re-using an old v0.8.0 workflow that converted from Montgomery form, double-check you are not applying the conversion twice. +- **Cause C**: **MVRV routes the batch to the wrong verifier**. The deployed verifier's digests are correct, but `MultipleVersionRollupVerifier.getVerifier(10, batchIndex)` returns an old verifier with different digests. This happens when re-proving bundles with a new prover (new digests) whose batch indices fall in a range still mapped to a legacy verifier. +- **Rule**: For guest v0.9.0 proofs, **always use `PostFeynman`** with digests from `.../releases/v0.9.0/bundle/digest_*.hex`, and **verify MVRV routing** before finalizing. +- **Verification — Digests**: Fetch canonical digests from S3 and deploy with `protocolVersion = 10`: + ```bash + BASE_URL="https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/releases/v0.9.0" + DIGEST1=$(curl -fsSL "${BASE_URL}/bundle/digest_1.hex" | tr -d '[:space:]') + DIGEST2=$(curl -fsSL "${BASE_URL}/bundle/digest_2.hex" | tr -d '[:space:]') + ``` + The S3 files are already in canonical form; no conversion or proof extraction is required. +- **Verification — MVRV Routing**: Before finalizing, confirm the verifier returned by MVRV for each target batch matches the verifier whose digests match the proofs: + ```bash + for idx in 128069 128070 128071; do + cast call $MVRV "getVerifier(uint256,uint256)(address)" 10 $idx --rpc-url $ANVIL_RPC + done + ``` + If any batch returns the old verifier while proofs use new digests, update MVRV: + ```bash + cast rpc anvil_impersonateAccount $OWNER --rpc-url $ANVIL_RPC + cast send $MVRV \ + "updateVerifier(uint256,uint64,address)" \ + 10 $START_BATCH $NEW_VERIFIER \ + --from $OWNER --rpc-url $ANVIL_RPC --unlocked + ``` + +### Trap 2: Anvil Forks Wrong Chain +- **Symptom**: `ScrollChain` proxy has no code, or `eth_chainId` returns `534352`. +- **Cause**: Anvil pointed at Scroll L2 RPC instead of Ethereum L1 RPC. +- **Rule**: Anvil must fork **Ethereum L1** (`chainId=1`). The ScrollChain proxy lives on L1. + +### Trap 3: L2 RPC Missing `debug_executionWitness` +- **Symptom**: Coordinator panics at startup or chunks never get assigned. +- **Cause**: Public RPC (`mainnet-rpc.scroll.io`, `sepolia-rpc.scroll.io`) blocks debug methods. +- **Rule**: Use **internal** L2 RPC proxies only. + +### Trap 7: Relayer Nonce Desync + +> **Fixed upstream / harness**: the relayer sender config now supports `chain_nonce_only` (default false), which initializes the nonce from the chain pending nonce only, ignoring `pending_transaction` — the shadow relayer config template sets it. Additionally `10-follow-up.sh --reset` now TRUNCATEs `pending_transaction` (the rows are not chain/fork-scoped and can also replay old calldata onto a fresh fork). The manual fix below is only needed if you run a relayer without those. + +- **Symptom**: Tx sent but never mined; `eth_getTransactionReceipt` returns null forever. +- **Cause**: `pending_transaction` table retains nonces from previous runs that were never confirmed. Relayer initializes nonce from `maxDbNonce + 1`, which is ahead of the on-chain nonce. +- **Rule**: After any relayer crash or Anvil restart: + ```sql + DELETE FROM pending_transaction WHERE sender_address = ''; + ``` + Then restart the relayer. + +### Trap 9: Anvil `eth_estimateGas` Rejects Fee Caps + +> **Fixed upstream**: `rollup/internal/controller/sender/estimategas.go` now sends an explicit non-zero gas cap in the estimation `CallMsg`, so Anvil no longer rejects fee-capped estimate calls. This entry is kept for reference when running older relayer builds. + +- **Symptom**: `failed to get fee data, err: Out of gas: gas required exceeds allowance: 0`. +- **Cause**: Anvil's `eth_estimateGas` fails when `CallMsg` has `GasFeeCap`/`GasTipCap` set but `Gas` is 0 (Go Ethereum client's default). +- **Rule**: If you hit this on a shadow fork, the correct fix belongs in the upstream `rollup/internal/controller/sender/estimategas.go` (do not maintain a local patch in this branch). Verify with the latest `develop` code and, if still present, fix it there so all shadow tests benefit. + +### Trap 10: Sender Balance Lost After Anvil Restart +- **Symptom**: `failed to send transaction, err: Insufficient funds for gas * price + value` even after successful gas estimation. +- **Cause**: `anvil_setBalance` funds do not persist across Anvil restarts. +- **Rule**: After every Anvil restart, verify and re-fund sender EOAs before starting the relayer: + ```bash + cast balance 0x410E7FD80a3Fc1E62A4D3450d11b71b812006eB9 --rpc-url http://localhost:18546 + ``` + +### Trap 11: Relayer Started Without Required Flags +- **Symptom**: Relayer prints help and exits with `Required flag "min-codec-version" not set`, or connects to wrong DB. +- **Cause**: `ROLLUP_RELAYER_CONFIG` env var is NOT supported. The relayer uses `--config` CLI flag. +- **Rule**: Always start relayer with BOTH flags: + ```bash + ./rollup_relayer --config /path/to/config.json --min-codec-version 10 + ``` + +### Trap 12: halo2 SRS Not in `~/.openvm/params/` +- **Symptom**: chunk/batch proofs succeed; the **first bundle proof** crashes the prover with + `Params file ".../.openvm/params/kzg_bn254_23.srs" does not exist`. Bundle stuck at `proving_status=2`. +- **Cause**: openvm reads the KZG SRS from `$HOME/.openvm/params/kzg_bn254_{22,23,24}.srs` only at the + bundle proof's halo2 stage; if the `.srs` files sit in `~/.openvm/` root (or anywhere else) they are + silently not found. +- **Rule**: `mkdir -p ~/.openvm/params && mv ~/.openvm/kzg_bn254_2{2,3,4}.srs ~/.openvm/params/`. Mount the + host openvm dir to `/root/.openvm` (writable) for the prover container and confirm the path resolves. + +### Trap 13: Prover Docker `--gpus device=N` + Wrong `CUDA_VISIBLE_DEVICES` +- **Symptom**: prover container exits (code 139) with `cudaErrorNoDevice: no CUDA-capable device is detected`; + only the GPU-0 prover works. +- **Cause**: `--gpus "device=N"` exposes only that GPU and **renumbers it to index 0** inside the container, + so `CUDA_VISIBLE_DEVICES=N` points at a nonexistent device. +- **Rule**: use `--gpus "device=$i"` with `CUDA_VISIBLE_DEVICES=0` (or `--gpus all` with `CUDA_VISIBLE_DEVICES=$i`). + +### Trap 14: Coordinator Verifier Assets vs Prover Circuit S3 Paths (v0.9.0) +- **Symptom**: coordinator asset download 403s or prover cannot find circuit apps. +- **Cause**: Starting with v0.9.0, both verifier assets and circuit apps are released under a unified `scroll-zkvm/releases/v0.9.0/` prefix. Earlier versions split them across `v0.8.0/verifier/` and `scroll-zkvm/galileov2/`. +- **Rule**: For v0.9.0, point both coordinator verifier assets and prover `circuits.galileoV2.base_url` at `…/scroll-zkvm/releases/v0.9.0/`. The expected layout is `{chunk,batch,bundle}//` for circuits and `verifier/` for coordinator assets. + +### Trap 16: Stale Proofs After Source-Code Revert / Restore + +- **Symptom**: Batch proof fails with `VM error: execution error: program exit code 1`, or bundle proof fails with `mismatch batch-proof exe commitment: expected=..., got=...`. +- **Cause**: The shadow DB contains chunk/batch proofs generated by a different code version (e.g. before a `git revert` and subsequent restore of v0.9.0 source adaptations). The stored proofs verify individually because the coordinator loads the same verifier, but the next-level prover rejects their execution commitment. +- **Rule**: After any non-trivial source change (Rust guest code, OpenVM version, `Cargo.lock`, or `rust-toolchain`), **treat existing shadow proofs as suspect**. Reset all relevant chunks, batches, and bundles to `proving_status = 1, proof = NULL` and re-prove from the lowest level. Do not rely on `proving_status = 4` alone. + +### Trap 17: `coordinator_cron` Re-Marks Corrupt Bundles as Ready + +- **Symptom**: Log is flooded with `format bundle prover task failure: unexpected end of JSON input` for high-index bundles, wasting prover cycles. +- **Cause**: `coordinator_cron` periodically scans batches and sets `bundle.batch_proofs_status = 2` when all member batches have `proving_status = 4`. If those batch proofs are `NULL`/corrupt (Trap 16), the bundle becomes "ready" and is assigned repeatedly. +- **Rule**: While cleaning up stale proofs, either: + 1. Stop `coordinator_cron` until all corrupt proofs are regenerated, or + 2. Reset **all** corrupt bundles/batches/chunks (`proving_status = 4 AND proof IS NULL`) to `proving_status = 1` so the cron never sees them as ready. + +### Trap 19: `miscData.lastCommittedBatchIndex` Desync → `ErrorBatchNotCommitted` (0x227a699e) + +- **Symptom**: `finalizeBundlePostEuclidV2` reverts with custom error `0x227a699e` during `eth_estimateGas`, even though `committedBatches[batchIndex]` on the fork matches the DB hash exactly. +- **Cause**: The deployed (Post-Feynman) ScrollChain rejects finalization when `batchIndex > miscData.lastCommittedBatchIndex`. `committedBatches[i]` being set is **not sufficient** — the bound check uses `miscData.lastCommittedBatchIndex` (slot `0xa1`, lowest 8 bytes). On mainnet `lastCommittedBatchIndex` is usually far ahead of `lastFinalizedBatchIndex`; if setup scripts (or manual patches) set it equal to the rewound `lastFinalizedBatchIndex`, every batch between the two becomes un-finalizable. +- **Diagnosis**: + ```bash + cast call $SCROLL_CHAIN "miscData()(uint64,uint64,uint32,bool)" --rpc-url $ANVIL_RPC + # field 1 = lastCommittedBatchIndex, field 2 = lastFinalizedBatchIndex + cast call $SCROLL_CHAIN "miscData()(uint64,uint64,uint32,bool)" --rpc-url $FORK_URL --block $FORK_BLOCK + ``` +- **Fix**: Patch slot `0xa1`, keeping the high bytes (reserved + flags + timestamp) intact and only replacing the two index fields: + ```bash + # lastCommitted=518665 (0x7ea09, real fork value), lastFinalized=518505 (0x7e969) + cast rpc anvil_setStorageAt $SCROLL_CHAIN 0xa1 \ + 0x0000000000000000000000016a537382000000000007e969000000000007ea09 \ + --rpc-url $ANVIL_RPC + ``` +- **Rule**: `01-setup-anvil.sh` now reads the real `lastCommittedBatchIndex` from fork state by default and preserves timestamp/flags. Only pass `--last-committed` when you deliberately want a different value. Do not set it too high either: `commitBatches` requires `parentBatchHash == committedBatches[lastCommittedBatchIndex]`, so an inflated value breaks future commits on the fork. + +### Trap 20: `nextCrossDomainMessageIndex` Too Low → `ErrorFinalizedIndexTooLarge` (0x16465978) + +- **Symptom**: After fixing Trap 19, finalization reverts with `execution reverted: \x16FYx` (selector `0x16465978`). +- **Cause**: `_afterFinalizeBatch` calls `L1MessageQueueV2.finalizePoppedCrossDomainMessage(totalL1MessagesPoppedOverall)`, which reverts if the new index exceeds `nextCrossDomainMessageIndex` (slot `0x67`). This happens when a manual patch or stale `--state` file left `nextCrossDomainMessageIndex` below the queue indices your batches pop. +- **Diagnosis**: + ```bash + cast call $MQV2 "nextCrossDomainMessageIndex()(uint256)" --rpc-url $ANVIL_RPC + cast call $MQV2 "nextCrossDomainMessageIndex()(uint256)" --rpc-url $FORK_URL --block $FORK_BLOCK + # also confirm the rolling hash the proof expects exists: + cast call $MQV2 "getMessageRollingHash(uint256)(bytes32)" $((TOTAL_L1 - 1)) --rpc-url $ANVIL_RPC + ``` +- **Fix**: Bump slot `0x67` to the real fork value (e.g. 998603 = `0xf3ccb`): + ```bash + cast rpc anvil_setStorageAt $MQV2 0x67 0x00000000000000000000000000000000000000000000000000000000000f3ccb --rpc-url $ANVIL_RPC + ``` + Never lower `nextUnfinalizedQueueIndex` (slot `0x68`) below a bundle's `totalL1MessagesPoppedOverall` — that yields `ErrorFinalizedIndexTooSmall` instead. +- **Rule**: `01-setup-anvil.sh` now defensively bumps slot `0x67` to the fork value when it is lower. Decode the revert selector first — `0x227a699e` and `0x16465978` look similar in relayer logs but have different roots. + +### Trap 21: Stale Cached Proof in Prover Local DB → VData Shape Mismatch + +- **Symptom**: Coordinator logs `proof generated by prover failed ... Proof shape verification failed: Invalid VData: Proof trace_vdata length (44) does not match number of AIRs (42)` with `proofTime=2` (i.e. instant submission from cache, not a real proof run). +- **Cause**: The prover's local LevelDB (`/db`) caches proofs keyed by task. A proof generated under a different circuit/asset version (e.g. before an S3 asset refresh or code revert/restore) is replayed and rejected by the coordinator's shape check. +- **Rule**: Fresh proofs (proofTime ~300s for bundles) from other provers succeed for the same task, so this is self-healing as long as one prover has a clean cache. To stop a prover from repeatedly burning attempts on a poisoned cache, stop it, delete `/db`, and restart. When switching circuit versions, wipe all prover local DBs as part of the reset ritual (same spirit as Trap 16). + +### Trap 24: `coordinator_cron` Collection Timeouts Shorter Than Real Proof Times → False Timeouts, Duplicate Dispatch, Attempt Exhaustion [both] + +- **Symptom**: Repeated `proof task have reach the timeout` warnings in coordinator logs for the **same task id**; the same bundle gets proved twice by different provers; submissions race and the loser gets a benign `validator failure chunk/batch have proved and verified success` reject from `proof_receiver.go`. +- **Cause**: The timeout checker (`coordinator/internal/controller/cron/collect_proof.go`) scans the `prover_task` table every cycle and marks tasks timed out after `{chunk,batch,bundle}_collection_time_sec`. On timeout it invalidates the `prover_task`, decrements `active_attempts`, and **permanently fails the task once `total_attempts >= session_attempts` (5)**. Observed incident: `configs/coordinator.json` had `bundle_collection_time_sec = 180` while real bundle proofs take ~335 s (up to ~90 min for 30-batch bundles). Every bundle task falsely timed out at 180 s, got duplicate-dispatched to a second prover (2× GPU waste), and the two submissions raced. +- **Fix**: Set the collection timeouts well above real proof times in `configs/coordinator.json` (and `configs/coordinator.json.template`): + - `bundle_collection_time_sec ≥ 7200` + - `chunk_collection_time_sec = 3600` and `batch_collection_time_sec = 180` are fine vs ~117 s / ~25 s actuals. + - **Remember**: the timeout checker runs in `coordinator_cron`, so the **cron's** config is the one that matters, not `coordinator_api`'s. +- **Structural gap**: **Note (fixed upstream)**: the coordinator now refunds the charged attempt (both `total_attempts` and `active_attempts`, status back to unassigned) when dispatch fails after `Update*Attempts` — see `recoverAttempts` in `internal/logic/provertask/*_prover_task.go` and `orm.RefundAttemptsByHash` — so format-failure paths no longer leave invisible half-charged tasks; the sweeper reset below is belt-and-braces. Historical description: if task formatting fails *after* attempts are incremented but *before* the `prover_task` row is inserted (e.g. the Trap 22 block-hash failure), no `prover_task` row exists and the timeout checker can never see it. The `sweep-stale-proving.sh` daemon is the safety net — this is why the sweeper also resets `total_attempts`, not just `proving_status`. + +## Step-by-Step Checklist + +### Phase 0: Environment Validation +- [ ] DB reachable on correct port +- [ ] L2 RPC supports `debug_executionWitness` +- [ ] Anvil not already running on target port +- [ ] Coordinator port 8390 free +- [ ] Prover GPU available (`nvidia-smi`) + +### Phase 1: DB Setup +- [ ] Import bundle range from production RDS +- [ ] **Exclude `proof` columns** from import +- [ ] Reset `proving_status = 1` for chunks, batches, bundles +- [ ] Insert missing parent batch skeleton +- [ ] Populate `l2_block` table and link via `chunk_hash` + +### Phase 2: Anvil Fork Setup +- [ ] Start Anvil forked from **Ethereum L1** (not Scroll L2) +- [ ] Verify `eth_chainId == 1` +- [ ] Fund owner and sender accounts (verify balances after any Anvil restart) +- [ ] Add prover EOA to `ScrollChain` +- [ ] Set `lastFinalizedBatchIndex` to `(first_target_batch - 1)` +- [ ] Set `lastCommittedBatchIndex` to mainnet value (do NOT reset to lastFinalized) +- [ ] (Sepolia) Verify end-batch `committedBatches` hashes are non-zero on Anvil +- [ ] (Sepolia) Set `L1MessageQueueV2.nextUnfinalizedQueueIndex` to pre-finalization value: + ```sql + SELECT MIN(total_l1_messages_popped_before) + FROM chunk + WHERE batch_hash = (SELECT hash FROM batch WHERE index = ); + ``` +- [ ] (Sepolia) **Verify slot number with `forge inspect L1MessageQueueV2 storage-layout`** before `anvil_setStorageAt` + +### Phase 3: Verifier Setup + +**Determine which scenario you are in:** + +**Scenario A — Re-using production proofs (like bundles 13445-13449)** +- [ ] Extract digests from proof instances +- [ ] Query Sepolia MVRV: `cast call "getVerifier(uint256,uint256)" 10 ` +- [ ] Query verifier digests: `cast call "verifierDigest1()"` / `"verifierDigest2()"` +- [ ] If digests match → **skip deployment**, use existing verifier +- [ ] If digests DON'T match → you are actually in Scenario B + +**Scenario B — Testing new guest / circuit version (0.8.0 / openvm 1.6+)** +- [ ] Generate new proofs with the new prover (coordinator + prover pipeline) +- [ ] Extract digests from **newly-generated** proof instances +- [ ] Deploy plonk verifier from `coordinator/build/bin/assets_v2/verifier.bin` +- [ ] Deploy `ZkEvmVerifierPostFeynman` with new digests + `protocolVersion = 10` +- [ ] Register on `MultipleVersionRollupVerifier` via `updateVerifier(10, startBatch, verifier)` +- [ ] Verify with `getVerifier(10, batchIndex)` + +### Phase 4: Coordinator + Prover +- [ ] Coordinator config points to correct `assets_v2/` directory +- [ ] Coordinator L2 RPC is internal/debug-enabled +- [ ] Prover config `base_url` uses correct S3 path (no `/releases/` for v0.8.0) +- [ ] Start coordinator, wait for `Start coordinator api successfully` +- [ ] Start prover(s), verify `Got task from coordinator` + +### Phase 5: Relayer Finalize +- [ ] Build relayer with latest code (rebuild if `estimategas.go` was patched for Anvil) +- [ ] Relayer config has `dry_run: false`, correct contract addresses +- [ ] Clear stale `pending_transaction` entries +- [ ] Reset target bundles/batches to `rollup_status = 1` +- [ ] **Sync `batch.withdraw_root` from batch proof metadata** (shadow fork only; see Trap 10) +- [ ] **Start relayer with `--config ` AND `--min-codec-version 10`** +- [ ] Monitor logs for `finalizeBundle in layer1` success +- [ ] Verify `lastFinalizedBatchIndex` advanced on Anvil + +## When Things Go Wrong + +| Error / Symptom | Most Likely Cause | See | +|-----------------|-------------------|-----| +| `VerificationFailed(0x439cc0cd)` | Wrong verifier type, digest mismatch, **or wrong bundle withdrawRoot**; in follow mode: post-fork L1 queue hashes missing | Trap 1, **Trap 10**, Trap 23 | +| `ErrorIncorrectBatchHash(0x2a1c1442)` | Sparse `committedBatches`, end batch hash is zero | Trap 4 | +| `ErrorFinalizedIndexTooLarge(0x16465978)` | `nextUnfinalizedQueueIndex`/`nextCrossDomainMessageIndex` too low | Trap 5, Trap 20, Trap 23 | +| Follow mode stalls: `failed to fetch block hashes of a chunk` | Poll-synced chunks lack `l2_block` linkage | Trap 22 | +| Old pending chunks never get sessions, no ERROR logged | `total_attempts >= 5` starvation; sweep must reset `total_attempts` | Trap 22 | +| Chunks verified but batch/bundle sessions never start | NULL `batch_hash`/`bundle_hash` parent links from poll sync | Trap 22 | +| Repeated `proof task have reach the timeout` for the same task id; duplicate proving; `have proved and verified success` rejects | Collection timeout misconfiguration (`*_collection_time_sec` < real proof times) in the **cron's** config | Trap 24 | +| `record not found` (parent batch) | Parent batch not imported | Trap 6 | +| `Out of gas: gas required exceeds allowance: 0` | Anvil gas estimation bug with fee caps | Trap 9 | +| `Insufficient funds for gas * price + value` | Sender balance is 0 on Anvil | Trap 10 | +| Tx sent but never mined | Nonce desync (`pending_transaction` stale) | Trap 7 | +| Relayer exits with `Required flag "min-codec-version" not set` | Missing CLI flags | Trap 11 | +| Coordinator assigns but prover gets nothing | L2 RPC missing `debug_executionWitness` | README.md | +| `CoordinatorEmptyProofData` | Prover crashed; reset stuck tasks | README.md | +| `Params file ".../kzg_bn254_23.srs" does not exist` (bundle proof crash) | halo2 SRS not in `~/.openvm/params/` | Trap 12 | +| Prover exits 139 `cudaErrorNoDevice` | `--gpus device=N` + wrong `CUDA_VISIBLE_DEVICES` | Trap 13 | +| Coordinator asset download 403 (`galileov2/verifier/...`) | Wrong S3 prefix; use `v0.8.0/verifier/` | Trap 14 | +| `l2_block` export hangs for minutes | Slow `chunk_hash` JOIN; export by block-number range | Trap 15 | +| `mismatch batch-proof exe commitment` or batch proof `VM error: execution error: program exit code 1` | Stale chunk/batch proofs generated by an earlier/reverted code version | Trap 16 | +| `format bundle prover task failure: unexpected end of JSON input` in a loop | `coordinator_cron` re-marks corrupt bundles as ready; stop cron or reset all stale proofs | Trap 17 | +| Provers busy but target bundles never prove | Newer bundles/batches created by relayer compete for prover slots | Trap 18 | + +## Lessons from the v0.9.0 Multi-Bundle Shadow Test + +The following issues were hit while finalizing bundles 17297–17301 (batches 517761–517765) on an Anvil mainnet fork with zkvm guest prover v0.9.0. Keep them in mind for future upgrades. + +### 1. Do not `git checkout --` uncommitted source changes blindly + +When cleaning up the branch, the v0.9.0 source adaptations (`libzkp`, `prover-bin`, Go `message` types, `rust-toolchain`, `Cargo.lock`) were accidentally reverted because they were not committed. They had to be reconstructed from compiler errors. Always check `git diff --stat` before a bulk revert, and stage or stash anything you intend to keep. + +### 2. `finalizeBundlePostEuclidV2` is the only finalize function, but the verifier must be Post-Feynman + +`ScrollChain` exposes only one bundle-finalize selector (`0xc1aa4e19`). The name says `PostEuclidV2`, but the verifier it actually calls is chosen by `MultipleVersionRollupVerifier.getVerifier(10, batchIndex)`. For GalileoV2 / v0.9.0 this must be a `ZkEvmVerifierPostFeynman`-style wrapper whose `protocolVersion` immutable is `10`. + +- `ZkEvmVerifierPostEuclid` computes `keccak256(publicInput)` — this is old code and will reject current proofs. +- `ZkEvmVerifierPostFeynman` computes `keccak256(protocolVersion || publicInput)` — this matches v0.9.0 `bundle_pi_hash`. + +For v0.9.0 GalileoV2 bundle proofs, `publicInput` is encoded as: + +```text +| layer2ChainId | messageQueueHash | numBatches | prevStateRoot | prevBatchHash | postStateRoot | batchHash | withdrawRoot | +| 8 bytes | 32 bytes | 4 bytes | 32 bytes | 32 bytes | 32 bytes | 32 bytes | 32 bytes | +``` + +The `messageQueueHash` is included in the public input (derived from `L1MessageQueueV2` by the contract). Older wrapper comments/documents may show the format without `messageQueueHash`; that format is for pre-GalileoV2 proofs. + +### 3. Copying the mainnet verifier via `anvil_setCode` fails for new guest versions + +`anvil_setCode` copies runtime bytecode but **preserves the original immutables** (`plonkVerifier`, `verifierDigest1/2`, `protocolVersion`). If your local v0.9.0 proofs use different digests than mainnet, the wrapper will return `VerificationFailed`. For a new guest version, deploy a fresh `ZkEvmVerifierPostFeynman` using the S3 release digests. + +### 4. MVRV routing must be verified per target batch + +After deploying a new verifier, confirm that `MVRV.getVerifier(10, batchIndex)` returns your wrapper for every batch you intend to finalize. If the fork block already contains a later mainnet verifier registration, a plain `updateVerifier` may be rejected; force the storage slot or impersonate the owner as needed for the shadow fork. + +### 5. v0.9.0 dependency graph needs a fresh `Cargo.lock` + +Pointing `Cargo.toml` to v0.9.0 is not enough. The first `cargo check` hit a revm version conflict because the old `Cargo.lock` pinned incompatible crate versions. Regenerating `Cargo.lock` resolved it. + +### 6. Prover aggregation circuits need deferral enabled + +OpenVM v2+ requires `Prover::enable_deferral(child_prover)` before proving aggregation tasks: + +- Batch proving needs a chunk child prover. +- Bundle proving needs a batch child prover. + +The prover config therefore needs `child_circuit_vks` so the prover can load the correct child circuit assets. + +### 7. S3 digest files are canonical — no proof extraction needed + +For v0.9.0, `.../releases/v0.9.0/bundle/digest_1.hex` and `digest_2.hex` are published in the canonical form expected by the Plonk verifier. Do not apply Montgomery→canonical conversion and do not extract digests from proof `instances` unless you are double-checking a specific artifact. + +### 8. Resetting bundles may require regenerating the entire proof chain + +When re-testing bundles 20000–20004 after the branch's source adaptations were reverted and restored, the existing chunk and batch proofs in the shadow DB no longer matched the current prover's execution commitments. The only reliable fix was to reset **all** chunks, batches, and bundles in the target range (`proving_status = 1, proof = NULL`) and let the provers rebuild the chain from scratch. + +- Do not assume `proving_status = 4` means the proof is compatible with the current code. +- Stop `coordinator_cron` while cleaning stale proofs, or it will re-mark corrupt bundles as ready and flood the log with `format bundle prover task failure`. +- Stop the relayer if you only need a fixed imported range; otherwise live L2 blocks create new batches that compete for prover time. + +### 10. Relayer must use the bundle withdrawRoot from proof metadata + +**Symptom**: `VerificationFailed(0x439cc0cd)` during relayer finalization even though the verifier digests and MVRV routing are correct. + +**Root cause**: The relayer was passing `dbBatch.WithdrawRoot` to `finalizeBundlePostEuclidV2`. In shadow-test setups, the batch table's top-level `withdraw_root` column can be stale: + +- `fetch-l2-blocks.py` cannot read `withdraw_root` from a standard L2 RPC, so it writes `0x0...0` into `l2_block.withdraw_root`. +- That placeholder propagates to `chunk.withdraw_root` and `batch.withdraw_root`. +- The prover correctly recomputes the real withdraw root while generating batch proofs and stores it in `batch.proof -> metadata.batch_info.withdraw_root` (and later in the bundle proof metadata). +- The contract uses the passed `withdrawRoot` when computing the public input hash, so a stale `0x0...0` produces a hash that does not match the proof's `bundle_pi_hash`. + +**Fix (relayer)**: Use the withdraw root from the verified bundle proof metadata when packing the finalize calldata: + +```go +if aggProof.MetaData.BundleInfo == nil { + return nil, fmt.Errorf("bundle %d proof metadata missing BundleInfo", dbBatch.Index) +} +withdrawRoot := aggProof.MetaData.BundleInfo.WithdrawRoot +``` + +**Fix (shadow DB)**: After batch proofs are verified, sync the top-level `batch.withdraw_root` column from the proof metadata so the DB is consistent: + +```bash +cd tests/shadow-testing/scripts +DB_DSN="postgresql://postgres:shadow_pass@localhost:5433/shadow_rollup" \ + python3 09-sync-batch-withdraw-roots.py --batch-range 517766:517795 +``` + +**Verification**: Decode the relayer's finalize calldata and confirm `withdrawRoot` equals `proof.metadata.bundle_info.withdraw_root`: + +```bash +# The 4th argument of finalizeBundlePostEuclidV2(bytes,uint256,bytes32,bytes32,bytes) +python3 -c "from eth_abi import decode; d=bytes.fromhex(open('/tmp/calldata.hex').read().strip()[8:]); \ + print('withdrawRoot:', '0x'+decode(['bytes','uint256','bytes32','bytes32','bytes'], d)[3].hex())" +``` + +**Production note**: On mainnet the `l2_block.withdraw_root` column is populated correctly, so `batch.withdraw_root` is trustworthy. The relayer change is defensive; the DB sync script is only needed for shadow forks that rely on `fetch-l2-blocks.py`. + +### 11. Large bundles (30 batches) are much slower than single-batch bundles + +The first successful shadow test finalized five single-batch bundles (17297–17301). The follow-up test targeted bundles 20000–20004, which are mostly 30-batch bundles. Plan timing accordingly: + +- Single-batch bundle proof: ~10–20 minutes. +- 30-batch bundle proof: ~30–90 minutes, depending on block complexity and GPU. + +With four GPUs, five 30-batch bundles can take 1–3 hours for the bundle proofs alone, after chunk and batch proofs are ready. + +## Documentation Priority + +When debugging, read docs in this order: + +1. `docs/COMMON-TROUBLESHOOTING.md` + the per-mode `TROUBLESHOOTING.md` (`follow/` or `snapshot/`) — fastest path to known traps +2. The per-mode `GUIDE.md` (`follow/GUIDE.md` or `snapshot/GUIDE.md`) — detailed setup and procedures +3. `README.md` — quick reference for common commands +4. `../../AGENTS.md` (repo root) — cross-network rules and secrets reference diff --git a/tests/shadow-testing/docs/TROUBLESHOOTING.md b/tests/shadow-testing/docs/TROUBLESHOOTING.md new file mode 100644 index 0000000000..afe2cf166f --- /dev/null +++ b/tests/shadow-testing/docs/TROUBLESHOOTING.md @@ -0,0 +1,7 @@ +# Troubleshooting & Pitfalls + +This document has been split by mode. Trap numbers are stable across all three files. + +- [`COMMON-TROUBLESHOOTING.md`](COMMON-TROUBLESHOOTING.md) — mode-independent traps (environment, verifier, relayer, prover setup) and the step-by-step checklist +- [`../follow/TROUBLESHOOTING.md`](../follow/TROUBLESHOOTING.md) — follow-mode traps (poll sync, starvation, live-mainnet finalization) +- [`../snapshot/TROUBLESHOOTING.md`](../snapshot/TROUBLESHOOTING.md) — snapshot-replay traps (historical fork, fixed bundle range, Sepolia) diff --git a/tests/shadow-testing/docs/contract-addresses.md b/tests/shadow-testing/docs/contract-addresses.md new file mode 100644 index 0000000000..c9fdec1c8e --- /dev/null +++ b/tests/shadow-testing/docs/contract-addresses.md @@ -0,0 +1,81 @@ +# Scroll L1 Contract Addresses + +> Auto-generated from genesis configs and on-chain queries. +> Last updated: 2026-05-31 + +## Mainnet (Ethereum L1) + +| Contract | Address | Verified Source | +|----------|---------|-----------------| +| **ScrollChain Proxy** | `0xa13BAF47339d63B743e7Da8741db5456DAc1E556` | [Etherscan](https://etherscan.io/address/0xa13BAF47339d63B743e7Da8741db5456DAc1E556) | +| ScrollChain Implementation | `0x0a20703878e68E587c59204cc0EA86098B8c3bA7` | (from proxy slot) | +| **MultipleVersionRollupVerifier** | `0x4CEA3E866e7c57fD75CB0CA3E9F5f1151D4Ead3F` | [Etherscan](https://etherscan.io/address/0x4CEA3E866e7c57fD75CB0CA3E9F5f1151D4Ead3F) | +| L1MessageQueueV1 | `0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B` | genesis.json | +| L1MessageQueueV2 | `0x56971da63A3C0205184FEF096E9ddFc7A8C2D18a` | genesis.json | +| L2SystemConfig | `0x331A873a2a85219863d80d248F9e2978fE88D0Ea` | genesis.json | +| Scroll Owner | `0x798576400F7D662961BA15C6b3F3d813447a26a6` | `owner()` on-chain | + +### Mainnet Verifier History (from on-chain) + +| Version | Start Batch | Verifier Address | Type | +|---------|-------------|------------------|------| +| 7 | 364,588 | `0xc084a6De8b0F2742396572d6f110eC87ca9329bA` | legacy | +| 8 | 0 | `0xa8d4702Aa5c09AF5dD1323E1842a43789021F485` | pre-v0.8.0 | +| 8 | 0 | `0xc3230A4C89a5Ce0455414215e533de4D8849b3f8` | Anvil-deployed (wrong digests) | +| **10** | 0 | `0x0dE180164Dc571522457101F5c47B2eaB36d0A82` | **GalileoV2 (mainnet)** | + +### Mainnet Batch Status (as of block ~25,213,000) + +- `lastCommittedBatchIndex`: ~517,843 +- `lastFinalizedBatchIndex`: 517,843 +- `committedBatches(517809)`: `0xeadeee9af865c6d13df6b66a45b3f3f161e6211aeb7d86e075a645f0e6a58f9e` +- `committedBatches(517843)`: `0x40545c71ed8fdcaabc06ad64599e9fdd4a62c1e2fd599a6642f64d229f7762a6` + +--- + +## Sepolia (Ethereum Testnet) + +| Contract | Address | Source | +|----------|---------|--------| +| **ScrollChain Proxy** | `0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0` | genesis.json | +| **MultipleVersionRollupVerifier** | `0x8A360c7F6fca548507017DdeD732bFe7E078F963` | `verifier()` on Sepolia | +| L1MessageQueueV1 | `0xF0B2293F5D834eAe920c6974D50957A1732de763` | genesis.json | +| L1MessageQueueV2 | `0xA0673eC0A48aa924f067F1274EcD281A10c5f19F` | genesis.json | +| L2SystemConfig | `0xF444cF06A3E3724e20B35c2989d3942ea8b59124` | genesis.json | +| Scroll Owner | `0xbE57544Eaf3515E888614a464EC9e0ad38f73e37` | `owner()` on Sepolia | + +### Sepolia Batch Status + +- `lastFinalizedBatchIndex`: 127,878 (0x1f386) + +--- + +## Cloak (Validium Testnet) + +| Contract | Address | Source | +|----------|---------|--------| +| **ScrollChain Proxy** | `0x9110B582327f6de87d8f833Ef7FAcD38CB093f64` | genesis.json | + +--- + +## How These Addresses Were Found + +### ScrollChain Proxy +The address `0xa13BAF47339d63B743e7Da8741db5456DAc1E556` appears in multiple places: +- `tests/prover-e2e/mainnet-galileoV2/genesis.json`: `"scrollChainAddress"` +- `coordinator/build/bin/conf/genesis.json` +- `bridge-history-api/conf/config.json` +- `scroll-devnets/charts/shadow-fork/e2e-test/values.yaml` + +**Critical verification step**: Initially, Anvil was mistakenly forking Scroll L2 (chainId=534352) instead of Ethereum L1. On Scroll L2, `0xa13B...` had no ScrollChain code. After correcting Anvil to fork Ethereum mainnet (chainId=1), the address correctly resolved to the ScrollChain proxy with: +- Implementation slot: `0x0a20703878e68E587c59204cc0EA86098B8c3bA7` +- `lastFinalizedBatchIndex()`: 517,828 +- `owner()`: `0x798576400F7D662961BA15C6b3F3d813447a26a6` + +### MultipleVersionRollupVerifier +- **Mainnet**: Queried via `cast call 0xa13BAF... "verifier()(address)"` on Ethereum mainnet RPC → `0x4CEA3E866e7c57fD75CB0CA3E9F5f1151D4Ead3F` +- **Sepolia**: Queried via `cast call 0x2D567... "verifier()(address)"` on Sepolia RPC → `0x8A360c7F6fca548507017DdeD732bFe7E078F963` +- Also referenced in `scroll-devnets/charts/shadow-fork/jobs/upgrade-contract.yaml` + +### Other Addresses +All other L1 contract addresses are extracted from the corresponding `genesis.json` files in `tests/prover-e2e//genesis.json`. diff --git a/tests/shadow-testing/follow/GUIDE.md b/tests/shadow-testing/follow/GUIDE.md new file mode 100644 index 0000000000..6abe1284b2 --- /dev/null +++ b/tests/shadow-testing/follow/GUIDE.md @@ -0,0 +1,137 @@ +# Follow Mode Guide — Shadow Coordinator + Prover Testing + +This guide documents the **follow mode** of the shadow coordinator + local prover environment: fork the ETH mainnet state from `FOLLOW_FORK_HOURS_BACK` hours in the past (default 5h), catch up the resulting backlog, then follow mainnet bundle production in real time. This is the **default acceptance test for prover/guest upgrades**. + +For a fixed historical bundle range (incident reproduction, single-bundle debugging, Sepolia testing, targeted codec-migration checks), see the [Snapshot Replay Mode Guide](../snapshot/GUIDE.md). Shared scripts live in [`../lib/`](../lib/), pitfalls in [`./TROUBLESHOOTING.md`](./TROUBLESHOOTING.md) (follow mode) and [`../docs/COMMON-TROUBLESHOOTING.md`](../docs/COMMON-TROUBLESHOOTING.md) (mode-independent). Runtime state (`.work/`) is shared by both modes at `tests/shadow-testing/.work` (i.e. `../.work` from here). + +## Architecture + +``` +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ Production RDS │ │ Shadow DB │ │ Shadow │ +│ (read-only via │────▶│ (local :5433) │────▶│ Coordinator │ +│ port-forward) │ │ │ │ (localhost:8390)│ +└──────────────────┘ └──────────────────┘ └────────┬─────────┘ + │ + │ assigns tasks + ▼ +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ L2 RPC │ │ Local Prover │ │ Verifier Assets │ +│ (mainnet-rpc. │◀────│ (GPU/CPU) │ │ (/tmp/shadow- │ +│ scroll.io) │ │ │ │ verifier-assets)│ +└──────────────────┘ └──────────────────┘ └──────────────────┘ +``` + +## Prerequisites + +### Hardware +- GPU with CUDA support (tested on RTX 3090) +- ~50GB disk space for Docker images + verifier assets + circuit downloads +- 16GB+ RAM + +### Software +- Docker + docker-compose +- PostgreSQL client (`psql`) +- Rust toolchain (for local prover binary) +- `kubectl` or SSH access to IDC for port-forwarding to production RDS + +### Network +- Access to IDC machine with port-forward to mainnet RDS (e.g., `idc-us-1-19`) +- Internet access for L2 RPC and S3 circuit downloads + +# Follow Mode (Primary) + +Follow mode forks the ETH mainnet state from **`FOLLOW_FORK_HOURS_BACK` hours in the past** (default 5; `0` = fork at the current tip) with Anvil, baseline-syncs the shadow DB from the mainnet read replica, then **catches up the backlog** (every bundle committed-but-not-finalized at the fork block, plus everything mainnet produced since) before **following** mainnet indefinitely — poll-syncing new chunk/batch/bundle rows, proving them with local GPU provers, and finalizing bundles on the fork — until a preset duration (`FOLLOW_RUN_HOURS`, default 48) or a failure. It answers the question a snapshot cannot: *can this prover fleet catch up a backlog and then keep pace with real mainnet bundle production?* The fork block is `tip - FOLLOW_FORK_HOURS_BACK*300` (12s L1 blocks); `lastFinalizedBatchIndex` and `lastCommittedBatchIndex` are read **at the fork block**, so the baseline window (fork-finalized → mainnet tip) is exactly the backlog. `make follow-report` splits metrics into catch-up and steady-state phases using `MAINNET_BUNDLE_TIP_AT_START` recorded in `.work/follow-run.env`. + +For a fixed historical bundle range (incident reproduction, single-bundle debugging, Sepolia, codec-migration checks), use the [Snapshot Replay Mode Guide](../snapshot/GUIDE.md). + +## Follow Mode Prerequisites + +All general prerequisites above apply, plus: + +- **Mainnet RDS read-replica access** — the `~/.pgpass` file on this machine contains valid credentials for the mainnet RDS read-only replica. Verify: + ```bash + psql -h localhost -p 15432 -U mainnet_infra_team_read_only -d mainnet_rollup -c "SELECT COUNT(*) FROM batch;" + # → 517,830+ batches + ``` +- **RDS tunnel watchdog** — the IDC port-forward to RDS (`localhost:15432`) must stay up for the entire run; a dead tunnel silently starves poll-sync. Run it under `autossh` (e.g. `autossh -M 0 -N -L 15432:...`) so it self-heals. +- Enough shadow-DB disk headroom for continuous row growth. + +For automated one-off baseline copies, `scroll-devnets/charts/shadow-fork/rollup-relayer/scripts/copy-db.sh` streams data from mainnet RDS to the local shadow DB via `postgres-tunnel` (`COPY ... TO STDOUT | COPY ... FROM STDIN`). + +## Bring-Up: `make follow` + +One command brings up the entire follow-mode stack (`scripts/10-follow-up.sh`): + +1. **Baseline sync** — `sync-mainnet-db.py` baseline mode copies ONLY the finalization-lag window: batches from the fork's `lastFinalizedBatchIndex - 1` to the mainnet tip, plus their chunks/`l2_block`/`l1_message` and overlapping bundles (typically ~100 batches / a few thousand blocks — NOT deep history). This window is not optional: L1 finalization is sequential (`prevBatchHash` chaining), so the shadow must prove and finalize every committed-but-not-finalized bundle in order before it can follow new ones. Rows at/below the finalized boundary are marked done (`rollup_status=5`, `proving_status=4`) and rows above are aligned to the fork's committed boundary, so a reused DB never carries stale state across forks. `10-follow-up.sh --reset` truncates the task tables first (use it whenever the DB may hold leftovers from older runs/imports — otherwise the coordinator treats ancient pending batches as work). Proof columns are never copied; everything is re-proven locally. +2. **Anvil fork** — fork ETH **L1** at the current block (never Scroll L2 — Trap 2), with `fusaka_timestamp: 2000000000` in the relayer config so Anvil accepts blob sidecars. +3. **Verifier wrapper** — deploy/register the `ZkEvmVerifierPostFeynman` wrapper matching the guest under test (manual procedure: "Real Verifier Deployment" in the [Snapshot Replay Mode Guide](../snapshot/GUIDE.md#real-verifier-deployment)). +4. **Coordinator** — start `coordinator_api` + `coordinator_cron` against the shadow DB. +5. **Provers** — start one prover per GPU. +6. **Relayer** — start the rollup relayer with local proposers **disabled** (`l2_config.{chunk,batch,bundle}_proposer_config.disable = true`): the relayer then only commits/finalizes what the DB contains, instead of synthesizing bundles at an unrealistic rate. The shadow relayer config template (`lib/configs/relayer.json.template`) additionally sets `l2_config.disable_l2_watcher = true` (the poll sync, not the relayer's L2 watcher, keeps `l2_block` populated — Trap 26) and `sender_config.chain_nonce_only = true` (sender nonces initialize from the fork, never from stale `pending_transaction` rows — Trap 7/27). +7. **Background daemons** — poll-sync, sweeper, hourly monitor (plain background processes with pidfiles in `.work/`; no agent/session cron is required). + +The run window is recorded in `.work/follow-run.env` (`SHADOW_REPORT_START`, `FOLLOW_RUN_HOURS=48`). Tear down with `make follow-stop` (`scripts/11-follow-stop.sh`, supports `--keep-anvil`). + +### Critical Behavior of the Poll-Sync (Do Not Bypass) + +- Newly inserted rows carry **mainnet's** `rollup_status`/commit/finalize columns, which are meaningless on the fork. The sync resets them per row range: + - `batch.index <= fork miscData.lastCommittedBatchIndex` → `rollup_status = 3` (already committed on the fork). + - `batch.index > boundary` → `rollup_status = 1` so the shadow relayer commits them on Anvil (requires `parentBatchHash == committedBatches[lastCommittedBatchIndex]`; keep Trap 19's boundary accurate). + - `bundle` → always `rollup_status = 1`. +- The boundary is queried from Anvil each poll cycle (`ANVIL_RPC` / `SCROLL_CHAIN` env vars to override), so it advances automatically as the shadow relayer commits new batches. +- `ON CONFLICT DO NOTHING` everywhere: rows already advanced by the shadow relayer are never overwritten. **Consequence**: columns populated lazily on mainnet after the row is first copied stay stale in the shadow DB. The sync re-derives them every cycle instead: + - `sync_l2_blocks()` — links `l2_block.chunk_hash` for recent chunks (the blocks usually exist from baseline import but with NULL `chunk_hash`; an UPDATE, not an INSERT, is what fixes it). Missing this starves chunk task formatting (Trap 22). + - `sync_parent_links()` — re-derives `chunk.batch_hash` and `batch.bundle_hash` from parent index ranges (mainnet sets them at proposal time; rows copied before that keep NULL forever and are invisible to the coordinator's proof-status promotion, Trap 22). +- **L1 message queue follow-along (mandatory)**: bundles that pop L1 messages enqueued after the fork block fail finalization (`VerificationFailed` / `ErrorFinalizedIndexTooLarge`, Trap 23). The poll loop runs `../lib/sync-queue-hashes.py` every cycle — it copies `getMessageRollingHash(i)` from a mainnet RPC into the fork's `messageRollingHashes` mapping (slot 101) and aligns `nextCrossDomainMessageIndex` (slot 103) with mainnet. +- **Watch item**: the first bundle whose batches were committed on mainnet **after** the fork block exercises the relayer's commit path on Anvil (blob-carrying `commitBatches` tx). Keep `fusaka_timestamp: 2000000000` in the relayer config so Anvil accepts the blob sidecar. + +## Day-to-Day Operations + +| Command | What It Does | +|---------|--------------| +| `make follow-status` | Latest monitor snapshot + lag summary | +| `make follow-report` | Report via `generate-catchup-report.py`, windowed to this run by `SHADOW_REPORT_START` (the metrics log accumulates across runs) | +| `make follow-stop` | Tear down the stack (`--keep-anvil` keeps the fork) | +| `make re-fork` | Recover from a fork desync (see Failure Recovery below) | + +### Background Daemons + +| Daemon | Script | Cadence | Purpose | +|--------|--------|---------|---------| +| Poll-sync | `sync-mainnet-db.py --poll-interval 60` | 60s loop | DB row sync + `l2_block`/parent-link repair; runs `../lib/sync-queue-hashes.py` every cycle (L1 queue rolling hashes + cursor follow mainnet, Trap 23) | +| Sweeper | `scripts/sweep-stale-proving.sh` | 10 min | Reset stale proving rows **and `total_attempts`** (attempt exhaustion silently starves tasks, Trap 22; also the safety net for the Trap 24 structural gap) | +| Monitor | `scripts/monitor-catchup.py >> .work/catchup-metrics.log` | 1 h | Hourly metrics snapshot: `finalized_lag`, alerts when lag > 3, verifier `protocolVersion` drift detection | + +All daemons are plain background processes with pidfiles in `.work/`, started by `10-follow-up.sh` — no agent/session cron is required. + +## Expected Steady State + +Mainnet produces ~1 bundle/hour; the pipeline proves + finalizes a bundle in ~10 minutes, so once the initial backlog is cleared the system idles most of the time — provers polling with `CoordinatorEmptyProofData` every ~20s is the **normal** idle state, not an error. + +Validation evidence from the first 48-hour follow run (4× GPU box): + +| Metric | Value | +|--------|-------| +| Duration | ~22 h of operation | +| Bundles proved **and finalized** | 90 (zero backlog at end, lag ≤ 1) | +| Chunks / batches proved | 333 / 92 | +| Avg proof time | chunk 117 s, batch 25 s, bundle 335 s | +| Mainnet cadence vs prove+finalize | ~1 bundle/hour vs ~10 min → large headroom | + +Sizing conclusion: **1 GPU suffices** (~26% duty cycle), **2 recommended** for burst/backlog absorption, **4 is comfortable headroom**. The current 4-GPU box can follow Scroll mainnet in real time. + +## Failure Recovery + +- **`make re-fork`** (`scripts/re-fork.sh`) — when the fork desyncs (Anvil crash/restart, state drift): re-fork Anvil at the latest block, redeploy the verifier wrapper, re-fund EOAs (Trap 10 — `anvil_setBalance` does not survive restarts), re-mirror L1 queue hashes (`sync-queue-hashes.py`, Trap 23), restart the relayer. +- **RDS tunnel watchdog** — keep the RDS port-forward under `autossh`; poll-sync stalls silently if the tunnel dies. +- **Verifier-drift alerting** — the hourly monitor snapshot detects verifier `protocolVersion` drift. If it fires, re-check the deployed wrapper and MVRV routing (Snapshot guide, "[Verify MVRV Routing](../snapshot/GUIDE.md#verify-mvrv-routing)") before trusting any finalize result. + +## Run Completion & Acceptance Criteria + +A follow run ends after `FOLLOW_RUN_HOURS` (default 48) or on failure. The run **passes** when: + +- **Lag ≤ 1** bundle sustained over the run window (monitor `finalized_lag`). +- **Zero manual intervention** over the run window (no manual SQL fixes, no daemon restarts). +- The report (`make follow-report`) answers: **kept pace?** (bundles created vs finalized), avg proof times per level (chunk/batch/bundle), and identifies bottlenecks (if any). + diff --git a/tests/shadow-testing/follow/Makefile b/tests/shadow-testing/follow/Makefile new file mode 100644 index 0000000000..55f947d0e2 --- /dev/null +++ b/tests/shadow-testing/follow/Makefile @@ -0,0 +1,53 @@ +# Follow Mode Makefile +# Fork at the CURRENT mainnet tip and follow mainnet indefinitely: +# baseline sync -> anvil -> verifier -> coordinator -> provers -> relayer +# + poll-sync/sweeper/monitor daemons. See scripts/10-follow-up.sh. +# +# Usage: +# make follow Bring up the full follow-mode stack +# make follow-status Latest monitor snapshot + finalize lag +# make follow-report Throughput report for the current run +# make re-fork Re-fork Anvil at latest block (recovery) +# make follow-stop Stop the follow-mode stack + +SCRIPT_DIR := $(shell cd "$(dir $(lastword $(MAKEFILE_LIST)))" && pwd) +CONFIG_FILE := $(SCRIPT_DIR)/configs/mainnet.json +# .work is shared by both modes and stays at tests/shadow-testing/.work. +WORK_DIR := $(SCRIPT_DIR)/../.work + +DB_DSN := $(shell jq -r '.db.dsn' $(CONFIG_FILE) 2>/dev/null) + +.PHONY: follow follow-stop follow-status follow-report re-fork help + +follow: + $(SCRIPT_DIR)/scripts/10-follow-up.sh + +follow-stop: + $(SCRIPT_DIR)/scripts/11-follow-stop.sh + +follow-status: + @echo "📊 Last monitor snapshot:" + @last=$$(grep '^{' $(WORK_DIR)/catchup-metrics.log 2>/dev/null | tail -1); \ + if [ -z "$$last" ]; then echo " (no metrics yet)"; \ + else printf '%s\n' "$$last" | (jq . 2>/dev/null || python3 -m json.tool); fi + @echo "" + @echo "Finalize lag (shadow DB):" + @psql "$(DB_DSN)" -Atq -c "SELECT 'max_bundle=' || COALESCE(MAX(index),0) || ' max_finalized=' || COALESCE(MAX(index) FILTER (WHERE rollup_status=5),0) || ' lag=' || (COALESCE(MAX(index),0) - COALESCE(MAX(index) FILTER (WHERE rollup_status=5),0)) FROM bundle;" 2>/dev/null || echo " (DB not accessible)" + +follow-report: + SHADOW_REPORT_START=$$(grep '^SHADOW_REPORT_START=' $(WORK_DIR)/follow-run.env 2>/dev/null | cut -d= -f2-) python3 $(SCRIPT_DIR)/scripts/generate-catchup-report.py + +re-fork: + $(SCRIPT_DIR)/scripts/re-fork.sh + +help: + @echo "Follow Mode Makefile (fork current mainnet tip, follow indefinitely)" + @echo "" + @echo " make follow Bring up the full follow-mode stack" + @echo " make follow-status Latest monitor snapshot + finalize lag" + @echo " make follow-report Throughput report for the current run" + @echo " make re-fork Re-fork Anvil at latest block (recovery)" + @echo " make follow-stop Stop the follow-mode stack" + @echo "" + @echo "For snapshot replay mode (historical fork, fixed bundle range), use:" + @echo " make -C ../snapshot help" diff --git a/tests/shadow-testing/follow/README.md b/tests/shadow-testing/follow/README.md new file mode 100644 index 0000000000..7886016b33 --- /dev/null +++ b/tests/shadow-testing/follow/README.md @@ -0,0 +1,16 @@ +# Follow Mode (Primary) + +Follow mode forks the ETH mainnet state from **FOLLOW_FORK_HOURS_BACK hours in the past** (default 5h), baseline-syncs the shadow DB from the mainnet read replica, then first **catches up** the resulting backlog (all bundles committed-but-not-finalized at the fork block plus everything mainnet produced since) and then **follows** mainnet indefinitely — poll-syncing new chunk/batch/bundle rows, proving them with local GPU provers, and finalizing on the fork — for a preset window (default 48h). It is the **default acceptance test for prover/guest upgrades**: it answers whether the prover fleet can catch up a backlog *and* keep pace with real mainnet bundle production. `FOLLOW_FORK_HOURS_BACK=0` forks at the current tip (no backlog). The final report splits metrics into catch-up and steady-state phases. + +## Quick Start + +```bash +cd tests/shadow-testing/follow +make follow # one-shot bring-up: baseline sync → Anvil fork → verifier → coordinator → provers → relayer → daemons +make follow-status # latest monitor snapshot + finalize lag +make follow-report # throughput report for this run (SHADOW_REPORT_START) +make re-fork # recover from a fork desync (re-fork at latest block) +make follow-stop # tear down (script supports --keep-anvil) +``` + +Full guide: [`GUIDE.md`](GUIDE.md). Pitfalls/traps: [`./TROUBLESHOOTING.md`](./TROUBLESHOOTING.md) (follow mode) and [`../docs/COMMON-TROUBLESHOOTING.md`](../docs/COMMON-TROUBLESHOOTING.md) (mode-independent). Runtime state lives in the shared `../.work/`. diff --git a/tests/shadow-testing/follow/TROUBLESHOOTING.md b/tests/shadow-testing/follow/TROUBLESHOOTING.md new file mode 100644 index 0000000000..7695afbde7 --- /dev/null +++ b/tests/shadow-testing/follow/TROUBLESHOOTING.md @@ -0,0 +1,111 @@ +# Follow Mode — Troubleshooting & Pitfalls + +Follow-mode-specific traps (poll sync, starvation, live-mainnet finalization). +Mode-independent traps (environment, verifier deployment, relayer flags, prover setup) and the +step-by-step checklist live in [`../docs/COMMON-TROUBLESHOOTING.md`](../docs/COMMON-TROUBLESHOOTING.md); +see also the [Follow Mode Guide](./GUIDE.md). Trap numbers are stable across the split files. + +## Critical Traps (Follow Mode) + +### Trap 22: Poll-Synced Chunks Missing `l2_block` Linkage → "failed to fetch block hashes of a chunk" [follow mode] + +- **Symptom**: In follow mode, after the initial backlog is proved, finalization stalls. Coordinator logs `format prover task failure ... failed to fetch block hashes of a chunk, chunk hash:0x... err:` on every dispatch attempt; provers spin on `CoordinatorEmptyProofData: get empty prover task` every ~20s; chunks pile up in `proving_status = 1` (with sweeps resetting stale `proving_status = 2` rows every 30 min). +- **Cause**: `sync-mainnet-db.py` poll mode copies new chunk/batch/bundle rows but historically skipped `l2_block` (watermarking the 181 GB mainnet table by `MAX(number)` times out). New chunks therefore had no block rows linked via `chunk_hash`, and the coordinator cannot format chunk tasks without them. Subtlety: the block rows usually **already exist** in the shadow DB (imported by block number during baseline) but with `chunk_hash = NULL`, so a plain `INSERT ... ON CONFLICT (number) DO NOTHING` copy is a no-op — the linkage must be established with an UPDATE. +- **Fix**: `sync_l2_blocks()` in `sync-mainnet-db.py` now runs every poll cycle: (1) `UPDATE l2_block SET chunk_hash = chunk.hash` for recent chunks (last 2000) whose blocks lack the link, then (2) copy any genuinely missing block rows from mainnet. One-off manual backfill if needed: + ```sql + UPDATE l2_block b SET chunk_hash = c.hash FROM chunk c + WHERE b.number BETWEEN c.start_block_number AND c.end_block_number + AND c.index > (SELECT COALESCE(MAX(index),0) - 2000 FROM chunk) + AND (b.chunk_hash IS NULL OR b.chunk_hash <> c.hash); + ``` +- **Diagnosis query**: chunks lacking block linkage — + ```sql + SELECT count(*) FROM chunk c + WHERE NOT EXISTS (SELECT 1 FROM l2_block b WHERE b.chunk_hash = c.hash); + ``` +- **Note**: `CoordinatorEmptyProofData` every 20s from an idle prover is the **normal** "no task available" poll response, not an error — chunk dispatch is serialized by parent-chunk proof dependency, so only 2-3 chunks prove concurrently even with 4 provers. It only indicates this trap when ALL provers spin AND the coordinator logs block-hash failures. +- **Secondary damage — attempt exhaustion starvation**: **Note (fixed upstream)**: this is now fixed in the coordinator itself — coordinator-side dispatch failures (task formatting, universal-task generation, prover-task insertion) refund the charged attempt via `orm.RefundAttemptsByHash` (`recoverAttempts` in `internal/logic/provertask/*_prover_task.go`), so `total_attempts` is no longer permanently burned by such failures. The sweeper's `total_attempts` reset described below is now belt-and-braces only. Historical description: the coordinator picks chunk tasks oldest-first but **skips tasks with `total_attempts >= 5`** (`chunk.go GetUnassignedChunk`: `total_attempts < maxAttempts`). Every failed dispatch during the outage burns one attempt, and `sweep-stale-proving.sh` historically reset only `proving_status`/`active_attempts`, not `total_attempts`. Result: the 44 backlog chunks hit 5/5 attempts and became permanently invisible — the coordinator silently leapfrogged to freshly-synced tip chunks while the backlog starved (symptom: only tip chunks prove, old pending chunks never get sessions, no ERROR logged). Fix: reset attempts after the root cause is repaired — + ```sql + UPDATE chunk SET total_attempts=0, active_attempts=0 + WHERE proving_status=1 AND total_attempts>0; + ``` + (same shape for `batch`/`bundle`). `sweep-stale-proving.sh` now resets `total_attempts = 0` on every swept row so future outages self-heal. +- **Diagnosis query for starvation**: oldest pending chunk with maxed attempts — + ```sql + SELECT index, total_attempts, active_attempts FROM chunk + WHERE proving_status = 1 ORDER BY index LIMIT 5; + ``` +- **Tertiary damage — NULL parent links block proof-status promotion**: poll sync copies chunk/batch rows with `ON CONFLICT DO NOTHING`, so rows copied *before* mainnet's proposer assigned them keep `batch_hash` / `bundle_hash` NULL forever. The coordinator_cron promotes `batch.chunk_proofs_status = Ready` only when all chunks joined via `chunk.batch_hash` are verified (`collect_proof.go checkBatchAllChunkReady`), and likewise `bundle.batch_proofs_status` via `batch.bundle_hash`. NULL links → promotion never happens → the batch/bundle is silently invisible to task selection (oldest-first query filters on the status flag; no ERROR is ever logged). Symptom: chunks all verified but batch sessions never start; one stray batch/bundle proves while its older siblings starve. Fix: re-derive links from the parent rows' index ranges — + ```sql + UPDATE chunk c SET batch_hash = b.hash FROM batch b + WHERE c.index BETWEEN b.start_chunk_index AND b.end_chunk_index + AND (c.batch_hash IS NULL OR c.batch_hash = '' OR c.batch_hash <> b.hash); + UPDATE batch b SET bundle_hash = u.hash FROM bundle u + WHERE b.index BETWEEN u.start_batch_index AND u.end_batch_index + AND (b.bundle_hash IS NULL OR b.bundle_hash = '' OR b.bundle_hash <> u.hash); + ``` + `sync-mainnet-db.py` runs both every poll cycle (`sync_parent_links()`, bounded to the recent 500 parents). + +### Trap 23: Bundles Popping Post-Fork L1 Messages → VerificationFailed (0x439cc0cd), then ErrorFinalizedIndexTooLarge (0x16465978) [follow mode] + +- **Symptom**: Most bundles finalize fine, but a bundle whose batches pop L1 messages enqueued **after the Anvil fork block** reverts on-chain with `VerificationFailed` (`0x439cc0cd`). After patching the queue hashes, it then reverts with `ErrorFinalizedIndexTooLarge` (`0x16465978`, appears as raw bytes `\x16FYx` in relayer logs). +- **Diagnosis flow (all verified during the 2026-07-13 incident, bundle 18070)**: + 1. Decode the bundle proof's `metadata.bundle_info` from the DB (`bundle.proof` is a JSON blob) and confirm every field matches mainnet DB values. + 2. Recompute `keccak256(abi.encodePacked(protocolVersion, publicInput))` with the wrapper's packed layout (`chainId 8B | msgQueueHash 32B | numBatches 4B | prevStateRoot | prevBatchHash | postStateRoot | batchHash | withdrawRoot`) and confirm it equals `metadata.bundle_pi_hash`. + 3. Call the wrapper's `verify(bundleProof, publicInput)` directly with the metadata-derived publicInput. **If it succeeds**, proof/digests are fine and the mismatch is contract-side — ScrollChain computes `messageQueueHash` itself via `L1MessageQueueV2.getMessageRollingHash()`. + 4. Compare `getMessageRollingHash(i)` on fork vs mainnet (public RPC e.g. `https://ethereum-rpc.publicnode.com` works; Alchemy demo key is 429-rate-limited). +- **Root cause**: `L1MessageQueueV2` keeps `mapping(uint256=>bytes32) messageRollingHashes` at **storage slot 101** (value = rolling hash with low 32 bits overwritten by enqueue timestamp; the getter clears those bits). Entries for messages enqueued after the fork block are zero on the fork, so the contract builds a publicInput whose `messageQueueHash` differs from the prover's → plonk rejects. Note the **off-by-one**: rh[i] is the hash *after* message i, so a bundle popping to index N needs rh[N-1]; DB `prev/post_l1_message_queue_hash` at popped_before=N equals `getMessageRollingHash(N-1)`. +- **Fix**: `scripts/sync-queue-hashes.py` copies `getMessageRollingHash(i)` from a mainnet RPC into the fork via `anvil_setStorageAt(queue, keccak256(pad32(i)‖pad32(101)), hash)` and also bumps `nextCrossDomainMessageIndex` (slot 103 = 0x67) to mainnet's value (this is what clears the follow-up `ErrorFinalizedIndexTooLarge`). It is idempotent and runs inside the `sync-mainnet-db.py` poll loop during follow mode (failures there only log a warning, never kill the DB sync). Run it manually after any Anvil restart/re-fork, and whenever a finalize reverts with either selector. +- **Rule of thumb**: if finalization fails only for bundles whose `post_l1_message_queue_hash != prev_l1_message_queue_hash` (i.e. the batch pops messages), suspect this trap before touching proofs or the verifier wrapper. + +### Trap 25: Orphaned Poll-Sync + Empty Watermark → Full Mainnet History Backfill [follow mode] + +- **Symptom**: Shadow DB suddenly fills with millions of mainnet rows (`sync-poll.log` shows `chunk: inserted 25000/6642569` and counting) even though the follow-mode baseline only covers the finalization-lag window (~3 chunks / 1 batch / 1 bundle). +- **Cause**: Two independent failures compound: + 1. **Orphaned daemon**: `11-follow-stop.sh` (or an earlier stop script) killed the loop `bash` process but not its `python3 sync-mainnet-db.py` child — the python process kept running in the background, invisible to pidfile checks. + 2. **Watermark = 0**: the DB was then reset (`--reset` TRUNCATEs the task tables). The orphaned sync's next poll computed `max(index) = 0` on the empty table and treated *all* of mainnet history as new rows, bulk-copying everything. +- **Defenses (all three are in place — do not remove any)**: + 1. `11-follow-stop.sh` kills the **whole process group** (`kill -- -$pid`, daemons are started with `setsid`), so python children die with their loop. + 2. `sync-mainnet-db.py` poll mode has a `MAX_POLL_DELTA = 5000` guard: if the watermark is 0 or the mainnet-vs-shadow delta exceeds 5000 rows, the poll **skips and warns** instead of backfilling. Bulk backfill is exclusively the baseline's job. + 3. `10-follow-up.sh` runs the baseline (`sync-baseline`) **before** starting any daemon, so a fresh DB always has a sane watermark before polling begins. +- **Recovery if it still happens** (e.g. you started a poll sync by hand against an empty DB): kill the sync process, then delete the contaminated rows below the baseline window: + + ```sql + DELETE FROM l2_block WHERE number < ; + DELETE FROM chunk WHERE index < ; + DELETE FROM batch WHERE index < ; + ``` + +### Trap 26: Relayer L2 Watcher Genesis-Crawls an Empty `l2_block` [follow mode] + +> **Fixed upstream**: the relayer now supports `l2_config.disable_l2_watcher` (default false = production behavior unchanged), which skips the watcher loop entirely. The shadow relayer config template (`lib/configs/relayer.json.template`) sets it — in follow mode the poll sync is what keeps `l2_block` populated for newly synced chunks, so the watcher is redundant. The harness ordering below remains as defense-in-depth. + +- **Symptom**: `l2_block` fills with rows numbered 1, 2, 3, … at ~30–60 blocks/s, `chunk_hash = NULL`, `withdraw_root = 0x0000…` — a full L2 history crawl that would take days and tens of GB, while relayer logs show `retrieved block height=…` climbing from genesis. +- **Cause**: `rollup_relayer` always runs an L2 watcher loop (`rollup/cmd/rollup_relayer/app/app.go` → `TryFetchRunningMissingBlocks` every 2 s) that fetches **all** blocks from `MAX(l2_block.number)+1` up to the L2 tip — reading the max **once** at loop entry. If the relayer is alive while `--reset` TRUNCATEs `l2_block` (or the table is empty for any other reason), the watcher sees `MAX = 0` and starts crawling from block 1; the in-flight call keeps going for days even after the baseline repopulates the window. +- **Fix (in place)**: `10-follow-up.sh --reset` now runs `11-follow-stop.sh` **before** the TRUNCATE, so no writer survives into the reset. Never TRUNCATE `l2_block` (or let it go empty) while a relayer is running. +- **Recovery**: kill the relayer (stops the crawl), `DELETE FROM l2_block WHERE number < `, restart the relayer — the watcher then computes `MAX` from the window rows and only fetches the small gap to tip, which is its normal, desirable behavior (keeps tip blocks present for newly synced chunks). + +### Trap 27: Relayer Cannot Commit/Finalize on the Fork — Balance, Sequencer, Nonce Checklist [follow mode] + +Three independent things must hold for the relayer to send its first on-fork commit; each fails with a distinct signature: + +1. **Zero EOA balance** → `Out of gas: gas required exceeds allowance: 0`. `10-follow-up.sh`'s idempotent restart skips `01-setup-anvil.sh` when Anvil is already running, so EOA funding never re-runs. Fix: `cast rpc anvil_setBalance 0x56bc75e2d63100000` for both the commit sender and the finalize sender. +2. **`ErrorCallerIsNotSequencer` (0x3cddbade)** on `commitBatches` → the commit sender is not authorized on the fork. `configs/mainnet.json` `accounts.commit_eoa` **must equal the address derived from the `COMMIT_KEY` hardcoded in `06-run-relayer.sh`** — they had drifted apart (`0xf39F…` vs `0xBC73…`), so `01-setup-anvil.sh` authorized an account the relayer never uses. Authorize manually: impersonate the ScrollChain owner and `cast send … "addSequencer(address)" --unlocked`. +3. **Tx stuck in txpool `queued` forever** → `pending_transaction` nonce desync (Trap 7 variant). The relayer's sender initializes its nonce as `max(db_max_nonce + 1, chain_pending_nonce)` (`rollup/internal/controller/sender/sender.go` `initializeNonce`). `pending_transaction` rows survive Anvil state-file restores, but the on-fork account nonce does not (a restored state can reset it to 0). The relayer then signs with a high nonce, Anvil queues the tx behind a gap that never fills, and *nothing ever mines* — commits silently stall with no error after the initial send. Diagnose with `cast nonce ` vs `cast rpc txpool_content`; fix: stop relayer, `DELETE FROM pending_transaction WHERE sender_address = ''` (or all rows), restart relayer so it re-initializes from the chain nonce. + +Also note: the relayer writes `rollup_status` **only** through its commit/finalize confirmation path (GORM `UPDATE … SET finalize_tx_hash, rollup_status`). If a batch/bundle shows `rollup_status = 5` with NULL `finalize_tx_hash` while `lastFinalizedBatchIndex` on the fork hasn't moved, do not trust the DB row — cross-check on-chain. `log_statement = 'mod'` on the shadow postgres is a cheap way to attribute every status write; it is asserted automatically by `02-prepare-db.sh` and `10-follow-up.sh` (re-applied on every setup, since `ALTER SYSTEM` lives in the container's data volume and is lost when the volume is recreated). Read the writes with `docker logs shadow-postgres` (or the postgres server log on a non-docker setup). + + +### Trap 28: Post-Fusaka Fork + Anvil 1.0.0 → Blob Base Fee Explosion, Commits Fail "Insufficient funds" [follow mode] + +- **Symptom**: Right after a fresh fork, every `commitBatches` attempt fails with `estimateGasLimit failure ... Insufficient funds` (EOA balance is fine — verified 100 ETH). Batches sit at `rollup_status = 1` forever; `cast blob-base-fee` on the fork returns ~1e18 wei. +- **Cause**: Anvil 1.0.0 predates the Fusaka fork. Forking post-Fusaka mainnet state inherits a large `excessBlobGas` (~1.8e8 when the mainnet blob market is congested), but Anvil prices blob gas with the **Dencun** update fraction (3338477), so the inherited excess maps to an astronomical blob base fee. Commit txs carry blob versioned hashes and become unaffordable. +- **Fix (codified)**: `lib/01-setup-anvil.sh` now mines empty blocks right after `wait_for_anvil` until `cast blob-base-fee` drops below 1 gwei (excess decays ~1/8 per empty block; ~400 blocks suffice from 1.8e8). Manual equivalent: `cast rpc anvil_mine 400 --rpc-url http://localhost:18545`. +- **Note**: Forking at tip does NOT dodge this — it only depends on the fork block's `excessBlobGas`, which is high whenever mainnet blob backlog is high. Long-term fix is upgrading Anvil to a Fusaka-aware release. + +### Trap 29: Same-Block Ordering — Manual `addProver` Mined After the Failing Finalize [follow mode] + +- **Symptom**: A `finalizeBundlePostEuclidV2` tx lands on-chain but reverts with `ErrorCallerIsNotProver` (0x7b263b17) even though `addProver` was sent first; the bundle ends up at `rollup_status = 7` (RollupFinalizeFailed), which `ProcessPendingBundles` **never retries**. +- **Cause**: Anvil mines both txs in the same block and orders the finalize (txIndex 0) before the `addProver` (txIndex 1). The finalize legitimately reverts at execution time. (Also reachable via an Anvil state restore from a pre-addProver backup — see Trap 27.) +- **Fix (codified)**: `10-follow-up.sh` step h now re-ensures `isProver(finalize_sender)` idempotently on every run, alongside the Trap-27 balance/sequencer checks. Manual recovery: impersonate the owner, `cast send … "addProver(address)" --unlocked`, verify `isProver` = true, then `UPDATE bundle SET rollup_status = 1 WHERE index = ` so the relayer retries. +- **Rule of thumb**: a bundle at `rollup_status = 7` is stranded by design (relayer logs it loudly). It always needs the manual `rollup_status = 1` reset after fixing the underlying cause. diff --git a/tests/shadow-testing/follow/configs/coordinator.json.template b/tests/shadow-testing/follow/configs/coordinator.json.template new file mode 100644 index 0000000000..5b63bd4b69 --- /dev/null +++ b/tests/shadow-testing/follow/configs/coordinator.json.template @@ -0,0 +1,40 @@ +{ + "prover_manager": { + "provers_per_session": 1, + "session_attempts": 5, + "external_prover_threshold": 32, + "bundle_collection_time_sec": 7200, + "batch_collection_time_sec": 180, + "chunk_collection_time_sec": 3600, + "verifier": { + "min_prover_version": "v4.4.45", + "verifiers": [ + { + "assets_path": "assets", + "fork_name": "galileoV2" + } + ] + } + }, + "db": { + "driver_name": "postgres", + "dsn": "postgres://postgres:YOUR_SHADOW_DB_PASSWORD@shadow-postgres:5432/shadow_rollup?sslmode=disable", + "maxOpenNum": 200, + "maxIdleNum": 20 + }, + "l2": { + "validium_mode": false, + "chain_id": 534352, + "l2geth": { + "endpoint": "https://l2geth-rpc-proxy.mainnet.aws.scroll.io" + } + }, + "auth": { + "secret": "YOUR_COORDINATOR_AUTH_SECRET", + "challenge_expire_duration_sec": 3600, + "login_expire_duration_sec": 3600 + }, + "sequencer": { + "decryption_key": "" + } +} diff --git a/tests/shadow-testing/follow/configs/mainnet.json.template b/tests/shadow-testing/follow/configs/mainnet.json.template new file mode 100644 index 0000000000..ff02fdc90d --- /dev/null +++ b/tests/shadow-testing/follow/configs/mainnet.json.template @@ -0,0 +1,45 @@ +{ + "name": "mainnet-shadow-fork", + "fork": { + "url": "https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY", + "block_number": 25202217, + "anvil_rpc": "http://localhost:18545" + }, + "contracts": { + "scroll_chain": "0xa13BAF47339d63B743e7Da8741db5456DAc1E556", + "l1_message_queue_v2": "0x56971da63A3C0205184FEF096E9ddFc7A8C2D18a", + "rollup_verifier": "0x4CEA3E866e7c57fD75CB0CA3E9F5f1151D4Ead3F", + "deployed_verifier": "0xb1F2C5c1ea2885278a1070350d12d3D8824265B0", + "owner": "0x798576400F7D662961BA15C6b3F3d813447a26a6" + }, + "accounts": { + "prover_eoa": "0x410E7FD80a3Fc1E62A4D3450d11b71b812006eB9", + "commit_eoa": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "reset": { + "last_finalized_batch_index": 517765, + "next_unfinalized_queue_index": 0, + "codec_version": 10, + "last_committed_batch_index": 517819 + }, + "db": { + "dsn": "postgresql://postgres:YOUR_SHADOW_DB_PASSWORD@localhost:5433/shadow_rollup" + }, + "genesis": "tests/prover-e2e/mainnet-galileoV2/genesis.json", + "assets": { + "assets_v2": "coordinator/build/bin/assets_v2" + }, + "prover": { + "name_prefix": "galileo6-shadowfork-prover", + "circuit_version": "v0.13.1", + "s3_base_url": "https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/releases/v0.9.0/" + }, + "relayer": { + "validium_mode": false, + "min_codec_version": 7, + "chain_monitor_enabled": false + }, + "e2e": { + "l2_rpc": "https://l2geth-rpc-proxy.mainnet.aws.scroll.io" + } +} diff --git a/tests/shadow-testing/follow/scripts/10-follow-up.sh b/tests/shadow-testing/follow/scripts/10-follow-up.sh new file mode 100755 index 0000000000..6a6253df97 --- /dev/null +++ b/tests/shadow-testing/follow/scripts/10-follow-up.sh @@ -0,0 +1,496 @@ +#!/usr/bin/env bash +# 10-follow-up.sh — one-shot orchestrator for "follow mode" shadow testing. +# +# Brings up the full follow-mode stack against a RECENT mainnet state: +# a. sanity checks (postgres 5433, mainnet DSN, alchemy key, stale ports) +# b. baseline DB sync from the mainnet read replica +# c. Anvil fork at tip - FOLLOW_FORK_HOURS_BACK*300 blocks (default 5h back, +# via 01-setup-anvil.sh) so the run opens with a real backlog to catch up +# d. verifier wrapper deploy + registration (via 03-deploy-verifier.sh) +# e. initial L1 queue rolling-hash sync (Trap 23) +# f. coordinator_api + coordinator_cron +# g. GPU provers (via 04-prover-up.sh) +# h. rollup relayer (via 06-run-relayer.sh) +# i. background daemon loops: poll sync / stale-proving sweeper / monitor +# j. records run metadata in .work/follow-run.env +# +# Idempotent-ish: a component whose pidfile exists and is alive is skipped. +# Usage: ./10-follow-up.sh [--config configs/mainnet.json] [--dry-run] [--reset] +# Env: FOLLOW_FORK_HOURS_BACK=0 forks at the current tip (no backlog). + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)" +LIB_DIR="$(cd "${SCRIPT_DIR}/../../lib" && pwd)" +source "${LIB_DIR}/anvil-utils.sh" + +# ─── Defaults (env-overridable) ────────────────────────────────────────────── +CONFIG_FILE="${CONFIG_FILE:-${PROJECT_ROOT}/configs/mainnet.json}" +# .work is shared by both modes and stays at tests/shadow-testing/.work. +WORK_DIR="${WORK_DIR:-${PROJECT_ROOT}/../.work}" +# Default mirrors sync-mainnet-db.py; override via env if the tunnel differs. +MAINNET_DSN="${MAINNET_DSN:-postgresql://mainnet_infra_team_read_only:AuexDUuaarskbG6tr9CH9gXsJqp4at67mddAbMrt@localhost:15432/mainnet_rollup}" +FOLLOW_RUN_HOURS="${FOLLOW_RUN_HOURS:-48}" +# Fork the L1 state this many hours in the PAST, so the run starts with a +# real backlog (all bundles committed-but-not-finalized at the fork block, +# plus everything mainnet produced since) to catch up before steady-state +# following. 0 = fork at the current tip (old behavior, near-idle start). +FOLLOW_FORK_HOURS_BACK="${FOLLOW_FORK_HOURS_BACK:-5}" +SYNC_POLL_INTERVAL="${SYNC_POLL_INTERVAL:-60}" +SWEEP_INTERVAL="${SWEEP_INTERVAL:-600}" +MONITOR_INTERVAL="${MONITOR_INTERVAL:-3600}" +EXPECTED_PROTOCOL_VERSION="${EXPECTED_PROTOCOL_VERSION:-10}" +# Follow mode runs on GalileoV2 (codec V10) blocks; the relayer must reject +# anything older, so force --min-codec-version 10 regardless of the config +# file's snapshot-mode value (see 06-run-relayer.sh MIN_CODEC override). +MIN_CODEC="${MIN_CODEC:-10}" +GPUS="${GPUS:-0,1}" +# Mainnet rule (AGENTS.md): resetting nextUnfinalizedQueueIndex to 0 is +# sufficient; sync-queue-hashes.py keeps nextCrossDomainMessageIndex current. +NEXT_QUEUE="${NEXT_QUEUE:-0}" +COORD_DIR="${COORD_DIR:-${REPO_ROOT}/coordinator/build/bin}" +DRY_RUN=false +RESET_DB=false + +while [[ $# -gt 0 ]]; do + case "$1" in + --config) CONFIG_FILE="$2"; shift 2 ;; + --dry-run) DRY_RUN=true; shift ;; + --reset) RESET_DB=true; shift ;; + -h|--help) sed -n '2,19p' "$0"; exit 0 ;; + *) log_error "Unknown option: $1"; exit 1 ;; + esac +done + +mkdir -p "$WORK_DIR" + +# ─── Helpers ───────────────────────────────────────────────────────────────── +pid_alive() { # pidfile -> true if file exists and process alive + local pidfile="$1" pid + [[ -f "$pidfile" ]] || return 1 + pid=$(cat "$pidfile" 2>/dev/null || true) + [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null +} + +any_of_our_pids() { # pid -> true if one of our pidfiles references it + local pid="$1" pf + for pf in "$WORK_DIR"/*.pid "$WORK_DIR"/prover-*/prover.pid; do + [[ -f "$pf" ]] || continue + [[ "$(cat "$pf" 2>/dev/null)" == "$pid" ]] && return 0 + done + return 1 +} + +check_port_free() { # port name -> error if occupied by a process we don't track + local port="$1" name="$2" pid + pid=$(lsof -ti :"$port" 2>/dev/null | head -1 || true) + if [[ -n "$pid" ]]; then + if any_of_our_pids "$pid"; then + log_info " port $port ($name): held by tracked pid $pid (will skip restart)" + elif $DRY_RUN; then + log_warn " port $port ($name): held by untracked pid $pid (would abort a real run)" + else + log_error " port $port ($name): held by untracked pid $pid ($(tr '\0' ' ' < /proc/$pid/cmdline 2>/dev/null | cut -c1-80))" + log_error " Stop it first (scripts/11-follow-stop.sh, or kill manually)." + exit 1 + fi + else + log_ok " port $port ($name): free" + fi +} + +run_step() { # in dry-run, print instead of executing + if $DRY_RUN; then + log_info "[dry-run] $*" + else + "$@" + fi +} + +# ─── Load config ───────────────────────────────────────────────────────────── +[[ -f "$CONFIG_FILE" ]] || { log_error "Config not found: $CONFIG_FILE"; exit 1; } +CONFIG_FILE="$(cd "$(dirname "$CONFIG_FILE")" && pwd)/$(basename "$CONFIG_FILE")" + +FORK_URL=$(jq -r '.fork.url' "$CONFIG_FILE") +ANVIL_RPC=$(jq -r '.fork.anvil_rpc' "$CONFIG_FILE") +SHADOW_DSN=$(jq -r '.db.dsn' "$CONFIG_FILE") +SCROLL_CHAIN=$(jq -r '.contracts.scroll_chain' "$CONFIG_FILE") +L1_MSG_QUEUE=$(jq -r '.contracts.l1_message_queue_v2' "$CONFIG_FILE") +ROLLUP_VERIFIER=$(jq -r '.contracts.rollup_verifier' "$CONFIG_FILE") +OWNER=$(jq -r '.contracts.owner' "$CONFIG_FILE") +PROVER_EOA=$(jq -r '.accounts.prover_eoa' "$CONFIG_FILE") +COMMIT_EOA=$(jq -r '.accounts.commit_eoa' "$CONFIG_FILE") +GENESIS=$(jq -r '.genesis' "$CONFIG_FILE") +[[ "$GENESIS" = /* ]] || GENESIS="${REPO_ROOT}/${GENESIS}" +CONFIG_NAME=$(basename "$CONFIG_FILE" .json) + +# ─── a. Sanity checks ──────────────────────────────────────────────────────── +log_info "=== a. Sanity checks ===" +require_cmd jq; require_cmd cast; require_cmd psql; require_cmd python3 +require_cmd forge; require_cmd anvil; require_cmd lsof + +# Alchemy key must be real, not a placeholder/demo +if [[ "$FORK_URL" == *demo* || "$FORK_URL" == *"<"* || "$FORK_URL" == *YOUR* ]]; then + log_error "fork.url in $CONFIG_FILE has no real API key: $FORK_URL" + exit 1 +fi +log_ok " fork.url key present" + +log_info " Checking shadow DB ($SHADOW_DSN) ..." +psql "$SHADOW_DSN" -Atq -c "SELECT 1" >/dev/null +log_ok " shadow DB reachable" + +# Attribute every write in the postgres server log (aids debugging "ghost" +# status writes — see TROUBLESHOOTING Trap 27 tail). ALTER SYSTEM persists in +# postgresql.auto.conf inside the data volume, so re-assert it on every +# bring-up: it is silently lost whenever the postgres container/volume is +# recreated. +if ! $DRY_RUN; then + psql "$SHADOW_DSN" -Atq -c "ALTER SYSTEM SET log_statement = 'mod';" >/dev/null \ + && psql "$SHADOW_DSN" -Atq -c "SELECT pg_reload_conf();" >/dev/null \ + && log_ok " postgres log_statement='mod' asserted (writes visible in the postgres server log)" \ + || log_warn " failed to set log_statement='mod' (non-fatal)" +fi + +log_info " Checking mainnet read replica ..." +timeout 15 psql "$MAINNET_DSN" -Atq -c "SELECT 1" >/dev/null \ + || { log_error "mainnet DSN unreachable: $MAINNET_DSN (is the RDS tunnel up?)"; exit 1; } +log_ok " mainnet DSN reachable" + +check_port_free 8390 coordinator-api +check_port_free 8391 coordinator-cron +check_port_free 18545 anvil + +# ─── b. Baseline DB sync ───────────────────────────────────────────────────── +# Window = everything NOT finalized at the fork block, up to the mainnet tip: +# L1 finalization is sequential (each finalize tx chains prevBatchHash), so the +# shadow must prove and finalize every committed-but-not-finalized bundle +# starting from the fork's lastFinalizedBatchIndex. With FOLLOW_FORK_HOURS_BACK +# > 0 this window covers the fork-back backlog PLUS everything mainnet produced +# between the fork block and now — that backlog is the run's catch-up phase. +# Anything older is already finalized on the fork and is copied only as a +# parent reference (marked done post-baseline). +# +# Resolve the fork block FIRST (rather than passing "latest") so that (a) the +# point is logged and reproducible, and (b) lastFinalized/lastCommitted below +# are read AT the fork block, not at the tip — with a fork-back hours this +# difference is exactly the backlog size. 300 blocks/hour = 12s L1 block time. +log_info "=== b. Baseline DB sync ===" +LATEST_BLOCK=$(cast block-number --rpc-url "$FORK_URL") +if [[ "$FOLLOW_FORK_HOURS_BACK" -gt 0 ]]; then + FORK_BLOCK_NUMBER=$((LATEST_BLOCK - FOLLOW_FORK_HOURS_BACK * 300)) +else + FORK_BLOCK_NUMBER=$LATEST_BLOCK +fi +log_info " fork block: $FORK_BLOCK_NUMBER (latest $LATEST_BLOCK, ${FOLLOW_FORK_HOURS_BACK}h back)" +LAST_FINALIZED=$(cast call "$SCROLL_CHAIN" "lastFinalizedBatchIndex()(uint256)" --rpc-url "$FORK_URL" --block "$FORK_BLOCK_NUMBER" | awk '{print $1}') +MAINNET_TIP=$(psql "$MAINNET_DSN" -Atq -c "SELECT MAX(index) FROM batch" | tr -d ' ') +MAINNET_BUNDLE_TIP=$(psql "$MAINNET_DSN" -Atq -c "SELECT MAX(index) FROM bundle" | tr -d ' ') +BASELINE_START=$((LAST_FINALIZED - 1)) +log_info " lastFinalizedBatchIndex@fork: $LAST_FINALIZED; mainnet batch tip: $MAINNET_TIP" +log_info " baseline window: ${BASELINE_START}..${MAINNET_TIP} ($((MAINNET_TIP - BASELINE_START)) batches = backlog + finalization lag)" +if $RESET_DB; then + # --reset: wipe task tables so the DB contains ONLY the finalization-lag + # window. Without this, stale rows from earlier runs/imports (thousands of + # pending historical batches) are seen by the coordinator as work. + # + # CRITICAL (Trap 26): any component that writes task tables MUST be stopped + # before the TRUNCATE. A relayer left running sees l2_block empty and its + # l2 watcher starts a full L2 genesis crawl (block 1 → tip, days of RPC + # calls, tens of GB of junk rows); an orphaned poll sync bulk-copies all + # mainnet history (Trap 25). A full stop also resets this script's + # idempotent pidfile checks, so every component is restarted fresh below. + log_warn " --reset: stopping all components before truncate" + if ! $DRY_RUN; then + bash "${SCRIPT_DIR}/11-follow-stop.sh" || log_warn " 11-follow-stop returned non-zero (continuing)" + fi + log_warn " --reset: truncating chunk/batch/bundle/l2_block/l1_message/pending_transaction" + if ! $DRY_RUN; then + psql "$SHADOW_DSN" -Atq --set ON_ERROR_STOP=1 -c "TRUNCATE chunk, batch, bundle, l2_block, l1_message" >/dev/null \ + || { log_error "TRUNCATE failed — aborting before baseline"; exit 1; } + # Trap 7/27: pending_transaction rows are not chain/fork-scoped. Stale + # rows from a previous run poison the relayer sender's nonce + # (initializeNonce = max(db_max+1, chain_nonce)) and can replay old + # calldata onto the fresh fork. Wipe them on every reset. + psql "$SHADOW_DSN" -Atq --set ON_ERROR_STOP=1 -c "TRUNCATE pending_transaction" >/dev/null \ + || { log_error "TRUNCATE pending_transaction failed — aborting"; exit 1; } + # Trap 21: wipe prover-local proof caches; they hold proofs from the + # previous run/circuit version and get replayed as VData mismatches. + rm -rf "${WORK_DIR}"/prover-*/db + # Remove stale state from the previous fork too: 01/03 will re-create it. + # follow-run.env carries the PREVIOUS run's report window (step j + # preserves SHADOW_REPORT_START on re-entry) — drop it on --reset so + # the new run gets a fresh report start time. + rm -f "${WORK_DIR}/anvil-${CONFIG_NAME}.state.json" "${WORK_DIR}/verifier.env" "${WORK_DIR}/follow-run.env" + fi +fi +export MAINNET_DSN +run_step python3 "${SCRIPT_DIR}/sync-mainnet-db.py" --init-from-batch "$BASELINE_START" +# Boundary rows (<= lastFinalized) are already finalized on the fork: mark +# them done so the coordinator never wastes work proving them. Their proof +# columns stay NULL — safe, they are only referenced via row fields +# (parent state root / hash), never by proof bytes. +# Rows ABOVE the boundary may carry stale rollup_status from a previous run +# on an older fork (finalized there, but not on this fresh fork): reset them +# so the relayer re-commits/re-finalizes them in chain order. Proofs already +# generated stay valid (proof content depends on L2 data, not L1 state). +if ! $DRY_RUN; then + MISC_RAW=$(cast call "$SCROLL_CHAIN" 0x06582acb --rpc-url "$FORK_URL" --block "$FORK_BLOCK_NUMBER") + FORK_COMMITTED=$((16#${MISC_RAW:2:64})) + log_info " fork lastCommittedBatchIndex: $FORK_COMMITTED" + psql "$SHADOW_DSN" -Atq -c " + UPDATE batch SET rollup_status = 5, proving_status = 4 + WHERE index <= ${LAST_FINALIZED} AND (rollup_status <> 5 OR proving_status <> 4); + UPDATE bundle SET rollup_status = 5, proving_status = 4 + WHERE end_batch_index <= ${LAST_FINALIZED} AND (rollup_status <> 5 OR proving_status <> 4); + UPDATE chunk SET proving_status = 4 FROM batch b + WHERE chunk.batch_hash = b.hash AND b.index <= ${LAST_FINALIZED} AND chunk.proving_status <> 4; + UPDATE batch SET rollup_status = 3, finalize_tx_hash = NULL, finalized_at = NULL + WHERE index > ${LAST_FINALIZED} AND index <= ${FORK_COMMITTED} AND rollup_status <> 3; + UPDATE batch SET rollup_status = 1, commit_tx_hash = NULL, committed_at = NULL, finalize_tx_hash = NULL, finalized_at = NULL + WHERE index > ${FORK_COMMITTED} AND rollup_status <> 1; + UPDATE bundle SET rollup_status = 1, finalize_tx_hash = NULL, finalized_at = NULL + WHERE end_batch_index > ${LAST_FINALIZED} AND rollup_status <> 1; + " >/dev/null + log_ok " rollup_status aligned to fork boundaries (finalized<=${LAST_FINALIZED}, committed<=${FORK_COMMITTED})" +fi + +# ─── c. Anvil fork at the chosen block ─────────────────────────────────────── +log_info "=== c. Anvil fork setup ===" +# FORK_BLOCK_NUMBER was resolved in step b (tip, or tip - FOLLOW_FORK_HOURS_BACK +# * 300). lastFinalized was read at that same block there. +log_info " fork block: $FORK_BLOCK_NUMBER" +log_info " lastFinalized: $LAST_FINALIZED (read from mainnet at fork block)" +log_info " nextQueueIndex: $NEXT_QUEUE" + +STATE_FILE="${WORK_DIR}/anvil-${CONFIG_NAME}.state.json" +if [[ -f "$STATE_FILE" ]]; then + # Anvil --state LOADS an existing file; a stale state file would silently + # resurrect the previous fork. Back it up so this fork starts fresh. + STATE_BAK="${STATE_FILE}.bak.$(date +%Y%m%d%H%M%S)" + log_warn " backing up existing state file -> $STATE_BAK" + run_step mv "$STATE_FILE" "$STATE_BAK" +fi + +ANVIL_FRESH=false +if pid_alive "${WORK_DIR}/anvil.pid"; then + log_info " Anvil already running (pid $(cat "${WORK_DIR}/anvil.pid")), skipping" +else + ANVIL_FRESH=true + # --deployed-verifier "" : 03-deploy-verifier.sh deploys a fresh wrapper + # below; the copy-from-old-fork fallback in 01 cannot work on a new fork. + run_step "${LIB_DIR}/01-setup-anvil.sh" \ + --fork-url "$FORK_URL" \ + --fork-block "$FORK_BLOCK_NUMBER" \ + --anvil-rpc "$ANVIL_RPC" \ + --state-file "$STATE_FILE" \ + --last-finalized "$LAST_FINALIZED" \ + --next-queue "$NEXT_QUEUE" \ + --deployed-verifier "" \ + --prover-eoa "$PROVER_EOA" \ + --commit-eoa "$COMMIT_EOA" \ + --owner "$OWNER" \ + --scroll-chain "$SCROLL_CHAIN" \ + --l1-msg-queue "$L1_MSG_QUEUE" \ + --rollup-verifier "$ROLLUP_VERIFIER" \ + --db-dsn "$SHADOW_DSN" +fi + +# ─── d. Deploy verifier wrapper ────────────────────────────────────────────── +# Full forge redeploy (not anvil_setCode) because anvil_setCode preserves the +# old wrapper's immutables (digest1/digest2/protocolVersion) — see AGENTS.md +# "anvil_setCode Does NOT Reset Immutables". +# EOA funding (owner/prover/commit) is already handled by 01-setup-anvil.sh +# step 7, so nothing extra is needed here. +log_info "=== d. Deploy verifier wrapper ===" +# Skip only when this is a re-entry into an already-running stack (Anvil not +# restarted by us) and a wrapper was previously deployed onto that same fork. +if [[ "$ANVIL_FRESH" != "true" && -s "${WORK_DIR}/verifier.env" && "${FORCE_REDEPLOY:-false}" != "true" ]]; then + log_info " verifier.env present and Anvil unchanged, reusing $(grep '^WRAPPER_ADDR=' "${WORK_DIR}/verifier.env" | cut -d= -f2)" +else + run_step "${LIB_DIR}/03-deploy-verifier.sh" --config "$CONFIG_FILE" +fi + +# ─── e. Initial queue-hash sync (Trap 23) ──────────────────────────────────── +log_info "=== e. L1 queue rolling-hash sync (Trap 23) ===" +export FORK_RPC="$ANVIL_RPC" +run_step python3 "${LIB_DIR}/sync-queue-hashes.py" + +# ─── f. Coordinator api + cron ─────────────────────────────────────────────── +log_info "=== f. Coordinator ===" +[[ -x "${COORD_DIR}/coordinator_api" ]] || { log_error "missing ${COORD_DIR}/coordinator_api (build: cd coordinator && make coordinator_api)"; exit 1; } +[[ -x "${COORD_DIR}/coordinator_cron" ]] || { log_error "missing ${COORD_DIR}/coordinator_cron"; exit 1; } + +# coordinator_api keeps using coordinator/build/bin/conf/config.json: verified +# its db.dsn already points at the shadow DB (localhost:5433/shadow_rollup) and +# it carries the api-specific prover_manager/verifier sections the running +# setup relies on. The shadow-testing follow/configs/coordinator.json is only needed +# for coordinator_cron, whose timeout checker requires the correct +# bundle/batch/chunk collection_time_sec values. +if pid_alive "${WORK_DIR}/coordinator-api.pid"; then + log_info " coordinator_api already running (pid $(cat "${WORK_DIR}/coordinator-api.pid")), skipping" +else + log_info " starting coordinator_api (log: .work/coordinator-api.log)" + if ! $DRY_RUN; then + ( + cd "$COORD_DIR" + setsid nohup ./coordinator_api \ + --config conf/config.json --http --http.addr 0.0.0.0 \ + --http.port 8390 --service.port 8390 \ + >> "${WORK_DIR}/coordinator-api.log" 2>&1 & + echo $! > "${WORK_DIR}/coordinator-api.pid" + ) + sleep 2 + pid_alive "${WORK_DIR}/coordinator-api.pid" || { log_error "coordinator_api died; tail .work/coordinator-api.log"; exit 1; } + fi +fi + +# coordinator_cron = timeout checker; must use the shadow-testing config with +# the correct collection times, plus the GalileoV2 genesis (current practice). +if pid_alive "${WORK_DIR}/coordinator-cron.pid"; then + log_info " coordinator_cron already running (pid $(cat "${WORK_DIR}/coordinator-cron.pid")), skipping" +else + log_info " starting coordinator_cron (log: .work/coordinator-cron.log)" + if ! $DRY_RUN; then + ( + cd "$PROJECT_ROOT" + setsid nohup "${COORD_DIR}/coordinator_cron" \ + --config "${PROJECT_ROOT}/configs/coordinator.json" \ + --genesis "$GENESIS" \ + --service.port 8391 \ + --log.file "${WORK_DIR}/coordinator-cron.log" --verbosity 3 \ + >> "${WORK_DIR}/coordinator-cron.log" 2>&1 & + echo $! > "${WORK_DIR}/coordinator-cron.pid" + ) + sleep 2 + pid_alive "${WORK_DIR}/coordinator-cron.pid" || { log_error "coordinator_cron died; tail .work/coordinator-cron.log"; exit 1; } + fi +fi + +# ─── g. Provers ────────────────────────────────────────────────────────────── +log_info "=== g. GPU provers ===" +PROVERS_RUNNING=true +IFS=',' read -ra GPU_ARRAY <<< "$GPUS" +for gpu in "${GPU_ARRAY[@]}"; do + pid_alive "${WORK_DIR}/prover-${gpu}/prover.pid" || PROVERS_RUNNING=false +done +if $PROVERS_RUNNING; then + log_info " provers on GPUs $GPUS already running, skipping" +else + run_step env GPUS="$GPUS" "${LIB_DIR}/04-prover-up.sh" --config "$CONFIG_NAME" +fi + +# ─── h. Relayer ────────────────────────────────────────────────────────────── +log_info "=== h. Rollup relayer ===" +# Trap 27: always (re-)ensure the relayer's senders can transact on the fork. +# 01-setup-anvil.sh does this too, but the idempotent path skips it when Anvil +# is already running (e.g. after an Anvil state restore wiped balances, +# sequencer authorization, or account nonces). All three ops are idempotent. +# Keep these keys in sync with 06-run-relayer.sh. +COMMIT_KEY="0x0afd95b5f1d9ef456b33c4e3720fbe70de7b4ff6e868fef454dc0aa60b09d8dc" +FINALIZE_KEY="0x01f1e12ee33f91d63172c3d51baa3cecb4469284b0ab45eed48e57fb5329ac4d" +COMMIT_SENDER=$(cast wallet address "$COMMIT_KEY") +FINALIZE_SENDER=$(cast wallet address "$FINALIZE_KEY") +if ! $DRY_RUN; then + cast rpc anvil_setBalance "$COMMIT_SENDER" 0x56bc75e2d63100000 --rpc-url "$ANVIL_RPC" >/dev/null + cast rpc anvil_setBalance "$FINALIZE_SENDER" 0x56bc75e2d63100000 --rpc-url "$ANVIL_RPC" >/dev/null + if [[ "$(cast call "$SCROLL_CHAIN" "isSequencer(address)(bool)" "$COMMIT_SENDER" --rpc-url "$ANVIL_RPC" 2>/dev/null)" != "true" ]]; then + log_warn " authorizing $COMMIT_SENDER as sequencer on the fork" + cast rpc anvil_impersonateAccount "$OWNER" --rpc-url "$ANVIL_RPC" >/dev/null + cast send --gas-limit 5000000 "$SCROLL_CHAIN" "addSequencer(address)" "$COMMIT_SENDER" \ + --from "$OWNER" --rpc-url "$ANVIL_RPC" --unlocked >/dev/null \ + || { cast rpc anvil_stopImpersonatingAccount "$OWNER" --rpc-url "$ANVIL_RPC" >/dev/null; log_error "addSequencer failed"; exit 1; } + cast rpc anvil_stopImpersonatingAccount "$OWNER" --rpc-url "$ANVIL_RPC" >/dev/null + fi + # isProver gates finalizeBundlePostEuclidV2 (ErrorCallerIsNotProver + # 0x7b263b17). An Anvil state restore from a pre-addProver backup silently + # drops it, and a failed finalize then strands the bundle at + # rollup_status=7 (not retried). Re-ensure it here, idempotently. + if [[ "$(cast call "$SCROLL_CHAIN" "isProver(address)(bool)" "$FINALIZE_SENDER" --rpc-url "$ANVIL_RPC" 2>/dev/null)" != "true" ]]; then + log_warn " authorizing $FINALIZE_SENDER as prover on the fork" + cast rpc anvil_impersonateAccount "$OWNER" --rpc-url "$ANVIL_RPC" >/dev/null + cast send --gas-limit 5000000 "$SCROLL_CHAIN" "addProver(address)" "$FINALIZE_SENDER" \ + --from "$OWNER" --rpc-url "$ANVIL_RPC" --unlocked >/dev/null \ + || { cast rpc anvil_stopImpersonatingAccount "$OWNER" --rpc-url "$ANVIL_RPC" >/dev/null; log_error "addProver failed"; exit 1; } + cast rpc anvil_stopImpersonatingAccount "$OWNER" --rpc-url "$ANVIL_RPC" >/dev/null + fi + log_ok " relayer EOAs funded (100 ETH), commit sender is sequencer, finalize sender is prover" +fi +if pid_alive "${WORK_DIR}/relayer-${CONFIG_NAME}.pid"; then + log_info " relayer already running (pid $(cat "${WORK_DIR}/relayer-${CONFIG_NAME}.pid")), skipping" +else + run_step env MIN_CODEC="$MIN_CODEC" "${LIB_DIR}/06-run-relayer.sh" --config "$CONFIG_NAME" +fi + +# ─── i. Background daemon loops ────────────────────────────────────────────── +log_info "=== i. Daemon loops ===" +start_loop() { # name interval logfile command... + local name="$1" interval="$2" logfile="$3"; shift 3 + local pidfile="${WORK_DIR}/${name}.pid" + if pid_alive "$pidfile"; then + log_info " ${name} loop already running (pid $(cat "$pidfile")), skipping" + return 0 + fi + log_info " starting ${name} loop (every ${interval}s, log: ${logfile})" + if ! $DRY_RUN; then + # Shell-escape each arg into a single command string. (Naive \"$@\" + # inside double quotes collapses all args into ONE quoted word.) + local cmd + cmd=$(printf '%q ' "$@") + # Detached self-restarting loop; pidfile tracks the loop shell. + setsid nohup bash -c "while true; do ${cmd} >>'${logfile}' 2>&1 || true; sleep ${interval}; done" \ + >/dev/null 2>&1 & + echo $! > "$pidfile" + fi +} + +start_loop sync-mainnet-db "$SYNC_POLL_INTERVAL" "${WORK_DIR}/sync-mainnet-db.log" \ + python3 "${SCRIPT_DIR}/sync-mainnet-db.py" --poll-interval "$SYNC_POLL_INTERVAL" +# Sweeper resets proving_status AND total_attempts (Trap 22/23 starvation traps). +start_loop sweeper "$SWEEP_INTERVAL" "${WORK_DIR}/sweeper.log" \ + bash "${SCRIPT_DIR}/sweep-stale-proving.sh" +# monitor-catchup.py appends to .work/catchup-metrics.log itself. +start_loop monitor "$MONITOR_INTERVAL" "${WORK_DIR}/monitor.log" \ + python3 "${SCRIPT_DIR}/monitor-catchup.py" + +# ─── j. Run metadata + summary ─────────────────────────────────────────────── +log_info "=== j. Run metadata ===" +FOLLOW_ENV="${WORK_DIR}/follow-run.env" +if ! $DRY_RUN; then + # Preserve an existing SHADOW_REPORT_START when components were skipped + # (i.e. this is a re-entry into an already-running run, not a fresh run). + EXISTING_START="" + [[ -f "$FOLLOW_ENV" ]] && EXISTING_START=$(grep '^SHADOW_REPORT_START=' "$FOLLOW_ENV" | cut -d= -f2- || true) + REPORT_START="${EXISTING_START:-$(date -u +%Y-%m-%dT%H:%M:%S%z)}" + cat > "$FOLLOW_ENV" < +# Kills the pid only if its cmdline matches the expected substring (guards +# against stale pidfiles whose pid was reused by an unrelated process). +stop_pid() { + local label="$1" pidfile="$2" expect="$3" pid + [[ -f "$pidfile" ]] || return 1 + pid=$(cat "$pidfile" 2>/dev/null || true) + if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then + if ! tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null | grep -qF "$expect"; then + log_warn " $label: pidfile stale (pid $pid is not '$expect'), not killing" + rm -f "$pidfile" + return 2 # let caller try a pattern/port fallback + else + # Loops/daemons are started via setsid, so the pidfile pid is a + # process-group leader: kill the whole group, otherwise children + # (e.g. the python sync process inside a bash loop) are orphaned + # and keep running against the DB. + kill -- "-$pid" 2>/dev/null || kill "$pid" 2>/dev/null || true + for _ in $(seq 1 10); do kill -0 "$pid" 2>/dev/null || break; sleep 1; done + if kill -0 "$pid" 2>/dev/null; then + log_warn " $label (pid $pid) ignored SIGTERM, sending SIGKILL" + kill -9 -- "-$pid" 2>/dev/null || kill -9 "$pid" 2>/dev/null || true + fi + STOPPED+=("$label (pid $pid)") + fi + fi + rm -f "$pidfile" + return 0 +} + +# fallback_pkill