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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) 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 +56 -9
  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 +12482 -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 +57 -10
  115. package/build/address.d.ts.map +1 -0
  116. package/build/address.js +80 -24
  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 +204 -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 +36 -9
  203. package/build/payments/bip341.d.ts.map +1 -0
  204. package/build/payments/bip341.js +35 -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 -152
  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 +429 -104
  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 +466 -144
  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 +113 -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 +411 -412
  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 +100 -36
  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 +175 -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 +66 -8
  332. package/scripts/bundle-ecc.ts +111 -0
  333. package/src/address.ts +81 -44
  334. package/src/bech32utils.ts +3 -3
  335. package/src/bip66.ts +34 -24
  336. package/src/block.ts +196 -84
  337. package/src/branded.ts +18 -0
  338. package/src/crypto.ts +64 -26
  339. package/src/ecc/context.ts +277 -0
  340. package/src/ecc/index.ts +14 -0
  341. package/src/ecc/types.ts +154 -0
  342. package/src/ecpair.d.ts +99 -0
  343. package/src/errors.ts +163 -0
  344. package/src/index.ts +113 -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 +34 -33
  355. package/src/payments/embed.ts +244 -41
  356. package/src/payments/index.ts +12 -10
  357. package/src/payments/p2ms.ts +490 -118
  358. package/src/payments/p2op.ts +431 -133
  359. package/src/payments/p2pk.ts +370 -72
  360. package/src/payments/p2pkh.ts +524 -130
  361. package/src/payments/p2sh.ts +572 -172
  362. package/src/payments/p2tr.ts +686 -194
  363. package/src/payments/p2wpkh.ts +484 -107
  364. package/src/payments/p2wsh.ts +526 -164
  365. package/src/payments/types.ts +80 -66
  366. package/src/psbt/bip371.ts +68 -51
  367. package/src/psbt/psbtutils.ts +39 -40
  368. package/src/psbt/types.ts +331 -0
  369. package/src/psbt/utils.ts +188 -0
  370. package/src/psbt/validation.ts +192 -0
  371. package/src/psbt.ts +566 -809
  372. package/src/pubkey.ts +22 -23
  373. package/src/push_data.ts +18 -16
  374. package/src/script.ts +82 -64
  375. package/src/script_number.ts +6 -6
  376. package/src/script_signature.ts +33 -36
  377. package/src/transaction.ts +458 -238
  378. package/src/types.ts +231 -100
  379. package/src/workers/WorkerSigningPool.node.ts +887 -0
  380. package/src/workers/WorkerSigningPool.ts +670 -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 +332 -0
  384. package/src/workers/signing-worker.ts +353 -0
  385. package/src/workers/types.ts +413 -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/vite.config.browser.ts +3 -42
  421. package/vitest.config.integration.ts +2 -0
  422. package/browser/bufferutils.d.ts +0 -34
  423. package/browser/chunks/crypto-BhCpKpek.js +0 -2033
  424. package/browser/chunks/payments-B1wlSccx.js +0 -1089
  425. package/browser/chunks/psbt-BCNk7JUx.js +0 -4055
  426. package/browser/chunks/script-DyPItFEl.js +0 -318
  427. package/browser/chunks/transaction-C_UbhMGn.js +0 -432
  428. package/browser/chunks/utils-DNZi-T5W.js +0 -761
  429. package/browser/ecc_lib.d.ts +0 -3
  430. package/browser/hooks/AdvancedSignatureManager.d.ts +0 -16
  431. package/browser/hooks/HookedSigner.d.ts +0 -4
  432. package/browser/hooks/SignatureManager.d.ts +0 -13
  433. package/browser/payments/lazy.d.ts +0 -2
  434. package/browser/typeforce.d.ts +0 -38
  435. package/build/bufferutils.d.ts +0 -34
  436. package/build/bufferutils.js +0 -141
  437. package/build/ecc_lib.d.ts +0 -3
  438. package/build/ecc_lib.js +0 -61
  439. package/build/hooks/AdvancedSignatureManager.d.ts +0 -16
  440. package/build/hooks/AdvancedSignatureManager.js +0 -52
  441. package/build/hooks/HookedSigner.d.ts +0 -4
  442. package/build/hooks/HookedSigner.js +0 -64
  443. package/build/hooks/SignatureManager.d.ts +0 -13
  444. package/build/hooks/SignatureManager.js +0 -45
  445. package/build/payments/lazy.d.ts +0 -2
  446. package/build/payments/lazy.js +0 -28
  447. package/build/tsconfig.tsbuildinfo +0 -1
  448. package/src/bufferutils.ts +0 -188
  449. package/src/ecc_lib.ts +0 -94
  450. package/src/hooks/AdvancedSignatureManager.ts +0 -104
  451. package/src/hooks/HookedSigner.ts +0 -108
  452. package/src/hooks/SignatureManager.ts +0 -84
  453. package/src/payments/lazy.ts +0 -28
  454. package/src/typeforce.d.ts +0 -38
  455. package/tsconfig.webpack.json +0 -18
