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