@bsv/sdk 1.5.3 → 1.6.0

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 (57) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/primitives/AESGCM.js +113 -137
  3. package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
  4. package/dist/cjs/src/primitives/BigNumber.js +1019 -3947
  5. package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
  6. package/dist/cjs/src/primitives/K256.js +53 -37
  7. package/dist/cjs/src/primitives/K256.js.map +1 -1
  8. package/dist/cjs/src/primitives/Mersenne.js +16 -21
  9. package/dist/cjs/src/primitives/Mersenne.js.map +1 -1
  10. package/dist/cjs/src/primitives/MontgomoryMethod.js.map +1 -1
  11. package/dist/cjs/src/primitives/utils.js +27 -17
  12. package/dist/cjs/src/primitives/utils.js.map +1 -1
  13. package/dist/cjs/src/script/Spend.js +618 -858
  14. package/dist/cjs/src/script/Spend.js.map +1 -1
  15. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  16. package/dist/esm/src/primitives/AESGCM.js +112 -137
  17. package/dist/esm/src/primitives/AESGCM.js.map +1 -1
  18. package/dist/esm/src/primitives/BigNumber.js +1011 -3969
  19. package/dist/esm/src/primitives/BigNumber.js.map +1 -1
  20. package/dist/esm/src/primitives/K256.js +53 -37
  21. package/dist/esm/src/primitives/K256.js.map +1 -1
  22. package/dist/esm/src/primitives/Mersenne.js +16 -21
  23. package/dist/esm/src/primitives/Mersenne.js.map +1 -1
  24. package/dist/esm/src/primitives/MontgomoryMethod.js.map +1 -1
  25. package/dist/esm/src/primitives/utils.js +29 -17
  26. package/dist/esm/src/primitives/utils.js.map +1 -1
  27. package/dist/esm/src/script/Spend.js +618 -857
  28. package/dist/esm/src/script/Spend.js.map +1 -1
  29. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  30. package/dist/types/src/primitives/AESGCM.d.ts.map +1 -1
  31. package/dist/types/src/primitives/BigNumber.d.ts +238 -1705
  32. package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
  33. package/dist/types/src/primitives/K256.d.ts.map +1 -1
  34. package/dist/types/src/primitives/Mersenne.d.ts +2 -2
  35. package/dist/types/src/primitives/Mersenne.d.ts.map +1 -1
  36. package/dist/types/src/primitives/utils.d.ts +2 -0
  37. package/dist/types/src/primitives/utils.d.ts.map +1 -1
  38. package/dist/types/src/script/Spend.d.ts +11 -1
  39. package/dist/types/src/script/Spend.d.ts.map +1 -1
  40. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  41. package/dist/umd/bundle.js +1 -1
  42. package/docs/performance.md +70 -0
  43. package/docs/primitives.md +262 -3049
  44. package/package.json +1 -1
  45. package/src/auth/__tests/Peer.test.ts +38 -23
  46. package/src/auth/certificates/__tests/MasterCertificate.test.ts +27 -20
  47. package/src/auth/certificates/__tests/VerifiableCertificate.test.ts +24 -24
  48. package/src/primitives/AESGCM.ts +118 -164
  49. package/src/primitives/BigNumber.ts +867 -4180
  50. package/src/primitives/K256.ts +57 -37
  51. package/src/primitives/Mersenne.ts +16 -20
  52. package/src/primitives/MontgomoryMethod.ts +2 -2
  53. package/src/primitives/__tests/ReductionContext.test.ts +6 -1
  54. package/src/primitives/utils.ts +28 -17
  55. package/src/script/Spend.ts +634 -1309
  56. package/src/transaction/__tests/Transaction.test.ts +14 -16
  57. package/src/transaction/__tests/Transaction.benchmarks.test.ts +0 -237
