@btc-vision/bitcoin 6.3.1 → 6.3.2

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 (259) hide show
  1. package/.babelrc +4 -0
  2. package/.gitattributes +2 -0
  3. package/.nyc_output/6368a5b2-daa5-4821-8ed0-b742d6fc7eab.json +1 -0
  4. package/.nyc_output/processinfo/6368a5b2-daa5-4821-8ed0-b742d6fc7eab.json +1 -0
  5. package/.nyc_output/processinfo/index.json +1 -0
  6. package/.prettierrc.json +12 -0
  7. package/CHANGELOG.md +403 -0
  8. package/CONTRIBUTING.md +83 -0
  9. package/browser/address.d.ts +16 -0
  10. package/{src → browser}/bip66.d.ts +6 -7
  11. package/{src → browser}/block.d.ts +29 -30
  12. package/{src → browser}/bufferutils.d.ts +34 -54
  13. package/browser/crypto/crypto.d.ts +1 -0
  14. package/{src → browser}/crypto.d.ts +13 -18
  15. package/browser/ecc_lib.d.ts +3 -0
  16. package/browser/hooks/AdvancedSignatureManager.d.ts +16 -0
  17. package/{src → browser}/hooks/HookedSigner.d.ts +4 -4
  18. package/browser/hooks/SignatureManager.d.ts +13 -0
  19. package/browser/index.d.ts +58 -0
  20. package/browser/index.js +2 -0
  21. package/browser/index.js.LICENSE.txt +14 -0
  22. package/browser/merkle.d.ts +1 -0
  23. package/browser/networks.d.ts +23 -0
  24. package/{src → browser}/ops.d.ts +126 -126
  25. package/browser/payments/bip341.d.ts +23 -0
  26. package/browser/payments/embed.d.ts +2 -0
  27. package/browser/payments/index.d.ts +41 -0
  28. package/{src → browser}/payments/lazy.d.ts +2 -2
  29. package/browser/payments/p2ms.d.ts +2 -0
  30. package/browser/payments/p2pk.d.ts +2 -0
  31. package/browser/payments/p2pkh.d.ts +2 -0
  32. package/browser/payments/p2sh.d.ts +2 -0
  33. package/browser/payments/p2tr.d.ts +2 -0
  34. package/browser/payments/p2wpkh.d.ts +2 -0
  35. package/browser/payments/p2wsh.d.ts +2 -0
  36. package/browser/psbt/bip371.d.ts +16 -0
  37. package/browser/psbt/psbtutils.d.ts +26 -0
  38. package/{src → browser}/psbt.d.ts +167 -238
  39. package/browser/push_data.d.ts +7 -0
  40. package/browser/script.d.ts +17 -0
  41. package/browser/script_number.d.ts +2 -0
  42. package/browser/script_signature.d.ts +7 -0
  43. package/{src → browser}/transaction.d.ts +48 -60
  44. package/{src → browser}/types.d.ts +37 -54
  45. package/build/address.d.ts +16 -0
  46. package/build/address.js +148 -0
  47. package/build/bip66.d.ts +6 -0
  48. package/build/bip66.js +99 -0
  49. package/build/block.d.ts +29 -0
  50. package/build/block.js +181 -0
  51. package/build/bufferutils.d.ts +34 -0
  52. package/build/bufferutils.js +141 -0
  53. package/build/crypto/crypto.d.ts +1 -0
  54. package/build/crypto/crypto.js +1 -0
  55. package/build/crypto.d.ts +13 -0
  56. package/build/crypto.js +87 -0
  57. package/build/ecc_lib.d.ts +3 -0
  58. package/build/ecc_lib.js +61 -0
  59. package/build/hooks/AdvancedSignatureManager.d.ts +16 -0
  60. package/build/hooks/AdvancedSignatureManager.js +52 -0
  61. package/build/hooks/HookedSigner.d.ts +4 -0
  62. package/build/hooks/HookedSigner.js +64 -0
  63. package/build/hooks/SignatureManager.d.ts +13 -0
  64. package/build/hooks/SignatureManager.js +45 -0
  65. package/build/index.d.ts +58 -0
  66. package/build/index.js +32 -0
  67. package/build/merkle.d.ts +1 -0
  68. package/build/merkle.js +19 -0
  69. package/build/networks.d.ts +23 -0
  70. package/build/networks.js +121 -0
  71. package/build/ops.d.ts +126 -0
  72. package/{src → build}/ops.js +127 -131
  73. package/build/payments/bip341.d.ts +23 -0
  74. package/build/payments/bip341.js +82 -0
  75. package/build/payments/embed.d.ts +2 -0
  76. package/build/payments/embed.js +39 -0
  77. package/build/payments/index.d.ts +41 -0
  78. package/build/payments/index.js +10 -0
  79. package/build/payments/lazy.d.ts +2 -0
  80. package/{src → build}/payments/lazy.js +28 -32
  81. package/build/payments/p2ms.d.ts +2 -0
  82. package/{src → build}/payments/p2ms.js +128 -158
  83. package/build/payments/p2pk.d.ts +2 -0
  84. package/build/payments/p2pk.js +68 -0
  85. package/build/payments/p2pkh.d.ts +2 -0
  86. package/build/payments/p2pkh.js +135 -0
  87. package/build/payments/p2sh.d.ts +2 -0
  88. package/build/payments/p2sh.js +175 -0
  89. package/build/payments/p2tr.d.ts +2 -0
  90. package/build/payments/p2tr.js +254 -0
  91. package/build/payments/p2wpkh.d.ts +2 -0
  92. package/build/payments/p2wpkh.js +130 -0
  93. package/build/payments/p2wsh.d.ts +2 -0
  94. package/build/payments/p2wsh.js +180 -0
  95. package/build/psbt/bip371.d.ts +16 -0
  96. package/build/psbt/bip371.js +246 -0
  97. package/build/psbt/psbtutils.d.ts +26 -0
  98. package/build/psbt/psbtutils.js +170 -0
  99. package/build/psbt.d.ts +167 -0
  100. package/build/psbt.js +1305 -0
  101. package/build/push_data.d.ts +7 -0
  102. package/build/push_data.js +57 -0
  103. package/build/script.d.ts +17 -0
  104. package/build/script.js +167 -0
  105. package/build/script_number.d.ts +2 -0
  106. package/build/script_number.js +49 -0
  107. package/build/script_signature.d.ts +7 -0
  108. package/build/script_signature.js +49 -0
  109. package/build/transaction.d.ts +48 -0
  110. package/build/transaction.js +445 -0
  111. package/build/types.d.ts +37 -0
  112. package/build/types.js +73 -0
  113. package/cjs/package.json +3 -0
  114. package/eslint.config.js +56 -0
  115. package/gulpfile.js +42 -0
  116. package/package.json +105 -50
  117. package/src/{address.js → address.ts} +93 -73
  118. package/src/{bip66.js → bip66.ts} +23 -19
  119. package/src/{block.js → block.ts} +114 -105
  120. package/src/{bufferutils.js → bufferutils.ts} +65 -67
  121. package/src/crypto/crypto-browser.js +75 -0
  122. package/src/crypto/crypto.ts +1 -0
  123. package/src/crypto.ts +108 -0
  124. package/src/{ecc_lib.js → ecc_lib.ts} +25 -53
  125. package/src/hooks/{AdvancedSignatureManager.js → AdvancedSignatureManager.ts} +34 -18
  126. package/src/hooks/HookedSigner.ts +108 -0
  127. package/src/hooks/{SignatureManager.js → SignatureManager.ts} +26 -14
  128. package/src/index.ts +86 -0
  129. package/src/{merkle.js → merkle.ts} +8 -7
  130. package/src/{networks.js → networks.ts} +44 -29
  131. package/src/ops.ts +282 -0
  132. package/src/payments/bip341.ts +140 -0
  133. package/src/payments/embed.ts +55 -0
  134. package/src/payments/{index.d.ts → index.ts} +20 -10
  135. package/src/payments/lazy.ts +28 -0
  136. package/src/payments/p2ms.ts +150 -0
  137. package/src/payments/{p2pk.js → p2pk.ts} +32 -29
  138. package/src/payments/{p2pkh.js → p2pkh.ts} +53 -47
  139. package/src/payments/{p2sh.js → p2sh.ts} +72 -71
  140. package/src/payments/{p2tr.js → p2tr.ts} +114 -125
  141. package/src/payments/{p2wpkh.js → p2wpkh.ts} +51 -56
  142. package/src/payments/{p2wsh.js → p2wsh.ts} +69 -81
  143. package/src/psbt/{bip371.js → bip371.ts} +191 -174
  144. package/src/psbt/psbtutils.ts +299 -0
  145. package/src/{psbt.js → psbt.ts} +1025 -679
  146. package/src/{push_data.js → push_data.ts} +35 -21
  147. package/src/{script.js → script.ts} +93 -77
  148. package/src/{script_number.js → script_number.ts} +15 -21
  149. package/src/{script_signature.js → script_signature.ts} +26 -14
  150. package/src/{transaction.js → transaction.ts} +247 -167
  151. package/src/types.ts +122 -0
  152. package/test/address.spec.js +124 -0
  153. package/test/address.spec.ts +177 -0
  154. package/test/bitcoin.core.spec.js +170 -0
  155. package/test/bitcoin.core.spec.ts +234 -0
  156. package/test/block.spec.js +141 -0
  157. package/test/block.spec.ts +194 -0
  158. package/test/bufferutils.spec.js +427 -0
  159. package/test/bufferutils.spec.ts +513 -0
  160. package/test/crypto.spec.js +41 -0
  161. package/test/crypto.spec.ts +55 -0
  162. package/test/fixtures/address.json +329 -0
  163. package/test/fixtures/block.json +148 -0
  164. package/test/fixtures/bufferutils.json +102 -0
  165. package/test/fixtures/core/README.md +26 -0
  166. package/test/fixtures/core/base58_encode_decode.json +50 -0
  167. package/test/fixtures/core/base58_keys_invalid.json +152 -0
  168. package/test/fixtures/core/base58_keys_valid.json +452 -0
  169. package/test/fixtures/core/blocks.json +27 -0
  170. package/test/fixtures/core/sig_canonical.json +7 -0
  171. package/test/fixtures/core/sig_noncanonical.json +33 -0
  172. package/test/fixtures/core/sighash.json +3505 -0
  173. package/test/fixtures/core/tx_valid.json +2023 -0
  174. package/test/fixtures/crypto.json +43 -0
  175. package/test/fixtures/ecdsa.json +217 -0
  176. package/test/fixtures/ecpair.json +141 -0
  177. package/test/fixtures/embed.json +108 -0
  178. package/test/fixtures/p2ms.json +434 -0
  179. package/test/fixtures/p2pk.json +179 -0
  180. package/test/fixtures/p2pkh.json +276 -0
  181. package/test/fixtures/p2sh.json +508 -0
  182. package/test/fixtures/p2tr.json +1198 -0
  183. package/test/fixtures/p2wpkh.json +290 -0
  184. package/test/fixtures/p2wsh.json +489 -0
  185. package/test/fixtures/psbt.json +924 -0
  186. package/test/fixtures/script.json +465 -0
  187. package/test/fixtures/script_number.json +225 -0
  188. package/test/fixtures/signature.json +140 -0
  189. package/test/fixtures/transaction.json +916 -0
  190. package/test/integration/_regtest.js +7 -0
  191. package/test/integration/_regtest.ts +6 -0
  192. package/test/integration/addresses.spec.js +116 -0
  193. package/test/integration/addresses.spec.ts +154 -0
  194. package/test/integration/bip32.spec.js +85 -0
  195. package/test/integration/bip32.spec.ts +151 -0
  196. package/test/integration/blocks.spec.js +26 -0
  197. package/test/integration/blocks.spec.ts +28 -0
  198. package/test/integration/cltv.spec.js +199 -0
  199. package/test/integration/cltv.spec.ts +283 -0
  200. package/test/integration/csv.spec.js +362 -0
  201. package/test/integration/csv.spec.ts +527 -0
  202. package/test/integration/payments.spec.js +98 -0
  203. package/test/integration/payments.spec.ts +135 -0
  204. package/test/integration/taproot.spec.js +532 -0
  205. package/test/integration/taproot.spec.ts +707 -0
  206. package/test/integration/transactions.spec.js +561 -0
  207. package/test/integration/transactions.spec.ts +769 -0
  208. package/test/payments.spec.js +97 -0
  209. package/test/payments.spec.ts +125 -0
  210. package/test/payments.utils.js +190 -0
  211. package/test/payments.utils.ts +208 -0
  212. package/test/psbt.spec.js +1044 -0
  213. package/test/psbt.spec.ts +1414 -0
  214. package/test/script.spec.js +151 -0
  215. package/test/script.spec.ts +210 -0
  216. package/test/script_number.spec.js +24 -0
  217. package/test/script_number.spec.ts +29 -0
  218. package/test/script_signature.spec.js +52 -0
  219. package/test/script_signature.spec.ts +66 -0
  220. package/test/transaction.spec.js +269 -0
  221. package/test/transaction.spec.ts +387 -0
  222. package/test/ts-node-register.js +5 -0
  223. package/test/tsconfig.json +45 -0
  224. package/test/types.spec.js +46 -0
  225. package/test/types.spec.ts +58 -0
  226. package/tsconfig.base.json +27 -0
  227. package/tsconfig.json +19 -0
  228. package/tsconfig.webpack.json +18 -0
  229. package/webpack.config.js +79 -0
  230. package/src/address.d.ts +0 -42
  231. package/src/crypto.js +0 -128
  232. package/src/ecc_lib.d.ts +0 -17
  233. package/src/hooks/AdvancedSignatureManager.d.ts +0 -44
  234. package/src/hooks/HookedSigner.js +0 -90
  235. package/src/hooks/SignatureManager.d.ts +0 -35
  236. package/src/index.d.ts +0 -42
  237. package/src/index.js +0 -87
  238. package/src/merkle.d.ts +0 -10
  239. package/src/networks.d.ts +0 -83
  240. package/src/payments/bip341.d.ts +0 -49
  241. package/src/payments/bip341.js +0 -124
  242. package/src/payments/embed.d.ts +0 -9
  243. package/src/payments/embed.js +0 -54
  244. package/src/payments/index.js +0 -69
  245. package/src/payments/p2ms.d.ts +0 -9
  246. package/src/payments/p2pk.d.ts +0 -10
  247. package/src/payments/p2pkh.d.ts +0 -10
  248. package/src/payments/p2sh.d.ts +0 -10
  249. package/src/payments/p2tr.d.ts +0 -10
  250. package/src/payments/p2wpkh.d.ts +0 -10
  251. package/src/payments/p2wsh.d.ts +0 -10
  252. package/src/psbt/bip371.d.ts +0 -42
  253. package/src/psbt/psbtutils.d.ts +0 -64
  254. package/src/psbt/psbtutils.js +0 -191
  255. package/src/push_data.d.ts +0 -29
  256. package/src/script.d.ts +0 -42
  257. package/src/script_number.d.ts +0 -19
  258. package/src/script_signature.d.ts +0 -21
  259. package/src/types.js +0 -106
@@ -1,25 +1,37 @@
1
- 'use strict';
2
- Object.defineProperty(exports, '__esModule', { value: true });
3
- exports.getTapKeySigFromWitness =
4
- exports.checkTaprootInputForSigs =
5
- exports.tapTreeFromList =
6
- exports.tapTreeToList =
7
- exports.tweakInternalPubKey =
8
- exports.checkTaprootOutputFields =
9
- exports.checkTaprootInputFields =
10
- exports.isTaprootOutput =
11
- exports.isTaprootInput =
12
- exports.serializeTaprootSignature =
13
- exports.tapScriptFinalizer =
14
- exports.toXOnly =
15
- void 0;
16
- const types_1 = require('../types');
17
- const transaction_1 = require('../transaction');
18
- const psbtutils_1 = require('./psbtutils');
19
- const bip341_1 = require('../payments/bip341');
20
- const payments_1 = require('../payments');
21
- const toXOnly = pubKey => (pubKey.length === 32 ? pubKey : pubKey.slice(1, 33));
22
- exports.toXOnly = toXOnly;
1
+ import {
2
+ PsbtInput,
3
+ PsbtOutput,
4
+ TapInternalKey,
5
+ TapLeaf,
6
+ TapLeafScript,
7
+ TapScriptSig,
8
+ TapTree,
9
+ } from 'bip174/src/lib/interfaces.js';
10
+ import { isTapleaf, isTaptree, Tapleaf, Taptree } from '../types.js';
11
+
12
+ import { Transaction } from '../transaction.js';
13
+
14
+ import {
15
+ LEAF_VERSION_TAPSCRIPT,
16
+ MAX_TAPTREE_DEPTH,
17
+ rootHashFromPath,
18
+ tapleafHash,
19
+ tweakKey,
20
+ } from '../payments/bip341.js';
21
+ import { p2tr } from '../payments/p2tr.js';
22
+ import {
23
+ isP2TR,
24
+ pubkeyPositionInScript,
25
+ signatureBlocksAction,
26
+ witnessStackToScriptWitness,
27
+ } from './psbtutils.js';
28
+
29
+ export const toXOnly = (pubKey: Buffer | Uint8Array): Buffer => {
30
+ const buffer = pubKey.length === 32 ? pubKey : pubKey.slice(1, 33);
31
+
32
+ return Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
33
+ };
34
+
23
35
  /**
24
36
  * Default tapscript finalizer. It searches for the `tapLeafHashToFinalize` if provided.
25
37
  * Otherwise it will search for the tapleaf that has at least one signature and has the shortest path.
@@ -29,37 +41,31 @@ exports.toXOnly = toXOnly;
29
41
  * and will try to build the finalScriptWitness.
30
42
  * @returns the finalScriptWitness or throws an exception if no tapleaf found.
31
43
  */
32
- function tapScriptFinalizer(inputIndex, input, tapLeafHashToFinalize) {
33
- const tapLeaf = findTapLeafToFinalize(
34
- input,
35
- inputIndex,
36
- tapLeafHashToFinalize,
37
- );
44
+ export function tapScriptFinalizer(
45
+ inputIndex: number,
46
+ input: PsbtInput,
47
+ tapLeafHashToFinalize?: Buffer,
48
+ ): {
49
+ finalScriptWitness: Buffer | undefined;
50
+ } {
51
+ const tapLeaf = findTapLeafToFinalize(input, inputIndex, tapLeafHashToFinalize);
52
+
38
53
  try {
39
54
  const sigs = sortSignatures(input, tapLeaf);
40
- const witness = sigs
41
- .concat(tapLeaf.script)
42
- .concat(tapLeaf.controlBlock);
43
- return {
44
- finalScriptWitness: (0, psbtutils_1.witnessStackToScriptWitness)(
45
- witness,
46
- ),
47
- };
55
+ const witness = sigs.concat(tapLeaf.script).concat(tapLeaf.controlBlock);
56
+ return { finalScriptWitness: witnessStackToScriptWitness(witness) };
48
57
  } catch (err) {
49
- throw new Error(
50
- `Can not finalize taproot input #${inputIndex}: ${err}`,
51
- );
58
+ throw new Error(`Can not finalize taproot input #${inputIndex}: ${err}`);
52
59
  }
53
60
  }
54
- exports.tapScriptFinalizer = tapScriptFinalizer;
55
- function serializeTaprootSignature(sig, sighashType) {
56
- const sighashTypeByte = sighashType
57
- ? Buffer.from([sighashType])
58
- : Buffer.from([]);
61
+
62
+ export function serializeTaprootSignature(sig: Buffer, sighashType?: number): Buffer {
63
+ const sighashTypeByte = sighashType ? Buffer.from([sighashType!]) : Buffer.from([]);
64
+
59
65
  return Buffer.concat([sig, sighashTypeByte]);
60
66
  }
61
- exports.serializeTaprootSignature = serializeTaprootSignature;
62
- function isTaprootInput(input) {
67
+
68
+ export function isTaprootInput(input: PsbtInput): boolean {
63
69
  return (
64
70
  input &&
65
71
  !!(
@@ -67,65 +73,68 @@ function isTaprootInput(input) {
67
73
  input.tapMerkleRoot ||
68
74
  (input.tapLeafScript && input.tapLeafScript.length) ||
69
75
  (input.tapBip32Derivation && input.tapBip32Derivation.length) ||
70
- (input.witnessUtxo &&
71
- (0, psbtutils_1.isP2TR)(input.witnessUtxo.script))
76
+ (input.witnessUtxo && isP2TR(input.witnessUtxo.script))
72
77
  )
73
78
  );
74
79
  }
75
- exports.isTaprootInput = isTaprootInput;
76
- function isTaprootOutput(output, script) {
80
+
81
+ export function isTaprootOutput(output: PsbtOutput, script?: Buffer): boolean {
77
82
  return (
78
83
  output &&
79
84
  !!(
80
85
  output.tapInternalKey ||
81
86
  output.tapTree ||
82
87
  (output.tapBip32Derivation && output.tapBip32Derivation.length) ||
83
- (script && (0, psbtutils_1.isP2TR)(script))
88
+ (script && isP2TR(script))
84
89
  )
85
90
  );
86
91
  }
87
- exports.isTaprootOutput = isTaprootOutput;
88
- function checkTaprootInputFields(inputData, newInputData, action) {
92
+
93
+ export function checkTaprootInputFields(
94
+ inputData: PsbtInput,
95
+ newInputData: PsbtInput,
96
+ action: string,
97
+ ): void {
89
98
  checkMixedTaprootAndNonTaprootInputFields(inputData, newInputData, action);
90
99
  checkIfTapLeafInTree(inputData, newInputData, action);
91
100
  }
92
- exports.checkTaprootInputFields = checkTaprootInputFields;
93
- function checkTaprootOutputFields(outputData, newOutputData, action) {
94
- checkMixedTaprootAndNonTaprootOutputFields(
95
- outputData,
96
- newOutputData,
97
- action,
98
- );
101
+
102
+ export function checkTaprootOutputFields(
103
+ outputData: PsbtOutput,
104
+ newOutputData: PsbtOutput,
105
+ action: string,
106
+ ): void {
107
+ checkMixedTaprootAndNonTaprootOutputFields(outputData, newOutputData, action);
99
108
  checkTaprootScriptPubkey(outputData, newOutputData);
100
109
  }
101
- exports.checkTaprootOutputFields = checkTaprootOutputFields;
102
- function checkTaprootScriptPubkey(outputData, newOutputData) {
110
+
111
+ function checkTaprootScriptPubkey(outputData: PsbtOutput, newOutputData: PsbtOutput): void {
103
112
  if (!newOutputData.tapTree && !newOutputData.tapInternalKey) return;
104
- const tapInternalKey =
105
- newOutputData.tapInternalKey || outputData.tapInternalKey;
113
+
114
+ const tapInternalKey = newOutputData.tapInternalKey || outputData.tapInternalKey;
106
115
  const tapTree = newOutputData.tapTree || outputData.tapTree;
116
+
107
117
  if (tapInternalKey) {
108
- const { script: scriptPubkey } = outputData;
118
+ const { script: scriptPubkey } = outputData as any;
109
119
  const script = getTaprootScripPubkey(tapInternalKey, tapTree);
110
120
  if (scriptPubkey && !scriptPubkey.equals(script))
111
- throw new Error(
112
- 'Error adding output. Script or address missmatch.',
113
- );
121
+ throw new Error('Error adding output. Script or address missmatch.');
114
122
  }
115
123
  }
116
- function getTaprootScripPubkey(tapInternalKey, tapTree) {
124
+
125
+ function getTaprootScripPubkey(tapInternalKey: TapInternalKey, tapTree?: TapTree): Buffer {
117
126
  const scriptTree = tapTree && tapTreeFromList(tapTree.leaves);
118
- const { output } = (0, payments_1.p2tr)({
127
+ const { output } = p2tr({
119
128
  internalPubkey: tapInternalKey,
120
129
  scriptTree,
121
130
  });
122
- return output;
131
+ return output!;
123
132
  }
124
- function tweakInternalPubKey(inputIndex, input) {
133
+
134
+ export function tweakInternalPubKey(inputIndex: number, input: PsbtInput): Buffer {
125
135
  const tapInternalKey = input.tapInternalKey;
126
- const outputKey =
127
- tapInternalKey &&
128
- (0, bip341_1.tweakKey)(tapInternalKey, input.tapMerkleRoot);
136
+ const outputKey = tapInternalKey && tweakKey(tapInternalKey, input.tapMerkleRoot);
137
+
129
138
  if (!outputKey)
130
139
  throw new Error(
131
140
  `Cannot tweak tap internal key for input #${inputIndex}. Public key: ${
@@ -134,7 +143,7 @@ function tweakInternalPubKey(inputIndex, input) {
134
143
  );
135
144
  return outputKey.x;
136
145
  }
137
- exports.tweakInternalPubKey = tweakInternalPubKey;
146
+
138
147
  /**
139
148
  * Convert a binary tree to a BIP371 type list. Each element of the list is (according to BIP371):
140
149
  * One or more tuples representing the depth, leaf version, and script for a leaf in the Taproot tree,
@@ -143,14 +152,12 @@ exports.tweakInternalPubKey = tweakInternalPubKey;
143
152
  * @param tree the binary tap tree
144
153
  * @returns a list of BIP 371 tapleaves
145
154
  */
146
- function tapTreeToList(tree) {
147
- if (!(0, types_1.isTaptree)(tree))
148
- throw new Error(
149
- 'Cannot convert taptree to tapleaf list. Expecting a tapree structure.',
150
- );
155
+ export function tapTreeToList(tree: Taptree): TapLeaf[] {
156
+ if (!isTaptree(tree))
157
+ throw new Error('Cannot convert taptree to tapleaf list. Expecting a tapree structure.');
151
158
  return _tapTreeToList(tree);
152
159
  }
153
- exports.tapTreeToList = tapTreeToList;
160
+
154
161
  /**
155
162
  * Convert a BIP371 TapLeaf list to a TapTree (binary).
156
163
  * @param leaves a list of tapleaves where each element of the list is (according to BIP371):
@@ -159,61 +166,57 @@ exports.tapTreeToList = tapTreeToList;
159
166
  * the tree is correctly reconstructed.
160
167
  * @returns the corresponding taptree, or throws an exception if the tree cannot be reconstructed
161
168
  */
162
- function tapTreeFromList(leaves = []) {
169
+ export function tapTreeFromList(leaves: TapLeaf[] = []): Taptree {
163
170
  if (leaves.length === 1 && leaves[0].depth === 0)
164
171
  return {
165
172
  output: leaves[0].script,
166
173
  version: leaves[0].leafVersion,
167
174
  };
175
+
168
176
  return insertLeavesInTree(leaves);
169
177
  }
170
- exports.tapTreeFromList = tapTreeFromList;
171
- function checkTaprootInputForSigs(input, action) {
178
+
179
+ export function checkTaprootInputForSigs(input: PsbtInput, action: string): boolean {
172
180
  const sigs = extractTaprootSigs(input);
173
- return sigs.some(sig =>
174
- (0, psbtutils_1.signatureBlocksAction)(
175
- sig,
176
- decodeSchnorrSignature,
177
- action,
178
- ),
179
- );
181
+ return sigs.some((sig) => signatureBlocksAction(sig, decodeSchnorrSignature, action));
180
182
  }
181
- exports.checkTaprootInputForSigs = checkTaprootInputForSigs;
182
- function decodeSchnorrSignature(signature) {
183
+
184
+ function decodeSchnorrSignature(signature: Buffer): {
185
+ signature: Buffer;
186
+ hashType: number;
187
+ } {
183
188
  return {
184
189
  signature: signature.slice(0, 64),
185
- hashType:
186
- signature.slice(64)[0] || transaction_1.Transaction.SIGHASH_DEFAULT,
190
+ hashType: signature.slice(64)[0] || Transaction.SIGHASH_DEFAULT,
187
191
  };
188
192
  }
189
- function extractTaprootSigs(input) {
190
- const sigs = [];
193
+
194
+ function extractTaprootSigs(input: PsbtInput): Buffer[] {
195
+ const sigs: Buffer[] = [];
191
196
  if (input.tapKeySig) sigs.push(input.tapKeySig);
192
- if (input.tapScriptSig)
193
- sigs.push(...input.tapScriptSig.map(s => s.signature));
197
+ if (input.tapScriptSig) sigs.push(...input.tapScriptSig.map((s) => s.signature));
194
198
  if (!sigs.length) {
195
- const finalTapKeySig = getTapKeySigFromWitness(
196
- input.finalScriptWitness,
197
- );
199
+ const finalTapKeySig = getTapKeySigFromWitness(input.finalScriptWitness);
198
200
  if (finalTapKeySig) sigs.push(finalTapKeySig);
199
201
  }
202
+
200
203
  return sigs;
201
204
  }
202
- function getTapKeySigFromWitness(finalScriptWitness) {
205
+
206
+ export function getTapKeySigFromWitness(finalScriptWitness?: Buffer): Buffer | undefined {
203
207
  if (!finalScriptWitness) return;
204
208
  const witness = finalScriptWitness.slice(2);
205
209
  // todo: add schnorr signature validation
206
210
  if (witness.length === 64 || witness.length === 65) return witness;
207
211
  }
208
- exports.getTapKeySigFromWitness = getTapKeySigFromWitness;
209
- function _tapTreeToList(tree, leaves = [], depth = 0) {
210
- if (depth > bip341_1.MAX_TAPTREE_DEPTH)
211
- throw new Error('Max taptree depth exceeded.');
212
+
213
+ function _tapTreeToList(tree: Taptree, leaves: TapLeaf[] = [], depth = 0): TapLeaf[] {
214
+ if (depth > MAX_TAPTREE_DEPTH) throw new Error('Max taptree depth exceeded.');
212
215
  if (!tree) return [];
213
- if ((0, types_1.isTapleaf)(tree)) {
216
+ if (isTapleaf(tree)) {
214
217
  leaves.push({
215
218
  depth,
216
- leafVersion: tree.version || bip341_1.LEAF_VERSION_TAPSCRIPT,
219
+ leafVersion: tree.version || LEAF_VERSION_TAPSCRIPT,
217
220
  script: tree.output,
218
221
  });
219
222
  return leaves;
@@ -222,17 +225,22 @@ function _tapTreeToList(tree, leaves = [], depth = 0) {
222
225
  if (tree[1]) _tapTreeToList(tree[1], leaves, depth + 1);
223
226
  return leaves;
224
227
  }
225
- function insertLeavesInTree(leaves) {
226
- let tree;
228
+
229
+ // Just like Taptree, but it accepts empty branches
230
+ type PartialTaptree = [PartialTaptree | Tapleaf, PartialTaptree | Tapleaf] | Tapleaf | undefined;
231
+
232
+ function insertLeavesInTree(leaves: TapLeaf[]): Taptree {
233
+ let tree: PartialTaptree;
227
234
  for (const leaf of leaves) {
228
235
  tree = insertLeafInTree(leaf, tree);
229
236
  if (!tree) throw new Error(`No room left to insert tapleaf in tree`);
230
237
  }
231
- return tree;
238
+
239
+ return tree as Taptree;
232
240
  }
233
- function insertLeafInTree(leaf, tree, depth = 0) {
234
- if (depth > bip341_1.MAX_TAPTREE_DEPTH)
235
- throw new Error('Max taptree depth exceeded.');
241
+
242
+ function insertLeafInTree(leaf: TapLeaf, tree?: PartialTaptree, depth = 0): PartialTaptree {
243
+ if (depth > MAX_TAPTREE_DEPTH) throw new Error('Max taptree depth exceeded.');
236
244
  if (leaf.depth === depth) {
237
245
  if (!tree)
238
246
  return {
@@ -241,50 +249,53 @@ function insertLeafInTree(leaf, tree, depth = 0) {
241
249
  };
242
250
  return;
243
251
  }
244
- if ((0, types_1.isTapleaf)(tree)) return;
252
+
253
+ if (isTapleaf(tree)) return;
245
254
  const leftSide = insertLeafInTree(leaf, tree && tree[0], depth + 1);
246
255
  if (leftSide) return [leftSide, tree && tree[1]];
256
+
247
257
  const rightSide = insertLeafInTree(leaf, tree && tree[1], depth + 1);
248
258
  if (rightSide) return [tree && tree[0], rightSide];
249
259
  }
260
+
250
261
  function checkMixedTaprootAndNonTaprootInputFields(
251
- inputData,
252
- newInputData,
253
- action,
254
- ) {
255
- const isBadTaprootUpdate =
256
- isTaprootInput(inputData) && hasNonTaprootFields(newInputData);
257
- const isBadNonTaprootUpdate =
258
- hasNonTaprootFields(inputData) && isTaprootInput(newInputData);
262
+ inputData: PsbtOutput,
263
+ newInputData: PsbtInput,
264
+ action: string,
265
+ ): void {
266
+ const isBadTaprootUpdate = isTaprootInput(inputData) && hasNonTaprootFields(newInputData);
267
+ const isBadNonTaprootUpdate = hasNonTaprootFields(inputData) && isTaprootInput(newInputData);
259
268
  const hasMixedFields =
260
269
  inputData === newInputData &&
261
270
  isTaprootInput(newInputData) &&
262
271
  hasNonTaprootFields(newInputData); // todo: bad? use !===
272
+
263
273
  if (isBadTaprootUpdate || isBadNonTaprootUpdate || hasMixedFields)
264
274
  throw new Error(
265
275
  `Invalid arguments for Psbt.${action}. ` +
266
276
  `Cannot use both taproot and non-taproot fields.`,
267
277
  );
268
278
  }
279
+
269
280
  function checkMixedTaprootAndNonTaprootOutputFields(
270
- inputData,
271
- newInputData,
272
- action,
273
- ) {
274
- const isBadTaprootUpdate =
275
- isTaprootOutput(inputData) && hasNonTaprootFields(newInputData);
276
- const isBadNonTaprootUpdate =
277
- hasNonTaprootFields(inputData) && isTaprootOutput(newInputData);
281
+ inputData: PsbtOutput,
282
+ newInputData: PsbtOutput,
283
+ action: string,
284
+ ): void {
285
+ const isBadTaprootUpdate = isTaprootOutput(inputData) && hasNonTaprootFields(newInputData);
286
+ const isBadNonTaprootUpdate = hasNonTaprootFields(inputData) && isTaprootOutput(newInputData);
278
287
  const hasMixedFields =
279
288
  inputData === newInputData &&
280
289
  isTaprootOutput(newInputData) &&
281
290
  hasNonTaprootFields(newInputData);
291
+
282
292
  if (isBadTaprootUpdate || isBadNonTaprootUpdate || hasMixedFields)
283
293
  throw new Error(
284
294
  `Invalid arguments for Psbt.${action}. ` +
285
295
  `Cannot use both taproot and non-taproot fields.`,
286
296
  );
287
297
  }
298
+
288
299
  /**
289
300
  * Checks if the tap leaf is part of the tap tree for the given input data.
290
301
  * Throws an error if the tap leaf is not part of the tap tree.
@@ -293,46 +304,43 @@ function checkMixedTaprootAndNonTaprootOutputFields(
293
304
  * @param action - The action being performed.
294
305
  * @throws {Error} - If the tap leaf is not part of the tap tree.
295
306
  */
296
- function checkIfTapLeafInTree(inputData, newInputData, action) {
307
+ function checkIfTapLeafInTree(inputData: PsbtInput, newInputData: PsbtInput, action: string): void {
297
308
  if (newInputData.tapMerkleRoot) {
298
- const newLeafsInTree = (newInputData.tapLeafScript || []).every(l =>
309
+ const newLeafsInTree = (newInputData.tapLeafScript || []).every((l) =>
299
310
  isTapLeafInTree(l, newInputData.tapMerkleRoot),
300
311
  );
301
- const oldLeafsInTree = (inputData.tapLeafScript || []).every(l =>
312
+ const oldLeafsInTree = (inputData.tapLeafScript || []).every((l) =>
302
313
  isTapLeafInTree(l, newInputData.tapMerkleRoot),
303
314
  );
304
315
  if (!newLeafsInTree || !oldLeafsInTree)
305
- throw new Error(
306
- `Invalid arguments for Psbt.${action}. Tapleaf not part of taptree.`,
307
- );
316
+ throw new Error(`Invalid arguments for Psbt.${action}. Tapleaf not part of taptree.`);
308
317
  } else if (inputData.tapMerkleRoot) {
309
- const newLeafsInTree = (newInputData.tapLeafScript || []).every(l =>
318
+ const newLeafsInTree = (newInputData.tapLeafScript || []).every((l) =>
310
319
  isTapLeafInTree(l, inputData.tapMerkleRoot),
311
320
  );
312
321
  if (!newLeafsInTree)
313
- throw new Error(
314
- `Invalid arguments for Psbt.${action}. Tapleaf not part of taptree.`,
315
- );
322
+ throw new Error(`Invalid arguments for Psbt.${action}. Tapleaf not part of taptree.`);
316
323
  }
317
324
  }
325
+
318
326
  /**
319
327
  * Checks if a TapLeafScript is present in a Merkle tree.
320
328
  * @param tapLeaf The TapLeafScript to check.
321
329
  * @param merkleRoot The Merkle root of the tree. If not provided, the function assumes the TapLeafScript is present.
322
330
  * @returns A boolean indicating whether the TapLeafScript is present in the tree.
323
331
  */
324
- function isTapLeafInTree(tapLeaf, merkleRoot) {
332
+ function isTapLeafInTree(tapLeaf: TapLeafScript, merkleRoot?: Buffer): boolean {
325
333
  if (!merkleRoot) return true;
326
- const leafHash = (0, bip341_1.tapleafHash)({
334
+
335
+ const leafHash = tapleafHash({
327
336
  output: tapLeaf.script,
328
337
  version: tapLeaf.leafVersion,
329
338
  });
330
- const rootHash = (0, bip341_1.rootHashFromPath)(
331
- tapLeaf.controlBlock,
332
- leafHash,
333
- );
339
+
340
+ const rootHash = rootHashFromPath(tapLeaf.controlBlock, leafHash);
334
341
  return rootHash.equals(merkleRoot);
335
342
  }
343
+
336
344
  /**
337
345
  * Sorts the signatures in the input's tapScriptSig array based on their position in the tapLeaf script.
338
346
  *
@@ -340,53 +348,58 @@ function isTapLeafInTree(tapLeaf, merkleRoot) {
340
348
  * @param tapLeaf - The TapLeafScript object.
341
349
  * @returns An array of sorted signatures as Buffers.
342
350
  */
343
- function sortSignatures(input, tapLeaf) {
344
- const leafHash = (0, bip341_1.tapleafHash)({
351
+ function sortSignatures(input: PsbtInput, tapLeaf: TapLeafScript): Buffer[] {
352
+ const leafHash = tapleafHash({
345
353
  output: tapLeaf.script,
346
354
  version: tapLeaf.leafVersion,
347
355
  });
356
+
348
357
  return (input.tapScriptSig || [])
349
- .filter(tss => tss.leafHash.equals(leafHash))
350
- .map(tss => addPubkeyPositionInScript(tapLeaf.script, tss))
358
+ .filter((tss) => tss.leafHash.equals(leafHash))
359
+ .map((tss) => addPubkeyPositionInScript(tapLeaf.script, tss))
351
360
  .sort((t1, t2) => t2.positionInScript - t1.positionInScript)
352
- .map(t => t.signature);
361
+ .map((t) => t.signature) as Buffer[];
353
362
  }
363
+
354
364
  /**
355
365
  * Adds the position of a public key in a script to a TapScriptSig object.
356
366
  * @param script The script in which to find the position of the public key.
357
367
  * @param tss The TapScriptSig object to add the position to.
358
368
  * @returns A TapScriptSigWitPosition object with the added position.
359
369
  */
360
- function addPubkeyPositionInScript(script, tss) {
370
+ function addPubkeyPositionInScript(script: Buffer, tss: TapScriptSig): TapScriptSigWitPosition {
361
371
  return Object.assign(
362
372
  {
363
- positionInScript: (0, psbtutils_1.pubkeyPositionInScript)(
364
- tss.pubkey,
365
- script,
366
- ),
373
+ positionInScript: pubkeyPositionInScript(tss.pubkey, script),
367
374
  },
368
375
  tss,
369
- );
376
+ ) as TapScriptSigWitPosition;
370
377
  }
378
+
371
379
  /**
372
380
  * Find tapleaf by hash, or get the signed tapleaf with the shortest path.
373
381
  */
374
- function findTapLeafToFinalize(input, inputIndex, leafHashToFinalize) {
382
+ function findTapLeafToFinalize(
383
+ input: PsbtInput,
384
+ inputIndex: number,
385
+ leafHashToFinalize?: Buffer,
386
+ ): TapLeafScript {
375
387
  if (!input.tapScriptSig || !input.tapScriptSig.length)
376
388
  throw new Error(
377
389
  `Can not finalize taproot input #${inputIndex}. No tapleaf script signature provided.`,
378
390
  );
379
391
  const tapLeaf = (input.tapLeafScript || [])
380
392
  .sort((a, b) => a.controlBlock.length - b.controlBlock.length)
381
- .find(leaf =>
382
- canFinalizeLeaf(leaf, input.tapScriptSig, leafHashToFinalize),
383
- );
393
+ .find((leaf) => canFinalizeLeaf(leaf, input.tapScriptSig!, leafHashToFinalize));
394
+
384
395
  if (!tapLeaf)
385
396
  throw new Error(
386
397
  `Can not finalize taproot input #${inputIndex}. Signature for tapleaf script not found.`,
387
398
  );
399
+
388
400
  return tapLeaf;
389
401
  }
402
+
390
403
  /**
391
404
  * Determines whether a TapLeafScript can be finalized.
392
405
  *
@@ -395,30 +408,34 @@ function findTapLeafToFinalize(input, inputIndex, leafHashToFinalize) {
395
408
  * @param hash - The optional hash to compare with the leaf hash.
396
409
  * @returns A boolean indicating whether the TapLeafScript can be finalized.
397
410
  */
398
- function canFinalizeLeaf(leaf, tapScriptSig, hash) {
399
- const leafHash = (0, bip341_1.tapleafHash)({
411
+ function canFinalizeLeaf(
412
+ leaf: TapLeafScript,
413
+ tapScriptSig: TapScriptSig[],
414
+ hash?: Buffer,
415
+ ): boolean {
416
+ const leafHash = tapleafHash({
400
417
  output: leaf.script,
401
418
  version: leaf.leafVersion,
402
419
  });
403
420
  const whiteListedHash = !hash || hash.equals(leafHash);
404
421
  return (
405
- whiteListedHash &&
406
- tapScriptSig.find(tss => tss.leafHash.equals(leafHash)) !== undefined
422
+ whiteListedHash && tapScriptSig!.find((tss) => tss.leafHash.equals(leafHash)) !== undefined
407
423
  );
408
424
  }
425
+
409
426
  /**
410
427
  * Checks if the given PsbtInput or PsbtOutput has non-taproot fields.
411
428
  * Non-taproot fields include redeemScript, witnessScript, and bip32Derivation.
412
429
  * @param io The PsbtInput or PsbtOutput to check.
413
430
  * @returns A boolean indicating whether the given input or output has non-taproot fields.
414
431
  */
415
- function hasNonTaprootFields(io) {
432
+ function hasNonTaprootFields(io: PsbtInput | PsbtOutput): boolean {
416
433
  return (
417
434
  io &&
418
- !!(
419
- io.redeemScript ||
420
- io.witnessScript ||
421
- (io.bip32Derivation && io.bip32Derivation.length)
422
- )
435
+ !!(io.redeemScript || io.witnessScript || (io.bip32Derivation && io.bip32Derivation.length))
423
436
  );
424
437
  }
438
+
439
+ interface TapScriptSigWitPosition extends TapScriptSig {
440
+ positionInScript: number;
441
+ }