@bsv/sdk 1.6.18 → 1.6.20

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 (64) hide show
  1. package/README.md +11 -11
  2. package/dist/cjs/package.json +5 -9
  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 +69 -167
  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 +285 -293
  10. package/dist/cjs/src/primitives/Point.js.map +1 -1
  11. package/dist/cjs/src/script/ScriptEvaluationError.js +27 -0
  12. package/dist/cjs/src/script/ScriptEvaluationError.js.map +1 -0
  13. package/dist/cjs/src/script/Spend.js +13 -7
  14. package/dist/cjs/src/script/Spend.js.map +1 -1
  15. package/dist/cjs/src/script/index.js +3 -1
  16. package/dist/cjs/src/script/index.js.map +1 -1
  17. package/dist/cjs/src/transaction/Beef.js +4 -4
  18. package/dist/cjs/src/transaction/Transaction.js +3 -3
  19. package/dist/cjs/src/transaction/Transaction.js.map +1 -1
  20. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  21. package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js +39 -39
  22. package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
  23. package/dist/esm/src/primitives/ECDSA.js +69 -167
  24. package/dist/esm/src/primitives/ECDSA.js.map +1 -1
  25. package/dist/esm/src/primitives/Hash.js +672 -444
  26. package/dist/esm/src/primitives/Hash.js.map +1 -1
  27. package/dist/esm/src/primitives/Point.js +268 -293
  28. package/dist/esm/src/primitives/Point.js.map +1 -1
  29. package/dist/esm/src/script/ScriptEvaluationError.js +33 -0
  30. package/dist/esm/src/script/ScriptEvaluationError.js.map +1 -0
  31. package/dist/esm/src/script/Spend.js +14 -8
  32. package/dist/esm/src/script/Spend.js.map +1 -1
  33. package/dist/esm/src/script/index.js +1 -0
  34. package/dist/esm/src/script/index.js.map +1 -1
  35. package/dist/esm/src/transaction/Beef.js +4 -4
  36. package/dist/esm/src/transaction/Transaction.js +3 -3
  37. package/dist/esm/src/transaction/Transaction.js.map +1 -1
  38. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  39. package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts +1 -1
  40. package/dist/types/src/auth/transports/SimplifiedFetchTransport.d.ts.map +1 -1
  41. package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
  42. package/dist/types/src/primitives/Hash.d.ts +12 -19
  43. package/dist/types/src/primitives/Hash.d.ts.map +1 -1
  44. package/dist/types/src/primitives/Point.d.ts +37 -5
  45. package/dist/types/src/primitives/Point.d.ts.map +1 -1
  46. package/dist/types/src/script/ScriptEvaluationError.d.ts +24 -0
  47. package/dist/types/src/script/ScriptEvaluationError.d.ts.map +1 -0
  48. package/dist/types/src/script/Spend.d.ts.map +1 -1
  49. package/dist/types/src/script/index.d.ts +1 -0
  50. package/dist/types/src/script/index.d.ts.map +1 -1
  51. package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
  52. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  53. package/dist/umd/bundle.js +20 -1
  54. package/dist/umd/bundle.js.map +1 -0
  55. package/package.json +5 -9
  56. package/src/auth/transports/SimplifiedFetchTransport.ts +64 -67
  57. package/src/primitives/ECDSA.ts +80 -222
  58. package/src/primitives/Hash.ts +752 -589
  59. package/src/primitives/Point.ts +277 -336
  60. package/src/script/ScriptEvaluationError.ts +44 -0
  61. package/src/script/Spend.ts +14 -12
  62. package/src/script/index.ts +1 -0
  63. package/src/transaction/Beef.ts +4 -4
  64. package/src/transaction/Transaction.ts +11 -3
@@ -2,7 +2,195 @@ import BasePoint from './BasePoint.js';
2
2
  import JPoint from './JacobianPoint.js';
3
3
  import BigNumber from './BigNumber.js';
4
4
  import { toArray, toHex } from './utils.js';
