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.

432 lines
14 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. /*
  2. Copyright 2018 0kims association
  3. This file is part of zksnark javascript library.
  4. zksnark javascript library is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. zksnark javascript library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with zksnark javascript library. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. const bigInt = require("./bigint.js");
  16. const assert = require("assert");
  17. const F1Field = require("./zqfield.js");
  18. const F2Field = require("./f2field.js");
  19. const F3Field = require("./f3field.js");
  20. const GCurve = require("./gcurve.js");
  21. class BN128 {
  22. constructor() {
  23. this.q = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583");
  24. this.r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
  25. this.g1 = [ bigInt(1), bigInt(2) ];
  26. this.g2 = [
  27. [
  28. bigInt("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
  29. bigInt("11559732032986387107991004021392285783925812861821192530917403151452391805634")
  30. ],
  31. [
  32. bigInt("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
  33. bigInt("4082367875863433681332203403145435568316851327593401208105741076214120093531")
  34. ]
  35. ];
  36. this.nonResidueF2 = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208582");
  37. this.nonResidueF6 = [ bigInt("9"), bigInt("1") ];
  38. this.F1 = new F1Field(this.q);
  39. this.F2 = new F2Field(this.F1, this.nonResidueF2);
  40. this.G1 = new GCurve(this.F1, this.g1);
  41. this.G2 = new GCurve(this.F2, this.g2);
  42. this.F6 = new F3Field(this.F2, this.nonResidueF6);
  43. this.F12 = new F2Field(this.F6, this.nonResidueF6);
  44. const self = this;
  45. this.F12._mulByNonResidue = function(a) {
  46. return [self.F2.mul(this.nonResidue, a[2]), a[0], a[1]];
  47. };
  48. this._preparePairing();
  49. }
  50. _preparePairing() {
  51. this.loopCount = bigInt("29793968203157093288");// CONSTANT
  52. // Set loopCountNeg
  53. if (this.loopCount.isNegative()) {
  54. this.loopCount = this.neg();
  55. this.loopCountNeg = true;
  56. } else {
  57. this.loopCountNeg = false;
  58. }
  59. // Set loop_count_bits
  60. let lc = this.loopCount;
  61. this.loop_count_bits = []; // Constant
  62. while (!lc.isZero()) {
  63. this.loop_count_bits.push( lc.isOdd() );
  64. lc = lc.shr(1);
  65. }
  66. this.two_inv = this.F1.inverse(bigInt(2));
  67. this.coef_b = bigInt(3);
  68. this.twist = [bigInt(9) , bigInt(1)];
  69. this.twist_coeff_b = this.F2.mulScalar( this.F2.inverse(this.twist), this.coef_b );
  70. this.frobenius_coeffs_c1_1 = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208582");
  71. this.twist_mul_by_q_X =
  72. [
  73. bigInt("21575463638280843010398324269430826099269044274347216827212613867836435027261"),
  74. bigInt("10307601595873709700152284273816112264069230130616436755625194854815875713954")
  75. ];
  76. this.twist_mul_by_q_Y =
  77. [
  78. bigInt("2821565182194536844548159561693502659359617185244120367078079554186484126554"),
  79. bigInt("3505843767911556378687030309984248845540243509899259641013678093033130930403")
  80. ];
  81. this.final_exponent = bigInt("552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480");
  82. }
  83. pairing(p1, p2) {
  84. const pre1 = this.precomputeG1(p1);
  85. const pre2 = this.precomputeG2(p2);
  86. const r1 = this.millerLoop(pre1, pre2);
  87. const res = this.finalExponentiation(r1);
  88. return res;
  89. }
  90. precomputeG1(p) {
  91. const Pcopy = this.G1.affine(p);
  92. const res = {};
  93. res.PX = Pcopy[0];
  94. res.PY = Pcopy[1];
  95. return res;
  96. }
  97. precomputeG2(p) {
  98. const Qcopy = this.G2.affine(p);
  99. const res = {
  100. QX: Qcopy[0],
  101. QY: Qcopy[1],
  102. coeffs: []
  103. };
  104. const R = {
  105. X: Qcopy[0],
  106. Y: Qcopy[1],
  107. Z: this.F2.one
  108. };
  109. let c;
  110. for (let i = this.loop_count_bits.length-2; i >= 0; --i)
  111. {
  112. const bit = this.loop_count_bits[i];
  113. c = this._doubleStep(R);
  114. res.coeffs.push(c);
  115. if (bit)
  116. {
  117. c = this._addStep(Qcopy, R);
  118. res.coeffs.push(c);
  119. }
  120. }
  121. const Q1 = this.G2.affine(this._g2MulByQ(Qcopy));
  122. assert(this.F2.equals(Q1[2], this.F2.one));
  123. const Q2 = this.G2.affine(this._g2MulByQ(Q1));
  124. assert(this.F2.equals(Q2[2], this.F2.one));
  125. if (this.loopCountNef)
  126. {
  127. R.Y = this.F2.neg(R.Y);
  128. }
  129. Q2[1] = this.F2.neg(Q2[1]);
  130. c = this._addStep(Q1, R);
  131. res.coeffs.push(c);
  132. c = this._addStep(Q2, R);
  133. res.coeffs.push(c);
  134. return res;
  135. }
  136. millerLoop(pre1, pre2) {
  137. let f = this.F12.one;
  138. let idx = 0;
  139. let c;
  140. for (let i = this.loop_count_bits.length-2; i >= 0; --i)
  141. {
  142. const bit = this.loop_count_bits[i];
  143. /* code below gets executed for all bits (EXCEPT the MSB itself) of
  144. alt_bn128_param_p (skipping leading zeros) in MSB to LSB
  145. order */
  146. c = pre2.coeffs[idx++];
  147. f = this.F12.square(f);
  148. f = this._mul_by_024(
  149. f,
  150. c.ell_0,
  151. this.F2.mulScalar(c.ell_VW , pre1.PY),
  152. this.F2.mulScalar(c.ell_VV , pre1.PX, ));
  153. if (bit)
  154. {
  155. c = pre2.coeffs[idx++];
  156. f = this._mul_by_024(
  157. f,
  158. c.ell_0,
  159. this.F2.mulScalar(c.ell_VW, pre1.PY, ),
  160. this.F2.mulScalar(c.ell_VV, pre1.PX, ));
  161. }
  162. }
  163. if (this.loopCountNef)
  164. {
  165. f = this.F12.inverse(f);
  166. }
  167. c = pre2.coeffs[idx++];
  168. f = this._mul_by_024(
  169. f,
  170. c.ell_0,
  171. this.F2.mulScalar(c.ell_VW, pre1.PY),
  172. this.F2.mulScalar(c.ell_VV, pre1.PX));
  173. c = pre2.coeffs[idx++];
  174. f = this._mul_by_024(
  175. f,
  176. c.ell_0,
  177. this.F2.mulScalar(c.ell_VW, pre1.PY, ),
  178. this.F2.mulScalar(c.ell_VV, pre1.PX));
  179. return f;
  180. }
  181. finalExponentiation(elt) {
  182. // TODO: There is an optimization in FF
  183. const res = this.F12.exp(elt,this.final_exponent);
  184. return res;
  185. }
  186. _doubleStep(current) {
  187. const X = current.X;
  188. const Y = current.Y;
  189. const Z = current.Z;
  190. const A = this.F2.mulScalar(this.F2.mul(X,Y), this.two_inv); // A = X1 * Y1 / 2
  191. const B = this.F2.square(Y); // B = Y1^2
  192. const C = this.F2.square(Z); // C = Z1^2
  193. const D = this.F2.add(C, this.F2.add(C,C)); // D = 3 * C
  194. const E = this.F2.mul(this.twist_coeff_b, D); // E = twist_b * D
  195. const F = this.F2.add(E, this.F2.add(E,E)); // F = 3 * E
  196. const G =
  197. this.F2.mulScalar(
  198. this.F2.add( B , F ),
  199. this.two_inv); // G = (B+F)/2
  200. const H =
  201. this.F2.sub(
  202. this.F2.square( this.F2.add(Y,Z) ),
  203. this.F2.add( B , C)); // H = (Y1+Z1)^2-(B+C)
  204. const I = this.F2.sub(E, B); // I = E-B
  205. const J = this.F2.square(X); // J = X1^2
  206. const E_squared = this.F2.square(E); // E_squared = E^2
  207. current.X = this.F2.mul( A, this.F2.sub(B,F) ); // X3 = A * (B-F)
  208. current.Y =
  209. this.F2.sub(
  210. this.F2.sub( this.F2.square(G) , E_squared ),
  211. this.F2.add( E_squared , E_squared )); // Y3 = G^2 - 3*E^2
  212. current.Z = this.F2.mul( B, H ); // Z3 = B * H
  213. const c = {
  214. ell_0 : this.F2.mul( I, this.twist), // ell_0 = xi * I
  215. ell_VW: this.F2.neg( H ), // ell_VW = - H (later: * yP)
  216. ell_VV: this.F2.add( J , this.F2.add(J,J) ) // ell_VV = 3*J (later: * xP)
  217. };
  218. return c;
  219. }
  220. _addStep(base, current) {
  221. const X1 = current.X;
  222. const Y1 = current.Y;
  223. const Z1 = current.Z;
  224. const x2 = base[0];
  225. const y2 = base[1];
  226. const D = this.F2.sub( X1, this.F2.mul(x2,Z1) ); // D = X1 - X2*Z1
  227. const E = this.F2.sub( Y1, this.F2.mul(y2,Z1) ); // E = Y1 - Y2*Z1
  228. const F = this.F2.square(D); // F = D^2
  229. const G = this.F2.square(E); // G = E^2
  230. const H = this.F2.mul(D,F); // H = D*F
  231. const I = this.F2.mul(X1,F); // I = X1 * F
  232. const J =
  233. this.F2.sub(
  234. this.F2.add( H, this.F2.mul(Z1,G) ),
  235. this.F2.add( I, I )); // J = H + Z1*G - (I+I)
  236. current.X = this.F2.mul( D , J ); // X3 = D*J
  237. current.Y =
  238. this.F2.sub(
  239. this.F2.mul( E , this.F2.sub(I,J) ),
  240. this.F2.mul( H , Y1)); // Y3 = E*(I-J)-(H*Y1)
  241. current.Z = this.F2.mul(Z1,H);
  242. const c = {
  243. ell_0 :
  244. this.F2.mul(
  245. this.twist,
  246. this.F2.sub(
  247. this.F2.mul(E , x2),
  248. this.F2.mul(D , y2))), // ell_0 = xi * (E * X2 - D * Y2)
  249. ell_VV : this.F2.neg(E), // ell_VV = - E (later: * xP)
  250. ell_VW : D // ell_VW = D (later: * yP )
  251. };
  252. return c;
  253. }
  254. _mul_by_024(a, ell_0, ell_VW, ell_VV) {
  255. // Old implementation
  256. const b = [
  257. [ell_0, this.F2.zero, ell_VV],
  258. [this.F2.zero, ell_VW, this.F2.zero]
  259. ];
  260. return this.F12.mul(a,b);
  261. /*
  262. // This is a new implementation,
  263. // But it does not look worthy
  264. // at least in javascript.
  265. let z0 = a[0][0];
  266. let z1 = a[0][1];
  267. let z2 = a[0][2];
  268. let z3 = a[1][0];
  269. let z4 = a[1][1];
  270. let z5 = a[1][2];
  271. const x0 = ell_0;
  272. const x2 = ell_VV;
  273. const x4 = ell_VW;
  274. const D0 = this.F2.mul(z0, x0);
  275. const D2 = this.F2.mul(z2, x2);
  276. const D4 = this.F2.mul(z4, x4);
  277. const t2 = this.F2.add(z0, z4);
  278. let t1 = this.F2.add(z0, z2);
  279. const s0 = this.F2.add(this.F2.add(z1,z3),z5);
  280. // For z.a_.a_ = z0.
  281. let S1 = this.F2.mul(z1, x2);
  282. let T3 = this.F2.add(S1, D4);
  283. let T4 = this.F2.add( this.F2.mul(this.nonResidueF6, T3),D0);
  284. z0 = T4;
  285. // For z.a_.b_ = z1
  286. T3 = this.F2.mul(z5, x4);
  287. S1 = this.F2.add(S1, T3);
  288. T3 = this.F2.add(T3, D2);
  289. T4 = this.F2.mul(this.nonResidueF6, T3);
  290. T3 = this.F2.mul(z1, x0);
  291. S1 = this.F2.add(S1, T3);
  292. T4 = this.F2.add(T4, T3);
  293. z1 = T4;
  294. // For z.a_.c_ = z2
  295. let t0 = this.F2.add(x0, x2);
  296. T3 = this.F2.sub(
  297. this.F2.mul(t1, t0),
  298. this.F2.add(D0, D2));
  299. T4 = this.F2.mul(z3, x4);
  300. S1 = this.F2.add(S1, T4);
  301. T3 = this.F2.add(T3, T4);
  302. // For z.b_.a_ = z3 (z3 needs z2)
  303. t0 = this.F2.add(z2, z4);
  304. z2 = T3;
  305. t1 = this.F2.add(x2, x4);
  306. T3 = this.F2.sub(
  307. this.F2.mul(t0,t1),
  308. this.F2.add(D2, D4));
  309. T4 = this.F2.mul(this.nonResidueF6, T3);
  310. T3 = this.F2.mul(z3, x0);
  311. S1 = this.F2.add(S1, T3);
  312. T4 = this.F2.add(T4, T3);
  313. z3 = T4;
  314. // For z.b_.b_ = z4
  315. T3 = this.F2.mul(z5, x2);
  316. S1 = this.F2.add(S1, T3);
  317. T4 = this.F2.mul(this.nonResidueF6, T3);
  318. t0 = this.F2.add(x0, x4);
  319. T3 = this.F2.sub(
  320. this.F2.mul(t2,t0),
  321. this.F2.add(D0, D4));
  322. T4 = this.F2.add(T4, T3);
  323. z4 = T4;
  324. // For z.b_.c_ = z5.
  325. t0 = this.F2.add(this.F2.add(x0, x2), x4);
  326. T3 = this.F2.sub(this.F2.mul(s0, t0), S1);
  327. z5 = T3;
  328. return [
  329. [z0, z1, z2],
  330. [z3, z4, z5]
  331. ];
  332. */
  333. }
  334. _g2MulByQ(p) {
  335. const fmx = [p[0][0], this.F1.mul(p[0][1], this.frobenius_coeffs_c1_1 )];
  336. const fmy = [p[1][0], this.F1.mul(p[1][1], this.frobenius_coeffs_c1_1 )];
  337. const fmz = [p[2][0], this.F1.mul(p[2][1], this.frobenius_coeffs_c1_1 )];
  338. return [
  339. this.F2.mul(this.twist_mul_by_q_X , fmx),
  340. this.F2.mul(this.twist_mul_by_q_Y , fmy),
  341. fmz
  342. ];
  343. }
  344. }
  345. module.exports = BN128;