lightning 4.10.1 → 4.10.5

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 (35) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/grpc/protos/lightning.proto +20 -0
  3. package/grpc/protos/signer.proto +3 -0
  4. package/lnd_messages/close_channel_request.js +35 -0
  5. package/lnd_messages/index.js +5 -0
  6. package/lnd_messages/open_channel_request.js +51 -0
  7. package/lnd_messages/pay_via_route_request.js +61 -0
  8. package/lnd_methods/index.js +2 -0
  9. package/lnd_methods/macaroon/accept_rpc_request.js +44 -0
  10. package/lnd_methods/macaroon/handle_rpc_request_update.js +148 -0
  11. package/lnd_methods/macaroon/methods.json +9 -5
  12. package/lnd_methods/macaroon/reject_rpc_request.js +52 -0
  13. package/lnd_methods/macaroon/subscribe_to_rpc_requests.js +150 -49
  14. package/lnd_methods/macaroon/uris_for_method.js +8 -5
  15. package/lnd_methods/offchain/get_failed_payments.js +190 -0
  16. package/lnd_methods/offchain/get_payments.js +1 -3
  17. package/lnd_methods/offchain/index.js +2 -0
  18. package/lnd_methods/offchain/probe_for_route.js +5 -0
  19. package/lnd_responses/rpc_invoice_as_invoice.js +4 -2
  20. package/lnd_responses/rpc_payment_as_payment.js +71 -21
  21. package/package.json +3 -3
  22. package/test/lnd_messages/test_close_channel_request.js +72 -0
  23. package/test/lnd_messages/test_open_channel_request.js +87 -0
  24. package/test/lnd_messages/test_pay_via_route_request.js +79 -0
  25. package/test/lnd_methods/macaroon/test_accept_rpc_request.js +37 -0
  26. package/test/lnd_methods/macaroon/test_handle_rpc_request_update.js +237 -0
  27. package/test/lnd_methods/macaroon/test_reject_rpc_request.js +41 -0
  28. package/test/lnd_methods/macaroon/test_subscribe_to_rpc_requests.js +242 -0
  29. package/test/lnd_methods/macaroon/test_uris_for_method.js +10 -0
  30. package/test/lnd_methods/offchain/test_get_failed_payments.js +160 -0
  31. package/test/lnd_methods/offchain/test_get_payments.js +2 -2
  32. package/test/lnd_methods/onchain/test_close_channel.js +0 -1
  33. package/test/lnd_responses/test_rpc_invoice_as_invoice.js +34 -0
  34. package/test/lnd_responses/test_rpc_payment_as_payment.js +43 -8
  35. package/test/protos/protos.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Versions
2
2
 
3
+ ## 4.10.5
4
+
5
+ - `getInvoice`, `getInvoices`, `subscribeToInvoice`, `subscribeToInvoices`:
6
+ Fix `payment` being set when undefined, correct `is_push` for AMP pushes
7
+
8
+ ## 4.10.3
9
+
10
+ - `grantAccess`: Fix support for non-working methods
11
+
3
12
  ## 4.10.1
4
13
 
5
14
  - `getWalletVersion`: Add support for LND v0.13.3-beta
@@ -1086,6 +1086,12 @@ message SignMessageRequest {
1086
1086
  base64.
1087
1087
  */
1088
1088
  bytes msg = 1;
1089
+
1090
+ /*
1091
+ Instead of the default double-SHA256 hashing of the message before signing,
1092
+ only use one round of hashing instead.
1093
+ */
1094
+ bool single_hash = 2;
1089
1095
  }
