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.

231 lines
5.9 KiB

5 years ago
5 years ago
  1. package r1csqap
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math/big"
  6. "github.com/mottla/go-snark/fields"
  7. )
  8. // Transpose transposes the *big.Int matrix
  9. func Transpose(matrix [][]*big.Int) [][]*big.Int {
  10. var r [][]*big.Int
  11. for i := 0; i < len(matrix[0]); i++ {
  12. var row []*big.Int
  13. for j := 0; j < len(matrix); j++ {
  14. row = append(row, matrix[j][i])
  15. }
  16. r = append(r, row)
  17. }
  18. return r
  19. }
  20. // ArrayOfBigZeros creates a *big.Int array with n elements to zero
  21. func ArrayOfBigZeros(num int) []*big.Int {
  22. bigZero := big.NewInt(int64(0))
  23. var r []*big.Int
  24. for i := 0; i < num; i++ {
  25. r = append(r, bigZero)
  26. }
  27. return r
  28. }
  29. func BigArraysEqual(a, b []*big.Int) bool {
  30. if len(a) != len(b) {
  31. return false
  32. }
  33. for i := 0; i < len(a); i++ {
  34. if !bytes.Equal(a[i].Bytes(), b[i].Bytes()) {
  35. return false
  36. }
  37. }
  38. return true
  39. }
  40. // PolynomialField is the Polynomial over a Finite Field where the polynomial operations are performed
  41. type PolynomialField struct {
  42. F fields.Fq
  43. }
  44. // NewPolynomialField creates a new PolynomialField with the given FiniteField
  45. func NewPolynomialField(f fields.Fq) PolynomialField {
  46. return PolynomialField{
  47. f,
  48. }
  49. }
  50. // Mul multiplies two polinomials over the Finite Field
  51. func (pf PolynomialField) Mul(a, b []*big.Int) []*big.Int {
  52. r := ArrayOfBigZeros(len(a) + len(b) - 1)
  53. for i := 0; i < len(a); i++ {
  54. for j := 0; j < len(b); j++ {
  55. r[i+j] = pf.F.Add(
  56. r[i+j],
  57. pf.F.Mul(a[i], b[j]))
  58. }
  59. }
  60. return r
  61. }
  62. // Div divides two polinomials over the Finite Field, returning the result and the remainder
  63. func (pf PolynomialField) Div(a, b []*big.Int) ([]*big.Int, []*big.Int) {
  64. // https://en.wikipedia.org/wiki/Division_algorithm
  65. r := ArrayOfBigZeros(len(a) - len(b) + 1)
  66. rem := a
  67. for len(rem) >= len(b) {
  68. l := pf.F.Div(rem[len(rem)-1], b[len(b)-1])
  69. pos := len(rem) - len(b)
  70. r[pos] = l
  71. aux := ArrayOfBigZeros(pos)
  72. aux1 := append(aux, l)
  73. aux2 := pf.Sub(rem, pf.Mul(b, aux1))
  74. rem = aux2[:len(aux2)-1]
  75. }
  76. return r, rem
  77. }
  78. func max(a, b int) int {
  79. if a > b {
  80. return a
  81. }
  82. return b
  83. }
  84. // Add adds two polinomials over the Finite Field
  85. func (pf PolynomialField) Add(a, b []*big.Int) []*big.Int {
  86. r := ArrayOfBigZeros(max(len(a), len(b)))
  87. for i := 0; i < len(a); i++ {
  88. r[i] = pf.F.Add(r[i], a[i])
  89. }
  90. for i := 0; i < len(b); i++ {
  91. r[i] = pf.F.Add(r[i], b[i])
  92. }
  93. return r
  94. }
  95. // Sub subtracts two polinomials over the Finite Field
  96. func (pf PolynomialField) Sub(a, b []*big.Int) []*big.Int {
  97. r := ArrayOfBigZeros(max(len(a), len(b)))
  98. for i := 0; i < len(a); i++ {
  99. r[i] = pf.F.Add(r[i], a[i])
  100. }
  101. for i := 0; i < len(b); i++ {
  102. r[i] = pf.F.Sub(r[i], b[i])
  103. }
  104. return r
  105. }
  106. // Eval evaluates the polinomial over the Finite Field at the given value x
  107. func (pf PolynomialField) Eval(v []*big.Int, x *big.Int) *big.Int {
  108. r := big.NewInt(int64(0))
  109. for i := 0; i < len(v); i++ {
  110. xi := pf.F.Exp(x, big.NewInt(int64(i)))
  111. elem := pf.F.Mul(v[i], xi)
  112. r = pf.F.Add(r, elem)
  113. }
  114. return r
  115. }
  116. // NewPolZeroAt generates a new polynomial that has value zero at the given value
  117. func (pf PolynomialField) NewPolZeroAt(pointPos, totalPoints int, height *big.Int) []*big.Int {
  118. //todo note that this will blow up. big may be necessary
  119. fac := 1
  120. //(xj-x0)(xj-x1)..(xj-x_j-1)(xj-x_j+1)..(x_j-x_k)
  121. for i := 1; i < totalPoints+1; i++ {
  122. if i != pointPos {
  123. fac = fac * (pointPos - i)
  124. }
  125. }
  126. facBig := big.NewInt(int64(fac))
  127. hf := pf.F.Div(height, facBig)
  128. r := []*big.Int{hf}
  129. for i := 1; i < totalPoints+1; i++ {
  130. if i != pointPos {
  131. ineg := big.NewInt(int64(-i))
  132. //is b1 necessary?
  133. b1 := big.NewInt(int64(1))
  134. r = pf.Mul(r, []*big.Int{ineg, b1})
  135. }
  136. }
  137. return r
  138. }
  139. // LagrangeInterpolation performs the Lagrange Interpolation / Lagrange Polynomials operation
  140. func (pf PolynomialField) LagrangeInterpolation(v []*big.Int) []*big.Int {
  141. // https://en.wikipedia.org/wiki/Lagrange_polynomial
  142. var r []*big.Int
  143. for i := 0; i < len(v); i++ {
  144. r = pf.Add(r, pf.NewPolZeroAt(i+1, len(v), v[i]))
  145. //r = pf.Mul(v[i], pf.NewPolZeroAt(i+1, len(v), v[i]))
  146. }
  147. //
  148. return r
  149. }
  150. // R1CSToQAP converts the R1CS values to the QAP values
  151. //it uses Lagrange interpolation to to fit a polynomial through each slice. The x coordinate
  152. //is simply a linear increment starting at 1
  153. //within this process, the polynomial is evaluated at position 0
  154. //so an alpha/beta/gamma value is the polynomial evaluated at 0
  155. // the domain polynomial therefor is (-1+x)(-2+x)...(-n+x)
  156. func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) (alphas [][]*big.Int, betas [][]*big.Int, gammas [][]*big.Int, domain []*big.Int) {
  157. aT := Transpose(a)
  158. bT := Transpose(b)
  159. cT := Transpose(c)
  160. fmt.Println(aT)
  161. fmt.Println(bT)
  162. fmt.Println(cT)
  163. for i := 0; i < len(aT); i++ {
  164. alphas = append(alphas, pf.LagrangeInterpolation(aT[i]))
  165. }
  166. for i := 0; i < len(bT); i++ {
  167. betas = append(betas, pf.LagrangeInterpolation(bT[i]))
  168. }
  169. for i := 0; i < len(cT); i++ {
  170. gammas = append(gammas, pf.LagrangeInterpolation(cT[i]))
  171. }
  172. //it used to range till len(alphas)-1, but this was wrong.
  173. z := []*big.Int{big.NewInt(int64(1))}
  174. for i := 1; i < len(a); i++ {
  175. z = pf.Mul(
  176. z,
  177. []*big.Int{
  178. pf.F.Neg(
  179. big.NewInt(int64(i))),
  180. big.NewInt(int64(1)),
  181. })
  182. }
  183. return alphas, betas, gammas, z
  184. }
  185. // CombinePolynomials combine the given polynomials arrays into one, also returns the P(x)
  186. func (pf PolynomialField) CombinePolynomials(r []*big.Int, ap, bp, cp [][]*big.Int) ([]*big.Int, []*big.Int, []*big.Int, []*big.Int) {
  187. var ax []*big.Int
  188. for i := 0; i < len(r); i++ {
  189. m := pf.Mul([]*big.Int{r[i]}, ap[i])
  190. ax = pf.Add(ax, m)
  191. }
  192. var bx []*big.Int
  193. for i := 0; i < len(r); i++ {
  194. m := pf.Mul([]*big.Int{r[i]}, bp[i])
  195. bx = pf.Add(bx, m)
  196. }
  197. var cx []*big.Int
  198. for i := 0; i < len(r); i++ {
  199. m := pf.Mul([]*big.Int{r[i]}, cp[i])
  200. cx = pf.Add(cx, m)
  201. }
  202. px := pf.Sub(pf.Mul(ax, bx), cx)
  203. return ax, bx, cx, px
  204. }
  205. // DivisorPolynomial returns the divisor polynomial given two polynomials
  206. func (pf PolynomialField) DivisorPolynomial(px, z []*big.Int) []*big.Int {
  207. quo, _ := pf.Div(px, z)
  208. return quo
  209. }