pasta field: foundation + helper + sub/neg proofs against REAL extraction

- extract.sh: scoped Charon/Aeneas extraction of fields::fp (pow_vartime
  patched upstream to index loops — semantics-preserving, crate tests pass;
  sqrt/cmp/sum/random/... opaque, documented)
- gen/: real transpiled model; subtle/CtOption hand-modeled (Choice := U8,
  CtOption := value × is_some), all other externals are axioms outside
  certificate cones
- Proofs/PPallas: Lucas/Pratt primality certificate (reused — it was the one
  genuine piece of the previous attempt)
- Proofs/Denote: Montgomery denotation ⟪a⟫ = feVal a · R⁻¹, Canon invariant
- Proofs/HelperSpecs: adc/sbb/mac exact ℕ specs (step-registered)
- Proofs/SubNegSpec: sub_spec (general two-case identity covering the
  t<2P reduction shape) and neg_spec, proven, no axioms

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mrwulf 2026-07-02 15:51:57 +02:00
parent 14e6b74814
commit 75ae21df06
12 changed files with 3174 additions and 0 deletions

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,143 @@
/- ──────────────────────────────────────────────────────────────────────────────
Proofs/Denote.lean — the SEMANTIC FOUNDATION: from machine limbs to 𝔽_p
(Pallas base field), MONTGOMERY FORM.
WHAT THIS FILE PROVIDES
* `P`, `Fp := ZMod P` — the Pallas modulus (primality from Proofs/PPallas.lean)
* `Fe := fields.fp.Fp` — the transpiled element type: 4 little-endian u64
limbs (`Array Std.U64 4`)
* `limbsVal`/`feVal` — the EXACT natural-number value Σ lᵢ·2^(64i)
* `R`, `Rinv` — the Montgomery factor 2²⁵⁶ and its inverse in 𝔽_p
* `denote` (⟪·⟫) — THE DENOTATION: ⟪a⟫ = feVal a · R⁻¹ ∈ 𝔽_p.
pasta_curves stores a·R mod p; dividing by R in the denotation makes
every proof statement live in plain 𝔽_p (⟪mul a b⟫ = ⟪a⟫·⟪b⟫ with NO
R-factor bookkeeping at the spec level).
* `Canon` — the representation invariant: feVal a < P. Unlike dalek's
radix-51 code (loose 2⁵²/2⁵⁴ bounds), pasta_curves keeps every element
STRICTLY REDUCED: each op ends with a conditional subtraction of p.
* `Fe.exists_limbs` — the destructuring device every proof starts with.
RUST ANALOG: src/fields/fp.rs — `pub struct Fp(pub(crate) [u64; 4])`,
invariant documented at the type: "little-endian bit order; values are
always in Montgomery form aR mod p, with the reduced representative".
Imports: gen/PallasFp (the transpiled code), Proofs/PPallas (primality).
Imported by: every other proof file.
────────────────────────────────────────────────────────────────────────────── -/
import PallasFp.Funs
import Proofs.PPallas
open Aeneas Aeneas.Std Result
open pasta_curves
namespace PastaProofs
/-- The Pallas base-field modulus
p = 2²⁵⁴ + 45560315531419706090280762371685220353. -/
def P : := 28948022309329048855892746252171976963363056481941560715954676764349967630337
theorem P_prime : Nat.Prime P := pallas_prime
instance : Fact (Nat.Prime P) := ⟨P_prime⟩
/-- 𝔽_p as mathlib's `ZMod P` — a `Field` because `P` is prime. -/
abbrev Fp := ZMod P
/-- The transpiled element type: 4 little-endian u64 limbs. -/
abbrev Fe := fields.fp.Fp
/-- Exact value of 4 little-endian u64 limbs. -/
def limbsVal (a0 a1 a2 a3 : U64) : :=
a0.val + 2^64 * a1.val + 2^128 * a2.val + 2^192 * a3.val
/-- Exact value of an `Fe`. -/
def feVal (a : Fe) : :=
match (↑a : List U64) with
| [a0, a1, a2, a3] => limbsVal a0 a1 a2 a3
| _ => 0
/-- Every `Fe` IS four named u64 limbs. -/
theorem Fe.exists_limbs (a : Fe) :
∃ a0 a1 a2 a3 : U64, (↑a : List U64) = [a0, a1, a2, a3] := by
obtain ⟨l, hl⟩ := a
match l, hl with
| [a0, a1, a2, a3], _ => exact ⟨a0, a1, a2, a3, rfl⟩
/-- Once limbs are named, `feVal` unfolds to the polynomial. -/
@[simp]
theorem feVal_eq (a : Fe) (a0 a1 a2 a3 : U64)
(h : (↑a : List U64) = [a0, a1, a2, a3]) :
feVal a = limbsVal a0 a1 a2 a3 := by
unfold feVal; rw [h]
/-- feVal of a literal `Array.make` — the form the generated code produces
(the length side condition `h` is quantified so simp matches any proof). -/
@[simp]
theorem feVal_make (a0 a1 a2 a3 : U64) (h) :
feVal (Array.make 4#usize [a0, a1, a2, a3] h) = limbsVal a0 a1 a2 a3 := rfl
/-- Any `Fe` value is < 2²⁵⁶ (four u64 limbs). -/
theorem feVal_lt (a : Fe) : feVal a < 2^256 := by
obtain ⟨a0, a1, a2, a3, hl⟩ := Fe.exists_limbs a
rw [feVal_eq a a0 a1 a2 a3 hl]
unfold limbsVal
scalar_tac
/-- The representation invariant: strictly reduced (value below the modulus).
Every constructor/operation of the crate maintains this. -/
def Canon (a : Fe) : Prop := feVal a < P
/-- The Montgomery factor. -/
def R : := 2^256
/-- P is odd (in particular ≠ 2), so 2 — hence R = 2²⁵⁶ — is a unit mod P. -/
theorem two_ne_zero_fp : (2 : Fp) ≠ 0 := by
intro h
have h2 : ((2 : ) : Fp).val = 2 :=
ZMod.val_cast_of_lt (by norm_num [P])
rw [show ((2:):Fp) = (2:Fp) by push_cast; ring, h, ZMod.val_zero] at h2
norm_num at h2
theorem R_ne_zero : (R : Fp) ≠ 0 := by
have hR : (R : Fp) = (2 : Fp)^256 := by unfold R; push_cast; ring
rw [hR]
exact pow_ne_zero 256 two_ne_zero_fp
/-- R⁻¹ in 𝔽_p (field inverse; noncomputable, spec-level only). -/
noncomputable def Rinv : Fp := (R : Fp)⁻¹
theorem R_mul_Rinv : (R : Fp) * Rinv = 1 :=
mul_inv_cancel₀ R_ne_zero
theorem Rinv_mul_R : Rinv * (R : Fp) = 1 := by
rw [mul_comm]; exact R_mul_Rinv
theorem Rinv_ne_zero : Rinv ≠ 0 := by
intro h
have := R_mul_Rinv
rw [h, mul_zero] at this
exact one_ne_zero this.symm
/-- THE DENOTATION: machine limbs ↦ 𝔽_p, absorbing the Montgomery factor. -/
noncomputable def denote (a : Fe) : Fp := (feVal a : Fp) * Rinv
notation "⟪" a "⟫" => denote a
/-- Two canonical representatives with equal denotation are limb-identical
in value: ⟪·⟫ is injective on `Canon`. -/
theorem denote_inj (a b : Fe) (ha : Canon a) (hb : Canon b)
(h : ⟪a⟫ = ⟪b⟫) : feVal a = feVal b := by
unfold denote at h
have h' : (feVal a : Fp) = (feVal b : Fp) :=
mul_right_cancel₀ Rinv_ne_zero h
have := (ZMod.natCast_eq_natCast_iff' (feVal a) (feVal b) P).mp h'
unfold Canon at ha hb
rwa [Nat.mod_eq_of_lt ha, Nat.mod_eq_of_lt hb] at this
/-- Congruence mod P transfers to equal denotations. -/
theorem denote_eq_of_feVal_congr (a b : Fe)
(h : feVal a % P = feVal b % P) : ⟪a⟫ = ⟪b⟫ := by
unfold denote
congr 1
exact (ZMod.natCast_eq_natCast_iff' _ _ _).mpr h
end PastaProofs

View file

@ -0,0 +1,104 @@
/- ──────────────────────────────────────────────────────────────────────────────
Proofs/HelperSpecs.lean — exact specs for the u64 carry primitives
adc / sbb / mac (src/arithmetic/fields.rs), TRANSPILED TRANSPARENTLY.
These three ~5-line const fns are the atoms of every Pallas field op:
* adc a b c = (lo, hi) with lo + 2⁶⁴·hi = a + b + c (exact )
* mac a b c d = (lo, hi) with lo + 2⁶⁴·hi = a + b·c + d (exact )
* sbb a b bor = (d, bor') with d + b + ⌊bor/2⁶³⌋ = a + 2⁶⁴·β'
where bor' ∈ {0, 2⁶⁴1} and β' = (bor' ≠ 0) (exact )
(sbb consumes only the TOP BIT of the incoming borrow word and produces
an all-ones/all-zeros borrow word — exactly the Rust convention:
`let (_, borrow) = sbb(..)` then `mask & borrow` and `borrow >> 63`.)
The u128 intermediates cannot overflow: a + b + c ≤ 3·(2⁶⁴1) < 2¹²⁸ and
a + b·c + d ≤ (2⁶⁴1) + (2⁶⁴1)² + (2⁶⁴1) < 2¹²⁸ — proved, not assumed.
Every lemma is `@[step]`-registered so the op proofs consume adc/sbb/mac
calls in one `let*` step each.
────────────────────────────────────────────────────────────────────────────── -/
import Proofs.Denote
open Aeneas Aeneas.Std Result
open pasta_curves
set_option maxHeartbeats 4000000
namespace PastaProofs
open Aeneas.Std.WP
/-- Generic step rule for `lift` of a pure computation: the result IS the
expression (the @[simp] val-lemmas of the Aeneas library then evaluate it). -/
@[step]
theorem lift_spec {α : Type u} (x : α) : lift x ⦃ y => y = x ⦄ := by
simp [lift]
/-- `x ||| y = 0` forces both to be zero (bitwise). -/
theorem nat_or_eq_zero {x y : } (h : x ||| y = 0) : x = 0 ∧ y = 0 := by
constructor <;> {
apply Nat.eq_of_testBit_eq
intro i
have := congrArg (fun n => n.testBit i) h
simp [Nat.testBit_or] at this
simp [this]
}
/-- Discharge tactic shared by the steps (same as the ed25519 repos). -/
macro "dis" : tactic =>
`(tactic| (subst_vars; try simp [Array.set_val_eq, *]; try scalar_tac))
/-- `adc a b carry = (lo, hi)` with `lo + 2⁶⁴·hi = a + b + carry` (exact). -/
@[step]
theorem adc_spec (a b c : U64) :
arithmetic.fields.adc a b c
⦃ p => p.1.val + 2^64 * p.2.val = a.val + b.val + c.val ∧
p.2.val ≤ 2 ⦄ := by
unfold arithmetic.fields.adc
have ha : a.val < 2^64 := by scalar_tac
have hb : b.val < 2^64 := by scalar_tac
have hc : c.val < 2^64 := by scalar_tac
step* by dis
-- lo = (a+b+c) mod 2⁶⁴, hi = (a+b+c) / 2⁶⁴: exact split of a 128-bit sum
simp_all [UScalar.cast_val_eq, Nat.shiftRight_eq_div_pow]
omega
/-- `mac a b c carry = (lo, hi)` with `lo + 2⁶⁴·hi = a + b·c + carry` (exact). -/
@[step]
theorem mac_spec (a b c d : U64) :
arithmetic.fields.mac a b c d
⦃ p => p.1.val + 2^64 * p.2.val = a.val + b.val * c.val + d.val ⦄ := by
unfold arithmetic.fields.mac
have ha : a.val < 2^64 := by scalar_tac
have hb : b.val < 2^64 := by scalar_tac
have hc : c.val < 2^64 := by scalar_tac
have hd : d.val < 2^64 := by scalar_tac
have hbc : b.val * c.val ≤ (2^64-1) * (2^64-1) :=
Nat.mul_le_mul (by omega) (by omega)
step* by dis
simp_all [UScalar.cast_val_eq, Nat.shiftRight_eq_div_pow]
omega
/-- `sbb a b borrow = (d, borrow')`:
* only the top bit β = ⌊borrow/2⁶³⌋ of the incoming borrow is consumed;
* `d + b + β = a + 2⁶⁴·β'` exactly, where β' ∈ {0,1} flags the borrow-out;
* the outgoing borrow WORD is 0 or all-ones (β' spread over 64 bits) —
the shape `mask & borrow` arithmetic downstream depends on. -/
@[step]
theorem sbb_spec (a b bor : U64) :
arithmetic.fields.sbb a b bor
⦃ p => (p.2.val = 0 ∧ p.1.val + b.val + bor.val / 2^63 = a.val)
(p.2.val = 2^64 - 1 ∧
p.1.val + b.val + bor.val / 2^63 = a.val + 2^64) ⦄ := by
unfold arithmetic.fields.sbb
have ha : a.val < 2^64 := by scalar_tac
have hb : b.val < 2^64 := by scalar_tac
have hbor : bor.val < 2^64 := by scalar_tac
have hβ : bor.val / 2^63 ≤ 1 := by omega
step* by dis
-- the wrapping u128 subtraction: ret = (a b β) mod 2¹²⁸;
-- d = ret mod 2⁶⁴, borrow' = (ret >>> 64) mod 2⁶⁴
simp_all [UScalar.cast_val_eq, Nat.shiftRight_eq_div_pow,
UScalar.size, U128.size, U64.size, U128.numBits_def, U64.numBits_def]
omega
end PastaProofs

View file

@ -0,0 +1,415 @@
/-
═══════════════════════════════════════════════════════════════════════════════
Proofs/PPallas.lean — primality of the Pallas (Pasta) base-field modulus
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
═══════════════════════════════════════════════════════════════════════════════
WHAT THIS FILE PROVES
`pallas_prime : Nat.Prime P` where P is the 255-bit modulus of the Pallas
curve base field F_p. Axiom-free Lucas/Pratt certificate.
CERTIFICATE TREE (p1 factorization, leaves first)
p 1 = 2³² · 3 · 463 · f1 · f2
where f1 = 539204044132271846773 (69 bits)
f2 = 8999194758858563409123804352480028797519453 (143 bits)
f1 1 = 2² · 3⁵ · 89 · 14923 · 417677162933
f2 1 = 2² · 3⁴ · 11 · 2531 · 115603 · 1197907 · 22160661629 · 325086459374267
Sub-leaves (all norm_num-certifiable):
417677162933 1 = 2² · 59 · 1973 · 897019
22160661629 1 = 2² · 7 · 19 · 41655379
14923 1 = 2 · 3² · 829
115603 1 = 2 · 3 · 19267
1197907 1 = 2 · 3 · 53 · 3767
325086459374267 1 = 2 · 509 · 413527 · 772231
463 1 = 2 · 3 · 7 · 11
2531 1 = 2 · 5 · 11 · 23
-/
import Mathlib.NumberTheory.LucasPrimality
import Mathlib.Data.ZMod.Basic
import Mathlib.Tactic.NormNum.Prime
set_option maxHeartbeats 8000000
set_option maxRecDepth 8000
namespace PPallas
-- ═════════════════════════════════════════════════════════════════════════════
-- Kernel-checkable modular exponentiation
-- ═════════════════════════════════════════════════════════════════════════════
/-- Fuel-based binary modular exponentiation, kernel-reducible (GMP-fast `decide`).
MATH (for sufficient fuel; made precise by `powModAux_eq`):
`powModAux fuel a k n = a^k mod n`.
Algorithm: square-and-multiply on binary digits of k. -/
def powModAux : Nat → Nat → Nat → Nat → Nat
| 0, _, _, n => 1 % n
| fuel + 1, a, k, n =>
if k = 0 then 1 % n
else if k % 2 = 1 then powModAux fuel (a * a % n) (k / 2) n * a % n
else powModAux fuel (a * a % n) (k / 2) n
/- Correctness of powModAux. k < 2^fuel ⇒ powModAux fuel a k n = a^k % n -/
theorem powModAux_eq : ∀ (fuel a k n : ), k < 2 ^ fuel → powModAux fuel a k n = a ^ k % n := by
intro fuel
induction fuel with
| zero =>
intro a k n hk
rw [pow_zero] at hk
have hk0 : k = 0 := by omega
subst hk0
simp [powModAux]
| succ f ih =>
intro a k n hk
by_cases hk0 : k = 0
· subst hk0; simp [powModAux]
· have hk2 : k / 2 < 2 ^ f := by
rw [pow_succ] at hk
omega
have hrec := ih (a * a % n) (k / 2) n hk2
have haa : a * a = a ^ 2 := (pow_two a).symm
simp only [powModAux, if_neg hk0]
by_cases hodd : k % 2 = 1
· rw [if_pos hodd, hrec, ← Nat.pow_mod, Nat.mod_mul_mod, haa, ← pow_mul, ← pow_succ,
show 2 * (k / 2) + 1 = k by omega]
· rw [if_neg hodd, hrec, ← Nat.pow_mod, haa, ← pow_mul,
show 2 * (k / 2) = k by omega]
/-- powMod a k n = a^k % n for all k < 2^256. Fuel fixed at 256 — enough for
all exponents in the certificate (n ≤ p < 2^255). -/
def powMod (a k n : ) : := powModAux 256 a k n
theorem cast_pow_eq (a k n : ) (hk : k < 2 ^ 256) :
(a : ZMod n) ^ k = ((powMod a k n : ) : ZMod n) := by
rw [powMod, powModAux_eq 256 a k n hk, ZMod.natCast_mod, Nat.cast_pow]
theorem pow_eq_one_of_powMod (a k n : ) (hk : k < 2 ^ 256) (h : powMod a k n = 1) :
(a : ZMod n) ^ k = 1 := by
rw [cast_pow_eq a k n hk, h, Nat.cast_one]
theorem pow_ne_one_of_powMod (a k n : ) (hk : k < 2 ^ 256) (hn : 1 < n)
(h1 : powMod a k n ≠ 1) (h2 : powMod a k n < n) :
(a : ZMod n) ^ k ≠ 1 := by
rw [cast_pow_eq a k n hk]
intro hcon
rw [show (1 : ZMod n) = ((1 : ) : ZMod n) by rw [Nat.cast_one],
ZMod.natCast_eq_natCast_iff'] at hcon
rw [Nat.mod_eq_of_lt h2, Nat.mod_eq_of_lt hn] at hcon
exact h1 hcon
-- ═════════════════════════════════════════════════════════════════════════════
-- The certificate chain (leaves first, building up to the root)
-- ═════════════════════════════════════════════════════════════════════════════
/-- Leaf: 14923 is prime. Witness g = 2. 149231 = 2 · 3² · 829 -/
theorem prime_14923 : Nat.Prime 14923 := by
refine lucas_primality 14923 ((2 : ) : ZMod 14923) ?_ ?_
· exact pow_eq_one_of_powMod 2 (14923 - 1) 14923 (by decide) (by decide)
· intro q hq hqd
have hfac : (14923 : ) - 1 = 2 * (3 ^ 2 * (829)) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((14923 - 1) / 2) 14923 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 2 ((14923 - 1) / 3) 14923 (by decide) (by decide) (by decide) (by decide)
have he : q = 829 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 2 ((14923 - 1) / 829) 14923 (by decide) (by decide) (by decide) (by decide)
/-- Leaf: 115603 is prime. Witness g = 2. 1156031 = 2 · 3 · 19267 -/
theorem prime_115603 : Nat.Prime 115603 := by
refine lucas_primality 115603 ((2 : ) : ZMod 115603) ?_ ?_
· exact pow_eq_one_of_powMod 2 (115603 - 1) 115603 (by decide) (by decide)
· intro q hq hqd
have hfac : (115603 : ) - 1 = 2 * (3 * (19267)) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((115603 - 1) / 2) 115603 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((115603 - 1) / 3) 115603 (by decide) (by decide) (by decide) (by decide)
have he : q = 19267 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 2 ((115603 - 1) / 19267) 115603 (by decide) (by decide) (by decide) (by decide)
/-- Leaf: 1197907 is prime. Witness g = 3. 11979071 = 2 · 3 · 53 · 3767 -/
theorem prime_1197907 : Nat.Prime 1197907 := by
refine lucas_primality 1197907 ((3 : ) : ZMod 1197907) ?_ ?_
· exact pow_eq_one_of_powMod 3 (1197907 - 1) 1197907 (by decide) (by decide)
· intro q hq hqd
have hfac : (1197907 : ) - 1 = 2 * (3 * (53 * (3767))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((1197907 - 1) / 2) 1197907 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((1197907 - 1) / 3) 1197907 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 53 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((1197907 - 1) / 53) 1197907 (by decide) (by decide) (by decide) (by decide)
have he : q = 3767 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 3 ((1197907 - 1) / 3767) 1197907 (by decide) (by decide) (by decide) (by decide)
/-- Leaf: 463 is prime. Witness g = 3. 4631 = 2 · 3 · 7 · 11 -/
theorem prime_463 : Nat.Prime 463 := by
refine lucas_primality 463 ((3 : ) : ZMod 463) ?_ ?_
· exact pow_eq_one_of_powMod 3 (463 - 1) 463 (by decide) (by decide)
· intro q hq hqd
have hfac : (463 : ) - 1 = 2 * (3 * (7 * (11))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((463 - 1) / 2) 463 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((463 - 1) / 3) 463 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 7 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((463 - 1) / 7) 463 (by decide) (by decide) (by decide) (by decide)
have he : q = 11 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 3 ((463 - 1) / 11) 463 (by decide) (by decide) (by decide) (by decide)
/-- Leaf: 2531 is prime. Witness g = 2. 25311 = 2 · 5 · 11 · 23 -/
theorem prime_2531 : Nat.Prime 2531 := by
refine lucas_primality 2531 ((2 : ) : ZMod 2531) ?_ ?_
· exact pow_eq_one_of_powMod 2 (2531 - 1) 2531 (by decide) (by decide)
· intro q hq hqd
have hfac : (2531 : ) - 1 = 2 * (5 * (11 * (23))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((2531 - 1) / 2) 2531 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 5 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((2531 - 1) / 5) 2531 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 11 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((2531 - 1) / 11) 2531 (by decide) (by decide) (by decide) (by decide)
have he : q = 23 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 2 ((2531 - 1) / 23) 2531 (by decide) (by decide) (by decide) (by decide)
/-- Node: 417677162933 is prime. Witness g = 2.
4176771629331 = 2² · 59 · 1973 · 897019 -/
theorem prime_417677162933 : Nat.Prime 417677162933 := by
refine lucas_primality 417677162933 ((2 : ) : ZMod 417677162933) ?_ ?_
· exact pow_eq_one_of_powMod 2 (417677162933 - 1) 417677162933 (by decide) (by decide)
· intro q hq hqd
have hfac : (417677162933 : ) - 1 = 2 ^ 2 * (59 * (1973 * (897019))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 2 ((417677162933 - 1) / 2) 417677162933 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 59 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((417677162933 - 1) / 59) 417677162933 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 1973 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((417677162933 - 1) / 1973) 417677162933 (by decide) (by decide) (by decide) (by decide)
have he : q = 897019 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 2 ((417677162933 - 1) / 897019) 417677162933 (by decide) (by decide) (by decide) (by decide)
/-- Node: 22160661629 is prime. Witness g = 3.
221606616291 = 2² · 7 · 19 · 41655379 -/
theorem prime_22160661629 : Nat.Prime 22160661629 := by
refine lucas_primality 22160661629 ((3 : ) : ZMod 22160661629) ?_ ?_
· exact pow_eq_one_of_powMod 3 (22160661629 - 1) 22160661629 (by decide) (by decide)
· intro q hq hqd
have hfac : (22160661629 : ) - 1 = 2 ^ 2 * (7 * (19 * (41655379))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 3 ((22160661629 - 1) / 2) 22160661629 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 7 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((22160661629 - 1) / 7) 22160661629 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 19 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 3 ((22160661629 - 1) / 19) 22160661629 (by decide) (by decide) (by decide) (by decide)
have he : q = 41655379 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 3 ((22160661629 - 1) / 41655379) 22160661629 (by decide) (by decide) (by decide) (by decide)
/-- Node: 325086459374267 is prime. Witness g = 2.
3250864593742671 = 2 · 509 · 413527 · 772231 -/
theorem prime_325086459374267 : Nat.Prime 325086459374267 := by
refine lucas_primality 325086459374267 ((2 : ) : ZMod 325086459374267) ?_ ?_
· exact pow_eq_one_of_powMod 2 (325086459374267 - 1) 325086459374267 (by decide) (by decide)
· intro q hq hqd
have hfac : (325086459374267 : ) - 1 = 2 * (509 * (413527 * (772231))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((325086459374267 - 1) / 2) 325086459374267 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 509 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((325086459374267 - 1) / 509) 325086459374267 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 413527 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((325086459374267 - 1) / 413527) 325086459374267 (by decide) (by decide) (by decide) (by decide)
have he : q = 772231 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
subst he
exact pow_ne_one_of_powMod 2 ((325086459374267 - 1) / 772231) 325086459374267 (by decide) (by decide) (by decide) (by decide)
/-- Node f1 = 539204044132271846773 (69 bits). Witness g = 5.
f11 = 2² · 3⁵ · 89 · 14923 · 417677162933
Recursive: 14923 and 417677162933 certified above. -/
theorem prime_539204044132271846773 : Nat.Prime 539204044132271846773 := by
refine lucas_primality 539204044132271846773 ((5 : ) : ZMod 539204044132271846773) ?_ ?_
· exact pow_eq_one_of_powMod 5 (539204044132271846773 - 1) 539204044132271846773 (by decide) (by decide)
· intro q hq hqd
have hfac : (539204044132271846773 : ) - 1 = 2 ^ 2 * (3 ^ 5 * (89 * (14923 * (417677162933)))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 5 ((539204044132271846773 - 1) / 2) 539204044132271846773 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 5 ((539204044132271846773 - 1) / 3) 539204044132271846773 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 89 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 5 ((539204044132271846773 - 1) / 89) 539204044132271846773 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 14923 := (Nat.prime_dvd_prime_iff_eq hq prime_14923).mp h
subst he
exact pow_ne_one_of_powMod 5 ((539204044132271846773 - 1) / 14923) 539204044132271846773 (by decide) (by decide) (by decide) (by decide)
have he : q = 417677162933 := (Nat.prime_dvd_prime_iff_eq hq prime_417677162933).mp hqd
subst he
exact pow_ne_one_of_powMod 5 ((539204044132271846773 - 1) / 417677162933) 539204044132271846773 (by decide) (by decide) (by decide) (by decide)
/-- Node f2 = 8999194758858563409123804352480028797519453 (143 bits). Witness g = 2.
f21 = 2² · 3⁴ · 11 · 2531 · 115603 · 1197907 · 22160661629 · 325086459374267
Recursive: large factors certified above. -/
theorem prime_8999194758858563409123804352480028797519453 : Nat.Prime 8999194758858563409123804352480028797519453 := by
refine lucas_primality 8999194758858563409123804352480028797519453 ((2 : ) : ZMod 8999194758858563409123804352480028797519453) ?_ ?_
· exact pow_eq_one_of_powMod 2 (8999194758858563409123804352480028797519453 - 1) 8999194758858563409123804352480028797519453 (by decide) (by decide)
· intro q hq hqd
have hfac : (8999194758858563409123804352480028797519453 : ) - 1 =
2 ^ 2 * (3 ^ 4 * (11 * (2531 * (115603 * (1197907 * (22160661629 * (325086459374267))))))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 2) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 3) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 11 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 11) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2531 := (Nat.prime_dvd_prime_iff_eq hq prime_2531).mp h
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 2531) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 115603 := (Nat.prime_dvd_prime_iff_eq hq prime_115603).mp h
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 115603) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 1197907 := (Nat.prime_dvd_prime_iff_eq hq prime_1197907).mp h
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 1197907) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 22160661629 := (Nat.prime_dvd_prime_iff_eq hq prime_22160661629).mp h
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 22160661629) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
have he : q = 325086459374267 := (Nat.prime_dvd_prime_iff_eq hq prime_325086459374267).mp hqd
subst he
exact pow_ne_one_of_powMod 2 ((8999194758858563409123804352480028797519453 - 1) / 325086459374267) 8999194758858563409123804352480028797519453 (by decide) (by decide) (by decide) (by decide)
/-- ROOT: Pallas base-field modulus P is prime. Witness g = 5.
P1 = 2³² · 3 · 463 · f1 · f2
with f1, f2 certified recursively above. -/
theorem prime_Pallas : Nat.Prime 28948022309329048855892746252171976963363056481941560715954676764349967630337 := by
refine lucas_primality 28948022309329048855892746252171976963363056481941560715954676764349967630337
((5 : ) : ZMod 28948022309329048855892746252171976963363056481941560715954676764349967630337) ?_ ?_
· exact pow_eq_one_of_powMod 5
(28948022309329048855892746252171976963363056481941560715954676764349967630337 - 1)
28948022309329048855892746252171976963363056481941560715954676764349967630337
(by decide) (by decide)
· intro q hq hqd
have hfac : (28948022309329048855892746252171976963363056481941560715954676764349967630337 : ) - 1 =
2 ^ 32 * (3 * (463 * (539204044132271846773 * (8999194758858563409123804352480028797519453)))) := by decide
rw [hfac] at hqd
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
subst he
exact pow_ne_one_of_powMod 5
((28948022309329048855892746252171976963363056481941560715954676764349967630337 - 1) / 2)
28948022309329048855892746252171976963363056481941560715954676764349967630337
(by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
subst he
exact pow_ne_one_of_powMod 5
((28948022309329048855892746252171976963363056481941560715954676764349967630337 - 1) / 3)
28948022309329048855892746252171976963363056481941560715954676764349967630337
(by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 463 := (Nat.prime_dvd_prime_iff_eq hq prime_463).mp h
subst he
exact pow_ne_one_of_powMod 5
((28948022309329048855892746252171976963363056481941560715954676764349967630337 - 1) / 463)
28948022309329048855892746252171976963363056481941560715954676764349967630337
(by decide) (by decide) (by decide) (by decide)
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
· have he : q = 539204044132271846773 := (Nat.prime_dvd_prime_iff_eq hq prime_539204044132271846773).mp h
subst he
exact pow_ne_one_of_powMod 5
((28948022309329048855892746252171976963363056481941560715954676764349967630337 - 1) / 539204044132271846773)
28948022309329048855892746252171976963363056481941560715954676764349967630337
(by decide) (by decide) (by decide) (by decide)
have he : q = 8999194758858563409123804352480028797519453 :=
(Nat.prime_dvd_prime_iff_eq hq prime_8999194758858563409123804352480028797519453).mp hqd
subst he
exact pow_ne_one_of_powMod 5
((28948022309329048855892746252171976963363056481941560715954676764349967630337 - 1) / 8999194758858563409123804352480028797519453)
28948022309329048855892746252171976963363056481941560715954676764349967630337
(by decide) (by decide) (by decide) (by decide)
end PPallas
-- ═════════════════════════════════════════════════════════════════════════════
-- Exported result
-- ═════════════════════════════════════════════════════════════════════════════
/-- The Pallas curve base field modulus is prime.
This is the only theorem from this file used downstream. -/
theorem pallas_prime : Nat.Prime 28948022309329048855892746252171976963363056481941560715954676764349967630337 :=
PPallas.prime_Pallas

View file

@ -0,0 +1,243 @@
/- ──────────────────────────────────────────────────────────────────────────────
Proofs/SubNegSpec.lean — subtraction and negation of the transpiled Fp.
RUST ANALOG (src/fields/fp.rs):
* `Fp::sub` (fp.rs:374-388): 4-limb sbb chain, then a conditional add-back
of the modulus masked by the final borrow word (`MODULUS.0[i] & borrow`).
* `Fp::neg` (fp.rs:405-...): computes p a by a 4-limb sbb chain, then
zeroes the result iff a = 0 (the `mask = ((a≠0) as u64)` trick).
THE SUB SPEC IS DELIBERATELY MORE GENERAL THAN Canon × Canon:
hypotheses feVal b ≤ P and feVal a < feVal b + P
conclusion Canon r ∧ (r + b = a r + b = a + P) (exact )
This covers the two call shapes in the crate:
* canonical x, y (x < P ≤ y + P): field subtraction;
* `sub t MODULUS` with t < 2P: the final conditional reduction of
`add` and `montgomery_reduce` (t ≥ P → t P; t < P → borrow, add-back
gives t itself).
The additive phrasing avoids -subtraction entirely; casting to 𝔽_p kills
the +P branch ((P : 𝔽_p) = 0), giving ⟪r⟫ = ⟪a⟫ ⟪b⟫.
Imports: Proofs/HelperSpecs (adc/sbb/mac atoms).
Imported by: AddSpec (add = adc chain ∘ sub · MODULUS), ReduceSpec
(montgomery_reduce ends with the same call), ConstSpecs, FieldMain.
────────────────────────────────────────────────────────────────────────────── -/
import Proofs.HelperSpecs
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))
/-- The transpiled MODULUS constant, as a limb list. -/
theorem MODULUS_limbs :
(↑fields.fp.MODULUS : List U64) =
[11037532056220336129#u64, 2469829653914515739#u64, 0#u64,
4611686018427387904#u64] := by
unfold fields.fp.MODULUS
rfl
/-- Its exact value is the Pallas prime. -/
theorem feVal_MODULUS : feVal fields.fp.MODULUS = P := by
rw [feVal_eq _ _ _ _ _ MODULUS_limbs]
unfold limbsVal P
norm_num
/-- `Fp::sub`: exact two-case value identity + canonicity (see file header). -/
theorem sub_spec (a b : Fe) (hbP : feVal b ≤ P) (hab : feVal a < feVal b + P) :
fields.fp.Fp.sub a b
⦃ r => Canon r ∧
(feVal r + feVal b = feVal a
feVal r + feVal b = feVal a + P) ⦄ := by
obtain ⟨a0, a1, a2, a3, hla⟩ := Fe.exists_limbs a
obtain ⟨b0, b1, b2, b3, hlb⟩ := Fe.exists_limbs b
rw [feVal_eq b b0 b1 b2 b3 hlb] at hbP
rw [feVal_eq a a0 a1 a2 a3 hla, feVal_eq b b0 b1 b2 b3 hlb] at hab
unfold fields.fp.Fp.sub
-- ── limb reads + the 4-step sbb chain ────────────────────────────────────
let* ⟨ i, hi ⟩ ← Array.index_usize_spec by dis
let* ⟨ i1, hi1 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d0, borrow0, hsb0 ⟩ ← sbb_spec by dis
let* ⟨ i2, hi2 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i3, hi3 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d1, borrow1, hsb1 ⟩ ← sbb_spec by dis
let* ⟨ i4, hi4 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i5, hi5 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d2, borrow2, hsb2 ⟩ ← sbb_spec by dis
let* ⟨ i6, hi6 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i7, hi7 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d3, borrow3, hsb3 ⟩ ← sbb_spec by dis
-- ── conditional add-back: (MODULUS[i] & borrow) + adc chain ──────────────
let* ⟨ i8, hi8 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i9, hi9, hi9bv ⟩ ← UScalar.and_spec by dis
let* ⟨ d01, carry0, hadc0 ⟩ ← adc_spec by dis
let* ⟨ i10, hi10 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i11, hi11, hi11bv ⟩ ← UScalar.and_spec by dis
let* ⟨ d11, carry1, hadc1 ⟩ ← adc_spec by dis
let* ⟨ i12, hi12 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i13, hi13, hi13bv ⟩ ← UScalar.and_spec by dis
let* ⟨ d21, carry2, hadc2 ⟩ ← adc_spec by dis
let* ⟨ i14, hi14 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i15, hi15, hi15bv ⟩ ← UScalar.and_spec by dis
let* ⟨ d31, carry3, hadc3 ⟩ ← adc_spec by dis
-- ── assemble ─────────────────────────────────────────────────────────────
-- identify the reads with the named limbs / MODULUS literals
-- val-level identifications of the reads (omega links through these)
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 hv_i8 : i8.val = 11037532056220336129 := by simp [hi8, MODULUS_limbs]
have hv_i10 : i10.val = 2469829653914515739 := by simp [hi10, MODULUS_limbs]
have hv_i12 : i12.val = 0 := by simp [hi12, MODULUS_limbs]
have hv_i14 : i14.val = 4611686018427387904 := by simp [hi14, MODULUS_limbs]
-- expose the -level land in the mask equations
simp only [UScalar.val_and, hv_i8, hv_i10, hv_i12, hv_i14] at hi9 hi11 hi13 hi15
-- limb bounds (make everything linear for omega)
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
have hb_d01 : d01.val < 2^64 := by scalar_tac
have hb_d11 : d11.val < 2^64 := by scalar_tac
have hb_d21 : d21.val < 2^64 := by scalar_tac
have hb_d31 : d31.val < 2^64 := by scalar_tac
have hb_a0 : a0.val < 2^64 := by scalar_tac
have hb_a1 : a1.val < 2^64 := by scalar_tac
have hb_a2 : a2.val < 2^64 := by scalar_tac
have hb_a3 : a3.val < 2^64 := by scalar_tac
have hb_b0 : b0.val < 2^64 := by scalar_tac
have hb_b1 : b1.val < 2^64 := by scalar_tac
have hb_b2 : b2.val < 2^64 := by scalar_tac
have hb_b3 : b3.val < 2^64 := by scalar_tac
-- resolve the mask values in the two borrow3 cases
rcases hsb3 with ⟨hbor3, hval3⟩ | ⟨hbor3, hval3⟩ <;>
[ (simp only [hbor3, Nat.and_zero] at hi9 hi11 hi13 hi15);
(simp only [hbor3, Nat.and_two_pow_sub_one_eq_mod] at hi9 hi11 hi13 hi15;
norm_num at hi9 hi11 hi13 hi15) ] <;>
· rw [feVal_eq a a0 a1 a2 a3 hla, feVal_eq b b0 b1 b2 b3 hlb]
constructor
· -- Canon: feVal r < P
unfold Canon
simp only [feVal_make]
unfold limbsVal P at *
trace_state
omega
· -- the two-case value identity
simp only [feVal_make]
unfold limbsVal P at *
omega
/-- `Fp::neg`: total, canonical, and denotes ⟪a⟫ (for canonical input). -/
theorem neg_spec (a : Fe) (ha : Canon a) :
fields.fp.Fp.neg a
⦃ r => Canon r ∧
(feVal r + feVal a = P (feVal r = 0 ∧ feVal a = 0)) ⦄ := by
obtain ⟨a0, a1, a2, a3, hla⟩ := Fe.exists_limbs a
unfold Canon at ha
rw [feVal_eq a a0 a1 a2 a3 hla] at ha
unfold fields.fp.Fp.neg
let* ⟨ i, hi ⟩ ← Array.index_usize_spec by dis
let* ⟨ i1, hi1 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d0, borrow0, hsb0 ⟩ ← sbb_spec by dis
let* ⟨ i2, hi2 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i3, hi3 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d1, borrow1, hsb1 ⟩ ← sbb_spec by dis
let* ⟨ i4, hi4 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i5, hi5 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d2, borrow2, hsb2 ⟩ ← sbb_spec by dis
let* ⟨ i6, hi6 ⟩ ← Array.index_usize_spec by dis
let* ⟨ i7, hi7 ⟩ ← Array.index_usize_spec by dis
let* ⟨ d3, borrow3, hsb3 ⟩ ← sbb_spec by dis
-- the is-zero test: i8 = a0 ||| a1, i9 = i8 ||| a2, i10 = i9 ||| a3
let* ⟨ i8, hi8, hi8bv ⟩ ← UScalar.or_spec by dis
let* ⟨ i9, hi9, hi9bv ⟩ ← UScalar.or_spec by dis
let* ⟨ i10, hi10, hi10bv ⟩ ← UScalar.or_spec by dis
let* ⟨ i11, hi11 ⟩ ← lift_spec by dis
let* ⟨ mask, hmask ⟩ ← lift_spec by dis
let* ⟨ i12, hi12, hi12bv ⟩ ← UScalar.and_spec by dis
let* ⟨ i13, hi13, hi13bv ⟩ ← UScalar.and_spec by dis
let* ⟨ i14, hi14, hi14bv ⟩ ← UScalar.and_spec by dis
let* ⟨ i15, hi15, hi15bv ⟩ ← UScalar.and_spec by dis
have hv_i : i.val = 11037532056220336129 := by simp [hi, MODULUS_limbs]
have hv_i1 : i1.val = a0.val := by simp [hi1, hla]
have hv_i2 : i2.val = 2469829653914515739 := by simp [hi2, MODULUS_limbs]
have hv_i3 : i3.val = a1.val := by simp [hi3, hla]
have hv_i4 : i4.val = 0 := by simp [hi4, MODULUS_limbs]
have hv_i5 : i5.val = a2.val := by simp [hi5, hla]
have hv_i6 : i6.val = 4611686018427387904 := by simp [hi6, MODULUS_limbs]
have hv_i7 : i7.val = a3.val := by simp [hi7, hla]
simp only [UScalar.val_or, hv_i1, hv_i3, hv_i5, hv_i7] at hi8 hi9 hi10
simp only [UScalar.val_and] at hi12 hi13 hi14 hi15
have hb_a0 : a0.val < 2^64 := by scalar_tac
have hb_a1 : a1.val < 2^64 := by scalar_tac
have hb_a2 : a2.val < 2^64 := by scalar_tac
have hb_a3 : a3.val < 2^64 := by scalar_tac
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
-- case: is the input zero?
by_cases hz : a0.val = 0 ∧ a1.val = 0 ∧ a2.val = 0 ∧ a3.val = 0
· -- a = 0: or-chain is 0, i11 = 1, mask = 0, result limbs all 0
obtain ⟨h0, h1, h2, h3⟩ := hz
have hor : i10.val = 0 := by
simp [hi10, hi9, hi8, h0, h1, h2, h3]
have hz10 : i10 = 0#u64 := by scalar_tac
have h11 : i11.val = 1 := by
subst hi11
simp [hz10]
have hm : mask.val = 0 := by
subst hmask
simp only [core.num.U64.wrapping_sub_val_eq]
simp [h11, U64.size, U64.numBits_def]
simp only [hm, Nat.and_zero] at hi12 hi13 hi14 hi15
constructor
· unfold Canon; simp only [feVal_make]; unfold limbsVal P; omega
· right
constructor
· simp only [feVal_make]; unfold limbsVal; omega
· rw [feVal_eq a a0 a1 a2 a3 hla]; unfold limbsVal; omega
· -- a ≠ 0: or-chain nonzero, i11 = 0, mask = all-ones, result = p a
have hor : i10.val ≠ 0 := by
rw [hi10, hi9, hi8]
intro hcon
apply hz
have c1 := nat_or_eq_zero hcon
have c2 := nat_or_eq_zero c1.1
have c3 := nat_or_eq_zero c2.1
exact ⟨c3.1, c3.2, c2.2, c1.2⟩
have hz10 : ¬ (i10 = 0#u64) := by scalar_tac
have h11 : i11.val = 0 := by
subst hi11
simp [hz10]
have hm : mask.val = 2^64 - 1 := by
subst hmask
simp only [core.num.U64.wrapping_sub_val_eq]
simp [h11, U64.size, U64.numBits_def]
rw [hm] at hi12 hi13 hi14 hi15
simp only [Nat.and_two_pow_sub_one_eq_mod] at hi12 hi13 hi14 hi15
rw [Nat.mod_eq_of_lt hb_d0] at hi12
rw [Nat.mod_eq_of_lt hb_d1] at hi13
rw [Nat.mod_eq_of_lt hb_d2] at hi14
rw [Nat.mod_eq_of_lt hb_d3] at hi15
constructor
· unfold Canon; simp only [feVal_make]; unfold limbsVal P at *; omega
· left
simp only [feVal_make, feVal_eq a a0 a1 a2 a3 hla]
unfold limbsVal P at *
omega
end PastaProofs

44
verification/extract.sh Executable file
View file

@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Regenerate the Lean model in gen/ from the Rust sources.
#
# SCOPE: Pallas base field 𝔽_p (src/fields/fp.rs) + the u64 helper primitives
# (src/arithmetic/fields.rs: adc/sbb/mac — translated TRANSPARENTLY,
# they are plain u128 arithmetic; no hand models).
#
# Rust --charon--> PallasFp.llbc --aeneas--> gen/PallasFp/*.lean
#
# Opaque items (documented in TRUSTED-BASE.md; all outside certificate cones):
# * trait impls needing RNG / serde / GPU / iterator machinery
# * sqrt (table-driven; out of scope for the field certificate)
#
# Usage: ./extract.sh
set -euo pipefail
source ~/aeneas-toolchain/env.sh
HERE="$(cd "$(dirname "$0")" && pwd)"
CRATE=~/GitClone/FormalVerification/sources/pasta_curves-source
echo "[1/2] charon: Rust -> LLBC (fields::fp + arithmetic helpers)"
cd "$CRATE"
charon cargo --preset=aeneas \
--start-from crate::fields::fp \
--opaque 'crate::fields::fp::_::fmt' \
--opaque 'crate::fields::fp::_::pow_by_t_minus1_over2' \
--opaque 'crate::fields::fp::_::get_lower_32' \
--opaque 'crate::fields::fp::_::ZETA' \
--opaque 'crate::fields::fp::_::from_uniform_bytes' \
--opaque 'crate::fields::fp::_::sqrt' \
--opaque 'crate::fields::fp::_::sqrt_ratio' \
--opaque 'crate::fields::fp::_::random' \
--opaque 'crate::fields::fp::_::sum' \
--opaque 'crate::fields::fp::_::product' \
--opaque 'crate::fields::fp::_::cmp' \
--opaque 'crate::fields::fp::_::partial_cmp' \
--dest-file "$HERE/PallasFp.llbc" \
-- --no-default-features
echo "[2/2] aeneas: LLBC -> Lean (split files, PallasFp.* modules)"
cd "$HERE"
aeneas -backend lean -split-files -subdir PallasFp -dest gen PallasFp.llbc
echo "Done. Now run ./check.sh to type-check the regenerated model."

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,195 @@
-- Hand-written models for external functions (derived from FunsExternal_Template.lean).
-- [pasta_curves]: external functions.
--
-- Modeling policy (same as the ed25519 repos):
-- * `subtle` items whose Rust bodies are real bit math are modeled FAITHFULLY
-- (ct_eq decides equality; select/bitand/not collapse to if-then-else /
-- boolean algebra on the documented {0,1} Choice invariant).
-- * `subtle` items whose Rust bodies are optimization barriers (black_box)
-- are semantically the identity and modeled so (Choice::from, unwrap_u8).
-- * core `as_ref`/`borrow` on arrays/references are the evident coercions.
-- * Everything else stays an AXIOM: Debug fmt, Ord/cmp, Sum/Product folds,
-- sqrt/sqrt_ratio/random and the sqrt-table helpers, ff trait defaults —
-- all deliberately opaque, all outside every certificate cone
-- (verified by the check.sh Phase-3 axiom audit).
import Aeneas
import PallasFp.Types
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
set_option maxHeartbeats 1000000
set_option maxRecDepth 2048
open pasta_curves
/-- [core::array::{impl core::convert::AsRef<[T]> for [T; N]}::as_ref]
MODEL: an array viewed as a slice — `Array.to_slice`. Needed transparently
by `pow_vartime` (`exp.as_ref()`). -/
@[rust_fun "core::array::{core::convert::AsRef<[@T; @N], [@T]>}::as_ref"]
def Array.Insts.CoreConvertAsRefSlice.as_ref
{T : Type} {N : Std.Usize} : Array T N → Result (Slice T) :=
fun a => ok a.to_slice
/-- [core::array::{impl core::convert::AsMut<[T]> for [T; N]}::as_mut]
AXIOM: not reachable from any transparent function in this extraction. -/
@[rust_fun "core::array::{core::convert::AsMut<[@T; @N], [@T]>}::as_mut"]
axiom Array.Insts.CoreConvertAsMutSlice.as_mut
{T : Type} {N : Std.Usize} :
Array T N → Result ((Slice T) × (Slice T → Array T N))
/-- [core::borrow::{impl core::borrow::Borrow<T> for T}::borrow]
MODEL: identity (Rust's blanket Borrow is `&self` — value semantics id). -/
@[rust_fun "core::borrow::{core::borrow::Borrow<@T, @T>}::borrow"]
def core.borrow.Borrow.Blanket.borrow {T : Type} : T → Result T := fun x => ok x
/-- [core::borrow::{impl core::borrow::Borrow<T> for &'_0 T}::borrow]
MODEL: identity. -/
@[rust_fun "core::borrow::{core::borrow::Borrow<&'0 @T, @T>}::borrow"]
def Shared0T.Insts.CoreBorrowBorrow.borrow {T : Type} : T → Result T := fun x => ok x
/-- [core::convert::{impl core::convert::AsRef<U> for &'_0 T}::as_ref]
MODEL: defer to the underlying instance (deref transparent). -/
@[rust_fun "core::convert::{core::convert::AsRef<&'0 @T, @U>}::as_ref"]
def Shared0T.Insts.CoreConvertAsRef.as_ref
{T : Type} {U : Type} (AsRefInst : core.convert.AsRef T U) : T → Result U :=
fun x => AsRefInst.as_ref x
/-- [ff::Field::sqrt] (trait DEFAULT method)
AXIOM: dead — `Fp` overrides `sqrt`; the default body is never called. -/
@[rust_fun "ff::Field::sqrt"]
axiom ff.Field.sqrt.default
{Self : Type} (FieldInst : ff.Field Self) :
Self → Result (subtle.CtOption Self)
/-- [ff::Field::pow_vartime] (trait DEFAULT method)
AXIOM: dead — `Fp` overrides `pow_vartime` (the patched index-loop version,
translated transparently in Funs.lean); the default body is never called. -/
@[rust_fun "ff::Field::pow_vartime"]
axiom ff.Field.pow_vartime.default
{Self : Type} {S : Type} (FieldInst : ff.Field Self)
(coreconvertAsRefSSliceU64Inst : core.convert.AsRef S (Slice Std.U64)) :
Self → S → Result Self
/-- [ff::PrimeField::from_u128] (trait DEFAULT method) — AXIOM: dead code here. -/
@[rust_fun "ff::PrimeField::from_u128"]
axiom ff.PrimeField.from_u128.default
{Self : Type} {Clause0_Repr : Type} (PrimeFieldInst : ff.PrimeField Self
Clause0_Repr) :
Std.U128 → Result Self
/-- [subtle::{subtle::Choice}::unwrap_u8]
MODEL: identity — Rust body is `self.0` behind a black_box fence. -/
@[rust_fun "subtle::{subtle::Choice}::unwrap_u8"]
def subtle.Choice.unwrap_u8 : subtle.Choice → Result Std.U8 := fun c => ok c
/-- [subtle::{impl BitAnd for Choice}::bitand]
MODEL: u8 bitwise AND (on the {0,1} invariant this is boolean ∧). -/
@[rust_fun
"subtle::{core::ops::bit::BitAnd<subtle::Choice, subtle::Choice, subtle::Choice>}::bitand"]
def subtle.Choice.Insts.CoreOpsBitBitAndChoiceChoice.bitand
: subtle.Choice → subtle.Choice → Result subtle.Choice :=
fun a b => ok (a &&& b)
/-- [subtle::{impl Not for Choice}::not]
MODEL: `1 ^ c` — Rust body is `Choice(1u8 ^ self.0)`; on {0,1} this is ¬. -/
@[rust_fun
"subtle::{core::ops::bit::Not<subtle::Choice, subtle::Choice>}::not"]
def subtle.Choice.Insts.CoreOpsBitNotChoice.not
: subtle.Choice → Result subtle.Choice :=
fun c => ok (1#u8 ^^^ c)
/-- [subtle::{impl From<u8> for Choice}::from]
MODEL: identity — Rust body reads the byte through a volatile/black_box
optimization fence; value semantics is id. (Callers uphold the {0,1}
contract; the crate's ct_eq-style producers only ever pass 0 or 1.) -/
@[rust_fun "subtle::{core::convert::From<subtle::Choice, u8>}::from"]
def subtle.Choice.Insts.CoreConvertFromU8.from
: Std.U8 → Result subtle.Choice := fun x => ok x
/-- [subtle::{impl ConstantTimeEq for u64}::ct_eq]
MODEL: the SPECIFICATION of subtle's xor/wrapping-neg/shift bit trick,
which returns 1 iff the two integers are equal (for ALL inputs): decide
`a = b`. -/
@[rust_fun "subtle::{subtle::ConstantTimeEq<u64>}::ct_eq"]
def U64.Insts.SubtleConstantTimeEq.ct_eq
: Std.U64 → Std.U64 → Result subtle.Choice :=
fun a b => ok (if a.val = b.val then 1#u8 else 0#u8)
/-- [subtle::{impl ConditionallySelectable for u64}::conditional_select]
MODEL: `a ^ (mask & (a ^ b))` with mask = (c as u64): equals `a` when
c = 0 and `b` when c = 1. Every Choice reaching this call is 0 or 1
(see TypesExternal policy), so if-then-else is exact. -/
@[rust_fun
"subtle::{subtle::ConditionallySelectable<u64>}::conditional_select"]
def U64.Insts.SubtleConditionallySelectable.conditional_select
: Std.U64 → Std.U64 → subtle.Choice → Result Std.U64 :=
fun a b c => ok (if c.val = 0 then a else b)
/-- [subtle::{subtle::CtOption<T>}::new]
MODEL: the struct constructor — store (value, is_some) verbatim. -/
@[rust_fun "subtle::{subtle::CtOption<@T>}::new"]
def subtle.CtOption.new
{T : Type} : T → subtle.Choice → Result (subtle.CtOption T) :=
fun v c => ok ⟨v, c⟩
/-- [Fp Debug::fmt] — AXIOM: formatting, no proof depends on it. -/
axiom fields.fp.Fp.Insts.CoreFmtDebug.fmt
:
fields.fp.Fp → core.fmt.Formatter → Result ((core.result.Result Unit
core.fmt.Error) × core.fmt.Formatter)
/-- [Fp PartialOrd::partial_cmp] — AXIOM: deliberately opaque (iterator fold). -/
axiom fields.fp.Fp.Insts.CoreCmpPartialOrdFp.partial_cmp
: fields.fp.Fp → fields.fp.Fp → Result (Option Ordering)
/-- [Fp Ord::cmp] — AXIOM: deliberately opaque (iterator fold). -/
axiom fields.fp.Fp.Insts.CoreCmpOrd.cmp
: fields.fp.Fp → fields.fp.Fp → Result Ordering
/-- [Fp Sum::sum] — AXIOM: deliberately opaque (iterator fold). -/
axiom fields.fp.Fp.Insts.CoreIterTraitsAccumSum.sum
{T : Type} {I : Type} (coreborrowBorrowTFpInst : core.borrow.Borrow T
fields.fp.Fp) (coreitertraitsiteratorIteratorInst :
core.iter.traits.iterator.Iterator I T) :
I → Result fields.fp.Fp
/-- [Fp Product::product] — AXIOM: deliberately opaque (iterator fold). -/
axiom fields.fp.Fp.Insts.CoreIterTraitsAccumProduct.product
{T : Type} {I : Type} (coreborrowBorrowTFpInst : core.borrow.Borrow T
fields.fp.Fp) (coreitertraitsiteratorIteratorInst :
core.iter.traits.iterator.Iterator I T) :
I → Result fields.fp.Fp
/-- [Fp ff::Field::sqrt] — AXIOM: TonelliShanks via helpers; out of scope
for the field certificate (documented in TRUSTED-BASE.md). -/
axiom fields.fp.Fp.Insts.FfField.sqrt
: fields.fp.Fp → Result (subtle.CtOption fields.fp.Fp)
/-- [Fp ff::Field::sqrt_ratio] — AXIOM: out of scope (see sqrt). -/
axiom fields.fp.Fp.Insts.FfField.sqrt_ratio
: fields.fp.Fp → fields.fp.Fp → Result (subtle.Choice × fields.fp.Fp)
/-- [Fp ff::Field::random] — AXIOM: RNG plumbing, untranslatable and irrelevant. -/
axiom fields.fp.Fp.Insts.FfField.random
{T0 : Type} (rand_coreRngCoreInst : rand_core.RngCore T0) :
T0 → Result fields.fp.Fp
/-- [Fp SqrtTableHelpers::get_lower_32] — AXIOM: sqrt-table helper, opaque. -/
axiom
fields.fp.Fp.Insts.Pasta_curvesArithmeticFieldsSqrtTableHelpersArrayU832.get_lower_32
: fields.fp.Fp → Result Std.U32
/-- [Fp SqrtTableHelpers::pow_by_t_minus1_over2] — AXIOM: sqrt-table helper
(closure-based), opaque. -/
axiom
fields.fp.Fp.Insts.Pasta_curvesArithmeticFieldsSqrtTableHelpersArrayU832.pow_by_t_minus1_over2
: fields.fp.Fp → Result fields.fp.Fp
/-- [Fp WithSmallOrderMulGroup::ZETA] — AXIOM: constant of an opaque impl. -/
axiom fields.fp.Fp.Insts.FfWithSmallOrderMulGroupArrayU8323.ZETA
: Result fields.fp.Fp
/-- [Fp FromUniformBytes::from_uniform_bytes] — AXIOM: opaque impl. -/
axiom fields.fp.Fp.Insts.FfFromUniformBytesArrayU83264.from_uniform_bytes
: Array Std.U8 64#usize → Result fields.fp.Fp

View file

@ -0,0 +1,224 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [pasta_curves]: external functions.
-- This is a template file: rename it to "FunsExternal.lean" and fill the holes.
import Aeneas
import PallasFp.Types
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
open pasta_curves
/-- [core::array::{impl core::convert::AsRef<[T]> for [T; N]}::as_ref]:
Source: '/rustc/library/core/src/array/mod.rs', lines 208:4-208:28
Name pattern: [core::array::{core::convert::AsRef<[@T; @N], [@T]>}::as_ref]
Visibility: public -/
@[rust_fun "core::array::{core::convert::AsRef<[@T; @N], [@T]>}::as_ref"]
axiom Array.Insts.CoreConvertAsRefSlice.as_ref
{T : Type} {N : Std.Usize} : Array T N → Result (Slice T)
/-- [core::array::{impl core::convert::AsMut<[T]> for [T; N]}::as_mut]:
Source: '/rustc/library/core/src/array/mod.rs', lines 217:4-217:36
Name pattern: [core::array::{core::convert::AsMut<[@T; @N], [@T]>}::as_mut]
Visibility: public -/
@[rust_fun "core::array::{core::convert::AsMut<[@T; @N], [@T]>}::as_mut"]
axiom Array.Insts.CoreConvertAsMutSlice.as_mut
{T : Type} {N : Std.Usize} :
Array T N → Result ((Slice T) × (Slice T → Array T N))
/-- [core::borrow::{impl core::borrow::Borrow<T> for T}::borrow]:
Source: '/rustc/library/core/src/borrow.rs', lines 214:4-214:26
Name pattern: [core::borrow::{core::borrow::Borrow<@T, @T>}::borrow]
Visibility: public -/
@[rust_fun "core::borrow::{core::borrow::Borrow<@T, @T>}::borrow"]
axiom core.borrow.Borrow.Blanket.borrow {T : Type} : T → Result T
/-- [core::borrow::{impl core::borrow::Borrow<T> for &'_0 T}::borrow]:
Source: '/rustc/library/core/src/borrow.rs', lines 230:4-230:26
Name pattern: [core::borrow::{core::borrow::Borrow<&'0 @T, @T>}::borrow]
Visibility: public -/
@[rust_fun "core::borrow::{core::borrow::Borrow<&'0 @T, @T>}::borrow"]
axiom Shared0T.Insts.CoreBorrowBorrow.borrow {T : Type} : T → Result T
/-- [core::convert::{impl core::convert::AsRef<U> for &'_0 T}::as_ref]:
Source: '/rustc/library/core/src/convert/mod.rs', lines 717:4-717:26
Name pattern: [core::convert::{core::convert::AsRef<&'0 @T, @U>}::as_ref]
Visibility: public -/
@[rust_fun "core::convert::{core::convert::AsRef<&'0 @T, @U>}::as_ref"]
axiom Shared0T.Insts.CoreConvertAsRef.as_ref
{T : Type} {U : Type} (AsRefInst : core.convert.AsRef T U) : T → Result U
/-- [ff::Field::sqrt]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 144:4-144:36
Name pattern: [ff::Field::sqrt]
Visibility: public -/
@[rust_fun "ff::Field::sqrt"]
axiom ff.Field.sqrt.default
{Self : Type} (FieldInst : ff.Field Self) :
Self → Result (subtle.CtOption Self)
/-- [ff::Field::pow_vartime]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 178:4-178:58
Name pattern: [ff::Field::pow_vartime]
Visibility: public -/
@[rust_fun "ff::Field::pow_vartime"]
axiom ff.Field.pow_vartime.default
{Self : Type} {S : Type} (FieldInst : ff.Field Self)
(coreconvertAsRefSSliceU64Inst : core.convert.AsRef S (Slice Std.U64)) :
Self → S → Result Self
/-- [ff::PrimeField::from_u128]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 254:4-254:33
Name pattern: [ff::PrimeField::from_u128]
Visibility: public -/
@[rust_fun "ff::PrimeField::from_u128"]
axiom ff.PrimeField.from_u128.default
{Self : Type} {Clause0_Repr : Type} (PrimeFieldInst : ff.PrimeField Self
Clause0_Repr) :
Std.U128 → Result Self
/-- [subtle::{subtle::Choice}::unwrap_u8]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 133:4-133:33
Name pattern: [subtle::{subtle::Choice}::unwrap_u8]
Visibility: public -/
@[rust_fun "subtle::{subtle::Choice}::unwrap_u8"]
axiom subtle.Choice.unwrap_u8 : subtle.Choice → Result Std.U8
/-- [subtle::{impl core::ops::bit::BitAnd<subtle::Choice, subtle::Choice> for subtle::Choice}::bitand]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 162:4-162:42
Name pattern: [subtle::{core::ops::bit::BitAnd<subtle::Choice, subtle::Choice, subtle::Choice>}::bitand]
Visibility: public -/
@[rust_fun
"subtle::{core::ops::bit::BitAnd<subtle::Choice, subtle::Choice, subtle::Choice>}::bitand"]
axiom subtle.Choice.Insts.CoreOpsBitBitAndChoiceChoice.bitand
: subtle.Choice → subtle.Choice → Result subtle.Choice
/-- [subtle::{impl core::ops::bit::Not<subtle::Choice> for subtle::Choice}::not]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 207:4-207:26
Name pattern: [subtle::{core::ops::bit::Not<subtle::Choice, subtle::Choice>}::not]
Visibility: public -/
@[rust_fun
"subtle::{core::ops::bit::Not<subtle::Choice, subtle::Choice>}::not"]
axiom subtle.Choice.Insts.CoreOpsBitNotChoice.not
: subtle.Choice → Result subtle.Choice
/-- [subtle::{impl core::convert::From<u8> for subtle::Choice}::from]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 238:4-238:32
Name pattern: [subtle::{core::convert::From<subtle::Choice, u8>}::from]
Visibility: public -/
@[rust_fun "subtle::{core::convert::From<subtle::Choice, u8>}::from"]
axiom subtle.Choice.Insts.CoreConvertFromU8.from
: Std.U8 → Result subtle.Choice
/-- [subtle::{impl subtle::ConstantTimeEq for u64}::ct_eq]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 348:12-348:51
Name pattern: [subtle::{subtle::ConstantTimeEq<u64>}::ct_eq]
Visibility: public -/
@[rust_fun "subtle::{subtle::ConstantTimeEq<u64>}::ct_eq"]
axiom U64.Insts.SubtleConstantTimeEq.ct_eq
: Std.U64 → Std.U64 → Result subtle.Choice
/-- [subtle::{impl subtle::ConditionallySelectable for u64}::conditional_select]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 513:12-513:77
Name pattern: [subtle::{subtle::ConditionallySelectable<u64>}::conditional_select]
Visibility: public -/
@[rust_fun
"subtle::{subtle::ConditionallySelectable<u64>}::conditional_select"]
axiom U64.Insts.SubtleConditionallySelectable.conditional_select
: Std.U64 → Std.U64 → subtle.Choice → Result Std.U64
/-- [subtle::{subtle::CtOption<T>}::new]:
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 678:4-678:56
Name pattern: [subtle::{subtle::CtOption<@T>}::new]
Visibility: public -/
@[rust_fun "subtle::{subtle::CtOption<@T>}::new"]
axiom subtle.CtOption.new
{T : Type} : T → subtle.Choice → Result (subtle.CtOption T)
/-- [pasta_curves::fields::fp::{impl core::fmt::Debug for pasta_curves::fields::fp::Fp}::fmt]:
Source: 'src/fields/fp.rs', lines 34:4-41:5
Visibility: public -/
axiom fields.fp.Fp.Insts.CoreFmtDebug.fmt
:
fields.fp.Fp → core.fmt.Formatter → Result ((core.result.Result Unit
core.fmt.Error) × core.fmt.Formatter)
/-- [pasta_curves::fields::fp::{impl core::cmp::PartialOrd<pasta_curves::fields::fp::Fp> for pasta_curves::fields::fp::Fp}::partial_cmp]:
Source: 'src/fields/fp.rs', lines 92:4-94:5
Visibility: public -/
axiom fields.fp.Fp.Insts.CoreCmpPartialOrdFp.partial_cmp
: fields.fp.Fp → fields.fp.Fp → Result (Option Ordering)
/-- [pasta_curves::fields::fp::{impl core::cmp::Ord for pasta_curves::fields::fp::Fp}::cmp]:
Source: 'src/fields/fp.rs', lines 77:4-88:5
Visibility: public -/
axiom fields.fp.Fp.Insts.CoreCmpOrd.cmp
: fields.fp.Fp → fields.fp.Fp → Result Ordering
/-- [pasta_curves::fields::fp::{impl core::iter::traits::accum::Sum<T> for pasta_curves::fields::fp::Fp}::sum]:
Source: 'src/fields/fp.rs', lines 179:4-181:5
Visibility: public -/
axiom fields.fp.Fp.Insts.CoreIterTraitsAccumSum.sum
{T : Type} {I : Type} (coreborrowBorrowTFpInst : core.borrow.Borrow T
fields.fp.Fp) (coreitertraitsiteratorIteratorInst :
core.iter.traits.iterator.Iterator I T) :
I → Result fields.fp.Fp
/-- [pasta_curves::fields::fp::{impl core::iter::traits::accum::Product<T> for pasta_curves::fields::fp::Fp}::product]:
Source: 'src/fields/fp.rs', lines 185:4-187:5
Visibility: public -/
axiom fields.fp.Fp.Insts.CoreIterTraitsAccumProduct.product
{T : Type} {I : Type} (coreborrowBorrowTFpInst : core.borrow.Borrow T
fields.fp.Fp) (coreitertraitsiteratorIteratorInst :
core.iter.traits.iterator.Iterator I T) :
I → Result fields.fp.Fp
/-- [pasta_curves::fields::fp::{impl ff::Field for pasta_curves::fields::fp::Fp}::sqrt]:
Source: 'src/fields/fp.rs', lines 566:4-575:5
Visibility: public -/
axiom fields.fp.Fp.Insts.FfField.sqrt
: fields.fp.Fp → Result (subtle.CtOption fields.fp.Fp)
/-- [pasta_curves::fields::fp::{impl ff::Field for pasta_curves::fields::fp::Fp}::sqrt_ratio]:
Source: 'src/fields/fp.rs', lines 550:4-558:5
Visibility: public -/
axiom fields.fp.Fp.Insts.FfField.sqrt_ratio
: fields.fp.Fp → fields.fp.Fp → Result (subtle.Choice × fields.fp.Fp)
/-- [pasta_curves::fields::fp::{impl ff::Field for pasta_curves::fields::fp::Fp}::random]:
Source: 'src/fields/fp.rs', lines 528:4-539:5
Visibility: public -/
axiom fields.fp.Fp.Insts.FfField.random
{T0 : Type} (rand_coreRngCoreInst : rand_core.RngCore T0) :
T0 → Result fields.fp.Fp
/-- [pasta_curves::fields::fp::{impl pasta_curves::arithmetic::fields::SqrtTableHelpers<[u8; 32usize]> for pasta_curves::fields::fp::Fp}::get_lower_32]:
Source: 'src/fields/fp.rs', lines 780:4-785:5 -/
axiom
fields.fp.Fp.Insts.Pasta_curvesArithmeticFieldsSqrtTableHelpersArrayU832.get_lower_32
: fields.fp.Fp → Result Std.U32
/-- [pasta_curves::fields::fp::{impl pasta_curves::arithmetic::fields::SqrtTableHelpers<[u8; 32usize]> for pasta_curves::fields::fp::Fp}::pow_by_t_minus1_over2]:
Source: 'src/fields/fp.rs', lines 749:4-778:5 -/
axiom
fields.fp.Fp.Insts.Pasta_curvesArithmeticFieldsSqrtTableHelpersArrayU832.pow_by_t_minus1_over2
: fields.fp.Fp → Result fields.fp.Fp
/-- [pasta_curves::fields::fp::{impl ff::WithSmallOrderMulGroup<[u8; 32usize], 3u8> for pasta_curves::fields::fp::Fp}::ZETA]
Source: 'src/fields/fp.rs', lines 789:4-794:7
Visibility: public -/
axiom fields.fp.Fp.Insts.FfWithSmallOrderMulGroupArrayU8323.ZETA
: Result fields.fp.Fp
/-- [pasta_curves::fields::fp::{impl ff::FromUniformBytes<[u8; 32usize], 64usize> for pasta_curves::fields::fp::Fp}::from_uniform_bytes]:
Source: 'src/fields/fp.rs', lines 800:4-811:5
Visibility: public -/
axiom fields.fp.Fp.Insts.FfFromUniformBytesArrayU83264.from_uniform_bytes
: Array Std.U8 64#usize → Result fields.fp.Fp

View file

@ -0,0 +1,234 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [pasta_curves]: type definitions
import Aeneas
import PallasFp.TypesExternal
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
namespace pasta_curves
/-- Trait declaration: [core::convert::AsRef]
Source: '/rustc/library/core/src/convert/mod.rs', lines 219:0-219:52
Name pattern: [core::convert::AsRef]
Visibility: public -/
@[rust_trait "core::convert::AsRef"]
structure core.convert.AsRef (Self : Type) (T : Type) where
as_ref : Self → Result T
/-- Trait declaration: [core::borrow::Borrow]
Source: '/rustc/library/core/src/borrow.rs', lines 158:0-158:40
Name pattern: [core::borrow::Borrow]
Visibility: public -/
@[rust_trait "core::borrow::Borrow"]
structure core.borrow.Borrow (Self : Type) (Borrowed : Type) where
borrow : Self → Result Borrowed
/-- Trait declaration: [core::ops::arith::Add]
Source: '/rustc/library/core/src/ops/arith.rs', lines 76:0-76:31
Name pattern: [core::ops::arith::Add]
Visibility: public -/
@[rust_trait "core::ops::arith::Add"]
structure core.ops.arith.Add (Self : Type) (Rhs : Type) (Self_Output : Type)
where
add : Self → Rhs → Result Self_Output
/-- Trait declaration: [core::ops::arith::Sub]
Source: '/rustc/library/core/src/ops/arith.rs', lines 188:0-188:31
Name pattern: [core::ops::arith::Sub]
Visibility: public -/
@[rust_trait "core::ops::arith::Sub"]
structure core.ops.arith.Sub (Self : Type) (Rhs : Type) (Self_Output : Type)
where
sub : Self → Rhs → Result Self_Output
/-- Trait declaration: [core::ops::arith::Mul]
Source: '/rustc/library/core/src/ops/arith.rs', lines 322:0-322:31
Name pattern: [core::ops::arith::Mul]
Visibility: public -/
@[rust_trait "core::ops::arith::Mul"]
structure core.ops.arith.Mul (Self : Type) (Rhs : Type) (Self_Output : Type)
where
mul : Self → Rhs → Result Self_Output
/-- Trait declaration: [core::ops::arith::Neg]
Source: '/rustc/library/core/src/ops/arith.rs', lines 690:0-690:19
Name pattern: [core::ops::arith::Neg]
Visibility: public -/
@[rust_trait "core::ops::arith::Neg"]
structure core.ops.arith.Neg (Self : Type) (Self_Output : Type) where
neg : Self → Result Self_Output
/-- Trait declaration: [core::ops::arith::AddAssign]
Source: '/rustc/library/core/src/ops/arith.rs', lines 768:0-768:37
Name pattern: [core::ops::arith::AddAssign]
Visibility: public -/
@[rust_trait "core::ops::arith::AddAssign"]
structure core.ops.arith.AddAssign (Self : Type) (Rhs : Type) where
add_assign : Self → Rhs → Result Self
/-- Trait declaration: [core::ops::arith::SubAssign]
Source: '/rustc/library/core/src/ops/arith.rs', lines 839:0-839:37
Name pattern: [core::ops::arith::SubAssign]
Visibility: public -/
@[rust_trait "core::ops::arith::SubAssign"]
structure core.ops.arith.SubAssign (Self : Type) (Rhs : Type) where
sub_assign : Self → Rhs → Result Self
/-- Trait declaration: [core::ops::arith::MulAssign]
Source: '/rustc/library/core/src/ops/arith.rs', lines 901:0-901:37
Name pattern: [core::ops::arith::MulAssign]
Visibility: public -/
@[rust_trait "core::ops::arith::MulAssign"]
structure core.ops.arith.MulAssign (Self : Type) (Rhs : Type) where
mul_assign : Self → Rhs → Result Self
/-- Trait declaration: [subtle::ConditionallySelectable]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 393:0-393:39
Name pattern: [subtle::ConditionallySelectable]
Visibility: public -/
@[rust_trait "subtle::ConditionallySelectable"
(parentClauses := ["coremarkerCopyInst"])]
structure subtle.ConditionallySelectable (Self : Type) where
coremarkerCopyInst : core.marker.Copy Self
conditional_select : Self → Self → subtle.Choice → Result Self
/-- Trait declaration: [subtle::ConstantTimeEq]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 262:0-262:24
Name pattern: [subtle::ConstantTimeEq]
Visibility: public -/
@[rust_trait "subtle::ConstantTimeEq"]
structure subtle.ConstantTimeEq (Self : Type) where
ct_eq : Self → Self → Result subtle.Choice
/-- Trait declaration: [rand_core::RngCore]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/src/lib.rs', lines 142:0-142:17
Name pattern: [rand_core::RngCore]
Visibility: public -/
@[rust_trait "rand_core::RngCore"]
structure rand_core.RngCore (Self : Type) where
next_u32 : Self → Result (Std.U32 × Self)
next_u64 : Self → Result (Std.U64 × Self)
fill_bytes : Self → Slice Std.U8 → Result (Self × (Slice Std.U8))
try_fill_bytes : Self → Slice Std.U8 → Result ((core.result.Result Unit
rand_core.error.Error) × Self × (Slice Std.U8))
/-- Trait declaration: [ff::Field]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 41:0-69:33
Name pattern: [ff::Field]
Visibility: public -/
@[rust_trait "ff::Field"
(parentClauses := ["corecmpEqInst", "coremarkerCopyInst", "corecloneCloneInst", "coredefaultDefaultInst", "corefmtDebugInst", "subtleConditionallySelectableInst", "subtleConstantTimeEqInst", "coreopsarithNegInst", "coreopsarithAddInst", "coreopsarithSubInst", "coreopsarithMulInst", "coreitertraitsaccumSumInst", "coreitertraitsaccumProductInst", "coreopsarithAddSelfSharedSelfSelfInst", "coreopsarithSubSelfSharedSelfSelfInst", "coreopsarithMulSelfSharedSelfSelfInst", "coreitertraitsaccumSumSelfSharedSelfInst", "coreitertraitsaccumProductSelfSharedSelfInst", "coreopsarithAddAssignInst", "coreopsarithSubAssignInst", "coreopsarithMulAssignInst", "coreopsarithAddAssignSelfSharedSelfInst", "coreopsarithSubAssignSelfSharedSelfInst", "coreopsarithMulAssignSelfSharedSelfInst"])
(consts := ["ZERO", "ONE"])]
structure ff.Field (Self : Type) where
ZERO : Result Self
ONE : Result Self
corecmpEqInst : core.cmp.Eq Self
coremarkerCopyInst : core.marker.Copy Self
corecloneCloneInst : core.clone.Clone Self
coredefaultDefaultInst : core.default.Default Self
corefmtDebugInst : core.fmt.Debug Self
subtleConditionallySelectableInst : subtle.ConditionallySelectable Self
subtleConstantTimeEqInst : subtle.ConstantTimeEq Self
coreopsarithNegInst : core.ops.arith.Neg Self Self
coreopsarithAddInst : core.ops.arith.Add Self Self Self
coreopsarithSubInst : core.ops.arith.Sub Self Self Self
coreopsarithMulInst : core.ops.arith.Mul Self Self Self
coreitertraitsaccumSumInst : core.iter.traits.accum.Sum Self Self
coreitertraitsaccumProductInst : core.iter.traits.accum.Product Self Self
coreopsarithAddSelfSharedSelfSelfInst : core.ops.arith.Add Self Self Self
coreopsarithSubSelfSharedSelfSelfInst : core.ops.arith.Sub Self Self Self
coreopsarithMulSelfSharedSelfSelfInst : core.ops.arith.Mul Self Self Self
coreitertraitsaccumSumSelfSharedSelfInst : core.iter.traits.accum.Sum Self
Self
coreitertraitsaccumProductSelfSharedSelfInst : core.iter.traits.accum.Product
Self Self
coreopsarithAddAssignInst : core.ops.arith.AddAssign Self Self
coreopsarithSubAssignInst : core.ops.arith.SubAssign Self Self
coreopsarithMulAssignInst : core.ops.arith.MulAssign Self Self
coreopsarithAddAssignSelfSharedSelfInst : core.ops.arith.AddAssign Self Self
coreopsarithSubAssignSelfSharedSelfInst : core.ops.arith.SubAssign Self Self
coreopsarithMulAssignSelfSharedSelfInst : core.ops.arith.MulAssign Self Self
random : forall {T1 : Type} (rand_coreRngCoreInst : rand_core.RngCore T1), T1
→ Result Self
square : Self → Result Self
double : Self → Result Self
invert : Self → Result (subtle.CtOption Self)
sqrt_ratio : Self → Self → Result (subtle.Choice × Self)
sqrt : Self → Result (subtle.CtOption Self)
pow_vartime : forall {S : Type} (coreconvertAsRefPSliceU64Inst :
core.convert.AsRef S (Slice Std.U64)), Self → S → Result Self
/-- Trait declaration: [ff::PrimeField]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 195:0-195:39
Name pattern: [ff::PrimeField]
Visibility: public -/
@[rust_trait "ff::PrimeField"
(parentClauses := ["FieldInst", "coreconvertFromSelfU64Inst", "coremarkerCopyInst", "coredefaultDefaultInst", "coreconvertAsRefSelf_ReprSliceU8Inst", "coreconvertAsMutSelf_ReprSliceU8Inst"])
(consts := ["MODULUS", "NUM_BITS", "CAPACITY", "TWO_INV", "MULTIPLICATIVE_GENERATOR", "S", "ROOT_OF_UNITY", "ROOT_OF_UNITY_INV", "DELTA"])]
structure ff.PrimeField (Self : Type) (Self_Repr : Type) where
MODULUS : Result Str
NUM_BITS : Result Std.U32
CAPACITY : Result Std.U32
TWO_INV : Result Self
MULTIPLICATIVE_GENERATOR : Result Self
S : Result Std.U32
ROOT_OF_UNITY : Result Self
ROOT_OF_UNITY_INV : Result Self
DELTA : Result Self
FieldInst : ff.Field Self
coreconvertFromSelfU64Inst : core.convert.From Self Std.U64
coremarkerCopyInst : core.marker.Copy Self_Repr
coredefaultDefaultInst : core.default.Default Self_Repr
coreconvertAsRefSelf_ReprSliceU8Inst : core.convert.AsRef Self_Repr (Slice
Std.U8)
coreconvertAsMutSelf_ReprSliceU8Inst : core.convert.AsMut Self_Repr (Slice
Std.U8)
from_u128 : Std.U128 → Result Self
from_repr : Self_Repr → Result (subtle.CtOption Self)
to_repr : Self → Result Self_Repr
is_odd : Self → Result subtle.Choice
/-- Trait declaration: [ff::WithSmallOrderMulGroup]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 358:0-358:57
Name pattern: [ff::WithSmallOrderMulGroup]
Visibility: public -/
@[rust_trait "ff::WithSmallOrderMulGroup" (parentClauses := ["PrimeFieldInst"])
(consts := ["ZETA"])]
structure ff.WithSmallOrderMulGroup (Self : Type) (Self_Clause0_Repr : Type) (N
: Std.U8) where
ZETA : Result Self
PrimeFieldInst : ff.PrimeField Self Self_Clause0_Repr
/-- Trait declaration: [ff::FromUniformBytes]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ff-0.13.1/src/lib.rs', lines 444:0-444:54
Name pattern: [ff::FromUniformBytes]
Visibility: public -/
@[rust_trait "ff::FromUniformBytes" (parentClauses := ["PrimeFieldInst"])]
structure ff.FromUniformBytes (Self : Type) (Self_Clause0_Repr : Type) (N :
Std.Usize) where
PrimeFieldInst : ff.PrimeField Self Self_Clause0_Repr
from_uniform_bytes : Array Std.U8 N → Result Self
/-- Trait declaration: [pasta_curves::arithmetic::fields::SqrtTableHelpers]
Source: 'src/arithmetic/fields.rs', lines 20:0-29:1 -/
structure arithmetic.fields.SqrtTableHelpers (Self : Type) (Self_Clause0_Repr :
Type) where
ffPrimeFieldInst : ff.PrimeField Self Self_Clause0_Repr
pow_by_t_minus1_over2 : Self → Result Self
get_lower_32 : Self → Result Std.U32
/-- [pasta_curves::fields::fp::Fp]
Source: 'src/fields/fp.rs', lines 31:0-31:35
Visibility: public -/
@[reducible]
def fields.fp.Fp := Array Std.U64 4#usize
end pasta_curves

View file

@ -0,0 +1,34 @@
-- Hand-written models for external types (derived from TypesExternal_Template.lean).
-- [pasta_curves]: external types.
--
-- Modeling policy (same as the ed25519 repos):
-- * `subtle.Choice` is MODELED as `Std.U8`. Rust invariant: the wrapped u8 is
-- always 0 or 1 (subtle's documented contract). Every Choice produced by
-- the models in FunsExternal.lean is literally 0 or 1, so if-then-else on
-- `c.val = 0` is exact for every value the transpiled code can construct.
-- * `subtle.CtOption T` is MODELED as a pair (value, is_some flag) — exactly
-- the Rust struct layout (`CtOption { value: T, is_some: Choice }`).
-- * `rand_core.error.Error` stays an opaque axiom: it is only reachable from
-- the (deliberately opaque) `random`, outside every certificate cone.
import Aeneas
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
set_option maxHeartbeats 1000000
set_option maxRecDepth 2048
/-- [subtle::Choice] — MODEL: a u8 carrying the {0,1} invariant. -/
@[reducible, rust_type "subtle::Choice"]
def subtle.Choice : Type := Std.U8
/-- [subtle::CtOption] — MODEL: the Rust struct `{ value: T, is_some: Choice }`. -/
@[rust_type "subtle::CtOption"]
structure subtle.CtOption (T : Type) where
value : T
is_some : subtle.Choice
/-- [rand_core::error::Error] — AXIOM: only reachable from the opaque `random`. -/
@[rust_type "rand_core::error::Error"]
axiom rand_core.error.Error : Type

View file

@ -0,0 +1,36 @@
-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [pasta_curves]: external types.
-- This is a template file: rename it to "TypesExternal.lean" and fill the holes.
import Aeneas
open Aeneas Aeneas.Std Result ControlFlow Error
set_option linter.dupNamespace false
set_option linter.hashCommand false
set_option linter.unusedVariables false
/- You can set the `maxHeartbeats` value with the `-max-heartbeats` CLI option -/
set_option maxHeartbeats 1000000
/- You can set the `maxRecDepth` value with the `-max-recdepth` CLI option -/
set_option maxRecDepth 2048
/-- [subtle::CtOption]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 647:0-647:22
Name pattern: [subtle::CtOption]
Visibility: public -/
@[rust_type "subtle::CtOption"]
axiom subtle.CtOption (T : Type) : Type
/-- [subtle::Choice]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs', lines 120:0-120:17
Name pattern: [subtle::Choice]
Visibility: public -/
@[rust_type "subtle::Choice"]
axiom subtle.Choice : Type
/-- [rand_core::error::Error]
Source: '/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/src/error.rs', lines 21:0-21:16
Name pattern: [rand_core::error::Error]
Visibility: public -/
@[rust_type "rand_core::error::Error"]
axiom rand_core.error.Error : Type