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 +1 -1
- package/grpc/protos/lightning.proto +19 -1
- package/index.js +2 -0
- package/lnd_methods/index.js +2 -0
- package/lnd_methods/macaroon/index.js +2 -1
- package/lnd_methods/macaroon/verify_access.js +85 -0
- package/lnd_methods/offchain/delete_payment.d.ts +18 -0
- package/lnd_methods/offchain/index.d.ts +1 -0
- package/package.json +3 -3
- package/test/lnd_methods/macaroon/test_verify_access.js +101 -0
- package/test/typescript/delete_payment.test-d.ts +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -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,
|
package/lnd_methods/index.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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}, () => {}));
|