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