lightning 5.15.2 → 5.16.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 +4 -0
- package/grpc/protos/lightning.proto +19 -3
- package/grpc/protos/signer.proto +47 -9
- package/lnd_methods/signer/input_signing_method.js +42 -0
- package/lnd_methods/signer/sign_transaction.js +26 -20
- package/package.json +2 -2
- package/test/lnd_methods/signer/test_input_signing_method.js +53 -0
package/CHANGELOG.md
CHANGED
|
@@ -2369,9 +2369,6 @@ message PendingChannelsResponse {
|
|
|
2369
2369
|
// The pending channel
|
|
2370
2370
|
PendingChannel channel = 1;
|
|
2371
2371
|
|
|
2372
|
-
// The height at which this channel will be confirmed
|
|
2373
|
-
uint32 confirmation_height = 2;
|
|
2374
|
-
|
|
2375
2372
|
/*
|
|
2376
2373
|
The amount calculated to be paid in fees for the current set of
|
|
2377
2374
|
commitment transactions. The fee amount is persisted with the channel
|
|
@@ -2390,6 +2387,9 @@ message PendingChannelsResponse {
|
|
|
2390
2387
|
transaction. This value can later be updated once the channel is open.
|
|
2391
2388
|
*/
|
|
2392
2389
|
int64 fee_per_kw = 6;
|
|
2390
|
+
|
|
2391
|
+
// Previously used for confirmation_height. Do not reuse.
|
|
2392
|
+
reserved 2;
|
|
2393
2393
|
}
|
|
2394
2394
|
|
|
2395
2395
|
message WaitingCloseChannel {
|
|
@@ -3633,6 +3633,14 @@ message ListPaymentsRequest {
|
|
|
3633
3633
|
of the returned payments is always oldest first (ascending index order).
|
|
3634
3634
|
*/
|
|
3635
3635
|
bool reversed = 4;
|
|
3636
|
+
|
|
3637
|
+
/*
|
|
3638
|
+
If set, all payments (complete and incomplete, independent of the
|
|
3639
|
+
max_payments parameter) will be counted. Note that setting this to true will
|
|
3640
|
+
increase the run time of the call significantly on systems that have a lot
|
|
3641
|
+
of payments, as all of them have to be iterated through to be counted.
|
|
3642
|
+
*/
|
|
3643
|
+
bool count_total_payments = 5;
|
|
3636
3644
|
}
|
|
3637
3645
|
|
|
3638
3646
|
message ListPaymentsResponse {
|
|
@@ -3650,6 +3658,14 @@ message ListPaymentsResponse {
|
|
|
3650
3658
|
as the index_offset to continue seeking forwards in the next request.
|
|
3651
3659
|
*/
|
|
3652
3660
|
uint64 last_index_offset = 3;
|
|
3661
|
+
|
|
3662
|
+
/*
|
|
3663
|
+
Will only be set if count_total_payments in the request was set. Represents
|
|
3664
|
+
the total number of payments (complete and incomplete, independent of the
|
|
3665
|
+
number of payments requested in the query) currently present in the payments
|
|
3666
|
+
database.
|
|
3667
|
+
*/
|
|
3668
|
+
uint64 total_num_payments = 4;
|
|
3653
3669
|
}
|
|
3654
3670
|
|
|
3655
3671
|
message DeletePaymentRequest {
|
package/grpc/protos/signer.proto
CHANGED
|
@@ -137,6 +137,7 @@ service Signer {
|
|
|
137
137
|
MuSig2Cleanup (experimental!) allows a caller to clean up a session early in
|
|
138
138
|
cases where it's obvious that the signing session won't succeed and the
|
|
139
139
|
resources can be released.
|
|
140
|
+
|
|
140
141
|
NOTE: The MuSig2 BIP is not final yet and therefore this API must be
|
|
141
142
|
considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
|
142
143
|
releases. Backward compatibility is not guaranteed!
|
|
@@ -174,6 +175,32 @@ message TxOut {
|
|
|
174
175
|
bytes pk_script = 2;
|
|
175
176
|
}
|
|
176
177
|
|
|
178
|
+
enum SignMethod {
|
|
179
|
+
/*
|
|
180
|
+
Specifies that a SegWit v0 (p2wkh, np2wkh, p2wsh) input script should be
|
|
181
|
+
signed.
|
|
182
|
+
*/
|
|
183
|
+
SIGN_METHOD_WITNESS_V0 = 0;
|
|
184
|
+
|
|
185
|
+
/*
|
|
186
|
+
Specifies that a SegWit v1 (p2tr) input should be signed by using the
|
|
187
|
+
BIP0086 method (commit to internal key only).
|
|
188
|
+
*/
|
|
189
|
+
SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086 = 1;
|
|
190
|
+
|
|
191
|
+
/*
|
|
192
|
+
Specifies that a SegWit v1 (p2tr) input should be signed by using a given
|
|
193
|
+
taproot hash to commit to in addition to the internal key.
|
|
194
|
+
*/
|
|
195
|
+
SIGN_METHOD_TAPROOT_KEY_SPEND = 2;
|
|
196
|
+
|
|
197
|
+
/*
|
|
198
|
+
Specifies that a SegWit v1 (p2tr) input should be spent using the script
|
|
199
|
+
path and that a specific leaf script should be signed for.
|
|
200
|
+
*/
|
|
201
|
+
SIGN_METHOD_TAPROOT_SCRIPT_SPEND = 3;
|
|
202
|
+
}
|
|
203
|
+
|
|
177
204
|
message SignDescriptor {
|
|
178
205
|
/*
|
|
179
206
|
A descriptor that precisely describes *which* key to use for signing. This
|
|
@@ -208,12 +235,23 @@ message SignDescriptor {
|
|
|
208
235
|
*/
|
|
209
236
|
bytes double_tweak = 3;
|
|
210
237
|
|
|
238
|
+
/*
|
|
239
|
+
The 32 byte input to the taproot tweak derivation that is used to derive
|
|
240
|
+
the output key from an internal key: outputKey = internalKey +
|
|
241
|
+
tagged_hash("tapTweak", internalKey || tapTweak).
|
|
242
|
+
|
|
243
|
+
When doing a BIP 86 spend, this field can be an empty byte slice.
|
|
244
|
+
|
|
245
|
+
When doing a normal key path spend, with the output key committing to an
|
|
246
|
+
actual script root, then this field should be: the tapscript root hash.
|
|
247
|
+
*/
|
|
248
|
+
bytes tap_tweak = 10;
|
|
249
|
+
|
|
211
250
|
/*
|
|
212
251
|
The full script required to properly redeem the output. This field will
|
|
213
|
-
only be populated if a p2tr, p2wsh or a p2sh output is being signed.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
public key (in case of a BIP-0086 output).
|
|
252
|
+
only be populated if a p2tr, p2wsh or a p2sh output is being signed. If a
|
|
253
|
+
taproot script path spend is being attempted, then this should be the raw
|
|
254
|
+
leaf script.
|
|
217
255
|
*/
|
|
218
256
|
bytes witness_script = 4;
|
|
219
257
|
|
|
@@ -235,12 +273,12 @@ message SignDescriptor {
|
|
|
235
273
|
int32 input_index = 8;
|
|
236
274
|
|
|
237
275
|
/*
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
276
|
+
The sign method specifies how the input should be signed. Depending on the
|
|
277
|
+
method, either the tap_tweak, witness_script or both need to be specified.
|
|
278
|
+
Defaults to SegWit v0 signing to be backward compatible with older RPC
|
|
279
|
+
clients.
|
|
242
280
|
*/
|
|
243
|
-
|
|
281
|
+
SignMethod sign_method = 9;
|
|
244
282
|
}
|
|
245
283
|
|
|
246
284
|
message SignReq {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const v0SpendMethod = 0;
|
|
2
|
+
const v1Bip86Method = 1;
|
|
3
|
+
const v1SpendMethod = 2;
|
|
4
|
+
const v1ScriptSpend = 3;
|
|
5
|
+
|
|
6
|
+
/** Determine a signing method for an input
|
|
7
|
+
|
|
8
|
+
{
|
|
9
|
+
input: [{
|
|
10
|
+
[root_hash]: <Taproot Root Hash Hex String>
|
|
11
|
+
[witness_script]: <Witness Script Hex String>
|
|
12
|
+
}]
|
|
13
|
+
[outputs]: [{
|
|
14
|
+
pk_script: <UTXO Output Script Buffer Object>
|
|
15
|
+
value: <UTXO Tokens Number>
|
|
16
|
+
}]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@returns
|
|
20
|
+
{
|
|
21
|
+
method: <Signing Method Number>
|
|
22
|
+
}
|
|
23
|
+
*/
|
|
24
|
+
module.exports = ({input, outputs}, cbk) => {
|
|
25
|
+
// Exit early when lack of previous outputs indicates a v0 spend
|
|
26
|
+
if (!outputs) {
|
|
27
|
+
return {method: v0SpendMethod};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Exit early when no leaf script or script commitment is present
|
|
31
|
+
if (!input.root_hash && !input.witness_script) {
|
|
32
|
+
return {method: v1Bip86Method};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Exit early when there is no leaf script, just a top level key spend
|
|
36
|
+
if (!input.witness_script) {
|
|
37
|
+
return {method: v1SpendMethod};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Sign for a leaf script for a key that commits to the scripts root hash
|
|
41
|
+
return {method: v1ScriptSpend};
|
|
42
|
+
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const asyncAuto = require('async/auto');
|
|
2
2
|
const {returnResult} = require('asyncjs-util');
|
|
3
3
|
|
|
4
|
+
const inputSigningMethod = require('./input_signing_method');
|
|
4
5
|
const {isLnd} = require('./../../lnd_requests');
|
|
5
6
|
|
|
6
7
|
const bufferAsHex = buffer => buffer.toString('hex');
|
|
7
|
-
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
const hexAsBuffer = hex => Buffer.from(hex || '', 'hex');
|
|
8
9
|
const {isArray} = Array;
|
|
9
10
|
const isV1 = scriptHex => scriptHex.length === 68 && /5120/.test(scriptHex);
|
|
10
11
|
const method = 'signOutputRaw';
|
|
@@ -28,9 +29,10 @@ const unimplementedError = '12 UNIMPLEMENTED: unknown service signrpc.Signer';
|
|
|
28
29
|
key_index: <Key Index Number>
|
|
29
30
|
output_script: <Output Script Hex String>
|
|
30
31
|
output_tokens: <Output Tokens Number>
|
|
32
|
+
[root_hash]: <Taproot Root Hash Hex String>
|
|
31
33
|
sighash: <Sighash Type Number>
|
|
32
34
|
vin: <Input Index To Sign Number>
|
|
33
|
-
witness_script: <Witness Script Hex String>
|
|
35
|
+
[witness_script]: <Witness Script Hex String>
|
|
34
36
|
}]
|
|
35
37
|
lnd: <Authenticated LND API Object>
|
|
36
38
|
[spending]: [{
|
|
@@ -65,8 +67,8 @@ module.exports = ({inputs, lnd, spending, transaction}, cbk) => {
|
|
|
65
67
|
return cbk();
|
|
66
68
|
},
|
|
67
69
|
|
|
68
|
-
// Derive the previous outputs set
|
|
69
|
-
|
|
70
|
+
// Derive the previous outputs set for Taproot spends
|
|
71
|
+
outputs: ['validate', ({}, cbk) => {
|
|
70
72
|
const outputs = [].concat(inputs).concat(spending || []).map(utxo => ({
|
|
71
73
|
pk_script: hexAsBuffer(utxo.output_script),
|
|
72
74
|
value: utxo.output_tokens,
|
|
@@ -83,25 +85,29 @@ module.exports = ({inputs, lnd, spending, transaction}, cbk) => {
|
|
|
83
85
|
}],
|
|
84
86
|
|
|
85
87
|
// Get signatures
|
|
86
|
-
signTransaction: ['
|
|
88
|
+
signTransaction: ['outputs', ({outputs}, cbk) => {
|
|
87
89
|
return lnd[type][method]({
|
|
88
|
-
prev_outputs:
|
|
90
|
+
prev_outputs: outputs,
|
|
89
91
|
raw_tx_bytes: hexAsBuffer(transaction),
|
|
90
|
-
sign_descs: inputs.map(input =>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
sign_descs: inputs.map(input => {
|
|
93
|
+
return {
|
|
94
|
+
input_index: input.vin,
|
|
95
|
+
key_desc: {
|
|
96
|
+
key_loc: {
|
|
97
|
+
key_family: input.key_family,
|
|
98
|
+
key_index: input.key_index,
|
|
99
|
+
},
|
|
96
100
|
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
output: {
|
|
102
|
+
pk_script: hexAsBuffer(input.output_script),
|
|
103
|
+
value: input.output_tokens,
|
|
104
|
+
},
|
|
105
|
+
sighash: input.sighash,
|
|
106
|
+
sign_method: inputSigningMethod({input, outputs}).method,
|
|
107
|
+
tap_tweak: hexAsBuffer(input.root_hash),
|
|
108
|
+
witness_script: hexAsBuffer(input.witness_script),
|
|
109
|
+
};
|
|
110
|
+
}),
|
|
105
111
|
},
|
|
106
112
|
(err, res) => {
|
|
107
113
|
if (!!err && err.message === unimplementedError) {
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"@grpc/grpc-js": "1.6.7",
|
|
11
11
|
"@grpc/proto-loader": "0.6.12",
|
|
12
12
|
"@types/express": "4.17.13",
|
|
13
|
-
"@types/node": "17.0.
|
|
13
|
+
"@types/node": "17.0.33",
|
|
14
14
|
"@types/request": "2.48.8",
|
|
15
15
|
"@types/ws": "8.5.3",
|
|
16
16
|
"async": "3.2.3",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"directory": "test/typescript"
|
|
60
60
|
},
|
|
61
61
|
"types": "index.d.ts",
|
|
62
|
-
"version": "5.
|
|
62
|
+
"version": "5.16.0"
|
|
63
63
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const method = require('./../../../lnd_methods/signer/input_signing_method');
|
|
4
|
+
|
|
5
|
+
const makeArgs = override => {
|
|
6
|
+
const args = {
|
|
7
|
+
input: {
|
|
8
|
+
root_hash: '00',
|
|
9
|
+
witness_script: '00',
|
|
10
|
+
},
|
|
11
|
+
outputs: [{
|
|
12
|
+
pk_script: Buffer.alloc(1),
|
|
13
|
+
value: 1,
|
|
14
|
+
}],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
Object.keys(override || {}).forEach(key => args[key] = override[key]);
|
|
18
|
+
|
|
19
|
+
return args;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const tests = [
|
|
23
|
+
{
|
|
24
|
+
args: makeArgs({}),
|
|
25
|
+
description: 'Input signing method is returned for a leaf spend',
|
|
26
|
+
expected: {method: 3},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
args: makeArgs({input: {}, outputs: undefined}),
|
|
30
|
+
description: 'Input signing method is returned for a regular spend',
|
|
31
|
+
expected: {method: 0},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
args: makeArgs({input: {}}),
|
|
35
|
+
description: 'Input signing method is returned for a bip86 spend',
|
|
36
|
+
expected: {method: 1},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
args: makeArgs({input: {root_hash: '00'}}),
|
|
40
|
+
description: 'Input signing method is returned for a top key script spend',
|
|
41
|
+
expected: {method: 2},
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
tests.forEach(({args, description, expected}) => {
|
|
46
|
+
return test(description, async ({end, strictSame}) => {
|
|
47
|
+
const res = method(args);
|
|
48
|
+
|
|
49
|
+
strictSame(res, expected, 'Got expected result');
|
|
50
|
+
|
|
51
|
+
return end();
|
|
52
|
+
});
|
|
53
|
+
});
|