@bsv/sdk 1.6.18 → 1.6.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +11 -11
  2. package/dist/cjs/package.json +4 -8
  3. package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js +39 -39
  4. package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
  5. package/dist/cjs/src/primitives/ECDSA.js +26 -125
  6. package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
  7. package/dist/cjs/src/primitives/Hash.js +660 -436
  8. package/dist/cjs/src/primitives/Hash.js.map +1 -1
  9. package/dist/cjs/src/primitives/Point.js +226 -213
  10. package/dist/cjs/src/primitives/Point.js.map +1 -1
  11. package/dist/cjs/src/transaction/Beef.js +4 -4
  12. package/dist/cjs/src/transaction/Transaction.js +3 -3
  13. package/dist/cjs/src/transaction/Transaction.js.map +1 -1
  14. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  15. package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js +39 -39
  16. package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
  17. package/dist/esm/src/primitives/ECDSA.js +26 -125
  18. package/dist/esm/src/primitives/ECDSA.js.map +1 -1
  19. package/dist/esm/src/primitives/Hash.js +672 -444
  20. package/dist/esm/src/primitives/Hash.js.map +1 -1
  21. package/dist/esm/src/primitives/Point.js +211 -213
  22. package/dist/esm/src/primitives/Point.js.map +1 -1
  23. package/dist/esm/src/transaction/Beef.js +4 -4
  24. package/dist/esm/src/transaction/Transaction.js +3 -3
  25. package/dist/esm/src/transaction/Transaction.js.map +1 -1
  26. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  27. package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts +1 -1
  28. package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts.map +1 -1
  29. package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
  30. package/dist/types/src/primitives/Hash.d.ts +12 -19
  31. package/dist/types/src/primitives/Hash.d.ts.map +1 -1
  32. package/dist/types/src/primitives/Point.d.ts +34 -0
  33. package/dist/types/src/primitives/Point.d.ts.map +1 -1
  34. package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
  35. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  36. package/dist/umd/bundle.js +20 -1
  37. package/dist/umd/bundle.js.map +1 -0
  38. package/package.json +4 -8
  39. package/src/auth/transports/SimplifiedFetchTransport.ts +64 -67
  40. package/src/primitives/ECDSA.ts +30 -173
  41. package/src/primitives/Hash.ts +752 -589
  42. package/src/primitives/Point.ts +222 -247
  43. package/src/transaction/Beef.ts +4 -4
  44. package/src/transaction/Transaction.ts +11 -3
@@ -4,6 +4,180 @@ import BigNumber from './BigNumber.js'
4
4
  import { toArray, toHex } from './utils.js'
5
5
  import ReductionContext from './ReductionContext.js'
6
6
 
