@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
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker Signing Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* These tests verify that signatures generated through the worker signing
|
|
5
|
+
* infrastructure are cryptographically valid.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
9
|
+
import * as ecc from 'tiny-secp256k1';
|
|
10
|
+
import { ECPairFactory } from 'ecpair';
|
|
11
|
+
import { randomBytes } from 'crypto';
|
|
12
|
+
|
|
13
|
+
import { SignatureType, type WorkerEccLib } from '../src/workers/types.js';
|
|
14
|
+
import { generateWorkerCode } from '../src/workers/signing-worker.js';
|
|
15
|
+
import { toXOnly } from '../src/pubkey.js';
|
|
16
|
+
import { initEccLib } from '../src/ecc/context.js';
|
|
17
|
+
import type { EccLib } from '../src/types.js';
|
|
18
|
+
|
|
19
|
+
const ECPair = ECPairFactory(ecc);
|
|
20
|
+
|
|
21
|
+
describe('Worker Signing - Signature Verification', () => {
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
initEccLib(ecc as unknown as EccLib);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('ECDSA Signature Generation and Verification', () => {
|
|
27
|
+
it('should generate valid ECDSA signature that verifies', () => {
|
|
28
|
+
// Create a real key pair
|
|
29
|
+
const keyPair = ECPair.makeRandom();
|
|
30
|
+
const privateKey = keyPair.privateKey!;
|
|
31
|
+
const publicKey = keyPair.publicKey;
|
|
32
|
+
|
|
33
|
+
// Create a random 32-byte hash (simulating a transaction hash)
|
|
34
|
+
const hash = randomBytes(32);
|
|
35
|
+
|
|
36
|
+
// Sign using the ECC library directly (simulating what worker does)
|
|
37
|
+
const signature = ecc.sign(hash, privateKey);
|
|
38
|
+
|
|
39
|
+
// Verify the signature is valid
|
|
40
|
+
const isValid = ecc.verify(hash, publicKey, signature);
|
|
41
|
+
expect(isValid).toBe(true);
|
|
42
|
+
|
|
43
|
+
// Verify signature length (should be 64 bytes for raw signature)
|
|
44
|
+
expect(signature.length).toBe(64);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should generate valid ECDSA signature with lowR', () => {
|
|
48
|
+
const keyPair = ECPair.makeRandom();
|
|
49
|
+
const privateKey = keyPair.privateKey!;
|
|
50
|
+
const publicKey = keyPair.publicKey;
|
|
51
|
+
const hash = randomBytes(32);
|
|
52
|
+
|
|
53
|
+
// Sign with lowR (grind for low R value)
|
|
54
|
+
const signature = ecc.sign(hash, privateKey, undefined);
|
|
55
|
+
|
|
56
|
+
// Verify the signature is valid
|
|
57
|
+
const isValid = ecc.verify(hash, publicKey, signature);
|
|
58
|
+
expect(isValid).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should produce different signatures for different hashes', () => {
|
|
62
|
+
const keyPair = ECPair.makeRandom();
|
|
63
|
+
const privateKey = keyPair.privateKey!;
|
|
64
|
+
|
|
65
|
+
const hash1 = randomBytes(32);
|
|
66
|
+
const hash2 = randomBytes(32);
|
|
67
|
+
|
|
68
|
+
const sig1 = ecc.sign(hash1, privateKey);
|
|
69
|
+
const sig2 = ecc.sign(hash2, privateKey);
|
|
70
|
+
|
|
71
|
+
// Signatures should be different
|
|
72
|
+
expect(Buffer.from(sig1).equals(Buffer.from(sig2))).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should fail verification with wrong public key', () => {
|
|
76
|
+
const keyPair1 = ECPair.makeRandom();
|
|
77
|
+
const keyPair2 = ECPair.makeRandom();
|
|
78
|
+
const hash = randomBytes(32);
|
|
79
|
+
|
|
80
|
+
const signature = ecc.sign(hash, keyPair1.privateKey!);
|
|
81
|
+
|
|
82
|
+
// Verify with wrong public key should fail
|
|
83
|
+
const isValid = ecc.verify(hash, keyPair2.publicKey, signature);
|
|
84
|
+
expect(isValid).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should fail verification with modified hash', () => {
|
|
88
|
+
const keyPair = ECPair.makeRandom();
|
|
89
|
+
const hash = randomBytes(32);
|
|
90
|
+
|
|
91
|
+
const signature = ecc.sign(hash, keyPair.privateKey!);
|
|
92
|
+
|
|
93
|
+
// Modify the hash
|
|
94
|
+
const modifiedHash = Buffer.from(hash);
|
|
95
|
+
modifiedHash[0] ^= 0xff;
|
|
96
|
+
|
|
97
|
+
const isValid = ecc.verify(modifiedHash, keyPair.publicKey, signature);
|
|
98
|
+
expect(isValid).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should fail verification with corrupted signature', () => {
|
|
102
|
+
const keyPair = ECPair.makeRandom();
|
|
103
|
+
const hash = randomBytes(32);
|
|
104
|
+
|
|
105
|
+
const signature = Buffer.from(ecc.sign(hash, keyPair.privateKey!));
|
|
106
|
+
|
|
107
|
+
// Corrupt the signature
|
|
108
|
+
signature[0] ^= 0xff;
|
|
109
|
+
|
|
110
|
+
const isValid = ecc.verify(hash, keyPair.publicKey, signature);
|
|
111
|
+
expect(isValid).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Schnorr Signature Generation and Verification', () => {
|
|
116
|
+
it('should generate valid Schnorr signature that verifies', () => {
|
|
117
|
+
const keyPair = ECPair.makeRandom();
|
|
118
|
+
const privateKey = keyPair.privateKey!;
|
|
119
|
+
const publicKey = keyPair.publicKey;
|
|
120
|
+
const hash = randomBytes(32);
|
|
121
|
+
|
|
122
|
+
// Sign with Schnorr
|
|
123
|
+
const signature = ecc.signSchnorr(hash, privateKey);
|
|
124
|
+
|
|
125
|
+
// Schnorr signatures are always 64 bytes
|
|
126
|
+
expect(signature.length).toBe(64);
|
|
127
|
+
|
|
128
|
+
// Verify using x-only public key (32 bytes)
|
|
129
|
+
const xOnlyPubkey = toXOnly(publicKey);
|
|
130
|
+
const isValid = ecc.verifySchnorr(hash, xOnlyPubkey, signature);
|
|
131
|
+
expect(isValid).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should produce different Schnorr signatures for different hashes', () => {
|
|
135
|
+
const keyPair = ECPair.makeRandom();
|
|
136
|
+
const privateKey = keyPair.privateKey!;
|
|
137
|
+
|
|
138
|
+
const hash1 = randomBytes(32);
|
|
139
|
+
const hash2 = randomBytes(32);
|
|
140
|
+
|
|
141
|
+
const sig1 = ecc.signSchnorr(hash1, privateKey);
|
|
142
|
+
const sig2 = ecc.signSchnorr(hash2, privateKey);
|
|
143
|
+
|
|
144
|
+
expect(Buffer.from(sig1).equals(Buffer.from(sig2))).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should fail Schnorr verification with wrong public key', () => {
|
|
148
|
+
const keyPair1 = ECPair.makeRandom();
|
|
149
|
+
const keyPair2 = ECPair.makeRandom();
|
|
150
|
+
const hash = randomBytes(32);
|
|
151
|
+
|
|
152
|
+
const signature = ecc.signSchnorr(hash, keyPair1.privateKey!);
|
|
153
|
+
|
|
154
|
+
const xOnlyPubkey2 = toXOnly(keyPair2.publicKey);
|
|
155
|
+
const isValid = ecc.verifySchnorr(hash, xOnlyPubkey2, signature);
|
|
156
|
+
expect(isValid).toBe(false);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should fail Schnorr verification with modified hash', () => {
|
|
160
|
+
const keyPair = ECPair.makeRandom();
|
|
161
|
+
const hash = randomBytes(32);
|
|
162
|
+
|
|
163
|
+
const signature = ecc.signSchnorr(hash, keyPair.privateKey!);
|
|
164
|
+
|
|
165
|
+
const modifiedHash = Buffer.from(hash);
|
|
166
|
+
modifiedHash[0] ^= 0xff;
|
|
167
|
+
|
|
168
|
+
const xOnlyPubkey = toXOnly(keyPair.publicKey);
|
|
169
|
+
const isValid = ecc.verifySchnorr(modifiedHash, xOnlyPubkey, signature);
|
|
170
|
+
expect(isValid).toBe(false);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should fail Schnorr verification with corrupted signature', () => {
|
|
174
|
+
const keyPair = ECPair.makeRandom();
|
|
175
|
+
const hash = randomBytes(32);
|
|
176
|
+
|
|
177
|
+
const signature = Buffer.from(ecc.signSchnorr(hash, keyPair.privateKey!));
|
|
178
|
+
signature[0] ^= 0xff;
|
|
179
|
+
|
|
180
|
+
const xOnlyPubkey = toXOnly(keyPair.publicKey);
|
|
181
|
+
const isValid = ecc.verifySchnorr(hash, xOnlyPubkey, signature);
|
|
182
|
+
expect(isValid).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('WorkerEccLib Interface Compatibility', () => {
|
|
187
|
+
it('should create WorkerEccLib compatible wrapper', () => {
|
|
188
|
+
const eccLib: WorkerEccLib = {
|
|
189
|
+
sign: (hash: Uint8Array, privateKey: Uint8Array, lowR?: boolean): Uint8Array => {
|
|
190
|
+
return ecc.sign(hash, privateKey, undefined);
|
|
191
|
+
},
|
|
192
|
+
signSchnorr: (hash: Uint8Array, privateKey: Uint8Array): Uint8Array => {
|
|
193
|
+
return ecc.signSchnorr(hash, privateKey);
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const keyPair = ECPair.makeRandom();
|
|
198
|
+
const hash = randomBytes(32);
|
|
199
|
+
|
|
200
|
+
// Test ECDSA through wrapper
|
|
201
|
+
const ecdsaSig = eccLib.sign(hash, keyPair.privateKey!);
|
|
202
|
+
expect(ecc.verify(hash, keyPair.publicKey, ecdsaSig)).toBe(true);
|
|
203
|
+
|
|
204
|
+
// Test Schnorr through wrapper
|
|
205
|
+
const schnorrSig = eccLib.signSchnorr!(hash, keyPair.privateKey!);
|
|
206
|
+
expect(ecc.verifySchnorr(hash, toXOnly(keyPair.publicKey), schnorrSig)).toBe(true);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should handle signing type dispatch correctly', () => {
|
|
210
|
+
const eccLib: WorkerEccLib = {
|
|
211
|
+
sign: (hash: Uint8Array, privateKey: Uint8Array): Uint8Array => {
|
|
212
|
+
return ecc.sign(hash, privateKey);
|
|
213
|
+
},
|
|
214
|
+
signSchnorr: (hash: Uint8Array, privateKey: Uint8Array): Uint8Array => {
|
|
215
|
+
return ecc.signSchnorr(hash, privateKey);
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const keyPair = ECPair.makeRandom();
|
|
220
|
+
const hash = randomBytes(32);
|
|
221
|
+
|
|
222
|
+
// Simulate worker dispatch based on signatureType
|
|
223
|
+
const signatureType = SignatureType.Schnorr;
|
|
224
|
+
|
|
225
|
+
let signature: Uint8Array;
|
|
226
|
+
if (signatureType === SignatureType.Schnorr) {
|
|
227
|
+
signature = eccLib.signSchnorr!(hash, keyPair.privateKey!);
|
|
228
|
+
} else {
|
|
229
|
+
signature = eccLib.sign(hash, keyPair.privateKey!);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Verify Schnorr signature
|
|
233
|
+
expect(signature.length).toBe(64);
|
|
234
|
+
expect(ecc.verifySchnorr(hash, toXOnly(keyPair.publicKey), signature)).toBe(true);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('Key Zeroing Security', () => {
|
|
239
|
+
it('should verify secureZero clears key data', () => {
|
|
240
|
+
// Simulate the secureZero function from worker
|
|
241
|
+
const secureZero = (arr: Uint8Array): void => {
|
|
242
|
+
arr.fill(0);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const privateKey = new Uint8Array(randomBytes(32));
|
|
246
|
+
expect(privateKey.some((b) => b !== 0)).toBe(true); // Has non-zero bytes
|
|
247
|
+
|
|
248
|
+
secureZero(privateKey);
|
|
249
|
+
|
|
250
|
+
expect(privateKey.every((b) => b === 0)).toBe(true); // All zeros
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should verify key is zeroed after signing (simulation)', () => {
|
|
254
|
+
const keyPair = ECPair.makeRandom();
|
|
255
|
+
const hash = randomBytes(32);
|
|
256
|
+
|
|
257
|
+
// Simulate what worker does: copy key, sign, zero
|
|
258
|
+
const keyCopy = new Uint8Array(keyPair.privateKey!);
|
|
259
|
+
|
|
260
|
+
// Sign
|
|
261
|
+
const signature = ecc.sign(hash, keyCopy);
|
|
262
|
+
|
|
263
|
+
// Zero the key copy
|
|
264
|
+
keyCopy.fill(0);
|
|
265
|
+
|
|
266
|
+
// Signature should still be valid
|
|
267
|
+
expect(ecc.verify(hash, keyPair.publicKey, signature)).toBe(true);
|
|
268
|
+
|
|
269
|
+
// Key copy should be zeroed
|
|
270
|
+
expect(keyCopy.every((b) => b === 0)).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe('Batch Signing Simulation', () => {
|
|
275
|
+
it('should sign multiple inputs with same key', () => {
|
|
276
|
+
const keyPair = ECPair.makeRandom();
|
|
277
|
+
const hashes = Array.from({ length: 10 }, () => randomBytes(32));
|
|
278
|
+
|
|
279
|
+
const signatures = hashes.map((hash) => ecc.sign(hash, keyPair.privateKey!));
|
|
280
|
+
|
|
281
|
+
// All signatures should be valid
|
|
282
|
+
for (let i = 0; i < hashes.length; i++) {
|
|
283
|
+
expect(ecc.verify(hashes[i], keyPair.publicKey, signatures[i])).toBe(true);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should sign mixed ECDSA and Schnorr in batch', () => {
|
|
288
|
+
const keyPair = ECPair.makeRandom();
|
|
289
|
+
const tasks = [
|
|
290
|
+
{ hash: randomBytes(32), type: SignatureType.ECDSA },
|
|
291
|
+
{ hash: randomBytes(32), type: SignatureType.Schnorr },
|
|
292
|
+
{ hash: randomBytes(32), type: SignatureType.ECDSA },
|
|
293
|
+
{ hash: randomBytes(32), type: SignatureType.Schnorr },
|
|
294
|
+
];
|
|
295
|
+
|
|
296
|
+
const results = tasks.map((task) => {
|
|
297
|
+
if (task.type === SignatureType.Schnorr) {
|
|
298
|
+
return {
|
|
299
|
+
signature: ecc.signSchnorr(task.hash, keyPair.privateKey!),
|
|
300
|
+
type: task.type,
|
|
301
|
+
hash: task.hash,
|
|
302
|
+
};
|
|
303
|
+
} else {
|
|
304
|
+
return {
|
|
305
|
+
signature: ecc.sign(task.hash, keyPair.privateKey!),
|
|
306
|
+
type: task.type,
|
|
307
|
+
hash: task.hash,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Verify all signatures
|
|
313
|
+
for (const result of results) {
|
|
314
|
+
if (result.type === SignatureType.Schnorr) {
|
|
315
|
+
expect(
|
|
316
|
+
ecc.verifySchnorr(
|
|
317
|
+
result.hash,
|
|
318
|
+
toXOnly(keyPair.publicKey),
|
|
319
|
+
result.signature,
|
|
320
|
+
),
|
|
321
|
+
).toBe(true);
|
|
322
|
+
} else {
|
|
323
|
+
expect(ecc.verify(result.hash, keyPair.publicKey, result.signature)).toBe(true);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('should handle 100 signatures in parallel simulation', () => {
|
|
329
|
+
const keyPair = ECPair.makeRandom();
|
|
330
|
+
const tasks = Array.from({ length: 100 }, (_, i) => ({
|
|
331
|
+
hash: randomBytes(32),
|
|
332
|
+
type: i % 2 === 0 ? SignatureType.ECDSA : SignatureType.Schnorr,
|
|
333
|
+
}));
|
|
334
|
+
|
|
335
|
+
const startTime = Date.now();
|
|
336
|
+
|
|
337
|
+
const results = tasks.map((task) => {
|
|
338
|
+
if (task.type === SignatureType.Schnorr) {
|
|
339
|
+
return {
|
|
340
|
+
signature: ecc.signSchnorr(task.hash, keyPair.privateKey!),
|
|
341
|
+
type: task.type,
|
|
342
|
+
hash: task.hash,
|
|
343
|
+
};
|
|
344
|
+
} else {
|
|
345
|
+
return {
|
|
346
|
+
signature: ecc.sign(task.hash, keyPair.privateKey!),
|
|
347
|
+
type: task.type,
|
|
348
|
+
hash: task.hash,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const duration = Date.now() - startTime;
|
|
354
|
+
|
|
355
|
+
// Verify all signatures
|
|
356
|
+
let validCount = 0;
|
|
357
|
+
for (const result of results) {
|
|
358
|
+
let isValid: boolean;
|
|
359
|
+
if (result.type === SignatureType.Schnorr) {
|
|
360
|
+
isValid = ecc.verifySchnorr(
|
|
361
|
+
result.hash,
|
|
362
|
+
toXOnly(keyPair.publicKey),
|
|
363
|
+
result.signature,
|
|
364
|
+
);
|
|
365
|
+
} else {
|
|
366
|
+
isValid = ecc.verify(result.hash, keyPair.publicKey, result.signature);
|
|
367
|
+
}
|
|
368
|
+
if (isValid) validCount++;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
expect(validCount).toBe(100);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
describe('Edge Cases', () => {
|
|
376
|
+
it('should handle hash with all zeros', () => {
|
|
377
|
+
const keyPair = ECPair.makeRandom();
|
|
378
|
+
const hash = new Uint8Array(32).fill(0);
|
|
379
|
+
|
|
380
|
+
const signature = ecc.sign(hash, keyPair.privateKey!);
|
|
381
|
+
expect(ecc.verify(hash, keyPair.publicKey, signature)).toBe(true);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('should handle hash with all 0xff', () => {
|
|
385
|
+
const keyPair = ECPair.makeRandom();
|
|
386
|
+
const hash = new Uint8Array(32).fill(0xff);
|
|
387
|
+
|
|
388
|
+
const signature = ecc.sign(hash, keyPair.privateKey!);
|
|
389
|
+
expect(ecc.verify(hash, keyPair.publicKey, signature)).toBe(true);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should handle sequential hashes', () => {
|
|
393
|
+
const keyPair = ECPair.makeRandom();
|
|
394
|
+
|
|
395
|
+
for (let i = 0; i < 10; i++) {
|
|
396
|
+
const hash = new Uint8Array(32);
|
|
397
|
+
hash[0] = i;
|
|
398
|
+
|
|
399
|
+
const signature = ecc.sign(hash, keyPair.privateKey!);
|
|
400
|
+
expect(ecc.verify(hash, keyPair.publicKey, signature)).toBe(true);
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should handle deterministic signatures (same hash, same key)', () => {
|
|
405
|
+
const privateKey = new Uint8Array(32).fill(0x42);
|
|
406
|
+
// Check if this is a valid private key
|
|
407
|
+
if (!ecc.isPrivate(privateKey)) {
|
|
408
|
+
// Use a known valid private key
|
|
409
|
+
privateKey.fill(0);
|
|
410
|
+
privateKey[31] = 1; // Smallest valid private key
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const hash = new Uint8Array(32).fill(0xab);
|
|
414
|
+
|
|
415
|
+
// tiny-secp256k1 uses RFC6979 for deterministic signatures
|
|
416
|
+
const sig1 = ecc.sign(hash, privateKey);
|
|
417
|
+
const sig2 = ecc.sign(hash, privateKey);
|
|
418
|
+
|
|
419
|
+
// Signatures should be identical (deterministic)
|
|
420
|
+
expect(Buffer.from(sig1).equals(Buffer.from(sig2))).toBe(true);
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
describe('Worker Code Execution Simulation', () => {
|
|
425
|
+
it('should execute simulated worker signing flow', () => {
|
|
426
|
+
// Simulate the complete worker signing flow
|
|
427
|
+
const eccLib: WorkerEccLib = {
|
|
428
|
+
sign: (hash, privateKey) => ecc.sign(hash, privateKey),
|
|
429
|
+
signSchnorr: (hash, privateKey) => ecc.signSchnorr(hash, privateKey),
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
const keyPair = ECPair.makeRandom();
|
|
433
|
+
const privateKeyCopy = new Uint8Array(keyPair.privateKey!);
|
|
434
|
+
const hash = randomBytes(32);
|
|
435
|
+
|
|
436
|
+
// Simulate worker message handling
|
|
437
|
+
const signatureType = SignatureType.ECDSA;
|
|
438
|
+
let signature: Uint8Array;
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
if (signatureType === SignatureType.Schnorr) {
|
|
442
|
+
if (!eccLib.signSchnorr) {
|
|
443
|
+
throw new Error('ECC library does not support Schnorr');
|
|
444
|
+
}
|
|
445
|
+
signature = eccLib.signSchnorr(hash, privateKeyCopy);
|
|
446
|
+
} else {
|
|
447
|
+
signature = eccLib.sign(hash, privateKeyCopy);
|
|
448
|
+
}
|
|
449
|
+
} finally {
|
|
450
|
+
// Always zero the key (secureZero)
|
|
451
|
+
privateKeyCopy.fill(0);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Verify signature
|
|
455
|
+
expect(ecc.verify(hash, keyPair.publicKey, signature)).toBe(true);
|
|
456
|
+
|
|
457
|
+
// Verify key was zeroed
|
|
458
|
+
expect(privateKeyCopy.every((b) => b === 0)).toBe(true);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
it('should handle signing errors gracefully', () => {
|
|
462
|
+
// Create an invalid private key (all zeros is invalid)
|
|
463
|
+
const invalidPrivateKey = new Uint8Array(32).fill(0);
|
|
464
|
+
const hash = randomBytes(32);
|
|
465
|
+
|
|
466
|
+
// tiny-secp256k1 should throw or return null for invalid key
|
|
467
|
+
expect(() => {
|
|
468
|
+
ecc.sign(hash, invalidPrivateKey);
|
|
469
|
+
}).toThrow();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should validate hash length', () => {
|
|
473
|
+
const keyPair = ECPair.makeRandom();
|
|
474
|
+
|
|
475
|
+
// Too short
|
|
476
|
+
const shortHash = new Uint8Array(31);
|
|
477
|
+
expect(() => {
|
|
478
|
+
ecc.sign(shortHash, keyPair.privateKey!);
|
|
479
|
+
}).toThrow();
|
|
480
|
+
|
|
481
|
+
// Too long
|
|
482
|
+
const longHash = new Uint8Array(33);
|
|
483
|
+
expect(() => {
|
|
484
|
+
ecc.sign(longHash, keyPair.privateKey!);
|
|
485
|
+
}).toThrow();
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it('should validate private key length', () => {
|
|
489
|
+
const hash = randomBytes(32);
|
|
490
|
+
|
|
491
|
+
// Too short
|
|
492
|
+
const shortKey = new Uint8Array(31).fill(0x42);
|
|
493
|
+
expect(() => {
|
|
494
|
+
ecc.sign(hash, shortKey);
|
|
495
|
+
}).toThrow();
|
|
496
|
+
|
|
497
|
+
// Too long
|
|
498
|
+
const longKey = new Uint8Array(33).fill(0x42);
|
|
499
|
+
expect(() => {
|
|
500
|
+
ecc.sign(hash, longKey);
|
|
501
|
+
}).toThrow();
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
describe('Taproot-Specific Tests', () => {
|
|
506
|
+
it('should generate valid key-path Taproot signature', () => {
|
|
507
|
+
const keyPair = ECPair.makeRandom();
|
|
508
|
+
const hash = randomBytes(32); // Taproot sighash
|
|
509
|
+
|
|
510
|
+
const signature = ecc.signSchnorr(hash, keyPair.privateKey!);
|
|
511
|
+
const xOnlyPubkey = toXOnly(keyPair.publicKey);
|
|
512
|
+
|
|
513
|
+
expect(signature.length).toBe(64);
|
|
514
|
+
expect(xOnlyPubkey.length).toBe(32);
|
|
515
|
+
expect(ecc.verifySchnorr(hash, xOnlyPubkey, signature)).toBe(true);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it('should generate valid script-path Taproot signature', () => {
|
|
519
|
+
const keyPair = ECPair.makeRandom();
|
|
520
|
+
// Script-path uses a different hash that includes the leaf hash
|
|
521
|
+
const hash = randomBytes(32);
|
|
522
|
+
const leafHash = randomBytes(32);
|
|
523
|
+
|
|
524
|
+
// The actual signing is the same, just the hash is computed differently
|
|
525
|
+
const signature = ecc.signSchnorr(hash, keyPair.privateKey!);
|
|
526
|
+
const xOnlyPubkey = toXOnly(keyPair.publicKey);
|
|
527
|
+
|
|
528
|
+
expect(ecc.verifySchnorr(hash, xOnlyPubkey, signature)).toBe(true);
|
|
529
|
+
|
|
530
|
+
// Leaf hash is stored in result for PSBT update
|
|
531
|
+
expect(leafHash.length).toBe(32);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it('should verify x-only pubkey extraction', () => {
|
|
535
|
+
const keyPair = ECPair.makeRandom();
|
|
536
|
+
const fullPubkey = keyPair.publicKey;
|
|
537
|
+
const xOnlyPubkey = toXOnly(fullPubkey);
|
|
538
|
+
|
|
539
|
+
// x-only pubkey should be 32 bytes (the x-coordinate)
|
|
540
|
+
expect(xOnlyPubkey.length).toBe(32);
|
|
541
|
+
|
|
542
|
+
// Should be the x-coordinate (bytes 1-32 of compressed pubkey)
|
|
543
|
+
expect(Buffer.from(xOnlyPubkey).equals(Buffer.from(fullPubkey.subarray(1, 33)))).toBe(
|
|
544
|
+
true,
|
|
545
|
+
);
|
|
546
|
+
});
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
describe('Real Transaction Hash Signing', () => {
|
|
550
|
+
it('should sign a real transaction sighash', () => {
|
|
551
|
+
const keyPair = ECPair.makeRandom();
|
|
552
|
+
|
|
553
|
+
// This is a real Bitcoin transaction sighash (SHA256d of signing data)
|
|
554
|
+
// In practice, this would come from PSBT's hashForSignature
|
|
555
|
+
const sighash = Buffer.from(
|
|
556
|
+
'0100000000000000000000000000000000000000000000000000000000000000',
|
|
557
|
+
'hex',
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
const signature = ecc.sign(sighash, keyPair.privateKey!);
|
|
561
|
+
|
|
562
|
+
// Verify signature
|
|
563
|
+
expect(ecc.verify(sighash, keyPair.publicKey, signature)).toBe(true);
|
|
564
|
+
|
|
565
|
+
// Signature should be 64 bytes raw (will be DER encoded when added to tx)
|
|
566
|
+
expect(signature.length).toBe(64);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('should handle multiple sighash types', () => {
|
|
570
|
+
const keyPair = ECPair.makeRandom();
|
|
571
|
+
|
|
572
|
+
// Different sighash values would produce different hashes
|
|
573
|
+
// Here we simulate signing with different "sighashes"
|
|
574
|
+
const sighashAll = randomBytes(32);
|
|
575
|
+
const sighashNone = randomBytes(32);
|
|
576
|
+
const sighashSingle = randomBytes(32);
|
|
577
|
+
|
|
578
|
+
const sigAll = ecc.sign(sighashAll, keyPair.privateKey!);
|
|
579
|
+
const sigNone = ecc.sign(sighashNone, keyPair.privateKey!);
|
|
580
|
+
const sigSingle = ecc.sign(sighashSingle, keyPair.privateKey!);
|
|
581
|
+
|
|
582
|
+
expect(ecc.verify(sighashAll, keyPair.publicKey, sigAll)).toBe(true);
|
|
583
|
+
expect(ecc.verify(sighashNone, keyPair.publicKey, sigNone)).toBe(true);
|
|
584
|
+
expect(ecc.verify(sighashSingle, keyPair.publicKey, sigSingle)).toBe(true);
|
|
585
|
+
|
|
586
|
+
// Cross-verification should fail
|
|
587
|
+
expect(ecc.verify(sighashAll, keyPair.publicKey, sigNone)).toBe(false);
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
describe('Worker Code Integrity', () => {
|
|
593
|
+
it('should generate code that contains signing logic', () => {
|
|
594
|
+
const code = generateWorkerCode();
|
|
595
|
+
|
|
596
|
+
// Must contain the signing dispatch logic
|
|
597
|
+
expect(code).toContain('signatureType === 1');
|
|
598
|
+
expect(code).toContain('eccLib.signSchnorr');
|
|
599
|
+
expect(code).toContain('eccLib.sign');
|
|
600
|
+
|
|
601
|
+
// Must contain result posting
|
|
602
|
+
expect(code).toContain("type: 'result'");
|
|
603
|
+
expect(code).toContain('signature');
|
|
604
|
+
expect(code).toContain('inputIndex');
|
|
605
|
+
expect(code).toContain('publicKey');
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
it('should generate code with proper error handling', () => {
|
|
609
|
+
const code = generateWorkerCode();
|
|
610
|
+
|
|
611
|
+
// Must have try-catch
|
|
612
|
+
expect(code).toContain('try {');
|
|
613
|
+
expect(code).toContain('} catch');
|
|
614
|
+
|
|
615
|
+
// Must post error on failure
|
|
616
|
+
expect(code).toContain("type: 'error'");
|
|
617
|
+
|
|
618
|
+
// Must zero key even on error (in finally or catch)
|
|
619
|
+
expect(code).toContain('secureZero(privateKey)');
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('should generate code with input validation', () => {
|
|
623
|
+
const code = generateWorkerCode();
|
|
624
|
+
|
|
625
|
+
// Must validate hash
|
|
626
|
+
expect(code).toContain('hash.length !== 32');
|
|
627
|
+
|
|
628
|
+
// Must validate privateKey
|
|
629
|
+
expect(code).toContain('privateKey.length !== 32');
|
|
630
|
+
|
|
631
|
+
// ECC library is bundled at compile time, no runtime check needed
|
|
632
|
+
expect(code).toContain('eccBundle');
|
|
633
|
+
expect(code).toContain('eccLib');
|
|
634
|
+
});
|
|
635
|
+
});
|