@btc-vision/bitcoin 6.5.1 → 6.5.3

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 (103) hide show
  1. package/browser/chunks/crypto-0PweVewC.js +2033 -0
  2. package/browser/chunks/{payments-BE4vwHhV.js → payments-CgasufRS.js} +410 -408
  3. package/browser/chunks/psbt-BIwOrKer.js +4096 -0
  4. package/browser/chunks/{script-COWGdiOo.js → script-CROJPzz_.js} +96 -96
  5. package/browser/chunks/{transaction-BiXwH2v4.js → transaction-DchBu35N.js} +158 -147
  6. package/browser/chunks/{utils-BKmkTzNZ.js → utils-CO5kmxe9.js} +225 -223
  7. package/browser/crypto.d.ts +1 -1
  8. package/browser/hooks/HookedSigner.d.ts +1 -1
  9. package/browser/index.d.ts +23 -1
  10. package/browser/index.js +6 -6
  11. package/browser/payments/index.d.ts +2 -2
  12. package/browser/payments/lazy.d.ts +1 -1
  13. package/browser/psbt/bip371.d.ts +5 -1
  14. package/browser/psbt.d.ts +1 -1
  15. package/browser/typeforce.d.ts +38 -0
  16. package/browser/types.d.ts +22 -20
  17. package/build/address.js +2 -2
  18. package/build/bip66.js +2 -2
  19. package/build/block.js +2 -2
  20. package/build/crypto.d.ts +1 -1
  21. package/build/crypto.js +2 -3
  22. package/build/hooks/HookedSigner.d.ts +1 -1
  23. package/build/index.d.ts +23 -1
  24. package/build/payments/bip341.js +1 -1
  25. package/build/payments/index.d.ts +2 -2
  26. package/build/payments/lazy.d.ts +1 -1
  27. package/build/payments/p2op.js +3 -3
  28. package/build/payments/p2pk.js +1 -1
  29. package/build/payments/p2pkh.js +3 -3
  30. package/build/payments/p2sh.js +3 -3
  31. package/build/payments/p2tr.js +9 -5
  32. package/build/payments/p2wpkh.js +3 -3
  33. package/build/payments/p2wsh.js +2 -2
  34. package/build/psbt/bip371.d.ts +5 -1
  35. package/build/psbt/bip371.js +10 -7
  36. package/build/psbt/psbtutils.js +5 -4
  37. package/build/psbt.d.ts +1 -1
  38. package/build/psbt.js +78 -45
  39. package/build/script.js +2 -2
  40. package/build/script_signature.js +7 -7
  41. package/build/transaction.js +22 -10
  42. package/build/tsconfig.tsbuildinfo +1 -0
  43. package/build/types.d.ts +22 -20
  44. package/build/types.js +10 -9
  45. package/package.json +32 -57
  46. package/src/address.ts +2 -2
  47. package/src/bip66.ts +2 -2
  48. package/src/block.ts +8 -5
  49. package/src/crypto.ts +3 -4
  50. package/src/ecc_lib.ts +1 -1
  51. package/src/hooks/HookedSigner.ts +1 -1
  52. package/src/index.ts +34 -12
  53. package/src/payments/bip341.ts +1 -1
  54. package/src/payments/embed.ts +1 -2
  55. package/src/payments/index.ts +4 -4
  56. package/src/payments/lazy.ts +3 -3
  57. package/src/payments/p2op.ts +4 -3
  58. package/src/payments/p2pk.ts +1 -1
  59. package/src/payments/p2pkh.ts +3 -3
  60. package/src/payments/p2sh.ts +13 -5
  61. package/src/payments/p2tr.ts +8 -9
  62. package/src/payments/p2wpkh.ts +3 -3
  63. package/src/payments/p2wsh.ts +4 -4
  64. package/src/psbt/bip371.ts +22 -13
  65. package/src/psbt/psbtutils.ts +8 -5
  66. package/src/psbt.ts +127 -80
  67. package/src/script.ts +4 -4
  68. package/src/script_signature.ts +7 -7
  69. package/src/transaction.ts +31 -18
  70. package/src/typeforce.d.ts +38 -0
  71. package/src/types.ts +34 -29
  72. package/test/address.spec.ts +12 -4
  73. package/test/bitcoin.core.spec.ts +1 -1
  74. package/test/block.spec.ts +1 -1
  75. package/test/bufferutils.spec.ts +1 -1
  76. package/test/crypto.spec.ts +3 -2
  77. package/test/fixtures/address.json +1 -1
  78. package/test/integration/addresses.spec.ts +1 -1
  79. package/test/integration/bip32.spec.ts +2 -2
  80. package/test/integration/blocks.spec.ts +1 -1
  81. package/test/integration/cltv.spec.ts +3 -3
  82. package/test/integration/csv.spec.ts +3 -3
  83. package/test/integration/payments.spec.ts +1 -1
  84. package/test/integration/taproot.spec.ts +8 -7
  85. package/test/integration/transactions.spec.ts +2 -2
  86. package/test/payments.spec.ts +4 -3
  87. package/test/psbt.spec.ts +106 -74
  88. package/test/script.spec.ts +73 -7
  89. package/test/script_number.spec.ts +1 -1
  90. package/test/script_signature.spec.ts +1 -1
  91. package/test/transaction.spec.ts +1 -1
  92. package/test/tsconfig.json +1 -1
  93. package/test/types.spec.ts +1 -1
  94. package/vitest.config.ts +16 -0
  95. package/.babelrc +0 -13
  96. package/.mocharc.json +0 -13
  97. package/browser/chunks/crypto-C6FlKKmp.js +0 -2006
  98. package/browser/chunks/psbt-Dlosf9CT.js +0 -3853
  99. package/cjs/package.json +0 -3
  100. package/gulpfile.js +0 -42
  101. package/src/crypto/crypto-browser.js +0 -75
  102. package/test/ts-node-register.js +0 -7
  103. package/webpack.config.js +0 -79
