You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
3.5 KiB

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