@btc-vision/bitcoin 6.5.6 → 7.0.0-alpha.1

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 (456) hide show
  1. package/HOW_TO_WRITE_GOOD_CODE.md +2436 -0
  2. package/benchmark/psbt-2000-inputs.bench.ts +178 -0
  3. package/benchmark/signing.bench.ts +147 -0
  4. package/browser/address.d.ts +57 -10
  5. package/browser/address.d.ts.map +1 -0
  6. package/browser/bech32utils.d.ts +9 -1
  7. package/browser/bech32utils.d.ts.map +1 -0
  8. package/browser/bip66.d.ts +11 -6
  9. package/browser/bip66.d.ts.map +1 -0
  10. package/browser/block.d.ts +117 -11
  11. package/browser/block.d.ts.map +1 -0
  12. package/browser/branded.d.ts +20 -0
  13. package/browser/branded.d.ts.map +1 -0
  14. package/browser/crypto/crypto.d.ts +1 -0
  15. package/browser/crypto/crypto.d.ts.map +1 -0
  16. package/browser/crypto.d.ts +46 -7
  17. package/browser/crypto.d.ts.map +1 -0
  18. package/browser/ecc/context.d.ts +129 -0
  19. package/browser/ecc/context.d.ts.map +1 -0
  20. package/browser/ecc/index.d.ts +11 -0
  21. package/browser/ecc/index.d.ts.map +1 -0
  22. package/browser/ecc/types.d.ts +128 -0
  23. package/browser/ecc/types.d.ts.map +1 -0
  24. package/browser/ecpair.d.ts +99 -0
  25. package/browser/errors.d.ts +124 -0
  26. package/browser/errors.d.ts.map +1 -0
  27. package/browser/index.d.ts +32 -5
  28. package/browser/index.d.ts.map +1 -0
  29. package/browser/index.js +12477 -101
  30. package/browser/io/BinaryReader.d.ts +276 -0
  31. package/browser/io/BinaryReader.d.ts.map +1 -0
  32. package/browser/io/BinaryWriter.d.ts +391 -0
  33. package/browser/io/BinaryWriter.d.ts.map +1 -0
  34. package/browser/io/MemoryPool.d.ts +220 -0
  35. package/browser/io/MemoryPool.d.ts.map +1 -0
  36. package/browser/io/base64.d.ts +13 -0
  37. package/browser/io/base64.d.ts.map +1 -0
  38. package/browser/io/hex.d.ts +67 -0
  39. package/browser/io/hex.d.ts.map +1 -0
  40. package/browser/io/index.d.ts +17 -0
  41. package/browser/io/index.d.ts.map +1 -0
  42. package/browser/io/utils.d.ts +199 -0
  43. package/browser/io/utils.d.ts.map +1 -0
  44. package/browser/merkle.d.ts +10 -1
  45. package/browser/merkle.d.ts.map +1 -0
  46. package/browser/networks.d.ts +70 -9
  47. package/browser/networks.d.ts.map +1 -0
  48. package/browser/opcodes.d.ts +1 -0
  49. package/browser/opcodes.d.ts.map +1 -0
  50. package/browser/payments/bip341.d.ts +35 -9
  51. package/browser/payments/bip341.d.ts.map +1 -0
  52. package/browser/payments/embed.d.ts +112 -1
  53. package/browser/payments/embed.d.ts.map +1 -0
  54. package/browser/payments/index.d.ts +17 -10
  55. package/browser/payments/index.d.ts.map +1 -0
  56. package/browser/payments/p2ms.d.ts +150 -0
  57. package/browser/payments/p2ms.d.ts.map +1 -0
  58. package/browser/payments/p2op.d.ts +150 -24
  59. package/browser/payments/p2op.d.ts.map +1 -0
  60. package/browser/payments/p2pk.d.ts +154 -1
  61. package/browser/payments/p2pk.d.ts.map +1 -0
  62. package/browser/payments/p2pkh.d.ts +176 -1
  63. package/browser/payments/p2pkh.d.ts.map +1 -0
  64. package/browser/payments/p2sh.d.ts +150 -1
  65. package/browser/payments/p2sh.d.ts.map +1 -0
  66. package/browser/payments/p2tr.d.ts +185 -1
  67. package/browser/payments/p2tr.d.ts.map +1 -0
  68. package/browser/payments/p2wpkh.d.ts +161 -1
  69. package/browser/payments/p2wpkh.d.ts.map +1 -0
  70. package/browser/payments/p2wsh.d.ts +146 -1
  71. package/browser/payments/p2wsh.d.ts.map +1 -0
  72. package/browser/payments/types.d.ts +94 -64
  73. package/browser/payments/types.d.ts.map +1 -0
  74. package/browser/psbt/bip371.d.ts +34 -8
  75. package/browser/psbt/bip371.d.ts.map +1 -0
  76. package/browser/psbt/psbtutils.d.ts +56 -16
  77. package/browser/psbt/psbtutils.d.ts.map +1 -0
  78. package/browser/psbt/types.d.ts +245 -0
  79. package/browser/psbt/types.d.ts.map +1 -0
  80. package/browser/psbt/utils.d.ts +64 -0
  81. package/browser/psbt/utils.d.ts.map +1 -0
  82. package/browser/psbt/validation.d.ts +84 -0
  83. package/browser/psbt/validation.d.ts.map +1 -0
  84. package/browser/psbt.d.ts +82 -118
  85. package/browser/psbt.d.ts.map +1 -0
  86. package/browser/pubkey.d.ts +27 -6
  87. package/browser/pubkey.d.ts.map +1 -0
  88. package/browser/push_data.d.ts +24 -2
  89. package/browser/push_data.d.ts.map +1 -0
  90. package/browser/script.d.ts +33 -8
  91. package/browser/script.d.ts.map +1 -0
  92. package/browser/script_number.d.ts +17 -0
  93. package/browser/script_number.d.ts.map +1 -0
  94. package/browser/script_signature.d.ts +23 -5
  95. package/browser/script_signature.d.ts.map +1 -0
  96. package/browser/transaction.d.ts +160 -18
  97. package/browser/transaction.d.ts.map +1 -0
  98. package/browser/types.d.ts +36 -38
  99. package/browser/types.d.ts.map +1 -0
  100. package/browser/workers/WorkerSigningPool.d.ts +143 -0
  101. package/browser/workers/WorkerSigningPool.d.ts.map +1 -0
  102. package/browser/workers/WorkerSigningPool.node.d.ts +116 -0
  103. package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -0
  104. package/browser/workers/ecc-bundle.d.ts +25 -0
  105. package/browser/workers/ecc-bundle.d.ts.map +1 -0
  106. package/browser/workers/index.d.ts +91 -0
  107. package/browser/workers/index.d.ts.map +1 -0
  108. package/browser/workers/psbt-parallel.d.ts +88 -0
  109. package/browser/workers/psbt-parallel.d.ts.map +1 -0
  110. package/browser/workers/signing-worker.d.ts +37 -0
  111. package/browser/workers/signing-worker.d.ts.map +1 -0
  112. package/browser/workers/types.d.ts +365 -0
  113. package/browser/workers/types.d.ts.map +1 -0
  114. package/build/address.d.ts +58 -11
  115. package/build/address.d.ts.map +1 -0
  116. package/build/address.js +82 -25
  117. package/build/address.js.map +1 -0
  118. package/build/bech32utils.d.ts +9 -1
  119. package/build/bech32utils.d.ts.map +1 -0
  120. package/build/bech32utils.js +10 -2
  121. package/build/bech32utils.js.map +1 -0
  122. package/build/bip66.d.ts +11 -6
  123. package/build/bip66.d.ts.map +1 -0
  124. package/build/bip66.js +32 -3
  125. package/build/bip66.js.map +1 -0
  126. package/build/block.d.ts +117 -11
  127. package/build/block.d.ts.map +1 -0
  128. package/build/block.js +202 -72
  129. package/build/block.js.map +1 -0
  130. package/build/branded.d.ts +20 -0
  131. package/build/branded.d.ts.map +1 -0
  132. package/build/branded.js +7 -0
  133. package/build/branded.js.map +1 -0
  134. package/build/crypto/crypto.d.ts +1 -0
  135. package/build/crypto/crypto.d.ts.map +1 -0
  136. package/build/crypto/crypto.js +1 -0
  137. package/build/crypto/crypto.js.map +1 -0
  138. package/build/crypto.d.ts +46 -7
  139. package/build/crypto.d.ts.map +1 -0
  140. package/build/crypto.js +65 -20
  141. package/build/crypto.js.map +1 -0
  142. package/build/ecc/context.d.ts +135 -0
  143. package/build/ecc/context.d.ts.map +1 -0
  144. package/build/ecc/context.js +232 -0
  145. package/build/ecc/context.js.map +1 -0
  146. package/build/ecc/index.d.ts +11 -0
  147. package/build/ecc/index.d.ts.map +1 -0
  148. package/build/ecc/index.js +11 -0
  149. package/build/ecc/index.js.map +1 -0
  150. package/build/ecc/types.d.ts +134 -0
  151. package/build/ecc/types.d.ts.map +1 -0
  152. package/build/ecc/types.js +8 -0
  153. package/build/ecc/types.js.map +1 -0
  154. package/build/errors.d.ts +124 -0
  155. package/build/errors.d.ts.map +1 -0
  156. package/build/errors.js +155 -0
  157. package/build/errors.js.map +1 -0
  158. package/build/index.d.ts +32 -5
  159. package/build/index.d.ts.map +1 -0
  160. package/build/index.js +26 -3
  161. package/build/index.js.map +1 -0
  162. package/build/io/BinaryReader.d.ts +276 -0
  163. package/build/io/BinaryReader.d.ts.map +1 -0
  164. package/build/io/BinaryReader.js +425 -0
  165. package/build/io/BinaryReader.js.map +1 -0
  166. package/build/io/BinaryWriter.d.ts +391 -0
  167. package/build/io/BinaryWriter.d.ts.map +1 -0
  168. package/build/io/BinaryWriter.js +611 -0
  169. package/build/io/BinaryWriter.js.map +1 -0
  170. package/build/io/MemoryPool.d.ts +220 -0
  171. package/build/io/MemoryPool.d.ts.map +1 -0
  172. package/build/io/MemoryPool.js +309 -0
  173. package/build/io/MemoryPool.js.map +1 -0
  174. package/build/io/base64.d.ts +13 -0
  175. package/build/io/base64.d.ts.map +1 -0
  176. package/build/io/base64.js +20 -0
  177. package/build/io/base64.js.map +1 -0
  178. package/build/io/hex.d.ts +67 -0
  179. package/build/io/hex.d.ts.map +1 -0
  180. package/build/io/hex.js +138 -0
  181. package/build/io/hex.js.map +1 -0
  182. package/build/io/index.d.ts +17 -0
  183. package/build/io/index.d.ts.map +1 -0
  184. package/build/io/index.js +23 -0
  185. package/build/io/index.js.map +1 -0
  186. package/build/io/utils.d.ts +199 -0
  187. package/build/io/utils.d.ts.map +1 -0
  188. package/build/io/utils.js +271 -0
  189. package/build/io/utils.js.map +1 -0
  190. package/build/merkle.d.ts +10 -1
  191. package/build/merkle.d.ts.map +1 -0
  192. package/build/merkle.js +12 -1
  193. package/build/merkle.js.map +1 -0
  194. package/build/networks.d.ts +70 -9
  195. package/build/networks.d.ts.map +1 -0
  196. package/build/networks.js +90 -4
  197. package/build/networks.js.map +1 -0
  198. package/build/opcodes.d.ts +1 -0
  199. package/build/opcodes.d.ts.map +1 -0
  200. package/build/opcodes.js +1 -0
  201. package/build/opcodes.js.map +1 -0
  202. package/build/payments/bip341.d.ts +35 -9
  203. package/build/payments/bip341.d.ts.map +1 -0
  204. package/build/payments/bip341.js +34 -15
  205. package/build/payments/bip341.js.map +1 -0
  206. package/build/payments/embed.d.ts +120 -1
  207. package/build/payments/embed.d.ts.map +1 -0
  208. package/build/payments/embed.js +215 -34
  209. package/build/payments/embed.js.map +1 -0
  210. package/build/payments/index.d.ts +17 -10
  211. package/build/payments/index.d.ts.map +1 -0
  212. package/build/payments/index.js +20 -10
  213. package/build/payments/index.js.map +1 -0
  214. package/build/payments/p2ms.d.ts +159 -1
  215. package/build/payments/p2ms.d.ts.map +1 -0
  216. package/build/payments/p2ms.js +427 -108
  217. package/build/payments/p2ms.js.map +1 -0
  218. package/build/payments/p2op.d.ts +158 -24
  219. package/build/payments/p2op.d.ts.map +1 -0
  220. package/build/payments/p2op.js +379 -93
  221. package/build/payments/p2op.js.map +1 -0
  222. package/build/payments/p2pk.d.ts +162 -1
  223. package/build/payments/p2pk.d.ts.map +1 -0
  224. package/build/payments/p2pk.js +327 -58
  225. package/build/payments/p2pk.js.map +1 -0
  226. package/build/payments/p2pkh.d.ts +185 -1
  227. package/build/payments/p2pkh.d.ts.map +1 -0
  228. package/build/payments/p2pkh.js +467 -114
  229. package/build/payments/p2pkh.js.map +1 -0
  230. package/build/payments/p2sh.d.ts +159 -1
  231. package/build/payments/p2sh.d.ts.map +1 -0
  232. package/build/payments/p2sh.js +500 -150
  233. package/build/payments/p2sh.js.map +1 -0
  234. package/build/payments/p2tr.d.ts +193 -1
  235. package/build/payments/p2tr.d.ts.map +1 -0
  236. package/build/payments/p2tr.js +592 -174
  237. package/build/payments/p2tr.js.map +1 -0
  238. package/build/payments/p2wpkh.d.ts +170 -1
  239. package/build/payments/p2wpkh.d.ts.map +1 -0
  240. package/build/payments/p2wpkh.js +428 -103
  241. package/build/payments/p2wpkh.js.map +1 -0
  242. package/build/payments/p2wsh.d.ts +155 -1
  243. package/build/payments/p2wsh.d.ts.map +1 -0
  244. package/build/payments/p2wsh.js +465 -143
  245. package/build/payments/p2wsh.js.map +1 -0
  246. package/build/payments/types.d.ts +98 -64
  247. package/build/payments/types.d.ts.map +1 -0
  248. package/build/payments/types.js +17 -13
  249. package/build/payments/types.js.map +1 -0
  250. package/build/psbt/bip371.d.ts +35 -9
  251. package/build/psbt/bip371.d.ts.map +1 -0
  252. package/build/psbt/bip371.js +117 -28
  253. package/build/psbt/bip371.js.map +1 -0
  254. package/build/psbt/psbtutils.d.ts +56 -16
  255. package/build/psbt/psbtutils.d.ts.map +1 -0
  256. package/build/psbt/psbtutils.js +71 -16
  257. package/build/psbt/psbtutils.js.map +1 -0
  258. package/build/psbt/types.d.ts +249 -0
  259. package/build/psbt/types.d.ts.map +1 -0
  260. package/build/psbt/types.js +6 -0
  261. package/build/psbt/types.js.map +1 -0
  262. package/build/psbt/utils.d.ts +68 -0
  263. package/build/psbt/utils.d.ts.map +1 -0
  264. package/build/psbt/utils.js +171 -0
  265. package/build/psbt/utils.js.map +1 -0
  266. package/build/psbt/validation.d.ts +88 -0
  267. package/build/psbt/validation.d.ts.map +1 -0
  268. package/build/psbt/validation.js +149 -0
  269. package/build/psbt/validation.js.map +1 -0
  270. package/build/psbt.d.ts +84 -120
  271. package/build/psbt.d.ts.map +1 -0
  272. package/build/psbt.js +406 -413
  273. package/build/psbt.js.map +1 -0
  274. package/build/pubkey.d.ts +27 -6
  275. package/build/pubkey.d.ts.map +1 -0
  276. package/build/pubkey.js +36 -12
  277. package/build/pubkey.js.map +1 -0
  278. package/build/push_data.d.ts +24 -2
  279. package/build/push_data.d.ts.map +1 -0
  280. package/build/push_data.js +44 -12
  281. package/build/push_data.js.map +1 -0
  282. package/build/script.d.ts +33 -8
  283. package/build/script.d.ts.map +1 -0
  284. package/build/script.js +101 -37
  285. package/build/script.js.map +1 -0
  286. package/build/script_number.d.ts +17 -0
  287. package/build/script_number.d.ts.map +1 -0
  288. package/build/script_number.js +19 -0
  289. package/build/script_number.js.map +1 -0
  290. package/build/script_signature.d.ts +23 -5
  291. package/build/script_signature.d.ts.map +1 -0
  292. package/build/script_signature.js +48 -15
  293. package/build/script_signature.js.map +1 -0
  294. package/build/transaction.d.ts +160 -18
  295. package/build/transaction.d.ts.map +1 -0
  296. package/build/transaction.js +443 -176
  297. package/build/transaction.js.map +1 -0
  298. package/build/tsconfig.build.tsbuildinfo +1 -0
  299. package/build/types.d.ts +36 -38
  300. package/build/types.d.ts.map +1 -0
  301. package/build/types.js +169 -57
  302. package/build/types.js.map +1 -0
  303. package/build/workers/WorkerSigningPool.d.ts +174 -0
  304. package/build/workers/WorkerSigningPool.d.ts.map +1 -0
  305. package/build/workers/WorkerSigningPool.js +553 -0
  306. package/build/workers/WorkerSigningPool.js.map +1 -0
  307. package/build/workers/WorkerSigningPool.node.d.ts +124 -0
  308. package/build/workers/WorkerSigningPool.node.d.ts.map +1 -0
  309. package/build/workers/WorkerSigningPool.node.js +753 -0
  310. package/build/workers/WorkerSigningPool.node.js.map +1 -0
  311. package/build/workers/ecc-bundle.d.ts +25 -0
  312. package/build/workers/ecc-bundle.d.ts.map +1 -0
  313. package/build/workers/ecc-bundle.js +25 -0
  314. package/build/workers/ecc-bundle.js.map +1 -0
  315. package/build/workers/index.d.ts +91 -0
  316. package/build/workers/index.d.ts.map +1 -0
  317. package/build/workers/index.js +114 -0
  318. package/build/workers/index.js.map +1 -0
  319. package/build/workers/psbt-parallel.d.ts +117 -0
  320. package/build/workers/psbt-parallel.d.ts.map +1 -0
  321. package/build/workers/psbt-parallel.js +233 -0
  322. package/build/workers/psbt-parallel.js.map +1 -0
  323. package/build/workers/signing-worker.d.ts +37 -0
  324. package/build/workers/signing-worker.d.ts.map +1 -0
  325. package/build/workers/signing-worker.js +350 -0
  326. package/build/workers/signing-worker.js.map +1 -0
  327. package/build/workers/types.d.ts +365 -0
  328. package/build/workers/types.d.ts.map +1 -0
  329. package/build/workers/types.js +60 -0
  330. package/build/workers/types.js.map +1 -0
  331. package/package.json +68 -9
  332. package/scripts/bundle-ecc.ts +111 -0
  333. package/src/address.ts +91 -45
  334. package/src/bech32utils.ts +3 -3
  335. package/src/bip66.ts +34 -24
  336. package/src/block.ts +205 -86
  337. package/src/branded.ts +18 -0
  338. package/src/crypto.ts +64 -26
  339. package/src/ecc/context.ts +280 -0
  340. package/src/ecc/index.ts +14 -0
  341. package/src/ecc/types.ts +147 -0
  342. package/src/ecpair.d.ts +99 -0
  343. package/src/errors.ts +163 -0
  344. package/src/index.ts +112 -9
  345. package/src/io/BinaryReader.ts +461 -0
  346. package/src/io/BinaryWriter.ts +696 -0
  347. package/src/io/MemoryPool.ts +343 -0
  348. package/src/io/base64.ts +20 -0
  349. package/src/io/hex.ts +155 -0
  350. package/src/io/index.ts +41 -0
  351. package/src/io/utils.ts +283 -0
  352. package/src/merkle.ts +14 -9
  353. package/src/networks.ts +9 -9
  354. package/src/payments/bip341.ts +32 -33
  355. package/src/payments/embed.ts +244 -41
  356. package/src/payments/index.ts +12 -10
  357. package/src/payments/p2ms.ts +497 -118
  358. package/src/payments/p2op.ts +432 -134
  359. package/src/payments/p2pk.ts +370 -72
  360. package/src/payments/p2pkh.ts +524 -130
  361. package/src/payments/p2sh.ts +572 -169
  362. package/src/payments/p2tr.ts +686 -194
  363. package/src/payments/p2wpkh.ts +482 -105
  364. package/src/payments/p2wsh.ts +524 -162
  365. package/src/payments/types.ts +80 -66
  366. package/src/psbt/bip371.ts +72 -51
  367. package/src/psbt/psbtutils.ts +39 -40
  368. package/src/psbt/types.ts +324 -0
  369. package/src/psbt/utils.ts +188 -0
  370. package/src/psbt/validation.ts +185 -0
  371. package/src/psbt.ts +608 -827
  372. package/src/pubkey.ts +22 -23
  373. package/src/push_data.ts +18 -16
  374. package/src/script.ts +81 -66
  375. package/src/script_number.ts +6 -6
  376. package/src/script_signature.ts +33 -36
  377. package/src/transaction.ts +462 -239
  378. package/src/types.ts +229 -100
  379. package/src/workers/WorkerSigningPool.node.ts +887 -0
  380. package/src/workers/WorkerSigningPool.ts +666 -0
  381. package/src/workers/ecc-bundle.ts +26 -0
  382. package/src/workers/index.ts +165 -0
  383. package/src/workers/psbt-parallel.ts +327 -0
  384. package/src/workers/signing-worker.ts +353 -0
  385. package/src/workers/types.ts +417 -0
  386. package/test/address.spec.ts +9 -6
  387. package/test/bitcoin.core.spec.ts +16 -17
  388. package/test/block.spec.ts +8 -7
  389. package/test/bufferutils.spec.ts +228 -214
  390. package/test/crypto.spec.ts +19 -11
  391. package/test/fixtures/p2pk.json +0 -8
  392. package/test/fixtures/p2pkh.json +1 -1
  393. package/test/fixtures/p2sh.json +1 -1
  394. package/test/fixtures/script.json +1 -1
  395. package/test/fixtures/transaction.json +2 -2
  396. package/test/integration/_regtest.ts +25 -0
  397. package/test/integration/addresses.spec.ts +4 -3
  398. package/test/integration/bip32.spec.ts +2 -1
  399. package/test/integration/blocks.spec.ts +1 -1
  400. package/test/integration/cltv.spec.ts +18 -16
  401. package/test/integration/csv.spec.ts +37 -64
  402. package/test/integration/payments.spec.ts +5 -3
  403. package/test/integration/taproot.spec.ts +76 -83
  404. package/test/integration/transactions.spec.ts +38 -35
  405. package/test/payments.spec.ts +35 -13
  406. package/test/payments.utils.ts +17 -16
  407. package/test/psbt.spec.ts +111 -100
  408. package/test/script.spec.ts +11 -10
  409. package/test/script_signature.spec.ts +9 -11
  410. package/test/taproot-cache.spec.ts +694 -0
  411. package/test/transaction.spec.ts +32 -40
  412. package/test/types.spec.ts +74 -29
  413. package/test/workers-pool.spec.ts +963 -0
  414. package/test/workers-signing.spec.ts +635 -0
  415. package/test/workers.spec.ts +1390 -0
  416. package/tsconfig.base.json +34 -18
  417. package/tsconfig.browser.json +15 -0
  418. package/tsconfig.build.json +5 -0
  419. package/tsconfig.json +5 -14
  420. package/typedoc.json +29 -0
  421. package/vite.config.browser.ts +3 -42
  422. package/vitest.config.integration.ts +2 -0
  423. package/browser/bufferutils.d.ts +0 -34
  424. package/browser/chunks/crypto-BhCpKpek.js +0 -2033
  425. package/browser/chunks/payments-B1wlSccx.js +0 -1089
  426. package/browser/chunks/psbt-BCNk7JUx.js +0 -4055
  427. package/browser/chunks/script-DyPItFEl.js +0 -318
  428. package/browser/chunks/transaction-C_UbhMGn.js +0 -432
  429. package/browser/chunks/utils-DNZi-T5W.js +0 -761
  430. package/browser/ecc_lib.d.ts +0 -3
  431. package/browser/hooks/AdvancedSignatureManager.d.ts +0 -16
  432. package/browser/hooks/HookedSigner.d.ts +0 -4
  433. package/browser/hooks/SignatureManager.d.ts +0 -13
  434. package/browser/payments/lazy.d.ts +0 -2
  435. package/browser/typeforce.d.ts +0 -38
  436. package/build/bufferutils.d.ts +0 -34
  437. package/build/bufferutils.js +0 -141
  438. package/build/ecc_lib.d.ts +0 -3
  439. package/build/ecc_lib.js +0 -61
  440. package/build/hooks/AdvancedSignatureManager.d.ts +0 -16
  441. package/build/hooks/AdvancedSignatureManager.js +0 -52
  442. package/build/hooks/HookedSigner.d.ts +0 -4
  443. package/build/hooks/HookedSigner.js +0 -64
  444. package/build/hooks/SignatureManager.d.ts +0 -13
  445. package/build/hooks/SignatureManager.js +0 -45
  446. package/build/payments/lazy.d.ts +0 -2
  447. package/build/payments/lazy.js +0 -28
  448. package/build/tsconfig.tsbuildinfo +0 -1
  449. package/src/bufferutils.ts +0 -188
  450. package/src/ecc_lib.ts +0 -94
  451. package/src/hooks/AdvancedSignatureManager.ts +0 -104
  452. package/src/hooks/HookedSigner.ts +0 -108
  453. package/src/hooks/SignatureManager.ts +0 -84
  454. package/src/payments/lazy.ts +0 -28
  455. package/src/typeforce.d.ts +0 -38
  456. package/tsconfig.webpack.json +0 -18
