Commit graph

10 commits

Author SHA1 Message Date
2b57db83a6 verification: close the two-button seam and level up the scalar button (P0-b)
THE SEAM. This repository is checked by two scripts, and until now neither
asserted anything about the other's scope. check.sh's dead-file gate simply
SKIPPED anything named Scalar*, so a new Proofs/ScalarX.lean was gated by
nothing at all: absent from one manifest by exemption, from the other by
omission, compiled by neither, inventoried by neither. Each button now reads
the other's manifest and requires every shipped proof source to belong to
EXACTLY ONE of them — neither orphaned nor double-claimed, both directions,
plus a phantom check on entries naming files that do not exist. Negative-tested
four ways, including the exact hole this item names.

THE SCALAR BUTTON. Closing the seam exposed it as the estate's weakest link,
having been left behind by every hardening round while the main button gained
five phases. 45 lines to 227:

  - source-integrity check over its sources;
  - harness-pin verification, so running THIS button alone is protected and not
    only running it after check.sh;
  - a kernel-side axiom-declaration gate over the compiled artifacts, replacing
    a source-text grep that is evadable four ways on v4.30.0-rc2;
  - a declaration inventory of ~1880 constants against its own allowlist,
    diffed both directions with a count trailer. These 13 modules were the only
    part of the proof corpus with no inventory: check.sh Phase 2c named them as
    uncovered on every run, and now names the button that covers them instead;
  - per-certificate exact-cone assertions replacing `-eq 13` over matching
    output lines. A count cannot say WHICH certificate is clean and passes just
    as happily if one cone is reported twice.

Every fork-specific fact was read from the existing script rather than assumed:
risc0 and betrusted audit sub_loop1_one_spec where dalek and anza audit
cond_add_l_one_spec, untouched.

THREE BUGS, ONE ROOT CAUSE, all found by the gates rather than by review. Each
reasoned about how a thing is SPELLED instead of what it BELONGS TO, and the
corpus punished each: Proofs/ScalarPackSpec.lean is named like the scalar layer
and owned by the main button.

  - the scalar dead-file gate globbed Scalar* and demanded ScalarPackSpec be
    scalar-owned. REMOVED rather than special-cased: the seam check tests
    membership in exactly one manifest, which is strictly stronger than any
    prefix;
  - the scalar axiom gate scanned Scalar*.olean, reporting "14 modules" for a
    13-module manifest. On a tree where check.sh had not run that artifact is
    absent and the button would have failed for a false reason. It now scans
    the manifest by membership and fails closed on a missing artifact;
  - Phase 2c's driver discovery globbed Inventory*.lean and claimed the other
    button's driver, then correctly complained its own manifest lacked those
    modules.

This is the family the campaign began with: a source-text axiom grep reasoning
about spelling. Recorded in TRUSTED-BASE.md because it generalises.

Also fixed: the first negative test of the scalar gate's absence check passed
for the wrong reason — the button recompiles before the gate runs, so removing
an artifact merely caused it to be rebuilt. Retested against the lifted phase,
where absence is a persistent condition.

Verified green: 24 runs across the four repositories — four main buttons, four
scalar buttons, and sixteen self-tests — zero red.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 12:30:28 +02:00
eda04cdcf9 Coherence pass 3: post-apex accuracy sweep, hygiene, guard ladder
- README: the pyramid diagram claimed the cofactored ZIP-215 equation,
  which is NOT the proven statement - corrected to the actual theorem
  (accepted IFF compress([s]B-[k]A) = R, byte-for-byte) and the signature
  row now names verify_accepts_iff; new "The signature apex (phase 1)"
  section states the theorem, this repo's glue architecture, the exact
  button-enforced axiom cone, and the phase-2 deferral.
- TRUSTED-BASE: item 5 rewritten from an aspirational hash paragraph to
  the structural boundary - certificate name, exact allowed cone, and the
  Phase 3b enforcement that fails the build on any deviation.
- Dead pre-merge artifacts removed: gen/CurveScalar, CurveScalar.llbc,
  extract-scalar.sh (the merged gen/CurveField universe is the single
  model; check-scalar.sh remains the scalar button, header updated).
- lean-guard: Guard 3a retry ladder (LEAN_MEM_WAIT_SEC) - a clamped run
  that dies on memory retries as headroom improves, converting ambient
  memory pressure from a deterministic abort into a delayed pass.

Fresh green buttons after these changes: check.sh (incl. Phase 3b apex
audit) + check-scalar.sh, both at shipped defaults, coherence pass 3
sweep 2026-07-05.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 11:48:18 +02:00
1841aa8b81 Merged gen: one CurveField universe (field + curve + scalar), both buttons green
Same architecture as the dalek/risc0/betrusted forks: the Scalar52
arithmetic start-froms (11 fns) plus scalar::from_bytes_mod_order[_wide]
join the CurveField extraction, so the field, curve, and scalar layers
share a single type universe - the prerequisite for the signature apex,
whose verify glue must see curve AND scalar calls resolve to proven
definitions by fully-qualified name.

Proofs/ScalarDenote.lean flips its import CurveScalar.Funs ->
CurveField.Funs (one line; the whole scalar proof chain recompiles
unchanged on the merged gen). check-scalar.sh repoints its GEN list.
gen/CurveScalar retained until the deprecation pass, as on the siblings.

check.sh + check-scalar.sh both green, all certificates axiom-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 23:15:54 +02:00
49859bf82f 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:49 +02:00
abb1045df3 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:27 +02:00
7dc6bdc40d 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:31 +02:00
e9774e0753 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:36:35 +02:00
681ce95293 scalar layer: add+sub fully proven mod l (port from dalek, own extraction)
The solana fork's Scalar52 sub/add/conditional_add_l extract token-identical
to upstream dalek (only the crate namespace differs: curve25519 vs
curve25519_dalek), so ScalarSubSpec/ScalarAddSpec port with the namespace
adjustment and verify against THIS fork's own gen (R2). ScalarLoop
infrastructure included. check-scalar.sh at dalek parity: full manifest +
5/5 kernel axiom audit, green at 300s/4096MB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:17:30 +02:00
37d83ab72b 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:27 +02:00
8440b53bdc 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
  - verification/gen/CurveScalar/{Types,Funs}.lean: transpiled model (28 defs)
  - verification/gen/CurveScalar/{TypesExternal,FunsExternal}.lean: hand-written
    external models (subtle.Choice + 2 subtle fns; namespace = curve25519)
  - 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 four 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:19:58 +02:00