Commit graph

13 commits

Author SHA1 Message Date
0b1fa12e15 Hash-to-scalar PROVEN: from_bytes_wide_spec - Scalar::from_hash's reduction is exact mod l
The apex brick of the scalar layer: for any 64 bytes (the opaque SHA-512
digest), [from_bytes_wide bytes] = (LE 512-bit value) mod l, with
canonical 52-bit-bounded output. Composition: bytes_unpack_spec (8x8
loops) -> split_words_lo/hi_spec (exact div/mod per limb, disjoint ORs
as additions) -> wide_split_telescope (isolated omega) -> montgomery_mul
by R and RR (R cancels as a unit, RR restores it) -> the canonical add.

The two kernel-capacity walls found and crossed en route (control repo
FAILURES.md updated):
- a montgomery_mul inside any walk motive replays its 400-line body at
  every kernel step (fix: named prefix functions in the pinned source);
- straight-line IndexMut closure chains make kernel defeq exponential in
  depth (fix: struct-literal construction - the split halves now build
  Scalar52([...]) directly). Full certificate: 77 s kernel-inclusive.

Regenerated gen (sources factor from_bytes_wide -> from_bytes_wide_parts
-> split_words_lo/hi; documented pure refactors, cargo-checked).
check-scalar.sh: 13 proof files, 13 kernel audits, all exactly
[propext, Classical.choice, Quot.sound]. Button pressed fresh: green.
2026-07-04 11:00:50 +02:00
a691a39426 Signature layer: the 64-byte unpack certificates (8x8 loops proven)
Toward Scalar::from_hash: bytes_unpack_spec proves the from_bytes_wide
word-unpack loops pack 64 little-endian bytes into 8 words exactly.

- Proofs/ScalarBytesSpec.lean (3308 lines): bytes_word_loop_spec_0..7,
  each split head/tail at j=4 (the 8-fold monolith grows exponentially
  in elaboration - METHOD 4). Disjoint-bit ORs become additions via
  core's Nat.two_pow_add_eq_or_of_lt with explicit calc bridges (the
  default simp set literalizes 2^8 -> 256 and breaks pow-form rewrites;
  simp only everywhere).
- Proofs/ScalarUnpackSpec.lean: bytes_unpack_spec composes the eight
  inner lemmas through the outer loop (iterator start needs a term-level
  equality rewrite per peel).

