You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Takes WHIR proof and produces Groth16 proof for on-chain verification via gnark
52
+
- CLI (`cmd/cli/`) and HTTP server (`cmd/server/`) modes
53
+
- R1CS must match the WHIR proof being verified; PK/VK must be generated together
54
+
55
+
## Critical Invariants
56
+
57
+
These invariants are critical for soundness. Violations can produce unsound proofs or verification failures.
58
+
59
+
### R1CS Constraint Satisfaction
60
+
```
61
+
For all constraints i: (A[i] · w) * (B[i] · w) = C[i] · w (mod BN254 prime)
62
+
```
63
+
Changes to `noir_to_r1cs()`, WitnessBuilder variants, or R1CS optimization passes must preserve this.
64
+
65
+
### Fiat-Shamir Transcript Determinism
66
+
Prover and verifier must construct identical Fiat-Shamir transcripts. The domain separator is derived from the serialized `WhirR1CSScheme`. Any change to proof structure, commitment ordering, or message sequencing breaks transcript consistency and causes verification failure.
67
+
68
+
### Public Input Binding
69
+
```
70
+
public_inputs[i] == witness[1 + i] for all i < num_public_inputs
71
+
```
72
+
The witness at position 0 is the constant `1`. `make_public_weight` and `compute_public_eval` use `n = num_public_inputs + 1` to account for this. Off-by-one here is a soundness vulnerability (see PR #321).
73
+
74
+
### Witness Layer Scheduling
75
+
Witness builders execute in layers. All builders depending on a `Challenge` must be in a later layer than the challenge source. Within a layer, execution order is irrelevant. Layers of type `Inverse` use Montgomery's batch inversion trick (single field inverse + multiplications). Violating layer ordering causes panics in `solve_witness_vec()`.
76
+
77
+
### Prover Message vs Prover Hint
78
+
-`prover_message`: Absorbed into Fiat-Shamir transcript — verifier derives challenges from it. Use for values that must be transcript-bound.
79
+
-`prover_hint_ark`: NOT absorbed into transcript — prover sends it but it doesn't affect challenges. Use only for values independently verified by WHIR (e.g., committed polynomial evaluations).
80
+
81
+
Misusing `prover_hint_ark` for a value that should be transcript-bound is a soundness vulnerability — a malicious prover can substitute arbitrary values without detection.
82
+
83
+
### NTT/Hash Engine Registration
84
+
```rust
85
+
provekit_common::register_ntt(); // Must be called once at startup
86
+
```
87
+
Registers the WHIR ArkNtt and Skyscraper hash engine globally. Forgetting this causes runtime panics.
88
+
89
+
## Key Types
90
+
91
+
### R1CS
92
+
```rust
93
+
pubstructR1CS {
94
+
pubnum_public_inputs:usize,
95
+
pubinterner:Interner, // Deduplicates field elements in matrices
96
+
puba:SparseMatrix, // Left constraint matrix
97
+
pubb:SparseMatrix, // Middle constraint matrix
98
+
pubc:SparseMatrix, // Right constraint matrix
99
+
}
100
+
```
101
+
102
+
### SparseMatrix
103
+
Uses delta-encoded column indices within rows (reduces serialized size ~30-50%). Key operations: `set()`, `iter_row()`, `transpose()`, `multiply()` (parallel via rayon).
104
+
105
+
### PrefixCovector / OffsetCovector
106
+
Memory-optimized covectors for zero-padded vectors. PrefixCovector stores only the non-zero prefix; OffsetCovector stores weights at an offset. Both implement `LinearForm` for MLE evaluation.
Serialized as postcard binary (`.np`) or JSON (`.json`). Hash config stored as 1-byte header.
116
+
117
+
### WitnessBuilder
118
+
~15+ variants: Constant, Sum, Product, Inverse, Challenge, DigitalDecomposition, SpiceWitnesses (RAM/ROM), LogUpInverse, BinOpLookupDenominator, etc. Each variant knows how to compute its witness value from prior witnesses.
119
+
120
+
### HashConfig
121
+
Runtime-selectable: Skyscraper (default, custom optimized), SHA256, Keccak, Blake3. Determines Merkle tree hash and Fiat-Shamir sponge.
17
122
18
123
## Build & Test
19
124
20
125
```bash
21
126
# Rust (requires nightly)
22
127
cargo fmt --all --check
23
-
cargo clippy --all-targets --all-features
24
-
cargo build --all-targets --all-features
25
-
cargo test --no-fail-fast --all-features --lib --tests --bins
cd recursive-verifier && go build ./... && go test -v -cover ./...
30
136
```
31
137
32
-
Toolchain: Rust nightly (nightly-2026-03-04), Go 1.24.
138
+
Toolchain: Rust nightly (nightly-2026-03-04), edition 2021, rust-version 1.85. Go 1.24.
139
+
140
+
CI runs on `ubuntu-24.04-arm`. End-to-end tests run on self-hosted ARM64 (`provekit-build`).
33
141
34
142
## Code Conventions
35
143
36
144
### Rust
37
145
38
-
- Use `cargo fmt` and `cargo clippy`. CI enforces both — clippy warnings are errors.
39
-
- Error handling: use `anyhow::Result<T>` with `.context("description")` for adding context. Do not use `.unwrap()` or `.expect()` in library code — only in tests and CLI entry points.
40
-
- All `unsafe` blocks must have a `// SAFETY:` comment explaining the invariant. CI denies missing safety docs.
41
-
- All public items must have `///` doc comments. CI runs `cargo doc` with `-D warnings`.
42
-
- Use `#[instrument(skip_all)]` from `tracing` for performance-critical function tracing. Do not log large objects.
43
-
- Prefer `rayon` for parallelism. Do not spawn raw threads.
44
-
- Use workspace dependencies from root `Cargo.toml` — do not add crate-specific dependency versions.
45
-
- Tests use `#[test_case]` for parameterized tests, `proptest`/`quickcheck` for property-based tests.
146
+
-**Formatting**: `cargo fmt`. CI enforces.
147
+
-**Linting**: `cargo clippy` with workspace-level lints: `warn` on `perf`, `complexity`, `style`, `correctness`, `suspicious`. `deny` on `missing_safety_doc`.
148
+
-**Error handling**: `anyhow::Result<T>` with `.context("description")`. Use `ensure!()` for invariant checks, `bail!()` for early returns. No `.unwrap()` or `.expect()` in library code — only in tests and CLI entry points.
149
+
-**Unsafe code**: All `unsafe` blocks must have `// SAFETY:` comment explaining the invariant. Avoid `unsafe` in proof system core (`provekit/*`) without team review.
150
+
-**Documentation**: All `pub` items need `///` doc comments. CI runs `cargo doc -D warnings`.
151
+
-**Tracing**: Use `#[instrument(skip_all)]` from `tracing` for function tracing. Do not log large objects.
152
+
-**Parallelism**: Use `rayon` for data parallelism. Do not spawn raw threads.
153
+
-**Dependencies**: Declare in root `Cargo.toml``[workspace.dependencies]`, reference with `{ workspace = true }` in crate `Cargo.toml`.
154
+
-**Testing**: `#[test_case]` for parameterized tests, `proptest`/`quickcheck` for property-based tests. Integration tests compile Noir programs end-to-end.
46
155
47
156
### Go (recursive-verifier/)
48
157
49
-
- Run `gofmt`, `go vet`, and `golangci-lint` before submitting.
50
-
- Keep `go.mod` tidy (`go mod tidy` must produce no diff).
158
+
-`gofmt`, `go vet`, `golangci-lint` must pass.
159
+
-`go mod tidy` must produce no diff.
160
+
161
+
## FFI Safety Rules (`tooling/provekit-ffi`)
162
+
163
+
- All `*const c_char` parameters must be valid null-terminated UTF-8.
164
+
-`pk_init()` must be called exactly once before any prove/verify.
165
+
-`pk_configure_memory()` must be called before `pk_init()` if using custom allocator.
166
+
- All returned `PKBuf` must be freed exactly once via `pk_free_buf()`.
167
+
- All FFI functions wrap Rust code with `catch_panic()` to prevent unwinding across the FFI boundary.
-**SparseMatrix**: Uses delta-encoded column indices on disk. `encode_col_deltas` / `decode_col_deltas` must roundtrip correctly.
175
+
-**Breaking changes**: Do not change serialization formats without migration plan — deployed verifiers and mobile clients depend on compatibility.
51
176
52
177
## Security Rules
53
178
54
179
This is a cryptographic proof system. Correctness and soundness are critical.
55
180
56
181
- Never skip or weaken constraint checks in prover/verifier code without explicit justification.
57
182
- Sensitive field elements must use `zeroize` for cleanup.
58
-
- Do not introduce `unsafe` code in the proof system core (`provekit/*`) without team review.
59
-
- FFI boundaries (`tooling/provekit-ffi`) must validate all input pointers and lengths.
60
-
- Do not change serialization formats (`postcard`, proof encoding) without migration plan — deployed verifiers depend on compatibility.
183
+
- Do not introduce `unsafe` code in `provekit/*` without team review.
184
+
- FFI boundaries must validate all input pointers and lengths.
185
+
- Do not change serialization formats without migration plan.
186
+
- All field arithmetic is mod BN254 prime. Montgomery representation used internally by arkworks — transparent to users.
61
187
62
188
## Code Review Checklist
63
189
64
190
When reviewing PRs, check for:
65
191
66
-
-**Soundness**: Changes to constraint generation, prover, or verifier must not weaken soundness guarantees. Any modification to R1CS compilation, witness generation, or proof verification logic must be scrutinized for missing constraints or bypassed checks.
67
-
-**Unsafe code**: New `unsafe` blocks must have `// SAFETY:` comments. Prefer safe alternatives.
68
-
-**Error handling**: No `.unwrap()` in library code. Use `anyhow::Result` with context.
192
+
-**Soundness**: Changes to constraint generation (`noir_to_r1cs`), witness builders, prover transcript messages (`prover_message` vs `prover_hint_ark`), or verification logic must not weaken soundness. Scrutinize for missing constraints, wrong witness layer ordering, or transcript inconsistencies.
193
+
-**Public input binding**: Any change to `make_public_weight`, `compute_public_eval`, or `verify_public_input_binding` must account for the constant-1 witness at position 0 (`n = num_public_inputs + 1`).
194
+
-**Transcript consistency**: Prover and verifier must produce identical Fiat-Shamir transcripts. Check that new prover messages are mirrored in verifier, and vice versa.
195
+
-**Unsafe code**: New `unsafe` blocks must have `// SAFETY:` comments. Prefer safe alternatives. Extra scrutiny for `skyscraper/` SIMD code.
196
+
-**Error handling**: No `.unwrap()` in library code. Use `anyhow::Result` with `context()`/`ensure!()`/`bail!()`.
69
197
-**Public API docs**: All new `pub` items need `///` doc comments.
70
-
-**Test coverage**: New functionality must include tests. Bug fixes must include regression tests.
71
-
-**Workspace deps**: Dependencies must be declared in root `Cargo.toml``[workspace.dependencies]`, not inline in crate `Cargo.toml` files.
72
-
-**Performance**: Changes to hot paths (NTT, polynomial operations, matrix multiplication) must not regress performance. Use `#[instrument]` for tracing.
73
-
-**Clippy compliance**: All clippy warnings must be resolved. The workspace enforces `warn` on `perf`, `complexity`, `style`, `correctness`, and `suspicious` lints.
198
+
-**Test coverage**: New functionality must include tests. Bug fixes must include regression tests. Property-based tests (`proptest`/`quickcheck`) preferred for mathematical operations.
199
+
-**Workspace deps**: Dependencies must be in root `Cargo.toml``[workspace.dependencies]`.
200
+
-**Serialization**: Changes to serialized types (`NoirProof`, `R1CS`, `SparseMatrix`, `WhirR1CSProof`) must maintain backward compatibility or include migration.
201
+
-**Performance**: Changes to hot paths (NTT, polynomial ops, sparse matrix multiply, sumcheck inner loop) must not regress performance. Use `#[instrument]` for tracing.
202
+
-**FFI safety**: Changes to `provekit-ffi` must maintain panic safety (`catch_panic`), pointer validation, and `PKBuf` lifetime correctness.
203
+
-**Clippy compliance**: All clippy warnings resolved. Workspace enforces `warn` on `perf`, `complexity`, `style`, `correctness`, `suspicious`.
74
204
-**Formatting**: `cargo fmt` for Rust, `gofmt` for Go. No exceptions.
75
205
76
206
## PR Guidelines
77
207
78
-
- Branch names: use prefix format like `username/description` (e.g., `px/fix-verifier`).
0 commit comments