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