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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Versions
2
2
 
3
+ ## 5.16.0
4
+
5
+ - `signTransaction`: Add `root_hash` to support Taproot signatures with scripts
6
+
3
7
  ## 5.15.2
4
8
 
5
9
  - `getFailedPayments`, `getPayments`, `getPendingPayments`: Remove
@@ -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 {
@@ -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. In case
214
- taproot_key_spend is set to true then this value must correspond to the
215
- taproot root hash (in case of a tapscript output) or the tap hashed internal
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
- Indicates that this should produce a signature that can be used for the key
239
- spend path of a taproot input. This requires the witness_script field to be
240
- set to the taproot root hash (in case of a tapscript output) or the tap
241
- hashed internal public key (in case of a BIP-0086 output).
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
- bool taproot_key_spend = 9;
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
- previousOutputs: ['validate', ({}, cbk) => {
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: ['previousOutputs', ({previousOutputs}, cbk) => {
88
+ signTransaction: ['outputs', ({outputs}, cbk) => {
87
89
  return lnd[type][method]({
88
- prev_outputs: previousOutputs,
90
+ prev_outputs: outputs,
89
91
  raw_tx_bytes: hexAsBuffer(transaction),
90
- sign_descs: inputs.map(input => ({
91
- input_index: input.vin,
92
- key_desc: {
93
- key_loc: {
94
- key_family: input.key_family,
95
- key_index: input.key_index,
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
- output: {
99
- pk_script: hexAsBuffer(input.output_script),
100
- value: input.output_tokens,
101
- },
102
- sighash: input.sighash,
103
- witness_script: hexAsBuffer(input.witness_script),
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.32",
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.15.2"
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
+ });