hex

3.5. Reusable certificates with primality?🔗

The explicitly requested construction tactic primality? uses a larger, finite search profile. It proves the Curve25519 field prime and offers a clickable Try this: replacement containing the complete checked certificate. This example checks the entire suggestion text, so changes to the generated certificate or its formatting are detected:

/-- info: Try this: [apply] exact Hex.Nat.prime_of_checkPrimeAt (c := Hex.Nat.PrimeCert.pock 57896044618658097711785492504343953926634992332820282019728792003956564819949 [(2, 0, Hex.Nat.PrimeCert.pock3 74058212732561358302231226437062788676166966415465897661863160754340907 2028478494862525422475607 22304740449229861598212 2028478494862525422475606 [(2, 0, Hex.Nat.PrimeCert.small 2), (2, 0, Hex.Nat.PrimeCert.small 353), (2, 0, Hex.Nat.PrimeCert.small 57467), (2, 0, Hex.Nat.PrimeCert.pock3 31757755568855353 4028945 289 4028944 [(5, 2, Hex.Nat.PrimeCert.small 2), (2, 0, Hex.Nat.PrimeCert.small 223), (2, 0, Hex.Nat.PrimeCert.small 4153)])])]) (by decide +kernel) -/ #guard_msgs in example : Hex.Nat.Prime (2 ^ 255 - 19) := ⊢ Hex.Nat.Prime (2 ^ 255 - 19) All goals completed! 🐙

Apply the suggestion to keep certificate search out of subsequent builds. The replacement uses Hex.Nat.prime_of_checkPrimeAt and decide +kernel; the kernel still replays the certificate. A standalone file containing the replacement needs only import HexPrimality.Cert. The goal retains the expression 2 ^ 255 - 19. With HexPrimalityMathlib imported, primality? also handles Nat.Prime and suggests the corresponding bridge theorem.

Construction supports inputs through 521 bits, recursive depth 32, and a shared limit of 1024 attempts. primality? (maxAttempts := 29) sets a smaller limit; Curve25519 succeeds at 29 and exhausts at 28. It uses stage-one Pollard p - 1 up to 524288, bounded rho work, and deterministic small witnesses before random candidates. Every limit is finite; exhaustion reports the seed, attempts, and resource profile. Success depends on finding enough factors of predecessors for Pocklington, rather than on bit length alone. Construction first tries the factors found by table division before running the more expensive factor search. It can use a power of two alone and can trade up to 63 small-divisor checks for a smaller factored part of the predecessor. These checks are included in the reusable certificate and replayed by the kernel. The ordinary primality policy keeps its existing smaller budget.

With the standard import HexIntFactor, plain primality? also discovers secp256k1, P-384 and Curve448. It preserves the first route's successful certificate; only exhaustion with attempts left triggers a complete retry with bounded ECM. Both routes share the same 1024 attempts and advancing random state. These three fields need an explicit finite Lean heartbeat allowance; set_option maxHeartbeats 4000000 is tested, without a recursion-depth option. See the field-prime tutorial for complete examples. An explicit factor := provider or using certificate bypasses automatic selection. Use primality? (factor := Hex.Nat.Construction.factorSearch) for core-only construction. Automatic fallback also costs time on unsupported inputs: the 507-bit fixture still exhausts, taking about 20.7 seconds instead of 0.9 seconds on the measured host. Native search runs synchronously, so a heartbeat overrun can be reported after it returns; heartbeats are not a wall-clock timeout.

The Curve25519 result has three non-leaf certificate nodes and eight factor entries. Kernel replay reads the already verified sieve bitset for table leaves, and compiled prime enumeration reads 64 candidate bits at a time. Both changes are proved equal to their original implementations.

The fixed-corpus comparison measured Curve25519 native decision at 0.57 seconds and a fresh complete primality? build from its numeral at 1.63 seconds, including Lake overhead and kernel replay. Paired runs using the original 2 ^ 255 - 19 expression took 2.17–2.29 seconds, compared with 7.01–10.41 seconds before these optimizations. FLINT and PARI native decisions took 25.9 and 55.4 milliseconds respectively. The native timings use a standalone executable; the full tactic currently runs search through Lean’s interpreter before kernel checking. All completed samples are retained. These are host-specific observations, not latency guarantees. The measurement report records every sample, certificate sizes, and the comparison with the larger reference certificate.

The fixed comparison corpus also includes standard cryptographic field primes. The current construction profile finds P-256 and the structured 511/512-bit benchmark primes and P-521. The default profile exhausts on secp256k1, P-384 and Curve448. The explicit ECM provider constructs all three: see the field-prime tutorial for complete examples and reusable proofs. P-521 uses 25 factor candidates and 170 attempts; the constructor admits at most 32 factors and still examines at most 4096 subsets. For the expression 2 ^ 521 - 1, set local maxRecDepth to 1024 and exponentiation.threshold to 521; its numeral needs neither option. The standard-field report records the default profile's factoring barriers and separate construction, rendering, and replay measurements. This is not a general-purpose prover for arbitrary cryptographic-size primes.

The first cactus plot compares native exact primality decisions with the complete primality? build. Native timings exclude Lean proof emission and kernel replay, imports, and input conversion. Hex uses certificate construction and a compiled self-check internally to decide primality; FLINT and PARI return exact decisions through their native algorithms. The dashed curve includes the full fresh Lake build: certificate construction, proof emission, imports, and kernel checking.

Native decision and complete Lean proof

Direct kernel measurements exclude imports, search, and proof elaboration. They check complete proof bodies, including expanded local auxiliary proofs. With PrimeCert’s fixed-window powering and the same selected Pocklington factors, supplied Curve25519 replay takes about 4.54 milliseconds for Hex and 3.54 milliseconds for PrimeCert on the recorded host. Curve448 takes 9.30 and 6.44 milliseconds. PrimeCert uses common witness bases; a separate matched-base experiment distinguishes that certificate choice from checker cost.

Complete automatic construction is a separate comparison. On the matched Curve25519 Nat.Prime goal, the repeated fresh-module experiment measures about 2.39 seconds for Hex primality? and 3.55 seconds for PrimeCert prime_cert?, including imports, construction, elaboration, and checking. These noisy shared-host observations are not portable performance promises. The replay attribution records exact revisions, every sample, component costs, negative controls, and construction regression checks. Hex uses Lean 4.34.0 and PrimeCert uses Lean 4.33.0; identical-code calibration is reported separately. The kernel replay comparison uses a supplied Curve448 certificate in both systems. The explicit ECM route in the field-prime tutorial constructs its own certificate. The corpus is small and structured.