Commit graph

22 commits

Author SHA1 Message Date
9eb3beabc4 verification: kernel-side axiom-declaration gate (Phase 2b) + self-test
Phase 1's anti-smuggling check reads source text. Measured today on Lean
v4.30.0-rc2, four distinct declarations compile cleanly and slip past its
anchored pattern:

    ` axiom cheat : ...`         one leading space
    `@[simp] axiom cheat : ...`  line starts with the attribute
    `unsafe axiom cheat : ...`   `unsafe` absent from the modifier list
    `axiom` <newline> `  cheat`  no space follows the keyword

Any of them yields a repository that proves False while the button prints
ALL GREEN. Only the tab variant is blocked, and by Lean, not by us.

Hardening the pattern would fix the exhibited syntax rather than the class,
which is the mistake this estate has made before. Phase 2b stops parsing text
and asks the kernel instead: it reads every compiled Proofs/*.olean with
readModuleData and rejects any declaration that is an axiom.

Design notes:
  - reads compiled artifacts rather than importing the modules, because
    Proofs.Basic and Proofs.ConstSpecs deliberately reuse `zero_spec` and a
    whole-corpus import is impossible by construction;
  - membership is self-deriving from the filesystem, so Scalar* and
    AxiomCheck are covered too — both are skipped by the CERTS audit and by
    the dead-file gate;
  - fails closed on absence: a missing .olean would make the scan vacuous, so
    the count of compiled modules must equal the count of shipped sources;
  - removes its temp source AND artifact on both paths, since a bare `rm`
    after the call never runs under `set -e` when the gate goes red — exactly
    how this repo accumulated 101 orphan .olean files;
  - ~3 s for the whole corpus, against ~53 s for one module-importing run.

Phase 1's grep stays as a fast first line of defence. Phase 2b is the gate
that is load-bearing.

selftest-axgate.sh attacks the shipping gate, lifted out of check.sh at run
time rather than copied. It asserts the specific diagnostic, so a rejection
for an unrelated reason fails too, and it was itself negative-tested: with
the gate's throwError removed, the self-test goes red on exactly that case.

No proof, statement, specification or certificate is touched. No attested
commit is altered — the log binds specific commit hashes, all of which remain
ancestors of HEAD.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 18:24:18 +02:00
2f182afd64 check.sh: delete the compiled audit artifact, not just its source
Phase 3 and 3b mktemp an audit file, compile it, then removed only the .lean —
leaving the .olean behind on every run. check-scalar.sh:38 has always done this
correctly (`rm -f "$AUD" "${AUD%.lean}.olean"`); the main script was the odd one
out. Estate-wide that had accumulated 101 orphan compiled modules with no
sibling source (dalek 44, anza/risc0/betrusted 19 each), invisible to git
because *.olean is gitignored. All swept.

The litter was inert — the names are not valid Lean identifiers, so nothing
could import them. It matters as a pattern: an audit whose verdict can depend on
untracked build state is the class of defect that took eight review rounds to
close in the sibling SLH-DSA repository (there: an orphan .olean with its source
deleted satisfied an import and the button went green). A build-hygiene phase
that purges compiled artifacts and bans stray files is the proper fix and is
queued as part of the protocol port; this commit stops the bleeding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 17:31:54 +02:00
33fb8bb231 Coherence pass 4 (the closing pass): 4-tier apex documentation + hygiene
- README: pyramid-diagram apex row upgraded to the proven full lift
  (accepted <=> decompress(R) = [k](-A)+[s]B), status table names all
  four button-enforced tiers, apex section gains the phase-2 tier table
  (half-lift / point equation / full lift) + the decompress-chain
  summary; source pin updated to the pushed patch commit.
- TRUSTED-BASE item 5: rewritten from the single byte-apex certificate
  to the FOUR enforced tiers (decompress_of_canonical noted as
  standard-three-only).
- gen/CurveField/FunsExternal.lean: stale root-namespace
  edwards.decompress.step_1/step_2 axioms removed (dead weight left
  behind by un-opaquing; outside every cone, but they forced
  fully-qualified unfolds - see control FAILURES.md).
- check.sh Phase 3b success echo aligned to "apex + full-lift" (echo
  only; the enforcing greps covered all four tiers already).

Validated by the pass-4 sweep: 9/9 buttons green (this repo's check.sh
+ check-scalar.sh among them), logs retained in the pass workspace.
Full record: formal-verification-control/COHERENCE-PASS-4.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 04:01:15 +02:00
eb2c77be09 PHASE 2 COMPLETE ON DALEK: THE FULL POINT-LEVEL LIFT
(verify_accepts_iff_decompress, button-enforced)

THE THEOREM: under the apex hypotheses, the signature's R bytes
DECOMPRESS to a valid on-curve point Pt, and

    verifier accepts   <=>   Pt = [k]*(-A) + [s]*B    (as points)

- accept iff decompress(R) equals the recomputed point. Every link of
the chain (byte comparison <-> canonical-encoding equality <-> point
equality <-> decompressed-point equality) is machine-checked over the
extracted code. Axiom cone EXACTLY the SHA-512 + wire-format boundary;
Phase 3b now enforces FOUR certificate tiers (byte apex, half-lift,
point equation, full lift).

Proofs/DecompressMain.lean:
- edwards_d_denote: the extracted EDWARDS_D constant denotes THE curve
  d (edwards_d_spec + edD_char cancelled by 121666 nonzero).
- decompress_of_canonical (standard three axioms): canonical encodings
  of valid on-curve points decompress to them - from_bytes recovers the
  y-residue exactly (sign bit discarded), Q's own x witnesses the
  square so sqrt_ratio_i returns the even root, the sign bit (Q's
  x-parity, from byte 31) selects +/-root, and the parity-injectivity
  argument pins the selection to edX Q; the assembled {X,Y,1,X*Y} is
  ExtValid and on-curve.
- verify_accepts_iff_decompress: the capstone composition.

Full button green fresh. Remaining: replicate x3, coherence pass 4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 00:05:55 +02:00
3c3283f86b Phase 2, decompress step 2: THE BYTE PARSER PROVEN (from_bytes_spec,
kernel-audited)

Proofs/FromBytesSpec.lean: FieldElement51::from_bytes is exact below bit
255 - for any 32 input bytes it succeeds with 51-bit limbs denoting
bytesVal b mod 2^255 (the sign bit is discarded, everything else is the
little-endian value). This is the y-parse of decompression: a canonical
encoding parses to exactly its y-residue.

- load8_at_spec: generic 8-byte little-endian loader (the disjoint-OR
  idiom with the product-order-robust or_add_low helper; per-round clear
  hygiene cured a fat-context elaboration timeout).
- window_extract / window_shift / digits_tile: the pure window algebra -
  five 64-bit windows at byte offsets 0/6/12/19/24, shifted 0/3/6/1/12,
  tile bits 0..254 exactly (base-2^51 digit identity).
- from_bytes_spec: the walk composing them; the five window equations
  come from ring-verified low/window/high decompositions of the byte sum.

Certificate exact standard three; full button green fresh. Next:
decompress_of_canonical (step 3/5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 22:55:18 +02:00
e17687b59f Phase 2, decompress part 2b: THE SQUARE-ROOT WALK PROVEN
(sqrt_ratio_i_sq_spec, kernel-audited)

The largest single proof of the decompress chain: for square u/v
(witness x, v nonzero), the extracted sqrt_ratio_i returns choice 1 and
the even-parity root - Bnd r (2^52), r^2 * v = u, r's canonical residue
even. The walk composes every previously certified piece: the
square/mul/pow_p58 candidate chain, sqrt_m1_spec, fe_ct_eq_spec x3 (the
three constant-time residue checks), neg_spec, the Choice bitor, and
fe_cond_assign_spec twice (root flip by sqrt(-1), then sign
normalization via is_negative).

Case analysis: sqrt_core's disjunction (v*r^2 = +/-u) against the check
flags - u = 0 collapses everything to the zero root; u != 0 with
v*r^2 = u kills both flip flags (u = -u forces u = 0 in odd
characteristic; u = -u*i forces u*(1+i) = 0 with 1+i nonzero); with
v*r^2 = -u the flip fires and (i*r)^2 * v = -(-u) = u. Parity: the odd-
prime negation flip (ZMod.neg_val), zero-root edge included. New
helpers: eq_neg_self_iff_zero, one_add_i_ne_zero.

Certificate exact standard three; full button green fresh. Remaining:
from_bytes walk, decompress_of_canonical, replication, pass 4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 22:03:57 +02:00
32d3c05495 Phase 2, decompress part 2a: fe conditional-select + THE SQUARE-ROOT CORE
(kernel-audited)

- fe_cond_assign_spec: the per-limb constant-time selection on field
  elements (real extracted code: five index_mut rounds over the u64
  select) keeps self iff the choice is 0 - the operation sqrt_ratio_i
  uses for both the root flip and the sign normalization. Walked with
  backfun-rewrite hygiene; the u64 model lemma restated locally
  (Proofs.Basic is a parallel root that clashes with ConstSpecs).
- sqrt_core: THE ALGEBRAIC HEART - for square u/v (witness x, v nonzero)
  the candidate r = (u*v^3)*(u*v^7)^((p-5)/8) satisfies v*r^2 = +/-u.
  The v-part of the exponent collapses by Fermat (8*(2^253-5) = 2(p-1));
  the residual x^((p-1)/2) is +/-1 by factoring its square. Exponent
  bookkeeping: (p-5)/8 = 2^252-3, (p-1)/2 = 2^254-10, all closed by
  norm_num after pow_mul merges.

Both certificates exact standard three. Full button green fresh.
Remaining: the sqrt_ratio_i walk composing these, from_bytes,
decompress_of_canonical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 21:16:05 +02:00
c908982c2c Phase 2, decompress part 1: pow_p58 + ct_eq semantics (kernel-audited)
Proofs/DecompressSpec.lean, the arithmetic ingredients of sqrt_ratio_i:
- pow_p58_spec: a^((p-5)/8) = a^(2^252 - 3) via the pow22501 chain (the
  invert_spec pattern).
- fe_ct_eq_spec: the constant-time field comparison DECIDES denotational
  equality - because to_bytes is canonical (to_bytes_spec), byte equality
  is residue equality in both directions. Supporting bridge lemmas:
  bytesVal_inj (little-endian digits are unique, so value equality forces
  list equality), bytesVal_congr, bytes_eq_iff_denote.
- sqrt(-1) needs no new work: ConstSpecs.sqrt_m1_spec (the constants
  campaign) already pins SQRT_M1 to Bnd + denote*denote = -1.

Both new certificates exact standard three; full button green fresh.
Remaining in the chain: the sqrt_ratio_i success-case walk, from_bytes,
decompress_of_canonical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 20:08:21 +02:00
5fb5047150 THE POINT-LEVEL VERIFICATION EQUATION: verify_accepts_iff_point_eq,
button-enforced (phase-2 goal reached on dalek)

CurveFieldProofs.verify_accepts_iff_point_eq: under the half-lift's
hypotheses, for ANY valid on-curve point Q whose canonical encoding is
the signature's R bytes,

    verifier accepts   <=>   Q = [k]*(-A) + [s]*B   (as denoted points)

- the literal point-level EdDSA verification equation, no decompress
needed: the canonical encoding is INJECTIVE on curve points.

Proofs/PointEqSpec.lean:
- one_add_d_y_sq_ne_zero: 1 + d*y^2 never vanishes - d nonsquare
  (edD_not_square, the completeness ingredient doing its second job)
  vs -1 a square (p = 1 mod 4).
- x_sq_of_onCurve + enc_inj_coord: the curve equation determines x^2
  from y; +/-x have different parities mod an odd prime unless x = 0,
  so y-residue + parity bit determine the point.
- enc_point_inj (standard three axioms): equal canonical encodings of
  valid on-curve points force equal denoted points.
- verify_accepts_iff_point_eq: half-lift + injectivity. Axiom cone
  EXACTLY the apex boundary; Phase 3b now enforces all THREE tiers
  (byte apex, half-lift, point equation).

Remaining phase-2 garnish: the constructive decompress specs (sqrt
chain), giving "the accepted bytes decompress to the recomputed point".
Full button green fresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 18:27:25 +02:00
fe021b9486 PHASE 2 HALF-LIFT PROVEN: verify_accepts_iff_point, button-enforced
THE THEOREM (CurveFieldProofs.verify_accepts_iff_point): for a parsing
signature, a valid on-curve public-key point, a canonical signature
scalar, and a successful recompute, there is a point R' - the certified
[k](-A) + [s]B, ExtValid and on-curve - with

    verifier accepts  <=>  bytesVal R_bytes
                             = (edY R').val + ((edX R').val % 2) * 2^255

The apex's byte-for-byte comparison IS point-encoding equality: the
signature's R bytes are accepted exactly when they are THE canonical
encoding of the recomputed point. Axiom cone: EXACTLY the apex boundary
(SHA-512 oracle + wire-format opaques; zero curve/scalar/backend axioms),
now enforced for BOTH apex and half-lift by check.sh Phase 3b.

New machinery in Proofs/PointLiftSpec.lean:
- bind_ok_inv: generic ok-inversion of one monadic bind - the clean way
  to invert oracle-bearing chains (axioms cannot be walked).
- recompute_inv: names the recompute chain's intermediates (hash, k,
  -A, R') with their defining equations, via eight flat bind_ok_inv
  steps after the pass-through reductions.
- Bytes64.exists_bytes + List.exists_len32: the 64-byte destructure -
  Lean's match refuses list patterns beyond ~32 elements, so the device
  is a 32-cons prefix + a list-level 32-destructure on the tail.
- The assembly: recompute_inv + from_bytes_mod_order_wide_spec (k
  canonical) + edwards_neg_law (-A) + vartime_dsm_basepoint_spec (R',
  valid, on-curve) + ed_compress_spec (er = canonical encoding) +
  rangeEq_iff_bytesVal (byte comparison = value equality), threaded
  through the ok-injectivity of the inverted equations.

Full button green fresh, incl. the extended Phase 3b.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 16:06:23 +02:00
de9d29907b Phase 2, half-lift items 2+5: dsm dispatch transfer + byte-comparison
bridge (Proofs/PointLiftSpec.lean, kernel-audited)

- vartime_dsm_basepoint_spec: the PUBLIC dsm entry the verifier calls
  (EdwardsPoint::vartime_double_scalar_mul_basepoint) satisfies the dsm
  certificate - under the serial pin the backend dispatch is the real
  constant Serial, so the wrapper reduces definitionally to the certified
  serial path. No new axioms; in CERTS.
- rangeEq_iff_bytesVal: the verifier's byte-wise comparison IS value
  equality of the encodings - little-endian digits are unique (32-fold
  byte peel, one omega over the flat bound set; U8 equality recovered via
  UScalar.eq_of_val_eq).

With ed_compress_spec and from_bytes_mod_order_wide_spec already landed,
the half-lift now needs only the recompute bind-chain inversion (the sha
calls are oracles - inverted from the hrec hypothesis the apex carries)
and the assembly theorem. Full button green fresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 14:36:03 +02:00
7f166eee12 Phase 2, half-lift prerequisite: the hash-to-scalar entry is canonical
(from_bytes_mod_order_wide_spec, kernel-audited)

Proofs/ScalarPackSpec.lean:
- scalar52_to_bytes_spec: Scalar52::to_bytes (the PACK step - pure
  bit-packing at radix 2^52, no reduction) serializes canonical limbs to
  exactly their value: bytesVal s = scVal a. Second application of the
  ToBytesSpec walk generator; boundary bytes 6 and 19 only (the two
  non-byte-aligned 52j offsets), disjoint ORs to additions as before.
- from_bytes_mod_order_wide_spec: the verifier's k = SHA-512-to-scalar
  entry composes from_bytes_wide_spec (the proven mod-l reduction) with
  the pack: for 64 input bytes of value T, the returned Scalar's 32
  bytes denote V with V < l and V = T (mod l) - precisely the scalar
  premises vartime_double_base_mul_spec consumes (V < l < 2^253).
- byte_split_52_4: the offset-4 chunk split for 52-bit limbs; the five
  ToBytesMath byte_split_* lemmas shed their unused 2^51 premises (pure
  telescopes, valid for all f).

Both certificates exact-standard-three. Full button green fresh.

Half-lift remaining (mapped in memory): dsm dispatch wrapper, recompute
bind-chain inversion, bytesVal injectivity, assembly in PointLiftSpec.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 14:10:09 +02:00
85cfb34a7d Phase 2, brick 1 complete: ed_compress_spec - compress emits the canonical
encoding of the denoted affine point (kernel-audited)

CurveFieldProofs.ed_compress_spec: for any valid extended point Pt
(ExtValid - the invariant every certified curve op guarantees),
    compress Pt = ok s   with
    bytesVal s = (edY Pt).val + ((edX Pt).val % 2) * 2^255
- the 32 wire bytes are the canonical little-endian y-residue with the
x-parity bit at position 255. Compress semantics AND canonicity in one
statement, because to_bytes_spec pins the bytes to the residue itself.

Supporting certificates in Proofs/CompressSpec.lean:
- is_negative_spec: the sign read is the parity of the CANONICAL residue
  (bit 0 of to_bytes) - (feVal x mod p) mod 2.
- Bytes32.exists_bytes: the 32-byte destructuring device (the
  Fe.exists_limbs idiom, 32-wide).
- to_bytes_spec': premise-free restatement of the canonicity brick.
- xor_top_bit (ToBytesMath): setting a clear top bit by XOR is addition -
  proven from xor_div_two_pow + and_xor_distrib_right, no bit-blasting.

The chain is entirely certified code: invert (Fermat), two muls, to_bytes
(canonicity), is_negative, and the sign-bit XOR. Axiom cone of
ed_compress_spec: exactly [propext, Classical.choice, Quot.sound].

check.sh: CompressSpec in PROOFS, ed_compress_spec in CERTS - full button
green fresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:33:58 +02:00
e07f51c7f7 Phase 2, brick 1a: to_bytes canonicity proven (to_bytes_spec, kernel-audited)
The load-bearing brick of the point-level apex equation:
FieldElement51::to_bytes always succeeds and its 32 output bytes denote
EXACTLY the represented residue - bytesVal s = feVal a mod p. Since the
canonical residue determines the bytes, this is simultaneously
canonicity ("output is the canonical encoding") and the injectivity
compress needs ("equal residues iff equal bytes").

- Proofs/ToBytesMath.lean: the context-free ℕ mathematics (METHOD 4) -
  the 5-rung carry telescope (div_rung/q_telescope), the q-trick facts
  (q = (h+19)/2^255 is a bit, fires iff h >= p), q_mod_p (adding 19q and
  discarding bit 255 subtracts pq exactly), carry_pack (the masked-limb
  assembly mod 2^255), five per-limb byte-chunk splits, and bytes_pack
  (the 32-byte little-endian reassembly, closed by one zify +
  linear_combination over the five splits).
- Proofs/ToBytesSpec.lean: the symbolic execution - at ~150 machine ops
  the longest walk in the repo, loop-free: weak reduce (reduce_spec),
  the q pass, the fold + carry pass, 32 byte extractions (the four
  limb-boundary bytes turn disjoint ORs into additions via
  Nat.two_pow_add_eq_or_of_lt), and the trailing top-bit debug-assert
  DISCHARGED (b31 = f4/2^44 < 2^7), not assumed.
- check.sh: ToBytesMath/ToBytesSpec in PROOFS, to_bytes_spec in CERTS
  (exact standard-three audit) - full button green fresh.

Walk lessons (for the control repo, next push): rw index-equations into
their consumers instead of subst (subst eliminates the wrong side or
dies on dependent do-motives); never rw [Nat.mod_eq_of_lt (by omega)]
(metavariable goal reaches omega) - state the bound with show.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:10:43 +02:00
c85704c0c4 THE SIGNATURE APEX: the EdDSA verification equation, proven and audited
`Proofs/SigApexSpec.lean`:
- `verify_loop_full` — the extracted 32-byte comparison loop returns exactly
  the byte-equality of the two arrays (induction; axiom cone = exactly
  [propext, Classical.choice, Quot.sound]).
- `verify_accepts_iff` — THE APEX: for a signature that parses, the
  extracted RustCrypto verifier accepts IFF the recomputed compressed point
      compress( [s]·B − [k]·A )
  equals the signature's R byte-for-byte. The recomputation is grounded in
  the PROVEN curve model (every curve and scalar call is a certified
  definition); k is whatever scalar the SHA-512 oracle produces — the
  honest EdDSA acceptance criterion with the hash opaque.

Boundary hygiene forced by the audit itself:
- The public vartime_double_scalar_mul_basepoint dispatch pulled the AVX2
  vector-backend axiom into the apex cone. Fixed at the build level:
  extract.sh pins RUSTFLAGS --cfg curve25519_dalek_backend="serial", so the
  SIMD arm compiles out; BackendKind has only Serial and
  get_selected_backend becomes a real definition (ok Serial).
- subtle.Choice.unwrap_u8 upgraded from axiom to the documented model
  definition (Choice := U8; unwrap_u8 = self.0) — it sits on the verify
  path via compress → is_negative.
- CurveSig modules added to GEN_MODULES (stale-olean incoherence otherwise).

check.sh grows Phase 3b: the apex certificate's axiom cone must equal
EXACTLY
  [propext, Classical.choice, Quot.sound,
   ed25519.Signature, sha2.Sha512,
   sha512_new, sha512_update, sha512_finalize_bytes,
   ed25519.Signature.to_bytes, signature.error.Error, Error.new]
— the SHA-512 hash oracle plus the opaque wire-format types. NO curve
axioms, NO scalar axioms, NO backend axioms, enforced on every button press.

Full check.sh green: 16 standard certificates + the apex audit.

Phase 2 (the point-level equation [s]B − [k]A = decompress R, needing
to_bytes canonicity and decompress) remains deferred and documented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:45:55 +02:00
133eab8467 NAF encoder proven end-to-end + the phase-1 double-scalar-mul apex
The complete non_adjacent_form(5) verification (four stages):
- `Proofs/DsmNafLoadSpec.lean` (generated) — the LE byte-to-word load.
- `Proofs/DsmNafMath.lean` — the digit loop's arithmetic core: window-read
  lemmas (single/cross-word), the exact ZZ invariant steps (Nat.mod_mul
  telescope), the carry-kill argument from V < 2^253, and the exit theorem.
- `Proofs/DsmNafLoopSpec.lean` — the w=5 digit loop by induction on the
  remaining-bits measure: per-step 64-bit window read (4-way word split),
  digit write via hcast/wrapping_sub (exact value window - 32*carry',
  oddness, |d| < 16), invariant carried through even/odd steps.
- `Proofs/DsmNafSpec.lean` — the public spec: both entry masserts
  DISCHARGED; the digits satisfy the NAF conditions and
      sum naf[k]*2^k = V   EXACTLY (integers, no modular slack)
  for any scalar whose LE byte value V is below 2^253.

And the campaign's brick 4, `Proofs/DsmMulSpec.lean`:
- `run_basepoint` — the transpiled ED25519_BASEPOINT_POINT is the standard
  base point: valid extended coordinates (X*Y = Z*T) and the curve equation,
  kernel-checked via denominator-free 121666-scaled witnesses. Includes the
  generic witness lemmas fp_mul_eq_of_witness / onCurve_of_witness.
- `vartime_double_base_mul_spec` — THE PHASE-1 COMPUTATIONAL SPEC of
  vartime_double_base::mul: for canonical scalars and a valid on-curve A,
  the result is valid, on-curve, and denotes
      dsmFold (naf a) (naf b) (edPt A) edBasePt edId 256
  with both digit arrays proven exact NAF encodings. Phase 2 (group
  semantics [a]A + [b]B) requires Edwards associativity — deferred and
  documented; nothing assumes it.

Also: removed a vestigial pre-re-extraction axiom stub
(backend.serial.scalar_mul.vartime_double_base.mul) from FunsExternal —
a root-level leftover that shadowed the real namespaced definition during
name resolution in proof files. Never referenced by any certificate (the
#print-axioms audit guards against that); deleted for hygiene.

CERTS += naf_load_spec, naf_exit, naf_digit_loop_spec,
non_adjacent_form_spec, run_basepoint, vartime_double_base_mul_spec —
each audited to exactly [propext, Classical.choice, Quot.sound].
Full check.sh green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:52:06 +02:00
195eafcc16 NAF campaign stages 1-2: LE load walks + the digit loop's arithmetic core
- `Proofs/DsmNafLoadSpec.lean` (generated) — the byte-to-word LE load of
  `non_adjacent_form`: four 8-peel inner walks (t |= bytes[8k+bi] << 8bi)
  and the outer 4-peel filling x_u64[0..3]; x_u64[4] stays 0 (the pad word
  the cross-word window reads at positions >= 251).

- `Proofs/DsmNafMath.lean` — the pure arithmetic of the w=5 digit loop:
  `nafSum`/`nafSum_set`; window-read lemmas `naf_window_single` /
  `naf_window_cross` (cross-word disjoint-OR read sees (V >> pos) mod 32);
  invariant steps `naf_even_step` / `naf_odd_step` (Nat.mod_mul telescope:
  digit + promoted carry reconstruct the consumed bits EXACTLY, in ZZ);
  carry-kill `naf_carry_even` / `naf_carry_odd` (V < 2^253 forces the
  carry dead before bit 256); `naf_exit` (nafSum naf 256 = V exactly).

The digit-loop walk (stage 3) composes these next; its invariant is
    nafSum naf 256 + carry*2^pos = V mod 2^pos
with digits at k >= pos all zero and carry = 1 -> pos <= 254.

CERTS += naf_load_spec, naf_window_cross, naf_exit (axiom-clean).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 15:30:18 +02:00
5f785a75a3 coherence pass 2: restore the one-button property, institutionalize audits
- check.sh: proofs memory default 6144 -> 8192 (ReduceSpec's norm_num
  step peaks above 6144; guard aborted gracefully — R3 was broken, S1
  held). Matches pasta's calibration.
- check.sh: dead-file gate now exempts Scalar* (delegated to
  check-scalar.sh); the gate had been un-passable since the scalar layer
  landed, masked by the memory failure.
- check.sh: axiom-audit phase routed through lean-guard (cgroup + flock;
  was raw lean -M), audit temp file moved into the workspace (lake env
  rejects /tmp inputs — the /tmp phase had never run green).
- check-scalar.sh: NEW Phase 3 kernel axiom audit — ScalarProofs.L_val
  must report exactly [propext, Classical.choice, Quot.sound].
- README: signature layer ' planned' (was 'in progress' with nothing
  started); planned certificate names marked as such.

Validated: full check.sh + check-scalar.sh green end-to-end in the pass-2
sweep (see formal-verification-control/COHERENCE-PASS-2.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 12:54:26 +02:00
c81b26d9c2 lean-guard: disable core dumps (no more apport popups on capped aborts)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:23:30 +02:00
67f1b11730 controls: route all compiles through lean-guard (memory-capped, single-flight)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:10:55 +02:00
8ce599c4aa group-law layer: complete twisted Edwards addition law proven
Extraction widened to backend::serial::curve_models + edwards (own gen/,
209 defs). Adapted the reference Ed* proof suite: namespace rename +
Curve25519TraitsIdentity -> Curve25519_dalekTraitsIdentity. New opaque
externals (scalar_mul backends, get_selected_backend, decompress, sum,
from_slice) are axioms outside both certificate cones — verified by the
Phase-3 audit. All 21 proofs compile; field certificates unchanged.

Not claimed (matching the reference solution's honest scope): edAdd
associativity, scalar multiplication, decompress/compress, AVX2 backend.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:50:42 +02:00
b79375600f field layer: 14 proofs pass, fieldImplementation axiom-clean
Ported from the locally verified Hermes working copy; FeQ and Square2Spec
(dead files in the published replica) now compile and are in the check
manifest. check.sh gates: source integrity, stub audit, zero axiom
declarations under Proofs/, per-certificate axiom audit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:17:44 +02:00