From 578b188d597367b0cfc089078e586d2de63ac0c5 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sun, 30 Nov 2025 00:13:45 -0800 Subject: [PATCH] Fix inner class typings. --- src/lib/crypto/secp256k1.ts | 53 ++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/lib/crypto/secp256k1.ts b/src/lib/crypto/secp256k1.ts index d928ce8..6504124 100644 --- a/src/lib/crypto/secp256k1.ts +++ b/src/lib/crypto/secp256k1.ts @@ -14,7 +14,7 @@ /** Alias to Uint8Array. */ export type Bytes = Uint8Array /** Signature instance, which allows recovering pubkey from it. */ -export type RecoveredSignature = Secp256k1['Signature'] & { recovery: number } +export type RecoveredSignature = Signature & { recovery: number } /** Weierstrass elliptic curve options. */ export type WeierstrassOpts = Readonly<{ p: bigint @@ -83,6 +83,9 @@ type KeygenFn = (seed?: Bytes) => KeysSecPub type MaybePromise = T | Promise +type Point = InstanceType +type Signature = InstanceType + export class Secp256k1 { /** * Curve params. secp256k1 is short weierstrass / koblitz curve. Equation is y² == x³ + ax + b. @@ -258,8 +261,8 @@ export class Secp256k1 { /** Point in 3d xyz projective coordinates. 3d takes less inversions than 2d. */ static Point = class { - static BASE: Secp256k1['Point'] - static ZERO: Secp256k1['Point'] + static BASE: Point + static ZERO: Point readonly X: bigint readonly Y: bigint readonly Z: bigint @@ -273,15 +276,15 @@ export class Secp256k1 { return Secp256k1.secp256k1_CURVE } /** Create 3d xyz point from 2d xy. (0, 0) => (0, 1, 0), not (0, 0, 1) */ - static fromAffine (ap: AffinePoint): Secp256k1['Point'] { + static fromAffine (ap: AffinePoint): Point { const { x, y } = ap - return x === 0n && y === 0n ? Secp256k1.I : new Secp256k1.Point(x, y, 1n) + return x === 0n && y === 0n ? Secp256k1.I : new this(x, y, 1n) } /** Convert Uint8Array or hex string to Point. */ - static fromBytes (bytes: Bytes): Secp256k1['Point'] { + static fromBytes (bytes: Bytes): Point { Secp256k1.abytes(bytes) const { publicKey: comp, publicKeyUncompressed: uncomp } = Secp256k1.lengths // e.g. for 32-byte: 33, 65 - let p: Secp256k1['Point'] | undefined = undefined + let p: Point | undefined = undefined const length = bytes.length const head = bytes[0] const tail = bytes.subarray(1) @@ -301,7 +304,7 @@ export class Secp256k1 { // Validate point return p ? p.assertValidity() : Secp256k1.err('bad point: not on curve') } - static fromHex (hex: string): Secp256k1['Point'] { + static fromHex (hex: string): Point { return Secp256k1.Point.fromBytes(Secp256k1.hexToBytes(hex)) } get x (): bigint { @@ -311,7 +314,7 @@ export class Secp256k1 { return this.toAffine().y } /** Equality check: compare points P&Q. */ - equals (other: Secp256k1['Point']): boolean { + equals (other: Point): boolean { const { X: X1, Y: Y1, Z: Z1 } = this const { X: X2, Y: Y2, Z: Z2 } = Secp256k1.apoint(other) // checks class equality const X1Z2 = Secp256k1.M(X1 * Z2) @@ -324,11 +327,11 @@ export class Secp256k1 { return this.equals(Secp256k1.I) } /** Flip point over y coordinate. */ - negate (): Secp256k1['Point'] { + negate (): Point { return new Secp256k1.Point(this.X, Secp256k1.M(-this.Y), this.Z) } /** Point doubling: P+P, complete formula. */ - double (): Secp256k1['Point'] { + double (): Point { return this.add(this) } /** @@ -337,7 +340,7 @@ export class Secp256k1 { * Cost: `12M + 0S + 3*a + 3*b3 + 23add`. */ // prettier-ignore - add (other: Secp256k1['Point']): Secp256k1['Point'] { + add (other: Point): Point { const { X: X1, Y: Y1, Z: Z1 } = this const { X: X2, Y: Y2, Z: Z2 } = Secp256k1.apoint(other) const a = 0n @@ -362,7 +365,7 @@ export class Secp256k1 { Z3 = Secp256k1.M(Z3 + t0) // step 40 return new Secp256k1.Point(X3, Y3, Z3) } - subtract (other: Secp256k1['Point']): Secp256k1['Point'] { + subtract (other: Point): Point { return this.add(Secp256k1.apoint(other).negate()) } /** @@ -372,7 +375,7 @@ export class Secp256k1 { * @param n scalar by which point is multiplied * @param safe safe mode guards against timing attacks; unsafe mode is faster */ - multiply (n: bigint, safe = true): Secp256k1['Point'] { + multiply (n: bigint, safe = true): Point { if (!safe && n === 0n) return Secp256k1.I Secp256k1.FnIsValidNot0(n) if (n === 1n) return this @@ -380,7 +383,7 @@ export class Secp256k1 { // init result point & fake point let p = Secp256k1.I let f = Secp256k1.G - for (let d: Secp256k1['Point'] = this; n > 0n; d = d.double(), n >>= 1n) { + for (let d: Point = this; n > 0n; d = d.double(), n >>= 1n) { // if bit is present, add to point // if not present, add to fake, for timing safety if (n & 1n) p = p.add(d) @@ -388,7 +391,7 @@ export class Secp256k1 { } return p } - multiplyUnsafe (scalar: bigint): Secp256k1['Point'] { + multiplyUnsafe (scalar: bigint): Point { return this.multiply(scalar, false) } /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */ @@ -404,7 +407,7 @@ export class Secp256k1 { return { x: Secp256k1.M(x * iz), y: Secp256k1.M(y * iz) } } /** Checks if the point is valid and on-curve. */ - assertValidity (): Secp256k1['Point'] { + 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) @@ -425,16 +428,16 @@ export class Secp256k1 { } /** Generator / base point */ - static G: Secp256k1['Point'] = new this.Point(this.Gx, this.Gy, 1n) + static G: Point = new this.Point(this.Gx, this.Gy, 1n) /** Identity / zero point */ - static I: Secp256k1['Point'] = new this.Point(0n, 1n, 0n) + static I: Point = new this.Point(0n, 1n, 0n) // Static aliases static { this.Point.BASE = this.G this.Point.ZERO = this.I } /** `Q = u1⋅G + u2⋅R`. Verifies Q is not ZERO. Unsafe: non-CT. */ - static doubleScalarMulUns = (R: Secp256k1['Point'], u1: bigint, u2: bigint): Secp256k1['Point'] => { + static doubleScalarMulUns = (R: Point, u1: bigint, u2: bigint): Point => { return this.G.multiply(u1, false).add(R.multiply(u2, false)).assertValidity() } static bytesToNumBE = (b: Bytes): bigint => this.big('0x' + (this.bytesToHex(b) || '0')) @@ -523,7 +526,7 @@ export class Secp256k1 { if (recovery != null) this.recovery = recovery Object.freeze(this) } - static fromBytes (b: Bytes, format: ECDSASignatureFormat = Secp256k1.SIG_COMPACT): Secp256k1['Signature'] { + static fromBytes (b: Bytes, format: ECDSASignatureFormat = Secp256k1.SIG_COMPACT): Signature { Secp256k1.assertSigLength(b, format) let rec: number | undefined if (format === Secp256k1.SIG_RECOVERED) { @@ -1104,7 +1107,7 @@ export class Secp256k1 { static pwindows = Math.ceil(this.scalarBits / this.W) + 1 // 33 for W=8, NOT 32 - see wNAF loop static pwindowSize = 2 ** (this.W - 1) // 128 for W=8 static precompute = () => { - const points: Secp256k1['Point'][] = [] + const points: Point[] = [] let p = this.G let b = p for (let w = 0; w < this.pwindows; w++) { @@ -1118,9 +1121,9 @@ export class Secp256k1 { } return points } - static Gpows: Secp256k1['Point'][] | undefined = undefined // precomputes for base point G + static Gpows: Point[] | undefined = undefined // precomputes for base point G // const-time negate - static ctneg = (cnd: boolean, p: Secp256k1['Point']) => { + static ctneg = (cnd: boolean, p: Point) => { const n = p.negate() return cnd ? n : p } @@ -1136,7 +1139,7 @@ export class Secp256k1 { * * !! Precomputes can be disabled by commenting-out call of the wNAF() inside Point#multiply(). */ - static wNAF = (n: bigint): { p: Secp256k1['Point']; f: Secp256k1['Point'] } => { + static wNAF = (n: bigint): { p: Point; f: Point } => { const comp = this.Gpows || (this.Gpows = this.precompute()) let p = this.I let f = this.G // f must be G, or could become I in the end -- 2.47.3