lightning 5.14.0 → 5.15.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 +6 -0
- package/README.md +2 -2
- package/grpc/protos/chainnotifier.proto +5 -3
- package/grpc/protos/lightning.proto +6 -1
- package/grpc/protos/signer.proto +308 -0
- package/index.js +6 -0
- package/lnd_methods/index.js +6 -0
- package/lnd_methods/macaroon/methods.json +13 -0
- package/lnd_methods/signer/begin_group_signing_session.js +144 -0
- package/lnd_methods/signer/end_group_signing_session.js +102 -0
- package/lnd_methods/signer/index.js +6 -0
- package/lnd_methods/signer/update_group_signing_session.js +110 -0
- package/lnd_responses/index.js +2 -0
- package/lnd_responses/rpc_group_session_as_session.js +51 -0
- package/package.json +6 -6
- package/test/lnd_methods/signer/test_begin_group_signing_session.js +134 -0
- package/test/lnd_methods/signer/test_diffie_hellman_compute_secret.js +3 -1
- package/test/lnd_methods/signer/test_end_group_signing_session.js +93 -0
- package/test/lnd_methods/signer/test_update_group_signing_session.js +108 -0
- package/test/lnd_responses/test_rpc_group_session_as_session.js +79 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const {returnResult} = require('asyncjs-util');
|
|
3
|
+
|
|
4
|
+
const {isLnd} = require('./../../lnd_requests');
|
|
5
|
+
|
|
6
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
7
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
const {isArray} = Array;
|
|
9
|
+
const {isBuffer} = Buffer;
|
|
10
|
+
const method = 'muSig2CombineSig';
|
|
11
|
+
const type = 'signer';
|
|
12
|
+
|
|
13
|
+
/** Complete a MuSig2 signing session
|
|
14
|
+
|
|
15
|
+
Requires LND built with `signrpc` build tag
|
|
16
|
+
|
|
17
|
+
Requires `signer:generate` permission
|
|
18
|
+
|
|
19
|
+
This method is not supported in LND 0.14.3 and below
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
id: <Session Id Hex String>
|
|
23
|
+
lnd: <Authenticated LND API Object>
|
|
24
|
+
[signatures]: [<Combine External Partial Signature Hex String>]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@returns via cbk or Promise
|
|
28
|
+
{
|
|
29
|
+
[signature]: <Combined Signature Hex String>
|
|
30
|
+
}
|
|
31
|
+
*/
|
|
32
|
+
module.exports = ({id, lnd, signatures}, cbk) => {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
return asyncAuto({
|
|
35
|
+
// Check arguments
|
|
36
|
+
validate: cbk => {
|
|
37
|
+
if (!id) {
|
|
38
|
+
return cbk([400, 'ExpectedSessionIdToFinishMuSig2Session']);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!isLnd({lnd, method, type})) {
|
|
42
|
+
return cbk([400, 'ExpectedAuthenticatedLndToFinishMuSig2Session']);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (isArray(signatures) && !signatures.length) {
|
|
46
|
+
return cbk([400, 'ExpectedPartialSignaturesToCombineToEndSession']);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return cbk();
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// Close out the signing session
|
|
53
|
+
endSession: ['validate', ({}, cbk) => {
|
|
54
|
+
// Exit early when there are signatures to combine
|
|
55
|
+
if (isArray(signatures)) {
|
|
56
|
+
return cbk();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return lnd[type].muSig2Cleanup({session_id: hexAsBuffer(id)}, err => {
|
|
60
|
+
if (!!err) {
|
|
61
|
+
return cbk([503, 'UnexpectedErrorCleaningUpMuSig2Session', {err}]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return cbk();
|
|
65
|
+
});
|
|
66
|
+
}],
|
|
67
|
+
|
|
68
|
+
// Update the session with signatures
|
|
69
|
+
updateSignatures: ['validate', ({}, cbk) => {
|
|
70
|
+
// Exit early when there are no signatures to update
|
|
71
|
+
if (!isArray(signatures)) {
|
|
72
|
+
return cbk(null, {});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return lnd[type][method]({
|
|
76
|
+
other_partial_signatures: signatures.map(hexAsBuffer),
|
|
77
|
+
session_id: hexAsBuffer(id),
|
|
78
|
+
},
|
|
79
|
+
(err, res) => {
|
|
80
|
+
if (!!err) {
|
|
81
|
+
return cbk([503, 'UnexpectedErrorFinishingMuSig2Session', {err}]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!res) {
|
|
85
|
+
return cbk([503, 'ExpectedResponseForMuSig2CombineRequest']);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (res.have_all_signatures === false) {
|
|
89
|
+
return cbk([400, 'ExpectedAllSignaturesProvidedForSession']);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!isBuffer(res.final_signature)) {
|
|
93
|
+
return cbk([503, 'ExpectedFinalSignatureInCombineResponse']);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return cbk(null, {signature: bufferAsHex(res.final_signature)});
|
|
97
|
+
});
|
|
98
|
+
}],
|
|
99
|
+
},
|
|
100
|
+
returnResult({reject, resolve, of: 'updateSignatures'}, cbk));
|
|
101
|
+
});
|
|
102
|
+
};
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
const beginGroupSigningSession = require('./begin_group_signing_session');
|
|
1
2
|
const diffieHellmanComputeSecret = require('./diffie_hellman_compute_secret');
|
|
3
|
+
const endGroupSigningSession = require('./end_group_signing_session');
|
|
2
4
|
const signBytes = require('./sign_bytes');
|
|
3
5
|
const signTransaction = require('./sign_transaction');
|
|
6
|
+
const updateGroupSigningSession = require('./update_group_signing_session');
|
|
4
7
|
const verifyBytesSignature = require('./verify_bytes_signature');
|
|
5
8
|
|
|
6
9
|
module.exports = {
|
|
10
|
+
beginGroupSigningSession,
|
|
7
11
|
diffieHellmanComputeSecret,
|
|
12
|
+
endGroupSigningSession,
|
|
8
13
|
signBytes,
|
|
9
14
|
signTransaction,
|
|
15
|
+
updateGroupSigningSession,
|
|
10
16
|
verifyBytesSignature,
|
|
11
17
|
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const {returnResult} = require('asyncjs-util');
|
|
3
|
+
|
|
4
|
+
const {isLnd} = require('./../../lnd_requests');
|
|
5
|
+
|
|
6
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
7
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
const {isArray} = Array;
|
|
9
|
+
const {isBuffer} = Buffer;
|
|
10
|
+
const isHash = n => !!n && /^[0-9A-F]{64}$/i.test(n);
|
|
11
|
+
const method = 'muSig2RegisterNonces';
|
|
12
|
+
const type = 'signer';
|
|
13
|
+
|
|
14
|
+
/** Update a MuSig2 signing session with nonces and generate a partial sig
|
|
15
|
+
|
|
16
|
+
All remote nonces are expected to be passed
|
|
17
|
+
|
|
18
|
+
Requires LND built with `signrpc` build tag
|
|
19
|
+
|
|
20
|
+
Requires `signer:generate` permission
|
|
21
|
+
|
|
22
|
+
This method is not supported in LND 0.14.3 and below
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
hash: <Hash to Sign Hex String>
|
|
26
|
+
id: <MuSig2 Session Id Hex String>
|
|
27
|
+
lnd: <Authenticated LND API Object>
|
|
28
|
+
nonces: [<Nonce Hex String>]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@returns via cbk or Promise
|
|
32
|
+
{
|
|
33
|
+
signature: <Partial Signature Hex String>
|
|
34
|
+
}
|
|
35
|
+
*/
|
|
36
|
+
module.exports = ({hash, id, lnd, nonces}, cbk) => {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
return asyncAuto({
|
|
39
|
+
// Check arguments
|
|
40
|
+
validate: cbk => {
|
|
41
|
+
if (!isHash(hash)) {
|
|
42
|
+
return cbk([400, 'ExpectedHashToSignToUpdateMuSig2Session']);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!id) {
|
|
46
|
+
return cbk([400, 'ExpectedSessionIdToUpdateMuSig2Session']);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!isLnd({lnd, method, type})) {
|
|
50
|
+
return cbk([400, 'ExpectedAuthenticatedLndToUpdateMuSig2Session']);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!isArray(nonces)) {
|
|
54
|
+
return cbk([400, 'ExpectedArrayOfNoncesToUpdateMuSig2Session']);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return cbk();
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// Update the session with the nonces
|
|
61
|
+
updateNonces: ['validate', ({}, cbk) => {
|
|
62
|
+
return lnd[type][method]({
|
|
63
|
+
other_signer_public_nonces: nonces.map(hexAsBuffer),
|
|
64
|
+
session_id: hexAsBuffer(id),
|
|
65
|
+
},
|
|
66
|
+
(err, res) => {
|
|
67
|
+
if (!!err) {
|
|
68
|
+
return cbk([503, 'UnexpectedErrorUpdatingMuSig2Session', {err}]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!res) {
|
|
72
|
+
return cbk([503, 'ExpectedResultOfRegisterNoncesRequest']);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (res.have_all_nonces !== true) {
|
|
76
|
+
return cbk([400, 'ExpectedAllNoncesForRegisterNoncesRequest']);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return cbk();
|
|
80
|
+
});
|
|
81
|
+
}],
|
|
82
|
+
|
|
83
|
+
// Partially sign the digest hash
|
|
84
|
+
sign: ['updateNonces', ({}, cbk) => {
|
|
85
|
+
return lnd[type].muSig2Sign({
|
|
86
|
+
message_digest: hexAsBuffer(hash),
|
|
87
|
+
session_id: hexAsBuffer(id),
|
|
88
|
+
},
|
|
89
|
+
(err, res) => {
|
|
90
|
+
if (!!err) {
|
|
91
|
+
return cbk([503, 'UnexpectedErrorSigningMuSig2Session', {err}]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!res) {
|
|
95
|
+
return cbk([503, 'ExpectedResultForMuSig2SignRequest']);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!isBuffer(res.local_partial_signature)) {
|
|
99
|
+
return cbk([503, 'ExpectedPartialSignatureForMuSig2SignRequest']);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return cbk(null, {
|
|
103
|
+
signature: bufferAsHex(res.local_partial_signature),
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}],
|
|
107
|
+
},
|
|
108
|
+
returnResult({reject, resolve, of: 'sign'}, cbk));
|
|
109
|
+
});
|
|
110
|
+
};
|
package/lnd_responses/index.js
CHANGED
|
@@ -26,6 +26,7 @@ const rpcFailedPolicyAsFail = require('./rpc_failed_policy_as_fail');
|
|
|
26
26
|
const rpcFeesAsChannelFees = require('./rpc_fees_as_channel_fees');
|
|
27
27
|
const rpcForwardAsForward = require('./rpc_forward_as_forward');
|
|
28
28
|
const rpcForwardAsForwardRequest = require('./rpc_forward_as_forward_request');
|
|
29
|
+
const rpcGroupSessionAsSession = require('./rpc_group_session_as_session');
|
|
29
30
|
const rpcHopAsHop = require('./rpc_hop_as_hop');
|
|
30
31
|
const rpcInvoiceAsInvoice = require('./rpc_invoice_as_invoice');
|
|
31
32
|
const rpcNetworkAsNetworkInfo = require('./rpc_network_as_network_info');
|
|
@@ -70,6 +71,7 @@ module.exports = {
|
|
|
70
71
|
rpcFeesAsChannelFees,
|
|
71
72
|
rpcForwardAsForward,
|
|
72
73
|
rpcForwardAsForwardRequest,
|
|
74
|
+
rpcGroupSessionAsSession,
|
|
73
75
|
rpcHopAsHop,
|
|
74
76
|
rpcInvoiceAsInvoice,
|
|
75
77
|
rpcNetworkAsNetworkInfo,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
2
|
+
const {isBuffer} = Buffer;
|
|
3
|
+
|
|
4
|
+
/** Map RPC MuSig2 Session to a MuSig2 Session
|
|
5
|
+
|
|
6
|
+
{
|
|
7
|
+
combined_key: <Combined Public Key Buffer Object>
|
|
8
|
+
local_public_nonces: <Two Concatenated Local Signer Nonces Buffer Object>
|
|
9
|
+
session_id: <Session Id Buffer Object>
|
|
10
|
+
taproot_internal_key: <Taproot Internal Public Key Buffer Object>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@throws
|
|
14
|
+
<Error>
|
|
15
|
+
|
|
16
|
+
@returns
|
|
17
|
+
{
|
|
18
|
+
external_key: <Final Script or Top Level Public Key Hex String>
|
|
19
|
+
id: <Session Id Hex String>
|
|
20
|
+
[internal_key]: <Internal Top Level Public Key Hex String>
|
|
21
|
+
nonce: <Session Compound Nonces Hex String>
|
|
22
|
+
}
|
|
23
|
+
*/
|
|
24
|
+
module.exports = args => {
|
|
25
|
+
if (!args) {
|
|
26
|
+
throw new Error('ExpectedResponseForMuSig2SessionRequest');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!isBuffer(args.combined_key)) {
|
|
30
|
+
throw new Error('ExpectedCombinedPublicKeyInMuSig2SessionResponse');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!isBuffer(args.local_public_nonces)) {
|
|
34
|
+
throw new Error('ExpectedLocalPublicNoncesInMuSig2SessionResponse');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!isBuffer(args.session_id)) {
|
|
38
|
+
throw new Error('ExpectedMuSig2SigningSessionIdInSessionResponse');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!isBuffer(args.taproot_internal_key)) {
|
|
42
|
+
throw new Error('ExpectedTaprootInternalKeyInMuSig2SessionResponse');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
external_key: bufferAsHex(args.combined_key),
|
|
47
|
+
id: bufferAsHex(args.session_id),
|
|
48
|
+
internal_key: bufferAsHex(args.taproot_internal_key) || undefined,
|
|
49
|
+
nonce: bufferAsHex(args.local_public_nonces),
|
|
50
|
+
};
|
|
51
|
+
};
|
package/package.json
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@grpc/grpc-js": "1.6.7",
|
|
11
|
-
"@grpc/proto-loader": "0.6.
|
|
11
|
+
"@grpc/proto-loader": "0.6.12",
|
|
12
12
|
"@types/express": "4.17.13",
|
|
13
|
-
"@types/node": "17.0.
|
|
13
|
+
"@types/node": "17.0.31",
|
|
14
14
|
"@types/request": "2.48.8",
|
|
15
15
|
"@types/ws": "8.5.3",
|
|
16
16
|
"async": "3.2.3",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"bolt09": "0.2.3",
|
|
23
23
|
"cbor": "8.1.0",
|
|
24
24
|
"ecpair": "2.0.1",
|
|
25
|
-
"express": "4.
|
|
25
|
+
"express": "4.18.1",
|
|
26
26
|
"invoices": "2.0.6",
|
|
27
27
|
"psbt": "2.0.1",
|
|
28
28
|
"tiny-secp256k1": "2.2.1",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"@alexbosworth/node-fetch": "2.6.2",
|
|
34
34
|
"@alexbosworth/tap": "15.0.11",
|
|
35
35
|
"tsd": "0.20.0",
|
|
36
|
-
"typescript": "4.6.
|
|
37
|
-
"ws": "8.
|
|
36
|
+
"typescript": "4.6.4",
|
|
37
|
+
"ws": "8.6.0"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=12.20"
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"directory": "test/typescript"
|
|
60
60
|
},
|
|
61
61
|
"types": "index.d.ts",
|
|
62
|
-
"version": "5.
|
|
62
|
+
"version": "5.15.0"
|
|
63
63
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {beginGroupSigningSession} = require('./../../../');
|
|
4
|
+
|
|
5
|
+
const makeLnd = (err, res) => {
|
|
6
|
+
return {
|
|
7
|
+
signer: {
|
|
8
|
+
muSig2CreateSession: ({}, cbk) => cbk(err, res)
|
|
9
|
+
},
|
|
10
|
+
wallet: {
|
|
11
|
+
deriveKey: ({}, cbk) => cbk(null, {
|
|
12
|
+
key_loc: {key_index: 0},
|
|
13
|
+
raw_key_bytes: Buffer.alloc(1),
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const makeArgs = override => {
|
|
20
|
+
const args = {
|
|
21
|
+
lnd: makeLnd(null, {
|
|
22
|
+
combined_key: Buffer.alloc(32),
|
|
23
|
+
local_public_nonces: Buffer.alloc(66),
|
|
24
|
+
session_id: Buffer.alloc(32),
|
|
25
|
+
taproot_internal_key: Buffer.alloc(0),
|
|
26
|
+
}),
|
|
27
|
+
key_family: 0,
|
|
28
|
+
key_index: 0,
|
|
29
|
+
public_keys: [Buffer.alloc(33, 2).toString('hex')],
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
Object.keys(override || {}).forEach(key => args[key] = override[key]);
|
|
33
|
+
|
|
34
|
+
return args;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const tests = [
|
|
38
|
+
{
|
|
39
|
+
args: makeArgs({lnd: undefined}),
|
|
40
|
+
description: 'LND object is required',
|
|
41
|
+
error: [400, 'ExpectedAuthenticatedLndToStartMuSig2Session'],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
args: makeArgs({key_family: undefined}),
|
|
45
|
+
description: 'A key family is required',
|
|
46
|
+
error: [400, 'ExpectedKeyFamilyToStartMuSig2Session'],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
args: makeArgs({key_index: undefined}),
|
|
50
|
+
description: 'The key index is required',
|
|
51
|
+
error: [400, 'ExpectedKeyIndexToStartMuSig2Session'],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
args: makeArgs({public_keys: undefined}),
|
|
55
|
+
description: 'Public keys are required',
|
|
56
|
+
error: [400, 'ExpectedArrayOfPublicKeysForMuSig2SessionStart'],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
args: makeArgs({public_keys: []}),
|
|
60
|
+
description: 'Remote public keys are required',
|
|
61
|
+
error: [400, 'ExpectedOtherPublicKeysForMuSig2SessionStart'],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
args: makeArgs({root_hash: 'root_hash'}),
|
|
65
|
+
description: 'Root hash must be valid',
|
|
66
|
+
error: [400, 'ExpectedHashWhenSpecifyingMuSig2ScriptRootHash'],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
args: makeArgs({
|
|
70
|
+
lnd: makeLnd({
|
|
71
|
+
details: 'unknown method MuSig2CreateSession for service signrpc.Signer',
|
|
72
|
+
}),
|
|
73
|
+
}),
|
|
74
|
+
description: 'MuSig2 must be supported',
|
|
75
|
+
error: [501, 'MuSig2BeginSigningSessionNotSupported'],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
args: makeArgs({lnd: makeLnd('err')}),
|
|
79
|
+
description: 'Unexpected errors are passed back',
|
|
80
|
+
error: [503, 'UnexpectedErrorCreatingMuSig2Session', {err: 'err'}],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
args: makeArgs({lnd: makeLnd(null, {})}),
|
|
84
|
+
description: 'A valid response is expected',
|
|
85
|
+
error: [503, 'ExpectedCombinedPublicKeyInMuSig2SessionResponse'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
args: makeArgs({}),
|
|
89
|
+
description: 'A group signing session is started',
|
|
90
|
+
expected: {
|
|
91
|
+
external_key: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
92
|
+
id: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
93
|
+
internal_key: undefined,
|
|
94
|
+
nonce: '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
args: makeArgs({
|
|
99
|
+
public_keys: [Buffer.alloc(32, 1).toString('hex')],
|
|
100
|
+
root_hash: Buffer.alloc(32).toString('hex'),
|
|
101
|
+
}),
|
|
102
|
+
description: 'A group signing session is started with a root hash',
|
|
103
|
+
expected: {
|
|
104
|
+
external_key: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
105
|
+
id: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
106
|
+
internal_key: undefined,
|
|
107
|
+
nonce: '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
args: makeArgs({is_key_spend: true}),
|
|
112
|
+
description: 'A group signing session is started with a key spend',
|
|
113
|
+
expected: {
|
|
114
|
+
external_key: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
115
|
+
id: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
116
|
+
internal_key: undefined,
|
|
117
|
+
nonce: '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
123
|
+
return test(description, async ({end, rejects, strictSame}) => {
|
|
124
|
+
if (!!error) {
|
|
125
|
+
await rejects(beginGroupSigningSession(args), error, 'Got expected err');
|
|
126
|
+
} else {
|
|
127
|
+
const res = await beginGroupSigningSession(args);
|
|
128
|
+
|
|
129
|
+
strictSame(res, expected, 'Got expected result');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return end();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {endGroupSigningSession} = require('./../../../');
|
|
4
|
+
|
|
5
|
+
const makeLnd = ({cleanErr, combineErr, combineRes}) => {
|
|
6
|
+
return {
|
|
7
|
+
signer: {
|
|
8
|
+
muSig2Cleanup: ({}, cbk) => cbk(cleanErr),
|
|
9
|
+
muSig2CombineSig: ({}, cbk) => cbk(combineErr, combineRes),
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const makeArgs = override => {
|
|
15
|
+
const args = {
|
|
16
|
+
id: Buffer.alloc(32).toString('hex'),
|
|
17
|
+
lnd: makeLnd({combineRes: {final_signature: Buffer.alloc(64)}}),
|
|
18
|
+
signatures: [Buffer.alloc(64).toString('hex')],
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
Object.keys(override || {}).forEach(key => args[key] = override[key]);
|
|
22
|
+
|
|
23
|
+
return args;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const tests = [
|
|
27
|
+
{
|
|
28
|
+
args: makeArgs({id: undefined}),
|
|
29
|
+
description: 'A session id is required',
|
|
30
|
+
error: [400, 'ExpectedSessionIdToFinishMuSig2Session'],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
args: makeArgs({lnd: undefined}),
|
|
34
|
+
description: 'An authenticated lnd is required',
|
|
35
|
+
error: [400, 'ExpectedAuthenticatedLndToFinishMuSig2Session'],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
args: makeArgs({signatures: []}),
|
|
39
|
+
description: 'Signatures are required',
|
|
40
|
+
error: [400, 'ExpectedPartialSignaturesToCombineToEndSession'],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
args: makeArgs({lnd: makeLnd({cleanErr: 'err'}), signatures: undefined}),
|
|
44
|
+
description: 'A cleanup error is passed back',
|
|
45
|
+
error: [503, 'UnexpectedErrorCleaningUpMuSig2Session', {err: 'err'}],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
args: makeArgs({lnd: makeLnd({combineErr: 'err'})}),
|
|
49
|
+
description: 'A combine error is passed back',
|
|
50
|
+
error: [503, 'UnexpectedErrorFinishingMuSig2Session', {err: 'err'}],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
args: makeArgs({lnd: makeLnd({combineRes: null})}),
|
|
54
|
+
description: 'A combine response is expected',
|
|
55
|
+
error: [503, 'ExpectedResponseForMuSig2CombineRequest'],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
args: makeArgs({lnd: makeLnd({combineRes: {have_all_signatures: false}})}),
|
|
59
|
+
description: 'A combine success response is expected',
|
|
60
|
+
error: [400, 'ExpectedAllSignaturesProvidedForSession'],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
args: makeArgs({lnd: makeLnd({combineRes: {}})}),
|
|
64
|
+
description: 'A combined signature is expected',
|
|
65
|
+
error: [503, 'ExpectedFinalSignatureInCombineResponse'],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
args: makeArgs({}),
|
|
69
|
+
description: 'A group signing session is ended',
|
|
70
|
+
expected: {
|
|
71
|
+
signature: '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
args: makeArgs({signatures: undefined}),
|
|
76
|
+
description: 'A group signing session is canceled',
|
|
77
|
+
expected: {},
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
82
|
+
return test(description, async ({end, rejects, strictSame}) => {
|
|
83
|
+
if (!!error) {
|
|
84
|
+
await rejects(endGroupSigningSession(args), error, 'Got expected err');
|
|
85
|
+
} else {
|
|
86
|
+
const res = await endGroupSigningSession(args);
|
|
87
|
+
|
|
88
|
+
strictSame(res, expected, 'Got expected result');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return end();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {updateGroupSigningSession} = require('./../../../');
|
|
4
|
+
|
|
5
|
+
const makeLnd = ({noncesErr, noncesRes, signErr, signRes}) => {
|
|
6
|
+
return {
|
|
7
|
+
signer: {
|
|
8
|
+
muSig2RegisterNonces: ({}, cbk) => cbk(noncesErr, noncesRes),
|
|
9
|
+
muSig2Sign: ({}, cbk) => cbk(signErr, signRes),
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const makeArgs = override => {
|
|
15
|
+
const args = {
|
|
16
|
+
hash: Buffer.alloc(32).toString('hex'),
|
|
17
|
+
id: Buffer.alloc(32).toString('hex'),
|
|
18
|
+
lnd: makeLnd({
|
|
19
|
+
noncesRes: {have_all_nonces: true},
|
|
20
|
+
signRes: {local_partial_signature: Buffer.alloc(64)},
|
|
21
|
+
}),
|
|
22
|
+
nonces: [Buffer.alloc(66).toString('hex')],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
Object.keys(override || {}).forEach(key => args[key] = override[key]);
|
|
26
|
+
|
|
27
|
+
return args;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const tests = [
|
|
31
|
+
{
|
|
32
|
+
args: makeArgs({hash: undefined}),
|
|
33
|
+
description: 'A hash to sign is required',
|
|
34
|
+
error: [400, 'ExpectedHashToSignToUpdateMuSig2Session'],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
args: makeArgs({id: undefined}),
|
|
38
|
+
description: 'A signing group id is required',
|
|
39
|
+
error: [400, 'ExpectedSessionIdToUpdateMuSig2Session'],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
args: makeArgs({lnd: undefined}),
|
|
43
|
+
description: 'LND object is required',
|
|
44
|
+
error: [400, 'ExpectedAuthenticatedLndToUpdateMuSig2Session'],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
args: makeArgs({nonces: undefined}),
|
|
48
|
+
description: 'Nonces are required',
|
|
49
|
+
error: [400, 'ExpectedArrayOfNoncesToUpdateMuSig2Session'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
args: makeArgs({lnd: makeLnd({noncesErr: 'err'})}),
|
|
53
|
+
description: 'Update nonces errors are passed back',
|
|
54
|
+
error: [503, 'UnexpectedErrorUpdatingMuSig2Session', {err: 'err'}],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
args: makeArgs({lnd: makeLnd({noncesRes: null})}),
|
|
58
|
+
description: 'An update response is expected',
|
|
59
|
+
error: [503, 'ExpectedResultOfRegisterNoncesRequest'],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
args: makeArgs({lnd: makeLnd({noncesRes: {}})}),
|
|
63
|
+
description: 'A successful update response is expected',
|
|
64
|
+
error: [400, 'ExpectedAllNoncesForRegisterNoncesRequest'],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
args: makeArgs({
|
|
68
|
+
lnd: makeLnd({noncesRes: {have_all_nonces: true}, signErr: 'err'}),
|
|
69
|
+
}),
|
|
70
|
+
description: 'Sign errors are passed back',
|
|
71
|
+
error: [503, 'UnexpectedErrorSigningMuSig2Session', {err: 'err'}],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
args: makeArgs({
|
|
75
|
+
lnd: makeLnd({noncesRes: {have_all_nonces: true}, signRes: null}),
|
|
76
|
+
}),
|
|
77
|
+
description: 'Sign response is expected',
|
|
78
|
+
error: [503, 'ExpectedResultForMuSig2SignRequest'],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
args: makeArgs({
|
|
82
|
+
lnd: makeLnd({noncesRes: {have_all_nonces: true}, signRes: {}}),
|
|
83
|
+
}),
|
|
84
|
+
description: 'A partial signature is expected',
|
|
85
|
+
error: [503, 'ExpectedPartialSignatureForMuSig2SignRequest'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
args: makeArgs({}),
|
|
89
|
+
description: 'A group signing session is updated',
|
|
90
|
+
expected: {
|
|
91
|
+
signature: '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
97
|
+
return test(description, async ({end, rejects, strictSame}) => {
|
|
98
|
+
if (!!error) {
|
|
99
|
+
await rejects(updateGroupSigningSession(args), error, 'Got expected err');
|
|
100
|
+
} else {
|
|
101
|
+
const res = await updateGroupSigningSession(args);
|
|
102
|
+
|
|
103
|
+
strictSame(res, expected, 'Got expected result');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return end();
|
|
107
|
+
});
|
|
108
|
+
});
|