The from_bytes_wide main walk itself is proven at elaboration level
(fail-probe verified end to end) but its single-decl kernel certificate
replays >30min; it ships next as a phase-split (plan in the control
repo's method notes). check-scalar.sh: 12 proof files, 12 kernel audits,
all exactly [propext, Classical.choice, Quot.sound]. Button green.
2026-07-04 03:22:28 +02:00
84da3793db Signature layer, first bricks: canonicity closure + hash-to-scalar foundation
Canonicity pass (the layer is now closed under its own preconditions):
- sub_val_spec post carries the exact value equation
  (exists beta <= 1, scVal r + scVal b = scVal a + ell*beta, with the
  underflow guard beta = 1 -> scVal a < scVal b)
- add/montgomery_reduce/mul/aggregate posts all carry scVal r < ell:
  canonical inputs give canonical outputs everywhere. Needed because
  from_bytes_wide (hash-to-scalar) feeds Montgomery outputs into add.

Hash-to-scalar foundation (toward Scalar::from_hash / EdDSA verify):
- extraction scope + from_bytes_wide (brings constants::R); regenerated gen
- source repos carry a documented Aeneas-compat patch: the bare
  `hi[4] = words[7] >> 20` extracts ill-typed at pin bf13c42e; masked
  (semantic no-op, words[7] >> 20 < 2^44)
- Proofs/ScalarWideSpec.lean: R constant lemmas (R = 2^260 mod ell,
  witness 2^260 = R + 255*ell) and montgomery_mul_spec, the single
  Montgomery round: [r]*2^260 = [a]*[b], canonical bounded output

check-scalar.sh: 10 proof files, 11 kernel audits, all exactly
[propext, Classical.choice, Quot.sound]. Button pressed fresh: green.
2026-07-03 23:18:32 +02:00
82ee511277 Scalar layer complete: Montgomery reduction + full mul ported, scalarImplementation aggregate
Port of the dalek Montgomery stack against THIS fork's own extraction
(gen sections byte-identical, proofs recompiled from scratch here):
- Proofs/ScalarMulSpec.lean      - mul_internal: 9 exact schoolbook columns
- Proofs/ScalarMontSpec.lean     - part1/part2 exact-division rounds
  (LFACTOR*L0 = -1 mod 2^52), head/tail telescopes, mont_bound, tail walk
- Proofs/ScalarReduceSpec.lean   - montgomery_reduce main walk:
  scDenote r * 2^260 = Z in ZMod ell + 52-bit output bounds
- Proofs/ScalarFullMulSpec.lean  - mul = double Montgomery round through
  RR = R^2 mod ell; R cancelled as a unit; post: [mul a b] = [a]*[b]
- Proofs/ScalarMain.lean         - scalarImplementation aggregate (ScBnd
  interfaces; canonical inputs discharge the Montgomery bound)

sub_val_spec/add_val_spec posts strengthened with result-limb bounds.
check-scalar.sh: 9 proof files, 10 kernel audits, all exactly
[propext, Classical.choice, Quot.sound]. Button pressed fresh: green.
2026-07-03 21:46:39 +02:00
49a68688c9 scalar layer: add+sub fully proven mod l against THIS fork's v4 extraction
This v4.1.x fork implements Scalar52::sub with TWO loops (loop0 = borrow
chain; loop1 adds L &&& underflow_mask — the arithmetic-mask constant-time
conditional), a genuinely different code path from upstream v5's
subtle-based conditional_add_l. Verified per R2 against this fork's own gen:

- sub_loop_spec (= loop0): borrow chain, verbatim technique from dalek
- sub_loop1_zero_spec / sub_loop1_one_spec: the masked-L add, both mask
  values (0 / 2^64-1), full carry chains
- sub_val_spec: denote(sub a b) = denote a - denote b in ZMod l; the
  underflow mask um = ((borrow>>>63) XOR 1) - 1 resolved per case
- add_loop_spec + add_val_spec: denote(add a b) = denote a + denote b
  (v4 add_loop extracts token-identical to v5; composition through this
  fork's own sub_val_spec)

check-scalar.sh: full manifest, 5/5 kernel axiom audit
[propext, Classical.choice, Quot.sound], green at 300-400s/4096MB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:45:16 +02:00
aa5b88abc7 lean-guard 3b: global-headroom clamp (sync with control master)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 17:51:16 +02:00
246fc61d9e 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:28 +02:00
661e8c4c8f coherence pass 1: TRUSTED-BASE scalar notes + both check-button docs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:58:31 +02:00
6fe31be80d Add scalar-layer foundation (Scalar52 arithmetic mod ℓ)
Transpile the Scalar52 limb backend (backend::serial::u64::scalar
add/sub/mul/square/montgomery_*) from Rust to Lean via Charon/Aeneas,
scoped at the function level to the iterator-free arithmetic core.

  - verification/extract-scalar.sh: function-level Charon/Aeneas extraction.
    This fork (v4.1.3) inlines a local `black_box` (a volatile read used as an
    optimization barrier) inside Scalar52::sub; charon cannot translate the
    `&raw const` it lowers to, so it is marked --opaque and modeled below.
  - verification/gen/CurveScalar/{Types,Funs}.lean: transpiled model (27 defs)
  - verification/gen/CurveScalar/FunsExternal.lean: hand-written model of
    Scalar52::sub::black_box as the identity on u64 (a volatile read returns
    the value written; the qualifier is only an optimization barrier).
    TypesExternal.lean is decl-free — this fork pulls in no external types
    (unlike v5 dalek, which routes sub through subtle::Choice).
  - verification/Proofs/ScalarDenote.lean: semantic foundation — Scalar52
    denotation into ℤ/ℓℤ, limb-bound invariant, and L_val (the transpiled
    constants::L denotes exactly the group order ℓ, kernel-checked).
  - verification/check-scalar.sh: guarded compile of the gen modules plus the
    denotation foundation.

check-scalar.sh passes: gen compiles; denotation + L = ℓ proven.
add/sub/mul remain in progress.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:24:39 +02:00
d3f7359832 group-law layer: complete twisted Edwards addition law proven
Extraction widened to backend::serial::curve_models + edwards (v4 Aeneas,
183 defs, own gen/). Reference Ed* suite adapted: namespace + v4
SharedA/SharedB instance renames. All 20 proofs compile under lean-guard
(ReduceSpec needs an 8GB cap against the widened gen — contained by the
guard, documented). Both certificates axiom-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:49:31 +02:00
681399d0de 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
59ab518093 field layer: 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. Basic.lean (never compiled under v4 Aeneas) removed rather than
shipped dead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:38:52 +02:00
ee0fe08ae8 skeleton: proof-pyramid layout, honest status table, trusted-base doc
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:10:26 +02:00