// -----------------
/** secp256k1 formula. Koblitz curves are subclass of weierstrass curves with a=0, making it x³+b */
- static koblitz = (x: bigint) => this.modP(this.modP(x * x) * x + this.b)
- /** assert is element of field mod P (incl. 0) */
- static FpIsValid = (n: bigint) => this.bigintInRange(n, 0n, this.P)
- /** assert is element of field mod P (excl. 0) */
- static FpIsValidNot0 = (n: bigint) => this.bigintInRange(n, 1n, this.P)
- /** assert is element of field mod N (excl. 0) */
- static FnIsValidNot0 = (n: bigint) => this.bigintInRange(n, 1n, this.N)
- static isEven = (y: bigint) => (y & 1n) === 0n
+ static koblitz = (x: bigint): bigint => this.modP(this.modP(x * x) * x + this.b)
+ static isEven = (y: bigint): boolean => (y & 1n) === 0n
static getPrefix = (y: bigint) => Uint8Array.of(this.isEven(y) ? 0x02 : 0x03)
/** lift_x from BIP340 calculates square root. Validates x, then validates root*root. */
- static lift_x (x: bigint) {
+ static lift_x (x: bigint): bigint {
// Let c = x³ + 7 mod p. Fail if x ≥ p. (also fail if x < 1)
- const c = this.koblitz(this.FpIsValidNot0(x))
+ const c = this.koblitz(this.bigintInRange(x, 1n, this.P))
// c = √y
// y = c^((p+1)/4) mod p
// This formula works for fields p = 3 mod 4 -- a special, fast case.
static Point (X: bigint, Y: bigint, Z: bigint): Point {
const secp256k1 = this
return Object.freeze({
- X: this.FpIsValid(X),
- Y: this.FpIsValidNot0(Y), // Y can't be 0 in Projective
- Z: this.FpIsValid(Z),
+ X: this.bigintInRange(X, 0n, this.P),
+ Y: this.bigintInRange(Y, 1n, this.P), // Y can't be 0 in Projective
+ Z: this.bigintInRange(Z, 0n, this.P),
/** Equality check: compare points P&Q. */
equals (other: Point): boolean {
const { X: X1, Y: Y1, Z: Z1 } = this
*/
multiply (n: bigint, safe = true): Point {
if (!safe && n === 0n) return secp256k1.I
- secp256k1.FnIsValidNot0(n)
+ secp256k1.bigintInRange(n, 1n, secp256k1.N)
if (n === 1n) return this
if (this.equals(secp256k1.G)) return secp256k1.wNAF(n).p
// init result point & fake point
/** Checks if the point is valid and on-curve. */
assertValidity (): Point {
const { x, y } = this.toAffine() // convert to 2d xy affine point.
- secp256k1.FpIsValidNot0(x) // must be in range 1 <= x,y < P
- secp256k1.FpIsValidNot0(y)
+ secp256k1.bigintInRange(x, 1n, secp256k1.P) // must be in range 1 <= x,y < P
+ secp256k1.bigintInRange(y, 1n, secp256k1.P)
// y² == x³ + ax + b, equation sides must be equal
return secp256k1.modP(y * y) === secp256k1.koblitz(x) ? this : secp256k1.err('bad point: not on curve')
},