From 2133f8d5df49ee2afc006fb9f8bcc7a9110e8f32 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sun, 30 Nov 2025 03:07:41 -0800 Subject: [PATCH] Convert inner class to factory function. --- src/lib/crypto/secp256k1.ts | 67 +++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/src/lib/crypto/secp256k1.ts b/src/lib/crypto/secp256k1.ts index 61ab406..8f5970f 100644 --- a/src/lib/crypto/secp256k1.ts +++ b/src/lib/crypto/secp256k1.ts @@ -11,6 +11,9 @@ * Functionality wrapped in a class for embedding into a Web Worker. */ +type Point = InstanceType +type Signature = ReturnType + /** Alias to Uint8Array. */ export type Bytes = Uint8Array /** Signature instance, which allows recovering pubkey from it. */ @@ -83,9 +86,6 @@ 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. @@ -393,7 +393,7 @@ export class Secp256k1 { /** Create 3d xyz point from 2d xy. (0, 0) => (0, 1, 0), not (0, 0, 1) */ static pointFromAffine (ap: AffinePoint): Point { const { x, y } = ap - return x === 0n && y === 0n ? Secp256k1.I : new this.Point(x, y, 1n) + return x === 0n && y === 0n ? this.I : new this.Point(x, y, 1n) } /** Convert Uint8Array or hex string to Point. */ static pointFromBytes (bytes: Bytes): Point { @@ -420,7 +420,7 @@ export class Secp256k1 { return p ? p.assertValidity() : this.err('bad point: not on curve') } static pointFromHex (hex: string): Point { - return this.pointFromBytes(Secp256k1.hexToBytes(hex)) + return this.pointFromBytes(this.hexToBytes(hex)) } /** Generator / base point */ @@ -507,43 +507,38 @@ export class Secp256k1 { static ALL_SIG = [this.SIG_COMPACT, this.SIG_RECOVERED, this.SIG_DER] as const /** ECDSA Signature class. Supports only compact 64-byte representation, not DER. */ - static Signature = class { - readonly r: bigint - readonly s: bigint - readonly recovery?: number - constructor (r: bigint, s: bigint, recovery?: number) { - this.r = Secp256k1.FnIsValidNot0(r) // 1 <= r < N - this.s = Secp256k1.FnIsValidNot0(s) // 1 <= s < N - if (recovery != null) this.recovery = recovery - Object.freeze(this) - } - addRecoveryBit (bit: number): RecoveredSignature { - return new Secp256k1.Signature(this.r, this.s, bit) as RecoveredSignature - } - hasHighS (): boolean { - return Secp256k1.highS(this.s) - } - toBytes (format: ECDSASignatureFormat = Secp256k1.SIG_COMPACT): Bytes { - const { r, s, recovery } = this - const res = Secp256k1.concatBytes(Secp256k1.numTo32b(r), Secp256k1.numTo32b(s)) - if (format === Secp256k1.SIG_RECOVERED) { - Secp256k1.assertRecoveryBit(recovery) - return Secp256k1.concatBytes(Uint8Array.of(recovery!), res) + static Signature = (r: bigint, s: bigint, recovery?: number) => { + return Object.freeze({ + r: this.FnIsValidNot0(r), // 1 <= r < N + s: this.FnIsValidNot0(s), // 1 <= s < N + recovery: recovery ?? undefined, + addRecoveryBit: (bit: number): RecoveredSignature => { + return this.Signature(r, s, bit) as RecoveredSignature + }, + hasHighS: (): boolean => { + return this.highS(s) + }, + toBytes: (format: ECDSASignatureFormat = this.SIG_COMPACT): Bytes => { + const res = this.concatBytes(this.numTo32b(r), this.numTo32b(s)) + if (format === this.SIG_RECOVERED) { + this.assertRecoveryBit(recovery) + return this.concatBytes(Uint8Array.of(recovery!), res) + } + return res } - return res - } + }) } - static signatureFromBytes (b: Bytes, format: ECDSASignatureFormat = Secp256k1.SIG_COMPACT): Signature { - Secp256k1.assertSigLength(b, format) + static signatureFromBytes (b: Bytes, format: ECDSASignatureFormat = this.SIG_COMPACT): Signature { + this.assertSigLength(b, format) let rec: number | undefined - if (format === Secp256k1.SIG_RECOVERED) { + if (format === this.SIG_RECOVERED) { rec = b[0] b = b.subarray(1) } - const r = Secp256k1.sliceBytesNumBE(b, 0, Secp256k1.L) - const s = Secp256k1.sliceBytesNumBE(b, Secp256k1.L, Secp256k1.L2) - return new this.Signature(r, s, rec) + const r = this.sliceBytesNumBE(b, 0, this.L) + const s = this.sliceBytesNumBE(b, this.L, this.L2) + return this.Signature(r, s, rec) } /** @@ -708,7 +703,7 @@ export class Secp256k1 { normS = this.modN(-s) // in the bottom half of CURVE.n recovery ^= 1 } - const sig = new this.Signature(r, normS, recovery) as RecoveredSignature // use normS, not s + const sig = this.Signature(r, normS, recovery) as RecoveredSignature // use normS, not s return sig.toBytes(opts.format) } return hmacDrbg(seed, k2sig) -- 2.47.3