ln-service 53.5.2 → 53.7.2

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 (26) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +51 -2
  3. package/index.js +4 -2
  4. package/package.json +16 -5
  5. package/test/integration/test_add_peer.js +25 -19
  6. package/test/integration/test_delete_pending_channel.js +18 -11
  7. package/test/integration/test_get_failed_payments.js +123 -119
  8. package/test/integration/test_get_node.js +48 -44
  9. package/test/integration/test_get_pending_force.js +8 -1
  10. package/test/integration/test_get_wallet_info.js +30 -15
  11. package/test/integration/test_open_channels.js +21 -14
  12. package/test/integration/test_propose_channel.js +438 -421
  13. package/test/integration/test_subscribe_to_channels.js +1 -1
  14. package/test/integration/test_subscribe_to_peer_messages.js +77 -71
  15. package/test/integration/test_subscribe_to_peers.js +23 -19
  16. package/test/routerrpc-integration/test_get_forwarding_reputations.js +64 -60
  17. package/test/routerrpc-integration/test_get_route_confidence.js +38 -34
  18. package/test/routerrpc-integration/test_get_route_through_hops.js +33 -14
  19. package/test/routerrpc-integration/test_pay_via_payment_details.js +118 -110
  20. package/test/routerrpc-integration/test_pay_via_routes.js +19 -1
  21. package/test/routerrpc-integration/test_probe_for_route.js +75 -71
  22. package/test/routerrpc-integration/test_subscribe_to_forward_requests.js +2 -2
  23. package/test/routerrpc-integration/test_subscribe_to_forwards.js +508 -504
  24. package/test/walletrpc-integration/test_fund_psbt.js +4 -1
  25. package/test/walletrpc-integration/test_partially_sign_psbt.js +216 -0
  26. package/test/walletrpc-integration/test_sign_psbt.js +4 -1
@@ -3,6 +3,7 @@ const {address} = require('bitcoinjs-lib');
3
3
  const {decodePsbt} = require('psbt');
4
4
  const {spawnLightningCluster} = require('ln-docker-daemons');
5
5
  const {test} = require('@alexbosworth/tap');
6
+ const tinysecp = require('tiny-secp256k1');
6
7
 
7
8
  const {createChainAddress} = require('./../../');
8
9
  const {fundPsbt} = require('./../../');
@@ -24,6 +25,8 @@ const txIdHexByteLength = 64;
24
25
 
25
26
  // Funding a transaction should result in a funded PSBT
