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.

185 lines
4.2 KiB

  1. package r1csqap
  2. import (
  3. "math/big"
  4. "github.com/arnaucube/go-snark/fields"
  5. )
  6. func Transpose(matrix [][]*big.Int) [][]*big.Int {
  7. var r [][]*big.Int
  8. for i := 0; i < len(matrix[0]); i++ {
  9. var row []*big.Int
  10. for j := 0; j < len(matrix); j++ {
  11. row = append(row, matrix[j][i])
  12. }
  13. r = append(r, row)
  14. }
  15. return r
  16. }
  17. func ArrayOfBigZeros(num int) []*big.Int {
  18. bigZero := big.NewInt(int64(0))
  19. var r []*big.Int
  20. for i := 0; i < num; i++ {
  21. r = append(r, bigZero)
  22. }
  23. return r
  24. }
  25. type PolynomialField struct {
  26. F fields.Fq
  27. }
  28. func NewPolynomialField(f fields.Fq) PolynomialField {
  29. return PolynomialField{
  30. f,
  31. }
  32. }
  33. func (pf PolynomialField) Mul(a, b []*big.Int) []*big.Int {
  34. r := ArrayOfBigZeros(len(a) + len(b) - 1)
  35. for i := 0; i < len(a); i++ {
  36. for j := 0; j < len(b); j++ {
  37. r[i+j] = pf.F.Add(
  38. r[i+j],
  39. pf.F.Mul(a[i], b[j]))
  40. }
  41. }
  42. return r
  43. }
  44. func (pf PolynomialField) Div(a, b []*big.Int) ([]*big.Int, []*big.Int) {
  45. // https://en.wikipedia.org/wiki/Division_algorithm
  46. r := ArrayOfBigZeros(len(a) - len(b) + 1)
  47. rem := a
  48. for len(rem) >= len(b) {
  49. l := pf.F.Div(rem[len(rem)-1], b[len(b)-1])
  50. pos := len(rem) - len(b)
  51. r[pos] = l
  52. aux := ArrayOfBigZeros(pos)
  53. aux1 := append(aux, l)
  54. aux2 := pf.Sub(rem, pf.Mul(b, aux1))
  55. rem = aux2[:len(aux2)-1]
  56. }
  57. return r, rem
  58. }
  59. func max(a, b int) int {
  60. if a > b {
  61. return a
  62. }
  63. return b
  64. }
  65. func (pf PolynomialField) Add(a, b []*big.Int) []*big.Int {
  66. r := ArrayOfBigZeros(max(len(a), len(b)))
  67. for i := 0; i < len(a); i++ {
  68. r[i] = pf.F.Add(r[i], a[i])
  69. }
  70. for i := 0; i < len(b); i++ {
  71. r[i] = pf.F.Add(r[i], b[i])
  72. }
  73. return r
  74. }
  75. func (pf PolynomialField) Sub(a, b []*big.Int) []*big.Int {
  76. r := ArrayOfBigZeros(max(len(a), len(b)))
  77. for i := 0; i < len(a); i++ {
  78. r[i] = pf.F.Add(r[i], a[i])
  79. }
  80. for i := 0; i < len(b); i++ {
  81. r[i] = pf.F.Sub(r[i], b[i])
  82. }
  83. return r
  84. }
  85. func (pf PolynomialField) Eval(v []*big.Int, x *big.Int) *big.Int {
  86. r := big.NewInt(int64(0))
  87. for i := 0; i < len(v); i++ {
  88. // xi := FloatPow(x, i)
  89. xi := pf.F.Exp(x, big.NewInt(int64(i)))
  90. elem := pf.F.Mul(v[i], xi)
  91. r = pf.F.Add(r, elem)
  92. }
  93. return r
  94. }
  95. func (pf PolynomialField) NewPolZeroAt(pointPos, totalPoints int, height *big.Int) []*big.Int {
  96. fac := 1
  97. for i := 1; i < totalPoints+1; i++ {
  98. if i != pointPos {
  99. fac = fac * (pointPos - i)
  100. }
  101. }
  102. facBig := big.NewInt(int64(fac))
  103. hf := pf.F.Div(height, facBig)
  104. r := []*big.Int{hf}
  105. for i := 1; i < totalPoints+1; i++ {
  106. if i != pointPos {
  107. ineg := big.NewInt(int64(-i))
  108. b1 := big.NewInt(int64(1))
  109. r = pf.Mul(r, []*big.Int{ineg, b1})
  110. }
  111. }
  112. return r
  113. }
  114. func (pf PolynomialField) LagrangeInterpolation(v []*big.Int) []*big.Int {
  115. // https://en.wikipedia.org/wiki/Lagrange_polynomial
  116. var r []*big.Int
  117. for i := 0; i < len(v); i++ {
  118. r = pf.Add(r, pf.NewPolZeroAt(i+1, len(v), v[i]))
  119. }
  120. //
  121. return r
  122. }
  123. func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) ([][]*big.Int, [][]*big.Int, [][]*big.Int, []*big.Int) {
  124. aT := Transpose(a)
  125. bT := Transpose(b)
  126. cT := Transpose(c)
  127. var alphas [][]*big.Int
  128. for i := 0; i < len(aT); i++ {
  129. alphas = append(alphas, pf.LagrangeInterpolation(aT[i]))
  130. }
  131. var betas [][]*big.Int
  132. for i := 0; i < len(bT); i++ {
  133. betas = append(betas, pf.LagrangeInterpolation(bT[i]))
  134. }
  135. var gammas [][]*big.Int
  136. for i := 0; i < len(cT); i++ {
  137. gammas = append(gammas, pf.LagrangeInterpolation(cT[i]))
  138. }
  139. z := []*big.Int{big.NewInt(int64(1))}
  140. for i := 1; i < len(aT[0])+1; i++ {
  141. ineg := big.NewInt(int64(-i))
  142. b1 := big.NewInt(int64(1))
  143. z = pf.Mul(z, []*big.Int{ineg, b1})
  144. }
  145. return alphas, betas, gammas, z
  146. }
  147. func (pf PolynomialField) CombinePolynomials(r []*big.Int, ap, bp, cp [][]*big.Int) ([]*big.Int, []*big.Int, []*big.Int, []*big.Int) {
  148. var alpha []*big.Int
  149. for i := 0; i < len(r); i++ {
  150. m := pf.Mul([]*big.Int{r[i]}, ap[i])
  151. alpha = pf.Add(alpha, m)
  152. }
  153. var beta []*big.Int
  154. for i := 0; i < len(r); i++ {
  155. m := pf.Mul([]*big.Int{r[i]}, bp[i])
  156. beta = pf.Add(beta, m)
  157. }
  158. var gamma []*big.Int
  159. for i := 0; i < len(r); i++ {
  160. m := pf.Mul([]*big.Int{r[i]}, cp[i])
  161. gamma = pf.Add(gamma, m)
  162. }
  163. px := pf.Sub(pf.Mul(alpha, beta), gamma)
  164. return alpha, beta, gamma, px
  165. }
  166. func (pf PolynomialField) DivisorPolinomial(px, z []*big.Int) []*big.Int {
  167. quo, _ := pf.Div(px, z)
  168. return quo
  169. }