import { mod , _free , toHexStr , fromHexStr , _malloc } from './mcl' ; import { MCLBN_FP_SIZE , MCLBN_FR_SIZE , MCLBN_G1_SIZE , MCLBN_G2_SIZE , MCLBN_GT_SIZE } from './constants' ; import getRandomValues from './getRandomValues' ; abstract class Common { internal public a_ : Uint32Array ; constructor ( size ) { this . a_ = new Uint32Array ( size / 4 ) ; } deserializeHexStr ( s ) { this . deserialize ( fromHexStr ( s ) ) ; } serializeToHexStr ( ) { return toHexStr ( this . serialize ( ) ) ; } dump ( msg = '' ) { console . log ( msg + this . serializeToHexStr ( ) ) ; } clear ( ) { this . a_ . fill ( 0 ) ; } copyToMem ( pos ) { mod . HEAP32 . set ( this . a_ , pos / 4 ) ; } copyFromMem ( pos ) { this . a_ . set ( mod . HEAP32 . subarray ( pos / 4 , pos / 4 + this . a_ . length ) ) ; } abstract setStr ( s , base ? ) ; abstract getStr ( base ? ) ; abstract isEqual ( rhs ) ; abstract isZero ( ) ; abstract deserialize ( v ) ; abstract serialize ( ) ; abstract setHashOf ( a ) ; internal _alloc ( ) { return _malloc ( this . a_ . length * 4 ) ; } internal _allocAndCopy ( ) { const pos = this . _alloc ( ) ; mod . HEAP32 . set ( this . a_ , pos / 4 ) ; return pos ; } internal _save ( pos ) { this . a_ . set ( mod . HEAP32 . subarray ( pos / 4 , pos / 4 + this . a_ . length ) ) ; } internal _saveAndFree ( pos ) { this . _save ( pos ) ; _free ( pos ) ; } internal _setter ( func , ... params ) { const pos = this . _alloc ( ) ; const r = func ( pos , ... params ) ; this . _saveAndFree ( pos ) ; if ( r ) throw new Error ( '_setter err' ) ; } internal _getter ( func , ... params ) { const pos = this . _allocAndCopy ( ) ; const s = func ( pos , ... params ) ; _free ( pos ) ; return s ; } internal _isEqual ( func , rhs ) { const xPos = this . _allocAndCopy ( ) ; const yPos = rhs . _allocAndCopy ( ) ; const r = func ( xPos , yPos ) ; _free ( yPos ) ; _free ( xPos ) ; return r === 1 ; } internal _op1 ( func ) { const y = new ( this . constructor as any ) ( ) ; const xPos = this . _allocAndCopy ( ) ; const yPos = y . _alloc ( ) ; func ( yPos , xPos ) ; y . _saveAndFree ( yPos ) ; _free ( xPos ) ; return y ; } internal _op2 ( func , y , Cstr = null ) { const z = Cstr ? new Cstr ( ) : new ( this . constructor as any ) ( ) ; const xPos = this . _allocAndCopy ( ) ; const yPos = y . _allocAndCopy ( ) ; const zPos = z . _alloc ( ) ; func ( zPos , xPos , yPos ) ; z . _saveAndFree ( zPos ) ; _free ( yPos ) ; _free ( xPos ) ; return z ; } internal _getSubArray ( idx , n ) { const d = this . a_ . length / n ; return new Uint32Array ( this . a_ . buffer , d * idx * 4 , d ) ; } internal _setSubArray ( lhs , idx , n ) { const d = this . a_ . length / n ; this . a_ . set ( lhs . a_ , d * idx ) ; } } abstract class IntType extends Common { abstract setInt ( x ) ; abstract isOne ( ) ; abstract setLittleEndian ( a ) ; abstract setLittleEndianMod ( a ) ; abstract setBigEndianMod ( a ) ; abstract setByCSPRNG ( ) ; } export class Fr extends IntType { constructor ( ) { super ( MCLBN_FR_SIZE ) ; } setInt ( x ) { this . _setter ( mod . _mclBnFr_setInt32 , x ) ; } deserialize ( s ) { this . _setter ( mod . mclBnFr_deserialize , s ) ; } serialize ( ) { return this . _getter ( mod . mclBnFr_serialize ) ; } setStr ( s , base = 0 ) { this . _setter ( mod . mclBnFr_setStr , s , base ) ; } getStr ( base = 0 ) { return this . _getter ( mod . mclBnFr_getStr , base ) ; } isZero ( ) { return this . _getter ( mod . _mclBnFr_isZero ) === 1 ; } isOne ( ) { return this . _getter ( mod . _mclBnFr_isOne ) === 1 ; } isEqual ( rhs ) { return this . _isEqual ( mod . _mclBnFr_isEqual , rhs ) ; } setLittleEndian ( a ) { this . _setter ( mod . mclBnFr_setLittleEndian , a ) ; } setLittleEndianMod ( a ) { this . _setter ( mod . mclBnFr_setLittleEndianMod , a ) ; } setBigEndianMod ( a ) { this . _setter ( mod . mclBnFr_setBigEndianMod , a ) ; } setByCSPRNG ( ) { const a = new Uint8Array ( MCLBN_FR_SIZE ) ; getRandomValues ( a ) ; this . setLittleEndian ( a ) ; } setHashOf ( s ) { this . _setter ( mod . mclBnFr_setHashOf , s ) ; } } export interface Fr { /** to distinct Fp and Fr for typescript */ __Fr : never ; } export const deserializeHexStrToFr = ( s ) => { const r = new Fr ( ) ; r . deserializeHexStr ( s ) ; return r ; } ; export class Fp extends IntType { constructor ( ) { super ( MCLBN_FP_SIZE ) ; } setInt ( x ) { this . _setter ( mod . _mclBnFp_setInt32 , x ) ; } deserialize ( s ) { this . _setter ( mod . mclBnFp_deserialize , s ) ; } serialize ( ) { return this . _getter ( mod . mclBnFp_serialize ) ; } setStr ( s , base = 0 ) { this . _setter ( mod . mclBnFp_setStr , s , base ) ; } getStr ( base = 0 ) { return this . _getter ( mod . mclBnFp_getStr , base ) ; } isOne ( ) { throw new Error ( 'Fp.isOne is not supported' ) ; } isZero ( ) { throw new Error ( 'Fp.isZero is not supported' ) ; } isEqual ( rhs ) { return this . _isEqual ( mod . _mclBnFp_isEqual , rhs ) ; } setLittleEndian ( a ) { this . _setter ( mod . mclBnFp_setLittleEndian , a ) ; } setLittleEndianMod ( a ) { this . _setter ( mod . mclBnFp_setLittleEndianMod , a ) ; } setBigEndianMod ( a ) { this . _setter ( mod . mclBnFp_setBigEndianMod , a ) ; } setByCSPRNG ( ) { const a = new Uint8Array ( MCLBN_FP_SIZE ) ; getRandomValues ( a ) ; this . setLittleEndian ( a ) ; } setHashOf ( s ) { this . _setter ( mod . mclBnFp_setHashOf , s ) ; } mapToG1 ( ) { const y = new G1 ( ) ; const xPos = this . _allocAndCopy ( ) ; const yPos = y . _alloc ( ) ; mod . _mclBnFp_mapToG1 ( yPos , xPos ) ; y . _saveAndFree ( yPos ) ; _free ( xPos ) ; return y ; } } export interface Fp { /** to distinct Fp and Fr for typescript */ __Fp : never ; } export const deserializeHexStrToFp = ( s ) => { const r = new Fp ( ) ; r . deserializeHexStr ( s ) ; return r ; } ; export class Fp2 extends Common { constructor ( ) { super ( MCLBN_FP_SIZE * 2 ) ; } 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 ( mod . mclBnFp2_deserialize , s ) ; } serialize ( ) { return this . _getter ( mod . mclBnFp2_serialize ) ; } getStr ( ) { throw new Error ( 'Fp2.getStr is not supported' ) ; } setStr ( ) { throw new Error ( 'Fp2.setStr is not supported' ) ; } isEqual ( rhs ) { return this . _isEqual ( mod . _mclBnFp2_isEqual , rhs ) ; } isZero ( ) { throw new Error ( 'Fp2.isZero is not supported' ) ; } setHashOf ( s ) { throw new Error ( 'Fp2.setHashOf is not supported' ) ; } 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 xPos = this . _allocAndCopy ( ) ; const yPos = y . _alloc ( ) ; mod . _mclBnFp2_mapToG2 ( yPos , xPos ) ; y . _saveAndFree ( yPos ) ; _free ( xPos ) ; return y ; } } export const deserializeHexStrToFp2 = ( s ) => { const r = new Fp2 ( ) ; r . deserializeHexStr ( s ) ; return r ; } ; abstract class EllipticType extends Common { abstract normalize ( ) ; abstract isValid ( ) ; abstract isValidOrder ( ) ; } export class G1 extends EllipticType { constructor ( ) { super ( MCLBN_G1_SIZE ) ; } deserialize ( s ) { this . _setter ( mod . mclBnG1_deserialize , s ) ; } serialize ( ) { return this . _getter ( mod . mclBnG1_serialize ) ; } setStr ( s , base = 0 ) { this . _setter ( mod . mclBnG1_setStr , s , base ) ; } getStr ( base = 0 ) { return this . _getter ( mod . mclBnG1_getStr , base ) ; } normalize ( ) { this . a_ = 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 ( mod . _mclBnG1_isZero ) === 1 ; } isValid ( ) { return this . _getter ( mod . _mclBnG1_isValid ) === 1 ; } isValidOrder ( ) { return this . _getter ( mod . _mclBnG1_isValidOrder ) === 1 ; } isEqual ( rhs ) { return this . _isEqual ( mod . _mclBnG1_isEqual , rhs ) ; } setHashOf ( s ) { this . _setter ( mod . mclBnG1_hashAndMapTo , s ) ; } } export const deserializeHexStrToG1 = ( s ) => { const r = new G1 ( ) ; r . deserializeHexStr ( s ) ; return r ; } ; export const setETHserialization = ( ETHserialization ) => { mod . _mclBn_setETHserialization ( ETHserialization ? 1 : 0 ) ; } ; export const setMapToMode = ( mode ) => { mod . _mclBn_setMapToMode ( mode ) ; } ; export const verifyOrderG1 = ( doVerify ) => { mod . _mclBn_verifyOrderG1 ( doVerify ? 1 : 0 ) ; } ; export const verifyOrderG2 = ( doVerify ) => { mod . _mclBn_verifyOrderG2 ( doVerify ? 1 : 0 ) ; } ; export const getBasePointG1 = ( ) => { const x = new G1 ( ) ; const xPos = x . _alloc ( ) ; mod . _mclBnG1_getBasePoint ( xPos ) ; x . _saveAndFree ( xPos ) ; if ( x . isZero ( ) ) { throw new Error ( 'not supported for pairing curves' ) ; } return x ; } ; export class G2 extends EllipticType { constructor ( ) { super ( MCLBN_G2_SIZE ) ; } deserialize ( s ) { this . _setter ( mod . mclBnG2_deserialize , s ) ; } serialize ( ) { return this . _getter ( mod . mclBnG2_serialize ) ; } setStr ( s , base = 0 ) { this . _setter ( mod . mclBnG2_setStr , s , base ) ; } getStr ( base = 0 ) { return this . _getter ( mod . mclBnG2_getStr , base ) ; } normalize ( ) { this . a_ = 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 ( mod . _mclBnG2_isZero ) === 1 ; } isValid ( ) { return this . _getter ( mod . _mclBnG2_isValid ) === 1 ; } isValidOrder ( ) { return this . _getter ( mod . _mclBnG2_isValidOrder ) === 1 ; } isEqual ( rhs ) { return this . _isEqual ( mod . _mclBnG2_isEqual , rhs ) ; } setHashOf ( s ) { this . _setter ( mod . mclBnG2_hashAndMapTo , s ) ; } } export const deserializeHexStrToG2 = ( s ) => { const r = new G2 ( ) ; r . deserializeHexStr ( s ) ; return r ; } ; export class GT extends Common { constructor ( ) { super ( MCLBN_GT_SIZE ) ; } setInt ( x ) { this . _setter ( mod . _mclBnGT_setInt32 , x ) ; } deserialize ( s ) { this . _setter ( mod . mclBnGT_deserialize , s ) ; } serialize ( ) { return this . _getter ( mod . mclBnGT_serialize ) ; } setStr ( s , base = 0 ) { this . _setter ( mod . mclBnGT_setStr , s , base ) ; } getStr ( base = 0 ) { return this . _getter ( mod . mclBnGT_getStr , base ) ; } isZero ( ) { return this . _getter ( mod . _mclBnGT_isZero ) === 1 ; } isOne ( ) { return this . _getter ( mod . _mclBnGT_isOne ) === 1 ; } isEqual ( rhs ) { return this . _isEqual ( mod . _mclBnGT_isEqual , rhs ) ; } setHashOf ( s ) { throw new Error ( 'GT.setHashOf is not supported' ) ; } } export const deserializeHexStrToGT = ( s ) => { const r = new GT ( ) ; r . deserializeHexStr ( s ) ; return r ; } ; export class PrecomputedG2 { internal p : number | null ; constructor ( Q ) { if ( ! ( Q instanceof G2 ) ) throw new Error ( 'PrecomputedG2:bad type' ) ; const byteSize = mod . _mclBn_getUint64NumToPrecompute ( ) * 8 ; this . p = _malloc ( byteSize ) ; const Qpos = Q . _allocAndCopy ( ) ; mod . _mclBn_precomputeG2 ( this . p , Qpos ) ; _free ( Qpos ) ; } destroy ( ) { if ( this . p != null ) _free ( this . p ) ; this . p = null ; } } export const neg = < T extends Fr | Fp | G1 | G2 | GT | Fp2 > ( x ) : T => { if ( x instanceof Fr ) { return x . _op1 ( mod . _mclBnFr_neg ) ; } if ( x instanceof Fp ) { return x . _op1 ( mod . _mclBnFp_neg ) ; } if ( x instanceof G1 ) { return x . _op1 ( mod . _mclBnG1_neg ) ; } if ( x instanceof G2 ) { return x . _op1 ( mod . _mclBnG2_neg ) ; } if ( x instanceof GT ) { return x . _op1 ( mod . _mclBnGT_neg ) ; } if ( x instanceof Fp2 ) { return x . _op1 ( mod . _mclBnFp2_neg ) ; } throw new Error ( 'neg:bad type' ) ; } ; export const sqr = < T extends Fp | Fr | GT | Fp2 > ( x ) : T => { if ( x instanceof Fp ) { return x . _op1 ( mod . _mclBnFp_sqr ) ; } if ( x instanceof Fr ) { return x . _op1 ( mod . _mclBnFr_sqr ) ; } if ( x instanceof GT ) { return x . _op1 ( mod . _mclBnGT_sqr ) ; } if ( x instanceof Fp2 ) { return x . _op1 ( mod . _mclBnFp2_sqr ) ; } throw new Error ( 'sqr:bad type' ) ; } ; export const inv = < T extends Fp | Fr | GT | Fp2 > ( x ) : T => { if ( x instanceof Fp ) { return x . _op1 ( mod . _mclBnFp_inv ) ; } if ( x instanceof Fr ) { return x . _op1 ( mod . _mclBnFr_inv ) ; } if ( x instanceof GT ) { return x . _op1 ( mod . _mclBnGT_inv ) ; } if ( x instanceof Fp2 ) { return x . _op1 ( mod . _mclBnFp2_inv ) ; } throw new Error ( 'inv:bad type' ) ; } ; export const normalize = < T extends G1 | G2 > ( x ) : T => { if ( x instanceof G1 ) { return x . _op1 ( mod . _mclBnG1_normalize ) ; } if ( x instanceof G2 ) { return x . _op1 ( mod . _mclBnG2_normalize ) ; } throw new Error ( 'normalize:bad type' ) ; } ; export const add = < T extends Fp | Fr | G1 | G2 | GT | Fp2 > ( x , y ) : T => { if ( x . constructor !== y . constructor ) throw new Error ( 'add:mismatch type' ) ; if ( x instanceof Fp ) { return x . _op2 ( mod . _mclBnFp_add , y ) ; } if ( x instanceof Fr ) { return x . _op2 ( mod . _mclBnFr_add , y ) ; } if ( x instanceof G1 ) { return x . _op2 ( mod . _mclBnG1_add , y ) ; } if ( x instanceof G2 ) { return x . _op2 ( mod . _mclBnG2_add , y ) ; } if ( x instanceof GT ) { return x . _op2 ( mod . _mclBnGT_add , y ) ; } if ( x instanceof Fp2 ) { return x . _op2 ( mod . _mclBnFp2_add , y ) ; } throw new Error ( 'add:bad type' ) ; } ; export const sub = < T extends Fp | Fr | G1 | G2 | GT | Fp2 > ( x , y ) : T => { if ( x . constructor !== y . constructor ) throw new Error ( 'sub:mismatch type' ) ; if ( x instanceof Fp ) { return x . _op2 ( mod . _mclBnFp_sub , y ) ; } if ( x instanceof Fr ) { return x . _op2 ( mod . _mclBnFr_sub , y ) ; } if ( x instanceof G1 ) { return x . _op2 ( mod . _mclBnG1_sub , y ) ; } if ( x instanceof G2 ) { return x . _op2 ( mod . _mclBnG2_sub , y ) ; } if ( x instanceof GT ) { return x . _op2 ( mod . _mclBnGT_sub , y ) ; } if ( x instanceof Fp2 ) { return x . _op2 ( mod . _mclBnFp2_sub , y ) ; } throw new Error ( 'sub:bad type' ) ; } ; export function mul ( x , y ) ; export function mul ( x , y ) ; export function mul ( x , y ) ; export function mul ( x , y ) ; export function mul ( x , y ) ; export function mul ( x , y ) ; export function mul ( x , y ) { if ( x instanceof Fp && y instanceof Fp ) { return x . _op2 ( mod . _mclBnFp_mul , y ) ; } if ( x instanceof Fr && y instanceof Fr ) { return x . _op2 ( mod . _mclBnFr_mul , y ) ; } if ( x instanceof G1 && y instanceof Fr ) { return x . _op2 ( mod . _mclBnG1_mul , y ) ; } if ( x instanceof G2 && y instanceof Fr ) { return x . _op2 ( mod . _mclBnG2_mul , y ) ; } if ( x instanceof GT && y instanceof GT ) { return x . _op2 ( mod . _mclBnGT_mul , y ) ; } if ( x instanceof Fp2 && y instanceof Fp2 ) { return x . _op2 ( mod . _mclBnFp2_mul , y ) ; } throw new Error ( 'mul:mismatch type' ) ; } const _mulVec = < T extends G1 | G2 > ( func , xVec , yVec , Cstr ) => { const n = xVec . length ; if ( n != yVec . length ) throw new Error ( `err _mulVec bad length ${ n }, ${ yVec . length }` ) ; const xSize = xVec [ 0 ] . a_ . length ; const ySize = yVec [ 0 ] . a_ . length ; const z = new Cstr ( ) ; const zPos = z . _alloc ( ) ; const xPos = _malloc ( xSize * n * 4 ) ; const yPos = _malloc ( ySize * n * 4 ) ; let pos = xPos / 4 ; for ( let i = 0 ; i < n ; i ++ ) { mod . HEAP32 . set ( xVec [ i ] . a_ , pos ) ; pos += xSize ; } pos = yPos / 4 ; for ( let i = 0 ; i < n ; i ++ ) { mod . HEAP32 . set ( yVec [ i ] . a_ , pos ) ; pos += ySize ; } func ( zPos , xPos , yPos , n ) ; _free ( yPos ) ; _free ( xPos ) ; z . _saveAndFree ( zPos ) ; return z ; } ; export const mulVec = < T extends G1 | G2 > ( xVec , yVec ) : T => { if ( xVec . length == 0 ) throw new Error ( 'mulVec:zero array' ) ; if ( xVec [ 0 ] instanceof G1 && yVec [ 0 ] instanceof Fr ) { return _mulVec ( mod . _mclBnG1_mulVec , xVec , yVec , G1 ) ; } if ( xVec [ 0 ] instanceof G2 && yVec [ 0 ] instanceof Fr ) { return _mulVec ( mod . _mclBnG2_mulVec , xVec , yVec , G2 ) ; } throw new Error ( 'mulVec:mismatch type' ) ; } ; export function div ( x , y ) ; export function div ( x , y ) ; export function div ( x , y ) ; export function div ( x , y ) ; export function div ( x , y ) { if ( x . constructor !== y . constructor ) throw new Error ( 'div:mismatch type' ) ; if ( x instanceof Fp ) { return x . _op2 ( mod . _mclBnFp_div , y ) ; } if ( x instanceof Fr ) { return x . _op2 ( mod . _mclBnFr_div , y ) ; } if ( x instanceof GT ) { return x . _op2 ( mod . _mclBnGT_div , y ) ; } if ( x instanceof Fp2 ) { return x . _op2 ( mod . _mclBnFp2_div , y ) ; } throw new Error ( 'div:bad type' ) ; } export const dbl = < T extends G1 | G2 > ( x ) : T => { if ( x instanceof G1 ) { return x . _op1 ( mod . _mclBnG1_dbl ) ; } if ( x instanceof G2 ) { return x . _op1 ( mod . _mclBnG2_dbl ) ; } throw new Error ( 'dbl:bad type' ) ; } ; export const hashToFr = ( s ) => { const x = new Fr ( ) ; x . setHashOf ( s ) ; return x ; } ; export const hashAndMapToG1 = ( s ) => { const x = new G1 ( ) ; x . setHashOf ( s ) ; return x ; } ; export const hashAndMapToG2 = ( s ) => { const x = new G2 ( ) ; x . setHashOf ( s ) ; return x ; } ; export const pow = ( x , y ) : GT => { if ( x instanceof GT && y instanceof Fr ) { return x . _op2 ( mod . _mclBnGT_pow , y ) ; } throw new Error ( 'pow:bad type' ) ; } ; export const pairing = ( P , Q ) : GT => { if ( P instanceof G1 && Q instanceof G2 ) { return P . _op2 ( mod . _mclBn_pairing , Q , GT ) ; } throw new Error ( 'exports.pairing:bad type' ) ; } ; export const millerLoop = ( P , Q ) : GT => { if ( P instanceof G1 && Q instanceof G2 ) { return P . _op2 ( mod . _mclBn_millerLoop , Q , GT ) ; } throw new Error ( 'exports.millerLoop:bad type' ) ; } ; export const precomputedMillerLoop = ( P , Qcoeff ) : GT => { if ( ! ( P instanceof G1 && Qcoeff instanceof PrecomputedG2 ) ) throw new Error ( 'exports.precomputedMillerLoop:bad type' ) ; const e = new GT ( ) ; const PPos = P . _allocAndCopy ( ) ; const ePos = e . _alloc ( ) ; mod . _mclBn_precomputedMillerLoop ( ePos , PPos , Qcoeff . p ) ; e . _saveAndFree ( ePos ) ; _free ( PPos ) ; return e ; } ; export const precomputedMillerLoop2 = ( P1 , Q1coeff , P2 , Q2coeff ) : GT => { 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 P1Pos = P1 . _allocAndCopy ( ) ; const P2Pos = P2 . _allocAndCopy ( ) ; const ePos = e . _alloc ( ) ; mod . _mclBn_precomputedMillerLoop2 ( ePos , P1Pos , Q1coeff . p , P2Pos , Q2coeff . p ) ; e . _saveAndFree ( ePos ) ; _free ( P1Pos ) ; _free ( P2Pos ) ; return e ; } ; export const precomputedMillerLoop2mixed = ( P1 , Q1 , P2 , Q2coeff ) : GT => { 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 P1Pos = P1 . _allocAndCopy ( ) ; const Q1Pos = Q1 . _allocAndCopy ( ) ; const P2Pos = P2 . _allocAndCopy ( ) ; const ePos = e . _alloc ( ) ; mod . _mclBn_precomputedMillerLoop2mixed ( ePos , P1Pos , Q1Pos , P2Pos , Q2coeff . p ) ; e . _saveAndFree ( ePos ) ; _free ( P1Pos ) ; _free ( Q1Pos ) ; _free ( P2Pos ) ; return e ; } ; export const finalExp = ( x ) : GT => { if ( x instanceof GT ) { return x . _op1 ( mod . _mclBn_finalExp ) ; } throw new Error ( 'finalExp:bad type' ) ; } ;