mcl-wasm
Version:
mcl ; A portable and fast pairing-based cryptography library for Node.js by WebAssembly
1,043 lines (1,042 loc) • 31.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.recoverG2 = exports.recoverG1 = exports.recoverFr = exports.shareG2 = exports.shareG1 = exports.shareFr = exports.finalExp = exports.precomputedMillerLoop2mixed = exports.precomputedMillerLoop2 = exports.precomputedMillerLoop = exports.millerLoop = exports.pairing = exports.pow = exports.hashAndMapToG2 = exports.hashAndMapToG1 = exports.hashToFr = exports.dbl = exports.div = exports.normalizeVec = exports.invVec = exports.invVecInPlace = exports.mulVec = exports.mul = exports.sub = exports.add = exports.normalize = exports.squareRoot = exports.inv = exports.sqr = exports.neg = exports.PrecomputedG2 = exports.deserializeHexStrToGT = exports.GT = exports.deserializeHexStrToG2 = exports.G2 = exports.getBasePointG1 = exports.verifyOrderG2 = exports.verifyOrderG1 = exports.setMapToMode = exports.setETHserialization = exports.deserializeHexStrToG1 = exports.G1 = exports.deserializeHexStrToFp2 = exports.Fp2 = exports.deserializeHexStrToFp = exports.Fp = exports.deserializeHexStrToFr = exports.Fr = void 0;
const mcl_1 = require("./mcl");
const constants_1 = require("./constants");
const getRandomValues_1 = __importDefault(require("./getRandomValues"));
class Common {
constructor(size) {
this.a_ = new Uint32Array(size / 4);
}
deserializeHexStr(s) {
this.deserialize((0, mcl_1.fromHexStr)(s));
}
serializeToHexStr() {
return (0, mcl_1.toHexStr)(this.serialize());
}
dump(msg = '') {
console.log(msg + this.serializeToHexStr());
}
clear() {
this.a_.fill(0);
}
// copy to allocated memory
copyToMem(pos) {
mcl_1.mod.HEAP32.set(this.a_, pos / 4);
}
// copy from allocated memory
copyFromMem(pos) {
this.a_.set(mcl_1.mod.HEAP32.subarray(pos / 4, pos / 4 + this.a_.length));
}
// internal methods
/** @internal alloc new array */
_alloc() {
return mcl_1.mod._malloc(this.a_.length * 4);
}
/** @internal stack alloc new array */
_salloc() {
return mcl_1.mod.stackAlloc(this.a_.length * 4);
}
/** @internal alloc and copy a_ to mod.HEAP32[pos / 4] */
_allocAndCopy() {
const pos = this._alloc();
mcl_1.mod.HEAP32.set(this.a_, pos / 4);
return pos;
}
/** @internal stack alloc and copy a_ to mod.HEAP32[pos / 4] */
_sallocAndCopy() {
const pos = this._salloc();
mcl_1.mod.HEAP32.set(this.a_, pos / 4);
return pos;
}
/** @internal save pos to a_ */
_save(pos) {
this.a_.set(mcl_1.mod.HEAP32.subarray(pos / 4, pos / 4 + this.a_.length));
}
/** @internal save and free */
_saveAndFree(pos) {
this._save(pos);
mcl_1.mod._free(pos);
}
/** @internal set parameter */
_setter(func, ...params) {
const stack = mcl_1.mod.stackSave();
const pos = this._salloc();
const r = func(pos, ...params);
this._save(pos);
mcl_1.mod.stackRestore(stack);
if (r !== undefined && r !== 0)
throw new Error('_setter err');
}
/** @internal getter */
_getter(func, ...params) {
const stack = mcl_1.mod.stackSave();
const pos = this._sallocAndCopy();
const s = func(pos, ...params);
mcl_1.mod.stackRestore(stack);
return s;
}
/** @internal */
_isEqual(func, rhs) {
const stack = mcl_1.mod.stackSave();
const xPos = this._sallocAndCopy();
const yPos = rhs._sallocAndCopy();
const r = func(xPos, yPos);
mcl_1.mod.stackRestore(stack);
return r === 1;
}
/** @internal func(y, this) and return y */
_op1(func) {
const y = new this.constructor();
const stack = mcl_1.mod.stackSave();
const xPos = this._sallocAndCopy();
const yPos = y._salloc();
func(yPos, xPos);
y._save(yPos);
mcl_1.mod.stackRestore(stack);
return y;
}
/** @internal func(z, this, y) and return z */
_op2(func, y, Cstr = null) {
const z = Cstr ? new Cstr() : new this.constructor();
const stack = mcl_1.mod.stackSave();
const xPos = this._sallocAndCopy();
const yPos = y._sallocAndCopy();
const zPos = z._salloc();
func(zPos, xPos, yPos);
z._save(zPos);
mcl_1.mod.stackRestore(stack);
return z;
}
/** @internal r = func(y, this) and return (true, b) if r = true else (false, null) */
_squareRoot(func) {
const y = new this.constructor();
const stack = mcl_1.mod.stackSave();
const xPos = this._sallocAndCopy();
const yPos = y._salloc();
const r = func(yPos, xPos);
y._save(yPos);
mcl_1.mod.stackRestore(stack);
return r === 0 ? [true, y] : [false, null];
}
/** @internal devide Uint32Array a into n and chose the idx-th */
_getSubArray(idx, n) {
const d = this.a_.length / n;
// return new Uint32Array(this.a_.buffer, d * idx * 4, d) // err : return reference to the buffer
// correct : make new buffer and copy it
return new Uint32Array(new Uint32Array(this.a_.buffer, d * idx * 4, d));
}
/** @internal set array lhs to idx */
_setSubArray(lhs, idx, n) {
const d = this.a_.length / n;
this.a_.set(lhs.a_, d * idx);
}
}
class IntType extends Common {
}
const _cloneArray = (x) => {
const cstr = x.constructor;
const r = new cstr();
r.a_.set(x.a_);
return r;
};
class Fr extends IntType {
constructor() {
super(constants_1.MCLBN_FR_SIZE);
}
clone() { return _cloneArray(this); }
setInt(x) {
this._setter(mcl_1.mod._mclBnFr_setInt32, x);
}
deserialize(s) {
this._setter(mcl_1.mod.mclBnFr_deserialize, s);
}
serialize() {
return this._getter(mcl_1.mod.mclBnFr_serialize);
}
setStr(s, base = 0) {
this._setter(mcl_1.mod.mclBnFr_setStr, s, base);
}
getStr(base = 0) {
return this._getter(mcl_1.mod.mclBnFr_getStr, base);
}
isZero() {
return this._getter(mcl_1.mod._mclBnFr_isZero) === 1;
}
isOne() {
return this._getter(mcl_1.mod._mclBnFr_isOne) === 1;
}
isEqual(rhs) {
return this._isEqual(mcl_1.mod._mclBnFr_isEqual, rhs);
}
setLittleEndian(a) {
this._setter(mcl_1.mod.mclBnFr_setLittleEndian, a);
}
setLittleEndianMod(a) {
this._setter(mcl_1.mod.mclBnFr_setLittleEndianMod, a);
}
setBigEndianMod(a) {
this._setter(mcl_1.mod.mclBnFr_setBigEndianMod, a);
}
setByCSPRNG() {
const a = new Uint8Array(constants_1.MCLBN_FR_SIZE);
(0, getRandomValues_1.default)(a);
this.setLittleEndian(a);
}
setHashOf(s) {
this._setter(mcl_1.mod.mclBnFr_setHashOf, s);
}
}
exports.Fr = Fr;
const deserializeHexStrToFr = (s) => {
const r = new Fr();
r.deserializeHexStr(s);
return r;
};
exports.deserializeHexStrToFr = deserializeHexStrToFr;
class Fp extends IntType {
constructor() {
super(constants_1.MCLBN_FP_SIZE);
}
clone() { return _cloneArray(this); }
setInt(x) {
this._setter(mcl_1.mod._mclBnFp_setInt32, x);
}
deserialize(s) {
this._setter(mcl_1.mod.mclBnFp_deserialize, s);
}
serialize() {
return this._getter(mcl_1.mod.mclBnFp_serialize);
}
setStr(s, base = 0) {
this._setter(mcl_1.mod.mclBnFp_setStr, s, base);
}
getStr(base = 0) {
return this._getter(mcl_1.mod.mclBnFp_getStr, base);
}
isOne() {
return this._getter(mcl_1.mod._mclBnFp_isOne) === 1;
}
isZero() {
return this._getter(mcl_1.mod._mclBnFp_isZero) === 1;
}
isEqual(rhs) {
return this._isEqual(mcl_1.mod._mclBnFp_isEqual, rhs);
}
setLittleEndian(a) {
this._setter(mcl_1.mod.mclBnFp_setLittleEndian, a);
}
setLittleEndianMod(a) {
this._setter(mcl_1.mod.mclBnFp_setLittleEndianMod, a);
}
setBigEndianMod(a) {
this._setter(mcl_1.mod.mclBnFp_setBigEndianMod, a);
}
setByCSPRNG() {
const a = new Uint8Array(constants_1.MCLBN_FP_SIZE);
(0, getRandomValues_1.default)(a);
this.setLittleEndian(a);
}
setHashOf(s) {
this._setter(mcl_1.mod.mclBnFp_setHashOf, s);
}
mapToG1() {
const y = new G1();
const stack = mcl_1.mod.stackSave();
const xPos = this._sallocAndCopy();
const yPos = y._salloc();
mcl_1.mod._mclBnFp_mapToG1(yPos, xPos);
y._save(yPos);
mcl_1.mod.stackRestore(stack);
return y;
}
}
exports.Fp = Fp;
const deserializeHexStrToFp = (s) => {
const r = new Fp();
r.deserializeHexStr(s);
return r;
};
exports.deserializeHexStrToFp = deserializeHexStrToFp;
class Fp2 extends Common {
constructor() {
super(constants_1.MCLBN_FP_SIZE * 2);
}
clone() { return _cloneArray(this); }
setInt(x, y) {
const v = new Fp();
v.setInt(x);
this.set_a(v);
v.setInt(y);
this.set_b(v);
}
deserialize(s) {
this._setter(mcl_1.mod.mclBnFp2_deserialize, s);
}
serialize() {
return this._getter(mcl_1.mod.mclBnFp2_serialize);
}
getStr(base = 0) {
return this.get_a().getStr(base) + ' ' + this.get_b().getStr(base);
}
setStr(s, base = 0) {
const ss = s.split(' ');
if (ss.length !== 2)
throw new Error('bad str');
const v = new Fp();
v.setStr(ss[0], base);
this.set_a(v);
v.setStr(ss[1], base);
this.set_b(v);
}
isEqual(rhs) {
return this._isEqual(mcl_1.mod._mclBnFp2_isEqual, rhs);
}
isZero() {
return this._getter(mcl_1.mod._mclBnFp2_isZero) === 1;
}
isOne() {
return this._getter(mcl_1.mod._mclBnFp2_isOne) === 1;
}
setHashOf(s) {
throw new Error('Fp2.setHashOf is not supported');
}
/*
x = a + bi where a, b in Fp and i^2 = -1
*/
get_a() {
const r = new Fp();
r.a_ = this._getSubArray(0, 2);
return r;
}
get_b() {
const r = new Fp();
r.a_ = this._getSubArray(1, 2);
return r;
}
set_a(v) {
this._setSubArray(v, 0, 2);
}
set_b(v) {
this._setSubArray(v, 1, 2);
}
mapToG2() {
const y = new G2();
const stack = mcl_1.mod.stackSave();
const xPos = this._sallocAndCopy();
const yPos = y._salloc();
mcl_1.mod._mclBnFp2_mapToG2(yPos, xPos);
y._save(yPos);
mcl_1.mod.stackRestore(stack);
return y;
}
}
exports.Fp2 = Fp2;
const deserializeHexStrToFp2 = (s) => {
const r = new Fp2();
r.deserializeHexStr(s);
return r;
};
exports.deserializeHexStrToFp2 = deserializeHexStrToFp2;
class EllipticType extends Common {
}
class G1 extends EllipticType {
constructor() {
super(constants_1.MCLBN_G1_SIZE);
}
clone() { return _cloneArray(this); }
deserialize(s) {
this._setter(mcl_1.mod.mclBnG1_deserialize, s);
}
serialize() {
return this._getter(mcl_1.mod.mclBnG1_serialize);
}
setStr(s, base = 0) {
this._setter(mcl_1.mod.mclBnG1_setStr, s, base);
}
getStr(base = 0) {
return this._getter(mcl_1.mod.mclBnG1_getStr, base);
}
normalize() {
this.a_ = (0, exports.normalize)(this).a_;
}
getX() {
const r = new Fp();
r.a_ = this._getSubArray(0, 3);
return r;
}
getY() {
const r = new Fp();
r.a_ = this._getSubArray(1, 3);
return r;
}
getZ() {
const r = new Fp();
r.a_ = this._getSubArray(2, 3);
return r;
}
setX(v) {
this._setSubArray(v, 0, 3);
}
setY(v) {
this._setSubArray(v, 1, 3);
}
setZ(v) {
this._setSubArray(v, 2, 3);
}
isZero() {
return this._getter(mcl_1.mod._mclBnG1_isZero) === 1;
}
isValid() {
return this._getter(mcl_1.mod._mclBnG1_isValid) === 1;
}
isValidOrder() {
return this._getter(mcl_1.mod._mclBnG1_isValidOrder) === 1;
}
isEqual(rhs) {
return this._isEqual(mcl_1.mod._mclBnG1_isEqual, rhs);
}
setHashOf(s) {
this._setter(mcl_1.mod.mclBnG1_hashAndMapTo, s);
}
}
exports.G1 = G1;
const deserializeHexStrToG1 = (s) => {
const r = new G1();
r.deserializeHexStr(s);
return r;
};
exports.deserializeHexStrToG1 = deserializeHexStrToG1;
const setETHserialization = (ETHserialization) => {
mcl_1.mod._mclBn_setETHserialization(ETHserialization ? 1 : 0);
};
exports.setETHserialization = setETHserialization;
// mode = mcl.IRTF for Ethereum 2.0 spec
const setMapToMode = (mode) => {
mcl_1.mod._mclBn_setMapToMode(mode);
};
exports.setMapToMode = setMapToMode;
const verifyOrderG1 = (doVerify) => {
mcl_1.mod._mclBn_verifyOrderG1(doVerify ? 1 : 0);
};
exports.verifyOrderG1 = verifyOrderG1;
const verifyOrderG2 = (doVerify) => {
mcl_1.mod._mclBn_verifyOrderG2(doVerify ? 1 : 0);
};
exports.verifyOrderG2 = verifyOrderG2;
const getBasePointG1 = () => {
const x = new G1();
const stack = mcl_1.mod.stackSave();
const xPos = x._salloc();
mcl_1.mod._mclBnG1_getBasePoint(xPos);
x._save(xPos);
mcl_1.mod.stackRestore(stack);
if (x.isZero()) {
throw new Error('not supported for pairing curves');
}
return x;
};
exports.getBasePointG1 = getBasePointG1;
class G2 extends EllipticType {
constructor() {
super(constants_1.MCLBN_G2_SIZE);
}
clone() { return _cloneArray(this); }
deserialize(s) {
this._setter(mcl_1.mod.mclBnG2_deserialize, s);
}
serialize() {
return this._getter(mcl_1.mod.mclBnG2_serialize);
}
setStr(s, base = 0) {
this._setter(mcl_1.mod.mclBnG2_setStr, s, base);
}
getStr(base = 0) {
return this._getter(mcl_1.mod.mclBnG2_getStr, base);
}
normalize() {
this.a_ = (0, exports.normalize)(this).a_;
}
getX() {
const r = new Fp2();
r.a_ = this._getSubArray(0, 3);
return r;
}
getY() {
const r = new Fp2();
r.a_ = this._getSubArray(1, 3);
return r;
}
getZ() {
const r = new Fp2();
r.a_ = this._getSubArray(2, 3);
return r;
}
setX(v) {
this._setSubArray(v, 0, 3);
}
setY(v) {
this._setSubArray(v, 1, 3);
}
setZ(v) {
this._setSubArray(v, 2, 3);
}
isZero() {
return this._getter(mcl_1.mod._mclBnG2_isZero) === 1;
}
isValid() {
return this._getter(mcl_1.mod._mclBnG2_isValid) === 1;
}
isValidOrder() {
return this._getter(mcl_1.mod._mclBnG2_isValidOrder) === 1;
}
isEqual(rhs) {
return this._isEqual(mcl_1.mod._mclBnG2_isEqual, rhs);
}
setHashOf(s) {
this._setter(mcl_1.mod.mclBnG2_hashAndMapTo, s);
}
}
exports.G2 = G2;
const deserializeHexStrToG2 = (s) => {
const r = new G2();
r.deserializeHexStr(s);
return r;
};
exports.deserializeHexStrToG2 = deserializeHexStrToG2;
class GT extends Common {
constructor() {
super(constants_1.MCLBN_GT_SIZE);
}
clone() { return _cloneArray(this); }
setInt(x) {
this._setter(mcl_1.mod._mclBnGT_setInt32, x);
}
deserialize(s) {
this._setter(mcl_1.mod.mclBnGT_deserialize, s);
}
serialize() {
return this._getter(mcl_1.mod.mclBnGT_serialize);
}
setStr(s, base = 0) {
this._setter(mcl_1.mod.mclBnGT_setStr, s, base);
}
getStr(base = 0) {
return this._getter(mcl_1.mod.mclBnGT_getStr, base);
}
isZero() {
return this._getter(mcl_1.mod._mclBnGT_isZero) === 1;
}
isOne() {
return this._getter(mcl_1.mod._mclBnGT_isOne) === 1;
}
isEqual(rhs) {
return this._isEqual(mcl_1.mod._mclBnGT_isEqual, rhs);
}
setHashOf(s) {
throw new Error('GT.setHashOf is not supported');
}
}
exports.GT = GT;
const deserializeHexStrToGT = (s) => {
const r = new GT();
r.deserializeHexStr(s);
return r;
};
exports.deserializeHexStrToGT = deserializeHexStrToGT;
class PrecomputedG2 {
constructor(Q) {
if (!(Q instanceof G2))
throw new Error('PrecomputedG2:bad type');
const byteSize = mcl_1.mod._mclBn_getUint64NumToPrecompute() * 8;
this.p = mcl_1.mod._malloc(byteSize); // keep this address
const stack = mcl_1.mod.stackSave();
const Qpos = Q._sallocAndCopy();
mcl_1.mod._mclBn_precomputeG2(this.p, Qpos);
mcl_1.mod.stackRestore(stack);
}
/*
call destroy if PrecomputedG2 is not necessary
to avoid memory leak
*/
destroy() {
if (this.p != null)
mcl_1.mod._free(this.p);
this.p = null;
}
}
exports.PrecomputedG2 = PrecomputedG2;
const neg = (x) => {
if (x instanceof Fr) {
return x._op1(mcl_1.mod._mclBnFr_neg);
}
if (x instanceof Fp) {
return x._op1(mcl_1.mod._mclBnFp_neg);
}
if (x instanceof G1) {
return x._op1(mcl_1.mod._mclBnG1_neg);
}
if (x instanceof G2) {
return x._op1(mcl_1.mod._mclBnG2_neg);
}
if (x instanceof GT) {
return x._op1(mcl_1.mod._mclBnGT_neg);
}
if (x instanceof Fp2) {
return x._op1(mcl_1.mod._mclBnFp2_neg);
}
throw new Error('neg:bad type');
};
exports.neg = neg;
const sqr = (x) => {
if (x instanceof Fp) {
return x._op1(mcl_1.mod._mclBnFp_sqr);
}
if (x instanceof Fr) {
return x._op1(mcl_1.mod._mclBnFr_sqr);
}
if (x instanceof GT) {
return x._op1(mcl_1.mod._mclBnGT_sqr);
}
if (x instanceof Fp2) {
return x._op1(mcl_1.mod._mclBnFp2_sqr);
}
throw new Error('sqr:bad type');
};
exports.sqr = sqr;
const inv = (x) => {
if (x instanceof Fp) {
return x._op1(mcl_1.mod._mclBnFp_inv);
}
if (x instanceof Fr) {
return x._op1(mcl_1.mod._mclBnFr_inv);
}
if (x instanceof GT) {
return x._op1(mcl_1.mod._mclBnGT_inv);
}
if (x instanceof Fp2) {
return x._op1(mcl_1.mod._mclBnFp2_inv);
}
throw new Error('inv:bad type');
};
exports.inv = inv;
const squareRoot = (x) => {
if (x instanceof Fp) {
return x._squareRoot(mcl_1.mod._mclBnFp_squareRoot);
}
if (x instanceof Fr) {
return x._squareRoot(mcl_1.mod._mclBnFr_squareRoot);
}
if (x instanceof Fp2) {
return x._squareRoot(mcl_1.mod._mclBnFp2_squareRoot);
}
throw new Error('squareRoot:bad type');
};
exports.squareRoot = squareRoot;
const normalize = (x) => {
if (x instanceof G1) {
return x._op1(mcl_1.mod._mclBnG1_normalize);
}
if (x instanceof G2) {
return x._op1(mcl_1.mod._mclBnG2_normalize);
}
throw new Error('normalize:bad type');
};
exports.normalize = normalize;
const add = (x, y) => {
if (x.constructor !== y.constructor)
throw new Error('add:mismatch type');
if (x instanceof Fp) {
return x._op2(mcl_1.mod._mclBnFp_add, y);
}
if (x instanceof Fr) {
return x._op2(mcl_1.mod._mclBnFr_add, y);
}
if (x instanceof G1) {
return x._op2(mcl_1.mod._mclBnG1_add, y);
}
if (x instanceof G2) {
return x._op2(mcl_1.mod._mclBnG2_add, y);
}
if (x instanceof GT) {
return x._op2(mcl_1.mod._mclBnGT_add, y);
}
if (x instanceof Fp2) {
return x._op2(mcl_1.mod._mclBnFp2_add, y);
}
throw new Error('add:bad type');
};
exports.add = add;
const sub = (x, y) => {
if (x.constructor !== y.constructor)
throw new Error('sub:mismatch type');
if (x instanceof Fp) {
return x._op2(mcl_1.mod._mclBnFp_sub, y);
}
if (x instanceof Fr) {
return x._op2(mcl_1.mod._mclBnFr_sub, y);
}
if (x instanceof G1) {
return x._op2(mcl_1.mod._mclBnG1_sub, y);
}
if (x instanceof G2) {
return x._op2(mcl_1.mod._mclBnG2_sub, y);
}
if (x instanceof GT) {
return x._op2(mcl_1.mod._mclBnGT_sub, y);
}
if (x instanceof Fp2) {
return x._op2(mcl_1.mod._mclBnFp2_sub, y);
}
throw new Error('sub:bad type');
};
exports.sub = sub;
function mul(x, y) {
if (x instanceof Fp && y instanceof Fp) {
return x._op2(mcl_1.mod._mclBnFp_mul, y);
}
if (x instanceof Fr && y instanceof Fr) {
return x._op2(mcl_1.mod._mclBnFr_mul, y);
}
if (x instanceof G1 && y instanceof Fr) {
return x._op2(mcl_1.mod._mclBnG1_mul, y);
}
if (x instanceof G2 && y instanceof Fr) {
return x._op2(mcl_1.mod._mclBnG2_mul, y);
}
if (x instanceof GT && y instanceof GT) {
return x._op2(mcl_1.mod._mclBnGT_mul, y);
}
if (x instanceof Fp2 && y instanceof Fp2) {
return x._op2(mcl_1.mod._mclBnFp2_mul, y);
}
throw new Error('mul:mismatch type');
}
exports.mul = mul;
// stack alloc memory and copy v to it and return the position
function _sarrayAllocAndCopy(v) {
if (v.length === 0)
throw new Error('zero size array');
const size = v[0].a_.length * 4;
const pos = mcl_1.mod.stackAlloc(size * v.length);
for (let i = 0; i < v.length; i++) {
v[i].copyToMem(pos + size * i);
}
return pos;
}
// copy pos to v
function _saveArray(v, pos) {
if (v.length === 0)
throw new Error('zero size array');
const size = v[0].a_.length * 4;
for (let i = 0; i < v.length; i++) {
v[i].copyFromMem(pos + size * i);
}
}
const _mulVec = (func, xVec, yVec, Cstr) => {
const n = xVec.length;
const z = new Cstr();
const stack = mcl_1.mod.stackSave();
const zPos = z._salloc();
const xPos = _sarrayAllocAndCopy(xVec);
const yPos = _sarrayAllocAndCopy(yVec);
func(zPos, xPos, yPos, n);
z._save(zPos);
mcl_1.mod.stackRestore(stack);
return z;
};
/*
sum G1 * Fr ; scalar mul
sum G2 * Fr ; scalar mul
*/
const mulVec = (xVec, yVec) => {
const n = xVec.length;
if (n === 0)
throw new Error('mulVec:zero array');
if (n !== yVec.length)
throw new Error(`err _mulVec bad length ${n}, ${yVec.length}`);
if (xVec[0] instanceof G1 && yVec[0] instanceof Fr) {
return _mulVec(mcl_1.mod._mclBnG1_mulVec, xVec, yVec, G1);
}
if (xVec[0] instanceof G2 && yVec[0] instanceof Fr) {
return _mulVec(mcl_1.mod._mclBnG2_mulVec, xVec, yVec, G2);
}
throw new Error('mulVec:mismatch type');
};
exports.mulVec = mulVec;
// wrap invVec and normalizeVec API
const _invVec = (func, yVec, xVec) => {
const n = xVec.length;
const stack = mcl_1.mod.stackSave();
const xPos = _sarrayAllocAndCopy(xVec);
func(xPos, xPos, n);
_saveArray(yVec, xPos);
mcl_1.mod.stackRestore(stack);
};
const invVecInPlace = (xVec) => {
const n = xVec.length;
if (n === 0)
return;
if (xVec[0] instanceof Fr) {
_invVec(mcl_1.mod._mclBnFr_invVec, xVec, xVec);
return;
}
if (xVec[0] instanceof Fp) {
_invVec(mcl_1.mod._mclBnFp_invVec, xVec, xVec);
return;
}
throw new Error('invVec: bad type');
};
exports.invVecInPlace = invVecInPlace;
const invVec = (xVec) => {
const n = xVec.length;
if (n === 0)
return [];
const cstr = xVec[0].constructor;
const yVec = Array.from({ length: n }, _ => new cstr());
if (xVec[0] instanceof Fr) {
_invVec(mcl_1.mod._mclBnFr_invVec, yVec, xVec);
return yVec;
}
if (xVec[0] instanceof Fp) {
_invVec(mcl_1.mod._mclBnFp_invVec, yVec, xVec);
return yVec;
}
throw new Error('invVec: bad type');
};
exports.invVec = invVec;
// faster than normalizing each one individually
// inplace only
const normalizeVec = (xVec) => {
const n = xVec.length;
if (n === 0)
return;
if (xVec[0] instanceof G1) {
_invVec(mcl_1.mod._mclBnG1_normalizeVec, xVec, xVec);
return;
}
if (xVec[0] instanceof G2) {
_invVec(mcl_1.mod._mclBnG2_normalizeVec, xVec, xVec);
return;
}
throw new Error('normalizeVec: bad type');
};
exports.normalizeVec = normalizeVec;
function div(x, y) {
if (x.constructor !== y.constructor)
throw new Error('div:mismatch type');
if (x instanceof Fp) {
return x._op2(mcl_1.mod._mclBnFp_div, y);
}
if (x instanceof Fr) {
return x._op2(mcl_1.mod._mclBnFr_div, y);
}
if (x instanceof GT) {
return x._op2(mcl_1.mod._mclBnGT_div, y);
}
if (x instanceof Fp2) {
return x._op2(mcl_1.mod._mclBnFp2_div, y);
}
throw new Error('div:bad type');
}
exports.div = div;
const dbl = (x) => {
if (x instanceof G1) {
return x._op1(mcl_1.mod._mclBnG1_dbl);
}
if (x instanceof G2) {
return x._op1(mcl_1.mod._mclBnG2_dbl);
}
throw new Error('dbl:bad type');
};
exports.dbl = dbl;
const hashToFr = (s) => {
const x = new Fr();
x.setHashOf(s);
return x;
};
exports.hashToFr = hashToFr;
const hashAndMapToG1 = (s) => {
const x = new G1();
x.setHashOf(s);
return x;
};
exports.hashAndMapToG1 = hashAndMapToG1;
const hashAndMapToG2 = (s) => {
const x = new G2();
x.setHashOf(s);
return x;
};
exports.hashAndMapToG2 = hashAndMapToG2;
const IntToArray = (_x) => {
let x = typeof _x === 'number' ? BigInt(_x) : _x;
if (x < 0n) {
throw new Error('IntToArray: negative value');
}
if (x === 0n)
return new Uint8Array(1);
const a = [];
while (x) {
a.push(Number(BigInt.asUintN(8, x)));
x >>= 8n;
}
return new Uint8Array(a);
};
const _powArray = (powArray, x, _y) => {
const cstr = x.constructor;
const z = new cstr();
const y = IntToArray(_y.valueOf());
const stack = mcl_1.mod.stackSave();
const zPos = z._salloc();
const xPos = x._sallocAndCopy();
const yPos = mcl_1.mod.stackAlloc(y.length);
mcl_1.mod.HEAP8.set(y, yPos);
const r = powArray(zPos, xPos, yPos, y.length);
z._save(zPos);
mcl_1.mod.stackRestore(stack);
if (r < 0)
throw new Error('powArray err');
return z;
};
function pow(x, y) {
if (x instanceof Fr) {
if (y instanceof Fr) {
return x._op2(mcl_1.mod._mclBnFr_pow, y);
}
else if (typeof (y) === 'number' || typeof (y) === 'bigint') {
return _powArray(mcl_1.mod._mclBnFr_powArray, x, y);
}
}
if (x instanceof Fp) {
if (y instanceof Fp) {
return x._op2(mcl_1.mod._mclBnFp_pow, y);
}
else if (typeof (y) === 'number' || typeof (y) === 'bigint') {
return _powArray(mcl_1.mod._mclBnFp_powArray, x, y);
}
}
if (x instanceof GT && y instanceof Fr) {
return x._op2(mcl_1.mod._mclBnGT_pow, y);
}
throw new Error('pow:bad type');
}
exports.pow = pow;
const pairing = (P, Q) => {
if (P instanceof G1 && Q instanceof G2) {
return P._op2(mcl_1.mod._mclBn_pairing, Q, GT);
}
throw new Error('exports.pairing:bad type');
};
exports.pairing = pairing;
const millerLoop = (P, Q) => {
if (P instanceof G1 && Q instanceof G2) {
return P._op2(mcl_1.mod._mclBn_millerLoop, Q, GT);
}
throw new Error('exports.millerLoop:bad type');
};
exports.millerLoop = millerLoop;
const precomputedMillerLoop = (P, Qcoeff) => {
if (!(P instanceof G1 && Qcoeff instanceof PrecomputedG2))
throw new Error('exports.precomputedMillerLoop:bad type');
const e = new GT();
const stack = mcl_1.mod.stackSave();
const PPos = P._sallocAndCopy();
const ePos = e._salloc();
mcl_1.mod._mclBn_precomputedMillerLoop(ePos, PPos, Qcoeff.p);
e._save(ePos);
mcl_1.mod.stackRestore(stack);
return e;
};
exports.precomputedMillerLoop = precomputedMillerLoop;
// millerLoop(P1, Q1coeff) * millerLoop(P2, Q2coeff)
const precomputedMillerLoop2 = (P1, Q1coeff, P2, Q2coeff) => {
if (!(P1 instanceof G1 && Q1coeff instanceof PrecomputedG2 && P2 instanceof G1 && Q2coeff instanceof PrecomputedG2))
throw new Error('exports.precomputedMillerLoop2mixed:bad type');
const e = new GT();
const stack = mcl_1.mod.stackSave();
const P1Pos = P1._sallocAndCopy();
const P2Pos = P2._sallocAndCopy();
const ePos = e._salloc();
mcl_1.mod._mclBn_precomputedMillerLoop2(ePos, P1Pos, Q1coeff.p, P2Pos, Q2coeff.p);
e._save(ePos);
mcl_1.mod.stackRestore(stack);
return e;
};
exports.precomputedMillerLoop2 = precomputedMillerLoop2;
// millerLoop(P1, Q1) * millerLoop(P2, Q2coeff)
const precomputedMillerLoop2mixed = (P1, Q1, P2, Q2coeff) => {
if (!(P1 instanceof G1 && Q1 instanceof G2 && P2 instanceof G1 && Q2coeff instanceof PrecomputedG2))
throw new Error('exports.precomputedMillerLoop2mixed:bad type');
const e = new GT();
const stack = mcl_1.mod.stackSave();
const P1Pos = P1._sallocAndCopy();
const Q1Pos = Q1._sallocAndCopy();
const P2Pos = P2._sallocAndCopy();
const ePos = e._salloc();
mcl_1.mod._mclBn_precomputedMillerLoop2mixed(ePos, P1Pos, Q1Pos, P2Pos, Q2coeff.p);
e._save(ePos);
mcl_1.mod.stackRestore(stack);
return e;
};
exports.precomputedMillerLoop2mixed = precomputedMillerLoop2mixed;
const finalExp = (x) => {
if (x instanceof GT) {
return x._op1(mcl_1.mod._mclBn_finalExp);
}
throw new Error('finalExp:bad type');
};
exports.finalExp = finalExp;
function _callShare(CstrT, func, vec, id) {
const a = new CstrT();
const stack = mcl_1.mod.stackSave();
const pos = a._salloc();
const vecPos = _sarrayAllocAndCopy(vec);
const idPos = id._sallocAndCopy();
func(pos, vecPos, vec.length, idPos);
a._save(pos);
mcl_1.mod.stackRestore(stack);
return a;
}
function _callRecover(CstrT, func, idVec, yVec) {
const k = yVec.length;
if (k !== idVec.length)
throw new Error('recover:bad length');
const a = new CstrT();
const stack = mcl_1.mod.stackSave();
const aPos = a._salloc();
const idVecPos = _sarrayAllocAndCopy(idVec);
const yVecPos = _sarrayAllocAndCopy(yVec);
const r = func(aPos, idVecPos, yVecPos, k);
a._save(aPos);
mcl_1.mod.stackRestore(stack);
if (r !== 0)
throw new Error('callRecover');
return a;
}
const shareFr = (vec, id) => {
return _callShare(Fr, mcl_1.mod._mclBn_FrEvaluatePolynomial, vec, id);
};
exports.shareFr = shareFr;
const shareG1 = (vec, id) => {
return _callShare(G1, mcl_1.mod._mclBn_G1EvaluatePolynomial, vec, id);
};
exports.shareG1 = shareG1;
const shareG2 = (vec, id) => {
return _callShare(G2, mcl_1.mod._mclBn_G2EvaluatePolynomial, vec, id);
};
exports.shareG2 = shareG2;
const recoverFr = (idVec, yVec) => {
return _callRecover(Fr, mcl_1.mod._mclBn_FrLagrangeInterpolation, idVec, yVec);
};
exports.recoverFr = recoverFr;
const recoverG1 = (idVec, yVec) => {
return _callRecover(G1, mcl_1.mod._mclBn_G1LagrangeInterpolation, idVec, yVec);
};
exports.recoverG1 = recoverG1;
const recoverG2 = (idVec, yVec) => {
return _callRecover(G2, mcl_1.mod._mclBn_G2LagrangeInterpolation, idVec, yVec);
};
exports.recoverG2 = recoverG2;