arnaucube
arnaucube/go-circom-prover-verifierPublic Self-hosted repository
go-circom-prover-verifier/prover/arithmetic.go
prover/arithmetic.goRaw
  1package prover
  2
  3import (
  4	"bytes"
  5	"math/big"
  6
  7	"github.com/iden3/go-circom-prover-verifier/types"
  8	"github.com/iden3/go-iden3-crypto/ff"
  9)
 10
 11func arrayOfZeroes(n int) []*big.Int {
 12	var r []*big.Int
 13	for i := 0; i < n; i++ {
 14		r = append(r, new(big.Int).SetInt64(0))
 15	}
 16	return r
 17}
 18func arrayOfZeroesE(n int) []*ff.Element {
 19	var r []*ff.Element
 20	for i := 0; i < n; i++ {
 21		r = append(r, ff.NewElement())
 22	}
 23	return r
 24}
 25
 26func fAdd(a, b *big.Int) *big.Int {
 27	ab := new(big.Int).Add(a, b)
 28	return new(big.Int).Mod(ab, types.R)
 29}
 30
 31func fSub(a, b *big.Int) *big.Int {
 32	ab := new(big.Int).Sub(a, b)
 33	return new(big.Int).Mod(ab, types.R)
 34}
 35
 36func fMul(a, b *big.Int) *big.Int {
 37	ab := new(big.Int).Mul(a, b)
 38	return new(big.Int).Mod(ab, types.R)
 39}
 40
 41func fDiv(a, b *big.Int) *big.Int {
 42	ab := new(big.Int).Mul(a, new(big.Int).ModInverse(b, types.R))
 43	return new(big.Int).Mod(ab, types.R)
 44}
 45
 46func fNeg(a *big.Int) *big.Int {
 47	return new(big.Int).Mod(new(big.Int).Neg(a), types.R)
 48}
 49
 50func fInv(a *big.Int) *big.Int {
 51	return new(big.Int).ModInverse(a, types.R)
 52}
 53
 54func fExp(base *big.Int, e *big.Int) *big.Int {
 55	res := big.NewInt(1)
 56	rem := new(big.Int).Set(e)
 57	exp := base
 58
 59	for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
 60		// if BigIsOdd(rem) {
 61		if rem.Bit(0) == 1 { // .Bit(0) returns 1 when is odd
 62			res = fMul(res, exp)
 63		}
 64		exp = fMul(exp, exp)
 65		rem = new(big.Int).Rsh(rem, 1)
 66	}
 67	return res
 68}
 69
 70func max(a, b int) int {
 71	if a > b {
 72		return a
 73	}
 74	return b
 75}
 76
 77func polynomialSub(a, b []*big.Int) []*big.Int {
 78	r := arrayOfZeroes(max(len(a), len(b)))
 79	for i := 0; i < len(a); i++ {
 80		r[i] = fAdd(r[i], a[i])
 81	}
 82	for i := 0; i < len(b); i++ {
 83		r[i] = fSub(r[i], b[i])
 84	}
 85	return r
 86}
 87
 88func polynomialSubE(a, b []*ff.Element) []*ff.Element {
 89	r := arrayOfZeroesE(max(len(a), len(b)))
 90	for i := 0; i < len(a); i++ {
 91		r[i].Add(r[i], a[i])
 92	}
 93	for i := 0; i < len(b); i++ {
 94		r[i].Sub(r[i], b[i])
 95	}
 96	return r
 97}
 98
 99func polynomialMul(a, b []*big.Int) []*big.Int {
100	r := arrayOfZeroes(len(a) + len(b) - 1)
101	for i := 0; i < len(a); i++ {
102		for j := 0; j < len(b); j++ {
103			r[i+j] = fAdd(r[i+j], fMul(a[i], b[j]))
104		}
105	}
106	return r
107}
108
109func polynomialMulE(a, b []*ff.Element) []*ff.Element {
110	r := arrayOfZeroesE(len(a) + len(b) - 1)
111	for i := 0; i < len(a); i++ {
112		for j := 0; j < len(b); j++ {
113			r[i+j].Add(r[i+j], ff.NewElement().Mul(a[i], b[j]))
114		}
115	}
116	return r
117}
118
119func polynomialDiv(a, b []*big.Int) ([]*big.Int, []*big.Int) {
120	// https://en.wikipedia.org/wiki/Division_algorithm
121	r := arrayOfZeroes(len(a) - len(b) + 1)
122	rem := a
123	for len(rem) >= len(b) {
124		l := fDiv(rem[len(rem)-1], b[len(b)-1])
125		pos := len(rem) - len(b)
126		r[pos] = l
127		aux := arrayOfZeroes(pos)
128		aux1 := append(aux, l)
129		aux2 := polynomialSub(rem, polynomialMul(b, aux1))
130		rem = aux2[:len(aux2)-1]
131	}
132	return r, rem
133}
134
135func polynomialDivE(a, b []*ff.Element) ([]*ff.Element, []*ff.Element) {
136	// https://en.wikipedia.org/wiki/Division_algorithm
137	r := arrayOfZeroesE(len(a) - len(b) + 1)
138	rem := a
139	for len(rem) >= len(b) {
140		l := ff.NewElement().Div(rem[len(rem)-1], b[len(b)-1])
141		pos := len(rem) - len(b)
142		r[pos] = l
143		aux := arrayOfZeroesE(pos)
144		aux1 := append(aux, l)
145		aux2 := polynomialSubE(rem, polynomialMulE(b, aux1))
146		rem = aux2[:len(aux2)-1]
147	}
148	return r, rem
149}