@btc-vision/bitcoin 6.5.5 → 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/AUDIT/README.md +9 -0
- package/HOW_TO_WRITE_GOOD_CODE.md +2436 -0
- package/SECURITY.md +27 -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 +37 -13
- 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 +83 -25
- 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 +24 -25
- 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 +11 -0
- package/browser/bufferutils.d.ts +0 -34
- package/browser/chunks/crypto-BhCpKpek.js +0 -2033
- package/browser/chunks/payments-yjA0Evsv.js +0 -1089
- package/browser/chunks/psbt-URK2hBFc.js +0 -4039
- 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/transaction.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BinaryReader, BinaryWriter, reverse, varuint, fromHex, toHex, alloc } from './io/index.js';
|
|
2
2
|
import * as bcrypto from './crypto.js';
|
|
3
3
|
import * as bscript from './script.js';
|
|
4
4
|
import { opcodes } from './script.js';
|
|
5
|
-
import * as types from './types.js';
|
|
6
|
-
const { typeforce } = types;
|
|
7
5
|
function varSliceSize(someScript) {
|
|
8
6
|
const length = someScript.length;
|
|
9
7
|
return varuint.encodingLength(length) + length;
|
|
@@ -15,29 +13,58 @@ function vectorSize(someVector) {
|
|
|
15
13
|
return sum + varSliceSize(witness);
|
|
16
14
|
}, 0));
|
|
17
15
|
}
|
|
18
|
-
const
|
|
16
|
+
const EMPTY_BYTES = new Uint8Array(0);
|
|
19
17
|
const EMPTY_WITNESS = [];
|
|
20
|
-
const ZERO =
|
|
21
|
-
const ONE =
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
18
|
+
const ZERO = fromHex('0000000000000000000000000000000000000000000000000000000000000000');
|
|
19
|
+
const ONE = fromHex('0000000000000000000000000000000000000000000000000000000000000001');
|
|
20
|
+
/** Maximum value for SIGHASH_SINGLE blank outputs (0xFFFFFFFFFFFFFFFF) */
|
|
21
|
+
const BLANK_OUTPUT_VALUE = 0xffffffffffffffffn;
|
|
22
|
+
/**
|
|
23
|
+
* Represents a Bitcoin transaction.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { Transaction, fromHex } from '@btc-vision/bitcoin';
|
|
28
|
+
*
|
|
29
|
+
* // Parse a transaction from hex
|
|
30
|
+
* const tx = Transaction.fromHex('0100000001...');
|
|
31
|
+
*
|
|
32
|
+
* // Create a new transaction
|
|
33
|
+
* const newTx = new Transaction();
|
|
34
|
+
* newTx.version = 2;
|
|
35
|
+
* newTx.addInput(prevTxHash, 0);
|
|
36
|
+
* newTx.addOutput(scriptPubKey, 50000n);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
30
39
|
export class Transaction {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
static DEFAULT_SEQUENCE = 0xffffffff;
|
|
41
|
+
static SIGHASH_DEFAULT = 0x00;
|
|
42
|
+
static SIGHASH_ALL = 0x01;
|
|
43
|
+
static SIGHASH_NONE = 0x02;
|
|
44
|
+
static SIGHASH_SINGLE = 0x03;
|
|
45
|
+
static SIGHASH_ANYONECANPAY = 0x80;
|
|
46
|
+
static SIGHASH_OUTPUT_MASK = 0x03;
|
|
47
|
+
static SIGHASH_INPUT_MASK = 0x80;
|
|
48
|
+
static ADVANCED_TRANSACTION_MARKER = 0x00;
|
|
49
|
+
static ADVANCED_TRANSACTION_FLAG = 0x01;
|
|
50
|
+
static TRUC_VERSION = 3;
|
|
51
|
+
static TRUC_MAX_VSIZE = 10000;
|
|
52
|
+
static TRUC_CHILD_MAX_VSIZE = 1000;
|
|
53
|
+
version = 1;
|
|
54
|
+
locktime = 0;
|
|
55
|
+
ins = [];
|
|
56
|
+
outs = [];
|
|
57
|
+
/**
|
|
58
|
+
* Parse a transaction from a Uint8Array buffer.
|
|
59
|
+
*
|
|
60
|
+
* @param buffer - The raw transaction bytes
|
|
61
|
+
* @param _NO_STRICT - If true, allow extra data after transaction
|
|
62
|
+
* @returns Parsed Transaction instance
|
|
63
|
+
*/
|
|
37
64
|
static fromBuffer(buffer, _NO_STRICT) {
|
|
38
|
-
const bufferReader = new
|
|
65
|
+
const bufferReader = new BinaryReader(buffer);
|
|
39
66
|
const tx = new Transaction();
|
|
40
|
-
tx.version = bufferReader.
|
|
67
|
+
tx.version = bufferReader.readInt32LE();
|
|
41
68
|
const marker = bufferReader.readUInt8();
|
|
42
69
|
const flag = bufferReader.readUInt8();
|
|
43
70
|
let hasWitnesses = false;
|
|
@@ -50,10 +77,10 @@ export class Transaction {
|
|
|
50
77
|
}
|
|
51
78
|
const vinLen = bufferReader.readVarInt();
|
|
52
79
|
for (let i = 0; i < vinLen; ++i) {
|
|
53
|
-
const hash = bufferReader.
|
|
54
|
-
const index = bufferReader.
|
|
55
|
-
const script = bufferReader.
|
|
56
|
-
const sequence = bufferReader.
|
|
80
|
+
const hash = bufferReader.readBytes(32);
|
|
81
|
+
const index = bufferReader.readUInt32LE();
|
|
82
|
+
const script = bufferReader.readVarBytes();
|
|
83
|
+
const sequence = bufferReader.readUInt32LE();
|
|
57
84
|
tx.ins.push({
|
|
58
85
|
hash: hash,
|
|
59
86
|
index: index,
|
|
@@ -65,31 +92,46 @@ export class Transaction {
|
|
|
65
92
|
const voutLen = bufferReader.readVarInt();
|
|
66
93
|
for (let i = 0; i < voutLen; ++i) {
|
|
67
94
|
tx.outs.push({
|
|
68
|
-
value: bufferReader.
|
|
69
|
-
script: bufferReader.
|
|
95
|
+
value: bufferReader.readUInt64LE(),
|
|
96
|
+
script: bufferReader.readVarBytes(),
|
|
70
97
|
});
|
|
71
98
|
}
|
|
72
99
|
if (hasWitnesses) {
|
|
73
100
|
for (let i = 0; i < vinLen; ++i) {
|
|
74
101
|
tx.ins[i].witness = bufferReader.readVector();
|
|
75
102
|
}
|
|
103
|
+
// was this pointless?
|
|
76
104
|
if (!tx.hasWitnesses())
|
|
77
105
|
throw new Error('Transaction has superfluous witness data');
|
|
78
106
|
}
|
|
79
|
-
tx.locktime = bufferReader.
|
|
107
|
+
tx.locktime = bufferReader.readUInt32LE();
|
|
80
108
|
if (_NO_STRICT)
|
|
81
109
|
return tx;
|
|
82
110
|
if (bufferReader.offset !== buffer.length)
|
|
83
111
|
throw new Error('Transaction has unexpected data');
|
|
84
112
|
return tx;
|
|
85
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse a transaction from a hex string.
|
|
116
|
+
*
|
|
117
|
+
* @param hex - The transaction as a hex string
|
|
118
|
+
* @returns Parsed Transaction instance
|
|
119
|
+
*/
|
|
86
120
|
static fromHex(hex) {
|
|
87
|
-
return Transaction.fromBuffer(
|
|
121
|
+
return Transaction.fromBuffer(fromHex(hex), false);
|
|
88
122
|
}
|
|
89
|
-
|
|
90
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Check if a hash is a coinbase hash (all zeros).
|
|
125
|
+
*
|
|
126
|
+
* @param hash - 32-byte hash to check
|
|
127
|
+
* @returns true if hash is all zeros (coinbase)
|
|
128
|
+
*/
|
|
129
|
+
static isCoinbaseHash(hash) {
|
|
130
|
+
if (hash.length !== 32) {
|
|
131
|
+
throw new TypeError('Expected 32-byte hash');
|
|
132
|
+
}
|
|
91
133
|
for (let i = 0; i < 32; ++i) {
|
|
92
|
-
if (
|
|
134
|
+
if (hash[i] !== 0)
|
|
93
135
|
return false;
|
|
94
136
|
}
|
|
95
137
|
return true;
|
|
@@ -97,21 +139,54 @@ export class Transaction {
|
|
|
97
139
|
isCoinbase() {
|
|
98
140
|
return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash);
|
|
99
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Add an input to this transaction.
|
|
144
|
+
*
|
|
145
|
+
* @param hash - 32-byte hash of the previous transaction
|
|
146
|
+
* @param index - Output index in the previous transaction
|
|
147
|
+
* @param sequence - Sequence number (defaults to 0xffffffff)
|
|
148
|
+
* @param scriptSig - Input script (defaults to empty)
|
|
149
|
+
* @returns The index of the newly added input
|
|
150
|
+
*/
|
|
100
151
|
addInput(hash, index, sequence, scriptSig) {
|
|
101
|
-
|
|
102
|
-
|
|
152
|
+
if (hash.length !== 32) {
|
|
153
|
+
throw new TypeError('Expected 32-byte hash');
|
|
154
|
+
}
|
|
155
|
+
if (!Number.isInteger(index) || index < 0 || index > 0xffffffff) {
|
|
156
|
+
throw new TypeError('Expected unsigned 32-bit integer for index');
|
|
157
|
+
}
|
|
158
|
+
if (sequence !== undefined &&
|
|
159
|
+
sequence !== null &&
|
|
160
|
+
(!Number.isInteger(sequence) || sequence < 0 || sequence > 0xffffffff)) {
|
|
161
|
+
throw new TypeError('Expected unsigned 32-bit integer for sequence');
|
|
162
|
+
}
|
|
163
|
+
if (sequence === undefined || sequence === null) {
|
|
103
164
|
sequence = Transaction.DEFAULT_SEQUENCE;
|
|
104
165
|
}
|
|
166
|
+
// Add the input and return the input's index
|
|
105
167
|
return (this.ins.push({
|
|
106
168
|
hash,
|
|
107
169
|
index,
|
|
108
|
-
script: scriptSig ||
|
|
170
|
+
script: scriptSig || EMPTY_BYTES,
|
|
109
171
|
sequence: sequence,
|
|
110
172
|
witness: EMPTY_WITNESS,
|
|
111
173
|
}) - 1);
|
|
112
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Add an output to this transaction.
|
|
177
|
+
*
|
|
178
|
+
* @param scriptPubKey - Output script (locking script)
|
|
179
|
+
* @param value - Output value in satoshis (bigint)
|
|
180
|
+
* @returns The index of the newly added output
|
|
181
|
+
*/
|
|
113
182
|
addOutput(scriptPubKey, value) {
|
|
114
|
-
|
|
183
|
+
if (!(scriptPubKey instanceof Uint8Array)) {
|
|
184
|
+
throw new TypeError('Expected Uint8Array for scriptPubKey');
|
|
185
|
+
}
|
|
186
|
+
if (typeof value !== 'bigint' || value < 0n || value > 0x7fffffffffffffffn) {
|
|
187
|
+
throw new TypeError('Expected bigint satoshi value (0 to 2^63-1)');
|
|
188
|
+
}
|
|
189
|
+
// Add the output and return the output's index
|
|
115
190
|
return (this.outs.push({
|
|
116
191
|
script: scriptPubKey,
|
|
117
192
|
value,
|
|
@@ -168,14 +243,33 @@ export class Transaction {
|
|
|
168
243
|
});
|
|
169
244
|
return newTx;
|
|
170
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Hash transaction for signing a specific input.
|
|
248
|
+
*
|
|
249
|
+
* Bitcoin uses a different hash for each signed transaction input.
|
|
250
|
+
* This method copies the transaction, makes the necessary changes based on the
|
|
251
|
+
* hashType, and then hashes the result.
|
|
252
|
+
* This hash can then be used to sign the provided transaction input.
|
|
253
|
+
*
|
|
254
|
+
* @param inIndex - Index of the input being signed
|
|
255
|
+
* @param prevOutScript - The script of the output being spent
|
|
256
|
+
* @param hashType - Signature hash type
|
|
257
|
+
* @returns 32-byte hash for signing
|
|
258
|
+
*/
|
|
171
259
|
hashForSignature(inIndex, prevOutScript, hashType) {
|
|
172
|
-
|
|
173
|
-
inIndex
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
260
|
+
if (!Number.isInteger(inIndex) || inIndex < 0) {
|
|
261
|
+
throw new TypeError('Expected non-negative integer for inIndex');
|
|
262
|
+
}
|
|
263
|
+
if (!(prevOutScript instanceof Uint8Array)) {
|
|
264
|
+
throw new TypeError('Expected Uint8Array for prevOutScript');
|
|
265
|
+
}
|
|
266
|
+
if (!Number.isInteger(hashType)) {
|
|
267
|
+
throw new TypeError('Expected integer for hashType');
|
|
268
|
+
}
|
|
269
|
+
// https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L29
|
|
177
270
|
if (inIndex >= this.ins.length)
|
|
178
271
|
return ONE;
|
|
272
|
+
// ignore OP_CODESEPARATOR
|
|
179
273
|
const decompiled = bscript.decompile(prevOutScript);
|
|
180
274
|
if (!decompiled)
|
|
181
275
|
throw new Error('Could not decompile prevOutScript');
|
|
@@ -183,44 +277,83 @@ export class Transaction {
|
|
|
183
277
|
return x !== opcodes.OP_CODESEPARATOR;
|
|
184
278
|
}));
|
|
185
279
|
const txTmp = this.clone();
|
|
280
|
+
// SIGHASH_NONE: ignore all outputs? (wildcard payee)
|
|
186
281
|
if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
|
|
187
282
|
txTmp.outs = [];
|
|
283
|
+
// ignore sequence numbers (except at inIndex)
|
|
188
284
|
txTmp.ins.forEach((input, i) => {
|
|
189
285
|
if (i === inIndex)
|
|
190
286
|
return;
|
|
191
287
|
input.sequence = 0;
|
|
192
288
|
});
|
|
289
|
+
// SIGHASH_SINGLE: ignore all outputs, except at the same index?
|
|
193
290
|
}
|
|
194
291
|
else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) {
|
|
292
|
+
// https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60
|
|
195
293
|
if (inIndex >= this.outs.length)
|
|
196
294
|
return ONE;
|
|
295
|
+
// truncate outputs after
|
|
197
296
|
txTmp.outs.length = inIndex + 1;
|
|
297
|
+
// "blank" outputs before (value = 0xFFFFFFFFFFFFFFFF, empty script)
|
|
198
298
|
for (let i = 0; i < inIndex; i++) {
|
|
199
|
-
txTmp.outs[i] =
|
|
299
|
+
txTmp.outs[i] = {
|
|
300
|
+
script: EMPTY_BYTES,
|
|
301
|
+
value: BLANK_OUTPUT_VALUE,
|
|
302
|
+
};
|
|
200
303
|
}
|
|
304
|
+
// ignore sequence numbers (except at inIndex)
|
|
201
305
|
txTmp.ins.forEach((input, y) => {
|
|
202
306
|
if (y === inIndex)
|
|
203
307
|
return;
|
|
204
308
|
input.sequence = 0;
|
|
205
309
|
});
|
|
206
310
|
}
|
|
311
|
+
// SIGHASH_ANYONECANPAY: ignore inputs entirely?
|
|
207
312
|
if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
|
|
208
313
|
txTmp.ins = [txTmp.ins[inIndex]];
|
|
209
314
|
txTmp.ins[0].script = ourScript;
|
|
315
|
+
// SIGHASH_ALL: only ignore input scripts
|
|
210
316
|
}
|
|
211
317
|
else {
|
|
318
|
+
// "blank" others input scripts
|
|
212
319
|
txTmp.ins.forEach((input) => {
|
|
213
|
-
input.script =
|
|
320
|
+
input.script = EMPTY_BYTES;
|
|
214
321
|
});
|
|
215
322
|
txTmp.ins[inIndex].script = ourScript;
|
|
216
323
|
}
|
|
217
|
-
|
|
218
|
-
buffer.
|
|
219
|
-
|
|
324
|
+
// serialize and hash
|
|
325
|
+
const buffer = alloc(txTmp.byteLength(false) + 4);
|
|
326
|
+
const writer = new BinaryWriter(buffer, txTmp.byteLength(false));
|
|
327
|
+
writer.writeInt32LE(hashType);
|
|
328
|
+
txTmp.#toBuffer(buffer, 0, false);
|
|
220
329
|
return bcrypto.hash256(buffer);
|
|
221
330
|
}
|
|
222
|
-
|
|
223
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Hash transaction for signing a Taproot (witness v1) input.
|
|
333
|
+
*
|
|
334
|
+
* @param inIndex - Index of the input being signed
|
|
335
|
+
* @param prevOutScripts - Scripts of all inputs being spent
|
|
336
|
+
* @param values - Values of all inputs being spent (bigint satoshis)
|
|
337
|
+
* @param hashType - Signature hash type
|
|
338
|
+
* @param leafHash - Optional leaf hash for script path spending
|
|
339
|
+
* @param annex - Optional annex data
|
|
340
|
+
* @returns 32-byte hash for signing
|
|
341
|
+
*/
|
|
342
|
+
hashForWitnessV1(inIndex, prevOutScripts, values, hashType, leafHash, annex, taprootCache) {
|
|
343
|
+
// https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#common-signature-message
|
|
344
|
+
if (!Number.isInteger(inIndex) || inIndex < 0 || inIndex > 0xffffffff) {
|
|
345
|
+
throw new TypeError('Expected unsigned 32-bit integer for inIndex');
|
|
346
|
+
}
|
|
347
|
+
if (!Array.isArray(prevOutScripts) ||
|
|
348
|
+
!prevOutScripts.every((s) => s instanceof Uint8Array)) {
|
|
349
|
+
throw new TypeError('Expected array of Uint8Array for prevOutScripts');
|
|
350
|
+
}
|
|
351
|
+
if (!Array.isArray(values) || !values.every((v) => typeof v === 'bigint')) {
|
|
352
|
+
throw new TypeError('Expected array of bigint for values');
|
|
353
|
+
}
|
|
354
|
+
if (!Number.isInteger(hashType) || hashType < 0 || hashType > 0xffffffff) {
|
|
355
|
+
throw new TypeError('Expected unsigned 32-bit integer for hashType');
|
|
356
|
+
}
|
|
224
357
|
if (values.length !== this.ins.length || prevOutScripts.length !== this.ins.length) {
|
|
225
358
|
throw new Error('Must supply prevout script and value for all inputs');
|
|
226
359
|
}
|
|
@@ -231,120 +364,215 @@ export class Transaction {
|
|
|
231
364
|
const isAnyoneCanPay = inputType === Transaction.SIGHASH_ANYONECANPAY;
|
|
232
365
|
const isNone = outputType === Transaction.SIGHASH_NONE;
|
|
233
366
|
const isSingle = outputType === Transaction.SIGHASH_SINGLE;
|
|
234
|
-
let hashPrevouts =
|
|
235
|
-
let hashAmounts =
|
|
236
|
-
let hashScriptPubKeys =
|
|
237
|
-
let hashSequences =
|
|
238
|
-
let hashOutputs =
|
|
367
|
+
let hashPrevouts = EMPTY_BYTES;
|
|
368
|
+
let hashAmounts = EMPTY_BYTES;
|
|
369
|
+
let hashScriptPubKeys = EMPTY_BYTES;
|
|
370
|
+
let hashSequences = EMPTY_BYTES;
|
|
371
|
+
let hashOutputs = EMPTY_BYTES;
|
|
372
|
+
// Use cache if provided (for SIGHASH_ALL, these are identical for all inputs)
|
|
239
373
|
if (!isAnyoneCanPay) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
374
|
+
if (taprootCache) {
|
|
375
|
+
hashPrevouts = taprootCache.hashPrevouts;
|
|
376
|
+
hashAmounts = taprootCache.hashAmounts;
|
|
377
|
+
hashScriptPubKeys = taprootCache.hashScriptPubKeys;
|
|
378
|
+
hashSequences = taprootCache.hashSequences;
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
let bufferWriter = new BinaryWriter(36 * this.ins.length);
|
|
382
|
+
this.ins.forEach((txIn) => {
|
|
383
|
+
bufferWriter.writeBytes(txIn.hash);
|
|
384
|
+
bufferWriter.writeUInt32LE(txIn.index);
|
|
385
|
+
});
|
|
386
|
+
hashPrevouts = bcrypto.sha256(bufferWriter.finish());
|
|
387
|
+
bufferWriter = new BinaryWriter(8 * this.ins.length);
|
|
388
|
+
values.forEach((value) => bufferWriter.writeUInt64LE(value));
|
|
389
|
+
hashAmounts = bcrypto.sha256(bufferWriter.finish());
|
|
390
|
+
bufferWriter = new BinaryWriter(prevOutScripts.map(varSliceSize).reduce((a, b) => a + b));
|
|
391
|
+
prevOutScripts.forEach((prevOutScript) => bufferWriter.writeVarBytes(prevOutScript));
|
|
392
|
+
hashScriptPubKeys = bcrypto.sha256(bufferWriter.finish());
|
|
393
|
+
bufferWriter = new BinaryWriter(4 * this.ins.length);
|
|
394
|
+
this.ins.forEach((txIn) => bufferWriter.writeUInt32LE(txIn.sequence));
|
|
395
|
+
hashSequences = bcrypto.sha256(bufferWriter.finish());
|
|
396
|
+
}
|
|
255
397
|
}
|
|
256
398
|
if (!(isNone || isSingle)) {
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
399
|
+
if (taprootCache) {
|
|
400
|
+
hashOutputs = taprootCache.hashOutputs;
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
if (!this.outs.length)
|
|
404
|
+
throw new Error('Add outputs to the transaction before signing.');
|
|
405
|
+
const txOutsSize = this.outs
|
|
406
|
+
.map((output) => 8 + varSliceSize(output.script))
|
|
407
|
+
.reduce((a, b) => a + b);
|
|
408
|
+
const bufferWriter = new BinaryWriter(txOutsSize);
|
|
409
|
+
this.outs.forEach((out) => {
|
|
410
|
+
bufferWriter.writeUInt64LE(out.value);
|
|
411
|
+
bufferWriter.writeVarBytes(out.script);
|
|
412
|
+
});
|
|
413
|
+
hashOutputs = bcrypto.sha256(bufferWriter.finish());
|
|
414
|
+
}
|
|
268
415
|
}
|
|
269
416
|
else if (isSingle && inIndex < this.outs.length) {
|
|
270
417
|
const output = this.outs[inIndex];
|
|
271
|
-
const bufferWriter =
|
|
272
|
-
bufferWriter.
|
|
273
|
-
bufferWriter.
|
|
274
|
-
hashOutputs = bcrypto.sha256(bufferWriter.
|
|
418
|
+
const bufferWriter = new BinaryWriter(8 + varSliceSize(output.script));
|
|
419
|
+
bufferWriter.writeUInt64LE(output.value);
|
|
420
|
+
bufferWriter.writeVarBytes(output.script);
|
|
421
|
+
hashOutputs = bcrypto.sha256(bufferWriter.finish());
|
|
275
422
|
}
|
|
276
423
|
const spendType = (leafHash ? 2 : 0) + (annex ? 1 : 0);
|
|
424
|
+
// Length calculation from:
|
|
425
|
+
// https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-14
|
|
426
|
+
// With extension from:
|
|
427
|
+
// https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki#signature-validation
|
|
277
428
|
const sigMsgSize = 174 -
|
|
278
429
|
(isAnyoneCanPay ? 49 : 0) -
|
|
279
430
|
(isNone ? 32 : 0) +
|
|
280
431
|
(annex ? 32 : 0) +
|
|
281
432
|
(leafHash ? 37 : 0);
|
|
282
|
-
const sigMsgWriter =
|
|
433
|
+
const sigMsgWriter = new BinaryWriter(sigMsgSize);
|
|
283
434
|
sigMsgWriter.writeUInt8(hashType);
|
|
284
|
-
|
|
285
|
-
sigMsgWriter.
|
|
286
|
-
sigMsgWriter.
|
|
287
|
-
sigMsgWriter.
|
|
288
|
-
sigMsgWriter.
|
|
289
|
-
sigMsgWriter.
|
|
435
|
+
// Transaction
|
|
436
|
+
sigMsgWriter.writeInt32LE(this.version);
|
|
437
|
+
sigMsgWriter.writeUInt32LE(this.locktime);
|
|
438
|
+
sigMsgWriter.writeBytes(hashPrevouts);
|
|
439
|
+
sigMsgWriter.writeBytes(hashAmounts);
|
|
440
|
+
sigMsgWriter.writeBytes(hashScriptPubKeys);
|
|
441
|
+
sigMsgWriter.writeBytes(hashSequences);
|
|
290
442
|
if (!(isNone || isSingle)) {
|
|
291
|
-
sigMsgWriter.
|
|
443
|
+
sigMsgWriter.writeBytes(hashOutputs);
|
|
292
444
|
}
|
|
445
|
+
// Input
|
|
293
446
|
sigMsgWriter.writeUInt8(spendType);
|
|
294
447
|
if (isAnyoneCanPay) {
|
|
295
448
|
const input = this.ins[inIndex];
|
|
296
|
-
sigMsgWriter.
|
|
297
|
-
sigMsgWriter.
|
|
298
|
-
sigMsgWriter.
|
|
299
|
-
sigMsgWriter.
|
|
300
|
-
sigMsgWriter.
|
|
449
|
+
sigMsgWriter.writeBytes(input.hash);
|
|
450
|
+
sigMsgWriter.writeUInt32LE(input.index);
|
|
451
|
+
sigMsgWriter.writeUInt64LE(values[inIndex]);
|
|
452
|
+
sigMsgWriter.writeVarBytes(prevOutScripts[inIndex]);
|
|
453
|
+
sigMsgWriter.writeUInt32LE(input.sequence);
|
|
301
454
|
}
|
|
302
455
|
else {
|
|
303
|
-
sigMsgWriter.
|
|
456
|
+
sigMsgWriter.writeUInt32LE(inIndex);
|
|
304
457
|
}
|
|
305
458
|
if (annex) {
|
|
306
|
-
const bufferWriter =
|
|
307
|
-
bufferWriter.
|
|
308
|
-
sigMsgWriter.
|
|
459
|
+
const bufferWriter = new BinaryWriter(varSliceSize(annex));
|
|
460
|
+
bufferWriter.writeVarBytes(annex);
|
|
461
|
+
sigMsgWriter.writeBytes(bcrypto.sha256(bufferWriter.finish()));
|
|
309
462
|
}
|
|
463
|
+
// Output
|
|
310
464
|
if (isSingle) {
|
|
311
|
-
sigMsgWriter.
|
|
465
|
+
sigMsgWriter.writeBytes(hashOutputs);
|
|
312
466
|
}
|
|
467
|
+
// BIP342 extension
|
|
313
468
|
if (leafHash) {
|
|
314
|
-
sigMsgWriter.
|
|
469
|
+
sigMsgWriter.writeBytes(leafHash);
|
|
315
470
|
sigMsgWriter.writeUInt8(0);
|
|
316
|
-
sigMsgWriter.
|
|
471
|
+
sigMsgWriter.writeUInt32LE(0xffffffff);
|
|
317
472
|
}
|
|
318
|
-
|
|
473
|
+
// Extra zero byte because:
|
|
474
|
+
// https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-19
|
|
475
|
+
const prefix = new Uint8Array([0x00]);
|
|
476
|
+
const sigMsg = sigMsgWriter.finish();
|
|
477
|
+
const combined = new Uint8Array(1 + sigMsg.length);
|
|
478
|
+
combined.set(prefix);
|
|
479
|
+
combined.set(sigMsg, 1);
|
|
480
|
+
return bcrypto.taggedHash('TapSighash', combined);
|
|
319
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* Pre-compute intermediate hashes for Taproot signing.
|
|
484
|
+
* Call this once before signing multiple inputs to avoid O(n^2) performance.
|
|
485
|
+
*
|
|
486
|
+
* @param prevOutScripts - Array of previous output scripts for all inputs
|
|
487
|
+
* @param values - Array of previous output values for all inputs
|
|
488
|
+
* @returns Cache object to pass to hashForWitnessV1
|
|
489
|
+
*/
|
|
490
|
+
getTaprootHashCache(prevOutScripts, values) {
|
|
491
|
+
// hashPrevouts
|
|
492
|
+
let bufferWriter = new BinaryWriter(36 * this.ins.length);
|
|
493
|
+
for (const txIn of this.ins) {
|
|
494
|
+
bufferWriter.writeBytes(txIn.hash);
|
|
495
|
+
bufferWriter.writeUInt32LE(txIn.index);
|
|
496
|
+
}
|
|
497
|
+
const hashPrevouts = bcrypto.sha256(bufferWriter.finish());
|
|
498
|
+
// hashAmounts
|
|
499
|
+
bufferWriter = new BinaryWriter(8 * values.length);
|
|
500
|
+
for (const value of values) {
|
|
501
|
+
bufferWriter.writeUInt64LE(value);
|
|
502
|
+
}
|
|
503
|
+
const hashAmounts = bcrypto.sha256(bufferWriter.finish());
|
|
504
|
+
// hashScriptPubKeys - compute size without intermediate array
|
|
505
|
+
let scriptPubKeysSize = 0;
|
|
506
|
+
for (const script of prevOutScripts) {
|
|
507
|
+
scriptPubKeysSize += varSliceSize(script);
|
|
508
|
+
}
|
|
509
|
+
bufferWriter = new BinaryWriter(scriptPubKeysSize);
|
|
510
|
+
for (const script of prevOutScripts) {
|
|
511
|
+
bufferWriter.writeVarBytes(script);
|
|
512
|
+
}
|
|
513
|
+
const hashScriptPubKeys = bcrypto.sha256(bufferWriter.finish());
|
|
514
|
+
// hashSequences
|
|
515
|
+
bufferWriter = new BinaryWriter(4 * this.ins.length);
|
|
516
|
+
for (const txIn of this.ins) {
|
|
517
|
+
bufferWriter.writeUInt32LE(txIn.sequence);
|
|
518
|
+
}
|
|
519
|
+
const hashSequences = bcrypto.sha256(bufferWriter.finish());
|
|
520
|
+
// hashOutputs - compute size without intermediate array
|
|
521
|
+
let txOutsSize = 0;
|
|
522
|
+
for (const out of this.outs) {
|
|
523
|
+
txOutsSize += 8 + varSliceSize(out.script);
|
|
524
|
+
}
|
|
525
|
+
bufferWriter = new BinaryWriter(txOutsSize);
|
|
526
|
+
for (const out of this.outs) {
|
|
527
|
+
bufferWriter.writeUInt64LE(out.value);
|
|
528
|
+
bufferWriter.writeVarBytes(out.script);
|
|
529
|
+
}
|
|
530
|
+
const hashOutputs = this.outs.length ? bcrypto.sha256(bufferWriter.finish()) : ZERO;
|
|
531
|
+
return { hashPrevouts, hashAmounts, hashScriptPubKeys, hashSequences, hashOutputs };
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Hash transaction for signing a SegWit v0 (P2WPKH/P2WSH) input.
|
|
535
|
+
*
|
|
536
|
+
* @param inIndex - Index of the input being signed
|
|
537
|
+
* @param prevOutScript - The script of the output being spent
|
|
538
|
+
* @param value - Value of the output being spent (bigint satoshis)
|
|
539
|
+
* @param hashType - Signature hash type
|
|
540
|
+
* @returns 32-byte hash for signing
|
|
541
|
+
*/
|
|
320
542
|
hashForWitnessV0(inIndex, prevOutScript, value, hashType) {
|
|
321
|
-
|
|
322
|
-
inIndex
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
543
|
+
if (!Number.isInteger(inIndex) || inIndex < 0 || inIndex > 0xffffffff) {
|
|
544
|
+
throw new TypeError('Expected unsigned 32-bit integer for inIndex');
|
|
545
|
+
}
|
|
546
|
+
if (!(prevOutScript instanceof Uint8Array)) {
|
|
547
|
+
throw new TypeError('Expected Uint8Array for prevOutScript');
|
|
548
|
+
}
|
|
549
|
+
if (typeof value !== 'bigint') {
|
|
550
|
+
throw new TypeError('Expected bigint for value');
|
|
551
|
+
}
|
|
552
|
+
if (!Number.isInteger(hashType) || hashType < 0 || hashType > 0xffffffff) {
|
|
553
|
+
throw new TypeError('Expected unsigned 32-bit integer for hashType');
|
|
554
|
+
}
|
|
555
|
+
let tbuffer;
|
|
328
556
|
let bufferWriter;
|
|
329
557
|
let hashOutputs = ZERO;
|
|
330
558
|
let hashPrevouts = ZERO;
|
|
331
559
|
let hashSequence = ZERO;
|
|
332
560
|
if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
|
|
333
|
-
tbuffer =
|
|
334
|
-
bufferWriter = new
|
|
561
|
+
tbuffer = alloc(36 * this.ins.length);
|
|
562
|
+
bufferWriter = new BinaryWriter(tbuffer, 0);
|
|
335
563
|
this.ins.forEach((txIn) => {
|
|
336
|
-
bufferWriter.
|
|
337
|
-
bufferWriter.
|
|
564
|
+
bufferWriter.writeBytes(txIn.hash);
|
|
565
|
+
bufferWriter.writeUInt32LE(txIn.index);
|
|
338
566
|
});
|
|
339
567
|
hashPrevouts = bcrypto.hash256(tbuffer);
|
|
340
568
|
}
|
|
341
569
|
if (!(hashType & Transaction.SIGHASH_ANYONECANPAY) &&
|
|
342
570
|
(hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
|
|
343
571
|
(hashType & 0x1f) !== Transaction.SIGHASH_NONE) {
|
|
344
|
-
tbuffer =
|
|
345
|
-
bufferWriter = new
|
|
572
|
+
tbuffer = alloc(4 * this.ins.length);
|
|
573
|
+
bufferWriter = new BinaryWriter(tbuffer, 0);
|
|
346
574
|
this.ins.forEach((txIn) => {
|
|
347
|
-
bufferWriter.
|
|
575
|
+
bufferWriter.writeUInt32LE(txIn.sequence);
|
|
348
576
|
});
|
|
349
577
|
hashSequence = bcrypto.hash256(tbuffer);
|
|
350
578
|
}
|
|
@@ -353,65 +581,120 @@ export class Transaction {
|
|
|
353
581
|
const txOutsSize = this.outs.reduce((sum, output) => {
|
|
354
582
|
return sum + 8 + varSliceSize(output.script);
|
|
355
583
|
}, 0);
|
|
356
|
-
tbuffer =
|
|
357
|
-
bufferWriter = new
|
|
584
|
+
tbuffer = alloc(txOutsSize);
|
|
585
|
+
bufferWriter = new BinaryWriter(tbuffer, 0);
|
|
358
586
|
this.outs.forEach((out) => {
|
|
359
|
-
bufferWriter.
|
|
360
|
-
bufferWriter.
|
|
587
|
+
bufferWriter.writeUInt64LE(out.value);
|
|
588
|
+
bufferWriter.writeVarBytes(out.script);
|
|
361
589
|
});
|
|
362
590
|
hashOutputs = bcrypto.hash256(tbuffer);
|
|
363
591
|
}
|
|
364
592
|
else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) {
|
|
365
593
|
const output = this.outs[inIndex];
|
|
366
|
-
tbuffer =
|
|
367
|
-
bufferWriter = new
|
|
368
|
-
bufferWriter.
|
|
369
|
-
bufferWriter.
|
|
594
|
+
tbuffer = alloc(8 + varSliceSize(output.script));
|
|
595
|
+
bufferWriter = new BinaryWriter(tbuffer, 0);
|
|
596
|
+
bufferWriter.writeUInt64LE(output.value);
|
|
597
|
+
bufferWriter.writeVarBytes(output.script);
|
|
370
598
|
hashOutputs = bcrypto.hash256(tbuffer);
|
|
371
599
|
}
|
|
372
|
-
tbuffer =
|
|
373
|
-
bufferWriter = new
|
|
600
|
+
tbuffer = alloc(156 + varSliceSize(prevOutScript));
|
|
601
|
+
bufferWriter = new BinaryWriter(tbuffer, 0);
|
|
374
602
|
const input = this.ins[inIndex];
|
|
375
|
-
bufferWriter.
|
|
376
|
-
bufferWriter.
|
|
377
|
-
bufferWriter.
|
|
378
|
-
bufferWriter.
|
|
379
|
-
bufferWriter.
|
|
380
|
-
bufferWriter.
|
|
381
|
-
bufferWriter.
|
|
382
|
-
bufferWriter.
|
|
383
|
-
bufferWriter.
|
|
384
|
-
bufferWriter.
|
|
385
|
-
bufferWriter.
|
|
603
|
+
bufferWriter.writeInt32LE(this.version);
|
|
604
|
+
bufferWriter.writeBytes(hashPrevouts);
|
|
605
|
+
bufferWriter.writeBytes(hashSequence);
|
|
606
|
+
bufferWriter.writeBytes(input.hash);
|
|
607
|
+
bufferWriter.writeUInt32LE(input.index);
|
|
608
|
+
bufferWriter.writeVarBytes(prevOutScript);
|
|
609
|
+
bufferWriter.writeUInt64LE(value);
|
|
610
|
+
bufferWriter.writeUInt32LE(input.sequence);
|
|
611
|
+
bufferWriter.writeBytes(hashOutputs);
|
|
612
|
+
bufferWriter.writeUInt32LE(this.locktime);
|
|
613
|
+
bufferWriter.writeUInt32LE(hashType);
|
|
386
614
|
return bcrypto.hash256(tbuffer);
|
|
387
615
|
}
|
|
616
|
+
/**
|
|
617
|
+
* Get the transaction hash.
|
|
618
|
+
*
|
|
619
|
+
* @param forWitness - If true, include witness data (wtxid)
|
|
620
|
+
* @returns 32-byte transaction hash
|
|
621
|
+
*/
|
|
388
622
|
getHash(forWitness) {
|
|
623
|
+
// wtxid for coinbase is always 32 bytes of 0x00
|
|
389
624
|
if (forWitness && this.isCoinbase())
|
|
390
|
-
return
|
|
391
|
-
return bcrypto.hash256(this
|
|
625
|
+
return new Uint8Array(32);
|
|
626
|
+
return bcrypto.hash256(this.#toBuffer(undefined, undefined, forWitness));
|
|
392
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Get the transaction ID (txid) as a hex string.
|
|
630
|
+
*
|
|
631
|
+
* @returns Transaction ID in reversed hex format
|
|
632
|
+
*/
|
|
393
633
|
getId() {
|
|
394
|
-
|
|
634
|
+
// transaction hash's are displayed in reverse order
|
|
635
|
+
return toHex(reverse(this.getHash(false)));
|
|
395
636
|
}
|
|
637
|
+
/**
|
|
638
|
+
* Serialize the transaction to a Uint8Array buffer.
|
|
639
|
+
*
|
|
640
|
+
* @param buffer - Optional pre-allocated buffer
|
|
641
|
+
* @param initialOffset - Optional starting offset in buffer
|
|
642
|
+
* @returns Serialized transaction bytes
|
|
643
|
+
*/
|
|
396
644
|
toBuffer(buffer, initialOffset) {
|
|
397
|
-
return this
|
|
645
|
+
return this.#toBuffer(buffer, initialOffset, true);
|
|
398
646
|
}
|
|
647
|
+
/**
|
|
648
|
+
* Serialize the transaction to a hex string.
|
|
649
|
+
*
|
|
650
|
+
* @returns Transaction as hex string
|
|
651
|
+
*/
|
|
399
652
|
toHex() {
|
|
400
|
-
return this.toBuffer(undefined, undefined)
|
|
653
|
+
return toHex(this.toBuffer(undefined, undefined));
|
|
401
654
|
}
|
|
655
|
+
/**
|
|
656
|
+
* Set the input script for a specific input.
|
|
657
|
+
*
|
|
658
|
+
* @param index - Input index
|
|
659
|
+
* @param scriptSig - The script to set
|
|
660
|
+
*/
|
|
402
661
|
setInputScript(index, scriptSig) {
|
|
403
|
-
|
|
662
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
663
|
+
throw new TypeError('Expected non-negative integer for index');
|
|
664
|
+
}
|
|
665
|
+
if (!(scriptSig instanceof Uint8Array)) {
|
|
666
|
+
throw new TypeError('Expected Uint8Array for scriptSig');
|
|
667
|
+
}
|
|
404
668
|
this.ins[index].script = scriptSig;
|
|
405
669
|
}
|
|
670
|
+
/**
|
|
671
|
+
* Set the witness data for a specific input.
|
|
672
|
+
*
|
|
673
|
+
* @param index - Input index
|
|
674
|
+
* @param witness - Array of witness elements
|
|
675
|
+
*/
|
|
406
676
|
setWitness(index, witness) {
|
|
407
|
-
|
|
677
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
678
|
+
throw new TypeError('Expected non-negative integer for index');
|
|
679
|
+
}
|
|
680
|
+
if (!Array.isArray(witness) || !witness.every((w) => w instanceof Uint8Array)) {
|
|
681
|
+
throw new TypeError('Expected array of Uint8Array for witness');
|
|
682
|
+
}
|
|
408
683
|
this.ins[index].witness = witness;
|
|
409
684
|
}
|
|
410
|
-
|
|
685
|
+
/**
|
|
686
|
+
* Internal method to serialize the transaction.
|
|
687
|
+
*
|
|
688
|
+
* @param buffer - Optional pre-allocated buffer
|
|
689
|
+
* @param initialOffset - Optional starting offset
|
|
690
|
+
* @param _ALLOW_WITNESS - Whether to include witness data
|
|
691
|
+
* @returns Serialized transaction bytes
|
|
692
|
+
*/
|
|
693
|
+
#toBuffer(buffer, initialOffset, _ALLOW_WITNESS = false) {
|
|
411
694
|
if (!buffer)
|
|
412
|
-
buffer =
|
|
413
|
-
const bufferWriter = new
|
|
414
|
-
bufferWriter.
|
|
695
|
+
buffer = alloc(this.byteLength(_ALLOW_WITNESS));
|
|
696
|
+
const bufferWriter = new BinaryWriter(buffer, initialOffset || 0);
|
|
697
|
+
bufferWriter.writeInt32LE(this.version);
|
|
415
698
|
const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
|
416
699
|
if (hasWitnesses) {
|
|
417
700
|
bufferWriter.writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER);
|
|
@@ -419,42 +702,26 @@ export class Transaction {
|
|
|
419
702
|
}
|
|
420
703
|
bufferWriter.writeVarInt(this.ins.length);
|
|
421
704
|
this.ins.forEach((txIn) => {
|
|
422
|
-
bufferWriter.
|
|
423
|
-
bufferWriter.
|
|
424
|
-
bufferWriter.
|
|
425
|
-
bufferWriter.
|
|
705
|
+
bufferWriter.writeBytes(txIn.hash);
|
|
706
|
+
bufferWriter.writeUInt32LE(txIn.index);
|
|
707
|
+
bufferWriter.writeVarBytes(txIn.script);
|
|
708
|
+
bufferWriter.writeUInt32LE(txIn.sequence);
|
|
426
709
|
});
|
|
427
710
|
bufferWriter.writeVarInt(this.outs.length);
|
|
428
711
|
this.outs.forEach((txOut) => {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
bufferWriter.writeSlice(txOut.valueBuffer);
|
|
434
|
-
}
|
|
435
|
-
bufferWriter.writeVarSlice(txOut.script);
|
|
712
|
+
bufferWriter.writeUInt64LE(txOut.value);
|
|
713
|
+
bufferWriter.writeVarBytes(txOut.script);
|
|
436
714
|
});
|
|
437
715
|
if (hasWitnesses) {
|
|
438
716
|
this.ins.forEach((input) => {
|
|
439
717
|
bufferWriter.writeVector(input.witness);
|
|
440
718
|
});
|
|
441
719
|
}
|
|
442
|
-
bufferWriter.
|
|
720
|
+
bufferWriter.writeUInt32LE(this.locktime);
|
|
721
|
+
// avoid slicing unless necessary
|
|
443
722
|
if (initialOffset !== undefined)
|
|
444
723
|
return buffer.subarray(initialOffset, bufferWriter.offset);
|
|
445
724
|
return buffer;
|
|
446
725
|
}
|
|
447
726
|
}
|
|
448
|
-
|
|
449
|
-
Transaction.SIGHASH_DEFAULT = 0x00;
|
|
450
|
-
Transaction.SIGHASH_ALL = 0x01;
|
|
451
|
-
Transaction.SIGHASH_NONE = 0x02;
|
|
452
|
-
Transaction.SIGHASH_SINGLE = 0x03;
|
|
453
|
-
Transaction.SIGHASH_ANYONECANPAY = 0x80;
|
|
454
|
-
Transaction.SIGHASH_OUTPUT_MASK = 0x03;
|
|
455
|
-
Transaction.SIGHASH_INPUT_MASK = 0x80;
|
|
456
|
-
Transaction.ADVANCED_TRANSACTION_MARKER = 0x00;
|
|
457
|
-
Transaction.ADVANCED_TRANSACTION_FLAG = 0x01;
|
|
458
|
-
Transaction.TRUC_VERSION = 3;
|
|
459
|
-
Transaction.TRUC_MAX_VSIZE = 10000;
|
|
460
|
-
Transaction.TRUC_CHILD_MAX_VSIZE = 1000;
|
|
727
|
+
//# sourceMappingURL=transaction.js.map
|