anza-ed25519-verified/verification/MODEL-CORRESPONDENCE.txt
mrwulf 7cfa0872d4 Round-7 F1: make model/template correspondence SEMANTIC, and fail closed
THE DEFECT, as found. GPT-5.6 showed the textual classifier could report
PROVEN for a name Lean resolves to an axiom: a definition appearing only
inside a `/- -/` comment was read as real. Repairing that exposed something
larger and already live. Aeneas wraps long declarations:

    axiom
      curve25519_dalek.edwards.EdwardsPoint.Insts.CoreOpsArithNegEdwardsPoint.neg

The old scanner required keyword and name on one physical line, so it matched
nothing there and SILENTLY DROPPED the declaration — no MODEL row, no PROVEN
row, no failure. Nine to ten externals per fork had no row at all, and the
tier-A/B `neg` was missing from every committed table while the trust
documents claimed that class was machine-checked. Four pinned tables were
wrong, in four repositories, with the buttons green over them. No attacker
was required; Aeneas's own formatting did it.

The lesson is not "write a better regex". The scanner was FAIL-OPEN: input it
could not parse produced silence instead of a stop. A gate that drops what it
cannot read is worse than no gate, because the green covers a gap that is
invisible in the diff.

THE REPAIR, in three layers that each do only what they honestly can.

  · DISCOVERY stays textual, because the template cannot be imported — it
    declares the same names as the model and they would clash. It now strips
    NESTED `/- -/` blocks, reads a name that wraps to a later line, tracks
    namespace/section/end, and FAILS CLOSED: an unparseable keyword exits 2
    naming file and line.
  · Phase 0d keeps the cheap pre-compile comparison against the table.
  · Phase 2d is new and authoritative. After compilation it generates a temp
    Lean driver (the Phase 2b idiom, so no permanent module and no manifest
    churn), imports every non-template gen module, and asks env.find? what
    each external IS: kind and originating module. Model module -> MODEL;
    non-axiom in a generated module -> PROVEN; an axiom outside the model, or
    a name that does not resolve, is a failure. Lean's verdict must equal the
    committed table's, and the answer count must equal the question count so
    a truncated resolver cannot pass.

THE TABLES were regenerated and verified three ways before being committed:
an independently written second scanner agreed on 228/228 rows across the
four forks; all 47 changed rows carry file:line evidence; and the PROVEN row
was put to Lean directly — kind = def, module = CurveField.Funs.

  dalek 54 -> 64 rows   anza 42 -> 51   risc0 48 -> 57   betrusted 47 -> 56

Also corrected: `from_residual` was recorded EXTRA in every fork; the
template does demand it, so it is MODEL. anza carried a spurious `hash|EXTRA`
row from a mis-parse.

NEGATIVE-TESTED. With Phase 0d neutered so Phase 2d was the gate under test,
a PROVEN row edited to MODEL produces:

    SEMANTIC DRIFT: ...neg — table says MODEL, Lean says PROVEN

selftest-correspondence.sh grew 4 cases -> 7: GPT's comment counterexample,
the wrapped declaration that was actually live, and a fail-closed check.

WHAT THIS DOES NOT CLOSE. Phase 2d resolves names in the environment built
from gen/. It establishes what a name IS — assumption or proof, and where —
not that the extraction faithfully represents the Rust. That remains the
Charon/Aeneas trust assumption and no gate here can close it.

Certified: both buttons, all four forks, purged trees. 8/8 green, with
62/48/53/52 externals resolved by Lean and every verdict matching.
2026-08-02 02:24:15 +02:00

52 lines
4.3 KiB
Text

