@btc-vision/bitcoin 6.3.5 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/.mocharc.json +13 -0
  2. package/browser/address.d.ts +1 -1
  3. package/browser/index.js +1 -1
  4. package/browser/index.js.LICENSE.txt +3 -3
  5. package/browser/networks.d.ts +1 -0
  6. package/browser/psbt/psbtutils.d.ts +1 -1
  7. package/build/address.d.ts +1 -1
  8. package/build/address.js +12 -5
  9. package/build/block.js +2 -2
  10. package/build/bufferutils.js +5 -5
  11. package/build/networks.d.ts +1 -0
  12. package/build/networks.js +11 -0
  13. package/build/psbt/psbtutils.js +2 -2
  14. package/build/psbt.js +3 -7
  15. package/package.json +26 -26
  16. package/src/address.ts +20 -6
  17. package/src/block.ts +233 -233
  18. package/src/bufferutils.ts +188 -180
  19. package/src/index.ts +86 -86
  20. package/src/networks.ts +12 -0
  21. package/src/psbt/bip371.ts +441 -441
  22. package/src/psbt/psbtutils.ts +4 -3
  23. package/src/psbt.ts +2187 -2187
  24. package/test/address.spec.ts +155 -177
  25. package/test/bitcoin.core.spec.ts +212 -234
  26. package/test/block.spec.ts +171 -194
  27. package/test/bufferutils.spec.ts +450 -513
  28. package/test/crypto.spec.ts +49 -55
  29. package/test/fixtures/address.json +3 -3
  30. package/test/integration/addresses.spec.ts +142 -154
  31. package/test/integration/bip32.spec.ts +130 -151
  32. package/test/integration/blocks.spec.ts +28 -28
  33. package/test/integration/cltv.spec.ts +241 -283
  34. package/test/integration/csv.spec.ts +452 -527
  35. package/test/integration/payments.spec.ts +110 -135
  36. package/test/integration/taproot.spec.ts +663 -707
  37. package/test/integration/transactions.spec.ts +668 -769
  38. package/test/payments.spec.ts +114 -125
  39. package/test/payments.utils.ts +165 -208
  40. package/test/psbt.spec.ts +1285 -1414
  41. package/test/script.spec.ts +186 -210
  42. package/test/script_number.spec.ts +26 -29
  43. package/test/script_signature.spec.ts +66 -66
  44. package/test/transaction.spec.ts +337 -387
  45. package/test/ts-node-register.js +7 -5
  46. package/test/tsconfig.json +4 -1
  47. package/test/types.spec.ts +53 -58
  48. package/.nyc_output/6368a5b2-daa5-4821-8ed0-b742d6fc7eab.json +0 -1
  49. package/.nyc_output/processinfo/6368a5b2-daa5-4821-8ed0-b742d6fc7eab.json +0 -1
  50. package/.nyc_output/processinfo/index.json +0 -1
  51. package/test/address.spec.js +0 -124
  52. package/test/bitcoin.core.spec.js +0 -170
  53. package/test/block.spec.js +0 -141
  54. package/test/bufferutils.spec.js +0 -427
  55. package/test/crypto.spec.js +0 -41
  56. package/test/integration/_regtest.js +0 -7
  57. package/test/integration/addresses.spec.js +0 -116
  58. package/test/integration/bip32.spec.js +0 -85
  59. package/test/integration/blocks.spec.js +0 -26
  60. package/test/integration/cltv.spec.js +0 -199
  61. package/test/integration/csv.spec.js +0 -362
  62. package/test/integration/payments.spec.js +0 -98
  63. package/test/integration/taproot.spec.js +0 -532
  64. package/test/integration/transactions.spec.js +0 -561
  65. package/test/payments.spec.js +0 -97
  66. package/test/payments.utils.js +0 -190
  67. package/test/psbt.spec.js +0 -1044
  68. package/test/script.spec.js +0 -151
  69. package/test/script_number.spec.js +0 -24
  70. package/test/script_signature.spec.js +0 -52
  71. package/test/transaction.spec.js +0 -269
  72. package/test/types.spec.js +0 -46
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const assert = require("assert");
4
- const mocha_1 = require("mocha");
5
- const bitcoin = require("../..");
6
- (0, mocha_1.describe)('bitcoinjs-lib (blocks)', () => {
7
- (0, mocha_1.it)('can extract a height from a CoinBase transaction', () => {
8
- // from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6
9
- const txHex = '010000000001010000000000000000000000000000000000000000000000000000000' +
10
- '000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a' +
11
- '2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98f' +
12
- 'd16761d220400000000000000aa340000d49f0000ffffffff02b07fc3660000000019' +
13
- '76a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266' +
14
- 'a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12' +
15
- 'bf1e40012000000000000000000000000000000000000000000000000000000000000' +
16
- '0000000000000';
17
- const tx = bitcoin.Transaction.fromHex(txHex);
18
- assert.strictEqual(tx.ins.length, 1);
19
- const script = tx.ins[0].script;
20
- // bitcoin.script.decompile(script) // returns [] :(
21
- assert.strictEqual(script[0], 0x03);
22
- const heightBuffer = script.slice(1, 4);
23
- const height = bitcoin.script.number.decode(heightBuffer);
24
- assert.strictEqual(height, 498303);
25
- });
26
- });
@@ -1,199 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const assert = require("assert");
4
- const ecpair_1 = require("ecpair");
5
- const ecc = require("tiny-secp256k1");
6
- const mocha_1 = require("mocha");
7
- const bitcoin = require("../..");
8
- const _regtest_1 = require("./_regtest");
9
- const ECPair = (0, ecpair_1.default)(ecc);
10
- const regtest = _regtest_1.regtestUtils.network;
11
- const bip65 = require('bip65');
12
- function toOutputScript(address) {
13
- return bitcoin.address.toOutputScript(address, regtest);
14
- }
15
- function idToHash(txid) {
16
- return Buffer.from(txid, 'hex').reverse();
17
- }
18
- const alice = ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest);
19
- const bob = ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest);
20
- (0, mocha_1.describe)('bitcoinjs-lib (transactions w/ CLTV)', () => {
21
- // force update MTP
22
- (0, mocha_1.before)(async () => {
23
- await _regtest_1.regtestUtils.mine(11);
24
- });
25
- const hashType = bitcoin.Transaction.SIGHASH_ALL;
26
- function cltvCheckSigOutput(aQ, bQ, lockTime) {
27
- return bitcoin.script.fromASM(`
28
- OP_IF
29
- ${bitcoin.script.number.encode(lockTime).toString('hex')}
30
- OP_CHECKLOCKTIMEVERIFY
31
- OP_DROP
32
- OP_ELSE
33
- ${bQ.publicKey.toString('hex')}
34
- OP_CHECKSIGVERIFY
35
- OP_ENDIF
36
- ${aQ.publicKey.toString('hex')}
37
- OP_CHECKSIG
38
- `
39
- .trim()
40
- .replace(/\s+/g, ' '));
41
- }
42
- function utcNow() {
43
- return Math.floor(Date.now() / 1000);
44
- }
45
- // expiry past, {Alice's signature} OP_TRUE
46
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
47
- 'the output after the expiry (in the past)', async () => {
48
- // 3 hours ago
49
- const lockTime = bip65.encode({ utc: utcNow() - 3600 * 3 });
50
- const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
51
- const { address } = bitcoin.payments.p2sh({
52
- redeem: { output: redeemScript, network: regtest },
53
- network: regtest,
54
- });
55
- // fund the P2SH(CLTV) address
56
- const unspent = await _regtest_1.regtestUtils.faucet(address, 1e5);
57
- const tx = new bitcoin.Transaction();
58
- tx.locktime = lockTime;
59
- // Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
60
- tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
61
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 7e4);
62
- // {Alice's signature} OP_TRUE
63
- const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
64
- const redeemScriptSig = bitcoin.payments.p2sh({
65
- redeem: {
66
- input: bitcoin.script.compile([
67
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
68
- bitcoin.opcodes.OP_TRUE,
69
- ]),
70
- output: redeemScript,
71
- },
72
- }).input;
73
- tx.setInputScript(0, redeemScriptSig);
74
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
75
- await _regtest_1.regtestUtils.verify({
76
- txId: tx.getId(),
77
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
78
- vout: 0,
79
- value: 7e4,
80
- });
81
- });
82
- // expiry will pass, {Alice's signature} OP_TRUE
83
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
84
- 'the output after the expiry (in the future)', async () => {
85
- const height = await _regtest_1.regtestUtils.height();
86
- // 5 blocks from now
87
- const lockTime = bip65.encode({ blocks: height + 5 });
88
- const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
89
- const { address } = bitcoin.payments.p2sh({
90
- redeem: { output: redeemScript, network: regtest },
91
- network: regtest,
92
- });
93
- // fund the P2SH(CLTV) address
94
- const unspent = await _regtest_1.regtestUtils.faucet(address, 1e5);
95
- const tx = new bitcoin.Transaction();
96
- tx.locktime = lockTime;
97
- // Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
98
- tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
99
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 7e4);
100
- // {Alice's signature} OP_TRUE
101
- const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
102
- const redeemScriptSig = bitcoin.payments.p2sh({
103
- redeem: {
104
- input: bitcoin.script.compile([
105
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
106
- bitcoin.opcodes.OP_TRUE,
107
- ]),
108
- output: redeemScript,
109
- },
110
- }).input;
111
- tx.setInputScript(0, redeemScriptSig);
112
- // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
113
- // ...
114
- // into the future!
115
- await _regtest_1.regtestUtils.mine(5);
116
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
117
- await _regtest_1.regtestUtils.verify({
118
- txId: tx.getId(),
119
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
120
- vout: 0,
121
- value: 7e4,
122
- });
123
- });
124
- // expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE
125
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Alice and Bob can ' +
126
- 'redeem the output at any time', async () => {
127
- // two hours ago
128
- const lockTime = bip65.encode({ utc: utcNow() - 3600 * 2 });
129
- const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
130
- const { address } = bitcoin.payments.p2sh({
131
- redeem: { output: redeemScript, network: regtest },
132
- network: regtest,
133
- });
134
- // fund the P2SH(CLTV) address
135
- const unspent = await _regtest_1.regtestUtils.faucet(address, 2e5);
136
- const tx = new bitcoin.Transaction();
137
- tx.locktime = lockTime;
138
- // Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
139
- tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
140
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 8e4);
141
- // {Alice's signature} {Bob's signature} OP_FALSE
142
- const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
143
- const redeemScriptSig = bitcoin.payments.p2sh({
144
- redeem: {
145
- input: bitcoin.script.compile([
146
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
147
- bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
148
- bitcoin.opcodes.OP_FALSE,
149
- ]),
150
- output: redeemScript,
151
- },
152
- }).input;
153
- tx.setInputScript(0, redeemScriptSig);
154
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
155
- await _regtest_1.regtestUtils.verify({
156
- txId: tx.getId(),
157
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
158
- vout: 0,
159
- value: 8e4,
160
- });
161
- });
162
- // expiry in the future, {Alice's signature} OP_TRUE
163
- (0, mocha_1.it)('can create (but fail to broadcast via 3PBP) a Transaction where Alice ' +
164
- 'attempts to redeem before the expiry', async () => {
165
- // two hours from now
166
- const lockTime = bip65.encode({ utc: utcNow() + 3600 * 2 });
167
- const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
168
- const { address } = bitcoin.payments.p2sh({
169
- redeem: { output: redeemScript, network: regtest },
170
- network: regtest,
171
- });
172
- // fund the P2SH(CLTV) address
173
- const unspent = await _regtest_1.regtestUtils.faucet(address, 2e4);
174
- const tx = new bitcoin.Transaction();
175
- tx.locktime = lockTime;
176
- // Note: nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
177
- tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
178
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 1e4);
179
- // {Alice's signature} OP_TRUE
180
- const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
181
- const redeemScriptSig = bitcoin.payments.p2sh({
182
- redeem: {
183
- input: bitcoin.script.compile([
184
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
185
- bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
186
- bitcoin.opcodes.OP_TRUE,
187
- ]),
188
- output: redeemScript,
189
- },
190
- }).input;
191
- tx.setInputScript(0, redeemScriptSig);
192
- await _regtest_1.regtestUtils.broadcast(tx.toHex()).catch(err => {
193
- assert.throws(() => {
194
- if (err)
195
- throw err;
196
- }, /Error: non-final/);
197
- });
198
- });
199
- });
@@ -1,362 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const assert = require("assert");
4
- const ecpair_1 = require("ecpair");
5
- const ecc = require("tiny-secp256k1");
6
- const mocha_1 = require("mocha");
7
- const bitcoin = require("../..");
8
- const _regtest_1 = require("./_regtest");
9
- const ECPair = (0, ecpair_1.default)(ecc);
10
- const regtest = _regtest_1.regtestUtils.network;
11
- const bip68 = require('bip68');
12
- const varuint = require('varuint-bitcoin');
13
- function toOutputScript(address) {
14
- return bitcoin.address.toOutputScript(address, regtest);
15
- }
16
- function idToHash(txid) {
17
- return Buffer.from(txid, 'hex').reverse();
18
- }
19
- const alice = ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest);
20
- const bob = ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest);
21
- const charles = ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsMSb4Ubnf', regtest);
22
- const dave = ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsMwS4pqnx', regtest);
23
- (0, mocha_1.describe)('bitcoinjs-lib (transactions w/ CSV)', () => {
24
- // force update MTP
25
- (0, mocha_1.before)(async () => {
26
- await _regtest_1.regtestUtils.mine(11);
27
- });
28
- const hashType = bitcoin.Transaction.SIGHASH_ALL;
29
- // IF MTP (from when confirmed) > seconds, _alice can redeem
30
- function csvCheckSigOutput(_alice, _bob, sequence) {
31
- return bitcoin.script.fromASM(`
32
- OP_IF
33
- ${bitcoin.script.number.encode(sequence).toString('hex')}
34
- OP_CHECKSEQUENCEVERIFY
35
- OP_DROP
36
- OP_ELSE
37
- ${_bob.publicKey.toString('hex')}
38
- OP_CHECKSIGVERIFY
39
- OP_ENDIF
40
- ${_alice.publicKey.toString('hex')}
41
- OP_CHECKSIG
42
- `
43
- .trim()
44
- .replace(/\s+/g, ' '));
45
- }
46
- // 2 of 3 multisig of _bob, _charles, _dave,
47
- // but after sequence1 time, _alice can allow the multisig to become 1 of 3.
48
- // but after sequence2 time, _alice can sign for the output all by themself.
49
- // Ref: https://github.com/bitcoinbook/bitcoinbook/blob/f8b883dcd4e3d1b9adf40fed59b7e898fbd9241f/ch07.asciidoc#complex-script-example
50
- // Note: bitcoinjs-lib will not offer specific support for problems with
51
- // advanced script usages such as below. Use at your own risk.
52
- function complexCsvOutput(_alice, _bob, _charles, _dave, sequence1, sequence2) {
53
- return bitcoin.script.fromASM(`
54
- OP_IF
55
- OP_IF
56
- OP_2
57
- OP_ELSE
58
- ${bitcoin.script.number.encode(sequence1).toString('hex')}
59
- OP_CHECKSEQUENCEVERIFY
60
- OP_DROP
61
- ${_alice.publicKey.toString('hex')}
62
- OP_CHECKSIGVERIFY
63
- OP_1
64
- OP_ENDIF
65
- ${_bob.publicKey.toString('hex')}
66
- ${_charles.publicKey.toString('hex')}
67
- ${_dave.publicKey.toString('hex')}
68
- OP_3
69
- OP_CHECKMULTISIG
70
- OP_ELSE
71
- ${bitcoin.script.number.encode(sequence2).toString('hex')}
72
- OP_CHECKSEQUENCEVERIFY
73
- OP_DROP
74
- ${_alice.publicKey.toString('hex')}
75
- OP_CHECKSIG
76
- OP_ENDIF
77
- `
78
- .trim()
79
- .replace(/\s+/g, ' '));
80
- }
81
- // expiry will pass, {Alice's signature} OP_TRUE
82
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
83
- 'the output after the expiry (in the future) (simple CHECKSEQUENCEVERIFY)', async () => {
84
- // 5 blocks from now
85
- const sequence = bip68.encode({ blocks: 5 });
86
- const p2sh = bitcoin.payments.p2sh({
87
- redeem: {
88
- output: csvCheckSigOutput(alice, bob, sequence),
89
- },
90
- network: regtest,
91
- });
92
- // fund the P2SH(CSV) address
93
- const unspent = await _regtest_1.regtestUtils.faucet(p2sh.address, 1e5);
94
- const utx = await _regtest_1.regtestUtils.fetch(unspent.txId);
95
- // for non segwit inputs, you must pass the full transaction buffer
96
- const nonWitnessUtxo = Buffer.from(utx.txHex, 'hex');
97
- // This is an example of using the finalizeInput second parameter to
98
- // define how you finalize the inputs, allowing for any type of script.
99
- const tx = new bitcoin.Psbt({ network: regtest })
100
- .setVersion(2)
101
- .addInput({
102
- hash: unspent.txId,
103
- index: unspent.vout,
104
- sequence,
105
- redeemScript: p2sh.redeem.output,
106
- nonWitnessUtxo,
107
- })
108
- .addOutput({
109
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
110
- value: 7e4,
111
- })
112
- .signInput(0, alice)
113
- .finalizeInput(0, csvGetFinalScripts) // See csvGetFinalScripts below
114
- .extractTransaction();
115
- // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
116
- // ...
117
- // into the future!
118
- await _regtest_1.regtestUtils.mine(10);
119
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
120
- await _regtest_1.regtestUtils.verify({
121
- txId: tx.getId(),
122
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
123
- vout: 0,
124
- value: 7e4,
125
- });
126
- });
127
- // expiry in the future, {Alice's signature} OP_TRUE
128
- (0, mocha_1.it)('can create (but fail to broadcast via 3PBP) a Transaction where Alice ' +
129
- 'attempts to redeem before the expiry (simple CHECKSEQUENCEVERIFY)', async () => {
130
- // two hours after confirmation
131
- const sequence = bip68.encode({ seconds: 7168 });
132
- const p2sh = bitcoin.payments.p2sh({
133
- network: regtest,
134
- redeem: {
135
- output: csvCheckSigOutput(alice, bob, sequence),
136
- },
137
- });
138
- // fund the P2SH(CSV) address
139
- const unspent = await _regtest_1.regtestUtils.faucet(p2sh.address, 2e4);
140
- const tx = new bitcoin.Transaction();
141
- tx.version = 2;
142
- tx.addInput(idToHash(unspent.txId), unspent.vout, sequence);
143
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 1e4);
144
- // {Alice's signature} OP_TRUE
145
- const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType);
146
- const redeemScriptSig = bitcoin.payments.p2sh({
147
- network: regtest,
148
- redeem: {
149
- network: regtest,
150
- output: p2sh.redeem.output,
151
- input: bitcoin.script.compile([
152
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
153
- bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
154
- bitcoin.opcodes.OP_TRUE,
155
- ]),
156
- },
157
- }).input;
158
- tx.setInputScript(0, redeemScriptSig);
159
- await _regtest_1.regtestUtils.broadcast(tx.toHex()).catch(err => {
160
- assert.throws(() => {
161
- if (err)
162
- throw err;
163
- }, /Error: non-BIP68-final/);
164
- });
165
- });
166
- // Check first combination of complex CSV, 2 of 3
167
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Bob and Charles ' +
168
- 'can send (complex CHECKSEQUENCEVERIFY)', async () => {
169
- // 2 blocks from now
170
- const sequence1 = bip68.encode({ blocks: 2 });
171
- // 5 blocks from now
172
- const sequence2 = bip68.encode({ blocks: 5 });
173
- const p2sh = bitcoin.payments.p2sh({
174
- redeem: {
175
- output: complexCsvOutput(alice, bob, charles, dave, sequence1, sequence2),
176
- },
177
- network: regtest,
178
- });
179
- // fund the P2SH(CCSV) address
180
- const unspent = await _regtest_1.regtestUtils.faucet(p2sh.address, 1e5);
181
- const tx = new bitcoin.Transaction();
182
- tx.version = 2;
183
- tx.addInput(idToHash(unspent.txId), unspent.vout);
184
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 7e4);
185
- // OP_0 {Bob sig} {Charles sig} OP_TRUE OP_TRUE
186
- const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType);
187
- const redeemScriptSig = bitcoin.payments.p2sh({
188
- network: regtest,
189
- redeem: {
190
- network: regtest,
191
- output: p2sh.redeem.output,
192
- input: bitcoin.script.compile([
193
- bitcoin.opcodes.OP_0,
194
- bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
195
- bitcoin.script.signature.encode(charles.sign(signatureHash), hashType),
196
- bitcoin.opcodes.OP_TRUE,
197
- bitcoin.opcodes.OP_TRUE,
198
- ]),
199
- },
200
- }).input;
201
- tx.setInputScript(0, redeemScriptSig);
202
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
203
- await _regtest_1.regtestUtils.verify({
204
- txId: tx.getId(),
205
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
206
- vout: 0,
207
- value: 7e4,
208
- });
209
- });
210
- // Check first combination of complex CSV, mediator + 1 of 3 after 2 blocks
211
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Alice (mediator) ' +
212
- 'and Bob can send after 2 blocks (complex CHECKSEQUENCEVERIFY)', async () => {
213
- // 2 blocks from now
214
- const sequence1 = bip68.encode({ blocks: 2 });
215
- // 5 blocks from now
216
- const sequence2 = bip68.encode({ blocks: 5 });
217
- const p2sh = bitcoin.payments.p2sh({
218
- redeem: {
219
- output: complexCsvOutput(alice, bob, charles, dave, sequence1, sequence2),
220
- },
221
- network: regtest,
222
- });
223
- // fund the P2SH(CCSV) address
224
- const unspent = await _regtest_1.regtestUtils.faucet(p2sh.address, 1e5);
225
- const tx = new bitcoin.Transaction();
226
- tx.version = 2;
227
- tx.addInput(idToHash(unspent.txId), unspent.vout, sequence1); // Set sequence1 for input
228
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 7e4);
229
- // OP_0 {Bob sig} {Alice mediator sig} OP_FALSE OP_TRUE
230
- const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType);
231
- const redeemScriptSig = bitcoin.payments.p2sh({
232
- network: regtest,
233
- redeem: {
234
- network: regtest,
235
- output: p2sh.redeem.output,
236
- input: bitcoin.script.compile([
237
- bitcoin.opcodes.OP_0,
238
- bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
239
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
240
- bitcoin.opcodes.OP_0,
241
- bitcoin.opcodes.OP_TRUE,
242
- ]),
243
- },
244
- }).input;
245
- tx.setInputScript(0, redeemScriptSig);
246
- // Wait 2 blocks
247
- await _regtest_1.regtestUtils.mine(2);
248
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
249
- await _regtest_1.regtestUtils.verify({
250
- txId: tx.getId(),
251
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
252
- vout: 0,
253
- value: 7e4,
254
- });
255
- });
256
- // Check first combination of complex CSV, mediator after 5 blocks
257
- (0, mocha_1.it)('can create (and broadcast via 3PBP) a Transaction where Alice (mediator) ' +
258
- 'can send after 5 blocks (complex CHECKSEQUENCEVERIFY)', async () => {
259
- // 2 blocks from now
260
- const sequence1 = bip68.encode({ blocks: 2 });
261
- // 5 blocks from now
262
- const sequence2 = bip68.encode({ blocks: 5 });
263
- const p2sh = bitcoin.payments.p2sh({
264
- redeem: {
265
- output: complexCsvOutput(alice, bob, charles, dave, sequence1, sequence2),
266
- },
267
- network: regtest,
268
- });
269
- // fund the P2SH(CCSV) address
270
- const unspent = await _regtest_1.regtestUtils.faucet(p2sh.address, 1e5);
271
- const tx = new bitcoin.Transaction();
272
- tx.version = 2;
273
- tx.addInput(idToHash(unspent.txId), unspent.vout, sequence2); // Set sequence2 for input
274
- tx.addOutput(toOutputScript(_regtest_1.regtestUtils.RANDOM_ADDRESS), 7e4);
275
- // {Alice mediator sig} OP_FALSE
276
- const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType);
277
- const redeemScriptSig = bitcoin.payments.p2sh({
278
- network: regtest,
279
- redeem: {
280
- network: regtest,
281
- output: p2sh.redeem.output,
282
- input: bitcoin.script.compile([
283
- bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
284
- bitcoin.opcodes.OP_0,
285
- ]),
286
- },
287
- }).input;
288
- tx.setInputScript(0, redeemScriptSig);
289
- // Wait 5 blocks
290
- await _regtest_1.regtestUtils.mine(5);
291
- await _regtest_1.regtestUtils.broadcast(tx.toHex());
292
- await _regtest_1.regtestUtils.verify({
293
- txId: tx.getId(),
294
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
295
- vout: 0,
296
- value: 7e4,
297
- });
298
- });
299
- });
300
- // This function is used to finalize a CSV transaction using PSBT.
301
- // See first test above.
302
- function csvGetFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH) {
303
- // Step 1: Check to make sure the meaningful script matches what you expect.
304
- const decompiled = bitcoin.script.decompile(script);
305
- // Checking if first OP is OP_IF... should do better check in production!
306
- // You may even want to check the public keys in the script against a
307
- // whitelist depending on the circumstances!!!
308
- // You also want to check the contents of the input to see if you have enough
309
- // info to actually construct the scriptSig and Witnesses.
310
- if (!decompiled || decompiled[0] !== bitcoin.opcodes.OP_IF) {
311
- throw new Error(`Can not finalize input #${inputIndex}`);
312
- }
313
- // Step 2: Create final scripts
314
- let payment = {
315
- network: regtest,
316
- output: script,
317
- // This logic should be more strict and make sure the pubkeys in the
318
- // meaningful script are the ones signing in the PSBT etc.
319
- input: bitcoin.script.compile([
320
- input.partialSig[0].signature,
321
- bitcoin.opcodes.OP_TRUE,
322
- ]),
323
- };
324
- if (isP2WSH && isSegwit)
325
- payment = bitcoin.payments.p2wsh({
326
- network: regtest,
327
- redeem: payment,
328
- });
329
- if (isP2SH)
330
- payment = bitcoin.payments.p2sh({
331
- network: regtest,
332
- redeem: payment,
333
- });
334
- function witnessStackToScriptWitness(witness) {
335
- let buffer = Buffer.allocUnsafe(0);
336
- function writeSlice(slice) {
337
- buffer = Buffer.concat([buffer, Buffer.from(slice)]);
338
- }
339
- function writeVarInt(i) {
340
- const currentLen = buffer.length;
341
- const varintLen = varuint.encodingLength(i);
342
- buffer = Buffer.concat([buffer, Buffer.allocUnsafe(varintLen)]);
343
- varuint.encode(i, buffer, currentLen);
344
- }
345
- function writeVarSlice(slice) {
346
- writeVarInt(slice.length);
347
- writeSlice(slice);
348
- }
349
- function writeVector(vector) {
350
- writeVarInt(vector.length);
351
- vector.forEach(writeVarSlice);
352
- }
353
- writeVector(witness);
354
- return buffer;
355
- }
356
- return {
357
- finalScriptSig: payment.input,
358
- finalScriptWitness: payment.witness && payment.witness.length > 0
359
- ? witnessStackToScriptWitness(payment.witness)
360
- : undefined,
361
- };
362
- }
@@ -1,98 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const ecpair_1 = require("ecpair");
4
- const ecc = require("tiny-secp256k1");
5
- const mocha_1 = require("mocha");
6
- const bitcoin = require("../..");
7
- const _regtest_1 = require("./_regtest");
8
- const ECPair = (0, ecpair_1.default)(ecc);
9
- const NETWORK = _regtest_1.regtestUtils.network;
10
- const keyPairs = [
11
- ECPair.makeRandom({ network: NETWORK }),
12
- ECPair.makeRandom({ network: NETWORK }),
13
- ];
14
- async function buildAndSign(depends, prevOutput, redeemScript, witnessScript) {
15
- const unspent = await _regtest_1.regtestUtils.faucetComplex(prevOutput, 5e4);
16
- const utx = await _regtest_1.regtestUtils.fetch(unspent.txId);
17
- const psbt = new bitcoin.Psbt({ network: NETWORK })
18
- .addInput({
19
- hash: unspent.txId,
20
- index: unspent.vout,
21
- nonWitnessUtxo: Buffer.from(utx.txHex, 'hex'),
22
- ...(redeemScript ? { redeemScript } : {}),
23
- ...(witnessScript ? { witnessScript } : {}),
24
- })
25
- .addOutput({
26
- address: _regtest_1.regtestUtils.RANDOM_ADDRESS,
27
- value: 2e4,
28
- });
29
- if (depends.signatures) {
30
- keyPairs.forEach(keyPair => {
31
- psbt.signInput(0, keyPair);
32
- });
33
- }
34
- else if (depends.signature) {
35
- psbt.signInput(0, keyPairs[0]);
36
- }
37
- return _regtest_1.regtestUtils.broadcast(psbt.finalizeAllInputs().extractTransaction().toHex());
38
- }
39
- ['p2ms', 'p2pk', 'p2pkh', 'p2wpkh'].forEach(k => {
40
- const fixtures = require('../fixtures/' + k);
41
- const { depends } = fixtures.dynamic;
42
- const fn = bitcoin.payments[k];
43
- const base = {};
44
- if (depends.pubkey)
45
- base.pubkey = keyPairs[0].publicKey;
46
- if (depends.pubkeys)
47
- base.pubkeys = keyPairs.map(x => x.publicKey);
48
- if (depends.m)
49
- base.m = base.pubkeys.length;
50
- const { output } = fn(base);
51
- if (!output)
52
- throw new TypeError('Missing output');
53
- (0, mocha_1.describe)('bitcoinjs-lib (payments - ' + k + ')', () => {
54
- (0, mocha_1.it)('can broadcast as an output, and be spent as an input', async () => {
55
- Object.assign(depends, { prevOutScriptType: k });
56
- await buildAndSign(depends, output, undefined, undefined);
57
- });
58
- (0, mocha_1.it)('can (as P2SH(' +
59
- k +
60
- ')) broadcast as an output, and be spent as an input', async () => {
61
- const p2sh = bitcoin.payments.p2sh({
62
- redeem: { output },
63
- network: NETWORK,
64
- });
65
- Object.assign(depends, { prevOutScriptType: 'p2sh-' + k });
66
- await buildAndSign(depends, p2sh.output, p2sh.redeem.output, undefined);
67
- });
68
- // NOTE: P2WPKH cannot be wrapped in P2WSH, consensus fail
69
- if (k === 'p2wpkh')
70
- return;
71
- (0, mocha_1.it)('can (as P2WSH(' +
72
- k +
73
- ')) broadcast as an output, and be spent as an input', async () => {
74
- const p2wsh = bitcoin.payments.p2wsh({
75
- redeem: { output },
76
- network: NETWORK,
77
- });
78
- Object.assign(depends, { prevOutScriptType: 'p2wsh-' + k });
79
- await buildAndSign(depends, p2wsh.output, undefined, p2wsh.redeem.output);
80
- });
81
- (0, mocha_1.it)('can (as P2SH(P2WSH(' +
82
- k +
83
- '))) broadcast as an output, and be spent as an input', async () => {
84
- const p2wsh = bitcoin.payments.p2wsh({
85
- redeem: { output },
86
- network: NETWORK,
87
- });
88
- const p2sh = bitcoin.payments.p2sh({
89
- redeem: { output: p2wsh.output },
90
- network: NETWORK,
91
- });
92
- Object.assign(depends, {
93
- prevOutScriptType: 'p2sh-p2wsh-' + k,
94
- });
95
- await buildAndSign(depends, p2sh.output, p2sh.redeem.output, p2wsh.redeem.output);
96
- });
97
- });
98
- });