ln-service 59.3.1 → 59.3.3
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/CHANGELOG.md +1 -1
- package/package.json +11 -10
- package/test/integration/test_propose_channel.js +66 -63
- package/test/macros/index.js +0 -16
- package/test/signerrpc-integration/test_begin_group_signing_session.js +159 -97
- package/test/signerrpc-integration/test_sign_taproot.js +136 -68
- package/test/walletrpc-integration/test_fund_psbt.js +169 -100
- package/test/macros/btcsuite_type_daemon.js +0 -143
- package/test/macros/chain_send_transaction.js +0 -102
- package/test/macros/change_password.js +0 -441
- package/test/macros/connect_chain_node.js +0 -27
- package/test/macros/create_cluster.js +0 -426
- package/test/macros/generate_blocks.js +0 -141
- package/test/macros/get_raw_transaction.js +0 -78
- package/test/macros/mine_transaction.js +0 -87
- package/test/macros/rpc.js +0 -82
- package/test/macros/spawn_chain_daemon.js +0 -88
- package/test/macros/spawn_lnd.js +0 -558
|
@@ -2,16 +2,17 @@ const {equal} = require('node:assert').strict;
|
|
|
2
2
|
const test = require('node:test');
|
|
3
3
|
|
|
4
4
|
const asyncRetry = require('async/retry');
|
|
5
|
-
const {
|
|
5
|
+
const {componentsOfTransaction} = require('@alexbosworth/blockchain');
|
|
6
6
|
const {controlBlock} = require('p2tr');
|
|
7
7
|
const {createPsbt} = require('psbt');
|
|
8
|
+
const {decodeBech32Address} = require('@alexbosworth/blockchain');
|
|
8
9
|
const {hashForTree} = require('p2tr');
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
10
|
+
const {idForTransaction} = require('@alexbosworth/blockchain');
|
|
11
|
+
const {p2wpkhOutputScript} = require('@alexbosworth/blockchain');
|
|
11
12
|
const {scriptElementsAsScript} = require('@alexbosworth/blockchain');
|
|
12
13
|
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
13
14
|
const tinysecp = require('tiny-secp256k1');
|
|
14
|
-
const {
|
|
15
|
+
const {transactionFromComponents} = require('@alexbosworth/blockchain');
|
|
15
16
|
const {v1OutputScript} = require('p2tr');
|
|
16
17
|
|
|
17
18
|
const {beginGroupSigningSession} = require('./../../');
|
|
@@ -23,17 +24,24 @@ const {getUtxos} = require('./../../');
|
|
|
23
24
|
const {signPsbt} = require('./../../');
|
|
24
25
|
const {signTransaction} = require('./../../');
|
|
25
26
|
|
|
27
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
26
28
|
const compile = elements => scriptElementsAsScript({elements}).script;
|
|
29
|
+
const componentsOfTx = tx => componentsOfTransaction({transaction: tx});
|
|
27
30
|
const count = 100;
|
|
28
31
|
const defaultInternalKey = '0350929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0';
|
|
29
|
-
const
|
|
32
|
+
const defaultLocktime = 0;
|
|
33
|
+
const defaultSequence = 0xffffffff;
|
|
34
|
+
const defaultTxVersion = 1;
|
|
35
|
+
const emptyScriptSig = '';
|
|
30
36
|
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
37
|
+
const idForTx = transaction => idForTransaction({transaction}).id;
|
|
31
38
|
const interval = retryCount => 10 * Math.pow(2, retryCount);
|
|
32
39
|
const OP_CHECKSIG = 172;
|
|
40
|
+
const p2wpkh = hash => p2wpkhOutputScript({hash}).script;
|
|
33
41
|
const smallTokens = 2e5;
|
|
34
42
|
const times = 20;
|
|
35
|
-
const {toOutputScript} = address;
|
|
36
43
|
const tokens = 1e6;
|
|
44
|
+
const transactionSighashDefault = 0;
|
|
37
45
|
|
|
38
46
|
// Signing a taproot transaction should result in a valid signature
|
|
39
47
|
test(`Sign a taproot transaction`, async () => {
|
|
@@ -119,23 +127,34 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
119
127
|
// Send the tx to the chain
|
|
120
128
|
await broadcastChainTransaction({lnd, transaction: signed.transaction});
|
|
121
129
|
|
|
122
|
-
|
|
123
|
-
const tx = new Transaction();
|
|
130
|
+
const spends = componentsOfTx(signed.transaction).outputs;
|
|
124
131
|
|
|
125
132
|
// The new tx spends the Taproot output
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
const inputs = [{
|
|
134
|
+
id: idForTx(signed.transaction),
|
|
135
|
+
script: emptyScriptSig,
|
|
136
|
+
sequence: defaultSequence,
|
|
137
|
+
vout: spends.findIndex(n => n.tokens === tokens),
|
|
138
|
+
}];
|
|
130
139
|
|
|
131
140
|
// Make an output to pay back into the wallet
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
);
|
|
141
|
+
const chainAddress = await createChainAddress({lnd});
|
|
142
|
+
|
|
143
|
+
const {program} = decodeBech32Address({address: chainAddress.address});
|
|
136
144
|
|
|
137
145
|
// Add output to the pay back transaction
|
|
138
|
-
|
|
146
|
+
const outputs = [{
|
|
147
|
+
script: bufferAsHex(p2wpkh(program)),
|
|
148
|
+
tokens: smallTokens,
|
|
149
|
+
}];
|
|
150
|
+
|
|
151
|
+
// Make a new tx that will spend the output back into the wallet
|
|
152
|
+
const unsigned = transactionFromComponents({
|
|
153
|
+
inputs,
|
|
154
|
+
outputs,
|
|
155
|
+
locktime: defaultLocktime,
|
|
156
|
+
version: defaultTxVersion,
|
|
157
|
+
});
|
|
139
158
|
|
|
140
159
|
const {signatures} = await signTransaction({
|
|
141
160
|
lnd,
|
|
@@ -145,14 +164,14 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
145
164
|
output_script: output.script,
|
|
146
165
|
output_tokens: tokens,
|
|
147
166
|
root_hash: hash,
|
|
148
|
-
sighash:
|
|
167
|
+
sighash: transactionSighashDefault,
|
|
149
168
|
vin: 0,
|
|
150
169
|
witness_script: witnessScript,
|
|
151
170
|
}],
|
|
152
|
-
transaction:
|
|
171
|
+
transaction: unsigned.transaction,
|
|
153
172
|
});
|
|
154
173
|
|
|
155
|
-
const [signature] = signatures
|
|
174
|
+
const [signature] = signatures;
|
|
156
175
|
|
|
157
176
|
const {block} = controlBlock({
|
|
158
177
|
external_key: output.external_key,
|
|
@@ -160,23 +179,28 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
160
179
|
script_branches: branches,
|
|
161
180
|
});
|
|
162
181
|
|
|
163
|
-
// Add the signature to the input
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
// Add the signature to the input and serialize the signed transaction
|
|
183
|
+
const {transaction} = transactionFromComponents({
|
|
184
|
+
outputs,
|
|
185
|
+
inputs: inputs.map(input => ({
|
|
186
|
+
id: input.id,
|
|
187
|
+
script: input.script,
|
|
188
|
+
sequence: input.sequence,
|
|
189
|
+
vout: input.vout,
|
|
190
|
+
witness: [signature, witnessScript, block],
|
|
191
|
+
})),
|
|
192
|
+
locktime: defaultLocktime,
|
|
193
|
+
version: defaultTxVersion,
|
|
170
194
|
});
|
|
171
195
|
|
|
172
|
-
await broadcastChainTransaction({lnd, transaction
|
|
196
|
+
await broadcastChainTransaction({lnd, transaction});
|
|
173
197
|
|
|
174
198
|
await asyncRetry({interval, times}, async () => {
|
|
175
199
|
await generate({});
|
|
176
200
|
|
|
177
201
|
const {utxos} = await getUtxos({lnd});
|
|
178
202
|
|
|
179
|
-
const utxo = utxos.find(n => n.transaction_id ===
|
|
203
|
+
const utxo = utxos.find(n => n.transaction_id === idForTx(transaction));
|
|
180
204
|
|
|
181
205
|
if (!utxo || !utxo.confirmation_count) {
|
|
182
206
|
throw new Error('ExpectedReceivedTaprootSpend');
|
|
@@ -192,7 +216,7 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
192
216
|
|
|
193
217
|
const topLevelKey = await getPublicKey({lnd, family: 805});
|
|
194
218
|
|
|
195
|
-
const unusedKey = ecp.makeRandom({
|
|
219
|
+
const unusedKey = ecp.makeRandom({});
|
|
196
220
|
|
|
197
221
|
const witnessScript = compile([
|
|
198
222
|
Buffer.from(unusedKey.publicKey).slice(1),
|
|
@@ -225,23 +249,34 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
225
249
|
// Send the tx to the chain
|
|
226
250
|
await broadcastChainTransaction({lnd, transaction: signed.transaction});
|
|
227
251
|
|
|
228
|
-
|
|
229
|
-
const tx = new Transaction();
|
|
252
|
+
const spends = componentsOfTx(signed.transaction).outputs;
|
|
230
253
|
|
|
231
254
|
// The new tx spends the Taproot output
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
255
|
+
const inputs = [{
|
|
256
|
+
id: idForTx(signed.transaction),
|
|
257
|
+
script: emptyScriptSig,
|
|
258
|
+
sequence: defaultSequence,
|
|
259
|
+
vout: spends.findIndex(n => n.tokens === tokens),
|
|
260
|
+
}];
|
|
236
261
|
|
|
237
262
|
// Make an output to pay back into the wallet
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
);
|
|
263
|
+
const chainAddress = await createChainAddress({lnd});
|
|
264
|
+
|
|
265
|
+
const {program} = decodeBech32Address({address: chainAddress.address});
|
|
242
266
|
|
|
243
267
|
// Add output to the pay back transaction
|
|
244
|
-
|
|
268
|
+
const outputs = [{
|
|
269
|
+
script: bufferAsHex(p2wpkh(program)),
|
|
270
|
+
tokens: smallTokens,
|
|
271
|
+
}];
|
|
272
|
+
|
|
273
|
+
// Make a new tx that will spend the output back into the wallet
|
|
274
|
+
const unsigned = transactionFromComponents({
|
|
275
|
+
inputs,
|
|
276
|
+
outputs,
|
|
277
|
+
locktime: defaultLocktime,
|
|
278
|
+
version: defaultTxVersion,
|
|
279
|
+
});
|
|
245
280
|
|
|
246
281
|
const {signatures} = await signTransaction({
|
|
247
282
|
lnd,
|
|
@@ -251,25 +286,36 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
251
286
|
output_script: output.script,
|
|
252
287
|
output_tokens: tokens,
|
|
253
288
|
root_hash: hash,
|
|
254
|
-
sighash:
|
|
289
|
+
sighash: transactionSighashDefault,
|
|
255
290
|
vin: 0,
|
|
256
291
|
}],
|
|
257
|
-
transaction:
|
|
292
|
+
transaction: unsigned.transaction,
|
|
258
293
|
});
|
|
259
294
|
|
|
260
|
-
const [signature] = signatures
|
|
261
|
-
|
|
262
|
-
// Add the signature to the input
|
|
263
|
-
|
|
295
|
+
const [signature] = signatures;
|
|
296
|
+
|
|
297
|
+
// Add the signature to the input and serialize the signed transaction
|
|
298
|
+
const {transaction} = transactionFromComponents({
|
|
299
|
+
outputs,
|
|
300
|
+
inputs: inputs.map(input => ({
|
|
301
|
+
id: input.id,
|
|
302
|
+
script: input.script,
|
|
303
|
+
sequence: input.sequence,
|
|
304
|
+
vout: input.vout,
|
|
305
|
+
witness: [signature],
|
|
306
|
+
})),
|
|
307
|
+
locktime: defaultLocktime,
|
|
308
|
+
version: defaultTxVersion,
|
|
309
|
+
});
|
|
264
310
|
|
|
265
|
-
await broadcastChainTransaction({lnd, transaction
|
|
311
|
+
await broadcastChainTransaction({lnd, transaction});
|
|
266
312
|
|
|
267
313
|
await asyncRetry({interval, times}, async () => {
|
|
268
314
|
await generate({});
|
|
269
315
|
|
|
270
316
|
const {utxos} = await getUtxos({lnd});
|
|
271
317
|
|
|
272
|
-
const utxo = utxos.find(n => n.transaction_id ===
|
|
318
|
+
const utxo = utxos.find(n => n.transaction_id === idForTx(transaction));
|
|
273
319
|
|
|
274
320
|
if (!utxo || !utxo.confirmation_count) {
|
|
275
321
|
throw new Error('ExpectedReceivedTaprootSpend');
|
|
@@ -309,23 +355,34 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
309
355
|
// Send the tx to the chain
|
|
310
356
|
await broadcastChainTransaction({lnd, transaction: signed.transaction});
|
|
311
357
|
|
|
312
|
-
|
|
313
|
-
const tx = new Transaction();
|
|
358
|
+
const spends = componentsOfTx(signed.transaction).outputs;
|
|
314
359
|
|
|
315
360
|
// The new tx spends the Taproot output
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
361
|
+
const inputs = [{
|
|
362
|
+
id: idForTx(signed.transaction),
|
|
363
|
+
script: emptyScriptSig,
|
|
364
|
+
sequence: defaultSequence,
|
|
365
|
+
vout: spends.findIndex(n => n.tokens === tokens),
|
|
366
|
+
}];
|
|
320
367
|
|
|
321
368
|
// Make an output to pay back into the wallet
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
);
|
|
369
|
+
const chainAddress = await createChainAddress({lnd});
|
|
370
|
+
|
|
371
|
+
const {program} = decodeBech32Address({address: chainAddress.address});
|
|
326
372
|
|
|
327
373
|
// Add output to the pay back transaction
|
|
328
|
-
|
|
374
|
+
const outputs = [{
|
|
375
|
+
script: bufferAsHex(p2wpkh(program)),
|
|
376
|
+
tokens: smallTokens,
|
|
377
|
+
}];
|
|
378
|
+
|
|
379
|
+
// Make a new tx that will spend the output back into the wallet
|
|
380
|
+
const unsigned = transactionFromComponents({
|
|
381
|
+
inputs,
|
|
382
|
+
outputs,
|
|
383
|
+
locktime: defaultLocktime,
|
|
384
|
+
version: defaultTxVersion,
|
|
385
|
+
});
|
|
329
386
|
|
|
330
387
|
const {signatures} = await signTransaction({
|
|
331
388
|
lnd,
|
|
@@ -334,25 +391,36 @@ test(`Sign a taproot transaction`, async () => {
|
|
|
334
391
|
key_index: topLevelKey.index,
|
|
335
392
|
output_script: output.script,
|
|
336
393
|
output_tokens: tokens,
|
|
337
|
-
sighash:
|
|
394
|
+
sighash: transactionSighashDefault,
|
|
338
395
|
vin: 0,
|
|
339
396
|
}],
|
|
340
|
-
transaction:
|
|
397
|
+
transaction: unsigned.transaction,
|
|
341
398
|
});
|
|
342
399
|
|
|
343
|
-
const [signature] = signatures
|
|
344
|
-
|
|
345
|
-
// Add the signature to the input
|
|
346
|
-
|
|
400
|
+
const [signature] = signatures;
|
|
401
|
+
|
|
402
|
+
// Add the signature to the input and serialize the signed transaction
|
|
403
|
+
const {transaction} = transactionFromComponents({
|
|
404
|
+
outputs,
|
|
405
|
+
inputs: inputs.map(input => ({
|
|
406
|
+
id: input.id,
|
|
407
|
+
script: input.script,
|
|
408
|
+
sequence: input.sequence,
|
|
409
|
+
vout: input.vout,
|
|
410
|
+
witness: [signature],
|
|
411
|
+
})),
|
|
412
|
+
locktime: defaultLocktime,
|
|
413
|
+
version: defaultTxVersion,
|
|
414
|
+
});
|
|
347
415
|
|
|
348
|
-
await broadcastChainTransaction({lnd, transaction
|
|
416
|
+
await broadcastChainTransaction({lnd, transaction});
|
|
349
417
|
|
|
350
418
|
await asyncRetry({interval, times}, async () => {
|
|
351
419
|
await generate({});
|
|
352
420
|
|
|
353
421
|
const {utxos} = await getUtxos({lnd});
|
|
354
422
|
|
|
355
|
-
const utxo = utxos.find(n => n.transaction_id ===
|
|
423
|
+
const utxo = utxos.find(n => n.transaction_id === idForTx(transaction));
|
|
356
424
|
|
|
357
425
|
if (!utxo || !utxo.confirmation_count) {
|
|
358
426
|
throw new Error('ExpectedReceivedTaprootSpend');
|