go-snark/fields/fq.go
fields/fq.goRaw
1package fields
2
3import (
4 "bytes"
5 "crypto/rand"
6 "math/big"
7)
8
9// Fq is the Z field over modulus Q
10type Fq struct {
11 Q *big.Int // Q
12}
13
14// NewFq generates a new Fq
15func NewFq(q *big.Int) Fq {
16 return Fq{
17 q,
18 }
19}
20
21// Zero returns a Zero value on the Fq
22func (fq Fq) Zero() *big.Int {
23 return big.NewInt(int64(0))
24}
25
26// One returns a One value on the Fq
27func (fq Fq) One() *big.Int {
28 return big.NewInt(int64(1))
29}
30
31// Add performs an addition on the Fq
32func (fq Fq) Add(a, b *big.Int) *big.Int {
33 r := new(big.Int).Add(a, b)
34 return new(big.Int).Mod(r, fq.Q)
35 // return r
36}
37
38// Double performs a doubling on the Fq
39func (fq Fq) Double(a *big.Int) *big.Int {
40 r := new(big.Int).Add(a, a)
41 return new(big.Int).Mod(r, fq.Q)
42 // return r
43}
44
45// Sub performs a subtraction on the Fq
46func (fq Fq) Sub(a, b *big.Int) *big.Int {
47 r := new(big.Int).Sub(a, b)
48 return new(big.Int).Mod(r, fq.Q)
49 // return r
50}
51
52// Neg performs a negation on the Fq
53func (fq Fq) Neg(a *big.Int) *big.Int {
54 m := new(big.Int).Neg(a)
55 return new(big.Int).Mod(m, fq.Q)
56 // return m
57}
58
59// Mul performs a multiplication on the Fq
60func (fq Fq) Mul(a, b *big.Int) *big.Int {
61 m := new(big.Int).Mul(a, b)
62 return new(big.Int).Mod(m, fq.Q)
63 // return m
64}
65
66func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
67 return fq.Mul(base, e)
68}
69
70// Inverse returns the inverse on the Fq
71func (fq Fq) Inverse(a *big.Int) *big.Int {
72 return new(big.Int).ModInverse(a, fq.Q)
73 // q := bigCopy(fq.Q)
74 // t := big.NewInt(int64(0))
75 // r := fq.Q
76 // newt := big.NewInt(int64(0))
77 // newr := fq.Affine(a)
78 // for !bytes.Equal(newr.Bytes(), big.NewInt(int64(0)).Bytes()) {
79 // q := new(big.Int).Div(bigCopy(r), bigCopy(newr))
80 //
81 // t = bigCopy(newt)
82 // newt = fq.Sub(t, fq.Mul(q, newt))
83 //
84 // r = bigCopy(newr)
85 // newr = fq.Sub(r, fq.Mul(q, newr))
86 // }
87 // if t.Cmp(big.NewInt(0)) == -1 { // t< 0
88 // t = fq.Add(t, q)
89 // }
90 // return t
91}
92
93// Div performs the division over the finite field
94func (fq Fq) Div(a, b *big.Int) *big.Int {
95 d := fq.Mul(a, fq.Inverse(b))
96 return new(big.Int).Mod(d, fq.Q)
97}
98
99// Square performs a square operation on the Fq
100func (fq Fq) Square(a *big.Int) *big.Int {
101 m := new(big.Int).Mul(a, a)
102 return new(big.Int).Mod(m, fq.Q)
103}
104
105// Exp performs the exponential over Fq
106func (fq Fq) Exp(base *big.Int, e *big.Int) *big.Int {
107 res := fq.One()
108 rem := fq.Copy(e)
109 exp := base
110
111 for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
112 if BigIsOdd(rem) {
113 res = fq.Mul(res, exp)
114 }
115 exp = fq.Square(exp)
116 rem = new(big.Int).Rsh(rem, 1)
117 }
118 return res
119}
120
121func (fq Fq) Rand() (*big.Int, error) {
122
123 // twoexp := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(maxbits)), nil)
124 // max := new(big.Int).Sub(twoexp, big.NewInt(1))
125
126 maxbits := fq.Q.BitLen()
127 b := make([]byte, (maxbits/8)-1)
128 // b := make([]byte, 3)
129 // b := make([]byte, 3)
130 _, err := rand.Read(b)
131 if err != nil {
132 return nil, err
133 }
134 r := new(big.Int).SetBytes(b)
135 rq := new(big.Int).Mod(r, fq.Q)
136
137 // return r over q, nil
138 return rq, nil
139}
140
141func (fq Fq) IsZero(a *big.Int) bool {
142 return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
143}
144
145func (fq Fq) Copy(a *big.Int) *big.Int {
146 return new(big.Int).SetBytes(a.Bytes())
147}
148
149func (fq Fq) Affine(a *big.Int) *big.Int {
150 nq := fq.Neg(fq.Q)
151
152 aux := a
153 if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
154 if aux.Cmp(nq) != 1 { // aux less or equal nq
155 aux = new(big.Int).Mod(aux, fq.Q)
156 }
157 if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
158 aux = new(big.Int).Add(aux, fq.Q)
159 }
160 } else {
161 if aux.Cmp(fq.Q) != -1 { // aux greater or equal nq
162 aux = new(big.Int).Mod(aux, fq.Q)
163 }
164 }
165 return aux
166}
167
168func (fq Fq) Equal(a, b *big.Int) bool {
169 aAff := fq.Affine(a)
170 bAff := fq.Affine(b)
171 return bytes.Equal(aAff.Bytes(), bAff.Bytes())
172}