5
- import ReductionContext from './ReductionContext.js';
5
+ // -----------------------------------------------------------------------------
6
+ // BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
7
+ // every Point.mul() call.
8
+ // -----------------------------------------------------------------------------
9
+ export const BI_ZERO = 0n;
10
+ export const BI_ONE = 1n;
11
+ export const BI_TWO = 2n;
12
+ export const BI_THREE = 3n;
13
+ export const BI_FOUR = 4n;
14
+ export const BI_EIGHT = 8n;
15
+ export const P_BIGINT = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
16
+ export const N_BIGINT = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
17
+ export const MASK_256 = (1n << 256n) - 1n; // 0xffff…ffff (256 sones)
18
+ export function red(x) {
19
+ // first fold
20
+ let hi = x >> 256n;
21
+ x = (x & MASK_256) + (hi << 32n) + hi * 977n;
22
+ // second fold (hi ≤ 2³² + 977 here, so one more pass is enough)
23
+ hi = x >> 256n;
24
+ x = (x & MASK_256) + (hi << 32n) + hi * 977n;
25
+ // final conditional subtraction
26
+ if (x >= P_BIGINT)
27
+ x -= P_BIGINT;
28
+ return x;
29
+ }
30
+ export const biMod = (a) => red((a % P_BIGINT + P_BIGINT) % P_BIGINT);
31
+ export const biModSub = (a, b) => (a >= b ? a - b : P_BIGINT - (b - a));
32
+ export const biModMul = (a, b) => red(a * b);
33
+ export const biModAdd = (a, b) => red(a + b);
34
+ export const biModInv = (a) => {
35
+ let lm = BI_ONE;
36
+ let hm = BI_ZERO;
37
+ let low = biMod(a);
38
+ let high = P_BIGINT;
39
+ while (low > BI_ONE) {
40
+ const r = high / low;
41
+ [lm, hm] = [hm - lm * r, lm];
42
+ [low, high] = [high - low * r, low];
43
+ }
44
+ return biMod(lm);
45
+ };
46
+ export const biModSqr = (a) => biModMul(a, a);
47
+ export const biModPow = (base, exp) => {
48
+ let result = BI_ONE;
49
+ base = biMod(base);
50
+ let e = exp;
51
+ while (e > BI_ZERO) {
52
+ if ((e & BI_ONE) === BI_ONE)
53
+ result = biModMul(result, base);
54
+ base = biModMul(base, base);
55
+ e >>= BI_ONE;
56
+ }
57
+ return result;
58
+ };
59
+ export const P_PLUS1_DIV4 = (P_BIGINT + 1n) >> 2n;
60
+ export const biModSqrt = (a) => {
61
+ const r = biModPow(a, P_PLUS1_DIV4);
62
+ return biModMul(r, r) === biMod(a) ? r : null;
63
+ };
64
+ const toBigInt = (x) => {
65
+ if (BigNumber.isBN(x))
66
+ return BigInt('0x' + x.toString(16));
67
+ if (typeof x === 'string')
68
+ return BigInt('0x' + x);
69
+ if (Array.isArray(x))
70
+ return BigInt('0x' + toHex(x));
71
+ return BigInt(x);
72
+ };
73
+ // Generator point coordinates as bigint constants
74
+ export const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
75
+ export const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8');
76
+ // Cache for precomputed windowed tables keyed by 'window:x:y'
77
+ const WNAF_TABLE_CACHE = new Map();
78
+ export const jpDouble = (P) => {
79
+ const { X: X1, Y: Y1, Z: Z1 } = P;
80
+ if (Y1 === BI_ZERO)
81
+ return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO };
82
+ const Y1sq = biModMul(Y1, Y1);
83
+ const S = biModMul(BI_FOUR, biModMul(X1, Y1sq));
84
+ const M = biModMul(BI_THREE, biModMul(X1, X1));
85
+ const X3 = biModSub(biModMul(M, M), biModMul(BI_TWO, S));
86
+ const Y3 = biModSub(biModMul(M, biModSub(S, X3)), biModMul(BI_EIGHT, biModMul(Y1sq, Y1sq)));
87
+ const Z3 = biModMul(BI_TWO, biModMul(Y1, Z1));
88
+ return { X: X3, Y: Y3, Z: Z3 };
89
+ };
90
+ export const jpAdd = (P, Q) => {
91
+ if (P.Z === BI_ZERO)
92
+ return Q;
93
+ if (Q.Z === BI_ZERO)
94
+ return P;
95
+ const Z1Z1 = biModMul(P.Z, P.Z);
96
+ const Z2Z2 = biModMul(Q.Z, Q.Z);
97
+ const U1 = biModMul(P.X, Z2Z2);
98
+ const U2 = biModMul(Q.X, Z1Z1);
99
+ const S1 = biModMul(P.Y, biModMul(Z2Z2, Q.Z));
100
+ const S2 = biModMul(Q.Y, biModMul(Z1Z1, P.Z));
101
+ const H = biModSub(U2, U1);
102
+ const r = biModSub(S2, S1);
103
+ if (H === BI_ZERO) {
104
+ if (r === BI_ZERO)
105
+ return jpDouble(P);
106
+ return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // Infinity
107
+ }
108
+ const HH = biModMul(H, H);
109
+ const HHH = biModMul(H, HH);
110
+ const V = biModMul(U1, HH);
111
+ const X3 = biModSub(biModSub(biModMul(r, r), HHH), biModMul(BI_TWO, V));
112
+ const Y3 = biModSub(biModMul(r, biModSub(V, X3)), biModMul(S1, HHH));
113
+ const Z3 = biModMul(H, biModMul(P.Z, Q.Z));
114
+ return { X: X3, Y: Y3, Z: Z3 };
115
+ };
116
+ export const jpNeg = (P) => {
117
+ if (P.Z === BI_ZERO)
118
+ return P;
119
+ return { X: P.X, Y: P_BIGINT - P.Y, Z: P.Z };
120
+ };
121
+ // Fast windowed-NAF scalar multiplication (default window = 5) in Jacobian
122
+ // coordinates. Returns Q = k * P0 as a JacobianPoint.
123
+ export const scalarMultiplyWNAF = (k, P0, window = 5) => {
124
+ const key = `${window}:${P0.x.toString(16)}:${P0.y.toString(16)}`;
125
+ let tbl = WNAF_TABLE_CACHE.get(key);
126
+ let P;
127
+ if (tbl === undefined) {
128
+ // Convert affine to Jacobian and pre-compute odd multiples
129
+ const tblSize = 1 << (window - 1); // e.g. w=5 → 16 entries
130
+ tbl = new Array(tblSize);
131
+ P = { X: P0.x, Y: P0.y, Z: BI_ONE };
132
+ tbl[0] = P;
133
+ const twoP = jpDouble(P);
134
+ for (let i = 1; i < tblSize; i++) {
135
+ tbl[i] = jpAdd(tbl[i - 1], twoP);
136
+ }
137
+ WNAF_TABLE_CACHE.set(key, tbl);
138
+ }
139
+ else {
140
+ P = tbl[0];
141
+ }
142
+ // Build wNAF representation of k
143
+ const wnaf = [];
144
+ const wBig = 1n << BigInt(window);
145
+ const wHalf = wBig >> 1n;
146
+ let kTmp = k;
147
+ while (kTmp > 0n) {
148
+ if ((kTmp & BI_ONE) === BI_ZERO) {
149
+ wnaf.push(0);
150
+ kTmp >>= BI_ONE;
151
+ }
152
+ else {
153
+ let z = kTmp & (wBig - 1n); // kTmp mod 2^w
154
+ if (z > wHalf)
155
+ z -= wBig; // make it odd & within (-2^{w-1}, 2^{w-1})
156
+ wnaf.push(Number(z));
157
+ kTmp -= z;
158
+ kTmp >>= BI_ONE;
159
+ }
160
+ }
161
+ // Accumulate from MSB to LSB
162
+ let Q = { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // infinity
163
+ for (let i = wnaf.length - 1; i >= 0; i--) {
164
+ Q = jpDouble(Q);
165
+ const di = wnaf[i];
166
+ if (di !== 0) {
167
+ const idx = Math.abs(di) >> 1; // (|di|-1)/2 because di is odd
168
+ const addend = di > 0 ? tbl[idx] : jpNeg(tbl[idx]);
169
+ Q = jpAdd(Q, addend);
170
+ }
171
+ }
172
+ return Q;
173
+ };
174
+ export const modN = (a) => {
175
+ let r = a % N_BIGINT;
176
+ if (r < 0n)
177
+ r += N_BIGINT;
178
+ return r;
179
+ };
180
+ export const modMulN = (a, b) => modN(a * b);
181
+ /** modular inverse modulo n with plain extended‑gcd (not constant‑time) */
182
+ export const modInvN = (a) => {
183
+ let lm = 1n;
184
+ let hm = 0n;
185
+ let low = modN(a);
186
+ let high = N_BIGINT;
187
+ while (low > 1n) {
188
+ const q = high / low;
189
+ [lm, hm] = [hm - lm * q, lm];
190
+ [low, high] = [high - low * q, low];
191
+ }
192
+ return modN(lm);
193
+ };
6
194
  /**
7
195
  * `Point` class is a representation of an elliptic curve point with affine coordinates.
8
196
  * It extends the functionality of BasePoint and carries x, y coordinates of point on the curve.
@@ -16,10 +204,6 @@ import ReductionContext from './ReductionContext.js';
16
204
  * @property inf - Flag to record if the point is at infinity in the Elliptic Curve.
17
205
  */
18
206
  export default class Point extends BasePoint {
19
- static red = new ReductionContext('k256');
20
- static a = new BigNumber(0).toRed(Point.red);
21
- static b = new BigNumber(7).toRed(Point.red);
22
- static zero = new BigNumber(0).toRed(Point.red);
23
207
  x;
24
208
  y;
25
209
  inf;
@@ -84,12 +268,6 @@ export default class Point extends BasePoint {
84
268
  const bytes = toArray(str, 'hex');
85
269
  return Point.fromDER(bytes);
86
270
  }
87
- static redSqrtOptimized(y2) {
88
- const red = Point.red;
89
- const p = red.m; // The modulus
90
- const exponent = p.addn(1).iushrn(2); // (p + 1) / 4
91
- return y2.redPow(exponent);
92
- }
93
271
  /**
94
272
  * Generates a point from an x coordinate and a boolean indicating whether the corresponding
95
273
  * y coordinate is odd.
@@ -106,62 +284,18 @@ export default class Point extends BasePoint {
106
284
  * const point = Point.fromX(xCoordinate, true);
107
285
  */
108
286
  static fromX(x, odd) {
109
- function mod(a, n) {
110
- return ((a % n) + n) % n;
111
- }
112
- function modPow(base, exponent, modulus) {
113
- let result = BigInt(1);
114
- base = mod(base, modulus);
115
- while (exponent > BigInt(0)) {
116
- if ((exponent & BigInt(1)) === BigInt(1)) {
117
- result = mod(result * base, modulus);
118
- }
119
- exponent >>= BigInt(1);
120
- base = mod(base * base, modulus);
121
- }
122
- return result;
123
- }
124
- function sqrtMod(a, p) {
125
- const exponent = (p + BigInt(1)) >> BigInt(2);
126
- const sqrtCandidate = modPow(a, exponent, p);
127
- if (mod(sqrtCandidate * sqrtCandidate, p) === mod(a, p)) {
128
- return sqrtCandidate;
129
- }
130
- else {
131
- return null;
132
- }
133
- }
134
- // Curve parameters for secp256k1
135
- const p = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
136
- const b = BigInt(7);
137
- let xBigInt;
138
- if (x instanceof BigNumber) {
139
- xBigInt = BigInt('0x' + x.toString(16));
140
- }
141
- else if (typeof x === 'string') {
142
- xBigInt = BigInt('0x' + x);
143
- }
144
- else if (Array.isArray(x)) {
145
- xBigInt = BigInt('0x' + toHex(x).padStart(64, '0'));
146
- }
147
- else if (typeof x === 'number') {
148
- xBigInt = BigInt(x);
149
- }
150
- else {
151
- throw new Error('Invalid x-coordinate type');
152
- }
153
- xBigInt = mod(xBigInt, p);
154
- const y2 = mod(modPow(xBigInt, BigInt(3), p) + b, p);
155
- let y = sqrtMod(y2, p);
156
- if (y === null) {
287
+ let xBigInt = toBigInt(x);
288
+ xBigInt = biMod(xBigInt);
289
+ const y2 = biModAdd(biModMul(biModSqr(xBigInt), xBigInt), 7n);
290
+ const y = biModSqrt(y2);
291
+ if (y === null)
157
292
  throw new Error('Invalid point');
158
- }
159
- const isYOdd = y % BigInt(2) === BigInt(1);
160
- if ((odd && !isYOdd) || (!odd && isYOdd)) {
161
- y = p - y;
293
+ let yBig = y;
294
+ if ((yBig & BI_ONE) !== (odd ? BI_ONE : BI_ZERO)) {
295
+ yBig = biModSub(P_BIGINT, yBig);
162
296
  }
163
297
  const xBN = new BigNumber(xBigInt.toString(16), 16);
164
- const yBN = new BigNumber(y.toString(16), 16);
298
+ const yBN = new BigNumber(yBig.toString(16), 16);
165
299
  return new Point(xBN, yBN);
166
300
  }
167
301
  /**
@@ -403,21 +537,30 @@ export default class Point extends BasePoint {
403
537
  }
404
538
  // P + (-P) = O
405
539
  if (this.neg().eq(p)) {
406
- return new Point(new BigNumber(0), new BigNumber(0));
540
+ return new Point(null, null);
407
541
  }
408
542
  // P + Q = O
409
543
  if (this.x?.cmp(p.x ?? new BigNumber(0)) === 0) {
410
- return new Point(new BigNumber(0), new BigNumber(0));
411
- }
412
- let c = this.y?.redSub(p.y ?? new BigNumber(0)) ?? new BigNumber(0);
413
- if (c.cmpn(0) !== 0) {
414
- c = c.redMul(this.x?.redSub(p.x ?? new BigNumber(0)).redInvm() ?? new BigNumber(1));
544
+ return new Point(null, null);
415
545
  }
416
- const nx = c?.redSqr().redISub(this.x ?? new BigNumber(0)).redISub(p.x ?? new BigNumber(0));
417
- const ny = (c ?? new BigNumber(1))
418
- .redMul((this.x ?? new BigNumber(0)).redSub(nx ?? new BigNumber(0)))
419
- .redISub(this.y ?? new BigNumber(0));
420
- return new Point(nx ?? new BigNumber(0), ny ?? new BigNumber(0));
546
+ const P1 = {
547
+ X: BigInt('0x' + this.x.fromRed().toString(16)),
548
+ Y: BigInt('0x' + this.y.fromRed().toString(16)),
549
+ Z: BI_ONE
550
+ };
551
+ const Q1 = {
552
+ X: BigInt('0x' + p.x.fromRed().toString(16)),
553
+ Y: BigInt('0x' + p.y.fromRed().toString(16)),
554
+ Z: BI_ONE
555
+ };
556
+ const R = jpAdd(P1, Q1);
557
+ if (R.Z === BI_ZERO)
558
+ return new Point(null, null);
559
+ const zInv = biModInv(R.Z);
560
+ const zInv2 = biModMul(zInv, zInv);
561
+ const xRes = biModMul(R.X, zInv2);
562
+ const yRes = biModMul(R.Y, biModMul(zInv2, zInv));
563
+ return new Point(xRes.toString(16), yRes.toString(16));
421
564
  }
422
565
  /**
423
566
  * Doubles the current point.
@@ -429,21 +572,21 @@ export default class Point extends BasePoint {
429
572
  * const result = P.dbl();
430
573
  * */
431
574
  dbl() {
432
- if (this.inf) {
575
+ if (this.inf)
433
576
  return this;
577
+ if (this.x === null || this.y === null) {
578
+ throw new Error('Point coordinates cannot be null');
434
579
  }
435
- // 2P = O
436
- const ys1 = (this.y ?? new BigNumber(0)).redAdd(this.y ?? new BigNumber(0));
437
- if (ys1.cmpn(0) === 0) {
438
- return new Point(new BigNumber(0), new BigNumber(0));
439
- }
440
- const a = this.curve.a;
441
- const x2 = (this.x ?? new BigNumber(0)).redSqr();
442
- const dyinv = ys1.redInvm();
443
- const c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv);
444
- const nx = c.redSqr().redISub((this.x ?? new BigNumber(0)).redAdd(this.x ?? new BigNumber(0)));
445
- const ny = c.redMul((this.x ?? new BigNumber(0)).redSub(nx)).redISub(this.y ?? new BigNumber(0));
446
- return new Point(nx, ny);
580
+ const X = BigInt('0x' + this.x.fromRed().toString(16));
581
+ const Y = BigInt('0x' + this.y.fromRed().toString(16));
582
+ if (Y === BI_ZERO)
583
+ return new Point(null, null);
584
+ const R = jpDouble({ X, Y, Z: BI_ONE });
585
+ const zInv = biModInv(R.Z);
586
+ const zInv2 = biModMul(zInv, zInv);
587
+ const xRes = biModMul(R.X, zInv2);
588
+ const yRes = biModMul(R.Y, biModMul(zInv2, zInv));
589
+ return new Point(xRes.toString(16), yRes.toString(16));
447
590
  }
448
591
  /**
449
592
  * Returns X coordinate of point
@@ -481,86 +624,45 @@ export default class Point extends BasePoint {
481
624
  k = new BigNumber(k, 16);
482
625
  }
483
626
  k = k;
484
- if (typeof BigInt === 'function') {
485
- if (this.inf) {
486
- return this;
487
- }
488
- const zero = 0n;
489
- const one = 1n;
490
- const p = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
491
- const n = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
492
- let kBig = BigInt('0x' + k.toString(16));
493
- const isNeg = kBig < zero;
494
- if (isNeg)
495
- kBig = -kBig;
496
- kBig = ((kBig % n) + n) % n;
497
- if (kBig === zero) {
498
- return new Point(null, null);
499
- }
500
- if (this.x === null || this.y === null) {
501
- throw new Error('Point coordinates cannot be null');
502
- }
503
- let Px;
504
- let Py;
505
- if (this === this.curve.g) {
506
- Px = GX_BIGINT;
507
- Py = GY_BIGINT;
508
- }
509
- else {
510
- Px = BigInt('0x' + this.x.fromRed().toString(16));
511
- Py = BigInt('0x' + this.y.fromRed().toString(16));
512
- }
513
- const mod = (a, m) => ((a % m) + m) % m;
514
- const modMul = (a, b, m) => mod(a * b, m);
515
- const modInv = (a, m) => {
516
- let lm = one;
517
- let hm = zero;
518
- let low = mod(a, m);
519
- let high = m;
520
- while (low > one) {
521
- const r = high / low;
522
- const nm = hm - lm * r;
523
- const neww = high - low * r;
524
- hm = lm;
525
- lm = nm;
526
- high = low;
527
- low = neww;
528
- }
529
- return mod(lm, m);
530
- };
531
- const scalarMultiply = (kVal, P0) => {
532
- // Delegate to the hoisted windowed-NAF implementation above. We
533
- // keep the wrapper so that the rest of the mul() code remains
534
- // untouched while providing a massive speed-up (≈4-6×).
535
- return scalarMultiplyWNAF(kVal, P0);
536
- };
537
- const R = scalarMultiply(kBig, { x: Px, y: Py });
538
- if (R.Z === zero) {
539
- return new Point(null, null);
540
- }
541
- const zInv = modInv(R.Z, p);
542
- const zInv2 = modMul(zInv, zInv, p);
543
- const xRes = modMul(R.X, zInv2, p);
544
- const yRes = modMul(R.Y, modMul(zInv2, zInv, p), p);
545
- const xBN = new BigNumber(xRes.toString(16), 16);
546
- const yBN = new BigNumber(yRes.toString(16), 16);
547
- const result = new Point(xBN, yBN);
548
- if (isNeg) {
549
- return result.neg();
550
- }
551
- return result;
627
+ if (this.inf) {
628
+ return this;
629
+ }
630
+ let kBig = BigInt('0x' + k.toString(16));
631
+ const isNeg = kBig < BI_ZERO;
632
+ if (isNeg)
633
+ kBig = -kBig;
634
+ kBig = biMod(kBig);
635
+ if (kBig === BI_ZERO) {
636
+ return new Point(null, null);
637
+ }
638
+ if (this.x === null || this.y === null) {
639
+ throw new Error('Point coordinates cannot be null');
640
+ }
641
+ let Px;
642
+ let Py;
643
+ if (this === this.curve.g) {
644
+ Px = GX_BIGINT;
645
+ Py = GY_BIGINT;
552
646
  }
553
647
  else {
554
- if (this.isInfinity()) {
555
- return this;
556
- }
557
- else if (this._hasDoubles(k)) {
558
- return this._fixedNafMul(k);
559
- }
560
- else {
561
- return this._endoWnafMulAdd([this], [k]);
562
- }
648
+ Px = BigInt('0x' + this.x.fromRed().toString(16));
649
+ Py = BigInt('0x' + this.y.fromRed().toString(16));
650
+ }
651
+ const R = scalarMultiplyWNAF(kBig, { x: Px, y: Py });
652
+ if (R.Z === BI_ZERO) {
653
+ return new Point(null, null);
654
+ }
655
+ const zInv = biModInv(R.Z);
656
+ const zInv2 = biModMul(zInv, zInv);
657
+ const xRes = biModMul(R.X, zInv2);
658
+ const yRes = biModMul(R.Y, biModMul(zInv2, zInv));
659
+ const xBN = new BigNumber(xRes.toString(16), 16);
660
+ const yBN = new BigNumber(yRes.toString(16), 16);
661
+ const result = new Point(xBN, yBN);
662
+ if (isNeg) {
663
+ return result.neg();
563
664
  }
665
+ return result;
564
666
  }
565
667
  /**
566
668
  * Performs a multiplication and addition operation in a single step.
@@ -894,7 +996,7 @@ export default class Point extends BasePoint {
894
996
  for (i = 0; i < points.length; i++) {
895
997
  const split = this.curve._endoSplit(coeffs[i]);
896
998
  let p = points[i];
897
- let beta = p._getBeta() ?? new Point(new BigNumber(0), new BigNumber(0));
999
+ let beta = p._getBeta() ?? new Point(null, null);
898
1000
  if (split.k1.negative !== 0) {
899
1001
  split.k1.ineg();
900
1002
  p = p.neg(true);
@@ -968,131 +1070,4 @@ export default class Point extends BasePoint {
968
1070
  };
969
1071
  }
970
1072
  }
971
- // -----------------------------------------------------------------------------
972
- // BigInt helpers & constants (secp256k1) – hoisted so we don't recreate them on
973
- // every Point.mul() call.
974
- // -----------------------------------------------------------------------------
975
- const BI_ZERO = 0n;
976
- const BI_ONE = 1n;
977
- const BI_TWO = 2n;
978
- const BI_THREE = 3n;
979
- const BI_FOUR = 4n;
980
- const BI_EIGHT = 8n;
981
- const P_BIGINT = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
982
- const MASK_256 = (1n << 256n) - 1n; // 0xffff…ffff (256 sones)
983
- function red(x) {
984
- // first fold
985
- let hi = x >> 256n;
986
- x = (x & MASK_256) + (hi << 32n) + hi * 977n;
987
- // second fold (hi ≤ 2³² + 977 here, so one more pass is enough)
988
- hi = x >> 256n;
989
- x = (x & MASK_256) + (hi << 32n) + hi * 977n;
990
- // final conditional subtraction
991
- if (x >= P_BIGINT)
992
- x -= P_BIGINT;
993
- return x;
994
- }
995
- const biModSub = (a, b) => (a >= b ? a - b : P_BIGINT - (b - a));
996
- const biModMul = (a, b) => red(a * b);
997
- // Generator point coordinates as bigint constants
998
- const GX_BIGINT = BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
999
- const GY_BIGINT = BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8');
1000
- // Cache for precomputed windowed tables keyed by 'window:x:y'
1001
- const WNAF_TABLE_CACHE = new Map();
1002
- const jpDouble = (P) => {
1003
- const { X: X1, Y: Y1, Z: Z1 } = P;
1004
- if (Y1 === BI_ZERO)
1005
- return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO };
1006
- const Y1sq = biModMul(Y1, Y1);
1007
- const S = biModMul(BI_FOUR, biModMul(X1, Y1sq));
1008
- const M = biModMul(BI_THREE, biModMul(X1, X1));
1009
- const X3 = biModSub(biModMul(M, M), biModMul(BI_TWO, S));
1010
- const Y3 = biModSub(biModMul(M, biModSub(S, X3)), biModMul(BI_EIGHT, biModMul(Y1sq, Y1sq)));
1011
- const Z3 = biModMul(BI_TWO, biModMul(Y1, Z1));
1012
- return { X: X3, Y: Y3, Z: Z3 };
1013
- };
1014
- const jpAdd = (P, Q) => {
1015
- if (P.Z === BI_ZERO)
1016
- return Q;
1017
- if (Q.Z === BI_ZERO)
1018
- return P;
1019
- const Z1Z1 = biModMul(P.Z, P.Z);
1020
- const Z2Z2 = biModMul(Q.Z, Q.Z);
1021
- const U1 = biModMul(P.X, Z2Z2);
1022
- const U2 = biModMul(Q.X, Z1Z1);
1023
- const S1 = biModMul(P.Y, biModMul(Z2Z2, Q.Z));
1024
- const S2 = biModMul(Q.Y, biModMul(Z1Z1, P.Z));
1025
- const H = biModSub(U2, U1);
1026
- const r = biModSub(S2, S1);
1027
- if (H === BI_ZERO) {
1028
- if (r === BI_ZERO)
1029
- return jpDouble(P);
1030
- return { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // Infinity
1031
- }
1032
- const HH = biModMul(H, H);
1033
- const HHH = biModMul(H, HH);
1034
- const V = biModMul(U1, HH);
1035
- const X3 = biModSub(biModSub(biModMul(r, r), HHH), biModMul(BI_TWO, V));
1036
- const Y3 = biModSub(biModMul(r, biModSub(V, X3)), biModMul(S1, HHH));
1037
- const Z3 = biModMul(H, biModMul(P.Z, Q.Z));
1038
- return { X: X3, Y: Y3, Z: Z3 };
1039
- };
1040
- const jpNeg = (P) => {
1041
- if (P.Z === BI_ZERO)
1042
- return P;
1043
- return { X: P.X, Y: P_BIGINT - P.Y, Z: P.Z };
1044
- };
1045
- // Fast windowed-NAF scalar multiplication (default window = 5) in Jacobian
1046
- // coordinates. Returns Q = k * P0 as a JacobianPoint.
1047
- const scalarMultiplyWNAF = (k, P0, window = 5) => {
1048
- const key = `${window}:${P0.x.toString(16)}:${P0.y.toString(16)}`;
1049
- let tbl = WNAF_TABLE_CACHE.get(key);
1050
- let P;
1051
- if (tbl === undefined) {
1052
- // Convert affine to Jacobian and pre-compute odd multiples
1053
- const tblSize = 1 << (window - 1); // e.g. w=5 → 16 entries
1054
- tbl = new Array(tblSize);
1055
- P = { X: P0.x, Y: P0.y, Z: BI_ONE };
1056
- tbl[0] = P;
1057
- const twoP = jpDouble(P);
1058
- for (let i = 1; i < tblSize; i++) {
1059
- tbl[i] = jpAdd(tbl[i - 1], twoP);
1060
- }
1061
- WNAF_TABLE_CACHE.set(key, tbl);
1062
- }
1063
- else {
1064
- P = tbl[0];
1065
- }
1066
- // Build wNAF representation of k
1067
- const wnaf = [];
1068
- const wBig = 1n << BigInt(window);
1069
- const wHalf = wBig >> 1n;
1070
- let kTmp = k;
1071
- while (kTmp > 0n) {
1072
- if ((kTmp & BI_ONE) === BI_ZERO) {
1073
- wnaf.push(0);
1074
- kTmp >>= BI_ONE;
1075
- }
1076
- else {
1077
- let z = kTmp & (wBig - 1n); // kTmp mod 2^w
1078
- if (z > wHalf)
1079
- z -= wBig; // make it odd & within (-2^{w-1}, 2^{w-1})
1080
- wnaf.push(Number(z));
1081
- kTmp -= z;
1082
- kTmp >>= BI_ONE;
1083
- }
1084
- }
1085
- // Accumulate from MSB to LSB
1086
- let Q = { X: BI_ZERO, Y: BI_ONE, Z: BI_ZERO }; // infinity
1087
- for (let i = wnaf.length - 1; i >= 0; i--) {
1088
- Q = jpDouble(Q);
1089
- const di = wnaf[i];
1090
- if (di !== 0) {
1091
- const idx = Math.abs(di) >> 1; // (|di|-1)/2 because di is odd
1092
- const addend = di > 0 ? tbl[idx] : jpNeg(tbl[idx]);
1093
- Q = jpAdd(Q, addend);
1094
- }
1095
- }
1096
- return Q;
1097
- };
1098
1073
  //# sourceMappingURL=Point.js.map