@btc-vision/bitcoin 7.0.0-alpha.3 → 7.0.0-alpha.5

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 (119) hide show
  1. package/README.md +139 -12
  2. package/browser/chunks/index.browser-CUaPaKyS.js +10742 -0
  3. package/browser/env.d.ts +13 -0
  4. package/browser/env.d.ts.map +1 -0
  5. package/browser/index.d.ts +1 -1
  6. package/browser/index.d.ts.map +1 -1
  7. package/browser/index.js +1894 -12851
  8. package/browser/io/index.d.ts +0 -1
  9. package/browser/io/index.d.ts.map +1 -1
  10. package/browser/types.d.ts.map +1 -1
  11. package/browser/workers/WorkerSigningPool.d.ts +6 -0
  12. package/browser/workers/WorkerSigningPool.d.ts.map +1 -1
  13. package/browser/workers/WorkerSigningPool.node.d.ts +6 -0
  14. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
  15. package/browser/workers/WorkerSigningPool.sequential.d.ts +69 -0
  16. package/browser/workers/WorkerSigningPool.sequential.d.ts.map +1 -0
  17. package/browser/workers/WorkerSigningPool.worklet.d.ts +64 -0
  18. package/browser/workers/WorkerSigningPool.worklet.d.ts.map +1 -0
  19. package/browser/workers/index.browser.d.ts +16 -0
  20. package/browser/workers/index.browser.d.ts.map +1 -0
  21. package/browser/workers/index.d.ts +4 -17
  22. package/browser/workers/index.d.ts.map +1 -1
  23. package/browser/workers/index.js +21 -0
  24. package/browser/workers/index.node.d.ts +12 -19
  25. package/browser/workers/index.node.d.ts.map +1 -1
  26. package/browser/workers/index.react-native.d.ts +28 -0
  27. package/browser/workers/index.react-native.d.ts.map +1 -0
  28. package/browser/workers/index.shared.d.ts +15 -0
  29. package/browser/workers/index.shared.d.ts.map +1 -0
  30. package/browser/workers/psbt-parallel.d.ts +2 -3
  31. package/browser/workers/psbt-parallel.d.ts.map +1 -1
  32. package/browser/workers/types.d.ts +17 -0
  33. package/browser/workers/types.d.ts.map +1 -1
  34. package/build/env.d.ts +13 -0
  35. package/build/env.d.ts.map +1 -0
  36. package/build/env.js +198 -0
  37. package/build/env.js.map +1 -0
  38. package/build/index.d.ts +2 -1
  39. package/build/index.d.ts.map +1 -1
  40. package/build/index.js +2 -1
  41. package/build/index.js.map +1 -1
  42. package/build/io/index.d.ts +0 -1
  43. package/build/io/index.d.ts.map +1 -1
  44. package/build/io/index.js +0 -2
  45. package/build/io/index.js.map +1 -1
  46. package/build/tsconfig.build.tsbuildinfo +1 -1
  47. package/build/types.d.ts.map +1 -1
  48. package/build/types.js +2 -16
  49. package/build/types.js.map +1 -1
  50. package/build/workers/WorkerSigningPool.d.ts +6 -0
  51. package/build/workers/WorkerSigningPool.d.ts.map +1 -1
  52. package/build/workers/WorkerSigningPool.js +8 -0
  53. package/build/workers/WorkerSigningPool.js.map +1 -1
  54. package/build/workers/WorkerSigningPool.node.d.ts +6 -0
  55. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
  56. package/build/workers/WorkerSigningPool.node.js +9 -2
  57. package/build/workers/WorkerSigningPool.node.js.map +1 -1
  58. package/build/workers/WorkerSigningPool.sequential.d.ts +78 -0
  59. package/build/workers/WorkerSigningPool.sequential.d.ts.map +1 -0
  60. package/build/workers/WorkerSigningPool.sequential.js +160 -0
  61. package/build/workers/WorkerSigningPool.sequential.js.map +1 -0
  62. package/build/workers/WorkerSigningPool.worklet.d.ts +79 -0
  63. package/build/workers/WorkerSigningPool.worklet.d.ts.map +1 -0
  64. package/build/workers/WorkerSigningPool.worklet.js +388 -0
  65. package/build/workers/WorkerSigningPool.worklet.js.map +1 -0
  66. package/build/workers/index.browser.d.ts +24 -0
  67. package/build/workers/index.browser.d.ts.map +1 -0
  68. package/build/workers/index.browser.js +30 -0
  69. package/build/workers/index.browser.js.map +1 -0
  70. package/build/workers/index.d.ts +6 -18
  71. package/build/workers/index.d.ts.map +1 -1
  72. package/build/workers/index.js +12 -11
  73. package/build/workers/index.js.map +1 -1
  74. package/build/workers/index.node.d.ts +17 -3
  75. package/build/workers/index.node.d.ts.map +1 -1
  76. package/build/workers/index.node.js +23 -4
  77. package/build/workers/index.node.js.map +1 -1
  78. package/build/workers/index.react-native.d.ts +28 -0
  79. package/build/workers/index.react-native.d.ts.map +1 -0
  80. package/build/workers/index.react-native.js +67 -0
  81. package/build/workers/index.react-native.js.map +1 -0
  82. package/build/workers/index.shared.d.ts +15 -0
  83. package/build/workers/index.shared.d.ts.map +1 -0
  84. package/build/workers/index.shared.js +20 -0
  85. package/build/workers/index.shared.js.map +1 -0
  86. package/build/workers/psbt-parallel.d.ts +2 -3
  87. package/build/workers/psbt-parallel.d.ts.map +1 -1
  88. package/build/workers/psbt-parallel.js +4 -4
  89. package/build/workers/psbt-parallel.js.map +1 -1
  90. package/build/workers/types.d.ts +17 -0
  91. package/build/workers/types.d.ts.map +1 -1
  92. package/package.json +19 -1
  93. package/src/env.ts +237 -0
  94. package/src/index.ts +1 -2
  95. package/src/io/index.ts +0 -3
  96. package/src/types.ts +4 -27
  97. package/src/workers/WorkerSigningPool.node.ts +10 -2
  98. package/src/workers/WorkerSigningPool.sequential.ts +190 -0
  99. package/src/workers/WorkerSigningPool.ts +9 -0
  100. package/src/workers/WorkerSigningPool.worklet.ts +519 -0
  101. package/src/workers/index.browser.ts +34 -0
  102. package/src/workers/index.node.ts +28 -5
  103. package/src/workers/index.react-native.ts +110 -0
  104. package/src/workers/index.shared.ts +58 -0
  105. package/src/workers/index.ts +15 -64
  106. package/src/workers/psbt-parallel.ts +8 -8
  107. package/src/workers/types.ts +21 -0
  108. package/test/env.spec.ts +418 -0
  109. package/test/workers-pool.spec.ts +43 -0
  110. package/test/workers-sequential.spec.ts +669 -0
  111. package/test/workers-worklet.spec.ts +500 -0
  112. package/vite.config.browser.ts +31 -6
  113. package/browser/io/MemoryPool.d.ts +0 -220
  114. package/browser/io/MemoryPool.d.ts.map +0 -1
  115. package/build/io/MemoryPool.d.ts +0 -220
  116. package/build/io/MemoryPool.d.ts.map +0 -1
  117. package/build/io/MemoryPool.js +0 -309
  118. package/build/io/MemoryPool.js.map +0 -1
  119. package/src/io/MemoryPool.ts +0 -343