@@ -1,10 +1,26 @@
1
+ /**
2
+ * Pay-to-Taproot (P2TR) payment class.
3
+ *
4
+ * P2TR is the Taproot output type (BIP341). It supports both key-path spending
5
+ * (single signature) and script-path spending (merkle tree of scripts).
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
1
10
  import { bech32m } from 'bech32';
2
- import { Buffer as NBuffer } from 'buffer';
3
11
  import { fromBech32 } from '../bech32utils.js';
4
- import { getEccLib } from '../ecc_lib.js';
5
- import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
12
+ import { getEccLib } from '../ecc/context.js';
13
+ import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
6
14
  import * as bscript from '../script.js';
7
- import { isTaptree, stacksEqual, TAPLEAF_VERSION_MASK, typeforce as typef } from '../types.js';
15
+ import {
16
+ stacksEqual,
17
+ TAPLEAF_VERSION_MASK,
18
+ type Bytes32,
19
+ type Script,
20
+ type SchnorrSignature,
21
+ type Taptree,
22
+ type XOnlyPublicKey,
23
+ } from '../types.js';
8
24
  import {
9
25
  findScriptPath,
10
26
  LEAF_VERSION_TAPSCRIPT,
@@ -12,298 +28,774 @@ import {
12
28
  tapleafHash,
13
29
  toHashTree,
14
30
  tweakKey,
31
+ type HashTree,
15
32
  } from './bip341.js';
16
- import { P2TRPayment, PaymentOpts, PaymentType } from './types.js';
17
- import * as lazy from './lazy.js';
33
+ import { concat, equals } from '../io/index.js';
34
+ import { PaymentType, type P2TRPayment, type PaymentOpts, type ScriptRedeem } from './types.js';
18
35
 
19
36
  const OPS = bscript.opcodes;
20
37
  const TAPROOT_WITNESS_VERSION = 0x01;
21
38
  const ANNEX_PREFIX = 0x50;
22
39
 
23
40
  /**
24
- * Creates a Pay-to-Taproot (P2TR) payment object.
41
+ * Pay-to-Taproot (P2TR) payment class.
42
+ *
43
+ * Creates locking scripts of the form: `OP_1 {x-only pubkey}`
44
+ *
45
+ * Key-path spending witness: `[signature]`
46
+ * Script-path spending witness: `[script inputs..., script, control block]`
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { P2TR } from '@btc-vision/bitcoin';
51
+ *
52
+ * // Key-path only (no scripts)
53
+ * const keyOnly = P2TR.fromInternalPubkey(internalPubkey);
54
+ * console.log(keyOnly.address); // bc1p... address
25
55
  *
26
- * @param a - The payment object containing the necessary data for P2TR.
27
- * @param opts - Optional payment options.
28
- * @returns The P2TR payment object.
29
- * @throws {TypeError} If the provided data is invalid or insufficient.
56
+ * // With script tree
57
+ * const withScripts = P2TR.fromInternalPubkey(internalPubkey, scriptTree);
58
+ *
59
+ * // Decode an existing output
60
+ * const decoded = P2TR.fromOutput(scriptPubKey);
61
+ * console.log(decoded.pubkey); // 32-byte x-only pubkey
62
+ * ```
30
63
  */