1090
1096
  message SignMessageResponse {
1091
1097
  // The signature for the given message
@@ -2132,6 +2138,20 @@ message FundingPsbtVerify {
2132
2138
 
2133
2139
  // The pending channel ID of the channel to get the PSBT for.
2134
2140
  bytes pending_chan_id = 2;
2141
+
2142
+ /*
2143
+ Can only be used if the no_publish flag was set to true in the OpenChannel
2144
+ call meaning that the caller is solely responsible for publishing the final
2145
+ funding transaction. If skip_finalize is set to true then lnd will not wait
2146
+ for a FundingPsbtFinalize state step and instead assumes that a transaction
2147
+ with the same TXID as the passed in PSBT will eventually confirm.
2148
+ IT IS ABSOLUTELY IMPERATIVE that the TXID of the transaction that is
2149
+ eventually published does have the _same TXID_ as the verified PSBT. That
2150
+ means no inputs or outputs can change, only signatures can be added. If the
2151
+ TXID changes between this call and the publish step then the channel will
2152
+ never be created and the funds will be in limbo.
2153
+ */
2154
+ bool skip_finalize = 3;
2135
2155
  }
2136
2156
 
2137
2157
  message FundingPsbtFinalize {
@@ -190,6 +190,9 @@ message SignMessageReq {
190
190
 
191
191
  // The key locator that identifies which key to use for signing.
192
192
  KeyLocator key_loc = 2;
193
+
194
+ // Double-SHA256 hash instead of just the default single round.
195
+ bool double_hash = 3;
193
196
  }
194
197
  message SignMessageResp {
195
198
  /*
@@ -0,0 +1,35 @@
1
+ const hashAsTxId = hash => hash.slice().reverse().toString('hex');
2
+
3
+ /** Derive open channel details from an open channel request gRPC message
4
+
5
+ {
6
+ channel_point: {
7
+ funding_txid_bytes: <Internal Byte Order Transaction Hash Buffer Object>
8
+ output_index: <Transaction Output Index Number>
9
+ }
10
+ delivery_address: <Request Cooperative Close Address String>
11
+ force: <Force Close Channel Bool>
12
+ sat_per_byte: <Chain Fee Tokens Per Virtual Byte String>
13
+ target_conf: <Target Confirm Within N Blocks Number>
14
+ }
15
+
16
+ @returns
17
+ {
18
+ [address]: <Request Sending Local Channel Funds To Address String>
19
+ [is_force_close]: <Is Force Close Bool>
20
+ [target_confirmations]: <Confirmation Target Number>
21
+ [tokens_per_vbyte]: <Tokens Per Virtual Byte Number>
22
+ transaction_id: <Transaction Id Hex String>
23
+ transaction_vout: <Transaction Output Index Number>
24
+ }
25
+ */
26
+ module.exports = args => {
27
+ return {
28
+ address: args.delivery_address || undefined,
29
+ is_force_close: args.force || undefined,
30
+ target_confirmations: args.target_conf || undefined,
31
+ tokens_per_vbyte: Number(args.sat_per_byte) || undefined,
32
+ transaction_id: hashAsTxId(args.channel_point.funding_txid_bytes),
33
+ transaction_vout: args.channel_point.output_index,
34
+ };
35
+ };
@@ -0,0 +1,5 @@
1
+ const closeChannelRequest = require('./close_channel_request');
2
+ const openChannelRequest = require('./open_channel_request');
3
+ const payViaRouteRequest = require('./pay_via_route_request');
4
+
5
+ module.exports = {closeChannelRequest, openChannelRequest, payViaRouteRequest};
@@ -0,0 +1,51 @@
1
+ const bufferAsHex = buffer => buffer.toString('hex');
2
+ const minConfs = (isZero, confs) => isZero ? Number() : (confs || undefined);
3
+
4
+ /** Derive open channel details from an open channel request gRPC message
5
+
6
+ {
7
+ close_address: <Cooperative Close Address String>
8
+ local_funding_amount: <Channel Capacity Tokens String>
9
+ min_htlc_msat: <Minimum HTLC Millitokens String>
10
+ node_pubkey: <Node Public Key Buffer Object>
11
+ node_pubkey_string: <Node Public Key Hex String>
12
+ private: <Channel Is Private Bool>
13
+ push_sat: <Gift Tokens String>
14
+ remote_csv_delay: <Peer Uncooperative Output CSV Delay Blocks Number>
15
+ sat_per_byte: <Tokens Per Virtual Byte String>
16
+ sat_per_vbyte: <Tokens Per Virtual Byte String>
17
+ spend_unconfirmed: <Spend Unconfirmed UTXOs Bool>
18
+ target_conf: <Funding Transaction Confirmation Target Number>
19
+ }
20
+
21
+ @returns
22
+ {
23
+ [chain_fee_tokens_per_vbyte]: <Chain Fee Tokens Per VByte Number>
24
+ [cooperative_close_address]: <Restrict Cooperative Close To Address String>
25
+ [give_tokens]: <Tokens to Gift To Partner Number>
26
+ [is_private]: <Channel is Private Bool>
27
+ local_tokens: <Local Tokens Number>
28
+ [min_confirmations]: <Spend UTXOs With Minimum Confirmations Number>
29
+ [min_htlc_mtokens]: <Minimum HTLC Millitokens String>
30
+ partner_public_key: <Public Key Hex String>
31
+ [partner_csv_delay]: <Peer Output CSV Delay Number>
32
+ }
33
+ */
34
+ module.exports = args => {
35
+ const feeRate = Number(args.sat_per_vbyte) || Number(args.sat_per_byte);
36
+ const hasMinHtlc = args.min_htlc_msat !== Number().toString();
37
+ const publicKey = bufferAsHex(args.node_pubkey) || args.node_pubkey_string;
38
+ const utxoConfs = minConfs(args.spend_unconfirmed, args.min_confirmations);
39
+
40
+ return {
41
+ chain_fee_tokens_per_vbyte: feeRate || undefined,
42
+ cooperative_close_address: args.close_address || undefined,
43
+ give_tokens: Number(args.push_sat) || undefined,
44
+ is_private: args.private || undefined,
45
+ local_tokens: Number(args.local_funding_amount),
46
+ min_confirmations: utxoConfs,
47
+ min_htlc_mtokens: hasMinHtlc ? args.min_htlc_msat : undefined,
48
+ partner_public_key: publicKey,
49
+ partner_csv_delay: args.remote_csv_delay || undefined,
50
+ };
51
+ };
@@ -0,0 +1,61 @@
1
+ const {rpcRouteAsRoute} = require('./../lnd_responses');
2
+
3
+ const bufferAsHex = buffer => buffer.toString('hex');
4
+
5
+ /** Derive payment details from a pay via route request
6
+
7
+ {
8
+ payment_hash: <Payment Hash Buffer Object>
9
+ route: {
10
+ hops: [{
11
+ amt_to_forward_msat: <Millitokens to Forward String>
12
+ chan_id: <Numeric Format Channel Id String>
13
+ chan_capacity: <Channel Capacity Number>
14
+ custom_records: {
15
+ <UInt64 String>: <Record Data Buffer>
16
+ }
17
+ expiry: <Timeout Chain Height Number>
18
+ fee_msat: <Fee in Millitokens String>
19
+ [mpp_record]: {
20
+ payment_addr: <Payment Identifier Buffer>
21
+ total_amt_msat: <Total Payment Millitokens Amount String>
22
+ }
23
+ [pub_key]: <Next Hop Public Key Hex String>
24
+ tlv_payload: <Has Extra TLV Data Bool>
25
+ }]
26
+ total_amt_msat: <Route Total Millitokens String>
27
+ total_fees_msat: <Route Total Fees Millitokens String>
28
+ total_time_lock: <Route Total Timelock Number>
29
+ }
30
+ }
31
+
32
+ @returns
33
+ {
34
+ id: <Payment Hash Hex String>
35
+ route: {
36
+ fee: <Route Fee Tokens Number>
37
+ fee_mtokens: <Route Fee Millitokens String>
38
+ hops: [{
39
+ channel: <Standard Format Channel Id String>
40
+ channel_capacity: <Channel Capacity Tokens Number>
41
+ fee: <Fee Tokens Number>
42
+ fee_mtokens: <Fee Millitokens String>
43
+ forward: <Forward Tokens Number>
44
+ forward_mtokens: <Forward Millitokens String>
45
+ public_key: <Forward Edge Public Key Hex String>
46
+ [timeout]: <Timeout Block Height Number>
47
+ }]
48
+ mtokens: <Total Fee-Inclusive Millitokens String>
49
+ [payment]: <Payment Identifier Hex String>
50
+ [timeout]: <Timeout Block Height Number>
51
+ tokens: <Total Fee-Inclusive Tokens Number>
52
+ [total_mtokens]: <Total Payment Millitokens String>
53
+ }
54
+ }
55
+ */
56
+ module.exports = args => {
57
+ return {
58
+ id: bufferAsHex(args.payment_hash),
59
+ route: rpcRouteAsRoute(args.route),
60
+ };
61
+ };
@@ -35,6 +35,7 @@ const {getChannelBalance} = require('./offchain');
35
35
  const {getChannels} = require('./offchain');
36
36
  const {getClosedChannels} = require('./offchain');
37
37
  const {getConnectedWatchtowers} = require('./offchain');
38
+ const {getFailedPayments} = require('./offchain');
38
39
  const {getFeeRates} = require('./offchain');
39
40
  const {getForwardingConfidence} = require('./offchain');
40
41
  const {getForwardingReputations} = require('./offchain');
@@ -164,6 +165,7 @@ module.exports = {
164
165
  getChannels,
165
166
  getClosedChannels,
166
167
  getConnectedWatchtowers,
168
+ getFailedPayments,
167
169
  getFeeRates,
168
170
  getForwardingConfidence,
169
171
  getForwardingReputations,
@@ -0,0 +1,44 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const feedback = {replace_response: false};
5
+
6
+ /** Accept an RPC request
7
+
8
+ {
9
+ id: <Request or Response Id Number To Accept>
10
+ subscription: <RPC Request Stream Object>
11
+ }
12
+
13
+ @returns via cbk or Promise
14
+ */
15
+ module.exports = ({id, subscription}, cbk) => {
16
+ return new Promise((resolve, reject) => {
17
+ return asyncAuto({
18
+ // Check arguments
19
+ validate: cbk => {
20
+ if (!id) {
21
+ return cbk([400, 'ExpectedRequestIdToAcceptRpcRequest']);
22
+ }
23
+
24
+ if (!subscription) {
25
+ return cbk([400, 'ExpectedRpcSubscriptionToAcceptRpcRequest']);
26
+ }
27
+
28
+ return cbk();
29
+ },
30
+
31
+ // Send accept feedback to the stream
32
+ accept: ['validate', ({}, cbk) => {
33
+ return subscription.write({feedback, request_id: id}, err => {
34
+ if (!!err) {
35
+ return cbk([503, 'UnexpectedErrorAcceptingRpcRequest', {err}]);
36
+ }
37
+
38
+ return cbk();
39
+ });
40
+ }],
41
+ },
42
+ returnResult({reject, resolve}, cbk));
43
+ });
44
+ };
@@ -0,0 +1,148 @@
1
+ const acceptRpcRequest = require('./accept_rpc_request');
2
+ const {closeChannelRequest} = require('./../../lnd_messages');
3
+ const {openChannelRequest} = require('./../../lnd_messages');
4
+ const {payViaRouteRequest} = require('./../../lnd_messages');
5
+ const rejectRpcRequest = require('./reject_rpc_request');
6
+ const {rpcRequestUpdateAsEvent} = require('./../../lnd_responses');
7
+
8
+ const isChanClose = n => !!n && n === '/lnrpc.Lightning/CloseChannel';
9
+ const isChanOpen = n => !!n && n.startsWith('/lnrpc.Lightning/OpenChannel');
10
+ const isPayViaRoute = n => !!n && n === '/routerrpc.Router/SendToRouteV2';
11
+
12
+ /** Handle an update from the RPC request stream
13
+
14
+ {
15
+ [is_intercepting_close_channel_requests]: <Intercept Channel Closes Bool>
16
+ [is_intercepting_open_channel_requests]: <Is Handling Open Requests Bool>
17
+ [is_intercepting_pay_via_routes_requests]: <Is Handling Route Reqs Bool>
18
+ subscription: <Stream Subscription Object>
19
+ update: {
20
+ request_id: <Request Id Number String>
21
+ raw_macaroon: <Raw Macaroon Buffer Object>
22
+ custom_caveat_condition: <Custom Caveat Condition String>
23
+ [request]: {
24
+ method_full_uri: <Method URI String>
25
+ serialized: <Raw Protobuf Request Buffer Object>
26
+ stream_rpc: <Is String RPC Bool>
27
+ type_name: <RPC Message Type String>
28
+ }
29
+ [response]: {
30
+ method_full_uri: <Method URI String>
31
+ serialized: <Raw Protobuf Response Buffer Object>
32
+ stream_rpc: <Is String RPC Bool>
33
+ type_name: <RPC Message Type String>
34
+ }
35
+ [stream_auth]: {
36
+ method_full_uri: <Method URI String>
37
+ }
38
+ intercept_type: <RPC Update Type String>
39
+ }
40
+ }
41
+
42
+ @throws
43
+ <Error>
44
+
45
+ @returns
46
+ {
47
+ [accept]: ({}, cbk) => {}
48
+ data: {
49
+ [accept]: ({}, cbk) => {}
50
+ id: <Request Id Number>
51
+ [macaroon]: <Base64 Encoded Macaroon String>
52
+ [reject]: ({}, cbk) => {}
53
+ [request]: {
54
+ [chain_fee_tokens_per_vbyte]: <Chain Fee Tokens Per VByte Number>
55
+ [cooperative_close_address]: <Prefer Cooperative Close To Address String>
56
+ [give_tokens]: <Tokens to Gift To Partner Number>
57
+ [is_private]: <Channel is Private Bool>
58
+ local_tokens: <Local Tokens Number>
59
+ [min_confirmations]: <Spend UTXOs With Minimum Confirmations Number>
60
+ [min_htlc_mtokens]: <Minimum HTLC Millitokens String>
61
+ partner_public_key: <Public Key Hex String>
62
+ [partner_csv_delay]: <Peer Output CSV Delay Number>
63
+ }
64
+ [uri]: <RPC URI String>
65
+ }
66
+ event: <Event Name String>
67
+ }
68
+ */
69
+ module.exports = args => {
70
+ const details = rpcRequestUpdateAsEvent(args.update);
71
+ const isInterceptCloseChans = !!args.is_intercepting_close_channel_requests;
72
+ const isInterceptOpenChans = !!args.is_intercepting_open_channel_requests;
73
+ const isInterceptPayOnRoute = !!args.is_intercepting_pay_via_routes_requests;
74
+
75
+ const {event} = details;
76
+ const {id} = details;
77
+ const {macaroon} = details;
78
+ const {request} = args.update;
79
+ const {subscription} = args;
80
+ const {uri} = details;
81
+
82
+ const accept = ({}, cbk) => acceptRpcRequest({id, subscription}, cbk);
83
+
84
+ // Exit early when intercepting channel closes
85
+ if (!!isInterceptCloseChans && !!request && isChanClose(uri)) {
86
+ const req = args.lnd.default.CloseChannel.requestDeserialize(
87
+ args.update.request.serialized
88
+ );
89
+
90
+ return {
91
+ event: 'close_channel_request',
92
+ data: {
93
+ accept,
94
+ id,
95
+ macaroon,
96
+ uri,
97
+ reject: ({message}, cbk) => {
98
+ return rejectRpcRequest({id, message, subscription}, cbk);
99
+ },
100
+ request: closeChannelRequest(req),
101
+ },
102
+ };
103
+ }
104
+
105
+ // Exit early when intercepting channel opens
106
+ if (!!isInterceptOpenChans && !!request && isChanOpen(uri)) {
107
+ const req = args.lnd.default.OpenChannel.requestDeserialize(
108
+ args.update.request.serialized
109
+ );
110
+
111
+ return {
112
+ event: 'open_channel_request',
113
+ data: {
114
+ accept,
115
+ id,
116
+ macaroon,
117
+ uri,
118
+ reject: ({message}, cbk) => {
119
+ return rejectRpcRequest({id, message, subscription}, cbk);
120
+ },
121
+ request: openChannelRequest(req),
122
+ },
123
+ };
124
+ }
125
+
126
+ // Exit early when intercepting pay via route requests
127
+ if (!!isInterceptPayOnRoute && !!request && isPayViaRoute(uri)) {
128
+ const req = args.lnd.router.SendToRouteV2.requestDeserialize(
129
+ args.update.request.serialized
130
+ );
131
+
132
+ return {
133
+ event: 'pay_via_route_request',
134
+ data: {
135
+ accept,
136
+ id,
137
+ macaroon,
138
+ uri,
139
+ reject: ({message}, cbk) => {
140
+ return rejectRpcRequest({id, message, subscription}, cbk);
141
+ },
142
+ request: payViaRouteRequest(req),
143
+ },
144
+ };
145
+ }
146
+
147
+ return {accept, event, data: {id, macaroon, uri}};
148
+ };
@@ -139,6 +139,10 @@
139
139
  "methods": ["ListTowers", "Policy", "Stats"],
140
140
  "type": "tower_client"
141
141
  },
142
+ "getFailedPayments": {
143
+ "method": "ListPayments",
144
+ "type": "default"
145
+ },
142
146
  "getFeeRates": {
143
147
  "method": "FeeReport",
144
148
  "type": "default"
@@ -214,7 +218,7 @@
214
218
  "method": "WalletBalance",
215
219
  "type": "default"
216
220
  },
217
- "getPendingChainBalance": {
221
+ "getPendingChannels": {
218
222
  "method": "PendingChannels",
219
223
  "type": "default"
220
224
  },
@@ -344,7 +348,7 @@
344
348
  },
345
349
  "setAutopilot": {
346
350
  "depends_on": ["getAutopilot"],
347
- "methods": ["modifyStatus", "setScores"],
351
+ "methods": ["ModifyStatus", "SetScores"],
348
352
  "type": "autopilot"
349
353
  },
350
354
  "settleHodlInvoice": {
@@ -435,7 +439,7 @@
435
439
  "type": "router"
436
440
  },
437
441
  "subscribeToPayViaRoutes": {
438
- "method": "sendToRouteV2",
442
+ "method": "SendToRouteV2",
439
443
  "type": "router"
440
444
  },
441
445
  "subscribeToPeers": {
@@ -462,11 +466,11 @@
462
466
  "type": "wallet"
463
467
  },
464
468
  "updateConnectedWatchtower": {
465
- "methods": ["addTower", "removeTower"],
469
+ "methods": ["AddTower", "RemoveTower"],
466
470
  "type": "tower_client"
467
471
  },
468
472
  "updateChainTransaction": {
469
- "method": "labelTransaction",
473
+ "method": "LabelTransaction",
470
474
  "type": "wallet"
471
475
  },
472
476
  "updatePathfindingSettings": {
@@ -0,0 +1,52 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const defaultRejectMessage = 'RpcRequestRejected';
5
+
6
+ /** Accept an RPC request
7
+
8
+ {
9
+ id: <Request or Response Id Number To Accept>
10
+ [message]: <Rejection Message String>
11
+ subscription: <RPC Request Stream Object>
12
+ }
13
+
14
+ @returns via cbk or Promise
15
+ */
16
+ module.exports = ({id, message, subscription}, cbk) => {
17
+ return new Promise((resolve, reject) => {
18
+ return asyncAuto({
19
+ // Check arguments
20
+ validate: cbk => {
21
+ if (!id) {
22
+ return cbk([400, 'ExpectedRequestIdToRejectRpcRequest']);
23
+ }
24
+
25
+ if (!subscription) {
26
+ return cbk([400, 'ExpectedRpcSubscriptionToRejectRpcRequest']);
27
+ }
28
+
29
+ return cbk();
30
+ },
31
+
32
+ // Send reject feedback to the stream
33
+ reject: ['validate', ({}, cbk) => {
34
+ return subscription.write({
35
+ feedback: {
36
+ error: message || defaultRejectMessage,
37
+ replace_response: false,
38
+ },
39
+ request_id: id,
40
+ },
41
+ err => {
42
+ if (!!err) {
43
+ return cbk([503, 'UnexpectedErrorRejectingRpcRequest', {err}]);
44
+ }
45
+
46
+ return cbk();
47
+ });
48
+ }],
49
+ },
50
+ returnResult({reject, resolve}, cbk));
51
+ });
52
+ };