[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"8iKbDGRgiy":3},"\u003Cdiv align=\"center\">\n\n![SP1 Lean](./.github/assets/header.png)\n\nFormal verification of SP1 Hypercube zkVM arithmetization\n\n\u003C/div>\n\n## Overview\n\nA formal verification, in **Lean 4**, of the RISC-V chips in\n[SP1](https://github.com/succinctlabs/sp1) — Succinct's zkVM.\n\nSP1 proves the correct execution of a RISC-V program by encoding each instruction as rows of arithmetic\nconstraints across a family of *chips* (one per operation: add, sub, bitwise, comparison, …). Those\nconstraints are written in Rust. This project takes the constraints SP1's chips actually enforce and\nproves, in Lean, that satisfying them forces the row to compute the right RISC-V result.\n\nThe circuits themselves are expressed in the [Clean](https://github.com/Verified-zkEVM/clean) zk-circuit\nDSL, and the reference for what each instruction *should* do is the official\n[Sail](https://github.com/riscv/sail-riscv) model of the RISC-V ISA. So a finished proof connects three\nthings: SP1's Rust constraints, the Clean circuit, and the RISC-V ISA.\n\n### What is proven\n\n- **Soundness** — if a chip's row satisfies its constraints, the row computes the result the RISC-V ISA\n  specifies for that instruction (proved against the Sail model). Every soundness theorem is\n  *axiom-clean* — `#print axioms` shows only Lean's standard axioms, no `sorry`.\n- **Completeness** — because the circuits carry explicit witnesses, we also prove that every correct\n  input is accepted (no spurious constraint rejects a valid row).\n- **Faithfulness** — the constraints the Lean proof reasons about are *exactly* the constraints SP1's Rust\n  code emits, so the proof can't be vacuously about a different circuit.\n\n### What is assumed / out of scope\n\n- The Sail model is taken as the ground-truth definition of RISC-V.\n- The Clean DSL and the Lean toolchain are trusted.\n- **Soundness is `sorry`-free.** A handful of *completeness* proofs are still deferred skeletons\n  (currently five: Mul, ShiftLeft, ShiftRight and DivRem chips, plus one prerequisite premise in the\n  gated-VM capstone). These are liveness gaps — they say \"this valid row is accepted\", not \"this row is\n  correct\" — so they never weaken a soundness claim. See [`docs/release-audit.md`](docs/release-audit.md)\n  for the exact inventory and [`docs/roadmap.md`](docs/roadmap.md) for the plan to close them.\n- This is a per-chip, per-row result plus a trace-level composition layer; it is not yet an end-to-end\n  proof of the whole zkVM.\n\n## Code Structure\n\nAll Lean sources live under `SP1Clean/`, with a mirror-of-SP1 layout. The root index\n`SP1Clean.lean` wires up every module's import.\n\n### `FormalModel/Contracts/`\nThe input structs and specifications, stated against the RV64 ISA functions — what each reader, operation,\nand chip is expected to compute.\n- `Contracts/Readers.lean` — reader-circuit specs (CPU state, R-type reader, register-access columns/timestamps).\n- `Contracts/Operations.lean` — operation-level specs.\n- `Contracts/Chips.lean` — chip-row `Inputs` + semantic `Spec`s; `Contracts/ChipAssumptions.lean` adds the ALU chips' `Assumptions`/`ProverAssumptions`.\n- `Trace/GuestProgram.lean` — the guest-program execution model (`GuestProgram`, `IsInitialState`, `SailChain`, `SP1Halted`).\n\n### `Math/`\nGeneral math with no SP1/Sail dependencies (the upstreaming candidate). Everything works over a prime field.\n- `Word.lean` — a `Word` as four little-endian 16-bit limbs, plus reassembly into a 64-bit value.\n- `Bitwise.lean` — byte-level AND/OR/XOR.\n- `MulCarryChain.lean` — multiplication carry-chain utilities.\n- `HWord.lean`, `GetElemFastPath.lean`, `Misc.lean` — half-word lemmas, a vector-access shim, misc lemmas.\n\n### `Model/`\nThe SP1 substrate — Sail wrappers and the lookup-bus model.\n- `Register.lean`, `SailWrap.lean`, `SailMemory.lean` — register state, Sail monad wrappers, and the Sail memory model.\n- `Channels.lean`, `ChipAir.lean`, `InteractionBus.lean`, `InteractionProjection.lean`,\n  `InteractionRecovery.lean` — the model of the lookup buses chips use to talk to each other.\n- `ByteTable.lean` — the static byte-lookup table (SP1's preprocessed `ByteChip`).\n- `SP1Constraint.lean` — shared SP1 opcode datatypes (`ByteOpcode`, `Opcode`).\n\n### `Native/Operations/` + `Proofs/Operations/`\nThe Clean circuit gadgets, one per operation (Add, Addw, Sub, Subw, Mul, Bitwise, BitwiseU16, Lt, U16Compare,\nU16MSB, U16toU8, IsZero(Word), IsEqualWord, Address, AddrAdd), each proved to compute the right 64-bit result.\nA structured op `\u003COp>/` is split across pillars: the witness + native arithmetic core\n(`Native/Operations/\u003COp>/{Populate,RawSpec}.lean`), the `FormalAssertion` proof\n(`Proofs/Operations/\u003COp>/Formal.lean`), and the auto-generated `eval` circuit (`Extracted/Circuit/\u003COp>.lean`).\nSingle-file (flat) ops live in `Native/Operations/`.\n\n### `Native/Readers/`\nRegister-adapter reader circuits that validate register reads/writes and instruction fetches per row:\n`CPUState.lean`, `RTypeReader.lean`, `ALUTypeReader.lean`, `RegisterAccessCols.lean`,\n`RegisterAccessTimestamp.lean`.\n\n### `Native/Chips/` + `Proofs/Chips/`\nThe chips: each composes the reader circuits, an operation gadget, and an `is_real` selector. A chip\n`\u003COp>Chip/` is split across pillars — the `main` circuit (`Native/Chips/\u003COp>Chip/Defs.lean`) and the\nsoundness/completeness proofs + Sail bridge (`Proofs/Chips/\u003COp>Chip/{Formal,Bridge}.lean`); the `Spec` lives\nin `FormalModel/Contracts/Chips.lean`. The ALU, control-flow, and memory chips are all here —\nAdd/Addi/Addw/Sub/Subw, Bitwise, Lt, Mul, DivRem, ShiftLeft/ShiftRight, AluX0, Branch, Jal/Jalr, UType, and\nthe Load*/Store*/LoadX0 memory chips — alongside the flat receiver-infra files `Proofs/Chips/ByteChip.lean`,\n`ProgramChip.lean`, and `MemoryProvider.lean`. (The 3 entangled complex chips DivRem/ShiftLeft/ShiftRight\nkeep their `Defs` in `Proofs/Chips/` too.) Soundness is proved and `sorry`-free throughout; a few\ncompleteness proofs are still deferred skeletons.\n\n### `Faithful/`\nThe faithfulness layer: proofs that the constraints used in the chip proofs are exactly those SP1 emits,\nplus witness-conformance checks (`*Witness.lean`) that the Lean witness matches SP1's `populate`. Shared\nscaffolding in `ChipTactics.lean` and `WitnessConformance.lean`.\n\n### `Extracted/`\nA copy of SP1's constraints, mechanically extracted from the Rust via `sp1-constraint-compiler`. The\nhand-written `ExtractionDSL.lean` defines the vocabulary these read in (a list of assertions plus lookup\ninteractions); the rest are the per-chip/op constraint lists, reader columns, and witness vectors.\n\n### `Soundness/`\nTrace-level consistency properties and the whole-machine capstone.\n- `ChipRow.lean` — the `ChipKind` structure-of-functions each chip registers.\n- `StateConsistency.lean` (PC chain), `MemoryConsistency.lean`, `ByteConsistency.lean`,\n  `ProgramConsistency.lean` — per-bus consistency.\n- `Opcode.lean` + `Coverage.lean` — the auditable `Opcode → chip → Sail` routing table (mirroring SP1's\n  `RiscvAir`); `InstructionTrace.lean` maps an instruction sequence to a `ChipRow` sequence;\n  `Completeness.lean` is the partial whole-VM-completeness layer.\n- `GatedVm/` + `SP1GatedVm.lean` — the execution capstone (`sp1_machine_soundness`), the final\n  Clean `FormalEnsemble`.\n\n### `SP1CleanTest/` — the test library (`lake test`)\nA separate top-level library (it imports `SP1Clean`, but is **not** part of the main `lake build`) holding\nthe conformance tests — the project's only `native_decide` (which trusts the whole compiler, so it is kept\nout of the main library by `scripts/check_no_native_decide.sh`). Two layers: `WitnessTests/` checks each\noperation's witness generator against explicit vectors dumped from SP1 (`\u003COp>Witness.lean` anchors +\nauto-generated `WitnessTests/Vectors/`), and `TraceGenTests/` checks whole chip traces re-derived from each\nchip's own circuit against SP1's real `generate_trace`. Shows conformance on test cases; doesn't directly\nprove witness generation faithful. Run with `lake test`.\n\n## How a proof connects to SP1\n\nEach operation is verified through a short chain of artifacts that together link SP1's Rust, the Clean\ncircuit, and the RISC-V ISA:\n\n1. **Gadget** (`Native/Operations/\u003COp>/` + `Proofs/Operations/\u003COp>/Formal.lean`) — the Clean circuit for the\n   operation, with a spec describing the result it computes on 64-bit words.\n2. **Chip** (`Native/Chips/\u003COp>Chip/Defs.lean` + `Proofs/Chips/\u003COp>Chip/Formal.lean`) — composes the gadget\n   with the register/instruction *readers* and an `is_real` selector, matching the shape of one of SP1's chips.\n3. **Sail bridge** (`Proofs/Chips/\u003COp>Chip/Bridge.lean`) — proves the chip's result matches the RISC-V ISA, as\n   defined by the Sail model.\n4. **Faithfulness anchor** (`Faithful/\u003COp>.lean`) — proves the constraints used above are exactly those SP1\n   emits, drawn from a Rust-extracted copy of SP1's constraints under `Extracted/`.\n\nBeyond a single row, chips talk to each other through lookup buses (registers, memory, the program ROM, a\nbyte table). These are modeled as a multiplicity-weighted interaction bus, with per-bus consistency lemmas\ncomposed into a whole-trace result. See [`docs/bus-model.md`](docs/bus-model.md) for that layer.\n\n## Building\n\n```bash\n# Build everything (the default target)\nlake build SP1Clean\n```\n\n## Toolchain & Dependencies\n\nAll dependencies are fetched from public Git repositories by `lake build` — there is nothing to check out\nby hand. They are pinned, and you should **not bump them**:\n\n| Dependency | Version / source |\n|------------|------------------|\n| Lean       | `leanprover/lean4:v4.28.0` (`lean-toolchain`) |\n| mathlib    | `github.com/leanprover-community/mathlib4 @ v4.28.0` |\n| Clean      | `github.com/Verified-zkEVM/clean @ main` |\n| `LeanRV64D` (Sail RV64 model) | `github.com/succinctlabs/sail-riscv-lean @ dtumad/clean-native` |\n| `RISCV` (lightweight RV64 ISA fns) | `github.com/succinctlabs/riscv-lean @ dtumad/clean-native` |\n| `Sail` (runtime) | `github.com/rems-project/lean-sail @ v4` (pulled in transitively) |\n\nThe two `succinctlabs/*` Sail dependencies are pinned to the `dtumad/clean-native` branch and each carries a\n4.28 `lean-toolchain`; this is what keeps the project from being bumped to 4.29.\n",1782661957278]