26
27
  test(`Fund PSBT`, async ({end, equal}) => {
28
+ const ecp = (await import('ecpair')).ECPairFactory(tinysecp);
29
+
27
30
  const {kill, nodes} = await spawnLightningCluster({});
28
31
 
29
32
  const [{generate, lnd}] = nodes;
@@ -86,7 +89,7 @@ test(`Fund PSBT`, async ({end, equal}) => {
86
89
 
87
90
  equal(output.output_script, expectedOutput, 'Got expected output script');
88
91
 
89
- const decoded = decodePsbt({psbt: funded.psbt});
92
+ const decoded = decodePsbt({ecp, psbt: funded.psbt});
90
93
 
91
94
  const [decodedInput] = decoded.inputs;
92
95
 
@@ -0,0 +1,216 @@
1
+ const asyncEach = require('async/each');
2
+ const asyncMap = require('async/map');
3
+ const asyncRetry = require('async/retry');
4
+ const {combinePsbts} = require('psbt');
5
+ const {createPsbt} = require('psbt');
6
+ const {decodePsbt} = require('psbt');
7
+ const {extractTransaction} = require('psbt');
8
+ const {finalizePsbt} = require('psbt');
9
+ const {spawnLightningCluster} = require('ln-docker-daemons');
10
+ const {test} = require('@alexbosworth/tap');
11
+ const tinysecp = require('tiny-secp256k1');
12
+ const {Transaction} = require('bitcoinjs-lib');
13
+ const {updatePsbt} = require('psbt');
14
+
15
+ const {broadcastChainTransaction} = require('./../../');
16
+ const {createChainAddress} = require('./../../');
17
+ const {fundPsbt} = require('./../../');
18
+ const {getChainBalance} = require('./../../');
19
+ const {getChainTransactions} = require('./../../');
20
+ const {getUtxos} = require('./../../');
21
+ const {partiallySignPsbt} = require('./../../');
22
+ const {sendToChainAddresses} = require('./../../');
23
+
24
+ const count = 150;
25
+ const flatten = arr => [].concat(...arr);
26
+ const interval = 10;
27
+ const size = 3;
28
+ const startingFunds = 1e7;
29
+ const times = 1000;
30
+ const tokens = 1e6;
31
+
32
+ // Partially signing a PSBT should result in a partially signed PSBT
33
+ test(`Partially sign PSBT`, async ({end, equal, strictSame}) => {
34
+ const ecp = (await import('ecpair')).ECPairFactory(tinysecp);
35
+
36
+ const {kill, nodes} = await spawnLightningCluster({size});
37
+
38
+ const [control, target, remote] = nodes;
39
+
40
+ try {
41
+ // Generate some funds for the control
42
+ await control.generate({count});
43
+
44
+ // Send starting coins to target and remote
45
+ await sendToChainAddresses({
46
+ lnd: control.lnd,
47
+ send_to: await asyncMap([target, remote], async ({lnd}) => {
48
+ return {
49
+ address: (await createChainAddress({lnd})).address,
50
+ tokens: startingFunds,
51
+ };
52
+ }),
53
+ });
54
+
55
+ // Make sure that the nodes have funds
56
+ await asyncRetry({interval, times}, async () => {
57
+ await asyncEach([control, target, remote], async ({lnd}) => {
58
+ await control.generate({});
59
+
60
+ if (!(await getChainBalance({lnd})).chain_balance) {
61
+ throw new Error('WaitingForChainBalance');
62
+ }
63
+ });
64
+ });
65
+
66
+ // Get UTXOs to spend
67
+ const [controlUtxo] = (await getUtxos({lnd: control.lnd})).utxos.reverse();
68
+ const [targetUtxo] = (await getUtxos({lnd: target.lnd})).utxos;
69
+ const [remoteUtxo] = (await getUtxos({lnd: remote.lnd})).utxos;
70
+
71
+ // Make addresses to spend to
72
+ const addresses = await asyncMap(nodes, async ({lnd}) => {
73
+ return await createChainAddress({lnd});
74
+ });
75
+
76
+ const [controlAddress, targetAddress, remoteAddress] = addresses;
77
+
78
+ // Fund the addresses using the selected UTXOs
79
+ const controlFund = await fundPsbt({
80
+ inputs: [{
81
+ transaction_id: controlUtxo.transaction_id,
82
+ transaction_vout: controlUtxo.transaction_vout,
83
+ }],
84
+ lnd: control.lnd,
85
+ outputs: [{tokens, address: controlAddress.address}],
86
+ });
87
+
88
+ const targetFund = await fundPsbt({
89
+ inputs: [{
90
+ transaction_id: targetUtxo.transaction_id,
91
+ transaction_vout: targetUtxo.transaction_vout,
92
+ }],
93
+ lnd: target.lnd,
94
+ outputs: [{tokens, address: targetAddress.address}],
95
+ });
96
+
97
+ const remoteFund = await fundPsbt({
98
+ inputs: [{
99
+ transaction_id: remoteUtxo.transaction_id,
100
+ transaction_vout: remoteUtxo.transaction_vout,
101
+ }],
102
+ lnd: remote.lnd,
103
+ outputs: [{tokens, address: remoteAddress.address}],
104
+ });
105
+
106
+ // Collect all inputs that are spending
107
+ const inputs = []
108
+ .concat(controlFund.inputs)
109
+ .concat(targetFund.inputs)
110
+ .concat(remoteFund.inputs);
111
+
112
+ // Collect all outputs being sent to
113
+ const outputs = []
114
+ .concat(controlFund.outputs)
115
+ .concat(targetFund.outputs)
116
+ .concat(remoteFund.outputs);
117
+
118
+ // Make a new PSBT that includes all the outputs and inputs
119
+ const base = createPsbt({
120
+ outputs: outputs.map(output => ({
121
+ script: output.output_script,
122
+ tokens: output.tokens,
123
+ })),
124
+ utxos: inputs.map(input => ({
125
+ id: input.transaction_id,
126
+ vout: input.transaction_vout,
127
+ })),
128
+ });
129
+
130
+ // Decode the PSBTs to get signing key details
131
+ const controlDecoded = decodePsbt({ecp, psbt: controlFund.psbt});
132
+ const targetDecoded = decodePsbt({ecp, psbt: targetFund.psbt});
133
+ const remoteDecoded = decodePsbt({ecp, psbt: remoteFund.psbt});
134
+
135
+ // Collect all the BIP32 derivations
136
+ const controlBip32Derivations = controlDecoded.inputs
137
+ .map(n => n.bip32_derivations);
138
+
139
+ const targetBip32Derivations = targetDecoded.inputs
140
+ .map(n => n.bip32_derivations);
141
+
142
+ const remoteBip32Derivations = remoteDecoded.inputs
143
+ .map(n => n.bip32_derivations);
144
+
145
+ const controlTransactions = controlDecoded.inputs
146
+ .map(n => n.non_witness_utxo);
147
+
148
+ const targetTransactions = targetDecoded.inputs
149
+ .map(n => n.non_witness_utxo);
150
+
151
+ const remoteTransactions = remoteDecoded.inputs
152
+ .map(n => n.non_witness_utxo);
153
+
154
+ const allDerivations = []
155
+ .concat(controlBip32Derivations)
156
+ .concat(targetBip32Derivations)
157
+ .concat(remoteBip32Derivations);
158
+
159
+ const bip32Derivations = flatten(allDerivations);
160
+
161
+ // Update the PSBT so that it has the consolidated details
162
+ const updated = updatePsbt({
163
+ ecp,
164
+ bip32_derivations: bip32Derivations,
165
+ psbt: base.psbt,
166
+ sighashes: inputs.map(input => ({
167
+ id: input.transaction_id,
168
+ sighash: Transaction.SIGHASH_ALL,
169
+ vout: input.transaction_vout,
170
+ })),
171
+ transactions: controlTransactions.concat(targetTransactions),
172
+ });
173
+
174
+ await partiallySignPsbt({lnd: control.lnd, psbt: updated.psbt});
175
+
176
+ // Sign the PSBT
177
+ const psbts = await asyncMap(nodes, async ({lnd}) => {
178
+ return (await partiallySignPsbt({lnd, psbt: updated.psbt})).psbt;
179
+ });
180
+
181
+ // Finalize the signatures
182
+ const finalize = finalizePsbt({
183
+ ecp,
184
+ psbt: combinePsbts({ecp, psbts}).psbt,
185
+ });
186
+
187
+ // Pull out the transaction
188
+ const {transaction} = extractTransaction({ecp, psbt: finalize.psbt});
189
+
190
+ // Publish the transaction
191
+ await broadcastChainTransaction({lnd: control.lnd, transaction});
192
+
193
+ // Make sure that the transaction confirms into a block
194
+ await asyncEach(nodes, async ({lnd}) => {
195
+ return asyncRetry({interval, times}, async () => {
196
+ await control.generate({});
197
+
198
+ const {utxos} = await getUtxos({lnd});
199
+
200
+ const [confirmed] = utxos.filter(n => n.tokens === tokens);
201
+
202
+ if (!confirmed || !confirmed.confirmation_count) {
203
+ throw new Error('ExpectedConfirmedCoin');
204
+ }
205
+
206
+ equal(confirmed.tokens, tokens, 'Got confirmed funds');
207
+ });
208
+ });
209
+ } catch (err) {
210
+ strictSame(err, [501, 'PartiallySignPsbtMethodNotSupported'], 'NoSupport');
211
+ } finally {
212
+ await kill({});
213
+ }
214
+
215
+ return end();
216
+ });
@@ -3,6 +3,7 @@ const {address} = require('bitcoinjs-lib');
3
3
  const {decodePsbt} = require('psbt');
4
4
  const {spawnLightningCluster} = require('ln-docker-daemons');
5
5
  const {test} = require('@alexbosworth/tap');
6
+ const tinysecp = require('tiny-secp256k1');
6
7
  const {Transaction} = require('bitcoinjs-lib');
7
8
 
8
9
  const {broadcastChainTransaction} = require('./../../');
@@ -29,6 +30,8 @@ const txIdHexByteLength = 64;
29
30
 
30
31
  // Signing a PSBT should result in a finalized PSBT
31
32
  test(`Sign PSBT`, async ({end, equal}) => {
33
+ const ecp = (await import('ecpair')).ECPairFactory(tinysecp);
34
+
32
35
  const {kill, nodes} = await spawnLightningCluster({size});
33
36
 
34
37
  const [control, target] = nodes;
@@ -72,7 +75,7 @@ test(`Sign PSBT`, async ({end, equal}) => {
72
75
 
73
76
  const tx = Transaction.fromHex(finalized.transaction);
74
77
 
75
- const decoded = decodePsbt({psbt: finalized.psbt});
78
+ const decoded = decodePsbt({ecp, psbt: finalized.psbt});
76
79
 
77
80
  equal(!!decoded, true, 'Got a finalized PSBT');
78
81
  equal(!!tx, true, 'Got a raw signed transaction');