@btc-vision/bitcoin 6.4.10 → 6.5.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/.babelrc +13 -4
- package/.mocharc.json +13 -13
- package/.prettierrc.json +12 -12
- package/CHANGELOG.md +403 -403
- package/CONTRIBUTING.md +83 -83
- package/LICENSE +21 -21
- package/README.md +201 -201
- package/browser/chunks/crypto-C6FlKKmp.js +2006 -0
- package/browser/chunks/payments-BE4vwHhV.js +1045 -0
- package/browser/chunks/psbt-Dlosf9CT.js +3853 -0
- package/browser/chunks/script-COWGdiOo.js +318 -0
- package/browser/chunks/transaction-BiXwH2v4.js +421 -0
- package/browser/chunks/utils-BKmkTzNZ.js +759 -0
- package/browser/crypto/crypto.d.ts +1 -1
- package/browser/index.d.ts +7 -27
- package/browser/index.js +92 -2
- package/build/index.d.ts +7 -27
- package/build/index.js +2 -2
- package/cjs/package.json +3 -3
- package/gulpfile.js +42 -42
- package/package.json +153 -150
- package/src/bip66.ts +107 -107
- package/src/block.ts +233 -233
- package/src/bufferutils.ts +188 -188
- package/src/crypto.ts +108 -108
- package/src/ecc_lib.ts +94 -94
- package/src/hooks/AdvancedSignatureManager.ts +104 -104
- package/src/hooks/SignatureManager.ts +84 -84
- package/src/index.ts +83 -105
- package/src/merkle.ts +31 -31
- package/src/opcodes.ts +280 -280
- package/src/payments/bip341.ts +140 -140
- package/src/payments/embed.ts +61 -61
- package/src/payments/index.ts +172 -172
- package/src/payments/lazy.ts +28 -28
- package/src/payments/p2ms.ts +156 -156
- package/src/payments/p2op.ts +195 -195
- package/src/payments/p2pk.ts +93 -93
- package/src/payments/p2pkh.ts +214 -214
- package/src/payments/p2tr.ts +309 -309
- package/src/psbt/bip371.ts +441 -441
- package/src/push_data.ts +97 -97
- package/src/script.ts +247 -247
- package/src/script_number.ts +72 -72
- package/src/script_signature.ts +91 -91
- package/src/transaction.ts +656 -656
- package/test/address.spec.ts +155 -155
- package/test/bitcoin.core.spec.ts +212 -212
- package/test/block.spec.ts +171 -171
- package/test/bufferutils.spec.ts +450 -450
- package/test/crypto.spec.ts +49 -49
- package/test/fixtures/address.json +329 -329
- package/test/fixtures/block.json +148 -148
- package/test/fixtures/bufferutils.json +102 -102
- package/test/fixtures/core/README.md +26 -26
- package/test/fixtures/core/base58_encode_decode.json +50 -50
- package/test/fixtures/core/base58_keys_invalid.json +152 -152
- package/test/fixtures/core/base58_keys_valid.json +452 -452
- package/test/fixtures/core/blocks.json +27 -27
- package/test/fixtures/core/sig_canonical.json +7 -7
- package/test/fixtures/core/sig_noncanonical.json +33 -33
- package/test/fixtures/core/sighash.json +3505 -3505
- package/test/fixtures/core/tx_valid.json +2023 -2023
- package/test/fixtures/crypto.json +43 -43
- package/test/fixtures/ecdsa.json +217 -217
- package/test/fixtures/ecpair.json +141 -141
- package/test/fixtures/embed.json +108 -108
- package/test/fixtures/p2ms.json +434 -434
- package/test/fixtures/p2pk.json +179 -179
- package/test/fixtures/p2pkh.json +276 -276
- package/test/fixtures/p2sh.json +508 -508
- package/test/fixtures/p2tr.json +1198 -1198
- package/test/fixtures/p2wpkh.json +290 -290
- package/test/fixtures/p2wsh.json +489 -489
- package/test/fixtures/psbt.json +924 -924
- package/test/fixtures/script.json +465 -465
- package/test/fixtures/script_number.json +225 -225
- package/test/fixtures/signature.json +140 -140
- package/test/fixtures/transaction.json +916 -916
- package/test/integration/_regtest.ts +6 -6
- package/test/integration/addresses.spec.ts +142 -142
- package/test/integration/bip32.spec.ts +130 -130
- package/test/integration/blocks.spec.ts +28 -28
- package/test/integration/cltv.spec.ts +241 -241
- package/test/integration/csv.spec.ts +452 -452
- package/test/integration/payments.spec.ts +110 -110
- package/test/integration/taproot.spec.ts +663 -663
- package/test/integration/transactions.spec.ts +668 -668
- package/test/payments.spec.ts +114 -114
- package/test/payments.utils.ts +165 -165
- package/test/psbt.spec.ts +1285 -1285
- package/test/script.spec.ts +186 -186
- package/test/script_number.spec.ts +26 -26
- package/test/script_signature.spec.ts +66 -66
- package/test/transaction.spec.ts +337 -337
- package/test/ts-node-register.js +7 -7
- package/test/tsconfig.json +48 -48
- package/test/types.spec.ts +53 -53
- package/tsconfig.base.json +27 -27
- package/tsconfig.json +19 -19
- package/tsconfig.webpack.json +18 -18
- package/vite.config.browser.ts +93 -0
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/.ready +0 -0
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/.release-please-manifest.json +0 -3
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/CHANGELOG.md +0 -962
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/CONTRIBUTING.md +0 -34
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/LICENSE +0 -24
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/README.md +0 -273
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/SECURITY.md +0 -2
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/addon.gypi +0 -204
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/bin/node-gyp.js +0 -138
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/.release-please-manifest.json +0 -3
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/LICENSE +0 -28
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/data/ninja/build.ninja +0 -4
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc +0 -12
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/GypVsCMake.md +0 -116
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/Hacking.md +0 -46
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/InputFormatReference.md +0 -1080
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/LanguageSpecification.md +0 -430
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/README.md +0 -27
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/Testing.md +0 -450
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/docs/UserDocumentation.md +0 -965
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/gyp +0 -8
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/gyp.bat +0 -5
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/gyp_main.py +0 -45
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -365
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -206
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -1272
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -1547
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -59
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -153
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -271
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -574
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -692
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -711
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -171
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -169
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -113
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -55
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -804
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -1173
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -1318
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -127
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -103
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -461
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -89
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -57
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -2745
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -3976
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -44
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -2964
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -67
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -1391
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -25
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -3115
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -98
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -771
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -1260
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -174
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -61
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -373
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -1938
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation_test.py +0 -53
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -302
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -3198
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -65
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/LICENSE +0 -3
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.APACHE +0 -177
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.BSD +0 -23
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/__init__.py +0 -15
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/_elffile.py +0 -108
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/_manylinux.py +0 -252
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/_musllinux.py +0 -83
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/_parser.py +0 -359
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/_structures.py +0 -61
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/_tokenizer.py +0 -192
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/markers.py +0 -252
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/metadata.py +0 -825
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/py.typed +0 -0
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/requirements.py +0 -90
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/specifiers.py +0 -1030
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/tags.py +0 -553
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/utils.py +0 -172
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pylib/packaging/version.py +0 -563
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/pyproject.toml +0 -120
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/release-please-config.json +0 -11
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/gyp/test_gyp.py +0 -261
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/Find-VisualStudio.cs +0 -250
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/build.js +0 -227
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/clean.js +0 -15
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/configure.js +0 -328
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/create-config-gypi.js +0 -150
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/download.js +0 -39
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/find-node-directory.js +0 -63
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/find-python.js +0 -310
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/find-visualstudio.js +0 -590
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/install.js +0 -415
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/list.js +0 -26
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/log.js +0 -168
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/node-gyp.js +0 -188
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/process-release.js +0 -146
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/rebuild.js +0 -12
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/remove.js +0 -43
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/lib/util.js +0 -81
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/macOS_Catalina_acid_test.sh +0 -21
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/package.json +0 -51
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/release-please-config.json +0 -40
- package/.yarn/unplugged/node-gyp-npm-10.2.0-cad1109948/node_modules/node-gyp/src/win_delay_load_hook.cc +0 -39
- package/browser/index.js.LICENSE.txt +0 -14
- package/browser/ops.d.ts +0 -126
- package/build/ops.d.ts +0 -126
- package/build/ops.js +0 -127
- package/coverage/tmp/coverage-31752-1735543485354-0.json +0 -1
- package/coverage/tmp/coverage-59920-1735543484555-0.json +0 -1
- package/coverage/tmp/coverage-66252-1735543483919-0.json +0 -1
- package/coverage/tmp/coverage-68440-1735543485236-0.json +0 -1
- package/coverage/tmp/coverage-70588-1735543484426-0.json +0 -1
- package/coverage/tmp/coverage-79292-1735543485296-0.json +0 -1
- package/coverage/tmp/coverage-80212-1735543483980-0.json +0 -1
|
@@ -1,241 +1,241 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
import { ECPairFactory } from 'ecpair';
|
|
3
|
-
import * as ecc from 'tiny-secp256k1';
|
|
4
|
-
import { before, describe, it } from 'mocha';
|
|
5
|
-
import * as bitcoin from '../../src/index.js';
|
|
6
|
-
import { regtestUtils } from './_regtest.js';
|
|
7
|
-
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
import bip65 from 'bip65';
|
|
10
|
-
|
|
11
|
-
const ECPair = ECPairFactory(ecc);
|
|
12
|
-
const regtest = regtestUtils.network;
|
|
13
|
-
|
|
14
|
-
function toOutputScript(address: string): Buffer {
|
|
15
|
-
return bitcoin.address.toOutputScript(address, regtest);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function idToHash(txid: string): Buffer {
|
|
19
|
-
return Buffer.from(txid, 'hex').reverse();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const alice = ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest);
|
|
23
|
-
const bob = ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest);
|
|
24
|
-
|
|
25
|
-
describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
|
|
26
|
-
// force update MTP
|
|
27
|
-
before(async () => {
|
|
28
|
-
await regtestUtils.mine(11);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const hashType = bitcoin.Transaction.SIGHASH_ALL;
|
|
32
|
-
|
|
33
|
-
interface KeyPair {
|
|
34
|
-
publicKey: Buffer;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function cltvCheckSigOutput(aQ: KeyPair, bQ: KeyPair, lockTime: number): Buffer {
|
|
38
|
-
return bitcoin.script.fromASM(
|
|
39
|
-
`
|
|
40
|
-
OP_IF
|
|
41
|
-
${bitcoin.script.number.encode(lockTime).toString('hex')}
|
|
42
|
-
OP_CHECKLOCKTIMEVERIFY
|
|
43
|
-
OP_DROP
|
|
44
|
-
OP_ELSE
|
|
45
|
-
${bQ.publicKey.toString('hex')}
|
|
46
|
-
OP_CHECKSIGVERIFY
|
|
47
|
-
OP_ENDIF
|
|
48
|
-
${aQ.publicKey.toString('hex')}
|
|
49
|
-
OP_CHECKSIG
|
|
50
|
-
`
|
|
51
|
-
.trim()
|
|
52
|
-
.replace(/\s+/g, ' '),
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function utcNow(): number {
|
|
57
|
-
return Math.floor(Date.now() / 1000);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// expiry past, {Alice's signature} OP_TRUE
|
|
61
|
-
it(
|
|
62
|
-
'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
|
|
63
|
-
'the output after the expiry (in the past)',
|
|
64
|
-
async () => {
|
|
65
|
-
// 3 hours ago
|
|
66
|
-
const lockTime = bip65.encode({ utc: utcNow() - 3600 * 3 });
|
|
67
|
-
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
68
|
-
const { address } = bitcoin.payments.p2sh({
|
|
69
|
-
redeem: { output: redeemScript, network: regtest },
|
|
70
|
-
network: regtest,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// fund the P2SH(CLTV) address
|
|
74
|
-
const unspent = await regtestUtils.faucet(address!, 1e5);
|
|
75
|
-
const tx = new bitcoin.Transaction();
|
|
76
|
-
tx.locktime = lockTime;
|
|
77
|
-
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
78
|
-
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
79
|
-
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
|
|
80
|
-
|
|
81
|
-
// {Alice's signature} OP_TRUE
|
|
82
|
-
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
83
|
-
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
84
|
-
redeem: {
|
|
85
|
-
input: bitcoin.script.compile([
|
|
86
|
-
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
87
|
-
bitcoin.opcodes.OP_TRUE,
|
|
88
|
-
]),
|
|
89
|
-
output: redeemScript,
|
|
90
|
-
},
|
|
91
|
-
}).input;
|
|
92
|
-
tx.setInputScript(0, redeemScriptSig!);
|
|
93
|
-
|
|
94
|
-
await regtestUtils.broadcast(tx.toHex());
|
|
95
|
-
|
|
96
|
-
await regtestUtils.verify({
|
|
97
|
-
txId: tx.getId(),
|
|
98
|
-
address: regtestUtils.RANDOM_ADDRESS,
|
|
99
|
-
vout: 0,
|
|
100
|
-
value: 7e4,
|
|
101
|
-
});
|
|
102
|
-
},
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
// expiry will pass, {Alice's signature} OP_TRUE
|
|
106
|
-
it(
|
|
107
|
-
'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
|
|
108
|
-
'the output after the expiry (in the future)',
|
|
109
|
-
async () => {
|
|
110
|
-
const height = await regtestUtils.height();
|
|
111
|
-
// 5 blocks from now
|
|
112
|
-
const lockTime = bip65.encode({ blocks: height + 5 });
|
|
113
|
-
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
114
|
-
const { address } = bitcoin.payments.p2sh({
|
|
115
|
-
redeem: { output: redeemScript, network: regtest },
|
|
116
|
-
network: regtest,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// fund the P2SH(CLTV) address
|
|
120
|
-
const unspent = await regtestUtils.faucet(address!, 1e5);
|
|
121
|
-
const tx = new bitcoin.Transaction();
|
|
122
|
-
tx.locktime = lockTime;
|
|
123
|
-
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
124
|
-
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
125
|
-
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
|
|
126
|
-
|
|
127
|
-
// {Alice's signature} OP_TRUE
|
|
128
|
-
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
129
|
-
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
130
|
-
redeem: {
|
|
131
|
-
input: bitcoin.script.compile([
|
|
132
|
-
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
133
|
-
bitcoin.opcodes.OP_TRUE,
|
|
134
|
-
]),
|
|
135
|
-
output: redeemScript,
|
|
136
|
-
},
|
|
137
|
-
}).input;
|
|
138
|
-
tx.setInputScript(0, redeemScriptSig!);
|
|
139
|
-
|
|
140
|
-
// TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
|
|
141
|
-
// ...
|
|
142
|
-
// into the future!
|
|
143
|
-
await regtestUtils.mine(5);
|
|
144
|
-
await regtestUtils.broadcast(tx.toHex());
|
|
145
|
-
await regtestUtils.verify({
|
|
146
|
-
txId: tx.getId(),
|
|
147
|
-
address: regtestUtils.RANDOM_ADDRESS,
|
|
148
|
-
vout: 0,
|
|
149
|
-
value: 7e4,
|
|
150
|
-
});
|
|
151
|
-
},
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE
|
|
155
|
-
it(
|
|
156
|
-
'can create (and broadcast via 3PBP) a Transaction where Alice and Bob can ' +
|
|
157
|
-
'redeem the output at any time',
|
|
158
|
-
async () => {
|
|
159
|
-
// two hours ago
|
|
160
|
-
const lockTime = bip65.encode({ utc: utcNow() - 3600 * 2 });
|
|
161
|
-
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
162
|
-
const { address } = bitcoin.payments.p2sh({
|
|
163
|
-
redeem: { output: redeemScript, network: regtest },
|
|
164
|
-
network: regtest,
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// fund the P2SH(CLTV) address
|
|
168
|
-
const unspent = await regtestUtils.faucet(address!, 2e5);
|
|
169
|
-
const tx = new bitcoin.Transaction();
|
|
170
|
-
tx.locktime = lockTime;
|
|
171
|
-
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
172
|
-
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
173
|
-
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 8e4);
|
|
174
|
-
|
|
175
|
-
// {Alice's signature} {Bob's signature} OP_FALSE
|
|
176
|
-
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
177
|
-
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
178
|
-
redeem: {
|
|
179
|
-
input: bitcoin.script.compile([
|
|
180
|
-
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
181
|
-
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
|
|
182
|
-
bitcoin.opcodes.OP_FALSE,
|
|
183
|
-
]),
|
|
184
|
-
output: redeemScript,
|
|
185
|
-
},
|
|
186
|
-
}).input;
|
|
187
|
-
tx.setInputScript(0, redeemScriptSig!);
|
|
188
|
-
|
|
189
|
-
await regtestUtils.broadcast(tx.toHex());
|
|
190
|
-
await regtestUtils.verify({
|
|
191
|
-
txId: tx.getId(),
|
|
192
|
-
address: regtestUtils.RANDOM_ADDRESS,
|
|
193
|
-
vout: 0,
|
|
194
|
-
value: 8e4,
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
// expiry in the future, {Alice's signature} OP_TRUE
|
|
200
|
-
it(
|
|
201
|
-
'can create (but fail to broadcast via 3PBP) a Transaction where Alice ' +
|
|
202
|
-
'attempts to redeem before the expiry',
|
|
203
|
-
async () => {
|
|
204
|
-
// two hours from now
|
|
205
|
-
const lockTime = bip65.encode({ utc: utcNow() + 3600 * 2 });
|
|
206
|
-
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
207
|
-
const { address } = bitcoin.payments.p2sh({
|
|
208
|
-
redeem: { output: redeemScript, network: regtest },
|
|
209
|
-
network: regtest,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// fund the P2SH(CLTV) address
|
|
213
|
-
const unspent = await regtestUtils.faucet(address!, 2e4);
|
|
214
|
-
const tx = new bitcoin.Transaction();
|
|
215
|
-
tx.locktime = lockTime;
|
|
216
|
-
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
217
|
-
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
218
|
-
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 1e4);
|
|
219
|
-
|
|
220
|
-
// {Alice's signature} OP_TRUE
|
|
221
|
-
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
222
|
-
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
223
|
-
redeem: {
|
|
224
|
-
input: bitcoin.script.compile([
|
|
225
|
-
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
226
|
-
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
|
|
227
|
-
bitcoin.opcodes.OP_TRUE,
|
|
228
|
-
]),
|
|
229
|
-
output: redeemScript,
|
|
230
|
-
},
|
|
231
|
-
}).input;
|
|
232
|
-
tx.setInputScript(0, redeemScriptSig!);
|
|
233
|
-
|
|
234
|
-
await regtestUtils.broadcast(tx.toHex()).catch((err) => {
|
|
235
|
-
assert.throws(() => {
|
|
236
|
-
if (err) throw err;
|
|
237
|
-
}, /Error: non-final/);
|
|
238
|
-
});
|
|
239
|
-
},
|
|
240
|
-
);
|
|
241
|
-
});
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import { ECPairFactory } from 'ecpair';
|
|
3
|
+
import * as ecc from 'tiny-secp256k1';
|
|
4
|
+
import { before, describe, it } from 'mocha';
|
|
5
|
+
import * as bitcoin from '../../src/index.js';
|
|
6
|
+
import { regtestUtils } from './_regtest.js';
|
|
7
|
+
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
import bip65 from 'bip65';
|
|
10
|
+
|
|
11
|
+
const ECPair = ECPairFactory(ecc);
|
|
12
|
+
const regtest = regtestUtils.network;
|
|
13
|
+
|
|
14
|
+
function toOutputScript(address: string): Buffer {
|
|
15
|
+
return bitcoin.address.toOutputScript(address, regtest);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function idToHash(txid: string): Buffer {
|
|
19
|
+
return Buffer.from(txid, 'hex').reverse();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const alice = ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest);
|
|
23
|
+
const bob = ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest);
|
|
24
|
+
|
|
25
|
+
describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
|
|
26
|
+
// force update MTP
|
|
27
|
+
before(async () => {
|
|
28
|
+
await regtestUtils.mine(11);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const hashType = bitcoin.Transaction.SIGHASH_ALL;
|
|
32
|
+
|
|
33
|
+
interface KeyPair {
|
|
34
|
+
publicKey: Buffer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function cltvCheckSigOutput(aQ: KeyPair, bQ: KeyPair, lockTime: number): Buffer {
|
|
38
|
+
return bitcoin.script.fromASM(
|
|
39
|
+
`
|
|
40
|
+
OP_IF
|
|
41
|
+
${bitcoin.script.number.encode(lockTime).toString('hex')}
|
|
42
|
+
OP_CHECKLOCKTIMEVERIFY
|
|
43
|
+
OP_DROP
|
|
44
|
+
OP_ELSE
|
|
45
|
+
${bQ.publicKey.toString('hex')}
|
|
46
|
+
OP_CHECKSIGVERIFY
|
|
47
|
+
OP_ENDIF
|
|
48
|
+
${aQ.publicKey.toString('hex')}
|
|
49
|
+
OP_CHECKSIG
|
|
50
|
+
`
|
|
51
|
+
.trim()
|
|
52
|
+
.replace(/\s+/g, ' '),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function utcNow(): number {
|
|
57
|
+
return Math.floor(Date.now() / 1000);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// expiry past, {Alice's signature} OP_TRUE
|
|
61
|
+
it(
|
|
62
|
+
'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
|
|
63
|
+
'the output after the expiry (in the past)',
|
|
64
|
+
async () => {
|
|
65
|
+
// 3 hours ago
|
|
66
|
+
const lockTime = bip65.encode({ utc: utcNow() - 3600 * 3 });
|
|
67
|
+
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
68
|
+
const { address } = bitcoin.payments.p2sh({
|
|
69
|
+
redeem: { output: redeemScript, network: regtest },
|
|
70
|
+
network: regtest,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// fund the P2SH(CLTV) address
|
|
74
|
+
const unspent = await regtestUtils.faucet(address!, 1e5);
|
|
75
|
+
const tx = new bitcoin.Transaction();
|
|
76
|
+
tx.locktime = lockTime;
|
|
77
|
+
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
78
|
+
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
79
|
+
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
|
|
80
|
+
|
|
81
|
+
// {Alice's signature} OP_TRUE
|
|
82
|
+
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
83
|
+
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
84
|
+
redeem: {
|
|
85
|
+
input: bitcoin.script.compile([
|
|
86
|
+
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
87
|
+
bitcoin.opcodes.OP_TRUE,
|
|
88
|
+
]),
|
|
89
|
+
output: redeemScript,
|
|
90
|
+
},
|
|
91
|
+
}).input;
|
|
92
|
+
tx.setInputScript(0, redeemScriptSig!);
|
|
93
|
+
|
|
94
|
+
await regtestUtils.broadcast(tx.toHex());
|
|
95
|
+
|
|
96
|
+
await regtestUtils.verify({
|
|
97
|
+
txId: tx.getId(),
|
|
98
|
+
address: regtestUtils.RANDOM_ADDRESS,
|
|
99
|
+
vout: 0,
|
|
100
|
+
value: 7e4,
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// expiry will pass, {Alice's signature} OP_TRUE
|
|
106
|
+
it(
|
|
107
|
+
'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
|
|
108
|
+
'the output after the expiry (in the future)',
|
|
109
|
+
async () => {
|
|
110
|
+
const height = await regtestUtils.height();
|
|
111
|
+
// 5 blocks from now
|
|
112
|
+
const lockTime = bip65.encode({ blocks: height + 5 });
|
|
113
|
+
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
114
|
+
const { address } = bitcoin.payments.p2sh({
|
|
115
|
+
redeem: { output: redeemScript, network: regtest },
|
|
116
|
+
network: regtest,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// fund the P2SH(CLTV) address
|
|
120
|
+
const unspent = await regtestUtils.faucet(address!, 1e5);
|
|
121
|
+
const tx = new bitcoin.Transaction();
|
|
122
|
+
tx.locktime = lockTime;
|
|
123
|
+
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
124
|
+
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
125
|
+
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
|
|
126
|
+
|
|
127
|
+
// {Alice's signature} OP_TRUE
|
|
128
|
+
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
129
|
+
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
130
|
+
redeem: {
|
|
131
|
+
input: bitcoin.script.compile([
|
|
132
|
+
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
133
|
+
bitcoin.opcodes.OP_TRUE,
|
|
134
|
+
]),
|
|
135
|
+
output: redeemScript,
|
|
136
|
+
},
|
|
137
|
+
}).input;
|
|
138
|
+
tx.setInputScript(0, redeemScriptSig!);
|
|
139
|
+
|
|
140
|
+
// TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
|
|
141
|
+
// ...
|
|
142
|
+
// into the future!
|
|
143
|
+
await regtestUtils.mine(5);
|
|
144
|
+
await regtestUtils.broadcast(tx.toHex());
|
|
145
|
+
await regtestUtils.verify({
|
|
146
|
+
txId: tx.getId(),
|
|
147
|
+
address: regtestUtils.RANDOM_ADDRESS,
|
|
148
|
+
vout: 0,
|
|
149
|
+
value: 7e4,
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE
|
|
155
|
+
it(
|
|
156
|
+
'can create (and broadcast via 3PBP) a Transaction where Alice and Bob can ' +
|
|
157
|
+
'redeem the output at any time',
|
|
158
|
+
async () => {
|
|
159
|
+
// two hours ago
|
|
160
|
+
const lockTime = bip65.encode({ utc: utcNow() - 3600 * 2 });
|
|
161
|
+
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
162
|
+
const { address } = bitcoin.payments.p2sh({
|
|
163
|
+
redeem: { output: redeemScript, network: regtest },
|
|
164
|
+
network: regtest,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// fund the P2SH(CLTV) address
|
|
168
|
+
const unspent = await regtestUtils.faucet(address!, 2e5);
|
|
169
|
+
const tx = new bitcoin.Transaction();
|
|
170
|
+
tx.locktime = lockTime;
|
|
171
|
+
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
172
|
+
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
173
|
+
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 8e4);
|
|
174
|
+
|
|
175
|
+
// {Alice's signature} {Bob's signature} OP_FALSE
|
|
176
|
+
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
177
|
+
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
178
|
+
redeem: {
|
|
179
|
+
input: bitcoin.script.compile([
|
|
180
|
+
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
181
|
+
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
|
|
182
|
+
bitcoin.opcodes.OP_FALSE,
|
|
183
|
+
]),
|
|
184
|
+
output: redeemScript,
|
|
185
|
+
},
|
|
186
|
+
}).input;
|
|
187
|
+
tx.setInputScript(0, redeemScriptSig!);
|
|
188
|
+
|
|
189
|
+
await regtestUtils.broadcast(tx.toHex());
|
|
190
|
+
await regtestUtils.verify({
|
|
191
|
+
txId: tx.getId(),
|
|
192
|
+
address: regtestUtils.RANDOM_ADDRESS,
|
|
193
|
+
vout: 0,
|
|
194
|
+
value: 8e4,
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// expiry in the future, {Alice's signature} OP_TRUE
|
|
200
|
+
it(
|
|
201
|
+
'can create (but fail to broadcast via 3PBP) a Transaction where Alice ' +
|
|
202
|
+
'attempts to redeem before the expiry',
|
|
203
|
+
async () => {
|
|
204
|
+
// two hours from now
|
|
205
|
+
const lockTime = bip65.encode({ utc: utcNow() + 3600 * 2 });
|
|
206
|
+
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
|
|
207
|
+
const { address } = bitcoin.payments.p2sh({
|
|
208
|
+
redeem: { output: redeemScript, network: regtest },
|
|
209
|
+
network: regtest,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// fund the P2SH(CLTV) address
|
|
213
|
+
const unspent = await regtestUtils.faucet(address!, 2e4);
|
|
214
|
+
const tx = new bitcoin.Transaction();
|
|
215
|
+
tx.locktime = lockTime;
|
|
216
|
+
// Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
|
|
217
|
+
tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
|
|
218
|
+
tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 1e4);
|
|
219
|
+
|
|
220
|
+
// {Alice's signature} OP_TRUE
|
|
221
|
+
const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
|
|
222
|
+
const redeemScriptSig = bitcoin.payments.p2sh({
|
|
223
|
+
redeem: {
|
|
224
|
+
input: bitcoin.script.compile([
|
|
225
|
+
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
|
|
226
|
+
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
|
|
227
|
+
bitcoin.opcodes.OP_TRUE,
|
|
228
|
+
]),
|
|
229
|
+
output: redeemScript,
|
|
230
|
+
},
|
|
231
|
+
}).input;
|
|
232
|
+
tx.setInputScript(0, redeemScriptSig!);
|
|
233
|
+
|
|
234
|
+
await regtestUtils.broadcast(tx.toHex()).catch((err) => {
|
|
235
|
+
assert.throws(() => {
|
|
236
|
+
if (err) throw err;
|
|
237
|
+
}, /Error: non-final/);
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
);
|
|
241
|
+
});
|