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.

191 lines
6.1 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
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 __P__ = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
  17. const __MASK__ = bigInt("28948022309329048855892746252171976963317496166410141009864396001978282409983"); // 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  18. const calculateWitness = require("./calculateWitness.js");
  19. module.exports = class Circuit {
  20. constructor(circuitDef) {
  21. this.nPubInputs = circuitDef.nPubInputs;
  22. this.nPrvInputs = circuitDef.nPrvInputs;
  23. this.nInputs = circuitDef.nInputs;
  24. this.nOutputs = circuitDef.nOutputs;
  25. this.nVars = circuitDef.nVars;
  26. this.nSignals = circuitDef.nSignals;
  27. this.nConstants = circuitDef.nConstants;
  28. this.nConstraints = circuitDef.constraints.length;
  29. this.signalName2Idx = circuitDef.signalName2Idx;
  30. this.components = circuitDef.components;
  31. this.componentName2Idx = circuitDef.componentName2Idx;
  32. this.signals = circuitDef.signals;
  33. this.constraints = circuitDef.constraints;
  34. this.templates = {};
  35. for (let t in circuitDef.templates) {
  36. this.templates[t] = eval(" const __f= " +circuitDef.templates[t] + "\n__f");
  37. }
  38. this.functions = {};
  39. for (let f in circuitDef.functions) {
  40. this.functions[f] = {
  41. params: circuitDef.functions[f].params,
  42. func: eval(" const __f= " +circuitDef.functions[f].func + "\n__f;")
  43. };
  44. }
  45. }
  46. calculateWitness(input, log) {
  47. return calculateWitness(this, input, log);
  48. }
  49. checkWitness(w) {
  50. const evalLC = (lc, w) => {
  51. let acc = bigInt(0);
  52. for (let k in lc) {
  53. acc= acc.add(bigInt(w[k]).mul(bigInt(lc[k]))).mod(__P__);
  54. }
  55. return acc;
  56. }
  57. const checkConstraint = (ct, w) => {
  58. const a=evalLC(ct[0],w);
  59. const b=evalLC(ct[1],w);
  60. const c=evalLC(ct[2],w);
  61. const res = (a.mul(b).sub(c)).affine(__P__);
  62. if (!res.isZero()) return false;
  63. return true;
  64. }
  65. for (let i=0; i<this.constraints.length; i++) {
  66. if (!checkConstraint(this.constraints[i], w)) {
  67. this.printCostraint(this.constraints[i]);
  68. return false;
  69. }
  70. }
  71. return true;
  72. }
  73. printCostraint(c) {
  74. const lc2str = (lc) => {
  75. let S = "";
  76. for (let k in lc) {
  77. let name = this.signals[k].names[0];
  78. if (name == "one") name = "";
  79. let v = bigInt(lc[k]);
  80. let vs;
  81. if (!v.lesserOrEquals(__P__.shr(bigInt(1)))) {
  82. v = __P__.sub(v);
  83. vs = "-"+v.toString();
  84. } else {
  85. if (S!="") {
  86. vs = "+"+v.toString();
  87. } else {
  88. vs = "";
  89. }
  90. if (vs!="1") {
  91. vs = vs + v.toString();;
  92. }
  93. }
  94. S= S + " " + vs + name;
  95. }
  96. return S;
  97. };
  98. const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`;
  99. console.log(S);
  100. }
  101. printConstraints() {
  102. for (let i=0; i<this.constraints.length; i++) {
  103. this.printCostraint(this.constraints[i]);
  104. }
  105. }
  106. getSignalIdx(name) {
  107. if (typeof(this.signalName2Idx[name]) != "undefined") return this.signalName2Idx[name];
  108. if (!isNaN(name)) return Number(name);
  109. throw new Error("Invalid signal identifier: ", name);
  110. }
  111. // returns the index of the i'th output
  112. outputIdx(i) {
  113. if (i>=this.nOutputs) throw new Error("Accessing an invalid output: "+i);
  114. return i+1;
  115. }
  116. // returns the index of the i'th input
  117. inputIdx(i) {
  118. if (i>=this.nInputs) throw new Error("Accessing an invalid input: "+i);
  119. return this.nOutputs + 1 + i;
  120. }
  121. // returns the index of the i'th public input
  122. pubInputIdx(i) {
  123. if (i>=this.nPubInputs) throw new Error("Accessing an invalid pubInput: "+i);
  124. return this.inputIdx(i);
  125. }
  126. // returns the index of the i'th private input
  127. prvInputIdx(i) {
  128. if (i>=this.nPrvInputs) throw new Error("Accessing an invalid prvInput: "+i);
  129. return this.inputIdx(this.nPubInputs + i);
  130. }
  131. // returns the index of the i'th variable
  132. varIdx(i) {
  133. if (i>=this.nVars) throw new Error("Accessing an invalid variable: "+i);
  134. return i;
  135. }
  136. // returns the index of the i'th constant
  137. constantIdx(i) {
  138. if (i>=this.nConstants) throw new Error("Accessing an invalid constant: "+i);
  139. return this.nVars + i;
  140. }
  141. // returns the index of the i'th signal
  142. signalIdx(i) {
  143. if (i>=this.nSignls) throw new Error("Accessing an invalid signal: "+i);
  144. return i;
  145. }
  146. signalNames(i) {
  147. return this.signals[ this.getSignalIdx(i) ].names.join(", ");
  148. }
  149. a(constraint, signalIdx) {
  150. return bigInt(this.constraints[constraint][0][signalIdx] || 0 );
  151. }
  152. b(constraint, signalIdx) {
  153. return bigInt(this.constraints[constraint][1][signalIdx] || 0);
  154. }
  155. c(constraint, signalIdx) {
  156. return bigInt(this.constraints[constraint][2][signalIdx] || 0);
  157. }
  158. };