UNPKG

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
"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;