Pairing working
This commit is contained in:
parent
143654c8d6
commit
a878d8ff59
325
src/bn128.js
Normal file
325
src/bn128.js
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
const bigInt = require("big-integer");
|
||||||
|
const assert = require("assert");
|
||||||
|
|
||||||
|
const F1Field = require("./f1field.js");
|
||||||
|
const F2Field = require("./f2field.js");
|
||||||
|
const F3Field = require("./f3field.js");
|
||||||
|
const GCurve = require("./gcurve.js");
|
||||||
|
|
||||||
|
class BN128 {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
this.q = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583");
|
||||||
|
this.r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
|
this.g1 = [ bigInt(1), bigInt(2) ];
|
||||||
|
this.g2 = [
|
||||||
|
[
|
||||||
|
bigInt("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
|
||||||
|
bigInt("11559732032986387107991004021392285783925812861821192530917403151452391805634")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
bigInt("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
|
||||||
|
bigInt("4082367875863433681332203403145435568316851327593401208105741076214120093531")
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
this.F1 = new F1Field(this.q);
|
||||||
|
this.F2 = new F2Field(this.F1, bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208582"));
|
||||||
|
this.G1 = new GCurve(this.F1, this.g1);
|
||||||
|
this.G2 = new GCurve(this.F2, this.g2);
|
||||||
|
this.F6 = new F3Field(this.F2, [ bigInt("9"), bigInt("1") ]);
|
||||||
|
this.F12 = new F2Field(this.F6, [ bigInt("9"), bigInt("1") ]);
|
||||||
|
const self = this;
|
||||||
|
this.F12._mulByNonResidue = function(a) {
|
||||||
|
return [self.F2.mul(this.nonResidue, a[2]), a[0], a[1]];
|
||||||
|
};
|
||||||
|
|
||||||
|
this._preparePairing();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_preparePairing() {
|
||||||
|
this.loopCount = bigInt("29793968203157093288");// CONSTANT
|
||||||
|
|
||||||
|
// Set loopCountNeg
|
||||||
|
if (this.loopCount.isNegative()) {
|
||||||
|
this.loopCount = this.neg();
|
||||||
|
this.loopCountNeg = true;
|
||||||
|
} else {
|
||||||
|
this.loopCountNeg = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set loop_count_bits
|
||||||
|
let lc = this.loopCount;
|
||||||
|
this.loop_count_bits = []; // Constant
|
||||||
|
while (!lc.isZero()) {
|
||||||
|
this.loop_count_bits.push( lc.isOdd() );
|
||||||
|
lc = lc.shiftRight(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.two_inv = this.F1.inverse(bigInt(2));
|
||||||
|
|
||||||
|
this.coef_b = bigInt(3);
|
||||||
|
this.twist = [bigInt(9) , bigInt(1)];
|
||||||
|
this.twist_coeff_b = this.F2.mulEscalar( this.F2.inverse(this.twist), this.coef_b );
|
||||||
|
|
||||||
|
this.frobenius_coeffs_c1_1 = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||||
|
this.twist_mul_by_q_X =
|
||||||
|
[
|
||||||
|
bigInt("21575463638280843010398324269430826099269044274347216827212613867836435027261"),
|
||||||
|
bigInt("10307601595873709700152284273816112264069230130616436755625194854815875713954")
|
||||||
|
];
|
||||||
|
this.twist_mul_by_q_Y =
|
||||||
|
[
|
||||||
|
bigInt("2821565182194536844548159561693502659359617185244120367078079554186484126554"),
|
||||||
|
bigInt("3505843767911556378687030309984248845540243509899259641013678093033130930403")
|
||||||
|
];
|
||||||
|
|
||||||
|
this.final_exponent = bigInt("552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pairing(p1, p2) {
|
||||||
|
|
||||||
|
const pre1 = this.precomputeG1(p1);
|
||||||
|
const pre2 = this.precomputeG2(p2);
|
||||||
|
|
||||||
|
const r1 = this.millerLoop(pre1, pre2);
|
||||||
|
|
||||||
|
const res = this.finalExponentiation(r1);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
precomputeG1(p) {
|
||||||
|
const Pcopy = this.G1.affine(p);
|
||||||
|
|
||||||
|
const res = {};
|
||||||
|
res.PX = Pcopy[0];
|
||||||
|
res.PY = Pcopy[1];
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
precomputeG2(p) {
|
||||||
|
|
||||||
|
const Qcopy = this.G2.affine(p);
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
QX: Qcopy[0],
|
||||||
|
QY: Qcopy[1],
|
||||||
|
coeffs: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const R = {
|
||||||
|
X: Qcopy[0],
|
||||||
|
Y: Qcopy[1],
|
||||||
|
Z: this.F2.one
|
||||||
|
};
|
||||||
|
|
||||||
|
let c;
|
||||||
|
|
||||||
|
for (let i = this.loop_count_bits.length-2; i >= 0; --i)
|
||||||
|
{
|
||||||
|
const bit = this.loop_count_bits[i];
|
||||||
|
|
||||||
|
c = this._doubleStep(R);
|
||||||
|
res.coeffs.push(c);
|
||||||
|
|
||||||
|
if (bit)
|
||||||
|
{
|
||||||
|
c = this._addStep(Qcopy, R);
|
||||||
|
res.coeffs.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Q1 = this.G2.affine(this._g2MulByQ(Qcopy));
|
||||||
|
assert(this.F2.equals(Q1[2], this.F2.one));
|
||||||
|
const Q2 = this.G2.affine(this._g2MulByQ(Q1));
|
||||||
|
assert(this.F2.equals(Q2[2], this.F2.one));
|
||||||
|
|
||||||
|
if (this.loopCountNef)
|
||||||
|
{
|
||||||
|
R.Y = this.F2.neg(R.Y);
|
||||||
|
}
|
||||||
|
Q2[1] = this.F2.neg(Q2[1]);
|
||||||
|
|
||||||
|
c = this._addStep(Q1, R);
|
||||||
|
res.coeffs.push(c);
|
||||||
|
|
||||||
|
c = this._addStep(Q2, R);
|
||||||
|
res.coeffs.push(c);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
millerLoop(pre1, pre2) {
|
||||||
|
let f = this.F12.one;
|
||||||
|
|
||||||
|
let idx = 0;
|
||||||
|
|
||||||
|
let c;
|
||||||
|
|
||||||
|
for (let i = this.loop_count_bits.length-2; i >= 0; --i)
|
||||||
|
{
|
||||||
|
const bit = this.loop_count_bits[i];
|
||||||
|
|
||||||
|
/* code below gets executed for all bits (EXCEPT the MSB itself) of
|
||||||
|
alt_bn128_param_p (skipping leading zeros) in MSB to LSB
|
||||||
|
order */
|
||||||
|
|
||||||
|
c = pre2.coeffs[idx++];
|
||||||
|
f = this.F12.square(f);
|
||||||
|
f = this._mul_by_024(
|
||||||
|
f,
|
||||||
|
c.ell_0,
|
||||||
|
this.F2.mulEscalar(c.ell_VW , pre1.PY),
|
||||||
|
this.F2.mulEscalar(c.ell_VV , pre1.PX, ));
|
||||||
|
|
||||||
|
if (bit)
|
||||||
|
{
|
||||||
|
c = pre2.coeffs[idx++];
|
||||||
|
f = this._mul_by_024(
|
||||||
|
f,
|
||||||
|
c.ell_0,
|
||||||
|
this.F2.mulEscalar(c.ell_VW, pre1.PY, ),
|
||||||
|
this.F2.mulEscalar(c.ell_VV, pre1.PX, ));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.loopCountNef)
|
||||||
|
{
|
||||||
|
f = this.F12.inverse(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
c = pre2.coeffs[idx++];
|
||||||
|
f = this._mul_by_024(
|
||||||
|
f,
|
||||||
|
c.ell_0,
|
||||||
|
this.F2.mulEscalar(c.ell_VW, pre1.PY),
|
||||||
|
this.F2.mulEscalar(c.ell_VV, pre1.PX));
|
||||||
|
|
||||||
|
c = pre2.coeffs[idx++];
|
||||||
|
f = this._mul_by_024(
|
||||||
|
f,
|
||||||
|
c.ell_0,
|
||||||
|
this.F2.mulEscalar(c.ell_VW, pre1.PY, ),
|
||||||
|
this.F2.mulEscalar(c.ell_VV, pre1.PX));
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
finalExponentiation(elt) {
|
||||||
|
// TODO: There is an optimization in FF
|
||||||
|
|
||||||
|
const res = this.F12.exp(elt,this.final_exponent);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
_doubleStep(current) {
|
||||||
|
const X = current.X;
|
||||||
|
const Y = current.Y;
|
||||||
|
const Z = current.Z;
|
||||||
|
|
||||||
|
const A = this.F2.mulEscalar(this.F2.mul(X,Y), this.two_inv); // A = X1 * Y1 / 2
|
||||||
|
const B = this.F2.square(Y); // B = Y1^2
|
||||||
|
const C = this.F2.square(Z); // C = Z1^2
|
||||||
|
const D = this.F2.add(C, this.F2.add(C,C)); // D = 3 * C
|
||||||
|
const E = this.F2.mul(this.twist_coeff_b, D); // E = twist_b * D
|
||||||
|
const F = this.F2.add(E, this.F2.add(E,E)); // F = 3 * E
|
||||||
|
const G =
|
||||||
|
this.F2.mulEscalar(
|
||||||
|
this.F2.add( B , F ),
|
||||||
|
this.two_inv); // G = (B+F)/2
|
||||||
|
const H =
|
||||||
|
this.F2.sub(
|
||||||
|
this.F2.square( this.F2.add(Y,Z) ),
|
||||||
|
this.F2.add( B , C)); // H = (Y1+Z1)^2-(B+C)
|
||||||
|
const I = this.F2.sub(E, B); // I = E-B
|
||||||
|
const J = this.F2.square(X); // J = X1^2
|
||||||
|
const E_squared = this.F2.square(E); // E_squared = E^2
|
||||||
|
|
||||||
|
current.X = this.F2.mul( A, this.F2.sub(B,F) ); // X3 = A * (B-F)
|
||||||
|
current.Y =
|
||||||
|
this.F2.sub(
|
||||||
|
this.F2.sub( this.F2.square(G) , E_squared ),
|
||||||
|
this.F2.add( E_squared , E_squared )); // Y3 = G^2 - 3*E^2
|
||||||
|
current.Z = this.F2.mul( B, H ); // Z3 = B * H
|
||||||
|
const c = {
|
||||||
|
ell_0 : this.F2.mul( I, this.twist), // ell_0 = xi * I
|
||||||
|
ell_VW: this.F2.neg( H ), // ell_VW = - H (later: * yP)
|
||||||
|
ell_VV: this.F2.add( J , this.F2.add(J,J) ) // ell_VV = 3*J (later: * xP)
|
||||||
|
};
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_addStep(base, current) {
|
||||||
|
|
||||||
|
const X1 = current.X;
|
||||||
|
const Y1 = current.Y;
|
||||||
|
const Z1 = current.Z;
|
||||||
|
const x2 = base[0];
|
||||||
|
const y2 = base[1];
|
||||||
|
|
||||||
|
const D = this.F2.sub( X1, this.F2.mul(x2,Z1) ); // D = X1 - X2*Z1
|
||||||
|
const E = this.F2.sub( Y1, this.F2.mul(y2,Z1) ); // E = Y1 - Y2*Z1
|
||||||
|
const F = this.F2.square(D); // F = D^2
|
||||||
|
const G = this.F2.square(E); // G = E^2
|
||||||
|
const H = this.F2.mul(D,F); // H = D*F
|
||||||
|
const I = this.F2.mul(X1,F); // I = X1 * F
|
||||||
|
const J =
|
||||||
|
this.F2.sub(
|
||||||
|
this.F2.add( H, this.F2.mul(Z1,G) ),
|
||||||
|
this.F2.add( I, I )); // J = H + Z1*G - (I+I)
|
||||||
|
|
||||||
|
current.X = this.F2.mul( D , J ); // X3 = D*J
|
||||||
|
current.Y =
|
||||||
|
this.F2.sub(
|
||||||
|
this.F2.mul( E , this.F2.sub(I,J) ),
|
||||||
|
this.F2.mul( H , Y1)); // Y3 = E*(I-J)-(H*Y1)
|
||||||
|
current.Z = this.F2.mul(Z1,H);
|
||||||
|
const c = {
|
||||||
|
ell_0 :
|
||||||
|
this.F2.mul(
|
||||||
|
this.twist,
|
||||||
|
this.F2.sub(
|
||||||
|
this.F2.mul(E , x2),
|
||||||
|
this.F2.mul(D , y2))), // ell_0 = xi * (E * X2 - D * Y2)
|
||||||
|
ell_VV : this.F2.neg(E), // ell_VV = - E (later: * xP)
|
||||||
|
ell_VW : D // ell_VW = D (later: * yP )
|
||||||
|
};
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mul_by_024(a, ell_0, ell_VW, ell_VV) {
|
||||||
|
|
||||||
|
const b = [
|
||||||
|
[ell_0, this.F2.zero, ell_VV],
|
||||||
|
[this.F2.zero, ell_VW, this.F2.zero]
|
||||||
|
];
|
||||||
|
|
||||||
|
return this.F12.mul(a,b);
|
||||||
|
|
||||||
|
// TODO There is a better version on libff. It should be ported.
|
||||||
|
}
|
||||||
|
|
||||||
|
_g2MulByQ(p) {
|
||||||
|
const fmx = [p[0][0], this.F1.mul(p[0][1], this.frobenius_coeffs_c1_1 )];
|
||||||
|
const fmy = [p[1][0], this.F1.mul(p[1][1], this.frobenius_coeffs_c1_1 )];
|
||||||
|
const fmz = [p[2][0], this.F1.mul(p[2][1], this.frobenius_coeffs_c1_1 )];
|
||||||
|
return [
|
||||||
|
this.F2.mul(this.twist_mul_by_q_X , fmx),
|
||||||
|
this.F2.mul(this.twist_mul_by_q_Y , fmy),
|
||||||
|
fmz
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BN128;
|
@ -24,8 +24,10 @@ const C = {
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
|
||||||
f2nonResidue: bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208582")
|
f2nonResidue: bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208582"),
|
||||||
|
f6nonResidue: [ bigInt("9"), bigInt("1") ],
|
||||||
|
f12nonResidue: [
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const F1 = new F1Field(C.q);
|
const F1 = new F1Field(C.q);
|
||||||
@ -35,7 +37,8 @@ C.two_inv= F1.inverse(bigInt(2));
|
|||||||
|
|
||||||
C.coef_b = bigInt(3);
|
C.coef_b = bigInt(3);
|
||||||
C.twist = [bigInt(9) , bigInt(1)];
|
C.twist = [bigInt(9) , bigInt(1)];
|
||||||
// C.twist_coeff_b = F2.mulEscalar( F2.inverse(C.twist), C.coef_b );
|
C.twist_coeff_b = F2.mulEscalar( F2.inverse(C.twist), C.coef_b );
|
||||||
|
|
||||||
|
|
||||||
module.exports = C;
|
module.exports = C;
|
||||||
|
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class F12Field {
|
|
||||||
constructor(p) {
|
|
||||||
this.p = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
add(a, b) {
|
|
||||||
const maxGrade = Math.max(a.length, b.length);
|
|
||||||
const res = new Array(maxGrade);
|
|
||||||
for (let i=0; i<maxGrade; i++) {
|
|
||||||
res[i] = this.F.add(a[i], b[i]);
|
|
||||||
}
|
|
||||||
return this._reduce(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub(a, b) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
neg(a) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
mul(a, b) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
inverse(a, b) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
div(a, b) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
isZero(a) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
mul_by_024(a, ell0, ellVW, ellVV) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = F2Field;
|
|
@ -1,4 +1,5 @@
|
|||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
|
const fUtils = require("./futils.js");
|
||||||
|
|
||||||
class F1Field {
|
class F1Field {
|
||||||
constructor(q) {
|
constructor(q) {
|
||||||
@ -8,10 +9,6 @@ class F1Field {
|
|||||||
this.one = bigInt.one;
|
this.one = bigInt.one;
|
||||||
}
|
}
|
||||||
|
|
||||||
e(a) {
|
|
||||||
return bigInt(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(a) {
|
copy(a) {
|
||||||
return bigInt(a);
|
return bigInt(a);
|
||||||
}
|
}
|
||||||
@ -20,6 +17,10 @@ class F1Field {
|
|||||||
return a.add(b);
|
return a.add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double(a) {
|
||||||
|
return this.add(a,a);
|
||||||
|
}
|
||||||
|
|
||||||
sub(a, b) {
|
sub(a, b) {
|
||||||
return a.minus(b);
|
return a.minus(b);
|
||||||
}
|
}
|
||||||
@ -69,6 +70,14 @@ class F1Field {
|
|||||||
return aux;
|
return aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mulEscalar(base, e) {
|
||||||
|
return fUtils.mulEscalar(this, base, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
exp(base, e) {
|
||||||
|
return fUtils.exp(this, base, e);
|
||||||
|
}
|
||||||
|
|
||||||
toString(a) {
|
toString(a) {
|
||||||
const ca = this.affine(a);
|
const ca = this.affine(a);
|
||||||
return `"0x${ca.toString(16)}"`;
|
return `"0x${ca.toString(16)}"`;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const bigInt = require("big-integer");
|
const fUtils = require("./futils.js");
|
||||||
|
|
||||||
class F2Field {
|
class F2Field {
|
||||||
constructor(F, nonResidue) {
|
constructor(F, nonResidue) {
|
||||||
@ -8,8 +8,8 @@ class F2Field {
|
|||||||
this.nonResidue = nonResidue;
|
this.nonResidue = nonResidue;
|
||||||
}
|
}
|
||||||
|
|
||||||
e(c0, c1) {
|
_mulByNonResidue(a) {
|
||||||
return [bigInt(c0), bigInt(c1)];
|
return this.F.mul(this.nonResidue, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(a) {
|
copy(a) {
|
||||||
@ -23,6 +23,10 @@ class F2Field {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double(a) {
|
||||||
|
return this.add(a,a);
|
||||||
|
}
|
||||||
|
|
||||||
sub(a, b) {
|
sub(a, b) {
|
||||||
return [
|
return [
|
||||||
this.F.sub(a[0], b[0]),
|
this.F.sub(a[0], b[0]),
|
||||||
@ -39,7 +43,7 @@ class F2Field {
|
|||||||
const bB = this.F.mul(a[1] , b[1]);
|
const bB = this.F.mul(a[1] , b[1]);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
this.F.add( aA , this.F.mul(this.nonResidue , bB)),
|
this.F.add( aA , this._mulByNonResidue(bB)),
|
||||||
this.F.sub(
|
this.F.sub(
|
||||||
this.F.mul(
|
this.F.mul(
|
||||||
this.F.add(a[0], a[1]),
|
this.F.add(a[0], a[1]),
|
||||||
@ -50,7 +54,7 @@ class F2Field {
|
|||||||
inverse(a) {
|
inverse(a) {
|
||||||
const t0 = this.F.square(a[0]);
|
const t0 = this.F.square(a[0]);
|
||||||
const t1 = this.F.square(a[1]);
|
const t1 = this.F.square(a[1]);
|
||||||
const t2 = this.F.sub(t0, this.F.mul(this.nonResidue, t1));
|
const t2 = this.F.sub(t0, this._mulByNonResidue(t1));
|
||||||
const t3 = this.F.inverse(t2);
|
const t3 = this.F.inverse(t2);
|
||||||
return [
|
return [
|
||||||
this.F.mul(a[0], t3),
|
this.F.mul(a[0], t3),
|
||||||
@ -77,10 +81,10 @@ class F2Field {
|
|||||||
this.F.add(a[0], a[1]) ,
|
this.F.add(a[0], a[1]) ,
|
||||||
this.F.add(
|
this.F.add(
|
||||||
a[0] ,
|
a[0] ,
|
||||||
this.F.mul(this.nonResidue , a[1]))),
|
this._mulByNonResidue(a[1]))),
|
||||||
this.F.add(
|
this.F.add(
|
||||||
ab,
|
ab,
|
||||||
this.F.mul(this.nonResidue, ab))),
|
this._mulByNonResidue(ab))),
|
||||||
this.F.add(ab, ab)
|
this.F.add(ab, ab)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -97,6 +101,14 @@ class F2Field {
|
|||||||
return [this.F.affine(a[0]), this.F.affine(a[1])];
|
return [this.F.affine(a[0]), this.F.affine(a[1])];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mulEscalar(base, e) {
|
||||||
|
return fUtils.mulEscalar(this, base, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
exp(base, e) {
|
||||||
|
return fUtils.exp(this, base, e);
|
||||||
|
}
|
||||||
|
|
||||||
toString(a) {
|
toString(a) {
|
||||||
const cp = this.affine(a);
|
const cp = this.affine(a);
|
||||||
return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
|
return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
|
||||||
|
158
src/f3field.js
Normal file
158
src/f3field.js
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
const fUtils = require("./futils.js");
|
||||||
|
|
||||||
|
class F3Field {
|
||||||
|
constructor(F, nonResidue) {
|
||||||
|
this.F = F;
|
||||||
|
this.zero = [this.F.zero, this.F.zero, this.F.zero];
|
||||||
|
this.one = [this.F.one, this.F.zero, this.F.zero];
|
||||||
|
this.nonResidue = nonResidue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mulByNonResidue(a) {
|
||||||
|
return this.F.mul(this.nonResidue, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(a) {
|
||||||
|
return [this.F.copy(a[0]), this.F.copy(a[1]), this.F.copy(a[2])];
|
||||||
|
}
|
||||||
|
|
||||||
|
add(a, b) {
|
||||||
|
return [
|
||||||
|
this.F.add(a[0], b[0]),
|
||||||
|
this.F.add(a[1], b[1]),
|
||||||
|
this.F.add(a[2], b[2])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
double(a) {
|
||||||
|
return this.add(a,a);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub(a, b) {
|
||||||
|
return [
|
||||||
|
this.F.sub(a[0], b[0]),
|
||||||
|
this.F.sub(a[1], b[1]),
|
||||||
|
this.F.sub(a[2], b[2])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
neg(a) {
|
||||||
|
return this.sub(this.zero, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
mul(a, b) {
|
||||||
|
|
||||||
|
const aA = this.F.mul(a[0] , b[0]);
|
||||||
|
const bB = this.F.mul(a[1] , b[1]);
|
||||||
|
const cC = this.F.mul(a[2] , b[2]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.F.add(
|
||||||
|
aA,
|
||||||
|
this._mulByNonResidue(
|
||||||
|
this.F.sub(
|
||||||
|
this.F.mul(
|
||||||
|
this.F.add(a[1], a[2]),
|
||||||
|
this.F.add(b[1], b[2])),
|
||||||
|
this.F.add(bB, cC)))), // aA + non_residue*((b+c)*(B+C)-bB-cC),
|
||||||
|
|
||||||
|
this.F.add(
|
||||||
|
this.F.sub(
|
||||||
|
this.F.mul(
|
||||||
|
this.F.add(a[0], a[1]),
|
||||||
|
this.F.add(b[0], b[1])),
|
||||||
|
this.F.add(aA, bB)),
|
||||||
|
this._mulByNonResidue( cC)), // (a+b)*(A+B)-aA-bB+non_residue*cC
|
||||||
|
|
||||||
|
this.F.add(
|
||||||
|
this.F.sub(
|
||||||
|
this.F.mul(
|
||||||
|
this.F.add(a[0], a[2]),
|
||||||
|
this.F.add(b[0], b[2])),
|
||||||
|
this.F.add(aA, cC)),
|
||||||
|
bB)]; // (a+c)*(A+C)-aA+bB-cC)
|
||||||
|
}
|
||||||
|
|
||||||
|
inverse(a) {
|
||||||
|
const t0 = this.F.square(a[0]); // t0 = a^2 ;
|
||||||
|
const t1 = this.F.square(a[1]); // t1 = b^2 ;
|
||||||
|
const t2 = this.F.square(a[2]); // t2 = c^2;
|
||||||
|
const t3 = this.F.mul(a[0],a[1]); // t3 = ab
|
||||||
|
const t4 = this.F.mul(a[0],a[2]); // t4 = ac
|
||||||
|
const t5 = this.F.mul(a[1],a[2]); // t5 = bc;
|
||||||
|
// c0 = t0 - non_residue * t5;
|
||||||
|
const c0 = this.F.sub(t0, this._mulByNonResidue(t5));
|
||||||
|
// c1 = non_residue * t2 - t3;
|
||||||
|
const c1 = this.F.sub(this._mulByNonResidue(t2), t3);
|
||||||
|
const c2 = this.F.sub(t1, t4); // c2 = t1-t4
|
||||||
|
|
||||||
|
// t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inverse();
|
||||||
|
const t6 =
|
||||||
|
this.F.inverse(
|
||||||
|
this.F.add(
|
||||||
|
this.F.mul(a[0], c0),
|
||||||
|
this._mulByNonResidue(
|
||||||
|
this.F.add(
|
||||||
|
this.F.mul(a[2], c1),
|
||||||
|
this.F.mul(a[1], c2)))));
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.F.mul(t6, c0), // t6*c0
|
||||||
|
this.F.mul(t6, c1), // t6*c1
|
||||||
|
this.F.mul(t6, c2)]; // t6*c2
|
||||||
|
}
|
||||||
|
|
||||||
|
div(a, b) {
|
||||||
|
return this.mul(a, this.inverse(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
square(a) {
|
||||||
|
const s0 = this.F.square(a[0]); // s0 = a^2
|
||||||
|
const ab = this.F.mul(a[0], a[1]); // ab = a*b
|
||||||
|
const s1 = this.F.add(ab, ab); // s1 = 2ab;
|
||||||
|
const s2 = this.F.square(
|
||||||
|
this.F.add(this.F.sub(a[0],a[1]), a[2])); // s2 = (a - b + c)^2;
|
||||||
|
const bc = this.F.mul(a[1],a[2]); // bc = b*c
|
||||||
|
const s3 = this.F.add(bc, bc); // s3 = 2*bc
|
||||||
|
const s4 = this.F.square(a[2]); // s4 = c^2
|
||||||
|
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.F.add(
|
||||||
|
s0,
|
||||||
|
this._mulByNonResidue(s3)), // s0 + non_residue * s3,
|
||||||
|
this.F.add(
|
||||||
|
s1,
|
||||||
|
this._mulByNonResidue(s4)), // s1 + non_residue * s4,
|
||||||
|
this.F.sub(
|
||||||
|
this.F.add( this.F.add(s1, s2) , s3 ),
|
||||||
|
this.F.add(s0, s4))]; // s1 + s2 + s3 - s0 - s4
|
||||||
|
}
|
||||||
|
|
||||||
|
isZero(a) {
|
||||||
|
return this.F.isZero(a[0]) && this.F.isZero(a[1]) && this.F.isZero(a[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
equals(a, b) {
|
||||||
|
return this.F.equals(a[0], b[0]) && this.F.equals(a[1], b[1]) && this.F.equals(a[2], b[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
affine(a) {
|
||||||
|
return [this.F.affine(a[0]), this.F.affine(a[1]), this.F.affine(a[2])];
|
||||||
|
}
|
||||||
|
|
||||||
|
mulEscalar(base, e) {
|
||||||
|
return fUtils.mulEscalar(this, base, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
exp(base, e) {
|
||||||
|
return fUtils.exp(this, base, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(a) {
|
||||||
|
const cp = this.affine(a);
|
||||||
|
return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])}, ${this.F.toString(cp[2])} ]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = F3Field;
|
34
src/futils.js
Normal file
34
src/futils.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const bigInt = require("big-integer");
|
||||||
|
|
||||||
|
exports.mulEscalar = (F, base, e) =>{
|
||||||
|
let res = F.zero;
|
||||||
|
let rem = bigInt(e);
|
||||||
|
let exp = base;
|
||||||
|
|
||||||
|
while (! rem.isZero()) {
|
||||||
|
if (rem.isOdd()) {
|
||||||
|
res = F.add(res, exp);
|
||||||
|
}
|
||||||
|
exp = F.double(exp);
|
||||||
|
rem = rem.shiftRight(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
exports.exp = (F, base, e) =>{
|
||||||
|
let res = F.one;
|
||||||
|
let rem = bigInt(e);
|
||||||
|
let exp = base;
|
||||||
|
|
||||||
|
while (! rem.isZero()) {
|
||||||
|
if (rem.isOdd()) {
|
||||||
|
res = F.mul(res, exp);
|
||||||
|
}
|
||||||
|
exp = F.square(exp);
|
||||||
|
rem = rem.shiftRight(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
const fUtils = require("./futils.js");
|
||||||
|
|
||||||
class GCurve {
|
class GCurve {
|
||||||
|
|
||||||
@ -105,19 +106,7 @@ class GCurve {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mulEscalar(base, e) {
|
mulEscalar(base, e) {
|
||||||
let res = this.zero;
|
return fUtils.mulEscalar(this, base, e);
|
||||||
let rem = e;
|
|
||||||
let exp = base;
|
|
||||||
|
|
||||||
while (! rem.isZero()) {
|
|
||||||
if (rem.isOdd()) {
|
|
||||||
res = this.add(res, exp);
|
|
||||||
}
|
|
||||||
exp = this.double(exp);
|
|
||||||
rem = rem.shiftRight(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
affine(p) {
|
affine(p) {
|
||||||
|
20
src/gt.js
20
src/gt.js
@ -1,20 +0,0 @@
|
|||||||
const bigInt = require("big-integer");
|
|
||||||
const ZnField = require("./znfield.js");
|
|
||||||
|
|
||||||
module.eports = class Gt {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
mul(p1, p2) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
|
|
||||||
equal(p1, p2) {
|
|
||||||
// TODO
|
|
||||||
throw new Error("Not Implementted");
|
|
||||||
}
|
|
||||||
};
|
|
@ -4,11 +4,10 @@ This module calculate the pairing of p1 and p2 where p1 in G1 and p2 in G2
|
|||||||
|
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
const F1Field = require("f1field");
|
const F1Field = require("./f1field");
|
||||||
const F2Field = require("f2field");
|
const F2Field = require("./f2field");
|
||||||
const F12Field = require("f12field");
|
const F3Field = require("./f3field");
|
||||||
const G1Curve = require("g1curve");
|
const GCurve = require("./gcurve");
|
||||||
const G2Curve = require("g2curve");
|
|
||||||
const constants = require("constants");
|
const constants = require("constants");
|
||||||
|
|
||||||
module.exports = new Pairing();
|
module.exports = new Pairing();
|
||||||
@ -16,8 +15,8 @@ module.exports = new Pairing();
|
|||||||
|
|
||||||
class Pairing {
|
class Pairing {
|
||||||
|
|
||||||
constructor() {
|
constructor(curve) {
|
||||||
this.loopCount = bigInt(11);// CONSTANT
|
this.loopCount = bigInt("29793968203157093288");// CONSTANT
|
||||||
|
|
||||||
// Set loopCountNeg
|
// Set loopCountNeg
|
||||||
if (this.loopCount.isNegative()) {
|
if (this.loopCount.isNegative()) {
|
||||||
@ -30,18 +29,17 @@ class Pairing {
|
|||||||
// Set loop_count_bits
|
// Set loop_count_bits
|
||||||
let lc = this.loopCount;
|
let lc = this.loopCount;
|
||||||
this.loop_count_bits = []; // Constant
|
this.loop_count_bits = []; // Constant
|
||||||
while (lc) {
|
while (!lc.isZero()) {
|
||||||
this.loop_count_bits.push( lc.isOdd() );
|
this.loop_count_bits.push( lc.isOdd() );
|
||||||
lc = lc.shiftRight(1);
|
lc = lc.shiftRight(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.F12 = new F12Field(constants.q);
|
this.F1 = curve.F1;
|
||||||
this.F2 = new F2Field(constants.q);
|
this.F2 = curve.F2;
|
||||||
this.F1 = new F1Field(constants.q);
|
this.G1 = curve.G1;
|
||||||
this.G1 = new GCurve(F1, constants.g1);
|
this.G2 = curve.G2;
|
||||||
this.G2 = new GCurve(F2, constants.g2);
|
this.F6 = curve.F6;
|
||||||
|
this.F12 = curve.F12;
|
||||||
this.twoInv = this.F1.inverse(bigInt(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pairing(p1, p2) {
|
pairing(p1, p2) {
|
||||||
@ -134,7 +132,7 @@ class Pairing {
|
|||||||
|
|
||||||
c = pre2.coeffs[idx++];
|
c = pre2.coeffs[idx++];
|
||||||
f = this.F12.square(f);
|
f = this.F12.square(f);
|
||||||
f = this.F12.mul_by_024(
|
f = this._mul_by_024(
|
||||||
f,
|
f,
|
||||||
c.ell_0,
|
c.ell_0,
|
||||||
this.F2.mul(pre1.PY, c.ell_VW),
|
this.F2.mul(pre1.PY, c.ell_VW),
|
||||||
@ -143,7 +141,7 @@ class Pairing {
|
|||||||
if (bit)
|
if (bit)
|
||||||
{
|
{
|
||||||
c = pre2.coeffs[idx++];
|
c = pre2.coeffs[idx++];
|
||||||
f = this.F12.mul_by_024(
|
f = this._mul_by_024(
|
||||||
f,
|
f,
|
||||||
c.ell_0,
|
c.ell_0,
|
||||||
this.F2.mul(pre1.PY, c.ell_VW),
|
this.F2.mul(pre1.PY, c.ell_VW),
|
||||||
@ -158,14 +156,14 @@ class Pairing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c = pre2.coeffs[idx++];
|
c = pre2.coeffs[idx++];
|
||||||
f = this.F12.mul_by_024(
|
f = this._mul_by_024(
|
||||||
f,
|
f,
|
||||||
c.ell_0,
|
c.ell_0,
|
||||||
this.F2.mul(pre1.PY, c.ell_VW),
|
this.F2.mul(pre1.PY, c.ell_VW),
|
||||||
this.F2.mul(pre1.PX, c.ell_VV));
|
this.F2.mul(pre1.PX, c.ell_VV));
|
||||||
|
|
||||||
c = pre2.coeffs[idx++];
|
c = pre2.coeffs[idx++];
|
||||||
f = this.F12.mul_by_024(
|
f = this._mul_by_024(
|
||||||
f,
|
f,
|
||||||
c.ell_0,
|
c.ell_0,
|
||||||
this.F2.mul(pre1.PY, c.ell_VW),
|
this.F2.mul(pre1.PY, c.ell_VW),
|
||||||
@ -250,4 +248,16 @@ class Pairing {
|
|||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_mul_by_024(a, ell_0, ell_VW, ell_VV) {
|
||||||
|
|
||||||
|
const b = [
|
||||||
|
[ell_0, this.F2.zero, ell_VV],
|
||||||
|
[this.F2.zero, ell_VW, this.F2.zero]
|
||||||
|
];
|
||||||
|
|
||||||
|
return this.F12.mul(a,b);
|
||||||
|
|
||||||
|
// TODO There is a better version on libff. It should be ported.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
139
test/algebra.js
139
test/algebra.js
@ -1,72 +1,151 @@
|
|||||||
const bigInt = require("big-integer");
|
|
||||||
const F1Field = require("../src/f1field.js");
|
|
||||||
const F2Field = require("../src/f2field.js");
|
|
||||||
const GCurve = require("../src/gcurve.js");
|
|
||||||
const constants = require("../src/constants.js");
|
|
||||||
const chai = require("chai");
|
const chai = require("chai");
|
||||||
|
|
||||||
|
const bigInt = require("big-integer");
|
||||||
|
const BN128 = require("../src/BN128.js");
|
||||||
|
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
|
|
||||||
describe("Curve G1 Test", () => {
|
describe("Curve G1 Test", () => {
|
||||||
it ("r*one == 0", () => {
|
it("r*one == 0", () => {
|
||||||
const F1 = new F1Field(constants.q);
|
const bn128 = new BN128();
|
||||||
const G1 = new GCurve(F1, constants.g1);
|
|
||||||
|
|
||||||
const res = G1.mulEscalar(G1.g, constants.r);
|
const res = bn128.G1.mulEscalar(bn128.G1.g, bn128.r);
|
||||||
|
|
||||||
assert(G1.equals(res, G1.zero), "G1 does not have range r");
|
assert(bn128.G1.equals(res, bn128.G1.zero), "G1 does not have range r");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should add match in various in G1", () => {
|
it("Should add match in various in G1", () => {
|
||||||
const F1 = new F1Field(constants.q);
|
|
||||||
const G1 = new GCurve(F1, constants.g1);
|
const bn128 = new BN128();
|
||||||
|
|
||||||
const r1 = bigInt(33);
|
const r1 = bigInt(33);
|
||||||
const r2 = bigInt(44);
|
const r2 = bigInt(44);
|
||||||
|
|
||||||
const gr1 = G1.mulEscalar(G1.g, r1);
|
const gr1 = bn128.G1.mulEscalar(bn128.G1.g, r1);
|
||||||
const gr2 = G1.mulEscalar(G1.g, r2);
|
const gr2 = bn128.G1.mulEscalar(bn128.G1.g, r2);
|
||||||
|
|
||||||
const grsum1 = G1.add(gr1, gr2);
|
const grsum1 = bn128.G1.add(gr1, gr2);
|
||||||
|
|
||||||
const grsum2 = G1.mulEscalar(G1.g, r1.add(r2));
|
const grsum2 = bn128.G1.mulEscalar(bn128.G1.g, r1.add(r2));
|
||||||
|
|
||||||
assert(G1.equals(grsum1, grsum2));
|
assert(bn128.G1.equals(grsum1, grsum2));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Curve G2 Test", () => {
|
describe("Curve G2 Test", () => {
|
||||||
it ("r*one == 0", () => {
|
it ("r*one == 0", () => {
|
||||||
const F1 = new F1Field(constants.q);
|
const bn128 = new BN128();
|
||||||
const F2 = new F2Field(F1, constants.f2nonResidue);
|
|
||||||
const G2 = new GCurve(F2, constants.g2);
|
|
||||||
|
|
||||||
const res = G2.mulEscalar(G2.g, constants.r);
|
const res = bn128.G2.mulEscalar(bn128.G2.g, bn128.r);
|
||||||
|
|
||||||
assert(G2.equals(res, G2.zero), "G2 does not have range r");
|
assert(bn128.G2.equals(res, bn128.G2.zero), "G2 does not have range r");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should add match in various in G2", () => {
|
it("Should add match in various in G2", () => {
|
||||||
const F1 = new F1Field(constants.q);
|
const bn128 = new BN128();
|
||||||
const F2 = new F2Field(F1, constants.f2nonResidue);
|
|
||||||
const G2 = new GCurve(F2, constants.g2);
|
|
||||||
|
|
||||||
const r1 = bigInt(33);
|
const r1 = bigInt(33);
|
||||||
const r2 = bigInt(44);
|
const r2 = bigInt(44);
|
||||||
|
|
||||||
const gr1 = G2.mulEscalar(G2.g, r1);
|
const gr1 = bn128.G2.mulEscalar(bn128.G2.g, r1);
|
||||||
const gr2 = G2.mulEscalar(G2.g, r2);
|
const gr2 = bn128.G2.mulEscalar(bn128.G2.g, r2);
|
||||||
|
|
||||||
const grsum1 = G2.add(gr1, gr2);
|
const grsum1 = bn128.G2.add(gr1, gr2);
|
||||||
|
|
||||||
const grsum2 = G2.mulEscalar(G2.g, r1.add(r2));
|
const grsum2 = bn128.G2.mulEscalar(bn128.G2.g, r1.add(r2));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
console.log(G2.toString(grsum1));
|
console.log(G2.toString(grsum1));
|
||||||
console.log(G2.toString(grsum2));
|
console.log(G2.toString(grsum2));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert(G2.equals(grsum1, grsum2));
|
assert(bn128.G2.equals(grsum1, grsum2));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("F6 testing", () => {
|
||||||
|
it("Should multiply and divide in F6", () => {
|
||||||
|
const bn128 = new BN128();
|
||||||
|
const a =
|
||||||
|
[
|
||||||
|
[bigInt("1"), bigInt("2")],
|
||||||
|
[bigInt("3"), bigInt("4")],
|
||||||
|
[bigInt("5"), bigInt("6")]
|
||||||
|
];
|
||||||
|
const b =
|
||||||
|
[
|
||||||
|
[bigInt("12"), bigInt("11")],
|
||||||
|
[bigInt("10"), bigInt("9")],
|
||||||
|
[bigInt("8"), bigInt("7")]
|
||||||
|
];
|
||||||
|
const c = bn128.F6.mul(a,b);
|
||||||
|
const d = bn128.F6.div(c,b);
|
||||||
|
|
||||||
|
assert(bn128.F6.equals(a, d));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("F12 testing", () => {
|
||||||
|
it("Should multiply and divide in F12", () => {
|
||||||
|
const bn128 = new BN128();
|
||||||
|
const a =
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[bigInt("1"), bigInt("2")],
|
||||||
|
[bigInt("3"), bigInt("4")],
|
||||||
|
[bigInt("5"), bigInt("6")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[bigInt("7"), bigInt("8")],
|
||||||
|
[bigInt("9"), bigInt("10")],
|
||||||
|
[bigInt("11"), bigInt("12")]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
const b =
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[bigInt("12"), bigInt("11")],
|
||||||
|
[bigInt("10"), bigInt("9")],
|
||||||
|
[bigInt("8"), bigInt("7")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[bigInt("6"), bigInt("5")],
|
||||||
|
[bigInt("4"), bigInt("3")],
|
||||||
|
[bigInt("2"), bigInt("1")]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
const c = bn128.F12.mul(a,b);
|
||||||
|
const d = bn128.F12.div(c,b);
|
||||||
|
|
||||||
|
assert(bn128.F12.equals(a, d));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Pairing", () => {
|
||||||
|
it("Should match pairing", () => {
|
||||||
|
const bn128 = new BN128();
|
||||||
|
|
||||||
|
|
||||||
|
const g1a = bn128.G1.mulEscalar(bn128.G1.g, 25);
|
||||||
|
const g2a = bn128.G2.mulEscalar(bn128.G2.g, 30);
|
||||||
|
|
||||||
|
const g1b = bn128.G1.mulEscalar(bn128.G1.g, 30);
|
||||||
|
const g2b = bn128.G2.mulEscalar(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 r1 = bn128.millerLoop(pre1a, pre2a);
|
||||||
|
const r2 = bn128.millerLoop(pre1b, pre2b);
|
||||||
|
|
||||||
|
const rbe = bn128.F12.mul(r1, bn128.F12.inverse(r2));
|
||||||
|
|
||||||
|
const res = bn128.finalExponentiation(rbe);
|
||||||
|
|
||||||
|
assert(bn128.F12.equals(res, bn128.F12.one));
|
||||||
|
}).timeout(10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user