ltl-accumulator-verified/verification/Proofs/Theorem3.lean
mrwulf 260ad64511 revision round 1: address both external reviews (GPT-5.6 + second Claude)
No theorem was wrong; every fix is spec-surface, audit-mechanism, docs,
or harness coverage. Changes:

LEAN (Claude F1, GPT M4):
- acceptIncl: the consumer's inclusion accept (m<n ∧ Root=some r) is now
  a named object, not just a theorem hypothesis. Root alone accepts
  out-of-range m; acceptIncl pins the guard.
- acceptIncl_complete / acceptIncl_sound: route Thm 1/2 through it.
- extractCons_correct_paper: Thm 3 at the paper's exact quantifiers
  (n₀≤n₁, no separate 0<n₀; n₀=0 discharged since D₀=[]=take 0).

SCRIPT (GPT H1/H2, Claude F3):
- Phase 3b: fail-closed audit-surface COVERAGE — every named decl under
  Proofs/ and gen/ must be in CONES or a documented EXCLUDE (sha256,
  Bytes); anonymous gen instances count-pinned; every CONES key must be
  queried by AxiomCheck (no pin-but-never-check). Tested: an
  unclassified theorem now makes the button exit 1.
- H2: distinct markers — LEAN GREEN always, ATTESTATION GREEN only when
  fidelity actually ran; SKIP/absent-pacta no longer emit the strong
  marker. Attestation gate keys on ATTESTATION GREEN.
- Phase 0: orphan-olean guard (every Proofs/*.olean needs a sibling
  .lean); deleted 6 orphans; untracked all *.olean/.lake from git and
  gitignored them (root cause of the F3 tarball leak).

HARNESS (Claude F1, GPT M3):
- added out-of-range families (m≥n, m>n, n₀>n₁, n₀=0); re-pinned counts
  230,271 / 230,016 (match the reviewer's independent RFC difftest
  exactly); narrowed 'exhaustive' wording to the tested domain.

DOCS: README stale rows fixed (freeze banner no longer contradicts
table); KNOWN-GAPS gap 3 reworded (general Lemma 2 = specializations),
+gaps 9 (cost), 10 (pin init), 11 (acceptIncl resolved); STATEMENT-MAP
+acceptIncl rows, +Lemma-2-general note, +constant-vs-property
clarification for §10(i).

Button: EXIT 0, coverage complete, ATTESTATION GREEN, 230,271/230,016.
56 pinned cones over an ENFORCED surface. LTL untouched (12, bcd15f9d).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:53:47 +02:00

81 lines
3.9 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/- S5.4 — **Theorem 3 (Consistency soundness)**, assembled: the explicit
extractor 𝓔 for history rewrites. Joins consRecBinding (steps 1-2,
S5.3) to extractMTH (step 3, S4).
Statement design per the corpus discipline: a NAMED function whose
correctness is about ITS OUTPUT (pigeonhole/choice cannot discharge
it), guarded by a permanent non-vacuity witness. -/
import Proofs.Binding3
namespace LTLAcc
/-- The consistency extractor 𝓔 (paper Theorem 3). On a claimed rewrite
— an accepted consistency proof `C` between the pinned root of `D₀`
and the head of `D₁`, where `D₀` is NOT the real prefix — return the
node collision found while walking the fold, or descend into the two
same-root prefix trees. -/
noncomputable def extractCons (n₀ : Nat) (C : List Hash)
(D₀ D₁ : List Bytes) : List UInt8 × List UInt8 :=
match extractConsNode n₀ D₁.length C true (MTH D₀) D₁ with
| some c => c
| none => extractMTH D₀ (D₁.take n₀)
/-- **Theorem 3 (Consistency soundness), explicit form**: if the
consumer's verifier accepts `C` between the pinned head `MTH D₀`
(size `n₀`) and the offered head `MTH D₁`, but `D₀` is not the real
prefix of `D₁`, then `extractCons` outputs a genuine SHA-256
collision. -/
theorem extractCons_correct (n₀ : Nat) (C : List Hash) (D₀ D₁ : List Bytes)
(hlen0 : D₀.length = n₀) (hn0 : 0 < n₀) (hle : n₀ ≤ D₁.length)
(hne : D₀ ≠ D₁.take n₀)
(hacc : ConsRec n₀ D₁.length C true (MTH D₀) = some (MTH D₀, MTH D₁)) :
IsCollision (extractCons n₀ C D₀ D₁).1 (extractCons n₀ C D₀ D₁).2 := by
have hbind := consRecBinding (MTH D₀) n₀ D₁.length C true D₁
(MTH D₀) (MTH D₁) rfl hn0 hle hacc rfl
rw [extractCons]
cases hrec : extractConsNode n₀ D₁.length C true (MTH D₀) D₁ with
| some c =>
rw [hrec] at hbind
exact hbind
| none =>
rw [hrec] at hbind
-- hbind : MTH D₀ = MTH (D₁.take n₀); descend
have htklen : (D₁.take n₀).length = n₀ := by
rw [List.length_take]; omega
exact extractMTH_correct D₀ (D₁.take n₀) (by omega) hne hbind
/-- Permanent non-vacuity witness: on a NON-rewrite input (the pinned
list IS the real prefix), the extractor's output is provably NOT a
collision — so the correctness conclusion is false for some inputs
and cannot be discharged by pigeonhole or choice. Uses the honest
n₀ = n base: D₀ = D₁ = [[7]], C = [], where ConsRec accepts and
extractConsNode returns none, so extractCons = extractMTH D₀ D₀ =
the equal leaf pair. -/
theorem extractCons_nonvacuous :
¬ IsCollision (extractCons 1 [] [([7] : List UInt8)] [([7] : List UInt8)]).1
(extractCons 1 [] [([7] : List UInt8)] [([7] : List UInt8)]).2 := by
rw [extractCons]
have hrec : extractConsNode 1 ([([7] : List UInt8)]).length [] true
(MTH [([7] : List UInt8)]) [([7] : List UInt8)] = none := by
rw [extractConsNode]; simp
rw [hrec]
rw [extractMTH]
simp only [List.length_singleton, if_pos (by omega : (1:Nat) ≤ 1)]
intro hcol
exact hcol.1 rfl
/-- Theorem 3 at the paper's exact quantifiers (review M4): `n₀ ≤ n₁`
without a separate `0 < n₀`. The `n₀ = 0` case is discharged: `D₀`
has length 0 so `D₀ = [] = D₁.take 0`, contradicting `hne`. -/
theorem extractCons_correct_paper (n₀ : Nat) (C : List Hash) (D₀ D₁ : List Bytes)
(hlen0 : D₀.length = n₀) (hle : n₀ ≤ D₁.length)
(hne : D₀ ≠ D₁.take n₀)
(hacc : ConsRec n₀ D₁.length C true (MTH D₀) = some (MTH D₀, MTH D₁)) :
IsCollision (extractCons n₀ C D₀ D₁).1 (extractCons n₀ C D₀ D₁).2 := by
rcases Nat.eq_zero_or_pos n₀ with h0 | hpos
· exfalso; apply hne
have hD0 : D₀ = [] := List.length_eq_zero_iff.mp (by omega)
rw [hD0, h0]; simp
· exact extractCons_correct n₀ C D₀ D₁ hlen0 hpos hle hne hacc
end LTLAcc