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.

235 lines
7.9 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. /*
  2. Copyright 2018 0kims association.
  3. This file is part of snarkjs.
  4. snarkjs is a free software: you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License as published by the
  6. Free Software Foundation, either version 3 of the License, or (at your option)
  7. any later version.
  8. snarkjs is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. more details.
  12. You should have received a copy of the GNU General Public License along with
  13. snarkjs. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. const bigInt = require("./bigint.js");
  16. const BN128 = require("./bn128.js");
  17. const PolField = require("./polfield.js");
  18. const ZqField = require("./zqfield.js");
  19. const bn128 = new BN128();
  20. const G1 = bn128.G1;
  21. const G2 = bn128.G2;
  22. const PolF = new PolField(new ZqField(bn128.r));
  23. const F = new ZqField(bn128.r);
  24. module.exports = function setup(circuit) {
  25. const setup = {
  26. vk_proof : {
  27. nVars: circuit.nVars,
  28. nPublic: circuit.nPubInputs + circuit.nOutputs
  29. },
  30. vk_verifier: {
  31. nPublic: circuit.nPubInputs + circuit.nOutputs
  32. },
  33. toxic: {}
  34. };
  35. setup.vk_proof.domainBits = PolF.log2(circuit.nConstraints + circuit.nPubInputs + circuit.nOutputs +1 -1) +1;
  36. setup.vk_proof.domainSize = 1 << setup.vk_proof.domainBits;
  37. calculatePolinomials(setup, circuit);
  38. setup.toxic.t = F.random();
  39. calculateEncriptedValuesAtT(setup, circuit);
  40. calculateHexps(setup, circuit);
  41. return setup;
  42. };
  43. function calculatePolinomials(setup, circuit) {
  44. setup.vk_proof.polsA = new Array(circuit.nVars);
  45. setup.vk_proof.polsB = new Array(circuit.nVars);
  46. setup.vk_proof.polsC = new Array(circuit.nVars);
  47. for (let i=0; i<circuit.nVars; i++) {
  48. setup.vk_proof.polsA[i] = {};
  49. setup.vk_proof.polsB[i] = {};
  50. setup.vk_proof.polsC[i] = {};
  51. }
  52. for (let c=0; c<circuit.nConstraints; c++) {
  53. for (let s in circuit.constraints[c][0]) {
  54. setup.vk_proof.polsA[s][c] = bigInt(circuit.constraints[c][0][s]);
  55. }
  56. for (let s in circuit.constraints[c][1]) {
  57. setup.vk_proof.polsB[s][c] = bigInt(circuit.constraints[c][1][s]);
  58. }
  59. for (let s in circuit.constraints[c][2]) {
  60. setup.vk_proof.polsC[s][c] = bigInt(circuit.constraints[c][2][s]);
  61. }
  62. }
  63. /**
  64. * add and process the constraints
  65. * input_i * 0 = 0
  66. * to ensure soundness of input consistency
  67. */
  68. for (let i = 0; i < circuit.nPubInputs + circuit.nOutputs + 1; ++i)
  69. {
  70. setup.vk_proof.polsA[i][circuit.nConstraints + i] = F.one;
  71. }
  72. }
  73. function calculateValuesAtT(setup, circuit) {
  74. const z_t = PolF.computeVanishingPolinomial(setup.vk_proof.domainBits, setup.toxic.t);
  75. const u = PolF.evaluateLagrangePolynomials(setup.vk_proof.domainBits, setup.toxic.t);
  76. const a_t = new Array(circuit.nVars).fill(F.zero);
  77. const b_t = new Array(circuit.nVars).fill(F.zero);
  78. const c_t = new Array(circuit.nVars).fill(F.zero);
  79. // TODO: substitute setup.polsA for coeficients
  80. for (let s=0; s<circuit.nVars; s++) {
  81. for (let c in setup.vk_proof.polsA[s]) {
  82. a_t[s] = F.add(a_t[s], F.mul(u[c], setup.vk_proof.polsA[s][c]));
  83. }
  84. for (let c in setup.vk_proof.polsB[s]) {
  85. b_t[s] = F.add(b_t[s], F.mul(u[c], setup.vk_proof.polsB[s][c]));
  86. }
  87. for (let c in setup.vk_proof.polsC[s]) {
  88. c_t[s] = F.add(c_t[s], F.mul(u[c], setup.vk_proof.polsC[s][c]));
  89. }
  90. }
  91. return {a_t, b_t, c_t, z_t};
  92. }
  93. function calculateEncriptedValuesAtT(setup, circuit) {
  94. const v = calculateValuesAtT(setup, circuit);
  95. setup.vk_proof.A = new Array(circuit.nVars+1);
  96. setup.vk_proof.B = new Array(circuit.nVars+1);
  97. setup.vk_proof.C = new Array(circuit.nVars+1);
  98. setup.vk_proof.Ap = new Array(circuit.nVars+1);
  99. setup.vk_proof.Bp = new Array(circuit.nVars+1);
  100. setup.vk_proof.Cp = new Array(circuit.nVars+1);
  101. setup.vk_proof.Kp = new Array(circuit.nVars+3);
  102. setup.vk_verifier.A = new Array(circuit.nPublic);
  103. setup.toxic.ka = F.random();
  104. setup.toxic.kb = F.random();
  105. setup.toxic.kc = F.random();
  106. setup.toxic.ra = F.random();
  107. setup.toxic.rb = F.random();
  108. setup.toxic.rc = F.mul(setup.toxic.ra, setup.toxic.rb);
  109. setup.toxic.kbeta = F.random();
  110. setup.toxic.kgamma = F.random();
  111. const gb = F.mul(setup.toxic.kbeta, setup.toxic.kgamma);
  112. setup.vk_verifier.vk_a = G2.affine(G2.mulScalar( G2.g, setup.toxic.ka));
  113. setup.vk_verifier.vk_b = G1.affine(G1.mulScalar( G1.g, setup.toxic.kb));
  114. setup.vk_verifier.vk_c = G2.affine(G2.mulScalar( G2.g, setup.toxic.kc));
  115. setup.vk_verifier.vk_gb_1 = G1.affine(G1.mulScalar( G1.g, gb));
  116. setup.vk_verifier.vk_gb_2 = G2.affine(G2.mulScalar( G2.g, gb));
  117. setup.vk_verifier.vk_g = G2.affine(G2.mulScalar( G2.g, setup.toxic.kgamma));
  118. for (let s=0; s<circuit.nVars; s++) {
  119. // A[i] = G1 * polA(t)
  120. const raat = F.mul(setup.toxic.ra, v.a_t[s]);
  121. const A = G1.affine(G1.mulScalar(G1.g, raat));
  122. setup.vk_proof.A[s] = A;
  123. if (s <= setup.vk_proof.nPublic) {
  124. setup.vk_verifier.A[s]=A;
  125. }
  126. // B1[i] = G1 * polB(t)
  127. const rbbt = F.mul(setup.toxic.rb, v.b_t[s]);
  128. const B1 = G1.affine(G1.mulScalar(G1.g, rbbt));
  129. // B2[i] = G2 * polB(t)
  130. const B2 = G2.affine(G2.mulScalar(G2.g, rbbt));
  131. setup.vk_proof.B[s]=B2;
  132. // C[i] = G1 * polC(t)
  133. const rcct = F.mul(setup.toxic.rc, v.c_t[s]);
  134. const C = G1.affine(G1.mulScalar( G1.g, rcct));
  135. setup.vk_proof.C[s] =C;
  136. // K = G1 * (A+B+C)
  137. const kt = F.affine(F.add(F.add(raat, rbbt), rcct));
  138. const K = G1.affine(G1.mulScalar( G1.g, kt));
  139. /*
  140. // Comment this lines to improve the process
  141. const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
  142. if (!G1.equals(K, Ktest)) {
  143. console.log ("=====FAIL======");
  144. }
  145. */
  146. setup.vk_proof.Ap[s] = G1.affine(G1.mulScalar(A, setup.toxic.ka));
  147. setup.vk_proof.Bp[s] = G1.affine(G1.mulScalar(B1, setup.toxic.kb));
  148. setup.vk_proof.Cp[s] = G1.affine(G1.mulScalar(C, setup.toxic.kc));
  149. setup.vk_proof.Kp[s] = G1.affine(G1.mulScalar(K, setup.toxic.kbeta));
  150. }
  151. // Extra coeficients
  152. const A = G1.mulScalar( G1.g, F.mul(setup.toxic.ra, v.z_t));
  153. setup.vk_proof.A[circuit.nVars] = G1.affine(A);
  154. setup.vk_proof.Ap[circuit.nVars] = G1.affine(G1.mulScalar(A, setup.toxic.ka));
  155. const B1 = G1.mulScalar( G1.g, F.mul(setup.toxic.rb, v.z_t));
  156. const B2 = G2.mulScalar( G2.g, F.mul(setup.toxic.rb, v.z_t));
  157. setup.vk_proof.B[circuit.nVars] = G2.affine(B2);
  158. setup.vk_proof.Bp[circuit.nVars] = G1.affine(G1.mulScalar(B1, setup.toxic.kb));
  159. const C = G1.mulScalar( G1.g, F.mul(setup.toxic.rc, v.z_t));
  160. setup.vk_proof.C[circuit.nVars] = G1.affine(C);
  161. setup.vk_proof.Cp[circuit.nVars] = G1.affine(G1.mulScalar(C, setup.toxic.kc));
  162. setup.vk_proof.Kp[circuit.nVars ] = G1.affine(G1.mulScalar(A, setup.toxic.kbeta));
  163. setup.vk_proof.Kp[circuit.nVars+1] = G1.affine(G1.mulScalar(B1, setup.toxic.kbeta));
  164. setup.vk_proof.Kp[circuit.nVars+2] = G1.affine(G1.mulScalar(C, setup.toxic.kbeta));
  165. // setup.vk_verifier.A[0] = G1.affine(G1.add(setup.vk_verifier.A[0], setup.vk_proof.A[circuit.nVars]));
  166. // vk_z
  167. setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
  168. G2.g,
  169. F.mul(setup.toxic.rc, v.z_t)));
  170. }
  171. function calculateHexps(setup) {
  172. const maxH = setup.vk_proof.domainSize+1;
  173. setup.vk_proof.hExps = new Array(maxH);
  174. setup.vk_proof.hExps[0] = G1.g;
  175. let eT = setup.toxic.t;
  176. for (let i=1; i<maxH; i++) {
  177. setup.vk_proof.hExps[i] = G1.affine(G1.mulScalar(G1.g, eT));
  178. eT = F.mul(eT, setup.toxic.t);
  179. }
  180. }