Formal Verification - #83
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
n13
left a comment
There was a problem hiding this comment.
The axiom-footprint gate does not cover the PR’s core no-UB/no-wrap claims. goldilocks_tier1 bundles the functional congruence/closure results, but it does not reference rustAdd_assume_sound, rustAdd_fixup_no_overflow, rustSub_assume_sound, rustSub_fixup_no_underflow, reduce_borrow_fixup_no_underflow, or addNoCanonicalize_fixup_no_overflow. Since lake build accepts declared axioms and the separate grep only rejects sorry/admit/sorryAx, any of those safety proofs could depend on a new custom axiom while the exact-footprint job still passes. This contradicts both the CI comment that the check catches stray axioms and the PR claim that the capstone bundles every claim. Please include the safety theorems in goldilocks_tier1 (or create a separate safety capstone) and run #print axioms on the complete assurance surface.
Verdict: request changes. All current checks pass, and I found no production Rust regression, but the formal-verification gate is incomplete for the guarantees this PR says it enforces.
Co-authored-by: Cursor <cursoragent@cursor.com>
n13
left a comment
There was a problem hiding this comment.
Re-reviewed the updated head (c5ce1202). The prior blocker is resolved: goldilocks_tier1_safety now bundles the add/sub assume soundness, add/sub fixup bounds, halve no-wrap, reduce borrow/product bounds, and unsafe-add fixup bound, while CI runs #print axioms against both the functional and safety capstones with the exact standard-axiom allowlist.
The revised formal-spec job passes, including Lean build and independent kernel checking, and the complete Rust, formatting, analysis, security, CodeQL, macOS, and Ubuntu checks are green. I found no remaining blocking issue.
Verdict: approve.
Summary
This PR does two things: shrinks the dependency footprint, and adds a machine-checked Lean 4 proof that the hand-optimized Goldilocks field arithmetic in
src/goldilocks.rsis correct.Dependency cleanup
upgrade rand— bumprandto the current release.trim criterion— buildcriterionwithdefault-features = false+cargo_bench_supportonly. This drops 28 packages fromCargo.lock(thehtml_reportsfeature pulled in the wholeplottersstack). Benchmarks still run; only HTML report generation is lost.Formal verification (
formal/)A new Lean 4 package proving the trickiest code in this crate — the overflow/underflow tricks,
NEG_ORDERcorrections,unreachable_uncheckedcompiler hints, and the 128-bit reduction ingoldilocks.rs— correct modulo p = 2^64 − 2^32 + 1. It follows the same conventions as theformal/packages in qp-zk-circuits and qp-plonky2: Lean v4.30.0, mathlib-free (builds in ~3 s, no cache to fetch in CI), kernel-checked end to end.For every operation (
add,sub,mul/reduce128,neg,halve,exp7,square,double,as_canonical_u64,is_zero,==), assuming only that inputs are u64s — canonicality is not assumed, matching the crate's non-canonical representation:rustAdd a b % P = (a + b) % P).reduce128is proven correct on the entire u128 range.assume(self.value > P && rhs.value > P)hints inadd/subare implied by their branch conditions, so theunreachable_uncheckedinsideassumeis dead code;+= NEG_ORDER/-= NEG_ORDERfix-ups annotated "Cannot overflow"/"Cannot underflow", andhalve'swrapping_add, genuinely never wrap;add_no_canonicalize_trashing_input's safety contract (x + y < 2^64 + P) is proven to hold at its call site inreduce128.Layout:
formal/GoldilocksSpec/Model.leangoldilocks.rsinto Nat-level definitions; each cites the Rust lines it mirrors. Wrapping ops are modeled as actually wrapping, so a wrong "cannot overflow" comment would make the theorems unprovable.formal/GoldilocksSpec/Correctness.leangoldilocks_tier1bundling every claim, and kernel-evaluated cross-checks of the model against the crate's owntest_against_p3_expected_valuesvectors (guards the hand-transcription trust seam).formal/ci/AxiomsCheck.leanCorrectness is stated as
Natcongruences (% P) rather than mathlib'sZMod p; the statements are equivalent (castingNat → ZMod Pidentifiesxwithx % P) and keeping the package dependency-free means CI needs no mathlib cache.CI
New
formal-specjob mirroring the qp-zk-circuits/qp-plonky2 pattern:lake buildvialeanprover/lean-action(pinned to a full commit SHA), with an independentleancheckerre-check of the compiled environment;formal/;goldilocks_tier1depends on exactly{propext, Classical.choice, Quot.sound}— the standard Lean axioms, nothing else.Test plan
lake buildclean from scratch (no warnings, ~3 s)goldilocks_tier1depends on exactlypropext, Classical.choice, Quot.soundtest_against_p3_expected_values,test_multiplication_large,test_canonical_reduction) by kernel evaluationcargo test/ benches unaffected by the criterion trim (Rust code untouched by the formal work)formal-specCI job green on this PRNote
Low Risk
No changes to production Rust crypto code; risk is mainly CI maintenance and lockfile churn from dev-dependency updates.
Overview
Adds a mathlib-free Lean 4 package under
formal/that modelssrc/goldilocks.rsand proves tier-1 properties (mod-P congruence, u64 closure, and soundness of overflow/assumepaths) for non-canonical representatives, capped bygoldilocks_tier1withdecidecross-checks against the Rust test vectors.CI gains a
formal-specjob: pinnedlean-actionwithlake build+leanchecker, a no-sorry/admitgrep, and an axiom-footprint check viaformal/ci/AxiomsCheck.lean.Rust dev-deps:
criterionis trimmed todefault-features = false+cargo_bench_support(drops HTML/plotters from the lockfile);Cargo.lockreflects routine transitive bumps.Reviewed by Cursor Bugbot for commit bf06652. Configure here.