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.

160 lines
3.4 KiB

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