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.

109 lines
2.5 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package prover
  2. import (
  3. "math"
  4. "math/big"
  5. "github.com/iden3/go-circom-prover-verifier/types"
  6. "github.com/iden3/go-iden3-crypto/ff"
  7. )
  8. type rootsT struct {
  9. roots [][]*ff.Element
  10. w []*ff.Element
  11. }
  12. func newRootsT() rootsT {
  13. var roots rootsT
  14. rem := new(big.Int).Sub(types.R, big.NewInt(1))
  15. s := 0
  16. for rem.Bit(0) == 0 { // rem.Bit==0 when even
  17. s++
  18. rem = new(big.Int).Rsh(rem, 1)
  19. }
  20. roots.w = make([]*ff.Element, s+1)
  21. roots.w[s] = ff.NewElement().SetBigInt(fExp(big.NewInt(5), rem))
  22. n := s - 1
  23. for n >= 0 {
  24. roots.w[n] = ff.NewElement().Mul(roots.w[n+1], roots.w[n+1])
  25. n--
  26. }
  27. roots.roots = make([][]*ff.Element, 50) // TODO WIP
  28. roots.setRoots(15)
  29. return roots
  30. }
  31. func (roots rootsT) setRoots(n int) {
  32. for i := n; i >= 0 && nil == roots.roots[i]; i-- { // TODO tmp i<=len(r)
  33. r := ff.NewElement().SetBigInt(big.NewInt(1))
  34. nroots := 1 << i
  35. var rootsi []*ff.Element
  36. for j := 0; j < nroots; j++ {
  37. rootsi = append(rootsi, r)
  38. r = ff.NewElement().Mul(r, roots.w[i])
  39. }
  40. roots.roots[i] = rootsi
  41. }
  42. }
  43. func fftroots(roots rootsT, pall []*ff.Element, bits, offset, step int) []*ff.Element {
  44. n := 1 << bits
  45. if n == 1 {
  46. return []*ff.Element{pall[offset]}
  47. } else if n == 2 {
  48. return []*ff.Element{
  49. ff.NewElement().Add(pall[offset], pall[offset+step]), // TODO tmp
  50. ff.NewElement().Sub(pall[offset], pall[offset+step]),
  51. }
  52. }
  53. ndiv2 := n >> 1
  54. p1 := fftroots(roots, pall, bits-1, offset, step*2)
  55. p2 := fftroots(roots, pall, bits-1, offset+step, step*2)
  56. out := make([]*ff.Element, n)
  57. for i := 0; i < ndiv2; i++ {
  58. out[i] = ff.NewElement().Add(p1[i], ff.NewElement().Mul(roots.roots[bits][i], p2[i]))
  59. out[i+ndiv2] = ff.NewElement().Sub(p1[i], ff.NewElement().Mul(roots.roots[bits][i], p2[i]))
  60. }
  61. return out
  62. }
  63. func fft(p []*ff.Element) []*ff.Element {
  64. if len(p) <= 1 {
  65. return p
  66. }
  67. bits := math.Log2(float64(len(p)-1)) + 1
  68. roots := newRootsT()
  69. roots.setRoots(int(bits))
  70. m := 1 << int(bits)
  71. ep := extend(p, m)
  72. res := fftroots(roots, ep, int(bits), 0, 1)
  73. return res
  74. }
  75. func ifft(p []*ff.Element) []*ff.Element {
  76. res := fft(p)
  77. bits := math.Log2(float64(len(p)-1)) + 1
  78. m := 1 << int(bits)
  79. twoinvm := ff.NewElement().SetBigInt(fInv(fMul(big.NewInt(1), big.NewInt(int64(m)))))
  80. var resn []*ff.Element
  81. for i := 0; i < m; i++ {
  82. resn = append(resn, ff.NewElement().Mul(res[(m-i)%m], twoinvm))
  83. }
  84. return resn
  85. }
  86. func extend(p []*ff.Element, e int) []*ff.Element {
  87. if e == len(p) {
  88. return p
  89. }
  90. z := arrayOfZeroesE(e - len(p))
  91. return append(p, z...)
  92. }