@@ -1,18 +1,16 @@
1
- import { BufferReader, BufferWriter, reverseBuffer, varuint } from './bufferutils.js';
1
+ import { alloc, BinaryReader, BinaryWriter, fromHex, reverse, toHex, varuint } from './io/index.js';
2
2
  import * as bcrypto from './crypto.js';
3
3
  import * as bscript from './script.js';
4
4
  import { opcodes } from './script.js';
5
- import * as types from './types.js';
5
+ import type { Bytes32, Satoshi, Script } from './types.js';
6
6
 
7
- const { typeforce } = types;
8
-
9
- function varSliceSize(someScript: Buffer): number {
7
+ function varSliceSize(someScript: Uint8Array): number {
10
8
  const length = someScript.length;
11
9
 
12
10
  return varuint.encodingLength(length) + length;
13
11
  }
14
12
 
15
- function vectorSize(someVector: Buffer[]): number {
13
+ function vectorSize(someVector: Uint8Array[]): number {
16
14
  const length = someVector.length;
17
15
 
18
16
  return (
@@ -23,46 +21,55 @@ function vectorSize(someVector: Buffer[]): number {
23
21
  );
24
22
  }
25
23
 
26
- const EMPTY_BUFFER: Buffer = Buffer.allocUnsafe(0);
27
- const EMPTY_WITNESS: Buffer[] = [];
28
- const ZERO: Buffer = Buffer.from(
29
- '0000000000000000000000000000000000000000000000000000000000000000',
30
- 'hex',
31
- );
32
- const ONE: Buffer = Buffer.from(
33
- '0000000000000000000000000000000000000000000000000000000000000001',
34
- 'hex',
35
- );
36
- const VALUE_UINT64_MAX: Buffer = Buffer.from('ffffffffffffffff', 'hex');
37
- const BLANK_OUTPUT: BlankOutput = {
38
- script: EMPTY_BUFFER,
39
- valueBuffer: VALUE_UINT64_MAX,
40
- };
41
-
42
- function isOutput(out: Output | BlankOutput): out is Output {
43
- return 'value' in out;
44
- }
24
+ const EMPTY_BYTES = new Uint8Array(0) as Script;
25
+ const EMPTY_WITNESS: Uint8Array[] = [];
26
+ const ZERO = fromHex('0000000000000000000000000000000000000000000000000000000000000000') as Bytes32;
27
+ const ONE = fromHex('0000000000000000000000000000000000000000000000000000000000000001') as Bytes32;
45
28
 
46
- export interface Output {
47
- script: Buffer;
48
- value: number;
29
+ /** Maximum value for SIGHASH_SINGLE blank outputs (0xFFFFFFFFFFFFFFFF) */
30
+ const BLANK_OUTPUT_VALUE = 0xffffffffffffffffn as Satoshi;
31
+
32
+ /**
33
+ * Cache for Taproot sighash intermediate values.
34
+ * These are identical for all inputs with SIGHASH_ALL, so compute once and reuse.
35
+ */
36
+ export interface TaprootHashCache {
37
+ readonly hashPrevouts: Bytes32;
38
+ readonly hashAmounts: Bytes32;
39
+ readonly hashScriptPubKeys: Bytes32;
40
+ readonly hashSequences: Bytes32;
41
+ readonly hashOutputs: Bytes32;
49
42
  }
50
43
 
51
- interface BlankOutput {
52
- script: Buffer;
53
- valueBuffer: Buffer;
44
+ export interface Output {
45
+ readonly script: Script;
46
+ readonly value: Satoshi;
54
47
  }
55
48
 
56
49
  export interface Input {
57
- hash: Buffer;
58
- index: number;
59
- script: Buffer;
50
+ readonly hash: Bytes32;
51
+ readonly index: number;
52
+ script: Script;
60
53
  sequence: number;
61
- witness: Buffer[];
54
+ witness: Uint8Array[];
62
55
  }
63
56
 
64
57
  /**
65
58
  * Represents a Bitcoin transaction.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { Transaction, fromHex } from '@btc-vision/bitcoin';
63
+ *
64
+ * // Parse a transaction from hex
65
+ * const tx = Transaction.fromHex('0100000001...');
66
+ *
67
+ * // Create a new transaction
68
+ * const newTx = new Transaction();
69
+ * newTx.version = 2;
70
+ * newTx.addInput(prevTxHash, 0);
71
+ * newTx.addOutput(scriptPubKey, 50000n);
72
+ * ```
66
73
  */
67
74
  export class Transaction {
68
75
  static readonly DEFAULT_SEQUENCE = 0xffffffff;
@@ -85,10 +92,17 @@ export class Transaction {
85
92
  ins: Input[] = [];
86
93
  outs: Output[] = [];
87
94
 
88
- static fromBuffer(buffer: Buffer, _NO_STRICT?: boolean): Transaction {
89
- const bufferReader = new BufferReader(buffer);
95
+ /**
96
+ * Parse a transaction from a Uint8Array buffer.
97
+ *
98
+ * @param buffer - The raw transaction bytes
99
+ * @param _NO_STRICT - If true, allow extra data after transaction
100
+ * @returns Parsed Transaction instance
101
+ */
102
+ static fromBuffer(buffer: Uint8Array, _NO_STRICT?: boolean): Transaction {
103
+ const bufferReader = new BinaryReader(buffer);
90
104
  const tx = new Transaction();
91
- tx.version = bufferReader.readInt32();
105
+ tx.version = bufferReader.readInt32LE();
92
106
 
93
107
  const marker = bufferReader.readUInt8();
94
108
  const flag = bufferReader.readUInt8();
@@ -105,10 +119,10 @@ export class Transaction {
105
119
 
106
120
  const vinLen = bufferReader.readVarInt();
107
121
  for (let i = 0; i < vinLen; ++i) {
108
- const hash = bufferReader.readSlice(32);
109
- const index = bufferReader.readUInt32();
110
- const script = bufferReader.readVarSlice();
111
- const sequence = bufferReader.readUInt32();
122
+ const hash = bufferReader.readBytes(32) as Bytes32;
123
+ const index = bufferReader.readUInt32LE();
124
+ const script = bufferReader.readVarBytes() as Script;
125
+ const sequence = bufferReader.readUInt32LE();
112
126
 
113
127
  tx.ins.push({
114
128
  hash: hash,
@@ -122,21 +136,21 @@ export class Transaction {
122
136
  const voutLen = bufferReader.readVarInt();
123
137
  for (let i = 0; i < voutLen; ++i) {
124
138
  tx.outs.push({
125
- value: bufferReader.readUInt64(),
126
- script: bufferReader.readVarSlice(),
139
+ value: bufferReader.readUInt64LE() as Satoshi,
140
+ script: bufferReader.readVarBytes() as Script,
127
141
  });
128
142
  }
129
143
 
130
144
  if (hasWitnesses) {
131
145
  for (let i = 0; i < vinLen; ++i) {
132
- tx.ins[i].witness = bufferReader.readVector();
146
+ tx.ins[i]!.witness = bufferReader.readVector();
133
147
  }
134
148
 
135
149
  // was this pointless?
136
150
  if (!tx.hasWitnesses()) throw new Error('Transaction has superfluous witness data');
137
151
  }
138
152
 
139
- tx.locktime = bufferReader.readUInt32();
153
+ tx.locktime = bufferReader.readUInt32LE();
140
154
 
141
155
  if (_NO_STRICT) return tx;
142
156
  if (bufferReader.offset !== buffer.length)
@@ -145,34 +159,61 @@ export class Transaction {
145
159
  return tx;
146
160
  }
147
161
 
162
+ /**
163
+ * Parse a transaction from a hex string.
164
+ *
165
+ * @param hex - The transaction as a hex string
166
+ * @returns Parsed Transaction instance
167
+ */
148
168
  static fromHex(hex: string): Transaction {
149
- return Transaction.fromBuffer(Buffer.from(hex, 'hex'), false);
169
+ return Transaction.fromBuffer(fromHex(hex), false);
150
170
  }
151
171
 
152
- static isCoinbaseHash(buffer: Buffer): boolean {
153
- typeforce(types.Hash256bit, buffer);
172
+ /**
173
+ * Check if a hash is a coinbase hash (all zeros).
174
+ *
175
+ * @param hash - 32-byte hash to check
176
+ * @returns true if hash is all zeros (coinbase)
177
+ */
178
+ static isCoinbaseHash(hash: Bytes32): boolean {
179
+ if (hash.length !== 32) {
180
+ throw new TypeError('Expected 32-byte hash');
181
+ }
154
182
  for (let i = 0; i < 32; ++i) {
155
- if (buffer[i] !== 0) return false;
183
+ if (hash[i] !== 0) return false;
156
184
  }
157
185
  return true;
158
186
  }
159
187
 
160
188
  isCoinbase(): boolean {
161
- return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash);
189
+ return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0]!.hash);
162
190
  }
163
191
 
164
- addInput(hash: Buffer, index: number, sequence?: number, scriptSig?: Buffer): number {
165
- typeforce(
166
- types.tuple(
167
- types.Hash256bit,
168
- types.UInt32,
169
- types.maybe(types.UInt32),
170
- types.maybe(types.Buffer),
171
- ),
172
- [hash, index, sequence, scriptSig],
173
- );
192
+ /**
193
+ * Add an input to this transaction.
194
+ *
195
+ * @param hash - 32-byte hash of the previous transaction
196
+ * @param index - Output index in the previous transaction
197
+ * @param sequence - Sequence number (defaults to 0xffffffff)
198
+ * @param scriptSig - Input script (defaults to empty)
199
+ * @returns The index of the newly added input
200
+ */
201
+ addInput(hash: Bytes32, index: number, sequence?: number, scriptSig?: Script): number {
202
+ if (hash.length !== 32) {
203
+ throw new TypeError('Expected 32-byte hash');
204
+ }
205
+ if (!Number.isInteger(index) || index < 0 || index > 0xffffffff) {
206
+ throw new TypeError('Expected unsigned 32-bit integer for index');
207
+ }
208
+ if (
209
+ sequence !== undefined &&
210
+ sequence !== null &&
211
+ (!Number.isInteger(sequence) || sequence < 0 || sequence > 0xffffffff)
212
+ ) {
213
+ throw new TypeError('Expected unsigned 32-bit integer for sequence');
214
+ }
174
215
 
175
- if (types.Null(sequence)) {
216
+ if (sequence === undefined || sequence === null) {
176
217
  sequence = Transaction.DEFAULT_SEQUENCE;
177
218
  }
178
219
 
@@ -181,15 +222,27 @@ export class Transaction {
181
222
  this.ins.push({
182
223
  hash,
183
224
  index,
184
- script: scriptSig || EMPTY_BUFFER,
185
- sequence: sequence as number,
225
+ script: scriptSig || EMPTY_BYTES,
226
+ sequence: sequence,
186
227
  witness: EMPTY_WITNESS,
187
228
  }) - 1
188
229
  );
189
230
  }
190
231
 
191
- addOutput(scriptPubKey: Buffer, value: number): number {
192
- typeforce(types.tuple(types.Buffer, types.Satoshi), [scriptPubKey, value]);
232
+ /**
233
+ * Add an output to this transaction.
234
+ *
235
+ * @param scriptPubKey - Output script (locking script)
236
+ * @param value - Output value in satoshis (bigint)
237
+ * @returns The index of the newly added output
238
+ */
239
+ addOutput(scriptPubKey: Script, value: Satoshi): number {
240
+ if (!(scriptPubKey instanceof Uint8Array)) {
241
+ throw new TypeError('Expected Uint8Array for scriptPubKey');
242
+ }
243
+ if (typeof value !== 'bigint' || value < 0n || value > 0x7fffffffffffffffn) {
244
+ throw new TypeError('Expected bigint satoshi value (0 to 2^63-1)');
245
+ }
193
246
 
194
247
  // Add the output and return the output's index
195
248
  return (
@@ -269,13 +322,22 @@ export class Transaction {
269
322
  * This method copies the transaction, makes the necessary changes based on the
270
323
  * hashType, and then hashes the result.
271
324
  * This hash can then be used to sign the provided transaction input.
325
+ *
326
+ * @param inIndex - Index of the input being signed
327
+ * @param prevOutScript - The script of the output being spent
328
+ * @param hashType - Signature hash type
329
+ * @returns 32-byte hash for signing
272
330
  */
273
- hashForSignature(inIndex: number, prevOutScript: Buffer, hashType: number): Buffer {
274
- typeforce(types.tuple(types.UInt32, types.Buffer, /* types.UInt8 */ types.Number), [
275
- inIndex,
276
- prevOutScript,
277
- hashType,
278
- ]);
331
+ hashForSignature(inIndex: number, prevOutScript: Script, hashType: number): Bytes32 {
332
+ if (!Number.isInteger(inIndex) || inIndex < 0) {
333
+ throw new TypeError('Expected non-negative integer for inIndex');
334
+ }
335
+ if (!(prevOutScript instanceof Uint8Array)) {
336
+ throw new TypeError('Expected Uint8Array for prevOutScript');
337
+ }
338
+ if (!Number.isInteger(hashType)) {
339
+ throw new TypeError('Expected integer for hashType');
340
+ }
279
341
 
280
342
  // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L29
281
343
  if (inIndex >= this.ins.length) return ONE;
@@ -310,9 +372,12 @@ export class Transaction {
310
372
  // truncate outputs after
311
373
  txTmp.outs.length = inIndex + 1;
312
374
 
313
- // "blank" outputs before
375
+ // "blank" outputs before (value = 0xFFFFFFFFFFFFFFFF, empty script)
314
376
  for (let i = 0; i < inIndex; i++) {
315
- (txTmp.outs as (Output | BlankOutput)[])[i] = BLANK_OUTPUT;
377
+ txTmp.outs[i] = {
378
+ script: EMPTY_BYTES,
379
+ value: BLANK_OUTPUT_VALUE,
380
+ };
316
381
  }
317
382
 
318
383
  // ignore sequence numbers (except at inIndex)
@@ -325,44 +390,63 @@ export class Transaction {
325
390
 
326
391
  // SIGHASH_ANYONECANPAY: ignore inputs entirely?
327
392
  if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
328
- txTmp.ins = [txTmp.ins[inIndex]];
329
- txTmp.ins[0].script = ourScript;
393
+ txTmp.ins = [txTmp.ins[inIndex]!];
394
+ txTmp.ins[0]!.script = ourScript;
330
395
 
331
396
  // SIGHASH_ALL: only ignore input scripts
332
397
  } else {
333
398
  // "blank" others input scripts
334
399
  txTmp.ins.forEach((input) => {
335
- input.script = EMPTY_BUFFER;
400
+ input.script = EMPTY_BYTES;
336
401
  });
337
- txTmp.ins[inIndex].script = ourScript;
402
+ txTmp.ins[inIndex]!.script = ourScript;
338
403
  }
339
404
 
340
405
  // serialize and hash
341
- const buffer: Buffer = Buffer.allocUnsafe(txTmp.byteLength(false) + 4);
342
- buffer.writeInt32LE(hashType, buffer.length - 4);
343
- txTmp.__toBuffer(buffer, 0, false);
406
+ const buffer: Uint8Array = alloc(txTmp.byteLength(false) + 4);
407
+ const writer = new BinaryWriter(buffer, txTmp.byteLength(false));
408
+ writer.writeInt32LE(hashType);
409
+ txTmp.#toBuffer(buffer, 0, false);
344
410
 
345
- return bcrypto.hash256(buffer);
411
+ return bcrypto.hash256(buffer) as Bytes32;
346
412
  }
347
413
 
414
+ /**
415
+ * Hash transaction for signing a Taproot (witness v1) input.
416
+ *
417
+ * @param inIndex - Index of the input being signed
418
+ * @param prevOutScripts - Scripts of all inputs being spent
419
+ * @param values - Values of all inputs being spent (bigint satoshis)
420
+ * @param hashType - Signature hash type
421
+ * @param leafHash - Optional leaf hash for script path spending
422
+ * @param annex - Optional annex data
423
+ * @returns 32-byte hash for signing
424
+ */
348
425
  hashForWitnessV1(
349
426
  inIndex: number,
350
- prevOutScripts: Buffer[],
351
- values: number[],
427
+ prevOutScripts: readonly Script[],
428
+ values: readonly Satoshi[],
352
429
  hashType: number,
353
- leafHash?: Buffer,
354
- annex?: Buffer,
355
- ): Buffer {
430
+ leafHash?: Bytes32,
431
+ annex?: Uint8Array,
432
+ taprootCache?: TaprootHashCache,
433
+ ): Bytes32 {
356
434
  // https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#common-signature-message
357
- typeforce(
358
- types.tuple(
359
- types.UInt32,
360
- typeforce.arrayOf(types.Buffer),
361
- typeforce.arrayOf(types.Satoshi),
362
- types.UInt32,
363
- ),
364
- [inIndex, prevOutScripts, values, hashType],
365
- );
435
+ if (!Number.isInteger(inIndex) || inIndex < 0 || inIndex > 0xffffffff) {
436
+ throw new TypeError('Expected unsigned 32-bit integer for inIndex');
437
+ }
438
+ if (
439
+ !Array.isArray(prevOutScripts) ||
440
+ !prevOutScripts.every((s) => s instanceof Uint8Array)
441
+ ) {
442
+ throw new TypeError('Expected array of Uint8Array for prevOutScripts');
443
+ }
444
+ if (!Array.isArray(values) || !values.every((v) => typeof v === 'bigint')) {
445
+ throw new TypeError('Expected array of bigint for values');
446
+ }
447
+ if (!Number.isInteger(hashType) || hashType < 0 || hashType > 0xffffffff) {
448
+ throw new TypeError('Expected unsigned 32-bit integer for hashType');
449
+ }
366
450
 
367
451
  if (values.length !== this.ins.length || prevOutScripts.length !== this.ins.length) {
368
452
  throw new Error('Must supply prevout script and value for all inputs');
@@ -379,56 +463,70 @@ export class Transaction {
379
463
  const isNone = outputType === Transaction.SIGHASH_NONE;
380
464
  const isSingle = outputType === Transaction.SIGHASH_SINGLE;
381
465
 
382
- let hashPrevouts = EMPTY_BUFFER;
383
- let hashAmounts = EMPTY_BUFFER;
384
- let hashScriptPubKeys = EMPTY_BUFFER;
385
- let hashSequences = EMPTY_BUFFER;
386
- let hashOutputs = EMPTY_BUFFER;
466
+ let hashPrevouts: Uint8Array = EMPTY_BYTES;
467
+ let hashAmounts: Uint8Array = EMPTY_BYTES;
468
+ let hashScriptPubKeys: Uint8Array = EMPTY_BYTES;
469
+ let hashSequences: Uint8Array = EMPTY_BYTES;
470
+ let hashOutputs: Uint8Array = EMPTY_BYTES;
387
471
 
472
+ // Use cache if provided (for SIGHASH_ALL, these are identical for all inputs)
388
473
  if (!isAnyoneCanPay) {
389
- let bufferWriter = BufferWriter.withCapacity(36 * this.ins.length);
390
- this.ins.forEach((txIn) => {
391
- bufferWriter.writeSlice(txIn.hash);
392
- bufferWriter.writeUInt32(txIn.index);
393
- });
394
- hashPrevouts = bcrypto.sha256(bufferWriter.end());
395
-
396
- bufferWriter = BufferWriter.withCapacity(8 * this.ins.length);
397
- values.forEach((value) => bufferWriter.writeUInt64(value));
398
- hashAmounts = bcrypto.sha256(bufferWriter.end());
399
-
400
- bufferWriter = BufferWriter.withCapacity(
401
- prevOutScripts.map(varSliceSize).reduce((a, b) => a + b),
402
- );
403
- prevOutScripts.forEach((prevOutScript) => bufferWriter.writeVarSlice(prevOutScript));
404
- hashScriptPubKeys = bcrypto.sha256(bufferWriter.end());
405
-
406
- bufferWriter = BufferWriter.withCapacity(4 * this.ins.length);
407
- this.ins.forEach((txIn) => bufferWriter.writeUInt32(txIn.sequence));
408
- hashSequences = bcrypto.sha256(bufferWriter.end());
474
+ if (taprootCache) {
475
+ hashPrevouts = taprootCache.hashPrevouts;
476
+ hashAmounts = taprootCache.hashAmounts;
477
+ hashScriptPubKeys = taprootCache.hashScriptPubKeys;
478
+ hashSequences = taprootCache.hashSequences;
479
+ } else {
480
+ let bufferWriter = new BinaryWriter(36 * this.ins.length);
481
+ this.ins.forEach((txIn) => {
482
+ bufferWriter.writeBytes(txIn.hash);
483
+ bufferWriter.writeUInt32LE(txIn.index);
484
+ });
485
+ hashPrevouts = bcrypto.sha256(bufferWriter.finish());
486
+
487
+ bufferWriter = new BinaryWriter(8 * this.ins.length);
488
+ values.forEach((value) => bufferWriter.writeUInt64LE(value));
489
+ hashAmounts = bcrypto.sha256(bufferWriter.finish());
490
+
491
+ bufferWriter = new BinaryWriter(
492
+ prevOutScripts.map(varSliceSize).reduce((a, b) => a + b),
493
+ );
494
+ prevOutScripts.forEach((prevOutScript) =>
495
+ bufferWriter.writeVarBytes(prevOutScript),
496
+ );
497
+ hashScriptPubKeys = bcrypto.sha256(bufferWriter.finish());
498
+
499
+ bufferWriter = new BinaryWriter(4 * this.ins.length);
500
+ this.ins.forEach((txIn) => bufferWriter.writeUInt32LE(txIn.sequence));
501
+ hashSequences = bcrypto.sha256(bufferWriter.finish());
502
+ }
409
503
  }
410
504
 
411
505
  if (!(isNone || isSingle)) {
412
- if (!this.outs.length)
413
- throw new Error('Add outputs to the transaction before signing.');
414
- const txOutsSize = this.outs
415
- .map((output) => 8 + varSliceSize(output.script))
416
- .reduce((a, b) => a + b);
417
- const bufferWriter = BufferWriter.withCapacity(txOutsSize);
418
-
419
- this.outs.forEach((out) => {
420
- bufferWriter.writeUInt64(out.value);
421
- bufferWriter.writeVarSlice(out.script);
422
- });
423
-
424
- hashOutputs = bcrypto.sha256(bufferWriter.end());
506
+ if (taprootCache) {
507
+ hashOutputs = taprootCache.hashOutputs;
508
+ } else {
509
+ if (!this.outs.length)
510
+ throw new Error('Add outputs to the transaction before signing.');
511
+ const txOutsSize = this.outs
512
+ .map((output) => 8 + varSliceSize(output.script))
513
+ .reduce((a, b) => a + b);
514
+ const bufferWriter = new BinaryWriter(txOutsSize);
515
+
516
+ this.outs.forEach((out) => {
517
+ bufferWriter.writeUInt64LE(out.value);
518
+ bufferWriter.writeVarBytes(out.script);
519
+ });
520
+
521
+ hashOutputs = bcrypto.sha256(bufferWriter.finish());
522
+ }
425
523
  } else if (isSingle && inIndex < this.outs.length) {
426
- const output = this.outs[inIndex];
524
+ const output = this.outs[inIndex]!;
427
525
 
428
- const bufferWriter = BufferWriter.withCapacity(8 + varSliceSize(output.script));
429
- bufferWriter.writeUInt64(output.value);
430
- bufferWriter.writeVarSlice(output.script);
431
- hashOutputs = bcrypto.sha256(bufferWriter.end());
526
+ const bufferWriter = new BinaryWriter(8 + varSliceSize(output.script));
527
+ bufferWriter.writeUInt64LE(output.value);
528
+ bufferWriter.writeVarBytes(output.script);
529
+ hashOutputs = bcrypto.sha256(bufferWriter.finish());
432
530
  }
433
531
 
434
532
  const spendType = (leafHash ? 2 : 0) + (annex ? 1 : 0);
@@ -443,82 +541,159 @@ export class Transaction {
443
541
  (isNone ? 32 : 0) +
444
542
  (annex ? 32 : 0) +
445
543
  (leafHash ? 37 : 0);
446
- const sigMsgWriter = BufferWriter.withCapacity(sigMsgSize);
544
+ const sigMsgWriter = new BinaryWriter(sigMsgSize);
447
545
 
448
546
  sigMsgWriter.writeUInt8(hashType);
449
547
  // Transaction
450
- sigMsgWriter.writeInt32(this.version);
451
- sigMsgWriter.writeUInt32(this.locktime);
452
- sigMsgWriter.writeSlice(hashPrevouts);
453
- sigMsgWriter.writeSlice(hashAmounts);
454
- sigMsgWriter.writeSlice(hashScriptPubKeys);
455
- sigMsgWriter.writeSlice(hashSequences);
548
+ sigMsgWriter.writeInt32LE(this.version);
549
+ sigMsgWriter.writeUInt32LE(this.locktime);
550
+ sigMsgWriter.writeBytes(hashPrevouts);
551
+ sigMsgWriter.writeBytes(hashAmounts);
552
+ sigMsgWriter.writeBytes(hashScriptPubKeys);
553
+ sigMsgWriter.writeBytes(hashSequences);
456
554
  if (!(isNone || isSingle)) {
457
- sigMsgWriter.writeSlice(hashOutputs);
555
+ sigMsgWriter.writeBytes(hashOutputs);
458
556
  }
459
557
  // Input
460
558
  sigMsgWriter.writeUInt8(spendType);
461
559
  if (isAnyoneCanPay) {
462
- const input = this.ins[inIndex];
463
- sigMsgWriter.writeSlice(input.hash);
464
- sigMsgWriter.writeUInt32(input.index);
465
- sigMsgWriter.writeUInt64(values[inIndex]);
466
- sigMsgWriter.writeVarSlice(prevOutScripts[inIndex]);
467
- sigMsgWriter.writeUInt32(input.sequence);
560
+ const input = this.ins[inIndex]!;
561
+ sigMsgWriter.writeBytes(input.hash);
562
+ sigMsgWriter.writeUInt32LE(input.index);
563
+ sigMsgWriter.writeUInt64LE(values[inIndex]!);
564
+ sigMsgWriter.writeVarBytes(prevOutScripts[inIndex]!);
565
+ sigMsgWriter.writeUInt32LE(input.sequence);
468
566
  } else {
469
- sigMsgWriter.writeUInt32(inIndex);
567
+ sigMsgWriter.writeUInt32LE(inIndex);
470
568
  }
471
569
  if (annex) {
472
- const bufferWriter = BufferWriter.withCapacity(varSliceSize(annex));
473
- bufferWriter.writeVarSlice(annex);
474
- sigMsgWriter.writeSlice(bcrypto.sha256(bufferWriter.end()));
570
+ const bufferWriter = new BinaryWriter(varSliceSize(annex));
571
+ bufferWriter.writeVarBytes(annex);
572
+ sigMsgWriter.writeBytes(bcrypto.sha256(bufferWriter.finish()));
475
573
  }
476
574
  // Output
477
575
  if (isSingle) {
478
- sigMsgWriter.writeSlice(hashOutputs);
576
+ sigMsgWriter.writeBytes(hashOutputs);
479
577
  }
480
578
  // BIP342 extension
481
579
  if (leafHash) {
482
- sigMsgWriter.writeSlice(leafHash);
580
+ sigMsgWriter.writeBytes(leafHash);
483
581
  sigMsgWriter.writeUInt8(0);
484
- sigMsgWriter.writeUInt32(0xffffffff);
582
+ sigMsgWriter.writeUInt32LE(0xffffffff);
485
583
  }
486
584
 
487
585
  // Extra zero byte because:
488
586
  // https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-19
489
- return bcrypto.taggedHash(
490
- 'TapSighash',
491
- Buffer.concat([Buffer.from([0x00]), sigMsgWriter.end()]),
492
- );
587
+ const prefix = new Uint8Array([0x00]);
588
+ const sigMsg = sigMsgWriter.finish();
589
+ const combined = new Uint8Array(1 + sigMsg.length);
590
+ combined.set(prefix);
591
+ combined.set(sigMsg, 1);
592
+ return bcrypto.taggedHash('TapSighash', combined) as Bytes32;
593
+ }
594
+
595
+ /**
596
+ * Pre-compute intermediate hashes for Taproot signing.
597
+ * Call this once before signing multiple inputs to avoid O(n^2) performance.
598
+ *
599
+ * @param prevOutScripts - Array of previous output scripts for all inputs
600
+ * @param values - Array of previous output values for all inputs
601
+ * @returns Cache object to pass to hashForWitnessV1
602
+ */
603
+ getTaprootHashCache(
604
+ prevOutScripts: readonly Script[],
605
+ values: readonly Satoshi[],
606
+ ): TaprootHashCache {
607
+ // hashPrevouts
608
+ let bufferWriter = new BinaryWriter(36 * this.ins.length);
609
+ for (const txIn of this.ins) {
610
+ bufferWriter.writeBytes(txIn.hash);
611
+ bufferWriter.writeUInt32LE(txIn.index);
612
+ }
613
+ const hashPrevouts = bcrypto.sha256(bufferWriter.finish());
614
+
615
+ // hashAmounts
616
+ bufferWriter = new BinaryWriter(8 * values.length);
617
+ for (const value of values) {
618
+ bufferWriter.writeUInt64LE(value);
619
+ }
620
+ const hashAmounts = bcrypto.sha256(bufferWriter.finish());
621
+
622
+ // hashScriptPubKeys - compute size without intermediate array
623
+ let scriptPubKeysSize = 0;
624
+ for (const script of prevOutScripts) {
625
+ scriptPubKeysSize += varSliceSize(script);
626
+ }
627
+ bufferWriter = new BinaryWriter(scriptPubKeysSize);
628
+ for (const script of prevOutScripts) {
629
+ bufferWriter.writeVarBytes(script);
630
+ }
631
+ const hashScriptPubKeys = bcrypto.sha256(bufferWriter.finish());
632
+
633
+ // hashSequences
634
+ bufferWriter = new BinaryWriter(4 * this.ins.length);
635
+ for (const txIn of this.ins) {
636
+ bufferWriter.writeUInt32LE(txIn.sequence);
637
+ }
638
+ const hashSequences = bcrypto.sha256(bufferWriter.finish());
639
+
640
+ // hashOutputs - compute size without intermediate array
641
+ let txOutsSize = 0;
642
+ for (const out of this.outs) {
643
+ txOutsSize += 8 + varSliceSize(out.script);
644
+ }
645
+ bufferWriter = new BinaryWriter(txOutsSize);
646
+ for (const out of this.outs) {
647
+ bufferWriter.writeUInt64LE(out.value);
648
+ bufferWriter.writeVarBytes(out.script);
649
+ }
650
+ const hashOutputs = this.outs.length ? bcrypto.sha256(bufferWriter.finish()) : ZERO;
651
+
652
+ return { hashPrevouts, hashAmounts, hashScriptPubKeys, hashSequences, hashOutputs };
493
653
  }
494
654
 
655
+ /**
656
+ * Hash transaction for signing a SegWit v0 (P2WPKH/P2WSH) input.
657
+ *
658
+ * @param inIndex - Index of the input being signed
659
+ * @param prevOutScript - The script of the output being spent
660
+ * @param value - Value of the output being spent (bigint satoshis)
661
+ * @param hashType - Signature hash type
662
+ * @returns 32-byte hash for signing
663
+ */
495
664
  hashForWitnessV0(
496
665
  inIndex: number,
497
- prevOutScript: Buffer,
498
- value: number,
666
+ prevOutScript: Script,
667
+ value: Satoshi,
499
668
  hashType: number,
500
- ): Buffer {
501
- typeforce(types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32), [
502
- inIndex,
503
- prevOutScript,
504
- value,
505
- hashType,
506
- ]);
669
+ ): Bytes32 {
670
+ if (!Number.isInteger(inIndex) || inIndex < 0 || inIndex > 0xffffffff) {
671
+ throw new TypeError('Expected unsigned 32-bit integer for inIndex');
672
+ }
673
+ if (!(prevOutScript instanceof Uint8Array)) {
674
+ throw new TypeError('Expected Uint8Array for prevOutScript');
675
+ }
676
+ if (typeof value !== 'bigint') {
677
+ throw new TypeError('Expected bigint for value');
678
+ }
679
+ if (!Number.isInteger(hashType) || hashType < 0 || hashType > 0xffffffff) {
680
+ throw new TypeError('Expected unsigned 32-bit integer for hashType');
681
+ }
507
682
 
508
- let tbuffer: Buffer = Buffer.from([]);
509
- let bufferWriter: BufferWriter;
683
+ let tbuffer: Uint8Array;
684
+ let bufferWriter: BinaryWriter;
510
685
 
511
686
  let hashOutputs = ZERO;
512
687
  let hashPrevouts = ZERO;
513
688
  let hashSequence = ZERO;
514
689
 
515
690
  if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
516
- tbuffer = Buffer.allocUnsafe(36 * this.ins.length);
517
- bufferWriter = new BufferWriter(tbuffer, 0);
691
+ tbuffer = alloc(36 * this.ins.length);
692
+ bufferWriter = new BinaryWriter(tbuffer, 0);
518
693
 
519
694
  this.ins.forEach((txIn) => {
520
- bufferWriter.writeSlice(txIn.hash);
521
- bufferWriter.writeUInt32(txIn.index);
695
+ bufferWriter.writeBytes(txIn.hash);
696
+ bufferWriter.writeUInt32LE(txIn.index);
522
697
  });
523
698
 
524
699
  hashPrevouts = bcrypto.hash256(tbuffer);
@@ -529,11 +704,11 @@ export class Transaction {
529
704
  (hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
530
705
  (hashType & 0x1f) !== Transaction.SIGHASH_NONE
531
706
  ) {
532
- tbuffer = Buffer.allocUnsafe(4 * this.ins.length);
533
- bufferWriter = new BufferWriter(tbuffer, 0);
707
+ tbuffer = alloc(4 * this.ins.length);
708
+ bufferWriter = new BinaryWriter(tbuffer, 0);
534
709
 
535
710
  this.ins.forEach((txIn) => {
536
- bufferWriter.writeUInt32(txIn.sequence);
711
+ bufferWriter.writeUInt32LE(txIn.sequence);
537
712
  });
538
713
 
539
714
  hashSequence = bcrypto.hash256(tbuffer);
@@ -547,85 +722,138 @@ export class Transaction {
547
722
  return sum + 8 + varSliceSize(output.script);
548
723
  }, 0);
549
724
 
550
- tbuffer = Buffer.allocUnsafe(txOutsSize);
551
- bufferWriter = new BufferWriter(tbuffer, 0);
725
+ tbuffer = alloc(txOutsSize);
726
+ bufferWriter = new BinaryWriter(tbuffer, 0);
552
727
 
553
728
  this.outs.forEach((out) => {
554
- bufferWriter.writeUInt64(out.value);
555
- bufferWriter.writeVarSlice(out.script);
729
+ bufferWriter.writeUInt64LE(out.value);
730
+ bufferWriter.writeVarBytes(out.script);
556
731
  });
557
732
 
558
733
  hashOutputs = bcrypto.hash256(tbuffer);
559
734
  } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) {
560
- const output = this.outs[inIndex];
735
+ const output = this.outs[inIndex]!;
561
736
 
562
- tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script));
563
- bufferWriter = new BufferWriter(tbuffer, 0);
564
- bufferWriter.writeUInt64(output.value);
565
- bufferWriter.writeVarSlice(output.script);
737
+ tbuffer = alloc(8 + varSliceSize(output.script));
738
+ bufferWriter = new BinaryWriter(tbuffer, 0);
739
+ bufferWriter.writeUInt64LE(output.value);
740
+ bufferWriter.writeVarBytes(output.script);
566
741
 
567
742
  hashOutputs = bcrypto.hash256(tbuffer);
568
743
  }
569
744
 
570
- tbuffer = Buffer.allocUnsafe(156 + varSliceSize(prevOutScript));
571
- bufferWriter = new BufferWriter(tbuffer, 0);
572
-
573
- const input = this.ins[inIndex];
574
- bufferWriter.writeInt32(this.version);
575
- bufferWriter.writeSlice(hashPrevouts);
576
- bufferWriter.writeSlice(hashSequence);
577
- bufferWriter.writeSlice(input.hash);
578
- bufferWriter.writeUInt32(input.index);
579
- bufferWriter.writeVarSlice(prevOutScript);
580
- bufferWriter.writeUInt64(value);
581
- bufferWriter.writeUInt32(input.sequence);
582
- bufferWriter.writeSlice(hashOutputs);
583
- bufferWriter.writeUInt32(this.locktime);
584
- bufferWriter.writeUInt32(hashType);
585
- return bcrypto.hash256(tbuffer);
745
+ tbuffer = alloc(156 + varSliceSize(prevOutScript));
746
+ bufferWriter = new BinaryWriter(tbuffer, 0);
747
+
748
+ const input = this.ins[inIndex]!;
749
+ bufferWriter.writeInt32LE(this.version);
750
+ bufferWriter.writeBytes(hashPrevouts);
751
+ bufferWriter.writeBytes(hashSequence);
752
+ bufferWriter.writeBytes(input.hash);
753
+ bufferWriter.writeUInt32LE(input.index);
754
+ bufferWriter.writeVarBytes(prevOutScript);
755
+ bufferWriter.writeUInt64LE(value);
756
+ bufferWriter.writeUInt32LE(input.sequence);
757
+ bufferWriter.writeBytes(hashOutputs);
758
+ bufferWriter.writeUInt32LE(this.locktime);
759
+ bufferWriter.writeUInt32LE(hashType);
760
+ return bcrypto.hash256(tbuffer) as Bytes32;
586
761
  }
587
762
 
588
- getHash(forWitness?: boolean): Buffer {
763
+ /**
764
+ * Get the transaction hash.
765
+ *
766
+ * @param forWitness - If true, include witness data (wtxid)
767
+ * @returns 32-byte transaction hash
768
+ */
769
+ getHash(forWitness?: boolean): Bytes32 {
589
770
  // wtxid for coinbase is always 32 bytes of 0x00
590
- if (forWitness && this.isCoinbase()) return Buffer.alloc(32, 0);
591
- return bcrypto.hash256(this.__toBuffer(undefined, undefined, forWitness));
771
+ if (forWitness && this.isCoinbase()) return new Uint8Array(32) as Bytes32;
772
+ return bcrypto.hash256(this.#toBuffer(undefined, undefined, forWitness)) as Bytes32;
592
773
  }
593
774
 
775
+ /**
776
+ * Get the transaction ID (txid) as a hex string.
777
+ *
778
+ * @returns Transaction ID in reversed hex format
779
+ */
594
780
  getId(): string {
595
781
  // transaction hash's are displayed in reverse order
596
- return reverseBuffer(this.getHash(false)).toString('hex');
782
+ return toHex(reverse(this.getHash(false)));
597
783
  }
598
784
 
599
- toBuffer(buffer?: Buffer, initialOffset?: number): Buffer {
600
- return this.__toBuffer(buffer, initialOffset, true);
785
+ /**
786
+ * Serialize the transaction to a Uint8Array buffer.
787
+ *
788
+ * @param buffer - Optional pre-allocated buffer
789
+ * @param initialOffset - Optional starting offset in buffer
790
+ * @returns Serialized transaction bytes
791
+ */
792
+ toBuffer(buffer?: Uint8Array, initialOffset?: number): Uint8Array {
793
+ return this.#toBuffer(buffer, initialOffset, true);
601
794
  }
602
795
 
796
+ /**
797
+ * Serialize the transaction to a hex string.
798
+ *
799
+ * @returns Transaction as hex string
800
+ */
603
801
  toHex(): string {
604
- return this.toBuffer(undefined, undefined).toString('hex');
802
+ return toHex(this.toBuffer(undefined, undefined));
605
803
  }
606
804
 
607
- setInputScript(index: number, scriptSig: Buffer): void {
608
- typeforce(types.tuple(types.Number, types.Buffer), [index, scriptSig]);
805
+ /**
806
+ * Set the input script for a specific input.
807
+ *
808
+ * @param index - Input index
809
+ * @param scriptSig - The script to set
810
+ */
811
+ setInputScript(index: number, scriptSig: Script): void {
812
+ if (!Number.isInteger(index) || index < 0) {
813
+ throw new TypeError('Expected non-negative integer for index');
814
+ }
815
+ if (!(scriptSig instanceof Uint8Array)) {
816
+ throw new TypeError('Expected Uint8Array for scriptSig');
817
+ }
609
818
 
610
- this.ins[index].script = scriptSig;
819
+ this.ins[index]!.script = scriptSig;
611
820
  }
612
821
 
613
- setWitness(index: number, witness: Buffer[]): void {
614
- typeforce(types.tuple(types.Number, [types.Buffer]), [index, witness]);
822
+ /**
823
+ * Set the witness data for a specific input.
824
+ *
825
+ * @param index - Input index
826
+ * @param witness - Array of witness elements
827
+ */
828
+ setWitness(index: number, witness: Uint8Array[]): void {
829
+ if (!Number.isInteger(index) || index < 0) {
830
+ throw new TypeError('Expected non-negative integer for index');
831
+ }
832
+ if (!Array.isArray(witness) || !witness.every((w) => w instanceof Uint8Array)) {
833
+ throw new TypeError('Expected array of Uint8Array for witness');
834
+ }
615
835
 
616
- this.ins[index].witness = witness;
836
+ this.ins[index]!.witness = witness;
617
837
  }
618
838
 
619
- private __toBuffer(
620
- buffer?: Buffer,
839
+ /**
840
+ * Internal method to serialize the transaction.
841
+ *
842
+ * @param buffer - Optional pre-allocated buffer
843
+ * @param initialOffset - Optional starting offset
844
+ * @param _ALLOW_WITNESS - Whether to include witness data
845
+ * @returns Serialized transaction bytes
846
+ */
847
+ #toBuffer(
848
+ buffer?: Uint8Array,
621
849
  initialOffset?: number,
622
850
  _ALLOW_WITNESS: boolean = false,
623
- ): Buffer {
624
- if (!buffer) buffer = Buffer.allocUnsafe(this.byteLength(_ALLOW_WITNESS)) as Buffer;
851
+ ): Uint8Array {
852
+ if (!buffer) buffer = alloc(this.byteLength(_ALLOW_WITNESS));
625
853
 
626
- const bufferWriter = new BufferWriter(buffer, initialOffset || 0);
854
+ const bufferWriter = new BinaryWriter(buffer, initialOffset || 0);
627
855
 
628
- bufferWriter.writeInt32(this.version);
856
+ bufferWriter.writeInt32LE(this.version);
629
857
 
630
858
  const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
631
859
 
@@ -637,21 +865,16 @@ export class Transaction {
637
865
  bufferWriter.writeVarInt(this.ins.length);
638
866
 
639
867
  this.ins.forEach((txIn) => {
640
- bufferWriter.writeSlice(txIn.hash);
641
- bufferWriter.writeUInt32(txIn.index);
642
- bufferWriter.writeVarSlice(txIn.script);
643
- bufferWriter.writeUInt32(txIn.sequence);
868
+ bufferWriter.writeBytes(txIn.hash);
869
+ bufferWriter.writeUInt32LE(txIn.index);
870
+ bufferWriter.writeVarBytes(txIn.script);
871
+ bufferWriter.writeUInt32LE(txIn.sequence);
644
872
  });
645
873
 
646
874
  bufferWriter.writeVarInt(this.outs.length);
647
- (this.outs as (Output | BlankOutput)[]).forEach((txOut) => {
648
- if (isOutput(txOut)) {
649
- bufferWriter.writeUInt64(txOut.value);
650
- } else {
651
- bufferWriter.writeSlice(txOut.valueBuffer);
652
- }
653
-
654
- bufferWriter.writeVarSlice(txOut.script);
875
+ this.outs.forEach((txOut) => {
876
+ bufferWriter.writeUInt64LE(txOut.value);
877
+ bufferWriter.writeVarBytes(txOut.script);
655
878
  });
656
879
 
657
880
  if (hasWitnesses) {
@@ -660,7 +883,7 @@ export class Transaction {
660
883
  });
661
884
  }
662
885
 
663
- bufferWriter.writeUInt32(this.locktime);
886
+ bufferWriter.writeUInt32LE(this.locktime);
664
887
 
665
888
  // avoid slicing unless necessary
666
889
  if (initialOffset !== undefined) return buffer.subarray(initialOffset, bufferWriter.offset);