diff --git a/src/ff.ts b/src/ff.ts index 3b7d5ec..d74dc0c 100644 --- a/src/ff.ts +++ b/src/ff.ts @@ -78,14 +78,10 @@ export interface Field { } export class Fq implements Field { - x: bigint + value: bigint constructor(x: bigint) { - this.x = mod(x, P) - } - - static fromTuple([x]: bigint[]): Fq { - return new Fq(x) + this.value = mod(x, P) } static zero(): Fq { @@ -93,31 +89,31 @@ export class Fq implements Field { } equals(rhs: Fq): boolean { - return this.x === rhs.x + return this.value === rhs.value } lt(rhs: Fq): boolean { - return this.x < rhs.x + return this.value < rhs.value } add(rhs: Fq): Fq { - return new Fq(this.x + rhs.x) + return new Fq(this.value + rhs.value) } sub(rhs: Fq): Fq { - return new Fq(this.x - rhs.x) + return new Fq(this.value - rhs.value) } neg(): Fq { - return new Fq(-this.x) + return new Fq(-this.value) } mul(rhs: Fq): Fq { - return new Fq(this.x * rhs.x) + return new Fq(this.value * rhs.value) } mulByScalar(c: bigint): Fq { - return new Fq(this.x * c) + return new Fq(this.value * c) } mulByNonResidue(): Fq { @@ -125,10 +121,10 @@ export class Fq implements Field { } inv() { - if (this.x === 0n) { + if (this.value === 0n) { throw new Error(`Inversion of zero`) } - return new Fq(gcd(this.x, P, 1n, 0n, P)) + return new Fq(gcd(this.value, P, 1n, 0n, P)) } exp(y: bigint): Fq { @@ -170,12 +166,12 @@ export class Fq implements Field { } toString() { - return `(Fq ${this.x.toString()})` + return `(Fq ${this.value.toString()})` } toJSON() { return { - x: this.x.toString(), + x: this.value.toString(), } } } @@ -220,11 +216,11 @@ export class Fq2 implements Field { } gt(rhs: Fq2): boolean { - return this.x.x > rhs.x.x && this.y.x > rhs.y.x + return this.x.value > rhs.x.value && this.y.value > rhs.y.value } lt(rhs: Fq2): boolean { - return this.x.x < rhs.x.x && this.y.x < rhs.y.x + return this.x.value < rhs.x.value && this.y.value < rhs.y.value } add(rhs: Fq2): Fq2 { @@ -320,10 +316,12 @@ export class Fq2 implements Field { } toTuple(): [bigint, bigint] { - return [this.x.x, this.y.x] + return [this.x.value, this.y.value] } } +type Fq2Tuple = ReturnType + /// Cubic extension to Fq2 export class Fq6 implements Field { x: Fq2 @@ -335,20 +333,20 @@ export class Fq6 implements Field { this.z = z } - static fromTuple([x, y, z]: [Fq2, Fq2, Fq2]): Fq6 { - return new Fq6(x, y, z) + static fromTuple([x, y, z]: [Fq2Tuple, Fq2Tuple, Fq2Tuple]): Fq6 { + return new Fq6(Fq2.fromTuple(x), Fq2.fromTuple(y), Fq2.fromTuple(z)) } static fromNumber(n: bigint): Fq6 { - return Fq6.fromTuple([Fq2.fromNumber(n), Fq2.zero(), Fq2.zero()]) + return new Fq6(Fq2.fromNumber(n), Fq2.zero(), Fq2.zero()) } static zero(): Fq6 { - return Fq6.fromTuple([Fq2.zero(), Fq2.zero(), Fq2.zero()]) + return new Fq6(Fq2.zero(), Fq2.zero(), Fq2.zero()) } static one(): Fq6 { - return Fq6.fromTuple([Fq2.one(), Fq2.zero(), Fq2.zero()]) + return new Fq6(Fq2.one(), Fq2.zero(), Fq2.zero()) } equals(rhs: Fq6): boolean { @@ -397,7 +395,7 @@ export class Fq6 implements Field { } mulByNonResidue(): Fq6 { - return Fq6.fromTuple([this.z.mulByNonResidue(), this.x, this.y]) + return new Fq6(this.z.mulByNonResidue(), this.x, this.y) } inv(): Fq6 { @@ -412,7 +410,7 @@ export class Fq6 implements Field { .add(a2.mul(t1).mulByNonResidue()) .add(a1.mul(t2).mulByNonResidue()) .inv() - return Fq6.fromTuple([t0.mul(factor), t1.mul(factor), t2.mul(factor)]) + return new Fq6(t0.mul(factor), t1.mul(factor), t2.mul(factor)) } toString() { @@ -436,6 +434,8 @@ export class Fq6 implements Field { } } +type Fq6Tuple = ReturnType + /// 12th degree extension to Fq export class Fq12 implements Field { x: Fq6 @@ -445,20 +445,20 @@ export class Fq12 implements Field { this.y = y } - static fromTuple([x, y]: [Fq6, Fq6]): Fq12 { - return new Fq12(x, y) + static fromTuple([x, y]: [Fq6Tuple, Fq6Tuple]): Fq12 { + return new Fq12(Fq6.fromTuple(x), Fq6.fromTuple(y)) } static fromNumber(n: bigint): Fq12 { - return Fq12.fromTuple([Fq6.fromNumber(n), Fq6.zero()]) + return new Fq12(Fq6.fromNumber(n), Fq6.zero()) } static zero(): Fq12 { - return Fq12.fromTuple([Fq6.zero(), Fq6.zero()]) + return new Fq12(Fq6.zero(), Fq6.zero()) } static one(): Fq12 { - return Fq12.fromTuple([Fq6.one(), Fq6.zero()]) + return new Fq12(Fq6.one(), Fq6.zero()) } equals(rhs: Fq12): boolean { @@ -517,7 +517,7 @@ export class Fq12 implements Field { } } - toTuple(): [ReturnType, ReturnType] { + toTuple(): [Fq6Tuple, Fq6Tuple] { return [this.x.toTuple(), this.y.toTuple()] } } diff --git a/src/pairing.ts b/src/pairing.ts index 66e1697..f3cab54 100644 --- a/src/pairing.ts +++ b/src/pairing.ts @@ -86,17 +86,17 @@ function lineDouble(r: PointG2, p: PointG1): Fq12 { .mul(Fq12.fromNumber(3n)) .mul(wideR.y.mul(Fq12.fromNumber(2n)).inv()) const v = wideR.y.sub(slope.mul(wideR.x)) - return Fq12.fromNumber(p.y.x).sub(Fq12.fromNumber(p.x.x).mul(slope)).sub(v) + return Fq12.fromNumber(p.y.value).sub(Fq12.fromNumber(p.x.value).mul(slope)).sub(v) } function lineAdd(r: PointG2, q: PointG2, p: PointG1): Fq12 { const wideR = r.untwist() const wideQ = q.untwist() if (wideR.x.equals(wideQ.x) && wideR.y.equals(wideQ.y.neg())) { - return Fq12.fromNumber(p.x.x).sub(wideR.x) + return Fq12.fromNumber(p.x.value).sub(wideR.x) } else { const slope = wideQ.y.sub(wideR.y).mul(wideQ.x.sub(wideR.x).inv()) const v = wideQ.y.mul(wideR.x).sub(wideR.y.mul(wideQ.x)).mul(wideR.x.sub(wideQ.x).inv()) - return Fq12.fromNumber(p.y.x).sub(Fq12.fromNumber(p.x.x).mul(slope)).sub(v) + return Fq12.fromNumber(p.y.value).sub(Fq12.fromNumber(p.x.value).mul(slope)).sub(v) } } diff --git a/src/point.ts b/src/point.ts index acbd616..eab8584 100644 --- a/src/point.ts +++ b/src/point.ts @@ -323,14 +323,14 @@ export class PointG2 implements PointInstanceType { untwist(): PointGT { const x1 = this.x const y1 = this.y - const root = Fq6.fromTuple([Fq2.zero(), Fq2.one(), Fq2.zero()]) + const root = new Fq6(Fq2.zero(), Fq2.one(), Fq2.zero()) // wideX = [ Fq12 (Fq6 x1 0 0) 0 ] * inv (Fq12 root 0) - const wideX = Fq12.fromTuple([Fq6.fromTuple([x1, Fq2.zero(), Fq2.zero()]), Fq6.zero()]).mul( - Fq12.fromTuple([root, Fq6.zero()]).inv(), + const wideX = new Fq12(new Fq6(x1, Fq2.zero(), Fq2.zero()), Fq6.zero()).mul( + new Fq12(root, Fq6.zero()).inv(), ) // wideY = [ Fq12 (Fq6 y1 0 0) 0 ] * inv (Fq12 0 root) - const wideY = Fq12.fromTuple([Fq6.fromTuple([y1, Fq2.zero(), Fq2.zero()]), Fq6.zero()]).mul( - Fq12.fromTuple([Fq6.zero(), root]).inv(), + const wideY = new Fq12(new Fq6(y1, Fq2.zero(), Fq2.zero()), Fq6.zero()).mul( + new Fq12(Fq6.zero(), root).inv(), ) return new PointGT(wideX, wideY) } diff --git a/src/utils.ts b/src/utils.ts index dfd6a58..b9a6d80 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,11 +1,11 @@ import { Fq, Fq12, Fq2, Fq6, P } from './ff' export function randomFq12(): Fq12 { - return Fq12.fromTuple([randomFq6(), randomFq6()]) + return new Fq12(randomFq6(), randomFq6()) } export function randomFq6(): Fq6 { - return Fq6.fromTuple([randomFq2(), randomFq2(), randomFq2()]) + return new Fq6(randomFq2(), randomFq2(), randomFq2()) } export function randomFq2(): Fq2 { diff --git a/test/bls.spec.ts b/test/bls.spec.ts index 2f60ae6..de2e98c 100644 --- a/test/bls.spec.ts +++ b/test/bls.spec.ts @@ -27,10 +27,10 @@ describe('BLS', () => { it('hashToPoint', () => { const p = hashToPoint(dst, messageBytes) - expect(p.x.x).to.eq( + expect(p.x.value).to.eq( 1198910066326735622577680242831393390970801051978648777282080468606313680859600948581997698323043835646099437524846n, ) - expect(p.y.x).to.eq( + expect(p.y.value).to.eq( 2057868841575584746120388979277317449872305248232397789541047611599466400564636994006407901750858857388914134998050n, ) }) diff --git a/test/ff.spec.ts b/test/ff.spec.ts index 74a7022..c58adf2 100644 --- a/test/ff.spec.ts +++ b/test/ff.spec.ts @@ -103,7 +103,7 @@ describe('finite fields', () => { for (const [x, y, z] of testVectors) { const a = new Fq(x) const b = new Fq(y) - expect(a.add(b).x).to.equal(z) + expect(a.add(b).value).to.equal(z) } }) @@ -112,7 +112,7 @@ describe('finite fields', () => { for (const [x, y, z] of testVectors) { const a = new Fq(x) const b = new Fq(y) - expect(a.sub(b).x).to.equal(z) + expect(a.sub(b).value).to.equal(z) } }) @@ -121,7 +121,7 @@ describe('finite fields', () => { for (const [x, y, z] of testVectors) { const a = new Fq(x) const b = new Fq(y) - expect(a.mul(b).x).to.equal(z) + expect(a.mul(b).value).to.equal(z) } }) @@ -132,7 +132,7 @@ describe('finite fields', () => { ) for (const [x, z] of testVectors) { const a = new Fq(x) - expect(a.inv().x).to.equal(z) + expect(a.inv().value).to.equal(z) } }) }) @@ -144,8 +144,8 @@ describe('finite fields', () => { const a = Fq2.fromTuple(x) const b = Fq2.fromTuple(y) const result = a.add(b) - expect(result.x.x).to.eq(z[0]) - expect(result.y.x).to.eq(z[1]) + expect(result.x.value).to.eq(z[0]) + expect(result.y.value).to.eq(z[1]) } }) @@ -162,8 +162,8 @@ describe('finite fields', () => { const a = Fq2.fromTuple(x) const b = Fq2.fromTuple(y) const result = a.sub(b) - expect(result.x.x).to.eq(z[0]) - expect(result.y.x).to.eq(z[1]) + expect(result.x.value).to.eq(z[0]) + expect(result.y.value).to.eq(z[1]) } }) @@ -173,8 +173,8 @@ describe('finite fields', () => { const a = Fq2.fromTuple(x) const b = Fq2.fromTuple(y) const result = a.mul(b) - expect(result.x.x).to.eq(z[0]) - expect(result.y.x).to.eq(z[1]) + expect(result.x.value).to.eq(z[0]) + expect(result.y.value).to.eq(z[1]) } }) }) @@ -183,78 +183,30 @@ describe('finite fields', () => { it('add', async () => { const testVectors = await readTestVectors('fp6_add', reviveFq6) for (const [x, y, z] of testVectors) { - const a = Fq6.fromTuple([ - Fq2.fromTuple(x[0]), - Fq2.fromTuple(x[1]), - Fq2.fromTuple(x[2]), - ]) - const b = Fq6.fromTuple([ - Fq2.fromTuple(y[0]), - Fq2.fromTuple(y[1]), - Fq2.fromTuple(y[2]), - ]) + const a = Fq6.fromTuple([x[0], x[1], x[2]]) + const b = Fq6.fromTuple([y[0], y[1], y[2]]) const result = a.add(b) - expect( - result.equals( - Fq6.fromTuple([ - Fq2.fromTuple(z[0]), - Fq2.fromTuple(z[1]), - Fq2.fromTuple(z[2]), - ]), - ), - ).to.eq(true) + expect(result.equals(Fq6.fromTuple([z[0], z[1], z[2]]))).to.eq(true) } }) it('sub', async () => { const testVectors = await readTestVectors('fp6_sub', reviveFq6) for (const [x, y, z] of testVectors) { - const a = Fq6.fromTuple([ - Fq2.fromTuple(x[0]), - Fq2.fromTuple(x[1]), - Fq2.fromTuple(x[2]), - ]) - const b = Fq6.fromTuple([ - Fq2.fromTuple(y[0]), - Fq2.fromTuple(y[1]), - Fq2.fromTuple(y[2]), - ]) + const a = Fq6.fromTuple([x[0], x[1], x[2]]) + const b = Fq6.fromTuple([y[0], y[1], y[2]]) const result = a.sub(b) - expect( - result.equals( - Fq6.fromTuple([ - Fq2.fromTuple(z[0]), - Fq2.fromTuple(z[1]), - Fq2.fromTuple(z[2]), - ]), - ), - ).to.eq(true) + expect(result.equals(Fq6.fromTuple([z[0], z[1], z[2]]))).to.eq(true) } }) it('mul', async () => { const testVectors = await readTestVectors('fp6_mul', reviveFq6) for (const [x, y, z] of testVectors) { - const a = Fq6.fromTuple([ - Fq2.fromTuple(x[0]), - Fq2.fromTuple(x[1]), - Fq2.fromTuple(x[2]), - ]) - const b = Fq6.fromTuple([ - Fq2.fromTuple(y[0]), - Fq2.fromTuple(y[1]), - Fq2.fromTuple(y[2]), - ]) + const a = Fq6.fromTuple([x[0], x[1], x[2]]) + const b = Fq6.fromTuple([y[0], y[1], y[2]]) const result = a.mul(b) - expect( - result.equals( - Fq6.fromTuple([ - Fq2.fromTuple(z[0]), - Fq2.fromTuple(z[1]), - Fq2.fromTuple(z[2]), - ]), - ), - ).to.eq(true) + expect(result.equals(Fq6.fromTuple([z[0], z[1], z[2]]))).to.eq(true) } }) }) @@ -267,43 +219,19 @@ describe('finite fields', () => { ) for (const [x, y, z] of testVectors) { const a = Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(x[0][0]), - Fq2.fromTuple(x[0][1]), - Fq2.fromTuple(x[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(x[1][0]), - Fq2.fromTuple(x[1][1]), - Fq2.fromTuple(x[1][2]), - ]), + [x[0][0], x[0][1], x[0][2]], + [x[1][0], x[1][1], x[1][2]], ]) const b = Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(y[0][0]), - Fq2.fromTuple(y[0][1]), - Fq2.fromTuple(y[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(y[1][0]), - Fq2.fromTuple(y[1][1]), - Fq2.fromTuple(y[1][2]), - ]), + [y[0][0], y[0][1], y[0][2]], + [y[1][0], y[1][1], y[1][2]], ]) const result = a.add(b) expect( result.equals( Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(z[0][0]), - Fq2.fromTuple(z[0][1]), - Fq2.fromTuple(z[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(z[1][0]), - Fq2.fromTuple(z[1][1]), - Fq2.fromTuple(z[1][2]), - ]), + [z[0][0], z[0][1], z[0][2]], + [z[1][0], z[1][1], z[1][2]], ]), ), ).to.eq(true) @@ -317,43 +245,19 @@ describe('finite fields', () => { ) for (const [x, y, z] of testVectors) { const a = Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(x[0][0]), - Fq2.fromTuple(x[0][1]), - Fq2.fromTuple(x[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(x[1][0]), - Fq2.fromTuple(x[1][1]), - Fq2.fromTuple(x[1][2]), - ]), + [x[0][0], x[0][1], x[0][2]], + [x[1][0], x[1][1], x[1][2]], ]) const b = Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(y[0][0]), - Fq2.fromTuple(y[0][1]), - Fq2.fromTuple(y[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(y[1][0]), - Fq2.fromTuple(y[1][1]), - Fq2.fromTuple(y[1][2]), - ]), + [y[0][0], y[0][1], y[0][2]], + [y[1][0], y[1][1], y[1][2]], ]) const result = a.sub(b) expect( result.equals( Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(z[0][0]), - Fq2.fromTuple(z[0][1]), - Fq2.fromTuple(z[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(z[1][0]), - Fq2.fromTuple(z[1][1]), - Fq2.fromTuple(z[1][2]), - ]), + [z[0][0], z[0][1], z[0][2]], + [z[1][0], z[1][1], z[1][2]], ]), ), ).to.eq(true) @@ -367,43 +271,19 @@ describe('finite fields', () => { ) for (const [x, y, z] of testVectors) { const a = Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(x[0][0]), - Fq2.fromTuple(x[0][1]), - Fq2.fromTuple(x[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(x[1][0]), - Fq2.fromTuple(x[1][1]), - Fq2.fromTuple(x[1][2]), - ]), + [x[0][0], x[0][1], x[0][2]], + [x[1][0], x[1][1], x[1][2]], ]) const b = Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(y[0][0]), - Fq2.fromTuple(y[0][1]), - Fq2.fromTuple(y[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(y[1][0]), - Fq2.fromTuple(y[1][1]), - Fq2.fromTuple(y[1][2]), - ]), + [y[0][0], y[0][1], y[0][2]], + [y[1][0], y[1][1], y[1][2]], ]) const result = a.mul(b) expect( result.equals( Fq12.fromTuple([ - Fq6.fromTuple([ - Fq2.fromTuple(z[0][0]), - Fq2.fromTuple(z[0][1]), - Fq2.fromTuple(z[0][2]), - ]), - Fq6.fromTuple([ - Fq2.fromTuple(z[1][0]), - Fq2.fromTuple(z[1][1]), - Fq2.fromTuple(z[1][2]), - ]), + [z[0][0], z[0][1], z[0][2]], + [z[1][0], z[1][1], z[1][2]], ]), ), ).to.eq(true) diff --git a/tsconfig.json b/tsconfig.json index 2f5c540..627a3c2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,5 @@ "outDir": "dist", "declaration": true }, - "include": ["./src"], - "exclude": ["**/*.spec.ts"] + "include": ["./src", "test/*.spec.ts"] }