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.

112 lines
2.3 KiB

  1. # R1CS-to-CCS (https://eprint.iacr.org/2023/552) Sage prototype
  2. # utils
  3. def matrix_vector_product(M, v):
  4. n = M.nrows()
  5. r = [F(0)] * n
  6. for i in range(0, n):
  7. for j in range(0, M.ncols()):
  8. r[i] += M[i][j] * v[j]
  9. return r
  10. def hadamard_product(a, b):
  11. n = len(a)
  12. r = [None] * n
  13. for i in range(0, n):
  14. r[i] = a[i] * b[i]
  15. return r
  16. def vec_add(a, b):
  17. n = len(a)
  18. r = [None] * n
  19. for i in range(0, n):
  20. r[i] = a[i] + b[i]
  21. return r
  22. def vec_elem_mul(a, s):
  23. r = [None] * len(a)
  24. for i in range(0, len(a)):
  25. r[i] = a[i] * s
  26. return r
  27. # end of utils
  28. # can use any finite field, using a small one for the example
  29. F = GF(101)
  30. # R1CS matrices for: x^3 + x + 5 = y (example from article
  31. # https://www.vitalik.ca/general/2016/12/10/qap.html )
  32. A = matrix([
  33. [F(0), 1, 0, 0, 0, 0],
  34. [0, 0, 0, 1, 0, 0],
  35. [0, 1, 0, 0, 1, 0],
  36. [5, 0, 0, 0, 0, 1],
  37. ])
  38. B = matrix([
  39. [F(0), 1, 0, 0, 0, 0],
  40. [0, 1, 0, 0, 0, 0],
  41. [1, 0, 0, 0, 0, 0],
  42. [1, 0, 0, 0, 0, 0],
  43. ])
  44. C = matrix([
  45. [F(0), 0, 0, 1, 0, 0],
  46. [0, 0, 0, 0, 1, 0],
  47. [0, 0, 0, 0, 0, 1],
  48. [0, 0, 1, 0, 0, 0],
  49. ])
  50. print("R1CS matrices:")
  51. print("A:", A)
  52. print("B:", B)
  53. print("C:", C)
  54. z = [F(1), 3, 35, 9, 27, 30]
  55. print("z:", z)
  56. assert len(z) == A.ncols()
  57. n = A.ncols() # == len(z)
  58. m = A.nrows()
  59. # l = len(io) # not used for now
  60. # check R1CS relation
  61. Az = matrix_vector_product(A, z)
  62. Bz = matrix_vector_product(B, z)
  63. Cz = matrix_vector_product(C, z)
  64. print("\nR1CS relation check (Az ∘ Bz == Cz):", hadamard_product(Az, Bz) == Cz)
  65. assert hadamard_product(Az, Bz) == Cz
  66. # Translate R1CS into CCS:
  67. print("\ntranslate R1CS into CCS:")
  68. # fixed parameters (and n, m, l are direct from R1CS)
  69. t=3
  70. q=2
  71. d=2
  72. S1=[0,1]
  73. S2=[2]
  74. S = [S1, S2]
  75. c0=1
  76. c1=-1
  77. c = [c0, c1]
  78. M = [A, B, C]
  79. print("CCS values:")
  80. print("n: %s, m: %s, t: %s, q: %s, d: %s" % (n, m, t, q, d))
  81. print("M:", M)
  82. print("z:", z)
  83. print("S:", S)
  84. print("c:", c)
  85. # check CCS relation (this is agnostic to R1CS, for any CCS instance)
  86. r = [F(0)] * m
  87. for i in range(0, q):
  88. hadamard_output = [F(1)]*m
  89. for j in S[i]:
  90. hadamard_output = hadamard_product(hadamard_output,
  91. matrix_vector_product(M[j], z))
  92. r = vec_add(r, vec_elem_mul(hadamard_output, c[i]))
  93. print("\nCCS relation check (∑ cᵢ ⋅ ◯ Mⱼ z == 0):", r == [0]*m)
  94. assert r == [0]*m