/ script / research / zk / circle-stark.sage
circle-stark.sage
 1  def random_mersenne_prime():
 2      while True:
 3          p = random_prime(100, 200)
 4          m = 2^p - 1
 5          if is_prime(m):
 6              return m
 7  
 8  #p = random_mersenne_prime()
 9  p = 8191
10  
11  # -1 should not be a quadratic residue modulo p
12  assert legendre_symbol(-1, p) == -1
13  assert p % 4 == 3
14  
15  F = GF(p)
16  R.<x> = F[]
17  K.<i> = F.extension(x^2 + 1)
18  
19  def get_point(t):
20      x = (1 - t^2)/(1 + t^2)
21      y = 2*t / (1 + t^2)
22      return (x, y)
23  
24  (p1_x, p1_y) = get_point(K(3))
25  assert p1_x^2 + p1_y^2 == 1
26  z = p1_x + i*p1_y
27  
28  (p2_x, p2_y) = get_point(K(7))
29  assert p2_x^2 + p2_y^2 == 1
30  w = p2_x + i*p2_y
31  
32  def abs(z):
33      return z[0]^2 + z[1]^2
34  
35  # z and w are now elements of F_p(i) which is a field
36  assert abs(z) == 1
37  assert abs(w) == 1
38  assert abs(z * w) == 1
39  
40  # We can also construct the inverse
41  def conjugate(z):
42      return z[0] - i*z[1]
43  # Remember that (x + iy)(x - iy) = x^2 - i^2 y^2 = x^2 + y^2
44  assert z * conjugate(z) in F
45  # Now we find the multiplicative inverse
46  z_inv = conjugate(z) / (z * conjugate(z))
47  assert z * z_inv == 1
48  
49  # Size of K is p^2
50  assert len(K) == p^2
51  
52  # Because in sage we cannot construct a homomorphism to GF(p^2) directly
53  # we instead construct the isomorphic field extension, and use that instead.
54  Fp2.<a> = GF(p^2)
55  conway_fp2 = a.minimal_polynomial()
56  L.<j> = F.extension(conway_fp2(x=x))
57  
58  y = L.multiplicative_generator()
59  phi = K.hom([y^(y.multiplicative_order()/i.multiplicative_order())])
60  # K ≌ GF(p^2)
61  assert phi.is_injective() and phi.is_surjective()
62  
63  assert a.multiplicative_order() == p^2 - 1
64  g_K = phi.inverse()(y)
65  g1 = g_K^int((p^2 - 1)/(p + 1))
66  assert abs(g1) == 1
67  
68  g2 = K.multiplicative_generator()
69  g2 = g2^(p - 1)
70  assert abs(g2) == 1
71  
72  # bug in sage where .unit_group is missing
73  # https://ask.sagemath.org/question/62822/make-morphism-from-gfp2s-multiplicative-group-to-gfps-multiplicative-group/
74  C = AbelianGroup([p + 1])
75  g, = C.gens()
76  while True:
77      print(f"Group of order = {g.order()}")
78      for C2 in C.subgroups():
79          print(f"  {C2}")
80      print()
81  
82      if g.order() == 1:
83          break
84  
85      # For some annoying reason, I cannot iterate on subgroups
86      # C = C.subgroup([g^2])
87      # Trying to get the subgroup of this will give me some error.
88      # Lets just construct it manually.
89      C = AbelianGroup([(g^2).order()])
90      g, = C.gens()
91