7
+ // -----------------------------------------------------------------------------
8
+ // BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
9
+ // every Point.mul() call.
10
+ // -----------------------------------------------------------------------------
11
+ export const BI_ZERO = 0n
12
+ export const BI_ONE = 1n
13
+ export const BI_TWO = 2n
14
+ export const BI_THREE = 3n
15
+ export const BI_FOUR = 4n
16
+ export const BI_EIGHT = 8n
17
+
18
+ export const P_BIGINT = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2Fn
19
+ export const N_BIGINT = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141n
20
+ export const MASK_256 = (1n << 256n) - 1n // 0xffff…ffff (256 sones)
21
+
22
+ export function red (x: bigint): bigint {
23
+ // first fold
24
+ let hi = x >> 256n
25
+ x = (x & MASK_256) + (hi << 32n) + hi * 977n
26
+
27
+ // second fold (hi ≤ 2³² + 977 here, so one more pass is enough)
28
+ hi = x >> 256n
29
+ x = (x & MASK_256) + (hi << 32n) + hi * 977n
30
+
31
+ // final conditional subtraction
32
+ if (x >= P_BIGINT) x -= P_BIGINT
33
+ return x
34
+ }
35
+
36
+ export const biMod = (a: bigint): bigint => red((a % P_BIGINT + P_BIGINT) % P_BIGINT)
37
+ export const biModSub = (a: bigint, b: bigint): bigint => (a >= b ? a - b : P_BIGINT - (b - a))
38
+ export const biModMul = (a: bigint, b: bigint): bigint => red(a * b)
39
+ export const biModAdd = (a: bigint, b: bigint): bigint => red(a + b)
40
+ export const biModInv = (a: bigint): bigint => { // binary‑ext GCD
41
+ let lm = BI_ONE; let hm = BI_ZERO; let low = biMod(a); let high = P_BIGINT
42
+ while (low > BI_ONE) { const r = high / low; [lm, hm] = [hm - lm * r, lm]; [low, high] = [high - low * r, low] }
43
+ return biMod(lm)
44
+ }
45
+ export const biModSqr = (a: bigint): bigint => biModMul(a, a)
46
+
47
+ // Generator point coordinates as bigint constants
48
+ export const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
49
+ export const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8')
50
+
51
+ // Cache for precomputed windowed tables keyed by 'window:x:y'
52
+ const WNAF_TABLE_CACHE: Map<string, JacobianPointBI[]> = new Map()
53
+
54
+ export interface JacobianPointBI { X: bigint, Y: bigint, Z: bigint }
55
+
56
+ export const jpDouble = (P: JacobianPointBI): JacobianPointBI => {
57
+ const { X: X1, Y: Y1, Z: Z1 } = P
58
+ if (Y1 === BI_ZERO) return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }
59
+
60
+ const Y1sq = biModMul(Y1, Y1)
61
+ const S = biModMul(BI_FOUR, biModMul(X1, Y1sq))
62
+ const M = biModMul(BI_THREE, biModMul(X1, X1))
63
+ const X3 = biModSub(biModMul(M, M), biModMul(BI_TWO, S))
64
+ const Y3 = biModSub(
65
+ biModMul(M, biModSub(S, X3)),
66
+ biModMul(BI_EIGHT, biModMul(Y1sq, Y1sq))
67
+ )
68
+ const Z3 = biModMul(BI_TWO, biModMul(Y1, Z1))
69
+ return { X: X3, Y: Y3, Z: Z3 }
70
+ }
71
+
72
+ export const jpAdd = (P: JacobianPointBI, Q: JacobianPointBI): JacobianPointBI => {
73
+ if (P.Z === BI_ZERO) return Q
74
+ if (Q.Z === BI_ZERO) return P
75
+
76
+ const Z1Z1 = biModMul(P.Z, P.Z)
77
+ const Z2Z2 = biModMul(Q.Z, Q.Z)
78
+ const U1 = biModMul(P.X, Z2Z2)
79
+ const U2 = biModMul(Q.X, Z1Z1)
80
+ const S1 = biModMul(P.Y, biModMul(Z2Z2, Q.Z))
81
+ const S2 = biModMul(Q.Y, biModMul(Z1Z1, P.Z))
82
+
83
+ const H = biModSub(U2, U1)
84
+ const r = biModSub(S2, S1)
85
+ if (H === BI_ZERO) {
86
+ if (r === BI_ZERO) return jpDouble(P)
87
+ return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO } // Infinity
88
+ }
89
+
90
+ const HH = biModMul(H, H)
91
+ const HHH = biModMul(H, HH)
92
+ const V = biModMul(U1, HH)
93
+
94
+ const X3 = biModSub(biModSub(biModMul(r, r), HHH), biModMul(BI_TWO, V))
95
+ const Y3 = biModSub(biModMul(r, biModSub(V, X3)), biModMul(S1, HHH))
96
+ const Z3 = biModMul(H, biModMul(P.Z, Q.Z))
97
+ return { X: X3, Y: Y3, Z: Z3 }
98
+ }
99
+
100
+ export const jpNeg = (P: JacobianPointBI): JacobianPointBI => {
101
+ if (P.Z === BI_ZERO) return P
102
+ return { X: P.X, Y: P_BIGINT - P.Y, Z: P.Z }
103
+ }
104
+
105
+ // Fast windowed-NAF scalar multiplication (default window = 5) in Jacobian
106
+ // coordinates. Returns Q = k * P0 as a JacobianPoint.
107
+ export const scalarMultiplyWNAF = (
108
+ k: bigint,
109
+ P0: { x: bigint, y: bigint },
110
+ window: number = 5
111
+ ): JacobianPointBI => {
112
+ const key = `${window}:${P0.x.toString(16)}:${P0.y.toString(16)}`
113
+ let tbl = WNAF_TABLE_CACHE.get(key)
114
+ let P: JacobianPointBI
115
+ if (tbl === undefined) {
116
+ // Convert affine to Jacobian and pre-compute odd multiples
117
+ const tblSize = 1 << (window - 1) // e.g. w=5 → 16 entries
118
+ tbl = new Array(tblSize)
119
+ P = { X: P0.x, Y: P0.y, Z: BI_ONE }
120
+ tbl[0] = P
121
+ const twoP = jpDouble(P)
122
+ for (let i = 1; i < tblSize; i++) {
123
+ tbl[i] = jpAdd(tbl[i - 1], twoP)
124
+ }
125
+ WNAF_TABLE_CACHE.set(key, tbl)
126
+ } else {
127
+ P = tbl[0]
128
+ }
129
+
130
+ // Build wNAF representation of k
131
+ const wnaf: number[] = []
132
+ const wBig = 1n << BigInt(window)
133
+ const wHalf = wBig >> 1n
134
+ let kTmp = k
135
+ while (kTmp > 0n) {
136
+ if ((kTmp & BI_ONE) === BI_ZERO) {
137
+ wnaf.push(0)
138
+ kTmp >>= BI_ONE
139
+ } else {
140
+ let z = kTmp & (wBig - 1n) // kTmp mod 2^w
141
+ if (z > wHalf) z -= wBig // make it odd & within (-2^{w-1}, 2^{w-1})
142
+ wnaf.push(Number(z))
143
+ kTmp -= z
144
+ kTmp >>= BI_ONE
145
+ }
146
+ }
147
+
148
+ // Accumulate from MSB to LSB
149
+ let Q: JacobianPointBI = { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO } // infinity
150
+ for (let i = wnaf.length - 1; i >= 0; i--) {
151
+ Q = jpDouble(Q)
152
+ const di = wnaf[i]
153
+ if (di !== 0) {
154
+ const idx = Math.abs(di) >> 1 // (|di|-1)/2 because di is odd
155
+ const addend = di > 0 ? tbl[idx] : jpNeg(tbl[idx])
156
+ Q = jpAdd(Q, addend)
157
+ }
158
+ }
159
+ return Q
160
+ }
161
+
162
+ export const modN = (a: bigint): bigint => {
163
+ let r = a % N_BIGINT
164
+ if (r < 0n) r += N_BIGINT
165
+ return r
166
+ }
167
+ export const modMulN = (a: bigint, b: bigint): bigint => modN(a * b)
168
+
169
+ /** modular inverse modulo n with plain extended‑gcd (not constant‑time) */
170
+ export const modInvN = (a: bigint): bigint => {
171
+ let lm = 1n; let hm = 0n
172
+ let low = modN(a); let high = N_BIGINT
173
+ while (low > 1n) {
174
+ const q = high / low
175
+ ;[lm, hm] = [hm - lm * q, lm]
176
+ ;[low, high] = [high - low * q, low]
177
+ }
178
+ return modN(lm)
179
+ }
180
+
7
181
  /**
8
182
  * `Point` class is a representation of an elliptic curve point with affine coordinates.
9
183
  * It extends the functionality of BasePoint and carries x, y coordinates of point on the curve.
@@ -456,17 +630,18 @@ export default class Point extends BasePoint {
456
630
  return new Point(new BigNumber(0), new BigNumber(0))
457
631
  }
458
632
 
459
- let c = this.y?.redSub(p.y ?? new BigNumber(0)) ?? new BigNumber(0)
460
- if (c.cmpn(0) !== 0) {
461
- c = c.redMul(this.x?.redSub(p.x ?? new BigNumber(0)).redInvm() ?? new BigNumber(1))
633
+ const q = {
634
+ x: BigInt('0x' + (p.x as BigNumber).fromRed().toString(16)),
635
+ y: BigInt('0x' + (p.y as BigNumber).fromRed().toString(16))
462
636
  }
463
-
464
- const nx = c?.redSqr().redISub(this.x ?? new BigNumber(0)).redISub(p.x ?? new BigNumber(0))
465
- const ny = (c ?? new BigNumber(1))
466
- .redMul((this.x ?? new BigNumber(0)).redSub(nx ?? new BigNumber(0)))
467
- .redISub(this.y ?? new BigNumber(0))
468
-
469
- return new Point(nx ?? new BigNumber(0), ny ?? new BigNumber(0))
637
+ const t = {
638
+ x: BigInt('0x' + (this.x as BigNumber).fromRed().toString(16)),
639
+ y: BigInt('0x' + (this.y as BigNumber).fromRed().toString(16))
640
+ }
641
+ const λ = biModMul(biModSub(q.y, t.y), biModInv(biModSub(q.x, t.x)))
642
+ const rx = biModSub(biModSub(biModSqr(λ), t.x), q.x)
643
+ const ry = biModSub(biModMul(λ, biModSub(t.x, rx)), t.y)
644
+ return new Point(rx.toString(16), ry.toString(16))
470
645
  }
471
646
 
472
647
  /**
@@ -538,102 +713,48 @@ export default class Point extends BasePoint {
538
713
  k = new BigNumber(k as number, 16)
539
714
  }
540
715
  k = k as BigNumber
541
- if (typeof BigInt === 'function') {
542
- if (this.inf) {
543
- return this
544
- }
545
-
546
- const zero = 0n
547
- const one = 1n
548
- const p = BigInt(
549
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
550
- )
551
- const n = BigInt(
552
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
553
- )
554
-
555
- let kBig = BigInt('0x' + k.toString(16))
556
- const isNeg = kBig < zero
557
- if (isNeg) kBig = -kBig
558
- kBig = ((kBig % n) + n) % n
559
- if (kBig === zero) {
560
- return new Point(null, null)
561
- }
562
-
563
- if (this.x === null || this.y === null) {
564
- throw new Error('Point coordinates cannot be null')
565
- }
566
-
567
- let Px: bigint
568
- let Py: bigint
569
- if (this === this.curve.g) {
570
- Px = GX_BIGINT
571
- Py = GY_BIGINT
572
- } else {
573
- Px = BigInt('0x' + this.x.fromRed().toString(16))
574
- Py = BigInt('0x' + this.y.fromRed().toString(16))
575
- }
576
-
577
- const mod = (a: bigint, m: bigint): bigint => ((a % m) + m) % m
578
- const modMul = (a: bigint, b: bigint, m: bigint): bigint => mod(a * b, m)
579
- const modInv = (a: bigint, m: bigint): bigint => {
580
- let lm = one
581
- let hm = zero
582
- let low = mod(a, m)
583
- let high = m
584
- while (low > one) {
585
- const r = high / low
586
- const nm = hm - lm * r
587
- const neww = high - low * r
588
- hm = lm
589
- lm = nm
590
- high = low
591
- low = neww
592
- }
593
- return mod(lm, m)
594
- }
716
+ if (this.inf) {
717
+ return this
718
+ }
595
719
 
596
- interface JacobianPoint {
597
- X: bigint
598
- Y: bigint
599
- Z: bigint
600
- }
720
+ let kBig = BigInt('0x' + k.toString(16))
721
+ const isNeg = kBig < BI_ZERO
722
+ if (isNeg) kBig = -kBig
723
+ kBig = biMod(kBig)
724
+ if (kBig === BI_ZERO) {
725
+ return new Point(null, null)
726
+ }
601
727
 
602
- const scalarMultiply = (
603
- kVal: bigint,
604
- P0: { x: bigint, y: bigint }
605
- ): JacobianPoint => {
606
- // Delegate to the hoisted windowed-NAF implementation above. We
607
- // keep the wrapper so that the rest of the mul() code remains
608
- // untouched while providing a massive speed-up (≈4-6×).
609
- return scalarMultiplyWNAF(kVal, P0) as unknown as JacobianPoint
610
- }
728
+ if (this.x === null || this.y === null) {
729
+ throw new Error('Point coordinates cannot be null')
730
+ }
611
731
 
612
- const R = scalarMultiply(kBig, { x: Px, y: Py })
613
- if (R.Z === zero) {
614
- return new Point(null, null)
615
- }
616
- const zInv = modInv(R.Z, p)
617
- const zInv2 = modMul(zInv, zInv, p)
618
- const xRes = modMul(R.X, zInv2, p)
619
- const yRes = modMul(R.Y, modMul(zInv2, zInv, p), p)
620
-
621
- const xBN = new BigNumber(xRes.toString(16), 16)
622
- const yBN = new BigNumber(yRes.toString(16), 16)
623
- const result = new Point(xBN, yBN)
624
- if (isNeg) {
625
- return result.neg()
626
- }
627
- return result
732
+ let Px: bigint
733
+ let Py: bigint
734
+ if (this === this.curve.g) {
735
+ Px = GX_BIGINT
736
+ Py = GY_BIGINT
628
737
  } else {
629
- if (this.isInfinity()) {
630
- return this
631
- } else if (this._hasDoubles(k)) {
632
- return this._fixedNafMul(k)
633
- } else {
634
- return this._endoWnafMulAdd([this], [k]) as Point
635
- }
738
+ Px = BigInt('0x' + this.x.fromRed().toString(16))
739
+ Py = BigInt('0x' + this.y.fromRed().toString(16))
636
740
  }
741
+
742
+ const R = scalarMultiplyWNAF(kBig, { x: Px, y: Py })
743
+ if (R.Z === BI_ZERO) {
744
+ return new Point(null, null)
745
+ }
746
+ const zInv = biModInv(R.Z)
747
+ const zInv2 = biModMul(zInv, zInv)
748
+ const xRes = biModMul(R.X, zInv2)
749
+ const yRes = biModMul(R.Y, biModMul(zInv2, zInv))
750
+
751
+ const xBN = new BigNumber(xRes.toString(16), 16)
752
+ const yBN = new BigNumber(yRes.toString(16), 16)
753
+ const result = new Point(xBN, yBN)
754
+ if (isNeg) {
755
+ return result.neg()
756
+ }
757
+ return result
637
758
  }
638
759
 
639
760
  /**
@@ -1107,149 +1228,3 @@ export default class Point extends BasePoint {
1107
1228
  }
1108
1229
  }
1109
1230
  }
1110
-
1111
- // -----------------------------------------------------------------------------
1112
- // BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
1113
- // every Point.mul() call.
1114
- // -----------------------------------------------------------------------------
1115
- const BI_ZERO = 0n
1116
- const BI_ONE = 1n
1117
- const BI_TWO = 2n
1118
- const BI_THREE = 3n
1119
- const BI_FOUR = 4n
1120
- const BI_EIGHT = 8n
1121
-
1122
- const P_BIGINT = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2Fn
1123
- const MASK_256 = (1n << 256n) - 1n // 0xffff…ffff (256 sones)
1124
-
1125
- function red (x: bigint): bigint {
1126
- // first fold
1127
- let hi = x >> 256n
1128
- x = (x & MASK_256) + (hi << 32n) + hi * 977n
1129
-
1130
- // second fold (hi ≤ 2³² + 977 here, so one more pass is enough)
1131
- hi = x >> 256n
1132
- x = (x & MASK_256) + (hi << 32n) + hi * 977n
1133
-
1134
- // final conditional subtraction
1135
- if (x >= P_BIGINT) x -= P_BIGINT
1136
- return x
1137
- }
1138
-
1139
- const biModSub = (a: bigint, b: bigint): bigint => (a >= b ? a - b : P_BIGINT - (b - a))
1140
- const biModMul = (a: bigint, b: bigint): bigint => red(a * b)
1141
-
1142
- // Generator point coordinates as bigint constants
1143
- const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
1144
- const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8')
1145
-
1146
- // Cache for precomputed windowed tables keyed by 'window:x:y'
1147
- const WNAF_TABLE_CACHE: Map<string, JacobianPointBI[]> = new Map()
1148
-
1149
- interface JacobianPointBI { X: bigint, Y: bigint, Z: bigint }
1150
-
1151
- const jpDouble = (P: JacobianPointBI): JacobianPointBI => {
1152
- const { X: X1, Y: Y1, Z: Z1 } = P
1153
- if (Y1 === BI_ZERO) return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }
1154
-
1155
- const Y1sq = biModMul(Y1, Y1)
1156
- const S = biModMul(BI_FOUR, biModMul(X1, Y1sq))
1157
- const M = biModMul(BI_THREE, biModMul(X1, X1))
1158
- const X3 = biModSub(biModMul(M, M), biModMul(BI_TWO, S))
1159
- const Y3 = biModSub(
1160
- biModMul(M, biModSub(S, X3)),
1161
- biModMul(BI_EIGHT, biModMul(Y1sq, Y1sq))
1162
- )
1163
- const Z3 = biModMul(BI_TWO, biModMul(Y1, Z1))
1164
- return { X: X3, Y: Y3, Z: Z3 }
1165
- }
1166
-
1167
- const jpAdd = (P: JacobianPointBI, Q: JacobianPointBI): JacobianPointBI => {
1168
- if (P.Z === BI_ZERO) return Q
1169
- if (Q.Z === BI_ZERO) return P
1170
-
1171
- const Z1Z1 = biModMul(P.Z, P.Z)
1172
- const Z2Z2 = biModMul(Q.Z, Q.Z)
1173
- const U1 = biModMul(P.X, Z2Z2)
1174
- const U2 = biModMul(Q.X, Z1Z1)
1175
- const S1 = biModMul(P.Y, biModMul(Z2Z2, Q.Z))
1176
- const S2 = biModMul(Q.Y, biModMul(Z1Z1, P.Z))
1177
-
1178
- const H = biModSub(U2, U1)
1179
- const r = biModSub(S2, S1)
1180
- if (H === BI_ZERO) {
1181
- if (r === BI_ZERO) return jpDouble(P)
1182
- return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO } // Infinity
1183
- }
1184
-
1185
- const HH = biModMul(H, H)
1186
- const HHH = biModMul(H, HH)
1187
- const V = biModMul(U1, HH)
1188
-
1189
- const X3 = biModSub(biModSub(biModMul(r, r), HHH), biModMul(BI_TWO, V))
1190
- const Y3 = biModSub(biModMul(r, biModSub(V, X3)), biModMul(S1, HHH))
1191
- const Z3 = biModMul(H, biModMul(P.Z, Q.Z))
1192
- return { X: X3, Y: Y3, Z: Z3 }
1193
- }
1194
-
1195
- const jpNeg = (P: JacobianPointBI): JacobianPointBI => {
1196
- if (P.Z === BI_ZERO) return P
1197
- return { X: P.X, Y: P_BIGINT - P.Y, Z: P.Z }
1198
- }
1199
-
1200
- // Fast windowed-NAF scalar multiplication (default window = 5) in Jacobian
1201
- // coordinates. Returns Q = k * P0 as a JacobianPoint.
1202
- const scalarMultiplyWNAF = (
1203
- k: bigint,
1204
- P0: { x: bigint, y: bigint },
1205
- window: number = 5
1206
- ): JacobianPointBI => {
1207
- const key = `${window}:${P0.x.toString(16)}:${P0.y.toString(16)}`
1208
- let tbl = WNAF_TABLE_CACHE.get(key)
1209
- let P: JacobianPointBI
1210
- if (tbl === undefined) {
1211
- // Convert affine to Jacobian and pre-compute odd multiples
1212
- const tblSize = 1 << (window - 1) // e.g. w=5 → 16 entries
1213
- tbl = new Array(tblSize)
1214
- P = { X: P0.x, Y: P0.y, Z: BI_ONE }
1215
- tbl[0] = P
1216
- const twoP = jpDouble(P)
1217
- for (let i = 1; i < tblSize; i++) {
1218
- tbl[i] = jpAdd(tbl[i - 1], twoP)
1219
- }
1220
- WNAF_TABLE_CACHE.set(key, tbl)
1221
- } else {
1222
- P = tbl[0]
1223
- }
1224
-
1225
- // Build wNAF representation of k
1226
- const wnaf: number[] = []
1227
- const wBig = 1n << BigInt(window)
1228
- const wHalf = wBig >> 1n
1229
- let kTmp = k
1230
- while (kTmp > 0n) {
1231
- if ((kTmp & BI_ONE) === BI_ZERO) {
1232
- wnaf.push(0)
1233
- kTmp >>= BI_ONE
1234
- } else {
1235
- let z = kTmp & (wBig - 1n) // kTmp mod 2^w
1236
- if (z > wHalf) z -= wBig // make it odd & within (-2^{w-1}, 2^{w-1})
1237
- wnaf.push(Number(z))
1238
- kTmp -= z
1239
- kTmp >>= BI_ONE
1240
- }
1241
- }
1242
-
1243
- // Accumulate from MSB to LSB
1244
- let Q: JacobianPointBI = { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO } // infinity
1245
- for (let i = wnaf.length - 1; i >= 0; i--) {
1246
- Q = jpDouble(Q)
1247
- const di = wnaf[i]
1248
- if (di !== 0) {
1249
- const idx = Math.abs(di) >> 1 // (|di|-1)/2 because di is odd
1250
- const addend = di > 0 ? tbl[idx] : jpNeg(tbl[idx])
1251
- Q = jpAdd(Q, addend)
1252
- }
1253
- }
1254
- return Q
1255
- }
@@ -21,18 +21,18 @@ export enum TX_DATA_FORMAT {
21
21
 
22
22
  /*
23
23
  * BEEF standard: BRC-62: Background Evaluation Extended Format (BEEF) Transactions
24
- * https://github.com/bitcoin-sv/BRCs/blob/master/transactions/0062.md
24
+ * https://github.com/bsv-blockchain/BRCs/blob/master/transactions/0062.md
25
25
  *
26
26
  * BUMP standard: BRC-74: BSV Unified Merkle Path (BUMP) Format
27
- * https://github.com/bitcoin-sv/BRCs/blob/master/transactions/0074.md
27
+ * https://github.com/bsv-blockchain/BRCs/blob/master/transactions/0074.md
28
28
  *
29
29
  * BRC-95: Atomic BEEF Transactions
30
- * https://github.com/bitcoin-sv/BRCs/blob/master/transactions/0095.md
30
+ * https://github.com/bsv-blockchain/BRCs/blob/master/transactions/0095.md
31
31
  *
32
32
  * The Atomic BEEF format is supported by the binary deserialization static method `fromBinary`.
33
33
  *
34
34
  * BRC-96: BEEF V2, Txid Only Extension
35
- * https://github.com/bitcoin-sv/BRCs/blob/master/transactions/0096.md
35
+ * https://github.com/bsv-blockchain/BRCs/blob/master/transactions/0096.md
36
36
  *
37
37
  * A valid serialized BEEF is the cornerstone of Simplified Payment Validation (SPV)
38
38
  * where they are exchanged between two non-trusting parties to establish the
@@ -119,7 +119,11 @@ export default class Transaction {
119
119
  static fromAtomicBEEF (beef: number[]): Transaction {
120
120
  const { tx, txid, beef: b } = Transaction.fromAnyBeef(beef)
121
121
  if (txid !== b.atomicTxid) {
122
- if (b.atomicTxid) { throw new Error(`Transaction with TXID ${b.atomicTxid} not found in BEEF data.`) } else { throw new Error('beef must conform to BRC-95 and must contain the subject txid.') }
122
+ if (b.atomicTxid != null) {
123
+ throw new Error(`Transaction with TXID ${b.atomicTxid} not found in BEEF data.`)
124
+ } else {
125
+ throw new Error('beef must conform to BRC-95 and must contain the subject txid.')
126
+ }
123
127
  }
124
128
  return tx
125
129
  }
@@ -129,10 +133,14 @@ export default class Transaction {
129
133
  if (b.txs.length < 1) {
130
134
  throw new Error('beef must include at least one transaction.')
131
135
  }
132
- const target = txid || b.atomicTxid || b.txs.slice(-1)[0].txid
136
+ const target = txid ?? b.atomicTxid ?? b.txs.slice(-1)[0].txid
133
137
  const tx = b.findAtomicTransaction(target)
134
138
  if (tx == null) {
135
- if (txid) { throw new Error(`Transaction with TXID ${target} not found in BEEF data.`) } else { throw new Error('beef does not contain transaction for atomic txid.') }
139
+ if (txid != null) {
140
+ throw new Error(`Transaction with TXID ${target} not found in BEEF data.`)
141
+ } else {
142
+ throw new Error('beef does not contain transaction for atomic txid.')
143
+ }
136
144
  }
137
145
  return { tx, beef: b, txid: target }
138
146
  }