A Lean 4 proof that the zkGolf AssertBytes record score of 240 is optimal, for every R1CS circuit whose constraint system is sound over the algebraic closure of the field. Every standard byte-check circuit satisfies this condition, because bit decomposition pins values with booleanity rows and those have the same two roots in every field. Circuits that rely on an equation having no solution in the specific field, such as residuosity checks, do not.
An R1CS circuit checks that 16 field elements are bytes. Its score is the number of witness allocations plus the number of constraints. If the constraint system stays sound over the algebraic closure, the score is at least 240.
theorem sixteen_bytes_score_lower_bound
{K : Type*} [Field K] [IsAlgClosed K]
(X : ConcreteScalarChecker K) (hX : ChecksBytes 16 X) :
240 ≤ X.scoreChecksBytes 16 X means X has 16 public inputs and its accepted set projects
onto at least 2^128 scalars.
The bound is tight in each coordinate. It gives at least 112 allocations and at least 128 constraints. The record circuit uses exactly 112 and 128.
The record circuit is a proven instance. RecordInstance.lean builds one byte
as a checker: 7 low bits, 7 booleanity rows, 1 product row. It proves
ChecksBytes 1 when the casts of 0..255 are distinct in the field. The score
is 15 by definition and at least 15 by the theorem.
RecordInstance16.lean builds all sixteen bytes: the one-byte gadget on
sixteen disjoint variable blocks, and the packing map ∑ 256^j · x_j. It
proves ChecksBytes 16 when the casts of 0..2^128 − 1 are distinct, which
holds over the closure of a prime field with p ≥ 2^128
(checksBytes16_of_charP). The score is 240 by definition and at least 240 by
sixteen_bytes_score_lower_bound.
The proof has no sorry and uses only the three standard Lean axioms.
AxiomAudit.lean checks this with #guard_msgs on #print axioms, so the
build fails if an axiom is added.
Model the circuit as C quadratic equations in n variables over an
algebraically closed field. The accepted inputs are the solutions. A linear map
L packs the 16 bytes into one scalar. The circuit distinguishes as many inputs
as L takes values on the solution set.
-
Affine Bézout bound. The solution set of
Cequations of degree at mostdhas at mostmin(d^C, d^n)irreducible components. This is most of the repository. Replace the equations by a weakly regular sequence of linear combinations to get a complete intersection, then bound the Hilbert function along the sequence. Each generator of degree at mostdmultiplies the bound by at mostd. The positive-dimensional case uses Lazard's divided-degree recurrence. Withd = 2the bound is2^min(C,n). -
Finite projections are constant on components. If
Lhas finite image on the solution set,Lis constant on each irreducible component. The image of an irreducible set is irreducible, and a finite irreducible set is a point. -
So
Ltakes at most2^min(C,n)values. -
16 bytes give
256^16 = 2^128inputs, somin(C,n) ≥ 128. This givesC ≥ 128andn ≥ 128. 16 variables are public, so at least 112 are witnesses.
C ≥ 8B A ≥ 7B A + C ≥ 15B B = 16 ⟹ score ≥ 240
The argument does not look at the structure of the circuit. It only counts components.
-
Degree 2 is required. The bound is
2^min(C,n)because R1CS rows are quadratic. Custom gates of higher degree give a weaker bound. -
Soundness over the closure is required. The field is algebraically closed and the finiteness hypothesis is on the geometric variety. A circuit can be sound over
F_pand fail this. Example: takeca quadratic non-residue and per byte assertbᵢ(bᵢ−1) = 0for 8 bits,y² = s, and(x − Σ2ⁱbᵢ)² = c·s. Each row is rank 1. OverF_p,y ≠ 0would makeca square, soy = 0andxis the bit recomposition. Over the closure,x = Σ2ⁱbᵢ + √c·tis a solution for everyt, so the accepted set is infinite. This circuit costs more than 240 and does not beat the bound. It shows the hypothesis cannot be dropped. -
The link to Clean is not included here. Clean formalises circuits, semantics, soundness, completeness, cost, and the R1CS check. A bridge from David Wong's submitted circuit to
rows16exists and is machine-checked, but it lives outside this repo: it needs Clean, and Clean cannot share a module with full Mathlib because both declareFin.foldl_eq_foldl_finRange. The bridge proves that the submitted circuit's flat constraints hold exactly when the assignment lies in therows16locus, and that its counted cost ischecker16's. It adds one axiom, the contest's assumption that the field order is prime. This repo stays mathlib-only. A general translation from arbitrary contest circuits cannot exist, by the example above. Whether anF_p-specific circuit scores below 240 is open.
Install elan. It reads lean-toolchain.
lake exe cache get # mathlib objects, about 7 GB
lake buildThere is no sorry in the tree. AxiomAudit.lean is in the default target, so
the build fails if a theorem uses an extra axiom.
To print the axioms:
printf 'import AssertBytes240.Optimality\n#print axioms ZkGolfOptimality.AssertBytes.sixteen_bytes_score_lower_bound\n' > Axioms.lean
lake env lean Axioms.lean'ZkGolfOptimality.AssertBytes.sixteen_bytes_score_lower_bound' depends on axioms:
[propext, Classical.choice, Quot.sound]
Mathlib is pinned in lakefile.lean to the revision the proof was checked
against.
| Path | What |
|---|---|
AssertBytes240/Optimality.lean |
the public statements, including the 240 bound |
AssertBytes240/RecordInstance.lean |
one byte of the record circuit as a checker |
AssertBytes240/RecordInstance16.lean |
the full sixteen-byte record circuit as a checker; score 240 |
AssertBytes240/Components.lean |
finite projections are constant on components (step 2) |
AssertBytes240/Algebra/ |
the affine Bézout bound (step 1) |
AssertBytes240/AxiomAudit.lean |
axiom check, run by the build |
Mathlib has no component-count bound of this kind. It has Bézout domains and Bézout's identity for gcd.