mirror of
https://github.com/CryptKeeperZK/ffjavascript.git
synced 2026-01-09 16:17:56 -05:00
Works in browser
This commit is contained in:
@@ -5,7 +5,8 @@ module.exports = {
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
7320
build/main.cjs
Normal file
7320
build/main.cjs
Normal file
File diff suppressed because one or more lines are too long
7320
build/main.js
Normal file
7320
build/main.js
Normal file
File diff suppressed because one or more lines are too long
18
index.js
18
index.js
@@ -1,18 +0,0 @@
|
||||
|
||||
exports.Scalar = require("./src/scalar");
|
||||
exports.PolField = require("./src/polfield.js");
|
||||
exports.F1Field = require("./src/f1field");
|
||||
exports.F2Field = require("./src/f2field");
|
||||
exports.F3Field = require("./src/f3field");
|
||||
|
||||
exports.ZqField = exports.F1Field;
|
||||
|
||||
exports.EC = require("./src/ec");
|
||||
|
||||
exports.buildBn128 = require("./src/bn128.js");
|
||||
exports.buildBls12381 = require("./src/bls12381.js");
|
||||
|
||||
exports.utils = require("./src/utils");
|
||||
exports.ChaCha = require("./src/chacha");
|
||||
|
||||
|
||||
20
main.js
Normal file
20
main.js
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
import * as _Scalar from "./src/scalar.js";
|
||||
export const Scalar=_Scalar;
|
||||
|
||||
export {default as PolField} from "./src/polfield.js";
|
||||
export {default as F1Field} from "./src/f1field.js";
|
||||
export {default as F2Field} from "./src/f2field.js";
|
||||
export {default as F3Field} from "./src/f3field.js";
|
||||
|
||||
export {default as ZqField} from "./src/f1field.js";
|
||||
|
||||
export {default as EC} from "./src/ec.js";
|
||||
|
||||
export {default as buildBn128} from "./src/bn128.js";
|
||||
export {default as buildBls12381} from "./src/bls12381.js";
|
||||
|
||||
import * as _utils from "./src/utils.js";
|
||||
export const utils = _utils;
|
||||
export {default as ChaCha} from "./src/chacha.js";
|
||||
|
||||
1286
package-lock.json
generated
1286
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -1,10 +1,17 @@
|
||||
{
|
||||
"name": "ffjavascript",
|
||||
"type": "module",
|
||||
"version": "0.1.3",
|
||||
"description": "Finite Field Library in Javascript",
|
||||
"main": "index.js",
|
||||
"main": "./build/main.cjs",
|
||||
"module": "./main.js",
|
||||
"exports": {
|
||||
"import": "./main.js",
|
||||
"require": "./build/main.cjs"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
"test": "mocha",
|
||||
"build": "rollup -c rollup.cjs.config.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -26,11 +33,18 @@
|
||||
"homepage": "https://github.com/iden3/ffjs#readme",
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmsnark": "0.0.10"
|
||||
"wasmcurves": "0.0.3",
|
||||
"worker-threads": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"blake2b": "^2.1.3",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^6.8.0"
|
||||
"eslint": "^6.8.0",
|
||||
"esm": "^3.2.25",
|
||||
"rollup": "^2.19.0",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
"rollup-plugin-node-globals": "^1.4.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
18
rollup.cjs.config.js
Normal file
18
rollup.cjs.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import resolve from "rollup-plugin-node-resolve";
|
||||
import commonJS from "rollup-plugin-commonjs";
|
||||
|
||||
export default {
|
||||
input: "main.js",
|
||||
output: {
|
||||
file: "build/main.js",
|
||||
format: "cjs",
|
||||
},
|
||||
external: ["crypto", "os", "worker_threads"],
|
||||
plugins: [
|
||||
resolve({ preferBuiltins: true }),
|
||||
commonJS({
|
||||
preserveSymlinks: true
|
||||
}),
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const bls12381_wasm = require("wasmsnark").bls12381_wasm;
|
||||
const buildEngine = require("./engine");
|
||||
const Scalar = require("./scalar");
|
||||
import wasmcurves from "wasmcurves";
|
||||
import buildEngine from "./engine.js";
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
let curve;
|
||||
|
||||
module.exports = async function buildBls12381() {
|
||||
export default async function buildBls12381() {
|
||||
|
||||
if (curve) return curve;
|
||||
const params = {
|
||||
name: "bls12381",
|
||||
wasm: bls12381_wasm,
|
||||
wasm: wasmcurves.bls12381_wasm,
|
||||
q: Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16),
|
||||
r: Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16),
|
||||
n8q: 48,
|
||||
@@ -20,6 +20,11 @@ module.exports = async function buildBls12381() {
|
||||
};
|
||||
|
||||
curve = await buildEngine(params);
|
||||
return curve;
|
||||
};
|
||||
|
||||
curve.terminate = function() {
|
||||
this.tm.terminate();
|
||||
curve = null;
|
||||
};
|
||||
return curve;
|
||||
}
|
||||
|
||||
|
||||
19
src/bn128.js
19
src/bn128.js
@@ -1,15 +1,15 @@
|
||||
const bn128_wasm = require("wasmsnark").bn128_wasm;
|
||||
const buildEngine = require("./engine");
|
||||
const Scalar = require("./scalar");
|
||||
import wasmcurves from "wasmcurves";
|
||||
import buildEngine from "./engine.js";
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
let curve;
|
||||
|
||||
module.exports = async function buildBn128() {
|
||||
export default async function buildBn128() {
|
||||
|
||||
if (curve) return curve;
|
||||
const params = {
|
||||
name: "bn128",
|
||||
wasm: bn128_wasm,
|
||||
wasm: wasmcurves.bn128_wasm,
|
||||
q: Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"),
|
||||
r: Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"),
|
||||
n8q: 32,
|
||||
@@ -19,6 +19,11 @@ module.exports = async function buildBn128() {
|
||||
};
|
||||
|
||||
curve = await buildEngine(params);
|
||||
return curve;
|
||||
};
|
||||
curve.terminate = function() {
|
||||
this.tm.terminate();
|
||||
curve = null;
|
||||
};
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
const Scalar = require("./scalar");
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
|
||||
function quarterRound(st, a, b, c, d) {
|
||||
@@ -34,7 +34,7 @@ function doubleRound(st) {
|
||||
quarterRound(st, 3, 4, 9,14);
|
||||
}
|
||||
|
||||
module.exports = class ChaCha {
|
||||
export default class ChaCha {
|
||||
|
||||
constructor(seed) {
|
||||
seed = seed || [0,0,0,0,0,0,0,0];
|
||||
@@ -93,4 +93,4 @@ module.exports = class ChaCha {
|
||||
if (this.state[14] != 0) return;
|
||||
this.state[15] = (this.state[15] + 1) >>> 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
14
src/ec.js
14
src/ec.js
@@ -19,9 +19,8 @@
|
||||
|
||||
|
||||
|
||||
const fUtils = require("./futils.js");
|
||||
const Scalar = require("./scalar");
|
||||
const assert = require("assert");
|
||||
import * as fUtils from "./futils.js";
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
|
||||
function isGreatest(F, a) {
|
||||
@@ -39,7 +38,7 @@ function isGreatest(F, a) {
|
||||
}
|
||||
|
||||
|
||||
class EC {
|
||||
export default class EC {
|
||||
|
||||
constructor(F, g) {
|
||||
this.F = F;
|
||||
@@ -152,6 +151,10 @@ class EC {
|
||||
return res;
|
||||
}
|
||||
|
||||
timesScalar(base, e) {
|
||||
return fUtils.mulScalar(this, base, e);
|
||||
}
|
||||
|
||||
mulScalar(base, e) {
|
||||
return fUtils.mulScalar(this, base, e);
|
||||
}
|
||||
@@ -388,7 +391,7 @@ class EC {
|
||||
P[1] = F.sqrt(x3b);
|
||||
|
||||
if (P[1] === null) {
|
||||
assert(false, "Invalid Point!");
|
||||
throw new Error("Invalid Point!");
|
||||
}
|
||||
|
||||
const s = isGreatest(F, P[1]);
|
||||
@@ -431,5 +434,4 @@ class EC {
|
||||
|
||||
}
|
||||
|
||||
module.exports = EC;
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
const WasmField1 =require("./wasm_field1");
|
||||
const WasmField2 =require("./wasm_field2");
|
||||
const WasmField3 =require("./wasm_field3");
|
||||
const WasmCurve = require("./wasm_curve");
|
||||
const buildThreadManager = require("./threadman");
|
||||
const Scalar = require("./scalar");
|
||||
const buildBatchApplyKey = require("./engine_applykey");
|
||||
const buildPairing = require("./engine_pairing");
|
||||
const buildMultiExp = require("./engine_multiexp");
|
||||
const buildFFT = require("./engine_fft");
|
||||
import WasmField1 from "./wasm_field1.js";
|
||||
import WasmField2 from "./wasm_field2.js";
|
||||
import WasmField3 from "./wasm_field3.js";
|
||||
import WasmCurve from "./wasm_curve.js";
|
||||
import buildThreadManager from "./threadman.js";
|
||||
import * as Scalar from "./scalar.js";
|
||||
import buildBatchApplyKey from "./engine_applykey.js";
|
||||
import buildPairing from "./engine_pairing.js";
|
||||
import buildMultiExp from "./engine_multiexp.js";
|
||||
import buildFFT from "./engine_fft.js";
|
||||
|
||||
module.exports = buildEngine;
|
||||
|
||||
async function buildEngine(params) {
|
||||
export default async function buildEngine(params) {
|
||||
|
||||
const tm = await buildThreadManager(params.wasm, params.singleThread);
|
||||
|
||||
|
||||
const curve = {};
|
||||
|
||||
curve.q = Scalar.e(params.wasm.q);
|
||||
@@ -46,6 +45,25 @@ async function buildEngine(params) {
|
||||
|
||||
buildPairing(curve);
|
||||
|
||||
curve.array2buffer = function(arr, sG) {
|
||||
const buff = new Uint8Array(sG*arr.length);
|
||||
|
||||
for (let i=0; i<arr.length; i++) {
|
||||
buff.set(arr[i], i*sG);
|
||||
}
|
||||
|
||||
return buff;
|
||||
};
|
||||
|
||||
curve.buffer2array = function(buff , sG) {
|
||||
const n= buff.length / sG;
|
||||
const arr = new Array(n);
|
||||
for (let i=0; i<n; i++) {
|
||||
arr[i] = buff.slice(i*sG, i*sG+sG);
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
module.exports = function buildBatchApplyKey(curve, groupName) {
|
||||
export default function buildBatchApplyKey(curve, groupName) {
|
||||
const G = curve[groupName];
|
||||
const Fr = curve.Fr;
|
||||
const tm = curve.tm;
|
||||
@@ -110,4 +110,4 @@ module.exports = function buildBatchApplyKey(curve, groupName) {
|
||||
|
||||
return outBuff;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
const assert = require("assert");
|
||||
|
||||
module.exports = function buildBatchConvert(tm, fnName, sIn, sOut) {
|
||||
export default function buildBatchConvert(tm, fnName, sIn, sOut) {
|
||||
return async function batchConvert(buffIn) {
|
||||
const nPoints = Math.floor(buffIn.byteLength / sIn);
|
||||
assert( nPoints * sIn === buffIn.byteLength);
|
||||
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<tm.concurrency; i++) {
|
||||
@@ -42,4 +43,4 @@ module.exports = function buildBatchConvert(tm, fnName, sIn, sOut) {
|
||||
|
||||
return fullBuffOut;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const assert = require("assert");
|
||||
const {log2, buffReverseBits} = require("./utils");
|
||||
import {log2, buffReverseBits} from "./utils.js";
|
||||
|
||||
module.exports = function buildFFT(curve, groupName) {
|
||||
export default function buildFFT(curve, groupName) {
|
||||
const G = curve[groupName];
|
||||
const Fr = curve.Fr;
|
||||
const tm = G.tm;
|
||||
async function _fft(buff, inverse, inType, outType, log) {
|
||||
|
||||
inType = inType || "affine";
|
||||
outType = outType || "affine";
|
||||
const MAX_BITS_THREAD = 12;
|
||||
@@ -72,11 +72,18 @@ module.exports = function buildFFT(curve, groupName) {
|
||||
}
|
||||
|
||||
|
||||
let returnArray = false;
|
||||
if (Array.isArray(buff)) {
|
||||
buff = curve.array2buffer(buff, sIn);
|
||||
returnArray = true;
|
||||
}
|
||||
|
||||
const nPoints = buff.byteLength / sIn;
|
||||
const bits = log2(nPoints);
|
||||
|
||||
assert( (1 << bits) == nPoints, "fft must be multiple of 2" );
|
||||
if ((1 << bits) != nPoints) {
|
||||
throw new Error("fft must be multiple of 2" );
|
||||
}
|
||||
|
||||
let inv;
|
||||
if (inverse) {
|
||||
@@ -216,7 +223,11 @@ module.exports = function buildFFT(curve, groupName) {
|
||||
}
|
||||
}
|
||||
|
||||
return buffOut;
|
||||
if (returnArray) {
|
||||
return curve.buffer2array(buffOut, sOut);
|
||||
} else {
|
||||
return buffOut;
|
||||
}
|
||||
}
|
||||
|
||||
G.fft = async function(buff, inType, outType, log) {
|
||||
@@ -240,7 +251,7 @@ module.exports = function buildFFT(curve, groupName) {
|
||||
fnName = "frm_fftMix";
|
||||
fnFFTJoin = "frm_fftJoin";
|
||||
} else {
|
||||
assert(false);
|
||||
throw new Error("Invalid group");
|
||||
}
|
||||
|
||||
const nPoints = Math.floor(buff.byteLength / sG);
|
||||
@@ -338,12 +349,16 @@ module.exports = function buildFFT(curve, groupName) {
|
||||
} else if (groupName == "G2") {
|
||||
fnName = "g2m_fftJoin";
|
||||
} else {
|
||||
assert(false);
|
||||
throw new Error("Invalid group");
|
||||
}
|
||||
|
||||
assert (buff1.byteLength == buff2.byteLength);
|
||||
if (buff1.byteLength != buff2.byteLength) {
|
||||
throw new Error("Invalid buffer size");
|
||||
}
|
||||
const nPoints = Math.floor(buff1.byteLength / sG);
|
||||
assert (nPoints == 1 << log2(nPoints));
|
||||
if (nPoints != 1 << log2(nPoints)) {
|
||||
throw new Error("Invalid number of points");
|
||||
}
|
||||
|
||||
let nChunks = 1 << log2(tm.concurrency);
|
||||
if (nPoints <= nChunks*2) nChunks = 1;
|
||||
@@ -403,11 +418,13 @@ module.exports = function buildFFT(curve, groupName) {
|
||||
fnName = "g2m_fftFinal";
|
||||
fnToAffine = "g2m_batchToAffine";
|
||||
} else {
|
||||
assert(false);
|
||||
throw new Error("Invalid group");
|
||||
}
|
||||
|
||||
const nPoints = Math.floor(buff.byteLength / sG);
|
||||
assert (nPoints == 1 << log2(nPoints));
|
||||
if (nPoints == 1 << log2(nPoints)) {
|
||||
throw new Error("Invalid number of points");
|
||||
}
|
||||
|
||||
const pointsPerChunk = Math.floor(nPoints / tm.concurrency);
|
||||
|
||||
@@ -452,4 +469,4 @@ module.exports = function buildFFT(curve, groupName) {
|
||||
|
||||
return fullBuffOut;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const assert = require("assert");
|
||||
const {log2} = require("./utils");
|
||||
import { log2 } from "./utils.js";
|
||||
|
||||
const pTSizes = [
|
||||
1 , 1, 1, 1, 2, 3, 4, 5,
|
||||
@@ -8,7 +7,7 @@ const pTSizes = [
|
||||
17, 17, 17, 17, 17, 17, 17, 17
|
||||
];
|
||||
|
||||
module.exports = function buildMultiexp(curve, groupName) {
|
||||
export default function buildMultiexp(curve, groupName) {
|
||||
const G = curve[groupName];
|
||||
async function _multiExp(buffBases, buffScalars, inType) {
|
||||
inType = inType || "affine";
|
||||
@@ -32,11 +31,13 @@ module.exports = function buildMultiexp(curve, groupName) {
|
||||
sGIn = G.F.n8*3;
|
||||
}
|
||||
} else {
|
||||
assert(false, "Invalid group");
|
||||
throw new Error("Invalid group");
|
||||
}
|
||||
const nPoints = Math.floor(buffBases.byteLength / sGIn);
|
||||
const sScalar = Math.floor(buffScalars.byteLength / nPoints);
|
||||
assert( sScalar * nPoints == buffScalars.byteLength, "Scalar size does not match");
|
||||
if( sScalar * nPoints != buffScalars.byteLength) {
|
||||
throw new Error("Scalar size does not match");
|
||||
}
|
||||
|
||||
const bitChunkSize = pTSizes[log2(nPoints)];
|
||||
const nChunks = Math.floor((sScalar*8 - 1) / bitChunkSize) +1;
|
||||
@@ -82,4 +83,4 @@ module.exports = function buildMultiexp(curve, groupName) {
|
||||
G.multiExpAffine = async function multiExpAffine(buffBases, buffScalars) {
|
||||
return await _multiExp(buffBases, buffScalars, "affine");
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
module.exports = function buildPairing(curve) {
|
||||
export default function buildPairing(curve) {
|
||||
const tm = curve.tm;
|
||||
curve.pairing = function pairing(a, b) {
|
||||
|
||||
@@ -85,4 +85,46 @@ module.exports = function buildPairing(curve) {
|
||||
|
||||
return r;
|
||||
};
|
||||
};
|
||||
|
||||
curve.prepareG1 = function(p) {
|
||||
this.tm.startSyncOp();
|
||||
const pP = this.tm.allocBuff(p);
|
||||
const pPrepP = this.tm.alloc(this.prePSize);
|
||||
this.tm.instance.exports[this.name + "_prepareG1"](pP, pPrepP);
|
||||
const res = this.tm.getBuff(pPrepP, this.prePSize);
|
||||
this.tm.endSyncOp();
|
||||
return res;
|
||||
};
|
||||
|
||||
curve.prepareG2 = function(q) {
|
||||
this.tm.startSyncOp();
|
||||
const pQ = this.tm.allocBuff(q);
|
||||
const pPrepQ = this.tm.alloc(this.preQSize);
|
||||
this.tm.instance.exports[this.name + "_prepareG2"](pQ, pPrepQ);
|
||||
const res = this.tm.getBuff(pPrepQ, this.preQSize);
|
||||
this.tm.endSyncOp();
|
||||
return res;
|
||||
};
|
||||
|
||||
curve.millerLoop = function(preP, preQ) {
|
||||
this.tm.startSyncOp();
|
||||
const pPreP = this.tm.allocBuff(preP);
|
||||
const pPreQ = this.tm.allocBuff(preQ);
|
||||
const pRes = this.tm.alloc(this.Gt.n8);
|
||||
this.tm.instance.exports[this.name + "_millerLoop"](pPreP, pPreQ, pRes);
|
||||
const res = this.tm.getBuff(pRes, this.Gt.n8);
|
||||
this.tm.endSyncOp();
|
||||
return res;
|
||||
};
|
||||
|
||||
curve.finalExponentiation = function(a) {
|
||||
this.tm.startSyncOp();
|
||||
const pA = this.tm.allocBuff(a);
|
||||
const pRes = this.tm.alloc(this.Gt.n8);
|
||||
this.tm.instance.exports[this.name + "_finalExponentiation"](pA, pRes);
|
||||
const res = this.tm.getBuff(pRes, this.Gt.n8);
|
||||
this.tm.endSyncOp();
|
||||
return res;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +1,55 @@
|
||||
const Scalar = require("./scalar");
|
||||
const assert = require("assert");
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
import F1Field_native from "./f1field_native.js";
|
||||
import F1Field_bigint from "./f1field_bigint.js";
|
||||
|
||||
const supportsNativeBigInt = typeof BigInt === "function";
|
||||
|
||||
let F1Field;
|
||||
let _F1Field;
|
||||
if (supportsNativeBigInt) {
|
||||
F1Field = require("./f1field_native");
|
||||
_F1Field = F1Field_native;
|
||||
} else {
|
||||
F1Field = require("./f1field_bigint");
|
||||
_F1Field = F1Field_bigint;
|
||||
}
|
||||
|
||||
export default class F1Field extends _F1Field {
|
||||
|
||||
// Returns a buffer with Little Endian Representation
|
||||
F1Field.prototype.toRprLE = function toRprLE(buff, o, e) {
|
||||
Scalar.toRprLE(buff, o, e, this.n64*8);
|
||||
};
|
||||
// Returns a buffer with Little Endian Representation
|
||||
toRprLE(buff, o, e) {
|
||||
Scalar.toRprLE(buff, o, e, this.n64*8);
|
||||
}
|
||||
|
||||
// Returns a buffer with Big Endian Representation
|
||||
F1Field.prototype.toRprBE = function toRprBE(buff, o, e) {
|
||||
Scalar.toRprBE(buff, o, e, this.n64*8);
|
||||
};
|
||||
// Returns a buffer with Big Endian Representation
|
||||
toRprBE(buff, o, e) {
|
||||
Scalar.toRprBE(buff, o, e, this.n64*8);
|
||||
}
|
||||
|
||||
// Returns a buffer with Big Endian Montgomery Representation
|
||||
F1Field.prototype.toRprBEM = function toRprBEM(buff, o, e) {
|
||||
return this.toRprBE(buff, o, this.mul(this.R, e));
|
||||
};
|
||||
// Returns a buffer with Big Endian Montgomery Representation
|
||||
toRprBEM(buff, o, e) {
|
||||
return this.toRprBE(buff, o, this.mul(this.R, e));
|
||||
}
|
||||
|
||||
F1Field.prototype.toRprLEM = function toRprLEM(buff, o, e) {
|
||||
return this.toRprLE(buff, o, this.mul(this.R, e));
|
||||
};
|
||||
toRprLEM(buff, o, e) {
|
||||
return this.toRprLE(buff, o, this.mul(this.R, e));
|
||||
}
|
||||
|
||||
|
||||
// Pases a buffer with Little Endian Representation
|
||||
F1Field.prototype.fromRprLE = function fromRprLE(buff, o) {
|
||||
return Scalar.fromRprLE(buff, o, this.n8);
|
||||
};
|
||||
// Pases a buffer with Little Endian Representation
|
||||
fromRprLE(buff, o) {
|
||||
return Scalar.fromRprLE(buff, o, this.n8);
|
||||
}
|
||||
|
||||
// Pases a buffer with Big Endian Representation
|
||||
F1Field.prototype.fromRprBE = function fromRprBE(buff, o) {
|
||||
return Scalar.fromRprBE(buff, o, this.n8);
|
||||
};
|
||||
// Pases a buffer with Big Endian Representation
|
||||
fromRprBE(buff, o) {
|
||||
return Scalar.fromRprBE(buff, o, this.n8);
|
||||
}
|
||||
|
||||
F1Field.prototype.fromRprLEM = function fromRprLEM(buff, o) {
|
||||
return this.mul(this.fromRprLE(buff, o), this.Ri);
|
||||
};
|
||||
fromRprLEM(buff, o) {
|
||||
return this.mul(this.fromRprLE(buff, o), this.Ri);
|
||||
}
|
||||
|
||||
F1Field.prototype.fromRprBEM = function fromRprBEM(buff, o) {
|
||||
return this.mul(this.fromRprBE(buff, o), this.Ri);
|
||||
};
|
||||
fromRprBEM(buff, o) {
|
||||
return this.mul(this.fromRprBE(buff, o), this.Ri);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = F1Field;
|
||||
|
||||
@@ -1,24 +1,8 @@
|
||||
const bigInt = require("big-integer");
|
||||
const assert = require("assert");
|
||||
const buildSqrt = require("./fsqrt");
|
||||
import bigInt from "big-integer";
|
||||
import buildSqrt from "./fsqrt.js";
|
||||
import {getRandomBytes} from "./random.js";
|
||||
|
||||
function getRandomByte() {
|
||||
if (typeof window !== "undefined") { // Browser
|
||||
if (typeof window.crypto !== "undefined") { // Supported
|
||||
let array = new Uint8Array(1);
|
||||
window.crypto.getRandomValues(array);
|
||||
return array[0];
|
||||
}
|
||||
else { // fallback
|
||||
return Math.floor(Math.random() * 256);
|
||||
}
|
||||
}
|
||||
else { // NodeJS
|
||||
return module.require("crypto").randomBytes(1)[0];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = class ZqField {
|
||||
export default class ZqField {
|
||||
constructor(p) {
|
||||
this.type="F1";
|
||||
this.one = bigInt.one;
|
||||
@@ -132,17 +116,17 @@ module.exports = class ZqField {
|
||||
}
|
||||
|
||||
div(a, b) {
|
||||
assert(!b.isZero(), "Division by zero");
|
||||
if (b.isZero()) throw new Error("Division by zero");
|
||||
return a.times(b.modInv(this.p)).mod(this.p);
|
||||
}
|
||||
|
||||
idiv(a, b) {
|
||||
assert(!b.isZero(), "Division by zero");
|
||||
if (b.isZero()) throw new Error("Division by zero");
|
||||
return a.divide(b);
|
||||
}
|
||||
|
||||
inv(a) {
|
||||
assert(!a.isZero(), "Division by zero");
|
||||
if (a.isZero()) throw new Error("Division by zero");
|
||||
return a.modInv(this.p);
|
||||
}
|
||||
|
||||
@@ -154,6 +138,10 @@ module.exports = class ZqField {
|
||||
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);
|
||||
}
|
||||
@@ -259,7 +247,7 @@ module.exports = class ZqField {
|
||||
let res = bigInt(0);
|
||||
let n = bigInt(this.p.square());
|
||||
while (!n.isZero()) {
|
||||
res = res.shiftLeft(8).add(bigInt(getRandomByte()));
|
||||
res = res.shiftLeft(8).add(bigInt(getRandomBytes(1)[0]));
|
||||
n = n.shiftRight(8);
|
||||
}
|
||||
return res.mod(this.p);
|
||||
@@ -295,5 +283,5 @@ module.exports = class ZqField {
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,10 @@
|
||||
/* global BigInt */
|
||||
const assert = require("assert");
|
||||
const Scalar = require("./scalar");
|
||||
const futils = require("./futils");
|
||||
const buildSqrt = require("./fsqrt");
|
||||
import * as Scalar from "./scalar.js";
|
||||
import * as futils from "./futils.js";
|
||||
import buildSqrt from "./fsqrt.js";
|
||||
import {getRandomBytes} from "./random.js";
|
||||
|
||||
function getRandomByte() {
|
||||
if (typeof window !== "undefined") { // Browser
|
||||
if (typeof window.crypto !== "undefined") { // Supported
|
||||
let array = new Uint8Array(1);
|
||||
window.crypto.getRandomValues(array);
|
||||
return array[0];
|
||||
}
|
||||
else { // fallback
|
||||
return Math.floor(Math.random() * 256);
|
||||
}
|
||||
}
|
||||
else { // NodeJS
|
||||
return module.require("crypto").randomBytes(1)[0];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = class ZqField {
|
||||
export default class ZqField {
|
||||
constructor(p) {
|
||||
this.type="F1";
|
||||
this.one = 1n;
|
||||
@@ -140,12 +124,12 @@ module.exports = class ZqField {
|
||||
}
|
||||
|
||||
idiv(a, b) {
|
||||
assert(b, "Division by zero");
|
||||
if (!b) throw new Error("Division by zero");
|
||||
return a / b;
|
||||
}
|
||||
|
||||
inv(a) {
|
||||
assert(a, "Division by zero");
|
||||
if (!a) throw new Error("Division by zero");
|
||||
|
||||
let t = 0n;
|
||||
let r = this.p;
|
||||
@@ -168,6 +152,10 @@ module.exports = class ZqField {
|
||||
return futils.exp(this, b, e);
|
||||
}
|
||||
|
||||
exp(b, e) {
|
||||
return futils.exp(this, b, e);
|
||||
}
|
||||
|
||||
band(a, b) {
|
||||
const res = ((a & b) & this.mask);
|
||||
return res >= this.p ? res-this.p : res;
|
||||
@@ -281,7 +269,7 @@ module.exports = class ZqField {
|
||||
const nBytes = (this.bitLength*2 / 8);
|
||||
let res =0n;
|
||||
for (let i=0; i<nBytes; i++) {
|
||||
res = (res << 8n) + BigInt(getRandomByte());
|
||||
res = (res << 8n) + BigInt(getRandomBytes(1)[0]);
|
||||
}
|
||||
return res % this.p;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const fUtils = require("./futils.js");
|
||||
const buildSqrt = require("./fsqrt");
|
||||
import * as fUtils from "./futils.js";
|
||||
import buildSqrt from "./fsqrt.js";
|
||||
|
||||
class F2Field {
|
||||
export default class F2Field {
|
||||
constructor(F, nonResidue) {
|
||||
this.type="F2";
|
||||
this.F = F;
|
||||
@@ -141,6 +141,10 @@ class F2Field {
|
||||
return fUtils.exp(this, base, e);
|
||||
}
|
||||
|
||||
exp(base, e) {
|
||||
return fUtils.exp(this, base, e);
|
||||
}
|
||||
|
||||
toString(a) {
|
||||
return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])} ]`;
|
||||
}
|
||||
@@ -230,4 +234,3 @@ class F2Field {
|
||||
|
||||
}
|
||||
|
||||
module.exports = F2Field;
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const fUtils = require("./futils.js");
|
||||
import * as fUtils from "./futils.js";
|
||||
|
||||
class F3Field {
|
||||
export default class F3Field {
|
||||
constructor(F, nonResidue) {
|
||||
this.type="F3";
|
||||
this.F = F;
|
||||
@@ -171,6 +171,10 @@ class F3Field {
|
||||
return fUtils.mulScalar(this, base, e);
|
||||
}
|
||||
|
||||
pow(base, e) {
|
||||
return fUtils.exp(this, base, e);
|
||||
}
|
||||
|
||||
exp(base, e) {
|
||||
return fUtils.exp(this, base, e);
|
||||
}
|
||||
@@ -275,5 +279,3 @@ class F3Field {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = F3Field;
|
||||
|
||||
20
src/fft.js
20
src/fft.js
@@ -24,8 +24,7 @@
|
||||
by the array [ p0, p1, p2, ... , pn ].
|
||||
*/
|
||||
|
||||
const assert = require("assert");
|
||||
class FFT {
|
||||
export default class FFT {
|
||||
constructor (G, F, opMulGF) {
|
||||
this.F = F;
|
||||
this.G = G;
|
||||
@@ -51,7 +50,8 @@ class FFT {
|
||||
|
||||
|
||||
this.roots = [];
|
||||
/* for (let i=0; i<16; i++) {
|
||||
/*
|
||||
for (let i=0; i<16; i++) {
|
||||
let r = this.F.one;
|
||||
n = 1 << i;
|
||||
const rootsi = new Array(n);
|
||||
@@ -62,7 +62,7 @@ class FFT {
|
||||
|
||||
this.roots.push(rootsi);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
this._setRoots(15);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,9 @@ class FFT {
|
||||
this._setRoots(bits);
|
||||
|
||||
const m = 1 << bits;
|
||||
assert (p.length == m);
|
||||
if (p.length != m) {
|
||||
throw new Error("Size must be multiple of 2");
|
||||
}
|
||||
const res = __fft(this, p, bits, 0, 1);
|
||||
return res;
|
||||
}
|
||||
@@ -97,8 +99,10 @@ class FFT {
|
||||
const bits = log2(p.length-1)+1;
|
||||
this._setRoots(bits);
|
||||
const m = 1 << bits;
|
||||
assert (p.length == m);
|
||||
const res = __ffti(this, p, bits, 0, 1);
|
||||
if (p.length != m) {
|
||||
throw new Error("Size must be multiple of 2");
|
||||
}
|
||||
const res = __fft(this, p, bits, 0, 1);
|
||||
const twoinvm = this.F.inv( this.F.mulScalar(this.F.one, m) );
|
||||
const resn = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
@@ -142,5 +146,3 @@ function __fft(PF, pall, bits, offset, step) {
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
module.exports = FFT;
|
||||
|
||||
110
src/fsqrt.js
110
src/fsqrt.js
@@ -1,28 +1,25 @@
|
||||
const Scalar = require("./scalar");
|
||||
const assert = require("assert");
|
||||
import * as Scalar from "./scalar.js";
|
||||
// Check here: https://eprint.iacr.org/2012/685.pdf
|
||||
|
||||
module.exports = function buildSqrt (F) {
|
||||
export default function buildSqrt (F) {
|
||||
if ((F.m % 2) == 1) {
|
||||
if (Scalar.eq(Scalar.mod(F.p, 4), 1 )) {
|
||||
if (Scalar.eq(Scalar.mod(F.p, 8), 1 )) {
|
||||
if (Scalar.eq(Scalar.mod(F.p, 16), 1 )) {
|
||||
// alg7_muller(F);
|
||||
alg5_tonelliShanks(F);
|
||||
} else if (Scalar.eq(Scalar.mod(F.p, 16), 1 )) {
|
||||
} else if (Scalar.eq(Scalar.mod(F.p, 16), 9 )) {
|
||||
alg4_kong(F);
|
||||
} else {
|
||||
assert(false);
|
||||
throw new Error("Field withot sqrt");
|
||||
}
|
||||
} else if (Scalar.eq(Scalar.mod(F.p, 8), 5 )) {
|
||||
alg3_atkin(F);
|
||||
} else {
|
||||
assert(false);
|
||||
throw new Error("Field withot sqrt");
|
||||
}
|
||||
} else if (Scalar.eq(Scalar.mod(F.p, 4), 3 )) {
|
||||
alg2_shanks(F);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
const pm2mod4 = Scalar.mod(Scalar.pow(F.p, F.m/2), 4);
|
||||
@@ -35,96 +32,9 @@ module.exports = function buildSqrt (F) {
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function alg7_muller(F) {
|
||||
F.sqrt_q = Scalar.pow(F.p, F.m);
|
||||
F.sqrt_2 = F.add(F.one, F.one);
|
||||
F.sqrt_4 = F.add(F.sqrt_2, F.sqrt_2);
|
||||
F.sqrt_e = Scalar.div( Scalar.sub(F.sqrt_q, 1) , 2);
|
||||
|
||||
F.sqrt_bits = Scalar.bits(Scalar.div( Scalar.sub(F.sqrt_q, 1) , 4));
|
||||
|
||||
F.sqrt_v = function(alfa) {
|
||||
const d = [];
|
||||
d[0] = alfa;
|
||||
d[1] = this.sub(this.square(alfa), this.sqrt_2);
|
||||
for (let j=F.sqrt_bits.length-2; j>0; j--) {
|
||||
const d0 =
|
||||
this.sub(
|
||||
this.mul(d[0], d[1]),
|
||||
alfa
|
||||
);
|
||||
const d1 =
|
||||
this.sub(
|
||||
this.square( d[ 1 - F.sqrt_bits[j] ]),
|
||||
this.sqrt_2
|
||||
);
|
||||
d[ 1 - F.sqrt_bits[j] ] = d0;
|
||||
d[ F.sqrt_bits[j] ] = d1;
|
||||
/*
|
||||
d[ 1 - F.sqrt_bits[j] ] =
|
||||
this.sub(
|
||||
this.mul(d[0], d[1]),
|
||||
alfa
|
||||
);
|
||||
d[ F.sqrt_bits[j] ] =
|
||||
this.sub(
|
||||
this.square( d[ 1 - F.sqrt_bits[j] ]),
|
||||
this.sqrt_2
|
||||
);
|
||||
*/
|
||||
}
|
||||
if (F.sqrt_bits[0] == 1) {
|
||||
return this.sub(
|
||||
this.mul(d[0], d[1]),
|
||||
alfa
|
||||
);
|
||||
} else {
|
||||
return this.sub(
|
||||
this.square(d[0]),
|
||||
this.sqrt_2
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
F.sqrt = function(a) {
|
||||
if (this.isZero(a)) return this.zero;
|
||||
if (this.eq(a, this.sqrt_4)) return this.sqrt_2;
|
||||
|
||||
|
||||
let t = this.one;
|
||||
let a1 = this.pow( this.sub(a, F.sqrt_4), F.sqrt_e);
|
||||
|
||||
while (this.eq(a1, this.one)) {
|
||||
t = this.random();
|
||||
while (this.isZero(t) || this.eq(t, this.one)) {
|
||||
t = this.random();
|
||||
}
|
||||
|
||||
const b = this.sub(this.mul(a, this.square(t)), this.sqrt_4);
|
||||
if (this.isZero(b)) {
|
||||
return this.mul(this.sqrt_2, this.inv(t));
|
||||
}
|
||||
|
||||
a1 = this.pow(b, F.sqrt_e);
|
||||
}
|
||||
|
||||
const alfa = this.sub(this.mul(a, this.square(t)), this.sqrt_2);
|
||||
|
||||
const x = this.div( this.sqrt_v(alfa), t);
|
||||
|
||||
const a0 = this.sub(this.square(x), a);
|
||||
|
||||
if (!this.isZero(a0)) return null;
|
||||
|
||||
return x;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function alg5_tonelliShanks(F) {
|
||||
F.sqrt_q = Scalar.pow(F.p, F.m);
|
||||
|
||||
@@ -180,13 +90,13 @@ function alg5_tonelliShanks(F) {
|
||||
|
||||
function alg4_kong(F) {
|
||||
F.sqrt = function() {
|
||||
assert(false, "Not implemented");
|
||||
throw new Error("Sqrt alg 4 not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
function alg3_atkin(F) {
|
||||
F.sqrt = function() {
|
||||
assert(false, "Not implemented");
|
||||
throw new Error("Sqrt alg 3 not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -213,7 +123,7 @@ function alg2_shanks(F) {
|
||||
|
||||
function alg10_adj(F) {
|
||||
F.sqrt = function() {
|
||||
assert(false, "Not implemented");
|
||||
throw new Error("Sqrt alg 10 not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -251,6 +161,6 @@ function alg9_adj(F) {
|
||||
|
||||
function alg8_complex(F) {
|
||||
F.sqrt = function() {
|
||||
assert(false, "Not implemented");
|
||||
throw new Error("Sqrt alg 8 not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Scalar = require("./scalar.js");
|
||||
const assert = require("assert");
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
|
||||
exports.mulScalar = (F, base, e) => {
|
||||
export function mulScalar(F, base, e) {
|
||||
let res;
|
||||
|
||||
if (Scalar.isZero(e)) return F.zero;
|
||||
@@ -33,7 +32,7 @@ exports.mulScalar = (F, base, e) => {
|
||||
} else if (n[n.length-1] == -1) {
|
||||
res = F.neg(base);
|
||||
} else {
|
||||
assert(false);
|
||||
throw new Error("invlaud NAF");
|
||||
}
|
||||
|
||||
for (let i=n.length-2; i>=0; i--) {
|
||||
@@ -48,7 +47,7 @@ exports.mulScalar = (F, base, e) => {
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -70,7 +69,7 @@ exports.mulScalar = (F, base, e) =>{
|
||||
*/
|
||||
|
||||
|
||||
exports.exp = (F, base, e) => {
|
||||
export function exp(F, base, e) {
|
||||
|
||||
if (Scalar.isZero(e)) return F.one;
|
||||
|
||||
@@ -90,6 +89,6 @@ exports.exp = (F, base, e) => {
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
by the array [ p0, p1, p2, ... , pn ].
|
||||
*/
|
||||
|
||||
class PolField {
|
||||
export default class PolField {
|
||||
constructor (F) {
|
||||
this.F = F;
|
||||
|
||||
@@ -509,7 +509,7 @@ class PolField {
|
||||
}
|
||||
|
||||
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.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])));
|
||||
@@ -615,4 +615,3 @@ function __bitReverse(p, bits) {
|
||||
}
|
||||
|
||||
|
||||
module.exports = PolField;
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/* global window */
|
||||
const ChaCha = require("./chacha");
|
||||
import ChaCha from "./chacha.js";
|
||||
import crypto from "crypto";
|
||||
|
||||
module.exports.getRandomBytes = getRandomBytes;
|
||||
module.exports.getRandomSeed = getRandomSeed;
|
||||
module.exports.getThreadRng = getThreadRng;
|
||||
|
||||
function getRandomBytes(n) {
|
||||
export function getRandomBytes(n) {
|
||||
let array = new Uint8Array(n);
|
||||
if (typeof window !== "undefined") { // Browser
|
||||
if (typeof window.crypto !== "undefined") { // Supported
|
||||
@@ -17,12 +14,12 @@ function getRandomBytes(n) {
|
||||
}
|
||||
}
|
||||
else { // NodeJS
|
||||
module.require("crypto").randomFillSync(array);
|
||||
crypto.randomFillSync(array);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function getRandomSeed() {
|
||||
export function getRandomSeed() {
|
||||
const arr = getRandomBytes(32);
|
||||
const arrV = new Uint32Array(arr.buffer);
|
||||
const seed = [];
|
||||
@@ -34,7 +31,7 @@ function getRandomSeed() {
|
||||
|
||||
let threadRng = null;
|
||||
|
||||
function getThreadRng() {
|
||||
export function getThreadRng() {
|
||||
if (threadRng) return threadRng;
|
||||
threadRng = new ChaCha(getRandomSeed());
|
||||
return threadRng;
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const fUtils = require("./futils.js");
|
||||
import * as fUtils from "./futils.js";
|
||||
|
||||
class RatField {
|
||||
export default class RatField {
|
||||
constructor(F) {
|
||||
this.F = F;
|
||||
this.zero = [F.zero, F.one];
|
||||
@@ -123,5 +123,3 @@ class RatField {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = RatField;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
|
||||
const assert = require("assert");
|
||||
import * as Scalar_native from "./scalar_native.js";
|
||||
import * as Scalar_bigint from "./scalar_bigint.js";
|
||||
|
||||
const supportsNativeBigInt = typeof BigInt === "function";
|
||||
|
||||
let Scalar;
|
||||
let Scalar = {};
|
||||
if (supportsNativeBigInt) {
|
||||
Scalar = require("./scalar_native.js");
|
||||
Object.assign(Scalar, Scalar_native);
|
||||
} else {
|
||||
Scalar = require("./scalar_bigint.js");
|
||||
Object.assign(Scalar, Scalar_bigint);
|
||||
}
|
||||
|
||||
|
||||
// Returns a buffer with Little Endian Representation
|
||||
Scalar.__proto__.toRprLE = function rprBE(buff, o, e, n8) {
|
||||
Scalar.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;
|
||||
@@ -22,7 +23,7 @@ Scalar.__proto__.toRprLE = function rprBE(buff, o, e, n8) {
|
||||
};
|
||||
|
||||
// Returns a buffer with Big Endian Representation
|
||||
Scalar.__proto__.toRprBE = function rprLEM(buff, o, e, n8) {
|
||||
Scalar.toRprBE = function rprLEM(buff, o, e, n8) {
|
||||
const s = "0000000" + e.toString(16);
|
||||
const v = new DataView(buff.buffer, o, n8);
|
||||
const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words;
|
||||
@@ -31,7 +32,7 @@ Scalar.__proto__.toRprBE = function rprLEM(buff, o, e, n8) {
|
||||
};
|
||||
|
||||
// Pases a buffer with Little Endian Representation
|
||||
Scalar.__proto__.fromRprLE = function rprLEM(buff, o, n8) {
|
||||
Scalar.fromRprLE = function rprLEM(buff, o, n8) {
|
||||
n8 = n8 || buff.byteLength;
|
||||
const v = new Uint32Array(buff.buffer, o, n8/4);
|
||||
const a = new Array(n8/4);
|
||||
@@ -40,7 +41,7 @@ Scalar.__proto__.fromRprLE = function rprLEM(buff, o, n8) {
|
||||
};
|
||||
|
||||
// Pases a buffer with Big Endian Representation
|
||||
Scalar.__proto__.fromRprBE = function rprLEM(buff, o, n8) {
|
||||
Scalar.fromRprBE = function rprLEM(buff, o, n8) {
|
||||
n8 = n8 || buff.byteLength;
|
||||
const v = new DataView(buff.buffer, o, n8);
|
||||
const a = new Array(n8/4);
|
||||
@@ -50,22 +51,69 @@ Scalar.__proto__.fromRprBE = function rprLEM(buff, o, n8) {
|
||||
return Scalar.fromString(a.join(""), 16);
|
||||
};
|
||||
|
||||
Scalar.__proto__.toString = function toString(a, radix) {
|
||||
Scalar.toString = function toString(a, radix) {
|
||||
return a.toString(radix);
|
||||
};
|
||||
|
||||
Scalar.__proto__.toLEBuff = function toLEBuff(a) {
|
||||
Scalar.toLEBuff = function toLEBuff(a) {
|
||||
const buff = new Uint8Array(Math.floor((Scalar.bitLength(a) - 1) / 8) +1);
|
||||
Scalar.toRprLE(buff, 0, a, buff.byteLength);
|
||||
return buff;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Scalar.zero = Scalar.e(0);
|
||||
Scalar.one = Scalar.e(1);
|
||||
|
||||
module.exports = Scalar;
|
||||
export let {
|
||||
toRprLE,
|
||||
toRprBE,
|
||||
fromRprLE,
|
||||
fromRprBE,
|
||||
toString,
|
||||
toLEBuff,
|
||||
zero,
|
||||
one,
|
||||
fromString,
|
||||
e,
|
||||
fromArray,
|
||||
bitLength,
|
||||
isNegative,
|
||||
isZero,
|
||||
shiftLeft,
|
||||
shiftRight,
|
||||
shl,
|
||||
shr,
|
||||
isOdd,
|
||||
naf,
|
||||
bits,
|
||||
toNumber,
|
||||
toArray,
|
||||
add,
|
||||
sub,
|
||||
neg,
|
||||
mul,
|
||||
square,
|
||||
pow,
|
||||
exp,
|
||||
abs,
|
||||
div,
|
||||
mod,
|
||||
eq,
|
||||
neq,
|
||||
lt,
|
||||
gt,
|
||||
leq,
|
||||
geq,
|
||||
band,
|
||||
bor,
|
||||
bxor,
|
||||
land,
|
||||
lor,
|
||||
lnot,
|
||||
} = Scalar;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const bigInt = require("big-integer");
|
||||
const assert = require("assert");
|
||||
import bigInt from "big-integer";
|
||||
|
||||
module.exports.fromString = function fromString(s, radix) {
|
||||
export function fromString(s, radix) {
|
||||
if (typeof s == "string") {
|
||||
if (s.slice(0,2) == "0x") {
|
||||
return bigInt(s.slice(2), 16);
|
||||
@@ -11,43 +10,43 @@ module.exports.fromString = function fromString(s, radix) {
|
||||
} else {
|
||||
return bigInt(s, radix);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.e = module.exports.fromString;
|
||||
export const e = fromString;
|
||||
|
||||
module.exports.fromArray = function fromArray(a, radix) {
|
||||
export function fromArray(a, radix) {
|
||||
return bigInt.fromArray(a, radix);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bitLength = function (a) {
|
||||
export function bitLength(a) {
|
||||
return bigInt(a).bitLength();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.isNegative = function (a) {
|
||||
export function isNegative(a) {
|
||||
return bigInt(a).isNegative();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.isZero = function (a) {
|
||||
export function isZero(a) {
|
||||
return bigInt(a).isZero();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.shiftLeft = function (a, n) {
|
||||
export function shiftLeft(a, n) {
|
||||
return bigInt(a).shiftLeft(n);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.shiftRight = function (a, n) {
|
||||
export function shiftRight(a, n) {
|
||||
return bigInt(a).shiftRight(n);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.shl = module.exports.shiftLeft;
|
||||
module.exports.shr = module.exports.shiftRight;
|
||||
export const shl = shiftLeft;
|
||||
export const shr = shiftRight;
|
||||
|
||||
module.exports.isOdd = function (a) {
|
||||
export function isOdd(a) {
|
||||
return bigInt(a).isOdd();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.naf = function naf(n) {
|
||||
export function naf(n) {
|
||||
let E = bigInt(n);
|
||||
const res = [];
|
||||
while (E.gt(bigInt.zero)) {
|
||||
@@ -61,10 +60,9 @@ module.exports.naf = function naf(n) {
|
||||
E = E.shiftRight(1);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.bits = function naf(n) {
|
||||
export function bits(n) {
|
||||
let E = bigInt(n);
|
||||
const res = [];
|
||||
while (E.gt(bigInt.zero)) {
|
||||
@@ -76,99 +74,105 @@ module.exports.bits = function naf(n) {
|
||||
E = E.shiftRight(1);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.toNumber = function(s) {
|
||||
assert(s.lt(bigInt("9007199254740992", 10)));
|
||||
export function toNumber(s) {
|
||||
if (!s.lt(bigInt("9007199254740992", 10))) {
|
||||
throw new Error("Number too big");
|
||||
}
|
||||
return s.toJSNumber();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.toArray = function(s, radix) {
|
||||
export function toArray(s, radix) {
|
||||
return bigInt(s).toArray(radix);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.add = function(a, b) {
|
||||
export function add(a, b) {
|
||||
return bigInt(a).add(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.sub = function(a, b) {
|
||||
export function sub(a, b) {
|
||||
return bigInt(a).minus(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.neg = function(a) {
|
||||
export function neg(a) {
|
||||
return bigInt.zero.minus(bigInt(a));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.mul = function(a, b) {
|
||||
export function mul(a, b) {
|
||||
return bigInt(a).times(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.square = function(a) {
|
||||
export function square(a) {
|
||||
return bigInt(a).square();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.pow = function(a, b) {
|
||||
export function pow(a, b) {
|
||||
return bigInt(a).pow(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.abs = function(a) {
|
||||
export function exp(a, b) {
|
||||
return bigInt(a).pow(bigInt(b));
|
||||
}
|
||||
|
||||
export function abs(a) {
|
||||
return bigInt(a).abs();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.div = function(a, b) {
|
||||
export function div(a, b) {
|
||||
return bigInt(a).divide(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.mod = function(a, b) {
|
||||
export function mod(a, b) {
|
||||
return bigInt(a).mod(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.eq = function(a, b) {
|
||||
export function eq(a, b) {
|
||||
return bigInt(a).eq(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.neq = function(a, b) {
|
||||
export function neq(a, b) {
|
||||
return bigInt(a).neq(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.lt = function(a, b) {
|
||||
export function lt(a, b) {
|
||||
return bigInt(a).lt(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.gt = function(a, b) {
|
||||
export function gt(a, b) {
|
||||
return bigInt(a).gt(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.leq = function(a, b) {
|
||||
export function leq(a, b) {
|
||||
return bigInt(a).leq(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.geq = function(a, b) {
|
||||
export function geq(a, b) {
|
||||
return bigInt(a).geq(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.band = function(a, b) {
|
||||
export function band(a, b) {
|
||||
return bigInt(a).and(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bor = function(a, b) {
|
||||
export function bor(a, b) {
|
||||
return bigInt(a).or(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bxor = function(a, b) {
|
||||
export function bxor(a, b) {
|
||||
return bigInt(a).xor(bigInt(b));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.band = function(a, b) {
|
||||
export function land(a, b) {
|
||||
return (!bigInt(a).isZero()) && (!bigInt(b).isZero());
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bor = function(a, b) {
|
||||
export function lor(a, b) {
|
||||
return (!bigInt(a).isZero()) || (!bigInt(b).isZero());
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bnot = function(a) {
|
||||
export function lnot(a) {
|
||||
return bigInt(a).isZero();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* global BigInt */
|
||||
const assert = require("assert");
|
||||
const hexLen = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4];
|
||||
|
||||
module.exports.fromString = function fromString(s, radix) {
|
||||
export function fromString(s, radix) {
|
||||
if ((!radix)||(radix==10)) {
|
||||
return BigInt(s);
|
||||
} else if (radix==16) {
|
||||
@@ -12,49 +11,49 @@ module.exports.fromString = function fromString(s, radix) {
|
||||
return BigInt("0x"+s);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.e = module.exports.fromString;
|
||||
export const e = fromString;
|
||||
|
||||
module.exports.fromArray = function fromArray(a, radix) {
|
||||
export function fromArray(a, radix) {
|
||||
let acc =0n;
|
||||
radix = BigInt(radix);
|
||||
for (let i=0; i<a.length; i++) {
|
||||
acc = acc*radix + BigInt(a[i]);
|
||||
}
|
||||
return acc;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bitLength = function (a) {
|
||||
export function bitLength(a) {
|
||||
const aS =a.toString(16);
|
||||
return (aS.length-1)*4 +hexLen[parseInt(aS[0], 16)];
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.isNegative = function (a) {
|
||||
export function isNegative(a) {
|
||||
return BigInt(a) < 0n;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.isZero = function (a) {
|
||||
export function isZero(a) {
|
||||
return !a;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.shiftLeft = function (a, n) {
|
||||
export function shiftLeft(a, n) {
|
||||
return BigInt(a) << BigInt(n);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.shiftRight = function (a, n) {
|
||||
export function shiftRight(a, n) {
|
||||
return BigInt(a) >> BigInt(n);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.shl = module.exports.shiftLeft;
|
||||
module.exports.shr = module.exports.shiftRight;
|
||||
export const shl = shiftLeft;
|
||||
export const shr = shiftRight;
|
||||
|
||||
module.exports.isOdd = function (a) {
|
||||
export function isOdd(a) {
|
||||
return (BigInt(a) & 1n) == 1n;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.naf = function naf(n) {
|
||||
export function naf(n) {
|
||||
let E = BigInt(n);
|
||||
const res = [];
|
||||
while (E) {
|
||||
@@ -68,10 +67,10 @@ module.exports.naf = function naf(n) {
|
||||
E = E >> 1n;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.bits = function naf(n) {
|
||||
export function bits(n) {
|
||||
let E = BigInt(n);
|
||||
const res = [];
|
||||
while (E) {
|
||||
@@ -83,14 +82,16 @@ module.exports.bits = function naf(n) {
|
||||
E = E >> 1n;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.toNumber = function(s) {
|
||||
assert(s<BigInt(Number.MAX_SAFE_INTEGER + 1));
|
||||
export function toNumber(s) {
|
||||
if (s>BigInt(Number.MAX_SAFE_INTEGER )) {
|
||||
throw new Error("Number too big");
|
||||
}
|
||||
return Number(s);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.toArray = function(s, radix) {
|
||||
export function toArray(s, radix) {
|
||||
const res = [];
|
||||
let rem = BigInt(s);
|
||||
radix = BigInt(radix);
|
||||
@@ -99,90 +100,94 @@ module.exports.toArray = function(s, radix) {
|
||||
rem = rem / radix;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.add = function(a, b) {
|
||||
export function add(a, b) {
|
||||
return BigInt(a) + BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.sub = function(a, b) {
|
||||
export function sub(a, b) {
|
||||
return BigInt(a) - BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.neg = function(a) {
|
||||
export function neg(a) {
|
||||
return -BigInt(a);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.mul = function(a, b) {
|
||||
export function mul(a, b) {
|
||||
return BigInt(a) * BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.square = function(a) {
|
||||
export function square(a) {
|
||||
return BigInt(a) * BigInt(a);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.pow = function(a, b) {
|
||||
export function pow(a, b) {
|
||||
return BigInt(a) ** BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.abs = function(a) {
|
||||
export function exp(a, b) {
|
||||
return BigInt(a) ** BigInt(b);
|
||||
}
|
||||
|
||||
export function abs(a) {
|
||||
return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.div = function(a, b) {
|
||||
export function div(a, b) {
|
||||
return BigInt(a) / BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.mod = function(a, b) {
|
||||
export function mod(a, b) {
|
||||
return BigInt(a) % BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.eq = function(a, b) {
|
||||
export function eq(a, b) {
|
||||
return BigInt(a) == BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.neq = function(a, b) {
|
||||
export function neq(a, b) {
|
||||
return BigInt(a) != BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.lt = function(a, b) {
|
||||
export function lt(a, b) {
|
||||
return BigInt(a) < BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.gt = function(a, b) {
|
||||
export function gt(a, b) {
|
||||
return BigInt(a) > BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.leq = function(a, b) {
|
||||
export function leq(a, b) {
|
||||
return BigInt(a) <= BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.geq = function(a, b) {
|
||||
export function geq(a, b) {
|
||||
return BigInt(a) >= BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.band = function(a, b) {
|
||||
export function band(a, b) {
|
||||
return BigInt(a) & BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bor = function(a, b) {
|
||||
export function bor(a, b) {
|
||||
return BigInt(a) | BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.bxor = function(a, b) {
|
||||
export function bxor(a, b) {
|
||||
return BigInt(a) ^ BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.land = function(a, b) {
|
||||
export function land(a, b) {
|
||||
return BigInt(a) && BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.lor = function(a, b) {
|
||||
export function lor(a, b) {
|
||||
return BigInt(a) || BigInt(b);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.lnot = function(a) {
|
||||
export function lnot(a) {
|
||||
return !BigInt(a);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global navigator, Blob, Worker, WebAssembly */
|
||||
/* global window, navigator, Blob, Worker, WebAssembly */
|
||||
/*
|
||||
Copyright 2019 0KIMS association.
|
||||
|
||||
@@ -21,17 +21,14 @@
|
||||
const MEM_SIZE = 4096; // Memory size in 64K Pakes (256Mb)
|
||||
|
||||
|
||||
const assert = require("assert");
|
||||
const thread = require("./threadman_thread");
|
||||
const FFT = require("./fft");
|
||||
const {log2, buffReverseBits} = require("./utils");
|
||||
import thread from "./threadman_thread.js";
|
||||
import os from "os";
|
||||
|
||||
import NodeWorker_mod from "worker_threads";
|
||||
const inBrowser = (typeof window !== "undefined");
|
||||
let NodeWorker;
|
||||
let NodeCrypto;
|
||||
if (!inBrowser) {
|
||||
NodeWorker = require("worker_threads").Worker;
|
||||
NodeCrypto = require("crypto");
|
||||
NodeWorker = NodeWorker_mod.Worker;
|
||||
}
|
||||
|
||||
class Deferred {
|
||||
@@ -43,17 +40,31 @@ class Deferred {
|
||||
}
|
||||
}
|
||||
|
||||
function base64ToArrayBuffer(base64) {
|
||||
if (process.browser) {
|
||||
var binary_string = window.atob(base64);
|
||||
var len = binary_string.length;
|
||||
var bytes = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
} else {
|
||||
return new Uint8Array(Buffer.from(base64, "base64"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function buildThreadManager(wasm, singleThread) {
|
||||
|
||||
export default 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);
|
||||
const wasmModule = await WebAssembly.compile(base64ToArrayBuffer(wasm.code));
|
||||
|
||||
tm.instance = await WebAssembly.instantiate(wasmModule, {
|
||||
env: {
|
||||
@@ -71,17 +82,17 @@ async function buildThreadManager(wasm, singleThread) {
|
||||
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.pTmp0 = tm.alloc(curve.G2.F.n8*3);
|
||||
// tm.pTmp1 = tm.alloc(curve.G2.F.n8*3);
|
||||
|
||||
|
||||
if (singleThread) {
|
||||
tm.code = wasm.code;
|
||||
tm.code = base64ToArrayBuffer(wasm.code);
|
||||
tm.taskManager = thread();
|
||||
await tm.taskManager([{
|
||||
cmd: "INIT",
|
||||
init: MEM_SIZE,
|
||||
code: wasm.code
|
||||
code: tm.code.slice()
|
||||
}]);
|
||||
tm.concurrency = 1;
|
||||
} else {
|
||||
@@ -94,7 +105,6 @@ async function buildThreadManager(wasm, singleThread) {
|
||||
if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) {
|
||||
concurrency = navigator.hardwareConcurrency;
|
||||
} else {
|
||||
const os = require("os");
|
||||
concurrency = os.cpus().length;
|
||||
}
|
||||
tm.concurrency = concurrency;
|
||||
@@ -120,12 +130,12 @@ async function buildThreadManager(wasm, singleThread) {
|
||||
|
||||
const initPromises = [];
|
||||
for (let i=0; i<tm.workers.length;i++) {
|
||||
const copyCode = wasm.code.buffer.slice(0);
|
||||
const copyCode = base64ToArrayBuffer(wasm.code).slice();
|
||||
initPromises.push(tm.postAction(i, [{
|
||||
cmd: "INIT",
|
||||
init: MEM_SIZE,
|
||||
code: copyCode
|
||||
}], [copyCode]));
|
||||
}], [copyCode.buffer]));
|
||||
}
|
||||
|
||||
await Promise.all(initPromises);
|
||||
@@ -157,18 +167,20 @@ class ThreadManager {
|
||||
}
|
||||
|
||||
startSyncOp() {
|
||||
assert(this.oldPFree == 0);
|
||||
if (this.oldPFree != 0) throw new Error("Sync operation in progress");
|
||||
this.oldPFree = this.u32[0];
|
||||
}
|
||||
|
||||
endSyncOp() {
|
||||
assert(this.oldPFree != 0);
|
||||
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) {
|
||||
assert(this.working[workerId] == false);
|
||||
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();
|
||||
@@ -236,7 +248,3 @@ class ThreadManager {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = buildThreadManager;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global WebAssembly */
|
||||
|
||||
module.exports = function thread(self) {
|
||||
export default function thread(self) {
|
||||
let instance;
|
||||
let memory;
|
||||
let u32;
|
||||
@@ -69,7 +69,6 @@ module.exports = function thread(self) {
|
||||
}
|
||||
|
||||
function runTask(task) {
|
||||
const self=this;
|
||||
if (task[0].cmd == "INIT") {
|
||||
return init(task[0]);
|
||||
}
|
||||
@@ -113,145 +112,6 @@ module.exports = function thread(self) {
|
||||
return ctx.out;
|
||||
}
|
||||
|
||||
function batchApplyKey(task) {
|
||||
const outBuffLen = task.buff.byteLength;
|
||||
const oldAlloc = u32[0];
|
||||
const pBufIn = allocBuffer(task.buff);
|
||||
const pFirst = allocBuffer(task.first);
|
||||
const pInc = allocBuffer(task.inc);
|
||||
const pBuffOut = alloc(outBuffLen);
|
||||
if (task.Gs == "G1") {
|
||||
instance.exports.g1m_batchApplyKey(pBufIn, task.n, pFirst, pInc, pBuffOut);
|
||||
} else {
|
||||
instance.exports.g2m_batchApplyKey(pBufIn, task.n, pFirst, pInc, pBuffOut);
|
||||
}
|
||||
|
||||
const outBuff = getBuffer(pBuffOut, outBuffLen).slice();
|
||||
u32[0] = oldAlloc;
|
||||
return [ outBuff, outBuff.buffer];
|
||||
}
|
||||
|
||||
function batchConvert(task) {
|
||||
const oldAlloc = u32[0];
|
||||
|
||||
const outBuffLen = task.n*task.sOut;
|
||||
const pBufIn = allocBuffer(task.buff);
|
||||
const pBuffOut = alloc(outBuffLen);
|
||||
|
||||
instance.exports[task.fnName](pBufIn, task.n, pBuffOut);
|
||||
const outBuff = getBuffer(pBuffOut, outBuffLen).slice();
|
||||
u32[0] = oldAlloc;
|
||||
return [ outBuff, outBuff.buffer];
|
||||
}
|
||||
|
||||
function batchConvertOld(task) {
|
||||
const oldAlloc = u32[0];
|
||||
|
||||
const outBuffLen = task.n*task.sGin;
|
||||
const pBufIn = allocBuffer(task.buff);
|
||||
const pBuffOut = alloc(outBuffLen);
|
||||
if (task.Gs == "G1") {
|
||||
if (task.fr=="LEM") {
|
||||
if (task.to=="U") {
|
||||
instance.exports.g1m_batchLEMtoU(pBufIn, task.n, pBuffOut);
|
||||
} else if (task.to=="C") {
|
||||
instance.exports.g1m_batchLEMtoC(pBufIn, task.n, pBuffOut);
|
||||
} else {
|
||||
throw new Error("Invalid to: "+task.to);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Invalid fr: "+task.fr);
|
||||
}
|
||||
} else if (task.Gs == "G2") {
|
||||
if (task.fr=="LEM") {
|
||||
if (task.to=="U") {
|
||||
instance.exports.g2m_batchLEMtoU(pBufIn, task.n, pBuffOut);
|
||||
} else if (task.to=="C") {
|
||||
instance.exports.g2m_batchLEMtoC(pBufIn, task.n, pBuffOut);
|
||||
} else {
|
||||
throw new Error("Invalid to: "+task.to);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Invalid fr: "+task.fr);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Invalid group: "+task.gs);
|
||||
}
|
||||
|
||||
const outBuff = getBuffer(pBuffOut, outBuffLen).slice();
|
||||
u32[0] = oldAlloc;
|
||||
return [ outBuff, outBuff.buffer];
|
||||
}
|
||||
|
||||
|
||||
function fft(task) {
|
||||
const oldAlloc = u32[0];
|
||||
|
||||
const maxBuffLen = task.n*task.sGin*3/2;
|
||||
const pBuff = alloc(maxBuffLen);
|
||||
setBuffer(pBuff, task.buff);
|
||||
if (task.Gs == "G1") {
|
||||
instance.exports.g1m_batchToJacobian(pBuff, task.n, pBuff);
|
||||
if (task.inverse) {
|
||||
instance.exports.g1m_ifft(pBuff, task.n);
|
||||
} else {
|
||||
instance.exports.g1m_fft(pBuff, task.n);
|
||||
}
|
||||
instance.exports.g1m_batchToAffine(pBuff, task.n, pBuff);
|
||||
} else if (task.Gs == "G2") {
|
||||
instance.exports.g2m_batchToJacobian(pBuff, task.n, pBuff);
|
||||
if (task.inverse) {
|
||||
instance.exports.g2m_ifft(pBuff, task.n);
|
||||
} else {
|
||||
instance.exports.g2m_fft(pBuff, task.n);
|
||||
}
|
||||
instance.exports.g2m_batchToAffine(pBuff, task.n, pBuff);
|
||||
} else if (task.Gs == "Fr") {
|
||||
if (task.inverse) {
|
||||
instance.exports.frm_ifft(pBuff, task.n);
|
||||
} else {
|
||||
instance.exports.frm_fft(pBuff, task.n);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Invalid group: "+task.gs);
|
||||
}
|
||||
|
||||
const outBuff = getBuffer(pBuff, task.n*task.sGin).slice();
|
||||
u32[0] = oldAlloc;
|
||||
return [ outBuff, outBuff.buffer];
|
||||
}
|
||||
|
||||
|
||||
function multiexp(task) {
|
||||
const oldAlloc = u32[0];
|
||||
|
||||
const pBuffBases = allocBuffer(task.buffBases);
|
||||
const pBuffScalars = allocBuffer(task.buffScalars);
|
||||
const pOut = alloc(task.sOut);
|
||||
instance.exports[task.fnName](pBuffBases, pBuffScalars, task.sScalar, task.n, pOut);
|
||||
|
||||
const outBuff = getBuffer(pOut, task.sOut).slice();
|
||||
u32[0] = oldAlloc;
|
||||
return [ outBuff, outBuff.buffer];
|
||||
}
|
||||
|
||||
|
||||
function taskManager(task) {
|
||||
if (task.command == "INIT") {
|
||||
return init(task);
|
||||
} else if (task.command == "BATCH_APPLY_KEY") {
|
||||
return batchApplyKey(task);
|
||||
} else if (task.command == "BATCH_CONVERT") {
|
||||
return batchConvert(task);
|
||||
} else if (task.command == "FFT") {
|
||||
return fft(task);
|
||||
} else if (task.command == "MULTIEXP") {
|
||||
return multiexp(task);
|
||||
} else {
|
||||
console.log("Invalid task", task);
|
||||
throw new Error("Invalid task");
|
||||
}
|
||||
}
|
||||
|
||||
return runTask;
|
||||
};
|
||||
}
|
||||
|
||||
43
src/utils.js
43
src/utils.js
@@ -1,10 +1,13 @@
|
||||
const assert = require("assert");
|
||||
import * as utils_native from "./utils_native.js";
|
||||
import * as utils_bigint from "./utils_bigint.js";
|
||||
|
||||
let utils = {};
|
||||
|
||||
const supportsNativeBigInt = typeof BigInt === "function";
|
||||
if (supportsNativeBigInt) {
|
||||
module.exports = require("./utils_native.js");
|
||||
Object.assign(utils, utils_native);
|
||||
} else {
|
||||
module.exports = require("./utils_bigint.js");
|
||||
Object.assign(utils, utils_bigint);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,36 +27,46 @@ function _revSlow(idx, bits) {
|
||||
return res;
|
||||
}
|
||||
|
||||
function bitReverse(idx, bits) {
|
||||
utils.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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function log2( V )
|
||||
utils.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 ) );
|
||||
}
|
||||
};
|
||||
|
||||
function buffReverseBits(buff, eSize) {
|
||||
utils.buffReverseBits = function buffReverseBits(buff, eSize) {
|
||||
const n = buff.byteLength /eSize;
|
||||
const bits = log2(n);
|
||||
assert (n == (1 << bits));
|
||||
const bits = utils.log2(n);
|
||||
if (n != (1 << bits)) {
|
||||
throw new Error("Invalid number of pointers");
|
||||
}
|
||||
for (let i=0; i<n; i++) {
|
||||
const r = bitReverse(i,bits);
|
||||
const r = utils.bitReverse(i,bits);
|
||||
if (i>r) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.bitReverse = bitReverse;
|
||||
module.exports.log2 = log2;
|
||||
module.exports.buffReverseBits = buffReverseBits;
|
||||
export let {
|
||||
bitReverse,
|
||||
log2,
|
||||
buffReverseBits,
|
||||
stringifyBigInts,
|
||||
unstringifyBigInts,
|
||||
beBuff2int,
|
||||
beInt2Buff,
|
||||
leBuff2int,
|
||||
leInt2Buff,
|
||||
} = utils;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const assert = require("assert");
|
||||
const bigInt = require("big-integer");
|
||||
import bigInt from "big-integer";
|
||||
|
||||
module.exports.stringifyBigInts = function stringifyBigInts(o) {
|
||||
export function stringifyBigInts(o) {
|
||||
if ((typeof(o) == "bigint") || o.eq !== undefined) {
|
||||
return o.toString(10);
|
||||
} else if (Array.isArray(o)) {
|
||||
@@ -16,9 +15,9 @@ module.exports.stringifyBigInts = function stringifyBigInts(o) {
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.unstringifyBigInts = function unstringifyBigInts(o) {
|
||||
export function unstringifyBigInts(o) {
|
||||
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
||||
return bigInt(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
@@ -33,51 +32,55 @@ module.exports.unstringifyBigInts = function unstringifyBigInts(o) {
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.beBuff2int = function beBuff2int(buff) {
|
||||
export function beBuff2int(buff) {
|
||||
let res = bigInt.zero;
|
||||
for (let i=0; i<buff.length; i++) {
|
||||
const n = bigInt(buff[buff.length - i - 1]);
|
||||
res = res.add(n.shiftLeft(i*8));
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.beInt2Buff = function beInt2Buff(n, len) {
|
||||
export function beInt2Buff(n, len) {
|
||||
let r = n;
|
||||
let o =len-1;
|
||||
const buff = Buffer.alloc(len);
|
||||
const buff = new Uint8Array(len);
|
||||
while ((r.gt(bigInt.zero))&&(o>=0)) {
|
||||
let c = Number(r.and(bigInt("255")));
|
||||
buff[o] = c;
|
||||
o--;
|
||||
r = r.shiftRight(8);
|
||||
}
|
||||
assert(r.eq(bigInt.zero));
|
||||
if (!r.eq(bigInt.zero)) {
|
||||
throw new Error("Number does not fit in this length");
|
||||
}
|
||||
return buff;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.leBuff2int = function leBuff2int (buff) {
|
||||
export function leBuff2int (buff) {
|
||||
let res = bigInt.zero;
|
||||
for (let i=0; i<buff.length; i++) {
|
||||
const n = bigInt(buff[i]);
|
||||
res = res.add(n.shiftLeft(i*8));
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.leInt2Buff = function leInt2Buff(n, len) {
|
||||
export function leInt2Buff(n, len) {
|
||||
let r = n;
|
||||
let o =0;
|
||||
const buff = Buffer.alloc(len);
|
||||
const buff = new Uint8Array(len);
|
||||
while ((r.gt(bigInt.zero))&&(o<buff.length)) {
|
||||
let c = Number(r.and(bigInt(255)));
|
||||
buff[o] = c;
|
||||
o++;
|
||||
r = r.shiftRight(8);
|
||||
}
|
||||
assert(r.eq(bigInt.zero));
|
||||
if (!r.eq(bigInt.zero)) {
|
||||
throw new Error("Number does not fit in this length");
|
||||
}
|
||||
return buff;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* global BigInt */
|
||||
const assert = require("assert");
|
||||
const Scalar =require("./scalar");
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
module.exports.stringifyBigInts = function stringifyBigInts(o) {
|
||||
export function stringifyBigInts(o) {
|
||||
if ((typeof(o) == "bigint") || o.eq !== undefined) {
|
||||
return o.toString(10);
|
||||
} else if (Array.isArray(o)) {
|
||||
@@ -17,9 +16,9 @@ module.exports.stringifyBigInts = function stringifyBigInts(o) {
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.unstringifyBigInts = function unstringifyBigInts(o) {
|
||||
export function unstringifyBigInts(o) {
|
||||
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
||||
return BigInt(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
@@ -35,95 +34,103 @@ module.exports.unstringifyBigInts = function unstringifyBigInts(o) {
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.beBuff2int = function beBuff2int(buff) {
|
||||
export function beBuff2int(buff) {
|
||||
let res = 0n;
|
||||
let i = buff.length;
|
||||
let offset = 0;
|
||||
const buffV = new DataView(buff.buffer);
|
||||
while (i>0) {
|
||||
if (i >= 4) {
|
||||
i -= 4;
|
||||
res += BigInt(buff.readUInt32BE(i)) << BigInt(offset*8);
|
||||
res += BigInt(buffV.getUint32(i)) << BigInt(offset*8);
|
||||
offset += 4;
|
||||
} else if (i >= 2) {
|
||||
i -= 2;
|
||||
res += BigInt(buff.readUInt16BE(i)) << BigInt(offset*8);
|
||||
res += BigInt(buffV.getUint16(i)) << BigInt(offset*8);
|
||||
offset += 2;
|
||||
} else {
|
||||
i -= 1;
|
||||
res += BigInt(buff.readUInt8(i)) << BigInt(offset*8);
|
||||
res += BigInt(buffV.getUint8(i)) << BigInt(offset*8);
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.beInt2Buff = function beInt2Buff(n, len) {
|
||||
export function beInt2Buff(n, len) {
|
||||
let r = n;
|
||||
const buff = Buffer.alloc(len);
|
||||
const buff = new Uint8Array(len);
|
||||
const buffV = new DataView(buff.buffer);
|
||||
let o = len;
|
||||
while (o > 0) {
|
||||
if (o-4 >= 0) {
|
||||
o -= 4;
|
||||
buff.writeUInt32BE(Number(r & 0xFFFFFFFFn), o);
|
||||
buffV.setUint32(o, Number(r & 0xFFFFFFFFn));
|
||||
r = r >> 32n;
|
||||
} else if (o-2 >= 0) {
|
||||
o -= 2;
|
||||
buff.writeUInt16BE(Number(r & 0xFFFFn), o);
|
||||
buffV.setUint16(o, Number(r & 0xFFFFn));
|
||||
r = r >> 16n;
|
||||
} else {
|
||||
o -= 1;
|
||||
buff.writeUInt8(Number(r & 0xFFn),o );
|
||||
buffV.setUint8(o, Number(r & 0xFFn));
|
||||
r = r >> 8n;
|
||||
}
|
||||
}
|
||||
assert(r == 0n);
|
||||
if (r) {
|
||||
throw new Error("Number does not fit in this length");
|
||||
}
|
||||
return buff;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.leBuff2int = function leBuff2int(buff) {
|
||||
export function leBuff2int(buff) {
|
||||
let res = 0n;
|
||||
let i = 0;
|
||||
const buffV = new DataView(buff.buffer);
|
||||
while (i<buff.length) {
|
||||
if (i + 4 <= buff.length) {
|
||||
res += BigInt(buff.readUInt32LE(i)) << BigInt( i*8);
|
||||
res += BigInt(buffV.getUint32(i, true)) << BigInt( i*8);
|
||||
i += 4;
|
||||
} else if (i + 4 <= buff.length) {
|
||||
res += BigInt(buff.readUInt16LE(i)) << BigInt( i*8);
|
||||
res += BigInt(buffV.getUint16(i, true)) << BigInt( i*8);
|
||||
i += 2;
|
||||
} else {
|
||||
res += BigInt(buff.readUInt8(i)) << BigInt( i*8);
|
||||
res += BigInt(buffV.getUint8(i, true)) << BigInt( i*8);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.leInt2Buff = function leInt2Buff(n, len) {
|
||||
export function leInt2Buff(n, len) {
|
||||
let r = n;
|
||||
if (typeof len === "undefined") {
|
||||
len = Math.floor((Scalar.bitLength(n) - 1) / 8) +1;
|
||||
if (len==0) len = 1;
|
||||
}
|
||||
const buff = Buffer.alloc(len);
|
||||
const buff = new Uint8Array(len);
|
||||
const buffV = new DataView(buff.buffer);
|
||||
let o = 0;
|
||||
while (o < len) {
|
||||
if (o+4 <= len) {
|
||||
buff.writeUInt32LE(Number(r & 0xFFFFFFFFn), o );
|
||||
buffV.setUint32(o, Number(r & 0xFFFFFFFFn), true );
|
||||
o += 4;
|
||||
r = r >> 32n;
|
||||
} else if (o+2 <= len) {
|
||||
buff.writeUInt16LE(Number(r & 0xFFFFn), o );
|
||||
buff.setUint16(Number(o, r & 0xFFFFn), true );
|
||||
o += 2;
|
||||
r = r >> 16n;
|
||||
} else {
|
||||
buff.writeUInt8(Number(r & 0xFFn), o );
|
||||
buff.setUint8(Number(o, r & 0xFFn), true );
|
||||
o += 1;
|
||||
r = r >> 8n;
|
||||
}
|
||||
}
|
||||
assert(r == 0n);
|
||||
if (r) {
|
||||
throw new Error("Number does not fit in this length");
|
||||
}
|
||||
return buff;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
|
||||
|
||||
const assert = require("assert");
|
||||
const Scalar = require("./scalar");
|
||||
const utils = require("./utils");
|
||||
const buildBatchConvert = require("./engine_batchconvert");
|
||||
import * as Scalar from "./scalar.js";
|
||||
import buildBatchConvert from "./engine_batchconvert.js";
|
||||
|
||||
class WasmCurve {
|
||||
export default class WasmCurve {
|
||||
|
||||
constructor(tm, prefix, F, pGen, pGb, cofactor) {
|
||||
this.tm = tm;
|
||||
@@ -77,7 +75,7 @@ class WasmCurve {
|
||||
} else if (b.byteLength == this.F.n8*2) {
|
||||
return this.op2("_addMixed", a, b);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
if (b.byteLength == this.F.n8*3) {
|
||||
@@ -85,10 +83,10 @@ class WasmCurve {
|
||||
} else if (b.byteLength == this.F.n8*2) {
|
||||
return this.op2("_addAffine", a, b);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +97,7 @@ class WasmCurve {
|
||||
} else if (b.byteLength == this.F.n8*2) {
|
||||
return this.op2("_subMixed", a, b);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
if (b.byteLength == this.F.n8*3) {
|
||||
@@ -107,10 +105,10 @@ class WasmCurve {
|
||||
} else if (b.byteLength == this.F.n8*2) {
|
||||
return this.op2("_subAffine", a, b);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +118,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
return this.op1Affine("_negAffine", a);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +128,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
return this.op1("_doubleAffine", a);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +138,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
return this.op1Bool("_isZeroAffine", a);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +152,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
fnName = this.prefix + "_timesScalarAffine";
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
this.tm.setBuff(this.pOp1, a);
|
||||
this.tm.setBuff(this.pOp2, s);
|
||||
@@ -169,7 +167,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
fnName = this.prefix + "_timesFrAffine";
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
this.tm.setBuff(this.pOp1, a);
|
||||
this.tm.setBuff(this.pOp2, s);
|
||||
@@ -184,7 +182,7 @@ class WasmCurve {
|
||||
} else if (b.byteLength == this.F.n8*2) {
|
||||
return this.op2bool("_eqMixed", a, b);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
if (b.byteLength == this.F.n8*3) {
|
||||
@@ -192,10 +190,10 @@ class WasmCurve {
|
||||
} else if (b.byteLength == this.F.n8*2) {
|
||||
return this.op2bool("_eqAffine", a, b);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +203,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
return a;
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +213,7 @@ class WasmCurve {
|
||||
} else if (a.byteLength == this.F.n8*2) {
|
||||
return this.op1("_toJacobian", a);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +222,7 @@ class WasmCurve {
|
||||
if (a.byteLength == this.F.n8*3) {
|
||||
this.tm.instance.exports[this.prefix + "_toAffine"](this.pOp1, this.pOp1);
|
||||
} else if (a.byteLength != this.F.n8*2) {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
this.tm.instance.exports[this.prefix + "_LEMtoU"](this.pOp1, this.pOp1);
|
||||
const res = this.tm.getBuff(this.pOp1, this.F.n8*2);
|
||||
@@ -238,6 +236,25 @@ class WasmCurve {
|
||||
return this.tm.getBuff(this.pOp1, this.F.n8*2);
|
||||
}
|
||||
|
||||
toRprCompressed(arr, offset, a) {
|
||||
this.tm.setBuff(this.pOp1, a);
|
||||
if (a.byteLength == this.F.n8*3) {
|
||||
this.tm.instance.exports[this.prefix + "_toAffine"](this.pOp1, this.pOp1);
|
||||
} else if (a.byteLength != this.F.n8*2) {
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
this.tm.instance.exports[this.prefix + "_LEMtoC"](this.pOp1, this.pOp1);
|
||||
const res = this.tm.getBuff(this.pOp1, this.F.n8);
|
||||
arr.set(res, offset);
|
||||
}
|
||||
|
||||
fromRprCompressed(arr, offset) {
|
||||
const buff = arr.slice(offset, offset + this.F.n8);
|
||||
this.tm.setBuff(this.pOp1, buff);
|
||||
this.tm.instance.exports[this.prefix + "_CtoLEM"](this.pOp1, this.pOp2);
|
||||
return this.tm.getBuff(this.pOp2, this.F.n8*2);
|
||||
}
|
||||
|
||||
toUncompressed(a) {
|
||||
const buff = new Uint8Array(this.F.n8*2);
|
||||
this.toRprUncompressed(buff, 0, a);
|
||||
@@ -254,7 +271,7 @@ class WasmCurve {
|
||||
const res = this.tm.getBuff(this.pOp1, this.F.n8*2);
|
||||
arr.set(res, offset);
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +291,7 @@ class WasmCurve {
|
||||
const y = this.F.toString(a.slice(this.F.n8), radix);
|
||||
return `[ ${x}, ${y} ]`;
|
||||
} else {
|
||||
assert(false, "invalid point size");
|
||||
throw new Error("invalid point size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,8 +369,11 @@ class WasmCurve {
|
||||
}
|
||||
}
|
||||
|
||||
e(a) {
|
||||
if (a instanceof Uint8Array) return a;
|
||||
return this.fromObject(a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = WasmCurve;
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
|
||||
const assert = require("assert");
|
||||
const Scalar = require("./scalar");
|
||||
const utils = require("./utils");
|
||||
const {getThreadRng} = require("./random");
|
||||
const buildBatchConvert = require("./engine_batchconvert");
|
||||
import * as Scalar from "./scalar.js";
|
||||
import * as utils from "./utils.js";
|
||||
import { getThreadRng } from "./random.js";
|
||||
import buildBatchConvert from "./engine_batchconvert.js";
|
||||
|
||||
|
||||
class WasmField1 {
|
||||
export default class WasmField1 {
|
||||
|
||||
constructor(tm, prefix, n8, p) {
|
||||
this.tm = tm;
|
||||
@@ -26,9 +25,9 @@ class WasmField1 {
|
||||
this.pOp2 = tm.alloc(n8);
|
||||
this.pOp3 = tm.alloc(n8);
|
||||
this.tm.instance.exports[prefix + "_zero"](this.pOp1);
|
||||
this.zero = this.getBuff(this.pOp1);
|
||||
this.zero = this.tm.getBuff(this.pOp1, this.n8);
|
||||
this.tm.instance.exports[prefix + "_one"](this.pOp1);
|
||||
this.one = this.getBuff(this.pOp1);
|
||||
this.one = this.tm.getBuff(this.pOp1, this.n8);
|
||||
|
||||
this.negone = this.neg(this.one);
|
||||
this.two = this.add(this.one, this.one);
|
||||
@@ -36,7 +35,9 @@ class WasmField1 {
|
||||
this.n64 = Math.floor(n8/8);
|
||||
this.n32 = Math.floor(n8/4);
|
||||
|
||||
assert(this.n64*8 == this.n8, "n8 must be a multiple of 8");
|
||||
if(this.n64*8 != this.n8) {
|
||||
throw new Error("n8 must be a multiple of 8");
|
||||
}
|
||||
|
||||
this.half = Scalar.shiftRight(this.p, Scalar.one);
|
||||
this.nqr = this.two;
|
||||
@@ -62,42 +63,36 @@ class WasmField1 {
|
||||
this.w[i] = this.square(this.w[i+1]);
|
||||
}
|
||||
|
||||
assert(this.eq(this.w[0], this.one));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
getBuff(p) {
|
||||
return this.tm.u8.slice(p, p+this.n8);
|
||||
}
|
||||
|
||||
setBuff(p, buff) {
|
||||
return this.tm.u8.set(buff, p);
|
||||
}
|
||||
|
||||
op2(opName, a, b) {
|
||||
this.setBuff(this.pOp1, a);
|
||||
this.setBuff(this.pOp2, 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.getBuff(this.pOp3);
|
||||
return this.tm.getBuff(this.pOp3, this.n8);
|
||||
}
|
||||
|
||||
op2Bool(opName, a, b) {
|
||||
this.setBuff(this.pOp1, a);
|
||||
this.setBuff(this.pOp2, 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.setBuff(this.pOp1, a);
|
||||
this.tm.setBuff(this.pOp1, a);
|
||||
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
||||
return this.getBuff(this.pOp3);
|
||||
return this.tm.getBuff(this.pOp3, this.n8);
|
||||
}
|
||||
|
||||
op1Bool(opName, a) {
|
||||
this.setBuff(this.pOp1, a);
|
||||
this.tm.setBuff(this.pOp1, a);
|
||||
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
||||
}
|
||||
|
||||
@@ -138,6 +133,14 @@ class WasmField1 {
|
||||
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);
|
||||
}
|
||||
@@ -227,5 +230,4 @@ class WasmField1 {
|
||||
|
||||
}
|
||||
|
||||
module.exports = WasmField1;
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { getThreadRng } from "./random.js";
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
|
||||
const assert = require("assert");
|
||||
const {getThreadRng} = require("./random");
|
||||
const Scalar = require("./scalar");
|
||||
|
||||
|
||||
class WasmField2 {
|
||||
export default class WasmField2 {
|
||||
|
||||
constructor(tm, prefix, F) {
|
||||
this.tm = tm;
|
||||
@@ -95,6 +92,14 @@ class WasmField2 {
|
||||
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);
|
||||
}
|
||||
@@ -127,7 +132,7 @@ class WasmField2 {
|
||||
res.set(c2, this.F.n8*2);
|
||||
return res;
|
||||
} else {
|
||||
assert(false, "invalid F2");
|
||||
throw new Error("invalid F2");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,5 +172,3 @@ class WasmField2 {
|
||||
|
||||
}
|
||||
|
||||
module.exports = WasmField2;
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
|
||||
|
||||
const assert = require("assert");
|
||||
const {getThreadRng} = require("./random");
|
||||
const Scalar = require("./scalar");
|
||||
import { getThreadRng } from "./random.js";
|
||||
import * as Scalar from "./scalar.js";
|
||||
|
||||
|
||||
class WasmField3 {
|
||||
export default class WasmField3 {
|
||||
|
||||
constructor(tm, prefix, F) {
|
||||
this.tm = tm;
|
||||
@@ -96,6 +95,14 @@ class WasmField3 {
|
||||
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);
|
||||
}
|
||||
@@ -130,7 +137,7 @@ class WasmField3 {
|
||||
res.set(c3, this.F.n8*2);
|
||||
return res;
|
||||
} else {
|
||||
assert(false, "invalid F3");
|
||||
throw new Error("invalid F3");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +171,7 @@ class WasmField3 {
|
||||
}
|
||||
|
||||
fromObject(a) {
|
||||
const buff = new Uint8Array(this.F.n8*2);
|
||||
const buff = new Uint8Array(this.F.n8*3);
|
||||
const b1 = this.F.fromObject(a[0]);
|
||||
const b2 = this.F.fromObject(a[1]);
|
||||
const b3 = this.F.fromObject(a[2]);
|
||||
@@ -176,5 +183,4 @@ class WasmField3 {
|
||||
|
||||
}
|
||||
|
||||
module.exports = WasmField3;
|
||||
|
||||
|
||||
200
test/algebra.js
200
test/algebra.js
@@ -17,16 +17,24 @@
|
||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const chai = require("chai");
|
||||
import chai from "chai";
|
||||
|
||||
const Scalar = require("../src/scalar.js");
|
||||
const bn128 = require("../src/bn128.js");
|
||||
const F1Field = require("../src/f1field.js");
|
||||
import * as Scalar from "../src/scalar.js";
|
||||
import buildBn128 from "../src/bn128.js";
|
||||
import F1Field from "../src/f1field.js";
|
||||
|
||||
const assert = chai.assert;
|
||||
|
||||
|
||||
describe("F1 testing", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
it("Should compute euclidean", () => {
|
||||
const F = new F1Field(Scalar.fromString("7"));
|
||||
const res = F.inv(F.e(4));
|
||||
@@ -65,8 +73,16 @@ describe("F1 testing", () => {
|
||||
});
|
||||
|
||||
describe("Curve G1 Test", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
it("r*one == 0", () => {
|
||||
const res = bn128.G1.mulScalar(bn128.G1.g, bn128.r);
|
||||
const res = bn128.G1.timesScalar(bn128.G1.g, bn128.r);
|
||||
|
||||
assert(bn128.G1.eq(res, bn128.G1.zero), "G1 does not have range r");
|
||||
});
|
||||
@@ -76,20 +92,28 @@ describe("Curve G1 Test", () => {
|
||||
const r1 = bn128.Fr.e(33);
|
||||
const r2 = bn128.Fr.e(44);
|
||||
|
||||
const gr1 = bn128.G1.mulScalar(bn128.G1.g, r1);
|
||||
const gr2 = bn128.G1.mulScalar(bn128.G1.g, r2);
|
||||
const gr1 = bn128.G1.timesFr(bn128.G1.g, r1);
|
||||
const gr2 = bn128.G1.timesFr(bn128.G1.g, r2);
|
||||
|
||||
const grsum1 = bn128.G1.add(gr1, gr2);
|
||||
|
||||
const grsum2 = bn128.G1.mulScalar(bn128.G1.g, bn128.Fr.add(r1, r2));
|
||||
const grsum2 = bn128.G1.timesFr(bn128.G1.g, bn128.Fr.add(r1, r2));
|
||||
|
||||
assert(bn128.G1.eq(grsum1, grsum2));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Curve G2 Test", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
it ("r*one == 0", () => {
|
||||
const res = bn128.G2.mulScalar(bn128.G2.g, bn128.r);
|
||||
const res = bn128.G2.timesScalar(bn128.G2.g, bn128.r);
|
||||
|
||||
assert(bn128.G2.eq(res, bn128.G2.zero), "G2 does not have range r");
|
||||
});
|
||||
@@ -98,12 +122,12 @@ describe("Curve G2 Test", () => {
|
||||
const r1 = bn128.Fr.e(33);
|
||||
const r2 = bn128.Fr.e(44);
|
||||
|
||||
const gr1 = bn128.G2.mulScalar(bn128.G2.g, r1);
|
||||
const gr2 = bn128.G2.mulScalar(bn128.G2.g, r2);
|
||||
const gr1 = bn128.G2.timesFr(bn128.G2.g, r1);
|
||||
const gr2 = bn128.G2.timesFr(bn128.G2.g, r2);
|
||||
|
||||
const grsum1 = bn128.G2.add(gr1, gr2);
|
||||
|
||||
const grsum2 = bn128.G2.mulScalar(bn128.G2.g, bn128.Fr.add(r1, r2));
|
||||
const grsum2 = bn128.G2.timesFr(bn128.G2.g, bn128.Fr.add(r1, r2));
|
||||
|
||||
/*
|
||||
console.log(G2.toString(grsum1));
|
||||
@@ -115,20 +139,26 @@ describe("Curve G2 Test", () => {
|
||||
});
|
||||
|
||||
describe("F6 testing", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
it("Should multiply and divide in F6", () => {
|
||||
|
||||
const a =
|
||||
[
|
||||
[bn128.F1.e("1"), bn128.F1.e("2")],
|
||||
[bn128.F1.e("3"), bn128.F1.e("4")],
|
||||
[bn128.F1.e("5"), bn128.F1.e("6")]
|
||||
];
|
||||
const b =
|
||||
[
|
||||
[bn128.F1.e("12"), bn128.F1.e("11")],
|
||||
[bn128.F1.e("10"), bn128.F1.e("9")],
|
||||
[bn128.F1.e("8"), bn128.F1.e("7")]
|
||||
];
|
||||
const a = bn128.F6.fromObject([
|
||||
[Scalar.e("1"), Scalar.e("2")],
|
||||
[Scalar.e("3"), Scalar.e("4")],
|
||||
[Scalar.e("5"), Scalar.e("6")]
|
||||
]);
|
||||
const b = bn128.F6.fromObject([
|
||||
[Scalar.e("12"), Scalar.e("11")],
|
||||
[Scalar.e("10"), Scalar.e("9")],
|
||||
[Scalar.e("8"), Scalar.e("7")]
|
||||
]);
|
||||
const c = bn128.F6.mul(a,b);
|
||||
const d = bn128.F6.div(c,b);
|
||||
|
||||
@@ -137,33 +167,39 @@ describe("F6 testing", () => {
|
||||
});
|
||||
|
||||
describe("F12 testing", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
it("Should multiply and divide in F12", () => {
|
||||
const a =
|
||||
[
|
||||
const a = bn128.Gt.fromObject([
|
||||
[
|
||||
[bn128.F1.e("1"), bn128.F1.e("2")],
|
||||
[bn128.F1.e("3"), bn128.F1.e("4")],
|
||||
[bn128.F1.e("5"), bn128.F1.e("6")]
|
||||
[Scalar.e("1"), Scalar.e("2")],
|
||||
[Scalar.e("3"), Scalar.e("4")],
|
||||
[Scalar.e("5"), Scalar.e("6")]
|
||||
],
|
||||
[
|
||||
[bn128.F1.e("7"), bn128.F1.e("8")],
|
||||
[bn128.F1.e("9"), bn128.F1.e("10")],
|
||||
[bn128.F1.e("11"), bn128.F1.e("12")]
|
||||
[Scalar.e("7"), Scalar.e("8")],
|
||||
[Scalar.e("9"), Scalar.e("10")],
|
||||
[Scalar.e("11"), Scalar.e("12")]
|
||||
]
|
||||
];
|
||||
const b =
|
||||
[
|
||||
]);
|
||||
const b = bn128.Gt.fromObject([
|
||||
[
|
||||
[bn128.F1.e("12"), bn128.F1.e("11")],
|
||||
[bn128.F1.e("10"), bn128.F1.e("9")],
|
||||
[bn128.F1.e("8"), bn128.F1.e("7")]
|
||||
[Scalar.e("12"), Scalar.e("11")],
|
||||
[Scalar.e("10"), Scalar.e("9")],
|
||||
[Scalar.e("8"), Scalar.e("7")]
|
||||
],
|
||||
[
|
||||
[bn128.F1.e("6"), bn128.F1.e("5")],
|
||||
[bn128.F1.e("4"), bn128.F1.e("3")],
|
||||
[bn128.F1.e("2"), bn128.F1.e("1")]
|
||||
[Scalar.e("6"), Scalar.e("5")],
|
||||
[Scalar.e("4"), Scalar.e("3")],
|
||||
[Scalar.e("2"), Scalar.e("1")]
|
||||
]
|
||||
];
|
||||
]);
|
||||
const c = bn128.F12.mul(a,b);
|
||||
const d = bn128.F12.div(c,b);
|
||||
|
||||
@@ -172,7 +208,15 @@ describe("F12 testing", () => {
|
||||
});
|
||||
|
||||
describe("Pairing", () => {
|
||||
/*
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
/*
|
||||
it("Should match pairing", () => {
|
||||
for (let i=0; i<1; i++) {
|
||||
const bn128 = new BN128();
|
||||
@@ -183,10 +227,10 @@ describe("Pairing", () => {
|
||||
const g1b = bn128.G1.mulScalar(bn128.G1.g, 30);
|
||||
const g2b = bn128.G2.mulScalar(bn128.G2.g, 25);
|
||||
|
||||
const pre1a = bn128.precomputeG1(g1a);
|
||||
const pre2a = bn128.precomputeG2(g2a);
|
||||
const pre1b = bn128.precomputeG1(g1b);
|
||||
const pre2b = bn128.precomputeG2(g2b);
|
||||
const pre1a = bn128.prepareG1(g1a);
|
||||
const pre2a = bn128.prepareG2(g2a);
|
||||
const pre1b = bn128.prepareG1(g1b);
|
||||
const pre2b = bn128.prepareG2(g2b);
|
||||
|
||||
const r1 = bn128.millerLoop(pre1a, pre2a);
|
||||
const r2 = bn128.millerLoop(pre1b, pre2b);
|
||||
@@ -198,19 +242,19 @@ describe("Pairing", () => {
|
||||
assert(bn128.F12.eq(res, bn128.F12.one));
|
||||
}
|
||||
}).timeout(10000);
|
||||
*/
|
||||
*/
|
||||
it("Should generate another pairing pairing", () => {
|
||||
for (let i=0; i<1; i++) {
|
||||
const g1a = bn128.G1.mulScalar(bn128.G1.g, 10);
|
||||
const g2a = bn128.G2.mulScalar(bn128.G2.g, 1);
|
||||
const g1a = bn128.G1.timesScalar(bn128.G1.g, 10);
|
||||
const g2a = bn128.G2.timesScalar(bn128.G2.g, 1);
|
||||
|
||||
const g1b = bn128.G1.mulScalar(bn128.G1.g, 1);
|
||||
const g2b = bn128.G2.mulScalar(bn128.G2.g, 10);
|
||||
const g1b = bn128.G1.timesScalar(bn128.G1.g, 1);
|
||||
const g2b = bn128.G2.timesScalar(bn128.G2.g, 10);
|
||||
|
||||
const pre1a = bn128.precomputeG1(g1a);
|
||||
const pre2a = bn128.precomputeG2(g2a);
|
||||
const pre1b = bn128.precomputeG1(g1b);
|
||||
const pre2b = bn128.precomputeG2(g2b);
|
||||
const pre1a = bn128.prepareG1(g1a);
|
||||
const pre2a = bn128.prepareG2(g2a);
|
||||
const pre1b = bn128.prepareG1(g1b);
|
||||
const pre2b = bn128.prepareG2(g2b);
|
||||
|
||||
const r1 = bn128.millerLoop(pre1a, pre2a);
|
||||
const r2 = bn128.finalExponentiation(r1);
|
||||
@@ -219,46 +263,62 @@ describe("Pairing", () => {
|
||||
|
||||
const r4 = bn128.finalExponentiation(r3);
|
||||
|
||||
|
||||
/*
|
||||
console.log("ML1: " ,bn128.F12.toString(r1));
|
||||
console.log("FE1: " ,bn128.F12.toString(r2));
|
||||
console.log("ML2: " ,bn128.F12.toString(r3));
|
||||
console.log("FE2: " ,bn128.F12.toString(r4));
|
||||
*/
|
||||
|
||||
assert(bn128.F12.eq(r2, r4));
|
||||
|
||||
|
||||
/* const r2 = bn128.millerLoop(pre1b, pre2b);
|
||||
/*
|
||||
const r2 = bn128.millerLoop(pre1b, pre2b);
|
||||
|
||||
const rbe = bn128.F12.mul(r1, bn128.F12.inverse(r2));
|
||||
|
||||
const res = bn128.finalExponentiation(rbe);
|
||||
|
||||
assert(bn128.F12.eq(res, bn128.F12.one)); */
|
||||
assert(bn128.F12.eq(res, bn128.F12.one));
|
||||
*/
|
||||
}
|
||||
}).timeout(10000);
|
||||
it("Should test rpr of F2", () => {
|
||||
const P1 = [
|
||||
});
|
||||
|
||||
describe("Compressed Form", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
it("Should test rpr of G2", () => {
|
||||
const P1 = bn128.G2.fromObject([
|
||||
[
|
||||
bn128.F1.e("1b2327ce7815d3358fe89fd8e5695305ed23682db29569f549ab8f48cae1f1c4",16),
|
||||
bn128.F1.e("1ed41ca6b3edc06237af648f845c270ff83bcde333f17863c1b71a43b271b46d",16)
|
||||
Scalar.e("1b2327ce7815d3358fe89fd8e5695305ed23682db29569f549ab8f48cae1f1c4",16),
|
||||
Scalar.e("1ed41ca6b3edc06237af648f845c270ff83bcde333f17863c1b71a43b271b46d",16)
|
||||
],
|
||||
[
|
||||
bn128.F1.e("122057912ab892abcf2e729f0f342baea3fe1b484840eb97c7d78cd7530f4ab5",16),
|
||||
bn128.F1.e("2cb317fd40d56eeb17b0c1ff9443661a42ec00cea060012873b3f643f1a5bff8",16)
|
||||
Scalar.e("122057912ab892abcf2e729f0f342baea3fe1b484840eb97c7d78cd7530f4ab5",16),
|
||||
Scalar.e("2cb317fd40d56eeb17b0c1ff9443661a42ec00cea060012873b3f643f1a5bff8",16)
|
||||
],
|
||||
[
|
||||
bn128.F1.one,
|
||||
bn128.F1.zero
|
||||
Scalar.one,
|
||||
Scalar.zero
|
||||
]
|
||||
];
|
||||
]);
|
||||
const buff = new Uint8Array(64);
|
||||
bn128.G2.toRprCompressed(buff, 0, P1);
|
||||
|
||||
const P2 = bn128.G2.fromRprCompressed(buff, 0);
|
||||
|
||||
console.log(P1[1][0].toString(16));
|
||||
console.log(P2[1][0].toString(16));
|
||||
/*
|
||||
console.log(bn128.G2.toString(P1, 16));
|
||||
console.log(bn128.G2.toString(P2, 16));
|
||||
*/
|
||||
|
||||
assert(bn128.G2.eq(P1,P2));
|
||||
}).timeout(10000);
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
const assert = require("assert");
|
||||
import assert from "assert";
|
||||
import buildBn128 from "../src/bn128.js";
|
||||
|
||||
describe("FFT in G1", async function () {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
describe("bn128 tester", async function () {
|
||||
this.timeout(100000);
|
||||
|
||||
|
||||
it("It shoud do an inverse FFT in G1", async () => {
|
||||
const bn128 = require("../index").bn128;
|
||||
const Fr = bn128.Fr;
|
||||
const G1 = bn128.G1;
|
||||
|
||||
@@ -13,21 +21,19 @@ describe("bn128 tester", async function () {
|
||||
for (let i=0; i<8; i++) a[i] = Fr.e(i+1);
|
||||
|
||||
const aG_expected = [];
|
||||
for (let i=0; i<8; i++) aG_expected[i] = G1.mulScalar(G1.g, a[i]);
|
||||
for (let i=0; i<8; i++) aG_expected[i] = G1.timesFr(G1.g, a[i]);
|
||||
|
||||
const A = await bn128.PFr.fft(a);
|
||||
const A = await bn128.Fr.fft(a);
|
||||
|
||||
|
||||
const AG = [];
|
||||
for (let i=0; i<8; i++) AG[i] = G1.mulScalar(G1.g, A[i]);
|
||||
for (let i=0; i<8; i++) AG[i] = G1.timesFr(G1.g, A[i]);
|
||||
|
||||
const aG_calculated = await G1.ifft(AG);
|
||||
const aG_calculated = await G1.ifft(AG, "jacobian", "jacobian");
|
||||
|
||||
for (let i=0; i<8; i++) {
|
||||
assert(G1.eq(aG_calculated[i], aG_expected[i]));
|
||||
}
|
||||
|
||||
bn128.engine.terminate();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const chai = require("chai");
|
||||
import chai from "chai";
|
||||
|
||||
const Scalar = require("../src/scalar");
|
||||
const PolField = require("../src/polfield.js");
|
||||
const ZqField = require("../src/f1field");
|
||||
import * as Scalar from "../src/scalar.js";
|
||||
import PolField from "../src/polfield.js";
|
||||
import ZqField from "../src/f1field.js";
|
||||
|
||||
const assert = chai.assert;
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const chai = require("chai");
|
||||
import chai from "chai";
|
||||
|
||||
const Scalar = require("../src/scalar.js");
|
||||
const ZqField = require("../src/f1field.js");
|
||||
const RatField = require("../src/ratfield.js");
|
||||
import * as Scalar from "../src/scalar.js";
|
||||
import ZqField from "../src/f1field.js";
|
||||
import RatField from "../src/ratfield.js";
|
||||
|
||||
const q = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const Z = new ZqField(q);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const assert = require("assert");
|
||||
import assert from "assert";
|
||||
|
||||
const ScalarN = require("../src/scalar_native.js");
|
||||
const ScalarB = require("../src/scalar_bigint.js");
|
||||
import * as ScalarN from "../src/scalar_native.js";
|
||||
import * as ScalarB from "../src/scalar_bigint.js";
|
||||
|
||||
describe("Basic scalar convertions", () => {
|
||||
it("Should convertion Native", () => {
|
||||
|
||||
24
test/sqrt.js
24
test/sqrt.js
@@ -17,16 +17,24 @@
|
||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const chai = require("chai");
|
||||
import chai from "chai";
|
||||
|
||||
const Scalar = require("../src/scalar.js");
|
||||
const bn128 = require("../src/bn128.js");
|
||||
const F1Field = require("../src/f1field.js");
|
||||
import * as Scalar from "../src/scalar.js";
|
||||
import buildBn128 from "../src/bn128.js";
|
||||
import F1Field from "../src/f1field.js";
|
||||
|
||||
const assert = chai.assert;
|
||||
|
||||
|
||||
describe("Sqrt testing", () => {
|
||||
let bn128;
|
||||
before( async() => {
|
||||
bn128 = await buildBn128();
|
||||
});
|
||||
after( async() => {
|
||||
bn128.terminate();
|
||||
});
|
||||
|
||||
/*
|
||||
it("Should compute sqrts", () => {
|
||||
const F = new F1Field(bn128.r);
|
||||
@@ -71,13 +79,13 @@ describe("Sqrt testing", () => {
|
||||
});
|
||||
it("Should compute sqrt m=2 p%4 = 3", () => {
|
||||
const F = bn128.F2;
|
||||
const e = Scalar.div(Scalar.pow(F.p, F.m), 2);
|
||||
const e = Scalar.div(Scalar.exp(F.F.p, F.m), 2);
|
||||
for (let i=0; i<100; i++) {
|
||||
const x2 = F.random();
|
||||
const x = F.sqrt(x2);
|
||||
if (x==null) {
|
||||
assert(F.eq( F.pow(x2, e), F.negone));
|
||||
if (!F.isSquare(x2)) {
|
||||
assert(F.eq( F.exp(x2, e), F.negone));
|
||||
} else {
|
||||
const x = F.sqrt(x2);
|
||||
assert(F.eq(F.square(x), x2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const assert = require("assert");
|
||||
import assert from "assert";
|
||||
|
||||
const ScalarN = require("../src/scalar_native.js");
|
||||
const ScalarB = require("../src/scalar_bigint.js");
|
||||
import * as ScalarN from "../src/scalar_native.js";
|
||||
import * as ScalarB from "../src/scalar_bigint.js";
|
||||
|
||||
const utilsN = require("../src/utils_native.js");
|
||||
const utilsB = require("../src/utils_bigint.js");
|
||||
import * as utilsN from "../src/utils_native.js";
|
||||
import * as utilsB from "../src/utils_bigint.js";
|
||||
|
||||
describe("Utils native", () => {
|
||||
const num = ScalarN.e(21888242871839275222246405745257275088614511777268538073601725287587578984328);
|
||||
@@ -12,21 +12,21 @@ describe("Utils native", () => {
|
||||
it("Should convert integer to buffer little-endian", () => {
|
||||
const buff = utilsN.leInt2Buff(num, 32);
|
||||
const numFromBuff = utilsN.leBuff2int(buff);
|
||||
|
||||
|
||||
assert(ScalarN.eq(num, numFromBuff), true);
|
||||
});
|
||||
|
||||
it("Should convert integer to buffer big-endian", () => {
|
||||
const buff = utilsN.beInt2Buff(num, 32);
|
||||
const numFromBuff = utilsN.beBuff2int(buff);
|
||||
|
||||
|
||||
assert(ScalarN.eq(num, numFromBuff), true);
|
||||
});
|
||||
|
||||
it("Should stringify bigInt", () => {
|
||||
const str = utilsN.stringifyBigInts(num);
|
||||
const numFromStr = utilsN.unstringifyBigInts(str);
|
||||
|
||||
|
||||
assert(ScalarN.eq(num, numFromStr), true);
|
||||
});
|
||||
});
|
||||
@@ -37,21 +37,21 @@ describe("Utils bigInt", () => {
|
||||
it("Should convert integer to buffer little-endian", () => {
|
||||
const buff = utilsB.leInt2Buff(num, 32);
|
||||
const numFromBuff = utilsB.leBuff2int(buff);
|
||||
|
||||
|
||||
assert(ScalarB.eq(num, numFromBuff), true);
|
||||
});
|
||||
|
||||
it("Should convert integer to buffer big-endian", () => {
|
||||
const buff = utilsB.beInt2Buff(num, 32);
|
||||
const numFromBuff = utilsB.beBuff2int(buff);
|
||||
|
||||
|
||||
assert(ScalarB.eq(num, numFromBuff), true);
|
||||
});
|
||||
|
||||
it("Should stringify bigInt", () => {
|
||||
const str = utilsB.stringifyBigInts(num);
|
||||
const numFromStr = utilsB.unstringifyBigInts(str);
|
||||
|
||||
|
||||
assert(ScalarB.eq(num, numFromStr), true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const ZqField = require("../src/f1field");
|
||||
const Scalar = require("../src/scalar");
|
||||
const assert = require("assert");
|
||||
import ZqField from "../src/f1field.js";
|
||||
import * as Scalar from "../src/scalar.js";
|
||||
import assert from "assert";
|
||||
|
||||
const q = Scalar.fromString("21888242871839275222246405745257275088696311157297823662689037894645226208583");
|
||||
const r = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
|
||||
Reference in New Issue
Block a user