Imported from zeko-labs/ethereum-settlement (
AGENTS.md). Install upstream withnpx skills add zeko-labs/ethereum-settlement. Copyright stays with the author.
Zeko Ethereum Settlement Agent Context
This repository is a proof-of-concept port of Zeko settlement from Mina to Ethereum. Treat it as experimental glue code around the real Zeko implementation, not as a replacement for the OCaml Zeko codebase.
Target Architecture
- The OCaml Zeko repository remains the source of ledger, transaction, bridge, action-state, proving, and rollup state-transition semantics.
- SP1 verifies the Mina/Pickles proof emitted by the OCaml Zeko circuits.
- Ethereum verifies the SP1 proof in Solidity.
- Solidity should only own Ethereum-side custody, settlement checkpointing, and minimal bridge/DA glue.
- Ethereum blob DA is the intended production DA path. Do not carry over the Mina-side DA committee as the final Ethereum design.
Current Settlement Shape
The current settlement PoC uses the o1 o1js-to-zkvm Pickles verifier path:
crates/pickles-verifieris adapted from o1'so1js-to-zkvmverifier.vendor/proof-systemsis the o1 SP1-compatible proof-systems branch.program/settlement/build.rsbuilds a verifier blob fromproofs/mainnet-blockchain-snark/vk.serde.json.crates/pickles-verifier/src/wire.rsaccepts both the legacy Kimchi-serde proof/VK files and Zeko's versioned compact OCaml wire. It reconstructs the native Kimchi values before verification; keep strict curve, length, and domain checks at this boundary.program/settlement/src/main.rsdecodes the verifier blob, reads aVerifiableProof, callspickles_verifier::verify, asserts the proof is valid, and commitsZkappPublicValues.script/src/bin/main.rs --executeusesMinimalExecutorRunnerdirectly. This avoids an SP1 6.1 SDK issue whereclient.execute(...).calculate_gas(false)returns public values but later fails withFailed to extract public value digest.
Do not reintroduce the old hand-written Mina-Rust/Kimchi-only settlement path.
It was incomplete for Pickles because Pickles requires the recursive/deferred
checks and accumulator verification in addition to outer Kimchi verification.
Do not add settlement-only serialization FFI to Zeko's proof-systems
submodule. The portable format is owned by Zeko's OCaml/Pickles layer, while
this repository owns conversion to the verifier's native Rust types.
Known Working Command
The last known successful local execute command was:
cargo run --release --bin zkapp -- --execute
It completed with:
proof_valid: truetotal gas: not calculated
Cycle counts depend on the guest and fixture revision. The authoritative optimization measurements are in the project status.
This command remains CPU-heavy, but the direct minimal-executor path should have much lower memory usage than the SP1 SDK execute wrapper.
Resource Safety
Be careful with SP1 workloads:
- The shared development Mac has only 16 GB RAM. For this workspace, run fake proving tests only: no real OCaml prover, SP1 execution, local or network proof generation, Groth16, or PLONK workloads.
- Reuse the persistent
zeko-devtmux session for Nix shells and builds. Inspect withtmux list-windows -t zeko-devand attach withtmux attach -t zeko-dev. Thezeko-devDocker container mounts the workspace at/workspace; its Nix store, home/toolchains, and Cargo target cache survive in named volumes. Do not recreate these or clean caches merely because a command observation timed out. - Limit builds to
CARGO_BUILD_JOBS=1andRAYON_NUM_THREADS=1, with Nix--max-jobs 1 --cores 1. Run one heavy Rust/OCaml build at a time. The container has a 6 GB memory cap; checkdocker stats --no-stream zeko-dev. - Do not run local proving on a laptop without explicit approval.
- Do not run
--prove, Groth16, PLONK, or network proof generation unless the user explicitly asks for it and the machine is sized for it. - Prefer running heavy SP1 commands on a remote Linux machine with at least 64 GB RAM; 128 GB+ is better for real proving.
- Use
tmuxand log output withteefor long runs. - Monitor memory with
ps,htop, or similar while running SP1 jobs. - If disk gets full, remove generated build artifacts such as
target/debug,target/release,target/elf-compilation, or temporary target directories. Never delete source, fixtures, or vendor directories unless asked.
Toolchain
Expected tools:
- Rust stable via
rustup - Succinct/SP1 toolchain installed via
sp1up cargo +succinct --versionshould workcargo prove --versionshould workprotoc- Go toolchain, because SP1 builds gnark-related components
- Docker/Foundry may be needed for Solidity/EVM paths
SP1 can build internal runner binaries under Cargo's registry cache. In sandboxed
environments this may require elevated filesystem access. If a build fails with
an error opening a .cargo-lock under
~/.cargo/registry/src/.../sp1-core-executor-runner-*/target, rerun the same
Cargo command outside the sandbox or with the appropriate approval.
Verification Commands
On the shared 16 GB Mac, use the non-deployable fake prover test build:
cargo test -p zeko-proof-api --no-default-features --features fake-prover-tests --bin zeko-proof-api -j 1
Set DATABASE_URL to an isolated PostgreSQL instance for the SQL regressions.
The persistent container uses
postgres://postgres@zeko-reliability-postgres/zeko_reliability_test.
See api/TESTING.md for reservation race tests and the
compile guard that prevents fake verification from being deployed.
The realized Rust Nix profile is /root/nix-profiles/zeko-rust; reuse it or
the existing zeko-dev:rust tmux shell rather than rebuilding an environment.
Useful non-proving checks:
cargo check --release --offline -p zkapp-script
cargo check --offline -p settlement-program -p zkapp-script -p zeko_sp1_lib -p zeko-proof-api
cargo test --offline -p pickles-verifier
cargo fmt --all
git diff --check
cargo fmt --all may print warnings about nightly-only rustfmt options such as
indent_style = Block and imports_granularity = Crate. Those warnings are
currently expected.
Settlement Binding Rules
The intended binding between Ethereum and the OCaml Zeko state transition is:
- L1 stores the expected Zeko verification-key hash.
- SP1 verifies the Mina/Pickles proof against that verification key.
- SP1 emits the verification-key hash in public values.
- Solidity compares the emitted hash to L1 state.
Do not add a separate Solidity account-update binding. The account update is public input to the Pickles proof; once the proof and verification-key hash are checked, that binding belongs inside the proof.
Important current limitation: the PoC vk_hash is currently a SHA-256 over the
fixture VK JSON bytes. Production must use the canonical OCaml/Mina
verification-key hash.
Current Public Values
The settlement guest derives versioned receipts from the verified OCaml proof:
- V1 binds the complete eight-field outer state, outer action state and length, synchronized checkpoint, slot range, Ethereum domain, batch sequence, Mina transaction hash, and verification-key identifier.
- V2 additionally binds the exact ordered inner actions to a depth-16 Keccak tree used by native and registered ERC-20 withdrawal claims.
- V3 additionally binds one proof-checked registry checkpoint, record hash, and canonical Mina Poseidon record commitment.
- V4 binds an ordered registry append batch through a depth-8 Keccak tree whose leaves contain both the Solidity record hash and Mina record commitment.
The remaining production limitation is data availability: no receipt binds EIP-4844 blob hashes or a canonical Zeko batch data root yet. Keep receipt and Solidity decoders versioned when extending the schema.
Data Availability Direction
The intended Ethereum DA design is blob-based:
- settlement transactions should be tied to ordered EIP-4844 blob versioned hashes
- the OCaml state-transition proof should use a batch data root derived from the blob payload as public input
- SP1 should emit the DA root and blob hashes
- Solidity should check emitted blob hashes against the blobs attached to the settlement transaction
There is currently no complete blob DA implementation. Missing pieces include
blob payload encoding, blob transaction submission, Solidity blobhash checks,
DA-root binding, blob archival/indexing, and an equivalence proof between the
EIP-4844 blob commitments and the Zeko batch data root.
Bridge Context
Read the original Zeko design docs in the sibling Zeko checkout under
src/app/zeko/circuits/design.
Important semantics from the OCaml design:
- L1 to L2 communication is via outer
Witnessactions. - L2 to L1 communication is via inner
Witnessactions. - Sequencer commits emit
Commitactions with ledger hash, inner action state, synchronized outer action state, action-state lengths, and slot bounds. - Deposits are accepted only once a later accepted commit synchronizes them.
- Deposits can be cancelled if timeout wins before accepting commit.
- Withdrawals need inclusion in a committed inner action state plus delay rules.
- Helper accounts track processed deposit/withdrawal/cancel indices.
The Solidity bridge custody code and SP1 bridge accumulator code are PoC glue, not the full Zeko bridge protocol.
Stale Or Legacy Areas
contracts/src/fixtures/groth16-fixture.jsonis legacy/stale until a fresh SP1 proof is generated.- The current settlement fixtures are o1 example fixtures. Production fixtures must come from the OCaml Zeko state-transition prover.
- Do not restore removed old files such as the hand-written Mina-Rust parser,
RKYV SRS blobs, or stale
proofs/*.txt/proofs/*.binfiles.
Development Style
- Keep changes scoped. This repo is glue around OCaml Zeko, so avoid inventing replacement ledger or bridge semantics in Rust/Solidity.
- Prefer reusing o1
o1js-to-zkvmverifier code for Pickles verification. - Prefer reusing OCaml Zeko outputs/fixtures for real state-transition data.
- Add negative tests for proof verification hardening when touching verifier logic.
- Do not silently change public-values layout or Solidity decoders without updating fixtures and documentation.
