@btc-vision/bitcoin 7.0.0-alpha.8 → 7.0.0-beta.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 (214) hide show
  1. package/README.md +22 -0
  2. package/benchmark-compare/BENCHMARK.md +144 -0
  3. package/benchmark-compare/compare.bench.ts +1024 -0
  4. package/benchmark-compare/harness.ts +220 -0
  5. package/benchmark-compare/package.json +18 -0
  6. package/browser/address.d.ts.map +1 -1
  7. package/browser/block.d.ts.map +1 -1
  8. package/browser/chunks/{psbt-parallel-PtTJ19DC.js → psbt-parallel-B-dfm5GZ.js} +2433 -2524
  9. package/browser/crypto-hashes.d.ts +4 -0
  10. package/browser/crypto-hashes.d.ts.map +1 -0
  11. package/browser/crypto-hashes.native.d.ts +4 -0
  12. package/browser/crypto-hashes.native.d.ts.map +1 -0
  13. package/browser/crypto.d.ts.map +1 -1
  14. package/browser/index.d.ts +3 -3
  15. package/browser/index.d.ts.map +1 -1
  16. package/browser/index.js +571 -547
  17. package/browser/io/base58check.d.ts +26 -0
  18. package/browser/io/base58check.d.ts.map +1 -0
  19. package/browser/io/base64.d.ts +8 -0
  20. package/browser/io/base64.d.ts.map +1 -1
  21. package/browser/io/hex.d.ts.map +1 -1
  22. package/browser/io/index.d.ts +2 -1
  23. package/browser/io/index.d.ts.map +1 -1
  24. package/browser/io/utils.d.ts.map +1 -1
  25. package/browser/payments/bip341.d.ts.map +1 -1
  26. package/browser/payments/p2op.d.ts.map +1 -1
  27. package/browser/payments/p2pkh.d.ts.map +1 -1
  28. package/browser/payments/p2sh.d.ts.map +1 -1
  29. package/browser/payments/p2tr.d.ts.map +1 -1
  30. package/browser/payments/p2wpkh.d.ts.map +1 -1
  31. package/browser/psbt/PsbtCache.d.ts.map +1 -1
  32. package/browser/psbt/PsbtSigner.d.ts.map +1 -1
  33. package/browser/psbt/PsbtTransaction.d.ts +2 -2
  34. package/browser/psbt/PsbtTransaction.d.ts.map +1 -1
  35. package/browser/psbt/bip371.d.ts.map +1 -1
  36. package/browser/psbt.d.ts +1 -1
  37. package/browser/psbt.d.ts.map +1 -1
  38. package/browser/react-native-quick-crypto.d.ts +11 -0
  39. package/browser/script.d.ts.map +1 -1
  40. package/browser/transaction.d.ts.map +1 -1
  41. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
  42. package/browser/workers/WorkerSigningPool.sequential.d.ts.map +1 -1
  43. package/browser/workers/index.js +5 -5
  44. package/build/address.d.ts.map +1 -1
  45. package/build/address.js +19 -12
  46. package/build/address.js.map +1 -1
  47. package/build/bech32utils.js.map +1 -1
  48. package/build/bip66.js +4 -4
  49. package/build/bip66.js.map +1 -1
  50. package/build/block.d.ts.map +1 -1
  51. package/build/block.js +9 -2
  52. package/build/block.js.map +1 -1
  53. package/build/crypto-hashes.d.ts +4 -0
  54. package/build/crypto-hashes.d.ts.map +1 -0
  55. package/build/crypto-hashes.js +4 -0
  56. package/build/crypto-hashes.js.map +1 -0
  57. package/build/crypto-hashes.native.d.ts +4 -0
  58. package/build/crypto-hashes.native.d.ts.map +1 -0
  59. package/build/crypto-hashes.native.js +15 -0
  60. package/build/crypto-hashes.native.js.map +1 -0
  61. package/build/crypto.d.ts.map +1 -1
  62. package/build/crypto.js +1 -2
  63. package/build/crypto.js.map +1 -1
  64. package/build/env.js.map +1 -1
  65. package/build/index.d.ts +3 -3
  66. package/build/index.d.ts.map +1 -1
  67. package/build/index.js +1 -1
  68. package/build/index.js.map +1 -1
  69. package/build/io/BinaryReader.js +1 -1
  70. package/build/io/BinaryReader.js.map +1 -1
  71. package/build/io/base58check.d.ts +26 -0
  72. package/build/io/base58check.d.ts.map +1 -0
  73. package/build/io/base58check.js +32 -0
  74. package/build/io/base58check.js.map +1 -0
  75. package/build/io/base64.d.ts +8 -0
  76. package/build/io/base64.d.ts.map +1 -1
  77. package/build/io/base64.js +14 -0
  78. package/build/io/base64.js.map +1 -1
  79. package/build/io/hex.d.ts.map +1 -1
  80. package/build/io/hex.js +3 -2
  81. package/build/io/hex.js.map +1 -1
  82. package/build/io/index.d.ts +2 -1
  83. package/build/io/index.d.ts.map +1 -1
  84. package/build/io/index.js +4 -2
  85. package/build/io/index.js.map +1 -1
  86. package/build/io/utils.d.ts.map +1 -1
  87. package/build/io/utils.js +3 -4
  88. package/build/io/utils.js.map +1 -1
  89. package/build/merkle.js.map +1 -1
  90. package/build/payments/bip341.d.ts.map +1 -1
  91. package/build/payments/bip341.js +4 -3
  92. package/build/payments/bip341.js.map +1 -1
  93. package/build/payments/embed.js.map +1 -1
  94. package/build/payments/p2ms.js.map +1 -1
  95. package/build/payments/p2op.d.ts.map +1 -1
  96. package/build/payments/p2op.js +6 -4
  97. package/build/payments/p2op.js.map +1 -1
  98. package/build/payments/p2pk.js.map +1 -1
  99. package/build/payments/p2pkh.d.ts.map +1 -1
  100. package/build/payments/p2pkh.js +3 -4
  101. package/build/payments/p2pkh.js.map +1 -1
  102. package/build/payments/p2sh.d.ts.map +1 -1
  103. package/build/payments/p2sh.js +3 -4
  104. package/build/payments/p2sh.js.map +1 -1
  105. package/build/payments/p2tr.d.ts.map +1 -1
  106. package/build/payments/p2tr.js +13 -6
  107. package/build/payments/p2tr.js.map +1 -1
  108. package/build/payments/p2wpkh.d.ts.map +1 -1
  109. package/build/payments/p2wpkh.js +7 -5
  110. package/build/payments/p2wpkh.js.map +1 -1
  111. package/build/payments/p2wsh.js.map +1 -1
  112. package/build/psbt/PsbtCache.d.ts.map +1 -1
  113. package/build/psbt/PsbtCache.js +8 -4
  114. package/build/psbt/PsbtCache.js.map +1 -1
  115. package/build/psbt/PsbtFinalizer.js +14 -8
  116. package/build/psbt/PsbtFinalizer.js.map +1 -1
  117. package/build/psbt/PsbtSigner.d.ts.map +1 -1
  118. package/build/psbt/PsbtSigner.js +3 -2
  119. package/build/psbt/PsbtSigner.js.map +1 -1
  120. package/build/psbt/PsbtTransaction.d.ts +2 -2
  121. package/build/psbt/PsbtTransaction.d.ts.map +1 -1
  122. package/build/psbt/PsbtTransaction.js.map +1 -1
  123. package/build/psbt/bip371.d.ts.map +1 -1
  124. package/build/psbt/bip371.js +4 -3
  125. package/build/psbt/bip371.js.map +1 -1
  126. package/build/psbt/utils.js.map +1 -1
  127. package/build/psbt.d.ts +1 -1
  128. package/build/psbt.d.ts.map +1 -1
  129. package/build/psbt.js.map +1 -1
  130. package/build/push_data.js +1 -1
  131. package/build/push_data.js.map +1 -1
  132. package/build/script.d.ts.map +1 -1
  133. package/build/script.js +4 -3
  134. package/build/script.js.map +1 -1
  135. package/build/script_number.js +1 -1
  136. package/build/script_number.js.map +1 -1
  137. package/build/script_signature.js.map +1 -1
  138. package/build/transaction.d.ts.map +1 -1
  139. package/build/transaction.js +2 -1
  140. package/build/transaction.js.map +1 -1
  141. package/build/tsconfig.build.tsbuildinfo +1 -1
  142. package/build/types.js.map +1 -1
  143. package/build/workers/WorkerSigningPool.js.map +1 -1
  144. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
  145. package/build/workers/WorkerSigningPool.node.js +25 -3
  146. package/build/workers/WorkerSigningPool.node.js.map +1 -1
  147. package/build/workers/WorkerSigningPool.sequential.d.ts.map +1 -1
  148. package/build/workers/WorkerSigningPool.sequential.js +2 -0
  149. package/build/workers/WorkerSigningPool.sequential.js.map +1 -1
  150. package/build/workers/index.js.map +1 -1
  151. package/build/workers/psbt-parallel.js.map +1 -1
  152. package/package.json +7 -5
  153. package/src/address.ts +18 -13
  154. package/src/bech32utils.ts +3 -3
  155. package/src/bip66.ts +18 -18
  156. package/src/block.ts +8 -3
  157. package/src/crypto-hashes.native.ts +18 -0
  158. package/src/crypto-hashes.ts +3 -0
  159. package/src/crypto.ts +1 -2
  160. package/src/env.ts +10 -8
  161. package/src/index.ts +4 -0
  162. package/src/io/BinaryReader.ts +1 -1
  163. package/src/io/base58check.ts +35 -0
  164. package/src/io/base64.ts +15 -0
  165. package/src/io/hex.ts +3 -2
  166. package/src/io/index.ts +5 -2
  167. package/src/io/utils.ts +6 -7
  168. package/src/merkle.ts +3 -3
  169. package/src/payments/bip341.ts +8 -7
  170. package/src/payments/embed.ts +1 -1
  171. package/src/payments/p2ms.ts +2 -2
  172. package/src/payments/p2op.ts +6 -4
  173. package/src/payments/p2pk.ts +2 -2
  174. package/src/payments/p2pkh.ts +7 -8
  175. package/src/payments/p2sh.ts +8 -9
  176. package/src/payments/p2tr.ts +24 -17
  177. package/src/payments/p2wpkh.ts +9 -7
  178. package/src/payments/p2wsh.ts +3 -3
  179. package/src/psbt/PsbtCache.ts +14 -11
  180. package/src/psbt/PsbtFinalizer.ts +17 -11
  181. package/src/psbt/PsbtSigner.ts +7 -6
  182. package/src/psbt/PsbtTransaction.ts +2 -2
  183. package/src/psbt/bip371.ts +4 -3
  184. package/src/psbt/utils.ts +1 -1
  185. package/src/psbt.ts +11 -9
  186. package/src/push_data.ts +5 -5
  187. package/src/react-native-quick-crypto.d.ts +11 -0
  188. package/src/script.ts +5 -4
  189. package/src/script_number.ts +6 -6
  190. package/src/script_signature.ts +2 -2
  191. package/src/transaction.ts +15 -14
  192. package/src/types.ts +1 -1
  193. package/src/workers/WorkerSigningPool.node.ts +28 -4
  194. package/src/workers/WorkerSigningPool.sequential.ts +2 -1
  195. package/src/workers/WorkerSigningPool.ts +3 -3
  196. package/src/workers/index.ts +1 -1
  197. package/src/workers/psbt-parallel.ts +3 -3
  198. package/test/address.spec.ts +1 -0
  199. package/test/bitcoin.core.spec.ts +9 -2
  200. package/test/browser/psbt.spec.ts +54 -29
  201. package/test/browser/workers-signing.spec.ts +8 -8
  202. package/test/crypto.spec.ts +1 -1
  203. package/test/env.spec.ts +2 -2
  204. package/test/integration/_regtest.ts +2 -2
  205. package/test/integration/blocks.spec.ts +1 -1
  206. package/test/integration/csv.spec.ts +1 -1
  207. package/test/integration/payments.spec.ts +2 -2
  208. package/test/integration/taproot.spec.ts +3 -3
  209. package/test/integration/transactions.spec.ts +6 -5
  210. package/test/psbt.spec.ts +49 -25
  211. package/test/transaction.spec.ts +6 -3
  212. package/test/workers-pool.spec.ts +5 -5
  213. package/test/workers-signing.spec.ts +8 -8
  214. package/test/workers.spec.ts +3 -3
