paid-services 3.1.2 → 3.5.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/.prettierignore +2 -0
- package/CHANGELOG.md +18 -0
- package/capacity/accept_capacity_change.js +284 -0
- package/capacity/ask_for_change_details.js +538 -0
- package/capacity/ask_for_decrease.js +185 -0
- package/capacity/assemble_replacement_tx.js +171 -0
- package/capacity/capacity_change_requests.js +85 -0
- package/capacity/change_channel_capacity.js +189 -0
- package/capacity/encode_change_request.js +62 -0
- package/capacity/encode_sign_capacity_response.js +32 -0
- package/capacity/fee_for_replacement.js +108 -0
- package/capacity/finalize_capacity_replacement.js +67 -0
- package/capacity/get_capacity_change_requests.js +99 -0
- package/capacity/get_capacity_replacement.js +372 -0
- package/capacity/get_replacement_signature.js +232 -0
- package/capacity/index.js +4 -0
- package/capacity/initiate_capacity_change.js +507 -0
- package/capacity/interim_replacement_psbt.js +57 -0
- package/capacity/is_open_witness_script.js +40 -0
- package/capacity/parse_accept_request.js +58 -0
- package/capacity/parse_accept_response.js +52 -0
- package/capacity/parse_capacity_change_request.js +108 -0
- package/capacity/parse_sign_capacity_request.js +59 -0
- package/capacity/propose_capacity_change.js +364 -0
- package/capacity/sign_capacity_replacement.js +119 -0
- package/capacity/witness_script_from_close_txs.js +50 -0
- package/index.js +6 -0
- package/p2p/encode_peer_request.js +59 -0
- package/p2p/encode_peer_response.js +44 -0
- package/p2p/encode_response_code.js +49 -0
- package/p2p/index.js +4 -0
- package/p2p/make_peer_request.js +151 -0
- package/p2p/parse_request_message.js +103 -0
- package/p2p/parse_response_code.js +60 -0
- package/p2p/return_failure_response.js +43 -0
- package/p2p/return_success_response.js +47 -0
- package/p2p/service_peer_requests.js +108 -0
- package/package.json +8 -4
- package/service_types.json +16 -0
- package/test/capacity/test_assemble_replacement_tx.js +46 -0
- package/test/capacity/test_capacity_change_requests.js +55 -0
- package/test/capacity/test_encode_change_request.js +54 -0
- package/test/capacity/test_encode_sign_capacity_response.js +47 -0
- package/test/capacity/test_fee_for_replacement.js +40 -0
- package/test/capacity/test_finalize_capacity_replacement.js +45 -0
- package/test/capacity/test_interim_replacement_psbt.js +44 -0
- package/test/capacity/test_is_open_witness_script.js +40 -0
- package/test/capacity/test_parse_accept_request.js +42 -0
- package/test/capacity/test_parse_capacity_change_request.js +52 -0
- package/test/capacity/test_parse_sign_capacity_request.js +49 -0
- package/test/capacity/test_witness_script_from_close_txs.js +53 -0
- package/test/integration/test_accept_capacity_change.js +189 -0
- package/test/integration/test_change_channel_capacity.js +203 -0
- package/test/integration/test_decrease_channel_capacity.js +216 -0
- package/test/integration/test_increase_channel_capacity.js +201 -0
- package/test/integration/test_service_peer_requests.js +59 -0
- package/test/integration/test_sign_capacity_replacement.js +142 -0
- package/test/p2p/test_encode_peer_request.js +53 -0
- package/test/p2p/test_encode_peer_response.js +38 -0
- package/test/p2p/test_encode_response_code.js +48 -0
- package/test/trades/test_decode_basic_trade.js +40 -0
- package/test/trades/test_decode_open_trade.js +50 -0
- package/test/trades/test_encode_open_trade.js +35 -0
- package/test/trades/test_encode_trade.js +37 -0
- package/trades/accept_trade.js +52 -0
- package/trades/create_trade.js +124 -44
- package/trades/decode_basic_trade.js +45 -0
- package/trades/decode_open_trade.js +69 -0
- package/trades/decode_trade.js +48 -66
- package/trades/decode_trade_secret.js +89 -0
- package/trades/encode_open_trade.js +89 -0
- package/trades/encode_trade.js +48 -33
- package/trades/encode_trade_secret.js +50 -0
- package/trades/finalize_trade_secret.js +116 -0
- package/trades/find_trade.js +314 -0
- package/trades/manage_trade.js +46 -35
- package/trades/network_from_network_record.js +8 -2
- package/trades/network_record_from_network.js +36 -0
- package/trades/network_record_from_request.js +6 -0
- package/trades/node_as_record.js +98 -0
- package/trades/record_as_node.js +113 -0
- package/trades/request_trade_by_id.js +89 -0
- package/trades/service_trade_requests.js +184 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const asyncRetry = require('async/retry');
|
|
3
|
+
const {closeChannel} = require('ln-service');
|
|
4
|
+
const {decodeChanId} = require('bolt07');
|
|
5
|
+
const {getChainTransactions} = require('ln-service');
|
|
6
|
+
const {getPendingChannels} = require('ln-service');
|
|
7
|
+
const {returnResult} = require('asyncjs-util');
|
|
8
|
+
const {Transaction} = require('bitcoinjs-lib');
|
|
9
|
+
|
|
10
|
+
const signCapacityReplacement = require('./sign_capacity_replacement');
|
|
11
|
+
const witnessScriptFromCloseTxs = require('./witness_script_from_close_txs');
|
|
12
|
+
|
|
13
|
+
const blocksBuffer = 1e3;
|
|
14
|
+
const {fromHex} = Transaction;
|
|
15
|
+
const interval = 200;
|
|
16
|
+
const notFoundIndex = -1;
|
|
17
|
+
const times = 72000;
|
|
18
|
+
const txIdAsHash = id => Buffer.from(id, 'hex').reverse();
|
|
19
|
+
|
|
20
|
+
/** Close channel and then sign the unsigned replacement transaction
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
channel: <Replace Channel Standard Format Id String>
|
|
24
|
+
id: <Channel Funding Transaction Id Hex String>
|
|
25
|
+
lnd: <Authenticated LND API Object>
|
|
26
|
+
output: <Original Funding Output Script Hex String>
|
|
27
|
+
unsigned: <Unsigned Replacement Transaction Hex String>
|
|
28
|
+
vout: <Channel Funding Output Index Number>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@returns via cbk or Promise
|
|
32
|
+
{
|
|
33
|
+
signature: <Funding Spend Signature Hex String>
|
|
34
|
+
transaction_id: <Replacement Transaction Id Hex String>
|
|
35
|
+
transaction_vout: <Replacement Transaction Output Index Number>
|
|
36
|
+
}
|
|
37
|
+
*/
|
|
38
|
+
module.exports = ({channel, id, lnd, output, unsigned, vout}, cbk) => {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
return asyncAuto({
|
|
41
|
+
// Check arguments
|
|
42
|
+
validate: cbk => {
|
|
43
|
+
if (!channel) {
|
|
44
|
+
return cbk([400, 'ExpectedChannelIdToSignReplacementTransaction']);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!id) {
|
|
48
|
+
return cbk([400, 'ExpectedFundingTxIdToSignReplacementTransaction']);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!lnd) {
|
|
52
|
+
return cbk([400, 'ExpectedLndToSignReplacementTransaction']);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!output) {
|
|
56
|
+
return cbk([400, 'ExpectedOutputScriptToGetReplacementSignature']);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!unsigned) {
|
|
60
|
+
return cbk([400, 'ExpectedUnsignedTxToGetReplacementSignature']);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (vout === undefined) {
|
|
64
|
+
return cbk([400, 'ExpectedFundingOutputIndexToGetReplacementSig']);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return cbk();
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// Find input index that is respending the original funding outpoint
|
|
71
|
+
vin: ['validate', ({}, cbk) => {
|
|
72
|
+
const inputIndex = fromHex(unsigned).ins.findIndex(input => {
|
|
73
|
+
return input.index === vout && input.hash.equals(txIdAsHash(id));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (inputIndex === notFoundIndex) {
|
|
77
|
+
return cbk([503, 'ExpectedReplacementTransactionSpendingFunding']);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return cbk(null, inputIndex);
|
|
81
|
+
}],
|
|
82
|
+
|
|
83
|
+
// Force close the channel to allow for looking up the public key
|
|
84
|
+
closeChannel: ['vin', ({}, cbk) => {
|
|
85
|
+
return closeChannel({
|
|
86
|
+
lnd,
|
|
87
|
+
is_force_close: true,
|
|
88
|
+
transaction_id: id,
|
|
89
|
+
transaction_vout: vout,
|
|
90
|
+
},
|
|
91
|
+
cbk);
|
|
92
|
+
}],
|
|
93
|
+
|
|
94
|
+
// Get the pending close channels to see the final channel balance
|
|
95
|
+
getPending: ['closeChannel', ({}, cbk) => {
|
|
96
|
+
return getPendingChannels({lnd}, cbk);
|
|
97
|
+
}],
|
|
98
|
+
|
|
99
|
+
// Get the post close channel transactions to find the open/close txs
|
|
100
|
+
getTx: ['closeChannel', ({}, cbk) => {
|
|
101
|
+
const after = decodeChanId({channel}).block_height - blocksBuffer;
|
|
102
|
+
|
|
103
|
+
return getChainTransactions({after, lnd}, cbk);
|
|
104
|
+
}],
|
|
105
|
+
|
|
106
|
+
// Find the funding witness script in the close transaction
|
|
107
|
+
script: ['closeChannel', 'getTx', ({closeChannel, getTx}, cbk) => {
|
|
108
|
+
try {
|
|
109
|
+
const {script} = witnessScriptFromCloseTxs({
|
|
110
|
+
closing_tx_id: closeChannel.transaction_id,
|
|
111
|
+
transactions: getTx.transactions,
|
|
112
|
+
transaction_id: id,
|
|
113
|
+
transaction_vout: vout,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return cbk(null, script);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
return cbk([503, err.message]);
|
|
119
|
+
}
|
|
120
|
+
}],
|
|
121
|
+
|
|
122
|
+
// Find the pending channel close that was just force closed
|
|
123
|
+
pending: [
|
|
124
|
+
'closeChannel',
|
|
125
|
+
'getPending',
|
|
126
|
+
({closeChannel, getPending}, cbk) =>
|
|
127
|
+
{
|
|
128
|
+
// The pending close tx has the closing transaction id
|
|
129
|
+
const pending = getPending.pending_channels.find(chan => {
|
|
130
|
+
return chan.transaction_id === id && chan.transaction_vout === vout;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (!pending) {
|
|
134
|
+
return cbk([503, 'ExpectedPendingChannelToGetReplacementSignature']);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// There should be no pending payments on the channel
|
|
138
|
+
if (!!pending.pending_payments && !!pending.pending_payments.length) {
|
|
139
|
+
return cbk([503, 'ExpectedNoActiveHtlcsOnCapacityChangeChannel']);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Return the local balance expected to be returned in replacement
|
|
143
|
+
return cbk(null, {
|
|
144
|
+
capacity: pending.capacity,
|
|
145
|
+
local_balance: pending.local_balance,
|
|
146
|
+
partner_public_key: pending.partner_public_key,
|
|
147
|
+
});
|
|
148
|
+
}],
|
|
149
|
+
|
|
150
|
+
// Given the unsigned transaction, look for the matching open proposal
|
|
151
|
+
waitForProposal: ['pending', ({pending}, cbk) => {
|
|
152
|
+
const id = fromHex(unsigned).getId();
|
|
153
|
+
|
|
154
|
+
return asyncRetry({interval, times}, cbk => {
|
|
155
|
+
return getPendingChannels({lnd}, (err, res) => {
|
|
156
|
+
if (!!err) {
|
|
157
|
+
return cbk(err);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Find an incoming channel that indicates it's safe to sign reopen
|
|
161
|
+
const incomingChannel = res.pending_channels.find(channel => {
|
|
162
|
+
// This will be an opening channel
|
|
163
|
+
if (!channel.is_opening) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// The new channel must be from the same peer
|
|
168
|
+
if (channel.partner_public_key !== pending.partner_public_key) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// The new channel must be spending the old transaction
|
|
173
|
+
if (channel.transaction_id !== id) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// The new channel must have at least the balance of the old one
|
|
178
|
+
if (channel.local_balance < pending.local_balance) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return true;
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (!incomingChannel) {
|
|
186
|
+
return cbk([503, 'FailedToFindPendingReplacementChannel']);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return cbk(null, {
|
|
190
|
+
transaction_id: incomingChannel.transaction_id,
|
|
191
|
+
transaction_vout: incomingChannel.transaction_vout,
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
cbk);
|
|
196
|
+
}],
|
|
197
|
+
|
|
198
|
+
// Sign the channel funding to prepare to authorize the new channel
|
|
199
|
+
signFunding: [
|
|
200
|
+
'pending',
|
|
201
|
+
'script',
|
|
202
|
+
'vin',
|
|
203
|
+
'waitForProposal',
|
|
204
|
+
({pending, script, vin, waitForProposal}, cbk) =>
|
|
205
|
+
{
|
|
206
|
+
return signCapacityReplacement({
|
|
207
|
+
lnd,
|
|
208
|
+
output,
|
|
209
|
+
script,
|
|
210
|
+
vin,
|
|
211
|
+
capacity: pending.capacity,
|
|
212
|
+
transaction: unsigned,
|
|
213
|
+
},
|
|
214
|
+
cbk);
|
|
215
|
+
}],
|
|
216
|
+
|
|
217
|
+
// Final signature
|
|
218
|
+
signature: [
|
|
219
|
+
'signFunding',
|
|
220
|
+
'waitForProposal',
|
|
221
|
+
({signFunding, waitForProposal}, cbk) =>
|
|
222
|
+
{
|
|
223
|
+
return cbk(null, {
|
|
224
|
+
signature: signFunding.signature,
|
|
225
|
+
transaction_id: waitForProposal.transaction_id,
|
|
226
|
+
transaction_vout: waitForProposal.transaction_vout,
|
|
227
|
+
});
|
|
228
|
+
}],
|
|
229
|
+
},
|
|
230
|
+
returnResult({reject, resolve, of: 'signature'}, cbk));
|
|
231
|
+
});
|
|
232
|
+
};
|