31
- export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPayment {
32
- if (
33
- !a.address &&
34
- !a.output &&
35
- !a.pubkey &&
36
- !a.internalPubkey &&
37
- !(a.witness && a.witness.length > 1)
38
- )
39
- throw new TypeError('Not enough data');
64
+ export class P2TR {
65
+ // Static public fields
66
+ static readonly NAME = PaymentType.P2TR;
67
+
68
+ // Private instance fields
69
+ readonly #network: Network;
70
+ readonly #opts: Required<PaymentOpts>;
71
+
72
+ // Input data (provided by user)
73
+ #inputAddress?: string | undefined;
74
+ #inputPubkey?: Uint8Array | undefined;
75
+ #inputInternalPubkey?: Uint8Array | undefined;
76
+ #inputHash?: Uint8Array | undefined;
77
+ #inputScriptTree?: Taptree | undefined;
78
+ #inputSignature?: Uint8Array | undefined;
79
+ #inputOutput?: Uint8Array | undefined;
80
+ #inputWitness?: Uint8Array[] | undefined;
81
+ #inputRedeem?: ScriptRedeem | undefined;
82
+ #inputRedeemVersion?: number | undefined;
83
+
84
+ // Cached computed values
85
+ #address?: string | undefined;
86
+ #pubkey?: XOnlyPublicKey | undefined;
87
+ #internalPubkey?: XOnlyPublicKey | undefined;
88
+ #hash?: Bytes32 | undefined;
89
+ #signature?: SchnorrSignature | undefined;
90
+ #output?: Script | undefined;
91
+ #redeem?: ScriptRedeem | undefined;
92
+ #redeemVersion?: number | undefined;
93
+ #witness?: Uint8Array[] | undefined;
94
+
95
+ // Cache flags
96
+ #addressComputed = false;
97
+ #pubkeyComputed = false;
98
+ #internalPubkeyComputed = false;
99
+ #hashComputed = false;
100
+ #signatureComputed = false;
101
+ #outputComputed = false;
102
+ #redeemComputed = false;
103
+ #redeemVersionComputed = false;
104
+ #witnessComputed = false;
105
+
106
+ // Decoded address cache
107
+ #decodedAddress?: { version: number; prefix: string; data: Uint8Array } | undefined;
108
+ #decodedAddressComputed = false;
109
+
110
+ // Witness without annex
111
+ #witnessWithoutAnnex?: Uint8Array[] | undefined;
112
+ #witnessWithoutAnnexComputed = false;
113
+
114
+ // Hash tree cache
115
+ #hashTree?: HashTree | undefined;
116
+ #hashTreeComputed = false;
117
+
118
+ /**
119
+ * Creates a new P2TR payment instance.
120
+ *
121
+ * @param params - Payment parameters
122
+ * @param params.address - Bech32m encoded address (bc1p...)
123
+ * @param params.pubkey - x-only output pubkey (32 bytes)
124
+ * @param params.internalPubkey - x-only internal pubkey (32 bytes)
125
+ * @param params.hash - Merkle root (32 bytes, or empty for key-path only)
126
+ * @param params.scriptTree - Full script tree definition
127
+ * @param params.signature - Schnorr signature (for key-path spending)
128
+ * @param params.output - The scriptPubKey
129
+ * @param params.witness - The witness stack
130
+ * @param params.redeem - Redeem script for script-path spending
131
+ * @param params.redeemVersion - Leaf version (defaults to LEAF_VERSION_TAPSCRIPT)
132
+ * @param params.network - Network parameters (defaults to mainnet)
133
+ * @param opts - Payment options
134
+ * @param opts.validate - Whether to validate inputs (default: true)
135
+ *
136
+ * @throws {TypeError} If validation is enabled and data is invalid
137
+ */
138
+ constructor(
139
+ params: {
140
+ address?: string | undefined;
141
+ pubkey?: Uint8Array | undefined;
142
+ internalPubkey?: Uint8Array | undefined;
143
+ hash?: Uint8Array | undefined;
144
+ scriptTree?: Taptree | undefined;
145
+ signature?: Uint8Array | undefined;
146
+ output?: Uint8Array | undefined;
147
+ witness?: Uint8Array[] | undefined;
148
+ redeem?: ScriptRedeem | undefined;
149
+ redeemVersion?: number | undefined;
150
+ network?: Network | undefined;
151
+ },
152
+ opts?: PaymentOpts,
153
+ ) {
154
+ this.#network = params.network ?? BITCOIN_NETWORK;
155
+ this.#opts = {
156
+ validate: opts?.validate ?? true,
157
+ allowIncomplete: opts?.allowIncomplete ?? false,
158
+ };
40
159
 
41
- opts = Object.assign({ validate: true }, opts || {});
160
+ // Store input data
161
+ this.#inputAddress = params.address;
162
+ this.#inputPubkey = params.pubkey;
163
+ this.#inputInternalPubkey = params.internalPubkey;
164
+ this.#inputHash = params.hash;
165
+ this.#inputScriptTree = params.scriptTree;
166
+ this.#inputSignature = params.signature;
167
+ this.#inputOutput = params.output;
168
+ this.#inputWitness = params.witness;
169
+ this.#inputRedeem = params.redeem;
170
+ this.#inputRedeemVersion = params.redeemVersion;
171
+
172
+ // Validate if requested
173
+ if (this.#opts.validate) {
174
+ this.#validate();
175
+ }
176
+ }
42
177
 
43
- typef(
44
- {
45
- address: typef.maybe(typef.String),
46
- input: typef.maybe(typef.BufferN(0)),
47
- network: typef.maybe(typef.Object),
48
- output: typef.maybe(typef.BufferN(34)),
49
- internalPubkey: typef.maybe(typef.BufferN(32)),
50
- hash: typef.maybe(typef.BufferN(32)), // merkle root hash, the tweak
51
- pubkey: typef.maybe(typef.BufferN(32)), // tweaked with `hash` from `internalPubkey`
52
- signature: typef.maybe(typef.anyOf(typef.BufferN(64), typef.BufferN(65))),
53
- witness: typef.maybe(typef.arrayOf(typef.Buffer)),
54
- scriptTree: typef.maybe(isTaptree),
55
- redeem: typef.maybe({
56
- output: typef.maybe(typef.Buffer), // tapleaf script
57
- redeemVersion: typef.maybe(typef.Number), // tapleaf version
58
- witness: typef.maybe(typef.arrayOf(typef.Buffer)),
59
- }),
60
- redeemVersion: typef.maybe(typef.Number),
61
- },
62
- a,
63
- );
178
+ // Public getters
179
+
180
+ /**
181
+ * Payment type discriminant.
182
+ */
183
+ get name(): typeof PaymentType.P2TR {
184
+ return PaymentType.P2TR;
185
+ }
186
+
187
+ /**
188
+ * Network parameters.
189
+ */
190
+ get network(): Network {
191
+ return this.#network;
192
+ }
64
193
 
65
- const _address = lazy.value(() => {
66
- return fromBech32(a.address!);
67
- });
194
+ /**
195
+ * Bech32m encoded address (bc1p... for mainnet).
196
+ */
197
+ get address(): string | undefined {
198
+ if (!this.#addressComputed) {
199
+ this.#address = this.#computeAddress();
200
+ this.#addressComputed = true;
201
+ }
202
+ return this.#address;
203
+ }
68
204
 
69
- // remove annex if present, ignored by taproot
70
- const _witness = lazy.value(() => {
71
- if (!a.witness || !a.witness.length) return;
72
- if (a.witness.length >= 2 && a.witness[a.witness.length - 1][0] === ANNEX_PREFIX) {
73
- return a.witness.slice(0, -1);
205
+ /**
206
+ * x-only output pubkey (32 bytes).
207
+ * This is the tweaked pubkey that appears in the output.
208
+ */
209
+ get pubkey(): XOnlyPublicKey | undefined {
210
+ if (!this.#pubkeyComputed) {
211
+ this.#pubkey = this.#computePubkey();
212
+ this.#pubkeyComputed = true;
74
213
  }
75
- return a.witness.slice();
76
- });
214
+ return this.#pubkey;
215
+ }
77
216
 
78
- const _hashTree = lazy.value(() => {
79
- if (a.scriptTree) return toHashTree(a.scriptTree);
80
- if (a.hash) return { hash: a.hash };
81
- return;
82
- });
217
+ /**
218
+ * x-only internal pubkey (32 bytes).
219
+ * This is the untweaked pubkey before adding the merkle root tweak.
220
+ */
221
+ get internalPubkey(): XOnlyPublicKey | undefined {
222
+ if (!this.#internalPubkeyComputed) {
223
+ this.#internalPubkey = this.#computeInternalPubkey();
224
+ this.#internalPubkeyComputed = true;
225
+ }
226
+ return this.#internalPubkey;
227
+ }
83
228
 
84
- const network = a.network || BITCOIN_NETWORK;
85
- const o: P2TRPayment = {
86
- name: PaymentType.P2TR,
87
- network,
88
- };
229
+ /**
230
+ * Merkle root hash (32 bytes).
231
+ * Present when a script tree is defined.
232
+ */
233
+ get hash(): Bytes32 | undefined {
234
+ if (!this.#hashComputed) {
235
+ this.#hash = this.#computeHash();
236
+ this.#hashComputed = true;
237
+ }
238
+ return this.#hash;
239
+ }
89
240
 
90
- lazy.prop(o, 'address', () => {
91
- if (!o.pubkey) return;
241
+ /**
242
+ * Schnorr signature (for key-path spending).
243
+ */
244
+ get signature(): SchnorrSignature | undefined {
245
+ if (!this.#signatureComputed) {
246
+ this.#signature = this.#computeSignature();
247
+ this.#signatureComputed = true;
248
+ }
249
+ return this.#signature;
250
+ }
92
251
 
93
- const words = bech32m.toWords(o.pubkey);
252
+ /**
253
+ * The scriptPubKey: `OP_1 {32-byte x-only pubkey}`
254
+ */
255
+ get output(): Script | undefined {
256
+ if (!this.#outputComputed) {
257
+ this.#output = this.#computeOutput();
258
+ this.#outputComputed = true;
259
+ }
260
+ return this.#output;
261
+ }
262
+
263
+ /**
264
+ * Redeem script information (for script-path spending).
265
+ */
266
+ get redeem(): ScriptRedeem | undefined {
267
+ if (!this.#redeemComputed) {
268
+ this.#redeem = this.#computeRedeem();
269
+ this.#redeemComputed = true;
270
+ }
271
+ return this.#redeem;
272
+ }
273
+
274
+ /**
275
+ * Leaf version (defaults to LEAF_VERSION_TAPSCRIPT = 0xc0).
276
+ */
277
+ get redeemVersion(): number {
278
+ if (!this.#redeemVersionComputed) {
279
+ this.#redeemVersion = this.#computeRedeemVersion();
280
+ this.#redeemVersionComputed = true;
281
+ }
282
+ return this.#redeemVersion ?? LEAF_VERSION_TAPSCRIPT;
283
+ }
284
+
285
+ /**
286
+ * Witness stack.
287
+ * Key-path: `[signature]`
288
+ * Script-path: `[script inputs..., script, control block]`
289
+ */
290
+ get witness(): Uint8Array[] | undefined {
291
+ if (!this.#witnessComputed) {
292
+ this.#witness = this.#computeWitness();
293
+ this.#witnessComputed = true;
294
+ }
295
+ return this.#witness;
296
+ }
297
+
298
+ // Static factory methods
299
+
300
+ /**
301
+ * Creates a P2TR payment from an internal pubkey (key-path only).
302
+ *
303
+ * @param internalPubkey - x-only internal pubkey (32 bytes)
304
+ * @param scriptTree - Optional script tree
305
+ * @param network - Network parameters (defaults to mainnet)
306
+ * @returns A new P2TR payment instance
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * // Key-path only
311
+ * const p2tr = P2TR.fromInternalPubkey(internalPubkey);
312
+ *
313
+ * // With script tree
314
+ * const withScripts = P2TR.fromInternalPubkey(internalPubkey, scriptTree);
315
+ * ```
316
+ */
317
+ static fromInternalPubkey(
318
+ internalPubkey: XOnlyPublicKey,
319
+ scriptTree?: Taptree,
320
+ network?: Network,
321
+ ): P2TR {
322
+ return new P2TR({ internalPubkey, scriptTree, network });
323
+ }
324
+
325
+ /**
326
+ * Creates a P2TR payment from a bech32m address.
327
+ *
328
+ * @param address - Bech32m encoded address (bc1p...)
329
+ * @param network - Network parameters (defaults to mainnet)
330
+ * @returns A new P2TR payment instance
331
+ */
332
+ static fromAddress(address: string, network?: Network): P2TR {
333
+ return new P2TR({ address, network });
334
+ }
335
+
336
+ /**
337
+ * Creates a P2TR payment from a scriptPubKey.
338
+ *
339
+ * @param output - The scriptPubKey
340
+ * @param network - Network parameters (defaults to mainnet)
341
+ * @returns A new P2TR payment instance
342
+ */
343
+ static fromOutput(output: Uint8Array, network?: Network): P2TR {
344
+ return new P2TR({ output, network });
345
+ }
346
+
347
+ /**
348
+ * Creates a P2TR payment from a signature (for key-path spending).
349
+ *
350
+ * @param signature - Schnorr signature
351
+ * @param internalPubkey - x-only internal pubkey
352
+ * @param network - Network parameters (defaults to mainnet)
353
+ * @returns A new P2TR payment instance
354
+ */
355
+ static fromSignature(
356
+ signature: SchnorrSignature,
357
+ internalPubkey?: XOnlyPublicKey,
358
+ network?: Network,
359
+ ): P2TR {
360
+ return new P2TR({ signature, internalPubkey, network });
361
+ }
362
+
363
+ // Private helper methods
364
+
365
+ #getDecodedAddress(): { version: number; prefix: string; data: Uint8Array } | undefined {
366
+ if (!this.#decodedAddressComputed) {
367
+ if (this.#inputAddress) {
368
+ const decoded = fromBech32(this.#inputAddress);
369
+ if (decoded) {
370
+ this.#decodedAddress = {
371
+ version: decoded.version,
372
+ prefix: decoded.prefix,
373
+ data: decoded.data,
374
+ };
375
+ }
376
+ }
377
+ this.#decodedAddressComputed = true;
378
+ }
379
+ return this.#decodedAddress;
380
+ }
381
+
382
+ #getWitnessWithoutAnnex(): Uint8Array[] | undefined {
383
+ if (!this.#witnessWithoutAnnexComputed) {
384
+ if (this.#inputWitness && this.#inputWitness.length > 0) {
385
+ // Remove annex if present
386
+ if (
387
+ this.#inputWitness.length >= 2 &&
388
+ this.#inputWitness[this.#inputWitness.length - 1]![0] === ANNEX_PREFIX
389
+ ) {
390
+ this.#witnessWithoutAnnex = this.#inputWitness.slice(0, -1);
391
+ } else {
392
+ this.#witnessWithoutAnnex = this.#inputWitness.slice();
393
+ }
394
+ }
395
+ this.#witnessWithoutAnnexComputed = true;
396
+ }
397
+ return this.#witnessWithoutAnnex;
398
+ }
399
+
400
+ #getHashTree(): HashTree | undefined {
401
+ if (!this.#hashTreeComputed) {
402
+ if (this.#inputScriptTree) {
403
+ this.#hashTree = toHashTree(this.#inputScriptTree);
404
+ } else if (this.#inputHash) {
405
+ this.#hashTree = { hash: this.#inputHash as Bytes32 };
406
+ }
407
+ this.#hashTreeComputed = true;
408
+ }
409
+ return this.#hashTree;
410
+ }
411
+
412
+ // Private computation methods
413
+
414
+ #computeAddress(): string | undefined {
415
+ if (this.#inputAddress) {
416
+ return this.#inputAddress;
417
+ }
418
+ const pk = this.pubkey;
419
+ if (!pk) return undefined;
420
+
421
+ const words = bech32m.toWords(pk);
94
422
  words.unshift(TAPROOT_WITNESS_VERSION);
95
- return bech32m.encode(network.bech32, words);
96
- });
423
+ return bech32m.encode(this.#network.bech32, words);
424
+ }
97
425
 
