lightning 5.14.0 → 5.15.2
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 +12 -0
- package/README.md +16 -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/info/get_route_to_destination.js +8 -0
- package/lnd_methods/macaroon/methods.json +13 -0
- package/lnd_methods/offchain/get_failed_payments.js +3 -1
- package/lnd_methods/offchain/get_payments.js +3 -1
- package/lnd_methods/offchain/get_pending_payments.js +2 -0
- package/lnd_methods/peers/add_external_socket.d.ts +20 -0
- package/lnd_methods/peers/index.d.ts +4 -0
- package/lnd_methods/peers/remove_external_socket.d.ts +20 -0
- package/lnd_methods/peers/update_alias.d.ts +11 -0
- package/lnd_methods/peers/update_color.d.ts +11 -0
- package/lnd_methods/signer/begin_group_signing_session.d.ts +33 -0
- package/lnd_methods/signer/begin_group_signing_session.js +144 -0
- package/lnd_methods/signer/end_group_signing_session.d.ts +21 -0
- package/lnd_methods/signer/end_group_signing_session.js +102 -0
- package/lnd_methods/signer/index.d.ts +3 -0
- package/lnd_methods/signer/index.js +6 -0
- package/lnd_methods/signer/update_group_signing_session.d.ts +23 -0
- package/lnd_methods/signer/update_group_signing_session.js +110 -0
- package/lnd_responses/index.js +2 -0
- package/lnd_responses/rpc_attempt_htlc_as_attempt.js +39 -5
- package/lnd_responses/rpc_group_session_as_session.js +51 -0
- package/lnd_responses/rpc_payment_as_payment.js +6 -0
- package/package.json +6 -6
- package/test/lnd_methods/info/test_get_route_to_destination.js +15 -0
- package/test/lnd_methods/offchain/test_get_payments.js +2 -0
- 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_attempt_htlc_as_attempt.js +19 -3
- package/test/lnd_responses/test_rpc_group_session_as_session.js +79 -0
- package/test/lnd_responses/test_rpc_payment_as_payment.js +5 -1
- package/test/typescript/add_external_socket.test-d.ts +14 -0
- package/test/typescript/begin_group_signing_session.test-d.ts +60 -0
- package/test/typescript/end_group_signing_session.test-d.ts +32 -0
- package/test/typescript/remove_external_socket.test-d.ts +14 -0
- package/test/typescript/update_alias.test-d.ts +14 -0
- package/test/typescript/update_color.test-d.ts +14 -0
- package/test/typescript/update_group_signing_session.test-d.ts +29 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthenticatedLightningArgs,
|
|
3
|
+
AuthenticatedLightningMethod,
|
|
4
|
+
} from '../../typescript/shared';
|
|
5
|
+
|
|
6
|
+
export type UpdateColorArgs = AuthenticatedLightningArgs<{
|
|
7
|
+
/** Node Color String */
|
|
8
|
+
color: string;
|
|
9
|
+
}>;
|
|
10
|
+
|
|
11
|
+
export const updateColor: AuthenticatedLightningMethod<UpdateColorArgs>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthenticatedLightningArgs,
|
|
3
|
+
AuthenticatedLightningMethod,
|
|
4
|
+
} from '../../typescript/shared';
|
|
5
|
+
|
|
6
|
+
export type BeginGroupSigningSessionArgs = AuthenticatedLightningArgs<{
|
|
7
|
+
/** Key Is BIP 86 Key Spend Key Bool */
|
|
8
|
+
is_key_spend?: boolean;
|
|
9
|
+
/** HD Seed Key Family Number */
|
|
10
|
+
key_family: number;
|
|
11
|
+
/** Key Index Number */
|
|
12
|
+
key_index: number;
|
|
13
|
+
/** External Public Key Hex String */
|
|
14
|
+
public_keys: string[];
|
|
15
|
+
/** Taproot Script Root Hash Hex String */
|
|
16
|
+
root_hash?: string;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
export type BeginGroupSigningSessionResult = {
|
|
20
|
+
/** Final Script or Top Level Public Key Hex String */
|
|
21
|
+
external_key: string;
|
|
22
|
+
/** Session Id Hex String */
|
|
23
|
+
id: string;
|
|
24
|
+
/** Internal Top Level Public Key Hex String */
|
|
25
|
+
internal_key?: string;
|
|
26
|
+
/** Session Compound Nonces Hex String */
|
|
27
|
+
nonce: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const beginGroupSigningSession: AuthenticatedLightningMethod<
|
|
31
|
+
BeginGroupSigningSessionArgs,
|
|
32
|
+
BeginGroupSigningSessionResult
|
|
33
|
+
>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const {returnResult} = require('asyncjs-util');
|
|
3
|
+
|
|
4
|
+
const getPublicKey = require('./../address/get_public_key');
|
|
5
|
+
const {isLnd} = require('./../../lnd_requests');
|
|
6
|
+
const {rpcGroupSessionAsSession} = require('./../../lnd_responses');
|
|
7
|
+
|
|
8
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
9
|
+
const {isArray} = Array;
|
|
10
|
+
const isHash = n => /^[0-9A-F]{64}$/i.test(n);
|
|
11
|
+
const method = 'muSig2CreateSession';
|
|
12
|
+
const type = 'signer';
|
|
13
|
+
const uniq = arr => Array.from(new Set(arr));
|
|
14
|
+
const unsupportedMessage = 'unknown method MuSig2CreateSession for service signrpc.Signer';
|
|
15
|
+
const xOnlyPublicKeyHexLength = 64;
|
|
16
|
+
const xOnlyPublicKey = hexKey => hexKey.slice(2);
|
|
17
|
+
|
|
18
|
+
/** Start a MuSig2 group signing session
|
|
19
|
+
|
|
20
|
+
Requires LND built with `signrpc`, `walletrpc` build tags
|
|
21
|
+
|
|
22
|
+
Requires `address:read`, `signer:generate` permissions
|
|
23
|
+
|
|
24
|
+
This method is not supported in LND 0.14.3 and below
|
|
25
|
+
|
|
26
|
+
{
|
|
27
|
+
lnd: <Authenticated LND API Object>
|
|
28
|
+
[is_key_spend]: <Key Is BIP 86 Key Spend Key Bool>
|
|
29
|
+
key_family: <HD Seed Key Family Number>
|
|
30
|
+
key_index: <Key Index Number>
|
|
31
|
+
public_keys: [<External Public Key Hex String>]
|
|
32
|
+
[root_hash]: <Taproot Script Root Hash Hex String>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@returns via cbk or Promise
|
|
36
|
+
{
|
|
37
|
+
external_key: <Final Script or Top Level Public Key Hex String>
|
|
38
|
+
id: <Session Id Hex String>
|
|
39
|
+
[internal_key]: <Internal Top Level Public Key Hex String>
|
|
40
|
+
nonce: <Session Compound Nonces Hex String>
|
|
41
|
+
}
|
|
42
|
+
*/
|
|
43
|
+
module.exports = (args, cbk) => {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
return asyncAuto({
|
|
46
|
+
// Check arguments
|
|
47
|
+
validate: cbk => {
|
|
48
|
+
if (!isLnd({method, type, lnd: args.lnd})) {
|
|
49
|
+
return cbk([400, 'ExpectedAuthenticatedLndToStartMuSig2Session']);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (args.key_family === undefined) {
|
|
53
|
+
return cbk([400, 'ExpectedKeyFamilyToStartMuSig2Session']);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (args.key_index === undefined) {
|
|
57
|
+
return cbk([400, 'ExpectedKeyIndexToStartMuSig2Session']);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!isArray(args.public_keys)) {
|
|
61
|
+
return cbk([400, 'ExpectedArrayOfPublicKeysForMuSig2SessionStart']);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!args.public_keys.length) {
|
|
65
|
+
return cbk([400, 'ExpectedOtherPublicKeysForMuSig2SessionStart']);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!!args.root_hash && !isHash(args.root_hash)) {
|
|
69
|
+
return cbk([400, 'ExpectedHashWhenSpecifyingMuSig2ScriptRootHash']);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return cbk();
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Get the local public key to pass it to the session along with others
|
|
76
|
+
getKey: ['validate', ({}, cbk) => {
|
|
77
|
+
return getPublicKey({
|
|
78
|
+
family: args.key_family,
|
|
79
|
+
index: args.key_index,
|
|
80
|
+
lnd: args.lnd,
|
|
81
|
+
},
|
|
82
|
+
cbk);
|
|
83
|
+
}],
|
|
84
|
+
|
|
85
|
+
// Put together the Taproot tweak flags for top level signing
|
|
86
|
+
taprootTweak: ['validate', ({}, cbk) => {
|
|
87
|
+
// Spend should include a top level Taproot script commitment proof
|
|
88
|
+
if (!!args.root_hash) {
|
|
89
|
+
return cbk(null, {script_root: hexAsBuffer(args.root_hash)});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Spend is absent a Taproot script, but is a top-level Taproot key
|
|
93
|
+
if (!!args.is_key_spend) {
|
|
94
|
+
return cbk(null, {key_spend_only: true});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return cbk();
|
|
98
|
+
}],
|
|
99
|
+
|
|
100
|
+
// Collect all public keys taking part in the signing session
|
|
101
|
+
publicKeys: ['getKey', ({getKey}, cbk) => {
|
|
102
|
+
// Trim public keys as necessary
|
|
103
|
+
const keys = [getKey.public_key].concat(args.public_keys).map(key => {
|
|
104
|
+
if (key.length === xOnlyPublicKeyHexLength) {
|
|
105
|
+
return key;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return xOnlyPublicKey(key);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return cbk(null, uniq(keys));
|
|
112
|
+
}],
|
|
113
|
+
|
|
114
|
+
// Create the signing session
|
|
115
|
+
create: [
|
|
116
|
+
'publicKeys',
|
|
117
|
+
'taprootTweak',
|
|
118
|
+
({publicKeys, taprootTweak}, cbk) =>
|
|
119
|
+
{
|
|
120
|
+
return args.lnd[type][method]({
|
|
121
|
+
all_signer_pubkeys: publicKeys.map(hexAsBuffer),
|
|
122
|
+
key_loc: {key_family: args.key_family, key_index: args.key_index},
|
|
123
|
+
taproot_tweak: taprootTweak,
|
|
124
|
+
},
|
|
125
|
+
(err, res) => {
|
|
126
|
+
if (!!err && err.details === unsupportedMessage) {
|
|
127
|
+
return cbk([501, 'MuSig2BeginSigningSessionNotSupported']);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!!err) {
|
|
131
|
+
return cbk([503, 'UnexpectedErrorCreatingMuSig2Session', {err}]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
return cbk(null, rpcGroupSessionAsSession(res));
|
|
136
|
+
} catch (err) {
|
|
137
|
+
return cbk([503, err.message]);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}],
|
|
141
|
+
},
|
|
142
|
+
returnResult({reject, resolve, of: 'create'}, cbk));
|
|
143
|
+
});
|
|
144
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthenticatedLightningArgs,
|
|
3
|
+
AuthenticatedLightningMethod,
|
|
4
|
+
} from '../../typescript/shared';
|
|
5
|
+
|
|
6
|
+
export type EndGroupSigningSessionArgs = AuthenticatedLightningArgs<{
|
|
7
|
+
/** Session Id Hex String */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Combine External Partial Signature Hex Strings */
|
|
10
|
+
signatures?: string[];
|
|
11
|
+
}>;
|
|
12
|
+
|
|
13
|
+
export type EndGroupSigningSessionResult = {
|
|
14
|
+
/** Combined Signature Hex String */
|
|
15
|
+
signature?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const endGroupSigningSession: AuthenticatedLightningMethod<
|
|
19
|
+
EndGroupSigningSessionArgs,
|
|
20
|
+
EndGroupSigningSessionResult
|
|
21
|
+
>;
|
|
@@ -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,4 +1,7 @@
|
|
|
1
|
+
export * from './begin_group_signing_session';
|
|
1
2
|
export * from './diffie_hellman_compute_secret';
|
|
3
|
+
export * from './end_group_signing_session';
|
|
2
4
|
export * from './sign_bytes';
|
|
3
5
|
export * from './sign_transaction';
|
|
6
|
+
export * from './update_group_signing_session';
|
|
4
7
|
export * from './verify_bytes_signature';
|
|
@@ -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,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthenticatedLightningArgs,
|
|
3
|
+
AuthenticatedLightningMethod,
|
|
4
|
+
} from '../../typescript/shared';
|
|
5
|
+
|
|
6
|
+
export type UpdateGroupSigningSessionArgs = AuthenticatedLightningArgs<{
|
|
7
|
+
/** Hash to Sign Hex String */
|
|
8
|
+
hash: string;
|
|
9
|
+
/** MuSig2 Session Id Hex String */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Nonce Hex Strings */
|
|
12
|
+
nonces: string[];
|
|
13
|
+
}>;
|
|
14
|
+
|
|
15
|
+
export type UpdateGroupSigningSessionResult = {
|
|
16
|
+
/** Partial Signature Hex String */
|
|
17
|
+
signature: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const updateGroupSigningSession: AuthenticatedLightningMethod<
|
|
21
|
+
UpdateGroupSigningSessionArgs,
|
|
22
|
+
UpdateGroupSigningSessionResult
|
|
23
|
+
>;
|
|
@@ -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,
|
|
@@ -61,7 +61,9 @@ const nsAsMs = ns => Number(BigInt(ns) / BigInt(1e6));
|
|
|
61
61
|
|
|
62
62
|
@returns
|
|
63
63
|
{
|
|
64
|
-
confirmed_at: <Payment Succeeded At ISO 8601 Date String>
|
|
64
|
+
[confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
|
|
65
|
+
created_at: <Attempt Was Started At ISO 8601 Date String>
|
|
66
|
+
[failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
|
|
65
67
|
is_confirmed: <Payment Attempt Succeeded Bool>
|
|
66
68
|
is_failed: <Payment Attempt Failed Bool>
|
|
67
69
|
is_pending: <Payment Attempt is Waiting For Resolution Bool>
|
|
@@ -91,6 +93,10 @@ module.exports = attempt => {
|
|
|
91
93
|
throw new Error('ExpectedRpcAttemptDetailsToDeriveAttempt');
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
if (!attempt.attempt_time_ns) {
|
|
97
|
+
throw new Error('ExpectedRpcAttemptStartTimeNs');
|
|
98
|
+
}
|
|
99
|
+
|
|
94
100
|
if (!attempt.resolve_time_ns) {
|
|
95
101
|
throw new Error('ExpectedRpcAttemptResolveTimeNs');
|
|
96
102
|
}
|
|
@@ -103,11 +109,39 @@ module.exports = attempt => {
|
|
|
103
109
|
throw new Error('ExpectedAttemptStatusInRpcAttemptDetails');
|
|
104
110
|
}
|
|
105
111
|
|
|
112
|
+
const route = rpcRouteAsRoute(attempt.route);
|
|
113
|
+
|
|
114
|
+
if (attempt.status === attemptStates.confirmed) {
|
|
115
|
+
return {
|
|
116
|
+
route,
|
|
117
|
+
confirmed_at: new Date(nsAsMs(attempt.resolve_time_ns)).toISOString(),
|
|
118
|
+
created_at: new Date(nsAsMs(attempt.attempt_time_ns)).toISOString(),
|
|
119
|
+
failed_at: undefined,
|
|
120
|
+
is_confirmed: true,
|
|
121
|
+
is_failed: false,
|
|
122
|
+
is_pending: false,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (attempt.status === attemptStates.failed) {
|
|
127
|
+
return {
|
|
128
|
+
route,
|
|
129
|
+
confirmed_at: undefined,
|
|
130
|
+
created_at: new Date(nsAsMs(attempt.attempt_time_ns)).toISOString(),
|
|
131
|
+
failed_at: new Date(nsAsMs(attempt.resolve_time_ns)).toISOString(),
|
|
132
|
+
is_confirmed: false,
|
|
133
|
+
is_failed: true,
|
|
134
|
+
is_pending: false,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
106
138
|
return {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
139
|
+
route,
|
|
140
|
+
confirmed_at: undefined,
|
|
141
|
+
created_at: new Date(nsAsMs(attempt.attempt_time_ns)).toISOString(),
|
|
142
|
+
failed_at: undefined,
|
|
143
|
+
is_confirmed: false,
|
|
144
|
+
is_failed: false,
|
|
110
145
|
is_pending: attempt.status === attemptStates.pending,
|
|
111
|
-
route: rpcRouteAsRoute(attempt.route),
|
|
112
146
|
};
|
|
113
147
|
};
|
|
@@ -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
|
+
};
|
|
@@ -81,6 +81,9 @@ const routePublicKeys = route => route.hops.map(n => n.public_key);
|
|
|
81
81
|
@returns
|
|
82
82
|
{
|
|
83
83
|
attempts: [{
|
|
84
|
+
[confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
|
|
85
|
+
created_at: <Attempt Was Started At ISO 8601 Date String>
|
|
86
|
+
[failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
|
|
84
87
|
[failure]: {
|
|
85
88
|
code: <Error Type Code Number>
|
|
86
89
|
[details]: {
|
|
@@ -108,6 +111,9 @@ const routePublicKeys = route => route.hops.map(n => n.public_key);
|
|
|
108
111
|
}
|
|
109
112
|
message: <Error Message String>
|
|
110
113
|
}
|
|
114
|
+
[confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
|
|
115
|
+
created_at: <Attempt Was Started At ISO 8601 Date String>
|
|
116
|
+
[failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
|
|
111
117
|
is_confirmed: <Payment Attempt Succeeded Bool>
|
|
112
118
|
is_failed: <Payment Attempt Failed Bool>
|
|
113
119
|
is_pending: <Payment Attempt is Waiting For Resolution Bool>
|
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.32",
|
|
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.2"
|
|
63
63
|
}
|