We have just folded space from Ix. Many machines on Ix. New machines.
The Ix platform enables the compilation of Lean 4 programs into zero-knowledge succinct non-interactive arguments of knowledge (zk-SNARKs). This allows the execution and typechecking of any Lean program to be verified by performing a sub-100-millisecond operation against an approximately 1 kilobyte certificate, regardless of the size of the original Lean program. In fact, the correctness of the entire mathlib library of formal mathematics, containing around 2 million lines of code, may be compiled in this way into a single kilobyte sized cryptographic certificate.
We call this technique zero-knowledge proof-carrying code or zkPCC, as an extension of the well-known proof-carrying code paradigm. Instead of a host system verifying formal proofs carried by an application as in proof-carrying code, in zkPCC the host or user verifies a cryptographic zero-knowledge proof generated from the typechecking of that formal proof. This greatly improves the runtime cost of this verification operation (potentially even up to O(1) depending on the specific zk-SNARK protocol used) and minimizes the complexity of locally dependent tooling (e.g. build systems for the formal proof language).
Additionally, while in proof-carrying code an application must reveal the proof artifact that demonstrates some formal property to the user, in zkPCC this proof artifact may be kept private, which opens up new possibilities for economic transactions over proofs.
⚠️ This repository is a pre-alpha work in progress and should not be used for any purpose.
Our expectation is that Ix, and zkPCC in general, will allow applications to frictionlessly ship security guarantees to their users. Some possible use cases could be:
- Software written in compiled languages like Rust can attach to their binaries proofs of type signatures or other formal properties verified by tools such as Aeneas. Given mature certified compilation infrastructure (e.g. a future CompCert equivalent in Lean4), proofs that the compilation occurred correctly can also be attached, which would mitigate supply-chain attacks, such as those famously described by Ken Thompson in Reflections on Trusting Trust. This would also enable secure decentralized binary caching, saving on the need for duplicative local recompilation or expensive continuous integration software.
- In operating systems, hardware based process isolation costs 25%-33% overhead in terms of processor cycles. This means everytime you buy a laptop, cell phone, web server, you have to pay for a third more computing power, because we don't know how to safely run applications in protection ring 0. By reducing verification overhead and improving portability over proof-carrying code, zkPCC potentially enables more sophisticated software-based process isolation.
- Decentralized platforms like the Ethereum blockchain could publish formal specifications of their protocol and then require clients, layer-2s, zkVMs, etc. to publish zkPCC proofs that their current specific version satisfies such specifications. Such proofs could be verified on-chain, and even programmatically gate certain protocol updates (e.g. version X validates that version X+1 is a correct update).
- Individual smart contracts can publish on-chain proofs of their formal models or proofs showing that their bytecode was generated from particular sources (currently a trusted block explorer feature).
- Cryptographic projects like the risc0 zkVM could include a proof of the correctness of their Lean 4 formal model alongside (or aggregated within) every proof produced by their zkVM.
In or around 1637, the mathematician Pierre Fermat conjectured the following:
- It is impossible to separate a cube into two cubes, or a fourth power into two fourth powers, or in general, any power higher than the second, into two like powers.
- I have discovered a truly marvelous proof of this
- which this margin is too narrow to contain.
The first part of this statement famously evaded proof for over 350 years before finally being demonstrated by Andrew Wiles in 1994. Mathematicians and historians of mathematics have also long debated the second part, whether Fermat's claim that he possessed a proof of the first part is credible, which seems unlikely given the complexity and modern mathematical infrastructure used by the Wiles proof of the first part. Rarely discussed, however, is the third part, which is in fact a statement of proof theory, specifically one which proposes an information theoretic lower bound to the size of the proof of a particular proposition.
The specific margin in question is page 85 in the 1621 edition of Diophantus' Arithmetica, which is a folio volume with dimensions 353mm tall by 225mm wide by 40mm deep. Leaving the precise dimensions of the margins as an exercise to the reader, it is trivial to show the proposition is false regardless of margin size, or the size of the proof (up to very large bounds) if one permits the proof to printed in the margin using arbitrarily small text, using microfilm, photolithography, etc. It is more interesting to assume that what Fermat meant was that the margin is too narrow to contain a proof written in Fermat's own handwriting.
Happily, we have an example of text we know would satisfy this constraint, Fermat's margin note itself! In Latin, the note reads:
Cubum autem in duos cubos, aut quadratoquadratum in duos quadratoquadratos & generaliter nullam in infinitum ultra quadratum potestatem in duos eiusdem nominis fas est dividere cuius rei demonstrationem mirabilem sane detexi. Hanc marginis exiguitas non caperet.
At 262 characters, and 8-bits per character, this is 2096 bits, or 262 bytes. This is quite small, but fortunately not quite as small as a Groth16 proof over BN254:
A Groth16 proof has two G1 points and one G2. In the BN254 pairing curve these take 64 and 128 bytes respectively uncompressed totaling 256 bytes for a proof.
So if we can show that a Groth16 proof of a proof of the first part of Fermat's Last Theorem is constructible, we will have clearly - though non-constructively- disproven the third part.
A Lean 4 formalization of Fermat's Last Theorem is in progress, and gives the statement as:
theorem PNat.pow_add_pow_ne_pow
(x y z : ℕ+)
(n : ℕ) (hn : n > 2) :
x^n + y^n ≠ z^n :=
PNat.pow_add_pow_ne_pow_of_FermatLastTheorem FLT.Wiles_Taylor_Wiles x y z n hnCurrently, as the dependencies of this theorem contain sorry holes, we cannot
feed it through ix (which only works over complete program graphs). Once the
formalization is complete, however, you will be able to do
> ix store FLT.lean PNat.pow_add_pow_ne_pow
e53c3d4bad8538e152a89d8bf75be178a3876252744961b9a087fe3973545c20
> ix prove --check e53c3d4bad8538e152a89d8bf75be178a3876252744961b9a087fe3973545c20
b44236ba17ad7445ae3eac48a8ba86ba00f08c069237b08451e311b688146e7e
to generate a multi-STARK proof that the theorem typechecks. With a Groth16 circuit that recursively proves verification of such proofs, i.e. a Groth16 final SNARK, the construction is complete, and we can embed a proof of Fermat's Last Theorem in Fermat's Margin Note.
Ix consists of the following core components:
- The Ix compiler,
which transforms Lean 4 programs into a format called
ixon, the ix object notation, which is an alpha-invariant content-addressable serialization or wire format. The compiler also includes a decompiler to convertixonobjects back into Lean programs (by preserving the alpha-relevant metadata in a separate ixon object and re-merging the computationally relevant and irrelevant parts). - The Aiur zkDSL which is a first-order functional programming language that generates multi-STARK circuits.
- The IxVM (not yet released), which implements reduction and typechecking
of
ixon(including ingress and egress from and to binary data). - Integration with the iroh p2p network so that
different ix users can easily share
ixondata between themselves.
Compiler performance benchmarks are tracked at https://bencher.dev/console/projects/ix/plots
- Install Clang to enable Bindgen, then set
LIBCLANG_PATHper https://rust-lang.github.io/rust-bindgen/requirements.html
- Build and test the Ix library with
lake buildandlake test - Install the
ixbinary withlake run install, or run withlake exe ix
Lean tests: lake test
lake test -- <suite>runs one or multiple primary test suites. Primary suites:ffi,byte-array,ixon,claim,commit,canon,keccak,sharing,graph-unit,condense-unitlake test -- --ignoredruns only the expensive test suites:shard-map,rust-canon-roundtrip,serial-canon-roundtrip,parallel-canon-roundtrip,graph-cross,condense-cross,compile,decompile,rust-serialize,rust-decompile,commit-io,aiur,aiur-hashes,ixvm- Most tests require at least 32 GB RAM
- The
compileanddecompiletests require 128 GB RAM aiurandaiur-hashesgenerate ZK proofs and use significant CPU
lake test -- --ignored <ignored-suite>runs one or multiple expensive suites by namelake test -- --include-ignoredruns both primary and expensive test suiteslake test -- --include-ignored <ignored-suite>runs all primary suites plus one or multiple expensive suiteslake test -- cliruns CLI integration testslake test -- rust-compileruns the Rust cross-compilation diagnostic
Rust tests: cargo test or cargo nextest run
The Ix kernel typechecker has an SP1 guest at sp1/guest/ driven by a host at
sp1/host/. The workflow is two steps: first compile a Lean program to a .ixe
serialized Ixon.Env, then feed that file to the SP1 host to either execute or
prove the typecheck.
Nix users only: enter the SP1 dev shell first to pick up cargo-prove and
the succinct Rust toolchain:
nix develop .#sp1
Non-Nix users: install the SP1 toolchain manually per the SP1 docs.
-
Compile a
.ixefrom a Lean file.ix compiletakes the Lean source as a positional argument and writes the serializedIxon.Env;--outsets the output path (default: the lowercased input stem plus.ixe). For a small demo env:lake exe ix compile Tests/MinimalDefs.lean --out minimal.ixeFor a larger, realistic env compile one of the
Benchmarks/Compiletargets, then scope proving to a single constant with--constant(step 2):lake exe ix compile Benchmarks/Compile/CompileInit.lean --out init.ixe -
Execute or prove under SP1. From
sp1/host/, run the host with--ixepointing at the file produced above:cd sp1/host # Execute the kernel typecheck in the SP1 VM (no proof), prints failures + cycles RUST_LOG=info cargo run --release -- --execute --ixe ../../minimal.ixe # Generate and verify a compressed SP1 proof of the same typecheck (CPU) WITHOUT_VK_VERIFICATION=1 RUST_LOG=info cargo run --release -- --ixe ../../minimal.ixe # Prove a single constant out of a larger env (Anon-only): the host resolves # the name and ships only that constant's closure sub-env. Full-closure by # default; add --skip-deps for a subject-only check (deps trusted). WITHOUT_VK_VERIFICATION=1 RUST_LOG=info cargo run --release -- --ixe ../../init.ixe --constant Nat.add_commWith no
--ixe, the host runs against an emptyIxon.Env.Verifying-key bypass (
WITHOUT_VK_VERIFICATION=1). Proving currently requires this environment variable;--executedoes not. The guest hashes via the patched BLAKE3'sBLAKE3_COMPRESSprecompile (seeargumentcomputer/BLAKE3branchsp1), whose recursion shapes aren't in the SP1 prover's bundledvk_map.bin. Without the bypass, proving aborts withvk not allowed/vk_root mismatch. The host is built with the SP1 fork'sexperimentalfeature, which honors this variable on both the prover and the light-node verifier. Drop it once a productionvk_map.binis regenerated with the new chip.Kernel modes. The default is Anon mode (metadata-erased kernel with lazy on-demand ingress — matches Aiur's
kernel_check_testsemantics). Pass--metato run Meta mode (preserves names + dup-level-param check; eager full-env ingress). Both prove the same structural typecheck; Meta is strictly more constrained but slightly more expensive in cycles.GPU proving (pre-production; depends on the SP1 fork). Build with the
cudafeature and setSP1_PROVER=cuda. Beyond the stock SP1 CUDA prerequisites (an NVIDIA GPU with CUDA 12+), the BLAKE3_COMPRESS precompile needs two prebuilt binaries that cannot come from a crate registry and must be produced from a local checkout of theargumentcomputer/sp1fork'sblake3-precompilebranch. SetSP1_FORK_DIRto that checkout. Skipping either step does not fail loudly — you getinvalid syscall number(stale runner) or a hang/ConnectionRefused(missing gpu-server).-
Runner-binary. The host spawns execution children from
sp1-core-executor-runner-binary, which embeds the JIT syscall dispatch; a stock/stale one panicsinvalid syscall numberon BLAKE3_COMPRESS. Build it from the fork and point the host at it:(cd "$SP1_FORK_DIR" && cargo build --release -p sp1-core-executor-runner-binary) export SP1_CORE_RUNNER_OVERRIDE_BINARY="$SP1_FORK_DIR/target/release/sp1-core-executor-runner-binary" -
GPU server. Install the fork's
sp1-gpu-serveronce into~/.sp1/binvia$SP1_FORK_DIR/sp1-gpu/scripts/install-fork-gpu-server.sh. The server extracts its own embedded runner to/tmp/sp1-native-runner-bin-{HASH}only if no file is already there, so pre-write the fork's runner-binary to that path to win the race (the hash is in the server binary:strings ~/.sp1/bin/sp1-gpu-server | grep -oE 'sp1-native-runner-bin-[0-9a-f]{64}').
With both in place:
WITHOUT_VK_VERIFICATION=1 SP1_PROVER=cuda RUST_LOG=info \ cargo run --release --features cuda -- --ixe ../../minimal.ixeOn an RTX PRO 6000 a
nataddcomm.ixecompressed proof takes ~14 s on GPU vs ~466 s on CPU.WITHOUT_VK_VERIFICATION=1is required as above; none of this is production-safe untilvk_map.binis regenerated with the new chip. See the SP1 CUDA docs for the base CUDA prerequisites.CUDA startup race (
scripts/cuda-runner.sh).sp1/.cargo/config.tomlwires every binary throughscripts/cuda-runner.sh, which works around an SP1 6.x CUDA-prover startup race: the SDK only retries the gpu-server socket connect for ~1 s (CUDA init can take longer),kill_on_dropSIGKILLs the server leaving an orphaned/tmp/sp1-cuda-*.sock→ConnectionRefused, and the NVIDIA driver holds contexts for tens of seconds after a SIGKILL so a fast retry hangs incuInit. The runner cleans the stale socket and retries with progressive backoff. It is a pass-through no-op whenSP1_PROVERis notcuda. -
The Ix kernel typechecker also has a Zisk guest at zisk/guest/ driven by a
host at zisk/host/. The workflow mirrors the SP1 one — first compile a Lean
program to a .ixe, then feed it to the Zisk host to either execute or prove
the typecheck.
Nix users only: enter the Zisk dev shell first to pick up cargo-zisk,
ziskemu, and the RISC-V toolchain needed to build the guest:
nix develop .#zisk
Non-Nix users: install Zisk manually per the Zisk install docs.
-
Compile a
.ixefrom a Lean file. Same as for SP1:lake exe ix compile Tests/MinimalDefs.lean --out minimal.ixe -
Execute or prove under Zisk. From
zisk/, run the host with--ixe:cd zisk # Execute the kernel typecheck in the Zisk VM (no proof), prints cycles RUST_LOG=info cargo run --release -- --execute --ixe ../minimal.ixe # Run the constraint checker without generating a proof RUST_LOG=info cargo run --release -- --verify-constraints --ixe ../minimal.ixe # Generate and verify a VadcopFinal proof of the same typecheck (CPU) RUST_LOG=info cargo run --release -- --ixe ../minimal.ixe # Check a single named constant out of a larger env. The host resolves the # name and ships only its closure sub-env (lazy fault-in, no whole-env load). # By default this is the FULL-CLOSURE typecheck — the constant and its whole # dependency closure (matching the Aiur `bench-typecheck --constant`). # Composes with --execute (cycles only) and plain prove. RUST_LOG=info cargo run --release -- --execute --ixe ../init.ixe --constant Nat.add_comm RUST_LOG=info cargo run --release -- --ixe ../init.ixe --constant Nat.add_comm # Add --skip-deps for a subject-only check (deps trusted, not re-checked): RUST_LOG=info cargo run --release -- --execute --ixe ../init.ixe --constant Vector.extract_append --skip-deps--constant/--skip-depsare the same flags the Aiurbench-typecheckuses, so the two backends share one vocabulary.--skip-depstrusts dependencies rather than re-checking them, so it is far cheaper than the full-closure default — reserve it for constants too expensive to full-closure-check that also can't be sharded (e.g.Vector.extract_appendover Init/Std). Seedocs/zisk-cycle-cost-model.mdfor the measured cost models across constant shapes.With no
--ixe, the host runs against an emptyIxon.Env. The host'sbuild.rsinvokeszisk_sdk::build_program("../guest"), socargo runtransparently rebuilds the guest ELF whenever its sources change.Kernel mode. The Zisk host runs Anon mode only (metadata-erased kernel with lazy on-demand ingress); there is no
--metaflag.GPU proving. Pass
--gpuat runtime — Zisk's prover backend ships with CUDA support by default (thecpu-onlyCargo feature is opt-out and is not set here):RUST_LOG=info cargo run --release -- --gpu --ixe ../minimal.ixeRequires a CUDA-capable GPU and the matching CUDA runtime libraries visible to the linker (
LD_LIBRARY_PATH). The Nix.#ziskshell wires these up automatically; for non-Nix setups follow the Zisk install docs.CUDA JIT cache (
CUDA_CACHE_MAXSIZE). The driver caches compiled proving kernels (PTX→SASS, under~/.nv/ComputeCache) and reuses them across processes — that's what keeps a second run warm. The default cap (~1 GB) is small enough that as a run JITs more kernel variants (bigger envs, more state-machine shapes) it forces LRU eviction and intermittent re-JIT cold spikes mid-run. Pin it to the 4 GB hard max to remove that failure mode (cost is only disk):export CUDA_CACHE_MAXSIZE=4294967296 # 4 GBWarm-batch proving and cold-start. The first GPU proof on a machine pays a large one-time cold-start: the proving kernels are JIT-compiled (PTX→SASS), almost entirely inside
GENERATING_INNER_PROOFS. Measured on an RTX PRO 6000, anataddcomm.ixeproof takes ~126 s cold vs ~12 s warm (the inner-proof phase alone drops from ~123 s to ~9 s; EXECUTE andCALCULATING_CONTRIBUTIONSare unchanged). Two things reuse that work:--ixeis repeatable, so passing several inputs proves them in one process and pays the cold-start once for the whole batch; and the JIT output is cached on disk (CUDA_CACHE_MAXSIZEabove), so even a fresh process stays warm — the ~12 s figure above is a separate process from the cold run. So a single small one-off proof looks slow (it eats the cold-start); amortize by batching, or just disregard it. By default proving is stateful with no checkpointing — if a run is killed it loses in-flight shard proofs and restarts from the first shard; use a proof store (--store-dir, see Sharding large environments below) to make a sharded run resumable.RUST_LOG=info cargo run --release -- --gpu \ --ixe ../nataddcomm.ixe --ixe ../stringappend.ixeMemlock limit (Linux). Zisk's assembly emulator
mmaps ROM and trace buffers withMAP_LOCKED, so the per-process locked-memory rlimit (ulimit -l) must be high enough to back the trace. Many Linux distros default to a low memlock limit; the Linux kernel itself sets non-privileged processes toRAM / 8, which is still too small for larger envs. Symptom:mmap(rom) errno=11=Resource temporarily unavailablefollowed byShmem creation … failed with exit status: 255duringSTARTING_ASM_MICROSERVICES.Per-shell (does not survive new logins or reboot):
sudo prlimit --memlock=unlimited:unlimited --pid $$ ulimit -l # confirm: prints 'unlimited'Persistent (recommended; both edits needed because
systemdand PAM apply rlimits on different paths —DefaultLimitMEMLOCKonly reaches services systemd spawns directly, interactive shells go through PAM):# 1. systemd-spawned services sudo sed -i 's|^#DefaultLimitMEMLOCK=.*|DefaultLimitMEMLOCK=infinity|' \ /etc/systemd/system.conf # 2. PAM session limits (applied to login shells, sudo, etc.) sudo tee /etc/security/limits.d/99-memlock.conf >/dev/null <<'EOF' * soft memlock unlimited * hard memlock unlimited EOF # Apply: log out of every login shell and back in (no reboot needed). # Verify in a new shell: ulimit -l # → unlimited cat /proc/$$/limits | grep "locked" # → unlimited / unlimitedMatches the Zisk installation docs.
Heap cap. The Zisk zkVM has a hard 512 MB RAM cap (
RAM_SIZE), of which ~510 MB is usable heap, and isn't configurable without rebuilding the proving setup. Envs whose deserialized in-memory representation exceeds that won't fit (fullTutorialDefs.leanpulls in Lean stdlib + Batteries + LSpec, around 1 GB resident). For bigger envs, prefer the SP1 backend (default 24 GB runtime capDEFAULT_MEMORY_LIMIT, configurable viaMEMORY_LIMITenv var up to a ~1 TB JIT ceilingMAX_JIT_LOG_ADDR), or scope to a single constant with--constant <name>(all backends), which resolves the name and ships only that constant's closure sub-env to the guest. By default it re-checks the full dependency closure; add--skip-depsto check it subject-only (dependencies trusted and lazily faulted in, not re-typechecked) — so individual constants of a large env still fit the cap, even ones whose full-closure typecheck would not. To prove a large env in full under Zisk, shard it (see Sharding large environments below): each shard ships only its own closure sub-env, so the pieces fit the cap even when the whole env does not.Host RAM cap (
--max-witness-stored). Distinct from the in-guest heap cap above, the prover side (Zisk'sproofman) holds in-flight witness traces in host RAM duringCALCULATING_CONTRIBUTIONS. Peak host RAM per shard ≈fixed-overhead + N × avg-witness-size, whereNis themax_witness_storedsetting. With the Blake3f precompile the Ix kernel typecheck workload measures roughly40 GB + N × 16 GBon typical 200–300 kB anon-byte shards — e.g.N = 10peaks near 200 GB (a--shard-bytes 250000 --max-witness-stored 10mergesort run completes under a 200 GiB guard without tripping it). An earlier pre-Blake3f figure of ~25 GB per witness is stale; the precompile shrank the witness.The
zisk-hostCLI defaults to--max-witness-stored 5(Zisk's built-in default is 10, tuned for larger-memory boxes). Override per machine:Host RAM --max-witness-storedNotes ≤ 128 GB 3Override down; consider smaller shards too 256 GB 5(project default)Comfortable margin on the typical setup 512 GB 10(Zisk default)Override up for maximum prover parallelism ≥ 1 TB 10(Zisk default)Override up; default is conservative for this workload Lowering the cap roughly linearly bounds peak RAM but throttles prover parallelism (~10–30 % slower in practice). Raise it if your machine has more RAM headroom; lower it if you OOM during
CALCULATING_CONTRIBUTIONS. Not relevant for--executeor--verify-constraintsmodes. -
Sharding large environments. A whole large env (e.g. all of
Init) does not fit a single Zisk proof: it overruns both the 512 MB guest heap and, more bindingly, the prover's minimal-trace shared-memory ceiling (64 GB per job on the assembly path). Sharding splits the env's type-checking work into pieces that are proven independently — each shipped with only its own dependency closure — and then folded into one aggregate proof. This is a two-part workflow: produce a shard manifest (a.ixesfile), then prove it with--shard-plan.(a) Produce a shard manifest. A manifest partitions the env's per-constant work, packing shards to a resource cap by real type-checking cost and cutting where cross-shard dependencies are fewest.
Profiling runs the kernel over the env (slow) and writes a
.ixprofcost map; sharding is instant graph work on that map, so it is cheap to re-tune without re-profiling. Both steps areixCLI subcommands:# Profile once (slow): init.ixe → init.ixprof (cost map + delta graph). lake exe ix profile init.ixe # Shard (instant): init.ixprof → init.ixes manifest. With no budget flags # it bin-packs to the fewest shards that each fit this box's RAM (peak # prover RAM ≈ `50 + 33 × cycles_billions` GB, targeting ~85 % of total). lake exe ix shard init.ixprof # Or pick a per-shard budget / a fixed count instead: # --max-ram 256 --max-cycles 4500000000 --shards 16ix shardalso reports the shard count, total predicted cycles, and a prove-time estimate from the measured leaf model (54 s + 158 s·Bstepsper shard). Sharded proving is sequential today, so the estimate assumes one prover;--parallelism Ndivides the wall-clock for a future N-prover setup (the sequential total is always shown alongside).(b) Prove the manifest. Pass the
.ixesto the host with--shard-planalongside the same--ixeit was built for. Each shard becomes one leaf proof (built over only that shard's closure sub-env), and the leaves fold up the manifest's aggregation tree into a single root proof:cd zisk RUST_LOG=info cargo run --release -- --gpu \ --ixe ../init.ixe --shard-plan ../init.ixesResumable proving (
--store-dir). A proof store makes a sharded run restartable and lets proofs be reused across runs and envs:RUST_LOG=info cargo run --release -- --gpu \ --ixe ../init.ixe --shard-plan ../init.ixes \ --store-dir ../init-store --require-closed--store-dir DIR: each completed shard proof is banked toDIR/proofs/<n>.{proof,cover,asm}as it finishes. Re-run the same command to resume — shards already covered by the store are skipped (not re-proven) and folded into the aggregate instead. Reuse is trustless: a stored proof is re-verified in-circuit at aggregation, never trusted by the host. Proofs are content-addressed, so a constant proven in one env is reused in any other env that contains it.--no-reuse: ignore the store for this run (the "no sharing" baseline); the existing store is neither read nor overwritten.--require-closed: error before proving unless every typing dependency of every certified constant is either proven in this run or already in the store — axioms are the only permitted residual. Turns "result modulo axioms" from a printed hope into an enforced precondition. Pairs with--planfor a no-prove check.
Other shard modes and tuning flags.
- Static partitioning without a manifest:
--shard-consts N(N work items per shard) or--shard-bytes B(pack contiguous items until serialized bytes exceedB). Simpler, but not balanced by real type-checking cost —--shard-planis the performant path. --plan: print the planned partition and exit, no proving.--execute: run the shards in the VM only and print per-shard cycle counts — use it to measure a shard's true cycle cost (e.g. to pick or recalibrate a cycle budget) without proving.--only-shard K: prove just the 1-indexed shardK(skips aggregation) for smoke-testing a single shard.--dump-input FILE: write one shard's guest stdin toFILEfor standalone profiling withziskemuorcargo-zisk.--agg-arity A(default 16): how many child proofs each aggregation step folds at once.
-
Install Nix
-
Enable Flakes
- Add
experimental-features = nix-command flakesto~/.config/nix/nix.confor/etc/nix/nix.conf - Add
trusted-users = root MYUSERto/etc/nix/nix.conf - Then restart the Nix daemon with
sudo pkill nix-daemon
- Add
Build and run the Ix CLI with nix build and nix run.
This will prompt you to optionally enable the Garnix cache, which can also be done by passing --accept-flake-config to the Nix command. Then when building, you should see copying path '/nix/store/<...>' from https://cache.garnix.io
To build and run the test suite, run nix build .#test and nix run .#test.

