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