arnaucube
arnaucube/go-snarkPublic Self-hosted repository
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}