CurveField/FunsExternal|Array.Insts.CoreHashHash.hash|MODEL
CurveField/FunsExternal|Bool.Insts.CoreConvertFromChoice.from|MODEL
CurveField/FunsExternal|Slice.Insts.CoreFmtDebug.fmt|MODEL
CurveField/FunsExternal|Slice.Insts.SubtleConstantTimeEq.ct_eq|MODEL
CurveField/FunsExternal|U32.Insts.CoreIterRangeStep.backward_checked|MODEL
CurveField/FunsExternal|U32.Insts.CoreIterRangeStep.forward_checked|MODEL
CurveField/FunsExternal|U32.Insts.CoreIterRangeStep.steps_between|MODEL
CurveField/FunsExternal|U64.Insts.SubtleConditionallySelectable.conditional_assign|MODEL
CurveField/FunsExternal|U64.Insts.SubtleConditionallySelectable.conditional_select|MODEL
CurveField/FunsExternal|U64.Insts.SubtleConditionallySelectable.conditional_swap|MODEL
CurveField/FunsExternal|U8.Insts.CoreHashHash.hash|MODEL
CurveField/FunsExternal|U8.Insts.SubtleConstantTimeEq.ct_eq|MODEL
CurveField/FunsExternal|backend.scalar_fits_in_128_bits|MODEL
CurveField/FunsExternal|backend.serial.curve_models.AffineNielsPoint.Insts.SubtleConditionallySelectable.conditional_swap|MODEL
CurveField/FunsExternal|backend.serial.curve_models.ProjectiveNielsPoint.Insts.SubtleConditionallySelectable.conditional_swap|MODEL
CurveField/FunsExternal|backend.serial.scalar_mul.variable_base.mul|MODEL
CurveField/FunsExternal|backend.serial.scalar_mul.vartime_triple_base.mul_128_128_256_prechecked|MODEL
CurveField/FunsExternal|backend.serial.u64.field.FieldElement51.Insts.CoreCmpEq.assert_fields_are_eq|MODEL
CurveField/FunsExternal|core.fmt.Formatter.debug_struct_field2_finish|MODEL
CurveField/FunsExternal|core.ops.range.RangeFull.Insts.CoreSliceIndexSliceIndexSliceSlice.get|MODEL
CurveField/FunsExternal|core.ops.range.RangeFull.Insts.CoreSliceIndexSliceIndexSliceSlice.get_mut|MODEL
CurveField/FunsExternal|core.ops.range.RangeFull.Insts.CoreSliceIndexSliceIndexSliceSlice.get_unchecked|MODEL
CurveField/FunsExternal|core.ops.range.RangeFull.Insts.CoreSliceIndexSliceIndexSliceSlice.get_unchecked_mut|MODEL
CurveField/FunsExternal|core.ops.range.RangeFull.Insts.CoreSliceIndexSliceIndexSliceSlice.index|MODEL
CurveField/FunsExternal|core.ops.range.RangeFull.Insts.CoreSliceIndexSliceIndexSliceSlice.index_mut|MODEL
CurveField/FunsExternal|core.result.Result.Insts.CoreOpsTry_traitFromResidualResultInfallibleE.from_residual|MODEL
CurveField/FunsExternal|core.result.Result.Insts.CoreOpsTry_traitTry.branch|MODEL
CurveField/FunsExternal|ed25519.Signature.r_bytes|MODEL
CurveField/FunsExternal|ed25519.Signature.s_bytes|MODEL
CurveField/FunsExternal|ed_sigs.sha512_hash3|MODEL
CurveField/FunsExternal|edwards.CompressedEdwardsY.Insts.CoreCmpEq.assert_fields_are_eq|MODEL
CurveField/FunsExternal|edwards.CompressedEdwardsY.from_slice|MODEL
CurveField/FunsExternal|edwards.EdwardsPoint.Insts.CoreCmpEq.assert_fields_are_eq|MODEL
CurveField/FunsExternal|edwards.EdwardsPoint.Insts.CoreIterTraitsAccumSum.sum|MODEL
CurveField/FunsExternal|edwards.EdwardsPoint.Insts.SubtleConditionallySelectable.conditional_assign|MODEL
CurveField/FunsExternal|edwards.EdwardsPoint.Insts.SubtleConditionallySelectable.conditional_swap|MODEL
CurveField/FunsExternal|edwards.affine.AffinePoint.Insts.CoreCmpEq.assert_fields_are_eq|MODEL
CurveField/FunsExternal|edwards.affine.AffinePoint.Insts.SubtleConditionallySelectable.conditional_assign|MODEL
CurveField/FunsExternal|edwards.affine.AffinePoint.Insts.SubtleConditionallySelectable.conditional_swap|MODEL
CurveField/FunsExternal|field.FieldElement51.internal_invert_batch|MODEL
CurveField/FunsExternal|subtle.Choice.Insts.CoreConvertFromU8.from|MODEL
CurveField/FunsExternal|subtle.Choice.Insts.CoreOpsBitBitAndChoiceChoice.bitand|MODEL
CurveField/FunsExternal|subtle.Choice.Insts.CoreOpsBitBitOrChoiceChoice.bitor|MODEL
CurveField/FunsExternal|subtle.Choice.unwrap_u8|MODEL
CurveField/FunsExternal|subtle.ConditionallySelectable.conditional_assign.default|MODEL
CurveField/FunsExternal|subtle.ConditionallySelectable.conditional_swap.default|MODEL
CurveField/FunsExternal|backend.vector.scalar_mul.variable_base.spec_avx2.mul|EXTRA
CurveField/FunsExternal|backend.vector.scalar_mul.vartime_double_base.spec_avx2.mul|EXTRA
CurveField/FunsExternal|backend.vector.scalar_mul.vartime_triple_base.spec_avx2.mul_128_128_256_prechecked|EXTRA
CurveField/TypesExternal|ed25519.Signature|MODEL
CurveField/TypesExternal|subtle.Choice|MODEL
CORRESPONDENCE-COUNT|51