From 7dd0bdf3af74fd2d60f91247c338500da92b29f0 Mon Sep 17 00:00:00 2001 From: Veronica Zheng Date: Thu, 17 Mar 2022 16:17:47 -0500 Subject: [PATCH 1/6] ses compatible - rename eval --- build/main.cjs | 4 ++-- src/polfield.js | 4 ++-- test/pols.js | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/main.cjs b/build/main.cjs index 04bd6f8..11fe79a 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -822,7 +822,7 @@ class PolField { return v; } - eval(p,x) { + eval1(p,x) { const F = this.F; if (p.length == 0) return F.zero; const m = this._next2Power(p.length); @@ -853,7 +853,7 @@ class PolField { let mpol = this.ruffini(roots, points[i][0]); const factor = this.F.mul( - this.F.inv(this.eval(mpol, points[i][0])), + this.F.inv(this.eval1(mpol, points[i][0])), points[i][1]); mpol = this.mulScalar(mpol, factor); sum = this.add(sum, mpol); diff --git a/src/polfield.js b/src/polfield.js index 6f570cb..465e551 100644 --- a/src/polfield.js +++ b/src/polfield.js @@ -192,7 +192,7 @@ export default class PolField { return v; } - eval(p,x) { + eval1(p,x) { const F = this.F; if (p.length == 0) return F.zero; const m = this._next2Power(p.length); @@ -223,7 +223,7 @@ export default class PolField { let mpol = this.ruffini(roots, points[i][0]); const factor = this.F.mul( - this.F.inv(this.eval(mpol, points[i][0])), + this.F.inv(this.eval1(mpol, points[i][0])), points[i][1]); mpol = this.mulScalar(mpol, factor); sum = this.add(sum, mpol); diff --git a/test/pols.js b/test/pols.js index 6615ba7..5229252 100644 --- a/test/pols.js +++ b/test/pols.js @@ -128,13 +128,13 @@ describe("Polynomial field", () => { it("Should evaluate and zero", () => { const PF = new PolField(new ZqField(r)); const p = [PF.F.neg(PF.F.e(2)), PF.F.e(1)]; - const v = PF.eval(p, PF.F.e(2)); + const v = PF.eval1(p, PF.F.e(2)); assert(PF.F.eq(v, PF.F.e(0))); }); it("Should evaluate bigger number", () => { const PF = new PolField(new ZqField(r)); const p = [PF.F.e(1), PF.F.e(2), PF.F.e(3)]; - const v = PF.eval(p, PF.F.e(2)); + const v = PF.eval1(p, PF.F.e(2)); assert(PF.F.eq(v, PF.F.e(17))); }); it("Should create lagrange polynomial minmal", () => { @@ -148,7 +148,7 @@ describe("Polynomial field", () => { const p=PF.lagrange(points); for (let i=0; i { const p=PF.lagrange(points); for (let i=0; i { const p = PF.ifft(a); for (let i=0; i Date: Sat, 26 Mar 2022 10:45:27 -0700 Subject: [PATCH 2/6] rename to evaluate --- build/main.cjs | 4 ++-- src/polfield.js | 4 ++-- test/pols.js | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/main.cjs b/build/main.cjs index 11fe79a..f77fd47 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -822,7 +822,7 @@ class PolField { return v; } - eval1(p,x) { + evaluate(p,x) { const F = this.F; if (p.length == 0) return F.zero; const m = this._next2Power(p.length); @@ -853,7 +853,7 @@ class PolField { let mpol = this.ruffini(roots, points[i][0]); const factor = this.F.mul( - this.F.inv(this.eval1(mpol, points[i][0])), + this.F.inv(this.evaluate(mpol, points[i][0])), points[i][1]); mpol = this.mulScalar(mpol, factor); sum = this.add(sum, mpol); diff --git a/src/polfield.js b/src/polfield.js index 465e551..467645f 100644 --- a/src/polfield.js +++ b/src/polfield.js @@ -192,7 +192,7 @@ export default class PolField { return v; } - eval1(p,x) { + evaluate(p,x) { const F = this.F; if (p.length == 0) return F.zero; const m = this._next2Power(p.length); @@ -223,7 +223,7 @@ export default class PolField { let mpol = this.ruffini(roots, points[i][0]); const factor = this.F.mul( - this.F.inv(this.eval1(mpol, points[i][0])), + this.F.inv(this.evaluate(mpol, points[i][0])), points[i][1]); mpol = this.mulScalar(mpol, factor); sum = this.add(sum, mpol); diff --git a/test/pols.js b/test/pols.js index 5229252..81fa9dd 100644 --- a/test/pols.js +++ b/test/pols.js @@ -128,13 +128,13 @@ describe("Polynomial field", () => { it("Should evaluate and zero", () => { const PF = new PolField(new ZqField(r)); const p = [PF.F.neg(PF.F.e(2)), PF.F.e(1)]; - const v = PF.eval1(p, PF.F.e(2)); + const v = PF.evaluate(p, PF.F.e(2)); assert(PF.F.eq(v, PF.F.e(0))); }); it("Should evaluate bigger number", () => { const PF = new PolField(new ZqField(r)); const p = [PF.F.e(1), PF.F.e(2), PF.F.e(3)]; - const v = PF.eval1(p, PF.F.e(2)); + const v = PF.evaluate(p, PF.F.e(2)); assert(PF.F.eq(v, PF.F.e(17))); }); it("Should create lagrange polynomial minmal", () => { @@ -148,7 +148,7 @@ describe("Polynomial field", () => { const p=PF.lagrange(points); for (let i=0; i { const p=PF.lagrange(points); for (let i=0; i { const p = PF.ifft(a); for (let i=0; i Date: Sat, 26 Mar 2022 13:00:15 -0700 Subject: [PATCH 3/6] conditional remove webwokers during compilation --- package-lock.json | 180 ++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- rollup.cjs.config.js | 8 +- src/threadman.js | 11 +++ 4 files changed, 199 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2711e35..24998cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,8 @@ "chai": "^4.2.0", "eslint": "^8.0.1", "mocha": "^8.2.1", - "rollup": "^2.38.5" + "rollup": "^2.38.5", + "rollup-plugin-jscc": "^2.0.0" } }, "node_modules/@eslint/eslintrc": { @@ -71,6 +72,24 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@jsbits/escape-regex-str": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@jsbits/escape-regex-str/-/escape-regex-str-1.0.3.tgz", + "integrity": "sha512-0800vYI2fg1nuUq/T9Tqv8DMOLLNiRAltxFbKIbR7szrvW6qTuI2+zGK51hV7NAAmUr4G83Kvpj2R6Yyg07iIw==", + "dev": true, + "engines": { + "node": ">=4.2" + } + }, + "node_modules/@jsbits/get-package-version": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@jsbits/get-package-version/-/get-package-version-1.0.3.tgz", + "integrity": "sha512-IJy1jRL01x7p6UEpgKa1lVLstMUx8EiIR8pPoS5sBfsHEoeLkzYiNpAfxPx8zLDUJyS1yBbChJjcWdPqyH285w==", + "dev": true, + "engines": { + "node": ">=4.2" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -668,6 +687,12 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -1009,6 +1034,22 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jscc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jscc/-/jscc-1.1.1.tgz", + "integrity": "sha512-anpZkTXwZbxfxLEBMciKxXMHx2xOLK2qhynIhTnoSyC+wGOEPrAoofxnADgblbarn0kijVMt1U71cQGmRF/1Og==", + "dev": true, + "dependencies": { + "@jsbits/escape-regex-str": "^1.0.2", + "@jsbits/get-package-version": "^1.0.2", + "magic-string": "^0.25.1", + "perf-regexes": "^1.0.1", + "skip-regex": "^1.0.2" + }, + "engines": { + "node": ">=6.0" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1067,6 +1108,15 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1322,6 +1372,15 @@ "node": "*" } }, + "node_modules/perf-regexes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/perf-regexes/-/perf-regexes-1.0.1.tgz", + "integrity": "sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==", + "dev": true, + "engines": { + "node": ">=6.14" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1433,6 +1492,32 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-jscc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-jscc/-/rollup-plugin-jscc-2.0.0.tgz", + "integrity": "sha512-5jG9q79K2u5uRBTKA+GA4gqt1zA7qHQRpcabZMoVs913gr75s428O7K3r58n2vADDzwIhiOKMo7rCMhOyks6dw==", + "dev": true, + "dependencies": { + "@jsbits/get-package-version": "^1.0.3", + "jscc": "^1.1.1", + "rollup-pluginutils": "^2.8.2" + }, + "engines": { + "node": ">=10.12.0" + }, + "peerDependencies": { + "rollup": ">=2" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1483,6 +1568,21 @@ "node": ">=8" } }, + "node_modules/skip-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", + "integrity": "sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==", + "dev": true, + "engines": { + "node": ">=4.2" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, "node_modules/string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -1856,6 +1956,18 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@jsbits/escape-regex-str": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@jsbits/escape-regex-str/-/escape-regex-str-1.0.3.tgz", + "integrity": "sha512-0800vYI2fg1nuUq/T9Tqv8DMOLLNiRAltxFbKIbR7szrvW6qTuI2+zGK51hV7NAAmUr4G83Kvpj2R6Yyg07iIw==", + "dev": true + }, + "@jsbits/get-package-version": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@jsbits/get-package-version/-/get-package-version-1.0.3.tgz", + "integrity": "sha512-IJy1jRL01x7p6UEpgKa1lVLstMUx8EiIR8pPoS5sBfsHEoeLkzYiNpAfxPx8zLDUJyS1yBbChJjcWdPqyH285w==", + "dev": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -2308,6 +2420,12 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -2558,6 +2676,19 @@ "argparse": "^2.0.1" } }, + "jscc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jscc/-/jscc-1.1.1.tgz", + "integrity": "sha512-anpZkTXwZbxfxLEBMciKxXMHx2xOLK2qhynIhTnoSyC+wGOEPrAoofxnADgblbarn0kijVMt1U71cQGmRF/1Og==", + "dev": true, + "requires": { + "@jsbits/escape-regex-str": "^1.0.2", + "@jsbits/get-package-version": "^1.0.2", + "magic-string": "^0.25.1", + "perf-regexes": "^1.0.1", + "skip-regex": "^1.0.2" + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2604,6 +2735,15 @@ "chalk": "^4.0.0" } }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2793,6 +2933,12 @@ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "perf-regexes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/perf-regexes/-/perf-regexes-1.0.1.tgz", + "integrity": "sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==", + "dev": true + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2865,6 +3011,26 @@ "fsevents": "~2.3.2" } }, + "rollup-plugin-jscc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-jscc/-/rollup-plugin-jscc-2.0.0.tgz", + "integrity": "sha512-5jG9q79K2u5uRBTKA+GA4gqt1zA7qHQRpcabZMoVs913gr75s428O7K3r58n2vADDzwIhiOKMo7rCMhOyks6dw==", + "dev": true, + "requires": { + "@jsbits/get-package-version": "^1.0.3", + "jscc": "^1.1.1", + "rollup-pluginutils": "^2.8.2" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2895,6 +3061,18 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "skip-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", + "integrity": "sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", diff --git a/package.json b/package.json index 34e1479..1c06ffc 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "chai": "^4.2.0", "eslint": "^8.0.1", "mocha": "^8.2.1", - "rollup": "^2.38.5" + "rollup": "^2.38.5", + "rollup-plugin-jscc": "^2.0.0" } } diff --git a/rollup.cjs.config.js b/rollup.cjs.config.js index f15b538..07d64c5 100644 --- a/rollup.cjs.config.js +++ b/rollup.cjs.config.js @@ -1,5 +1,6 @@ import fs from "fs"; import { builtinModules as builtin } from "module"; +import jscc from 'rollup-plugin-jscc' const pkg = JSON.parse(fs.readFileSync("./package.json")); @@ -12,5 +13,10 @@ export default { external: [ ...Object.keys(pkg.dependencies), ...builtin, - ] + ], + plugins: [ + jscc({ + values: { _SES: process.env.SES }, + }) + ], }; diff --git a/src/threadman.js b/src/threadman.js index 61310a9..f78677f 100644 --- a/src/threadman.js +++ b/src/threadman.js @@ -24,7 +24,11 @@ const MEM_SIZE = 25; // Memory size in 64K Pakes (1600Kb) import thread from "./threadman_thread.js"; import os from "os"; + +/*#if _SES +//#else */ import Worker from "web-worker"; +//#endif class Deferred { constructor() { @@ -81,7 +85,10 @@ export default async function buildThreadManager(wasm, singleThread) { // tm.pTmp1 = tm.alloc(curve.G2.F.n8*3); +/*#if _SES +//#else */ if (singleThread) { +//#endif tm.code = wasm.code; tm.taskManager = thread(); await tm.taskManager([{ @@ -90,6 +97,8 @@ export default async function buildThreadManager(wasm, singleThread) { code: tm.code.slice() }]); tm.concurrency = 1; +/*#if _SES +//#else */ } else { tm.workers = []; tm.pendingDeferreds = []; @@ -133,6 +142,8 @@ export default async function buildThreadManager(wasm, singleThread) { await Promise.all(initPromises); } +//#endif + return tm; function getOnMsg(i) { From ad7a8fdd379c37c7a010ffaa82c6b17c44f7bd63 Mon Sep 17 00:00:00 2001 From: Veronica Zheng Date: Mon, 28 Mar 2022 17:01:54 -0700 Subject: [PATCH 4/6] add btoa check --- src/threadman.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threadman.js b/src/threadman.js index f78677f..460db85 100644 --- a/src/threadman.js +++ b/src/threadman.js @@ -44,7 +44,7 @@ function sleep(ms) { } function stringToBase64(str) { - if (process.browser) { + if (process.browser && typeof globalThis.btoa === "function") { return globalThis.btoa(str); } else { return Buffer.from(str).toString("base64"); From 0ba7c3dfaf970d26635f6d56f847e3f136ed6905 Mon Sep 17 00:00:00 2001 From: Veronica Zheng Date: Mon, 28 Mar 2022 17:08:12 -0700 Subject: [PATCH 5/6] add ses build --- package.json | 4 +++- rollup.cjs.config.js | 8 +------- rollup.ses.config.js | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 rollup.ses.config.js diff --git a/package.json b/package.json index 1c06ffc..b8f2158 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,11 @@ "import": "./main.js", "require": "./build/main.cjs" }, + "browser": "./build/main.ses.cjs", "scripts": { "test": "mocha", - "build": "rollup -c rollup.cjs.config.js" + "build": "rollup -c rollup.cjs.config.js", + "buildses": "SES=true rollup -c rollup.ses.config.js" }, "repository": { "type": "git", diff --git a/rollup.cjs.config.js b/rollup.cjs.config.js index 07d64c5..f15b538 100644 --- a/rollup.cjs.config.js +++ b/rollup.cjs.config.js @@ -1,6 +1,5 @@ import fs from "fs"; import { builtinModules as builtin } from "module"; -import jscc from 'rollup-plugin-jscc' const pkg = JSON.parse(fs.readFileSync("./package.json")); @@ -13,10 +12,5 @@ export default { external: [ ...Object.keys(pkg.dependencies), ...builtin, - ], - plugins: [ - jscc({ - values: { _SES: process.env.SES }, - }) - ], + ] }; diff --git a/rollup.ses.config.js b/rollup.ses.config.js new file mode 100644 index 0000000..40ff2fa --- /dev/null +++ b/rollup.ses.config.js @@ -0,0 +1,18 @@ +import config from "./rollup.cjs.config.js"; +import jscc from 'rollup-plugin-jscc' + +export default { + input: "main.js", + output: { + file: "build/main.ses.cjs", + format: "cjs", + }, + external: [ + ...config.external, + ], + plugins: [ + jscc({ + values: { _SES: process.env.SES }, + }) + ], +}; From bdc78341eadd289e45cc50d046c7df547d12d6ff Mon Sep 17 00:00:00 2001 From: Veronica Zheng Date: Mon, 28 Mar 2022 17:21:22 -0700 Subject: [PATCH 6/6] include main.ses.cjs --- build/main.ses.cjs | 6712 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6712 insertions(+) create mode 100644 build/main.ses.cjs diff --git a/build/main.ses.cjs b/build/main.ses.cjs new file mode 100644 index 0000000..5d1fd82 --- /dev/null +++ b/build/main.ses.cjs @@ -0,0 +1,6712 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var bigInt = require('big-integer'); +var crypto = require('crypto'); +var wasmcurves = require('wasmcurves'); +require('os'); +var wasmbuilder = require('wasmbuilder'); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +var bigInt__default = /*#__PURE__*/_interopDefaultLegacy(bigInt); +var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto); + +/* global BigInt */ +const hexLen = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4]; + +function fromString$2(s, radix) { + if ((!radix)||(radix==10)) { + return BigInt(s); + } else if (radix==16) { + if (s.slice(0,2) == "0x") { + return BigInt(s); + } else { + return BigInt("0x"+s); + } + } +} + +const e$2 = fromString$2; + +function fromArray$2(a, radix) { + let acc =BigInt(0); + radix = BigInt(radix); + for (let i=0; i> BigInt(n); +} + +const shl$2 = shiftLeft$2; +const shr$2 = shiftRight$2; + +function isOdd$2(a) { + return (BigInt(a) & BigInt(1)) == BigInt(1); +} + + +function naf$2(n) { + let E = BigInt(n); + const res = []; + while (E) { + if (E & BigInt(1)) { + const z = 2 - Number(E % BigInt(4)); + res.push( z ); + E = E - BigInt(z); + } else { + res.push( 0 ); + } + E = E >> BigInt(1); + } + return res; +} + + +function bits$2(n) { + let E = BigInt(n); + const res = []; + while (E) { + if (E & BigInt(1)) { + res.push(1); + } else { + res.push( 0 ); + } + E = E >> BigInt(1); + } + return res; +} + +function toNumber$2(s) { + if (s>BigInt(Number.MAX_SAFE_INTEGER )) { + throw new Error("Number too big"); + } + return Number(s); +} + +function toArray$2(s, radix) { + const res = []; + let rem = BigInt(s); + radix = BigInt(radix); + while (rem) { + res.unshift( Number(rem % radix)); + rem = rem / radix; + } + return res; +} + + +function add$2(a, b) { + return BigInt(a) + BigInt(b); +} + +function sub$2(a, b) { + return BigInt(a) - BigInt(b); +} + +function neg$2(a) { + return -BigInt(a); +} + +function mul$2(a, b) { + return BigInt(a) * BigInt(b); +} + +function square$2(a) { + return BigInt(a) * BigInt(a); +} + +function pow$2(a, b) { + return BigInt(a) ** BigInt(b); +} + +function exp$3(a, b) { + return BigInt(a) ** BigInt(b); +} + +function abs$2(a) { + return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a); +} + +function div$2(a, b) { + return BigInt(a) / BigInt(b); +} + +function mod$2(a, b) { + return BigInt(a) % BigInt(b); +} + +function eq$2(a, b) { + return BigInt(a) == BigInt(b); +} + +function neq$2(a, b) { + return BigInt(a) != BigInt(b); +} + +function lt$2(a, b) { + return BigInt(a) < BigInt(b); +} + +function gt$2(a, b) { + return BigInt(a) > BigInt(b); +} + +function leq$2(a, b) { + return BigInt(a) <= BigInt(b); +} + +function geq$2(a, b) { + return BigInt(a) >= BigInt(b); +} + +function band$2(a, b) { + return BigInt(a) & BigInt(b); +} + +function bor$2(a, b) { + return BigInt(a) | BigInt(b); +} + +function bxor$2(a, b) { + return BigInt(a) ^ BigInt(b); +} + +function land$2(a, b) { + return BigInt(a) && BigInt(b); +} + +function lor$2(a, b) { + return BigInt(a) || BigInt(b); +} + +function lnot$2(a) { + return !BigInt(a); +} + +var Scalar_native = /*#__PURE__*/Object.freeze({ + __proto__: null, + fromString: fromString$2, + e: e$2, + fromArray: fromArray$2, + bitLength: bitLength$2, + isNegative: isNegative$2, + isZero: isZero$2, + shiftLeft: shiftLeft$2, + shiftRight: shiftRight$2, + shl: shl$2, + shr: shr$2, + isOdd: isOdd$2, + naf: naf$2, + bits: bits$2, + toNumber: toNumber$2, + toArray: toArray$2, + add: add$2, + sub: sub$2, + neg: neg$2, + mul: mul$2, + square: square$2, + pow: pow$2, + exp: exp$3, + abs: abs$2, + div: div$2, + mod: mod$2, + eq: eq$2, + neq: neq$2, + lt: lt$2, + gt: gt$2, + leq: leq$2, + geq: geq$2, + band: band$2, + bor: bor$2, + bxor: bxor$2, + land: land$2, + lor: lor$2, + lnot: lnot$2 +}); + +function fromString$1(s, radix) { + if (typeof s == "string") { + if (s.slice(0,2) == "0x") { + return bigInt__default["default"](s.slice(2), 16); + } else { + return bigInt__default["default"](s,radix); + } + } else { + return bigInt__default["default"](s, radix); + } +} + +const e$1 = fromString$1; + +function fromArray$1(a, radix) { + return bigInt__default["default"].fromArray(a, radix); +} + +function bitLength$1(a) { + return bigInt__default["default"](a).bitLength(); +} + +function isNegative$1(a) { + return bigInt__default["default"](a).isNegative(); +} + +function isZero$1(a) { + return bigInt__default["default"](a).isZero(); +} + +function shiftLeft$1(a, n) { + return bigInt__default["default"](a).shiftLeft(n); +} + +function shiftRight$1(a, n) { + return bigInt__default["default"](a).shiftRight(n); +} + +const shl$1 = shiftLeft$1; +const shr$1 = shiftRight$1; + +function isOdd$1(a) { + return bigInt__default["default"](a).isOdd(); +} + + +function naf$1(n) { + let E = bigInt__default["default"](n); + const res = []; + while (E.gt(bigInt__default["default"].zero)) { + if (E.isOdd()) { + const z = 2 - E.mod(4).toJSNumber(); + res.push( z ); + E = E.minus(z); + } else { + res.push( 0 ); + } + E = E.shiftRight(1); + } + return res; +} + +function bits$1(n) { + let E = bigInt__default["default"](n); + const res = []; + while (E.gt(bigInt__default["default"].zero)) { + if (E.isOdd()) { + res.push(1); + } else { + res.push( 0 ); + } + E = E.shiftRight(1); + } + return res; +} + +function toNumber$1(s) { + if (!s.lt(bigInt__default["default"]("9007199254740992", 10))) { + throw new Error("Number too big"); + } + return s.toJSNumber(); +} + +function toArray$1(s, radix) { + return bigInt__default["default"](s).toArray(radix); +} + +function add$1(a, b) { + return bigInt__default["default"](a).add(bigInt__default["default"](b)); +} + +function sub$1(a, b) { + return bigInt__default["default"](a).minus(bigInt__default["default"](b)); +} + +function neg$1(a) { + return bigInt__default["default"].zero.minus(bigInt__default["default"](a)); +} + +function mul$1(a, b) { + return bigInt__default["default"](a).times(bigInt__default["default"](b)); +} + +function square$1(a) { + return bigInt__default["default"](a).square(); +} + +function pow$1(a, b) { + return bigInt__default["default"](a).pow(bigInt__default["default"](b)); +} + +function exp$2(a, b) { + return bigInt__default["default"](a).pow(bigInt__default["default"](b)); +} + +function abs$1(a) { + return bigInt__default["default"](a).abs(); +} + +function div$1(a, b) { + return bigInt__default["default"](a).divide(bigInt__default["default"](b)); +} + +function mod$1(a, b) { + return bigInt__default["default"](a).mod(bigInt__default["default"](b)); +} + +function eq$1(a, b) { + return bigInt__default["default"](a).eq(bigInt__default["default"](b)); +} + +function neq$1(a, b) { + return bigInt__default["default"](a).neq(bigInt__default["default"](b)); +} + +function lt$1(a, b) { + return bigInt__default["default"](a).lt(bigInt__default["default"](b)); +} + +function gt$1(a, b) { + return bigInt__default["default"](a).gt(bigInt__default["default"](b)); +} + +function leq$1(a, b) { + return bigInt__default["default"](a).leq(bigInt__default["default"](b)); +} + +function geq$1(a, b) { + return bigInt__default["default"](a).geq(bigInt__default["default"](b)); +} + +function band$1(a, b) { + return bigInt__default["default"](a).and(bigInt__default["default"](b)); +} + +function bor$1(a, b) { + return bigInt__default["default"](a).or(bigInt__default["default"](b)); +} + +function bxor$1(a, b) { + return bigInt__default["default"](a).xor(bigInt__default["default"](b)); +} + +function land$1(a, b) { + return (!bigInt__default["default"](a).isZero()) && (!bigInt__default["default"](b).isZero()); +} + +function lor$1(a, b) { + return (!bigInt__default["default"](a).isZero()) || (!bigInt__default["default"](b).isZero()); +} + +function lnot$1(a) { + return bigInt__default["default"](a).isZero(); +} + +var Scalar_bigint = /*#__PURE__*/Object.freeze({ + __proto__: null, + fromString: fromString$1, + e: e$1, + fromArray: fromArray$1, + bitLength: bitLength$1, + isNegative: isNegative$1, + isZero: isZero$1, + shiftLeft: shiftLeft$1, + shiftRight: shiftRight$1, + shl: shl$1, + shr: shr$1, + isOdd: isOdd$1, + naf: naf$1, + bits: bits$1, + toNumber: toNumber$1, + toArray: toArray$1, + add: add$1, + sub: sub$1, + neg: neg$1, + mul: mul$1, + square: square$1, + pow: pow$1, + exp: exp$2, + abs: abs$1, + div: div$1, + mod: mod$1, + eq: eq$1, + neq: neq$1, + lt: lt$1, + gt: gt$1, + leq: leq$1, + geq: geq$1, + band: band$1, + bor: bor$1, + bxor: bxor$1, + land: land$1, + lor: lor$1, + lnot: lnot$1 +}); + +const supportsNativeBigInt$2 = typeof BigInt === "function"; + +let Scalar$1 = {}; +if (supportsNativeBigInt$2) { + Object.assign(Scalar$1, Scalar_native); +} else { + Object.assign(Scalar$1, Scalar_bigint); +} + + +// Returns a buffer with Little Endian Representation +Scalar$1.toRprLE = function rprBE(buff, o, e, n8) { + const s = "0000000" + e.toString(16); + const v = new Uint32Array(buff.buffer, o, n8/4); + const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words; + for (let i=0; i> 5)+1; // Number of 32bit words; + for (let i=0; i a[a.length-i-1] = ch.toString(16).padStart(8,"0") ); + return Scalar$1.fromString(a.join(""), 16); +}; + +// Pases a buffer with Big Endian Representation +Scalar$1.fromRprBE = function rprLEM(buff, o, n8) { + n8 = n8 || buff.byteLength; + o = o || 0; + const v = new DataView(buff.buffer, buff.byteOffset + o, n8); + const a = new Array(n8/4); + for (let i=0; i. +*/ + +/* + This library does operations on polynomials with coefficients in a field F. + + A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented + by the array [ p0, p1, p2, ... , pn ]. + */ + +class PolField { + constructor (F) { + this.F = F; + + let rem = F.sqrt_t; + let s = F.sqrt_s; + + const five = this.F.add(this.F.add(this.F.two, this.F.two), this.F.one); + + this.w = new Array(s+1); + this.wi = new Array(s+1); + this.w[s] = this.F.pow(five, rem); + this.wi[s] = this.F.inv(this.w[s]); + + let n=s-1; + while (n>=0) { + this.w[n] = this.F.square(this.w[n+1]); + this.wi[n] = this.F.square(this.wi[n+1]); + n--; + } + + + this.roots = []; +/* for (let i=0; i<16; i++) { + let r = this.F.one; + n = 1 << i; + const rootsi = new Array(n); + for (let j=0; j this.F.sqrt_s) n = this.s; + for (let i=n; (i>=0) && (!this.roots[i]); i--) { + let r = this.F.one; + const nroots = 1 << i; + const rootsi = new Array(nroots); + for (let j=0; j a.length) { + [b, a] = [a, b]; + } + + if ((b.length <= 2) || (b.length < log2$2(a.length))) { + return this.mulNormal(a,b); + } else { + return this.mulFFT(a,b); + } + } + + mulNormal(a, b) { + let res = []; + for (let i=0; i0) { + const z = new Array(n).fill(this.F.zero); + return z.concat(p); + } else { + if (-n >= p.length) return []; + return p.slice(-n); + } + } + + eval2(p, x) { + let v = this.F.zero; + let ix = this.F.one; + for (let i=0; i> 1), + F.mul( + x, + _eval(p, newX, offset+step , step << 1, n >> 1))); + return res; + } + } + + lagrange(points) { + let roots = [this.F.one]; + for (let i=0; i> 1; + const p1 = this._fft(pall, bits-1, offset, step*2); + const p2 = this._fft(pall, bits-1, offset+step, step*2); + + const out = new Array(n); + + let m= this.F.one; + for (let i=0; i0 && this.F.eq(p[i], this.F.zero) ) i--; + return p.slice(0, i+1); + } + + eq(a, b) { + const pa = this.reduce(a); + const pb = this.reduce(b); + + if (pa.length != pb.length) return false; + for (let i=0; i=0; i--) { + res[i] = this.F.add(this.F.mul(res[i+1], r), p[i+1]); + } + return res; + } + + _next2Power(v) { + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; + } + + toString(p) { + const ap = this.normalize(p); + let S = ""; + for (let i=ap.length-1; i>=0; i--) { + if (!this.F.eq(p[i], this.F.zero)) { + if (S!="") S += " + "; + S = S + p[i].toString(10); + if (i>0) { + S = S + "x"; + if (i>1) { + S = S + "^" +i; + } + } + } + } + return S; + } + + normalize(p) { + const res = new Array(p.length); + for (let i=0; i + // rec = x^(k-2-scaleV)/ v + // + // res = x^m/v = x^(m + (2*k-2 - scaleV) - (2*k-2 - scaleV)) /v => + // res = rec * x^(m - (2*k-2 - scaleV)) => + // res = rec * x^(m - 2*k + 2 + scaleV) + + const rec = this._reciprocal(this.scaleX(v, scaleV), kbits); + const res = this.scaleX(rec, m - 2*k + 2 + scaleV); + + return res; + } + + div(_u, _v) { + if (_u.length < _v.length) return []; + const kbits = log2$2(_v.length-1)+1; + const k = 1 << kbits; + + const u = this.scaleX(_u, k-_v.length); + const v = this.scaleX(_v, k-_v.length); + + const n = v.length-1; + let m = u.length-1; + + const s = this._reciprocal(v, kbits); + let t; + if (m>2*n) { + t = this.sub(this.scaleX([this.F.one], 2*n), this.mul(s, v)); + } + + let q = []; + let rem = u; + let us, ut; + let finish = false; + + while (!finish) { + us = this.mul(rem, s); + q = this.add(q, this.scaleX(us, -2*n)); + + if ( m > 2*n ) { + ut = this.mul(rem, t); + rem = this.scaleX(ut, -2*n); + m = rem.length-1; + } else { + finish = true; + } + } + + return q; + } + + + // returns the ith nth-root of one + oneRoot(n, i) { + let nbits = log2$2(n-1)+1; + let res = this.F.one; + let r = i; + + if(i>=n) { + throw new Error("Given 'i' should be lower than 'n'"); + } + else if (1<0) { + if (r & 1 == 1) { + res = this.F.mul(res, this.w[nbits]); + } + r = r >> 1; + nbits --; + } + return res; + } + + computeVanishingPolinomial(bits, t) { + const m = 1 << bits; + return this.F.sub(this.F.pow(t, m), this.F.one); + } + + evaluateLagrangePolynomials(bits, t) { + const m= 1 << bits; + const tm = this.F.pow(t, m); + const u= new Array(m).fill(this.F.zero); + this._setRoots(bits); + const omega = this.w[bits]; + + if (this.F.eq(tm, this.F.one)) { + for (let i = 0; i < m; i++) { + if (this.F.eq(this.roots[bits][0],t)) { // i.e., t equals omega^i + u[i] = this.F.one; + return u; + } + } + } + + const z = this.F.sub(tm, this.F.one); + // let l = this.F.mul(z, this.F.pow(this.F.twoinv, m)); + let l = this.F.mul(z, this.F.inv(this.F.e(m))); + for (let i = 0; i < m; i++) { + u[i] = this.F.mul(l, this.F.inv(this.F.sub(t,this.roots[bits][i]))); + l = this.F.mul(l, omega); + } + + return u; + } + + log2(V) { + return log2$2(V); + } +} + +function log2$2( V ) +{ + return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); +} + + +function __fft$1(PF, pall, bits, offset, step) { + + const n = 1 << bits; + if (n==1) { + return [ pall[offset] ]; + } else if (n==2) { + return [ + PF.F.add(pall[offset], pall[offset + step]), + PF.F.sub(pall[offset], pall[offset + step])]; + } + + const ndiv2 = n >> 1; + const p1 = __fft$1(PF, pall, bits-1, offset, step*2); + const p2 = __fft$1(PF, pall, bits-1, offset+step, step*2); + + const out = new Array(n); + + for (let i=0; i> 1; + const p1 = __fft2(PF, pall.slice(0, ndiv2), bits-1); + const p2 = __fft2(PF, pall.slice(ndiv2), bits-1); + + const out = new Array(n); + + for (let i=0; i>=1; + } + return res; +} + +function rev(idx, bits) { + return ( + _revTable$1[idx >>> 24] | + (_revTable$1[(idx >>> 16) & 0xFF] << 8) | + (_revTable$1[(idx >>> 8) & 0xFF] << 16) | + (_revTable$1[idx & 0xFF] << 24) + ) >>> (32-bits); +} + +function __bitReverse(p, bits) { + for (let k=0; kk) { + const tmp= p[k]; + p[k] = p[r]; + p[r] = tmp; + } + } + +} + +/* + Copyright 2018 0kims association. + + This file is part of snarkjs. + + snarkjs is a free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your option) + any later version. + + snarkjs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + snarkjs. If not, see . +*/ + + +function mulScalar(F, base, e) { + let res; + + if (isZero(e)) return F.zero; + + const n = naf(e); + + if (n[n.length-1] == 1) { + res = base; + } else if (n[n.length-1] == -1) { + res = F.neg(base); + } else { + throw new Error("invlaud NAF"); + } + + for (let i=n.length-2; i>=0; i--) { + + res = F.double(res); + + if (n[i] == 1) { + res = F.add(res, base); + } else if (n[i] == -1) { + res = F.sub(res, base); + } + } + + return res; +} + + +/* +exports.mulScalar = (F, base, e) =>{ + let res = F.zero; + let rem = bigInt(e); + let exp = base; + + while (! rem.eq(bigInt.zero)) { + if (rem.and(bigInt.one).eq(bigInt.one)) { + res = F.add(res, exp); + } + exp = F.double(exp); + rem = rem.shiftRight(1); + } + + return res; +}; +*/ + + +function exp(F, base, e) { + + if (isZero(e)) return F.one; + + const n = bits(e); + + if (n.legth==0) return F.one; + + let res = base; + + for (let i=n.length-2; i>=0; i--) { + + res = F.square(res); + + if (n[i]) { + res = F.mul(res, base); + } + } + + return res; +} + +// Check here: https://eprint.iacr.org/2012/685.pdf + +function buildSqrt (F) { + if ((F.m % 2) == 1) { + if (eq(mod(F.p, 4), 1 )) { + if (eq(mod(F.p, 8), 1 )) { + if (eq(mod(F.p, 16), 1 )) { + // alg7_muller(F); + alg5_tonelliShanks(F); + } else if (eq(mod(F.p, 16), 9 )) { + alg4_kong(F); + } else { + throw new Error("Field withot sqrt"); + } + } else if (eq(mod(F.p, 8), 5 )) { + alg3_atkin(F); + } else { + throw new Error("Field withot sqrt"); + } + } else if (eq(mod(F.p, 4), 3 )) { + alg2_shanks(F); + } + } else { + const pm2mod4 = mod(pow(F.p, F.m/2), 4); + if (pm2mod4 == 1) { + alg10_adj(F); + } else if (pm2mod4 == 3) { + alg9_adj(F); + } else { + alg8_complex(F); + } + + } +} + + +function alg5_tonelliShanks(F) { + F.sqrt_q = pow(F.p, F.m); + + F.sqrt_s = 0; + F.sqrt_t = sub(F.sqrt_q, 1); + + while (!isOdd(F.sqrt_t)) { + F.sqrt_s = F.sqrt_s + 1; + F.sqrt_t = div(F.sqrt_t, 2); + } + + let c0 = F.one; + + while (F.eq(c0, F.one)) { + const c = F.random(); + F.sqrt_z = F.pow(c, F.sqrt_t); + c0 = F.pow(F.sqrt_z, 2 ** (F.sqrt_s-1) ); + } + + F.sqrt_tm1d2 = div(sub(F.sqrt_t, 1),2); + + F.sqrt = function(a) { + const F=this; + if (F.isZero(a)) return F.zero; + let w = F.pow(a, F.sqrt_tm1d2); + const a0 = F.pow( F.mul(F.square(w), a), 2 ** (F.sqrt_s-1) ); + if (F.eq(a0, F.negone)) return null; + + let v = F.sqrt_s; + let x = F.mul(a, w); + let b = F.mul(x, w); + let z = F.sqrt_z; + while (!F.eq(b, F.one)) { + let b2k = F.square(b); + let k=1; + while (!F.eq(b2k, F.one)) { + b2k = F.square(b2k); + k++; + } + + w = z; + for (let i=0; i>> 0; + st[d] = (st[d] ^ st[a]) >>> 0; + st[d] = ((st[d] << 16) | ((st[d]>>>16) & 0xFFFF)) >>> 0; + + st[c] = (st[c] + st[d]) >>> 0; + st[b] = (st[b] ^ st[c]) >>> 0; + st[b] = ((st[b] << 12) | ((st[b]>>>20) & 0xFFF)) >>> 0; + + st[a] = (st[a] + st[b]) >>> 0; + st[d] = (st[d] ^ st[a]) >>> 0; + st[d] = ((st[d] << 8) | ((st[d]>>>24) & 0xFF)) >>> 0; + + st[c] = (st[c] + st[d]) >>> 0; + st[b] = (st[b] ^ st[c]) >>> 0; + st[b] = ((st[b] << 7) | ((st[b]>>>25) & 0x7F)) >>> 0; +} + +function doubleRound(st) { + quarterRound(st, 0, 4, 8,12); + quarterRound(st, 1, 5, 9,13); + quarterRound(st, 2, 6,10,14); + quarterRound(st, 3, 7,11,15); + + quarterRound(st, 0, 5,10,15); + quarterRound(st, 1, 6,11,12); + quarterRound(st, 2, 7, 8,13); + quarterRound(st, 3, 4, 9,14); +} + +class ChaCha { + + constructor(seed) { + seed = seed || [0,0,0,0,0,0,0,0]; + this.state = [ + 0x61707865, + 0x3320646E, + 0x79622D32, + 0x6B206574, + seed[0], + seed[1], + seed[2], + seed[3], + seed[4], + seed[5], + seed[6], + seed[7], + 0, + 0, + 0, + 0 + ]; + this.idx = 16; + this.buff = new Array(16); + } + + nextU32() { + if (this.idx == 16) this.update(); + return this.buff[this.idx++]; + } + + nextU64() { + return add(mul(this.nextU32(), 0x100000000), this.nextU32()); + } + + nextBool() { + return (this.nextU32() & 1) == 1; + } + + update() { + // Copy the state + for (let i=0; i<16; i++) this.buff[i] = this.state[i]; + + // Apply the rounds + for (let i=0; i<10; i++) doubleRound(this.buff); + + // Add to the initial + for (let i=0; i<16; i++) this.buff[i] = (this.buff[i] + this.state[i]) >>> 0; + + this.idx = 0; + + this.state[12] = (this.state[12] + 1) >>> 0; + if (this.state[12] != 0) return; + this.state[13] = (this.state[13] + 1) >>> 0; + if (this.state[13] != 0) return; + this.state[14] = (this.state[14] + 1) >>> 0; + if (this.state[14] != 0) return; + this.state[15] = (this.state[15] + 1) >>> 0; + } +} + +function getRandomBytes(n) { + let array = new Uint8Array(n); + if (process.browser) { // Browser + if (typeof globalThis.crypto !== "undefined") { // Supported + globalThis.crypto.getRandomValues(array); + } else { // fallback + for (let i=0; i>>0; + } + } + } + else { // NodeJS + crypto__default["default"].randomFillSync(array); + } + return array; +} + +function getRandomSeed() { + const arr = getRandomBytes(32); + const arrV = new Uint32Array(arr.buffer); + const seed = []; + for (let i=0; i<8; i++) { + seed.push(arrV[i]); + } + return seed; +} + +let threadRng = null; + +function getThreadRng() { + if (threadRng) return threadRng; + threadRng = new ChaCha(getRandomSeed()); + return threadRng; +} + +/* + Copyright 2018 0kims association. + + This file is part of snarkjs. + + snarkjs is a free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your option) + any later version. + + snarkjs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + snarkjs. If not, see . +*/ + +/* + This library does operations on polynomials with coefficients in a field F. + + A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented + by the array [ p0, p1, p2, ... , pn ]. + */ + +class FFT { + constructor (G, F, opMulGF) { + this.F = F; + this.G = G; + this.opMulGF = opMulGF; + + let rem = F.sqrt_t; + let s = F.sqrt_s; + + let nqr = F.one; + while (F.eq(F.pow(nqr, F.half), F.one)) nqr = F.add(nqr, F.one); + + this.w = new Array(s+1); + this.wi = new Array(s+1); + this.w[s] = this.F.pow(nqr, rem); + this.wi[s] = this.F.inv(this.w[s]); + + let n=s-1; + while (n>=0) { + this.w[n] = this.F.square(this.w[n+1]); + this.wi[n] = this.F.square(this.wi[n+1]); + n--; + } + + + this.roots = []; + /* + for (let i=0; i<16; i++) { + let r = this.F.one; + n = 1 << i; + const rootsi = new Array(n); + for (let j=0; j=0) && (!this.roots[i]); i--) { + let r = this.F.one; + const nroots = 1 << i; + const rootsi = new Array(nroots); + for (let j=0; j> 1; + const p1 = __fft(PF, pall, bits-1, offset, step*2); + const p2 = __fft(PF, pall, bits-1, offset+step, step*2); + + const out = new Array(n); + + for (let i=0; i> this.one; + this.bitLength = bitLength(this.p); + this.mask = (this.one << BigInt(this.bitLength)) - this.one; + + this.n64 = Math.floor((this.bitLength - 1) / 64)+1; + this.n32 = this.n64*2; + this.n8 = this.n64*8; + this.R = this.e(this.one << BigInt(this.n64*64)); + this.Ri = this.inv(this.R); + + const e = this.negone >> this.one; + this.nqr = this.two; + let r = this.pow(this.nqr, e); + while (!this.eq(r, this.negone)) { + this.nqr = this.nqr + this.one; + r = this.pow(this.nqr, e); + } + + + this.s = 0; + this.t = this.negone; + + while ((this.t & this.one) == this.zero) { + this.s = this.s + 1; + this.t = this.t >> this.one; + } + + this.nqr_to_t = this.pow(this.nqr, this.t); + + buildSqrt(this); + + this.FFT = new FFT(this, this, this.mul.bind(this)); + this.shift = this.square(this.nqr); + } + + e(a,b) { + let res; + if (!b) { + res = BigInt(a); + } else if (b==16) { + res = BigInt("0x"+a); + } + if (res < 0) { + let nres = -res; + if (nres >= this.p) nres = nres % this.p; + return this.p - nres; + } else { + return (res>= this.p) ? res%this.p : res; + } + + } + + add(a, b) { + const res = a + b; + return res >= this.p ? res-this.p : res; + } + + sub(a, b) { + return (a >= b) ? a-b : this.p-b+a; + } + + neg(a) { + return a ? this.p-a : a; + } + + mul(a, b) { + return (a*b)%this.p; + } + + mulScalar(base, s) { + return (base * this.e(s)) % this.p; + } + + square(a) { + return (a*a) % this.p; + } + + eq(a, b) { + return a==b; + } + + neq(a, b) { + return a!=b; + } + + lt(a, b) { + const aa = (a > this.half) ? a - this.p : a; + const bb = (b > this.half) ? b - this.p : b; + return aa < bb; + } + + gt(a, b) { + const aa = (a > this.half) ? a - this.p : a; + const bb = (b > this.half) ? b - this.p : b; + return aa > bb; + } + + leq(a, b) { + const aa = (a > this.half) ? a - this.p : a; + const bb = (b > this.half) ? b - this.p : b; + return aa <= bb; + } + + geq(a, b) { + const aa = (a > this.half) ? a - this.p : a; + const bb = (b > this.half) ? b - this.p : b; + return aa >= bb; + } + + div(a, b) { + return this.mul(a, this.inv(b)); + } + + idiv(a, b) { + if (!b) throw new Error("Division by zero"); + return a / b; + } + + inv(a) { + if (!a) throw new Error("Division by zero"); + + let t = this.zero; + let r = this.p; + let newt = this.one; + let newr = a % this.p; + while (newr) { + let q = r/newr; + [t, newt] = [newt, t-q*newt]; + [r, newr] = [newr, r-q*newr]; + } + if (t= this.p ? res-this.p : res; + } + + bor(a, b) { + const res = ((a | b) & this.mask); + return res >= this.p ? res-this.p : res; + } + + bxor(a, b) { + const res = ((a ^ b) & this.mask); + return res >= this.p ? res-this.p : res; + } + + bnot(a) { + const res = a ^ this.mask; + return res >= this.p ? res-this.p : res; + } + + shl(a, b) { + if (Number(b) < this.bitLength) { + const res = (a << b) & this.mask; + return res >= this.p ? res-this.p : res; + } else { + const nb = this.p - b; + if (Number(nb) < this.bitLength) { + return a >> nb; + } else { + return this.zero; + } + } + } + + shr(a, b) { + if (Number(b) < this.bitLength) { + return a >> b; + } else { + const nb = this.p - b; + if (Number(nb) < this.bitLength) { + const res = (a << nb) & this.mask; + return res >= this.p ? res-this.p : res; + } else { + return 0; + } + } + } + + land(a, b) { + return (a && b) ? this.one : this.zero; + } + + lor(a, b) { + return (a || b) ? this.one : this.zero; + } + + lnot(a) { + return (a) ? this.zero : this.one; + } + + sqrt_old(n) { + + if (n == this.zero) return this.zero; + + // Test that have solution + const res = this.pow(n, this.negone >> this.one); + if ( res != this.one ) return null; + + let m = this.s; + let c = this.nqr_to_t; + let t = this.pow(n, this.t); + let r = this.pow(n, this.add(this.t, this.one) >> this.one ); + + while ( t != this.one ) { + let sq = this.square(t); + let i = 1; + while (sq != this.one ) { + i++; + sq = this.square(sq); + } + + // b = c ^ m-i-1 + let b = c; + for (let j=0; j< m-i-1; j ++) b = this.square(b); + + m = i; + c = this.square(b); + t = this.mul(t, c); + r = this.mul(r, b); + } + + if (r > (this.p >> this.one)) { + r = this.neg(r); + } + + return r; + } + + normalize(a, b) { + a = BigInt(a,b); + if (a < 0) { + let na = -a; + if (na >= this.p) na = na % this.p; + return this.p - na; + } else { + return (a>= this.p) ? a%this.p : a; + } + } + + random() { + const nBytes = (this.bitLength*2 / 8); + let res =this.zero; + for (let i=0; i this.half)&&(base == 10)) { + const v = this.p-a; + vs = "-"+v.toString(base); + } else { + vs = a.toString(base); + } + return vs; + } + + isZero(a) { + return a == this.zero; + } + + fromRng(rng) { + let v; + do { + v=this.zero; + for (let i=0; i= this.p); + v = (v * this.Ri) % this.p; // Convert from montgomery + return v; + } + + fft(a) { + return this.FFT.fft(a); + } + + ifft(a) { + return this.FFT.ifft(a); + } + +} + +class ZqField { + constructor(p) { + this.type="F1"; + this.one = bigInt__default["default"].one; + this.zero = bigInt__default["default"].zero; + this.p = bigInt__default["default"](p); + this.m = 1; + this.negone = this.p.minus(bigInt__default["default"].one); + this.two = bigInt__default["default"](2); + this.half = this.p.shiftRight(1); + this.bitLength = this.p.bitLength(); + this.mask = bigInt__default["default"].one.shiftLeft(this.bitLength).minus(bigInt__default["default"].one); + + this.n64 = Math.floor((this.bitLength - 1) / 64)+1; + this.n32 = this.n64*2; + this.n8 = this.n64*8; + this.R = bigInt__default["default"].one.shiftLeft(this.n64*64); + this.Ri = this.inv(this.R); + + const e = this.negone.shiftRight(this.one); + this.nqr = this.two; + let r = this.pow(this.nqr, e); + while (!r.equals(this.negone)) { + this.nqr = this.nqr.add(this.one); + r = this.pow(this.nqr, e); + } + + this.s = this.zero; + this.t = this.negone; + + while (!this.t.isOdd()) { + this.s = this.s.add(this.one); + this.t = this.t.shiftRight(this.one); + } + + this.nqr_to_t = this.pow(this.nqr, this.t); + + buildSqrt(this); + + this.FFT = new FFFT(this, this, this.mul.bind(this)); + + this.shift = this.square(this.nqr); + } + + e(a,b) { + + const res = bigInt__default["default"](a,b); + + return this.normalize(res); + + } + + add(a, b) { + let res = a.add(b); + if (res.geq(this.p)) { + res = res.minus(this.p); + } + return res; + } + + sub(a, b) { + if (a.geq(b)) { + return a.minus(b); + } else { + return this.p.minus(b.minus(a)); + } + } + + neg(a) { + if (a.isZero()) return a; + return this.p.minus(a); + } + + mul(a, b) { + return a.times(b).mod(this.p); + } + + mulScalar(base, s) { + return base.times(bigInt__default["default"](s)).mod(this.p); + } + + square(a) { + return a.square().mod(this.p); + } + + eq(a, b) { + return a.eq(b); + } + + neq(a, b) { + return a.neq(b); + } + + lt(a, b) { + const aa = a.gt(this.half) ? a.minus(this.p) : a; + const bb = b.gt(this.half) ? b.minus(this.p) : b; + return aa.lt(bb); + } + + gt(a, b) { + const aa = a.gt(this.half) ? a.minus(this.p) : a; + const bb = b.gt(this.half) ? b.minus(this.p) : b; + return aa.gt(bb); + } + + leq(a, b) { + const aa = a.gt(this.half) ? a.minus(this.p) : a; + const bb = b.gt(this.half) ? b.minus(this.p) : b; + return aa.leq(bb); + } + + geq(a, b) { + const aa = a.gt(this.half) ? a.minus(this.p) : a; + const bb = b.gt(this.half) ? b.minus(this.p) : b; + return aa.geq(bb); + } + + div(a, b) { + if (b.isZero()) throw new Error("Division by zero"); + return a.times(b.modInv(this.p)).mod(this.p); + } + + idiv(a, b) { + if (b.isZero()) throw new Error("Division by zero"); + return a.divide(b); + } + + inv(a) { + if (a.isZero()) throw new Error("Division by zero"); + return a.modInv(this.p); + } + + mod(a, b) { + return a.mod(b); + } + + pow(a, b) { + return a.modPow(b, this.p); + } + + exp(a, b) { + return a.modPow(b, this.p); + } + + band(a, b) { + return a.and(b).and(this.mask).mod(this.p); + } + + bor(a, b) { + return a.or(b).and(this.mask).mod(this.p); + } + + bxor(a, b) { + return a.xor(b).and(this.mask).mod(this.p); + } + + bnot(a) { + return a.xor(this.mask).mod(this.p); + } + + shl(a, b) { + if (b.lt(this.bitLength)) { + return a.shiftLeft(b).and(this.mask).mod(this.p); + } else { + const nb = this.p.minus(b); + if (nb.lt(this.bitLength)) { + return this.shr(a, nb); + } else { + return bigInt__default["default"].zero; + } + } + } + + shr(a, b) { + if (b.lt(this.bitLength)) { + return a.shiftRight(b); + } else { + const nb = this.p.minus(b); + if (nb.lt(this.bitLength)) { + return this.shl(a, nb); + } else { + return bigInt__default["default"].zero; + } + } + } + + land(a, b) { + return (a.isZero() || b.isZero()) ? bigInt__default["default"].zero : bigInt__default["default"].one; + } + + lor(a, b) { + return (a.isZero() && b.isZero()) ? bigInt__default["default"].zero : bigInt__default["default"].one; + } + + lnot(a) { + return a.isZero() ? bigInt__default["default"].one : bigInt__default["default"].zero; + } + + sqrt_old(n) { + + if (n.equals(this.zero)) return this.zero; + + // Test that have solution + const res = this.pow(n, this.negone.shiftRight(this.one)); + if (!res.equals(this.one)) return null; + + let m = parseInt(this.s); + let c = this.nqr_to_t; + let t = this.pow(n, this.t); + let r = this.pow(n, this.add(this.t, this.one).shiftRight(this.one) ); + + while (!t.equals(this.one)) { + let sq = this.square(t); + let i = 1; + while (!sq.equals(this.one)) { + i++; + sq = this.square(sq); + } + + // b = c ^ m-i-1 + let b = c; + for (let j=0; j< m-i-1; j ++) b = this.square(b); + + m = i; + c = this.square(b); + t = this.mul(t, c); + r = this.mul(r, b); + } + + if (r.greater(this.p.shiftRight(this.one))) { + r = this.neg(r); + } + + return r; + } + + normalize(a) { + a = bigInt__default["default"](a); + if (a.isNegative()) { + return this.p.minus(a.abs().mod(this.p)); + } else { + return a.mod(this.p); + } + } + + random() { + let res = bigInt__default["default"](0); + let n = bigInt__default["default"](this.p.square()); + while (!n.isZero()) { + res = res.shiftLeft(8).add(bigInt__default["default"](getRandomBytes(1)[0])); + n = n.shiftRight(8); + } + return res.mod(this.p); + } + + toString(a, base) { + base = base || 10; + let vs; + if ((!a.lesserOrEquals(this.p.shiftRight(bigInt__default["default"](1))))&&(base==10)) { + const v = this.p.minus(a); + vs = "-"+v.toString(base); + } else { + vs = a.toString(base); + } + + return vs; + } + + isZero(a) { + return a.isZero(); + } + + fromRng(rng) { + let v; + do { + v = bigInt__default["default"](0); + for (let i=0; i. +*/ + +class F2Field { + constructor(F, nonResidue) { + this.type="F2"; + this.F = F; + this.zero = [this.F.zero, this.F.zero]; + this.one = [this.F.one, this.F.zero]; + this.negone = this.neg(this.one); + this.nonResidue = nonResidue; + this.m = F.m*2; + this.p = F.p; + this.n64 = F.n64*2; + this.n32 = this.n64*2; + this.n8 = this.n64*8; + + buildSqrt(this); + } + + _mulByNonResidue(a) { + return this.F.mul(this.nonResidue, a); + } + + copy(a) { + return [this.F.copy(a[0]), this.F.copy(a[1])]; + } + + add(a, b) { + return [ + this.F.add(a[0], b[0]), + this.F.add(a[1], b[1]) + ]; + } + + double(a) { + return this.add(a,a); + } + + sub(a, b) { + return [ + this.F.sub(a[0], b[0]), + this.F.sub(a[1], b[1]) + ]; + } + + neg(a) { + return this.sub(this.zero, a); + } + + conjugate(a) { + return [ + a[0], + this.F.neg(a[1]) + ]; + } + + mul(a, b) { + const aA = this.F.mul(a[0] , b[0]); + const bB = this.F.mul(a[1] , b[1]); + + return [ + this.F.add( aA , this._mulByNonResidue(bB)), + this.F.sub( + this.F.mul( + this.F.add(a[0], a[1]), + this.F.add(b[0], b[1])), + this.F.add(aA, bB))]; + } + + inv(a) { + const t0 = this.F.square(a[0]); + const t1 = this.F.square(a[1]); + const t2 = this.F.sub(t0, this._mulByNonResidue(t1)); + const t3 = this.F.inv(t2); + return [ + this.F.mul(a[0], t3), + this.F.neg(this.F.mul( a[1], t3)) ]; + } + + div(a, b) { + return this.mul(a, this.inv(b)); + } + + square(a) { + const ab = this.F.mul(a[0] , a[1]); + + /* + [ + (a + b) * (a + non_residue * b) - ab - non_residue * ab, + ab + ab + ]; + */ + + return [ + this.F.sub( + this.F.mul( + this.F.add(a[0], a[1]) , + this.F.add( + a[0] , + this._mulByNonResidue(a[1]))), + this.F.add( + ab, + this._mulByNonResidue(ab))), + this.F.add(ab, ab) + ]; + } + + isZero(a) { + return this.F.isZero(a[0]) && this.F.isZero(a[1]); + } + + eq(a, b) { + return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]); + } + + mulScalar(base, e) { + return mulScalar(this, base, e); + } + + pow(base, e) { + return exp(this, base, e); + } + + exp(base, e) { + return exp(this, base, e); + } + + toString(a) { + return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])} ]`; + } + + fromRng(rng) { + const c0 = this.F.fromRng(rng); + const c1 = this.F.fromRng(rng); + return [c0, c1]; + } + + gt(a, b) { + if (this.F.gt(a[0], b[0])) return true; + if (this.F.gt(b[0], a[0])) return false; + if (this.F.gt(a[1], b[1])) return true; + return false; + } + + geq(a, b) { + return this.gt(a, b) || this.eq(a, b); + } + + lt(a, b) { + return !this.geq(a,b); + } + + leq(a, b) { + return !this.gt(a,b); + } + + neq(a, b) { + return !this.eq(a,b); + } + + random() { + return [this.F.random(), this.F.random()]; + } + + + toRprLE(buff, o, e) { + this.F.toRprLE(buff, o, e[0]); + this.F.toRprLE(buff, o+this.F.n8, e[1]); + } + + toRprBE(buff, o, e) { + this.F.toRprBE(buff, o, e[1]); + this.F.toRprBE(buff, o+this.F.n8, e[0]); + } + + toRprLEM(buff, o, e) { + this.F.toRprLEM(buff, o, e[0]); + this.F.toRprLEM(buff, o+this.F.n8, e[1]); + } + + + toRprBEM(buff, o, e) { + this.F.toRprBEM(buff, o, e[1]); + this.F.toRprBEM(buff, o+this.F.n8, e[0]); + } + + fromRprLE(buff, o) { + o = o || 0; + const c0 = this.F.fromRprLE(buff, o); + const c1 = this.F.fromRprLE(buff, o+this.F.n8); + return [c0, c1]; + } + + fromRprBE(buff, o) { + o = o || 0; + const c1 = this.F.fromRprBE(buff, o); + const c0 = this.F.fromRprBE(buff, o+this.F.n8); + return [c0, c1]; + } + + fromRprLEM(buff, o) { + o = o || 0; + const c0 = this.F.fromRprLEM(buff, o); + const c1 = this.F.fromRprLEM(buff, o+this.F.n8); + return [c0, c1]; + } + + fromRprBEM(buff, o) { + o = o || 0; + const c1 = this.F.fromRprBEM(buff, o); + const c0 = this.F.fromRprBEM(buff, o+this.F.n8); + return [c0, c1]; + } + + toObject(a) { + return a; + } + +} + +/* + Copyright 2018 0kims association. + + This file is part of snarkjs. + + snarkjs is a free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your option) + any later version. + + snarkjs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + snarkjs. If not, see . +*/ + +class F3Field { + constructor(F, nonResidue) { + this.type="F3"; + this.F = F; + this.zero = [this.F.zero, this.F.zero, this.F.zero]; + this.one = [this.F.one, this.F.zero, this.F.zero]; + this.negone = this.neg(this.one); + this.nonResidue = nonResidue; + this.m = F.m*3; + this.p = F.p; + this.n64 = F.n64*3; + this.n32 = this.n64*2; + this.n8 = this.n64*8; + } + + _mulByNonResidue(a) { + return this.F.mul(this.nonResidue, a); + } + + copy(a) { + return [this.F.copy(a[0]), this.F.copy(a[1]), this.F.copy(a[2])]; + } + + add(a, b) { + return [ + this.F.add(a[0], b[0]), + this.F.add(a[1], b[1]), + this.F.add(a[2], b[2]) + ]; + } + + double(a) { + return this.add(a,a); + } + + sub(a, b) { + return [ + this.F.sub(a[0], b[0]), + this.F.sub(a[1], b[1]), + this.F.sub(a[2], b[2]) + ]; + } + + neg(a) { + return this.sub(this.zero, a); + } + + mul(a, b) { + + const aA = this.F.mul(a[0] , b[0]); + const bB = this.F.mul(a[1] , b[1]); + const cC = this.F.mul(a[2] , b[2]); + + return [ + this.F.add( + aA, + this._mulByNonResidue( + this.F.sub( + this.F.mul( + this.F.add(a[1], a[2]), + this.F.add(b[1], b[2])), + this.F.add(bB, cC)))), // aA + non_residue*((b+c)*(B+C)-bB-cC), + + this.F.add( + this.F.sub( + this.F.mul( + this.F.add(a[0], a[1]), + this.F.add(b[0], b[1])), + this.F.add(aA, bB)), + this._mulByNonResidue( cC)), // (a+b)*(A+B)-aA-bB+non_residue*cC + + this.F.add( + this.F.sub( + this.F.mul( + this.F.add(a[0], a[2]), + this.F.add(b[0], b[2])), + this.F.add(aA, cC)), + bB)]; // (a+c)*(A+C)-aA+bB-cC) + } + + inv(a) { + const t0 = this.F.square(a[0]); // t0 = a^2 ; + const t1 = this.F.square(a[1]); // t1 = b^2 ; + const t2 = this.F.square(a[2]); // t2 = c^2; + const t3 = this.F.mul(a[0],a[1]); // t3 = ab + const t4 = this.F.mul(a[0],a[2]); // t4 = ac + const t5 = this.F.mul(a[1],a[2]); // t5 = bc; + // c0 = t0 - non_residue * t5; + const c0 = this.F.sub(t0, this._mulByNonResidue(t5)); + // c1 = non_residue * t2 - t3; + const c1 = this.F.sub(this._mulByNonResidue(t2), t3); + const c2 = this.F.sub(t1, t4); // c2 = t1-t4 + + // t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inv(); + const t6 = + this.F.inv( + this.F.add( + this.F.mul(a[0], c0), + this._mulByNonResidue( + this.F.add( + this.F.mul(a[2], c1), + this.F.mul(a[1], c2))))); + + return [ + this.F.mul(t6, c0), // t6*c0 + this.F.mul(t6, c1), // t6*c1 + this.F.mul(t6, c2)]; // t6*c2 + } + + div(a, b) { + return this.mul(a, this.inv(b)); + } + + square(a) { + const s0 = this.F.square(a[0]); // s0 = a^2 + const ab = this.F.mul(a[0], a[1]); // ab = a*b + const s1 = this.F.add(ab, ab); // s1 = 2ab; + const s2 = this.F.square( + this.F.add(this.F.sub(a[0],a[1]), a[2])); // s2 = (a - b + c)^2; + const bc = this.F.mul(a[1],a[2]); // bc = b*c + const s3 = this.F.add(bc, bc); // s3 = 2*bc + const s4 = this.F.square(a[2]); // s4 = c^2 + + + return [ + this.F.add( + s0, + this._mulByNonResidue(s3)), // s0 + non_residue * s3, + this.F.add( + s1, + this._mulByNonResidue(s4)), // s1 + non_residue * s4, + this.F.sub( + this.F.add( this.F.add(s1, s2) , s3 ), + this.F.add(s0, s4))]; // s1 + s2 + s3 - s0 - s4 + } + + isZero(a) { + return this.F.isZero(a[0]) && this.F.isZero(a[1]) && this.F.isZero(a[2]); + } + + eq(a, b) { + return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]) && this.F.eq(a[2], b[2]); + } + + affine(a) { + return [this.F.affine(a[0]), this.F.affine(a[1]), this.F.affine(a[2])]; + } + + mulScalar(base, e) { + return mulScalar(this, base, e); + } + + pow(base, e) { + return exp(this, base, e); + } + + exp(base, e) { + return exp(this, base, e); + } + + toString(a) { + return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])}, ${this.F.toString(a[2])} ]`; + } + + fromRng(rng) { + const c0 = this.F.fromRng(rng); + const c1 = this.F.fromRng(rng); + const c2 = this.F.fromRng(rng); + return [c0, c1, c2]; + } + + gt(a, b) { + if (this.F.gt(a[0], b[0])) return true; + if (this.F.gt(b[0], a[0])) return false; + if (this.F.gt(a[1], b[1])) return true; + if (this.F.gt(b[1], a[1])) return false; + if (this.F.gt(a[2], b[2])) return true; + return false; + } + + + geq(a, b) { + return this.gt(a, b) || this.eq(a, b); + } + + lt(a, b) { + return !this.geq(a,b); + } + + leq(a, b) { + return !this.gt(a,b); + } + + neq(a, b) { + return !this.eq(a,b); + } + + random() { + return [this.F.random(), this.F.random(), this.F.random()]; + } + + + toRprLE(buff, o, e) { + this.F.toRprLE(buff, o, e[0]); + this.F.toRprLE(buff, o+this.F.n8, e[1]); + this.F.toRprLE(buff, o+this.F.n8*2, e[2]); + } + + toRprBE(buff, o, e) { + this.F.toRprBE(buff, o, e[2]); + this.F.toRprBE(buff, o+this.F.n8, e[1]); + this.F.toRprBE(buff, o+this.F.n8*2, e[0]); + } + + toRprLEM(buff, o, e) { + this.F.toRprLEM(buff, o, e[0]); + this.F.toRprLEM(buff, o+this.F.n8, e[1]); + this.F.toRprLEM(buff, o+this.F.n8*2, e[2]); + } + + + toRprBEM(buff, o, e) { + this.F.toRprBEM(buff, o, e[2]); + this.F.toRprBEM(buff, o+this.F.n8, e[1]); + this.F.toRprBEM(buff, o+this.F.n8*2, e[0]); + } + + fromRprLE(buff, o) { + o = o || 0; + const c0 = this.F.fromRprLE(buff, o); + const c1 = this.F.fromRprLE(buff, o+this.n8); + const c2 = this.F.fromRprLE(buff, o+this.n8*2); + return [c0, c1, c2]; + } + + fromRprBE(buff, o) { + o = o || 0; + const c2 = this.F.fromRprBE(buff, o); + const c1 = this.F.fromRprBE(buff, o+this.n8); + const c0 = this.F.fromRprBE(buff, o+this.n8*2); + return [c0, c1, c2]; + } + + fromRprLEM(buff, o) { + o = o || 0; + const c0 = this.F.fromRprLEM(buff, o); + const c1 = this.F.fromRprLEM(buff, o+this.n8); + const c2 = this.F.fromRprLEM(buff, o+this.n8*2); + return [c0, c1, c2]; + } + + fromRprBEM(buff, o) { + o = o || 0; + const c2 = this.F.fromRprBEM(buff, o); + const c1 = this.F.fromRprBEM(buff, o+this.n8); + const c0 = this.F.fromRprBEM(buff, o+this.n8*2); + return [c0, c1, c2]; + } + + toObject(a) { + return a; + } +} + +/* + Copyright 2018 0kims association. + + This file is part of snarkjs. + + snarkjs is a free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your option) + any later version. + + snarkjs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + snarkjs. If not, see . +*/ + + +function isGreatest(F, a) { + if (Array.isArray(a)) { + for (let i=a.length-1; i>=0; i--) { + if (!F.F.isZero(a[i])) { + return isGreatest(F.F, a[i]); + } + } + return 0; + } else { + const na = F.neg(a); + return gt(a, na); + } +} + + +class EC { + + constructor(F, g) { + this.F = F; + this.g = g; + if (this.g.length == 2) this.g[2] = this.F.one; + this.zero = [this.F.zero, this.F.one, this.F.zero]; + } + + add(p1, p2) { + + const F = this.F; + + if (this.eq(p1, this.zero)) return p2; + if (this.eq(p2, this.zero)) return p1; + + const res = new Array(3); + + const Z1Z1 = F.square( p1[2] ); + const Z2Z2 = F.square( p2[2] ); + + const U1 = F.mul( p1[0] , Z2Z2 ); // U1 = X1 * Z2Z2 + const U2 = F.mul( p2[0] , Z1Z1 ); // U2 = X2 * Z1Z1 + + const Z1_cubed = F.mul( p1[2] , Z1Z1); + const Z2_cubed = F.mul( p2[2] , Z2Z2); + + const S1 = F.mul( p1[1] , Z2_cubed); // S1 = Y1 * Z2 * Z2Z2 + const S2 = F.mul( p2[1] , Z1_cubed); // S2 = Y2 * Z1 * Z1Z1 + + if (F.eq(U1,U2) && F.eq(S1,S2)) { + return this.double(p1); + } + + const H = F.sub( U2 , U1 ); // H = U2-U1 + + const S2_minus_S1 = F.sub( S2 , S1 ); + + const I = F.square( F.add(H,H) ); // I = (2 * H)^2 + const J = F.mul( H , I ); // J = H * I + + const r = F.add( S2_minus_S1 , S2_minus_S1 ); // r = 2 * (S2-S1) + const V = F.mul( U1 , I ); // V = U1 * I + + res[0] = + F.sub( + F.sub( F.square(r) , J ), + F.add( V , V )); // X3 = r^2 - J - 2 * V + + const S1_J = F.mul( S1 , J ); + + res[1] = + F.sub( + F.mul( r , F.sub(V,res[0])), + F.add( S1_J,S1_J )); // Y3 = r * (V-X3)-2 S1 J + + res[2] = + F.mul( + H, + F.sub( + F.square( F.add(p1[2],p2[2]) ), + F.add( Z1Z1 , Z2Z2 ))); // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H + + return res; + } + + neg(p) { + return [p[0], this.F.neg(p[1]), p[2]]; + } + + sub(a, b) { + return this.add(a, this.neg(b)); + } + + double(p) { + const F = this.F; + + const res = new Array(3); + + if (this.eq(p, this.zero)) return p; + + const A = F.square( p[0] ); // A = X1^2 + const B = F.square( p[1] ); // B = Y1^2 + const C = F.square( B ); // C = B^2 + + let D = + F.sub( + F.square( F.add(p[0] , B )), + F.add( A , C)); + D = F.add(D,D); // D = 2 * ((X1 + B)^2 - A - C) + + const E = F.add( F.add(A,A), A); // E = 3 * A + const FF =F.square( E ); // F = E^2 + + res[0] = F.sub( FF , F.add(D,D) ); // X3 = F - 2 D + + let eightC = F.add( C , C ); + eightC = F.add( eightC , eightC ); + eightC = F.add( eightC , eightC ); + + res[1] = + F.sub( + F.mul( + E, + F.sub( D, res[0] )), + eightC); // Y3 = E * (D - X3) - 8 * C + + const Y1Z1 = F.mul( p[1] , p[2] ); + res[2] = F.add( Y1Z1 , Y1Z1 ); // Z3 = 2 * Y1 * Z1 + + return res; + } + + timesScalar(base, e) { + return mulScalar(this, base, e); + } + + mulScalar(base, e) { + return mulScalar(this, base, e); + } + + affine(p) { + const F = this.F; + if (this.isZero(p)) { + return this.zero; + } else if (F.eq(p[2], F.one)) { + return p; + } else { + const Z_inv = F.inv(p[2]); + const Z2_inv = F.square(Z_inv); + const Z3_inv = F.mul(Z2_inv, Z_inv); + + const res = new Array(3); + res[0] = F.mul(p[0],Z2_inv); + res[1] = F.mul(p[1],Z3_inv); + res[2] = F.one; + + return res; + } + } + + multiAffine(arr) { + const keys = Object.keys(arr); + const F = this.F; + const accMul = new Array(keys.length+1); + accMul[0] = F.one; + for (let i = 0; i< keys.length; i++) { + if (F.eq(arr[keys[i]][2], F.zero)) { + accMul[i+1] = accMul[i]; + } else { + accMul[i+1] = F.mul(accMul[i], arr[keys[i]][2]); + } + } + + accMul[keys.length] = F.inv(accMul[keys.length]); + + for (let i = keys.length-1; i>=0; i--) { + if (F.eq(arr[keys[i]][2], F.zero)) { + accMul[i] = accMul[i+1]; + arr[keys[i]] = this.zero; + } else { + const Z_inv = F.mul(accMul[i], accMul[i+1]); + accMul[i] = F.mul(arr[keys[i]][2], accMul[i+1]); + + const Z2_inv = F.square(Z_inv); + const Z3_inv = F.mul(Z2_inv, Z_inv); + + arr[keys[i]][0] = F.mul(arr[keys[i]][0],Z2_inv); + arr[keys[i]][1] = F.mul(arr[keys[i]][1],Z3_inv); + arr[keys[i]][2] = F.one; + } + } + + } + + eq(p1, p2) { + const F = this.F; + + if (this.F.eq(p1[2], this.F.zero)) return this.F.eq(p2[2], this.F.zero); + if (this.F.eq(p2[2], this.F.zero)) return false; + + const Z1Z1 = F.square( p1[2] ); + const Z2Z2 = F.square( p2[2] ); + + const U1 = F.mul( p1[0] , Z2Z2 ); + const U2 = F.mul( p2[0] , Z1Z1 ); + + const Z1_cubed = F.mul( p1[2] , Z1Z1); + const Z2_cubed = F.mul( p2[2] , Z2Z2); + + const S1 = F.mul( p1[1] , Z2_cubed); + const S2 = F.mul( p2[1] , Z1_cubed); + + return (F.eq(U1,U2) && F.eq(S1,S2)); + } + + isZero(p) { + return this.F.isZero(p[2]); + } + + toString(p) { + const cp = this.affine(p); + return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`; + } + + fromRng(rng) { + const F = this.F; + let P = []; + let greatest; + do { + P[0] = F.fromRng(rng); + greatest = rng.nextBool(); + const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b); + P[1] = F.sqrt(x3b); + } while ((P[1] == null)||(F.isZero[P])); + + const s = isGreatest(F, P[1]); + if (greatest ^ s) P[1] = F.neg(P[1]); + P[2] = F.one; + + if (this.cofactor) { + P = this.mulScalar(P, this.cofactor); + } + + P = this.affine(P); + + return P; + + } + + toRprLE(buff, o, p) { + p = this.affine(p); + if (this.isZero(p)) { + const BuffV = new Uint8Array(buff, o, this.F.n8*2); + BuffV.fill(0); + return; + } + this.F.toRprLE(buff, o, p[0]); + this.F.toRprLE(buff, o+this.F.n8, p[1]); + } + + toRprBE(buff, o, p) { + p = this.affine(p); + if (this.isZero(p)) { + const BuffV = new Uint8Array(buff, o, this.F.n8*2); + BuffV.fill(0); + return; + } + this.F.toRprBE(buff, o, p[0]); + this.F.toRprBE(buff, o+this.F.n8, p[1]); + } + + toRprLEM(buff, o, p) { + p = this.affine(p); + if (this.isZero(p)) { + const BuffV = new Uint8Array(buff, o, this.F.n8*2); + BuffV.fill(0); + return; + } + this.F.toRprLEM(buff, o, p[0]); + this.F.toRprLEM(buff, o+this.F.n8, p[1]); + } + + toRprLEJM(buff, o, p) { + p = this.affine(p); + if (this.isZero(p)) { + const BuffV = new Uint8Array(buff, o, this.F.n8*2); + BuffV.fill(0); + return; + } + this.F.toRprLEM(buff, o, p[0]); + this.F.toRprLEM(buff, o+this.F.n8, p[1]); + this.F.toRprLEM(buff, o+2*this.F.n8, p[2]); + } + + + toRprBEM(buff, o, p) { + p = this.affine(p); + if (this.isZero(p)) { + const BuffV = new Uint8Array(buff, o, this.F.n8*2); + BuffV.fill(0); + return; + } + this.F.toRprBEM(buff, o, p[0]); + this.F.toRprBEM(buff, o+this.F.n8, p[1]); + } + + fromRprLE(buff, o) { + o = o || 0; + const x = this.F.fromRprLE(buff, o); + const y = this.F.fromRprLE(buff, o+this.F.n8); + if (this.F.isZero(x) && this.F.isZero(y)) { + return this.zero; + } + return [x, y, this.F.one]; + } + + fromRprBE(buff, o) { + o = o || 0; + const x = this.F.fromRprBE(buff, o); + const y = this.F.fromRprBE(buff, o+this.F.n8); + if (this.F.isZero(x) && this.F.isZero(y)) { + return this.zero; + } + return [x, y, this.F.one]; + } + + fromRprLEM(buff, o) { + o = o || 0; + const x = this.F.fromRprLEM(buff, o); + const y = this.F.fromRprLEM(buff, o+this.F.n8); + if (this.F.isZero(x) && this.F.isZero(y)) { + return this.zero; + } + return [x, y, this.F.one]; + } + + fromRprLEJM(buff, o) { + o = o || 0; + const x = this.F.fromRprLEM(buff, o); + const y = this.F.fromRprLEM(buff, o+this.F.n8); + const z = this.F.fromRprLEM(buff, o+this.F.n8*2); + if (this.F.isZero(x) && this.F.isZero(y)) { + return this.zero; + } + return [x, y, z]; + } + + fromRprBEM(buff, o) { + o = o || 0; + const x = this.F.fromRprBEM(buff, o); + const y = this.F.fromRprBEM(buff, o+this.F.n8); + if (this.F.isZero(x) && this.F.isZero(y)) { + return this.zero; + } + return [x, y, this.F.one]; + } + + fromRprCompressed(buff, o) { + const F = this.F; + const v = new Uint8Array(buff.buffer, o, F.n8); + if (v[0] & 0x40) return this.zero; + const P = new Array(3); + + const greatest = ((v[0] & 0x80) != 0); + v[0] = v[0] & 0x7F; + P[0] = F.fromRprBE(buff, o); + if (greatest) v[0] = v[0] | 0x80; // set back again the old value + + const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b); + P[1] = F.sqrt(x3b); + + if (P[1] === null) { + throw new Error("Invalid Point!"); + } + + const s = isGreatest(F, P[1]); + if (greatest ^ s) P[1] = F.neg(P[1]); + P[2] = F.one; + + return P; + } + + toRprCompressed(buff, o, p) { + p = this.affine(p); + const v = new Uint8Array(buff.buffer, o, this.F.n8); + if (this.isZero(p)) { + v.fill(0); + v[0] = 0x40; + return; + } + this.F.toRprBE(buff, o, p[0]); + + if (isGreatest(this.F, p[1])) { + v[0] = v[0] | 0x80; + } + } + + + fromRprUncompressed(buff, o) { + if (buff[0] & 0x40) return this.zero; + + return this.fromRprBE(buff, o); + } + + toRprUncompressed(buff, o, p) { + this.toRprBE(buff, o, p); + + if (this.isZero(p)) { + buff[o] = buff[o] | 0x40; + } + } + + +} + +/* global BigInt */ + +function stringifyBigInts$2(o) { + if ((typeof(o) == "bigint") || o.eq !== undefined) { + return o.toString(10); + } else if (o instanceof Uint8Array) { + return fromRprLE(o, 0); + } else if (Array.isArray(o)) { + return o.map(stringifyBigInts$2); + } else if (typeof o == "object") { + const res = {}; + const keys = Object.keys(o); + keys.forEach( (k) => { + res[k] = stringifyBigInts$2(o[k]); + }); + return res; + } else { + return o; + } +} + +function unstringifyBigInts$2(o) { + if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) { + return BigInt(o); + } else if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o) )) { + return BigInt(o); + } else if (Array.isArray(o)) { + return o.map(unstringifyBigInts$2); + } else if (typeof o == "object") { + if (o===null) return null; + const res = {}; + const keys = Object.keys(o); + keys.forEach( (k) => { + res[k] = unstringifyBigInts$2(o[k]); + }); + return res; + } else { + return o; + } +} + +function beBuff2int$2(buff) { + let res = BigInt(0); + let i = buff.length; + let offset = 0; + const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); + while (i>0) { + if (i >= 4) { + i -= 4; + res += BigInt(buffV.getUint32(i)) << BigInt(offset*8); + offset += 4; + } else if (i >= 2) { + i -= 2; + res += BigInt(buffV.getUint16(i)) << BigInt(offset*8); + offset += 2; + } else { + i -= 1; + res += BigInt(buffV.getUint8(i)) << BigInt(offset*8); + offset += 1; + } + } + return res; +} + +function beInt2Buff$2(n, len) { + let r = n; + const buff = new Uint8Array(len); + const buffV = new DataView(buff.buffer); + let o = len; + while (o > 0) { + if (o-4 >= 0) { + o -= 4; + buffV.setUint32(o, Number(r & BigInt(0xFFFFFFFF))); + r = r >> BigInt(32); + } else if (o-2 >= 0) { + o -= 2; + buffV.setUint16(o, Number(r & BigInt(0xFFFF))); + r = r >> BigInt(16); + } else { + o -= 1; + buffV.setUint8(o, Number(r & BigInt(0xFF))); + r = r >> BigInt(8); + } + } + if (r) { + throw new Error("Number does not fit in this length"); + } + return buff; +} + + +function leBuff2int$2(buff) { + let res = BigInt(0); + let i = 0; + const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); + while (i> BigInt(32); + } else if (o+2 <= len) { + buffV.setUint16(Number(o, r & BigInt(0xFFFF)), true ); + o += 2; + r = r >> BigInt(16); + } else { + buffV.setUint8(Number(o, r & BigInt(0xFF)), true ); + o += 1; + r = r >> BigInt(8); + } + } + if (r) { + throw new Error("Number does not fit in this length"); + } + return buff; +} + + +function stringifyFElements$1(F, o) { + if ((typeof(o) == "bigint") || o.eq !== undefined) { + return o.toString(10); + } else if (o instanceof Uint8Array) { + return F.toString(F.e(o)); + } else if (Array.isArray(o)) { + return o.map(stringifyFElements$1.bind(this,F)); + } else if (typeof o == "object") { + const res = {}; + const keys = Object.keys(o); + keys.forEach( (k) => { + res[k] = stringifyFElements$1(F, o[k]); + }); + return res; + } else { + return o; + } +} + + +function unstringifyFElements$1(F, o) { + if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) { + return F.e(o); + } else if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o) )) { + return F.e(o); + } else if (Array.isArray(o)) { + return o.map(unstringifyFElements$1.bind(this,F)); + } else if (typeof o == "object") { + if (o===null) return null; + const res = {}; + const keys = Object.keys(o); + keys.forEach( (k) => { + res[k] = unstringifyFElements$1(F, o[k]); + }); + return res; + } else { + return o; + } +} + +var utils_native = /*#__PURE__*/Object.freeze({ + __proto__: null, + stringifyBigInts: stringifyBigInts$2, + unstringifyBigInts: unstringifyBigInts$2, + beBuff2int: beBuff2int$2, + beInt2Buff: beInt2Buff$2, + leBuff2int: leBuff2int$2, + leInt2Buff: leInt2Buff$2, + stringifyFElements: stringifyFElements$1, + unstringifyFElements: unstringifyFElements$1 +}); + +function stringifyBigInts$1(o) { + if ((typeof(o) == "bigint") || o.eq !== undefined) { + return o.toString(10); + } else if (Array.isArray(o)) { + return o.map(stringifyBigInts$1); + } else if (typeof o == "object") { + const res = {}; + const keys = Object.keys(o); + keys.forEach( (k) => { + res[k] = stringifyBigInts$1(o[k]); + }); + return res; + } else { + return o; + } +} + +function unstringifyBigInts$1(o) { + if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) { + return bigInt__default["default"](o); + } else if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o) )) { + return bigInt__default["default"](o); + } else if (Array.isArray(o)) { + return o.map(unstringifyBigInts$1); + } else if (typeof o == "object") { + const res = {}; + const keys = Object.keys(o); + keys.forEach( (k) => { + res[k] = unstringifyBigInts$1(o[k]); + }); + return res; + } else { + return o; + } +} + +function beBuff2int$1(buff) { + let res = bigInt__default["default"].zero; + for (let i=0; i=0)) { + let c = Number(r.and(bigInt__default["default"]("255"))); + buff[o] = c; + o--; + r = r.shiftRight(8); + } + if (!r.eq(bigInt__default["default"].zero)) { + throw new Error("Number does not fit in this length"); + } + return buff; +} + + +function leBuff2int$1 (buff) { + let res = bigInt__default["default"].zero; + for (let i=0; i>=1; + } + return res; +} + +utils$1.bitReverse = function bitReverse(idx, bits) { + return ( + _revTable[idx >>> 24] | + (_revTable[(idx >>> 16) & 0xFF] << 8) | + (_revTable[(idx >>> 8) & 0xFF] << 16) | + (_revTable[idx & 0xFF] << 24) + ) >>> (32-bits); +}; + + +utils$1.log2 = function log2( V ) +{ + return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); +}; + +utils$1.buffReverseBits = function buffReverseBits(buff, eSize) { + const n = buff.byteLength /eSize; + const bits = utils$1.log2(n); + if (n != (1 << bits)) { + throw new Error("Invalid number of pointers"); + } + for (let i=0; ir) { + const tmp = buff.slice(i*eSize, (i+1)*eSize); + buff.set( buff.slice(r*eSize, (r+1)*eSize), i*eSize); + buff.set(tmp, r*eSize); + } + } +}; + + +utils$1.array2buffer = function(arr, sG) { + const buff = new Uint8Array(sG*arr.length); + + for (let i=0; i0) { + // bytes to copy from this page + const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r; + const srcView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset+o, l); + if (l == len) return srcView.slice(); + if (!buff) { + if (len <= PAGE_SIZE) { + buff = new Uint8Array(len); + } else { + buff = new BigBuffer(len); + } + } + buff.set(srcView, len-r); + r = r-l; + p ++; + o = 0; + } + + return buff; + } + + set(buff, offset) { + if (offset === undefined) offset = 0; + + const len = buff.byteLength; + + if (len==0) return; + + const firstPage = Math.floor(offset / PAGE_SIZE); + const lastPage = Math.floor((offset+len-1) / PAGE_SIZE); + + if (firstPage == lastPage) { + if ((buff instanceof BigBuffer)&&(buff.buffers.length==1)) { + return this.buffers[firstPage].set(buff.buffers[0], offset % PAGE_SIZE); + } else { + return this.buffers[firstPage].set(buff, offset % PAGE_SIZE); + } + + } + + + let p = firstPage; + let o = offset % PAGE_SIZE; + let r = len; + while (r>0) { + const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r; + const srcView = buff.slice( len -r, len -r+l); + const dstView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset + o, l); + dstView.set(srcView); + r = r-l; + p ++; + o = 0; + } + + } +} + +function buildBatchConvert(tm, fnName, sIn, sOut) { + return async function batchConvert(buffIn) { + const nPoints = Math.floor(buffIn.byteLength / sIn); + if ( nPoints * sIn !== buffIn.byteLength) { + throw new Error("Invalid buffer size"); + } + const pointsPerChunk = Math.floor(nPoints/tm.concurrency); + const opPromises = []; + for (let i=0; i=0; i--) { + this.w[i] = this.square(this.w[i+1]); + } + + if (!this.eq(this.w[0], this.one)) { + throw new Error("Error calculating roots of unity"); + } + + this.batchToMontgomery = buildBatchConvert(tm, prefix + "_batchToMontgomery", this.n8, this.n8); + this.batchFromMontgomery = buildBatchConvert(tm, prefix + "_batchFromMontgomery", this.n8, this.n8); + } + + + op2(opName, a, b) { + this.tm.setBuff(this.pOp1, a); + this.tm.setBuff(this.pOp2, b); + this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3); + return this.tm.getBuff(this.pOp3, this.n8); + } + + op2Bool(opName, a, b) { + this.tm.setBuff(this.pOp1, a); + this.tm.setBuff(this.pOp2, b); + return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2); + } + + op1(opName, a) { + this.tm.setBuff(this.pOp1, a); + this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3); + return this.tm.getBuff(this.pOp3, this.n8); + } + + op1Bool(opName, a) { + this.tm.setBuff(this.pOp1, a); + return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3); + } + + add(a,b) { + return this.op2("_add", a, b); + } + + + eq(a,b) { + return this.op2Bool("_eq", a, b); + } + + isZero(a) { + return this.op1Bool("_isZero", a); + } + + sub(a,b) { + return this.op2("_sub", a, b); + } + + neg(a) { + return this.op1("_neg", a); + } + + inv(a) { + return this.op1("_inverse", a); + } + + toMontgomery(a) { + return this.op1("_toMontgomery", a); + } + + fromMontgomery(a) { + return this.op1("_fromMontgomery", a); + } + + mul(a,b) { + return this.op2("_mul", a, b); + } + + div(a, b) { + this.tm.setBuff(this.pOp1, a); + this.tm.setBuff(this.pOp2, b); + this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2); + this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3); + return this.tm.getBuff(this.pOp3, this.n8); + } + + square(a) { + return this.op1("_square", a); + } + + isSquare(a) { + return this.op1Bool("_isSquare", a); + } + + sqrt(a) { + return this.op1("_sqrt", a); + } + + exp(a, b) { + if (!(b instanceof Uint8Array)) { + b = toLEBuff(e(b)); + } + this.tm.setBuff(this.pOp1, a); + this.tm.setBuff(this.pOp2, b); + this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3); + return this.tm.getBuff(this.pOp3, this.n8); + } + + isNegative(a) { + return this.op1Bool("_isNegative", a); + } + + e(a, b) { + if (a instanceof Uint8Array) return a; + let ra = e(a, b); + if (isNegative(ra)) { + ra = neg(ra); + if (gt(ra, this.p)) { + ra = mod(ra, this.p); + } + ra = sub(this.p, ra); + } else { + if (gt(ra, this.p)) { + ra = mod(ra, this.p); + } + } + const buff = leInt2Buff(ra, this.n8); + return this.toMontgomery(buff); + } + + toString(a, radix) { + const an = this.fromMontgomery(a); + const s = fromRprLE(an, 0); + return toString(s, radix); + } + + fromRng(rng) { + let v; + const buff = new Uint8Array(this.n8); + do { + v = zero; + for (let i=0; i memory.buffer.byteLength) { + const currentPages = memory.buffer.byteLength / 0x10000; + let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1; + if (requiredPages>MAXMEM) requiredPages=MAXMEM; + memory.grow(requiredPages-currentPages); + } + return res; + } + + function allocBuffer(buffer) { + const p = alloc(buffer.byteLength); + setBuffer(p, buffer); + return p; + } + + function getBuffer(pointer, length) { + const u8 = new Uint8Array(memory.buffer); + return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length); + } + + function setBuffer(pointer, buffer) { + const u8 = new Uint8Array(memory.buffer); + u8.set(new Uint8Array(buffer), pointer); + } + + function runTask(task) { + if (task[0].cmd == "INIT") { + return init(task[0]); + } + const ctx = { + vars: [], + out: [] + }; + const u32a = new Uint32Array(memory.buffer, 0, 1); + const oldAlloc = u32a[0]; + for (let i=0; i. +*/ + +// const MEM_SIZE = 1000; // Memory size in 64K Pakes (512Mb) +const MEM_SIZE = 25; // Memory size in 64K Pakes (1600Kb) + + +class Deferred { + constructor() { + this.promise = new Promise((resolve, reject)=> { + this.reject = reject; + this.resolve = resolve; + }); + } +} + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +function stringToBase64(str) { + if (process.browser && typeof globalThis.btoa === "function") { + return globalThis.btoa(str); + } else { + return Buffer.from(str).toString("base64"); + } +} + +stringToBase64("(" + thread.toString() + ")(self)"); + + + +async function buildThreadManager(wasm, singleThread) { + const tm = new ThreadManager(); + + tm.memory = new WebAssembly.Memory({initial:MEM_SIZE}); + tm.u8 = new Uint8Array(tm.memory.buffer); + tm.u32 = new Uint32Array(tm.memory.buffer); + + const wasmModule = await WebAssembly.compile(wasm.code); + + tm.instance = await WebAssembly.instantiate(wasmModule, { + env: { + "memory": tm.memory + } + }); + + tm.singleThread = singleThread; + tm.initalPFree = tm.u32[0]; // Save the Pointer to free space. + tm.pq = wasm.pq; + tm.pr = wasm.pr; + tm.pG1gen = wasm.pG1gen; + tm.pG1zero = wasm.pG1zero; + tm.pG2gen = wasm.pG2gen; + tm.pG2zero = wasm.pG2zero; + tm.pOneT = wasm.pOneT; + + // tm.pTmp0 = tm.alloc(curve.G2.F.n8*3); + // tm.pTmp1 = tm.alloc(curve.G2.F.n8*3); + + + tm.code = wasm.code; + tm.taskManager = thread(); + await tm.taskManager([{ + cmd: "INIT", + init: MEM_SIZE, + code: tm.code.slice() + }]); + tm.concurrency = 1; + + return tm; + +} + +class ThreadManager { + constructor() { + this.actionQueue = []; + this.oldPFree = 0; + } + + startSyncOp() { + if (this.oldPFree != 0) throw new Error("Sync operation in progress"); + this.oldPFree = this.u32[0]; + } + + endSyncOp() { + if (this.oldPFree == 0) throw new Error("No sync operation in progress"); + this.u32[0] = this.oldPFree; + this.oldPFree = 0; + } + + postAction(workerId, e, transfers, _deferred) { + if (this.working[workerId]) { + throw new Error("Posting a job t a working worker"); + } + this.working[workerId] = true; + + this.pendingDeferreds[workerId] = _deferred ? _deferred : new Deferred(); + this.workers[workerId].postMessage(e, transfers); + + return this.pendingDeferreds[workerId].promise; + } + + processWorks() { + for (let i=0; (i 0); i++) { + if (this.working[i] == false) { + const work = this.actionQueue.shift(); + this.postAction(i, work.data, work.transfers, work.deferred); + } + } + } + + queueAction(actionData, transfers) { + const d = new Deferred(); + + if (this.singleThread) { + const res = this.taskManager(actionData); + d.resolve(res); + } else { + this.actionQueue.push({ + data: actionData, + transfers: transfers, + deferred: d + }); + this.processWorks(); + } + return d.promise; + } + + resetMemory() { + this.u32[0] = this.initalPFree; + } + + allocBuff(buff) { + const pointer = this.alloc(buff.byteLength); + this.setBuff(pointer, buff); + return pointer; + } + + getBuff(pointer, length) { + return this.u8.slice(pointer, pointer+ length); + } + + setBuff(pointer, buffer) { + this.u8.set(new Uint8Array(buffer), pointer); + } + + alloc(length) { + while (this.u32[0] & 3) this.u32[0]++; // Return always aligned pointers + const res = this.u32[0]; + this.u32[0] += length; + return res; + } + + async terminate() { + for (let i=0; i=0; i--) { + if (!G.isZero(res)) { + for (let j=0; jMAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE; + if (chunkSize { + if (logger) logger.debug(`Multiexp end: ${logText}: ${i}/${nPoints}`); + return r; + })); + } + + const result = await Promise.all(opPromises); + + let res = G.zero; + for (let i=result.length-1; i>=0; i--) { + res = G.add(res, result[i]); + } + + return res; + } + + G.multiExp = async function multiExpAffine(buffBases, buffScalars, logger, logText) { + return await _multiExp(buffBases, buffScalars, "jacobian", logger, logText); + }; + G.multiExpAffine = async function multiExpAffine(buffBases, buffScalars, logger, logText) { + return await _multiExp(buffBases, buffScalars, "affine", logger, logText); + }; +} + +function buildFFT(curve, groupName) { + const G = curve[groupName]; + const Fr = curve.Fr; + const tm = G.tm; + async function _fft(buff, inverse, inType, outType, logger, loggerTxt) { + + inType = inType || "affine"; + outType = outType || "affine"; + const MAX_BITS_THREAD = 14; + + let sIn, sMid, sOut, fnIn2Mid, fnMid2Out, fnFFTMix, fnFFTJoin, fnFFTFinal; + if (groupName == "G1") { + if (inType == "affine") { + sIn = G.F.n8*2; + fnIn2Mid = "g1m_batchToJacobian"; + } else { + sIn = G.F.n8*3; + } + sMid = G.F.n8*3; + if (inverse) { + fnFFTFinal = "g1m_fftFinal"; + } + fnFFTJoin = "g1m_fftJoin"; + fnFFTMix = "g1m_fftMix"; + + if (outType == "affine") { + sOut = G.F.n8*2; + fnMid2Out = "g1m_batchToAffine"; + } else { + sOut = G.F.n8*3; + } + + } else if (groupName == "G2") { + if (inType == "affine") { + sIn = G.F.n8*2; + fnIn2Mid = "g2m_batchToJacobian"; + } else { + sIn = G.F.n8*3; + } + sMid = G.F.n8*3; + if (inverse) { + fnFFTFinal = "g2m_fftFinal"; + } + fnFFTJoin = "g2m_fftJoin"; + fnFFTMix = "g2m_fftMix"; + if (outType == "affine") { + sOut = G.F.n8*2; + fnMid2Out = "g2m_batchToAffine"; + } else { + sOut = G.F.n8*3; + } + } else if (groupName == "Fr") { + sIn = G.n8; + sMid = G.n8; + sOut = G.n8; + if (inverse) { + fnFFTFinal = "frm_fftFinal"; + } + fnFFTMix = "frm_fftMix"; + fnFFTJoin = "frm_fftJoin"; + } + + + let returnArray = false; + if (Array.isArray(buff)) { + buff = array2buffer(buff, sIn); + returnArray = true; + } else { + buff = buff.slice(0, buff.byteLength); + } + + const nPoints = buff.byteLength / sIn; + const bits = log2(nPoints); + + if ((1 << bits) != nPoints) { + throw new Error("fft must be multiple of 2" ); + } + + if (bits == Fr.s +1) { + let buffOut; + + if (inverse) { + buffOut = await _fftExtInv(buff, inType, outType, logger, loggerTxt); + } else { + buffOut = await _fftExt(buff, inType, outType, logger, loggerTxt); + } + + if (returnArray) { + return buffer2array(buffOut, sOut); + } else { + return buffOut; + } + } + + let inv; + if (inverse) { + inv = Fr.inv(Fr.e(nPoints)); + } + + let buffOut; + + buffReverseBits(buff, sIn); + + let chunks; + let pointsInChunk = Math.min(1 << MAX_BITS_THREAD, nPoints); + let nChunks = nPoints / pointsInChunk; + + while ((nChunks < tm.concurrency)&&(pointsInChunk>=16)) { + nChunks *= 2; + pointsInChunk /= 2; + } + + const l2Chunk = log2(pointsInChunk); + + const promises = []; + for (let i = 0; i< nChunks; i++) { + if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix start: ${i}/${nChunks}`); + const task = []; + task.push({cmd: "ALLOC", var: 0, len: sMid*pointsInChunk}); + const buffChunk = buff.slice( (pointsInChunk * i)*sIn, (pointsInChunk * (i+1))*sIn); + task.push({cmd: "SET", var: 0, buff: buffChunk}); + if (fnIn2Mid) { + task.push({cmd: "CALL", fnName:fnIn2Mid, params: [{var:0}, {val: pointsInChunk}, {var: 0}]}); + } + for (let j=1; j<=l2Chunk;j++) { + task.push({cmd: "CALL", fnName:fnFFTMix, params: [{var:0}, {val: pointsInChunk}, {val: j}]}); + } + + if (l2Chunk==bits) { + if (fnFFTFinal) { + task.push({cmd: "ALLOCSET", var: 1, buff: inv}); + task.push({cmd: "CALL", fnName: fnFFTFinal, params:[ + {var: 0}, + {val: pointsInChunk}, + {var: 1}, + ]}); + } + if (fnMid2Out) { + task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:0}, {val: pointsInChunk}, {var: 0}]}); + } + task.push({cmd: "GET", out: 0, var: 0, len: pointsInChunk*sOut}); + } else { + task.push({cmd: "GET", out:0, var: 0, len: sMid*pointsInChunk}); + } + promises.push(tm.queueAction(task).then( (r) => { + if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix end: ${i}/${nChunks}`); + return r; + })); + } + + chunks = await Promise.all(promises); + for (let i = 0; i< nChunks; i++) chunks[i] = chunks[i][0]; + + for (let i = l2Chunk+1; i<=bits; i++) { + if (logger) logger.debug(`${loggerTxt}: fft ${bits} join: ${i}/${bits}`); + const nGroups = 1 << (bits - i); + const nChunksPerGroup = nChunks / nGroups; + const opPromises = []; + for (let j=0; j { + if (logger) logger.debug(`${loggerTxt}: fft ${bits} join ${i}/${bits} ${j+1}/${nGroups} ${k}/${nChunksPerGroup/2}`); + return r; + })); + } + } + + const res = await Promise.all(opPromises); + for (let j=0; j0; i--) { + buffOut.set(chunks[i], p); + p += pointsInChunk*sOut; + delete chunks[i]; // Liberate mem + } + buffOut.set(chunks[0].slice(0, (pointsInChunk-1)*sOut), p); + delete chunks[0]; + } else { + for (let i=0; i (1<<28)) { + buffOut = new BigBuffer(res1[0].byteLength*2); + } else { + buffOut = new Uint8Array(res1[0].byteLength*2); + } + + buffOut.set(res1[0]); + buffOut.set(res1[1], res1[0].byteLength); + + return buffOut; + } + + async function _fftExtInv(buff, inType, outType, logger, loggerTxt) { + let b1, b2; + b1 = buff.slice( 0 , buff.byteLength/2); + b2 = buff.slice( buff.byteLength/2, buff.byteLength); + + const promises = []; + + promises.push( _fft(b1, true, inType, "jacobian", logger, loggerTxt)); + promises.push( _fft(b2, true, inType, "jacobian", logger, loggerTxt)); + + [b1, b2] = await Promise.all(promises); + + const res1 = await _fftJoinExt(b1, b2, "fftJoinExtInv", Fr.one, Fr.shiftInv, "jacobian", outType, logger, loggerTxt); + + let buffOut; + if (res1[0].byteLength > (1<<28)) { + buffOut = new BigBuffer(res1[0].byteLength*2); + } else { + buffOut = new Uint8Array(res1[0].byteLength*2); + } + + buffOut.set(res1[0]); + buffOut.set(res1[1], res1[0].byteLength); + + return buffOut; + } + + + async function _fftJoinExt(buff1, buff2, fn, first, inc, inType, outType, logger, loggerTxt) { + const MAX_CHUNK_SIZE = 1<<16; + const MIN_CHUNK_SIZE = 1<<4; + + let fnName; + let fnIn2Mid, fnMid2Out; + let sOut, sIn, sMid; + + if (groupName == "G1") { + if (inType == "affine") { + sIn = G.F.n8*2; + fnIn2Mid = "g1m_batchToJacobian"; + } else { + sIn = G.F.n8*3; + } + sMid = G.F.n8*3; + fnName = "g1m_"+fn; + if (outType == "affine") { + fnMid2Out = "g1m_batchToAffine"; + sOut = G.F.n8*2; + } else { + sOut = G.F.n8*3; + } + } else if (groupName == "G2") { + if (inType == "affine") { + sIn = G.F.n8*2; + fnIn2Mid = "g2m_batchToJacobian"; + } else { + sIn = G.F.n8*3; + } + fnName = "g2m_"+fn; + sMid = G.F.n8*3; + if (outType == "affine") { + fnMid2Out = "g2m_batchToAffine"; + sOut = G.F.n8*2; + } else { + sOut = G.F.n8*3; + } + } else if (groupName == "Fr") { + sIn = Fr.n8; + sOut = Fr.n8; + sMid = Fr.n8; + fnName = "frm_" + fn; + } else { + throw new Error("Invalid group"); + } + + if (buff1.byteLength != buff2.byteLength) { + throw new Error("Invalid buffer size"); + } + const nPoints = Math.floor(buff1.byteLength / sIn); + if (nPoints != 1 << log2(nPoints)) { + throw new Error("Invalid number of points"); + } + + let chunkSize = Math.floor(nPoints /tm.concurrency); + if (chunkSize < MIN_CHUNK_SIZE) chunkSize = MIN_CHUNK_SIZE; + if (chunkSize > MAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE; + + const opPromises = []; + + for (let i=0; i { + if (logger) logger.debug(`${loggerTxt}: fftJoinExt End: ${i}/${nPoints}`); + return r; + }) + ); + } + + const result = await Promise.all(opPromises); + + let fullBuffOut1; + let fullBuffOut2; + if (nPoints * sOut > 1<<28) { + fullBuffOut1 = new BigBuffer(nPoints*sOut); + fullBuffOut2 = new BigBuffer(nPoints*sOut); + } else { + fullBuffOut1 = new Uint8Array(nPoints*sOut); + fullBuffOut2 = new Uint8Array(nPoints*sOut); + } + + let p =0; + for (let i=0; i Fr.s+1) { + if (logger) logger.error("lagrangeEvaluations input too big"); + throw new Error("lagrangeEvaluations input too big"); + } + + let t0 = buff.slice(0, buff.byteLength/2); + let t1 = buff.slice(buff.byteLength/2, buff.byteLength); + + + const shiftToSmallM = Fr.exp(Fr.shift, nPoints/2); + const sConst = Fr.inv( Fr.sub(Fr.one, shiftToSmallM)); + + [t0, t1] = await _fftJoinExt(t0, t1, "prepareLagrangeEvaluation", sConst, Fr.shiftInv, inType, "jacobian", logger, loggerTxt + " prep"); + + const promises = []; + + promises.push( _fft(t0, true, "jacobian", outType, logger, loggerTxt + " t0")); + promises.push( _fft(t1, true, "jacobian", outType, logger, loggerTxt + " t1")); + + [t0, t1] = await Promise.all(promises); + + let buffOut; + if (t0.byteLength > (1<<28)) { + buffOut = new BigBuffer(t0.byteLength*2); + } else { + buffOut = new Uint8Array(t0.byteLength*2); + } + + buffOut.set(t0); + buffOut.set(t1, t0.byteLength); + + return buffOut; + }; + + G.fftMix = async function fftMix(buff) { + const sG = G.F.n8*3; + let fnName, fnFFTJoin; + if (groupName == "G1") { + fnName = "g1m_fftMix"; + fnFFTJoin = "g1m_fftJoin"; + } else if (groupName == "G2") { + fnName = "g2m_fftMix"; + fnFFTJoin = "g2m_fftJoin"; + } else if (groupName == "Fr") { + fnName = "frm_fftMix"; + fnFFTJoin = "frm_fftJoin"; + } else { + throw new Error("Invalid group"); + } + + const nPoints = Math.floor(buff.byteLength / sG); + const power = log2(nPoints); + + let nChunks = 1 << log2(tm.concurrency); + + if (nPoints <= nChunks*2) nChunks = 1; + + const pointsPerChunk = nPoints / nChunks; + + const powerChunk = log2(pointsPerChunk); + + const opPromises = []; + for (let i=0; i=0; i--) { + fullBuffOut.set(result[i][0], p); + p+=result[i][0].byteLength; + } + + return fullBuffOut; + }; +} + +async function buildEngine(params) { + + const tm = await buildThreadManager(params.wasm, params.singleThread); + + + const curve = {}; + + curve.q = e(params.wasm.q); + curve.r = e(params.wasm.r); + curve.name = params.name; + curve.tm = tm; + curve.prePSize = params.wasm.prePSize; + curve.preQSize = params.wasm.preQSize; + curve.Fr = new WasmField1(tm, "frm", params.n8r, params.r); + curve.F1 = new WasmField1(tm, "f1m", params.n8q, params.q); + curve.F2 = new WasmField2(tm, "f2m", curve.F1); + curve.G1 = new WasmCurve(tm, "g1m", curve.F1, params.wasm.pG1gen, params.wasm.pG1b, params.cofactorG1); + curve.G2 = new WasmCurve(tm, "g2m", curve.F2, params.wasm.pG2gen, params.wasm.pG2b, params.cofactorG2); + curve.F6 = new WasmField3(tm, "f6m", curve.F2); + curve.F12 = new WasmField2(tm, "ftm", curve.F6); + + curve.Gt = curve.F12; + + buildBatchApplyKey(curve, "G1"); + buildBatchApplyKey(curve, "G2"); + buildBatchApplyKey(curve, "Fr"); + + buildMultiexp(curve, "G1"); + buildMultiexp(curve, "G2"); + + buildFFT(curve, "G1"); + buildFFT(curve, "G2"); + buildFFT(curve, "Fr"); + + buildPairing(curve); + + curve.array2buffer = function(arr, sG) { + const buff = new Uint8Array(sG*arr.length); + + for (let i=0; i= 0) { + curve = await buildBn128(singleThread, plugins); + } else if (["BLS12381"].indexOf(normName) >= 0) { + curve = await buildBls12381(singleThread, plugins); + } else { + throw new Error(`Curve not supported: ${name}`); + } + return curve; + + function normalizeName(n) { + return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); + } + +} + +const Scalar=_Scalar; +const utils = _utils; + +exports.BigBuffer = BigBuffer; +exports.ChaCha = ChaCha; +exports.EC = EC; +exports.F1Field = F1Field; +exports.F2Field = F2Field; +exports.F3Field = F3Field; +exports.PolField = PolField; +exports.Scalar = Scalar; +exports.ZqField = F1Field; +exports.buildBls12381 = buildBls12381; +exports.buildBn128 = buildBn128; +exports.getCurveFromName = getCurveFromName; +exports.getCurveFromQ = getCurveFromQ; +exports.getCurveFromR = getCurveFromR; +exports.utils = utils;