package/src/io/index.ts CHANGED
@@ -34,8 +34,5 @@ export {
34
34
  toUtf8,
35
35
  } from './utils.js';
36
36
 
37
- // Memory pools
38
- export { MemoryPool, SimpleMemoryPool } from './MemoryPool.js';
39
-
40
37
  // Re-export varuint for Bitcoin CompactSize encoding
41
38
  export { varuint };
package/src/types.ts CHANGED
@@ -17,10 +17,6 @@ import type {
17
17
  XOnlyPublicKey,
18
18
  } from './branded.js';
19
19
 
20
- // ============================================================================
21
- // Branded Types (re-exported from branded.ts to avoid circular dependencies)
22
- // ============================================================================
23
-
24
20
  export type {
25
21
  Bytes32,
26
22
  Bytes20,
@@ -34,22 +30,15 @@ export type {
34
30
  Script,
35
31
  } from './branded.js';
36
32
 
37
- // ============================================================================
38
- // Constants
39
- // ============================================================================
40
-
41
33
  /** @internal Do not mutate */
42
34
  const EC_P = fromHex('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
35
+
43
36
  /** @internal Do not mutate — secp256k1 curve order */
44
37
  const EC_N = fromHex('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
45
38
 
46
39
  export const SATOSHI_MAX = 21n * 10n ** 14n;
47
40
  export const TAPLEAF_VERSION_MASK = 0xfe;
48
41
 
49
- // ============================================================================
50
- // Type Guards
51
- // ============================================================================
52
-
53
42
  export function isUInt8(value: unknown): value is number {
54
43
  return typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 0xff;
55
44
  }
@@ -96,8 +85,7 @@ export function isBytes20(value: unknown): value is Bytes20 {
96
85
  export function isXOnlyPublicKey(value: unknown): value is XOnlyPublicKey {
97
86
  if (!(value instanceof Uint8Array) || value.length !== 32) return false;
98
87
  if (isZero(value)) return false;
99
- if (compare(value, EC_P) >= 0) return false;
100
- return true;
88
+ return compare(value, EC_P) < 0;
101
89
  }
102
90
 
103
91
  export function isPoint(value: unknown): value is PublicKey {
@@ -130,8 +118,7 @@ export function isSatoshi(value: unknown): value is Satoshi {
130
118
  export function isPrivateKey(value: unknown): value is PrivateKey {
131
119
  if (!(value instanceof Uint8Array) || value.length !== 32) return false;
132
120
  if (isZero(value)) return false;
133
- if (compare(value, EC_N) >= 0) return false;
134
- return true;
121
+ return compare(value, EC_N) < 0;
135
122
  }
136
123
 
137
124
  export function isSchnorrSignature(value: unknown): value is SchnorrSignature {
@@ -146,9 +133,7 @@ export function isScript(value: unknown): value is Script {
146
133
  return value instanceof Uint8Array;
147
134
  }
148
135
 
149
- // ============================================================================
150
136
  // Taproot Types
151
- // ============================================================================
152
137
 
153
138
  export interface Tapleaf {
154
139
  readonly output: Uint8Array;
@@ -178,23 +163,17 @@ export function isTaptree(value: unknown): value is Taptree {
178
163
  return value.every((node: unknown) => isTaptree(node));
179
164
  }
180
165
 
181
- // ============================================================================
182
- // ECC Interface (re-exported from ecc/types.ts for backward compatibility)
183
- // ============================================================================
166
+ // ECC Interface
184
167
 
185
168
  export type { CryptoBackend, XOnlyPointAddTweakResult, EccLib, Parity } from './ecc/types.js';
186
169
 
187
- // ============================================================================
188
170
  // Stack Types
189
- // ============================================================================
190
171
 
191
172
  export type StackElement = Uint8Array | number;
192
173
  export type Stack = readonly StackElement[];
193
174
  export type StackFunction = () => Stack;
194
175
 
195
- // ============================================================================
196
176
  // Utility Functions
197
- // ============================================================================
198
177
 
199
178
  export function stacksEqual(a: Uint8Array[], b: Uint8Array[]): boolean {
200
179
  if (a.length !== b.length) return false;
@@ -236,9 +215,7 @@ export function toSatoshi(value: bigint): Satoshi {
236
215
  return value as Satoshi;
237
216
  }
238
217
 
239
- // ============================================================================
240
218
  // Assertion Helpers
241
- // ============================================================================
242
219
 
243
220
  export function assertXOnlyPublicKey(
244
221
  value: unknown,
@@ -353,6 +353,15 @@ export class NodeWorkerSigningPool {
353
353
  }
354
354
  }
355
355
 
356
+ /**
357
+ * Disposes of the pool by shutting down all workers.
358
+ *
359
+ * Enables `await using pool = ...` syntax for automatic cleanup.
360
+ */
361
+ public async [Symbol.asyncDispose](): Promise<void> {
362
+ await this.shutdown();
363
+ }
364
+
356
365
  /**
357
366
  * Shuts down the pool and terminates all workers.
358
367
  *
@@ -384,7 +393,7 @@ export class NodeWorkerSigningPool {
384
393
  */
385
394
  #createWorkerScript(): string {
386
395
  // Node.js worker_threads can directly require/import modules
387
- const workerCode = `
396
+ return `
388
397
  const { parentPort } = require('worker_threads');
389
398
 
390
399
  /**
@@ -649,7 +658,6 @@ function handleSignBatch(msg) {
649
658
  });
650
659
  }
651
660
  `;
652
- return workerCode;
653
661
  }
654
662
 
655
663
  /**
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Sequential signing pool for environments without worker support (React Native).
3
+ *
4
+ * Signs inputs one-by-one on the main thread using the CryptoBackend
5
+ * from EccContext. Same API shape as WorkerSigningPool so consumers
6
+ * can swap transparently.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+
11
+ import type {
12
+ ParallelSignerKeyPair,
13
+ ParallelSigningResult,
14
+ SigningResultMessage,
15
+ SigningTask,
16
+ WorkerPoolConfig,
17
+ } from './types.js';
18
+ import { SignatureType } from './types.js';
19
+ import { EccContext } from '../ecc/context.js';
20
+ import type { MessageHash, PrivateKey } from '@btc-vision/ecpair';
21
+
22
+ /**
23
+ * Sequential signing pool — signs inputs one-by-one on the main thread.
24
+ *
25
+ * Provides the same public API as WorkerSigningPool but without any
26
+ * threading. Intended for React Native or other environments where
27
+ * Web Workers and worker_threads are unavailable.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { SequentialSigningPool } from '@btc-vision/bitcoin/workers';
32
+ *
33
+ * const pool = SequentialSigningPool.getInstance();
34
+ * const result = await pool.signBatch(tasks, keyPair);
35
+ * ```
36
+ */
37
+ export class SequentialSigningPool {
38
+ static #instance: SequentialSigningPool | null = null;
39
+
40
+ private constructor(_config: WorkerPoolConfig = {}) {
41
+ // Config accepted for API compatibility but not used —
42
+ // sequential pool has no workers to configure.
43
+ }
44
+
45
+ /**
46
+ * Number of workers — always 0 for sequential pool.
47
+ */
48
+ public get workerCount(): number {
49
+ return 0;
50
+ }
51
+
52
+ /**
53
+ * Idle workers — always 0.
54
+ */
55
+ public get idleWorkerCount(): number {
56
+ return 0;
57
+ }
58
+
59
+ /**
60
+ * Busy workers — always 0.
61
+ */
62
+ public get busyWorkerCount(): number {
63
+ return 0;
64
+ }
65
+
66
+ /**
67
+ * Whether workers are preserved — always false (no workers to preserve).
68
+ */
69
+ public get isPreservingWorkers(): boolean {
70
+ return false;
71
+ }
72
+
73
+ /**
74
+ * Gets the singleton instance.
75
+ */
76
+ public static getInstance(config?: WorkerPoolConfig): SequentialSigningPool {
77
+ if (!SequentialSigningPool.#instance) {
78
+ SequentialSigningPool.#instance = new SequentialSigningPool(config);
79
+ }
80
+ return SequentialSigningPool.#instance;
81
+ }
82
+
83
+ /**
84
+ * Resets the singleton instance (for testing).
85
+ */
86
+ public static resetInstance(): void {
87
+ SequentialSigningPool.#instance = null;
88
+ }
89
+
90
+ /**
91
+ * No-op — no workers to preserve.
92
+ */
93
+ public preserveWorkers(): void {
94
+ // No-op: no workers to preserve
95
+ }
96
+
97
+ /**
98
+ * No-op — no workers to release.
99
+ */
100
+ public releaseWorkers(): void {
101
+ // No-op
102
+ }
103
+
104
+ /**
105
+ * No-op — no initialization required.
106
+ */
107
+ public async initialize(): Promise<void> {
108
+ // No-op: nothing to initialize
109
+ }
110
+
111
+ /**
112
+ * Signs tasks sequentially on the main thread.
113
+ */
114
+ // eslint-disable-next-line @typescript-eslint/require-await
115
+ public async signBatch(
116
+ tasks: readonly SigningTask[],
117
+ keyPair: ParallelSignerKeyPair,
118
+ ): Promise<ParallelSigningResult> {
119
+ const startTime = performance.now();
120
+
121
+ if (tasks.length === 0) {
122
+ return {
123
+ success: true,
124
+ signatures: new Map(),
125
+ errors: new Map(),
126
+ durationMs: performance.now() - startTime,
127
+ };
128
+ }
129
+
130
+ const ecc = EccContext.get().lib;
131
+ const privateKey = keyPair.getPrivateKey();
132
+
133
+ const signatures = new Map<number, SigningResultMessage>();
134
+ const errors = new Map<number, string>();
135
+
136
+ try {
137
+ for (const task of tasks) {
138
+ try {
139
+ let signature: Uint8Array;
140
+
141
+ const hash = task.hash as MessageHash;
142
+ const key = privateKey as PrivateKey;
143
+
144
+ if (task.signatureType === SignatureType.Schnorr) {
145
+ signature = ecc.signSchnorr!(hash, key);
146
+ } else {
147
+ signature = ecc.sign(hash, key);
148
+ }
149
+
150
+ signatures.set(task.inputIndex, {
151
+ type: 'result',
152
+ taskId: task.taskId,
153
+ signature,
154
+ inputIndex: task.inputIndex,
155
+ publicKey: keyPair.publicKey,
156
+ signatureType: task.signatureType,
157
+ leafHash: task.leafHash,
158
+ });
159
+ } catch (err: unknown) {
160
+ const message = err instanceof Error ? err.message : 'Signing failed';
161
+ errors.set(task.inputIndex, message);
162
+ }
163
+ }
164
+ } finally {
165
+ // SECURITY: Zero the private key
166
+ privateKey.fill(0);
167
+ }
168
+
169
+ return {
170
+ success: errors.size === 0,
171
+ signatures,
172
+ errors,
173
+ durationMs: performance.now() - startTime,
174
+ };
175
+ }
176
+
177
+ /**
178
+ * No-op — no workers to shut down.
179
+ */
180
+ public async shutdown(): Promise<void> {
181
+ // No-op: nothing to shut down
182
+ }
183
+
184
+ /**
185
+ * Enables `await using pool = ...` syntax.
186
+ */
187
+ public async [Symbol.asyncDispose](): Promise<void> {
188
+ await this.shutdown();
189
+ }
190
+ }
@@ -389,6 +389,15 @@ export class WorkerSigningPool {
389
389
  }
390
390
  }
391
391
 
392
+ /**
393
+ * Disposes of the pool by shutting down all workers.
394
+ *
395
+ * Enables `await using pool = ...` syntax for automatic cleanup.
396
+ */
397
+ public async [Symbol.asyncDispose](): Promise<void> {
398
+ await this.shutdown();
399
+ }
400
+
392
401
  /**
393
402
  * Shuts down the pool and terminates all workers.
394
403
  *