@@ -69,7 +69,8 @@ export class PsbtSigner {
69
69
  this.#txFromBuffer,
70
70
  );
71
71
 
72
- const prevoutHash = unsignedTx.ins[inputIndex]!.hash;
72
+ const txIn = unsignedTx.ins[inputIndex] as Transaction['ins'][0];
73
+ const prevoutHash = txIn.hash;
73
74
  const utxoHash = nonWitnessUtxoTx.getHash();
74
75
 
75
76
  if (!equals(prevoutHash, utxoHash)) {
@@ -78,8 +79,8 @@ export class PsbtSigner {
78
79
  );
79
80
  }
80
81
 
81
- const prevoutIndex = unsignedTx.ins[inputIndex]!.index;
82
- prevout = nonWitnessUtxoTx.outs[prevoutIndex]!;
82
+ const prevoutIndex = txIn.index;
83
+ prevout = nonWitnessUtxoTx.outs[prevoutIndex] as Transaction['outs'][0];
83
84
  } else if (input.witnessUtxo) {
84
85
  prevout = {
85
86
  script: input.witnessUtxo.script as Script,
@@ -108,7 +109,7 @@ export class PsbtSigner {
108
109
  if (!p2pkhPayment.output) throw new Error('Unable to create signing script');
109
110
  hash = unsignedTx.hashForWitnessV0(
110
111
  inputIndex,
111
- p2pkhPayment.output as Script,
112
+ p2pkhPayment.output,
112
113
  prevout.value,
113
114
  sighashType,
114
115
  );
@@ -198,7 +199,7 @@ export class PsbtSigner {
198
199
  signingScripts,
199
200
  values,
200
201
  sighashType,
201
- tapLeaf.hash as Bytes32,
202
+ tapLeaf.hash,
202
203
  undefined,
203
204
  taprootCache,
204
205
  );
@@ -206,7 +207,7 @@ export class PsbtSigner {
206
207
  return {
207
208
  pubkey: pubkey as PublicKey,
208
209
  hash: tapScriptHash,
209
- leafHash: tapLeaf.hash as Bytes32,
210
+ leafHash: tapLeaf.hash,
210
211
  };
211
212
  });
212
213
 
@@ -3,7 +3,7 @@ import { fromHex, reverse } from '../io/index.js';
3
3
  import { Transaction } from '../transaction.js';
4
4
  import type { Bytes32 } from '../types.js';
5
5
  import { checkTxEmpty } from './validation.js';
6
- import type { TransactionInput, TransactionOutput } from './types.js';
6
+ import type { PsbtTxOutput, TransactionInput } from './types.js';
7
7
 
8
8
  /**
9
9
  * Empty version-2 transaction with zero inputs and zero outputs.
@@ -56,7 +56,7 @@ export class PsbtTransaction implements ITransaction {
56
56
  this.tx.addInput(hash, input.index, input.sequence);
57
57
  }
58
58
 
59
- public addOutput(output: TransactionOutput): void {
59
+ public addOutput(output: PsbtTxOutput): void {
60
60
  if (
61
61
  output.script === undefined ||
62
62
  output.value === undefined ||
@@ -180,10 +180,11 @@ export function tapTreeToList(tree: Taptree): TapLeaf[] {
180
180
  * @returns the corresponding taptree, or throws an exception if the tree cannot be reconstructed
181
181
  */
182
182
  export function tapTreeFromList(leaves: TapLeaf[] = []): Taptree {
183
- if (leaves.length === 1 && leaves[0]!.depth === 0)
183
+ const firstLeaf = leaves[0];
184
+ if (leaves.length === 1 && firstLeaf && firstLeaf.depth === 0)
184
185
  return {
185
- output: new Uint8Array(leaves[0]!.script),
186
- version: leaves[0]!.leafVersion,
186
+ output: new Uint8Array(firstLeaf.script),
187
+ version: firstLeaf.leafVersion,
187
188
  };
188
189
 
189
190
  return insertLeavesInTree(leaves);
package/src/psbt/utils.ts CHANGED
@@ -73,7 +73,7 @@ export function sighashTypeToString(sighashType: number): string {
73
73
  */
74
74
  export function compressPubkey(pubkey: Uint8Array): Uint8Array {
75
75
  if (pubkey.length === 65) {
76
- const parity = pubkey[64]! & 1;
76
+ const parity = (pubkey[64] as number) & 1;
77
77
  const newKey = new Uint8Array(pubkey.subarray(0, 33));
78
78
  newKey[0] = 2 | parity;
79
79
  return newKey;
package/src/psbt.ts CHANGED
@@ -3,6 +3,7 @@ import type {
3
3
  PsbtGlobalUpdate,
4
4
  PsbtInput,
5
5
  PsbtInputUpdate,
6
+ PsbtOutput,
6
7
  PsbtOutputUpdate,
7
8
  TapKeySig,
8
9
  TapScriptSig,
@@ -79,6 +80,7 @@ export type {
79
80
  PsbtInputExtended,
80
81
  PsbtOutputExtended,
81
82
  PsbtOutputExtendedScript,
83
+ PsbtOutputExtendedAddress,
82
84
  HDSigner,
83
85
  HDSignerAsync,
84
86
  Signer,
@@ -348,7 +350,7 @@ export class Psbt {
348
350
  if (this.#cache.tx.ins.length <= inputIndex) {
349
351
  throw new Error('Input index too high');
350
352
  }
351
- this.#cache.tx.ins[inputIndex]!.sequence = sequence;
353
+ (this.#cache.tx.ins[inputIndex] as { sequence: number }).sequence = sequence;
352
354
  this.#cache.invalidate('outputs');
353
355
  return this;
354
356
  }
@@ -386,11 +388,11 @@ export class Psbt {
386
388
  }
387
389
  : inputData;
388
390
  this.data.addInput(normalizedInputData);
389
- const txIn = this.#cache.tx.ins[this.#cache.tx.ins.length - 1]!;
391
+ const txIn = this.#cache.tx.ins[this.#cache.tx.ins.length - 1] as Transaction['ins'][0];
390
392
  checkTxInputCache(this.#cache, txIn);
391
393
 
392
394
  const inputIndex = this.data.inputs.length - 1;
393
- const input = this.data.inputs[inputIndex]!;
395
+ const input = this.data.inputs[inputIndex] as PsbtInput;
394
396
  if (input.nonWitnessUtxo) {
395
397
  this.#cache.addNonWitnessTxCache(input, inputIndex, txFromBuffer);
396
398
  }
@@ -558,7 +560,7 @@ export class Psbt {
558
560
  validator: ValidateSigFunction,
559
561
  pubkey?: PublicKey,
560
562
  ): boolean {
561
- const input = this.data.inputs[inputIndex]!;
563
+ const input = this.data.inputs[inputIndex] as PsbtInput;
562
564
  if (isTaprootInput(input))
563
565
  return this.#validateSignaturesOfTaprootInput(inputIndex, validator, pubkey);
564
566
 
@@ -795,7 +797,7 @@ export class Psbt {
795
797
 
796
798
  public updateInput(inputIndex: number, updateData: PsbtInputUpdate): this {
797
799
  if (updateData.witnessScript) checkInvalidP2WSH(updateData.witnessScript);
798
- checkTaprootInputFields(this.data.inputs[inputIndex]!, updateData, 'updateInput');
800
+ checkTaprootInputFields(this.data.inputs[inputIndex] as PsbtInput, updateData, 'updateInput');
799
801
  const normalizedUpdate = updateData.witnessUtxo
800
802
  ? {
801
803
  ...updateData,
@@ -811,7 +813,7 @@ export class Psbt {
811
813
  this.data.updateInput(inputIndex, normalizedUpdate);
812
814
  if (updateData.nonWitnessUtxo) {
813
815
  this.#cache.addNonWitnessTxCache(
814
- this.data.inputs[inputIndex]!,
816
+ this.data.inputs[inputIndex] as PsbtInput,
815
817
  inputIndex,
816
818
  txFromBuffer,
817
819
  );
@@ -820,7 +822,7 @@ export class Psbt {
820
822
  }
821
823
 
822
824
  public updateOutput(outputIndex: number, updateData: PsbtOutputUpdate): this {
823
- const outputData = this.data.outputs[outputIndex]!;
825
+ const outputData = this.data.outputs[outputIndex] as PsbtOutput;
824
826
  checkTaprootOutputFields(outputData, updateData, 'updateOutput');
825
827
 
826
828
  this.data.updateOutput(outputIndex, updateData);
@@ -986,7 +988,7 @@ export class Psbt {
986
988
  validator: ValidateSigFunction,
987
989
  pubkey?: PublicKey,
988
990
  ): boolean {
989
- const input = this.data.inputs[inputIndex]!;
991
+ const input = this.data.inputs[inputIndex] as PsbtInput;
990
992
  const tapKeySig = input?.tapKeySig;
991
993
  const tapScriptSig = input?.tapScriptSig;
992
994
  if (!input && !tapKeySig && !(tapScriptSig && !tapScriptSig.length))
@@ -1049,7 +1051,7 @@ export class Psbt {
1049
1051
  sighashTypes,
1050
1052
  );
1051
1053
 
1052
- const sig = keyPair.sign(hash) as Uint8Array;
1054
+ const sig = keyPair.sign(hash);
1053
1055
  const partialSig = [
1054
1056
  {
1055
1057
  pubkey,
package/src/push_data.ts CHANGED
@@ -61,19 +61,19 @@ export function decode(
61
61
  size: number;
62
62
  } | null {
63
63
  const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
64
- const opcode = buffer[offset];
64
+ const opcode = buffer[offset] as number;
65
65
  let num: number;
66
66
  let size: number;
67
67
 
68
68
  // ~6 bit
69
- if (opcode! < opcodes.OP_PUSHDATA1) {
70
- num = opcode!;
69
+ if (opcode < opcodes.OP_PUSHDATA1) {
70
+ num = opcode;
71
71
  size = 1;
72
72
 
73
73
  // 8 bit
74
74
  } else if (opcode === opcodes.OP_PUSHDATA1) {
75
75
  if (offset + 2 > buffer.length) return null;
76
- num = buffer[offset + 1]!;
76
+ num = buffer[offset + 1] as number;
77
77
  size = 2;
78
78
 
79
79
  // 16 bit
@@ -92,7 +92,7 @@ export function decode(
92
92
  }
93
93
 
94
94
  return {
95
- opcode: opcode!,
95
+ opcode,
96
96
  number: num,
97
97
  size,
98
98
  };
@@ -0,0 +1,11 @@
1
+ declare module 'react-native-quick-crypto' {
2
+ interface Hash {
3
+ update(data: Uint8Array | string): Hash;
4
+ digest(): Buffer;
5
+ }
6
+ interface QuickCrypto {
7
+ createHash(algorithm: string): Hash;
8
+ }
9
+ const QuickCrypto: QuickCrypto;
10
+ export default QuickCrypto;
11
+ }
package/src/script.ts CHANGED
@@ -41,8 +41,9 @@ export function countNonPushOnlyOPs(value: Stack): number {
41
41
  function asMinimalOP(buffer: Uint8Array): number | undefined {
42
42
  if (buffer.length === 0) return opcodes.OP_0;
43
43
  if (buffer.length !== 1) return undefined;
44
- if (buffer[0]! >= 1 && buffer[0]! <= 16) return OP_INT_BASE + buffer[0]!;
45
- if (buffer[0] === 0x81) return opcodes.OP_1NEGATE;
44
+ const firstByte = buffer[0] as number;
45
+ if (firstByte >= 1 && firstByte <= 16) return OP_INT_BASE + firstByte;
46
+ if (firstByte === 0x81) return opcodes.OP_1NEGATE;
46
47
  return undefined;
47
48
  }
48
49
 
@@ -129,7 +130,7 @@ export function decompile(buffer: Uint8Array | Stack): Array<number | Uint8Array
129
130
  let i = 0;
130
131
 
131
132
  while (i < buffer.length) {
132
- const opcode = buffer[i]!;
133
+ const opcode = buffer[i] as number;
133
134
 
134
135
  // data chunk
135
136
  if (opcode > opcodes.OP_0 && opcode <= opcodes.OP_PUSHDATA4) {
@@ -248,7 +249,7 @@ export function isCanonicalPubKey(buffer: Uint8Array): boolean {
248
249
 
249
250
  export function isCanonicalScriptSignature(buffer: Uint8Array): boolean {
250
251
  if (!(buffer instanceof Uint8Array)) return false;
251
- if (!isDefinedHashType(buffer[buffer.length - 1]!)) return false;
252
+ if (!isDefinedHashType(buffer[buffer.length - 1] as number)) return false;
252
253
 
253
254
  return bip66.check(buffer.subarray(0, -1));
254
255
  }
@@ -16,8 +16,8 @@ export function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): n
16
16
  if (length === 0) return 0;
17
17
  if (length > maxLength) throw new TypeError('Script number overflow');
18
18
  if (minimal) {
19
- if ((buffer[length - 1]! & 0x7f) === 0) {
20
- if (length <= 1 || (buffer[length - 2]! & 0x80) === 0)
19
+ if (((buffer[length - 1] as number) & 0x7f) === 0) {
20
+ if (length <= 1 || ((buffer[length - 2] as number) & 0x80) === 0)
21
21
  throw new Error('Non-minimally encoded script number');
22
22
  }
23
23
  }
@@ -34,10 +34,10 @@ export function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): n
34
34
  // 32-bit / 24-bit / 16-bit / 8-bit
35
35
  let result = 0;
36
36
  for (let i = 0; i < length; ++i) {
37
- result |= buffer[i]! << (8 * i);
37
+ result |= (buffer[i] as number) << (8 * i);
38
38
  }
39
39
 
40
- if (buffer[length - 1]! & 0x80) return -(result & ~(0x80 << (8 * (length - 1))));
40
+ if ((buffer[length - 1] as number) & 0x80) return -(result & ~(0x80 << (8 * (length - 1))));
41
41
  return result;
42
42
  }
43
43
 
@@ -62,10 +62,10 @@ export function encode(_number: number): Buffer {
62
62
  value >>= 8;
63
63
  }
64
64
 
65
- if (buffer[size - 1]! & 0x80) {
65
+ if ((buffer[size - 1] as number) & 0x80) {
66
66
  buffer.writeUInt8(negative ? 0x80 : 0x00, size - 1);
67
67
  } else if (negative) {
68
- buffer[size - 1]! |= 0x80;
68
+ buffer[size - 1] = (buffer[size - 1] as number) | 0x80;
69
69
  }
70
70
 
71
71
  return buffer;
@@ -24,7 +24,7 @@ function toDER(x: Uint8Array): Uint8Array {
24
24
  while (x[i] === 0) ++i;
25
25
  if (i === x.length) return ZERO;
26
26
  x = x.subarray(i);
27
- if (x[0]! & 0x80) return concat([ZERO, x]);
27
+ if ((x[0] as number) & 0x80) return concat([ZERO, x]);
28
28
  return x;
29
29
  }
30
30
 
@@ -56,7 +56,7 @@ export interface ScriptSignature {
56
56
  * @throws Error if the hashType is invalid.
57
57
  */
58
58
  export function decode(buffer: Uint8Array): ScriptSignature {
59
- const hashType = buffer[buffer.length - 1]!;
59
+ const hashType = buffer[buffer.length - 1] as number;
60
60
  if (!isDefinedHashType(hashType)) {
61
61
  throw new Error(`Invalid hashType ${hashType}`);
62
62
  }
@@ -144,7 +144,7 @@ export class Transaction {
144
144
 
145
145
  if (hasWitnesses) {
146
146
  for (let i = 0; i < vinLen; ++i) {
147
- tx.ins[i]!.witness = bufferReader.readVector();
147
+ (tx.ins[i] as Transaction['ins'][0]).witness = bufferReader.readVector();
148
148
  }
149
149
 
150
150
  // was this pointless?
@@ -187,7 +187,8 @@ export class Transaction {
187
187
  }
188
188
 
189
189
  isCoinbase(): boolean {
190
- return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0]!.hash);
190
+ const firstIn = this.ins[0];
191
+ return this.ins.length === 1 && firstIn !== undefined && Transaction.isCoinbaseHash(firstIn.hash);
191
192
  }
192
193
 
193
194
  /**
@@ -391,8 +392,8 @@ export class Transaction {
391
392
 
392
393
  // SIGHASH_ANYONECANPAY: ignore inputs entirely?
393
394
  if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
394
- txTmp.ins = [txTmp.ins[inIndex]!];
395
- txTmp.ins[0]!.script = ourScript;
395
+ txTmp.ins = [txTmp.ins[inIndex] as Transaction['ins'][0]];
396
+ (txTmp.ins[0] as Transaction['ins'][0]).script = ourScript;
396
397
 
397
398
  // SIGHASH_ALL: only ignore input scripts
398
399
  } else {
@@ -400,7 +401,7 @@ export class Transaction {
400
401
  txTmp.ins.forEach((input) => {
401
402
  input.script = EMPTY_BYTES;
402
403
  });
403
- txTmp.ins[inIndex]!.script = ourScript;
404
+ (txTmp.ins[inIndex] as Transaction['ins'][0]).script = ourScript;
404
405
  }
405
406
 
406
407
  // serialize and hash
@@ -522,7 +523,7 @@ export class Transaction {
522
523
  hashOutputs = bcrypto.sha256(bufferWriter.finish());
523
524
  }
524
525
  } else if (isSingle && inIndex < this.outs.length) {
525
- const output = this.outs[inIndex]!;
526
+ const output = this.outs[inIndex] as Transaction['outs'][0];
526
527
 
527
528
  const bufferWriter = new BinaryWriter(8 + varSliceSize(output.script));
528
529
  bufferWriter.writeUInt64LE(output.value);
@@ -558,11 +559,11 @@ export class Transaction {
558
559
  // Input
559
560
  sigMsgWriter.writeUInt8(spendType);
560
561
  if (isAnyoneCanPay) {
561
- const input = this.ins[inIndex]!;
562
+ const input = this.ins[inIndex] as Transaction['ins'][0];
562
563
  sigMsgWriter.writeBytes(input.hash);
563
564
  sigMsgWriter.writeUInt32LE(input.index);
564
- sigMsgWriter.writeUInt64LE(values[inIndex]!);
565
- sigMsgWriter.writeVarBytes(prevOutScripts[inIndex]!);
565
+ sigMsgWriter.writeUInt64LE(values[inIndex] as Satoshi);
566
+ sigMsgWriter.writeVarBytes(prevOutScripts[inIndex] as Uint8Array);
566
567
  sigMsgWriter.writeUInt32LE(input.sequence);
567
568
  } else {
568
569
  sigMsgWriter.writeUInt32LE(inIndex);
@@ -733,7 +734,7 @@ export class Transaction {
733
734
 
734
735
  hashOutputs = bcrypto.hash256(tbuffer);
735
736
  } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) {
736
- const output = this.outs[inIndex]!;
737
+ const output = this.outs[inIndex] as Transaction['outs'][0];
737
738
 
738
739
  tbuffer = alloc(8 + varSliceSize(output.script));
739
740
  bufferWriter = new BinaryWriter(tbuffer, 0);
@@ -746,7 +747,7 @@ export class Transaction {
746
747
  tbuffer = alloc(156 + varSliceSize(prevOutScript));
747
748
  bufferWriter = new BinaryWriter(tbuffer, 0);
748
749
 
749
- const input = this.ins[inIndex]!;
750
+ const input = this.ins[inIndex] as Transaction['ins'][0];
750
751
  bufferWriter.writeInt32LE(this.version);
751
752
  bufferWriter.writeBytes(hashPrevouts);
752
753
  bufferWriter.writeBytes(hashSequence);
@@ -770,7 +771,7 @@ export class Transaction {
770
771
  getHash(forWitness?: boolean): Bytes32 {
771
772
  // wtxid for coinbase is always 32 bytes of 0x00
772
773
  if (forWitness && this.isCoinbase()) return new Uint8Array(32) as Bytes32;
773
- return bcrypto.hash256(this.#toBuffer(undefined, undefined, forWitness)) as Bytes32;
774
+ return bcrypto.hash256(this.#toBuffer(undefined, undefined, forWitness));
774
775
  }
775
776
 
776
777
  /**
@@ -817,7 +818,7 @@ export class Transaction {
817
818
  throw new TypeError('Expected Uint8Array for scriptSig');
818
819
  }
819
820
 
820
- this.ins[index]!.script = scriptSig;
821
+ (this.ins[index] as Transaction['ins'][0]).script = scriptSig;
821
822
  }
822
823
 
823
824
  /**
@@ -834,7 +835,7 @@ export class Transaction {
834
835
  throw new TypeError('Expected array of Uint8Array for witness');
835
836
  }
836
837
 
837
- this.ins[index]!.witness = witness;
838
+ (this.ins[index] as Transaction['ins'][0]).witness = witness;
838
839
  }
839
840
 
840
841
  /**
package/src/types.ts CHANGED
@@ -177,7 +177,7 @@ export type StackFunction = () => Stack;
177
177
 
178
178
  export function stacksEqual(a: Uint8Array[], b: Uint8Array[]): boolean {
179
179
  if (a.length !== b.length) return false;
180
- return a.every((x, i) => equals(x, b[i]!));
180
+ return a.every((x, i) => equals(x, b[i] as Uint8Array));
181
181
  }
182
182
 
183
183
  export function toBytes32(value: Uint8Array): Bytes32 {
@@ -289,7 +289,7 @@ export class NodeWorkerSigningPool {
289
289
  const taskBatches: SigningTask[][] = Array.from({ length: workerCount }, () => []);
290
290
 
291
291
  for (let i = 0; i < tasks.length; i++) {
292
- taskBatches[i % workerCount]!.push(tasks[i]!);
292
+ (taskBatches[i % workerCount] as SigningTask[]).push(tasks[i] as SigningTask);
293
293
  }
294
294
 
295
295
  // Get private key once
@@ -784,16 +784,40 @@ function handleSignBatch(msg) {
784
784
  leafHash: task.leafHash,
785
785
  }));
786
786
 
787
+ // Copy private key for this worker (original shared across workers)
788
+ const workerPrivateKey = new Uint8Array(privateKey);
789
+
787
790
  // Create batch message
788
791
  const message: BatchSigningMessage = {
789
792
  type: 'signBatch',
790
793
  batchId,
791
794
  tasks: batchTasks,
792
- privateKey,
795
+ privateKey: workerPrivateKey,
793
796
  };
794
797
 
795
- // Send to worker
796
- worker.worker.postMessage(message);
798
+ // Collect ArrayBuffers for zero-copy transfer.
799
+ // Only transfer buffers unique to this worker batch — NOT publicKey
800
+ // (shared across all worker batches, would detach for other workers).
801
+ const keyBuf = workerPrivateKey.buffer;
802
+ const transferList: ArrayBuffer[] = [keyBuf];
803
+ const seen = new Set<ArrayBuffer>([keyBuf]);
804
+ for (const task of batchTasks) {
805
+ const hashBuf = task.hash.buffer as ArrayBuffer;
806
+ if (!seen.has(hashBuf)) {
807
+ seen.add(hashBuf);
808
+ transferList.push(hashBuf);
809
+ }
810
+ if (task.leafHash) {
811
+ const leafBuf = task.leafHash.buffer as ArrayBuffer;
812
+ if (!seen.has(leafBuf)) {
813
+ seen.add(leafBuf);
814
+ transferList.push(leafBuf);
815
+ }
816
+ }
817
+ }
818
+
819
+ // Send to worker with transfer list (zero-copy)
820
+ worker.worker.postMessage(message, transferList);
797
821
  });
798
822
  }
799
823
 
@@ -142,7 +142,8 @@ export class SequentialSigningPool {
142
142
  const key = privateKey as PrivateKey;
143
143
 
144
144
  if (task.signatureType === SignatureType.Schnorr) {
145
- signature = ecc.signSchnorr!(hash, key);
145
+ if (!ecc.signSchnorr) throw new Error('Schnorr signing not supported');
146
+ signature = ecc.signSchnorr(hash, key);
146
147
  } else {
147
148
  signature = ecc.sign(hash, key);
148
149
  }
@@ -319,7 +319,7 @@ export class WorkerSigningPool {
319
319
  const taskBatches: SigningTask[][] = Array.from({ length: workerCount }, () => []);
320
320
 
321
321
  for (let i = 0; i < tasks.length; i++) {
322
- taskBatches[i % workerCount]!.push(tasks[i]!);
322
+ (taskBatches[i % workerCount] as SigningTask[]).push(tasks[i] as SigningTask);
323
323
  }
324
324
 
325
325
  // Get private key once
@@ -338,7 +338,7 @@ export class WorkerSigningPool {
338
338
  const errors = new Map<number, string>();
339
339
 
340
340
  for (let i = 0; i < batchResults.length; i++) {
341
- const result = batchResults[i]!;
341
+ const result = batchResults[i] as PromiseSettledResult<BatchSigningResultMessage>;
342
342
  if (result.status === 'fulfilled') {
343
343
  const batchResult = result.value;
344
344
 
@@ -365,7 +365,7 @@ export class WorkerSigningPool {
365
365
  const errorMsg = reason?.message ?? 'Batch signing failed';
366
366
 
367
367
  // Add error for each task in the failed batch
368
- const failedBatch = taskBatches[i]!;
368
+ const failedBatch = taskBatches[i] as SigningTask[];
369
369
  for (const task of failedBatch) {
370
370
  errors.set(task.inputIndex, errorMsg);
371
371
  }
@@ -57,7 +57,7 @@ export * from './index.shared.js';
57
57
  * @returns 'node' for Node.js, 'browser' for browsers, 'unknown' otherwise
58
58
  */
59
59
  export function detectRuntime(): 'node' | 'browser' | 'react-native' | 'unknown' {
60
- if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
60
+ if (typeof navigator !== 'undefined' && (navigator as {product?: string}).product === 'ReactNative') {
61
61
  return 'react-native';
62
62
  }
63
63
  if (typeof process !== 'undefined' && process.versions?.node) {
@@ -118,7 +118,7 @@ export async function signPsbtParallel(
118
118
  pool = poolOrConfig;
119
119
  } else {
120
120
  const { WorkerSigningPool } = await import('./WorkerSigningPool.js');
121
- pool = WorkerSigningPool.getInstance(poolOrConfig as WorkerPoolConfig | undefined);
121
+ pool = WorkerSigningPool.getInstance(poolOrConfig);
122
122
  if (!pool.isPreservingWorkers) {
123
123
  shouldShutdown = true;
124
124
  }
@@ -177,7 +177,7 @@ export function prepareSigningTasks(
177
177
  const pubkey = keyPair.publicKey;
178
178
 
179
179
  for (let i = 0; i < inputs.length; i++) {
180
- const input = inputs[i]!;
180
+ const input = inputs[i] as PsbtInput;
181
181
 
182
182
  // Check if this input can be signed with this key
183
183
  if (!psbt.inputHasPubkey(i, pubkey as PublicKey)) {
@@ -285,7 +285,7 @@ export function applySignaturesToPsbt(
285
285
  const pubkey = keyPair.publicKey;
286
286
 
287
287
  for (const [inputIndex, sigResult] of result.signatures) {
288
- const input = psbt.data.inputs[inputIndex]!;
288
+ const input = psbt.data.inputs[inputIndex] as PsbtInput;
289
289
 
290
290
  if (sigResult.signatureType === SignatureType.Schnorr) {
291
291
  // Taproot signature
@@ -66,6 +66,7 @@ describe('address', () => {
66
66
  assert.strictEqual(actual.version, f.version);
67
67
  // Support both bech32 and bech32Opnet prefixes
68
68
  const network = NETWORKS[f.network];
69
+ assert.ok(network, `Unknown network: ${f.network}`);
69
70
  const validPrefixes = [network.bech32, network.bech32Opnet].filter(Boolean);
70
71
  assert.ok(
71
72
  validPrefixes.includes(actual.prefix),
@@ -21,6 +21,7 @@ describe('Bitcoin-core', () => {
21
21
  const fb58 = f[1];
22
22
 
23
23
  it('can decode ' + fb58, () => {
24
+ assert(fb58 !== undefined);
24
25
  const buffer = base58.decode(fb58);
25
26
  const actual = toHex(new Uint8Array(buffer));
26
27
 
@@ -28,6 +29,7 @@ describe('Bitcoin-core', () => {
28
29
  });
29
30
 
30
31
  it('can encode ' + fhex, () => {
32
+ assert(fhex !== undefined);
31
33
  const buffer = fromHex(fhex);
32
34
  const actual = base58.encode(buffer);
33
35
 
@@ -78,6 +80,7 @@ describe('Bitcoin-core', () => {
78
80
  const strng = f[0];
79
81
 
80
82
  it('throws on ' + strng, () => {
83
+ assert(strng !== undefined);
81
84
  assert.throws(() => {
82
85
  const address = bitcoin.address.fromBase58Check(strng);
83
86
 
@@ -113,10 +116,12 @@ describe('Bitcoin-core', () => {
113
116
  // const verifyFlags = f[2] // TODO: do we need to test this?
114
117
 
115
118
  it('can decode ' + fhex, () => {
119
+ assert(inputs !== undefined);
116
120
  const transaction = bitcoin.Transaction.fromHex(fhex as string);
117
121
 
118
122
  transaction.ins.forEach((txIn, i) => {
119
- const input = inputs[i];
123
+ const input = (inputs as unknown[][])[i];
124
+ assert(input !== undefined);
120
125
 
121
126
  // reverse because test data is reversed
122
127
  const prevOutHash = reverseCopy(fromHex(input[0] as string));
@@ -196,7 +201,9 @@ describe('Bitcoin-core', () => {
196
201
  if (i === 0) return;
197
202
  if (i % 2 !== 0) return;
198
203
 
199
- const description = sigNoncanonical[i - 1].slice(0, -1);
204
+ const prev = sigNoncanonical[i - 1];
205
+ assert(prev !== undefined);
206
+ const description = prev.slice(0, -1);
200
207
  const buffer = fromHex(hex);
201
208
 
202
209
  it('throws on ' + description, () => {