Skip to content

feat: make KoalaBear Rabin irreducibility certificates re-checkable by kernel replay - #306

Merged
alexanderlhicks merged 1 commit into
Verified-zkEVM:mainfrom
zksecurity:pr/rabin-replay-safe
Aug 17, 2026
Merged

feat: make KoalaBear Rabin irreducibility certificates re-checkable by kernel replay#306
alexanderlhicks merged 1 commit into
Verified-zkEVM:mainfrom
zksecurity:pr/rabin-replay-safe

Conversation

@kobizk

@kobizk kobizk commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Add explicit-cardinality Rabin wrappers so quinticPoly_irreducible/sexticPoly_irreducible state their certificates with the field size as a numeral, letting a from-empty kernel replay avoid reducing Fintype.card (ZMod p) (~p elements); definitionally equal, nothing weakened.

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Summary

The PR introduces wrapper lemmas that accept an explicit field cardinality parameter q (with a hypothesis Fintype.card F = q) and then subst hq to delegate to existing Rabin irreducibility tests. This makes the certificates in quinticPoly_irreducible and sexticPoly_irreducible definitionally equal to numerals, so a kernel replay from an empty environment can compute them without reducing Fintype.card (ZMod p) (~p elements). All existing behavior is preserved; no sorry or admit are added or removed.

Key Changes:

  • RabinCertificate.lean: Added irreducible_of_rabin_prime_degree_of_card and irreducible_of_rabin_degree_six_of_card. Both take (q : ℕ) and (hq : Fintype.card F = q), then subst hq and call the original lemmas. This ensures the certificate’s cardinality argument is a numeral (e.g. fieldSize), not a Fintype.card expression.
  • QuinticIrreducible.lean: Replaced two calls to irreducible_of_rabin_prime_degree (which required rw [hcard]) with a single call to the new irreducible_of_rabin_prime_degree_of_card, passing fieldSize and hcard. The rw steps are eliminated; subproofs dvd_X_pow_sub_X_of_runChain and isCoprime_X_pow_sub_X_of_runChain are unchanged.
  • SexticIrreducible.lean: Replaced call to irreducible_of_rabin_degree_six with the new irreducible_of_rabin_degree_six_of_card, passing fieldSize and hcard. Three rw steps removed.

Objective: The change is purely about making the proof terms amenable to kernel replay for verification without requiring the kernel to compute Fintype.card (ZMod p) for a large prime (~p). The mathematical content is unchanged.


Statistics

Metric Count
📝 Files Changed 3
Lines Added 41
Lines Removed 12

Lean Declarations

✏️ Added: 2 declaration(s)

CompPoly/Data/Polynomial/RabinCertificate.lean (2)

  • theorem irreducible_of_rabin_degree_six_of_card {F : Type*} [Field F] [Fintype F]
  • theorem irreducible_of_rabin_prime_degree_of_card {F : Type*} [Field F] [Fintype F]

sorry Tracking

  • No sorrys were added, removed, or affected.

📋 **Additional Analysis**

Minor style violation detected; otherwise compliant with guidelines.


📄 **Per-File Summaries**
  • CompPoly/Data/Polynomial/RabinCertificate.lean: Added two new theorems, irreducible_of_rabin_prime_degree_of_card and irreducible_of_rabin_degree_six_of_card, which are variants of the existing irreducible_of_rabin_degree_six and irreducible_of_rabin_prime_degree that take an explicit cardinality parameter q with a hypothesis Fintype.card F = q and then subst hq to delegate to the original theorems. The docstrings explain that this
  • CompPoly/Fields/KoalaBear/Ext5/QuinticIrreducible.lean: The proof of quinticPoly_irreducible was refactored to replace the two-step irreducible_of_rabin_prime_degree calls (which required rewriting by hcard : Fintype.card Field = fieldSize) with a single call to the new lemma irreducible_of_rabin_prime_degree_of_card, which takes fieldSize and hcard as explicit parameters. The two underlying subproofs (dvd_X_pow_sub_X_of_runChain and isCoprime_X_pow_sub_X_of_runChain) remain unchanged; the refactor eliminates the rw [hcard] steps, streamlining the proof.
  • CompPoly/Fields/KoalaBear/Ext6/SexticIrreducible.lean: The proof of sexticPoly_irreducible was updated to call irreducible_of_rabin_degree_six_of_card (instead of irreducible_of_rabin_degree_six), passing fieldSize and hcard as explicit arguments. The three rw [hcard] steps were removed from the body of the proof, as the new lemma presumably handles the cardinality condition internally.