@@ -43,38 +43,58 @@ export default class K256 extends Mersenne {
43
43
  * k256.split(input, output);
44
44
  */
45
45
  split (input: BigNumber, output: BigNumber): void {
46
- // 256 = 9 * 26 + 22
47
- const mask = 0x3fffff
46
+ const mask = 0x3fffff // 22 bits
47
+ const inputWords = input.words // Access via getter
48
+ const inputNominalLength = input.length // Access via getter, respects _nominalWordLength
48
49
 
49
- const outLen = Math.min(input.length, 9)
50
- let i = 0
51
- for (; i < outLen; i++) {
52
- output.words[i] = input.words[i]
50
+ const outLen = Math.min(inputNominalLength, 9)
51
+ const tempOutputWords = new Array(outLen + (inputNominalLength > 9 ? 1 : 0)).fill(0)
52
+
53
+ for (let i = 0; i < outLen; i++) {
54
+ tempOutputWords[i] = inputWords[i]
53
55
  }
54
- output.length = outLen
56
+ let currentOutputWordCount = outLen
57
+
58
+ if (inputNominalLength <= 9) {
59
+ const finalOutputWords = new Array(currentOutputWordCount)
60
+ for (let i = 0; i < currentOutputWordCount; ++i) finalOutputWords[i] = tempOutputWords[i]
61
+ output.words = finalOutputWords // Use setter
55
62
 
56
- if (input.length <= 9) {
57
- input.words[0] = 0
58
- input.length = 1
63
+ input.words = [0] // Use setter to set to 0
59
64
  return
60
65
  }
61
66
 
62
67
  // Shift by 9 limbs
63
- let prev = input.words[9]
64
- output.words[output.length++] = prev & mask
68
+ let prev = inputWords[9]
69
+ tempOutputWords[currentOutputWordCount++] = prev & mask
70
+
71
+ const finalOutputWords = new Array(currentOutputWordCount)
72
+ for (let i = 0; i < currentOutputWordCount; ++i) finalOutputWords[i] = tempOutputWords[i]
73
+ output.words = finalOutputWords // Use setter for output
65
74
 
66
- for (i = 10; i < input.length; i++) {
67
- const next = input.words[i] | 0
68
- input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22)
75
+ // For input modification
76
+ const tempInputNewWords = new Array(Math.max(1, inputNominalLength - 9)).fill(0)
77
+ let currentInputNewWordCount = 0
78
+
79
+ for (let i = 10; i < inputNominalLength; i++) {
80
+ const next = inputWords[i] | 0
81
+ if (currentInputNewWordCount < tempInputNewWords.length) { // Boundary check
82
+ tempInputNewWords[currentInputNewWordCount++] = ((next & mask) << 4) | (prev >>> 22)
83
+ }
69
84
  prev = next
70
85
  }
71
86
  prev >>>= 22
72
- input.words[i - 10] = prev
73
- if (prev === 0 && input.length > 10) {
74
- input.length -= 10
75
- } else {
76
- input.length -= 9
87
+ if (currentInputNewWordCount < tempInputNewWords.length) { // Boundary check
88
+ tempInputNewWords[currentInputNewWordCount++] = prev
89
+ } else if (prev !== 0 && tempInputNewWords.length > 0) { // If prev is non-zero but no space, this is an issue.
90
+ // This case implies original logic might have relied on array auto-expansion or specific length handling
91
+ // For safety, if there's still a carry and no space, the array should have been bigger.
92
+ // However, the original logic `input.length -= 9` suggests truncation.
77
93
  }
94
+
95
+ const finalInputNewWords = new Array(currentInputNewWordCount)
96
+ for (let i = 0; i < currentInputNewWordCount; ++i) finalInputNewWords[i] = tempInputNewWords[i]
97
+ input.words = finalInputNewWords // Use setter, which will strip and set magnitude
78
98
  }
79
99
 
80
100
  /**
@@ -90,27 +110,27 @@ export default class K256 extends Mersenne {
90
110
  * const result = k256.imulK(number);
91
111
  */
92
112
  imulK (num: BigNumber): BigNumber {
93
- // K = 0x1000003d1 = [ 0x40, 0x3d1 ]
94
- num.words[num.length] = 0
95
- num.words[num.length + 1] = 0
96
- num.length += 2
113
+ const currentWords = num.words // Get current words based on _magnitude and _nominalWordLength
114
+ const originalNominalLength = num.length // Getter
97
115
 
98
- // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
99
- let lo = 0
100
- for (let i = 0; i < num.length; i++) {
101
- const w = num.words[i] | 0
102
- lo += w * 0x3d1
103
- num.words[i] = lo & 0x3ffffff
104
- lo = w * 0x40 + ((lo / 0x4000000) | 0)
116
+ const newNominalLength = originalNominalLength + 2
117
+ const tempWords = new Array(newNominalLength).fill(0)
118
+
119
+ for (let i = 0; i < originalNominalLength; i++) {
120
+ tempWords[i] = currentWords[i]
105
121
  }
122
+ // tempWords is now effectively num.words expanded with zeroes
106
123
 
107
- // Fast length reduction
108
- if (num.words[num.length - 1] === 0) {
109
- num.length--
110
- if (num.words[num.length - 1] === 0) {
111
- num.length--
112
- }
124
+ let lo = 0
125
+ for (let i = 0; i < newNominalLength; i++) { // Iterate up to new expanded length
126
+ const w = tempWords[i] | 0
127
+ lo += w * 0x3d1 // 0x3d1 = 977
128
+ tempWords[i] = lo & 0x3ffffff // 26-bit mask
129
+ lo = w * 0x40 + ((lo / 0x4000000) | 0) // 0x40 = 64. 0x4000000 = 2^26
113
130
  }
131
+
132
+ num.words = tempWords // Use setter to re-initialize from tempWords
133
+ // The setter will handle _magnitude, _sign, _nominalWordLength, and strip.
114
134
  return num
115
135
  }
116
136
  }
@@ -31,7 +31,7 @@ export default class Mersenne {
31
31
  this.name = name
32
32
  this.p = new BigNumber(p, 16)
33
33
  this.n = this.p.bitLength()
34
- this.k = new BigNumber(1).iushln(this.n).isub(this.p)
34
+ this.k = new BigNumber(BigInt(1)).iushln(this.n).isub(this.p) // Use 1n for BigInt compatibility
35
35
 
36
36
  this.tmp = this._tmp()
37
37
  }
@@ -44,8 +44,9 @@ export default class Mersenne {
44
44
  * @returns A BigNumber with scaled size depending on prime magnitude.
45
45
  */
46
46
  private _tmp (): BigNumber {
47
- const tmp = new BigNumber()
48
- tmp.words = new Array(Math.ceil(this.n / 13))
47
+ const tmp = new BigNumber(BigInt(0)) // Initialize with BigInt 0
48
+ const requiredWords = Math.ceil(this.n / BigNumber.wordSize)
49
+ tmp.expand(Math.max(1, requiredWords)) // Expand sets _nominalWordLength
49
50
  return tmp
50
51
  }
51
52
 
@@ -63,32 +64,25 @@ export default class Mersenne {
63
64
  ireduce (num: BigNumber): BigNumber {
64
65
  // Assumes that `num` is less than `P^2`
65
66
  // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
66
- let r = num
67
+ const r = num // num is directly modified
67
68
  let rlen
68
69
 
69
70
  do {
70
- this.split(r, this.tmp)
71
- r = this.imulK(r)
72
- r = r.iadd(this.tmp)
71
+ this.split(r, this.tmp) // r is modified (becomes HI), this.tmp becomes LO
72
+ this.imulK(r) // r becomes HI * K
73
+ r.iadd(this.tmp) // r becomes HI * K + LO
73
74
  rlen = r.bitLength()
74
75
  } while (rlen > this.n)
75
76
 
76
77
  const cmp = rlen < this.n ? -1 : r.ucmp(this.p)
77
78
  if (cmp === 0) {
78
- r.words[0] = 0
79
- r.length = 1
79
+ r.words = [0] // Set to zero using the words setter
80
80
  } else if (cmp > 0) {
81
81
  r.isub(this.p)
82
- } else {
83
- if (r.strip !== undefined) {
84
- // r is a BN v4 instance
85
- r.strip()
86
- } else {
87
- // r is a BN v5 instance
88
- r.strip()
89
- }
90
82
  }
91
-
83
+ // No explicit strip needed here if operations maintain correctness and setter handles it.
84
+ // However, ensuring it's stripped to minimal form after reduction is good.
85
+ r.strip()
92
86
  return r
93
87
  }
94
88
 
@@ -97,13 +91,15 @@ export default class Mersenne {
97
91
  * to meet the magnitude of the pseudo-Mersenne prime.
98
92
  *
99
93
  * @method split
100
- * @param input - The BigNumber to be shifted.
101
- * @param out - The BigNumber to hold the shifted result.
94
+ * @param input - The BigNumber to be shifted (will contain HI part).
95
+ * @param out - The BigNumber to hold the shifted result (LO part).
102
96
  *
103
97
  * @example
104
98
  * mersenne.split(new BigNumber('2345', 16), new BigNumber());
105
99
  */
106
100
  split (input: BigNumber, out: BigNumber): void {
101
+ // out gets the LO bits (shifted out part)
102
+ // input gets modified to be the HI bits (remaining part after shift)
107
103
  input.iushrn(this.n, 0, out)
108
104
  }
109
105
 
@@ -94,8 +94,8 @@ export default class MontgomoryMethod extends ReductionContext {
94
94
  */
95
95
  imul (a: BigNumber, b: BigNumber): BigNumber {
96
96
  if (a.isZero() || b.isZero()) {
97
- a.words[0] = 0
98
- a.length = 1
97
+ a.words[0] = 0;
98
+ (a as any).length = 1
99
99
  return a
100
100
  }
101
101
 
@@ -248,7 +248,12 @@ describe('BN.js/Reduction context', function () {
248
248
 
249
249
  it('should avoid 4.1.0 regresion', function () {
250
250
  const bits2int = (obits, q): BigNumber => {
251
- const bits = new BigNumber(obits)
251
+ let bits
252
+ if (Buffer.isBuffer(obits)) {
253
+ bits = new BigNumber(obits.toString('hex'), 16)
254
+ } else {
255
+ bits = new BigNumber(obits)
256
+ }
252
257
  const shift = (obits.length << 3) - q.bitLength()
253
258
  if (shift > 0) {
254
259
  bits.ishrn(shift)
@@ -379,21 +379,20 @@ export const fromBase58Check = (
379
379
 
380
380
  export class Writer {
381
381
  public bufs: number[][]
382
+ private length: number
382
383
 
383
384
  constructor (bufs?: number[][]) {
384
385
  this.bufs = bufs !== undefined ? bufs : []
386
+ this.length = 0
387
+ for (const b of this.bufs) this.length += b.length
385
388
  }
386
389
 
387
390
  getLength (): number {
388
- let len = 0
389
- for (const buf of this.bufs) {
390
- len = len + buf.length
391
- }
392
- return len
391
+ return this.length
393
392
  }
394
393
 
395
394
  toArray (): number[] {
396
- const totalLength = this.getLength()
395
+ const totalLength = this.length
397
396
  const ret = new Array(totalLength)
398
397
  let offset = 0
399
398
  for (const buf of this.bufs) {
@@ -406,6 +405,7 @@ export class Writer {
406
405
 
407
406
  write (buf: number[]): this {
408
407
  this.bufs.push(buf)
408
+ this.length += buf.length
409
409
  return this
410
410
  }
411
411
 
@@ -415,6 +415,7 @@ export class Writer {
415
415
  buf2[i] = buf[buf.length - 1 - i]
416
416
  }
417
417
  this.bufs.push(buf2)
418
+ this.length += buf2.length
418
419
  return this
419
420
  }
420
421
 
@@ -433,10 +434,12 @@ export class Writer {
433
434
  }
434
435
 
435
436
  writeUInt16BE (n: number): this {
436
- this.bufs.push([
437
+ const buf = [
437
438
  (n >> 8) & 0xff, // shift right 8 bits to get the high byte
438
439
  n & 0xff // low byte is just the last 8 bits
439
- ])
440
+ ]
441
+ this.bufs.push(buf)
442
+ this.length += 2
440
443
  return this
441
444
  }
442
445
 
@@ -445,10 +448,12 @@ export class Writer {
445
448
  }
446
449
 
447
450
  writeUInt16LE (n: number): this {
448
- this.bufs.push([
451
+ const buf = [
449
452
  n & 0xff, // low byte is just the last 8 bits
450
453
  (n >> 8) & 0xff // shift right 8 bits to get the high byte
451
- ])
454
+ ]
455
+ this.bufs.push(buf)
456
+ this.length += 2
452
457
  return this
453
458
  }
454
459
 
@@ -457,12 +462,14 @@ export class Writer {
457
462
  }
458
463
 
459
464
  writeUInt32BE (n: number): this {
460
- this.bufs.push([
465
+ const buf = [
461
466
  (n >> 24) & 0xff, // highest byte
462
467
  (n >> 16) & 0xff,
463
468
  (n >> 8) & 0xff,
464
469
  n & 0xff // lowest byte
465
- ])
470
+ ]
471
+ this.bufs.push(buf)
472
+ this.length += 4
466
473
  return this
467
474
  }
468
475
 
@@ -471,12 +478,14 @@ export class Writer {
471
478
  }
472
479
 
473
480
  writeUInt32LE (n: number): this {
474
- this.bufs.push([
481
+ const buf = [
475
482
  n & 0xff, // lowest byte
476
483
  (n >> 8) & 0xff,
477
484
  (n >> 16) & 0xff,
478
485
  (n >> 24) & 0xff // highest byte
479
- ])
486
+ ]
487
+ this.bufs.push(buf)
488
+ this.length += 4
480
489
  return this
481
490
  }
482
491
 
@@ -587,24 +596,26 @@ export class Writer {
587
596
  export class Reader {
588
597
  public bin: number[]
589
598
  public pos: number
599
+ private readonly length: number
590
600
 
591
601
  constructor (bin: number[] = [], pos: number = 0) {
592
602
  this.bin = bin
593
603
  this.pos = pos
604
+ this.length = bin.length
594
605
  }
595
606
 
596
607
  public eof (): boolean {
597
- return this.pos >= this.bin.length
608
+ return this.pos >= this.length
598
609
  }
599
610
 
600
- public read (len = this.bin.length): number[] {
611
+ public read (len = this.length): number[] {
601
612
  const start = this.pos
602
613
  const end = this.pos + len
603
614
  this.pos = end
604
615
  return this.bin.slice(start, end)
605
616
  }
606
617
 
607
- public readReverse (len = this.bin.length): number[] {
618
+ public readReverse (len = this.length): number[] {
608
619
  const buf2 = new Array(len)
609
620
  for (let i = 0; i < len; i++) {
610
621
  buf2[i] = this.bin[this.pos + len - 1 - i]