lightning 4.7.0 → 4.7.1

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,6 +1,6 @@
1
1
  # Versions
2
2
 
3
- ## 4.7.0
3
+ ## 4.7.1
4
4
 
5
5
  - `getPayment`: Add `created_at` to indicate the creation date of the payment
6
6
  - `getPayment`: Add `request` to indicate serialized payment request
@@ -532,6 +532,14 @@ service Lightning {
532
532
  */
533
533
  rpc ListPermissions (ListPermissionsRequest)
534
534
  returns (ListPermissionsResponse);
535
+
536
+ /*
537
+ CheckMacaroonPermissions checks whether a request follows the constraints
538
+ imposed on the macaroon and that the macaroon is authorized to follow the
539
+ provided permissions.
540
+ */
541
+ rpc CheckMacaroonPermissions (CheckMacPermRequest)
542
+ returns (CheckMacPermResponse);
535
543
  }
536
544
 
537
545
  message Utxo {
@@ -4005,4 +4013,14 @@ message MacaroonId {
4005
4013
  message Op {
4006
4014
  string entity = 1;
4007
4015
  repeated string actions = 2;
4008
- }
4016
+ }
4017
+
4018
+ message CheckMacPermRequest {
4019
+ bytes macaroon = 1;
4020
+ repeated MacaroonPermission permissions = 2;
4021
+ string fullMethod = 3;
4022
+ }
4023
+
4024
+ message CheckMacPermResponse {
4025
+ bool valid = 1;
4026
+ }
package/index.js CHANGED
@@ -15,6 +15,7 @@ const {decodePaymentRequest} = require('./lnd_methods');
15
15
  const {deleteFailedPayAttempts} = require('./lnd_methods');
16
16
  const {deleteFailedPayments} = require('./lnd_methods');
17
17
  const {deleteForwardingReputations} = require('./lnd_methods');
18
+ const {deletePayment} = require('./lnd_methods');
18
19
  const {deletePayments} = require('./lnd_methods');
19
20
  const {diffieHellmanComputeSecret} = require('./lnd_methods');
20
21
  const {disableChannel} = require('./lnd_methods');
@@ -145,6 +146,7 @@ module.exports = {
145
146
  deleteFailedPayAttempts,
146
147
  deleteFailedPayments,
147
148
  deleteForwardingReputations,
149
+ deletePayment,
148
150
  deletePayments,
149
151
  disableChannel,
150
152
  disconnectWatchtower,
@@ -119,6 +119,7 @@ const {updateChainTransaction} = require('./onchain');
119
119
  const {updateConnectedWatchtower} = require('./offchain');
120
120
  const {updatePathfindingSettings} = require('./offchain');
121
121
  const {updateRoutingFees} = require('./offchain');
122
+ const {verifyAccess} = require('./macaroon');
122
123
  const {verifyBackup} = require('./offchain');
123
124
  const {verifyBackups} = require('./offchain');
124
125
  const {verifyBytesSignature} = require('./signer');
@@ -246,6 +247,7 @@ module.exports = {
246
247
  updateConnectedWatchtower,
247
248
  updatePathfindingSettings,
248
249
  updateRoutingFees,
250
+ verifyAccess,
249
251
  verifyBackup,
250
252
  verifyBackups,
251
253
  verifyBytesSignature,
@@ -1,5 +1,6 @@
1
1
  const getAccessIds = require('./get_access_ids');
2
2
  const grantAccess = require('./grant_access');
3
3
  const revokeAccess = require('./revoke_access');
4
+ const verifyAccess = require('./verify_access');
4
5
 
5
- module.exports = {getAccessIds, grantAccess, revokeAccess};
6
+ module.exports = {getAccessIds, grantAccess, revokeAccess, verifyAccess};
@@ -0,0 +1,85 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const {isLnd} = require('./../../lnd_requests');
5
+
6
+ const accessDeniedMessage = 'permission denied';
7
+ const asPermission = n => ({action: n.split(':')[1], entity: n.split(':')[0]});
8
+ const base64AsBuffer = base64 => Buffer.from(base64, 'base64');
9
+ const {isArray} = Array;
10
+ const isBoolean = n => n === false || n === true;
11
+ const method = 'checkMacaroonPermissions';
12
+ const notSupported = /unknown/;
13
+ const type = 'default';
14
+
15
+ /** Verify an access token has a given set of permissions
16
+
17
+ Note: this method is not supported in LND versions 0.13.1 and below
18
+
19
+ Requires `macaroon:read` permission
20
+
21
+ {
22
+ lnd: <Authenticated LND API Object>
23
+ macaroon: <Base64 Encoded Macaroon String>
24
+ permissions: [<Entity:Action String>]
25
+ }
26
+
27
+ @returns via cbk or Promise
28
+ {
29
+ is_valid: <Access Token is Valid For Described Permissions Bool>
30
+ }
31
+ */
32
+ module.exports = ({lnd, macaroon, permissions}, cbk) => {
33
+ return new Promise((resolve, reject) => {
34
+ return asyncAuto({
35
+ // Check arguments
36
+ validate: cbk => {
37
+ if (!isLnd({lnd, method, type})) {
38
+ return cbk([400, 'ExpectedAuthenticatedLndApiObjectToVerifyAccess']);
39
+ }
40
+
41
+ if (!macaroon) {
42
+ return cbk([400, 'ExpectedMacaroonToVerifyAccess']);
43
+ }
44
+
45
+ if (!isArray(permissions)) {
46
+ return cbk([400, 'ExpectedPermissionsArrayToVerifyAccess']);
47
+ }
48
+
49
+ return cbk();
50
+ },
51
+
52
+ // Check macaroon access
53
+ check: ['validate', ({}, cbk) => {
54
+ return lnd[type][method]({
55
+ macaroon: base64AsBuffer(macaroon),
56
+ permissions: permissions.map(permission => asPermission(permission)),
57
+ },
58
+ (err, res) => {
59
+ if (!!err && notSupported.test(err.details)) {
60
+ return cbk([501, 'VerifyAccessMethodNotSupported']);
61
+ }
62
+
63
+ if (!!err && err.details === accessDeniedMessage) {
64
+ return cbk(null, {is_valid: false});
65
+ }
66
+
67
+ if (!!err) {
68
+ return cbk([503, 'UnexpectedErrorFromCheckMacaroonMethod', {err}]);
69
+ }
70
+
71
+ if (!res) {
72
+ return cbk([503, 'ExpectedResponseFromCheckMacaroonRequest']);
73
+ }
74
+
75
+ if (!isBoolean(res.valid)) {
76
+ return cbk([503, 'ExpectedValidIndicatorInCheckMacaroonResponse']);
77
+ }
78
+
79
+ return cbk(null, {is_valid: res.valid});
80
+ });
81
+ }],
82
+ },
83
+ returnResult({reject, resolve, of: 'check'}, cbk));
84
+ });
85
+ };
@@ -0,0 +1,18 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript';
5
+
6
+ export type DeletePaymentArgs = AuthenticatedLightningArgs<{
7
+ /** Payment Preimage Hash Hex String */
8
+ id: string;
9
+ }>;
10
+
11
+ /**
12
+ * Delete a payment record
13
+ *
14
+ * Requires `offchain:write` permission
15
+ *
16
+ * Note: this method is not supported on LND 0.13.1 and below
17
+ */
18
+ export const deletePayment: AuthenticatedLightningMethod<DeletePaymentArgs>;
@@ -3,6 +3,7 @@ export * from './decode_payment_request';
3
3
  export * from './delete_failed_pay_attempts';
4
4
  export * from './delete_failed_payments';
5
5
  export * from './delete_forwarding_reputations';
6
+ export * from './delete_payment';
6
7
  export * from './delete_payments';
7
8
  export * from './disable_channel';
8
9
  export * from './disconnect_watchtower';
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "@grpc/grpc-js": "1.3.7",
11
11
  "@grpc/proto-loader": "0.6.5",
12
12
  "@types/express": "4.17.13",
13
- "@types/node": "16.9.1",
13
+ "@types/node": "16.9.6",
14
14
  "@types/request": "2.48.7",
15
15
  "@types/ws": "7.4.7",
16
16
  "async": "3.2.1",
@@ -19,7 +19,7 @@
19
19
  "bn.js": "5.2.0",
20
20
  "body-parser": "1.19.0",
21
21
  "bolt07": "1.7.3",
22
- "bolt09": "0.1.5",
22
+ "bolt09": "0.2.0",
23
23
  "cbor": "8.0.0",
24
24
  "express": "4.17.1",
25
25
  "invoices": "2.0.0",
@@ -56,5 +56,5 @@
56
56
  "directory": "test/typescript"
57
57
  },
58
58
  "types": "index.d.ts",
59
- "version": "4.7.0"
59
+ "version": "4.7.1"
60
60
  }
@@ -0,0 +1,101 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const {verifyAccess} = require('./../../../lnd_methods');
4
+
5
+ const makeArgs = overrides => {
6
+ const args = {
7
+ lnd: {
8
+ default: {
9
+ checkMacaroonPermissions: ({}, cbk) => cbk(null, {valid: true}),
10
+ },
11
+ },
12
+ macaroon: Buffer.from('macaroon').toString('base64'),
13
+ permissions: ['entity:action'],
14
+ };
15
+
16
+ Object.keys(overrides).forEach(k => args[k] = overrides[k]);
17
+
18
+ return args;
19
+ };
20
+
21
+ const tests = [
22
+ {
23
+ args: makeArgs({lnd: undefined}),
24
+ description: 'LND is required to verify access',
25
+ error: [400, 'ExpectedAuthenticatedLndApiObjectToVerifyAccess'],
26
+ },
27
+ {
28
+ args: makeArgs({macaroon: undefined}),
29
+ description: 'A macaroon is required',
30
+ error: [400, 'ExpectedMacaroonToVerifyAccess'],
31
+ },
32
+ {
33
+ args: makeArgs({permissions: undefined}),
34
+ description: 'Permissions to check are required',
35
+ error: [400, 'ExpectedPermissionsArrayToVerifyAccess'],
36
+ },
37
+ {
38
+ args: makeArgs({
39
+ lnd: {
40
+ default: {
41
+ checkMacaroonPermissions: ({}, cbk) => cbk({details: 'unknown ser'}),
42
+ },
43
+ },
44
+ }),
45
+ description: 'Method not supported error returned',
46
+ error: [501, 'VerifyAccessMethodNotSupported'],
47
+ },
48
+ {
49
+ args: makeArgs({
50
+ lnd: {
51
+ default: {
52
+ checkMacaroonPermissions: ({}, cbk) => cbk({
53
+ details: 'permission denied',
54
+ }),
55
+ },
56
+ },
57
+ }),
58
+ description: 'Method not supported error returned',
59
+ expected: {is_valid: false},
60
+ },
61
+ {
62
+ args: makeArgs({
63
+ lnd: {default: {checkMacaroonPermissions: ({}, cbk) => cbk('err')}},
64
+ }),
65
+ description: 'Errors are passed back',
66
+ error: [503, 'UnexpectedErrorFromCheckMacaroonMethod', {err: 'err'}],
67
+ },
68
+ {
69
+ args: makeArgs({
70
+ lnd: {default: {checkMacaroonPermissions: ({}, cbk) => cbk()}},
71
+ }),
72
+ description: 'A response is expected',
73
+ error: [503, 'ExpectedResponseFromCheckMacaroonRequest'],
74
+ },
75
+ {
76
+ args: makeArgs({
77
+ lnd: {default: {checkMacaroonPermissions: ({}, cbk) => cbk(null, {})}},
78
+ }),
79
+ description: 'A valid attribute is expected',
80
+ error: [503, 'ExpectedValidIndicatorInCheckMacaroonResponse'],
81
+ },
82
+ {
83
+ args: makeArgs({}),
84
+ description: 'Validity is returned',
85
+ expected: {is_valid: true},
86
+ },
87
+ ];
88
+
89
+ tests.forEach(({args, description, error, expected}) => {
90
+ return test(description, async ({end, rejects, strictSame}) => {
91
+ if (!!error) {
92
+ await rejects(() => verifyAccess(args), error, 'Got expected error');
93
+ } else {
94
+ const res = await verifyAccess(args);
95
+
96
+ strictSame(res, expected, 'Got expected result');
97
+ }
98
+
99
+ return end();
100
+ });
101
+ });
@@ -0,0 +1,15 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {AuthenticatedLnd} from '../../lnd_grpc';
3
+ import {deletePayment} from '../../lnd_methods';
4
+
5
+ const lnd = {} as AuthenticatedLnd;
6
+ const id = '0';
7
+
8
+ expectError(deletePayment());
9
+ expectError(deletePayment({}));
10
+ expectError(deletePayment({lnd}));
11
+ expectError(deletePayment({id}));
12
+
13
+ expectType<void>(await deletePayment({lnd, id}));
14
+
15
+ expectType<void>(deletePayment({lnd, id}, () => {}));