import Mathlib import Definitions.Def_TateCurve_XMultStructure import Definitions.Def_TateCurve_TateParameter import Definitions.Def_WeierstrassCurve_AddFormula import Definitions.Def_NetPairing_Basic import Theorems.Thm_TateCurve_equation_pointX_pointY import Theorems.Thm_TateCurve_pointX_inv import Theorems.Thm_TateCurve_pointX_zpow_mul set_option autoImplicit false set_option linter.unusedSectionVars false namespace WeierstrassCurve.Affine variable {F : Type*} [Field F] {W : WeierstrassCurve F} lemma addX_mul_sq_of_X_ne' [DecidableEq F] {x₁ x₂ : F} (y₁ y₂ : F) (hx : x₁ ≠ x₂) : W.toAffine.addX x₁ x₂ (W.toAffine.slope x₁ x₂ y₁ y₂) * (x₁ - x₂) ^ 2 = (y₁ - y₂) ^ 2 + W.a₁ * (y₁ - y₂) * (x₁ - x₂) - (W.a₂ + x₁ + x₂) * (x₁ - x₂) ^ 2 := by have hd : x₁ - x₂ ≠ 0 := sub_ne_zero.mpr hx rw [slope_of_X_ne hx, addX] field_simp ring theorem addX_add_addX_negY_mul_sq' [DecidableEq F] {x₁ x₂ y₁ y₂ : F} (h₁ : W.toAffine.Equation x₁ y₁) (h₂ : W.toAffine.Equation x₂ y₂) (hx : x₁ ≠ x₂) : (W.toAffine.addX x₁ x₂ (W.toAffine.slope x₁ x₂ y₁ y₂) + W.toAffine.addX x₁ x₂ (W.toAffine.slope x₁ x₂ y₁ (W.toAffine.negY x₂ y₂))) * (x₁ - x₂) ^ 2 = 2 * (x₁ * x₂) * (x₁ + x₂) + W.b₂ * (x₁ * x₂) + W.b₄ * (x₁ + x₂) + W.b₆ := by have e₁ := addX_mul_sq_of_X_ne' (W := W) y₁ y₂ hx have e₂ := addX_mul_sq_of_X_ne' (W := W) y₁ (W.toAffine.negY x₂ y₂) hx rw [W.toAffine.equation_iff x₁ y₁] at h₁ rw [W.toAffine.equation_iff x₂ y₂] at h₂ rw [add_mul, e₁, e₂, negY, b₂, b₄, b₆] linear_combination 2 * h₁ + 2 * h₂ end WeierstrassCurve.Affine set_option linter.unusedSectionVars false open WeierstrassCurve.Affine open Polynomial namespace TateCurve variable {K : Type*} [NontriviallyNormedField K] [IsUltrametricDist K] [CompleteSpace K] [CharZero K] [DecidableEq K] variable {q u : K} structure SymAddHyps (q : K) : Prop where sum : ∀ u v : K, AddParams q u v → (pointX q (u * v) + pointX q (u * v⁻¹)) * (pointX q u - pointX q v) ^ 2 = symSumNum q (pointX q u) (pointX q v) prod : ∀ u v : K, AddParams q u v → pointX q (u * v) * pointX q (u * v⁻¹) * (pointX q u - pointX q v) ^ 2 = symProdNum q (pointX q u) (pointX q v) dbl : ∀ u : K, u ≠ 0 → OffLattice q u → OffLattice q (u ^ 2) → pointX q (u ^ 2) * ((curve q).Ψ₂Sq).eval (pointX q u) = ((curve q).Φ 2).eval (pointX q u) section TatePoint lemma equation_point (hq0 : q ≠ 0) (hq : ‖q‖₊ < 1) (hu0 : u ≠ 0) (hu : OffLattice q u) : (curve q).toAffine.Equation (pointX q u) (pointY q u) := by have h := equation_pointX_pointY hq0 hq hu0 hu rw [WeierstrassCurve.Affine.equation_iff] show pointY q u ^ 2 + (curve q).a₁ * pointX q u * pointY q u + (curve q).a₃ * pointY q u = pointX q u ^ 3 + (curve q).a₂ * pointX q u ^ 2 + (curve q).a₄ * pointX q u + (curve q).a₆ rw [curve_a₁, curve_a₂, curve_a₃, curve_a₄, curve_a₆] linear_combination h lemma nonsingular_point (hq0 : q ≠ 0) (hq : ‖q‖₊ < 1) (hu0 : u ≠ 0) (hu : OffLattice q u) : (curve q).toAffine.Nonsingular (pointX q u) (pointY q u) := (WeierstrassCurve.Affine.equation_iff_nonsingular_of_Δ_ne_zero (Δ_ne_zero hq0 hq)).mp (equation_point hq0 hq hu0 hu) end TatePoint section PowerBookkeeping private lemma pow_succ_mul_inv (hu0 : u ≠ 0) (k : ℕ) : u ^ (k + 1) * u⁻¹ = u ^ k := by rw [pow_succ, mul_assoc, mul_inv_cancel₀ hu0, mul_one] private lemma addParams_pow (hq0 : q ≠ 0) (hu0 : u ≠ 0) {N k : ℕ} (hk : k + 3 ≤ N) (hoff : ∀ j : ℕ, 1 ≤ j → j ≤ N → OffLattice q (u ^ j)) : AddParams q (u ^ (k + 2)) u := by have h1 : OffLattice q u := by have h := hoff 1 le_rfl (by omega); rwa [pow_one] at h have hmul : OffLattice q (u ^ (k + 2) * u) := by have h := hoff (k + 2 + 1) (by omega) (by omega) rwa [pow_succ] at h have hdiv : OffLattice q (u ^ (k + 2) * u⁻¹) := by have h := hoff (k + 1) (by omega) (by omega) have heq : u ^ (k + 2) * u⁻¹ = u ^ (k + 1) := pow_succ_mul_inv hu0 (k + 1) rwa [heq] exact ⟨hq0, pow_ne_zero _ hu0, hu0, hoff (k + 2) (by omega) (by omega), h1, hmul, hdiv⟩ lemma offLattice_pow_of_prime {p j : ℕ} {s : ℤ} (hq0 : q ≠ 0) (hu0 : u ≠ 0) (hu : OffLattice q u) (hpow : u ^ p = q ^ s) (hp : p.Prime) (hj0 : 0 < j) (hjp : j < p) : OffLattice q (u ^ j) := by intro n hn have hju : u ^ ((j : ℕ) : ℤ) = q ^ (-n) := by rw [zpow_natCast] have h1 : q ^ (-n) * (q ^ n * u ^ j) = q ^ (-n) * 1 := by rw [hn] rwa [← mul_assoc, ← zpow_add₀ hq0, neg_add_cancel, zpow_zero, one_mul, mul_one] at h1 have hpz : u ^ ((p : ℕ) : ℤ) = q ^ s := by rw [zpow_natCast]; exact hpow have hcop : Nat.Coprime p j := (Nat.Prime.coprime_iff_not_dvd hp).mpr (fun hdvd => absurd (Nat.le_of_dvd hj0 hdvd) (by omega)) have hbez : (1 : ℤ) = (p : ℤ) * Nat.gcdA p j + (j : ℤ) * Nat.gcdB p j := by have h := Nat.gcd_eq_gcd_ab p j rwa [hcop.gcd_eq_one, Nat.cast_one] at h have hkey : u = q ^ (s * Nat.gcdA p j + (-n) * Nat.gcdB p j) := by have h1 : u = (u ^ ((p : ℕ) : ℤ)) ^ Nat.gcdA p j * (u ^ ((j : ℕ) : ℤ)) ^ Nat.gcdB p j := by rw [← zpow_mul, ← zpow_mul, ← zpow_add₀ hu0, ← hbez, zpow_one] rw [h1, hpz, hju, ← zpow_mul, ← zpow_mul, ← zpow_add₀ hq0] exact hu (-(s * Nat.gcdA p j + (-n) * Nat.gcdB p j)) (by rw [hkey, ← zpow_add₀ hq0, neg_add_cancel, zpow_zero]) end PowerBookkeeping section Ladder theorem xOrZero_nsmul_of_forall_ne_zero (hyps : SymAddHyps q) (hq0 : q ≠ 0) (hu0 : u ≠ 0) {N : ℕ} (hoff : ∀ j : ℕ, 1 ≤ j → j ≤ N → OffLattice q (u ^ j)) (hns : (curve q).toAffine.Nonsingular (pointX q u) (pointY q u)) (htor : ∀ m : ℕ, 2 ≤ m → m ≤ N → m • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) ≠ 0) : ∀ j : ℕ, 1 ≤ j → j ≤ N → j • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) ≠ 0 ∧ (j • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point)).xOrZero = pointX q (u ^ j) := by set P : (curve q).toAffine.Point := Point.some (pointX q u) (pointY q u) hns with hP intro j induction j using Nat.strong_induction_on with | _ j ih => intro hj1 hjN rcases lt_or_ge j 3 with hj3 | hj3 · interval_cases j · refine ⟨by rw [one_nsmul, hP]; exact Point.some_ne_zero hns, ?_⟩ rw [one_nsmul, hP, Point.xOrZero_some, pow_one] · have hoff1 : OffLattice q u := by have h := hoff 1 le_rfl (by omega); rwa [pow_one] at h have hoff2 : OffLattice q (u ^ 2) := hoff 2 (by omega) hjN by_cases hy : pointY q u = (curve q).toAffine.negY (pointX q u) (pointY q u) · exact absurd (by rw [two_nsmul, hP]; exact Point.add_self_of_Y_eq hy) (htor 2 le_rfl hjN) · have hT : ((curve q).toAffine.Ψ₂Sq).eval (pointX q u) ≠ 0 := by have hsq := WeierstrassCurve.Affine.sq_sub_negY_eq_eval_Ψ₂Sq (W := (curve q).toAffine) hns.left rw [← hsq] exact pow_ne_zero 2 (sub_ne_zero.mpr hy) have hcurve := WeierstrassCurve.Affine.addX_self_mul_Ψ₂Sq (W := (curve q).toAffine) hns.left hy have hser : pointX q (u ^ 2) * ((curve q).toAffine.Ψ₂Sq).eval (pointX q u) = (((curve q).toAffine.Φ 2)).eval (pointX q u) := hyps.dbl u hu0 hoff1 hoff2 have hx2 : (curve q).toAffine.addX (pointX q u) (pointX q u) ((curve q).toAffine.slope (pointX q u) (pointX q u) (pointY q u) (pointY q u)) = pointX q (u ^ 2) := mul_right_cancel₀ hT (hcurve.trans hser.symm) refine ⟨?_, ?_⟩ · rw [two_nsmul, hP, Point.add_self_of_Y_ne hy] exact Point.some_ne_zero _ · rw [two_nsmul, hP, Point.add_self_of_Y_ne hy, Point.xOrZero_some] exact hx2 · obtain ⟨k, rfl⟩ : ∃ k, j = k + 3 := ⟨j - 3, by omega⟩ obtain ⟨hQne, hQx⟩ := ih (k + 2) (by omega) (by omega) (by omega) obtain ⟨hRne, hRx⟩ := ih (k + 1) (by omega) (by omega) (by omega) obtain ⟨xj, yj, hj, hQeq⟩ : ∃ (xj yj : K) (hj : (curve q).toAffine.Nonsingular xj yj), (k + 2) • P = Point.some xj yj hj := by cases hQP : (k + 2) • P with | zero => exact absurd hQP hQne | @some a b hc => exact ⟨a, b, hc, rfl⟩ have hxj : xj = pointX q (u ^ (k + 2)) := by rw [hQeq, Point.xOrZero_some] at hQx exact hQx by_cases hxx : xj = pointX q u · exfalso rcases Y_eq_of_X_eq hj.left hns.left hxx with hyy | hyy · have hQP : (k + 2) • P = P := by rw [hQeq, hP] subst hxx; subst hyy rw [Subsingleton.elim hj hns] have hsucc : (k + 2) • P = (k + 1) • P + P := succ_nsmul P (k + 1) have h0 : (k + 1) • P + P = 0 + P := by rw [zero_add, ← hsucc, hQP] exact hRne (add_right_cancel h0) · have hQP : (k + 2) • P = -P := by rw [hQeq, hP, Point.neg_some] subst hxx; subst hyy exact congrArg _ (Subsingleton.elim _ _) have hk3 : (k + 3) • P = 0 := by have hsucc : (k + 3) • P = (k + 2) • P + P := succ_nsmul P (k + 2) rw [hsucc, hQP, neg_add_cancel] exact htor (k + 3) (by omega) hjN hk3 · have hap : AddParams q (u ^ (k + 2)) u := addParams_pow hq0 hu0 hjN hoff have hS1 := hyps.sum (u ^ (k + 2)) u hap rw [show u ^ (k + 2) * u = u ^ (k + 2 + 1) from (pow_succ u (k + 2)).symm, show u ^ (k + 2) * u⁻¹ = u ^ (k + 1) from pow_succ_mul_inv hu0 (k + 1), symSumNum_eq_b, ← hxj] at hS1 have hsum := WeierstrassCurve.Affine.addX_add_addX_negY_mul_sq' (W := curve q) hj.left hns.left hxx have hAm : (curve q).toAffine.addX xj (pointX q u) ((curve q).toAffine.slope xj (pointX q u) yj ((curve q).toAffine.negY (pointX q u) (pointY q u))) = pointX q (u ^ (k + 1)) := by have h1 := hRx have hsucc2 : (k + 2) • P = (k + 1) • P + P := succ_nsmul P (k + 1) have hrearr : (k + 1) • P = (k + 2) • P + -P := by rw [hsucc2, add_neg_cancel_right] rw [hrearr, hQeq, hP, Point.neg_some, Point.add_of_X_ne hxx, Point.xOrZero_some] at h1 exact h1 have hD2 : (xj - pointX q u) ^ 2 ≠ 0 := pow_ne_zero 2 (sub_ne_zero.mpr hxx) have hcomb := mul_right_cancel₀ hD2 (hsum.trans hS1.symm) rw [hAm] at hcomb have hfinal : (curve q).toAffine.addX xj (pointX q u) ((curve q).toAffine.slope xj (pointX q u) yj (pointY q u)) = pointX q (u ^ (k + 2 + 1)) := add_right_cancel hcomb have hsucc : (k + 3) • P = (k + 2) • P + P := succ_nsmul P (k + 2) refine ⟨?_, ?_⟩ · rw [hsucc, hQeq, hP, Point.add_of_X_ne hxx] exact Point.some_ne_zero _ · rw [hsucc, hQeq, hP, Point.add_of_X_ne hxx, Point.xOrZero_some] exact hfinal end Ladder section Endgame lemma pointX_pow_pred_eq (hq0 : q ≠ 0) (hu0 : u ≠ 0) (hu : OffLattice q u) {p : ℕ} (hp1 : 1 ≤ p) {s : ℤ} (hpow : u ^ p = q ^ s) : pointX q (u ^ (p - 1)) = pointX q u := by have h1 : u ^ p = u ^ (p - 1) * u := by conv_lhs => rw [show p = (p - 1) + 1 by omega] rw [pow_succ] have h2 : u ^ (p - 1) = q ^ s * u⁻¹ := by rw [← hpow, h1, mul_assoc, mul_inv_cancel₀ hu0, mul_one] rw [h2, pointX_zpow_mul hq0, pointX_inv hq0 hu0 hu] theorem nsmul_prime_eq_zero_of_forall_ne_zero {p : ℕ} (hyps : SymAddHyps q) (hq0 : q ≠ 0) (hu0 : u ≠ 0) (hu : OffLattice q u) {s : ℤ} (hpow : u ^ p = q ^ s) (hp : p.Prime) (hodd : Odd p) (hns : (curve q).toAffine.Nonsingular (pointX q u) (pointY q u)) (htor : ∀ m : ℕ, 2 ≤ m → m ≤ p - 1 → m • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) ≠ 0) : p • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) = 0 := by set P : (curve q).toAffine.Point := Point.some (pointX q u) (pointY q u) hns with hP have hp3 : 3 ≤ p := by have h2 := hp.two_le rcases hodd with ⟨t, ht⟩ omega have hoff : ∀ j : ℕ, 1 ≤ j → j ≤ p - 1 → OffLattice q (u ^ j) := fun j hj1 hj2 => offLattice_pow_of_prime hq0 hu0 hu hpow hp (by omega) (by omega) have halign := xOrZero_nsmul_of_forall_ne_zero hyps hq0 hu0 hoff hns htor obtain ⟨hne, hx⟩ := halign (p - 1) (by omega) le_rfl have hXp : pointX q (u ^ (p - 1)) = pointX q u := pointX_pow_pred_eq hq0 hu0 hu (by omega) hpow obtain ⟨x', y', h', hQeq⟩ : ∃ (x' y' : K) (h' : (curve q).toAffine.Nonsingular x' y'), (p - 1) • P = Point.some x' y' h' := by cases hQP : (p - 1) • P with | zero => exact absurd hQP hne | @some a b hc => exact ⟨a, b, hc, rfl⟩ have hx' : x' = pointX q u := by rw [hQeq, Point.xOrZero_some] at hx rw [hx, hXp] rcases Y_eq_of_X_eq h'.left hns.left hx' with hyy | hyy · exfalso have hQP : (p - 1) • P = P := by rw [hQeq, hP] subst hx'; subst hyy rw [Subsingleton.elim h' hns] obtain ⟨hne2, _⟩ := halign (p - 2) (by omega) (by omega) have h0 : (p - 2) • P + P = 0 + P := by rw [zero_add, ← succ_nsmul, show p - 2 + 1 = p - 1 by omega, hQP] exact hne2 (add_right_cancel h0) · have hQP : (p - 1) • P = -P := by rw [hQeq, hP, Point.neg_some] subst hx'; subst hyy exact congrArg _ (Subsingleton.elim _ _) have hsucc : p • P = (p - 1) • P + P := by conv_lhs => rw [show p = (p - 1) + 1 by omega] exact succ_nsmul P (p - 1) rw [hsucc, hQP, neg_add_cancel] theorem nsmul_prime_eq_zero_or_exists_nsmul_eq_zero {p : ℕ} (hyps : SymAddHyps q) (hq0 : q ≠ 0) (hu0 : u ≠ 0) (hu : OffLattice q u) {s : ℤ} (hpow : u ^ p = q ^ s) (hp : p.Prime) (hodd : Odd p) (hns : (curve q).toAffine.Nonsingular (pointX q u) (pointY q u)) : p • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) = 0 ∨ ∃ m : ℕ, 2 ≤ m ∧ m ≤ p - 1 ∧ m • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) = 0 := by by_cases h : ∃ m : ℕ, 2 ≤ m ∧ m ≤ p - 1 ∧ m • (Point.some (pointX q u) (pointY q u) hns : (curve q).toAffine.Point) = 0 · exact Or.inr h · refine Or.inl (nsmul_prime_eq_zero_of_forall_ne_zero hyps hq0 hu0 hu hpow hp hodd hns (fun m hm1 hm2 hm0 => h ⟨m, hm1, hm2, hm0⟩)) end Endgame end TateCurve