qap.sage 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #!/usr/bin/env sage
  2. """
  3. The following code is taken from the examples outlined in the article:
  4. "R1CS and QAP - From Zero to Hero with Finite Fields & sagemath".
  5. (https://risencrypto.github.io/R1CSQAP/). The Sage examples begin at the
  6. end of the section called "Conversion to Arithemetic Circuits & then R1CS".
  7. Note that this example uses the same polynomial as the file qap.py
  8. in this directory.
  9. """
  10. header = """
  11. This script demonstrates the conversion of a set of R1CS matrices to QAP form.
  12. For more information, read the code comments in the file for this script.
  13. """
  14. print(header)
  15. # Define the R1CS matrices over the finite field GF(41)
  16. F41 = GF(41)
  17. L = Matrix(F41, [
  18. [0,1,0,0,0,0],
  19. [0,0,0,1,0,0],
  20. [0,1,0,0,1,0],
  21. [5,0,0,0,0,1],]
  22. )
  23. R = Matrix(F41, [
  24. [0,1,0,0,0,0],
  25. [0,1,0,0,0,0],
  26. [1,0,0,0,0,0],
  27. [1,0,0,0,0,0,],])
  28. O = Matrix(F41, [
  29. [0,0,0,1,0,0],
  30. [0,0,0,0,1,0],
  31. [0,0,0,0,0,1],
  32. [0,0,1,0,0,0,],])
  33. # Print R1CS matrices
  34. print(L)
  35. print()
  36. print(R)
  37. print()
  38. print(O)
  39. print()
  40. # Debug: this section should print 35*x^3 + 36*x^2 + 16*x + 36
  41. # It represents the Lagrange interpolation for the first column of matrix L.
  42. R41.<x> = PolynomialRing(F41)
  43. points = [(1,0),(2,0),(3,0),(4,5)]
  44. R41.lagrange_polynomial(points)
  45. # Convert matrices L, R, and O to QAP form using Lagrange interpolation, i.e.
  46. # repeat the above lines of code for every column of every matrix.
  47. M = [L, R, O]
  48. PolyM = []
  49. for m in M:
  50. PolyList = []
  51. for i in range(m.ncols()):
  52. points = []
  53. for j in range(m.nrows()):
  54. points.append([j+1,m[j,i]])
  55. Poly = R41.lagrange_polynomial(points).coefficients(sparse=False)
  56. if(len(Poly) < m.nrows()):
  57. # if degree of the polynomial is less than 4
  58. # we add zeroes to represent the missed out terms
  59. dif = m.nrows() - len(Poly)
  60. for c in range(dif):
  61. Poly.append(0);
  62. PolyList.append(Poly)
  63. PolyM.append(Matrix(F41, PolyList))
  64. # Print the new matrices containing QAP form polynomials.
  65. # Each matrix should have 6 polynomials. This corresponds to the number of elements
  66. # in the solution vector (which is 6 using the example from the article).
  67. print(PolyM[0])
  68. print()
  69. print(PolyM[1])
  70. print()
  71. print(PolyM[2])
  72. print()
  73. # Solution vector (defined over the finite field). This is known only to the prover.
  74. S = vector(F41,[1, 3, 35, 9, 27, 30])
  75. # Create the L, Rx & Ox polynomials. Perform the dot product of the solution vector
  76. # with each of the matrices obtained in the previous step.
  77. Lx = R41(list(S*PolyM[0]))
  78. Rx = R41(list(S*PolyM[1]))
  79. Ox = R41(list(S*PolyM[2]))
  80. print("Lx = " + str(Lx))
  81. print("Rx = " + str(Rx))
  82. print("Ox = " + str(Ox))
  83. # Multiply polynomials Lx and Rx and subtract Ox. This is how we check the
  84. # constraints of the circuit and corresponds to checking the vectors in
  85. # the R1CS step.
  86. # Note: the verifier does not know the polynomial T.
  87. T = Lx*Rx - Ox
  88. print("T(x) = ", end="")
  89. print(T)
  90. # Check Tx at x = 1, 2, 3, 4. The output of each should be 0.
  91. print("T(1) = " + str(T(1)))
  92. print("T(2) = " + str(T(2)))
  93. print("T(3) = " + str(T(3)))
  94. print("T(4) = " + str(T(4)))
  95. # This polynomial is known to both the prover and verifier
  96. Z = R41((x-1)*(x-2)*(x-3)*(x-4))
  97. H = T.quo_rem(Z)
  98. print("Quotient of Z/T = ", end="")
  99. print(H[0])
  100. # The remainder here must be 0, indicating that Z exactly divides T.
  101. print("Remainder of Z/T = ", end="")
  102. print(H[1])