98
- lazy.prop(o, 'hash', () => {
99
- const hashTree = _hashTree();
100
- if (hashTree) return hashTree.hash;
426
+ #computePubkey(): XOnlyPublicKey | undefined {
427
+ if (this.#inputPubkey) {
428
+ return this.#inputPubkey as XOnlyPublicKey;
429
+ }
430
+ if (this.#inputOutput) {
431
+ return this.#inputOutput.subarray(2) as XOnlyPublicKey;
432
+ }
433
+ if (this.#inputAddress) {
434
+ return this.#getDecodedAddress()?.data as XOnlyPublicKey | undefined;
435
+ }
436
+ const internalPk = this.internalPubkey;
437
+ if (internalPk) {
438
+ const tweakedKey = tweakKey(internalPk, this.hash);
439
+ if (tweakedKey) {
440
+ return tweakedKey.x as XOnlyPublicKey;
441
+ }
442
+ }
443
+ return undefined;
444
+ }
445
+
446
+ #computeInternalPubkey(): XOnlyPublicKey | undefined {
447
+ if (this.#inputInternalPubkey) {
448
+ return this.#inputInternalPubkey as XOnlyPublicKey;
449
+ }
450
+ const witness = this.#getWitnessWithoutAnnex();
451
+ if (witness && witness.length > 1) {
452
+ return witness[witness.length - 1]!.subarray(1, 33) as XOnlyPublicKey;
453
+ }
454
+ return undefined;
455
+ }
101
456
 
