pasta-pallas-verified/verification/Proofs/AddSpec.lean
mrwulf 7d7bc25353 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:31 +02:00

90 lines
4.2 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.

/- ──────────────────────────────────────────────────────────────────────────────
Proofs/AddSpec.lean — addition of the transpiled Fp.
RUST ANALOG (src/fields/fp.rs:392-403): 4-limb adc chain computing the raw
sum d = a + b (the final carry is PROVABLY zero: a, b < p < 2²⁵⁵ so
a + b < 2²⁵⁶), followed by `(&Fp(d)).sub(&MODULUS)` — the same conditional
reduction proven general in Proofs/SubNegSpec.lean (d < 2P shape).
SPEC (exact , additive):
Canon a → Canon b →
add a b = ok r with Canon r ∧ (r = a + b r + P = a + b).
────────────────────────────────────────────────────────────────────────────── -/
import Proofs.SubNegSpec
open Aeneas Aeneas.Std Result
open pasta_curves
set_option maxHeartbeats 8000000
set_option linter.unusedTactic false
set_option linter.unreachableTactic false
namespace PastaProofs
open Aeneas.Std.WP
macro "dis" : tactic =>
`(tactic| (subst_vars; try simp [Array.set_val_eq, *]; try scalar_tac))
/-- `Fp::add`: total, canonical, exact value (see file header). -/
theorem add_spec (a b : Fe) (ha : Canon a) (hb : Canon b) :
fields.fp.Fp.add a b
⦃ r => Canon r ∧
(feVal r = feVal a + feVal b
feVal r + P = feVal a + feVal b) ⦄ := by
obtain ⟨a0, a1, a2, a3, hla⟩ := Fe.exists_limbs a
obtain ⟨b0, b1, b2, b3, hlb⟩ := Fe.exists_limbs b
unfold Canon at ha hb
rw [feVal_eq a a0 a1 a2 a3 hla] at ha
rw [feVal_eq b b0 b1 b2 b3 hlb] at hb
unfold fields.fp.Fp.add
let* ⟨ i, hi ⟩ ← Array.index_usize_spec by dis
let* ⟨ i1, hi1 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d0, carry0, hadc0 ⟩ ← adc_spec by dis
let* ⟨ i2, hi2 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i3, hi3 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d1, carry1, hadc1 ⟩ ← adc_spec by dis
let* ⟨ i4, hi4 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i5, hi5 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d2, carry2, hadc2 ⟩ ← adc_spec by dis
let* ⟨ i6, hi6 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i7, hi7 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d3, carry3, hadc3 ⟩ ← adc_spec by dis
-- identify reads
have hv_i : i.val = a0.val := by simp [hi, hla]
have hv_i1 : i1.val = b0.val := by simp [hi1, hlb]
have hv_i2 : i2.val = a1.val := by simp [hi2, hla]
have hv_i3 : i3.val = b1.val := by simp [hi3, hlb]
have hv_i4 : i4.val = a2.val := by simp [hi4, hla]
have hv_i5 : i5.val = b2.val := by simp [hi5, hlb]
have hv_i6 : i6.val = a3.val := by simp [hi6, hla]
have hv_i7 : i7.val = b3.val := by simp [hi7, hlb]
have hb_d0 : d0.val < 2^64 := by scalar_tac
have hb_d1 : d1.val < 2^64 := by scalar_tac
have hb_d2 : d2.val < 2^64 := by scalar_tac
have hb_d3 : d3.val < 2^64 := by scalar_tac
-- the raw sum: Σd + 2²⁵⁶·carry3 = a + b < 2P < 2²⁵⁶, hence carry3 = 0
have hsum : limbsVal d0 d1 d2 d3 + 2^256 * carry3.val =
limbsVal a0 a1 a2 a3 + limbsVal b0 b1 b2 b3 := by
unfold limbsVal at *
omega
-- the conditional reduction: sub (Σd) MODULUS with Σd < 2P
have hMle : feVal fields.fp.MODULUS ≤ P := le_of_eq feVal_MODULUS
have hdlt : feVal (Array.make 4#usize [d0, d1, d2, d3] (by simp)) <
feVal fields.fp.MODULUS + P := by
rw [feVal_MODULUS, feVal_make]
unfold limbsVal P at *
omega
-- MEMORY DISCIPLINE (post 2026-07-02 OOM): sub_spec's two arithmetic
-- preconditions are discharged by EXACT matches against the facts proven
-- above — never by the blanket `dis` (simp [*] + scalar_tac saturates in
-- this ~60-hypothesis context and allocates without bound).
let* ⟨ r, hr_canon, hr_val ⟩ ← sub_spec by
(first | exact hMle | exact hdlt)
-- conclude
rw [feVal_eq a a0 a1 a2 a3 hla, feVal_eq b b0 b1 b2 b3 hlb]
refine ⟨hr_canon, ?_⟩
rw [feVal_MODULUS, feVal_make] at hr_val
unfold Canon limbsVal P at *
omega
end PastaProofs