/- 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 end LTLAcc