Last updated: 2026-08-17 01:09 UTC.

…y kernel replay

The KoalaBear degree-5 and degree-6 extension irreducibility proofs
(`quinticPoly_irreducible`, `sexticPoly_irreducible`) type-check fine at
compile time but are effectively unbounded to *re-check* from an empty
environment (Lean's `Environment.replay`, as used by `lean4checker` and by
external proof-auditing tools): the check grows past 58 GiB without finishing.

Cause: the Rabin lemmas are stated in terms of `Fintype.card F`, and the callers
bridge the concrete field size in with `rw [hcard]`. On a cold re-check the
kernel is forced to reduce `Fintype.card (ZMod p)` -- an enumeration of ~p
(~2.1e9 for KoalaBear) elements -- to reconcile it with the numeral. Compilation
avoids this because the elaborator handles the equation propositionally; replay
re-faces the raw defeq. (The huge `X^(card^k)` power is *not* the cause -- it
stays syntactically matched and is never reduced; the `X^4-C` degree-4 extension,
which has no such enumeration, re-checks fine at the same closure size.)

Fix: add explicit-cardinality wrappers `irreducible_of_rabin_prime_degree_of_card`
and `irreducible_of_rabin_degree_six_of_card` that take the field size as a
numeral `q` with `Fintype.card F = q`, proved by `subst hq` from the existing
lemmas -- so they are definitionally the same statement, no axiom, nothing
weakened. The two callers pass `q := fieldSize` and drop the `rw [hcard]` casts,
so the certificates are stated with `q` concrete and the kernel never enumerates
`Fintype.card`.

Measured on the degree-6 case: re-checking the full 19,908-constant closure goes
from unbounded (>58 GiB, killed) to ~9 s.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kobizk kobizk changed the title Make the KoalaBear Rabin irreducibility certificates re-checkable by kernel replay feat: make KoalaBear Rabin irreducibility certificates re-checkable by kernel replay Aug 17, 2026
@kobizk
kobizk force-pushed the pr/rabin-replay-safe branch from 5e84edb to 1d0ce31 Compare August 17, 2026 01:08
@alexanderlhicks
alexanderlhicks merged commit 32a0c29 into Verified-zkEVM:main Aug 17, 2026
5 checks passed
@alexanderlhicks

Copy link
Copy Markdown
Collaborator

Thanks!

alexanderlhicks added a commit that referenced this pull request Aug 18, 2026
…307)

The `_of_card` wrappers added in #306 are correct, but their docstrings
justified the numeral form by claiming the `Fintype.card F` form makes a
from-empty kernel replay reduce `Fintype.card F` (for a `ZMod p` field, an
enumeration of ~`p` elements). It does not: `rw [hcard]` elaborates to
`Eq.mpr (id (congrArg motive hcard)) cert`, whose kernel check only
beta-reduces the motive, so `Fintype.card F` never reaches whnf position.
Measured kernel type-checking of both proofs is single-digit milliseconds
either way, with run-to-run variance exceeding the difference between the
forms; and since Lean kernel-checks each theorem at `addDecl` during an
ordinary build, a from-empty replay runs that same check.

Replace the rationale with the one that does hold, and that
`irreducible_X_pow_four_sub_C_of_card` already documents on the binomial
side: the generated certificates are already stated in terms of `fieldSize`,
so each Rabin condition applies directly instead of needing a `rw [hcard]`
cast. Also drop the claim that the two forms are "definitionally equal" —
the plain form is the `q := Fintype.card F` instance of the numeral one.

Make `q` implicit and rename `hq` to `hcard`, matching the binomial
`_of_card` form: `q` is uniquely determined by `hcard`, which precedes
`h_trace`/`h_cop`, so inference never needs higher-order matching.

Update `docs/wiki/field-extensions.md`, whose "Adding a new non-binomial
extension" recipe still routed new extensions to the non-`_of_card`
wrappers that the two canonical callers had moved away from, per the
maintenance contract in `docs/wiki/README.md`.

Pin the round trip in `CompPolyTests.RabinCertificate`: instantiating each
`_of_card` form at `q := Fintype.card F` with `rfl` must recover the plain
statement verbatim, so "nothing is weakened" is checked rather than
asserted. The opposite direction is the wrapper's own proof body.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants