@btc-vision/bitcoin 7.0.0-alpha.0 → 7.0.0-alpha.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 (296) hide show
  1. package/browser/address.d.ts +6 -2
  2. package/browser/address.d.ts.map +1 -1
  3. package/browser/block.d.ts.map +1 -1
  4. package/browser/branded.d.ts +3 -14
  5. package/browser/branded.d.ts.map +1 -1
  6. package/browser/crypto.d.ts +1 -1
  7. package/browser/ecc/context.d.ts +4 -4
  8. package/browser/ecc/context.d.ts.map +1 -1
  9. package/browser/ecc/types.d.ts +1 -1
  10. package/browser/ecc/types.d.ts.map +1 -1
  11. package/browser/index.d.ts +3 -2
  12. package/browser/index.d.ts.map +1 -1
  13. package/browser/index.js +3579 -3539
  14. package/browser/io/BinaryReader.d.ts +15 -15
  15. package/browser/io/BinaryReader.d.ts.map +1 -1
  16. package/browser/io/BinaryWriter.d.ts +17 -17
  17. package/browser/io/BinaryWriter.d.ts.map +1 -1
  18. package/browser/io/MemoryPool.d.ts +20 -20
  19. package/browser/io/MemoryPool.d.ts.map +1 -1
  20. package/browser/opcodes.d.ts +11 -0
  21. package/browser/opcodes.d.ts.map +1 -1
  22. package/browser/payments/bip341.d.ts +1 -1
  23. package/browser/payments/bip341.d.ts.map +1 -1
  24. package/browser/payments/embed.d.ts +1 -1
  25. package/browser/payments/embed.d.ts.map +1 -1
  26. package/browser/payments/p2ms.d.ts.map +1 -1
  27. package/browser/payments/p2op.d.ts +1 -1
  28. package/browser/payments/p2op.d.ts.map +1 -1
  29. package/browser/payments/p2pk.d.ts +1 -1
  30. package/browser/payments/p2pk.d.ts.map +1 -1
  31. package/browser/payments/p2pkh.d.ts +1 -1
  32. package/browser/payments/p2pkh.d.ts.map +1 -1
  33. package/browser/payments/p2sh.d.ts.map +1 -1
  34. package/browser/payments/p2tr.d.ts +2 -2
  35. package/browser/payments/p2tr.d.ts.map +1 -1
  36. package/browser/payments/p2wpkh.d.ts +1 -1
  37. package/browser/payments/p2wpkh.d.ts.map +1 -1
  38. package/browser/payments/p2wsh.d.ts.map +1 -1
  39. package/browser/payments/types.d.ts +1 -1
  40. package/browser/payments/types.d.ts.map +1 -1
  41. package/browser/psbt/PsbtCache.d.ts +54 -0
  42. package/browser/psbt/PsbtCache.d.ts.map +1 -0
  43. package/browser/psbt/PsbtFinalizer.d.ts +21 -0
  44. package/browser/psbt/PsbtFinalizer.d.ts.map +1 -0
  45. package/browser/psbt/PsbtSigner.d.ts +32 -0
  46. package/browser/psbt/PsbtSigner.d.ts.map +1 -0
  47. package/browser/psbt/PsbtTransaction.d.ts +25 -0
  48. package/browser/psbt/PsbtTransaction.d.ts.map +1 -0
  49. package/browser/psbt/bip371.d.ts.map +1 -1
  50. package/browser/psbt/types.d.ts +14 -14
  51. package/browser/psbt/types.d.ts.map +1 -1
  52. package/browser/psbt/validation.d.ts +1 -1
  53. package/browser/psbt/validation.d.ts.map +1 -1
  54. package/browser/psbt.d.ts +27 -39
  55. package/browser/psbt.d.ts.map +1 -1
  56. package/browser/script.d.ts.map +1 -1
  57. package/browser/transaction.d.ts +4 -4
  58. package/browser/transaction.d.ts.map +1 -1
  59. package/browser/types.d.ts +4 -2
  60. package/browser/types.d.ts.map +1 -1
  61. package/browser/workers/WorkerSigningPool.d.ts +17 -17
  62. package/browser/workers/WorkerSigningPool.d.ts.map +1 -1
  63. package/browser/workers/WorkerSigningPool.node.d.ts +12 -12
  64. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
  65. package/browser/workers/index.d.ts +3 -50
  66. package/browser/workers/index.d.ts.map +1 -1
  67. package/browser/workers/index.node.d.ts +24 -0
  68. package/browser/workers/index.node.d.ts.map +1 -0
  69. package/browser/workers/psbt-parallel.d.ts +1 -1
  70. package/browser/workers/psbt-parallel.d.ts.map +1 -1
  71. package/browser/workers/types.d.ts.map +1 -1
  72. package/build/address.d.ts +6 -2
  73. package/build/address.d.ts.map +1 -1
  74. package/build/address.js +32 -19
  75. package/build/address.js.map +1 -1
  76. package/build/block.d.ts.map +1 -1
  77. package/build/block.js +2 -4
  78. package/build/block.js.map +1 -1
  79. package/build/branded.d.ts +3 -14
  80. package/build/branded.d.ts.map +1 -1
  81. package/build/branded.js +0 -5
  82. package/build/branded.js.map +1 -1
  83. package/build/crypto.d.ts +1 -1
  84. package/build/ecc/context.d.ts +4 -4
  85. package/build/ecc/context.d.ts.map +1 -1
  86. package/build/ecc/context.js +75 -52
  87. package/build/ecc/context.js.map +1 -1
  88. package/build/ecc/types.d.ts +1 -1
  89. package/build/ecc/types.d.ts.map +1 -1
  90. package/build/index.d.ts +3 -2
  91. package/build/index.d.ts.map +1 -1
  92. package/build/index.js +3 -3
  93. package/build/index.js.map +1 -1
  94. package/build/io/BinaryReader.d.ts +15 -15
  95. package/build/io/BinaryReader.d.ts.map +1 -1
  96. package/build/io/BinaryReader.js +17 -17
  97. package/build/io/BinaryReader.js.map +1 -1
  98. package/build/io/BinaryWriter.d.ts +17 -17
  99. package/build/io/BinaryWriter.d.ts.map +1 -1
  100. package/build/io/BinaryWriter.js +39 -39
  101. package/build/io/BinaryWriter.js.map +1 -1
  102. package/build/io/MemoryPool.d.ts +20 -20
  103. package/build/io/MemoryPool.d.ts.map +1 -1
  104. package/build/io/MemoryPool.js +28 -28
  105. package/build/io/MemoryPool.js.map +1 -1
  106. package/build/opcodes.d.ts +11 -0
  107. package/build/opcodes.d.ts.map +1 -1
  108. package/build/opcodes.js +19 -4
  109. package/build/opcodes.js.map +1 -1
  110. package/build/payments/bip341.d.ts +1 -2
  111. package/build/payments/bip341.d.ts.map +1 -1
  112. package/build/payments/bip341.js +1 -2
  113. package/build/payments/bip341.js.map +1 -1
  114. package/build/payments/embed.d.ts +1 -1
  115. package/build/payments/embed.d.ts.map +1 -1
  116. package/build/payments/embed.js +14 -14
  117. package/build/payments/embed.js.map +1 -1
  118. package/build/payments/p2ms.d.ts.map +1 -1
  119. package/build/payments/p2ms.js +21 -21
  120. package/build/payments/p2ms.js.map +1 -1
  121. package/build/payments/p2op.d.ts +1 -1
  122. package/build/payments/p2op.d.ts.map +1 -1
  123. package/build/payments/p2op.js +18 -18
  124. package/build/payments/p2op.js.map +1 -1
  125. package/build/payments/p2pk.d.ts +1 -1
  126. package/build/payments/p2pk.d.ts.map +1 -1
  127. package/build/payments/p2pk.js +17 -17
  128. package/build/payments/p2pk.js.map +1 -1
  129. package/build/payments/p2pkh.d.ts +1 -1
  130. package/build/payments/p2pkh.d.ts.map +1 -1
  131. package/build/payments/p2pkh.js +20 -20
  132. package/build/payments/p2pkh.js.map +1 -1
  133. package/build/payments/p2sh.d.ts.map +1 -1
  134. package/build/payments/p2sh.js +22 -20
  135. package/build/payments/p2sh.js.map +1 -1
  136. package/build/payments/p2tr.d.ts +2 -2
  137. package/build/payments/p2tr.d.ts.map +1 -1
  138. package/build/payments/p2tr.js +23 -23
  139. package/build/payments/p2tr.js.map +1 -1
  140. package/build/payments/p2wpkh.d.ts +1 -1
  141. package/build/payments/p2wpkh.d.ts.map +1 -1
  142. package/build/payments/p2wpkh.js +20 -20
  143. package/build/payments/p2wpkh.js.map +1 -1
  144. package/build/payments/p2wsh.d.ts.map +1 -1
  145. package/build/payments/p2wsh.js +22 -22
  146. package/build/payments/p2wsh.js.map +1 -1
  147. package/build/payments/types.d.ts +1 -1
  148. package/build/payments/types.d.ts.map +1 -1
  149. package/build/psbt/PsbtCache.d.ts +54 -0
  150. package/build/psbt/PsbtCache.d.ts.map +1 -0
  151. package/build/psbt/PsbtCache.js +249 -0
  152. package/build/psbt/PsbtCache.js.map +1 -0
  153. package/build/psbt/PsbtFinalizer.d.ts +21 -0
  154. package/build/psbt/PsbtFinalizer.d.ts.map +1 -0
  155. package/build/psbt/PsbtFinalizer.js +157 -0
  156. package/build/psbt/PsbtFinalizer.js.map +1 -0
  157. package/build/psbt/PsbtSigner.d.ts +32 -0
  158. package/build/psbt/PsbtSigner.d.ts.map +1 -0
  159. package/build/psbt/PsbtSigner.js +192 -0
  160. package/build/psbt/PsbtSigner.js.map +1 -0
  161. package/build/psbt/PsbtTransaction.d.ts +25 -0
  162. package/build/psbt/PsbtTransaction.d.ts.map +1 -0
  163. package/build/psbt/PsbtTransaction.js +61 -0
  164. package/build/psbt/PsbtTransaction.js.map +1 -0
  165. package/build/psbt/bip371.d.ts.map +1 -1
  166. package/build/psbt/bip371.js +6 -2
  167. package/build/psbt/bip371.js.map +1 -1
  168. package/build/psbt/psbtutils.js +1 -1
  169. package/build/psbt/psbtutils.js.map +1 -1
  170. package/build/psbt/types.d.ts +14 -14
  171. package/build/psbt/types.d.ts.map +1 -1
  172. package/build/psbt/validation.d.ts +1 -1
  173. package/build/psbt/validation.d.ts.map +1 -1
  174. package/build/psbt/validation.js +1 -1
  175. package/build/psbt/validation.js.map +1 -1
  176. package/build/psbt.d.ts +27 -39
  177. package/build/psbt.d.ts.map +1 -1
  178. package/build/psbt.js +142 -755
  179. package/build/psbt.js.map +1 -1
  180. package/build/script.d.ts.map +1 -1
  181. package/build/script.js +4 -4
  182. package/build/script.js.map +1 -1
  183. package/build/transaction.d.ts +4 -4
  184. package/build/transaction.d.ts.map +1 -1
  185. package/build/transaction.js +6 -5
  186. package/build/transaction.js.map +1 -1
  187. package/build/tsconfig.build.tsbuildinfo +1 -1
  188. package/build/types.d.ts +4 -2
  189. package/build/types.d.ts.map +1 -1
  190. package/build/types.js +12 -9
  191. package/build/types.js.map +1 -1
  192. package/build/workers/WorkerSigningPool.d.ts +17 -17
  193. package/build/workers/WorkerSigningPool.d.ts.map +1 -1
  194. package/build/workers/WorkerSigningPool.js +25 -25
  195. package/build/workers/WorkerSigningPool.js.map +1 -1
  196. package/build/workers/WorkerSigningPool.node.d.ts +12 -12
  197. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
  198. package/build/workers/WorkerSigningPool.node.js +23 -23
  199. package/build/workers/WorkerSigningPool.node.js.map +1 -1
  200. package/build/workers/index.d.ts +3 -3
  201. package/build/workers/index.d.ts.map +1 -1
  202. package/build/workers/index.js +0 -3
  203. package/build/workers/index.js.map +1 -1
  204. package/build/workers/index.node.d.ts +24 -0
  205. package/build/workers/index.node.d.ts.map +1 -0
  206. package/build/workers/index.node.js +26 -0
  207. package/build/workers/index.node.js.map +1 -0
  208. package/build/workers/psbt-parallel.d.ts +1 -1
  209. package/build/workers/psbt-parallel.d.ts.map +1 -1
  210. package/build/workers/psbt-parallel.js.map +1 -1
  211. package/build/workers/types.d.ts.map +1 -1
  212. package/build/workers/types.js.map +1 -1
  213. package/package.json +30 -10
  214. package/src/address.ts +53 -21
  215. package/src/block.ts +15 -8
  216. package/src/branded.ts +15 -13
  217. package/src/crypto.ts +1 -1
  218. package/src/ecc/context.ts +85 -64
  219. package/src/ecc/types.ts +1 -8
  220. package/src/index.ts +48 -14
  221. package/src/io/BinaryReader.ts +18 -18
  222. package/src/io/BinaryWriter.ts +43 -43
  223. package/src/io/MemoryPool.ts +32 -32
  224. package/src/opcodes.ts +21 -4
  225. package/src/payments/bip341.ts +2 -4
  226. package/src/payments/embed.ts +18 -18
  227. package/src/payments/p2ms.ts +32 -25
  228. package/src/payments/p2op.ts +22 -22
  229. package/src/payments/p2pk.ts +20 -20
  230. package/src/payments/p2pkh.ts +25 -25
  231. package/src/payments/p2sh.ts +30 -27
  232. package/src/payments/p2tr.ts +31 -31
  233. package/src/payments/p2wpkh.ts +25 -25
  234. package/src/payments/p2wsh.ts +27 -27
  235. package/src/payments/types.ts +1 -1
  236. package/src/psbt/PsbtCache.ts +325 -0
  237. package/src/psbt/PsbtFinalizer.ts +213 -0
  238. package/src/psbt/PsbtSigner.ts +302 -0
  239. package/src/psbt/PsbtTransaction.ts +82 -0
  240. package/src/psbt/bip371.ts +7 -3
  241. package/src/psbt/psbtutils.ts +1 -1
  242. package/src/psbt/types.ts +14 -21
  243. package/src/psbt/validation.ts +5 -12
  244. package/src/psbt.ts +363 -1130
  245. package/src/script.ts +6 -9
  246. package/src/transaction.ts +18 -14
  247. package/src/types.ts +28 -17
  248. package/src/workers/WorkerSigningPool.node.ts +31 -31
  249. package/src/workers/WorkerSigningPool.ts +35 -39
  250. package/src/workers/index.node.ts +27 -0
  251. package/src/workers/index.ts +7 -9
  252. package/src/workers/psbt-parallel.ts +2 -7
  253. package/src/workers/types.ts +5 -1
  254. package/test/address.spec.ts +2 -2
  255. package/test/bitcoin.core.spec.ts +5 -2
  256. package/test/browser/payments.spec.ts +151 -0
  257. package/test/browser/psbt.spec.ts +1510 -0
  258. package/test/browser/script.spec.ts +223 -0
  259. package/test/browser/setup.ts +13 -0
  260. package/test/browser/workers-signing.spec.ts +537 -0
  261. package/test/crypto.spec.ts +2 -2
  262. package/test/fixtures/core/base58_encode_decode.json +12 -48
  263. package/test/fixtures/core/base58_keys_invalid.json +50 -150
  264. package/test/fixtures/core/sighash.json +1 -3
  265. package/test/fixtures/core/tx_valid.json +133 -501
  266. package/test/fixtures/embed.json +3 -11
  267. package/test/fixtures/p2ms.json +21 -91
  268. package/test/fixtures/p2pk.json +5 -24
  269. package/test/fixtures/p2pkh.json +7 -36
  270. package/test/fixtures/p2sh.json +8 -54
  271. package/test/fixtures/p2tr.json +2 -6
  272. package/test/fixtures/p2wpkh.json +7 -36
  273. package/test/fixtures/p2wsh.json +14 -59
  274. package/test/fixtures/psbt.json +2 -6
  275. package/test/fixtures/script.json +12 -48
  276. package/test/integration/addresses.spec.ts +11 -5
  277. package/test/integration/bip32.spec.ts +1 -1
  278. package/test/integration/cltv.spec.ts +10 -6
  279. package/test/integration/csv.spec.ts +10 -9
  280. package/test/integration/payments.spec.ts +8 -4
  281. package/test/integration/taproot.spec.ts +26 -6
  282. package/test/integration/transactions.spec.ts +22 -8
  283. package/test/payments.spec.ts +1 -1
  284. package/test/payments.utils.ts +1 -1
  285. package/test/psbt.spec.ts +250 -64
  286. package/test/script_signature.spec.ts +1 -1
  287. package/test/transaction.spec.ts +18 -5
  288. package/test/tsconfig.json +6 -20
  289. package/test/workers-pool.spec.ts +22 -23
  290. package/test/workers-signing.spec.ts +7 -3
  291. package/test/workers.spec.ts +6 -7
  292. package/typedoc.json +39 -0
  293. package/vitest.config.browser.ts +68 -0
  294. package/browser/ecpair.d.ts +0 -99
  295. package/src/ecpair.d.ts +0 -99
  296. package/test/taproot-cache.spec.ts +0 -694
package/build/psbt.js CHANGED
@@ -1,32 +1,44 @@
1
- import { Psbt as PsbtBase, checkForInput, checkForOutput, } from 'bip174';
2
- import { clone, reverse, equals, fromHex, toHex, fromBase64 } from './io/index.js';
3
- import { fromOutputScript, isUnknownSegwitVersion, toOutputScript } from './address.js';
1
+ import { checkForInput, checkForOutput, Psbt as PsbtBase } from 'bip174';
2
+ import { clone, equals, fromBase64, fromHex, toHex } from './io/index.js';
3
+ import { fromOutputScript, toOutputScript } from './address.js';
4
4
  import { bitcoin as btcNetwork } from './networks.js';
5
5
  import * as payments from './payments/index.js';
6
- import { tapleafHash } from './payments/bip341.js';
7
6
  import { checkTaprootInputFields, checkTaprootOutputFields, isTaprootInput, serializeTaprootSignature, tapScriptFinalizer, } from './psbt/bip371.js';
8
7
  import { toXOnly } from './pubkey.js';
9
- import { isP2TR, isP2WPKH, pubkeyInScript, witnessStackToScriptWitness, } from './psbt/psbtutils.js';
10
- import { check32Bit, checkCache, checkInputsForPartialSig, checkPartialSigSighashes, checkScriptForPubkey, checkTxEmpty, checkTxForDupeIns, checkTxInputCache, isFinalized, } from './psbt/validation.js';
11
- import { checkInvalidP2WSH, classifyScript, compressPubkey, getMeaningfulScript, isPubkeyLike, isSigLike, range, scriptWitnessToWitnessStack, sighashTypeToString, } from './psbt/utils.js';
12
8
  import * as bscript from './script.js';
13
9
  import { Transaction } from './transaction.js';
10
+ // Import composition classes
11
+ import { PsbtCache } from './psbt/PsbtCache.js';
12
+ import { PsbtSigner } from './psbt/PsbtSigner.js';
13
+ import { getFinalScripts as _getFinalScripts, prepareFinalScripts as _prepareFinalScripts, PsbtFinalizer, } from './psbt/PsbtFinalizer.js';
14
+ import { PsbtTransaction, transactionFromBuffer } from './psbt/PsbtTransaction.js';
15
+ import { check32Bit, checkCache, checkInputsForPartialSig, checkPartialSigSighashes, checkScriptForPubkey, checkTxForDupeIns, checkTxInputCache, isFinalized, } from './psbt/validation.js';
16
+ import { checkInvalidP2WSH, classifyScript, getMeaningfulScript, range } from './psbt/utils.js';
17
+ import { witnessStackToScriptWitness } from './psbt/psbtutils.js';
18
+ // Re-export for backwards compatibility
19
+ export { getFinalScripts, prepareFinalScripts };
20
+ export { PsbtCache } from './psbt/PsbtCache.js';
21
+ export { PsbtSigner } from './psbt/PsbtSigner.js';
22
+ export { PsbtFinalizer } from './psbt/PsbtFinalizer.js';
23
+ export { PsbtTransaction, transactionFromBuffer } from './psbt/PsbtTransaction.js';
14
24
  /**
15
25
  * These are the default arguments for a Psbt instance.
16
26
  */
17
27
  const DEFAULT_OPTS = {
18
- /**
19
- * A bitcoinjs Network object. This is only used if you pass an `address`
20
- * parameter to addOutput. Otherwise it is not needed and can be left default.
21
- */
22
28
  network: btcNetwork,
23
- /**
24
- * When extractTransaction is called, the fee rate is checked.
25
- * THIS IS NOT TO BE RELIED ON.
26
- * It is only here as a last ditch effort to prevent sending a 500 BTC fee etc.
27
- */
28
- maximumFeeRate: 5000, // satoshi per byte
29
+ maximumFeeRate: 5000,
29
30
  };
31
+ /** Helper to create a Transaction from a buffer */
32
+ function txFromBuffer(buf) {
33
+ return Transaction.fromBuffer(buf);
34
+ }
35
+ // Standalone exports that delegate to PsbtFinalizer
36
+ function getFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH, canRunChecks = true, solution) {
37
+ return _getFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH, canRunChecks, solution);
38
+ }
39
+ function prepareFinalScripts(script, scriptType, partialSig, isSegwit, isP2SH, isP2WSH, solution) {
40
+ return _prepareFinalScripts(script, scriptType, partialSig, isSegwit, isP2SH, isP2WSH, solution);
41
+ }
30
42
  /**
31
43
  * Psbt class can parse and generate a PSBT binary based off of the BIP174.
32
44
  * There are 6 roles that this class fulfills. (Explained in BIP174)
@@ -64,39 +76,23 @@ const DEFAULT_OPTS = {
64
76
  * Transaction Extractor: This role will perform some checks before returning a
65
77
  * Transaction object. Such as fee rate not being larger than maximumFeeRate etc.
66
78
  */
67
- /**
68
- * Psbt class can parse and generate a PSBT binary based off of the BIP174.
69
- */
70
79
  export class Psbt {
71
80
  data;
72
81
  #cache;
82
+ #signer;
83
+ #finalizer;
73
84
  #opts;
74
85
  constructor(opts = {}, data = new PsbtBase(new PsbtTransaction())) {
75
86
  this.data = data;
76
87
  this.#opts = Object.assign({}, DEFAULT_OPTS, opts);
77
- this.#cache = {
78
- nonWitnessUtxoTxCache: [],
79
- nonWitnessUtxoBufCache: [],
80
- txInCache: {},
81
- // unsignedTx.tx property is dynamically added by PsbtBase
82
- tx: this.data.globalMap.unsignedTx.tx,
83
- unsafeSignNonSegwit: false,
84
- hasSignatures: false,
85
- };
88
+ const tx = this.data.globalMap.unsignedTx.tx;
89
+ this.#cache = new PsbtCache(tx);
86
90
  if (opts.version === 3) {
87
91
  this.setVersionTRUC();
88
92
  }
89
93
  else if (this.data.inputs.length === 0)
90
94
  this.setVersion(2);
91
95
  }
92
- /** @internal - Exposed for testing. Do not use in production code. */
93
- get __CACHE() {
94
- return this.#cache;
95
- }
96
- /** @internal - Exposed for testing. Do not use in production code. */
97
- get opts() {
98
- return this.#opts;
99
- }
100
96
  get inputCount() {
101
97
  return this.data.inputs.length;
102
98
  }
@@ -125,7 +121,9 @@ export class Psbt {
125
121
  try {
126
122
  address = fromOutputScript(output.script, this.#opts.network);
127
123
  }
128
- catch (_) { }
124
+ catch (_) {
125
+ // Not all scripts can be converted to an address
126
+ }
129
127
  return {
130
128
  script: clone(output.script),
131
129
  value: output.value,
@@ -133,6 +131,20 @@ export class Psbt {
133
131
  };
134
132
  });
135
133
  }
134
+ /** Lazily initialized signer - created on first access */
135
+ get #lazySigner() {
136
+ if (!this.#signer) {
137
+ this.#signer = new PsbtSigner(this.#cache, txFromBuffer);
138
+ }
139
+ return this.#signer;
140
+ }
141
+ /** Lazily initialized finalizer - created on first access */
142
+ get #lazyFinalizer() {
143
+ if (!this.#finalizer) {
144
+ this.#finalizer = new PsbtFinalizer(this.#cache, txFromBuffer);
145
+ }
146
+ return this.#finalizer;
147
+ }
136
148
  static fromBase64(data, opts = {}) {
137
149
  const buffer = fromBase64(data);
138
150
  return this.fromBuffer(buffer, opts);
@@ -145,7 +157,6 @@ export class Psbt {
145
157
  const psbtBase = PsbtBase.fromBuffer(buffer, transactionFromBuffer);
146
158
  const psbt = new Psbt(opts, psbtBase);
147
159
  checkTxForDupeIns(psbt.#cache.tx, psbt.#cache);
148
- // Check if restored PSBT has any signatures (partial or finalized)
149
160
  psbt.#cache.hasSignatures = psbt.data.inputs.some((input) => input.partialSig?.length ||
150
161
  input.tapKeySig ||
151
162
  input.tapScriptSig?.length ||
@@ -158,20 +169,21 @@ export class Psbt {
158
169
  return this;
159
170
  }
160
171
  clone() {
161
- // TODO: more efficient cloning
162
- const clonedOpts = JSON.parse(JSON.stringify(this.#opts));
172
+ const clonedOpts = structuredClone(this.#opts);
163
173
  return Psbt.fromBuffer(new Uint8Array(this.data.toBuffer()), clonedOpts);
164
174
  }
175
+ get maximumFeeRate() {
176
+ return this.#opts.maximumFeeRate;
177
+ }
165
178
  setMaximumFeeRate(satoshiPerByte) {
166
- check32Bit(satoshiPerByte); // 42.9 BTC per byte IS excessive... so throw
179
+ check32Bit(satoshiPerByte);
167
180
  this.#opts.maximumFeeRate = satoshiPerByte;
168
181
  }
169
182
  setVersion(version) {
170
183
  check32Bit(version);
171
184
  checkInputsForPartialSig(this.data.inputs, 'setVersion', this.#cache.hasSignatures);
172
- const c = this.#cache;
173
- c.tx.version = version;
174
- c.extractedTx = undefined;
185
+ this.#cache.tx.version = version;
186
+ this.#cache.invalidate('outputs');
175
187
  return this;
176
188
  }
177
189
  setVersionTRUC() {
@@ -180,20 +192,18 @@ export class Psbt {
180
192
  setLocktime(locktime) {
181
193
  check32Bit(locktime);
182
194
  checkInputsForPartialSig(this.data.inputs, 'setLocktime', this.#cache.hasSignatures);
183
- const c = this.#cache;
184
- c.tx.locktime = locktime;
185
- c.extractedTx = undefined;
195
+ this.#cache.tx.locktime = locktime;
196
+ this.#cache.invalidate('outputs');
186
197
  return this;
187
198
  }
188
199
  setInputSequence(inputIndex, sequence) {
189
200
  check32Bit(sequence);
190
201
  checkInputsForPartialSig(this.data.inputs, 'setInputSequence', this.#cache.hasSignatures);
191
- const c = this.#cache;
192
- if (c.tx.ins.length <= inputIndex) {
202
+ if (this.#cache.tx.ins.length <= inputIndex) {
193
203
  throw new Error('Input index too high');
194
204
  }
195
- c.tx.ins[inputIndex].sequence = sequence;
196
- c.extractedTx = undefined;
205
+ this.#cache.tx.ins[inputIndex].sequence = sequence;
206
+ this.#cache.invalidate('outputs');
197
207
  return this;
198
208
  }
199
209
  addInputs(inputDatas, checkPartialSigs = true) {
@@ -211,7 +221,6 @@ export class Psbt {
211
221
  }
212
222
  if (inputData.witnessScript)
213
223
  checkInvalidP2WSH(inputData.witnessScript);
214
- // Convert witnessUtxo for bip174 v3 compatibility (value: bigint, script: Uint8Array)
215
224
  const normalizedInputData = inputData.witnessUtxo
216
225
  ? {
217
226
  ...inputData,
@@ -223,45 +232,25 @@ export class Psbt {
223
232
  },
224
233
  }
225
234
  : inputData;
226
- const c = this.#cache;
227
235
  this.data.addInput(normalizedInputData);
228
- const txIn = c.tx.ins[c.tx.ins.length - 1];
229
- checkTxInputCache(c, txIn);
236
+ const txIn = this.#cache.tx.ins[this.#cache.tx.ins.length - 1];
237
+ checkTxInputCache(this.#cache, txIn);
230
238
  const inputIndex = this.data.inputs.length - 1;
231
239
  const input = this.data.inputs[inputIndex];
232
240
  if (input.nonWitnessUtxo) {
233
- addNonWitnessTxCache(this.#cache, input, inputIndex);
241
+ this.#cache.addNonWitnessTxCache(input, inputIndex, txFromBuffer);
234
242
  }
235
- c.fee = undefined;
236
- c.feeRate = undefined;
237
- c.extractedTx = undefined;
238
- c.prevOuts = undefined;
239
- c.signingScripts = undefined;
240
- c.values = undefined;
241
- c.taprootHashCache = undefined;
243
+ this.#cache.invalidate('full');
242
244
  return this;
243
245
  }
244
246
  addOutputs(outputDatas, checkPartialSigs = true) {
245
247
  outputDatas.forEach((outputData) => this.addOutput(outputData, checkPartialSigs));
246
248
  return this;
247
249
  }
248
- /**
249
- * Add an output to the PSBT.
250
- *
251
- * **PERFORMANCE WARNING:** Passing an `address` string is ~10x slower than passing
252
- * a `script` directly due to address parsing overhead (bech32 decode, etc.).
253
- * For high-performance use cases with many outputs, pre-compute the script using
254
- * `toOutputScript(address, network)` and pass `{ script, value }` instead.
255
- *
256
- * @param outputData - Output data with either `address` or `script`, and `value`
257
- * @param checkPartialSigs - Whether to check for existing signatures (default: true)
258
- */
259
250
  addOutput(outputData, checkPartialSigs = true) {
260
251
  const hasAddress = 'address' in outputData;
261
252
  const hasScript = 'script' in outputData;
262
- if (!outputData ||
263
- outputData.value === undefined ||
264
- (!hasAddress && !hasScript)) {
253
+ if (!outputData || outputData.value === undefined || (!hasAddress && !hasScript)) {
265
254
  throw new Error(`Invalid arguments for Psbt.addOutput. ` +
266
255
  `Requires single object with at least [script or address] and [value]`);
267
256
  }
@@ -275,12 +264,8 @@ export class Psbt {
275
264
  outputData = Object.assign({}, outputData, { script });
276
265
  }
277
266
  checkTaprootOutputFields(outputData, outputData, 'addOutput');
278
- const c = this.#cache;
279
267
  this.data.addOutput(outputData);
280
- c.fee = undefined;
281
- c.feeRate = undefined;
282
- c.extractedTx = undefined;
283
- c.taprootHashCache = undefined;
268
+ this.#cache.invalidate('outputs');
284
269
  return this;
285
270
  }
286
271
  extractTransaction(disableFeeCheck, disableOutputChecks) {
@@ -289,24 +274,24 @@ export class Psbt {
289
274
  }
290
275
  if (!this.data.inputs.every(isFinalized))
291
276
  throw new Error('Not finalized');
292
- const c = this.#cache;
293
277
  if (!disableFeeCheck) {
294
- checkFees(this, c, this.#opts);
278
+ this.#cache.computeFeeRate(this.data.inputs, disableOutputChecks, txFromBuffer);
279
+ this.#cache.checkFees(this.#opts);
295
280
  }
296
- if (c.extractedTx)
297
- return c.extractedTx;
298
- const tx = c.tx.clone();
299
- inputFinalizeGetAmts(this.data.inputs, tx, c, true, disableOutputChecks);
281
+ if (this.#cache.extractedTx)
282
+ return this.#cache.extractedTx;
283
+ const tx = this.#cache.tx.clone();
284
+ this.#cache.finalizeAndComputeAmounts(this.data.inputs, tx, true, disableOutputChecks, txFromBuffer);
300
285
  return tx;
301
286
  }
302
287
  getFeeRate(disableOutputChecks = false) {
303
- return getTxCacheValue('feeRate', 'fee rate', this.data.inputs, this.#cache, disableOutputChecks);
288
+ return this.#cache.computeFeeRate(this.data.inputs, disableOutputChecks, txFromBuffer);
304
289
  }
305
290
  getFee(disableOutputChecks = false) {
306
- return getTxCacheValue('fee', 'fee', this.data.inputs, this.#cache, disableOutputChecks);
291
+ return this.#cache.computeFee(this.data.inputs, disableOutputChecks, txFromBuffer);
307
292
  }
308
293
  finalizeAllInputs() {
309
- checkForInput(this.data.inputs, 0); // making sure we have at least one
294
+ checkForInput(this.data.inputs, 0);
310
295
  range(this.data.inputs.length).forEach((idx) => this.finalizeInput(idx));
311
296
  return this;
312
297
  }
@@ -325,36 +310,35 @@ export class Psbt {
325
310
  }
326
311
  getInputType(inputIndex) {
327
312
  const input = checkForInput(this.data.inputs, inputIndex);
328
- const script = getScriptFromUtxo(inputIndex, input, this.#cache);
329
- const result = getMeaningfulScript(script, inputIndex, 'input', input.redeemScript ||
330
- redeemFromFinalScriptSig(input.finalScriptSig), input.witnessScript ||
331
- redeemFromFinalWitnessScript(input.finalScriptWitness));
313
+ const script = this.#cache.getScriptFromUtxo(inputIndex, input, txFromBuffer);
314
+ const result = getMeaningfulScript(script, inputIndex, 'input', input.redeemScript || this.#cache.redeemFromFinalScriptSig(input.finalScriptSig), input.witnessScript ||
315
+ this.#cache.redeemFromFinalWitnessScript(input.finalScriptWitness));
332
316
  const type = result.type === 'raw' ? '' : result.type + '-';
333
317
  const mainType = classifyScript(result.meaningfulScript);
334
318
  return (type + mainType);
335
319
  }
336
320
  inputHasPubkey(inputIndex, pubkey) {
337
321
  const input = checkForInput(this.data.inputs, inputIndex);
338
- return pubkeyInInput(pubkey, input, inputIndex, this.#cache);
322
+ return this.#cache.pubkeyInInput(pubkey, input, inputIndex, txFromBuffer);
339
323
  }
340
324
  inputHasHDKey(inputIndex, root) {
341
325
  const input = checkForInput(this.data.inputs, inputIndex);
342
- const derivationIsMine = bip32DerivationIsMine(root);
326
+ const derivationIsMine = this.#lazySigner.bip32DerivationIsMine(root);
343
327
  return !!input.bip32Derivation && input.bip32Derivation.some(derivationIsMine);
344
328
  }
345
329
  outputHasPubkey(outputIndex, pubkey) {
346
330
  const output = checkForOutput(this.data.outputs, outputIndex);
347
- return pubkeyInOutput(pubkey, output, outputIndex, this.#cache);
331
+ return this.#cache.pubkeyInOutput(pubkey, output, outputIndex);
348
332
  }
349
333
  outputHasHDKey(outputIndex, root) {
350
334
  const output = checkForOutput(this.data.outputs, outputIndex);
351
- const derivationIsMine = bip32DerivationIsMine(root);
335
+ const derivationIsMine = this.#lazySigner.bip32DerivationIsMine(root);
352
336
  return !!output.bip32Derivation && output.bip32Derivation.some(derivationIsMine);
353
337
  }
354
338
  validateSignaturesOfAllInputs(validator) {
355
- checkForInput(this.data.inputs, 0); // making sure we have at least one
339
+ checkForInput(this.data.inputs, 0);
356
340
  const results = range(this.data.inputs.length).map((idx) => this.validateSignaturesOfInput(idx, validator));
357
- return results.reduce((final, res) => res && final, true);
341
+ return results.every((res) => res);
358
342
  }
359
343
  validateSignaturesOfInput(inputIndex, validator, pubkey) {
360
344
  const input = this.data.inputs[inputIndex];
@@ -381,56 +365,43 @@ export class Psbt {
381
365
  }
382
366
  return this;
383
367
  }
384
- signAllInputsHDAsync(hdKeyPair, sighashTypes = [Transaction.SIGHASH_ALL]) {
385
- return new Promise((resolve, reject) => {
386
- if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
387
- return reject(new Error('Need HDSigner to sign input'));
388
- }
389
- const results = [];
390
- const promises = [];
391
- for (const i of range(this.data.inputs.length)) {
392
- promises.push(this.signInputHDAsync(i, hdKeyPair, sighashTypes).then(() => {
393
- results.push(true);
394
- }, () => {
395
- results.push(false);
396
- }));
397
- }
398
- return Promise.all(promises).then(() => {
399
- if (results.every((v) => !v)) {
400
- return reject(new Error('No inputs were signed'));
401
- }
402
- resolve();
403
- });
404
- });
368
+ async signAllInputsHDAsync(hdKeyPair, sighashTypes = [Transaction.SIGHASH_ALL]) {
369
+ if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
370
+ throw new Error('Need HDSigner to sign input');
371
+ }
372
+ const results = [];
373
+ const promises = [];
374
+ for (const i of range(this.data.inputs.length)) {
375
+ promises.push(this.signInputHDAsync(i, hdKeyPair, sighashTypes).then(() => {
376
+ results.push(true);
377
+ }, () => {
378
+ results.push(false);
379
+ }));
380
+ }
381
+ await Promise.all(promises);
382
+ if (results.every((v) => !v)) {
383
+ throw new Error('No inputs were signed');
384
+ }
405
385
  }
406
386
  signInputHD(inputIndex, hdKeyPair, sighashTypes = [Transaction.SIGHASH_ALL]) {
407
387
  if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
408
388
  throw new Error('Need HDSigner to sign input');
409
389
  }
410
- const signers = getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair);
390
+ const signers = this.#lazySigner.getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair);
411
391
  signers.forEach((signer) => this.signInput(inputIndex, signer, sighashTypes));
412
392
  return this;
413
393
  }
414
- signInputHDAsync(inputIndex, hdKeyPair, sighashTypes = [Transaction.SIGHASH_ALL]) {
415
- return new Promise((resolve, reject) => {
416
- if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
417
- return reject(new Error('Need HDSigner to sign input'));
418
- }
419
- const signers = getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair);
420
- const promises = signers.map((signer) => this.signInputAsync(inputIndex, signer, sighashTypes));
421
- return Promise.all(promises)
422
- .then(() => {
423
- resolve();
424
- })
425
- .catch(reject);
426
- });
394
+ async signInputHDAsync(inputIndex, hdKeyPair, sighashTypes = [Transaction.SIGHASH_ALL]) {
395
+ if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
396
+ throw new Error('Need HDSigner to sign input');
397
+ }
398
+ const signers = this.#lazySigner.getSignersFromHD(inputIndex, this.data.inputs, hdKeyPair);
399
+ const promises = signers.map((signer) => this.signInputAsync(inputIndex, signer, sighashTypes));
400
+ await Promise.all(promises);
427
401
  }
428
402
  signAllInputs(keyPair, sighashTypes) {
429
403
  if (!keyPair || !keyPair.publicKey)
430
404
  throw new Error('Need Signer to sign input');
431
- // TODO: Add a pubkey/pubkeyhash cache to each input
432
- // as input information is added, then eventually
433
- // optimize this method.
434
405
  const results = [];
435
406
  for (const i of range(this.data.inputs.length)) {
436
407
  try {
@@ -446,29 +417,22 @@ export class Psbt {
446
417
  }
447
418
  return this;
448
419
  }
449
- signAllInputsAsync(keyPair, sighashTypes) {
450
- return new Promise((resolve, reject) => {
451
- if (!keyPair || !keyPair.publicKey)
452
- return reject(new Error('Need Signer to sign input'));
453
- // TODO: Add a pubkey/pubkeyhash cache to each input
454
- // as input information is added, then eventually
455
- // optimize this method.
456
- const results = [];
457
- const promises = [];
458
- for (const [i] of this.data.inputs.entries()) {
459
- promises.push(this.signInputAsync(i, keyPair, sighashTypes).then(() => {
460
- results.push(true);
461
- }, () => {
462
- results.push(false);
463
- }));
464
- }
465
- return Promise.all(promises).then(() => {
466
- if (results.every((v) => !v)) {
467
- return reject(new Error('No inputs were signed'));
468
- }
469
- resolve();
470
- });
471
- });
420
+ async signAllInputsAsync(keyPair, sighashTypes) {
421
+ if (!keyPair || !keyPair.publicKey)
422
+ throw new Error('Need Signer to sign input');
423
+ const results = [];
424
+ const promises = [];
425
+ for (const [i] of this.data.inputs.entries()) {
426
+ promises.push(this.signInputAsync(i, keyPair, sighashTypes).then(() => {
427
+ results.push(true);
428
+ }, () => {
429
+ results.push(false);
430
+ }));
431
+ }
432
+ await Promise.all(promises);
433
+ if (results.every((v) => !v)) {
434
+ throw new Error('No inputs were signed');
435
+ }
472
436
  }
473
437
  signInput(inputIndex, keyPair, sighashTypes) {
474
438
  if (!keyPair || !keyPair.publicKey) {
@@ -530,7 +494,6 @@ export class Psbt {
530
494
  if (updateData.witnessScript)
531
495
  checkInvalidP2WSH(updateData.witnessScript);
532
496
  checkTaprootInputFields(this.data.inputs[inputIndex], updateData, 'updateInput');
533
- // Convert witnessUtxo for bip174 v3 compatibility (value: bigint, script: Uint8Array)
534
497
  const normalizedUpdate = updateData.witnessUtxo
535
498
  ? {
536
499
  ...updateData,
@@ -544,7 +507,7 @@ export class Psbt {
544
507
  : updateData;
545
508
  this.data.updateInput(inputIndex, normalizedUpdate);
546
509
  if (updateData.nonWitnessUtxo) {
547
- addNonWitnessTxCache(this.#cache, this.data.inputs[inputIndex], inputIndex);
510
+ this.#cache.addNonWitnessTxCache(this.data.inputs[inputIndex], inputIndex, txFromBuffer);
548
511
  }
549
512
  return this;
550
513
  }
@@ -576,13 +539,13 @@ export class Psbt {
576
539
  const pubkey = keyPair.publicKey instanceof Uint8Array
577
540
  ? keyPair.publicKey
578
541
  : new Uint8Array(keyPair.publicKey);
579
- const hashesForSig = getTaprootHashesForSig(inputIndex, input, this.data.inputs, pubkey, this.#cache, tapLeafHashToSign, allowedSighashTypes);
542
+ const hashesForSig = this.#lazySigner.getTaprootHashesForSig(inputIndex, input, this.data.inputs, pubkey, tapLeafHashToSign, allowedSighashTypes);
580
543
  if (!hashesForSig || !hashesForSig.length)
581
544
  throw new Error(`Can not sign for input #${inputIndex} with the key ${toHex(pubkey)}`);
582
545
  return hashesForSig;
583
546
  }
584
547
  #finalizeInput(inputIndex, input, finalScriptsFunc = getFinalScripts, canRunChecks = true) {
585
- const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(inputIndex, input, this.#cache);
548
+ const { script, isP2SH, isP2WSH, isSegwit } = this.#lazyFinalizer.getScriptFromInput(inputIndex, input);
586
549
  if (!script)
587
550
  throw new Error(`No script found for input #${inputIndex}`);
588
551
  checkPartialSigSighashes(input);
@@ -599,7 +562,6 @@ export class Psbt {
599
562
  #finalizeTaprootInput(inputIndex, input, tapLeafHashToFinalize, finalScriptsFunc = tapScriptFinalizer) {
600
563
  if (!input.witnessUtxo)
601
564
  throw new Error(`Cannot finalize input #${inputIndex}. Missing witness utxo.`);
602
- // Check key spend first. Increased privacy and reduced block space.
603
565
  if (input.tapKeySig) {
604
566
  const payment = payments.p2tr({
605
567
  output: input.witnessUtxo.script,
@@ -619,14 +581,12 @@ export class Psbt {
619
581
  }
620
582
  #validateSignaturesOfInput(inputIndex, validator, pubkey) {
621
583
  const input = this.data.inputs[inputIndex];
622
- const partialSig = (input || {}).partialSig;
584
+ const partialSig = input?.partialSig;
623
585
  if (!input || !partialSig || partialSig.length < 1)
624
586
  throw new Error('No signatures to validate');
625
587
  if (typeof validator !== 'function')
626
588
  throw new Error('Need validator function to validate signatures');
627
- const mySigs = pubkey
628
- ? partialSig.filter((sig) => equals(sig.pubkey, pubkey))
629
- : partialSig;
589
+ const mySigs = pubkey ? partialSig.filter((sig) => equals(sig.pubkey, pubkey)) : partialSig;
630
590
  if (mySigs.length < 1)
631
591
  throw new Error('No signatures for this pubkey');
632
592
  const results = [];
@@ -638,9 +598,9 @@ export class Psbt {
638
598
  const pSigPubkey = pSig.pubkey;
639
599
  const sig = bscript.signature.decode(pSigSignature);
640
600
  const { hash, script } = sighashCache !== sig.hashType || !hashCache || !scriptCache
641
- ? getHashForSig(inputIndex, Object.assign({}, input, {
601
+ ? this.#lazySigner.getHashForSig(inputIndex, Object.assign({}, input, {
642
602
  sighashType: sig.hashType,
643
- }), this.#cache, true)
603
+ }), true)
644
604
  : { hash: hashCache, script: scriptCache };
645
605
  sighashCache = sig.hashType;
646
606
  hashCache = hash;
@@ -652,22 +612,22 @@ export class Psbt {
652
612
  }
653
613
  #validateSignaturesOfTaprootInput(inputIndex, validator, pubkey) {
654
614
  const input = this.data.inputs[inputIndex];
655
- const tapKeySig = (input || {}).tapKeySig;
656
- const tapScriptSig = (input || {}).tapScriptSig;
615
+ const tapKeySig = input?.tapKeySig;
616
+ const tapScriptSig = input?.tapScriptSig;
657
617
  if (!input && !tapKeySig && !(tapScriptSig && !tapScriptSig.length))
658
618
  throw new Error('No signatures to validate');
659
619
  if (typeof validator !== 'function')
660
620
  throw new Error('Need validator function to validate signatures');
661
621
  const xPubkey = pubkey ? toXOnly(pubkey) : undefined;
662
622
  const allHashses = xPubkey
663
- ? getTaprootHashesForSig(inputIndex, input, this.data.inputs, xPubkey, this.#cache)
664
- : getAllTaprootHashesForSig(inputIndex, input, this.data.inputs, this.#cache);
623
+ ? this.#lazySigner.getTaprootHashesForSig(inputIndex, input, this.data.inputs, xPubkey)
624
+ : this.#lazySigner.getAllTaprootHashesForSig(inputIndex, input, this.data.inputs);
665
625
  if (!allHashses.length)
666
626
  throw new Error('No signatures for this pubkey');
667
627
  const tapKeyHash = allHashses.find((h) => !h.leafHash);
668
628
  let validationResultCount = 0;
669
629
  if (tapKeySig && tapKeyHash) {
670
- const isValidTapkeySig = validator(tapKeyHash.pubkey, tapKeyHash.hash, trimTaprootSig(tapKeySig));
630
+ const isValidTapkeySig = validator(tapKeyHash.pubkey, tapKeyHash.hash, this.#lazySigner.trimTaprootSig(tapKeySig));
671
631
  if (!isValidTapkeySig)
672
632
  return false;
673
633
  validationResultCount++;
@@ -677,7 +637,7 @@ export class Psbt {
677
637
  const tapSigPubkey = tapSig.pubkey;
678
638
  const tapSigHash = allHashses.find((h) => equals(tapSigPubkey, h.pubkey));
679
639
  if (tapSigHash) {
680
- const isValidTapScriptSig = validator(tapSigPubkey, tapSigHash.hash, trimTaprootSig(tapSig.signature));
640
+ const isValidTapScriptSig = validator(tapSigPubkey, tapSigHash.hash, this.#lazySigner.trimTaprootSig(tapSig.signature));
681
641
  if (!isValidTapScriptSig)
682
642
  return false;
683
643
  validationResultCount++;
@@ -690,7 +650,7 @@ export class Psbt {
690
650
  const pubkey = keyPair.publicKey instanceof Uint8Array
691
651
  ? keyPair.publicKey
692
652
  : new Uint8Array(keyPair.publicKey);
693
- const { hash, sighashType } = getHashAndSighashType(this.data.inputs, inputIndex, pubkey, this.#cache, sighashTypes);
653
+ const { hash, sighashType } = this.#lazySigner.getHashAndSighashType(this.data.inputs, inputIndex, pubkey, sighashTypes);
694
654
  const sig = keyPair.sign(hash);
695
655
  const partialSig = [
696
656
  {
@@ -708,7 +668,6 @@ export class Psbt {
708
668
  : new Uint8Array(keyPair.publicKey));
709
669
  if (!('signSchnorr' in keyPair) || typeof keyPair.signSchnorr !== 'function')
710
670
  throw new Error(`Need Schnorr Signer to sign taproot input #${inputIndex}.`);
711
- // checkTaprootHashesForSig validates signSchnorr exists
712
671
  const hashesForSig = this.checkTaprootHashesForSig(inputIndex, input, keyPair, tapLeafHashToSign, allowedSighashTypes);
713
672
  const signSchnorr = keyPair.signSchnorr.bind(keyPair);
714
673
  const tapKeySig = hashesForSig
@@ -735,7 +694,7 @@ export class Psbt {
735
694
  const pubkey = keyPair.publicKey instanceof Uint8Array
736
695
  ? keyPair.publicKey
737
696
  : new Uint8Array(keyPair.publicKey);
738
- const { hash, sighashType } = getHashAndSighashType(this.data.inputs, inputIndex, pubkey, this.#cache, sighashTypes);
697
+ const { hash, sighashType } = this.#lazySigner.getHashAndSighashType(this.data.inputs, inputIndex, pubkey, sighashTypes);
739
698
  return Promise.resolve(keyPair.sign(hash)).then((signature) => {
740
699
  const sig = signature instanceof Uint8Array ? signature : new Uint8Array(signature);
741
700
  const partialSig = [
@@ -754,7 +713,6 @@ export class Psbt {
754
713
  : new Uint8Array(keyPair.publicKey));
755
714
  if (!('signSchnorr' in keyPair) || typeof keyPair.signSchnorr !== 'function')
756
715
  throw new Error(`Need Schnorr Signer to sign taproot input #${inputIndex}.`);
757
- // checkTaprootHashesForSig validates signSchnorr exists
758
716
  const hashesForSig = this.checkTaprootHashesForSig(inputIndex, input, keyPair, tapLeafHash, sighashTypes);
759
717
  const signSchnorr = keyPair.signSchnorr.bind(keyPair);
760
718
  const signaturePromises = [];
@@ -789,575 +747,4 @@ export class Psbt {
789
747
  }
790
748
  }
791
749
  }
792
- /**
793
- * This function is needed to pass to the bip174 base class's fromBuffer.
794
- * It takes the "transaction buffer" portion of the psbt buffer and returns a
795
- * Transaction (From the bip174 library) interface.
796
- */
797
- const transactionFromBuffer = (buffer) => new PsbtTransaction(buffer);
798
- /**
799
- * This class implements the Transaction interface from bip174 library.
800
- * It contains a bitcoinjs-lib Transaction object.
801
- */
802
- class PsbtTransaction {
803
- tx;
804
- constructor(buffer = new Uint8Array([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
805
- this.tx = Transaction.fromBuffer(buffer);
806
- checkTxEmpty(this.tx);
807
- Object.defineProperty(this, 'tx', {
808
- enumerable: false,
809
- writable: true,
810
- });
811
- }
812
- getInputOutputCounts() {
813
- return {
814
- inputCount: this.tx.ins.length,
815
- outputCount: this.tx.outs.length,
816
- };
817
- }
818
- addInput(input) {
819
- if (input.hash === undefined ||
820
- input.index === undefined ||
821
- (!(input.hash instanceof Uint8Array) && typeof input.hash !== 'string') ||
822
- typeof input.index !== 'number') {
823
- throw new Error('Error adding input.');
824
- }
825
- const hash = (typeof input.hash === 'string' ? reverse(fromHex(input.hash)) : input.hash);
826
- this.tx.addInput(hash, input.index, input.sequence);
827
- }
828
- addOutput(output) {
829
- if (output.script === undefined ||
830
- output.value === undefined ||
831
- !(output.script instanceof Uint8Array) ||
832
- typeof output.value !== 'bigint') {
833
- throw new Error('Error adding output.');
834
- }
835
- this.tx.addOutput(output.script, output.value);
836
- }
837
- toBuffer() {
838
- return this.tx.toBuffer();
839
- }
840
- }
841
- function canFinalize(input, script, scriptType) {
842
- switch (scriptType) {
843
- case 'pubkey':
844
- case 'pubkeyhash':
845
- case 'witnesspubkeyhash':
846
- return hasSigs(1, input.partialSig);
847
- case 'multisig': {
848
- const p2ms = payments.p2ms({
849
- output: script,
850
- });
851
- if (p2ms.m === undefined)
852
- throw new Error('Cannot determine m for multisig');
853
- return hasSigs(p2ms.m, input.partialSig, p2ms.pubkeys);
854
- }
855
- case 'nonstandard':
856
- return true;
857
- default:
858
- return false;
859
- }
860
- }
861
- function hasSigs(neededSigs, partialSig, pubkeys) {
862
- if (!partialSig)
863
- return false;
864
- let sigs;
865
- if (pubkeys) {
866
- sigs = pubkeys
867
- .map((pkey) => {
868
- const pubkey = compressPubkey(pkey);
869
- return partialSig.find((pSig) => equals(pSig.pubkey, pubkey));
870
- })
871
- .filter((v) => !!v);
872
- }
873
- else {
874
- sigs = partialSig;
875
- }
876
- if (sigs.length > neededSigs)
877
- throw new Error('Too many signatures');
878
- return sigs.length === neededSigs;
879
- }
880
- function bip32DerivationIsMine(root) {
881
- return (d) => {
882
- const fingerprint = root.fingerprint instanceof Uint8Array
883
- ? root.fingerprint
884
- : new Uint8Array(root.fingerprint);
885
- if (!equals(d.masterFingerprint, fingerprint))
886
- return false;
887
- const derivedPubkey = root.derivePath(d.path).publicKey;
888
- const pubkey = derivedPubkey instanceof Uint8Array ? derivedPubkey : new Uint8Array(derivedPubkey);
889
- if (!equals(pubkey, d.pubkey))
890
- return false;
891
- return true;
892
- };
893
- }
894
- function checkFees(psbt, cache, opts) {
895
- const feeRate = cache.feeRate || psbt.getFeeRate();
896
- if (!cache.extractedTx)
897
- throw new Error('Transaction not extracted');
898
- const vsize = cache.extractedTx.virtualSize();
899
- const satoshis = feeRate * vsize;
900
- if (feeRate >= opts.maximumFeeRate) {
901
- throw new Error(`Warning: You are paying around ${(satoshis / 1e8).toFixed(8)} in ` +
902
- `fees, which is ${feeRate} satoshi per byte for a transaction ` +
903
- `with a VSize of ${vsize} bytes (segwit counted as 0.25 byte per ` +
904
- `byte). Use setMaximumFeeRate method to raise your threshold, or ` +
905
- `pass true to the first arg of extractTransaction.`);
906
- }
907
- }
908
- function getTxCacheValue(key, name, inputs, c, disableOutputChecks = false) {
909
- if (!inputs.every(isFinalized))
910
- throw new Error(`PSBT must be finalized to calculate ${name}`);
911
- if (key === 'feeRate' && c.feeRate)
912
- return c.feeRate;
913
- if (key === 'fee' && c.fee)
914
- return c.fee;
915
- let tx;
916
- let mustFinalize = true;
917
- if (c.extractedTx) {
918
- tx = c.extractedTx;
919
- mustFinalize = false;
920
- }
921
- else {
922
- tx = c.tx.clone();
923
- }
924
- inputFinalizeGetAmts(inputs, tx, c, mustFinalize, disableOutputChecks);
925
- const value = key === 'feeRate' ? c.feeRate : c.fee;
926
- if (value === undefined)
927
- throw new Error(`Failed to calculate ${name}`);
928
- return value;
929
- }
930
- export function getFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH, canRunChecks = true, solution) {
931
- const scriptType = classifyScript(script);
932
- if (!canFinalize(input, script, scriptType) && canRunChecks) {
933
- throw new Error(`Can not finalize input #${inputIndex}`);
934
- }
935
- if (!input.partialSig)
936
- throw new Error('Input missing partial signatures');
937
- return prepareFinalScripts(script, scriptType, input.partialSig, isSegwit, isP2SH, isP2WSH, solution);
938
- }
939
- export function prepareFinalScripts(script, scriptType, partialSig, isSegwit, isP2SH, isP2WSH, solution) {
940
- let finalScriptSig;
941
- let finalScriptWitness;
942
- // Wow, the payments API is very handy
943
- const payment = getPayment(script, scriptType, partialSig);
944
- const p2wsh = !isP2WSH ? null : payments.p2wsh({ redeem: payment });
945
- const p2sh = !isP2SH ? null : payments.p2sh({ redeem: p2wsh || payment });
946
- if (isSegwit) {
947
- if (p2wsh && p2wsh.witness) {
948
- finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness);
949
- }
950
- else if (payment && payment.witness) {
951
- finalScriptWitness = witnessStackToScriptWitness(payment.witness);
952
- }
953
- else {
954
- // nonstandard segwit script
955
- finalScriptWitness = witnessStackToScriptWitness(solution ?? [new Uint8Array([0x00])]);
956
- }
957
- if (p2sh) {
958
- finalScriptSig = p2sh?.input;
959
- }
960
- }
961
- else {
962
- if (p2sh) {
963
- finalScriptSig = p2sh?.input;
964
- }
965
- else {
966
- if (!payment) {
967
- finalScriptSig = (Array.isArray(solution) && solution[0] ? solution[0] : new Uint8Array([0x01]));
968
- }
969
- else {
970
- finalScriptSig = payment.input;
971
- }
972
- }
973
- }
974
- return {
975
- finalScriptSig,
976
- finalScriptWitness,
977
- };
978
- }
979
- function getHashAndSighashType(inputs, inputIndex, pubkey, cache, sighashTypes) {
980
- const input = checkForInput(inputs, inputIndex);
981
- const { hash, sighashType, script } = getHashForSig(inputIndex, input, cache, false, sighashTypes);
982
- checkScriptForPubkey(pubkey, script, 'sign');
983
- return {
984
- hash,
985
- sighashType,
986
- };
987
- }
988
- function getHashForSig(inputIndex, input, cache, forValidate, sighashTypes) {
989
- const unsignedTx = cache.tx;
990
- const sighashType = input.sighashType || Transaction.SIGHASH_ALL;
991
- checkSighashTypeAllowed(sighashType, sighashTypes);
992
- let hash;
993
- let prevout;
994
- if (input.nonWitnessUtxo) {
995
- const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(cache, input, inputIndex);
996
- const prevoutHash = unsignedTx.ins[inputIndex].hash;
997
- const utxoHash = nonWitnessUtxoTx.getHash();
998
- // If a non-witness UTXO is provided, its hash must match the hash specified in the prevout
999
- if (!equals(prevoutHash, utxoHash)) {
1000
- throw new Error(`Non-witness UTXO hash for input #${inputIndex} doesn't match the hash specified in the prevout`);
1001
- }
1002
- const prevoutIndex = unsignedTx.ins[inputIndex].index;
1003
- prevout = nonWitnessUtxoTx.outs[prevoutIndex];
1004
- }
1005
- else if (input.witnessUtxo) {
1006
- prevout = {
1007
- script: input.witnessUtxo.script,
1008
- value: input.witnessUtxo.value,
1009
- };
1010
- }
1011
- else {
1012
- throw new Error('Need a Utxo input item for signing');
1013
- }
1014
- const { meaningfulScript, type } = getMeaningfulScript(prevout.script, inputIndex, 'input', input.redeemScript, input.witnessScript);
1015
- const script = meaningfulScript;
1016
- if (['p2sh-p2wsh', 'p2wsh'].indexOf(type) >= 0) {
1017
- hash = unsignedTx.hashForWitnessV0(inputIndex, script, prevout.value, sighashType);
1018
- }
1019
- else if (isP2WPKH(meaningfulScript)) {
1020
- // P2WPKH uses the P2PKH template for prevoutScript when signing
1021
- const p2pkhPayment = payments.p2pkh({
1022
- hash: meaningfulScript.subarray(2),
1023
- });
1024
- if (!p2pkhPayment.output)
1025
- throw new Error('Unable to create signing script');
1026
- hash = unsignedTx.hashForWitnessV0(inputIndex, p2pkhPayment.output, prevout.value, sighashType);
1027
- }
1028
- else {
1029
- // non-segwit
1030
- if (input.nonWitnessUtxo === undefined && !cache.unsafeSignNonSegwit)
1031
- throw new Error(`Input #${inputIndex} has witnessUtxo but non-segwit script: ` +
1032
- toHex(meaningfulScript));
1033
- if (!forValidate && cache.unsafeSignNonSegwit)
1034
- console.warn('Warning: Signing non-segwit inputs without the full parent transaction ' +
1035
- 'means there is a chance that a miner could feed you incorrect information ' +
1036
- "to trick you into paying large fees. This behavior is the same as Psbt's predecessor " +
1037
- '(TransactionBuilder - now removed) when signing non-segwit scripts. You are not ' +
1038
- 'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' +
1039
- 'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' +
1040
- '*********************');
1041
- hash = unsignedTx.hashForSignature(inputIndex, script, sighashType);
1042
- }
1043
- return {
1044
- script,
1045
- sighashType,
1046
- hash,
1047
- };
1048
- }
1049
- function getAllTaprootHashesForSig(inputIndex, input, inputs, cache) {
1050
- const allPublicKeys = [];
1051
- if (input.tapInternalKey) {
1052
- const key = getPrevoutTaprootKey(inputIndex, input, cache);
1053
- if (key) {
1054
- allPublicKeys.push(key);
1055
- }
1056
- }
1057
- if (input.tapScriptSig) {
1058
- const tapScriptPubkeys = input.tapScriptSig.map((tss) => tss.pubkey);
1059
- allPublicKeys.push(...tapScriptPubkeys);
1060
- }
1061
- const allHashes = allPublicKeys.map((pubicKey) => getTaprootHashesForSig(inputIndex, input, inputs, pubicKey, cache));
1062
- return allHashes.flat();
1063
- }
1064
- function getPrevoutTaprootKey(inputIndex, input, cache) {
1065
- const { script } = getScriptAndAmountFromUtxo(inputIndex, input, cache);
1066
- return isP2TR(script) ? script.subarray(2, 34) : null;
1067
- }
1068
- function trimTaprootSig(signature) {
1069
- return signature.length === 64 ? signature : signature.subarray(0, 64);
1070
- }
1071
- function getTaprootHashesForSig(inputIndex, input, inputs, pubkey, cache, tapLeafHashToSign, allowedSighashTypes) {
1072
- const unsignedTx = cache.tx;
1073
- const sighashType = input.sighashType || Transaction.SIGHASH_DEFAULT;
1074
- checkSighashTypeAllowed(sighashType, allowedSighashTypes);
1075
- if (!cache.prevOuts) {
1076
- const prevOuts = inputs.map((i, index) => getScriptAndAmountFromUtxo(index, i, cache));
1077
- cache.prevOuts = prevOuts;
1078
- cache.signingScripts = prevOuts.map((o) => o.script);
1079
- cache.values = prevOuts.map((o) => o.value);
1080
- }
1081
- const signingScripts = cache.signingScripts;
1082
- const values = cache.values;
1083
- // Compute taproot hash cache once for all inputs (O(n) -> O(1) per input)
1084
- if (!cache.taprootHashCache) {
1085
- cache.taprootHashCache = unsignedTx.getTaprootHashCache(signingScripts, values);
1086
- }
1087
- const taprootCache = cache.taprootHashCache;
1088
- const hashes = [];
1089
- if (input.tapInternalKey && !tapLeafHashToSign) {
1090
- const outputKey = getPrevoutTaprootKey(inputIndex, input, cache) || new Uint8Array(0);
1091
- if (equals(toXOnly(pubkey), outputKey)) {
1092
- const tapKeyHash = unsignedTx.hashForWitnessV1(inputIndex, signingScripts, values, sighashType, undefined, undefined, taprootCache);
1093
- hashes.push({ pubkey: pubkey, hash: tapKeyHash });
1094
- }
1095
- }
1096
- const tapLeafHashes = (input.tapLeafScript || [])
1097
- .filter((tapLeaf) => pubkeyInScript(pubkey, tapLeaf.script))
1098
- .map((tapLeaf) => {
1099
- const hash = tapleafHash({
1100
- output: tapLeaf.script,
1101
- version: tapLeaf.leafVersion,
1102
- });
1103
- return Object.assign({ hash }, tapLeaf);
1104
- })
1105
- .filter((tapLeaf) => !tapLeafHashToSign || equals(tapLeafHashToSign, tapLeaf.hash))
1106
- .map((tapLeaf) => {
1107
- const tapScriptHash = unsignedTx.hashForWitnessV1(inputIndex, signingScripts, values, sighashType, tapLeaf.hash, undefined, taprootCache);
1108
- return {
1109
- pubkey: pubkey,
1110
- hash: tapScriptHash,
1111
- leafHash: tapLeaf.hash,
1112
- };
1113
- });
1114
- return hashes.concat(tapLeafHashes);
1115
- }
1116
- function checkSighashTypeAllowed(sighashType, sighashTypes) {
1117
- if (sighashTypes && sighashTypes.indexOf(sighashType) < 0) {
1118
- const str = sighashTypeToString(sighashType);
1119
- throw new Error(`Sighash type is not allowed. Retry the sign method passing the ` +
1120
- `sighashTypes array of whitelisted types. Sighash type: ${str}`);
1121
- }
1122
- }
1123
- function getPayment(script, scriptType, partialSig) {
1124
- const scriptBranded = script;
1125
- switch (scriptType) {
1126
- case 'multisig': {
1127
- const sigs = getSortedSigs(script, partialSig);
1128
- return payments.p2ms({
1129
- output: scriptBranded,
1130
- signatures: sigs,
1131
- });
1132
- }
1133
- case 'pubkey':
1134
- return payments.p2pk({
1135
- output: scriptBranded,
1136
- signature: partialSig[0].signature,
1137
- });
1138
- case 'pubkeyhash':
1139
- return payments.p2pkh({
1140
- output: scriptBranded,
1141
- pubkey: partialSig[0].pubkey,
1142
- signature: partialSig[0].signature,
1143
- });
1144
- case 'witnesspubkeyhash':
1145
- return payments.p2wpkh({
1146
- output: scriptBranded,
1147
- pubkey: partialSig[0].pubkey,
1148
- signature: partialSig[0].signature,
1149
- });
1150
- default:
1151
- throw new Error(`Unknown script type: ${scriptType}`);
1152
- }
1153
- }
1154
- function getScriptFromInput(inputIndex, input, cache) {
1155
- const unsignedTx = cache.tx;
1156
- const res = {
1157
- script: null,
1158
- isSegwit: false,
1159
- isP2SH: false,
1160
- isP2WSH: false,
1161
- };
1162
- res.isP2SH = !!input.redeemScript;
1163
- res.isP2WSH = !!input.witnessScript;
1164
- if (input.witnessScript) {
1165
- res.script = input.witnessScript;
1166
- }
1167
- else if (input.redeemScript) {
1168
- res.script = input.redeemScript;
1169
- }
1170
- else {
1171
- if (input.nonWitnessUtxo) {
1172
- const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(cache, input, inputIndex);
1173
- const prevoutIndex = unsignedTx.ins[inputIndex].index;
1174
- res.script = nonWitnessUtxoTx.outs[prevoutIndex].script;
1175
- }
1176
- else if (input.witnessUtxo) {
1177
- res.script = input.witnessUtxo.script;
1178
- }
1179
- }
1180
- if (input.witnessScript || (res.script && isP2WPKH(res.script))) {
1181
- res.isSegwit = true;
1182
- }
1183
- else {
1184
- try {
1185
- const output = res.script;
1186
- if (!output)
1187
- throw new TypeError('Invalid script for segwit address');
1188
- res.isSegwit = isUnknownSegwitVersion(output);
1189
- }
1190
- catch (e) { }
1191
- }
1192
- return res;
1193
- }
1194
- function getSignersFromHD(inputIndex, inputs, hdKeyPair) {
1195
- const input = checkForInput(inputs, inputIndex);
1196
- if (!input.bip32Derivation || input.bip32Derivation.length === 0) {
1197
- throw new Error('Need bip32Derivation to sign with HD');
1198
- }
1199
- const myDerivations = input.bip32Derivation
1200
- .map((bipDv) => {
1201
- if (equals(bipDv.masterFingerprint, hdKeyPair.fingerprint)) {
1202
- return bipDv;
1203
- }
1204
- else {
1205
- return;
1206
- }
1207
- })
1208
- .filter((v) => !!v);
1209
- if (myDerivations.length === 0) {
1210
- throw new Error('Need one bip32Derivation masterFingerprint to match the HDSigner fingerprint');
1211
- }
1212
- return myDerivations.map((bipDv) => {
1213
- const node = hdKeyPair.derivePath(bipDv.path);
1214
- if (!equals(bipDv.pubkey, node.publicKey)) {
1215
- throw new Error('pubkey did not match bip32Derivation');
1216
- }
1217
- return node;
1218
- });
1219
- }
1220
- function getSortedSigs(script, partialSig) {
1221
- const p2ms = payments.p2ms({ output: script });
1222
- if (!p2ms.pubkeys)
1223
- throw new Error('Cannot extract pubkeys from multisig script');
1224
- // for each pubkey in order of p2ms script
1225
- const result = [];
1226
- for (const pk of p2ms.pubkeys) {
1227
- // filter partialSig array by pubkey being equal
1228
- const matched = partialSig.filter((ps) => {
1229
- return equals(ps.pubkey, pk);
1230
- })[0];
1231
- if (matched) {
1232
- result.push(new Uint8Array(matched.signature));
1233
- }
1234
- }
1235
- return result;
1236
- }
1237
- function addNonWitnessTxCache(cache, input, inputIndex) {
1238
- if (!input.nonWitnessUtxo)
1239
- throw new Error('nonWitnessUtxo is required');
1240
- // Prevent prototype pollution - ensure input is a valid object
1241
- if (input === null || input === Object.prototype) {
1242
- throw new Error('Invalid input object');
1243
- }
1244
- const nonWitnessUtxoBuf = input.nonWitnessUtxo;
1245
- cache.nonWitnessUtxoBufCache[inputIndex] = nonWitnessUtxoBuf;
1246
- cache.nonWitnessUtxoTxCache[inputIndex] = Transaction.fromBuffer(nonWitnessUtxoBuf);
1247
- const self = cache;
1248
- const selfIndex = inputIndex;
1249
- delete input.nonWitnessUtxo;
1250
- // Using Reflect.defineProperty to avoid prototype pollution concerns
1251
- Reflect.defineProperty(input, 'nonWitnessUtxo', {
1252
- enumerable: true,
1253
- get() {
1254
- const buf = self.nonWitnessUtxoBufCache[selfIndex];
1255
- const txCache = self.nonWitnessUtxoTxCache[selfIndex];
1256
- if (buf !== undefined) {
1257
- return buf;
1258
- }
1259
- else {
1260
- const newBuf = txCache.toBuffer();
1261
- self.nonWitnessUtxoBufCache[selfIndex] = newBuf;
1262
- return newBuf;
1263
- }
1264
- },
1265
- set(data) {
1266
- self.nonWitnessUtxoBufCache[selfIndex] = data;
1267
- },
1268
- });
1269
- }
1270
- function inputFinalizeGetAmts(inputs, tx, cache, mustFinalize, disableOutputChecks) {
1271
- let inputAmount = 0n;
1272
- inputs.forEach((input, idx) => {
1273
- if (mustFinalize && input.finalScriptSig)
1274
- tx.ins[idx].script = input.finalScriptSig;
1275
- if (mustFinalize && input.finalScriptWitness) {
1276
- tx.ins[idx].witness = scriptWitnessToWitnessStack(input.finalScriptWitness);
1277
- }
1278
- if (input.witnessUtxo) {
1279
- inputAmount += input.witnessUtxo.value;
1280
- }
1281
- else if (input.nonWitnessUtxo) {
1282
- const nwTx = nonWitnessUtxoTxFromCache(cache, input, idx);
1283
- const vout = tx.ins[idx].index;
1284
- const out = nwTx.outs[vout];
1285
- inputAmount += out.value;
1286
- }
1287
- });
1288
- const outputAmount = tx.outs.reduce((total, o) => total + o.value, 0n);
1289
- const fee = inputAmount - outputAmount;
1290
- if (!disableOutputChecks) {
1291
- if (fee < 0n) {
1292
- throw new Error(`Outputs are spending more than Inputs ${inputAmount} < ${outputAmount}`);
1293
- }
1294
- }
1295
- const bytes = tx.virtualSize();
1296
- cache.fee = Number(fee);
1297
- cache.extractedTx = tx;
1298
- cache.feeRate = Math.floor(Number(fee) / bytes);
1299
- }
1300
- function nonWitnessUtxoTxFromCache(cache, input, inputIndex) {
1301
- const c = cache.nonWitnessUtxoTxCache;
1302
- if (!c[inputIndex]) {
1303
- addNonWitnessTxCache(cache, input, inputIndex);
1304
- }
1305
- return c[inputIndex];
1306
- }
1307
- function getScriptFromUtxo(inputIndex, input, cache) {
1308
- const { script } = getScriptAndAmountFromUtxo(inputIndex, input, cache);
1309
- return script;
1310
- }
1311
- function getScriptAndAmountFromUtxo(inputIndex, input, cache) {
1312
- if (input.witnessUtxo !== undefined) {
1313
- return {
1314
- script: input.witnessUtxo.script,
1315
- value: input.witnessUtxo.value,
1316
- };
1317
- }
1318
- else if (input.nonWitnessUtxo !== undefined) {
1319
- const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(cache, input, inputIndex);
1320
- const o = nonWitnessUtxoTx.outs[cache.tx.ins[inputIndex].index];
1321
- return { script: o.script, value: o.value };
1322
- }
1323
- else {
1324
- throw new Error("Can't find pubkey in input without Utxo data");
1325
- }
1326
- }
1327
- function pubkeyInInput(pubkey, input, inputIndex, cache) {
1328
- const script = getScriptFromUtxo(inputIndex, input, cache);
1329
- const { meaningfulScript } = getMeaningfulScript(script, inputIndex, 'input', input.redeemScript, input.witnessScript);
1330
- return pubkeyInScript(pubkey, meaningfulScript);
1331
- }
1332
- function pubkeyInOutput(pubkey, output, outputIndex, cache) {
1333
- const script = cache.tx.outs[outputIndex].script;
1334
- const { meaningfulScript } = getMeaningfulScript(script, outputIndex, 'output', output.redeemScript, output.witnessScript);
1335
- return pubkeyInScript(pubkey, meaningfulScript);
1336
- }
1337
- function redeemFromFinalScriptSig(finalScript) {
1338
- if (!finalScript)
1339
- return;
1340
- const decomp = bscript.decompile(finalScript);
1341
- if (!decomp)
1342
- return;
1343
- const lastItem = decomp[decomp.length - 1];
1344
- if (!(lastItem instanceof Uint8Array) || isPubkeyLike(lastItem) || isSigLike(lastItem))
1345
- return;
1346
- const sDecomp = bscript.decompile(lastItem);
1347
- if (!sDecomp)
1348
- return;
1349
- return lastItem;
1350
- }
1351
- function redeemFromFinalWitnessScript(finalScript) {
1352
- if (!finalScript)
1353
- return;
1354
- const decomp = scriptWitnessToWitnessStack(finalScript);
1355
- const lastItem = decomp[decomp.length - 1];
1356
- if (isPubkeyLike(lastItem))
1357
- return;
1358
- const sDecomp = bscript.decompile(lastItem);
1359
- if (!sDecomp)
1360
- return;
1361
- return lastItem;
1362
- }
1363
750
  //# sourceMappingURL=psbt.js.map