@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.
- 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 +56 -9
- 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 +12482 -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 +57 -10
- package/build/address.d.ts.map +1 -0
- package/build/address.js +80 -24
- 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 +204 -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 +36 -9
- package/build/payments/bip341.d.ts.map +1 -0
- package/build/payments/bip341.js +35 -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 -152
- 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 +429 -104
- 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 +466 -144
- 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 +113 -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 +411 -412
- 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 +100 -36
- 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 +175 -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 +66 -8
- package/scripts/bundle-ecc.ts +111 -0
- package/src/address.ts +81 -44
- package/src/bech32utils.ts +3 -3
- package/src/bip66.ts +34 -24
- package/src/block.ts +196 -84
- package/src/branded.ts +18 -0
- package/src/crypto.ts +64 -26
- package/src/ecc/context.ts +277 -0
- package/src/ecc/index.ts +14 -0
- package/src/ecc/types.ts +154 -0
- package/src/ecpair.d.ts +99 -0
- package/src/errors.ts +163 -0
- package/src/index.ts +113 -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 +34 -33
- package/src/payments/embed.ts +244 -41
- package/src/payments/index.ts +12 -10
- package/src/payments/p2ms.ts +490 -118
- package/src/payments/p2op.ts +431 -133
- package/src/payments/p2pk.ts +370 -72
- package/src/payments/p2pkh.ts +524 -130
- package/src/payments/p2sh.ts +572 -172
- package/src/payments/p2tr.ts +686 -194
- package/src/payments/p2wpkh.ts +484 -107
- package/src/payments/p2wsh.ts +526 -164
- package/src/payments/types.ts +80 -66
- package/src/psbt/bip371.ts +68 -51
- package/src/psbt/psbtutils.ts +39 -40
- package/src/psbt/types.ts +331 -0
- package/src/psbt/utils.ts +188 -0
- package/src/psbt/validation.ts +192 -0
- package/src/psbt.ts +566 -809
- package/src/pubkey.ts +22 -23
- package/src/push_data.ts +18 -16
- package/src/script.ts +82 -64
- package/src/script_number.ts +6 -6
- package/src/script_signature.ts +33 -36
- package/src/transaction.ts +458 -238
- package/src/types.ts +231 -100
- package/src/workers/WorkerSigningPool.node.ts +887 -0
- package/src/workers/WorkerSigningPool.ts +670 -0
- package/src/workers/ecc-bundle.ts +26 -0
- package/src/workers/index.ts +165 -0
- package/src/workers/psbt-parallel.ts +332 -0
- package/src/workers/signing-worker.ts +353 -0
- package/src/workers/types.ts +413 -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/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/src/payments/p2wsh.ts
CHANGED
|
@@ -1,223 +1,585 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pay-to-Witness-Script-Hash (P2WSH) payment class.
|
|
3
|
+
*
|
|
4
|
+
* P2WSH is the native SegWit version of P2SH. The witness program is
|
|
5
|
+
* a 32-byte SHA256 hash of the script, and spending requires the witness
|
|
6
|
+
* stack with the script and its inputs.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
1
11
|
import { bech32 } from 'bech32';
|
|
2
12
|
import * as bcrypto from '../crypto.js';
|
|
3
|
-
import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
|
|
13
|
+
import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
|
|
4
14
|
import * as bscript from '../script.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type StackElement,
|
|
10
|
-
type StackFunction,
|
|
11
|
-
} from '../types.js';
|
|
12
|
-
import { P2WSHPayment, PaymentOpts, PaymentType } from './types.js';
|
|
13
|
-
import * as lazy from './lazy.js';
|
|
15
|
+
import { isPoint, stacksEqual, type StackElement } from '../types.js';
|
|
16
|
+
import type { Bytes32, Script } from '../types.js';
|
|
17
|
+
import { equals } from '../io/index.js';
|
|
18
|
+
import { PaymentType, type P2WSHPayment, type PaymentOpts, type ScriptRedeem } from './types.js';
|
|
14
19
|
|
|
15
20
|
const OPS = bscript.opcodes;
|
|
21
|
+
const EMPTY_BUFFER = new Uint8Array(0);
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Checks if a stack element is an uncompressed public key.
|
|
25
|
+
*/
|
|
19
26
|
function chunkHasUncompressedPubkey(chunk: StackElement): boolean {
|
|
20
|
-
if (
|
|
27
|
+
if (chunk instanceof Uint8Array && chunk.length === 65 && chunk[0] === 0x04 && isPoint(chunk)) {
|
|
21
28
|
return true;
|
|
22
|
-
} else {
|
|
23
|
-
return false;
|
|
24
29
|
}
|
|
30
|
+
return false;
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
// input: <>
|
|
28
|
-
// witness: [redeemScriptSig ...] {redeemScript}
|
|
29
|
-
// output: OP_0 {sha256(redeemScript)}
|
|
30
33
|
/**
|
|
31
|
-
*
|
|
34
|
+
* Pay-to-Witness-Script-Hash (P2WSH) payment class.
|
|
32
35
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* @
|
|
36
|
+
* Creates locking scripts of the form: `OP_0 {sha256(redeemScript)}`
|
|
37
|
+
* Spending witness: `[{redeemScriptSig...}, {redeemScript}]`
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { P2WSH, P2MS } from '@btc-vision/bitcoin';
|
|
42
|
+
*
|
|
43
|
+
* // Wrap a multisig in P2WSH
|
|
44
|
+
* const multisig = P2MS.fromPubkeys(2, [pubkey1, pubkey2, pubkey3]);
|
|
45
|
+
* const p2wsh = P2WSH.fromRedeem({ output: multisig.output });
|
|
46
|
+
* console.log(p2wsh.address); // bc1q... bech32 address
|
|
47
|
+
*
|
|
48
|
+
* // Decode an existing output
|
|
49
|
+
* const decoded = P2WSH.fromOutput(scriptPubKey);
|
|
50
|
+
* console.log(decoded.hash); // 32-byte witness program
|
|
51
|
+
* ```
|
|
37
52
|
*/
|
|
38
|
-
export
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
opts = Object.assign({ validate: true }, opts || {});
|
|
53
|
+
export class P2WSH {
|
|
54
|
+
// Static public fields
|
|
55
|
+
static readonly NAME = PaymentType.P2WSH;
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
address: typef.maybe(typef.String),
|
|
48
|
-
hash: typef.maybe(typef.BufferN(32)),
|
|
49
|
-
output: typef.maybe(typef.BufferN(34)),
|
|
50
|
-
|
|
51
|
-
redeem: typef.maybe({
|
|
52
|
-
input: typef.maybe(typef.Buffer),
|
|
53
|
-
network: typef.maybe(typef.Object),
|
|
54
|
-
output: typef.maybe(typef.Buffer),
|
|
55
|
-
witness: typef.maybe(typef.arrayOf(typef.Buffer)),
|
|
56
|
-
}),
|
|
57
|
-
input: typef.maybe(typef.BufferN(0)),
|
|
58
|
-
witness: typef.maybe(typef.arrayOf(typef.Buffer)),
|
|
59
|
-
},
|
|
60
|
-
a,
|
|
61
|
-
);
|
|
57
|
+
// Private instance fields
|
|
58
|
+
readonly #network: Network;
|
|
59
|
+
readonly #opts: Required<PaymentOpts>;
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
// Input data (provided by user)
|
|
62
|
+
#inputAddress?: string | undefined;
|
|
63
|
+
#inputHash?: Uint8Array | undefined;
|
|
64
|
+
#inputOutput?: Uint8Array | undefined;
|
|
65
|
+
#inputRedeem?: ScriptRedeem | undefined;
|
|
66
|
+
#inputWitness?: Uint8Array[] | undefined;
|
|
67
|
+
|
|
68
|
+
// Cached computed values
|
|
69
|
+
#address?: string | undefined;
|
|
70
|
+
#hash?: Uint8Array | undefined;
|
|
71
|
+
#output?: Uint8Array | undefined;
|
|
72
|
+
#input?: Uint8Array | undefined;
|
|
73
|
+
#redeem?: ScriptRedeem | undefined;
|
|
74
|
+
#witness?: Uint8Array[] | undefined;
|
|
75
|
+
|
|
76
|
+
// Cache flags
|
|
77
|
+
#addressComputed = false;
|
|
78
|
+
#hashComputed = false;
|
|
79
|
+
#outputComputed = false;
|
|
80
|
+
#inputComputed = false;
|
|
81
|
+
#redeemComputed = false;
|
|
82
|
+
#witnessComputed = false;
|
|
83
|
+
|
|
84
|
+
// Decoded address cache
|
|
85
|
+
#decodedAddress?: { version: number; prefix: string; data: Uint8Array } | undefined;
|
|
86
|
+
#decodedAddressComputed = false;
|
|
87
|
+
|
|
88
|
+
// Decoded redeem chunks cache
|
|
89
|
+
#redeemChunks?: (Uint8Array | number)[] | undefined;
|
|
90
|
+
#redeemChunksComputed = false;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Creates a new P2WSH payment instance.
|
|
94
|
+
*
|
|
95
|
+
* @param params - Payment parameters
|
|
96
|
+
* @param params.address - Bech32 encoded address
|
|
97
|
+
* @param params.hash - 32-byte witness program (SHA256 of script)
|
|
98
|
+
* @param params.output - The scriptPubKey
|
|
99
|
+
* @param params.redeem - The redeem script information
|
|
100
|
+
* @param params.witness - The witness stack
|
|
101
|
+
* @param params.network - Network parameters (defaults to mainnet)
|
|
102
|
+
* @param opts - Payment options
|
|
103
|
+
* @param opts.validate - Whether to validate inputs (default: true)
|
|
104
|
+
*
|
|
105
|
+
* @throws {TypeError} If validation is enabled and data is invalid
|
|
106
|
+
*/
|
|
107
|
+
constructor(
|
|
108
|
+
params: {
|
|
109
|
+
address?: string | undefined;
|
|
110
|
+
hash?: Uint8Array | undefined;
|
|
111
|
+
output?: Uint8Array | undefined;
|
|
112
|
+
redeem?: ScriptRedeem | undefined;
|
|
113
|
+
witness?: Uint8Array[] | undefined;
|
|
114
|
+
network?: Network | undefined;
|
|
115
|
+
},
|
|
116
|
+
opts?: PaymentOpts,
|
|
117
|
+
) {
|
|
118
|
+
// Derive network from redeem if not specified
|
|
119
|
+
let network = params.network;
|
|
120
|
+
if (!network) {
|
|
121
|
+
network = (params.redeem && params.redeem.network) || BITCOIN_NETWORK;
|
|
122
|
+
}
|
|
123
|
+
this.#network = network;
|
|
124
|
+
this.#opts = {
|
|
125
|
+
validate: opts?.validate ?? true,
|
|
126
|
+
allowIncomplete: opts?.allowIncomplete ?? false,
|
|
71
127
|
};
|
|
72
|
-
});
|
|
73
|
-
const _rchunks = lazy.value(() => {
|
|
74
|
-
return bscript.decompile(a.redeem!.input!);
|
|
75
|
-
}) as StackFunction;
|
|
76
128
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
129
|
+
// Store input data
|
|
130
|
+
this.#inputAddress = params.address;
|
|
131
|
+
this.#inputHash = params.hash;
|
|
132
|
+
this.#inputOutput = params.output;
|
|
133
|
+
this.#inputRedeem = params.redeem;
|
|
134
|
+
this.#inputWitness = params.witness;
|
|
135
|
+
|
|
136
|
+
// Validate if requested
|
|
137
|
+
if (this.#opts.validate) {
|
|
138
|
+
this.#validate();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Public getters
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Payment type discriminant.
|
|
146
|
+
*/
|
|
147
|
+
get name(): string {
|
|
148
|
+
const r = this.redeem;
|
|
149
|
+
if (r !== undefined && r.name !== undefined) {
|
|
150
|
+
return `p2wsh-${r.name}`;
|
|
151
|
+
}
|
|
152
|
+
return PaymentType.P2WSH;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Network parameters.
|
|
157
|
+
*/
|
|
158
|
+
get network(): Network {
|
|
159
|
+
return this.#network;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Bech32 encoded address (bc1q... for mainnet).
|
|
164
|
+
*/
|
|
165
|
+
get address(): string | undefined {
|
|
166
|
+
if (!this.#addressComputed) {
|
|
167
|
+
this.#address = this.#computeAddress();
|
|
168
|
+
this.#addressComputed = true;
|
|
169
|
+
}
|
|
170
|
+
return this.#address;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 32-byte witness program (SHA256 of redeem script).
|
|
175
|
+
*/
|
|
176
|
+
get hash(): Bytes32 | undefined {
|
|
177
|
+
if (!this.#hashComputed) {
|
|
178
|
+
this.#hash = this.#computeHash();
|
|
179
|
+
this.#hashComputed = true;
|
|
180
|
+
}
|
|
181
|
+
return this.#hash as Bytes32 | undefined;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* The scriptPubKey: `OP_0 {32-byte hash}`
|
|
186
|
+
*/
|
|
187
|
+
get output(): Script | undefined {
|
|
188
|
+
if (!this.#outputComputed) {
|
|
189
|
+
this.#output = this.#computeOutput();
|
|
190
|
+
this.#outputComputed = true;
|
|
191
|
+
}
|
|
192
|
+
return this.#output as Script | undefined;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The scriptSig (always empty for native SegWit).
|
|
197
|
+
*/
|
|
198
|
+
get input(): Script | undefined {
|
|
199
|
+
if (!this.#inputComputed) {
|
|
200
|
+
this.#input = this.#computeInput();
|
|
201
|
+
this.#inputComputed = true;
|
|
202
|
+
}
|
|
203
|
+
return this.#input as Script | undefined;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* The redeem script information.
|
|
208
|
+
*/
|
|
209
|
+
get redeem(): ScriptRedeem | undefined {
|
|
210
|
+
if (!this.#redeemComputed) {
|
|
211
|
+
this.#redeem = this.#computeRedeem();
|
|
212
|
+
this.#redeemComputed = true;
|
|
213
|
+
}
|
|
214
|
+
return this.#redeem;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Witness stack: `[{scriptSig...}, {redeemScript}]`
|
|
219
|
+
*/
|
|
220
|
+
get witness(): Uint8Array[] | undefined {
|
|
221
|
+
if (!this.#witnessComputed) {
|
|
222
|
+
this.#witness = this.#computeWitness();
|
|
223
|
+
this.#witnessComputed = true;
|
|
224
|
+
}
|
|
225
|
+
return this.#witness;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Static factory methods
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Creates a P2WSH payment from a redeem script.
|
|
232
|
+
*
|
|
233
|
+
* @param redeem - The redeem script information
|
|
234
|
+
* @param network - Network parameters (defaults to mainnet)
|
|
235
|
+
* @returns A new P2WSH payment instance
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```typescript
|
|
239
|
+
* const p2wsh = P2WSH.fromRedeem({ output: redeemScript });
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
static fromRedeem(redeem: ScriptRedeem, network?: Network): P2WSH {
|
|
243
|
+
return new P2WSH({ redeem, network });
|
|
80
244
|
}
|
|
81
245
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Creates a P2WSH payment from a bech32 address.
|
|
248
|
+
*
|
|
249
|
+
* @param address - Bech32 encoded address
|
|
250
|
+
* @param network - Network parameters (defaults to mainnet)
|
|
251
|
+
* @returns A new P2WSH payment instance
|
|
252
|
+
*/
|
|
253
|
+
static fromAddress(address: string, network?: Network): P2WSH {
|
|
254
|
+
return new P2WSH({ address, network });
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Creates a P2WSH payment from a 32-byte witness program.
|
|
259
|
+
*
|
|
260
|
+
* @param hash - 32-byte witness program (SHA256 of script)
|
|
261
|
+
* @param network - Network parameters (defaults to mainnet)
|
|
262
|
+
* @returns A new P2WSH payment instance
|
|
263
|
+
*/
|
|
264
|
+
static fromHash(hash: Bytes32, network?: Network): P2WSH {
|
|
265
|
+
return new P2WSH({ hash, network });
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Creates a P2WSH payment from a scriptPubKey.
|
|
270
|
+
*
|
|
271
|
+
* @param output - The scriptPubKey
|
|
272
|
+
* @param network - Network parameters (defaults to mainnet)
|
|
273
|
+
* @returns A new P2WSH payment instance
|
|
274
|
+
*/
|
|
275
|
+
static fromOutput(output: Uint8Array, network?: Network): P2WSH {
|
|
276
|
+
return new P2WSH({ output, network });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Private helper methods
|
|
280
|
+
|
|
281
|
+
#getDecodedAddress(): { version: number; prefix: string; data: Uint8Array } | undefined {
|
|
282
|
+
if (!this.#decodedAddressComputed) {
|
|
283
|
+
if (this.#inputAddress) {
|
|
284
|
+
const result = bech32.decode(this.#inputAddress);
|
|
285
|
+
const version = result.words.shift();
|
|
286
|
+
const data = bech32.fromWords(result.words);
|
|
287
|
+
this.#decodedAddress = {
|
|
288
|
+
version: version ?? 0,
|
|
289
|
+
prefix: result.prefix,
|
|
290
|
+
data: new Uint8Array(data),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
this.#decodedAddressComputed = true;
|
|
294
|
+
}
|
|
295
|
+
return this.#decodedAddress;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
#getRedeemChunks(): (Uint8Array | number)[] | undefined {
|
|
299
|
+
if (!this.#redeemChunksComputed) {
|
|
300
|
+
if (this.#inputRedeem?.input) {
|
|
301
|
+
this.#redeemChunks = bscript.decompile(this.#inputRedeem.input) ?? undefined;
|
|
302
|
+
}
|
|
303
|
+
this.#redeemChunksComputed = true;
|
|
304
|
+
}
|
|
305
|
+
return this.#redeemChunks;
|
|
306
|
+
}
|
|
86
307
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
308
|
+
// Private computation methods
|
|
309
|
+
|
|
310
|
+
#computeAddress(): string | undefined {
|
|
311
|
+
if (this.#inputAddress) {
|
|
312
|
+
return this.#inputAddress;
|
|
313
|
+
}
|
|
314
|
+
const h = this.hash;
|
|
315
|
+
if (!h) return undefined;
|
|
316
|
+
|
|
317
|
+
const words = bech32.toWords(h);
|
|
90
318
|
words.unshift(0x00);
|
|
91
|
-
return bech32.encode(network.bech32, words);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
319
|
+
return bech32.encode(this.#network.bech32, words);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
#computeHash(): Uint8Array | undefined {
|
|
323
|
+
if (this.#inputHash) {
|
|
324
|
+
return this.#inputHash;
|
|
325
|
+
}
|
|
326
|
+
if (this.#inputOutput) {
|
|
327
|
+
return this.#inputOutput.subarray(2) as Bytes32;
|
|
328
|
+
}
|
|
329
|
+
if (this.#inputAddress) {
|
|
330
|
+
return this.#getDecodedAddress()?.data as Bytes32 | undefined;
|
|
331
|
+
}
|
|
332
|
+
const r = this.redeem;
|
|
333
|
+
if (r && r.output) {
|
|
334
|
+
return bcrypto.sha256(r.output) as Bytes32;
|
|
335
|
+
}
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
#computeOutput(): Uint8Array | undefined {
|
|
340
|
+
if (this.#inputOutput) {
|
|
341
|
+
return this.#inputOutput;
|
|
342
|
+
}
|
|
343
|
+
const h = this.hash;
|
|
344
|
+
if (!h) return undefined;
|
|
345
|
+
|
|
346
|
+
return bscript.compile([OPS.OP_0, h]) as Script;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#computeInput(): Uint8Array | undefined {
|
|
350
|
+
if (this.witness) {
|
|
351
|
+
return EMPTY_BUFFER as Script;
|
|
352
|
+
}
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
#computeRedeem(): ScriptRedeem | undefined {
|
|
357
|
+
if (this.#inputRedeem) {
|
|
358
|
+
return this.#inputRedeem;
|
|
359
|
+
}
|
|
360
|
+
if (this.#inputWitness && this.#inputWitness.length > 0) {
|
|
361
|
+
return {
|
|
362
|
+
output: this.#inputWitness[this.#inputWitness.length - 1] as Script,
|
|
363
|
+
input: EMPTY_BUFFER as Script,
|
|
364
|
+
witness: this.#inputWitness.slice(0, -1),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
return undefined;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
#computeWitness(): Uint8Array[] | undefined {
|
|
371
|
+
if (this.#inputWitness) {
|
|
372
|
+
return this.#inputWitness;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const r = this.#inputRedeem;
|
|
376
|
+
if (r) {
|
|
377
|
+
// Transform redeem input to witness stack
|
|
378
|
+
if (r.input && r.input.length > 0 && r.output && r.output.length > 0) {
|
|
379
|
+
const chunks = this.#getRedeemChunks();
|
|
380
|
+
if (chunks) {
|
|
381
|
+
const stack = bscript.toStack(chunks);
|
|
382
|
+
// Assign, and blank the existing input
|
|
383
|
+
this.#redeem = Object.assign({ witness: stack }, r, { input: EMPTY_BUFFER });
|
|
384
|
+
this.#redeemComputed = true;
|
|
385
|
+
return ([] as Uint8Array[]).concat(stack, r.output);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (!r.output) return undefined;
|
|
390
|
+
if (!r.witness) return undefined;
|
|
391
|
+
return ([] as Uint8Array[]).concat(r.witness, r.output);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Validation
|
|
398
|
+
|
|
399
|
+
#validate(): void {
|
|
400
|
+
let hash: Uint8Array = new Uint8Array(0);
|
|
401
|
+
|
|
402
|
+
if (this.#inputAddress) {
|
|
403
|
+
const addr = this.#getDecodedAddress();
|
|
404
|
+
if (!addr) {
|
|
405
|
+
throw new TypeError('Invalid address');
|
|
406
|
+
}
|
|
407
|
+
if (addr.prefix !== this.#network.bech32) {
|
|
147
408
|
throw new TypeError('Invalid prefix or Network mismatch');
|
|
148
|
-
|
|
149
|
-
if (
|
|
150
|
-
|
|
409
|
+
}
|
|
410
|
+
if (addr.version !== 0x00) {
|
|
411
|
+
throw new TypeError('Invalid address version');
|
|
412
|
+
}
|
|
413
|
+
if (addr.data.length !== 32) {
|
|
414
|
+
throw new TypeError('Invalid address data');
|
|
415
|
+
}
|
|
416
|
+
hash = addr.data;
|
|
151
417
|
}
|
|
152
418
|
|
|
153
|
-
if (
|
|
154
|
-
if (hash.length > 0 && !
|
|
155
|
-
|
|
419
|
+
if (this.#inputHash) {
|
|
420
|
+
if (hash.length > 0 && !equals(hash, this.#inputHash)) {
|
|
421
|
+
throw new TypeError('Hash mismatch');
|
|
422
|
+
} else {
|
|
423
|
+
hash = this.#inputHash;
|
|
424
|
+
}
|
|
156
425
|
}
|
|
157
426
|
|
|
158
|
-
if (
|
|
159
|
-
if (
|
|
427
|
+
if (this.#inputOutput) {
|
|
428
|
+
if (
|
|
429
|
+
this.#inputOutput.length !== 34 ||
|
|
430
|
+
this.#inputOutput[0] !== OPS.OP_0 ||
|
|
431
|
+
this.#inputOutput[1] !== 0x20
|
|
432
|
+
) {
|
|
160
433
|
throw new TypeError('Output is invalid');
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
434
|
+
}
|
|
435
|
+
const hash2 = this.#inputOutput.subarray(2);
|
|
436
|
+
if (hash.length > 0 && !equals(hash, hash2)) {
|
|
437
|
+
throw new TypeError('Hash mismatch');
|
|
438
|
+
} else {
|
|
439
|
+
hash = hash2;
|
|
440
|
+
}
|
|
164
441
|
}
|
|
165
442
|
|
|
166
|
-
if (
|
|
167
|
-
if (
|
|
443
|
+
if (this.#inputRedeem) {
|
|
444
|
+
if (this.#inputRedeem.network && this.#inputRedeem.network !== this.#network) {
|
|
168
445
|
throw new TypeError('Network mismatch');
|
|
446
|
+
}
|
|
169
447
|
|
|
170
|
-
//
|
|
448
|
+
// Is there two redeem sources?
|
|
171
449
|
if (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
)
|
|
450
|
+
this.#inputRedeem.input &&
|
|
451
|
+
this.#inputRedeem.input.length > 0 &&
|
|
452
|
+
this.#inputRedeem.witness &&
|
|
453
|
+
this.#inputRedeem.witness.length > 0
|
|
454
|
+
) {
|
|
177
455
|
throw new TypeError('Ambiguous witness source');
|
|
456
|
+
}
|
|
178
457
|
|
|
179
|
-
//
|
|
180
|
-
if (
|
|
181
|
-
const decompile = bscript.decompile(
|
|
182
|
-
if (!decompile || decompile.length < 1)
|
|
458
|
+
// Is the redeem output non-empty/valid?
|
|
459
|
+
if (this.#inputRedeem.output) {
|
|
460
|
+
const decompile = bscript.decompile(this.#inputRedeem.output);
|
|
461
|
+
if (!decompile || decompile.length < 1) {
|
|
183
462
|
throw new TypeError('Redeem.output is invalid');
|
|
184
|
-
|
|
463
|
+
}
|
|
464
|
+
if (this.#inputRedeem.output.byteLength > 3600) {
|
|
185
465
|
throw new TypeError('Redeem.output unspendable if larger than 3600 bytes');
|
|
186
|
-
|
|
466
|
+
}
|
|
467
|
+
if (bscript.countNonPushOnlyOPs(decompile) > 201) {
|
|
187
468
|
throw new TypeError(
|
|
188
469
|
'Redeem.output unspendable with more than 201 non-push ops',
|
|
189
470
|
);
|
|
471
|
+
}
|
|
190
472
|
|
|
191
|
-
//
|
|
192
|
-
const hash2 = bcrypto.sha256(
|
|
193
|
-
if (hash.length > 0 && !
|
|
194
|
-
|
|
473
|
+
// Match hash against other sources
|
|
474
|
+
const hash2 = bcrypto.sha256(this.#inputRedeem.output);
|
|
475
|
+
if (hash.length > 0 && !equals(hash, hash2)) {
|
|
476
|
+
throw new TypeError('Hash mismatch');
|
|
477
|
+
} else {
|
|
478
|
+
hash = hash2;
|
|
479
|
+
}
|
|
195
480
|
}
|
|
196
481
|
|
|
197
|
-
|
|
482
|
+
const chunks = this.#getRedeemChunks();
|
|
483
|
+
if (this.#inputRedeem.input && chunks && !bscript.isPushOnly(chunks)) {
|
|
198
484
|
throw new TypeError('Non push-only scriptSig');
|
|
199
|
-
|
|
485
|
+
}
|
|
486
|
+
if (
|
|
487
|
+
this.#inputWitness &&
|
|
488
|
+
this.#inputRedeem.witness &&
|
|
489
|
+
!stacksEqual(this.#inputWitness, this.#inputRedeem.witness)
|
|
490
|
+
) {
|
|
200
491
|
throw new TypeError('Witness and redeem.witness mismatch');
|
|
492
|
+
}
|
|
201
493
|
if (
|
|
202
|
-
(
|
|
203
|
-
(
|
|
204
|
-
(bscript.decompile(
|
|
494
|
+
(this.#inputRedeem.input && chunks?.some(chunkHasUncompressedPubkey)) ||
|
|
495
|
+
(this.#inputRedeem.output &&
|
|
496
|
+
(bscript.decompile(this.#inputRedeem.output) || []).some(
|
|
497
|
+
chunkHasUncompressedPubkey,
|
|
498
|
+
))
|
|
205
499
|
) {
|
|
206
500
|
throw new TypeError('redeem.input or redeem.output contains uncompressed pubkey');
|
|
207
501
|
}
|
|
208
502
|
}
|
|
209
503
|
|
|
210
|
-
if (
|
|
211
|
-
const wScript =
|
|
212
|
-
if (
|
|
504
|
+
if (this.#inputWitness && this.#inputWitness.length > 0) {
|
|
505
|
+
const wScript = this.#inputWitness[this.#inputWitness.length - 1]!;
|
|
506
|
+
if (
|
|
507
|
+
this.#inputRedeem &&
|
|
508
|
+
this.#inputRedeem.output &&
|
|
509
|
+
!equals(this.#inputRedeem.output, wScript)
|
|
510
|
+
) {
|
|
213
511
|
throw new TypeError('Witness and redeem.output mismatch');
|
|
512
|
+
}
|
|
214
513
|
if (
|
|
215
|
-
|
|
514
|
+
this.#inputWitness.some(chunkHasUncompressedPubkey) ||
|
|
216
515
|
(bscript.decompile(wScript) || []).some(chunkHasUncompressedPubkey)
|
|
217
|
-
)
|
|
516
|
+
) {
|
|
218
517
|
throw new TypeError('Witness contains uncompressed pubkey');
|
|
518
|
+
}
|
|
219
519
|
}
|
|
220
520
|
}
|
|
221
521
|
|
|
222
|
-
|
|
522
|
+
/**
|
|
523
|
+
* Converts to a plain P2WSHPayment object for backwards compatibility.
|
|
524
|
+
*
|
|
525
|
+
* @returns A P2WSHPayment object
|
|
526
|
+
*/
|
|
527
|
+
toPayment(): P2WSHPayment {
|
|
528
|
+
// Access witness first as it may modify redeem (transform input to witness)
|
|
529
|
+
const witness = this.witness;
|
|
530
|
+
const redeem = this.redeem;
|
|
531
|
+
return {
|
|
532
|
+
name: this.name,
|
|
533
|
+
network: this.network,
|
|
534
|
+
address: this.address,
|
|
535
|
+
hash: this.hash,
|
|
536
|
+
output: this.output,
|
|
537
|
+
input: this.input,
|
|
538
|
+
redeem,
|
|
539
|
+
witness,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Creates a Pay-to-Witness-Script-Hash (P2WSH) payment object.
|
|
546
|
+
*
|
|
547
|
+
* This is the legacy factory function for backwards compatibility.
|
|
548
|
+
* For new code, prefer using the P2WSH class directly.
|
|
549
|
+
*
|
|
550
|
+
* @param a - The payment object containing the necessary data
|
|
551
|
+
* @param opts - Optional payment options
|
|
552
|
+
* @returns The P2WSH payment object
|
|
553
|
+
* @throws {TypeError} If the required data is not provided or if the data is invalid
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```typescript
|
|
557
|
+
* import { p2wsh, p2ms } from '@btc-vision/bitcoin';
|
|
558
|
+
*
|
|
559
|
+
* // Wrap a multisig in P2WSH
|
|
560
|
+
* const multisig = p2ms({ m: 2, pubkeys: [pk1, pk2, pk3] });
|
|
561
|
+
* const payment = p2wsh({ redeem: multisig });
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
export function p2wsh(a: Omit<P2WSHPayment, 'name'>, opts?: PaymentOpts): P2WSHPayment {
|
|
565
|
+
if (!a.address && !a.hash && !a.output && !a.redeem && !a.witness) {
|
|
566
|
+
throw new TypeError('Not enough data');
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const instance = new P2WSH(
|
|
570
|
+
{
|
|
571
|
+
address: a.address,
|
|
572
|
+
hash: a.hash,
|
|
573
|
+
output: a.output,
|
|
574
|
+
redeem: a.redeem,
|
|
575
|
+
witness: a.witness,
|
|
576
|
+
network: a.network,
|
|
577
|
+
},
|
|
578
|
+
opts,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
// Return the computed payment
|
|
582
|
+
// Note: We don't use Object.assign(toPayment(), a) because that would
|
|
583
|
+
// overwrite computed properties (like modified redeem) with original values
|
|
584
|
+
return instance.toPayment();
|
|
223
585
|
}
|