@bitgo-beta/sdk-coin-flrp 1.0.1-beta.28 → 1.0.1-beta.281
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/dist/src/flrp.d.ts +6 -75
- package/dist/src/flrp.d.ts.map +1 -1
- package/dist/src/flrp.js +13 -298
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -2
- package/dist/src/lib/ExportInCTxBuilder.d.ts +50 -0
- package/dist/src/lib/ExportInCTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/ExportInCTxBuilder.js +187 -0
- package/dist/src/lib/ExportInPTxBuilder.d.ts +47 -0
- package/dist/src/lib/ExportInPTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/ExportInPTxBuilder.js +330 -0
- package/dist/src/lib/ImportInCTxBuilder.d.ts +47 -0
- package/dist/src/lib/ImportInCTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/ImportInCTxBuilder.js +213 -0
- package/dist/src/lib/ImportInPTxBuilder.d.ts +33 -0
- package/dist/src/lib/ImportInPTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/ImportInPTxBuilder.js +197 -0
- package/dist/src/lib/atomicInCTransactionBuilder.d.ts +18 -16
- package/dist/src/lib/atomicInCTransactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/atomicInCTransactionBuilder.js +38 -36
- package/dist/src/lib/atomicTransactionBuilder.d.ts +42 -76
- package/dist/src/lib/atomicTransactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/atomicTransactionBuilder.js +141 -218
- package/dist/src/lib/iface.d.ts +50 -51
- package/dist/src/lib/iface.d.ts.map +1 -1
- package/dist/src/lib/iface.js +22 -10
- package/dist/src/lib/index.d.ts +4 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +10 -2
- package/dist/src/lib/keyPair.d.ts +5 -5
- package/dist/src/lib/keyPair.d.ts.map +1 -1
- package/dist/src/lib/keyPair.js +17 -9
- package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts +46 -0
- package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/permissionlessValidatorTxBuilder.js +134 -0
- package/dist/src/lib/transaction.d.ts +8 -73
- package/dist/src/lib/transaction.d.ts.map +1 -1
- package/dist/src/lib/transaction.js +139 -207
- package/dist/src/lib/transactionBuilder.d.ts +107 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +210 -0
- package/dist/src/lib/transactionBuilderFactory.d.ts +27 -30
- package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilderFactory.js +84 -75
- package/dist/src/lib/utils.d.ts +98 -147
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +346 -319
- package/dist/test/resources/account.d.ts +49 -0
- package/dist/test/resources/account.d.ts.map +1 -0
- package/dist/test/resources/account.js +52 -0
- package/dist/test/resources/transactionData/exportInC.d.ts +20 -0
- package/dist/test/resources/transactionData/exportInC.d.ts.map +1 -0
- package/dist/test/resources/transactionData/exportInC.js +34 -0
- package/dist/test/resources/transactionData/exportInP.d.ts +69 -0
- package/dist/test/resources/transactionData/exportInP.d.ts.map +1 -0
- package/dist/test/resources/transactionData/exportInP.js +140 -0
- package/dist/test/resources/transactionData/importInP.d.ts +35 -0
- package/dist/test/resources/transactionData/importInP.d.ts.map +1 -0
- package/dist/test/resources/transactionData/importInP.js +58 -0
- package/dist/test/unit/lib/exportInCTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/exportInCTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/exportInCTxBuilder.js +166 -0
- package/dist/test/unit/lib/exportInPTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/exportInPTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/exportInPTxBuilder.js +121 -0
- package/dist/test/unit/lib/importInPTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/importInPTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/importInPTxBuilder.js +73 -0
- package/dist/test/unit/lib/keyPair.d.ts +2 -0
- package/dist/test/unit/lib/keyPair.d.ts.map +1 -0
- package/dist/test/unit/lib/keyPair.js +158 -0
- package/dist/test/unit/lib/signFlowTestSuit.d.ts +20 -0
- package/dist/test/unit/lib/signFlowTestSuit.d.ts.map +1 -0
- package/dist/test/unit/lib/signFlowTestSuit.js +93 -0
- package/dist/test/unit/lib/utils.js +29 -223
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -13
- package/.eslintignore +0 -5
- package/.eslintrc.json +0 -7
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -0
- package/dist/src/iface.d.ts +0 -25
- package/dist/src/iface.d.ts.map +0 -1
- package/dist/src/iface.js +0 -3
- package/dist/src/lib/constants.d.ts +0 -11
- package/dist/src/lib/constants.d.ts.map +0 -1
- package/dist/src/lib/constants.js +0 -17
- package/dist/src/lib/errors.d.ts +0 -8
- package/dist/src/lib/errors.d.ts.map +0 -1
- package/dist/src/lib/errors.js +0 -19
- package/dist/src/lib/exportInCTxBuilder.d.ts +0 -77
- package/dist/src/lib/exportInCTxBuilder.d.ts.map +0 -1
- package/dist/src/lib/exportInCTxBuilder.js +0 -170
- package/dist/src/lib/exportInPTxBuilder.d.ts +0 -30
- package/dist/src/lib/exportInPTxBuilder.d.ts.map +0 -1
- package/dist/src/lib/exportInPTxBuilder.js +0 -56
- package/dist/test/unit/flrp.d.ts +0 -2
- package/dist/test/unit/flrp.d.ts.map +0 -1
- package/dist/test/unit/flrp.js +0 -118
- package/dist/test/unit/lib/atomicTransactionBuilder.d.ts +0 -2
- package/dist/test/unit/lib/atomicTransactionBuilder.d.ts.map +0 -1
- package/dist/test/unit/lib/atomicTransactionBuilder.js +0 -222
- package/dist/test/unit/lib/exportTxBuilder.d.ts +0 -2
- package/dist/test/unit/lib/exportTxBuilder.d.ts.map +0 -1
- package/dist/test/unit/lib/exportTxBuilder.js +0 -45
- package/dist/test/unit/lib/transaction.d.ts +0 -2
- package/dist/test/unit/lib/transaction.d.ts.map +0 -1
- package/dist/test/unit/lib/transaction.js +0 -460
- package/dist/test/unit/smoke.d.ts +0 -2
- package/dist/test/unit/smoke.d.ts.map +0 -1
- package/dist/test/unit/smoke.js +0 -23
package/dist/src/lib/utils.js
CHANGED
|
@@ -1,27 +1,74 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Utils = void 0;
|
|
7
|
+
const flarejs_1 = require("@flarenetwork/flarejs");
|
|
4
8
|
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
|
-
const
|
|
9
|
+
const buffer_1 = require("buffer");
|
|
6
10
|
const crypto_1 = require("crypto");
|
|
7
|
-
const
|
|
11
|
+
const secp256k1_1 = require("@bitgo-beta/secp256k1");
|
|
12
|
+
const iface_1 = require("./iface");
|
|
13
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
14
|
+
const bech32_1 = require("bech32");
|
|
8
15
|
class Utils {
|
|
9
16
|
constructor() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Helper method to convert address components to string
|
|
19
|
+
*/
|
|
20
|
+
this.addressToString = (hrp, prefix, address) => {
|
|
21
|
+
// Convert the address bytes to 5-bit words for bech32 encoding
|
|
22
|
+
const words = bech32_1.bech32.toWords(address);
|
|
23
|
+
// Create the full bech32 address with format: P-{hrp}1{bech32_encoded_address}
|
|
24
|
+
return `${prefix}-${bech32_1.bech32.encode(hrp, words)}`;
|
|
25
|
+
};
|
|
26
|
+
// In utils.ts, add this method to the Utils class:
|
|
27
|
+
/**
|
|
28
|
+
* Parse an address string into a Buffer
|
|
29
|
+
* @param address - The address to parse
|
|
30
|
+
* @returns Buffer containing the parsed address
|
|
31
|
+
*/
|
|
32
|
+
//TODO: need check and validate this method
|
|
33
|
+
this.parseAddress = (address) => {
|
|
34
|
+
return this.stringToAddress(address);
|
|
35
|
+
};
|
|
36
|
+
this.stringToAddress = (address, hrp) => {
|
|
37
|
+
// Handle hex addresses
|
|
38
|
+
if (address.startsWith('0x')) {
|
|
39
|
+
return buffer_1.Buffer.from(address.slice(2), 'hex');
|
|
40
|
+
}
|
|
41
|
+
// Handle raw hex without 0x prefix
|
|
42
|
+
if (/^[0-9a-fA-F]{40}$/.test(address)) {
|
|
43
|
+
return buffer_1.Buffer.from(address, 'hex');
|
|
44
|
+
}
|
|
45
|
+
// Handle Bech32 addresses
|
|
46
|
+
const parts = address.trim().split('-');
|
|
47
|
+
if (parts.length < 2) {
|
|
48
|
+
throw new Error('Error - Valid address should include -');
|
|
49
|
+
}
|
|
50
|
+
const split = parts[1].lastIndexOf('1');
|
|
51
|
+
if (split < 0) {
|
|
52
|
+
throw new Error('Error - Valid bech32 address must include separator (1)');
|
|
53
|
+
}
|
|
54
|
+
const humanReadablePart = parts[1].slice(0, split);
|
|
55
|
+
if (humanReadablePart !== 'flare' && humanReadablePart !== 'costwo') {
|
|
56
|
+
throw new Error('Error - Invalid HRP');
|
|
57
|
+
}
|
|
58
|
+
return buffer_1.Buffer.from(bech32_1.bech32.fromWords(bech32_1.bech32.decode(parts[1]).words));
|
|
13
59
|
};
|
|
14
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if addresses in wallet match UTXO output addresses
|
|
63
|
+
*/
|
|
15
64
|
includeIn(walletAddresses, otxoOutputAddresses) {
|
|
16
65
|
return walletAddresses.map((a) => otxoOutputAddresses.includes(a)).reduce((a, b) => a && b, true);
|
|
17
66
|
}
|
|
18
67
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @
|
|
22
|
-
* @returns {boolean} - the validation result
|
|
68
|
+
* Validates a Flare address or array of addresses
|
|
69
|
+
* @param {string | string[]} address - address(es) to validate
|
|
70
|
+
* @returns {boolean} - validation result
|
|
23
71
|
*/
|
|
24
|
-
/** @inheritdoc */
|
|
25
72
|
isValidAddress(address) {
|
|
26
73
|
const addressArr = Array.isArray(address) ? address : address.split('~');
|
|
27
74
|
for (const address of addressArr) {
|
|
@@ -31,66 +78,57 @@ class Utils {
|
|
|
31
78
|
}
|
|
32
79
|
return true;
|
|
33
80
|
}
|
|
81
|
+
// Regex patterns
|
|
82
|
+
// export const ADDRESS_REGEX = /^(^P||NodeID)-[a-zA-Z0-9]+$/;
|
|
83
|
+
// export const HEX_REGEX = /^(0x){0,1}([0-9a-f])+$/i;
|
|
34
84
|
isValidAddressRegex(address) {
|
|
35
|
-
return
|
|
85
|
+
return /^(^P||NodeID)-[a-zA-Z0-9]+$/.test(address);
|
|
36
86
|
}
|
|
37
87
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* @
|
|
41
|
-
* @returns {boolean} - the validation result
|
|
88
|
+
* Validates a block ID
|
|
89
|
+
* @param {string} hash - block ID to validate
|
|
90
|
+
* @returns {boolean} - validation result
|
|
42
91
|
*/
|
|
43
|
-
/** @inheritdoc */
|
|
44
92
|
isValidBlockId(hash) {
|
|
45
|
-
// FlareJS equivalent - check if it's a valid CB58 hash with correct length
|
|
46
93
|
try {
|
|
47
|
-
const decoded = Buffer.from(hash);
|
|
48
|
-
return decoded.length ===
|
|
94
|
+
const decoded = buffer_1.Buffer.from(hash, 'hex');
|
|
95
|
+
return decoded.length === 32;
|
|
49
96
|
}
|
|
50
97
|
catch {
|
|
51
98
|
return false;
|
|
52
99
|
}
|
|
53
100
|
}
|
|
54
101
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* @param {string} pub - the public key to be validated
|
|
59
|
-
* @returns {boolean} - the validation result
|
|
102
|
+
* Validates a public key
|
|
103
|
+
* @param {string} pub - public key to validate
|
|
104
|
+
* @returns {boolean} - validation result
|
|
60
105
|
*/
|
|
61
106
|
isValidPublicKey(pub) {
|
|
62
107
|
if ((0, sdk_core_1.isValidXpub)(pub))
|
|
63
108
|
return true;
|
|
64
109
|
let pubBuf;
|
|
65
|
-
if (pub.length ===
|
|
110
|
+
if (pub.length === 50) {
|
|
66
111
|
try {
|
|
67
|
-
|
|
68
|
-
pubBuf = Buffer.from(pub, 'hex'); // Temporary placeholder
|
|
112
|
+
pubBuf = buffer_1.Buffer.from(pub, 'hex');
|
|
69
113
|
}
|
|
70
114
|
catch {
|
|
71
115
|
return false;
|
|
72
116
|
}
|
|
73
117
|
}
|
|
74
118
|
else {
|
|
75
|
-
if (pub.length !==
|
|
119
|
+
if (pub.length !== 66 && pub.length !== 130)
|
|
76
120
|
return false;
|
|
77
|
-
}
|
|
78
121
|
const firstByte = pub.slice(0, 2);
|
|
79
|
-
|
|
80
|
-
if (pub.length === constants_1.UNCOMPRESSED_PUBLIC_KEY_LENGTH && firstByte !== '04') {
|
|
122
|
+
if (pub.length === 130 && firstByte !== '04')
|
|
81
123
|
return false;
|
|
82
|
-
|
|
83
|
-
// compressed public key
|
|
84
|
-
if (pub.length === constants_1.COMPRESSED_PUBLIC_KEY_LENGTH && firstByte !== '02' && firstByte !== '03') {
|
|
124
|
+
if (pub.length === 66 && firstByte !== '02' && firstByte !== '03')
|
|
85
125
|
return false;
|
|
86
|
-
}
|
|
87
126
|
if (!this.allHexChars(pub))
|
|
88
127
|
return false;
|
|
89
|
-
pubBuf = Buffer.from(pub, 'hex');
|
|
128
|
+
pubBuf = buffer_1.Buffer.from(pub, 'hex');
|
|
90
129
|
}
|
|
91
|
-
// validate the public key using BitGo secp256k1
|
|
92
130
|
try {
|
|
93
|
-
secp256k1_1.ecc.isPoint(pubBuf);
|
|
131
|
+
secp256k1_1.ecc.isPoint(pubBuf);
|
|
94
132
|
return true;
|
|
95
133
|
}
|
|
96
134
|
catch (e) {
|
|
@@ -98,269 +136,131 @@ class Utils {
|
|
|
98
136
|
}
|
|
99
137
|
}
|
|
100
138
|
/**
|
|
101
|
-
*
|
|
102
|
-
* private key
|
|
103
|
-
*
|
|
104
|
-
* The protocol key format is described in the @stacks/transactions npm package, in the
|
|
105
|
-
* createStacksPrivateKey function:
|
|
106
|
-
* https://github.com/blockstack/stacks.js/blob/master/packages/transactions/src/keys.ts#L125
|
|
107
|
-
*
|
|
108
|
-
* @param {string} prv - the private key (or extended private key) to be validated
|
|
109
|
-
* @returns {boolean} - the validation result
|
|
139
|
+
* Validates a private key
|
|
140
|
+
* @param {string} prv - private key to validate
|
|
141
|
+
* @returns {boolean} - validation result
|
|
110
142
|
*/
|
|
111
143
|
isValidPrivateKey(prv) {
|
|
112
144
|
if ((0, sdk_core_1.isValidXprv)(prv))
|
|
113
145
|
return true;
|
|
114
|
-
if (prv.length !==
|
|
146
|
+
if (prv.length !== 64 && prv.length !== 66)
|
|
115
147
|
return false;
|
|
116
|
-
|
|
117
|
-
if (prv.length === constants_1.SUFFIXED_PRIVATE_KEY_LENGTH &&
|
|
118
|
-
prv.slice(constants_1.RAW_PRIVATE_KEY_LENGTH) !== constants_1.PRIVATE_KEY_COMPRESSED_SUFFIX) {
|
|
148
|
+
if (prv.length === 66 && prv.slice(64) !== '01')
|
|
119
149
|
return false;
|
|
120
|
-
}
|
|
121
150
|
return this.allHexChars(prv);
|
|
122
151
|
}
|
|
123
152
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* @param {string} maybe - the string to be validated
|
|
127
|
-
* @returns {boolean} - the validation result
|
|
153
|
+
* Checks if a string contains only hex characters
|
|
128
154
|
*/
|
|
129
|
-
allHexChars(
|
|
130
|
-
return
|
|
155
|
+
allHexChars(str) {
|
|
156
|
+
return /^(0x){0,1}([0-9a-f])+$/i.test(str);
|
|
131
157
|
}
|
|
132
158
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* @param {string} address - the Ethereum address to validate
|
|
137
|
-
* @returns {boolean} - true if valid Ethereum address format
|
|
159
|
+
* Creates a signature using the Flare network parameters
|
|
160
|
+
* Returns a 65-byte signature (64 bytes signature + 1 byte recovery parameter)
|
|
138
161
|
*/
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
162
|
+
createSignature(network, message, prv) {
|
|
163
|
+
const messageHash = this.sha256(message);
|
|
164
|
+
const signature = secp256k1_1.ecc.sign(messageHash, prv);
|
|
165
|
+
// Get the public key from the private key for recovery parameter determination
|
|
166
|
+
const publicKey = secp256k1_1.ecc.pointFromScalar(prv, true);
|
|
167
|
+
if (!publicKey) {
|
|
168
|
+
throw new Error('Failed to derive public key from private key');
|
|
142
169
|
}
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
*
|
|
151
|
-
* @param {T} obj - the source object
|
|
152
|
-
* @param {K[]} keys - array of property keys to pick
|
|
153
|
-
* @returns {Pick<T, K>} - new object with only the specified properties
|
|
154
|
-
*/
|
|
155
|
-
pick(obj, keys) {
|
|
156
|
-
const result = {};
|
|
157
|
-
for (const key of keys) {
|
|
158
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
159
|
-
result[key] = obj[key];
|
|
170
|
+
// Try recovery with param 0 and 1 to find the correct one
|
|
171
|
+
let recoveryParam = 0;
|
|
172
|
+
for (let i = 0; i <= 1; i++) {
|
|
173
|
+
const recovered = secp256k1_1.ecc.recoverPublicKey(messageHash, signature, i, true);
|
|
174
|
+
if (recovered && buffer_1.Buffer.from(recovered).equals(buffer_1.Buffer.from(publicKey))) {
|
|
175
|
+
recoveryParam = i;
|
|
176
|
+
break;
|
|
160
177
|
}
|
|
161
178
|
}
|
|
162
|
-
|
|
179
|
+
// Append recovery parameter to create 65-byte signature
|
|
180
|
+
const sigWithRecovery = buffer_1.Buffer.alloc(65);
|
|
181
|
+
buffer_1.Buffer.from(signature).copy(sigWithRecovery, 0);
|
|
182
|
+
sigWithRecovery[64] = recoveryParam;
|
|
183
|
+
return sigWithRecovery;
|
|
163
184
|
}
|
|
164
185
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* @param {unknown} a - first value to compare
|
|
168
|
-
* @param {unknown} b - second value to compare
|
|
169
|
-
* @returns {boolean} - true if values are deeply equal
|
|
186
|
+
* Verifies a signature
|
|
170
187
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
188
|
+
verifySignature(network, message, signature, publicKey) {
|
|
189
|
+
try {
|
|
190
|
+
const messageHash = this.sha256(message);
|
|
191
|
+
return secp256k1_1.ecc.verify(signature, messageHash, publicKey);
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
177
194
|
return false;
|
|
178
|
-
if (typeof a === 'object') {
|
|
179
|
-
if (Array.isArray(a) !== Array.isArray(b))
|
|
180
|
-
return false;
|
|
181
|
-
if (Array.isArray(a)) {
|
|
182
|
-
const arrB = b;
|
|
183
|
-
if (a.length !== arrB.length)
|
|
184
|
-
return false;
|
|
185
|
-
for (let i = 0; i < a.length; i++) {
|
|
186
|
-
if (!this.isEqual(a[i], arrB[i]))
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
const objA = a;
|
|
192
|
-
const objB = b;
|
|
193
|
-
const keysA = Object.keys(objA);
|
|
194
|
-
const keysB = Object.keys(objB);
|
|
195
|
-
if (keysA.length !== keysB.length)
|
|
196
|
-
return false;
|
|
197
|
-
for (const key of keysA) {
|
|
198
|
-
if (!keysB.includes(key))
|
|
199
|
-
return false;
|
|
200
|
-
if (!this.isEqual(objA[key], objB[key]))
|
|
201
|
-
return false;
|
|
202
|
-
}
|
|
203
|
-
return true;
|
|
204
195
|
}
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
/** @inheritdoc */
|
|
208
|
-
isValidSignature(signature) {
|
|
209
|
-
throw new sdk_core_1.NotImplementedError('isValidSignature not implemented');
|
|
210
|
-
}
|
|
211
|
-
/** @inheritdoc */
|
|
212
|
-
isValidTransactionId(txId) {
|
|
213
|
-
throw new sdk_core_1.NotImplementedError('isValidTransactionId not implemented');
|
|
214
196
|
}
|
|
215
197
|
/**
|
|
216
|
-
*
|
|
217
|
-
* @param network
|
|
218
|
-
* @param message
|
|
219
|
-
* @param prv
|
|
220
|
-
* @return signature
|
|
198
|
+
* Creates a new signature object
|
|
221
199
|
*/
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const signature = secp256k1_1.ecc.sign(message, prv);
|
|
226
|
-
return Buffer.from(signature);
|
|
227
|
-
}
|
|
228
|
-
catch (error) {
|
|
229
|
-
throw new Error(`Failed to create signature: ${error}`);
|
|
230
|
-
}
|
|
200
|
+
createNewSig(sigHex) {
|
|
201
|
+
const buffer = buffer_1.Buffer.from(sigHex.padStart(130, '0'), 'hex');
|
|
202
|
+
return new flarejs_1.Signature(buffer);
|
|
231
203
|
}
|
|
232
204
|
/**
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* @param
|
|
237
|
-
* @param publicKey - public key instead of private key for verification
|
|
238
|
-
* @return true if it's verify successful
|
|
205
|
+
* Creates an empty signature with embedded address for signature slot identification.
|
|
206
|
+
* The address is embedded at position 90 (after the first 45 zero bytes).
|
|
207
|
+
* This allows the signing logic to determine which slot belongs to which address.
|
|
208
|
+
* @param addressHex The 20-byte address in hex format (40 chars, without 0x prefix)
|
|
239
209
|
*/
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
210
|
+
createEmptySigWithAddress(addressHex) {
|
|
211
|
+
// First 45 bytes (90 hex chars) are zeros, followed by 20-byte address (40 hex chars)
|
|
212
|
+
const cleanAddr = this.removeHexPrefix(addressHex).toLowerCase();
|
|
213
|
+
const sigHex = '0'.repeat(90) + cleanAddr.padStart(40, '0');
|
|
214
|
+
const buffer = buffer_1.Buffer.from(sigHex, 'hex');
|
|
215
|
+
return new flarejs_1.Signature(buffer);
|
|
247
216
|
}
|
|
248
217
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
* @param message
|
|
252
|
-
* @param signature
|
|
253
|
-
* @return recovered public key
|
|
218
|
+
* Extracts the embedded address from an empty signature.
|
|
219
|
+
* Returns the address hex string (40 chars) or empty string if not found.
|
|
254
220
|
*/
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
catch (error) {
|
|
262
|
-
throw new Error(`Failed to recover signature: ${error}`);
|
|
221
|
+
getAddressFromEmptySig(sig) {
|
|
222
|
+
const cleanSig = this.removeHexPrefix(sig);
|
|
223
|
+
if (cleanSig.length >= 130) {
|
|
224
|
+
// Address is at position 90-130 (last 40 hex chars = 20 bytes)
|
|
225
|
+
return cleanSig.substring(90, 130).toLowerCase();
|
|
263
226
|
}
|
|
227
|
+
return '';
|
|
264
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Computes SHA256 hash
|
|
231
|
+
*/
|
|
265
232
|
sha256(buf) {
|
|
266
233
|
return (0, crypto_1.createHash)('sha256').update(buf).digest();
|
|
267
234
|
}
|
|
268
235
|
/**
|
|
269
|
-
*
|
|
270
|
-
* It's to reuse in TransactionBuilder and TransactionBuilderFactory
|
|
271
|
-
*
|
|
272
|
-
* @param rawTransaction Transaction as hex string
|
|
236
|
+
* Validates raw transaction format
|
|
273
237
|
*/
|
|
274
238
|
validateRawTransaction(rawTransaction) {
|
|
275
239
|
if (!rawTransaction) {
|
|
276
240
|
throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
|
|
277
241
|
}
|
|
278
|
-
if (!
|
|
242
|
+
if (!this.allHexChars(rawTransaction)) {
|
|
279
243
|
throw new sdk_core_1.ParseTransactionError('Raw transaction is not hex string');
|
|
280
244
|
}
|
|
281
245
|
}
|
|
282
246
|
/**
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
* @param {DeprecatedTx} tx
|
|
286
|
-
* @param {string} blockchainId
|
|
287
|
-
* @returns true if tx is for blockchainId
|
|
288
|
-
*/
|
|
289
|
-
isTransactionOf(tx, blockchainId) {
|
|
290
|
-
// FlareJS equivalent - this would need proper CB58 encoding implementation
|
|
291
|
-
try {
|
|
292
|
-
const txRecord = tx;
|
|
293
|
-
const unsignedTx = txRecord.getUnsignedTx();
|
|
294
|
-
const transaction = unsignedTx.getTransaction();
|
|
295
|
-
const txBlockchainId = transaction.getBlockchainID();
|
|
296
|
-
return Buffer.from(txBlockchainId).toString('hex') === blockchainId;
|
|
297
|
-
}
|
|
298
|
-
catch (error) {
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Check if Output is from PVM.
|
|
304
|
-
* Output could be EVM or PVM output.
|
|
305
|
-
* @param {DeprecatedOutput} output
|
|
306
|
-
* @returns {boolean} output has transferable output structure
|
|
307
|
-
*/
|
|
308
|
-
deprecatedIsTransferableOutput(output) {
|
|
309
|
-
return 'getOutput' in output;
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Check if Output is from PVM.
|
|
313
|
-
* Output could be EVM or PVM output.
|
|
314
|
-
* @param {Output} output
|
|
315
|
-
* @returns {boolean} output is TransferableOutput
|
|
247
|
+
* Checks if output is TransferableOutput type
|
|
316
248
|
*/
|
|
317
249
|
isTransferableOutput(output) {
|
|
318
|
-
return
|
|
250
|
+
return output?._type === flarejs_1.TypeSymbols.TransferableOutput;
|
|
319
251
|
}
|
|
320
252
|
/**
|
|
321
|
-
*
|
|
322
|
-
* @param network required to stringify addresses
|
|
323
|
-
* @return mapper function
|
|
324
|
-
*/
|
|
325
|
-
deprecatedMapOutputToEntry(network) {
|
|
326
|
-
return (output) => {
|
|
327
|
-
if (this.deprecatedIsTransferableOutput(output)) {
|
|
328
|
-
// Simplified implementation for FlareJS
|
|
329
|
-
try {
|
|
330
|
-
const transferableOutput = output;
|
|
331
|
-
const amount = transferableOutput.amount();
|
|
332
|
-
// Simplified address handling - would need proper FlareJS address utilities
|
|
333
|
-
const address = 'flare-address-placeholder'; // TODO: implement proper address conversion
|
|
334
|
-
return {
|
|
335
|
-
value: amount.toString(),
|
|
336
|
-
address,
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
catch (error) {
|
|
340
|
-
throw new Error(`Failed to map output: ${error}`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
// Handle EVM output case - simplified
|
|
345
|
-
return {
|
|
346
|
-
value: '0', // TODO: implement proper amount extraction
|
|
347
|
-
address: '0x0000000000000000000000000000000000000000', // TODO: implement proper address extraction
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Return a mapper function to that network address representation.
|
|
354
|
-
* @param network required to stringify addresses
|
|
355
|
-
* @return mapper function
|
|
253
|
+
* Maps outputs to entry format
|
|
356
254
|
*/
|
|
357
255
|
mapOutputToEntry(network) {
|
|
358
256
|
return (output) => {
|
|
359
257
|
if (this.isTransferableOutput(output)) {
|
|
360
|
-
const
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
258
|
+
const outputAmount = output.amount();
|
|
259
|
+
const address = output.output
|
|
260
|
+
.getOwners()
|
|
261
|
+
.map((a) => this.addressToString(network.hrp, network.alias, buffer_1.Buffer.from(a)))
|
|
262
|
+
.sort()
|
|
263
|
+
.join(iface_1.ADDRESS_SEPARATOR);
|
|
364
264
|
return {
|
|
365
265
|
value: outputAmount.toString(),
|
|
366
266
|
address,
|
|
@@ -372,116 +272,243 @@ class Utils {
|
|
|
372
272
|
};
|
|
373
273
|
}
|
|
374
274
|
/**
|
|
375
|
-
*
|
|
376
|
-
* @param hex string
|
|
377
|
-
* @returns hex without 0x
|
|
275
|
+
* Removes 0x prefix from hex string
|
|
378
276
|
*/
|
|
379
277
|
removeHexPrefix(hex) {
|
|
380
|
-
|
|
381
|
-
return hex.substring(2);
|
|
382
|
-
}
|
|
383
|
-
return hex;
|
|
278
|
+
return hex.startsWith('0x') ? hex.substring(2) : hex;
|
|
384
279
|
}
|
|
385
280
|
/**
|
|
386
|
-
*
|
|
387
|
-
* @param {string} outputidx number
|
|
388
|
-
* @return {Buffer} buffer of size 4 with that number value
|
|
281
|
+
* Converts output index to buffer
|
|
389
282
|
*/
|
|
390
283
|
outputidxNumberToBuffer(outputidx) {
|
|
391
|
-
return Buffer.from(Number(outputidx).toString(16).padStart(
|
|
284
|
+
return buffer_1.Buffer.from(Number(outputidx).toString(16).padStart(8, '0'), 'hex');
|
|
392
285
|
}
|
|
393
286
|
/**
|
|
394
|
-
*
|
|
395
|
-
* @param {Buffer} outputidx
|
|
396
|
-
* @return {string} outputidx number
|
|
287
|
+
* Converts output index buffer to number string
|
|
397
288
|
*/
|
|
398
289
|
outputidxBufferToNumber(outputidx) {
|
|
399
290
|
return parseInt(outputidx.toString('hex'), 16).toString();
|
|
400
291
|
}
|
|
292
|
+
// Required by BaseUtils interface but not implemented
|
|
293
|
+
isValidSignature(signature) {
|
|
294
|
+
throw new sdk_core_1.NotImplementedError('isValidSignature not implemented');
|
|
295
|
+
}
|
|
296
|
+
isValidTransactionId(txId) {
|
|
297
|
+
throw new sdk_core_1.NotImplementedError('isValidTransactionId not implemented');
|
|
298
|
+
}
|
|
401
299
|
/**
|
|
402
|
-
*
|
|
403
|
-
* @param {string} data - CB58 encoded string
|
|
404
|
-
* @returns {Buffer} decoded buffer
|
|
300
|
+
* Decodes a base58 string with checksum to a Buffer
|
|
405
301
|
*/
|
|
406
|
-
cb58Decode(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return Buffer.from(data, 'hex');
|
|
411
|
-
}
|
|
412
|
-
catch {
|
|
413
|
-
// Fallback to buffer from string
|
|
414
|
-
return Buffer.from(data);
|
|
302
|
+
cb58Decode(str) {
|
|
303
|
+
const decoded = bs58_1.default.decode(str);
|
|
304
|
+
if (!this.validateChecksum(buffer_1.Buffer.from(decoded))) {
|
|
305
|
+
throw new Error('Invalid checksum');
|
|
415
306
|
}
|
|
307
|
+
return buffer_1.Buffer.from(decoded.slice(0, decoded.length - 4));
|
|
416
308
|
}
|
|
417
309
|
/**
|
|
418
|
-
*
|
|
419
|
-
* @param {string} hrp - Human readable part
|
|
420
|
-
* @param {string} chainid - Chain identifier
|
|
421
|
-
* @param {Buffer} addressBuffer - Address buffer
|
|
422
|
-
* @returns {string} Address string
|
|
310
|
+
* Validates a checksum on a Buffer and returns true if valid, false if not
|
|
423
311
|
*/
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
312
|
+
validateChecksum(buff) {
|
|
313
|
+
const hashSlice = buff.slice(buff.length - 4);
|
|
314
|
+
const calculatedHashSlice = (0, crypto_1.createHash)('sha256')
|
|
315
|
+
.update(buff.slice(0, buff.length - 4))
|
|
316
|
+
.digest()
|
|
317
|
+
.slice(28);
|
|
318
|
+
return hashSlice.toString('hex') === calculatedHashSlice.toString('hex');
|
|
427
319
|
}
|
|
428
320
|
/**
|
|
429
|
-
*
|
|
430
|
-
* Follows FlareJS utils.stringToBytes pattern
|
|
431
|
-
* @param {string} text - Text to convert
|
|
432
|
-
* @returns {Uint8Array} Byte array
|
|
321
|
+
* Encodes a Buffer as a base58 string with checksum
|
|
433
322
|
*/
|
|
434
|
-
|
|
435
|
-
|
|
323
|
+
cb58Encode(bytes) {
|
|
324
|
+
const withChecksum = this.addChecksum(bytes);
|
|
325
|
+
return bs58_1.default.encode(withChecksum);
|
|
436
326
|
}
|
|
437
327
|
/**
|
|
438
|
-
*
|
|
439
|
-
* @param {Uint8Array} bytes - Bytes to convert
|
|
440
|
-
* @returns {string} Decoded string
|
|
328
|
+
* Adds a checksum to a Buffer and returns the concatenated result
|
|
441
329
|
*/
|
|
442
|
-
|
|
443
|
-
|
|
330
|
+
addChecksum(buff) {
|
|
331
|
+
const hashSlice = (0, crypto_1.createHash)('sha256').update(buff).digest().slice(28);
|
|
332
|
+
return buffer_1.Buffer.concat([buff, hashSlice]);
|
|
444
333
|
}
|
|
445
334
|
/**
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* @param {
|
|
449
|
-
* @
|
|
335
|
+
* Check if tx is for the blockchainId
|
|
336
|
+
*
|
|
337
|
+
* @param {DeprecatedTx} tx
|
|
338
|
+
* @param {string} blockchainId
|
|
339
|
+
* @returns true if tx is for blockchainId
|
|
450
340
|
*/
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
341
|
+
// TODO: remove DeprecatedTx usage
|
|
342
|
+
isTransactionOf(tx, blockchainId) {
|
|
343
|
+
// FlareJS equivalent - this would need proper CB58 encoding implementation
|
|
344
|
+
try {
|
|
345
|
+
const txRecord = tx;
|
|
346
|
+
const unsignedTx = txRecord.getUnsignedTx();
|
|
347
|
+
const transaction = unsignedTx.getTransaction();
|
|
348
|
+
const txBlockchainId = transaction.getBlockchainID();
|
|
349
|
+
return buffer_1.Buffer.from(txBlockchainId).toString('hex') === blockchainId;
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
return false;
|
|
454
353
|
}
|
|
455
|
-
|
|
456
|
-
|
|
354
|
+
}
|
|
355
|
+
flareIdString(value) {
|
|
356
|
+
return new flarejs_1.Id(buffer_1.Buffer.from(value, 'hex'));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Extract credentials from raw transaction bytes.
|
|
360
|
+
* Signed transactions have credentials appended after the transaction body.
|
|
361
|
+
* This function handles both checking for credentials and extracting them.
|
|
362
|
+
*
|
|
363
|
+
* @param rawBytes - The full raw transaction bytes
|
|
364
|
+
* @param tx - The parsed transaction (must have toBytes method)
|
|
365
|
+
* @param vmType - The VM type ('EVM' or 'PVM') to get the correct codec
|
|
366
|
+
* @returns Object with hasCredentials flag and credentials array
|
|
367
|
+
*/
|
|
368
|
+
extractCredentialsFromRawBytes(rawBytes, tx, vmType = 'EVM') {
|
|
369
|
+
try {
|
|
370
|
+
// Get the size of the transaction without credentials using the default codec
|
|
371
|
+
const codec = flarejs_1.utils.getManagerForVM(vmType).getDefaultCodec();
|
|
372
|
+
const txBytes = tx.toBytes(codec);
|
|
373
|
+
const txSize = txBytes.length;
|
|
374
|
+
// If raw bytes are not longer than tx bytes, there are no credentials
|
|
375
|
+
if (rawBytes.length <= txSize) {
|
|
376
|
+
return { hasCredentials: false, credentials: [] };
|
|
377
|
+
}
|
|
378
|
+
// Extract credential bytes (everything after the transaction)
|
|
379
|
+
const credentialBytes = rawBytes.slice(txSize);
|
|
380
|
+
// Parse credentials
|
|
381
|
+
// Format: [num_credentials: 4 bytes] [credentials...]
|
|
382
|
+
if (credentialBytes.length < 4) {
|
|
383
|
+
return { hasCredentials: false, credentials: [] };
|
|
384
|
+
}
|
|
385
|
+
const numCredentials = credentialBytes.readUInt32BE(0);
|
|
386
|
+
// Check if there are credentials in raw bytes (for hasCredentials flag)
|
|
387
|
+
const hasCredentials = numCredentials > 0;
|
|
388
|
+
if (numCredentials === 0) {
|
|
389
|
+
return { hasCredentials: false, credentials: [] };
|
|
390
|
+
}
|
|
391
|
+
const credentials = [];
|
|
392
|
+
let offset = 4;
|
|
393
|
+
for (let i = 0; i < numCredentials; i++) {
|
|
394
|
+
if (offset + 8 > credentialBytes.length) {
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
// Read type ID (4 bytes) - Type ID 9 = secp256k1 credential
|
|
398
|
+
const typeId = credentialBytes.readUInt32BE(offset);
|
|
399
|
+
offset += 4;
|
|
400
|
+
// Validate credential type (9 = secp256k1)
|
|
401
|
+
if (typeId !== 9) {
|
|
402
|
+
continue; // Skip unsupported credential types
|
|
403
|
+
}
|
|
404
|
+
// Read number of signatures (4 bytes)
|
|
405
|
+
const numSigs = credentialBytes.readUInt32BE(offset);
|
|
406
|
+
offset += 4;
|
|
407
|
+
// Parse all signatures for this credential
|
|
408
|
+
const signatures = [];
|
|
409
|
+
for (let j = 0; j < numSigs; j++) {
|
|
410
|
+
if (offset + 65 > credentialBytes.length) {
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
// Each signature is 65 bytes (64 bytes signature + 1 byte recovery)
|
|
414
|
+
const sigBytes = buffer_1.Buffer.from(credentialBytes.slice(offset, offset + 65));
|
|
415
|
+
signatures.push(new flarejs_1.Signature(sigBytes));
|
|
416
|
+
offset += 65;
|
|
417
|
+
}
|
|
418
|
+
// Create credential with the parsed signatures
|
|
419
|
+
if (signatures.length > 0) {
|
|
420
|
+
credentials.push(new flarejs_1.Credential(signatures));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return { hasCredentials, credentials };
|
|
457
424
|
}
|
|
458
|
-
|
|
459
|
-
return
|
|
425
|
+
catch (e) {
|
|
426
|
+
// If parsing fails, return no credentials
|
|
427
|
+
return { hasCredentials: false, credentials: [] };
|
|
460
428
|
}
|
|
461
|
-
throw new sdk_core_1.InvalidTransactionError('Invalid memo format');
|
|
462
429
|
}
|
|
463
430
|
/**
|
|
464
|
-
* Parse
|
|
465
|
-
*
|
|
466
|
-
* @
|
|
431
|
+
* Parse credentials from raw bytes at a specific offset
|
|
432
|
+
* This is useful when the standard extraction fails due to serialization differences
|
|
433
|
+
* @param rawBytes Raw transaction bytes including credentials
|
|
434
|
+
* @param offset Byte offset where credentials start
|
|
435
|
+
* @returns Array of parsed credentials
|
|
467
436
|
*/
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
437
|
+
parseCredentialsAtOffset(rawBytes, offset) {
|
|
438
|
+
try {
|
|
439
|
+
if (rawBytes.length <= offset + 4) {
|
|
440
|
+
return [];
|
|
441
|
+
}
|
|
442
|
+
const credentialBytes = rawBytes.slice(offset);
|
|
443
|
+
const numCredentials = credentialBytes.readUInt32BE(0);
|
|
444
|
+
if (numCredentials === 0) {
|
|
445
|
+
return [];
|
|
446
|
+
}
|
|
447
|
+
const credentials = [];
|
|
448
|
+
let pos = 4;
|
|
449
|
+
for (let i = 0; i < numCredentials; i++) {
|
|
450
|
+
if (pos + 8 > credentialBytes.length) {
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
// Read type ID (4 bytes) - Type ID 9 = secp256k1 credential
|
|
454
|
+
const typeId = credentialBytes.readUInt32BE(pos);
|
|
455
|
+
pos += 4;
|
|
456
|
+
if (typeId !== 9) {
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
// Read number of signatures (4 bytes)
|
|
460
|
+
const numSigs = credentialBytes.readUInt32BE(pos);
|
|
461
|
+
pos += 4;
|
|
462
|
+
// Parse all signatures for this credential
|
|
463
|
+
const signatures = [];
|
|
464
|
+
for (let j = 0; j < numSigs; j++) {
|
|
465
|
+
if (pos + 65 > credentialBytes.length) {
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
const sigBytes = buffer_1.Buffer.from(credentialBytes.slice(pos, pos + 65));
|
|
469
|
+
signatures.push(new flarejs_1.Signature(sigBytes));
|
|
470
|
+
pos += 65;
|
|
471
|
+
}
|
|
472
|
+
if (signatures.length > 0) {
|
|
473
|
+
credentials.push(new flarejs_1.Credential(signatures));
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return credentials;
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return [];
|
|
471
480
|
}
|
|
472
|
-
return this.bytesToString(memoBytes);
|
|
473
481
|
}
|
|
474
482
|
/**
|
|
475
|
-
*
|
|
476
|
-
* @param
|
|
477
|
-
* @param
|
|
478
|
-
* @
|
|
483
|
+
* FlareJS wrapper to recover signature
|
|
484
|
+
* @param network
|
|
485
|
+
* @param message
|
|
486
|
+
* @param signature
|
|
487
|
+
* @return recovered public key
|
|
479
488
|
*/
|
|
480
|
-
|
|
481
|
-
|
|
489
|
+
recoverySignature(network, message, signature) {
|
|
490
|
+
try {
|
|
491
|
+
// Hash the message first - must match the hash used in signing
|
|
492
|
+
const messageHash = (0, crypto_1.createHash)('sha256').update(message).digest();
|
|
493
|
+
// Extract recovery parameter and signature
|
|
494
|
+
if (signature.length !== 65) {
|
|
495
|
+
throw new Error('Invalid signature length - expected 65 bytes (64 bytes signature + 1 byte recovery)');
|
|
496
|
+
}
|
|
497
|
+
const recoveryParam = signature[64];
|
|
498
|
+
const sigOnly = signature.slice(0, 64);
|
|
499
|
+
// Recover public key using the provided recovery parameter
|
|
500
|
+
const recovered = secp256k1_1.ecc.recoverPublicKey(messageHash, sigOnly, recoveryParam, true);
|
|
501
|
+
if (!recovered) {
|
|
502
|
+
throw new Error('Failed to recover public key');
|
|
503
|
+
}
|
|
504
|
+
return buffer_1.Buffer.from(recovered);
|
|
505
|
+
}
|
|
506
|
+
catch (error) {
|
|
507
|
+
throw new Error(`Failed to recover signature: ${error}`);
|
|
508
|
+
}
|
|
482
509
|
}
|
|
483
510
|
}
|
|
484
511
|
exports.Utils = Utils;
|
|
485
512
|
const utils = new Utils();
|
|
486
513
|
exports.default = utils;
|
|
487
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLG1EQVE4QjtBQUU5QixxREFBNEM7QUFDNUMsbUNBQW9DO0FBRXBDLDJDQVdxQjtBQUVyQixNQUFhLEtBQUs7SUFBbEI7UUE0RlMsaUJBQVksR0FBRyxDQUFDLEdBQVcsRUFBVSxFQUFFO1lBQzVDLHlDQUF5QztZQUN6QyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsNEJBQTRCO1FBQzlELENBQUMsQ0FBQztJQThaSixDQUFDO0lBNWZRLFNBQVMsQ0FBQyxlQUF5QixFQUFFLG1CQUE2QjtRQUN2RSxPQUFPLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEcsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsa0JBQWtCO0lBQ2xCLGNBQWMsQ0FBQyxPQUEwQjtRQUN2QyxNQUFNLFVBQVUsR0FBYSxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFbkYsS0FBSyxNQUFNLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZDLE9BQU8sS0FBSyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxt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QUM7UUFDbEMsQ0FBQztRQUVELElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRUQsTUFBTSxJQUFJLGtDQUF1QixDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxjQUFjLENBQUMsU0FBcUI7UUFDbEMsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxTQUFxQixFQUFFLE9BQU8sR0FBRyxJQUFJO1FBQ3BELE9BQU8sU0FBUyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBN2ZELHNCQTZmQztBQUVELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7QUFFMUIsa0JBQWUsS0FBSyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVHJhbnNmZXJhYmxlT3V0cHV0IH0gZnJvbSAnQGZsYXJlbmV0d29yay9mbGFyZWpzJztcbmltcG9ydCB7XG4gIEJhc2VVdGlscyxcbiAgRW50cnksXG4gIEludmFsaWRUcmFuc2FjdGlvbkVycm9yLFxuICBpc1ZhbGlkWHBydixcbiAgaXNWYWxpZFhwdWIsXG4gIE5vdEltcGxlbWVudGVkRXJyb3IsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgRmxhcmVOZXR3b3JrIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgeyBlY2MgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBEZXByZWNhdGVkT3V0cHV0LCBEZXByZWNhdGVkVHgsIE91dHB1dCB9IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHtcbiAgREVDT0RFRF9CTE9DS19JRF9MRU5HVEgsXG4gIFNIT1JUX1BVQl9LRVlfTEVOR1RILFxuICBDT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RILFxuICBVTkNPTVBSRVNTRURfUFVCTElDX0tFWV9MRU5HVEgsXG4gIFJBV19QUklWQVRFX0tFWV9MRU5HVEgsXG4gIFNVRkZJWEVEX1BSSVZBVEVfS0VZX0xFTkdUSCxcbiAgUFJJVkFURV9LRVlfQ09NUFJFU1NFRF9TVUZGSVgsXG4gIE9VVFBVVF9JTkRFWF9IRVhfTEVOR1RILFxuICBBRERSRVNTX1JFR0VYLFxuICBIRVhfUkVHRVgsXG59IGZyb20gJy4vY29uc3RhbnRzJztcblxuZXhwb3J0IGNsYXNzIFV0aWxzIGltcGxlbWVudHMgQmFzZVV0aWxzIHtcbiAgcHVibGljIGluY2x1ZGVJbih3YWxsZXRBZGRyZXNzZXM6IHN0cmluZ1tdLCBvdHhvT3V0cHV0QWRkcmVzc2VzOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB3YWxsZXRBZGRyZXNzZXMubWFwKChhKSA9PiBvdHhvT3V0cHV0QWRkcmVzc2VzLmluY2x1ZGVzKGEpKS5yZWR1Y2UoKGEsIGIpID0+IGEgJiYgYiwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGl0IGlzIGEgdmFsaWQgYWRkcmVzcyBubyBpbGxlZ2FsIGNoYXJhY3RlcnNcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgLSBhZGRyZXNzIHRvIGJlIHZhbGlkYXRlZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGFkZHJlc3NBcnI6IHN0cmluZ1tdID0gQXJyYXkuaXNBcnJheShhZGRyZXNzKSA/IGFkZHJlc3MgOiBhZGRyZXNzLnNwbGl0KCd+Jyk7XG5cbiAgICBmb3IgKGNvbnN0IGFkZHJlc3Mgb2YgYWRkcmVzc0Fycikge1xuICAgICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzUmVnZXgoYWRkcmVzcykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1ZhbGlkQWRkcmVzc1JlZ2V4KGFkZHJlc3M6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBBRERSRVNTX1JFR0VYLnRlc3QoYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGl0IGlzIGEgdmFsaWQgYmxvY2tJZCB3aXRoIGxlbmd0aCA2NiBpbmNsdWRpbmcgMHhcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggLSBibG9ja0lkIHRvIGJlIHZhbGlkYXRlZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQmxvY2tJZChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAvLyBGbGFyZUpTIGVxdWl2YWxlbnQgLSBjaGVjayBpZiBpdCdzIGEgdmFsaWQgQ0I1OCBoYXNoIHdpdGggY29ycmVjdCBsZW5ndGhcbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVjb2RlZCA9IEJ1ZmZlci5mcm9tKGhhc2gpOyAvLyBGbGFyZUpTIHNob3VsZCBwcm92aWRlIENCNTggdXRpbGl0aWVzXG4gICAgICByZXR1cm4gZGVjb2RlZC5sZW5ndGggPT09IERFQ09ERURfQkxPQ0tfSURfTEVOR1RIO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIHN0cmluZyBpcyBhIHZhbGlkIHByb3RvY29sIHB1YmxpYyBrZXkgb3JcbiAgICogZXh0ZW5kZWQgcHVibGljIGtleS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YiAtIHRoZSAgcHVibGljIGtleSB0byBiZSB2YWxpZGF0ZWRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdGhlIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBpc1ZhbGlkUHVibGljS2V5KHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzVmFsaWRYcHViKHB1YikpIHJldHVybiB0cnVlO1xuXG4gICAgbGV0IHB1YkJ1ZjogQnVmZmVyO1xuICAgIGlmIChwdWIubGVuZ3RoID09PSBTSE9SVF9QVUJfS0VZX0xFTkdUSCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gRm9yIEZsYXJlSlMsIHdlJ2xsIG5lZWQgdG8gaW1wbGVtZW50IENCNTggZGVjb2RlIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7IC8vIFRlbXBvcmFyeSBwbGFjZWhvbGRlclxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHB1Yi5sZW5ndGggIT09IENPTVBSRVNTRURfUFVCTElDX0tFWV9MRU5HVEggJiYgcHViLmxlbmd0aCAhPT0gVU5DT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RIKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmlyc3RCeXRlID0gcHViLnNsaWNlKDAsIDIpO1xuXG4gICAgICAvLyB1bmNvbXByZXNzZWQgcHVibGljIGtleVxuICAgICAgaWYgKHB1Yi5sZW5ndGggPT09IFVOQ09NUFJFU1NFRF9QVUJMSUNfS0VZX0xFTkdUSCAmJiBmaXJzdEJ5dGUgIT09ICcwNCcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBjb21wcmVzc2VkIHB1YmxpYyBrZXlcbiAgICAgIGlmIChwdWIubGVuZ3RoID09PSBDT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RIICYmIGZpcnN0Qnl0ZSAhPT0gJzAyJyAmJiBmaXJzdEJ5dGUgIT09ICcwMycpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuYWxsSGV4Q2hhcnMocHViKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7XG4gICAgfVxuICAgIC8vIHZhbGlkYXRlIHRoZSBwdWJsaWMga2V5IHVzaW5nIEJpdEdvIHNlY3AyNTZrMVxuICAgIHRyeSB7XG4gICAgICBlY2MuaXNQb2ludChwdWJCdWYpOyAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgcG9pbnRcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcGFyc2VBZGRyZXNzID0gKHB1Yjogc3RyaW5nKTogQnVmZmVyID0+IHtcbiAgICAvLyBGbGFyZUpTIGVxdWl2YWxlbnQgZm9yIGFkZHJlc3MgcGFyc2luZ1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShwdWIsICdoZXgnKTsgLy8gU2ltcGxpZmllZCBpbXBsZW1lbnRhdGlvblxuICB9O1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBwcm90b2NvbCBwcml2YXRlIGtleSwgb3IgZXh0ZW5kZWRcbiAgICogcHJpdmF0ZSBrZXkuXG4gICAqXG4gICAqIFRoZSBwcm90b2NvbCBrZXkgZm9ybWF0IGlzIGRlc2NyaWJlZCBpbiB0aGUgQHN0YWNrcy90cmFuc2FjdGlvbnMgbnBtIHBhY2thZ2UsIGluIHRoZVxuICAgKiBjcmVhdGVTdGFja3NQcml2YXRlS2V5IGZ1bmN0aW9uOlxuICAgKiBodHRwczovL2dpdGh1Yi5jb20vYmxvY2tzdGFjay9zdGFja3MuanMvYmxvYi9tYXN0ZXIvcGFja2FnZXMvdHJhbnNhY3Rpb25zL3NyYy9rZXlzLnRzI0wxMjVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBydiAtIHRoZSBwcml2YXRlIGtleSAob3IgZXh0ZW5kZWQgcHJpdmF0ZSBrZXkpIHRvIGJlIHZhbGlkYXRlZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIGlzVmFsaWRQcml2YXRlS2V5KHBydjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzVmFsaWRYcHJ2KHBydikpIHJldHVybiB0cnVlO1xuXG4gICAgaWYgKHBydi5sZW5ndGggIT09IFJBV19QUklWQVRFX0tFWV9MRU5HVEggJiYgcHJ2Lmxlbmd0aCAhPT0gU1VGRklYRURfUFJJVkFURV9LRVlfTEVOR1RIKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgcHJ2Lmxlbmd0aCA9PT0gU1VGRklYRURfUFJJVkFURV9LRVlfTEVOR1RIICYmXG4gICAgICBwcnYuc2xpY2UoUkFXX1BSSVZBVEVfS0VZX0xFTkdUSCkgIT09IFBSSVZBVEVfS0VZX0NPTVBSRVNTRURfU1VGRklYXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYWxsSGV4Q2hhcnMocHJ2KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSBjb21wb3NlZCBvZiBoZXggY2hhcnMgb25seVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWF5YmUgLSB0aGUgIHN0cmluZyB0byBiZSB2YWxpZGF0ZWRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdGhlIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBhbGxIZXhDaGFycyhtYXliZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIEhFWF9SRUdFWC50ZXN0KG1heWJlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaWdodHdlaWdodCBFdGhlcmV1bSBhZGRyZXNzIHZhbGlkYXRpb25cbiAgICogVmFsaWRhdGVzIHRoYXQgYW4gYWRkcmVzcyBpcyBhIDQwLWNoYXJhY3RlciBoZXggc3RyaW5nIChvcHRpb25hbGx5IHByZWZpeGVkIHdpdGggMHgpXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIC0gdGhlIEV0aGVyZXVtIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdHJ1ZSBpZiB2YWxpZCBFdGhlcmV1bSBhZGRyZXNzIGZvcm1hdFxuICAgKi9cbiAgaXNWYWxpZEV0aGVyZXVtQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoIWFkZHJlc3MgfHwgdHlwZW9mIGFkZHJlc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIDB4IHByZWZpeCBpZiBwcmVzZW50XG4gICAgY29uc3QgY2xlYW5BZGRyZXNzID0gYWRkcmVzcy5zdGFydHNXaXRoKCcweCcpID8gYWRkcmVzcy5zbGljZSgyKSA6IGFkZHJlc3M7XG5cbiAgICAvLyBDaGVjayBpZiBpdCdzIGV4YWN0bHkgNDAgaGV4IGNoYXJhY3RlcnNcbiAgICByZXR1cm4gY2xlYW5BZGRyZXNzLmxlbmd0aCA9PT0gNDAgJiYgL15bMC05YS1mQS1GXXs0MH0kLy50ZXN0KGNsZWFuQWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogUGljayBzcGVjaWZpYyBwcm9wZXJ0aWVzIGZyb20gYW4gb2JqZWN0IChyZXBsYWNlcyBsb2Rhc2gucGljaylcbiAgICpcbiAgICogQHBhcmFtIHtUfSBvYmogLSB0aGUgc291cmNlIG9iamVjdFxuICAgKiBAcGFyYW0ge0tbXX0ga2V5cyAtIGFycmF5IG9mIHByb3BlcnR5IGtleXMgdG8gcGlja1xuICAgKiBAcmV0dXJucyB7UGljazxULCBLPn0gLSBuZXcgb2JqZWN0IHdpdGggb25seSB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXNcbiAgICovXG4gIHBpY2s8VCwgSyBleHRlbmRzIGtleW9mIFQ+KG9iajogVCwga2V5czogS1tdKTogUGljazxULCBLPiB7XG4gICAgY29uc3QgcmVzdWx0ID0ge30gYXMgUGljazxULCBLPjtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IG9ialtrZXldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIERlZXAgZXF1YWxpdHkgY29tcGFyaXNvbiAocmVwbGFjZXMgbG9kYXNoLmlzRXF1YWwpXG4gICAqXG4gICAqIEBwYXJhbSB7dW5rbm93bn0gYSAtIGZpcnN0IHZhbHVlIHRvIGNvbXBhcmVcbiAgICogQHBhcmFtIHt1bmtub3dufSBiIC0gc2Vjb25kIHZhbHVlIHRvIGNvbXBhcmVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdHJ1ZSBpZiB2YWx1ZXMgYXJlIGRlZXBseSBlcXVhbFxuICAgKi9cbiAgaXNFcXVhbChhOiB1bmtub3duLCBiOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgaWYgKGEgPT09IGIpIHJldHVybiB0cnVlO1xuXG4gICAgaWYgKGEgPT09IG51bGwgfHwgYSA9PT0gdW5kZWZpbmVkIHx8IGIgPT09IG51bGwgfHwgYiA9PT0gdW5kZWZpbmVkKSByZXR1cm4gYSA9PT0gYjtcblxuICAgIGlmICh0eXBlb2YgYSAhPT0gdHlwZW9mIGIpIHJldHVybiBmYWxzZTtcblxuICAgIGlmICh0eXBlb2YgYSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGEpICE9PSBBcnJheS5pc0FycmF5KGIpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIGNvbnN0IGFyckIgPSBiIGFzIHVua25vd25bXTtcbiAgICAgICAgaWYgKGEubGVuZ3RoICE9PSBhcnJCLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoIXRoaXMuaXNFcXVhbChhW2ldLCBhcnJCW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvYmpBID0gYSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNvbnN0IG9iakIgPSBiIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgY29uc3Qga2V5c0EgPSBPYmplY3Qua2V5cyhvYmpBKTtcbiAgICAgIGNvbnN0IGtleXNCID0gT2JqZWN0LmtleXMob2JqQik7XG4gICAgICBpZiAoa2V5c0EubGVuZ3RoICE9PSBrZXlzQi5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgICAgZm9yIChjb25zdCBrZXkgb2Yga2V5c0EpIHtcbiAgICAgICAgaWYgKCFrZXlzQi5pbmNsdWRlcyhrZXkpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmICghdGhpcy5pc0VxdWFsKG9iakFba2V5XSwgb2JqQltrZXldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRTaWduYXR1cmUoc2lnbmF0dXJlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcignaXNWYWxpZFNpZ25hdHVyZSBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkVHJhbnNhY3Rpb25JZCh0eElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcignaXNWYWxpZFRyYW5zYWN0aW9uSWQgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogRmxhcmVKUyB3cmFwcGVyIHRvIGNyZWF0ZSBzaWduYXR1cmUgYW5kIHJldHVybiBpdCBmb3IgY3JlZGVudGlhbHNcbiAgICogQHBhcmFtIG5ldHdvcmtcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHBhcmFtIHBydlxuICAgKiBAcmV0dXJuIHNpZ25hdHVyZVxuICAgKi9cbiAgY3JlYXRlU2lnbmF0dXJlKG5ldHdvcms6IEZsYXJlTmV0d29yaywgbWVzc2FnZTogQnVmZmVyLCBwcnY6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgLy8gVXNlIEJpdEdvIHNlY3AyNTZrMSBzaW5jZSBGbGFyZUpTIG1heSBub3QgZXhwb3NlIEtleVBhaXIgaW4gdGhlIHNhbWUgd2F5XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGVjYy5zaWduKG1lc3NhZ2UsIHBydik7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oc2lnbmF0dXJlKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gY3JlYXRlIHNpZ25hdHVyZTogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmxhcmVKUyB3cmFwcGVyIHRvIHZlcmlmeSBzaWduYXR1cmVcbiAgICogQHBhcmFtIG5ldHdvcmtcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHBhcmFtIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0gcHVibGljS2V5IC0gcHVibGljIGtleSBpbnN0ZWFkIG9mIHByaXZhdGUga2V5IGZvciB2ZXJpZmljYXRpb25cbiAgICogQHJldHVybiB0cnVlIGlmIGl0J3MgdmVyaWZ5IHN1Y2Nlc3NmdWxcbiAgICovXG4gIHZlcmlmeVNpZ25hdHVyZShuZXR3b3JrOiBGbGFyZU5ldHdvcmssIG1lc3NhZ2U6IEJ1ZmZlciwgc2lnbmF0dXJlOiBCdWZmZXIsIHB1YmxpY0tleTogQnVmZmVyKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBlY2MudmVyaWZ5KG1lc3NhZ2UsIHB1YmxpY0tleSwgc2lnbmF0dXJlKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFyZUpTIHdyYXBwZXIgdG8gcmVjb3ZlciBzaWduYXR1cmVcbiAgICogQHBhcmFtIG5ldHdvcmtcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHBhcmFtIHNpZ25hdHVyZVxuICAgKiBAcmV0dXJuIHJlY292ZXJlZCBwdWJsaWMga2V5XG4gICAqL1xuICByZWNvdmVyeVNpZ25hdHVyZShuZXR3b3JrOiBGbGFyZU5ldHdvcmssIG1lc3NhZ2U6IEJ1ZmZlciwgc2lnbmF0dXJlOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIHRyeSB7XG4gICAgICAvLyBUaGlzIHdvdWxkIG5lZWQgdG8gYmUgaW1wbGVtZW50ZWQgd2l0aCBzZWNwMjU2azEgcmVjb3ZlcnlcbiAgICAgIC8vIEZvciBub3csIHRocm93aW5nIGVycm9yIHNpbmNlIHJlY292ZXJ5IGxvZ2ljIHdvdWxkIG5lZWQgdG8gYmUgYWRhcHRlZFxuICAgICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ3JlY292ZXJ5U2lnbmF0dXJlIG5vdCBmdWxseSBpbXBsZW1lbnRlZCBmb3IgRmxhcmVKUycpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZWNvdmVyIHNpZ25hdHVyZTogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICBzaGEyNTYoYnVmOiBVaW50OEFycmF5KTogQnVmZmVyIHtcbiAgICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGJ1ZikuZGlnZXN0KCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgdGhlIHJhdyB0cmFuc2FjdGlvbiBoYXMgYSB2YWxpZCBmb3JtYXQgaW4gdGhlIGJsb2NrY2hhaW4gY29udGV4dCwgdGhyb3cgb3RoZXJ3aXNlLlxuICAgKiBJdCdzIHRvIHJldXNlIGluIFRyYW5zYWN0aW9uQnVpbGRlciBhbmQgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeVxuICAgKlxuICAgKiBAcGFyYW0gcmF3VHJhbnNhY3Rpb24gVHJhbnNhY3Rpb24gYXMgaGV4IHN0cmluZ1xuICAgKi9cbiAgdmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFyYXdUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdSYXcgdHJhbnNhY3Rpb24gaXMgZW1wdHknKTtcbiAgICB9XG4gICAgaWYgKCF1dGlscy5hbGxIZXhDaGFycyhyYXdUcmFuc2FjdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBub3QgaGV4IHN0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0eCBpcyBmb3IgdGhlIGJsb2NrY2hhaW5JZFxuICAgKlxuICAgKiBAcGFyYW0ge0RlcHJlY2F0ZWRUeH0gdHhcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJsb2NrY2hhaW5JZFxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHR4IGlzIGZvciBibG9ja2NoYWluSWRcbiAgICovXG4gIGlzVHJhbnNhY3Rpb25PZih0eDogRGVwcmVjYXRlZFR4LCBibG9ja2NoYWluSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vIEZsYXJlSlMgZXF1aXZhbGVudCAtIHRoaXMgd291bGQgbmVlZCBwcm9wZXIgQ0I1OCBlbmNvZGluZyBpbXBsZW1lbnRhdGlvblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB0eFJlY29yZCA9IHR4IGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gKHR4UmVjb3JkLmdldFVuc2lnbmVkVHggYXMgKCkgPT4gUmVjb3JkPHN0cmluZywgdW5rbm93bj4pKCk7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9ICh1bnNpZ25lZFR4LmdldFRyYW5zYWN0aW9uIGFzICgpID0+IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSgpO1xuICAgICAgY29uc3QgdHhCbG9ja2NoYWluSWQgPSAodHJhbnNhY3Rpb24uZ2V0QmxvY2tjaGFpbklEIGFzICgpID0+IHVua25vd24pKCk7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20odHhCbG9ja2NoYWluSWQgYXMgc3RyaW5nKS50b1N0cmluZygnaGV4JykgPT09IGJsb2NrY2hhaW5JZDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBPdXRwdXQgaXMgZnJvbSBQVk0uXG4gICAqIE91dHB1dCBjb3VsZCBiZSBFVk0gb3IgUFZNIG91dHB1dC5cbiAgICogQHBhcmFtIHtEZXByZWNhdGVkT3V0cHV0fSBvdXRwdXRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IG91dHB1dCBoYXMgdHJhbnNmZXJhYmxlIG91dHB1dCBzdHJ1Y3R1cmVcbiAgICovXG4gIGRlcHJlY2F0ZWRJc1RyYW5zZmVyYWJsZU91dHB1dChvdXRwdXQ6IERlcHJlY2F0ZWRPdXRwdXQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gJ2dldE91dHB1dCcgaW4gKG91dHB1dCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgT3V0cHV0IGlzIGZyb20gUFZNLlxuICAgKiBPdXRwdXQgY291bGQgYmUgRVZNIG9yIFBWTSBvdXRwdXQuXG4gICAqIEBwYXJhbSB7T3V0cHV0fSBvdXRwdXRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IG91dHB1dCBpcyBUcmFuc2ZlcmFibGVPdXRwdXRcbiAgICovXG4gIGlzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dDogT3V0cHV0KTogb3V0cHV0IGlzIFRyYW5zZmVyYWJsZU91dHB1dCB7XG4gICAgcmV0dXJuIHR5cGVvZiAob3V0cHV0IGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmdldE91dHB1dCA9PT0gJ2Z1bmN0aW9uJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBtYXBwZXIgZnVuY3Rpb24gdG8gdGhhdCBuZXR3b3JrIGFkZHJlc3MgcmVwcmVzZW50YXRpb24uXG4gICAqIEBwYXJhbSBuZXR3b3JrIHJlcXVpcmVkIHRvIHN0cmluZ2lmeSBhZGRyZXNzZXNcbiAgICogQHJldHVybiBtYXBwZXIgZnVuY3Rpb25cbiAgICovXG4gIGRlcHJlY2F0ZWRNYXBPdXRwdXRUb0VudHJ5KG5ldHdvcms6IEZsYXJlTmV0d29yayk6IChvdXRwdXQ6IERlcHJlY2F0ZWRPdXRwdXQpID0+IEVudHJ5IHtcbiAgICByZXR1cm4gKG91dHB1dDogRGVwcmVjYXRlZE91dHB1dCkgPT4ge1xuICAgICAgaWYgKHRoaXMuZGVwcmVjYXRlZElzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dCkpIHtcbiAgICAgICAgLy8gU2ltcGxpZmllZCBpbXBsZW1lbnRhdGlvbiBmb3IgRmxhcmVKU1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHRyYW5zZmVyYWJsZU91dHB1dCA9IG91dHB1dCBhcyB1bmtub3duIGFzIFRyYW5zZmVyYWJsZU91dHB1dDtcbiAgICAgICAgICBjb25zdCBhbW91bnQgPSB0cmFuc2ZlcmFibGVPdXRwdXQuYW1vdW50KCk7XG5cbiAgICAgICAgICAvLyBTaW1wbGlmaWVkIGFkZHJlc3MgaGFuZGxpbmcgLSB3b3VsZCBuZWVkIHByb3BlciBGbGFyZUpTIGFkZHJlc3MgdXRpbGl0aWVzXG4gICAgICAgICAgY29uc3QgYWRkcmVzcyA9ICdmbGFyZS1hZGRyZXNzLXBsYWNlaG9sZGVyJzsgLy8gVE9ETzogaW1wbGVtZW50IHByb3BlciBhZGRyZXNzIGNvbnZlcnNpb25cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBhZGRyZXNzLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbWFwIG91dHB1dDogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSGFuZGxlIEVWTSBvdXRwdXQgY2FzZSAtIHNpbXBsaWZpZWRcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2YWx1ZTogJzAnLCAvLyBUT0RPOiBpbXBsZW1lbnQgcHJvcGVyIGFtb3VudCBleHRyYWN0aW9uXG4gICAgICAgICAgYWRkcmVzczogJzB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsIC8vIFRPRE86IGltcGxlbWVudCBwcm9wZXIgYWRkcmVzcyBleHRyYWN0aW9uXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBtYXBwZXIgZnVuY3Rpb24gdG8gdGhhdCBuZXR3b3JrIGFkZHJlc3MgcmVwcmVzZW50YXRpb24uXG4gICAqIEBwYXJhbSBuZXR3b3JrIHJlcXVpcmVkIHRvIHN0cmluZ2lmeSBhZGRyZXNzZXNcbiAgICogQHJldHVybiBtYXBwZXIgZnVuY3Rpb25cbiAgICovXG4gIG1hcE91dHB1dFRvRW50cnkobmV0d29yazogRmxhcmVOZXR3b3JrKTogKE91dHB1dCkgPT4gRW50cnkge1xuICAgIHJldHVybiAob3V0cHV0OiBPdXRwdXQpID0+IHtcbiAgICAgIGlmICh0aGlzLmlzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dCkpIHtcbiAgICAgICAgY29uc3QgdHJhbnNmZXJhYmxlT3V0cHV0ID0gb3V0cHV0IGFzIFRyYW5zZmVyYWJsZU91dHB1dDtcbiAgICAgICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gdHJhbnNmZXJhYmxlT3V0cHV0LmFtb3VudCgpO1xuXG4gICAgICAgIC8vIFNpbXBsaWZpZWQgYWRkcmVzcyBoYW5kbGluZyBmb3IgRmxhcmVKU1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gJ2ZsYXJlLWFkZHJlc3MtcGxhY2Vob2xkZXInOyAvLyBUT0RPOiBpbXBsZW1lbnQgcHJvcGVyIGFkZHJlc3MgY29udmVyc2lvblxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmFsdWU6IG91dHB1dEFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgIGFkZHJlc3MsXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgb3V0cHV0IHR5cGUnKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIHJlbW92ZSBoZXggcHJlZml4ICgweClcbiAgICogQHBhcmFtIGhleCBzdHJpbmdcbiAgICogQHJldHVybnMgaGV4IHdpdGhvdXQgMHhcbiAgICovXG4gIHJlbW92ZUhleFByZWZpeChoZXg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKGhleC5zdGFydHNXaXRoKCcweCcpKSB7XG4gICAgICByZXR1cm4gaGV4LnN1YnN0cmluZygyKTtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdXRwdXRpZHggY29udmVydCBmcm9tIG51bWJlciAoYXMgc3RyaW5nKSB0byBidWZmZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvdXRwdXRpZHggbnVtYmVyXG4gICAqIEByZXR1cm4ge0J1ZmZlcn0gYnVmZmVyIG9mIHNpemUgNCB3aXRoIHRoYXQgbnVtYmVyIHZhbHVlXG4gICAqL1xuICBvdXRwdXRpZHhOdW1iZXJUb0J1ZmZlcihvdXRwdXRpZHg6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKE51bWJlcihvdXRwdXRpZHgpLnRvU3RyaW5nKDE2KS5wYWRTdGFydChPVVRQVVRfSU5ERVhfSEVYX0xFTkdUSCwgJzAnKSwgJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE91dHB1dGlkeCBidWZmZXIgdG8gbnVtYmVyIChhcyBzdHJpbmcpXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBvdXRwdXRpZHhcbiAgICogQHJldHVybiB7c3RyaW5nfSBvdXRwdXRpZHggbnVtYmVyXG4gICAqL1xuICBvdXRwdXRpZHhCdWZmZXJUb051bWJlcihvdXRwdXRpZHg6IEJ1ZmZlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBhcnNlSW50KG91dHB1dGlkeC50b1N0cmluZygnaGV4JyksIDE2KS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENCNTggZGVjb2RlIGZ1bmN0aW9uIC0gc2ltcGxlIEJhc2U1OCBkZWNvZGUgaW1wbGVtZW50YXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBDQjU4IGVuY29kZWQgc3RyaW5nXG4gICAqIEByZXR1cm5zIHtCdWZmZXJ9IGRlY29kZWQgYnVmZmVyXG4gICAqL1xuICBjYjU4RGVjb2RlKGRhdGE6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgLy8gRm9yIG5vdywgdXNlIGEgc2ltcGxlIGhleCBkZWNvZGUgYXMgcGxhY2Vob2xkZXJcbiAgICAvLyBJbiBhIGZ1bGwgaW1wbGVtZW50YXRpb24sIHRoaXMgd291bGQgYmUgcHJvcGVyIENCNTggZGVjb2RpbmdcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEsICdoZXgnKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIEZhbGxiYWNrIHRvIGJ1ZmZlciBmcm9tIHN0cmluZ1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGFkZHJlc3MgYnVmZmVyIHRvIGJlY2gzMiBzdHJpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhycCAtIEh1bWFuIHJlYWRhYmxlIHBhcnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYWluaWQgLSBDaGFpbiBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBhZGRyZXNzQnVmZmVyIC0gQWRkcmVzcyBidWZmZXJcbiAgICogQHJldHVybnMge3N0cmluZ30gQWRkcmVzcyBzdHJpbmdcbiAgICovXG4gIGFkZHJlc3NUb1N0cmluZyhocnA6IHN0cmluZywgY2hhaW5pZDogc3RyaW5nLCBhZGRyZXNzQnVmZmVyOiBCdWZmZXIpOiBzdHJpbmcge1xuICAgIC8vIFNpbXBsZSBpbXBsZW1lbnRhdGlvbiAtIGluIHByYWN0aWNlIHRoaXMgd291bGQgdXNlIGJlY2gzMiBlbmNvZGluZ1xuICAgIHJldHVybiBgJHtjaGFpbmlkfS0ke2FkZHJlc3NCdWZmZXIudG9TdHJpbmcoJ2hleCcpfWA7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBzdHJpbmcgdG8gYnl0ZXMgZm9yIEZsYXJlSlMgbWVtb1xuICAgKiBGb2xsb3dzIEZsYXJlSlMgdXRpbHMuc3RyaW5nVG9CeXRlcyBwYXR0ZXJuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGV4dCB0byBjb252ZXJ0XG4gICAqIEByZXR1cm5zIHtVaW50OEFycmF5fSBCeXRlIGFycmF5XG4gICAqL1xuICBzdHJpbmdUb0J5dGVzKHRleHQ6IHN0cmluZyk6IFVpbnQ4QXJyYXkge1xuICAgIHJldHVybiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUodGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBieXRlcyB0byBzdHJpbmcgZnJvbSBGbGFyZUpTIG1lbW9cbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBieXRlcyAtIEJ5dGVzIHRvIGNvbnZlcnRcbiAgICogQHJldHVybnMge3N0cmluZ30gRGVjb2RlZCBzdHJpbmdcbiAgICovXG4gIGJ5dGVzVG9TdHJpbmcoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoYnl0ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBtZW1vIGJ5dGVzIGZyb20gdmFyaW91cyBpbnB1dCBmb3JtYXRzXG4gICAqIFN1cHBvcnRzIHN0cmluZywgSlNPTiBvYmplY3QsIG9yIHJhdyBieXRlc1xuICAgKiBAcGFyYW0ge3N0cmluZyB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgVWludDhBcnJheX0gbWVtbyAtIE1lbW8gZGF0YVxuICAgKiBAcmV0dXJucyB7VWludDhBcnJheX0gTWVtbyBieXRlcyBmb3IgRmxhcmVKU1xuICAgKi9cbiAgY3JlYXRlTWVtb0J5dGVzKG1lbW86IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgVWludDhBcnJheSk6IFVpbnQ4QXJyYXkge1xuICAgIGlmIChtZW1vIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBtZW1vID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRoaXMuc3RyaW5nVG9CeXRlcyhtZW1vKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG1lbW8gPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gdGhpcy5zdHJpbmdUb0J5dGVzKEpTT04uc3RyaW5naWZ5KG1lbW8pKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgbWVtbyBmb3JtYXQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBtZW1vIGJ5dGVzIHRvIHN0cmluZ1xuICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IG1lbW9CeXRlcyAtIE1lbW8gYnl0ZXMgZnJvbSBGbGFyZUpTIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IERlY29kZWQgbWVtbyBzdHJpbmdcbiAgICovXG4gIHBhcnNlTWVtb0J5dGVzKG1lbW9CeXRlczogVWludDhBcnJheSk6IHN0cmluZyB7XG4gICAgaWYgKG1lbW9CeXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYnl0ZXNUb1N0cmluZyhtZW1vQnl0ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIG1lbW8gc2l6ZSAoRmxhcmVKUyBoYXMgdHJhbnNhY3Rpb24gc2l6ZSBsaW1pdHMpXG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0gbWVtb0J5dGVzIC0gTWVtbyBieXRlc1xuICAgKiBAcGFyYW0ge251bWJlcn0gbWF4U2l6ZSAtIE1heGltdW0gc2l6ZSBpbiBieXRlcyAoZGVmYXVsdCA0S0IpXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIG1lbW8gaXMgd2l0aGluIHNpemUgbGltaXRzXG4gICAqL1xuICB2YWxpZGF0ZU1lbW9TaXplKG1lbW9CeXRlczogVWludDhBcnJheSwgbWF4U2l6ZSA9IDQwOTYpOiBib29sZWFuIHtcbiAgICByZXR1cm4gbWVtb0J5dGVzLmxlbmd0aCA8PSBtYXhTaXplO1xuICB9XG59XG5cbmNvbnN0IHV0aWxzID0gbmV3IFV0aWxzKCk7XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWxzO1xuIl19
|
|
514
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQVErQjtBQUMvQixtREFROEI7QUFFOUIsbUNBQWdDO0FBQ2hDLG1DQUFvQztBQUNwQyxxREFBNEM7QUFDNUMsbUNBQWtFO0FBQ2xFLGdEQUF3QjtBQUN4QixtQ0FBZ0M7QUFFaEMsTUFBYSxLQUFLO0lBQWxCO1FBaVFFOztXQUVHO1FBQ0ksb0JBQWUsR0FBRyxDQUFDLEdBQVcsRUFBRSxNQUFjLEVBQUUsT0FBZSxFQUFVLEVBQUU7WUFDaEYsK0RBQStEO1lBQy9ELE1BQU0sS0FBSyxHQUFHLGVBQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEMsK0VBQStFO1lBQy9FLE9BQU8sR0FBRyxNQUFNLElBQUksZUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNsRCxDQUFDLENBQUM7UUF5Q0YsbURBQW1EO1FBRW5EOzs7O1dBSUc7UUFDSCwyQ0FBMkM7UUFDcEMsaUJBQVksR0FBRyxDQUFDLE9BQWUsRUFBVSxFQUFFO1lBQ2hELE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUM7UUFFSyxvQkFBZSxHQUFHLENBQUMsT0FBZSxFQUFFLEdBQVksRUFBVSxFQUFFO1lBQ2pFLHVCQUF1QjtZQUN2QixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDN0IsT0FBTyxlQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDOUMsQ0FBQztZQUVELG1DQUFtQztZQUNuQyxJQUFJLG1CQUFtQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUN0QyxPQUFP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c0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgU2lnbmF0dXJlLFxuICBUcmFuc2ZlcmFibGVPdXRwdXQsXG4gIFRyYW5zZmVyT3V0cHV0LFxuICBUeXBlU3ltYm9scyxcbiAgSWQsXG4gIENyZWRlbnRpYWwsXG4gIHV0aWxzIGFzIEZsYXJlVXRpbHMsXG59IGZyb20gJ0BmbGFyZW5ldHdvcmsvZmxhcmVqcyc7XG5pbXBvcnQge1xuICBCYXNlVXRpbHMsXG4gIEVudHJ5LFxuICBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcixcbiAgaXNWYWxpZFhwcnYsXG4gIGlzVmFsaWRYcHViLFxuICBOb3RJbXBsZW1lbnRlZEVycm9yLFxuICBQYXJzZVRyYW5zYWN0aW9uRXJyb3IsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IEZsYXJlTmV0d29yayB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSAnYnVmZmVyJztcbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgZWNjIH0gZnJvbSAnQGJpdGdvLWJldGEvc2VjcDI1NmsxJztcbmltcG9ydCB7IEFERFJFU1NfU0VQQVJBVE9SLCBPdXRwdXQsIERlcHJlY2F0ZWRUeCB9IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IGJzNTggZnJvbSAnYnM1OCc7XG5pbXBvcnQgeyBiZWNoMzIgfSBmcm9tICdiZWNoMzInO1xuXG5leHBvcnQgY2xhc3MgVXRpbHMgaW1wbGVtZW50cyBCYXNlVXRpbHMge1xuICAvKipcbiAgICogQ2hlY2sgaWYgYWRkcmVzc2VzIGluIHdhbGxldCBtYXRjaCBVVFhPIG91dHB1dCBhZGRyZXNzZXNcbiAgICovXG4gIHB1YmxpYyBpbmNsdWRlSW4od2FsbGV0QWRkcmVzc2VzOiBzdHJpbmdbXSwgb3R4b091dHB1dEFkZHJlc3Nlczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gd2FsbGV0QWRkcmVzc2VzLm1hcCgoYSkgPT4gb3R4b091dHB1dEFkZHJlc3Nlcy5pbmNsdWRlcyhhKSkucmVkdWNlKChhLCBiKSA9PiBhICYmIGIsIHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIEZsYXJlIGFkZHJlc3Mgb3IgYXJyYXkgb2YgYWRkcmVzc2VzXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgc3RyaW5nW119IGFkZHJlc3MgLSBhZGRyZXNzKGVzKSB0byB2YWxpZGF0ZVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nIHwgc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICBjb25zdCBhZGRyZXNzQXJyOiBzdHJpbmdbXSA9IEFycmF5LmlzQXJyYXkoYWRkcmVzcykgPyBhZGRyZXNzIDogYWRkcmVzcy5zcGxpdCgnficpO1xuXG4gICAgZm9yIChjb25zdCBhZGRyZXNzIG9mIGFkZHJlc3NBcnIpIHtcbiAgICAgIGlmICghdGhpcy5pc1ZhbGlkQWRkcmVzc1JlZ2V4KGFkZHJlc3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIFJlZ2V4IHBhdHRlcm5zXG4gIC8vIGV4cG9ydCBjb25zdCBBRERSRVNTX1JFR0VYID0gL14oXlB8fE5vZGVJRCktW2EtekEtWjAtOV0rJC87XG4gIC8vIGV4cG9ydCBjb25zdCBIRVhfUkVHRVggPSAvXigweCl7MCwxfShbMC05YS1mXSkrJC9pO1xuXG4gIHByaXZhdGUgaXNWYWxpZEFkZHJlc3NSZWdleChhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gL14oXlB8fE5vZGVJRCktW2EtekEtWjAtOV0rJC8udGVzdChhZGRyZXNzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBibG9jayBJRFxuICAgKiBAcGFyYW0ge3N0cmluZ30gaGFzaCAtIGJsb2NrIElEIHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBpc1ZhbGlkQmxvY2tJZChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVjb2RlZCA9IEJ1ZmZlci5mcm9tKGhhc2gsICdoZXgnKTtcbiAgICAgIHJldHVybiBkZWNvZGVkLmxlbmd0aCA9PT0gMzI7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIHB1YmxpYyBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YiAtIHB1YmxpYyBrZXkgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIGlzVmFsaWRQdWJsaWNLZXkocHViOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoaXNWYWxpZFhwdWIocHViKSkgcmV0dXJuIHRydWU7XG5cbiAgICBsZXQgcHViQnVmOiBCdWZmZXI7XG4gICAgaWYgKHB1Yi5sZW5ndGggPT09IDUwKSB7XG4gICAgICB0cnkge1xuICAgICAgICBwdWJCdWYgPSBCdWZmZXIuZnJvbShwdWIsICdoZXgnKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChwdWIubGVuZ3RoICE9PSA2NiAmJiBwdWIubGVuZ3RoICE9PSAxMzApIHJldHVybiBmYWxzZTtcblxuICAgICAgY29uc3QgZmlyc3RCeXRlID0gcHViLnNsaWNlKDAsIDIpO1xuICAgICAgaWYgKHB1Yi5sZW5ndGggPT09IDEzMCAmJiBmaXJzdEJ5dGUgIT09ICcwNCcpIHJldHVybiBmYWxzZTtcbiAgICAgIGlmIChwdWIubGVuZ3RoID09PSA2NiAmJiBmaXJzdEJ5dGUgIT09ICcwMicgJiYgZmlyc3RCeXRlICE9PSAnMDMnKSByZXR1cm4gZmFsc2U7XG4gICAgICBpZiAoIXRoaXMuYWxsSGV4Q2hhcnMocHViKSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICBwdWJCdWYgPSBCdWZmZXIuZnJvbShwdWIsICdoZXgnKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgZWNjLmlzUG9pbnQocHViQnVmKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgcHJpdmF0ZSBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBydiAtIHByaXZhdGUga2V5IHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBpc1ZhbGlkUHJpdmF0ZUtleShwcnY6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmIChpc1ZhbGlkWHBydihwcnYpKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAocHJ2Lmxlbmd0aCAhPT0gNjQgJiYgcHJ2Lmxlbmd0aCAhPT0gNjYpIHJldHVybiBmYWxzZTtcbiAgICBpZiAocHJ2Lmxlbmd0aCA9PT0gNjYgJiYgcHJ2LnNsaWNlKDY0KSAhPT0gJzAxJykgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0aGlzLmFsbEhleENoYXJzKHBydik7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgc3RyaW5nIGNvbnRhaW5zIG9ubHkgaGV4IGNoYXJhY3RlcnNcbiAgICovXG4gIGFsbEhleENoYXJzKHN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIC9eKDB4KXswLDF9KFswLTlhLWZdKSskL2kudGVzdChzdHIpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzaWduYXR1cmUgdXNpbmcgdGhlIEZsYXJlIG5ldHdvcmsgcGFyYW1ldGVyc1xuICAgKiBSZXR1cm5zIGEgNjUtYnl0ZSBzaWduYXR1cmUgKDY0IGJ5dGVzIHNpZ25hdHVyZSArIDEgYnl0ZSByZWNvdmVyeSBwYXJhbWV0ZXIpXG4gICAqL1xuICBjcmVhdGVTaWduYXR1cmUobmV0d29yazogRmxhcmVOZXR3b3JrLCBtZXNzYWdlOiBCdWZmZXIsIHBydjogQnVmZmVyKTogQnVmZmVyIHtcbiAgICBjb25zdCBtZXNzYWdlSGFzaCA9IHRoaXMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgIGNvbnN0IHNpZ25hdHVyZSA9IGVjYy5zaWduKG1lc3NhZ2VIYXNoLCBwcnYpO1xuXG4gICAgLy8gR2V0IHRoZSBwdWJsaWMga2V5IGZyb20gdGhlIHByaXZhdGUga2V5IGZvciByZWNvdmVyeSBwYXJhbWV0ZXIgZGV0ZXJtaW5hdGlvblxuICAgIGNvbnN0IHB1YmxpY0tleSA9IGVjYy5wb2ludEZyb21TY2FsYXIocHJ2LCB0cnVlKTtcbiAgICBpZiAoIXB1YmxpY0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZGVyaXZlIHB1YmxpYyBrZXkgZnJvbSBwcml2YXRlIGtleScpO1xuICAgIH1cblxuICAgIC8vIFRyeSByZWNvdmVyeSB3aXRoIHBhcmFtIDAgYW5kIDEgdG8gZmluZCB0aGUgY29ycmVjdCBvbmVcbiAgICBsZXQgcmVjb3ZlcnlQYXJhbSA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMTsgaSsrKSB7XG4gICAgICBjb25zdCByZWNvdmVyZWQgPSBlY2MucmVjb3ZlclB1YmxpY0tleShtZXNzYWdlSGFzaCwgc2lnbmF0dXJlLCBpLCB0cnVlKTtcbiAgICAgIGlmIChyZWNvdmVyZWQgJiYgQnVmZmVyLmZyb20ocmVjb3ZlcmVkKS5lcXVhbHMoQnVmZmVyLmZyb20ocHVibGljS2V5KSkpIHtcbiAgICAgICAgcmVjb3ZlcnlQYXJhbSA9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFwcGVuZCByZWNvdmVyeSBwYXJhbWV0ZXIgdG8gY3JlYXRlIDY1LWJ5dGUgc2lnbmF0dXJlXG4gICAgY29uc3Qgc2lnV2l0aFJlY292ZXJ5ID0gQnVmZmVyLmFsbG9jKDY1KTtcbiAgICBCdWZmZXIuZnJvbShzaWduYXR1cmUpLmNvcHkoc2lnV2l0aFJlY292ZXJ5LCAwKTtcbiAgICBzaWdXaXRoUmVjb3ZlcnlbNjRdID0gcmVjb3ZlcnlQYXJhbTtcblxuICAgIHJldHVybiBzaWdXaXRoUmVjb3Zlcnk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpZXMgYSBzaWduYXR1cmVcbiAgICovXG4gIHZlcmlmeVNpZ25hdHVyZShuZXR3b3JrOiBGbGFyZU5ldHdvcmssIG1lc3NhZ2U6IEJ1ZmZlciwgc2lnbmF0dXJlOiBCdWZmZXIsIHB1YmxpY0tleTogQnVmZmVyKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1lc3NhZ2VIYXNoID0gdGhpcy5zaGEyNTYobWVzc2FnZSk7XG4gICAgICByZXR1cm4gZWNjLnZlcmlmeShzaWduYXR1cmUsIG1lc3NhZ2VIYXNoLCBwdWJsaWNLZXkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBzaWduYXR1cmUgb2JqZWN0XG4gICAqL1xuICBjcmVhdGVOZXdTaWcoc2lnSGV4OiBzdHJpbmcpOiBTaWduYXR1cmUge1xuICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHNpZ0hleC5wYWRTdGFydCgxMzAsICcwJyksICdoZXgnKTtcbiAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShidWZmZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gZW1wdHkgc2lnbmF0dXJlIHdpdGggZW1iZWRkZWQgYWRkcmVzcyBmb3Igc2lnbmF0dXJlIHNsb3QgaWRlbnRpZmljYXRpb24uXG4gICAqIFRoZSBhZGRyZXNzIGlzIGVtYmVkZGVkIGF0IHBvc2l0aW9uIDkwIChhZnRlciB0aGUgZmlyc3QgNDUgemVybyBieXRlcykuXG4gICAqIFRoaXMgYWxsb3dzIHRoZSBzaWduaW5nIGxvZ2ljIHRvIGRldGVybWluZSB3aGljaCBzbG90IGJlbG9uZ3MgdG8gd2hpY2ggYWRkcmVzcy5cbiAgICogQHBhcmFtIGFkZHJlc3NIZXggVGhlIDIwLWJ5dGUgYWRkcmVzcyBpbiBoZXggZm9ybWF0ICg0MCBjaGFycywgd2l0aG91dCAweCBwcmVmaXgpXG4gICAqL1xuICBjcmVhdGVFbXB0eVNpZ1dpdGhBZGRyZXNzKGFkZHJlc3NIZXg6IHN0cmluZyk6IFNpZ25hdHVyZSB7XG4gICAgLy8gRmlyc3QgNDUgYnl0ZXMgKDkwIGhleCBjaGFycykgYXJlIHplcm9zLCBmb2xsb3dlZCBieSAyMC1ieXRlIGFkZHJlc3MgKDQwIGhleCBjaGFycylcbiAgICBjb25zdCBjbGVhbkFkZHIgPSB0aGlzLnJlbW92ZUhleFByZWZpeChhZGRyZXNzSGV4KS50b0xvd2VyQ2FzZSgpO1xuICAgIGNvbnN0IHNpZ0hleCA9ICcwJy5yZXBlYXQoOTApICsgY2xlYW5BZGRyLnBhZFN0YXJ0KDQwLCAnMCcpO1xuICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHNpZ0hleCwgJ2hleCcpO1xuICAgIHJldHVybiBuZXcgU2lnbmF0dXJlKGJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdHMgdGhlIGVtYmVkZGVkIGFkZHJlc3MgZnJvbSBhbiBlbXB0eSBzaWduYXR1cmUuXG4gICAqIFJldHVybnMgdGhlIGFkZHJlc3MgaGV4IHN0cmluZyAoNDAgY2hhcnMpIG9yIGVtcHR5IHN0cmluZyBpZiBub3QgZm91bmQuXG4gICAqL1xuICBnZXRBZGRyZXNzRnJvbUVtcHR5U2lnKHNpZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBjbGVhblNpZyA9IHRoaXMucmVtb3ZlSGV4UHJlZml4KHNpZyk7XG4gICAgaWYgKGNsZWFuU2lnLmxlbmd0aCA+PSAxMzApIHtcbiAgICAgIC8vIEFkZHJlc3MgaXMgYXQgcG9zaXRpb24gOTAtMTMwIChsYXN0IDQwIGhleCBjaGFycyA9IDIwIGJ5dGVzKVxuICAgICAgcmV0dXJuIGNsZWFuU2lnLnN1YnN0cmluZyg5MCwgMTMwKS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogQ29tcHV0ZXMgU0hBMjU2IGhhc2hcbiAgICovXG4gIHNoYTI1NihidWY6IFVpbnQ4QXJyYXkpOiBCdWZmZXIge1xuICAgIHJldHVybiBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoYnVmKS5kaWdlc3QoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgcmF3IHRyYW5zYWN0aW9uIGZvcm1hdFxuICAgKi9cbiAgdmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFyYXdUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdSYXcgdHJhbnNhY3Rpb24gaXMgZW1wdHknKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmFsbEhleENoYXJzKHJhd1RyYW5zYWN0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlVHJhbnNhY3Rpb25FcnJvcignUmF3IHRyYW5zYWN0aW9uIGlzIG5vdCBoZXggc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBvdXRwdXQgaXMgVHJhbnNmZXJhYmxlT3V0cHV0IHR5cGVcbiAgICovXG4gIGlzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dDogT3V0cHV0KTogb3V0cHV0IGlzIFRyYW5zZmVyYWJsZU91dHB1dCB7XG4gICAgcmV0dXJuIG91dHB1dD8uX3R5cGUgPT09IFR5cGVTeW1ib2xzLlRyYW5zZmVyYWJsZU91dHB1dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIG91dHB1dHMgdG8gZW50cnkgZm9ybWF0XG4gICAqL1xuICBtYXBPdXRwdXRUb0VudHJ5KG5ldHdvcms6IEZsYXJlTmV0d29yayk6IChPdXRwdXQpID0+IEVudHJ5IHtcbiAgICByZXR1cm4gKG91dHB1dDogT3V0cHV0KSA9PiB7XG4gICAgICBpZiAodGhpcy5pc1RyYW5zZmVyYWJsZU91dHB1dChvdXRwdXQpKSB7XG4gICAgICAgIGNvbnN0IG91dHB1dEFtb3VudCA9IG91dHB1dC5hbW91bnQoKTtcbiAgICAgICAgY29uc3QgYWRkcmVzcyA9IChvdXRwdXQub3V0cHV0IGFzIFRyYW5zZmVyT3V0cHV0KVxuICAgICAgICAgIC5nZXRPd25lcnMoKVxuICAgICAgICAgIC5tYXAoKGEpID0+IHRoaXMuYWRkcmVzc1RvU3RyaW5nKG5ldHdvcmsuaHJwLCBuZXR3b3JrLmFsaWFzLCBCdWZmZXIuZnJvbShhKSkpXG4gICAgICAgICAgLnNvcnQoKVxuICAgICAgICAgIC5qb2luKEFERFJFU1NfU0VQQVJBVE9SKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2YWx1ZTogb3V0cHV0QW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBvdXRwdXQgdHlwZScpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyAweCBwcmVmaXggZnJvbSBoZXggc3RyaW5nXG4gICAqL1xuICByZW1vdmVIZXhQcmVmaXgoaGV4OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBoZXguc3RhcnRzV2l0aCgnMHgnKSA/IGhleC5zdWJzdHJpbmcoMikgOiBoZXg7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb3V0cHV0IGluZGV4IHRvIGJ1ZmZlclxuICAgKi9cbiAgb3V0cHV0aWR4TnVtYmVyVG9CdWZmZXIob3V0cHV0aWR4OiBzdHJpbmcpOiBCdWZmZXIge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShOdW1iZXIob3V0cHV0aWR4KS50b1N0cmluZygxNikucGFkU3RhcnQoOCwgJzAnKSwgJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIG91dHB1dCBpbmRleCBidWZmZXIgdG8gbnVtYmVyIHN0cmluZ1xuICAgKi9cbiAgb3V0cHV0aWR4QnVmZmVyVG9OdW1iZXIob3V0cHV0aWR4OiBCdWZmZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiBwYXJzZUludChvdXRwdXRpZHgudG9TdHJpbmcoJ2hleCcpLCAxNikudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8vIFJlcXVpcmVkIGJ5IEJhc2VVdGlscyBpbnRlcmZhY2UgYnV0IG5vdCBpbXBsZW1lbnRlZFxuICBpc1ZhbGlkU2lnbmF0dXJlKHNpZ25hdHVyZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2lzVmFsaWRTaWduYXR1cmUgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICBpc1ZhbGlkVHJhbnNhY3Rpb25JZCh0eElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcignaXNWYWxpZFRyYW5zYWN0aW9uSWQgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIG1ldGhvZCB0byBjb252ZXJ0IGFkZHJlc3MgY29tcG9uZW50cyB0byBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyBhZGRyZXNzVG9TdHJpbmcgPSAoaHJwOiBzdHJpbmcsIHByZWZpeDogc3RyaW5nLCBhZGRyZXNzOiBCdWZmZXIpOiBzdHJpbmcgPT4ge1xuICAgIC8vIENvbnZlcnQgdGhlIGFkZHJlc3MgYnl0ZXMgdG8gNS1iaXQgd29yZHMgZm9yIGJlY2gzMiBlbmNvZGluZ1xuICAgIGNvbnN0IHdvcmRzID0gYmVjaDMyLnRvV29yZHMoYWRkcmVzcyk7XG4gICAgLy8gQ3JlYXRlIHRoZSBmdWxsIGJlY2gzMiBhZGRyZXNzIHdpdGggZm9ybWF0OiBQLXtocnB9MXtiZWNoMzJfZW5jb2RlZF9hZGRyZXNzfVxuICAgIHJldHVybiBgJHtwcmVmaXh9LSR7YmVjaDMyLmVuY29kZShocnAsIHdvcmRzKX1gO1xuICB9O1xuXG4gIC8qKlxuICAgKiBEZWNvZGVzIGEgYmFzZTU4IHN0cmluZyB3aXRoIGNoZWNrc3VtIHRvIGEgQnVmZmVyXG4gICAqL1xuICBwdWJsaWMgY2I1OERlY29kZShzdHI6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgY29uc3QgZGVjb2RlZCA9IGJzNTguZGVjb2RlKHN0cik7XG4gICAgaWYgKCF0aGlzLnZhbGlkYXRlQ2hlY2tzdW0oQnVmZmVyLmZyb20oZGVjb2RlZCkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY2hlY2tzdW0nKTtcbiAgICB9XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRlY29kZWQuc2xpY2UoMCwgZGVjb2RlZC5sZW5ndGggLSA0KSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgY2hlY2tzdW0gb24gYSBCdWZmZXIgYW5kIHJldHVybnMgdHJ1ZSBpZiB2YWxpZCwgZmFsc2UgaWYgbm90XG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlQ2hlY2tzdW0oYnVmZjogQnVmZmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaGFzaFNsaWNlID0gYnVmZi5zbGljZShidWZmLmxlbmd0aCAtIDQpO1xuICAgIGNvbnN0IGNhbGN1bGF0ZWRIYXNoU2xpY2UgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKVxuICAgICAgLnVwZGF0ZShidWZmLnNsaWNlKDAsIGJ1ZmYubGVuZ3RoIC0gNCkpXG4gICAgICAuZGlnZXN0KClcbiAgICAgIC5zbGljZSgyOCk7XG4gICAgcmV0dXJuIGhhc2hTbGljZS50b1N0cmluZygnaGV4JykgPT09IGNhbGN1bGF0ZWRIYXNoU2xpY2UudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuY29kZXMgYSBCdWZmZXIgYXMgYSBiYXNlNTggc3RyaW5nIHdpdGggY2hlY2tzdW1cbiAgICovXG4gIHB1YmxpYyBjYjU4RW5jb2RlKGJ5dGVzOiBCdWZmZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IHdpdGhDaGVja3N1bSA9IHRoaXMuYWRkQ2hlY2tzdW0oYnl0ZXMpO1xuICAgIHJldHVybiBiczU4LmVuY29kZSh3aXRoQ2hlY2tzdW0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjaGVja3N1bSB0byBhIEJ1ZmZlciBhbmQgcmV0dXJucyB0aGUgY29uY2F0ZW5hdGVkIHJlc3VsdFxuICAgKi9cbiAgcHJpdmF0ZSBhZGRDaGVja3N1bShidWZmOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIGNvbnN0IGhhc2hTbGljZSA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShidWZmKS5kaWdlc3QoKS5zbGljZSgyOCk7XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoW2J1ZmYsIGhhc2hTbGljZV0pO1xuICB9XG5cbiAgLy8gSW4gdXRpbHMudHMsIGFkZCB0aGlzIG1ldGhvZCB0byB0aGUgVXRpbHMgY2xhc3M6XG5cbiAgLyoqXG4gICAqIFBhcnNlIGFuIGFkZHJlc3Mgc3RyaW5nIGludG8gYSBCdWZmZXJcbiAgICogQHBhcmFtIGFkZHJlc3MgLSBUaGUgYWRkcmVzcyB0byBwYXJzZVxuICAgKiBAcmV0dXJucyBCdWZmZXIgY29udGFpbmluZyB0aGUgcGFyc2VkIGFkZHJlc3NcbiAgICovXG4gIC8vVE9ETzogbmVlZCBjaGVjayBhbmQgdmFsaWRhdGUgdGhpcyBtZXRob2RcbiAgcHVibGljIHBhcnNlQWRkcmVzcyA9IChhZGRyZXNzOiBzdHJpbmcpOiBCdWZmZXIgPT4ge1xuICAgIHJldHVybiB0aGlzLnN0cmluZ1RvQWRkcmVzcyhhZGRyZXNzKTtcbiAgfTtcblxuICBwdWJsaWMgc3RyaW5nVG9BZGRyZXNzID0gKGFkZHJlc3M6IHN0cmluZywgaHJwPzogc3RyaW5nKTogQnVmZmVyID0+IHtcbiAgICAvLyBIYW5kbGUgaGV4IGFkZHJlc3Nlc1xuICAgIGlmIChhZGRyZXNzLnN0YXJ0c1dpdGgoJzB4JykpIHtcbiAgICAgIHJldHVybiBCdWZmZXIuZnJvbShhZGRyZXNzLnNsaWNlKDIpLCAnaGV4Jyk7XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHJhdyBoZXggd2l0aG91dCAweCBwcmVmaXhcbiAgICBpZiAoL15bMC05YS1mQS1GXXs0MH0kLy50ZXN0KGFkZHJlc3MpKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oYWRkcmVzcywgJ2hleCcpO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSBCZWNoMzIgYWRkcmVzc2VzXG4gICAgY29uc3QgcGFydHMgPSBhZGRyZXNzLnRyaW0oKS5zcGxpdCgnLScpO1xuICAgIGlmIChwYXJ0cy5sZW5ndGggPCAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIC0gVmFsaWQgYWRkcmVzcyBzaG91bGQgaW5jbHVkZSAtJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3BsaXQgPSBwYXJ0c1sxXS5sYXN0SW5kZXhPZignMScpO1xuICAgIGlmIChzcGxpdCA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXJyb3IgLSBWYWxpZCBiZWNoMzIgYWRkcmVzcyBtdXN0IGluY2x1ZGUgc2VwYXJhdG9yICgxKScpO1xuICAgIH1cblxuICAgIGNvbnN0IGh1bWFuUmVhZGFibGVQYXJ0ID0gcGFydHNbMV0uc2xpY2UoMCwgc3BsaXQpO1xuICAgIGlmIChodW1hblJlYWRhYmxlUGFydCAhPT0gJ2ZsYXJlJyAmJiBodW1hblJlYWRhYmxlUGFydCAhPT0gJ2Nvc3R3bycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXJyb3IgLSBJbnZhbGlkIEhSUCcpO1xuICAgIH1cblxuICAgIHJldHVybiBCdWZmZXIuZnJvbShiZWNoMzIuZnJvbVdvcmRzKGJlY2gzMi5kZWNvZGUocGFydHNbMV0pLndvcmRzKSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHR4IGlzIGZvciB0aGUgYmxvY2tjaGFpbklkXG4gICAqXG4gICAqIEBwYXJhbSB7RGVwcmVjYXRlZFR4fSB0eFxuICAgKiBAcGFyYW0ge3N0cmluZ30gYmxvY2tjaGFpbklkXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdHggaXMgZm9yIGJsb2NrY2hhaW5JZFxuICAgKi9cbiAgLy8gVE9ETzogcmVtb3ZlIERlcHJlY2F0ZWRUeCB1c2FnZVxuICBpc1RyYW5zYWN0aW9uT2YodHg6IERlcHJlY2F0ZWRUeCwgYmxvY2tjaGFpbklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAvLyBGbGFyZUpTIGVxdWl2YWxlbnQgLSB0aGlzIHdvdWxkIG5lZWQgcHJvcGVyIENCNTggZW5jb2RpbmcgaW1wbGVtZW50YXRpb25cbiAgICB0cnkge1xuICAgICAgY29uc3QgdHhSZWNvcmQgPSB0eCBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgY29uc3QgdW5zaWduZWRUeCA9ICh0eFJlY29yZC5nZXRVbnNpZ25lZFR4IGFzICgpID0+IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSgpO1xuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAodW5zaWduZWRUeC5nZXRUcmFuc2FjdGlvbiBhcyAoKSA9PiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikoKTtcbiAgICAgIGNvbnN0IHR4QmxvY2tjaGFpbklkID0gKHRyYW5zYWN0aW9uLmdldEJsb2NrY2hhaW5JRCBhcyAoKSA9PiB1bmtub3duKSgpO1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHR4QmxvY2tjaGFpbklkIGFzIHN0cmluZykudG9TdHJpbmcoJ2hleCcpID09PSBibG9ja2NoYWluSWQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBmbGFyZUlkU3RyaW5nKHZhbHVlOiBzdHJpbmcpOiBJZCB7XG4gICAgcmV0dXJuIG5ldyBJZChCdWZmZXIuZnJvbSh2YWx1ZSwgJ2hleCcpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0IGNyZWRlbnRpYWxzIGZyb20gcmF3IHRyYW5zYWN0aW9uIGJ5dGVzLlxuICAgKiBTaWduZWQgdHJhbnNhY3Rpb25zIGhhdmUgY3JlZGVudGlhbHMgYXBwZW5kZWQgYWZ0ZXIgdGhlIHRyYW5zYWN0aW9uIGJvZHkuXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyBib3RoIGNoZWNraW5nIGZvciBjcmVkZW50aWFscyBhbmQgZXh0cmFjdGluZyB0aGVtLlxuICAgKlxuICAgKiBAcGFyYW0gcmF3Qnl0ZXMgLSBUaGUgZnVsbCByYXcgdHJhbnNhY3Rpb24gYnl0ZXNcbiAgICogQHBhcmFtIHR4IC0gVGhlIHBhcnNlZCB0cmFuc2FjdGlvbiAobXVzdCBoYXZlIHRvQnl0ZXMgbWV0aG9kKVxuICAgKiBAcGFyYW0gdm1UeXBlIC0gVGhlIFZNIHR5cGUgKCdFVk0nIG9yICdQVk0nKSB0byBnZXQgdGhlIGNvcnJlY3QgY29kZWNcbiAgICogQHJldHVybnMgT2JqZWN0IHdpdGggaGFzQ3JlZGVudGlhbHMgZmxhZyBhbmQgY3JlZGVudGlhbHMgYXJyYXlcbiAgICovXG4gIGV4dHJhY3RDcmVkZW50aWFsc0Zyb21SYXdCeXRlcyhcbiAgICByYXdCeXRlczogQnVmZmVyLFxuICAgIHR4OiB7IHRvQnl0ZXMoY29kZWM6IHVua25vd24pOiBVaW50OEFycmF5IH0sXG4gICAgdm1UeXBlOiAnRVZNJyB8ICdQVk0nID0gJ0VWTSdcbiAgKTogeyBoYXNDcmVkZW50aWFsczogYm9vbGVhbjsgY3JlZGVudGlhbHM6IENyZWRlbnRpYWxbXSB9IHtcbiAgICB0cnkge1xuICAgICAgLy8gR2V0IHRoZSBzaXplIG9mIHRoZSB0cmFuc2FjdGlvbiB3aXRob3V0IGNyZWRlbnRpYWxzIHVzaW5nIHRoZSBkZWZhdWx0IGNvZGVjXG4gICAgICBjb25zdCBjb2RlYyA9IEZsYXJlVXRpbHMuZ2V0TWFuYWdlckZvclZNKHZtVHlwZSkuZ2V0RGVmYXVsdENvZGVjKCk7XG4gICAgICBjb25zdCB0eEJ5dGVzID0gdHgudG9CeXRlcyhjb2RlYyk7XG4gICAgICBjb25zdCB0eFNpemUgPSB0eEJ5dGVzLmxlbmd0aDtcblxuICAgICAgLy8gSWYgcmF3IGJ5dGVzIGFyZSBub3QgbG9uZ2VyIHRoYW4gdHggYnl0ZXMsIHRoZXJlIGFyZSBubyBjcmVkZW50aWFsc1xuICAgICAgaWYgKHJhd0J5dGVzLmxlbmd0aCA8PSB0eFNpemUpIHtcbiAgICAgICAgcmV0dXJuIHsgaGFzQ3JlZGVudGlhbHM6IGZhbHNlLCBjcmVkZW50aWFsczogW10gfTtcbiAgICAgIH1cblxuICAgICAgLy8gRXh0cmFjdCBjcmVkZW50aWFsIGJ5dGVzIChldmVyeXRoaW5nIGFmdGVyIHRoZSB0cmFuc2FjdGlvbilcbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxCeXRlcyA9IHJhd0J5dGVzLnNsaWNlKHR4U2l6ZSk7XG5cbiAgICAgIC8vIFBhcnNlIGNyZWRlbnRpYWxzXG4gICAgICAvLyBGb3JtYXQ6IFtudW1fY3JlZGVudGlhbHM6IDQgYnl0ZXNdIFtjcmVkZW50aWFscy4uLl1cbiAgICAgIGlmIChjcmVkZW50aWFsQnl0ZXMubGVuZ3RoIDwgNCkge1xuICAgICAgICByZXR1cm4geyBoYXNDcmVkZW50aWFsczogZmFsc2UsIGNyZWRlbnRpYWxzOiBbXSB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBudW1DcmVkZW50aWFscyA9IGNyZWRlbnRpYWxCeXRlcy5yZWFkVUludDMyQkUoMCk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoZXJlIGFyZSBjcmVkZW50aWFscyBpbiByYXcgYnl0ZXMgKGZvciBoYXNDcmVkZW50aWFscyBmbGFnKVxuICAgICAgY29uc3QgaGFzQ3JlZGVudGlhbHMgPSBudW1DcmVkZW50aWFscyA+IDA7XG5cbiAgICAgIGlmIChudW1DcmVkZW50aWFscyA9PT0gMCkge1xuICAgICAgICByZXR1cm4geyBoYXNDcmVkZW50aWFsczogZmFsc2UsIGNyZWRlbnRpYWxzOiBbXSB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjcmVkZW50aWFsczogQ3JlZGVudGlhbFtdID0gW107XG4gICAgICBsZXQgb2Zmc2V0ID0gNDtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1DcmVkZW50aWFsczsgaSsrKSB7XG4gICAgICAgIGlmIChvZmZzZXQgKyA4ID4gY3JlZGVudGlhbEJ5dGVzLmxlbmd0aCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVhZCB0eXBlIElEICg0IGJ5dGVzKSAtIFR5cGUgSUQgOSA9IHNlY3AyNTZrMSBjcmVkZW50aWFsXG4gICAgICAgIGNvbnN0IHR5cGVJZCA9IGNyZWRlbnRpYWxCeXRlcy5yZWFkVUludDMyQkUob2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0ICs9IDQ7XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgY3JlZGVudGlhbCB0eXBlICg5ID0gc2VjcDI1NmsxKVxuICAgICAgICBpZiAodHlwZUlkICE9PSA5KSB7XG4gICAgICAgICAgY29udGludWU7IC8vIFNraXAgdW5zdXBwb3J0ZWQgY3JlZGVudGlhbCB0eXBlc1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVhZCBudW1iZXIgb2Ygc2lnbmF0dXJlcyAoNCBieXRlcylcbiAgICAgICAgY29uc3QgbnVtU2lncyA9IGNyZWRlbnRpYWxCeXRlcy5yZWFkVUludDMyQkUob2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0ICs9IDQ7XG5cbiAgICAgICAgLy8gUGFyc2UgYWxsIHNpZ25hdHVyZXMgZm9yIHRoaXMgY3JlZGVudGlhbFxuICAgICAgICBjb25zdCBzaWduYXR1cmVzOiBTaWduYXR1cmVbXSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bVNpZ3M7IGorKykge1xuICAgICAgICAgIGlmIChvZmZzZXQgKyA2NSA+IGNyZWRlbnRpYWxCeXRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBFYWNoIHNpZ25hdHVyZSBpcyA2NSBieXRlcyAoNjQgYnl0ZXMgc2lnbmF0dXJlICsgMSBieXRlIHJlY292ZXJ5KVxuICAgICAgICAgIGNvbnN0IHNpZ0J5dGVzID0gQnVmZmVyLmZyb20oY3JlZGVudGlhbEJ5dGVzLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgNjUpKTtcbiAgICAgICAgICBzaWduYXR1cmVzLnB1c2gobmV3IFNpZ25hdHVyZShzaWdCeXRlcykpO1xuICAgICAgICAgIG9mZnNldCArPSA2NTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBjcmVkZW50aWFsIHdpdGggdGhlIHBhcnNlZCBzaWduYXR1cmVzXG4gICAgICAgIGlmIChzaWduYXR1cmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjcmVkZW50aWFscy5wdXNoKG5ldyBDcmVkZW50aWFsKHNpZ25hdHVyZXMpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4geyBoYXNDcmVkZW50aWFscywgY3JlZGVudGlhbHMgfTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBJZiBwYXJzaW5nIGZhaWxzLCByZXR1cm4gbm8gY3JlZGVudGlhbHNcbiAgICAgIHJldHVybiB7IGhhc0NyZWRlbnRpYWxzOiBmYWxzZSwgY3JlZGVudGlhbHM6IFtdIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIGNyZWRlbnRpYWxzIGZyb20gcmF3IGJ5dGVzIGF0IGEgc3BlY2lmaWMgb2Zmc2V0XG4gICAqIFRoaXMgaXMgdXNlZnVsIHdoZW4gdGhlIHN0YW5kYXJkIGV4dHJhY3Rpb24gZmFpbHMgZHVlIHRvIHNlcmlhbGl6YXRpb24gZGlmZmVyZW5jZXNcbiAgICogQHBhcmFtIHJhd0J5dGVzIFJhdyB0cmFuc2FjdGlvbiBieXRlcyBpbmNsdWRpbmcgY3JlZGVudGlhbHNcbiAgICogQHBhcmFtIG9mZnNldCBCeXRlIG9mZnNldCB3aGVyZSBjcmVkZW50aWFscyBzdGFydFxuICAgKiBAcmV0dXJucyBBcnJheSBvZiBwYXJzZWQgY3JlZGVudGlhbHNcbiAgICovXG4gIHBhcnNlQ3JlZGVudGlhbHNBdE9mZnNldChyYXdCeXRlczogQnVmZmVyLCBvZmZzZXQ6IG51bWJlcik6IENyZWRlbnRpYWxbXSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChyYXdCeXRlcy5sZW5ndGggPD0gb2Zmc2V0ICsgNCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxCeXRlcyA9IHJhd0J5dGVzLnNsaWNlKG9mZnNldCk7XG4gICAgICBjb25zdCBudW1DcmVkZW50aWFscyA9IGNyZWRlbnRpYWxCeXRlcy5yZWFkVUludDMyQkUoMCk7XG5cbiAgICAgIGlmIChudW1DcmVkZW50aWFscyA9PT0gMCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxzOiBDcmVkZW50aWFsW10gPSBbXTtcbiAgICAgIGxldCBwb3MgPSA0O1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNyZWRlbnRpYWxzOyBpKyspIHtcbiAgICAgICAgaWYgKHBvcyArIDggPiBjcmVkZW50aWFsQnl0ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWFkIHR5cGUgSUQgKDQgYnl0ZXMpIC0gVHlwZSBJRCA5ID0gc2VjcDI1NmsxIGNyZWRlbnRpYWxcbiAgICAgICAgY29uc3QgdHlwZUlkID0gY3JlZGVudGlhbEJ5dGVzLnJlYWRVSW50MzJCRShwb3MpO1xuICAgICAgICBwb3MgKz0gNDtcblxuICAgICAgICBpZiAodHlwZUlkICE9PSA5KSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWFkIG51bWJlciBvZiBzaWduYXR1cmVzICg0IGJ5dGVzKVxuICAgICAgICBjb25zdCBudW1TaWdzID0gY3JlZGVudGlhbEJ5dGVzLnJlYWRVSW50MzJCRShwb3MpO1xuICAgICAgICBwb3MgKz0gNDtcblxuICAgICAgICAvLyBQYXJzZSBhbGwgc2lnbmF0dXJlcyBmb3IgdGhpcyBjcmVkZW50aWFsXG4gICAgICAgIGNvbnN0IHNpZ25hdHVyZXM6IFNpZ25hdHVyZVtdID0gW107XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtU2lnczsgaisrKSB7XG4gICAgICAgICAgaWYgKHBvcyArIDY1ID4gY3JlZGVudGlhbEJ5dGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHNpZ0J5dGVzID0gQnVmZmVyLmZyb20oY3JlZGVudGlhbEJ5dGVzLnNsaWNlKHBvcywgcG9zICsgNjUpKTtcbiAgICAgICAgICBzaWduYXR1cmVzLnB1c2gobmV3IFNpZ25hdHVyZShzaWdCeXRlcykpO1xuICAgICAgICAgIHBvcyArPSA2NTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzaWduYXR1cmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjcmVkZW50aWFscy5wdXNoKG5ldyBDcmVkZW50aWFsKHNpZ25hdHVyZXMpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gY3JlZGVudGlhbHM7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZsYXJlSlMgd3JhcHBlciB0byByZWNvdmVyIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0gbmV0d29ya1xuICAgKiBAcGFyYW0gbWVzc2FnZVxuICAgKiBAcGFyYW0gc2lnbmF0dXJlXG4gICAqIEByZXR1cm4gcmVjb3ZlcmVkIHB1YmxpYyBrZXlcbiAgICovXG4gIHJlY292ZXJ5U2lnbmF0dXJlKG5ldHdvcms6IEZsYXJlTmV0d29yaywgbWVzc2FnZTogQnVmZmVyLCBzaWduYXR1cmU6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEhhc2ggdGhlIG1lc3NhZ2UgZmlyc3QgLSBtdXN0IG1hdGNoIHRoZSBoYXNoIHVzZWQgaW4gc2lnbmluZ1xuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUobWVzc2FnZSkuZGlnZXN0KCk7XG5cbiAgICAgIC8vIEV4dHJhY3QgcmVjb3ZlcnkgcGFyYW1ldGVyIGFuZCBzaWduYXR1cmVcbiAgICAgIGlmIChzaWduYXR1cmUubGVuZ3RoICE9PSA2NSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlIGxlbmd0aCAtIGV4cGVjdGVkIDY1IGJ5dGVzICg2NCBieXRlcyBzaWduYXR1cmUgKyAxIGJ5dGUgcmVjb3ZlcnkpJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlY292ZXJ5UGFyYW0gPSBzaWduYXR1cmVbNjRdO1xuICAgICAgY29uc3Qgc2lnT25seSA9IHNpZ25hdHVyZS5zbGljZSgwLCA2NCk7XG5cbiAgICAgIC8vIFJlY292ZXIgcHVibGljIGtleSB1c2luZyB0aGUgcHJvdmlkZWQgcmVjb3ZlcnkgcGFyYW1ldGVyXG4gICAgICBjb25zdCByZWNvdmVyZWQgPSBlY2MucmVjb3ZlclB1YmxpY0tleShtZXNzYWdlSGFzaCwgc2lnT25seSwgcmVjb3ZlcnlQYXJhbSwgdHJ1ZSk7XG4gICAgICBpZiAoIXJlY292ZXJlZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byByZWNvdmVyIHB1YmxpYyBrZXknKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHJlY292ZXJlZCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJlY292ZXIgc2lnbmF0dXJlOiAke2Vycm9yfWApO1xuICAgIH1cbiAgfVxufVxuXG5jb25zdCB1dGlscyA9IG5ldyBVdGlscygpO1xuZXhwb3J0IGRlZmF1bHQgdXRpbHM7XG4iXX0=
|