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