]> git.codecow.com Git - libnemo.git/commitdiff
Convert inner class to factory function.
authorChris Duncan <chris@zoso.dev>
Sun, 30 Nov 2025 11:07:41 +0000 (03:07 -0800)
committerChris Duncan <chris@zoso.dev>
Sun, 30 Nov 2025 11:07:41 +0000 (03:07 -0800)
src/lib/crypto/secp256k1.ts

index 61ab4069627e3803c8b5749cfe47bad12ff6632d..8f5970ff43ab8cfd7dc04236bb84c76a5a4553fc 100644 (file)
@@ -11,6 +11,9 @@
  * Functionality wrapped in a class for embedding into a Web Worker.
  */
 
+type Point = InstanceType<typeof Secp256k1.Point>
+type Signature = ReturnType<typeof Secp256k1.Signature>
+
 /** 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> = T | Promise<T>
 
-type Point = InstanceType<typeof Secp256k1.Point>
-type Signature = InstanceType<typeof Secp256k1.Signature>
-
 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)