Rename field methods: multiply to mul

This commit is contained in:
Paul Miller 2022-12-27 01:17:11 +00:00
parent 6ffe656871
commit 0277c01efd
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
7 changed files with 302 additions and 298 deletions

@ -42,25 +42,25 @@ const Fp2Add = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({
c1: Fp.add(c1, r1),
});
const Fp2Subtract = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({
c0: Fp.subtract(c0, r0),
c1: Fp.subtract(c1, r1),
c0: Fp.sub(c0, r0),
c1: Fp.sub(c1, r1),
});
const Fp2Multiply = ({ c0, c1 }: Fp2, rhs: Fp2) => {
if (typeof rhs === 'bigint') return { c0: Fp.multiply(c0, rhs), c1: Fp.multiply(c1, rhs) };
if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) };
// (a+bi)(c+di) = (acbd) + (ad+bc)i
const { c0: r0, c1: r1 } = rhs;
let t1 = Fp.multiply(c0, r0); // c0 * o0
let t2 = Fp.multiply(c1, r1); // c1 * o1
let t1 = Fp.mul(c0, r0); // c0 * o0
let t2 = Fp.mul(c1, r1); // c1 * o1
// (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i
const o0 = Fp.subtract(t1, t2);
const o1 = Fp.subtract(Fp.multiply(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
const o0 = Fp.sub(t1, t2);
const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2));
return { c0: o0, c1: o1 };
};
const Fp2Square = ({ c0, c1 }: Fp2) => {
const a = Fp.add(c0, c1);
const b = Fp.subtract(c0, c1);
const b = Fp.sub(c0, c1);
const c = Fp.add(c0, c0);
return { c0: Fp.multiply(a, b), c1: Fp.multiply(c, c1) };
return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) };
};
type Fp2Utils = {
fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2;
@ -94,17 +94,17 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums),
// Normalized
add: Fp2Add,
subtract: Fp2Subtract,
multiply: Fp2Multiply,
sub: Fp2Subtract,
mul: Fp2Multiply,
square: Fp2Square,
// NonNormalized stuff
addN: Fp2Add,
subtractN: Fp2Subtract,
multiplyN: Fp2Multiply,
subN: Fp2Subtract,
mulN: Fp2Multiply,
squareN: Fp2Square,
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
div: (lhs, rhs) =>
Fp2.multiply(lhs, typeof rhs === 'bigint' ? Fp.invert(Fp.create(rhs)) : Fp2.invert(rhs)),
Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.invert(Fp.create(rhs)) : Fp2.invert(rhs)),
invert: ({ c0: a, c1: b }) => {
// We wish to find the multiplicative inverse of a nonzero
// element a + bu in Fp2. We leverage an identity
@ -120,7 +120,7 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
// of (a + bu). Importantly, this can be computing using
// only a single inversion in Fp.
const factor = Fp.invert(Fp.create(a * a + b * b));
return { c0: Fp.multiply(factor, Fp.create(a)), c1: Fp.multiply(factor, Fp.create(-b)) };
return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) };
},
sqrt: (num) => {
// TODO: Optimize this line. It's extremely slow.
@ -156,12 +156,12 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
// }
reim: ({ c0, c1 }) => ({ re: c0, im: c1 }),
// multiply by u + 1
mulByNonresidue: ({ c0, c1 }) => ({ c0: Fp.subtract(c0, c1), c1: Fp.add(c0, c1) }),
mulByNonresidue: ({ c0, c1 }) => ({ c0: Fp.sub(c0, c1), c1: Fp.add(c0, c1) }),
multiplyByB: ({ c0, c1 }) => {
let t0 = Fp.multiply(c0, 4n); // 4 * c0
let t1 = Fp.multiply(c1, 4n); // 4 * c1
let t0 = Fp.mul(c0, 4n); // 4 * c0
let t1 = Fp.mul(c1, 4n); // 4 * c1
// (T0-T1) + (T0+T1)*i
return { c0: Fp.subtract(t0, t1), c1: Fp.add(t0, t1) };
return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) };
},
fromBigTuple: (tuple: BigintTuple | bigint[]) => {
if (tuple.length !== 2) throw new Error('Invalid tuple');
@ -170,7 +170,7 @@ const Fp2: mod.Field<Fp2> & Fp2Utils = {
},
frobeniusMap: ({ c0, c1 }, power: number): Fp2 => ({
c0,
c1: Fp.multiply(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]),
c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]),
}),
};
// Finite extension field over irreducible polynominal.
@ -223,50 +223,50 @@ const Fp6Add = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({
c2: Fp2.add(c2, r2),
});
const Fp6Subtract = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({
c0: Fp2.subtract(c0, r0),
c1: Fp2.subtract(c1, r1),
c2: Fp2.subtract(c2, r2),
c0: Fp2.sub(c0, r0),
c1: Fp2.sub(c1, r1),
c2: Fp2.sub(c2, r2),
});
const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => {
if (typeof rhs === 'bigint') {
return {
c0: Fp2.multiply(c0, rhs),
c1: Fp2.multiply(c1, rhs),
c2: Fp2.multiply(c2, rhs),
c0: Fp2.mul(c0, rhs),
c1: Fp2.mul(c1, rhs),
c2: Fp2.mul(c2, rhs),
};
}
const { c0: r0, c1: r1, c2: r2 } = rhs;
const t0 = Fp2.multiply(c0, r0); // c0 * o0
const t1 = Fp2.multiply(c1, r1); // c1 * o1
const t2 = Fp2.multiply(c2, r2); // c2 * o2
const t0 = Fp2.mul(c0, r0); // c0 * o0
const t1 = Fp2.mul(c1, r1); // c1 * o1
const t2 = Fp2.mul(c2, r2); // c2 * o2
return {
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
c0: Fp2.add(
t0,
Fp2.mulByNonresidue(
Fp2.subtract(Fp2.multiply(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))
Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))
)
),
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
c1: Fp2.add(
Fp2.subtract(Fp2.multiply(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)),
Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)),
Fp2.mulByNonresidue(t2)
),
// T1 + (c0 + c2) * (r0 + r2) - T0 + T2
c2: Fp2.subtract(Fp2.add(t1, Fp2.multiply(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)),
};
};
const Fp6Square = ({ c0, c1, c2 }: Fp6) => {
let t0 = Fp2.square(c0); // c0²
let t1 = Fp2.multiply(Fp2.multiply(c0, c1), 2n); // 2 * c0 * c1
let t3 = Fp2.multiply(Fp2.multiply(c1, c2), 2n); // 2 * c1 * c2
let t1 = Fp2.mul(Fp2.mul(c0, c1), 2n); // 2 * c0 * c1
let t3 = Fp2.mul(Fp2.mul(c1, c2), 2n); // 2 * c1 * c2
let t4 = Fp2.square(c2); // c2²
return {
c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0
c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
c2: Fp2.subtract(
Fp2.subtract(Fp2.add(Fp2.add(t1, Fp2.square(Fp2.add(Fp2.subtract(c0, c1), c2))), t3), t0),
c2: Fp2.sub(
Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.square(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0),
t4
),
};
@ -298,32 +298,32 @@ const Fp6: mod.Field<Fp6> & Fp6Utils = {
},
// Do we need division by bigint at all? Should be done via order:
div: (lhs, rhs) =>
Fp6.multiply(lhs, typeof rhs === 'bigint' ? Fp.invert(Fp.create(rhs)) : Fp6.invert(rhs)),
Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.invert(Fp.create(rhs)) : Fp6.invert(rhs)),
pow: (num, power) => mod.FpPow(Fp6, num, power),
invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums),
// Normalized
add: Fp6Add,
subtract: Fp6Subtract,
multiply: Fp6Multiply,
sub: Fp6Subtract,
mul: Fp6Multiply,
square: Fp6Square,
// NonNormalized stuff
addN: Fp6Add,
subtractN: Fp6Subtract,
multiplyN: Fp6Multiply,
subN: Fp6Subtract,
mulN: Fp6Multiply,
squareN: Fp6Square,
invert: ({ c0, c1, c2 }) => {
let t0 = Fp2.subtract(Fp2.square(c0), Fp2.mulByNonresidue(Fp2.multiply(c2, c1))); // c0² - c2 * c1 * (u + 1)
let t1 = Fp2.subtract(Fp2.mulByNonresidue(Fp2.square(c2)), Fp2.multiply(c0, c1)); // c2² * (u + 1) - c0 * c1
let t2 = Fp2.subtract(Fp2.square(c1), Fp2.multiply(c0, c2)); // c1² - c0 * c2
let t0 = Fp2.sub(Fp2.square(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))); // c0² - c2 * c1 * (u + 1)
let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.square(c2)), Fp2.mul(c0, c1)); // c2² * (u + 1) - c0 * c1
let t2 = Fp2.sub(Fp2.square(c1), Fp2.mul(c0, c2)); // c1² - c0 * c2
// 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0)
let t4 = Fp2.invert(
Fp2.add(
Fp2.mulByNonresidue(Fp2.add(Fp2.multiply(c2, t1), Fp2.multiply(c1, t2))),
Fp2.multiply(c0, t0)
Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))),
Fp2.mul(c0, t0)
)
);
return { c0: Fp2.multiply(t4, t0), c1: Fp2.multiply(t4, t1), c2: Fp2.multiply(t4, t2) };
return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) };
},
// Bytes utils
fromBytes: (b: Uint8Array): Fp6 => {
@ -354,35 +354,35 @@ const Fp6: mod.Field<Fp6> & Fp6Utils = {
},
frobeniusMap: ({ c0, c1, c2 }, power: number) => ({
c0: Fp2.frobeniusMap(c0, power),
c1: Fp2.multiply(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]),
c2: Fp2.multiply(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]),
c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]),
c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]),
}),
mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }),
// Sparse multiplication
multiplyBy1: ({ c0, c1, c2 }, b1: Fp2): Fp6 => ({
c0: Fp2.mulByNonresidue(Fp2.multiply(c2, b1)),
c1: Fp2.multiply(c0, b1),
c2: Fp2.multiply(c1, b1),
c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)),
c1: Fp2.mul(c0, b1),
c2: Fp2.mul(c1, b1),
}),
// Sparse multiplication
multiplyBy01({ c0, c1, c2 }, b0: Fp2, b1: Fp2): Fp6 {
let t0 = Fp2.multiply(c0, b0); // c0 * b0
let t1 = Fp2.multiply(c1, b1); // c1 * b1
let t0 = Fp2.mul(c0, b0); // c0 * b0
let t1 = Fp2.mul(c1, b1); // c1 * b1
return {
// ((c1 + c2) * b1 - T1) * (u + 1) + T0
c0: Fp2.add(Fp2.mulByNonresidue(Fp2.subtract(Fp2.multiply(Fp2.add(c1, c2), b1), t1)), t0),
c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0),
// (b0 + b1) * (c0 + c1) - T0 - T1
c1: Fp2.subtract(Fp2.subtract(Fp2.multiply(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1),
// (c0 + c2) * b0 - T0 + T1
c2: Fp2.add(Fp2.subtract(Fp2.multiply(Fp2.add(c0, c2), b0), t0), t1),
c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1),
};
},
multiplyByFp2: ({ c0, c1, c2 }, rhs: Fp2): Fp6 => ({
c0: Fp2.multiply(c0, rhs),
c1: Fp2.multiply(c1, rhs),
c2: Fp2.multiply(c2, rhs),
c0: Fp2.mul(c0, rhs),
c1: Fp2.mul(c1, rhs),
c2: Fp2.mul(c2, rhs),
}),
};
@ -448,26 +448,26 @@ const Fp12Add = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({
c1: Fp6.add(c1, r1),
});
const Fp12Subtract = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({
c0: Fp6.subtract(c0, r0),
c1: Fp6.subtract(c1, r1),
c0: Fp6.sub(c0, r0),
c1: Fp6.sub(c1, r1),
});
const Fp12Multiply = ({ c0, c1 }: Fp12, rhs: Fp12 | bigint) => {
if (typeof rhs === 'bigint') return { c0: Fp6.multiply(c0, rhs), c1: Fp6.multiply(c1, rhs) };
if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) };
let { c0: r0, c1: r1 } = rhs;
let t1 = Fp6.multiply(c0, r0); // c0 * r0
let t2 = Fp6.multiply(c1, r1); // c1 * r1
let t1 = Fp6.mul(c0, r0); // c0 * r0
let t2 = Fp6.mul(c1, r1); // c1 * r1
return {
c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v
// (c0 + c1) * (r0 + r1) - (T1 + T2)
c1: Fp6.subtract(Fp6.multiply(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)),
};
};
const Fp12Square = ({ c0, c1 }: Fp12) => {
let ab = Fp6.multiply(c0, c1); // c0 * c1
let ab = Fp6.mul(c0, c1); // c0 * c1
return {
// (c1 * v + c0) * (c0 + c1) - AB - AB * v
c0: Fp6.subtract(
Fp6.subtract(Fp6.multiply(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab),
c0: Fp6.sub(
Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab),
Fp6.mulByNonresidue(ab)
),
c1: Fp6.add(ab, ab),
@ -478,7 +478,7 @@ function Fp4Square(a: Fp2, b: Fp2): { first: Fp2; second: Fp2 } {
const b2 = Fp2.square(b);
return {
first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a²
second: Fp2.subtract(Fp2.subtract(Fp2.square(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
second: Fp2.sub(Fp2.sub(Fp2.square(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b²
};
}
type Fp12Utils = {
@ -508,22 +508,22 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
throw new Error('Not implemented');
},
invert: ({ c0, c1 }) => {
let t = Fp6.invert(Fp6.subtract(Fp6.square(c0), Fp6.mulByNonresidue(Fp6.square(c1)))); // 1 / (c0² - c1² * v)
return { c0: Fp6.multiply(c0, t), c1: Fp6.negate(Fp6.multiply(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
let t = Fp6.invert(Fp6.sub(Fp6.square(c0), Fp6.mulByNonresidue(Fp6.square(c1)))); // 1 / (c0² - c1² * v)
return { c0: Fp6.mul(c0, t), c1: Fp6.negate(Fp6.mul(c1, t)) }; // ((C0 * T) * T) + (-C1 * T) * w
},
div: (lhs, rhs) =>
Fp12.multiply(lhs, typeof rhs === 'bigint' ? Fp.invert(Fp.create(rhs)) : Fp12.invert(rhs)),
Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.invert(Fp.create(rhs)) : Fp12.invert(rhs)),
pow: (num, power) => mod.FpPow(Fp12, num, power),
invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums),
// Normalized
add: Fp12Add,
subtract: Fp12Subtract,
multiply: Fp12Multiply,
sub: Fp12Subtract,
mul: Fp12Multiply,
square: Fp12Square,
// NonNormalized stuff
addN: Fp12Add,
subtractN: Fp12Subtract,
multiplyN: Fp12Multiply,
subN: Fp12Subtract,
mulN: Fp12Multiply,
squareN: Fp12Square,
// Bytes utils
@ -555,9 +555,9 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
return {
c0: r0,
c1: Fp6.create({
c0: Fp2.multiply(c0, coeff),
c1: Fp2.multiply(c1, coeff),
c2: Fp2.multiply(c2, coeff),
c0: Fp2.mul(c0, coeff),
c1: Fp2.mul(c1, coeff),
c2: Fp2.mul(c2, coeff),
}),
};
},
@ -568,8 +568,8 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
return {
c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0
// (c1 + c0) * [o0, o1+o4] - T0 - T1
c1: Fp6.subtract(
Fp6.subtract(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0),
c1: Fp6.sub(
Fp6.sub(Fp6.multiplyBy01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0),
t1
),
};
@ -593,14 +593,14 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
let t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
return {
c0: Fp6.create({
c0: Fp2.add(Fp2.multiply(Fp2.subtract(t3, c0c0), 2n), t3), // 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.multiply(Fp2.subtract(t5, c0c1), 2n), t5), // 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.multiply(Fp2.subtract(t7, c0c2), 2n), t7),
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), 2n), t3), // 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), 2n), t5), // 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), 2n), t7),
}), // 2 * (T7 - c0c2) + T7
c1: Fp6.create({
c0: Fp2.add(Fp2.multiply(Fp2.add(t9, c1c0), 2n), t9), // 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.multiply(Fp2.add(t4, c1c1), 2n), t4), // 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.multiply(Fp2.add(t6, c1c2), 2n), t6),
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), 2n), t9), // 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), 2n), t4), // 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), 2n), t6),
}),
}; // 2 * (T6 + c1c2) + T6
},
@ -608,7 +608,7 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
let z = Fp12.ONE;
for (let i = BLS_X_LEN - 1; i >= 0; i--) {
z = Fp12._cyclotomicSquare(z);
if (bitGet(n, i)) z = Fp12.multiply(z, num);
if (bitGet(n, i)) z = Fp12.mul(z, num);
}
return z;
},
@ -619,23 +619,23 @@ const Fp12: mod.Field<Fp12> & Fp12Utils = {
// this^(q⁶) / this
const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num);
// t0^(q²) * t0
const t1 = Fp12.multiply(Fp12.frobeniusMap(t0, 2), t0);
const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0);
const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x));
const t3 = Fp12.multiply(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2);
const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2);
const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x));
const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x));
const t6 = Fp12.multiply(
const t6 = Fp12.mul(
Fp12.conjugate(Fp12._cyclotomicExp(t5, x)),
Fp12._cyclotomicSquare(t2)
);
const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x));
const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.multiply(t2, t5), 2);
const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.multiply(t4, t1), 3);
const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.multiply(t6, Fp12.conjugate(t1)), 1);
const t7_t3c_t1 = Fp12.multiply(Fp12.multiply(t7, Fp12.conjugate(t3)), t1);
const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2);
const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3);
const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1);
const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1);
// (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1
return Fp12.multiply(
Fp12.multiply(Fp12.multiply(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1),
return Fp12.mul(
Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1),
t7_t3c_t1
);
},
@ -855,18 +855,18 @@ const P_MINUS_9_DIV_16 = (Fp.ORDER ** 2n - 9n) / 16n;
// if valid square root is found
function sqrt_div_fp2(u: Fp2, v: Fp2) {
const v7 = Fp2.pow(v, 7n);
const uv7 = Fp2.multiply(u, v7);
const uv15 = Fp2.multiply(uv7, Fp2.multiply(v7, v));
const uv7 = Fp2.mul(u, v7);
const uv15 = Fp2.mul(uv7, Fp2.mul(v7, v));
// gamma = uv⁷ * (uv¹⁵)^((p² - 9) / 16)
const gamma = Fp2.multiply(Fp2.pow(uv15, P_MINUS_9_DIV_16), uv7);
const gamma = Fp2.mul(Fp2.pow(uv15, P_MINUS_9_DIV_16), uv7);
let success = false;
let result = gamma;
// Constant-time routine, so we do not early-return.
const positiveRootsOfUnity = FP2_ROOTS_OF_UNITY.slice(0, 4);
positiveRootsOfUnity.forEach((root) => {
// Valid if (root * gamma)² * v - u == 0
const candidate = Fp2.multiply(root, gamma);
if (Fp2.isZero(Fp2.subtract(Fp2.multiply(Fp2.pow(candidate, 2n), v), u)) && !success) {
const candidate = Fp2.mul(root, gamma);
if (Fp2.isZero(Fp2.sub(Fp2.mul(Fp2.pow(candidate, 2n), v), u)) && !success) {
success = true;
result = candidate;
}
@ -885,13 +885,13 @@ function map_to_curve_simple_swu_9mod16(t: bigint[] | Fp2): [Fp2, Fp2] {
if (Array.isArray(t)) t = Fp2.fromBigTuple(t);
const t2 = Fp2.pow(t, 2n);
const iso_3_z_t2 = Fp2.multiply(iso_3_z, t2);
const iso_3_z_t2 = Fp2.mul(iso_3_z, t2);
const ztzt = Fp2.add(iso_3_z_t2, Fp2.pow(iso_3_z_t2, 2n)); // (Z * t² + Z² * t⁴)
let denominator = Fp2.negate(Fp2.multiply(iso_3_a, ztzt)); // -a(Z * t² + Z² * t⁴)
let numerator = Fp2.multiply(iso_3_b, Fp2.add(ztzt, Fp2.ONE)); // b(Z * t² + Z² * t⁴ + 1)
let denominator = Fp2.negate(Fp2.mul(iso_3_a, ztzt)); // -a(Z * t² + Z² * t⁴)
let numerator = Fp2.mul(iso_3_b, Fp2.add(ztzt, Fp2.ONE)); // b(Z * t² + Z² * t⁴ + 1)
// Exceptional case
if (Fp2.isZero(denominator)) denominator = Fp2.multiply(iso_3_z, iso_3_a);
if (Fp2.isZero(denominator)) denominator = Fp2.mul(iso_3_z, iso_3_a);
// v = D³
let v = Fp2.pow(denominator, 3n);
@ -899,9 +899,9 @@ function map_to_curve_simple_swu_9mod16(t: bigint[] | Fp2): [Fp2, Fp2] {
let u = Fp2.add(
Fp2.add(
Fp2.pow(numerator, 3n),
Fp2.multiply(Fp2.multiply(iso_3_a, numerator), Fp2.pow(denominator, 2n))
Fp2.mul(Fp2.mul(iso_3_a, numerator), Fp2.pow(denominator, 2n))
),
Fp2.multiply(iso_3_b, v)
Fp2.mul(iso_3_b, v)
);
// Attempt y = sqrt(u / v)
const { success, sqrtCandidateOrGamma } = sqrt_div_fp2(u, v);
@ -909,22 +909,22 @@ function map_to_curve_simple_swu_9mod16(t: bigint[] | Fp2): [Fp2, Fp2] {
if (success) y = sqrtCandidateOrGamma;
// Handle case where (u / v) is not square
// sqrt_candidate(x1) = sqrt_candidate(x0) * t³
const sqrtCandidateX1 = Fp2.multiply(sqrtCandidateOrGamma, Fp2.pow(t, 3n));
const sqrtCandidateX1 = Fp2.mul(sqrtCandidateOrGamma, Fp2.pow(t, 3n));
// u(x1) = Z³ * t⁶ * u(x0)
u = Fp2.multiply(Fp2.pow(iso_3_z_t2, 3n), u);
u = Fp2.mul(Fp2.pow(iso_3_z_t2, 3n), u);
let success2 = false;
FP2_ETAs.forEach((eta) => {
// Valid solution if (eta * sqrt_candidate(x1))² * v - u == 0
const etaSqrtCandidate = Fp2.multiply(eta, sqrtCandidateX1);
const temp = Fp2.subtract(Fp2.multiply(Fp2.pow(etaSqrtCandidate, 2n), v), u);
const etaSqrtCandidate = Fp2.mul(eta, sqrtCandidateX1);
const temp = Fp2.sub(Fp2.mul(Fp2.pow(etaSqrtCandidate, 2n), v), u);
if (Fp2.isZero(temp) && !success && !success2) {
y = etaSqrtCandidate;
success2 = true;
}
});
if (!success && !success2) throw new Error('Hash to Curve - Optimized SWU failure');
if (success2) numerator = Fp2.multiply(numerator, iso_3_z_t2);
if (success2) numerator = Fp2.mul(numerator, iso_3_z_t2);
y = y as Fp2;
if (sgn0_fp2(t) !== sgn0_fp2(y)) y = Fp2.negate(y);
return [Fp2.div(numerator, denominator), y];
@ -945,27 +945,27 @@ function map_to_curve_simple_swu_3mod4(u: Fp): [Fp, Fp] {
// Static value so we can know that is there always root
const c2 = Fp.sqrt(Fp.pow(Fp.negate(Z), 3n)); // sqrt((-Z) ^ 3)
const tv1 = Fp.square(u); // u ** 2n;
const tv3 = Fp.multiply(Z, tv1); //
const tv3 = Fp.mul(Z, tv1); //
let xDen = Fp.add(Fp.square(tv3), tv3);
// X
const xNum1 = Fp.multiply(Fp.add(xDen, Fp.ONE), B); // (xd + 1) * B
const xNum2 = Fp.multiply(tv3, xNum1); // x2 = x2n / xd = Z * u^2 * x1n / xd
xDen = Fp.multiply(Fp.negate(A), xDen); // -A * xDen
if (Fp.isZero(xDen)) xDen = Fp.multiply(A, Z);
const xNum1 = Fp.mul(Fp.add(xDen, Fp.ONE), B); // (xd + 1) * B
const xNum2 = Fp.mul(tv3, xNum1); // x2 = x2n / xd = Z * u^2 * x1n / xd
xDen = Fp.mul(Fp.negate(A), xDen); // -A * xDen
if (Fp.isZero(xDen)) xDen = Fp.mul(A, Z);
let tv2 = Fp.square(xDen); // xDen ^ 2
const gxd = Fp.multiply(tv2, xDen); // xDen ^ 3
tv2 = Fp.multiply(A, tv2); // A * tv2
let gx1 = Fp.multiply(Fp.add(Fp.square(xNum1), tv2), xNum1); // x1n^3 + A * x1n * xd^2
tv2 = Fp.multiply(B, gxd); // B * gxd
const gxd = Fp.mul(tv2, xDen); // xDen ^ 3
tv2 = Fp.mul(A, tv2); // A * tv2
let gx1 = Fp.mul(Fp.add(Fp.square(xNum1), tv2), xNum1); // x1n^3 + A * x1n * xd^2
tv2 = Fp.mul(B, gxd); // B * gxd
gx1 = Fp.add(gx1, tv2); // x1n^3 + A * x1n * xd^2 + B * xd^3
tv2 = Fp.multiply(gx1, gxd); // gx1 * gxd
const tv4 = Fp.multiply(Fp.square(gxd), tv2); // gx1 * gxd^3
tv2 = Fp.mul(gx1, gxd); // gx1 * gxd
const tv4 = Fp.mul(Fp.square(gxd), tv2); // gx1 * gxd^3
// Y
const y1 = Fp.multiply(Fp.pow(tv4, c1), tv2); // gx1 * gxd * (gx1 * gxd^3)^((q - 3) / 4)
const y2 = Fp.multiply(Fp.multiply(Fp.multiply(y1, c2), tv1), u); // y1 * c2 * tv1 * u
const y1 = Fp.mul(Fp.pow(tv4, c1), tv2); // gx1 * gxd * (gx1 * gxd^3)^((q - 3) / 4)
const y2 = Fp.mul(Fp.mul(Fp.mul(y1, c2), tv1), u); // y1 * c2 * tv1 * u
let xNum, yPos;
// y1^2 * gxd == gx1
if (Fp.equals(Fp.multiply(Fp.square(y1), gxd), gx1)) {
if (Fp.equals(Fp.mul(Fp.square(y1), gxd), gx1)) {
xNum = xNum1;
yPos = y1;
} else {
@ -985,10 +985,10 @@ function isogenyMap<T, F extends mod.Field<T>>(
y: T
): [T, T] {
const [xNum, xDen, yNum, yDen] = COEFF.map((val) =>
val.reduce((acc, i) => field.add(field.multiply(acc, x), i))
val.reduce((acc, i) => field.add(field.mul(acc, x), i))
);
x = field.div(xNum, xDen); // xNum / xDen
y = field.multiply(y, field.div(yNum, yDen)); // y * (yNum / yDev)
y = field.mul(y, field.div(yNum, yDen)); // y * (yNum / yDev)
return [x, y];
}
// 3-isogeny map from E' to E
@ -1005,8 +1005,8 @@ const wcu = Fp12.create({ c0: Fp6.ZERO, c1: ut_root });
const [wsq_inv, wcu_inv] = Fp12.invertBatch([wsq, wcu]);
function psi(x: Fp2, y: Fp2): [Fp2, Fp2] {
// Untwist Fp2->Fp12 && frobenius(1) && twist back
const x2 = Fp12.multiply(Fp12.frobeniusMap(Fp12.multiplyByFp2(wsq_inv, x), 1), wsq).c0.c0;
const y2 = Fp12.multiply(Fp12.frobeniusMap(Fp12.multiplyByFp2(wcu_inv, y), 1), wcu).c0.c0;
const x2 = Fp12.mul(Fp12.frobeniusMap(Fp12.multiplyByFp2(wsq_inv, x), 1), wsq).c0.c0;
const y2 = Fp12.mul(Fp12.frobeniusMap(Fp12.multiplyByFp2(wcu_inv, y), 1), wcu).c0.c0;
return [x2, y2];
}
// Ψ endomorphism
@ -1021,7 +1021,7 @@ const PSI2_C1 =
0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn;
function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] {
return [Fp2.multiply(x, PSI2_C1), Fp2.negate(y)];
return [Fp2.mul(x, PSI2_C1), Fp2.negate(y)];
}
function G2psi2(c: ProjectiveConstructor<Fp2>, P: ProjectivePointType<Fp2>) {
const affine = P.toAffine();
@ -1113,7 +1113,7 @@ export const bls12_381: CurveFn<Fp, Fp2, Fp6, Fp12> = bls({
// φ endomorphism
const cubicRootOfUnityModP =
0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen;
const phi = new c(Fp.multiply(point.x, cubicRootOfUnityModP), point.y, point.z);
const phi = new c(Fp.mul(point.x, cubicRootOfUnityModP), point.y, point.z);
// todo: unroll
const xP = point.multiplyUnsafe(bls12_381.CURVE.x).negate(); // [x]P

@ -92,8 +92,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT, (num) => {
const a = Fp.create(num);
deepStrictEqual(Fp.subtract(a, Fp.ZERO), a);
deepStrictEqual(Fp.subtract(a, a), Fp.ZERO);
deepStrictEqual(Fp.sub(a, Fp.ZERO), a);
deepStrictEqual(Fp.sub(a, a), Fp.ZERO);
})
);
});
@ -102,9 +102,9 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT, (num1) => {
const a = Fp.create(num1);
const b = Fp.create(num1);
deepStrictEqual(Fp.subtract(Fp.ZERO, a), Fp.negate(a));
deepStrictEqual(Fp.subtract(a, b), Fp.add(a, Fp.negate(b)));
deepStrictEqual(Fp.subtract(a, b), Fp.add(a, Fp.multiply(b, Fp.create(-1n))));
deepStrictEqual(Fp.sub(Fp.ZERO, a), Fp.negate(a));
deepStrictEqual(Fp.sub(a, b), Fp.add(a, Fp.negate(b)));
deepStrictEqual(Fp.sub(a, b), Fp.add(a, Fp.mul(b, Fp.create(-1n))));
})
);
});
@ -112,8 +112,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT, (num) => {
const a = Fp.create(num);
deepStrictEqual(Fp.negate(a), Fp.subtract(Fp.ZERO, a));
deepStrictEqual(Fp.negate(a), Fp.multiply(a, Fp.create(-1n)));
deepStrictEqual(Fp.negate(a), Fp.sub(Fp.ZERO, a));
deepStrictEqual(Fp.negate(a), Fp.mul(a, Fp.create(-1n)));
})
);
});
@ -123,7 +123,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT, FC_BIGINT, (num1, num2) => {
const a = Fp.create(num1);
const b = Fp.create(num2);
deepStrictEqual(Fp.multiply(a, b), Fp.multiply(b, a));
deepStrictEqual(Fp.mul(a, b), Fp.mul(b, a));
})
);
});
@ -133,7 +133,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const a = Fp.create(num1);
const b = Fp.create(num2);
const c = Fp.create(num3);
deepStrictEqual(Fp.multiply(a, Fp.multiply(b, c)), Fp.multiply(Fp.multiply(a, b), c));
deepStrictEqual(Fp.mul(a, Fp.mul(b, c)), Fp.mul(Fp.mul(a, b), c));
})
);
});
@ -143,7 +143,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const a = Fp.create(num1);
const b = Fp.create(num2);
const c = Fp.create(num3);
deepStrictEqual(Fp.multiply(a, Fp.add(b, c)), Fp.add(Fp.multiply(b, a), Fp.multiply(c, a)));
deepStrictEqual(Fp.mul(a, Fp.add(b, c)), Fp.add(Fp.mul(b, a), Fp.mul(c, a)));
})
);
});
@ -151,13 +151,13 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT, (num) => {
const a = Fp.create(num);
deepStrictEqual(Fp.multiply(a, Fp.create(0n)), Fp.ZERO);
deepStrictEqual(Fp.multiply(a, Fp.ZERO), Fp.ZERO);
deepStrictEqual(Fp.multiply(a, Fp.create(1n)), a);
deepStrictEqual(Fp.multiply(a, Fp.ONE), a);
deepStrictEqual(Fp.multiply(a, Fp.create(2n)), Fp.add(a, a));
deepStrictEqual(Fp.multiply(a, Fp.create(3n)), Fp.add(Fp.add(a, a), a));
deepStrictEqual(Fp.multiply(a, Fp.create(4n)), Fp.add(Fp.add(Fp.add(a, a), a), a));
deepStrictEqual(Fp.mul(a, Fp.create(0n)), Fp.ZERO);
deepStrictEqual(Fp.mul(a, Fp.ZERO), Fp.ZERO);
deepStrictEqual(Fp.mul(a, Fp.create(1n)), a);
deepStrictEqual(Fp.mul(a, Fp.ONE), a);
deepStrictEqual(Fp.mul(a, Fp.create(2n)), Fp.add(a, a));
deepStrictEqual(Fp.mul(a, Fp.create(3n)), Fp.add(Fp.add(a, a), a));
deepStrictEqual(Fp.mul(a, Fp.create(4n)), Fp.add(Fp.add(Fp.add(a, a), a), a));
})
);
});
@ -165,7 +165,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT, (num) => {
const a = Fp.create(num);
deepStrictEqual(Fp.square(a), Fp.multiply(a, a));
deepStrictEqual(Fp.square(a), Fp.mul(a, a));
})
);
});
@ -175,8 +175,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const a = Fp.create(num);
deepStrictEqual(Fp.pow(a, 0n), Fp.ONE);
deepStrictEqual(Fp.pow(a, 1n), a);
deepStrictEqual(Fp.pow(a, 2n), Fp.multiply(a, a));
deepStrictEqual(Fp.pow(a, 3n), Fp.multiply(Fp.multiply(a, a), a));
deepStrictEqual(Fp.pow(a, 2n), Fp.mul(a, a));
deepStrictEqual(Fp.pow(a, 3n), Fp.mul(Fp.mul(a, a), a));
})
);
});
@ -221,7 +221,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT, FC_BIGINT, (num1, num2) => {
const a = Fp.create(num1);
const b = Fp.create(num2);
deepStrictEqual(Fp.div(a, b), Fp.multiply(a, Fp.invert(b)));
deepStrictEqual(Fp.div(a, b), Fp.mul(a, Fp.invert(b)));
})
);
});
@ -285,8 +285,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_2, (num) => {
const a = Fp2.fromBigTuple([num[0], num[1]]);
deepStrictEqual(Fp2.subtract(a, Fp2.ZERO), a);
deepStrictEqual(Fp2.subtract(a, a), Fp2.ZERO);
deepStrictEqual(Fp2.sub(a, Fp2.ZERO), a);
deepStrictEqual(Fp2.sub(a, a), Fp2.ZERO);
})
);
});
@ -295,9 +295,9 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT_2, (num1) => {
const a = Fp2.fromBigTuple([num1[0], num1[1]]);
const b = Fp2.fromBigTuple([num1[0], num1[1]]);
deepStrictEqual(Fp2.subtract(Fp2.ZERO, a), Fp2.negate(a));
deepStrictEqual(Fp2.subtract(a, b), Fp2.add(a, Fp2.negate(b)));
deepStrictEqual(Fp2.subtract(a, b), Fp2.add(a, Fp2.multiply(b, -1n)));
deepStrictEqual(Fp2.sub(Fp2.ZERO, a), Fp2.negate(a));
deepStrictEqual(Fp2.sub(a, b), Fp2.add(a, Fp2.negate(b)));
deepStrictEqual(Fp2.sub(a, b), Fp2.add(a, Fp2.mul(b, -1n)));
})
);
});
@ -305,8 +305,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_2, (num) => {
const a = Fp2.fromBigTuple([num[0], num[1]]);
deepStrictEqual(Fp2.negate(a), Fp2.subtract(Fp2.ZERO, a));
deepStrictEqual(Fp2.negate(a), Fp2.multiply(a, -1n));
deepStrictEqual(Fp2.negate(a), Fp2.sub(Fp2.ZERO, a));
deepStrictEqual(Fp2.negate(a), Fp2.mul(a, -1n));
})
);
});
@ -316,7 +316,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT_2, FC_BIGINT_2, (num1, num2) => {
const a = Fp2.fromBigTuple([num1[0], num1[1]]);
const b = Fp2.fromBigTuple([num2[0], num2[1]]);
deepStrictEqual(Fp2.multiply(a, b), Fp2.multiply(b, a));
deepStrictEqual(Fp2.mul(a, b), Fp2.mul(b, a));
})
);
});
@ -326,7 +326,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const a = Fp2.fromBigTuple([num1[0], num1[1]]);
const b = Fp2.fromBigTuple([num2[0], num2[1]]);
const c = Fp2.fromBigTuple([num3[0], num3[1]]);
deepStrictEqual(Fp2.multiply(a, Fp2.multiply(b, c)), Fp2.multiply(Fp2.multiply(a, b), c));
deepStrictEqual(Fp2.mul(a, Fp2.mul(b, c)), Fp2.mul(Fp2.mul(a, b), c));
})
);
});
@ -337,8 +337,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const b = Fp2.fromBigTuple([num2[0], num2[1]]);
const c = Fp2.fromBigTuple([num3[0], num3[1]]);
deepStrictEqual(
Fp2.multiply(a, Fp2.add(b, c)),
Fp2.add(Fp2.multiply(b, a), Fp2.multiply(c, a))
Fp2.mul(a, Fp2.add(b, c)),
Fp2.add(Fp2.mul(b, a), Fp2.mul(c, a))
);
})
);
@ -347,13 +347,13 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_2, (num) => {
const a = Fp2.fromBigTuple([num[0], num[1]]);
deepStrictEqual(Fp2.multiply(a, 0n), Fp2.ZERO);
deepStrictEqual(Fp2.multiply(a, Fp2.ZERO), Fp2.ZERO);
deepStrictEqual(Fp2.multiply(a, 1n), a);
deepStrictEqual(Fp2.multiply(a, Fp2.ONE), a);
deepStrictEqual(Fp2.multiply(a, 2n), Fp2.add(a, a));
deepStrictEqual(Fp2.multiply(a, 3n), Fp2.add(Fp2.add(a, a), a));
deepStrictEqual(Fp2.multiply(a, 4n), Fp2.add(Fp2.add(Fp2.add(a, a), a), a));
deepStrictEqual(Fp2.mul(a, 0n), Fp2.ZERO);
deepStrictEqual(Fp2.mul(a, Fp2.ZERO), Fp2.ZERO);
deepStrictEqual(Fp2.mul(a, 1n), a);
deepStrictEqual(Fp2.mul(a, Fp2.ONE), a);
deepStrictEqual(Fp2.mul(a, 2n), Fp2.add(a, a));
deepStrictEqual(Fp2.mul(a, 3n), Fp2.add(Fp2.add(a, a), a));
deepStrictEqual(Fp2.mul(a, 4n), Fp2.add(Fp2.add(Fp2.add(a, a), a), a));
})
);
});
@ -361,7 +361,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_2, (num) => {
const a = Fp2.fromBigTuple([num[0], num[1]]);
deepStrictEqual(Fp2.square(a), Fp2.multiply(a, a));
deepStrictEqual(Fp2.square(a), Fp2.mul(a, a));
})
);
});
@ -371,8 +371,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const a = Fp2.fromBigTuple([num[0], num[1]]);
deepStrictEqual(Fp2.pow(a, 0n), Fp2.ONE);
deepStrictEqual(Fp2.pow(a, 1n), a);
deepStrictEqual(Fp2.pow(a, 2n), Fp2.multiply(a, a));
deepStrictEqual(Fp2.pow(a, 3n), Fp2.multiply(Fp2.multiply(a, a), a));
deepStrictEqual(Fp2.pow(a, 2n), Fp2.mul(a, a));
deepStrictEqual(Fp2.pow(a, 3n), Fp2.mul(Fp2.mul(a, a), a));
})
);
});
@ -410,7 +410,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT_2, FC_BIGINT_2, (num1, num2) => {
const a = Fp2.fromBigTuple([num1[0], num1[1]]);
const b = Fp2.fromBigTuple([num2[0], num2[1]]);
deepStrictEqual(Fp2.div(a, b), Fp2.multiply(a, Fp2.invert(b)));
deepStrictEqual(Fp2.div(a, b), Fp2.mul(a, Fp2.invert(b)));
})
);
});
@ -536,8 +536,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_12, (num) => {
const a = Fp12.fromBigTwelve(num);
deepStrictEqual(Fp12.subtract(a, Fp12.ZERO), a);
deepStrictEqual(Fp12.subtract(a, a), Fp12.ZERO);
deepStrictEqual(Fp12.sub(a, Fp12.ZERO), a);
deepStrictEqual(Fp12.sub(a, a), Fp12.ZERO);
})
);
});
@ -546,9 +546,9 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT_12, (num1) => {
const a = Fp12.fromBigTwelve(num1);
const b = Fp12.fromBigTwelve(num1);
deepStrictEqual(Fp12.subtract(Fp12.ZERO, a), Fp12.negate(a));
deepStrictEqual(Fp12.subtract(a, b), Fp12.add(a, Fp12.negate(b)));
deepStrictEqual(Fp12.subtract(a, b), Fp12.add(a, Fp12.multiply(b, -1n)));
deepStrictEqual(Fp12.sub(Fp12.ZERO, a), Fp12.negate(a));
deepStrictEqual(Fp12.sub(a, b), Fp12.add(a, Fp12.negate(b)));
deepStrictEqual(Fp12.sub(a, b), Fp12.add(a, Fp12.mul(b, -1n)));
})
);
});
@ -556,8 +556,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_12, (num) => {
const a = Fp12.fromBigTwelve(num);
deepStrictEqual(Fp12.negate(a), Fp12.subtract(Fp12.ZERO, a));
deepStrictEqual(Fp12.negate(a), Fp12.multiply(a, -1n));
deepStrictEqual(Fp12.negate(a), Fp12.sub(Fp12.ZERO, a));
deepStrictEqual(Fp12.negate(a), Fp12.mul(a, -1n));
})
);
});
@ -567,7 +567,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT_12, FC_BIGINT_12, (num1, num2) => {
const a = Fp12.fromBigTwelve(num1);
const b = Fp12.fromBigTwelve(num2);
deepStrictEqual(Fp12.multiply(a, b), Fp12.multiply(b, a));
deepStrictEqual(Fp12.mul(a, b), Fp12.mul(b, a));
})
);
});
@ -578,8 +578,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const b = Fp12.fromBigTwelve(num2);
const c = Fp12.fromBigTwelve(num3);
deepStrictEqual(
Fp12.multiply(a, Fp12.multiply(b, c)),
Fp12.multiply(Fp12.multiply(a, b), c)
Fp12.mul(a, Fp12.mul(b, c)),
Fp12.mul(Fp12.mul(a, b), c)
);
})
);
@ -591,8 +591,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const b = Fp12.fromBigTwelve(num2);
const c = Fp12.fromBigTwelve(num3);
deepStrictEqual(
Fp12.multiply(a, Fp12.add(b, c)),
Fp12.add(Fp12.multiply(b, a), Fp12.multiply(c, a))
Fp12.mul(a, Fp12.add(b, c)),
Fp12.add(Fp12.mul(b, a), Fp12.mul(c, a))
);
})
);
@ -601,13 +601,13 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_12, (num) => {
const a = Fp12.fromBigTwelve(num);
deepStrictEqual(Fp12.multiply(a, 0n), Fp12.ZERO);
deepStrictEqual(Fp12.multiply(a, Fp12.ZERO), Fp12.ZERO);
deepStrictEqual(Fp12.multiply(a, 1n), a);
deepStrictEqual(Fp12.multiply(a, Fp12.ONE), a);
deepStrictEqual(Fp12.multiply(a, 2n), Fp12.add(a, a));
deepStrictEqual(Fp12.multiply(a, 3n), Fp12.add(Fp12.add(a, a), a));
deepStrictEqual(Fp12.multiply(a, 4n), Fp12.add(Fp12.add(Fp12.add(a, a), a), a));
deepStrictEqual(Fp12.mul(a, 0n), Fp12.ZERO);
deepStrictEqual(Fp12.mul(a, Fp12.ZERO), Fp12.ZERO);
deepStrictEqual(Fp12.mul(a, 1n), a);
deepStrictEqual(Fp12.mul(a, Fp12.ONE), a);
deepStrictEqual(Fp12.mul(a, 2n), Fp12.add(a, a));
deepStrictEqual(Fp12.mul(a, 3n), Fp12.add(Fp12.add(a, a), a));
deepStrictEqual(Fp12.mul(a, 4n), Fp12.add(Fp12.add(Fp12.add(a, a), a), a));
})
);
});
@ -615,7 +615,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.assert(
fc.property(FC_BIGINT_12, (num) => {
const a = Fp12.fromBigTwelve(num);
deepStrictEqual(Fp12.square(a), Fp12.multiply(a, a));
deepStrictEqual(Fp12.square(a), Fp12.mul(a, a));
})
);
});
@ -625,8 +625,8 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
const a = Fp12.fromBigTwelve(num);
deepStrictEqual(Fp12.pow(a, 0n), Fp12.ONE);
deepStrictEqual(Fp12.pow(a, 1n), a);
deepStrictEqual(Fp12.pow(a, 2n), Fp12.multiply(a, a));
deepStrictEqual(Fp12.pow(a, 3n), Fp12.multiply(Fp12.multiply(a, a), a));
deepStrictEqual(Fp12.pow(a, 2n), Fp12.mul(a, a));
deepStrictEqual(Fp12.pow(a, 3n), Fp12.mul(Fp12.mul(a, a), a));
})
);
});
@ -664,7 +664,7 @@ const getPubKey = (priv) => bls.getPublicKey(priv);
fc.property(FC_BIGINT_12, FC_BIGINT_12, (num1, num2) => {
const a = Fp12.fromBigTwelve(num1);
const b = Fp12.fromBigTwelve(num2);
deepStrictEqual(Fp12.div(a, b), Fp12.multiply(a, Fp12.invert(b)));
deepStrictEqual(Fp12.div(a, b), Fp12.mul(a, Fp12.invert(b)));
})
);
});
@ -1519,7 +1519,7 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
should('pairing/creates negative G1 pairing', () => {
const p1 = pairing(G1, G2);
const p2 = pairing(G1.negate(), G2);
deepStrictEqual(Fp12.multiply(p1, p2), Fp12.ONE);
deepStrictEqual(Fp12.mul(p1, p2), Fp12.ONE);
});
should('pairing/creates negative G2 pairing', () => {
const p2 = pairing(G1.negate(), G2);
@ -1534,7 +1534,7 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
should('pairing/G1 billinearity', () => {
const p1 = pairing(G1, G2);
const p2 = pairing(G1.multiply(2n), G2);
deepStrictEqual(Fp12.multiply(p1, p1), p2);
deepStrictEqual(Fp12.mul(p1, p1), p2);
});
should('pairing/should not degenerate', () => {
const p1 = pairing(G1, G2);
@ -1547,7 +1547,7 @@ should('bls12-381/basic/should not verify wrong multi-signature as simple signat
should('pairing/G2 billinearity', () => {
const p1 = pairing(G1, G2);
const p2 = pairing(G1, G2.multiply(2n));
deepStrictEqual(Fp12.multiply(p1, p1), p2);
deepStrictEqual(Fp12.mul(p1, p1), p2);
});
should('pairing/proper pairing composite check', () => {
const p1 = pairing(G1.multiply(37n), G2.multiply(27n));

@ -114,33 +114,33 @@ export function bls<Fp2, Fp6, Fp12>(
// Double
let t0 = Fp2.square(Ry); // Ry²
let t1 = Fp2.square(Rz); // Rz²
let t2 = Fp2.multiplyByB(Fp2.multiply(t1, 3n)); // 3 * T1 * B
let t3 = Fp2.multiply(t2, 3n); // 3 * T2
let t4 = Fp2.subtract(Fp2.subtract(Fp2.square(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
let t2 = Fp2.multiplyByB(Fp2.mul(t1, 3n)); // 3 * T1 * B
let t3 = Fp2.mul(t2, 3n); // 3 * T2
let t4 = Fp2.sub(Fp2.sub(Fp2.square(Fp2.add(Ry, Rz)), t1), t0); // (Ry + Rz)² - T1 - T0
ell_coeff.push([
Fp2.subtract(t2, t0), // T2 - T0
Fp2.multiply(Fp2.square(Rx), 3n), // 3 * Rx²
Fp2.sub(t2, t0), // T2 - T0
Fp2.mul(Fp2.square(Rx), 3n), // 3 * Rx²
Fp2.negate(t4), // -T4
]);
Rx = Fp2.div(Fp2.multiply(Fp2.multiply(Fp2.subtract(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.subtract(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.multiply(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rz = Fp2.multiply(t0, t4); // T0 * T4
Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
Ry = Fp2.sub(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
Rz = Fp2.mul(t0, t4); // T0 * T4
if (bitGet(CURVE.x, i)) {
// Addition
let t0 = Fp2.subtract(Ry, Fp2.multiply(Qy, Rz)); // Ry - Qy * Rz
let t1 = Fp2.subtract(Rx, Fp2.multiply(Qx, Rz)); // Rx - Qx * Rz
let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
ell_coeff.push([
Fp2.subtract(Fp2.multiply(t0, Qx), Fp2.multiply(t1, Qy)), // T0 * Qx - T1 * Qy
Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)), // T0 * Qx - T1 * Qy
Fp2.negate(t0), // -T0
t1, // T1
]);
let t2 = Fp2.square(t1); // T1²
let t3 = Fp2.multiply(t2, t1); // T2 * T1
let t4 = Fp2.multiply(t2, Rx); // T2 * Rx
let t5 = Fp2.add(Fp2.subtract(t3, Fp2.multiply(t4, 2n)), Fp2.multiply(Fp2.square(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
Rx = Fp2.multiply(t1, t5); // T1 * T5
Ry = Fp2.subtract(Fp2.multiply(Fp2.subtract(t4, t5), t0), Fp2.multiply(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
Rz = Fp2.multiply(Rz, t3); // Rz * T3
let t3 = Fp2.mul(t2, t1); // T2 * T1
let t4 = Fp2.mul(t2, Rx); // T2 * Rx
let t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, 2n)), Fp2.mul(Fp2.square(t0), Rz)); // T3 - 2 * T4 + T0² * Rz
Rx = Fp2.mul(t1, t5); // T1 * T5
Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)); // (T4 - T5) * T0 - T3 * Ry
Rz = Fp2.mul(Rz, t3); // Rz * T3
}
}
return ell_coeff;
@ -152,11 +152,11 @@ export function bls<Fp2, Fp6, Fp12>(
let f12 = Fp12.ONE;
for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
const E = ell[j];
f12 = Fp12.multiplyBy014(f12, E[0], Fp2.multiply(E[1], Px), Fp2.multiply(E[2], Py));
f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
if (bitGet(CURVE.x, i)) {
j += 1;
const F = ell[j];
f12 = Fp12.multiplyBy014(f12, F[0], Fp2.multiply(F[1], Px), Fp2.multiply(F[2], Py));
f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
}
if (i !== 0) f12 = Fp12.square(f12);
}
@ -325,7 +325,7 @@ export function bls<Fp2, Fp6, Fp12>(
// and do one exp after multiplying 2 points.
const ePHm = pairing(P.negate(), Hm, false);
const eGS = pairing(G, S, false);
const exp = Fp12.finalExponentiate(Fp12.multiply(eGS, ePHm));
const exp = Fp12.finalExponentiate(Fp12.mul(eGS, ePHm));
return Fp12.equals(exp, Fp12.ONE);
}
@ -385,7 +385,7 @@ export function bls<Fp2, Fp6, Fp12>(
paired.push(pairing(groupPublicKey, message, false));
}
paired.push(pairing(G1.Point.BASE.negate(), sig, false));
const product = paired.reduce((a, b) => Fp12.multiply(a, b), Fp12.ONE);
const product = paired.reduce((a, b) => Fp12.mul(a, b), Fp12.ONE);
const exp = Fp12.finalExponentiate(product);
return Fp12.equals(exp, Fp12.ONE);
} catch {

@ -280,7 +280,6 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
const C = modP(T1 * d * T2); // C = T1*d*T2
const D = modP(Z1 * Z2); // D = Z1*Z2
const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B
// TODO: do we need to check for same point here? Looks like working without it
const F = D - C; // F = D-C
const G = D + C; // G = D+C
const H = modP(B - a * A); // H = B-a*A

@ -1,5 +1,5 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// Default group related functions
// Abelian group utilities
const _0n = BigInt(0);
const _1n = BigInt(1);
@ -67,8 +67,9 @@ export function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number) {
/**
* Implements w-ary non-adjacent form for calculating ec multiplication.
* @param n
* @param W window size
* @param affinePoint optional 2d point to save cached precompute windows on it.
* @param n bits
* @returns real and fake (for const-time) points
*/
wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } {

@ -1,6 +1,6 @@
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import * as utils from './utils.js';
// Utilities for modular arithmetics
// Utilities for modular arithmetics and finite fields
const _0n = BigInt(0);
const _1n = BigInt(1);
const _2n = BigInt(2);
@ -161,14 +161,14 @@ export interface Field<T> {
// 2-args
equals(lhs: T, rhs: T): boolean;
add(lhs: T, rhs: T): T;
subtract(lhs: T, rhs: T): T;
multiply(lhs: T, rhs: T | bigint): T;
sub(lhs: T, rhs: T): T;
mul(lhs: T, rhs: T | bigint): T;
pow(lhs: T, power: bigint): T;
div(lhs: T, rhs: T | bigint): T;
// N for NonNormalized (for now)
addN(lhs: T, rhs: T): T;
subtractN(lhs: T, rhs: T): T;
multiplyN(lhs: T, rhs: T | bigint): T;
subN(lhs: T, rhs: T): T;
mulN(lhs: T, rhs: T | bigint): T;
squareN(num: T): T;
// Optional
@ -182,8 +182,8 @@ export interface Field<T> {
// prettier-ignore
const FIELD_FIELDS = [
'create', 'isValid', 'isZero', 'negate', 'invert', 'sqrt', 'square',
'equals', 'add', 'subtract', 'multiply', 'pow', 'div',
'addN', 'subtractN', 'multiplyN', 'squareN'
'equals', 'add', 'sub', 'mul', 'pow', 'div',
'addN', 'subN', 'mulN', 'squareN'
] as const;
export function validateField<T>(field: Field<T>) {
for (const i of ['ORDER', 'MASK'] as const) {
@ -210,7 +210,7 @@ export function FpPow<T>(f: Field<T>, num: T, power: bigint): T {
let p = f.ONE;
let d = num;
while (power > _0n) {
if (power & _1n) p = f.multiply(p, d);
if (power & _1n) p = f.mul(p, d);
d = f.square(d);
power >>= 1n;
}
@ -223,21 +223,21 @@ export function FpInvertBatch<T>(f: Field<T>, nums: T[]): T[] {
const lastMultiplied = nums.reduce((acc, num, i) => {
if (f.isZero(num)) return acc;
tmp[i] = acc;
return f.multiply(acc, num);
return f.mul(acc, num);
}, f.ONE);
// Invert last element
const inverted = f.invert(lastMultiplied);
// Walk from last to first, multiply them by inverted each other MOD p
nums.reduceRight((acc, num, i) => {
if (f.isZero(num)) return acc;
tmp[i] = f.multiply(acc, tmp[i]);
return f.multiply(acc, num);
tmp[i] = f.mul(acc, tmp[i]);
return f.mul(acc, num);
}, inverted);
return tmp;
}
export function FpDiv<T>(f: Field<T>, lhs: T, rhs: T | bigint): T {
return f.multiply(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
}
// NOTE: very fragile, always bench. Major performance points:
@ -274,16 +274,16 @@ export function Fp(
square: (num) => mod(num * num, ORDER),
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
subtract: (lhs, rhs) => mod(lhs - rhs, ORDER),
multiply: (lhs, rhs) => mod(lhs * rhs, ORDER),
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
pow: (num, power) => FpPow(f, num, power),
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
// Same as above, but doesn't normalize
squareN: (num) => num * num,
addN: (lhs, rhs) => lhs + rhs,
subtractN: (lhs, rhs) => lhs - rhs,
multiplyN: (lhs, rhs) => lhs * rhs,
subN: (lhs, rhs) => lhs - rhs,
mulN: (lhs, rhs) => lhs * rhs,
invert: (num) => invert(num, ORDER),
sqrt: redef.sqrt || sqrtP,

@ -230,8 +230,8 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
function weierstrassEquation(x: T): T {
const { a, b } = CURVE;
const x2 = Fp.square(x); // x * x
const x3 = Fp.multiply(x2, x); // x2 * x
return Fp.add(Fp.add(x3, Fp.multiply(x, a)), b); // x3 + a * x + b
const x3 = Fp.mul(x2, x); // x2 * x
return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
}
function isWithinCurveOrder(num: bigint): boolean {
@ -305,11 +305,11 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
* Compare one point to another.
*/
equals(other: ProjectivePoint): boolean {
if (!(other instanceof ProjectivePoint)) throw new TypeError('ProjectivePoint expected');
assertPrjPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;
const { x: X2, y: Y2, z: Z2 } = other;
const U1 = Fp.equals(Fp.multiply(X1, Z2), Fp.multiply(X2, Z1));
const U2 = Fp.equals(Fp.multiply(Y1, Z2), Fp.multiply(Y2, Z1));
const U1 = Fp.equals(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
const U2 = Fp.equals(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
return U1 && U2;
}
@ -330,38 +330,38 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
double() {
const { a, b } = CURVE;
const b3 = Fp.multiply(b, 3n);
const b3 = Fp.mul(b, 3n);
const { x: X1, y: Y1, z: Z1 } = this;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
let t0 = Fp.multiply(X1, X1); // step 1
let t1 = Fp.multiply(Y1, Y1);
let t2 = Fp.multiply(Z1, Z1);
let t3 = Fp.multiply(X1, Y1);
let t0 = Fp.mul(X1, X1); // step 1
let t1 = Fp.mul(Y1, Y1);
let t2 = Fp.mul(Z1, Z1);
let t3 = Fp.mul(X1, Y1);
t3 = Fp.add(t3, t3); // step 5
Z3 = Fp.multiply(X1, Z1);
Z3 = Fp.mul(X1, Z1);
Z3 = Fp.add(Z3, Z3);
X3 = Fp.multiply(a, Z3);
Y3 = Fp.multiply(b3, t2);
X3 = Fp.mul(a, Z3);
Y3 = Fp.mul(b3, t2);
Y3 = Fp.add(X3, Y3); // step 10
X3 = Fp.subtract(t1, Y3);
X3 = Fp.sub(t1, Y3);
Y3 = Fp.add(t1, Y3);
Y3 = Fp.multiply(X3, Y3);
X3 = Fp.multiply(t3, X3);
Z3 = Fp.multiply(b3, Z3); // step 15
t2 = Fp.multiply(a, t2);
t3 = Fp.subtract(t0, t2);
t3 = Fp.multiply(a, t3);
Y3 = Fp.mul(X3, Y3);
X3 = Fp.mul(t3, X3);
Z3 = Fp.mul(b3, Z3); // step 15
t2 = Fp.mul(a, t2);
t3 = Fp.sub(t0, t2);
t3 = Fp.mul(a, t3);
t3 = Fp.add(t3, Z3);
Z3 = Fp.add(t0, t0); // step 20
t0 = Fp.add(Z3, t0);
t0 = Fp.add(t0, t2);
t0 = Fp.multiply(t0, t3);
t0 = Fp.mul(t0, t3);
Y3 = Fp.add(Y3, t0);
t2 = Fp.multiply(Y1, Z1); // step 25
t2 = Fp.mul(Y1, Z1); // step 25
t2 = Fp.add(t2, t2);
t0 = Fp.multiply(t2, t3);
X3 = Fp.subtract(X3, t0);
Z3 = Fp.multiply(t2, t1);
t0 = Fp.mul(t2, t3);
X3 = Fp.sub(X3, t0);
Z3 = Fp.mul(t2, t1);
Z3 = Fp.add(Z3, Z3); // step 30
Z3 = Fp.add(Z3, Z3);
return new ProjectivePoint(X3, Y3, Z3);
@ -372,51 +372,51 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
// https://eprint.iacr.org/2015/1060, algorithm 1
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
add(other: ProjectivePoint): ProjectivePoint {
if (!(other instanceof ProjectivePoint)) throw new TypeError('ProjectivePoint expected');
assertPrjPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;
const { x: X2, y: Y2, z: Z2 } = other;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
const a = CURVE.a;
const b3 = Fp.multiply(CURVE.b, 3n);
let t0 = Fp.multiply(X1, X2); // step 1
let t1 = Fp.multiply(Y1, Y2);
let t2 = Fp.multiply(Z1, Z2);
const b3 = Fp.mul(CURVE.b, 3n);
let t0 = Fp.mul(X1, X2); // step 1
let t1 = Fp.mul(Y1, Y2);
let t2 = Fp.mul(Z1, Z2);
let t3 = Fp.add(X1, Y1);
let t4 = Fp.add(X2, Y2); // step 5
t3 = Fp.multiply(t3, t4);
t3 = Fp.mul(t3, t4);
t4 = Fp.add(t0, t1);
t3 = Fp.subtract(t3, t4);
t3 = Fp.sub(t3, t4);
t4 = Fp.add(X1, Z1);
let t5 = Fp.add(X2, Z2); // step 10
t4 = Fp.multiply(t4, t5);
t4 = Fp.mul(t4, t5);
t5 = Fp.add(t0, t2);
t4 = Fp.subtract(t4, t5);
t4 = Fp.sub(t4, t5);
t5 = Fp.add(Y1, Z1);
X3 = Fp.add(Y2, Z2); // step 15
t5 = Fp.multiply(t5, X3);
t5 = Fp.mul(t5, X3);
X3 = Fp.add(t1, t2);
t5 = Fp.subtract(t5, X3);
Z3 = Fp.multiply(a, t4);
X3 = Fp.multiply(b3, t2); // step 20
t5 = Fp.sub(t5, X3);
Z3 = Fp.mul(a, t4);
X3 = Fp.mul(b3, t2); // step 20
Z3 = Fp.add(X3, Z3);
X3 = Fp.subtract(t1, Z3);
X3 = Fp.sub(t1, Z3);
Z3 = Fp.add(t1, Z3);
Y3 = Fp.multiply(X3, Z3);
Y3 = Fp.mul(X3, Z3);
t1 = Fp.add(t0, t0); // step 25
t1 = Fp.add(t1, t0);
t2 = Fp.multiply(a, t2);
t4 = Fp.multiply(b3, t4);
t2 = Fp.mul(a, t2);
t4 = Fp.mul(b3, t4);
t1 = Fp.add(t1, t2);
t2 = Fp.subtract(t0, t2); // step 30
t2 = Fp.multiply(a, t2);
t2 = Fp.sub(t0, t2); // step 30
t2 = Fp.mul(a, t2);
t4 = Fp.add(t4, t2);
t0 = Fp.multiply(t1, t4);
t0 = Fp.mul(t1, t4);
Y3 = Fp.add(Y3, t0);
t0 = Fp.multiply(t5, t4); // step 35
X3 = Fp.multiply(t3, X3);
X3 = Fp.subtract(X3, t0);
t0 = Fp.multiply(t3, t1);
Z3 = Fp.multiply(t5, Z3);
t0 = Fp.mul(t5, t4); // step 35
X3 = Fp.mul(t3, X3);
X3 = Fp.sub(X3, t0);
t0 = Fp.mul(t3, t1);
Z3 = Fp.mul(t5, Z3);
Z3 = Fp.add(Z3, t0); // step 40
return new ProjectivePoint(X3, Y3, Z3);
}
@ -453,7 +453,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
}
if (k1neg) k1p = k1p.negate();
if (k2neg) k2p = k2p.negate();
k2p = new ProjectivePoint(Fp.multiply(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
k2p = new ProjectivePoint(Fp.mul(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
return k1p.add(k2p);
}
@ -496,7 +496,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
k1p = wnaf.constTimeNegate(k1neg, k1p);
k2p = wnaf.constTimeNegate(k2neg, k2p);
k2p = new ProjectivePoint(Fp.multiply(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
k2p = new ProjectivePoint(Fp.mul(k2p.x, CURVE.endo.beta), k2p.y, k2p.z);
point = k1p.add(k2p);
fake = f1p.add(f2p);
} else {
@ -517,9 +517,9 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
// If invZ was 0, we return zero point. However we still want to execute
// all operations, so we replace invZ with a random number, 1.
if (invZ == null) invZ = is0 ? Fp.ONE : Fp.invert(z);
const ax = Fp.multiply(x, invZ);
const ay = Fp.multiply(y, invZ);
const zz = Fp.multiply(z, invZ);
const ax = Fp.mul(x, invZ);
const ay = Fp.mul(y, invZ);
const zz = Fp.mul(z, invZ);
if (is0) return Point.ZERO;
if (!Fp.equals(zz, Fp.ONE)) throw new Error('invZ was invalid');
return new Point(ax, ay);
@ -539,6 +539,10 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
}
}
const wnaf = wNAF(ProjectivePoint, CURVE.endo ? nBitLength / 2 : nBitLength);
function assertPrjPoint(other: unknown) {
if (!(other instanceof ProjectivePoint)) throw new TypeError('ProjectivePoint expected');
}
// Stores precomputed values for points.
const pointPrecomputes = new WeakMap<Point, ProjectivePoint[]>();