102
- const w = _witness();
457
+ #computeHash(): Bytes32 | undefined {
458
+ const hashTree = this.#getHashTree();
459
+ if (hashTree) {
460
+ return hashTree.hash as Bytes32;
461
+ }
462
+
463
+ const w = this.#getWitnessWithoutAnnex();
103
464
  if (w && w.length > 1) {
104
- const controlBlock = w[w.length - 1];
105
- const leafVersion = controlBlock[0] & TAPLEAF_VERSION_MASK;
106
- const script = w[w.length - 2];
465
+ const controlBlock = w[w.length - 1]!;
466
+ const leafVersion = controlBlock[0]! & TAPLEAF_VERSION_MASK;
467
+ const script = w[w.length - 2]!;
107
468
  const leafHash = tapleafHash({
108
469
  output: script,
109
470
  version: leafVersion,
110
471
  });
111
- return rootHashFromPath(controlBlock, leafHash);
472
+ return rootHashFromPath(controlBlock, leafHash) as Bytes32;
112
473
  }
113
474
 
114
475
  return undefined;
115
- });
116
- lazy.prop(o, 'output', () => {
117
- if (!o.pubkey) return;
118
- return bscript.compile([OPS.OP_1, o.pubkey]);
119
- });
120
- lazy.prop(o, 'redeemVersion', () => {
121
- if (a.redeemVersion) return a.redeemVersion;
122
- if (a.redeem && a.redeem.redeemVersion !== undefined && a.redeem.redeemVersion !== null) {
123
- return a.redeem.redeemVersion;
476
+ }
477
+
478
+ #computeSignature(): SchnorrSignature | undefined {
479
+ if (this.#inputSignature) {
480
+ return this.#inputSignature as SchnorrSignature;
481
+ }
482
+ const witness = this.#getWitnessWithoutAnnex();
483
+ if (witness && witness.length === 1) {
484
+ return witness[0] as SchnorrSignature;
485
+ }
486
+ return undefined;
487
+ }
488
+
489
+ #computeOutput(): Script | undefined {
490
+ if (this.#inputOutput) {
491
+ return this.#inputOutput as Script;
124
492
  }
493
+ const pk = this.pubkey;
494
+ if (!pk) return undefined;
125
495
 
126
- return LEAF_VERSION_TAPSCRIPT;
127
- });
128
- lazy.prop(o, 'redeem', () => {
129
- const witness = _witness(); // witness without annex
130
- if (!witness || witness.length < 2) return;
496
+ return bscript.compile([OPS.OP_1, pk]) as Script;
497
+ }
131
498
 
499
+ #computeRedeem(): ScriptRedeem | undefined {
500
+ if (this.#inputRedeem) {
501
+ return this.#inputRedeem;
502
+ }
503
+ const witness = this.#getWitnessWithoutAnnex();
504
+ if (!witness || witness.length < 2) {
505
+ return undefined;
506
+ }
132
507
  return {
133
- output: witness[witness.length - 2],
508
+ output: witness[witness.length - 2] as Script,
134
509
  witness: witness.slice(0, -2),
135
- redeemVersion: witness[witness.length - 1][0] & TAPLEAF_VERSION_MASK,
510
+ redeemVersion: witness[witness.length - 1]![0]! & TAPLEAF_VERSION_MASK,
136
511
  };
137
- });
138
- lazy.prop(o, 'pubkey', () => {
139
- if (a.pubkey) return a.pubkey;
140
- if (a.output) return a.output.subarray(2);
141
- if (a.address) return _address().data;
142
- if (o.internalPubkey) {
143
- const tweakedKey = tweakKey(o.internalPubkey, o.hash);
144
- if (tweakedKey) return tweakedKey.x;
145
- }
146
- });
147
- lazy.prop(o, 'internalPubkey', () => {
148
- if (a.internalPubkey) return a.internalPubkey;
149
- const witness = _witness();
150
- if (witness && witness.length > 1) return witness[witness.length - 1].subarray(1, 33);
151
- });
152
- lazy.prop(o, 'signature', () => {
153
- if (a.signature) return a.signature;
154
- const witness = _witness(); // witness without annex
155
- if (!witness || witness.length !== 1) return;
156
- return witness[0];
157
- });
158
-
159
- lazy.prop(o, 'witness', () => {
160
- if (a.witness) return a.witness;
161
- const hashTree = _hashTree();
162
- if (hashTree && a.redeem && a.redeem.output && a.internalPubkey) {
512
+ }
513
+
514
+ #computeRedeemVersion(): number | undefined {
515
+ if (this.#inputRedeemVersion !== undefined) {
516
+ return this.#inputRedeemVersion;
517
+ }
518
+ if (
519
+ this.#inputRedeem &&
520
+ this.#inputRedeem.redeemVersion !== undefined &&
521
+ this.#inputRedeem.redeemVersion !== null
522
+ ) {
523
+ return this.#inputRedeem.redeemVersion;
524
+ }
525
+ return LEAF_VERSION_TAPSCRIPT;
526
+ }
527
+
528
+ #computeWitness(): Uint8Array[] | undefined {
529
+ if (this.#inputWitness) {
530
+ return this.#inputWitness;
531
+ }
532
+
533
+ const hashTree = this.#getHashTree();
534
+ if (hashTree && this.#inputRedeem?.output && this.#inputInternalPubkey) {
163
535
  const leafHash = tapleafHash({
164
- output: a.redeem.output,
165
- version: o.redeemVersion,
536
+ output: this.#inputRedeem.output,
537
+ version: this.redeemVersion,
166
538
  });
167
539
  const path = findScriptPath(hashTree, leafHash);
168
- if (!path) return;
169
- const outputKey = tweakKey(a.internalPubkey, hashTree.hash);
170
- if (!outputKey) return;
171
- const controlBock = NBuffer.concat(
172
- [NBuffer.from([o.redeemVersion! | outputKey.parity]), a.internalPubkey].concat(
173
- path,
174
- ),
175
- );
176
- return [a.redeem.output, controlBock];
177
- }
178
- if (a.signature) return [a.signature];
179
- });
180
-
181
- // extended validation
182
- if (opts.validate) {
183
- let pubkey: Buffer = NBuffer.from([]);
184
- if (a.address) {
185
- if (network && network.bech32 !== _address().prefix)
540
+ if (!path) return undefined;
541
+
542
+ const outputKey = tweakKey(this.#inputInternalPubkey as XOnlyPublicKey, hashTree.hash);
543
+ if (!outputKey) return undefined;
544
+
545
+ const version = this.redeemVersion ?? 0xc0;
546
+ const controlBlock = concat([
547
+ new Uint8Array([version | outputKey.parity]),
548
+ this.#inputInternalPubkey,
549
+ ...path,
550
+ ]);
551
+ return [this.#inputRedeem.output, controlBlock];
552
+ }
553
+
554
+ if (this.#inputSignature) {
555
+ return [this.#inputSignature];
556
+ }
557
+
558
+ return undefined;
559
+ }
560
+
561
+ // Validation
562
+
563
+ #validate(): void {
564
+ let pubkey: Uint8Array = new Uint8Array(0);
565
+
566
+ if (this.#inputAddress) {
567
+ const addr = this.#getDecodedAddress();
568
+ if (!addr) {
569
+ throw new TypeError('Invalid address');
570
+ }
571
+ if (this.#network && this.#network.bech32 !== addr.prefix) {
186
572
  throw new TypeError('Invalid prefix or Network mismatch');
187
- if (_address().version !== TAPROOT_WITNESS_VERSION)
573
+ }
574
+ if (addr.version !== TAPROOT_WITNESS_VERSION) {
188
575
  throw new TypeError('Invalid address version');
189
- if (_address().data.length !== 32) throw new TypeError('Invalid address data');
190
- pubkey = _address().data;
576
+ }
577
+ if (addr.data.length !== 32) {
578
+ throw new TypeError('Invalid address data');
579
+ }
580
+ pubkey = addr.data;
191
581
  }
192
582
 
193
- if (a.pubkey) {
194
- if (pubkey.length > 0 && !pubkey.equals(a.pubkey))
583
+ if (this.#inputPubkey) {
584
+ if (pubkey.length > 0 && !equals(pubkey, this.#inputPubkey)) {
195
585
  throw new TypeError('Pubkey mismatch');
196
- else pubkey = a.pubkey;
586
+ } else {
587
+ pubkey = this.#inputPubkey;
588
+ }
197
589
  }
198
590
 
199
- if (a.output) {
200
- if (a.output.length !== 34 || a.output[0] !== OPS.OP_1 || a.output[1] !== 0x20)
591
+ if (this.#inputOutput) {
592
+ if (
593
+ this.#inputOutput.length !== 34 ||
594
+ this.#inputOutput[0] !== OPS.OP_1 ||
595
+ this.#inputOutput[1] !== 0x20
596
+ ) {
201
597
  throw new TypeError('Output is invalid');
202
- if (pubkey.length > 0 && !pubkey.equals(a.output.subarray(2)))
598
+ }
599
+ if (pubkey.length > 0 && !equals(pubkey, this.#inputOutput.subarray(2))) {
203
600
  throw new TypeError('Pubkey mismatch');
204
- else pubkey = a.output.subarray(2);
601
+ } else {
602
+ pubkey = this.#inputOutput.subarray(2);
603
+ }
205
604
  }
206
605
 
207
- if (a.internalPubkey) {
208
- const tweakedKey = tweakKey(a.internalPubkey, o.hash);
209
- if (pubkey.length > 0 && !pubkey.equals(tweakedKey!.x))
606
+ if (this.#inputInternalPubkey) {
607
+ const tweakedKey = tweakKey(this.#inputInternalPubkey as XOnlyPublicKey, this.hash);
608
+ if (!tweakedKey) {
609
+ throw new TypeError('Invalid internal pubkey');
610
+ }
611
+ if (pubkey.length > 0 && !equals(pubkey, tweakedKey.x)) {
210
612
  throw new TypeError('Pubkey mismatch');
211
- else pubkey = tweakedKey!.x;
613
+ } else {
614
+ pubkey = tweakedKey.x;
615
+ }
212
616
  }
213
617
 
214
- /*if (pubkey && pubkey.length) {
215
- if (!getEccLib().isXOnlyPoint(pubkey))
216
- throw new TypeError('Invalid pubkey for p2tr');
217
- }*/
618
+ const hashTree = this.#getHashTree();
218
619
 
219
- const hashTree = _hashTree();
220
-
221
- if (a.hash && hashTree) {
222
- if (!a.hash.equals(hashTree.hash)) throw new TypeError('Hash mismatch');
620
+ if (this.#inputHash && hashTree) {
621
+ if (!equals(this.#inputHash, hashTree.hash)) {
622
+ throw new TypeError('Hash mismatch');
623
+ }
223
624
  }
224
625
 
225
- if (a.redeem && a.redeem.output && hashTree) {
626
+ if (this.#inputRedeem?.output && hashTree) {
226
627
  const leafHash = tapleafHash({
227
- output: a.redeem.output,
228
- version: o.redeemVersion,
628
+ output: this.#inputRedeem.output,
629
+ version: this.redeemVersion,
229
630
  });
230
- if (!findScriptPath(hashTree, leafHash))
631
+ if (!findScriptPath(hashTree, leafHash)) {
231
632
  throw new TypeError('Redeem script not in tree');
633
+ }
232
634
  }
233
635
 
234
- const witness = _witness();
636
+ const witness = this.#getWitnessWithoutAnnex();
235
637
 
236
- // compare the provided redeem data with the one computed from witness
237
- if (a.redeem && o.redeem) {
238
- if (a.redeem.redeemVersion) {
239
- if (a.redeem.redeemVersion !== o.redeem.redeemVersion)
638
+ // Compare provided redeem with computed from witness
639
+ if (this.#inputRedeem && this.redeem) {
640
+ if (this.#inputRedeem.redeemVersion) {
641
+ if (this.#inputRedeem.redeemVersion !== this.redeem.redeemVersion) {
240
642
  throw new TypeError('Redeem.redeemVersion and witness mismatch');
643
+ }
241
644
  }
242
645
 
243
- if (a.redeem.output) {
244
- if (bscript.decompile(a.redeem.output)!.length === 0)
646
+ if (this.#inputRedeem.output) {
647
+ const decompiled = bscript.decompile(this.#inputRedeem.output);
648
+ if (!decompiled || decompiled.length === 0) {
245
649
  throw new TypeError('Redeem.output is invalid');
650
+ }
246
651
 
247
- // output redeem is constructed from the witness
248
- if (o.redeem.output && !a.redeem.output.equals(o.redeem.output))
652
+ if (this.redeem.output && !equals(this.#inputRedeem.output, this.redeem.output)) {
249
653
  throw new TypeError('Redeem.output and witness mismatch');
654
+ }
250
655
  }
251
- if (a.redeem.witness) {
252
- if (o.redeem.witness && !stacksEqual(a.redeem.witness, o.redeem.witness))
656
+ if (this.#inputRedeem.witness) {
657
+ if (
658
+ this.redeem.witness &&
659
+ !stacksEqual(this.#inputRedeem.witness, this.redeem.witness)
660
+ ) {
253
661
  throw new TypeError('Redeem.witness and witness mismatch');
662
+ }
254
663
  }
255
664
  }
256
665
 
257
- if (witness && witness.length) {
666
+ if (witness && witness.length > 0) {
258
667
  if (witness.length === 1) {
259
- // key spending
260
- if (a.signature && !a.signature.equals(witness[0]))
668
+ // Key-path spending
669
+ if (this.#inputSignature && !equals(this.#inputSignature!, witness[0]!)) {
261
670
  throw new TypeError('Signature mismatch');
671
+ }
262
672
  } else {
263
- // script path spending
264
- const controlBlock = witness[witness.length - 1];
265
- if (controlBlock.length < 33)
673
+ // Script-path spending
674
+ const controlBlock = witness[witness.length - 1]!;
675
+ if (controlBlock.length < 33) {
266
676
  throw new TypeError(
267
677
  `The control-block length is too small. Got ${controlBlock.length}, expected min 33.`,
268
678
  );
679
+ }
269
680
 
270
- if ((controlBlock.length - 33) % 32 !== 0)
681
+ if ((controlBlock.length - 33) % 32 !== 0) {
271
682
  throw new TypeError(
272
683
  `The control-block length of ${controlBlock.length} is incorrect!`,
273
684
  );
685
+ }
274
686
 
275
687
  const m = (controlBlock.length - 33) / 32;
276
- if (m > 128)
688
+ if (m > 128) {
277
689
  throw new TypeError(`The script path is too long. Got ${m}, expected max 128.`);
690
+ }
278
691
 
279
- const internalPubkey = controlBlock.subarray(1, 33);
280
- if (a.internalPubkey && !a.internalPubkey.equals(internalPubkey))
692
+ const internalPk = controlBlock.subarray(1, 33);
693
+ if (this.#inputInternalPubkey && !equals(this.#inputInternalPubkey!, internalPk)) {
281
694
  throw new TypeError('Internal pubkey mismatch');
695
+ }
282
696
 
283
- if (!getEccLib().isXOnlyPoint(internalPubkey))
697
+ if (!getEccLib().isXOnlyPoint(internalPk)) {
284
698
  throw new TypeError('Invalid internalPubkey for p2tr witness');
699
+ }
285
700
 
286
- const leafVersion = controlBlock[0] & TAPLEAF_VERSION_MASK;
287
- const script = witness[witness.length - 2];
701
+ const leafVersion = controlBlock[0]! & TAPLEAF_VERSION_MASK;
702
+ const script = witness[witness.length - 2]!;
288
703
 
289
704
  const leafHash = tapleafHash({
290
705
  output: script,
291
706
  version: leafVersion,
292
707
  });
293
- const hash = rootHashFromPath(controlBlock, leafHash);
708
+ const computedHash = rootHashFromPath(controlBlock, leafHash);
294
709
 
295
- const outputKey = tweakKey(internalPubkey, hash);
296
- if (!outputKey)
297
- // todo: needs test data
710
+ const outputKey = tweakKey(internalPk as XOnlyPublicKey, computedHash);
711
+ if (!outputKey) {
298
712
  throw new TypeError('Invalid outputKey for p2tr witness');
713
+ }
299
714
 
300
- if (pubkey.length && !pubkey.equals(outputKey.x))
715
+ if (pubkey.length > 0 && !equals(pubkey, outputKey.x)) {
301
716
  throw new TypeError('Pubkey mismatch for p2tr witness');
717
+ }
302
718
 
303
- if (outputKey.parity !== (controlBlock[0] & 1)) throw new Error('Incorrect parity');
719
+ if (outputKey.parity !== (controlBlock[0]! & 1)) {
720
+ throw new Error('Incorrect parity');
721
+ }
304
722
  }
305
723
  }
306
724
  }
307
725
 
308
- return Object.assign(o, a);
726
+ /**
727
+ * Converts to a plain P2TRPayment object for backwards compatibility.
728
+ *
729
+ * @returns A P2TRPayment object
730
+ */
731
+ toPayment(): P2TRPayment {
732
+ return {
733
+ name: this.name,
734
+ network: this.network,
735
+ address: this.address,
736
+ pubkey: this.pubkey,
737
+ internalPubkey: this.internalPubkey,
738
+ hash: this.hash,
739
+ scriptTree: this.#inputScriptTree,
740
+ signature: this.signature,
741
+ output: this.output,
742
+ redeem: this.redeem,
743
+ redeemVersion: this.redeemVersion,
744
+ witness: this.witness,
745
+ };
746
+ }
747
+ }
748
+
749
+ /**
750
+ * Creates a Pay-to-Taproot (P2TR) payment object.
751
+ *
752
+ * This is the legacy factory function for backwards compatibility.
753
+ * For new code, prefer using the P2TR class directly.
754
+ *
755
+ * @param a - The payment object containing the necessary data
756
+ * @param opts - Optional payment options
757
+ * @returns The P2TR payment object
758
+ * @throws {TypeError} If the required data is not provided or if the data is invalid
759
+ *
760
+ * @example
761
+ * ```typescript
762
+ * import { p2tr } from '@btc-vision/bitcoin';
763
+ *
764
+ * // Key-path only
765
+ * const payment = p2tr({ internalPubkey });
766
+ *
767
+ * // With script tree
768
+ * const withScripts = p2tr({ internalPubkey, scriptTree });
769
+ * ```
770
+ */
771
+ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPayment {
772
+ if (
773
+ !a.address &&
774
+ !a.output &&
775
+ !a.pubkey &&
776
+ !a.internalPubkey &&
777
+ !(a.witness && a.witness.length > 1)
778
+ ) {
779
+ throw new TypeError('Not enough data');
780
+ }
781
+
782
+ const instance = new P2TR(
783
+ {
784
+ address: a.address,
785
+ pubkey: a.pubkey,
786
+ internalPubkey: a.internalPubkey,
787
+ hash: a.hash,
788
+ scriptTree: a.scriptTree,
789
+ signature: a.signature,
790
+ output: a.output,
791
+ witness: a.witness,
792
+ redeem: a.redeem,
793
+ redeemVersion: a.redeemVersion,
794
+ network: a.network,
795
+ },
796
+ opts,
797
+ );
798
+
799
+ // Return a merged object for backwards compatibility
800
+ return Object.assign(instance.toPayment(), a);
309
801
  }