go-snark/bn128/g1.go
bn128/g1.goRaw
1package bn128
2
3import (
4 "math/big"
5
6 "github.com/arnaucube/go-snark/fields"
7)
8
9type G1 struct {
10 F fields.Fq
11 G [3]*big.Int
12}
13
14func NewG1(f fields.Fq, g [2]*big.Int) G1 {
15 var g1 G1
16 g1.F = f
17 g1.G = [3]*big.Int{
18 g[0],
19 g[1],
20 g1.F.One(),
21 }
22 return g1
23}
24
25func (g1 G1) Zero() [2]*big.Int {
26 return [2]*big.Int{g1.F.Zero(), g1.F.Zero()}
27}
28func (g1 G1) IsZero(p [3]*big.Int) bool {
29 return g1.F.IsZero(p[2])
30}
31
32func (g1 G1) Add(p1, p2 [3]*big.Int) [3]*big.Int {
33
34 // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
35 // https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp#L208
36 // http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
37
38 if g1.IsZero(p1) {
39 return p2
40 }
41 if g1.IsZero(p2) {
42 return p1
43 }
44
45 x1 := p1[0]
46 y1 := p1[1]
47 z1 := p1[2]
48 x2 := p2[0]
49 y2 := p2[1]
50 z2 := p2[2]
51
52 z1z1 := g1.F.Square(z1)
53 z2z2 := g1.F.Square(z2)
54
55 u1 := g1.F.Mul(x1, z2z2)
56 u2 := g1.F.Mul(x2, z1z1)
57
58 t0 := g1.F.Mul(z2, z2z2)
59 s1 := g1.F.Mul(y1, t0)
60
61 t1 := g1.F.Mul(z1, z1z1)
62 s2 := g1.F.Mul(y2, t1)
63
64 h := g1.F.Sub(u2, u1)
65 t2 := g1.F.Add(h, h)
66 i := g1.F.Square(t2)
67 j := g1.F.Mul(h, i)
68 t3 := g1.F.Sub(s2, s1)
69 r := g1.F.Add(t3, t3)
70 v := g1.F.Mul(u1, i)
71 t4 := g1.F.Square(r)
72 t5 := g1.F.Add(v, v)
73 t6 := g1.F.Sub(t4, j)
74 x3 := g1.F.Sub(t6, t5)
75 t7 := g1.F.Sub(v, x3)
76 t8 := g1.F.Mul(s1, j)
77 t9 := g1.F.Add(t8, t8)
78 t10 := g1.F.Mul(r, t7)
79
80 y3 := g1.F.Sub(t10, t9)
81
82 t11 := g1.F.Add(z1, z2)
83 t12 := g1.F.Square(t11)
84 t13 := g1.F.Sub(t12, z1z1)
85 t14 := g1.F.Sub(t13, z2z2)
86 z3 := g1.F.Mul(t14, h)
87
88 return [3]*big.Int{x3, y3, z3}
89}
90
91func (g1 G1) Neg(p [3]*big.Int) [3]*big.Int {
92 return [3]*big.Int{
93 p[0],
94 g1.F.Neg(p[1]),
95 p[2],
96 }
97}
98func (g1 G1) Sub(a, b [3]*big.Int) [3]*big.Int {
99 return g1.Add(a, g1.Neg(b))
100}
101func (g1 G1) Double(p [3]*big.Int) [3]*big.Int {
102
103 // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
104 // http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
105 // https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp#L325
106
107 if g1.IsZero(p) {
108 return p
109 }
110
111 a := g1.F.Square(p[0])
112 b := g1.F.Square(p[1])
113 c := g1.F.Square(b)
114
115 t0 := g1.F.Add(p[0], b)
116 t1 := g1.F.Square(t0)
117 t2 := g1.F.Sub(t1, a)
118 t3 := g1.F.Sub(t2, c)
119
120 d := g1.F.Double(t3)
121 e := g1.F.Add(g1.F.Add(a, a), a)
122 f := g1.F.Square(e)
123
124 t4 := g1.F.Double(d)
125 x3 := g1.F.Sub(f, t4)
126
127 t5 := g1.F.Sub(d, x3)
128 twoC := g1.F.Add(c, c)
129 fourC := g1.F.Add(twoC, twoC)
130 t6 := g1.F.Add(fourC, fourC)
131 t7 := g1.F.Mul(e, t5)
132 y3 := g1.F.Sub(t7, t6)
133
134 t8 := g1.F.Mul(p[1], p[2])
135 z3 := g1.F.Double(t8)
136
137 return [3]*big.Int{x3, y3, z3}
138}
139
140func (g1 G1) MulScalar(p [3]*big.Int, e *big.Int) [3]*big.Int {
141 // https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Double-and-add
142 // for more possible implementations see g2.go file, at the function g2.MulScalar()
143
144 q := [3]*big.Int{g1.F.Zero(), g1.F.Zero(), g1.F.Zero()}
145 d := g1.F.Copy(e)
146 r := p
147 for i := d.BitLen() - 1; i >= 0; i-- {
148 q = g1.Double(q)
149 if d.Bit(i) == 1 {
150 q = g1.Add(q, r)
151 }
152 }
153
154 return q
155}
156
157func (g1 G1) Affine(p [3]*big.Int) [2]*big.Int {
158 if g1.IsZero(p) {
159 return g1.Zero()
160 }
161
162 zinv := g1.F.Inverse(p[2])
163 zinv2 := g1.F.Square(zinv)
164 x := g1.F.Mul(p[0], zinv2)
165
166 zinv3 := g1.F.Mul(zinv2, zinv)
167 y := g1.F.Mul(p[1], zinv3)
168
169 return [2]*big.Int{x, y}
170}
171
172func (g1 G1) Equal(p1, p2 [3]*big.Int) bool {
173 if g1.IsZero(p1) {
174 return g1.IsZero(p2)
175 }
176 if g1.IsZero(p2) {
177 return g1.IsZero(p1)
178 }
179
180 z1z1 := g1.F.Square(p1[2])
181 z2z2 := g1.F.Square(p2[2])
182
183 u1 := g1.F.Mul(p1[0], z2z2)
184 u2 := g1.F.Mul(p2[0], z1z1)
185
186 z1cub := g1.F.Mul(p1[2], z1z1)
187 z2cub := g1.F.Mul(p2[2], z2z2)
188
189 s1 := g1.F.Mul(p1[1], z2cub)
190 s2 := g1.F.Mul(p2[1], z1cub)
191
192 return g1.F.Equal(u1, u2) && g1.F.Equal(s1, s2)
193}