package/src/psbt.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { Psbt as PsbtBase } from 'bip174';
2
2
  import * as varuint from 'bip174/src/lib/converter/varint.js';
3
+
4
+ interface VaruintDecode {
5
+ (buffer: Buffer, offset?: number): number;
6
+ bytes: number;
7
+ }
8
+ const varuintDecode = varuint.decode as VaruintDecode;
3
9
  import {
4
10
  Bip32Derivation,
5
11
  KeyValue,
@@ -16,7 +22,7 @@ import {
16
22
  TransactionFromBuffer,
17
23
  } from 'bip174/src/lib/interfaces.js';
18
24
  import { checkForInput, checkForOutput } from 'bip174/src/lib/utils.js';
19
- import { BIP32Interface } from 'bip32';
25
+ import { BIP32Interface } from '@btc-vision/bip32';
20
26
  import { ECPairInterface } from 'ecpair';
21
27
  import { fromOutputScript, isUnknownSegwitVersion, toOutputScript } from './address.js';
22
28
  import { cloneBuffer, reverseBuffer } from './bufferutils.js';
@@ -146,8 +152,8 @@ export class Psbt {
146
152
  __NON_WITNESS_UTXO_TX_CACHE: [],
147
153
  __NON_WITNESS_UTXO_BUF_CACHE: [],
148
154
  __TX_IN_CACHE: {},
149
- // @ts-expect-error no.
150
- __TX: this.data.globalMap.unsignedTx.tx, // Now TypeScript knows unsignedTx is a PsbtTransaction
155
+ // unsignedTx.tx property is dynamically added by PsbtBase
156
+ __TX: (this.data.globalMap.unsignedTx as PsbtTransaction).tx,
151
157
  __UNSAFE_SIGN_NONSEGWIT: false,
152
158
  };
153
159
 
@@ -232,7 +238,8 @@ export class Psbt {
232
238
 
233
239
  clone(): Psbt {
234
240
  // TODO: more efficient cloning
235
- return Psbt.fromBuffer(this.data.toBuffer(), JSON.parse(JSON.stringify(this.opts)));
241
+ const clonedOpts = JSON.parse(JSON.stringify(this.opts)) as PsbtOptsOptional;
242
+ return Psbt.fromBuffer(this.data.toBuffer(), clonedOpts);
236
243
  }
237
244
 
238
245
  setMaximumFeeRate(satoshiPerByte: number): void {
@@ -316,11 +323,13 @@ export class Psbt {
316
323
  }
317
324
 
318
325
  addOutput(outputData: PsbtOutputExtended): this {
326
+ const hasAddress = 'address' in outputData;
327
+ const hasScript = 'script' in outputData;
319
328
  if (
320
329
  arguments.length > 1 ||
321
330
  !outputData ||
322
331
  outputData.value === undefined ||
323
- ((outputData as any).address === undefined && (outputData as any).script === undefined)
332
+ (!hasAddress && !hasScript)
324
333
  ) {
325
334
  throw new Error(
326
335
  `Invalid arguments for Psbt.addOutput. ` +
@@ -328,8 +337,8 @@ export class Psbt {
328
337
  );
329
338
  }
330
339
  checkInputsForPartialSig(this.data.inputs, 'addOutput');
331
- const { address } = outputData as any;
332
- if (typeof address === 'string') {
340
+ if (hasAddress) {
341
+ const { address } = outputData as PsbtOutputExtendedAddress;
333
342
  const { network } = this.opts;
334
343
  const script = toOutputScript(address, network);
335
344
  outputData = Object.assign({}, outputData, { script });
@@ -367,17 +376,11 @@ export class Psbt {
367
376
  this.data.inputs,
368
377
  this.__CACHE,
369
378
  disableOutputChecks,
370
- )!;
379
+ );
371
380
  }
372
381
 
373
382
  getFee(disableOutputChecks: boolean = false): number {
374
- return getTxCacheValue(
375
- '__FEE',
376
- 'fee',
377
- this.data.inputs,
378
- this.__CACHE,
379
- disableOutputChecks,
380
- )!;
383
+ return getTxCacheValue('__FEE', 'fee', this.data.inputs, this.__CACHE, disableOutputChecks);
381
384
  }
382
385
 
383
386
  finalizeAllInputs(): this {
@@ -466,7 +469,7 @@ export class Psbt {
466
469
  const results = range(this.data.inputs.length).map((idx) =>
467
470
  this.validateSignaturesOfInput(idx, validator),
468
471
  );
469
- return results.reduce((final, res) => res === true && final, true);
472
+ return results.reduce((final, res) => res && final, true);
470
473
  }
471
474
 
472
475
  validateSignaturesOfInput(
@@ -495,7 +498,7 @@ export class Psbt {
495
498
  results.push(false);
496
499
  }
497
500
  }
498
- if (results.every((v) => v === false)) {
501
+ if (results.every((v) => !v)) {
499
502
  throw new Error('No inputs were signed');
500
503
  }
501
504
  return this;
@@ -505,7 +508,7 @@ export class Psbt {
505
508
  hdKeyPair: HDSigner | HDSignerAsync,
506
509
  sighashTypes: number[] = [Transaction.SIGHASH_ALL],
507
510
  ): Promise<void> {
508
- return new Promise((resolve, reject): any => {
511
+ return new Promise((resolve, reject) => {
509
512
  if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
510
513
  return reject(new Error('Need HDSigner to sign input'));
511
514
  }
@@ -525,7 +528,7 @@ export class Psbt {
525
528
  );
526
529
  }
527
530
  return Promise.all(promises).then(() => {
528
- if (results.every((v) => v === false)) {
531
+ if (results.every((v) => !v)) {
529
532
  return reject(new Error('No inputs were signed'));
530
533
  }
531
534
  resolve();
@@ -551,7 +554,7 @@ export class Psbt {
551
554
  hdKeyPair: HDSigner | HDSignerAsync,
552
555
  sighashTypes: number[] = [Transaction.SIGHASH_ALL],
553
556
  ): Promise<void> {
554
- return new Promise((resolve, reject): any => {
557
+ return new Promise((resolve, reject) => {
555
558
  if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
556
559
  return reject(new Error('Need HDSigner to sign input'));
557
560
  }
@@ -585,7 +588,7 @@ export class Psbt {
585
588
  results.push(false);
586
589
  }
587
590
  }
588
- if (results.every((v) => v === false)) {
591
+ if (results.every((v) => !v)) {
589
592
  throw new Error('No inputs were signed');
590
593
  }
591
594
  return this;
@@ -595,7 +598,7 @@ export class Psbt {
595
598
  keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface,
596
599
  sighashTypes?: number[],
597
600
  ): Promise<void> {
598
- return new Promise((resolve, reject): any => {
601
+ return new Promise((resolve, reject) => {
599
602
  if (!keyPair || !keyPair.publicKey)
600
603
  return reject(new Error('Need Signer to sign input'));
601
604
 
@@ -617,7 +620,7 @@ export class Psbt {
617
620
  );
618
621
  }
619
622
  return Promise.all(promises).then(() => {
620
- if (results.every((v) => v === false)) {
623
+ if (results.every((v) => !v)) {
621
624
  return reject(new Error('No inputs were signed'));
622
625
  }
623
626
  resolve();
@@ -779,11 +782,15 @@ export class Psbt {
779
782
  if (typeof keyPair.signSchnorr !== 'function')
780
783
  throw new Error(`Need Schnorr Signer to sign taproot input #${inputIndex}.`);
781
784
 
785
+ const pubkey = Buffer.isBuffer(keyPair.publicKey)
786
+ ? keyPair.publicKey
787
+ : Buffer.from(keyPair.publicKey);
788
+
782
789
  const hashesForSig = getTaprootHashesForSig(
783
790
  inputIndex,
784
791
  input,
785
792
  this.data.inputs,
786
- keyPair.publicKey,
793
+ pubkey,
787
794
  this.__CACHE,
788
795
  tapLeafHashToSign,
789
796
  allowedSighashTypes,
@@ -791,9 +798,7 @@ export class Psbt {
791
798
 
792
799
  if (!hashesForSig || !hashesForSig.length)
793
800
  throw new Error(
794
- `Can not sign for input #${inputIndex} with the key ${keyPair.publicKey.toString(
795
- 'hex',
796
- )}`,
801
+ `Can not sign for input #${inputIndex} with the key ${pubkey.toString('hex')}`,
797
802
  );
798
803
 
799
804
  return hashesForSig;
@@ -848,7 +853,8 @@ export class Psbt {
848
853
  output: input.witnessUtxo.script,
849
854
  signature: input.tapKeySig,
850
855
  });
851
- const finalScriptWitness = witnessStackToScriptWitness(payment.witness!);
856
+ if (!payment.witness) throw new Error('Cannot finalize taproot key spend');
857
+ const finalScriptWitness = witnessStackToScriptWitness(payment.witness);
852
858
  this.data.updateInput(inputIndex, { finalScriptWitness });
853
859
  } else {
854
860
  const { finalScriptWitness } = finalScriptsFunc(
@@ -878,13 +884,13 @@ export class Psbt {
878
884
  const mySigs = pubkey ? partialSig.filter((sig) => sig.pubkey.equals(pubkey)) : partialSig;
879
885
  if (mySigs.length < 1) throw new Error('No signatures for this pubkey');
880
886
  const results: boolean[] = [];
881
- let hashCache: Buffer;
882
- let scriptCache: Buffer;
883
- let sighashCache: number;
887
+ let hashCache: Buffer | undefined;
888
+ let scriptCache: Buffer | undefined;
889
+ let sighashCache: number | undefined;
884
890
  for (const pSig of mySigs) {
885
891
  const sig = bscript.signature.decode(pSig.signature);
886
892
  const { hash, script } =
887
- sighashCache! !== sig.hashType
893
+ sighashCache !== sig.hashType || !hashCache || !scriptCache
888
894
  ? getHashForSig(
889
895
  inputIndex,
890
896
  Object.assign({}, input, {
@@ -893,14 +899,14 @@ export class Psbt {
893
899
  this.__CACHE,
894
900
  true,
895
901
  )
896
- : { hash: hashCache!, script: scriptCache! };
902
+ : { hash: hashCache, script: scriptCache };
897
903
  sighashCache = sig.hashType;
898
904
  hashCache = hash;
899
905
  scriptCache = script;
900
906
  checkScriptForPubkey(pSig.pubkey, script, 'verify');
901
907
  results.push(validator(pSig.pubkey, hash, sig.signature));
902
908
  }
903
- return results.every((res) => res === true);
909
+ return results.every((res) => res);
904
910
  }
905
911
 
906
912
  private validateSignaturesOfTaprootInput(
@@ -960,18 +966,26 @@ export class Psbt {
960
966
  ): this {
961
967
  //hookSigner(keyPair);
962
968
 
969
+ const pubkey = Buffer.isBuffer(keyPair.publicKey)
970
+ ? keyPair.publicKey
971
+ : Buffer.from(keyPair.publicKey);
972
+
963
973
  const { hash, sighashType } = getHashAndSighashType(
964
974
  this.data.inputs,
965
975
  inputIndex,
966
- keyPair.publicKey,
976
+ pubkey,
967
977
  this.__CACHE,
968
978
  sighashTypes,
969
979
  );
970
980
 
981
+ const sig = keyPair.sign(hash);
971
982
  const partialSig = [
972
983
  {
973
- pubkey: keyPair.publicKey,
974
- signature: bscript.signature.encode(keyPair.sign(hash), sighashType),
984
+ pubkey,
985
+ signature: bscript.signature.encode(
986
+ Buffer.isBuffer(sig) ? sig : Buffer.from(sig),
987
+ sighashType,
988
+ ),
975
989
  },
976
990
  ];
977
991
 
@@ -988,6 +1002,11 @@ export class Psbt {
988
1002
  ): this {
989
1003
  //hookSigner(keyPair);
990
1004
 
1005
+ const pubkey = Buffer.isBuffer(keyPair.publicKey)
1006
+ ? keyPair.publicKey
1007
+ : Buffer.from(keyPair.publicKey);
1008
+
1009
+ // checkTaprootHashesForSig validates signSchnorr exists
991
1010
  const hashesForSig = this.checkTaprootHashesForSig(
992
1011
  inputIndex,
993
1012
  input,
@@ -995,11 +1014,15 @@ export class Psbt {
995
1014
  tapLeafHashToSign,
996
1015
  allowedSighashTypes,
997
1016
  );
1017
+ const signSchnorr = (keyPair.signSchnorr as (h: Buffer) => Uint8Array).bind(keyPair);
1018
+
1019
+ const toBuffer = (data: Uint8Array | Buffer): Buffer =>
1020
+ Buffer.isBuffer(data) ? data : Buffer.from(data);
998
1021
 
999
1022
  const tapKeySig: TapKeySig = hashesForSig
1000
1023
  .filter((h) => !h.leafHash)
1001
1024
  .map((h) =>
1002
- serializeTaprootSignature(keyPair.signSchnorr!(h.hash), input.sighashType),
1025
+ serializeTaprootSignature(toBuffer(signSchnorr(h.hash)), input.sighashType),
1003
1026
  )[0];
1004
1027
 
1005
1028
  const tapScriptSig: TapScriptSig[] = hashesForSig
@@ -1007,9 +1030,9 @@ export class Psbt {
1007
1030
  .map(
1008
1031
  (h) =>
1009
1032
  ({
1010
- pubkey: toXOnly(keyPair.publicKey),
1033
+ pubkey: toXOnly(pubkey),
1011
1034
  signature: serializeTaprootSignature(
1012
- keyPair.signSchnorr!(h.hash),
1035
+ toBuffer(signSchnorr(h.hash)),
1013
1036
  input.sighashType,
1014
1037
  ),
1015
1038
  leafHash: h.leafHash,
@@ -1034,19 +1057,24 @@ export class Psbt {
1034
1057
  ): Promise<void> {
1035
1058
  //hookSigner(keyPair);
1036
1059
 
1060
+ const pubkey = Buffer.isBuffer(keyPair.publicKey)
1061
+ ? keyPair.publicKey
1062
+ : Buffer.from(keyPair.publicKey);
1063
+
1037
1064
  const { hash, sighashType } = getHashAndSighashType(
1038
1065
  this.data.inputs,
1039
1066
  inputIndex,
1040
- keyPair.publicKey,
1067
+ pubkey,
1041
1068
  this.__CACHE,
1042
1069
  sighashTypes,
1043
1070
  );
1044
1071
 
1045
1072
  return Promise.resolve(keyPair.sign(hash)).then((signature) => {
1073
+ const sig = Buffer.isBuffer(signature) ? signature : Buffer.from(signature);
1046
1074
  const partialSig = [
1047
1075
  {
1048
- pubkey: keyPair.publicKey,
1049
- signature: bscript.signature.encode(signature, sighashType),
1076
+ pubkey,
1077
+ signature: bscript.signature.encode(sig, sighashType),
1050
1078
  },
1051
1079
  ];
1052
1080
 
@@ -1063,6 +1091,11 @@ export class Psbt {
1063
1091
  ): Promise<void> {
1064
1092
  //hookSigner(keyPair);
1065
1093
 
1094
+ const pubkey = Buffer.isBuffer(keyPair.publicKey)
1095
+ ? keyPair.publicKey
1096
+ : Buffer.from(keyPair.publicKey);
1097
+
1098
+ // checkTaprootHashesForSig validates signSchnorr exists
1066
1099
  const hashesForSig = this.checkTaprootHashesForSig(
1067
1100
  inputIndex,
1068
1101
  input,
@@ -1070,6 +1103,12 @@ export class Psbt {
1070
1103
  tapLeafHash,
1071
1104
  sighashTypes,
1072
1105
  );
1106
+ const signSchnorr = (
1107
+ keyPair.signSchnorr as (hash: Buffer) => Uint8Array | Promise<Uint8Array>
1108
+ ).bind(keyPair);
1109
+
1110
+ const toBuffer = (data: Uint8Array | Buffer): Buffer =>
1111
+ Buffer.isBuffer(data) ? data : Buffer.from(data);
1073
1112
 
1074
1113
  const signaturePromises: Promise<
1075
1114
  { tapKeySig: Buffer } | { tapScriptSig: TapScriptSig[] }
@@ -1077,25 +1116,26 @@ export class Psbt {
1077
1116
 
1078
1117
  const tapKeyHash = hashesForSig.filter((h) => !h.leafHash)[0];
1079
1118
  if (tapKeyHash) {
1080
- const tapKeySigPromise = Promise.resolve(keyPair.signSchnorr!(tapKeyHash.hash)).then(
1081
- (sig) => {
1082
- return {
1083
- tapKeySig: serializeTaprootSignature(sig, input.sighashType),
1084
- };
1085
- },
1086
- );
1119
+ const tapKeySigPromise = Promise.resolve(signSchnorr(tapKeyHash.hash)).then((sig) => {
1120
+ return {
1121
+ tapKeySig: serializeTaprootSignature(toBuffer(sig), input.sighashType),
1122
+ };
1123
+ });
1087
1124
  signaturePromises.push(tapKeySigPromise);
1088
1125
  }
1089
1126
 
1090
1127
  const tapScriptHashes = hashesForSig.filter((h) => !!h.leafHash);
1091
1128
  if (tapScriptHashes.length) {
1092
1129
  const tapScriptSigPromises = tapScriptHashes.map(async (tsh) => {
1093
- const signature = await keyPair.signSchnorr!(tsh.hash);
1130
+ const signature = await signSchnorr(tsh.hash);
1094
1131
 
1095
1132
  const tapScriptSig = [
1096
1133
  {
1097
- pubkey: toXOnly(keyPair.publicKey),
1098
- signature: serializeTaprootSignature(signature, input.sighashType),
1134
+ pubkey: toXOnly(pubkey),
1135
+ signature: serializeTaprootSignature(
1136
+ toBuffer(signature),
1137
+ input.sighashType,
1138
+ ),
1099
1139
  leafHash: tsh.leafHash,
1100
1140
  } as TapScriptSig,
1101
1141
  ];
@@ -1293,11 +1333,12 @@ function canFinalize(input: PsbtInput, script: Buffer, scriptType: string): bool
1293
1333
  case 'pubkeyhash':
1294
1334
  case 'witnesspubkeyhash':
1295
1335
  return hasSigs(1, input.partialSig);
1296
- case 'multisig':
1336
+ case 'multisig': {
1297
1337
  const p2ms = payments.p2ms({
1298
1338
  output: script,
1299
1339
  });
1300
1340
  return hasSigs(p2ms.m!, input.partialSig, p2ms.pubkeys);
1341
+ }
1301
1342
  case 'nonstandard':
1302
1343
  return true;
1303
1344
  default:
@@ -1306,21 +1347,21 @@ function canFinalize(input: PsbtInput, script: Buffer, scriptType: string): bool
1306
1347
  }
1307
1348
 
1308
1349
  function checkCache(cache: PsbtCache): void {
1309
- if (cache.__UNSAFE_SIGN_NONSEGWIT !== false) {
1350
+ if (cache.__UNSAFE_SIGN_NONSEGWIT) {
1310
1351
  throw new Error('Not BIP174 compliant, can not export');
1311
1352
  }
1312
1353
  }
1313
1354
 
1314
- function hasSigs(neededSigs: number, partialSig?: any[], pubkeys?: Buffer[]): boolean {
1355
+ function hasSigs(neededSigs: number, partialSig?: PartialSig[], pubkeys?: Buffer[]): boolean {
1315
1356
  if (!partialSig) return false;
1316
- let sigs: any;
1357
+ let sigs: PartialSig[];
1317
1358
  if (pubkeys) {
1318
1359
  sigs = pubkeys
1319
1360
  .map((pkey) => {
1320
1361
  const pubkey = compressPubkey(pkey);
1321
1362
  return partialSig.find((pSig) => pSig.pubkey.equals(pubkey));
1322
1363
  })
1323
- .filter((v) => !!v);
1364
+ .filter((v): v is PartialSig => !!v);
1324
1365
  } else {
1325
1366
  sigs = partialSig;
1326
1367
  }
@@ -1334,8 +1375,13 @@ function isFinalized(input: PsbtInput): boolean {
1334
1375
 
1335
1376
  function bip32DerivationIsMine(root: HDSigner): (d: Bip32Derivation) => boolean {
1336
1377
  return (d: Bip32Derivation): boolean => {
1337
- if (!d.masterFingerprint.equals(root.fingerprint)) return false;
1338
- if (!root.derivePath(d.path).publicKey.equals(d.pubkey)) return false;
1378
+ const fingerprint = Buffer.isBuffer(root.fingerprint)
1379
+ ? root.fingerprint
1380
+ : Buffer.from(root.fingerprint);
1381
+ if (!d.masterFingerprint.equals(fingerprint)) return false;
1382
+ const derivedPubkey = root.derivePath(d.path).publicKey;
1383
+ const pubkey = Buffer.isBuffer(derivedPubkey) ? derivedPubkey : Buffer.from(derivedPubkey);
1384
+ if (!pubkey.equals(d.pubkey)) return false;
1339
1385
  return true;
1340
1386
  };
1341
1387
  }
@@ -1407,7 +1453,7 @@ function checkTxForDupeIns(tx: Transaction, cache: PsbtCache): void {
1407
1453
  }
1408
1454
 
1409
1455
  function checkTxInputCache(cache: PsbtCache, input: { hash: Buffer; index: number }): void {
1410
- const key = reverseBuffer(Buffer.from(input.hash)).toString('hex') + ':' + input.index;
1456
+ const key = `${reverseBuffer(Buffer.from(input.hash)).toString('hex')}:${input.index}`;
1411
1457
  if (cache.__TX_IN_CACHE[key]) throw new Error('Duplicate input detected.');
1412
1458
  cache.__TX_IN_CACHE[key] = 1;
1413
1459
  }
@@ -1445,7 +1491,7 @@ function getTxCacheValue(
1445
1491
  inputs: PsbtInput[],
1446
1492
  c: PsbtCache,
1447
1493
  disableOutputChecks: boolean = false,
1448
- ): number | undefined {
1494
+ ): number {
1449
1495
  if (!inputs.every(isFinalized)) throw new Error(`PSBT must be finalized to calculate ${name}`);
1450
1496
  if (key === '__FEE_RATE' && c.__FEE_RATE) return c.__FEE_RATE;
1451
1497
  if (key === '__FEE' && c.__FEE) return c.__FEE;
@@ -1458,8 +1504,9 @@ function getTxCacheValue(
1458
1504
  tx = c.__TX.clone();
1459
1505
  }
1460
1506
  inputFinalizeGetAmts(inputs, tx, c, mustFinalize, disableOutputChecks);
1461
- if (key === '__FEE_RATE') return c.__FEE_RATE!;
1462
- else if (key === '__FEE') return c.__FEE!;
1507
+ const value = key === '__FEE_RATE' ? c.__FEE_RATE : c.__FEE;
1508
+ if (value === undefined) throw new Error(`Failed to calculate ${name}`);
1509
+ return value;
1463
1510
  }
1464
1511
 
1465
1512
  /**
@@ -1625,7 +1672,7 @@ function getHashForSig(
1625
1672
  }
1626
1673
 
1627
1674
  const prevoutIndex = unsignedTx.ins[inputIndex].index;
1628
- prevout = nonWitnessUtxoTx.outs[prevoutIndex] as Output;
1675
+ prevout = nonWitnessUtxoTx.outs[prevoutIndex];
1629
1676
  } else if (input.witnessUtxo) {
1630
1677
  prevout = input.witnessUtxo;
1631
1678
  } else {
@@ -1650,17 +1697,17 @@ function getHashForSig(
1650
1697
  } else if (isP2WPKH(meaningfulScript)) {
1651
1698
  // P2WPKH uses the P2PKH template for prevoutScript when signing
1652
1699
  const signingScript = payments.p2pkh({
1653
- hash: meaningfulScript.slice(2),
1700
+ hash: meaningfulScript.subarray(2),
1654
1701
  }).output!;
1655
1702
  hash = unsignedTx.hashForWitnessV0(inputIndex, signingScript, prevout.value, sighashType);
1656
1703
  } else {
1657
1704
  // non-segwit
1658
- if (input.nonWitnessUtxo === undefined && cache.__UNSAFE_SIGN_NONSEGWIT === false)
1705
+ if (input.nonWitnessUtxo === undefined && !cache.__UNSAFE_SIGN_NONSEGWIT)
1659
1706
  throw new Error(
1660
1707
  `Input #${inputIndex} has witnessUtxo but non-segwit script: ` +
1661
- `${meaningfulScript.toString('hex')}`,
1708
+ meaningfulScript.toString('hex'),
1662
1709
  );
1663
- if (!forValidate && cache.__UNSAFE_SIGN_NONSEGWIT !== false)
1710
+ if (!forValidate && cache.__UNSAFE_SIGN_NONSEGWIT)
1664
1711
  console.warn(
1665
1712
  'Warning: Signing non-segwit inputs without the full parent transaction ' +
1666
1713
  'means there is a chance that a miner could feed you incorrect information ' +
@@ -1905,8 +1952,8 @@ function getSignersFromHD(
1905
1952
  }
1906
1953
 
1907
1954
  return myDerivations.map((bipDv) => {
1908
- const node = hdKeyPair.derivePath(bipDv!.path);
1909
- if (!bipDv!.pubkey.equals(node.publicKey)) {
1955
+ const node = hdKeyPair.derivePath(bipDv.path);
1956
+ if (!bipDv.pubkey.equals(node.publicKey)) {
1910
1957
  throw new Error('pubkey did not match bip32Derivation');
1911
1958
  }
1912
1959
  return node;
@@ -1935,12 +1982,12 @@ function scriptWitnessToWitnessStack(buffer: Buffer): Buffer[] {
1935
1982
 
1936
1983
  function readSlice(n: number): Buffer {
1937
1984
  offset += n;
1938
- return buffer.slice(offset - n, offset);
1985
+ return buffer.subarray(offset - n, offset);
1939
1986
  }
1940
1987
 
1941
1988
  function readVarInt(): number {
1942
- const vi = varuint.decode(buffer, offset);
1943
- offset += (varuint.decode as any).bytes;
1989
+ const vi = varuintDecode(buffer, offset);
1990
+ offset += varuintDecode.bytes;
1944
1991
  return vi;
1945
1992
  }
1946
1993
 
@@ -2019,11 +2066,11 @@ function inputFinalizeGetAmts(
2019
2066
  } else if (input.nonWitnessUtxo) {
2020
2067
  const nwTx = nonWitnessUtxoTxFromCache(cache, input, idx);
2021
2068
  const vout = tx.ins[idx].index;
2022
- const out = nwTx.outs[vout] as Output;
2069
+ const out = nwTx.outs[vout];
2023
2070
  inputAmount += out.value;
2024
2071
  }
2025
2072
  });
2026
- const outputAmount = (tx.outs as Output[]).reduce((total, o) => total + o.value, 0);
2073
+ const outputAmount = tx.outs.reduce((total, o) => total + o.value, 0);
2027
2074
  const fee = inputAmount - outputAmount;
2028
2075
  if (!disableOutputChecks) {
2029
2076
  if (fee < 0) {
@@ -2132,11 +2179,11 @@ function redeemFromFinalWitnessScript(finalScript: Buffer | undefined): Buffer |
2132
2179
  function compressPubkey(pubkey: Buffer): Buffer {
2133
2180
  if (pubkey.length === 65) {
2134
2181
  const parity = pubkey[64] & 1;
2135
- const newKey = pubkey.slice(0, 33);
2182
+ const newKey = Buffer.from(pubkey.subarray(0, 33));
2136
2183
  newKey[0] = 2 | parity;
2137
2184
  return newKey;
2138
2185
  }
2139
- return pubkey.slice();
2186
+ return Buffer.from(pubkey);
2140
2187
  }
2141
2188
 
2142
2189
  function isPubkeyLike(buf: Buffer): boolean {
@@ -2170,8 +2217,8 @@ function getMeaningfulScript(
2170
2217
 
2171
2218
  if (isP2SHP2WSH) {
2172
2219
  meaningfulScript = witnessScript!;
2173
- checkRedeemScript(index, script, redeemScript!, ioType);
2174
- checkWitnessScript(index, redeemScript!, witnessScript!, ioType);
2220
+ checkRedeemScript(index, script, redeemScript, ioType);
2221
+ checkWitnessScript(index, redeemScript, witnessScript!, ioType);
2175
2222
  checkInvalidP2WSH(meaningfulScript);
2176
2223
  } else if (isP2WSH) {
2177
2224
  meaningfulScript = witnessScript!;
package/src/script.ts CHANGED
@@ -36,7 +36,7 @@ export function countNonPushOnlyOPs(value: Stack): number {
36
36
  return value.length - value.filter(isPushOnlyChunk).length;
37
37
  }
38
38
 
39
- function asMinimalOP(buffer: Buffer): number | void {
39
+ function asMinimalOP(buffer: Buffer): number | undefined {
40
40
  if (buffer.length === 0) return opcodes.OP_0;
41
41
  if (buffer.length !== 1) return;
42
42
  if (buffer[0] >= 1 && buffer[0] <= 16) return OP_INT_BASE + buffer[0];
@@ -135,7 +135,7 @@ export function decompile(buffer: Buffer | Array<number | Buffer>): Array<number
135
135
  // attempt to read too much data?
136
136
  if (i + d.number > buffer.length) return null;
137
137
 
138
- const data = buffer.slice(i, i + d.number);
138
+ const data = buffer.subarray(i, i + d.number);
139
139
  i += d.number;
140
140
 
141
141
  // decompile minimally
@@ -176,7 +176,7 @@ export function toASM(chunks: Buffer | Array<number | Buffer>): string {
176
176
  if (singleChunkIsBuffer(chunk)) {
177
177
  const op = asMinimalOP(chunk);
178
178
  if (op === undefined) return chunk.toString('hex');
179
- chunk = op as number;
179
+ chunk = op;
180
180
  }
181
181
 
182
182
  // opcode!
@@ -240,7 +240,7 @@ export function isCanonicalScriptSignature(buffer: Buffer): boolean {
240
240
  if (!Buffer.isBuffer(buffer)) return false;
241
241
  if (!isDefinedHashType(buffer[buffer.length - 1])) return false;
242
242
 
243
- return bip66.check(buffer.slice(0, -1));
243
+ return bip66.check(buffer.subarray(0, -1));
244
244
  }
245
245
 
246
246
  export const number = scriptNumber;
@@ -15,7 +15,7 @@ function toDER(x: Buffer): Buffer {
15
15
  let i = 0;
16
16
  while (x[i] === 0) ++i;
17
17
  if (i === x.length) return ZERO;
18
- x = x.slice(i);
18
+ x = x.subarray(i);
19
19
  if (x[0] & 0x80) return Buffer.concat([ZERO, x], 1 + x.length);
20
20
  return x;
21
21
  }
@@ -28,7 +28,7 @@ function toDER(x: Buffer): Buffer {
28
28
  * @returns The converted buffer.
29
29
  */
30
30
  function fromDER(x: Buffer): Buffer {
31
- if (x[0] === 0x00) x = x.slice(1);
31
+ if (x[0] === 0x00) x = x.subarray(1);
32
32
  const buffer = Buffer.alloc(32, 0);
33
33
  const bstart = Math.max(0, 32 - x.length);
34
34
  x.copy(buffer, bstart);
@@ -50,10 +50,10 @@ interface ScriptSignature {
50
50
  export function decode(buffer: Buffer): ScriptSignature {
51
51
  const hashType = buffer.readUInt8(buffer.length - 1);
52
52
  if (!isDefinedHashType(hashType)) {
53
- throw new Error('Invalid hashType ' + hashType);
53
+ throw new Error(`Invalid hashType ${hashType}`);
54
54
  }
55
55
 
56
- const decoded = bip66.decode(buffer.slice(0, -1));
56
+ const decoded = bip66.decode(buffer.subarray(0, -1));
57
57
  const r = fromDER(decoded.r);
58
58
  const s = fromDER(decoded.s);
59
59
  const signature = Buffer.concat([r, s], 64);
@@ -78,14 +78,14 @@ export function encode(signature: Buffer, hashType: number): Buffer {
78
78
  );
79
79
 
80
80
  if (!isDefinedHashType(hashType)) {
81
- throw new Error('Invalid hashType ' + hashType);
81
+ throw new Error(`Invalid hashType ${hashType}`);
82
82
  }
83
83
 
84
84
  const hashTypeBuffer = Buffer.allocUnsafe(1);
85
85
  hashTypeBuffer.writeUInt8(hashType, 0);
86
86
 
87
- const r = toDER(signature.slice(0, 32));
88
- const s = toDER(signature.slice(32, 64));
87
+ const r = toDER(signature.subarray(0, 32));
88
+ const s = toDER(signature.subarray(32, 64));
89
89
 
90
90
  return Buffer.concat([bip66.encode(r, s), hashTypeBuffer]);
91
91
  }