@bitgo-beta/sdk-coin-sol 7.6.4-beta.782 → 7.6.4-beta.784
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solSafeRecovery.d.ts","sourceRoot":"","sources":["../../../../test/unit/solSafeRecovery.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const assert_1 = __importDefault(require("assert"));
|
|
40
|
+
const sinon_1 = __importDefault(require("sinon"));
|
|
41
|
+
const nacl = __importStar(require("tweetnacl"));
|
|
42
|
+
const base58 = __importStar(require("bs58"));
|
|
43
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
44
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
45
|
+
const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
|
|
46
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
47
|
+
const src_1 = require("../../src");
|
|
48
|
+
const lib_1 = require("../../src/lib");
|
|
49
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
50
|
+
const testData = __importStar(require("../fixtures/sol"));
|
|
51
|
+
/**
|
|
52
|
+
* End-to-end Safe SOL recovery: real MPS DKG + VRF roots -> deriveSafeWalletKeys (slot-4 eddsaMpc
|
|
53
|
+
* child) -> buildSafeRecoverKeyParams -> Sol.recover() with the real MPS 2-of-2 signing path. Only
|
|
54
|
+
* chain queries are mocked.
|
|
55
|
+
*
|
|
56
|
+
* This proves the derived child keychain is accepted as `bitgoKey`, the re-encrypted child shares
|
|
57
|
+
* decrypt and sign, and the resulting signature verifies under the derived wallet address.
|
|
58
|
+
*/
|
|
59
|
+
describe('Safe SOL recovery end-to-end', function () {
|
|
60
|
+
const sandbox = sinon_1.default.createSandbox();
|
|
61
|
+
let bitgo;
|
|
62
|
+
let basecoin;
|
|
63
|
+
let roots;
|
|
64
|
+
before(async function () {
|
|
65
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
66
|
+
bitgo.safeRegister('tsol', src_1.Tsol.createInstance);
|
|
67
|
+
bitgo.initializeTestVars();
|
|
68
|
+
basecoin = bitgo.coin('tsol');
|
|
69
|
+
const [userDkg, backupDkg, bitgoDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
70
|
+
const [vrfUser, vrfBackup] = await sdk_lib_mpc_1.MpsVrfUtils.generateVrfDKGKeyShares();
|
|
71
|
+
roots = {
|
|
72
|
+
secp256k1Multisig: { user: 'u', backup: 'b', bitgo: 'g' },
|
|
73
|
+
ed25519Multisig: { user: 'u', backup: { prv: 'b', chainCode: 'c' }, bitgo: 'g' },
|
|
74
|
+
ecdsaMpc: {
|
|
75
|
+
user: { signing: Buffer.alloc(0), vrf: Buffer.alloc(0) },
|
|
76
|
+
backup: { signing: Buffer.alloc(0), vrf: Buffer.alloc(0) },
|
|
77
|
+
bitgo: 'g',
|
|
78
|
+
},
|
|
79
|
+
eddsaMpc: {
|
|
80
|
+
user: { signing: userDkg.getReducedKeyShare(), vrf: vrfUser.getKeyShare() },
|
|
81
|
+
backup: { signing: backupDkg.getReducedKeyShare(), vrf: vrfBackup.getKeyShare() },
|
|
82
|
+
bitgo: bitgoDkg.getCommonKeychain(),
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
afterEach(function () {
|
|
87
|
+
sandbox.restore();
|
|
88
|
+
});
|
|
89
|
+
async function deriveChild(account) {
|
|
90
|
+
const derived = await (0, sdk_core_1.deriveSafeWalletKeys)({ coin: 'tsol', slot: 'eddsaMpc', account, roots });
|
|
91
|
+
(0, assert_1.default)(derived.slot === 'eddsaMpc');
|
|
92
|
+
const mpc = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
93
|
+
const publicKey = mpc.deriveUnhardened(derived.keys.commonKeychain, 'm/0').slice(0, 64);
|
|
94
|
+
return { derived, publicKey, address: new src_1.KeyPair({ pub: publicKey }).getAddress() };
|
|
95
|
+
}
|
|
96
|
+
function stubChain(walletAddress) {
|
|
97
|
+
const getDataFromNode = sandbox.stub(src_1.Sol.prototype, 'getDataFromNode');
|
|
98
|
+
getDataFromNode
|
|
99
|
+
.withArgs({
|
|
100
|
+
payload: { id: '1', jsonrpc: '2.0', method: 'getLatestBlockhash', params: [{ commitment: 'finalized' }] },
|
|
101
|
+
})
|
|
102
|
+
.resolves(testData.SolResponses.getBlockhashResponse);
|
|
103
|
+
getDataFromNode
|
|
104
|
+
.withArgs({ payload: { id: '1', jsonrpc: '2.0', method: 'getBalance', params: [walletAddress] } })
|
|
105
|
+
.resolves(testData.SolResponses.getAccountBalanceResponse);
|
|
106
|
+
getDataFromNode
|
|
107
|
+
.withArgs({
|
|
108
|
+
payload: {
|
|
109
|
+
id: '1',
|
|
110
|
+
jsonrpc: '2.0',
|
|
111
|
+
method: 'getFeeForMessage',
|
|
112
|
+
params: [sinon_1.default.match.string, { commitment: 'finalized' }],
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
.resolves(testData.SolResponses.getFeesForMessageResponse);
|
|
116
|
+
}
|
|
117
|
+
it('recovers a Safe SOL wallet offline: derive -> map -> sign, verifiable under the derived address', async function () {
|
|
118
|
+
const { derived, publicKey, address } = await deriveChild(0);
|
|
119
|
+
stubChain(address);
|
|
120
|
+
const keyParams = await (0, sdk_core_1.buildSafeRecoverKeyParams)({
|
|
121
|
+
bitgo,
|
|
122
|
+
coin: 'tsol',
|
|
123
|
+
slot: 'eddsaMpc',
|
|
124
|
+
keys: derived.keys,
|
|
125
|
+
mode: 'signed',
|
|
126
|
+
});
|
|
127
|
+
(0, assert_1.default)(keyParams.mode === 'signed');
|
|
128
|
+
assert_1.default.strictEqual(keyParams.isTss, true);
|
|
129
|
+
assert_1.default.strictEqual(keyParams.broadcast, false);
|
|
130
|
+
assert_1.default.strictEqual(keyParams.bitgoKey, derived.keys.commonKeychain);
|
|
131
|
+
const recovery = await basecoin.recover({
|
|
132
|
+
...keyParams,
|
|
133
|
+
recoveryDestination: testData.keys.destinationPubKey,
|
|
134
|
+
});
|
|
135
|
+
(0, assert_1.default)('serializedTx' in recovery);
|
|
136
|
+
assert_1.default.strictEqual(recovery.scanIndex, 0);
|
|
137
|
+
// The signature on the recovered tx verifies under the derived child wallet key.
|
|
138
|
+
const tx = await new lib_1.TransactionBuilderFactory(statics_1.coins.get('tsol')).from(recovery.serializedTx).build();
|
|
139
|
+
assert_1.default.strictEqual(tx.signature.length, 1);
|
|
140
|
+
assert_1.default.strictEqual(nacl.sign.detached.verify(new Uint8Array(tx.signablePayload), new Uint8Array(base58.decode(tx.signature[0])), new Uint8Array(Buffer.from(publicKey, 'hex'))), true);
|
|
141
|
+
});
|
|
142
|
+
it('returns an unsigned sweep from the derived child address with no key material in the params', async function () {
|
|
143
|
+
const { derived, address } = await deriveChild(0);
|
|
144
|
+
stubChain(address);
|
|
145
|
+
const keyParams = await (0, sdk_core_1.buildSafeRecoverKeyParams)({
|
|
146
|
+
bitgo,
|
|
147
|
+
coin: 'tsol',
|
|
148
|
+
slot: 'eddsaMpc',
|
|
149
|
+
keys: derived.keys,
|
|
150
|
+
mode: 'unsigned',
|
|
151
|
+
});
|
|
152
|
+
(0, assert_1.default)(keyParams.mode === 'unsigned');
|
|
153
|
+
(0, assert_1.default)(!('userKey' in keyParams) && !('backupKey' in keyParams) && !('walletPassphrase' in keyParams));
|
|
154
|
+
const recovery = await basecoin.recover({
|
|
155
|
+
...keyParams,
|
|
156
|
+
recoveryDestination: testData.keys.destinationPubKey,
|
|
157
|
+
});
|
|
158
|
+
(0, assert_1.default)('txRequests' in recovery);
|
|
159
|
+
const unsignedTx = recovery.txRequests[0].transactions[0].unsignedTx;
|
|
160
|
+
assert_1.default.strictEqual(unsignedTx.coinSpecific?.commonKeychain, derived.keys.commonKeychain);
|
|
161
|
+
assert_1.default.strictEqual(unsignedTx.derivationPath, 'm/0');
|
|
162
|
+
(0, assert_1.default)(unsignedTx.signableHex);
|
|
163
|
+
const tx = await new lib_1.TransactionBuilderFactory(statics_1.coins.get('tsol')).from(unsignedTx.serializedTx).build();
|
|
164
|
+
assert_1.default.strictEqual(tx.inputs[0].address, address);
|
|
165
|
+
});
|
|
166
|
+
it('fails closed when the signing shares belong to a different account than bitgoKey', async function () {
|
|
167
|
+
const account0 = await deriveChild(0);
|
|
168
|
+
const account1 = await deriveChild(1);
|
|
169
|
+
stubChain(account0.address);
|
|
170
|
+
const keyParams = await (0, sdk_core_1.buildSafeRecoverKeyParams)({
|
|
171
|
+
bitgo,
|
|
172
|
+
coin: 'tsol',
|
|
173
|
+
slot: 'eddsaMpc',
|
|
174
|
+
keys: account1.derived.keys,
|
|
175
|
+
mode: 'signed',
|
|
176
|
+
});
|
|
177
|
+
(0, assert_1.default)(keyParams.mode === 'signed');
|
|
178
|
+
await assert_1.default.rejects(basecoin.recover({
|
|
179
|
+
...keyParams,
|
|
180
|
+
bitgoKey: account0.derived.keys.commonKeychain,
|
|
181
|
+
recoveryDestination: testData.keys.destinationPubKey,
|
|
182
|
+
}), /commonKeyChain from keycard does not match bitgoKey/);
|
|
183
|
+
});
|
|
184
|
+
it('fails closed when the wallet passphrase cannot decrypt the re-encrypted child shares', async function () {
|
|
185
|
+
const { derived, address } = await deriveChild(0);
|
|
186
|
+
stubChain(address);
|
|
187
|
+
const keyParams = await (0, sdk_core_1.buildSafeRecoverKeyParams)({
|
|
188
|
+
bitgo,
|
|
189
|
+
coin: 'tsol',
|
|
190
|
+
slot: 'eddsaMpc',
|
|
191
|
+
keys: derived.keys,
|
|
192
|
+
mode: 'signed',
|
|
193
|
+
});
|
|
194
|
+
(0, assert_1.default)(keyParams.mode === 'signed');
|
|
195
|
+
await assert_1.default.rejects(basecoin.recover({
|
|
196
|
+
...keyParams,
|
|
197
|
+
walletPassphrase: 'not-the-ephemeral-passphrase',
|
|
198
|
+
recoveryDestination: testData.keys.destinationPubKey,
|
|
199
|
+
}), /Error decrypting user keychain/);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29sU2FmZVJlY292ZXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3NvbFNhZmVSZWNvdmVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG9EQUE0QjtBQUM1QixrREFBMEI7QUFDMUIsZ0RBQWtDO0FBQ2xDLDZDQUErQjtBQUMvQixtREFBK0Q7QUFDL0QsaURBQStDO0FBQy9DLHlEQUErRDtBQUMvRCxtREFLOEI7QUFDOUIsbUNBQStDO0FBQy9DLHVDQUEwRDtBQUMxRCxpREFBNEM7QUFDNUMsMERBQTRDO0FBRTVDOzs7Ozs7O0dBT0c7QUFDSCxRQUFRLENBQUMsOEJBQThCLEVBQUU7SUFDdkMsTUFBTSxPQUFPLEdBQUcsZUFBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3RDLElBQUksS0FBbUIsQ0FBQztJQUN4QixJQUFJLFFBQWMsQ0FBQztJQUNuQixJQUFJLEtBQXlCLENBQUM7SUFFOUIsTUFBTSxDQUFDLEtBQUs7UUFDVixLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFVBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNoRCxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMzQixRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQVMsQ0FBQztRQUV0QyxNQUFNLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsR0FBRyxNQUFNLHFCQUFPLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUNqRixNQUFNLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxHQUFHLE1BQU0seUJBQVcsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ3pFLEtBQUssR0FBRztZQUNOLGlCQUFpQixFQUFFLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUU7WUFDekQsZUFBZSxFQUFFLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFO1lBQ2hGLFFBQVEsRUFBRTtnQkFDUixJQUFJLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDeEQsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQzFELEtBQUssRUFBRSxHQUFHO2FBQ1g7WUFDRCxRQUFRLEVBQUU7Z0JBQ1IsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUU7Z0JBQzNFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxTQUFTLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxHQUFHLEVBQUUsU0FBUyxDQUFDLFdBQVcsRUFBRSxFQUFFO2dCQUNqRixLQUFLLEVBQUUsUUFBUSxDQUFDLGlCQUFpQixFQUFFO2FBQ3BDO1NBQ0YsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsU0FBUyxDQUFDO1FBQ1IsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBRUgsS0FBSyxVQUFVLFdBQVcsQ0FBQyxPQUFlO1FBQ3hDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBQSwrQkFBb0IsRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMvRixJQUFBLGdCQUFNLEVBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQztRQUNwQyxNQUFNLEdBQUcsR0FBRyxNQUFNLHVCQUFZLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUMzRCxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN4RixPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsSUFBSSxhQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO0lBQ3ZGLENBQUM7SUFFRCxTQUFTLFNBQVMsQ0FBQyxhQUFxQjtRQUN0QyxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQUcsQ0FBQyxTQUFTLEVBQUUsaUJBQThCLENBQUMsQ0FBQztRQUNwRixlQUFlO2FBQ1osUUFBUSxDQUFDO1lBQ1IsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFO1NBQzFHLENBQUM7YUFDRCxRQUFRLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3hELGVBQWU7YUFDWixRQUFRLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUM7YUFDakcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUM3RCxlQUFlO2FBQ1osUUFBUSxDQUFDO1lBQ1IsT0FBTyxFQUFFO2dCQUNQLEVBQUUsRUFBRSxHQUFHO2dCQUNQLE9BQU8sRUFBRSxLQUFLO2dCQUNkLE1BQU0sRUFBRSxrQkFBa0I7Z0JBQzFCLE1BQU0sRUFBRSxDQUFDLGVBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxDQUFDO2FBQzFEO1NBQ0YsQ0FBQzthQUNELFFBQVEsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDL0QsQ0FBQztJQUVELEVBQUUsQ0FBQyxpR0FBaUcsRUFBRSxLQUFLO1FBQ3pHLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdELFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuQixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUEsb0NBQXlCLEVBQUM7WUFDaEQsS0FBSztZQUNMLElBQUksRUFBRSxNQUFNO1lBQ1osSUFBSSxFQUFFLFVBQVU7WUFDaEIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1lBQ2xCLElBQUksRUFBRSxRQUFRO1NBQ2YsQ0FBQyxDQUFDO1FBQ0gsSUFBQSxnQkFBTSxFQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUM7UUFDcEMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxQyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQy9DLGdCQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUVwRSxNQUFNLFFBQVEsR0FBRyxNQUFNLFFBQVEsQ0FBQyxPQUFPLENBQUM7WUFDdEMsR0FBRyxTQUFTO1lBQ1osbUJBQW1CLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxpQkFBaUI7U0FDckQsQ0FBQyxDQUFDO1FBRUgsSUFBQSxnQkFBTSxFQUFDLGNBQWMsSUFBSSxRQUFRLENBQUMsQ0FBQztRQUNuQyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTFDLGlGQUFpRjtRQUNqRixNQUFNLEVBQUUsR0FBRyxNQUFNLElBQUksK0JBQXlCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDdEcsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0MsZ0JBQU0sQ0FBQyxXQUFXLENBQ2hCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FDdkIsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUNsQyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUM5QyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUM5QyxFQUNELElBQUksQ0FDTCxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNkZBQTZGLEVBQUUsS0FBSztRQUNyRyxNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xELFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuQixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUEsb0NBQXlCLEVBQUM7WUFDaEQsS0FBSztZQUNMLElBQUksRUFBRSxNQUFNO1lBQ1osSUFBSSxFQUFFLFVBQVU7WUFDaEIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1lBQ2xCLElBQUksRUFBRSxVQUFVO1NBQ2pCLENBQUMsQ0FBQztRQUNILElBQUEsZ0JBQU0sRUFBQyxTQUFTLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxDQUFDO1FBQ3RDLElBQUEsZ0JBQU0sRUFBQyxDQUFDLENBQUMsU0FBUyxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLGtCQUFrQixJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFFdkcsTUFBTSxRQUFRLEdBQUcsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDO1lBQ3RDLEdBQUcsU0FBUztZQUNaLG1CQUFtQixFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsaUJBQWlCO1NBQ3JELENBQUMsQ0FBQztRQUNILElBQUEsZ0JBQU0sRUFBQyxZQUFZLElBQUksUUFBUSxDQUFDLENBQUM7UUFFakMsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO1FBQ3JFLGdCQUFNLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsY0FBYyxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekYsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNyRCxJQUFBLGdCQUFNLEVBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQy9CLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSwrQkFBeUIsQ0FBQyxlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4RyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxrRkFBa0YsRUFBRSxLQUFLO1FBQzFGLE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFNUIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFBLG9DQUF5QixFQUFDO1lBQ2hELEtBQUs7WUFDTCxJQUFJLEVBQUUsTUFBTTtZQUNaLElBQUksRUFBRSxVQUFVO1lBQ2hCLElBQUksRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUk7WUFDM0IsSUFBSSxFQUFFLFFBQVE7U0FDZixDQUFDLENBQUM7UUFDSCxJQUFBLGdCQUFNLEVBQUMsU0FBUyxDQUFDLElBQUksS0FBSyxRQUFRLENBQUMsQ0FBQztRQUVwQyxNQUFNLGdCQUFNLENBQUMsT0FBTyxDQUNsQixRQUFRLENBQUMsT0FBTyxDQUFDO1lBQ2YsR0FBRyxTQUFTO1lBQ1osUUFBUSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWM7WUFDOUMsbUJBQW1CLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxpQkFBaUI7U0FDckQsQ0FBQyxFQUNGLHFEQUFxRCxDQUN0RCxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0ZBQXNGLEVBQUUsS0FBSztRQUM5RixNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xELFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuQixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUEsb0NBQXlCLEVBQUM7WUFDaEQsS0FBSztZQUNMLElBQUksRUFBRSxNQUFNO1lBQ1osSUFBSSxFQUFFLFVBQVU7WUFDaEIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1lBQ2xCLElBQUksRUFBRSxRQUFRO1NBQ2YsQ0FBQyxDQUFDO1FBQ0gsSUFBQSxnQkFBTSxFQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUM7UUFFcEMsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FDbEIsUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUNmLEdBQUcsU0FBUztZQUNaLGdCQUFnQixFQUFFLDhCQUE4QjtZQUNoRCxtQkFBbUIsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLGlCQUFpQjtTQUNyRCxDQUFDLEVBQ0YsZ0NBQWdDLENBQ2pDLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IFNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCAqIGFzIG5hY2wgZnJvbSAndHdlZXRuYWNsJztcbmltcG9ydCAqIGFzIGJhc2U1OCBmcm9tICdiczU4JztcbmltcG9ydCB7IFRlc3RCaXRHbywgVGVzdEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R29BUEkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstYXBpJztcbmltcG9ydCB7IE1QU1V0aWwsIE1wc1ZyZlV0aWxzIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWxpYi1tcGMnO1xuaW1wb3J0IHtcbiAgYnVpbGRTYWZlUmVjb3ZlcktleVBhcmFtcyxcbiAgZGVyaXZlU2FmZVdhbGxldEtleXMsXG4gIEVERFNBTWV0aG9kcyxcbiAgdHlwZSBEZWNyeXB0ZWRTYWZlUm9vdHMsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IEtleVBhaXIsIFRzb2wsIFNvbCB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5IH0gZnJvbSAnLi4vLi4vc3JjL2xpYic7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0ICogYXMgdGVzdERhdGEgZnJvbSAnLi4vZml4dHVyZXMvc29sJztcblxuLyoqXG4gKiBFbmQtdG8tZW5kIFNhZmUgU09MIHJlY292ZXJ5OiByZWFsIE1QUyBES0cgKyBWUkYgcm9vdHMgLT4gZGVyaXZlU2FmZVdhbGxldEtleXMgKHNsb3QtNCBlZGRzYU1wY1xuICogY2hpbGQpIC0+IGJ1aWxkU2FmZVJlY292ZXJLZXlQYXJhbXMgLT4gU29sLnJlY292ZXIoKSB3aXRoIHRoZSByZWFsIE1QUyAyLW9mLTIgc2lnbmluZyBwYXRoLiBPbmx5XG4gKiBjaGFpbiBxdWVyaWVzIGFyZSBtb2NrZWQuXG4gKlxuICogVGhpcyBwcm92ZXMgdGhlIGRlcml2ZWQgY2hpbGQga2V5Y2hhaW4gaXMgYWNjZXB0ZWQgYXMgYGJpdGdvS2V5YCwgdGhlIHJlLWVuY3J5cHRlZCBjaGlsZCBzaGFyZXNcbiAqIGRlY3J5cHQgYW5kIHNpZ24sIGFuZCB0aGUgcmVzdWx0aW5nIHNpZ25hdHVyZSB2ZXJpZmllcyB1bmRlciB0aGUgZGVyaXZlZCB3YWxsZXQgYWRkcmVzcy5cbiAqL1xuZGVzY3JpYmUoJ1NhZmUgU09MIHJlY292ZXJ5IGVuZC10by1lbmQnLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IHNhbmRib3ggPSBTaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgYmFzZWNvaW46IFRzb2w7XG4gIGxldCByb290czogRGVjcnlwdGVkU2FmZVJvb3RzO1xuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0c29sJywgVHNvbC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0c29sJykgYXMgVHNvbDtcblxuICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2csIGJpdGdvRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIGNvbnN0IFt2cmZVc2VyLCB2cmZCYWNrdXBdID0gYXdhaXQgTXBzVnJmVXRpbHMuZ2VuZXJhdGVWcmZES0dLZXlTaGFyZXMoKTtcbiAgICByb290cyA9IHtcbiAgICAgIHNlY3AyNTZrMU11bHRpc2lnOiB7IHVzZXI6ICd1JywgYmFja3VwOiAnYicsIGJpdGdvOiAnZycgfSxcbiAgICAgIGVkMjU1MTlNdWx0aXNpZzogeyB1c2VyOiAndScsIGJhY2t1cDogeyBwcnY6ICdiJywgY2hhaW5Db2RlOiAnYycgfSwgYml0Z286ICdnJyB9LFxuICAgICAgZWNkc2FNcGM6IHtcbiAgICAgICAgdXNlcjogeyBzaWduaW5nOiBCdWZmZXIuYWxsb2MoMCksIHZyZjogQnVmZmVyLmFsbG9jKDApIH0sXG4gICAgICAgIGJhY2t1cDogeyBzaWduaW5nOiBCdWZmZXIuYWxsb2MoMCksIHZyZjogQnVmZmVyLmFsbG9jKDApIH0sXG4gICAgICAgIGJpdGdvOiAnZycsXG4gICAgICB9LFxuICAgICAgZWRkc2FNcGM6IHtcbiAgICAgICAgdXNlcjogeyBzaWduaW5nOiB1c2VyRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLCB2cmY6IHZyZlVzZXIuZ2V0S2V5U2hhcmUoKSB9LFxuICAgICAgICBiYWNrdXA6IHsgc2lnbmluZzogYmFja3VwRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLCB2cmY6IHZyZkJhY2t1cC5nZXRLZXlTaGFyZSgpIH0sXG4gICAgICAgIGJpdGdvOiBiaXRnb0RrZy5nZXRDb21tb25LZXljaGFpbigpLFxuICAgICAgfSxcbiAgICB9O1xuICB9KTtcblxuICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3gucmVzdG9yZSgpO1xuICB9KTtcblxuICBhc3luYyBmdW5jdGlvbiBkZXJpdmVDaGlsZChhY2NvdW50OiBudW1iZXIpIHtcbiAgICBjb25zdCBkZXJpdmVkID0gYXdhaXQgZGVyaXZlU2FmZVdhbGxldEtleXMoeyBjb2luOiAndHNvbCcsIHNsb3Q6ICdlZGRzYU1wYycsIGFjY291bnQsIHJvb3RzIH0pO1xuICAgIGFzc2VydChkZXJpdmVkLnNsb3QgPT09ICdlZGRzYU1wYycpO1xuICAgIGNvbnN0IG1wYyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgY29uc3QgcHVibGljS2V5ID0gbXBjLmRlcml2ZVVuaGFyZGVuZWQoZGVyaXZlZC5rZXlzLmNvbW1vbktleWNoYWluLCAnbS8wJykuc2xpY2UoMCwgNjQpO1xuICAgIHJldHVybiB7IGRlcml2ZWQsIHB1YmxpY0tleSwgYWRkcmVzczogbmV3IEtleVBhaXIoeyBwdWI6IHB1YmxpY0tleSB9KS5nZXRBZGRyZXNzKCkgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0dWJDaGFpbih3YWxsZXRBZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBnZXREYXRhRnJvbU5vZGUgPSBzYW5kYm94LnN0dWIoU29sLnByb3RvdHlwZSwgJ2dldERhdGFGcm9tTm9kZScgYXMga2V5b2YgU29sKTtcbiAgICBnZXREYXRhRnJvbU5vZGVcbiAgICAgIC53aXRoQXJncyh7XG4gICAgICAgIHBheWxvYWQ6IHsgaWQ6ICcxJywganNvbnJwYzogJzIuMCcsIG1ldGhvZDogJ2dldExhdGVzdEJsb2NraGFzaCcsIHBhcmFtczogW3sgY29tbWl0bWVudDogJ2ZpbmFsaXplZCcgfV0gfSxcbiAgICAgIH0pXG4gICAgICAucmVzb2x2ZXModGVzdERhdGEuU29sUmVzcG9uc2VzLmdldEJsb2NraGFzaFJlc3BvbnNlKTtcbiAgICBnZXREYXRhRnJvbU5vZGVcbiAgICAgIC53aXRoQXJncyh7IHBheWxvYWQ6IHsgaWQ6ICcxJywganNvbnJwYzogJzIuMCcsIG1ldGhvZDogJ2dldEJhbGFuY2UnLCBwYXJhbXM6IFt3YWxsZXRBZGRyZXNzXSB9IH0pXG4gICAgICAucmVzb2x2ZXModGVzdERhdGEuU29sUmVzcG9uc2VzLmdldEFjY291bnRCYWxhbmNlUmVzcG9uc2UpO1xuICAgIGdldERhdGFGcm9tTm9kZVxuICAgICAgLndpdGhBcmdzKHtcbiAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgbWV0aG9kOiAnZ2V0RmVlRm9yTWVzc2FnZScsXG4gICAgICAgICAgcGFyYW1zOiBbU2lub24ubWF0Y2guc3RyaW5nLCB7IGNvbW1pdG1lbnQ6ICdmaW5hbGl6ZWQnIH1dLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5yZXNvbHZlcyh0ZXN0RGF0YS5Tb2xSZXNwb25zZXMuZ2V0RmVlc0Zvck1lc3NhZ2VSZXNwb25zZSk7XG4gIH1cblxuICBpdCgncmVjb3ZlcnMgYSBTYWZlIFNPTCB3YWxsZXQgb2ZmbGluZTogZGVyaXZlIC0+IG1hcCAtPiBzaWduLCB2ZXJpZmlhYmxlIHVuZGVyIHRoZSBkZXJpdmVkIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgeyBkZXJpdmVkLCBwdWJsaWNLZXksIGFkZHJlc3MgfSA9IGF3YWl0IGRlcml2ZUNoaWxkKDApO1xuICAgIHN0dWJDaGFpbihhZGRyZXNzKTtcblxuICAgIGNvbnN0IGtleVBhcmFtcyA9IGF3YWl0IGJ1aWxkU2FmZVJlY292ZXJLZXlQYXJhbXMoe1xuICAgICAgYml0Z28sXG4gICAgICBjb2luOiAndHNvbCcsXG4gICAgICBzbG90OiAnZWRkc2FNcGMnLFxuICAgICAga2V5czogZGVyaXZlZC5rZXlzLFxuICAgICAgbW9kZTogJ3NpZ25lZCcsXG4gICAgfSk7XG4gICAgYXNzZXJ0KGtleVBhcmFtcy5tb2RlID09PSAnc2lnbmVkJyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGtleVBhcmFtcy5pc1RzcywgdHJ1ZSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGtleVBhcmFtcy5icm9hZGNhc3QsIGZhbHNlKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoa2V5UGFyYW1zLmJpdGdvS2V5LCBkZXJpdmVkLmtleXMuY29tbW9uS2V5Y2hhaW4pO1xuXG4gICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgIC4uLmtleVBhcmFtcyxcbiAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHRlc3REYXRhLmtleXMuZGVzdGluYXRpb25QdWJLZXksXG4gICAgfSk7XG5cbiAgICBhc3NlcnQoJ3NlcmlhbGl6ZWRUeCcgaW4gcmVjb3ZlcnkpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZWNvdmVyeS5zY2FuSW5kZXgsIDApO1xuXG4gICAgLy8gVGhlIHNpZ25hdHVyZSBvbiB0aGUgcmVjb3ZlcmVkIHR4IHZlcmlmaWVzIHVuZGVyIHRoZSBkZXJpdmVkIGNoaWxkIHdhbGxldCBrZXkuXG4gICAgY29uc3QgdHggPSBhd2FpdCBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQoJ3Rzb2wnKSkuZnJvbShyZWNvdmVyeS5zZXJpYWxpemVkVHgpLmJ1aWxkKCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LnNpZ25hdHVyZS5sZW5ndGgsIDEpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgIG5hY2wuc2lnbi5kZXRhY2hlZC52ZXJpZnkoXG4gICAgICAgIG5ldyBVaW50OEFycmF5KHR4LnNpZ25hYmxlUGF5bG9hZCksXG4gICAgICAgIG5ldyBVaW50OEFycmF5KGJhc2U1OC5kZWNvZGUodHguc2lnbmF0dXJlWzBdKSksXG4gICAgICAgIG5ldyBVaW50OEFycmF5KEJ1ZmZlci5mcm9tKHB1YmxpY0tleSwgJ2hleCcpKVxuICAgICAgKSxcbiAgICAgIHRydWVcbiAgICApO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBhbiB1bnNpZ25lZCBzd2VlcCBmcm9tIHRoZSBkZXJpdmVkIGNoaWxkIGFkZHJlc3Mgd2l0aCBubyBrZXkgbWF0ZXJpYWwgaW4gdGhlIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB7IGRlcml2ZWQsIGFkZHJlc3MgfSA9IGF3YWl0IGRlcml2ZUNoaWxkKDApO1xuICAgIHN0dWJDaGFpbihhZGRyZXNzKTtcblxuICAgIGNvbnN0IGtleVBhcmFtcyA9IGF3YWl0IGJ1aWxkU2FmZVJlY292ZXJLZXlQYXJhbXMoe1xuICAgICAgYml0Z28sXG4gICAgICBjb2luOiAndHNvbCcsXG4gICAgICBzbG90OiAnZWRkc2FNcGMnLFxuICAgICAga2V5czogZGVyaXZlZC5rZXlzLFxuICAgICAgbW9kZTogJ3Vuc2lnbmVkJyxcbiAgICB9KTtcbiAgICBhc3NlcnQoa2V5UGFyYW1zLm1vZGUgPT09ICd1bnNpZ25lZCcpO1xuICAgIGFzc2VydCghKCd1c2VyS2V5JyBpbiBrZXlQYXJhbXMpICYmICEoJ2JhY2t1cEtleScgaW4ga2V5UGFyYW1zKSAmJiAhKCd3YWxsZXRQYXNzcGhyYXNlJyBpbiBrZXlQYXJhbXMpKTtcblxuICAgIGNvbnN0IHJlY292ZXJ5ID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAuLi5rZXlQYXJhbXMsXG4gICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiB0ZXN0RGF0YS5rZXlzLmRlc3RpbmF0aW9uUHViS2V5LFxuICAgIH0pO1xuICAgIGFzc2VydCgndHhSZXF1ZXN0cycgaW4gcmVjb3ZlcnkpO1xuXG4gICAgY29uc3QgdW5zaWduZWRUeCA9IHJlY292ZXJ5LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHVuc2lnbmVkVHguY29pblNwZWNpZmljPy5jb21tb25LZXljaGFpbiwgZGVyaXZlZC5rZXlzLmNvbW1vbktleWNoYWluKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwodW5zaWduZWRUeC5kZXJpdmF0aW9uUGF0aCwgJ20vMCcpO1xuICAgIGFzc2VydCh1bnNpZ25lZFR4LnNpZ25hYmxlSGV4KTtcbiAgICBjb25zdCB0eCA9IGF3YWl0IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCgndHNvbCcpKS5mcm9tKHVuc2lnbmVkVHguc2VyaWFsaXplZFR4KS5idWlsZCgpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5pbnB1dHNbMF0uYWRkcmVzcywgYWRkcmVzcyk7XG4gIH0pO1xuXG4gIGl0KCdmYWlscyBjbG9zZWQgd2hlbiB0aGUgc2lnbmluZyBzaGFyZXMgYmVsb25nIHRvIGEgZGlmZmVyZW50IGFjY291bnQgdGhhbiBiaXRnb0tleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBhY2NvdW50MCA9IGF3YWl0IGRlcml2ZUNoaWxkKDApO1xuICAgIGNvbnN0IGFjY291bnQxID0gYXdhaXQgZGVyaXZlQ2hpbGQoMSk7XG4gICAgc3R1YkNoYWluKGFjY291bnQwLmFkZHJlc3MpO1xuXG4gICAgY29uc3Qga2V5UGFyYW1zID0gYXdhaXQgYnVpbGRTYWZlUmVjb3ZlcktleVBhcmFtcyh7XG4gICAgICBiaXRnbyxcbiAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgIHNsb3Q6ICdlZGRzYU1wYycsXG4gICAgICBrZXlzOiBhY2NvdW50MS5kZXJpdmVkLmtleXMsXG4gICAgICBtb2RlOiAnc2lnbmVkJyxcbiAgICB9KTtcbiAgICBhc3NlcnQoa2V5UGFyYW1zLm1vZGUgPT09ICdzaWduZWQnKTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIC4uLmtleVBhcmFtcyxcbiAgICAgICAgYml0Z29LZXk6IGFjY291bnQwLmRlcml2ZWQua2V5cy5jb21tb25LZXljaGFpbixcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogdGVzdERhdGEua2V5cy5kZXN0aW5hdGlvblB1YktleSxcbiAgICAgIH0pLFxuICAgICAgL2NvbW1vbktleUNoYWluIGZyb20ga2V5Y2FyZCBkb2VzIG5vdCBtYXRjaCBiaXRnb0tleS9cbiAgICApO1xuICB9KTtcblxuICBpdCgnZmFpbHMgY2xvc2VkIHdoZW4gdGhlIHdhbGxldCBwYXNzcGhyYXNlIGNhbm5vdCBkZWNyeXB0IHRoZSByZS1lbmNyeXB0ZWQgY2hpbGQgc2hhcmVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHsgZGVyaXZlZCwgYWRkcmVzcyB9ID0gYXdhaXQgZGVyaXZlQ2hpbGQoMCk7XG4gICAgc3R1YkNoYWluKGFkZHJlc3MpO1xuXG4gICAgY29uc3Qga2V5UGFyYW1zID0gYXdhaXQgYnVpbGRTYWZlUmVjb3ZlcktleVBhcmFtcyh7XG4gICAgICBiaXRnbyxcbiAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgIHNsb3Q6ICdlZGRzYU1wYycsXG4gICAgICBrZXlzOiBkZXJpdmVkLmtleXMsXG4gICAgICBtb2RlOiAnc2lnbmVkJyxcbiAgICB9KTtcbiAgICBhc3NlcnQoa2V5UGFyYW1zLm1vZGUgPT09ICdzaWduZWQnKTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIC4uLmtleVBhcmFtcyxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ25vdC10aGUtZXBoZW1lcmFsLXBhc3NwaHJhc2UnLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiB0ZXN0RGF0YS5rZXlzLmRlc3RpbmF0aW9uUHViS2V5LFxuICAgICAgfSksXG4gICAgICAvRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluL1xuICAgICk7XG4gIH0pO1xufSk7XG4iXX0=
|