@bitgo-beta/sdk-coin-eth 4.4.1-beta.202 → 4.4.1-beta.2021
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/erc20Token.d.ts +1 -1
- package/dist/src/erc20Token.d.ts.map +1 -1
- package/dist/src/erc20Token.js +49 -28
- package/dist/src/erc721Token.d.ts +60 -0
- package/dist/src/erc721Token.d.ts.map +1 -0
- package/dist/src/erc721Token.js +334 -0
- package/dist/src/erc7984Token.d.ts +187 -0
- package/dist/src/erc7984Token.d.ts.map +1 -0
- package/dist/src/erc7984Token.js +946 -0
- package/dist/src/eth.d.ts +10 -8
- package/dist/src/eth.d.ts.map +1 -1
- package/dist/src/eth.js +54 -39
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -2
- package/dist/src/lib/index.d.ts +1 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +7 -2
- package/dist/src/lib/messages/index.d.ts +3 -0
- package/dist/src/lib/messages/index.d.ts.map +1 -0
- package/dist/src/lib/messages/index.js +6 -0
- package/dist/src/lib/transactionBuilder.d.ts +10 -5
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +17 -7
- package/dist/src/lib/transferBuilders/index.d.ts +2 -2
- package/dist/src/lib/transferBuilders/index.d.ts.map +1 -1
- package/dist/src/lib/transferBuilders/index.js +3 -2
- package/dist/src/register.d.ts +2 -0
- package/dist/src/register.d.ts.map +1 -1
- package/dist/src/register.js +39 -2
- package/dist/src/sepeth.d.ts +8 -0
- package/dist/src/sepeth.d.ts.map +1 -0
- package/dist/src/sepeth.js +14 -0
- package/dist/test/fixtures/eth.d.ts +39 -0
- package/dist/test/fixtures/eth.d.ts.map +1 -0
- package/dist/test/fixtures/eth.js +262 -0
- package/dist/test/resources/erc1155Abi.d.ts +40 -0
- package/dist/test/resources/erc1155Abi.d.ts.map +1 -0
- package/dist/test/resources/erc1155Abi.js +329 -0
- package/dist/test/resources/erc721Abi.d.ts +12 -0
- package/dist/test/resources/erc721Abi.d.ts.map +1 -0
- package/dist/test/resources/erc721Abi.js +34 -0
- package/dist/test/resources/eth.d.ts +51 -0
- package/dist/test/resources/eth.d.ts.map +1 -0
- package/dist/test/resources/eth.js +72 -0
- package/dist/test/resources/nftEncodings.d.ts +4 -0
- package/dist/test/resources/nftEncodings.d.ts.map +1 -0
- package/dist/test/resources/nftEncodings.js +7 -0
- package/dist/test/resources/walletSimpleAbi.d.ts +12 -0
- package/dist/test/resources/walletSimpleAbi.d.ts.map +1 -0
- package/dist/test/resources/walletSimpleAbi.js +44 -0
- package/dist/test/unit/erc7984Token.d.ts +2 -0
- package/dist/test/unit/erc7984Token.d.ts.map +1 -0
- package/dist/test/unit/erc7984Token.js +1589 -0
- package/dist/test/unit/eth.d.ts +2 -0
- package/dist/test/unit/eth.d.ts.map +1 -0
- package/dist/test/unit/eth.js +2701 -0
- package/dist/test/unit/ethWallet.d.ts +2 -0
- package/dist/test/unit/ethWallet.d.ts.map +1 -0
- package/dist/test/unit/ethWallet.js +552 -0
- package/dist/test/unit/fixtures/ethMultiSigBackupKey.d.ts +4 -0
- package/dist/test/unit/fixtures/ethMultiSigBackupKey.d.ts.map +1 -0
- package/dist/test/unit/fixtures/ethMultiSigBackupKey.js +10 -0
- package/dist/test/unit/fixtures/ethTssBackupKey.d.ts +5 -0
- package/dist/test/unit/fixtures/ethTssBackupKey.d.ts.map +1 -0
- package/dist/test/unit/fixtures/ethTssBackupKey.js +25 -0
- package/dist/test/unit/getBuilder.d.ts +3 -0
- package/dist/test/unit/getBuilder.d.ts.map +1 -0
- package/dist/test/unit/getBuilder.js +10 -0
- package/dist/test/unit/keyPair.d.ts +2 -0
- package/dist/test/unit/keyPair.d.ts.map +1 -0
- package/dist/test/unit/keyPair.js +175 -0
- package/dist/test/unit/register.d.ts +2 -0
- package/dist/test/unit/register.d.ts.map +1 -0
- package/dist/test/unit/register.js +75 -0
- package/dist/test/unit/transaction.d.ts +2 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +117 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.js +101 -0
- package/dist/test/unit/transactionBuilder/contractCall.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/contractCall.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/contractCall.js +101 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegation.js +59 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.js +136 -0
- package/dist/test/unit/transactionBuilder/flushCoins.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/flushCoins.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/flushCoins.js +133 -0
- package/dist/test/unit/transactionBuilder/flushTokens.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/flushTokens.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/flushTokens.js +298 -0
- package/dist/test/unit/transactionBuilder/send.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/send.js +331 -0
- package/dist/test/unit/transactionBuilder/sendERC7984Token.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/sendERC7984Token.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/sendERC7984Token.js +361 -0
- package/dist/test/unit/transactionBuilder/sendNFT.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/sendNFT.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/sendNFT.js +295 -0
- package/dist/test/unit/transactionBuilder/singleSigSend.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/singleSigSend.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/singleSigSend.js +196 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.js +436 -0
- package/dist/test/unit/transferBuilder.d.ts +2 -0
- package/dist/test/unit/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transferBuilder.js +124 -0
- package/dist/test/unit/utils.d.ts +2 -0
- package/dist/test/unit/utils.d.ts.map +1 -0
- package/dist/test/unit/utils.js +74 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +17 -13
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -771
|
@@ -0,0 +1,2701 @@
|
|
|
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 sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
40
|
+
const nock_1 = __importDefault(require("nock"));
|
|
41
|
+
const sinon_1 = __importDefault(require("sinon"));
|
|
42
|
+
const secp256k1_1 = require("@bitgo-beta/secp256k1");
|
|
43
|
+
const secp256k1 = __importStar(require("secp256k1"));
|
|
44
|
+
const superagent_1 = __importDefault(require("superagent"));
|
|
45
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
46
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
47
|
+
const src_1 = require("../../src");
|
|
48
|
+
const assert_1 = __importDefault(require("assert"));
|
|
49
|
+
const getBuilder_1 = require("./getBuilder");
|
|
50
|
+
const testData = __importStar(require("../resources/eth"));
|
|
51
|
+
const mockData = __importStar(require("../fixtures/eth"));
|
|
52
|
+
const should_1 = __importDefault(require("should"));
|
|
53
|
+
const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
|
|
54
|
+
const ethMultiSigBackupKey_1 = require("./fixtures/ethMultiSigBackupKey");
|
|
55
|
+
const ethTssBackupKey_1 = require("./fixtures/ethTssBackupKey");
|
|
56
|
+
nock_1.default.enableNetConnect();
|
|
57
|
+
describe('ETH:', function () {
|
|
58
|
+
let bitgo;
|
|
59
|
+
let hopTxBitgoSignature;
|
|
60
|
+
let sandbox;
|
|
61
|
+
const address1 = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
62
|
+
const address2 = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
|
|
63
|
+
const hopContractAddress = '0x47ce7cc86efefef19f8fb516b11735d183da8635';
|
|
64
|
+
const hopDestinationAddress = '0x9c7e8ce6825bD48278B3Ab59228EE26f8BE7925b';
|
|
65
|
+
const hopTx = '0xf86b808504a817c8ff8252ff949c7e8ce6825bd48278b3ab59228ee26f8be7925b87038d7ea4c68000801ca011bc22c664570133dfca4f08a0b8d02339cf467046d6a4152f04f368d0eaf99ea01d6dc5cf0c897c8d4c3e1df53d0d042784c424536a4cc5b802552b7d64fee8b5';
|
|
66
|
+
const hopTxid = '0x4af65143bc77da2b50f35b3d13cacb4db18f026bf84bc0743550bc57b9b53351';
|
|
67
|
+
const userReqSig = '0x404db307f6147f0d8cd338c34c13906ef46a6faa7e0e119d5194ef05aec16e6f3d710f9b7901460f97e924066b62efd74443bd34402c6d40b49c203a559ff2c8';
|
|
68
|
+
const buildDefiTxHex = async (data) => {
|
|
69
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
70
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
71
|
+
txBuilder.fee({ fee: '10', gasLimit: '100000' });
|
|
72
|
+
txBuilder.counter(1);
|
|
73
|
+
txBuilder.contract(address1);
|
|
74
|
+
txBuilder.data(data);
|
|
75
|
+
return (await txBuilder.build()).toBroadcastFormat();
|
|
76
|
+
};
|
|
77
|
+
const defiCalldata = (signature, values) => {
|
|
78
|
+
const types = signature.slice(signature.indexOf('(') + 1, -1).split(',');
|
|
79
|
+
const methodId = ethereumjs_abi_1.default.methodID(signature.split('(')[0], types);
|
|
80
|
+
return '0x' + Buffer.concat([methodId, ethereumjs_abi_1.default.rawEncode(types, values)]).toString('hex');
|
|
81
|
+
};
|
|
82
|
+
before(function () {
|
|
83
|
+
const bitgoKeyXprv = 'xprv9s21ZrQH143K3tpWBHWe31sLoXNRQ9AvRYJgitkKxQ4ATFQMwvr7hHNqYRUnS7PsjzB7aK1VxqHLuNQjj1sckJ2Jwo2qxmsvejwECSpFMfC';
|
|
84
|
+
const bitgoKey = secp256k1_1.bip32.fromBase58(bitgoKeyXprv);
|
|
85
|
+
if (!bitgoKey.privateKey) {
|
|
86
|
+
throw new Error('no privateKey');
|
|
87
|
+
}
|
|
88
|
+
const bitgoXpub = bitgoKey.neutered().toBase58();
|
|
89
|
+
hopTxBitgoSignature =
|
|
90
|
+
'0xaa' +
|
|
91
|
+
Buffer.from(secp256k1.ecdsaSign(Buffer.from(hopTxid.slice(2), 'hex'), bitgoKey.privateKey).signature).toString('hex');
|
|
92
|
+
const env = 'test';
|
|
93
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
94
|
+
src_1.Erc20Token.createTokenConstructors().forEach(({ name, coinConstructor }) => {
|
|
95
|
+
bitgo.safeRegister(name, coinConstructor);
|
|
96
|
+
});
|
|
97
|
+
bitgo.safeRegister('teth', src_1.Teth.createInstance);
|
|
98
|
+
bitgo.safeRegister('hteth', src_1.Hteth.createInstance);
|
|
99
|
+
sdk_core_1.common.Environments[env].hsmXpub = bitgoXpub;
|
|
100
|
+
bitgo.initializeTestVars();
|
|
101
|
+
sandbox = sinon_1.default.createSandbox();
|
|
102
|
+
});
|
|
103
|
+
after(function () {
|
|
104
|
+
nock_1.default.cleanAll();
|
|
105
|
+
sandbox.restore();
|
|
106
|
+
});
|
|
107
|
+
describe('EIP1559', function () {
|
|
108
|
+
it('should sign a transaction with EIP1559 fee params', async function () {
|
|
109
|
+
const coin = bitgo.coin('teth');
|
|
110
|
+
const userKeychain = {
|
|
111
|
+
prv: 'xprv9s21ZrQH143K3hekyNj7TciR4XNYe1kMj68W2ipjJGNHETWP7o42AjDnSPgKhdZ4x8NBAvaL72RrXjuXNdmkMqLERZza73oYugGtbLFXG8g',
|
|
112
|
+
pub: 'xpub661MyMwAqRbcGBjE5QG7pkf9cZD33UUD6K46q7ELrbuG7FqXfLNGiXYGHeEnGBb5AWREnk1eA28g8ArZvURbhshXWkTtddHRo54fgyVvLdb',
|
|
113
|
+
rawPub: '023636e68b7b204573abda2616aff6b584910dece2543f1cc6d842caac7d74974b',
|
|
114
|
+
rawPrv: '7438a50010ce7b1dfd86e68046cc78ba1ebd242d6d85d9904d3fcc08734bc172',
|
|
115
|
+
};
|
|
116
|
+
const halfSignedTransaction = await coin.signTransaction({
|
|
117
|
+
txPrebuild: {
|
|
118
|
+
eip1559: { maxPriorityFeePerGas: 10, maxFeePerGas: 10 },
|
|
119
|
+
isBatch: false,
|
|
120
|
+
recipients: [
|
|
121
|
+
{
|
|
122
|
+
amount: '42',
|
|
123
|
+
address: '0xc93b13642d93b4218bb85f67317d6b37286e8028',
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
expireTime: 1627949214,
|
|
127
|
+
contractSequenceId: 12,
|
|
128
|
+
gasLimit: undefined,
|
|
129
|
+
gasPrice: undefined,
|
|
130
|
+
hopTransaction: undefined,
|
|
131
|
+
backupKeyNonce: undefined,
|
|
132
|
+
sequenceId: undefined,
|
|
133
|
+
nextContractSequenceId: 0,
|
|
134
|
+
},
|
|
135
|
+
prv: userKeychain.prv,
|
|
136
|
+
});
|
|
137
|
+
halfSignedTransaction.halfSigned.eip1559.maxPriorityFeePerGas.should.equal(10);
|
|
138
|
+
halfSignedTransaction.halfSigned.eip1559.maxFeePerGas.should.equal(10);
|
|
139
|
+
});
|
|
140
|
+
it('should sign a transaction with EIP1559 fee params for CCR', async function () {
|
|
141
|
+
const coin = bitgo.coin('hteth');
|
|
142
|
+
const signTransaction = sinon_1.default.spy(src_1.AbstractEthLikeNewCoins.prototype, 'signTransaction');
|
|
143
|
+
const userKeychain = {
|
|
144
|
+
prv: 'xprv9s21ZrQH143K3hekyNj7TciR4XNYe1kMj68W2ipjJGNHETWP7o42AjDnSPgKhdZ4x8NBAvaL72RrXjuXNdmkMqLERZza73oYugGtbLFXG8g',
|
|
145
|
+
pub: 'xpub661MyMwAqRbcGBjE5QG7pkf9cZD33UUD6K46q7ELrbuG7FqXfLNGiXYGHeEnGBb5AWREnk1eA28g8ArZvURbhshXWkTtddHRo54fgyVvLdb',
|
|
146
|
+
rawPub: '023636e68b7b204573abda2616aff6b584910dece2543f1cc6d842caac7d74974b',
|
|
147
|
+
rawPrv: '7438a50010ce7b1dfd86e68046cc78ba1ebd242d6d85d9904d3fcc08734bc172',
|
|
148
|
+
};
|
|
149
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
150
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
151
|
+
txBuilder.fee({
|
|
152
|
+
fee: '10',
|
|
153
|
+
gasLimit: '1000',
|
|
154
|
+
});
|
|
155
|
+
const key = testData.KEYPAIR_PRV.getKeys().prv;
|
|
156
|
+
const transferBuilder = txBuilder.transfer();
|
|
157
|
+
transferBuilder
|
|
158
|
+
.amount('0')
|
|
159
|
+
.to('0x19645032c7f1533395d44a629462e751084d3e4c')
|
|
160
|
+
.expirationTime(1590066728)
|
|
161
|
+
.contractSequenceId(5)
|
|
162
|
+
.key(key);
|
|
163
|
+
txBuilder.contract(address1);
|
|
164
|
+
const tx = await txBuilder.build();
|
|
165
|
+
const halfSignedTransaction = await coin.signTransaction({
|
|
166
|
+
txPrebuild: {
|
|
167
|
+
eip1559: { maxPriorityFeePerGas: 10, maxFeePerGas: 10 },
|
|
168
|
+
isBatch: false,
|
|
169
|
+
recipients: [
|
|
170
|
+
{
|
|
171
|
+
amount: '42',
|
|
172
|
+
address: '0xc93b13642d93b4218bb85f67317d6b37286e8028',
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
expireTime: 1627949214,
|
|
176
|
+
contractSequenceId: 12,
|
|
177
|
+
gasLimit: undefined,
|
|
178
|
+
gasPrice: undefined,
|
|
179
|
+
hopTransaction: undefined,
|
|
180
|
+
backupKeyNonce: undefined,
|
|
181
|
+
sequenceId: undefined,
|
|
182
|
+
nextContractSequenceId: 0,
|
|
183
|
+
txHex: tx.toBroadcastFormat(),
|
|
184
|
+
},
|
|
185
|
+
prv: userKeychain.prv,
|
|
186
|
+
isEvmBasedCrossChainRecovery: true,
|
|
187
|
+
});
|
|
188
|
+
(0, assert_1.default)(halfSignedTransaction.halfSigned.txHex);
|
|
189
|
+
assert_1.default.strictEqual(halfSignedTransaction.halfSigned.eip1559.maxFeePerGas, 10);
|
|
190
|
+
sandbox.assert.calledOnce(signTransaction);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
describe('Transaction Verification', function () {
|
|
194
|
+
it('should verify a normal txPrebuild from the bitgo server that matches the client txParams', async function () {
|
|
195
|
+
const coin = bitgo.coin('teth');
|
|
196
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
197
|
+
const txParams = {
|
|
198
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
199
|
+
wallet: wallet,
|
|
200
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
201
|
+
};
|
|
202
|
+
const txPrebuild = {
|
|
203
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
204
|
+
nextContractSequenceId: 0,
|
|
205
|
+
gasPrice: 20000000000,
|
|
206
|
+
gasLimit: 500000,
|
|
207
|
+
isBatch: false,
|
|
208
|
+
coin: 'teth',
|
|
209
|
+
wallet: 'fakeWalletId',
|
|
210
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
211
|
+
};
|
|
212
|
+
const verification = {};
|
|
213
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
214
|
+
txParams,
|
|
215
|
+
txPrebuild: txPrebuild,
|
|
216
|
+
wallet,
|
|
217
|
+
verification,
|
|
218
|
+
});
|
|
219
|
+
isTransactionVerified.should.equal(true);
|
|
220
|
+
});
|
|
221
|
+
it('should verify a batch txPrebuild from the bitgo server that matches the client txParams', async function () {
|
|
222
|
+
const coin = bitgo.coin('teth');
|
|
223
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
224
|
+
const txParams = {
|
|
225
|
+
recipients: [
|
|
226
|
+
{ amount: '1000000000000', address: address1 },
|
|
227
|
+
{ amount: '2500000000000', address: address2 },
|
|
228
|
+
],
|
|
229
|
+
wallet: wallet,
|
|
230
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
231
|
+
};
|
|
232
|
+
const txPrebuild = {
|
|
233
|
+
recipients: [
|
|
234
|
+
{ amount: '3500000000000', address: (coin?.staticsCoin?.network).batcherContractAddress },
|
|
235
|
+
],
|
|
236
|
+
nextContractSequenceId: 0,
|
|
237
|
+
gasPrice: 20000000000,
|
|
238
|
+
gasLimit: 500000,
|
|
239
|
+
isBatch: true,
|
|
240
|
+
coin: 'teth',
|
|
241
|
+
walletId: 'fakeWalletId',
|
|
242
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
243
|
+
};
|
|
244
|
+
const verification = {};
|
|
245
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
246
|
+
txParams,
|
|
247
|
+
txPrebuild: txPrebuild,
|
|
248
|
+
wallet,
|
|
249
|
+
verification,
|
|
250
|
+
});
|
|
251
|
+
isTransactionVerified.should.equal(true);
|
|
252
|
+
});
|
|
253
|
+
it('should verify ENS address resolution changing recipient address in client txParams', async function () {
|
|
254
|
+
const coin = bitgo.coin('teth');
|
|
255
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
256
|
+
const txParams = {
|
|
257
|
+
recipients: [{ amount: '1000000000000', address: 'bitgotestwallet.eth' }],
|
|
258
|
+
wallet: wallet,
|
|
259
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
260
|
+
};
|
|
261
|
+
const txPrebuild = {
|
|
262
|
+
recipients: [{ amount: '1000000000000', address: '0x40a663963810449d6e72533657a74f112c3b901a' }],
|
|
263
|
+
nextContractSequenceId: 0,
|
|
264
|
+
gasPrice: 20000000000,
|
|
265
|
+
gasLimit: 500000,
|
|
266
|
+
isBatch: false,
|
|
267
|
+
coin: 'teth',
|
|
268
|
+
walletId: 'fakeWalletId',
|
|
269
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
270
|
+
};
|
|
271
|
+
const verification = {};
|
|
272
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
273
|
+
txParams,
|
|
274
|
+
txPrebuild: txPrebuild,
|
|
275
|
+
wallet,
|
|
276
|
+
verification,
|
|
277
|
+
});
|
|
278
|
+
isTransactionVerified.should.equal(true);
|
|
279
|
+
});
|
|
280
|
+
it('should verify a hop txPrebuild from the bitgo server that matches the client txParams', async function () {
|
|
281
|
+
const coin = bitgo.coin('teth');
|
|
282
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
283
|
+
const txParams = {
|
|
284
|
+
recipients: [{ amount: 1000000000000000, address: hopDestinationAddress }],
|
|
285
|
+
wallet: wallet,
|
|
286
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
287
|
+
hop: true,
|
|
288
|
+
};
|
|
289
|
+
const txPrebuild = {
|
|
290
|
+
recipients: [{ amount: '5000000000000000', address: hopContractAddress }],
|
|
291
|
+
nextContractSequenceId: 0,
|
|
292
|
+
gasPrice: 20000000000,
|
|
293
|
+
gasLimit: 500000,
|
|
294
|
+
isBatch: false,
|
|
295
|
+
coin: 'teth',
|
|
296
|
+
walletId: 'fakeWalletId',
|
|
297
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
298
|
+
hopTransaction: {
|
|
299
|
+
tx: hopTx,
|
|
300
|
+
id: hopTxid,
|
|
301
|
+
signature: hopTxBitgoSignature,
|
|
302
|
+
paymentId: '2773928196',
|
|
303
|
+
gasPrice: 20000000000,
|
|
304
|
+
gasLimit: 500000,
|
|
305
|
+
amount: '1000000000000000',
|
|
306
|
+
recipient: hopDestinationAddress,
|
|
307
|
+
nonce: 0,
|
|
308
|
+
userReqSig: userReqSig,
|
|
309
|
+
gasPriceMax: 500000000000,
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
const verification = {};
|
|
313
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
314
|
+
txParams,
|
|
315
|
+
txPrebuild: txPrebuild,
|
|
316
|
+
wallet,
|
|
317
|
+
verification,
|
|
318
|
+
});
|
|
319
|
+
isTransactionVerified.should.equal(true);
|
|
320
|
+
});
|
|
321
|
+
it('should reject when client txParams are missing', async function () {
|
|
322
|
+
const coin = bitgo.coin('teth');
|
|
323
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
324
|
+
const txParams = null;
|
|
325
|
+
const txPrebuild = {
|
|
326
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
327
|
+
nextContractSequenceId: 0,
|
|
328
|
+
gasPrice: 20000000000,
|
|
329
|
+
gasLimit: 500000,
|
|
330
|
+
isBatch: false,
|
|
331
|
+
coin: 'teth',
|
|
332
|
+
walletId: 'fakeWalletId',
|
|
333
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
334
|
+
};
|
|
335
|
+
const verification = {};
|
|
336
|
+
await coin
|
|
337
|
+
.verifyTransaction({ txParams: txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
338
|
+
.should.be.rejectedWith('missing params');
|
|
339
|
+
});
|
|
340
|
+
it('should reject txPrebuild that is both batch and hop', async function () {
|
|
341
|
+
const coin = bitgo.coin('teth');
|
|
342
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
343
|
+
const txParams = {
|
|
344
|
+
recipients: [
|
|
345
|
+
{ amount: '1000000000000', address: address1 },
|
|
346
|
+
{ amount: '2500000000000', address: address2 },
|
|
347
|
+
],
|
|
348
|
+
wallet: wallet,
|
|
349
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
350
|
+
hop: true,
|
|
351
|
+
};
|
|
352
|
+
const txPrebuild = {
|
|
353
|
+
recipients: [{ amount: '3500000000000', address: address1 }],
|
|
354
|
+
nextContractSequenceId: 0,
|
|
355
|
+
gasPrice: 20000000000,
|
|
356
|
+
gasLimit: 500000,
|
|
357
|
+
isBatch: true,
|
|
358
|
+
coin: 'teth',
|
|
359
|
+
walletId: 'fakeWalletId',
|
|
360
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
361
|
+
hopTransaction: {
|
|
362
|
+
tx: hopTx,
|
|
363
|
+
id: hopTxid,
|
|
364
|
+
signature: hopTxBitgoSignature,
|
|
365
|
+
paymentId: '2773928196',
|
|
366
|
+
gasPrice: 20000000000,
|
|
367
|
+
gasLimit: 500000,
|
|
368
|
+
amount: '1000000000000000',
|
|
369
|
+
recipient: hopDestinationAddress,
|
|
370
|
+
nonce: 0,
|
|
371
|
+
userReqSig: userReqSig,
|
|
372
|
+
gasPriceMax: 500000000000,
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
const verification = {};
|
|
376
|
+
await coin
|
|
377
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
378
|
+
.should.be.rejectedWith('tx cannot be both a batch and hop transaction');
|
|
379
|
+
});
|
|
380
|
+
it('should reject a txPrebuild with more than one recipient', async function () {
|
|
381
|
+
const coin = bitgo.coin('teth');
|
|
382
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
383
|
+
const txParams = {
|
|
384
|
+
recipients: [
|
|
385
|
+
{ amount: '1000000000000', address: address1 },
|
|
386
|
+
{ amount: '2500000000000', address: address2 },
|
|
387
|
+
],
|
|
388
|
+
wallet: wallet,
|
|
389
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
390
|
+
};
|
|
391
|
+
const txPrebuild = {
|
|
392
|
+
recipients: [
|
|
393
|
+
{ amount: '1000000000000', address: address1 },
|
|
394
|
+
{ amount: '2500000000000', address: address2 },
|
|
395
|
+
],
|
|
396
|
+
nextContractSequenceId: 0,
|
|
397
|
+
gasPrice: 20000000000,
|
|
398
|
+
gasLimit: 500000,
|
|
399
|
+
isBatch: true,
|
|
400
|
+
coin: 'teth',
|
|
401
|
+
walletId: 'fakeWalletId',
|
|
402
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
403
|
+
};
|
|
404
|
+
const verification = {};
|
|
405
|
+
await coin
|
|
406
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
407
|
+
.should.be.rejectedWith(`teth doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
|
|
408
|
+
});
|
|
409
|
+
it('should reject a hop txPrebuild that does not send to its hop address', async function () {
|
|
410
|
+
const coin = bitgo.coin('teth');
|
|
411
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
412
|
+
const txParams = {
|
|
413
|
+
recipients: [{ amount: '1000000000000000', address: hopDestinationAddress }],
|
|
414
|
+
wallet: wallet,
|
|
415
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
416
|
+
hop: true,
|
|
417
|
+
};
|
|
418
|
+
const txPrebuild = {
|
|
419
|
+
recipients: [{ amount: '5000000000000000', address: address1 }],
|
|
420
|
+
nextContractSequenceId: 0,
|
|
421
|
+
gasPrice: 20000000000,
|
|
422
|
+
gasLimit: 500000,
|
|
423
|
+
isBatch: false,
|
|
424
|
+
coin: 'teth',
|
|
425
|
+
walletId: 'fakeWalletId',
|
|
426
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
427
|
+
hopTransaction: {
|
|
428
|
+
tx: hopTx,
|
|
429
|
+
id: hopTxid,
|
|
430
|
+
signature: hopTxBitgoSignature,
|
|
431
|
+
paymentId: '0',
|
|
432
|
+
gasPrice: 20000000000,
|
|
433
|
+
gasLimit: 500000,
|
|
434
|
+
amount: '1000000000000000',
|
|
435
|
+
recipient: hopDestinationAddress,
|
|
436
|
+
nonce: 0,
|
|
437
|
+
userReqSig: userReqSig,
|
|
438
|
+
gasPriceMax: 500000000000,
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
const verification = {};
|
|
442
|
+
await coin
|
|
443
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
444
|
+
.should.be.rejectedWith('recipient address of txPrebuild does not match hop address');
|
|
445
|
+
});
|
|
446
|
+
it('should reject a batch txPrebuild from the bitgo server with the wrong total amount', async function () {
|
|
447
|
+
const coin = bitgo.coin('teth');
|
|
448
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
449
|
+
const txParams = {
|
|
450
|
+
recipients: [
|
|
451
|
+
{ amount: '1000000000000', address: address1 },
|
|
452
|
+
{ amount: '2500000000000', address: address2 },
|
|
453
|
+
],
|
|
454
|
+
wallet: wallet,
|
|
455
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
456
|
+
};
|
|
457
|
+
const txPrebuild = {
|
|
458
|
+
recipients: [
|
|
459
|
+
{ amount: '5500000000000', address: (coin?.staticsCoin?.network).batcherContractAddress },
|
|
460
|
+
],
|
|
461
|
+
nextContractSequenceId: 0,
|
|
462
|
+
gasPrice: 20000000000,
|
|
463
|
+
gasLimit: 500000,
|
|
464
|
+
isBatch: true,
|
|
465
|
+
coin: 'teth',
|
|
466
|
+
walletId: 'fakeWalletId',
|
|
467
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
468
|
+
};
|
|
469
|
+
const verification = {};
|
|
470
|
+
await coin
|
|
471
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
472
|
+
.should.be.rejectedWith('batch transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client');
|
|
473
|
+
});
|
|
474
|
+
it('should reject a batch txPrebuild from the bitgo server that does not send to the batcher contract address', async function () {
|
|
475
|
+
const coin = bitgo.coin('teth');
|
|
476
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
477
|
+
const txParams = {
|
|
478
|
+
recipients: [
|
|
479
|
+
{ amount: '1000000000000', address: address1 },
|
|
480
|
+
{ amount: '2500000000000', address: address2 },
|
|
481
|
+
],
|
|
482
|
+
wallet: wallet,
|
|
483
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
484
|
+
};
|
|
485
|
+
const txPrebuild = {
|
|
486
|
+
recipients: [{ amount: '3500000000000', address: hopContractAddress }],
|
|
487
|
+
nextContractSequenceId: 0,
|
|
488
|
+
gasPrice: 20000000000,
|
|
489
|
+
gasLimit: 500000,
|
|
490
|
+
isBatch: true,
|
|
491
|
+
coin: 'teth',
|
|
492
|
+
walletId: 'fakeWalletId',
|
|
493
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
494
|
+
};
|
|
495
|
+
const verification = {};
|
|
496
|
+
await coin
|
|
497
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
498
|
+
.should.be.rejectedWith('recipient address of txPrebuild does not match batcher address');
|
|
499
|
+
});
|
|
500
|
+
it('should reject a normal txPrebuild from the bitgo server with the wrong amount', async function () {
|
|
501
|
+
const coin = bitgo.coin('teth');
|
|
502
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
503
|
+
const txParams = {
|
|
504
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
505
|
+
wallet: wallet,
|
|
506
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
507
|
+
};
|
|
508
|
+
const txPrebuild = {
|
|
509
|
+
recipients: [{ amount: '2000000000000', address: address1 }],
|
|
510
|
+
nextContractSequenceId: 0,
|
|
511
|
+
gasPrice: 20000000000,
|
|
512
|
+
gasLimit: 500000,
|
|
513
|
+
isBatch: false,
|
|
514
|
+
coin: 'teth',
|
|
515
|
+
walletId: 'fakeWalletId',
|
|
516
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
517
|
+
};
|
|
518
|
+
const verification = {};
|
|
519
|
+
await coin
|
|
520
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
521
|
+
.should.be.rejectedWith('normal transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client');
|
|
522
|
+
});
|
|
523
|
+
it('should reject a normal txPrebuild from the bitgo server with the wrong recipient', async function () {
|
|
524
|
+
const coin = bitgo.coin('teth');
|
|
525
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
526
|
+
const txParams = {
|
|
527
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
528
|
+
wallet: wallet,
|
|
529
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
530
|
+
};
|
|
531
|
+
const txPrebuild = {
|
|
532
|
+
recipients: [{ amount: '1000000000000', address: address2 }],
|
|
533
|
+
nextContractSequenceId: 0,
|
|
534
|
+
gasPrice: 20000000000,
|
|
535
|
+
gasLimit: 500000,
|
|
536
|
+
isBatch: false,
|
|
537
|
+
coin: 'teth',
|
|
538
|
+
walletId: 'fakeWalletId',
|
|
539
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
540
|
+
};
|
|
541
|
+
const verification = {};
|
|
542
|
+
await coin
|
|
543
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
544
|
+
.should.be.rejectedWith('destination address in normal txPrebuild does not match that in txParams supplied by client');
|
|
545
|
+
});
|
|
546
|
+
it('should verify a token txPrebuild from the bitgo server that matches the client txParams', async function () {
|
|
547
|
+
const coin = bitgo.coin('test');
|
|
548
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
549
|
+
const txParams = {
|
|
550
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
551
|
+
wallet: wallet,
|
|
552
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
553
|
+
};
|
|
554
|
+
const txPrebuild = {
|
|
555
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
556
|
+
nextContractSequenceId: 0,
|
|
557
|
+
gasPrice: 20000000000,
|
|
558
|
+
gasLimit: 500000,
|
|
559
|
+
isBatch: false,
|
|
560
|
+
coin: 'teth',
|
|
561
|
+
token: 'test',
|
|
562
|
+
walletId: 'fakeWalletId',
|
|
563
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
564
|
+
};
|
|
565
|
+
const verification = {};
|
|
566
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
567
|
+
txParams,
|
|
568
|
+
txPrebuild: txPrebuild,
|
|
569
|
+
wallet,
|
|
570
|
+
verification,
|
|
571
|
+
});
|
|
572
|
+
isTransactionVerified.should.equal(true);
|
|
573
|
+
});
|
|
574
|
+
it('should reject a txPrebuild from the bitgo server with the wrong coin', async function () {
|
|
575
|
+
const coin = bitgo.coin('teth');
|
|
576
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {});
|
|
577
|
+
const txParams = {
|
|
578
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
579
|
+
wallet: wallet,
|
|
580
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
581
|
+
};
|
|
582
|
+
const txPrebuild = {
|
|
583
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
584
|
+
nextContractSequenceId: 0,
|
|
585
|
+
gasPrice: 20000000000,
|
|
586
|
+
gasLimit: 500000,
|
|
587
|
+
isBatch: false,
|
|
588
|
+
coin: 'btc',
|
|
589
|
+
walletId: 'fakeWalletId',
|
|
590
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
591
|
+
};
|
|
592
|
+
const verification = {};
|
|
593
|
+
await coin
|
|
594
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
595
|
+
.should.be.rejectedWith('coin in txPrebuild did not match that in txParams supplied by client');
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
describe('TSS Transaction Verification', function () {
|
|
599
|
+
const expectDefiRejection = async (p, messagePattern) => {
|
|
600
|
+
try {
|
|
601
|
+
await p;
|
|
602
|
+
}
|
|
603
|
+
catch (err) {
|
|
604
|
+
err.should.be.instanceOf(sdk_core_1.TxIntentMismatchRecipientError);
|
|
605
|
+
err.message.should.match(messagePattern);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
throw new Error('expected verifyTransaction to be rejected, but it resolved');
|
|
609
|
+
};
|
|
610
|
+
it('should verify TSS consolidation transaction when txPrebuild has consolidateId', async function () {
|
|
611
|
+
const coin = bitgo.coin('hteth');
|
|
612
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
613
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
614
|
+
coinSpecific: {
|
|
615
|
+
baseAddress: baseAddress,
|
|
616
|
+
},
|
|
617
|
+
});
|
|
618
|
+
// txParams without recipients (as in consolidation flow)
|
|
619
|
+
const txParams = {
|
|
620
|
+
wallet: wallet,
|
|
621
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
622
|
+
};
|
|
623
|
+
// txPrebuild with consolidateId (set by server during consolidation build)
|
|
624
|
+
const txPrebuild = {
|
|
625
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
626
|
+
txHex: '0x',
|
|
627
|
+
coin: 'hteth',
|
|
628
|
+
walletId: 'fakeWalletId',
|
|
629
|
+
};
|
|
630
|
+
const verification = {};
|
|
631
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
632
|
+
txParams: txParams,
|
|
633
|
+
txPrebuild: txPrebuild,
|
|
634
|
+
wallet,
|
|
635
|
+
verification,
|
|
636
|
+
walletType: 'tss',
|
|
637
|
+
});
|
|
638
|
+
isTransactionVerified.should.equal(true);
|
|
639
|
+
});
|
|
640
|
+
it('should verify TSS transaction when txParams.type is consolidate', async function () {
|
|
641
|
+
const coin = bitgo.coin('hteth');
|
|
642
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
643
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
644
|
+
coinSpecific: {
|
|
645
|
+
baseAddress: baseAddress,
|
|
646
|
+
},
|
|
647
|
+
});
|
|
648
|
+
const txParams = {
|
|
649
|
+
type: 'consolidate',
|
|
650
|
+
wallet: wallet,
|
|
651
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
652
|
+
};
|
|
653
|
+
const txPrebuild = {
|
|
654
|
+
txHex: '0x',
|
|
655
|
+
coin: 'hteth',
|
|
656
|
+
walletId: 'fakeWalletId',
|
|
657
|
+
};
|
|
658
|
+
const verification = {};
|
|
659
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
660
|
+
txParams: txParams,
|
|
661
|
+
txPrebuild: txPrebuild,
|
|
662
|
+
wallet,
|
|
663
|
+
verification,
|
|
664
|
+
walletType: 'tss',
|
|
665
|
+
});
|
|
666
|
+
isTransactionVerified.should.equal(true);
|
|
667
|
+
});
|
|
668
|
+
it('should verify TSS transaction when txParams.prebuildTx has consolidateId', async function () {
|
|
669
|
+
const coin = bitgo.coin('hteth');
|
|
670
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
671
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
672
|
+
coinSpecific: {
|
|
673
|
+
baseAddress: baseAddress,
|
|
674
|
+
},
|
|
675
|
+
});
|
|
676
|
+
const txParams = {
|
|
677
|
+
wallet: wallet,
|
|
678
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
679
|
+
prebuildTx: {
|
|
680
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
681
|
+
},
|
|
682
|
+
};
|
|
683
|
+
const txPrebuild = {
|
|
684
|
+
txHex: '0x',
|
|
685
|
+
coin: 'hteth',
|
|
686
|
+
walletId: 'fakeWalletId',
|
|
687
|
+
};
|
|
688
|
+
const verification = {};
|
|
689
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
690
|
+
txParams: txParams,
|
|
691
|
+
txPrebuild: txPrebuild,
|
|
692
|
+
wallet,
|
|
693
|
+
verification,
|
|
694
|
+
walletType: 'tss',
|
|
695
|
+
});
|
|
696
|
+
isTransactionVerified.should.equal(true);
|
|
697
|
+
});
|
|
698
|
+
it('should reject TSS transaction without recipients, consolidateId, or valid type', async function () {
|
|
699
|
+
const coin = bitgo.coin('hteth');
|
|
700
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
701
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
702
|
+
coinSpecific: {
|
|
703
|
+
baseAddress: baseAddress,
|
|
704
|
+
},
|
|
705
|
+
});
|
|
706
|
+
const txParams = {
|
|
707
|
+
wallet: wallet,
|
|
708
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
709
|
+
};
|
|
710
|
+
const txPrebuild = {
|
|
711
|
+
txHex: '0x',
|
|
712
|
+
coin: 'hteth',
|
|
713
|
+
walletId: 'fakeWalletId',
|
|
714
|
+
};
|
|
715
|
+
const verification = {};
|
|
716
|
+
await coin
|
|
717
|
+
.verifyTransaction({
|
|
718
|
+
txParams: txParams,
|
|
719
|
+
txPrebuild: txPrebuild,
|
|
720
|
+
wallet,
|
|
721
|
+
verification,
|
|
722
|
+
walletType: 'tss',
|
|
723
|
+
})
|
|
724
|
+
.should.be.rejectedWith('missing txParams');
|
|
725
|
+
});
|
|
726
|
+
it('should verify TSS transaction with acceleration type', async function () {
|
|
727
|
+
const coin = bitgo.coin('hteth');
|
|
728
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
729
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
730
|
+
coinSpecific: {
|
|
731
|
+
baseAddress: baseAddress,
|
|
732
|
+
},
|
|
733
|
+
});
|
|
734
|
+
const txParams = {
|
|
735
|
+
type: 'acceleration',
|
|
736
|
+
wallet: wallet,
|
|
737
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
738
|
+
};
|
|
739
|
+
const txPrebuild = {
|
|
740
|
+
txHex: '0x',
|
|
741
|
+
coin: 'hteth',
|
|
742
|
+
walletId: 'fakeWalletId',
|
|
743
|
+
};
|
|
744
|
+
const verification = {};
|
|
745
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
746
|
+
txParams: txParams,
|
|
747
|
+
txPrebuild: txPrebuild,
|
|
748
|
+
wallet,
|
|
749
|
+
verification,
|
|
750
|
+
walletType: 'tss',
|
|
751
|
+
});
|
|
752
|
+
isTransactionVerified.should.equal(true);
|
|
753
|
+
});
|
|
754
|
+
it('should verify TSS transaction with fillNonce type', async function () {
|
|
755
|
+
const coin = bitgo.coin('hteth');
|
|
756
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
757
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
758
|
+
coinSpecific: {
|
|
759
|
+
baseAddress: baseAddress,
|
|
760
|
+
},
|
|
761
|
+
});
|
|
762
|
+
const txParams = {
|
|
763
|
+
type: 'fillNonce',
|
|
764
|
+
wallet: wallet,
|
|
765
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
766
|
+
};
|
|
767
|
+
const txPrebuild = {
|
|
768
|
+
txHex: '0x',
|
|
769
|
+
coin: 'hteth',
|
|
770
|
+
walletId: 'fakeWalletId',
|
|
771
|
+
};
|
|
772
|
+
const verification = {};
|
|
773
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
774
|
+
txParams: txParams,
|
|
775
|
+
txPrebuild: txPrebuild,
|
|
776
|
+
wallet,
|
|
777
|
+
verification,
|
|
778
|
+
walletType: 'tss',
|
|
779
|
+
});
|
|
780
|
+
isTransactionVerified.should.equal(true);
|
|
781
|
+
});
|
|
782
|
+
it('should verify TSS transaction with defiApprove type', async function () {
|
|
783
|
+
const coin = bitgo.coin('hteth');
|
|
784
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
785
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
786
|
+
coinSpecific: {
|
|
787
|
+
baseAddress: baseAddress,
|
|
788
|
+
},
|
|
789
|
+
});
|
|
790
|
+
// DeFi deposit flow is intent-based: recipients/calldata are built server-side
|
|
791
|
+
// from defiParams, so txParams has no recipients (see CGD-1815).
|
|
792
|
+
const txParams = {
|
|
793
|
+
type: 'defiApprove',
|
|
794
|
+
defiParams: { vaultId: 'hteth-usdc-test', amount: '10' },
|
|
795
|
+
wallet: wallet,
|
|
796
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
797
|
+
};
|
|
798
|
+
const txPrebuild = {
|
|
799
|
+
txHex: await buildDefiTxHex(defiCalldata('approve(address,uint256)', [address1, '10'])),
|
|
800
|
+
coin: 'hteth',
|
|
801
|
+
walletId: 'fakeWalletId',
|
|
802
|
+
};
|
|
803
|
+
const verification = {};
|
|
804
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
805
|
+
txParams: txParams,
|
|
806
|
+
txPrebuild: txPrebuild,
|
|
807
|
+
wallet,
|
|
808
|
+
verification,
|
|
809
|
+
walletType: 'tss',
|
|
810
|
+
});
|
|
811
|
+
isTransactionVerified.should.equal(true);
|
|
812
|
+
});
|
|
813
|
+
it('should verify TSS transaction with wrapApprove type and no recipients', async function () {
|
|
814
|
+
const coin = bitgo.coin('hteth');
|
|
815
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
816
|
+
coinSpecific: {
|
|
817
|
+
baseAddress: '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be',
|
|
818
|
+
},
|
|
819
|
+
});
|
|
820
|
+
// WP derives the underlying token contract, wrapper spender, and approve
|
|
821
|
+
// calldata from tokenName and amount, so the client intent has no recipients.
|
|
822
|
+
const txParams = {
|
|
823
|
+
type: 'wrapApprove',
|
|
824
|
+
tokenName: 'hteth:cusdt',
|
|
825
|
+
amount: '1000000',
|
|
826
|
+
};
|
|
827
|
+
const txPrebuild = {
|
|
828
|
+
txHex: '0x',
|
|
829
|
+
coin: 'hteth',
|
|
830
|
+
walletId: 'fakeWalletId',
|
|
831
|
+
};
|
|
832
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
833
|
+
txParams: txParams,
|
|
834
|
+
txPrebuild: txPrebuild,
|
|
835
|
+
wallet,
|
|
836
|
+
verification: {},
|
|
837
|
+
walletType: 'tss',
|
|
838
|
+
});
|
|
839
|
+
isTransactionVerified.should.equal(true);
|
|
840
|
+
});
|
|
841
|
+
it('should verify TSS transaction with defiDeposit type', async function () {
|
|
842
|
+
const coin = bitgo.coin('hteth');
|
|
843
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
844
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
845
|
+
coinSpecific: {
|
|
846
|
+
baseAddress: baseAddress,
|
|
847
|
+
},
|
|
848
|
+
});
|
|
849
|
+
const txParams = {
|
|
850
|
+
type: 'defiDeposit',
|
|
851
|
+
defiParams: { vaultId: 'hteth-usdc-test', amount: '10', operationId: 'fakeOperationId' },
|
|
852
|
+
wallet: wallet,
|
|
853
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
854
|
+
};
|
|
855
|
+
const txPrebuild = {
|
|
856
|
+
txHex: await buildDefiTxHex(defiCalldata('deposit(uint256,address)', ['10', address1])),
|
|
857
|
+
coin: 'hteth',
|
|
858
|
+
walletId: 'fakeWalletId',
|
|
859
|
+
};
|
|
860
|
+
const verification = {};
|
|
861
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
862
|
+
txParams: txParams,
|
|
863
|
+
txPrebuild: txPrebuild,
|
|
864
|
+
wallet,
|
|
865
|
+
verification,
|
|
866
|
+
walletType: 'tss',
|
|
867
|
+
});
|
|
868
|
+
isTransactionVerified.should.equal(true);
|
|
869
|
+
});
|
|
870
|
+
it('should reject DeFi calldata that redirects funds or grants excess approval', async function () {
|
|
871
|
+
const coin = bitgo.coin('hteth');
|
|
872
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, { coinSpecific: { baseAddress: address1 } });
|
|
873
|
+
const verify = async (type, defiParams, data) => coin.verifyTransaction({
|
|
874
|
+
txParams: { type, defiParams, wallet },
|
|
875
|
+
txPrebuild: { txHex: await buildDefiTxHex(data), coin: 'hteth', walletId: 'fakeWalletId' },
|
|
876
|
+
wallet,
|
|
877
|
+
verification: {},
|
|
878
|
+
walletType: 'tss',
|
|
879
|
+
});
|
|
880
|
+
// defiApprove: attacker approve(attacker, MAX_UINT256) disguised as defiApprove
|
|
881
|
+
await expectDefiRejection(verify('defiApprove', { vaultId: 'vault', amount: '10' }, defiCalldata('approve(address,uint256)', [address2, '1000000000000000000'])), /amount does not match/);
|
|
882
|
+
// defiDeposit: funds redirected to attacker receiver
|
|
883
|
+
await expectDefiRejection(verify('defiDeposit', { vaultId: 'vault', amount: '10' }, defiCalldata('deposit(uint256,address)', ['10', address2])), /receiver does not match/);
|
|
884
|
+
// defiWithdraw: receiver and owner both attacker
|
|
885
|
+
await expectDefiRejection(verify('defiWithdraw', { vaultId: 'vault', amount: '10' }, defiCalldata('redeem(uint256,address,address)', ['5', address2, address2])), /receiver and owner/);
|
|
886
|
+
});
|
|
887
|
+
it('should reject DeFi calldata with wrong selector, wrong owner alone, or wrong deposit amount', async function () {
|
|
888
|
+
const coin = bitgo.coin('hteth');
|
|
889
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, { coinSpecific: { baseAddress: address1 } });
|
|
890
|
+
const verify = async (type, defiParams, data) => coin.verifyTransaction({
|
|
891
|
+
txParams: { type, defiParams, wallet },
|
|
892
|
+
txPrebuild: { txHex: await buildDefiTxHex(data), coin: 'hteth', walletId: 'fakeWalletId' },
|
|
893
|
+
wallet,
|
|
894
|
+
verification: {},
|
|
895
|
+
walletType: 'tss',
|
|
896
|
+
});
|
|
897
|
+
const defiParams = { vaultId: 'vault', amount: '10' };
|
|
898
|
+
// defiApprove with a non-approve selector (transfer disguised as approve)
|
|
899
|
+
await expectDefiRejection(verify('defiApprove', defiParams, defiCalldata('transfer(address,uint256)', [address2, '10'])), /approve\(address,uint256\)/);
|
|
900
|
+
// defiDeposit with a non-deposit selector
|
|
901
|
+
await expectDefiRejection(verify('defiDeposit', defiParams, defiCalldata('approve(address,uint256)', [address1, '10'])), /deposit\(uint256,address\)/);
|
|
902
|
+
// defiWithdraw with a non-redeem selector
|
|
903
|
+
await expectDefiRejection(verify('defiWithdraw', defiParams, defiCalldata('approve(address,uint256)', [address1, '10'])), /redeem\(uint256,address,address\)/);
|
|
904
|
+
// defiWithdraw: receiver ok but owner is attacker
|
|
905
|
+
await expectDefiRejection(verify('defiWithdraw', defiParams, defiCalldata('redeem(uint256,address,address)', ['10', address1, address2])), /receiver and owner/);
|
|
906
|
+
// defiWithdraw: receiver and owner ok but shares do not match defiParams.amount
|
|
907
|
+
await expectDefiRejection(verify('defiWithdraw', defiParams, defiCalldata('redeem(uint256,address,address)', ['999', address1, address1])), /shares do not match/);
|
|
908
|
+
// defiDeposit: receiver ok but amount mismatch
|
|
909
|
+
await expectDefiRejection(verify('defiDeposit', defiParams, defiCalldata('deposit(uint256,address)', ['999', address1])), /amount does not match/);
|
|
910
|
+
});
|
|
911
|
+
it('should fail closed when defi intent parameters are missing or calldata is short', async function () {
|
|
912
|
+
const coin = bitgo.coin('hteth');
|
|
913
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, { coinSpecific: { baseAddress: address1 } });
|
|
914
|
+
const verify = async (type, defiParams, data) => coin.verifyTransaction({
|
|
915
|
+
txParams: { type, defiParams, wallet },
|
|
916
|
+
txPrebuild: { txHex: await buildDefiTxHex(data), coin: 'hteth', walletId: 'fakeWalletId' },
|
|
917
|
+
wallet,
|
|
918
|
+
verification: {},
|
|
919
|
+
walletType: 'tss',
|
|
920
|
+
});
|
|
921
|
+
// Missing defiParams for each defi type -> fail closed
|
|
922
|
+
await expectDefiRejection(verify('defiApprove', undefined, defiCalldata('approve(address,uint256)', [address1, '10'])), /missing required intent parameters/);
|
|
923
|
+
await expectDefiRejection(verify('defiDeposit', undefined, defiCalldata('deposit(uint256,address)', ['10', address1])), /missing required intent parameters/);
|
|
924
|
+
await expectDefiRejection(verify('defiWithdraw', undefined, defiCalldata('redeem(uint256,address,address)', ['5', address1, address1])), /missing required intent parameters/);
|
|
925
|
+
// Short/empty calldata with no valid selector prefix -> selector mismatch (fail closed)
|
|
926
|
+
await expectDefiRejection(verify('defiApprove', { vaultId: 'vault', amount: '10' }, '0x'), /approve\(address,uint256\)/);
|
|
927
|
+
});
|
|
928
|
+
it('should verify TSS transaction with defiWithdraw type', async function () {
|
|
929
|
+
const coin = bitgo.coin('hteth');
|
|
930
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, { coinSpecific: { baseAddress: address1 } });
|
|
931
|
+
const txParams = {
|
|
932
|
+
type: 'defiWithdraw',
|
|
933
|
+
defiParams: { vaultId: 'hteth-usdc-test', amount: '10' },
|
|
934
|
+
wallet,
|
|
935
|
+
};
|
|
936
|
+
const txPrebuild = {
|
|
937
|
+
txHex: await buildDefiTxHex(defiCalldata('redeem(uint256,address,address)', ['10', address1, address1])),
|
|
938
|
+
coin: 'hteth',
|
|
939
|
+
walletId: 'fakeWalletId',
|
|
940
|
+
};
|
|
941
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
942
|
+
txParams: txParams,
|
|
943
|
+
txPrebuild: txPrebuild,
|
|
944
|
+
wallet,
|
|
945
|
+
verification: {},
|
|
946
|
+
walletType: 'tss',
|
|
947
|
+
});
|
|
948
|
+
isTransactionVerified.should.equal(true);
|
|
949
|
+
});
|
|
950
|
+
describe('consolidationToBaseAddress verification', function () {
|
|
951
|
+
it('should verify consolidation when recipient matches base address', async function () {
|
|
952
|
+
const coin = bitgo.coin('hteth');
|
|
953
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
954
|
+
// Build a real transaction that sends to the baseAddress
|
|
955
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
956
|
+
txBuilder.type(sdk_core_1.TransactionType.SingleSigSend);
|
|
957
|
+
txBuilder.fee({
|
|
958
|
+
fee: '10',
|
|
959
|
+
gasLimit: '21000',
|
|
960
|
+
});
|
|
961
|
+
txBuilder.counter(1);
|
|
962
|
+
txBuilder.contract(baseAddress);
|
|
963
|
+
txBuilder.value('1000000000000000000');
|
|
964
|
+
const tx = await txBuilder.build();
|
|
965
|
+
const txHex = tx.toBroadcastFormat();
|
|
966
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
967
|
+
coinSpecific: {
|
|
968
|
+
baseAddress: baseAddress,
|
|
969
|
+
},
|
|
970
|
+
});
|
|
971
|
+
const txParams = {
|
|
972
|
+
type: 'consolidate',
|
|
973
|
+
wallet: wallet,
|
|
974
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
975
|
+
};
|
|
976
|
+
const txPrebuild = {
|
|
977
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
978
|
+
txHex: txHex,
|
|
979
|
+
coin: 'hteth',
|
|
980
|
+
walletId: 'fakeWalletId',
|
|
981
|
+
};
|
|
982
|
+
const verification = {
|
|
983
|
+
consolidationToBaseAddress: true,
|
|
984
|
+
};
|
|
985
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
986
|
+
txParams: txParams,
|
|
987
|
+
txPrebuild: txPrebuild,
|
|
988
|
+
wallet,
|
|
989
|
+
verification,
|
|
990
|
+
walletType: 'tss',
|
|
991
|
+
});
|
|
992
|
+
isTransactionVerified.should.equal(true);
|
|
993
|
+
});
|
|
994
|
+
it('should reject consolidation when recipient does not match base address', async function () {
|
|
995
|
+
const coin = bitgo.coin('hteth');
|
|
996
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
997
|
+
const wrongRecipient = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
|
|
998
|
+
// Build a transaction that sends to a DIFFERENT address (not baseAddress)
|
|
999
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
1000
|
+
txBuilder.type(sdk_core_1.TransactionType.SingleSigSend);
|
|
1001
|
+
txBuilder.fee({
|
|
1002
|
+
fee: '10',
|
|
1003
|
+
gasLimit: '21000',
|
|
1004
|
+
});
|
|
1005
|
+
txBuilder.counter(1);
|
|
1006
|
+
txBuilder.contract(wrongRecipient);
|
|
1007
|
+
txBuilder.value('1000000000000000000');
|
|
1008
|
+
const tx = await txBuilder.build();
|
|
1009
|
+
const txHex = tx.toBroadcastFormat();
|
|
1010
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
1011
|
+
coinSpecific: {
|
|
1012
|
+
baseAddress: baseAddress,
|
|
1013
|
+
},
|
|
1014
|
+
});
|
|
1015
|
+
const txParams = {
|
|
1016
|
+
type: 'consolidate',
|
|
1017
|
+
wallet: wallet,
|
|
1018
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
1019
|
+
};
|
|
1020
|
+
const txPrebuild = {
|
|
1021
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
1022
|
+
txHex: txHex,
|
|
1023
|
+
coin: 'hteth',
|
|
1024
|
+
walletId: 'fakeWalletId',
|
|
1025
|
+
};
|
|
1026
|
+
const verification = {
|
|
1027
|
+
consolidationToBaseAddress: true,
|
|
1028
|
+
};
|
|
1029
|
+
await coin
|
|
1030
|
+
.verifyTransaction({
|
|
1031
|
+
txParams: txParams,
|
|
1032
|
+
txPrebuild: txPrebuild,
|
|
1033
|
+
wallet,
|
|
1034
|
+
verification,
|
|
1035
|
+
walletType: 'tss',
|
|
1036
|
+
})
|
|
1037
|
+
.should.be.rejectedWith('Consolidation transaction recipient does not match wallet base address');
|
|
1038
|
+
});
|
|
1039
|
+
it('should throw error when txHex is missing for consolidation verification', async function () {
|
|
1040
|
+
const coin = bitgo.coin('hteth');
|
|
1041
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
1042
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
1043
|
+
coinSpecific: {
|
|
1044
|
+
baseAddress: baseAddress,
|
|
1045
|
+
},
|
|
1046
|
+
});
|
|
1047
|
+
const txParams = {
|
|
1048
|
+
type: 'consolidate',
|
|
1049
|
+
wallet: wallet,
|
|
1050
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
1051
|
+
};
|
|
1052
|
+
const txPrebuild = {
|
|
1053
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
1054
|
+
// Intentionally missing txHex
|
|
1055
|
+
coin: 'hteth',
|
|
1056
|
+
walletId: 'fakeWalletId',
|
|
1057
|
+
};
|
|
1058
|
+
const verification = {
|
|
1059
|
+
consolidationToBaseAddress: true,
|
|
1060
|
+
};
|
|
1061
|
+
await coin
|
|
1062
|
+
.verifyTransaction({
|
|
1063
|
+
txParams: txParams,
|
|
1064
|
+
txPrebuild: txPrebuild,
|
|
1065
|
+
wallet,
|
|
1066
|
+
verification,
|
|
1067
|
+
walletType: 'tss',
|
|
1068
|
+
})
|
|
1069
|
+
.should.be.rejectedWith('missing txHex in txPrebuild');
|
|
1070
|
+
});
|
|
1071
|
+
it('should verify ERC20 token consolidation when calldata recipient matches base address', async function () {
|
|
1072
|
+
const coin = bitgo.coin('hteth');
|
|
1073
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
1074
|
+
const tokenContractAddress = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
|
1075
|
+
// Build an ERC20 transfer(address, uint256) tx — mimics what the server returns
|
|
1076
|
+
// for a v6 TSS wallet token consolidation: txJson.to = token contract,
|
|
1077
|
+
// actual recipient is encoded in the 0xa9059cbb calldata
|
|
1078
|
+
const methodId = ethereumjs_abi_1.default.methodID('transfer', ['address', 'uint256']);
|
|
1079
|
+
const encodedParams = ethereumjs_abi_1.default.rawEncode(['address', 'uint256'], [baseAddress, '10000000']);
|
|
1080
|
+
const erc20TransferData = '0x' + Buffer.concat([methodId, encodedParams]).toString('hex');
|
|
1081
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
1082
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
1083
|
+
txBuilder.fee({ fee: '10', gasLimit: '60000' });
|
|
1084
|
+
txBuilder.counter(1);
|
|
1085
|
+
txBuilder.contract(tokenContractAddress);
|
|
1086
|
+
txBuilder.data(erc20TransferData);
|
|
1087
|
+
const tx = await txBuilder.build();
|
|
1088
|
+
const txHex = tx.toBroadcastFormat();
|
|
1089
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
1090
|
+
coinSpecific: { baseAddress },
|
|
1091
|
+
});
|
|
1092
|
+
const isTransactionVerified = await coin.verifyTransaction({
|
|
1093
|
+
txParams: { type: 'consolidate', wallet, walletPassphrase: 'fake' },
|
|
1094
|
+
txPrebuild: { consolidateId: 'abc123', txHex, coin: 'hteth', walletId: 'fakeWalletId' },
|
|
1095
|
+
wallet,
|
|
1096
|
+
verification: { consolidationToBaseAddress: true },
|
|
1097
|
+
walletType: 'tss',
|
|
1098
|
+
});
|
|
1099
|
+
isTransactionVerified.should.equal(true);
|
|
1100
|
+
});
|
|
1101
|
+
it('should reject ERC20 token consolidation when calldata recipient does not match base address', async function () {
|
|
1102
|
+
const coin = bitgo.coin('hteth');
|
|
1103
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
1104
|
+
const wrongRecipient = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
|
|
1105
|
+
const tokenContractAddress = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
|
1106
|
+
// Build an ERC20 transfer where calldata recipient is a WRONG address
|
|
1107
|
+
const methodId = ethereumjs_abi_1.default.methodID('transfer', ['address', 'uint256']);
|
|
1108
|
+
const encodedParams = ethereumjs_abi_1.default.rawEncode(['address', 'uint256'], [wrongRecipient, '10000000']);
|
|
1109
|
+
const erc20TransferData = '0x' + Buffer.concat([methodId, encodedParams]).toString('hex');
|
|
1110
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
1111
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
1112
|
+
txBuilder.fee({ fee: '10', gasLimit: '60000' });
|
|
1113
|
+
txBuilder.counter(1);
|
|
1114
|
+
txBuilder.contract(tokenContractAddress);
|
|
1115
|
+
txBuilder.data(erc20TransferData);
|
|
1116
|
+
const tx = await txBuilder.build();
|
|
1117
|
+
const txHex = tx.toBroadcastFormat();
|
|
1118
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
1119
|
+
coinSpecific: { baseAddress },
|
|
1120
|
+
});
|
|
1121
|
+
await coin
|
|
1122
|
+
.verifyTransaction({
|
|
1123
|
+
txParams: { type: 'consolidate', wallet, walletPassphrase: 'fake' },
|
|
1124
|
+
txPrebuild: { consolidateId: 'abc123', txHex, coin: 'hteth', walletId: 'fakeWalletId' },
|
|
1125
|
+
wallet,
|
|
1126
|
+
verification: { consolidationToBaseAddress: true },
|
|
1127
|
+
walletType: 'tss',
|
|
1128
|
+
})
|
|
1129
|
+
.should.be.rejectedWith('Consolidation transaction recipient does not match wallet base address');
|
|
1130
|
+
});
|
|
1131
|
+
it('should throw error when wallet is missing baseAddress for consolidation verification', async function () {
|
|
1132
|
+
const coin = bitgo.coin('hteth');
|
|
1133
|
+
const baseAddress = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
1134
|
+
// Build a real transaction
|
|
1135
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
1136
|
+
txBuilder.type(sdk_core_1.TransactionType.SingleSigSend);
|
|
1137
|
+
txBuilder.fee({
|
|
1138
|
+
fee: '10',
|
|
1139
|
+
gasLimit: '21000',
|
|
1140
|
+
});
|
|
1141
|
+
txBuilder.counter(1);
|
|
1142
|
+
txBuilder.contract(baseAddress);
|
|
1143
|
+
txBuilder.value('1000000000000000000');
|
|
1144
|
+
const tx = await txBuilder.build();
|
|
1145
|
+
const txHex = tx.toBroadcastFormat();
|
|
1146
|
+
// Wallet without baseAddress
|
|
1147
|
+
const wallet = new sdk_core_1.Wallet(bitgo, coin, {
|
|
1148
|
+
coinSpecific: {},
|
|
1149
|
+
});
|
|
1150
|
+
const txParams = {
|
|
1151
|
+
type: 'consolidate',
|
|
1152
|
+
wallet: wallet,
|
|
1153
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
1154
|
+
};
|
|
1155
|
+
const txPrebuild = {
|
|
1156
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
1157
|
+
txHex: txHex,
|
|
1158
|
+
coin: 'hteth',
|
|
1159
|
+
walletId: 'fakeWalletId',
|
|
1160
|
+
};
|
|
1161
|
+
const verification = {
|
|
1162
|
+
consolidationToBaseAddress: true,
|
|
1163
|
+
};
|
|
1164
|
+
await coin
|
|
1165
|
+
.verifyTransaction({
|
|
1166
|
+
txParams: txParams,
|
|
1167
|
+
txPrebuild: txPrebuild,
|
|
1168
|
+
wallet,
|
|
1169
|
+
verification,
|
|
1170
|
+
walletType: 'tss',
|
|
1171
|
+
})
|
|
1172
|
+
.should.be.rejectedWith('Unable to determine base address for consolidation');
|
|
1173
|
+
});
|
|
1174
|
+
});
|
|
1175
|
+
});
|
|
1176
|
+
describe('Address Verification', function () {
|
|
1177
|
+
describe('isWalletAddress', function () {
|
|
1178
|
+
it('should verify an address generated using forwarder version 1', async function () {
|
|
1179
|
+
const coin = bitgo.coin('hteth');
|
|
1180
|
+
const keychains = [
|
|
1181
|
+
{
|
|
1182
|
+
id: '691f638f1d3c9fce8f5aa691569a99eb',
|
|
1183
|
+
source: 'user',
|
|
1184
|
+
type: 'independent',
|
|
1185
|
+
pub: 'xpub661MyMwAqRbcGVb3PfCzwiEX94AB1nJQtzVmsa5SriNrfKZZAcAvRgxh1Augm6s8yoD8gSkq2FdZ8YCdVXUgLjf9QxvdYAJK5UthAmpQshU',
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
id: '691f638f0b74e73b1f440ea4aceda87e',
|
|
1189
|
+
source: 'backup',
|
|
1190
|
+
type: 'independent',
|
|
1191
|
+
pub: 'xpub661MyMwAqRbcF46pRHda3sZbuPzza9A9MiqAU9JRod8huYtyV4NY2oeJXsis7r26L1vmLntf9BcZJe1m4CQNSvYWfwpe1hSpo6J4x6YF1eN',
|
|
1192
|
+
},
|
|
1193
|
+
{
|
|
1194
|
+
id: '68b9ec587d0ba1c7440de551068c36a7',
|
|
1195
|
+
source: 'bitgo',
|
|
1196
|
+
type: 'independent',
|
|
1197
|
+
pub: 'xpub661MyMwAqRbcGzTn5eyNGDkb18R43nH79HokYLc5PXZM19V8UrbuLdVRaCQMs4EeCAjnqmoYXqfyusTU46WoZMDyLpmTzoUX66ZBwGFjt1a',
|
|
1198
|
+
},
|
|
1199
|
+
];
|
|
1200
|
+
const params = {
|
|
1201
|
+
address: '0x6069a4baf2360bf67a6d02a7fc43d8f3910016ae',
|
|
1202
|
+
baseAddress: '0xe1253bcce7d87db522fbceec6e55c9f78c376d9f',
|
|
1203
|
+
coinSpecific: {
|
|
1204
|
+
salt: '0x7',
|
|
1205
|
+
forwarderVersion: 1,
|
|
1206
|
+
},
|
|
1207
|
+
keychains,
|
|
1208
|
+
index: 7,
|
|
1209
|
+
walletVersion: 1,
|
|
1210
|
+
};
|
|
1211
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1212
|
+
isWalletAddr.should.equal(true);
|
|
1213
|
+
});
|
|
1214
|
+
it('should verify an address generated using forwarder version 2', async function () {
|
|
1215
|
+
const coin = bitgo.coin('hteth');
|
|
1216
|
+
const keychains = [
|
|
1217
|
+
{
|
|
1218
|
+
id: '691e8c7b3c8aaa791118d9ce616d3b21',
|
|
1219
|
+
source: 'user',
|
|
1220
|
+
type: 'independent',
|
|
1221
|
+
pub: 'xpub661MyMwAqRbcGrCxCX39zb3TvYjTqfUGwEUZHjnraRFm1WeMw9gfCD1wwc2wUDmBBZ2TkccJMwf5eBTja8r3z6HMxoTZGW6nvyoJMQFsecv',
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
id: '691e8c7b1967fd6d9867a22a1a4131a0',
|
|
1225
|
+
source: 'backup',
|
|
1226
|
+
type: 'independent',
|
|
1227
|
+
pub: 'xpub661MyMwAqRbcGKhdeC4nr1ta8d27xThtfFFHgbxWMrVb595meMS8i3fBMrTz8EdQMWBKHHKzxapGgheoMymVvRcQmaGDykRTBbtXqbiu9ps',
|
|
1228
|
+
},
|
|
1229
|
+
{
|
|
1230
|
+
id: '68b9ec587d0ba1c7440de551068c36a7',
|
|
1231
|
+
source: 'bitgo',
|
|
1232
|
+
type: 'independent',
|
|
1233
|
+
pub: 'xpub661MyMwAqRbcGzTn5eyNGDkb18R43nH79HokYLc5PXZM19V8UrbuLdVRaCQMs4EeCAjnqmoYXqfyusTU46WoZMDyLpmTzoUX66ZBwGFjt1a',
|
|
1234
|
+
},
|
|
1235
|
+
];
|
|
1236
|
+
const params = {
|
|
1237
|
+
address: '0xf636ceddffe41d106586875c0e56dc8feb6268f7',
|
|
1238
|
+
baseAddress: '0xdc485da076ed4a2b19584e9a1fdbb974f89b60f4',
|
|
1239
|
+
coinSpecific: {
|
|
1240
|
+
salt: '0x17',
|
|
1241
|
+
forwarderVersion: 2,
|
|
1242
|
+
},
|
|
1243
|
+
keychains,
|
|
1244
|
+
index: 23,
|
|
1245
|
+
walletVersion: 2,
|
|
1246
|
+
};
|
|
1247
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1248
|
+
isWalletAddr.should.equal(true);
|
|
1249
|
+
});
|
|
1250
|
+
it('should verify a wallet version 5 forwarder version 4', async function () {
|
|
1251
|
+
const coin = bitgo.coin('hteth');
|
|
1252
|
+
const keychains = [
|
|
1253
|
+
{
|
|
1254
|
+
id: '691e242d93f8d7ad0705887449763c96',
|
|
1255
|
+
source: 'user',
|
|
1256
|
+
type: 'tss',
|
|
1257
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
id: '691e242df8b6323d4b08df366864af66',
|
|
1261
|
+
source: 'backup',
|
|
1262
|
+
type: 'tss',
|
|
1263
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1264
|
+
},
|
|
1265
|
+
{
|
|
1266
|
+
id: '691e242c0595b4cfee6f957c1d6458f7',
|
|
1267
|
+
source: 'bitgo',
|
|
1268
|
+
type: 'tss',
|
|
1269
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1270
|
+
},
|
|
1271
|
+
];
|
|
1272
|
+
const params = {
|
|
1273
|
+
address: '0xd63b5e2b8d1b4fba3625460508900bf2a0499a4d',
|
|
1274
|
+
baseAddress: '0xf1e3d30798acdf3a12fa5beb5fad8efb23d5be11',
|
|
1275
|
+
coinSpecific: {
|
|
1276
|
+
salt: '0x75',
|
|
1277
|
+
forwarderVersion: 4,
|
|
1278
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1279
|
+
},
|
|
1280
|
+
keychains,
|
|
1281
|
+
index: 117,
|
|
1282
|
+
walletVersion: 5,
|
|
1283
|
+
};
|
|
1284
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1285
|
+
isWalletAddr.should.equal(true);
|
|
1286
|
+
});
|
|
1287
|
+
it('should verify a wallet version 6 forwarder version 5', async function () {
|
|
1288
|
+
const coin = bitgo.coin('hteth');
|
|
1289
|
+
const keychains = [
|
|
1290
|
+
{
|
|
1291
|
+
id: '691f630e0c56098288a9b7fa107db144',
|
|
1292
|
+
source: 'user',
|
|
1293
|
+
type: 'tss',
|
|
1294
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1295
|
+
},
|
|
1296
|
+
{
|
|
1297
|
+
id: '691f630f1d3c9fce8f5a730bff826cf9',
|
|
1298
|
+
source: 'backup',
|
|
1299
|
+
type: 'tss',
|
|
1300
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
id: '691f630d56735e5eb61b06e353fe7639',
|
|
1304
|
+
source: 'bitgo',
|
|
1305
|
+
type: 'tss',
|
|
1306
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1307
|
+
},
|
|
1308
|
+
];
|
|
1309
|
+
const params = {
|
|
1310
|
+
address: '0xa33f0975f53cdcfcc0cb564d25fb5be03b0651cf',
|
|
1311
|
+
baseAddress: '0xc012041dac143a59fa491db3a2b67b69bd78b685',
|
|
1312
|
+
coinSpecific: {
|
|
1313
|
+
forwarderVersion: 5,
|
|
1314
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1315
|
+
},
|
|
1316
|
+
keychains,
|
|
1317
|
+
index: 7,
|
|
1318
|
+
walletVersion: 6,
|
|
1319
|
+
};
|
|
1320
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1321
|
+
isWalletAddr.should.equal(true);
|
|
1322
|
+
});
|
|
1323
|
+
it('should reject when actual address differs from expected address', async function () {
|
|
1324
|
+
const coin = bitgo.coin('hteth');
|
|
1325
|
+
const params = {
|
|
1326
|
+
address: '0x28904591f735994f050804fda3b61b813b16e04c',
|
|
1327
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1328
|
+
walletVersion: 1,
|
|
1329
|
+
coinSpecific: {
|
|
1330
|
+
salt: '0xc5a',
|
|
1331
|
+
forwarderVersion: 1,
|
|
1332
|
+
},
|
|
1333
|
+
};
|
|
1334
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), sdk_core_1.UnexpectedAddressError);
|
|
1335
|
+
});
|
|
1336
|
+
it('should reject if coinSpecific field is not an object', async function () {
|
|
1337
|
+
const coin = bitgo.coin('teth');
|
|
1338
|
+
const params = {
|
|
1339
|
+
address: '0xb0b56eeae1b283918caca02a14ada2df17a98e6d',
|
|
1340
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1341
|
+
};
|
|
1342
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), sdk_core_1.InvalidAddressVerificationObjectPropertyError);
|
|
1343
|
+
});
|
|
1344
|
+
it('should reject if the derived address is in invalid format', async function () {
|
|
1345
|
+
const coin = bitgo.coin('teth');
|
|
1346
|
+
const params = {
|
|
1347
|
+
address: '0xe0b56eeae1b283918caca02a14ada2df17a98bvf',
|
|
1348
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1349
|
+
coinSpecific: {
|
|
1350
|
+
salt: '0xc5a',
|
|
1351
|
+
forwarderVersion: 1,
|
|
1352
|
+
},
|
|
1353
|
+
};
|
|
1354
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), sdk_core_1.InvalidAddressError);
|
|
1355
|
+
});
|
|
1356
|
+
it('should reject if base address is undefined', async function () {
|
|
1357
|
+
const coin = bitgo.coin('teth');
|
|
1358
|
+
const params = {
|
|
1359
|
+
address: '0xb0b56eeae1b283918caca02a14ada2df17a98e6d',
|
|
1360
|
+
coinSpecific: {
|
|
1361
|
+
salt: '0xc5a',
|
|
1362
|
+
forwarderVersion: 1,
|
|
1363
|
+
},
|
|
1364
|
+
};
|
|
1365
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), sdk_core_1.InvalidAddressError);
|
|
1366
|
+
});
|
|
1367
|
+
it('should reject if base address is in invalid format', async function () {
|
|
1368
|
+
const coin = bitgo.coin('teth');
|
|
1369
|
+
const params = {
|
|
1370
|
+
address: '0xb0b56eeae1b283918caca02a14ada2df17a98e6d',
|
|
1371
|
+
baseAddress: '0xe0b56eeae1b283918caca02a14ada2df17a98bvf',
|
|
1372
|
+
coinSpecific: {
|
|
1373
|
+
salt: '0xc5a',
|
|
1374
|
+
forwarderVersion: 1,
|
|
1375
|
+
},
|
|
1376
|
+
};
|
|
1377
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), sdk_core_1.InvalidAddressError);
|
|
1378
|
+
});
|
|
1379
|
+
describe('MPC wallet addresses', function () {
|
|
1380
|
+
const commonKeychain = '03f9c2fb2e5a8b78a44f5d1e4f906f8e3d7a0e6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9e8d7c6b5a4' +
|
|
1381
|
+
'93827160594857463728190a0b0c0d0e0f101112131415161718191a1b1c1d1e1f';
|
|
1382
|
+
const keychains = [
|
|
1383
|
+
{ pub: 'user_pub', commonKeychain },
|
|
1384
|
+
{ pub: 'backup_pub', commonKeychain },
|
|
1385
|
+
{ pub: 'bitgo_pub', commonKeychain },
|
|
1386
|
+
];
|
|
1387
|
+
it('should verify an MPC wallet address with forwarder version 3', async function () {
|
|
1388
|
+
const coin = bitgo.coin('teth');
|
|
1389
|
+
const params = {
|
|
1390
|
+
address: '0x01153f3adfe454a72589ca9ef74f013c19e54961',
|
|
1391
|
+
coinSpecific: {
|
|
1392
|
+
forwarderVersion: 3,
|
|
1393
|
+
},
|
|
1394
|
+
keychains,
|
|
1395
|
+
index: 0,
|
|
1396
|
+
walletVersion: 3,
|
|
1397
|
+
};
|
|
1398
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1399
|
+
isWalletAddr.should.equal(true);
|
|
1400
|
+
});
|
|
1401
|
+
it('should verify an MPC wallet address with forwarder version 5', async function () {
|
|
1402
|
+
const coin = bitgo.coin('teth');
|
|
1403
|
+
const params = {
|
|
1404
|
+
address: '0x01153f3adfe454a72589ca9ef74f013c19e54961',
|
|
1405
|
+
coinSpecific: {
|
|
1406
|
+
forwarderVersion: 5,
|
|
1407
|
+
},
|
|
1408
|
+
keychains,
|
|
1409
|
+
index: 0,
|
|
1410
|
+
walletVersion: 6,
|
|
1411
|
+
};
|
|
1412
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1413
|
+
isWalletAddr.should.equal(true);
|
|
1414
|
+
});
|
|
1415
|
+
it('should reject MPC wallet address with wrong address', async function () {
|
|
1416
|
+
const coin = bitgo.coin('teth');
|
|
1417
|
+
const params = {
|
|
1418
|
+
address: '0x0000000000000000000000000000000000000001',
|
|
1419
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1420
|
+
coinSpecific: {
|
|
1421
|
+
forwarderVersion: 3,
|
|
1422
|
+
},
|
|
1423
|
+
keychains,
|
|
1424
|
+
index: 0,
|
|
1425
|
+
walletVersion: 3,
|
|
1426
|
+
};
|
|
1427
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1428
|
+
isWalletAddr.should.equal(false);
|
|
1429
|
+
});
|
|
1430
|
+
it('should reject MPC wallet address with invalid address format', async function () {
|
|
1431
|
+
const coin = bitgo.coin('teth');
|
|
1432
|
+
const params = {
|
|
1433
|
+
address: '0xinvalid',
|
|
1434
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1435
|
+
coinSpecific: {
|
|
1436
|
+
forwarderVersion: 3,
|
|
1437
|
+
},
|
|
1438
|
+
keychains,
|
|
1439
|
+
index: 0,
|
|
1440
|
+
walletVersion: 3,
|
|
1441
|
+
};
|
|
1442
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), sdk_core_1.InvalidAddressError);
|
|
1443
|
+
});
|
|
1444
|
+
it('should reject if keychains are missing for MPC wallet', async function () {
|
|
1445
|
+
const coin = bitgo.coin('teth');
|
|
1446
|
+
const params = {
|
|
1447
|
+
address: '0x9e7ce8c24d9f76a814e23633e61be7cb8e6e2d5e',
|
|
1448
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1449
|
+
coinSpecific: {
|
|
1450
|
+
forwarderVersion: 3,
|
|
1451
|
+
},
|
|
1452
|
+
index: 0,
|
|
1453
|
+
walletVersion: 3,
|
|
1454
|
+
};
|
|
1455
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), Error);
|
|
1456
|
+
});
|
|
1457
|
+
it('should reject if commonKeychain is missing for MPC wallet', async function () {
|
|
1458
|
+
const coin = bitgo.coin('teth');
|
|
1459
|
+
const invalidKeychains = [{ pub: 'user_pub' }, { pub: 'backup_pub' }, { pub: 'bitgo_pub' }];
|
|
1460
|
+
const params = {
|
|
1461
|
+
address: '0x9e7ce8c24d9f76a814e23633e61be7cb8e6e2d5e',
|
|
1462
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1463
|
+
coinSpecific: {
|
|
1464
|
+
forwarderVersion: 3,
|
|
1465
|
+
},
|
|
1466
|
+
keychains: invalidKeychains,
|
|
1467
|
+
index: 0,
|
|
1468
|
+
walletVersion: 3,
|
|
1469
|
+
};
|
|
1470
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), Error);
|
|
1471
|
+
});
|
|
1472
|
+
});
|
|
1473
|
+
describe('deriveAddress (MPC)', function () {
|
|
1474
|
+
// Same vector as the MPC isWalletAddress tests above:
|
|
1475
|
+
// commonKeychain @ index 0 -> 0x01153f3adfe454a72589ca9ef74f013c19e54961
|
|
1476
|
+
const commonKeychain = '03f9c2fb2e5a8b78a44f5d1e4f906f8e3d7a0e6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9e8d7c6b5a4' +
|
|
1477
|
+
'93827160594857463728190a0b0c0d0e0f101112131415161718191a1b1c1d1e1f';
|
|
1478
|
+
const keychains = [
|
|
1479
|
+
{ pub: 'user_pub', commonKeychain },
|
|
1480
|
+
{ pub: 'backup_pub', commonKeychain },
|
|
1481
|
+
{ pub: 'bitgo_pub', commonKeychain },
|
|
1482
|
+
];
|
|
1483
|
+
it('should derive the expected MPC address for a commonKeychain at index 0', async function () {
|
|
1484
|
+
const coin = bitgo.coin('teth');
|
|
1485
|
+
const result = await coin.deriveAddress({ keychains, index: 0, walletVersion: 3 });
|
|
1486
|
+
result.address.should.equal('0x01153f3adfe454a72589ca9ef74f013c19e54961');
|
|
1487
|
+
result.index.should.equal(0);
|
|
1488
|
+
assert_1.default.strictEqual(result.derivationPath, 'm/0');
|
|
1489
|
+
});
|
|
1490
|
+
it('round-trips with isWalletAddress (derived address verifies as true)', async function () {
|
|
1491
|
+
const coin = bitgo.coin('teth');
|
|
1492
|
+
const derived = await coin.deriveAddress({ keychains, index: 3, walletVersion: 6 });
|
|
1493
|
+
const verified = await coin.isWalletAddress({
|
|
1494
|
+
address: derived.address,
|
|
1495
|
+
coinSpecific: { forwarderVersion: 5 },
|
|
1496
|
+
keychains,
|
|
1497
|
+
index: 3,
|
|
1498
|
+
walletVersion: 6,
|
|
1499
|
+
});
|
|
1500
|
+
verified.should.equal(true);
|
|
1501
|
+
});
|
|
1502
|
+
it('should throw when neither MPC nor forwarder inputs are provided', async function () {
|
|
1503
|
+
const coin = bitgo.coin('teth');
|
|
1504
|
+
// walletVersion 1 with no coinSpecific.forwarderVersion and no baseAddress is ambiguous
|
|
1505
|
+
await assert_1.default.rejects(async () => coin.deriveAddress({ keychains, index: 0, walletVersion: 1 }), /could not determine an ETH derivation strategy/);
|
|
1506
|
+
});
|
|
1507
|
+
it('should throw if keychains are missing', async function () {
|
|
1508
|
+
const coin = bitgo.coin('teth');
|
|
1509
|
+
await assert_1.default.rejects(async () => coin.deriveAddress({ keychains: [], index: 0, walletVersion: 3 }), /keychains/);
|
|
1510
|
+
});
|
|
1511
|
+
});
|
|
1512
|
+
describe('deriveAddress (forwarder)', function () {
|
|
1513
|
+
// Same vectors as the forwarder isWalletAddress tests above (coin: hteth).
|
|
1514
|
+
// salt == index for BitGo forwarders, so deriving by index reproduces the address.
|
|
1515
|
+
it('derives the exact v1 forwarder address and round-trips', async function () {
|
|
1516
|
+
const coin = bitgo.coin('hteth');
|
|
1517
|
+
const baseAddress = '0xe1253bcce7d87db522fbceec6e55c9f78c376d9f';
|
|
1518
|
+
const result = await coin.deriveAddress({
|
|
1519
|
+
baseAddress,
|
|
1520
|
+
index: 7,
|
|
1521
|
+
walletVersion: 1,
|
|
1522
|
+
coinSpecific: { forwarderVersion: 1 },
|
|
1523
|
+
});
|
|
1524
|
+
result.address.should.equal('0x6069a4baf2360bf67a6d02a7fc43d8f3910016ae');
|
|
1525
|
+
const verified = await coin.isWalletAddress({
|
|
1526
|
+
address: result.address,
|
|
1527
|
+
baseAddress,
|
|
1528
|
+
index: 7,
|
|
1529
|
+
walletVersion: 1,
|
|
1530
|
+
coinSpecific: { salt: '0x7', forwarderVersion: 1 },
|
|
1531
|
+
});
|
|
1532
|
+
verified.should.equal(true);
|
|
1533
|
+
});
|
|
1534
|
+
it('derives the exact v2 forwarder address', async function () {
|
|
1535
|
+
const coin = bitgo.coin('hteth');
|
|
1536
|
+
const result = await coin.deriveAddress({
|
|
1537
|
+
baseAddress: '0xdc485da076ed4a2b19584e9a1fdbb974f89b60f4',
|
|
1538
|
+
index: 23,
|
|
1539
|
+
walletVersion: 2,
|
|
1540
|
+
coinSpecific: { forwarderVersion: 2 },
|
|
1541
|
+
});
|
|
1542
|
+
result.address.should.equal('0xf636ceddffe41d106586875c0e56dc8feb6268f7');
|
|
1543
|
+
});
|
|
1544
|
+
it('derives the exact v4 forwarder address (wallet v5, needs feeAddress)', async function () {
|
|
1545
|
+
const coin = bitgo.coin('hteth');
|
|
1546
|
+
const result = await coin.deriveAddress({
|
|
1547
|
+
baseAddress: '0xf1e3d30798acdf3a12fa5beb5fad8efb23d5be11',
|
|
1548
|
+
index: 117,
|
|
1549
|
+
walletVersion: 5,
|
|
1550
|
+
coinSpecific: { forwarderVersion: 4, feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09' },
|
|
1551
|
+
});
|
|
1552
|
+
result.address.should.equal('0xd63b5e2b8d1b4fba3625460508900bf2a0499a4d');
|
|
1553
|
+
});
|
|
1554
|
+
it('throws if baseAddress is missing for a forwarder', async function () {
|
|
1555
|
+
const coin = bitgo.coin('hteth');
|
|
1556
|
+
await assert_1.default.rejects(async () => coin.deriveAddress({ index: 7, walletVersion: 1, coinSpecific: { forwarderVersion: 1 } }), /baseAddress is required/);
|
|
1557
|
+
});
|
|
1558
|
+
it('throws if feeAddress is missing for a v4 forwarder', async function () {
|
|
1559
|
+
const coin = bitgo.coin('hteth');
|
|
1560
|
+
await assert_1.default.rejects(async () => coin.deriveAddress({
|
|
1561
|
+
baseAddress: '0xf1e3d30798acdf3a12fa5beb5fad8efb23d5be11',
|
|
1562
|
+
index: 117,
|
|
1563
|
+
walletVersion: 5,
|
|
1564
|
+
coinSpecific: { forwarderVersion: 4 },
|
|
1565
|
+
}), /feeAddress is required/);
|
|
1566
|
+
});
|
|
1567
|
+
it('throws for forwarder version 0 (not derivable)', async function () {
|
|
1568
|
+
const coin = bitgo.coin('hteth');
|
|
1569
|
+
await assert_1.default.rejects(async () => coin.deriveAddress({
|
|
1570
|
+
baseAddress: '0xe1253bcce7d87db522fbceec6e55c9f78c376d9f',
|
|
1571
|
+
index: 0,
|
|
1572
|
+
walletVersion: 1,
|
|
1573
|
+
coinSpecific: { forwarderVersion: 0 },
|
|
1574
|
+
}), /version 0 addresses cannot be derived/);
|
|
1575
|
+
});
|
|
1576
|
+
});
|
|
1577
|
+
describe('Base Address Verification', function () {
|
|
1578
|
+
it('should verify base address for wallet version 6 (TSS)', async function () {
|
|
1579
|
+
const coin = bitgo.coin('hteth');
|
|
1580
|
+
const keychains = [
|
|
1581
|
+
{
|
|
1582
|
+
id: '691f630e0c56098288a9b7fa107db144',
|
|
1583
|
+
source: 'user',
|
|
1584
|
+
type: 'tss',
|
|
1585
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
id: '691f630f1d3c9fce8f5a730bff826cf9',
|
|
1589
|
+
source: 'backup',
|
|
1590
|
+
type: 'tss',
|
|
1591
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1592
|
+
},
|
|
1593
|
+
{
|
|
1594
|
+
id: '691f630d56735e5eb61b06e353fe7639',
|
|
1595
|
+
source: 'bitgo',
|
|
1596
|
+
type: 'tss',
|
|
1597
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1598
|
+
},
|
|
1599
|
+
];
|
|
1600
|
+
const baseAddress = '0xc012041dac143a59fa491db3a2b67b69bd78b685';
|
|
1601
|
+
const params = {
|
|
1602
|
+
address: baseAddress,
|
|
1603
|
+
baseAddress: baseAddress,
|
|
1604
|
+
coinSpecific: {
|
|
1605
|
+
salt: '0x0',
|
|
1606
|
+
forwarderVersion: 5,
|
|
1607
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1608
|
+
},
|
|
1609
|
+
keychains,
|
|
1610
|
+
index: 0,
|
|
1611
|
+
walletVersion: 6,
|
|
1612
|
+
};
|
|
1613
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1614
|
+
isWalletAddr.should.equal(true);
|
|
1615
|
+
});
|
|
1616
|
+
it('should verify base address for wallet version 5 (TSS)', async function () {
|
|
1617
|
+
const coin = bitgo.coin('hteth');
|
|
1618
|
+
const keychains = [
|
|
1619
|
+
{
|
|
1620
|
+
id: '691e242d93f8d7ad0705887449763c96',
|
|
1621
|
+
source: 'user',
|
|
1622
|
+
type: 'tss',
|
|
1623
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1624
|
+
},
|
|
1625
|
+
{
|
|
1626
|
+
id: '691e242df8b6323d4b08df366864af66',
|
|
1627
|
+
source: 'backup',
|
|
1628
|
+
type: 'tss',
|
|
1629
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1630
|
+
},
|
|
1631
|
+
{
|
|
1632
|
+
id: '691e242c0595b4cfee6f957c1d6458f7',
|
|
1633
|
+
source: 'bitgo',
|
|
1634
|
+
type: 'tss',
|
|
1635
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1636
|
+
},
|
|
1637
|
+
];
|
|
1638
|
+
const baseAddress = '0xf1e3d30798acdf3a12fa5beb5fad8efb23d5be11';
|
|
1639
|
+
const params = {
|
|
1640
|
+
address: baseAddress,
|
|
1641
|
+
baseAddress: baseAddress,
|
|
1642
|
+
coinSpecific: {
|
|
1643
|
+
salt: '0x0',
|
|
1644
|
+
forwarderVersion: 4,
|
|
1645
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1646
|
+
},
|
|
1647
|
+
keychains,
|
|
1648
|
+
index: 0,
|
|
1649
|
+
walletVersion: 5,
|
|
1650
|
+
};
|
|
1651
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1652
|
+
isWalletAddr.should.equal(true);
|
|
1653
|
+
});
|
|
1654
|
+
it('should reject base address verification with non-zero index', async function () {
|
|
1655
|
+
const coin = bitgo.coin('hteth');
|
|
1656
|
+
const keychains = [
|
|
1657
|
+
{
|
|
1658
|
+
id: '691f630e0c56098288a9b7fa107db144',
|
|
1659
|
+
source: 'user',
|
|
1660
|
+
type: 'tss',
|
|
1661
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1662
|
+
},
|
|
1663
|
+
{
|
|
1664
|
+
id: '691f630f1d3c9fce8f5a730bff826cf9',
|
|
1665
|
+
source: 'backup',
|
|
1666
|
+
type: 'tss',
|
|
1667
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1668
|
+
},
|
|
1669
|
+
{
|
|
1670
|
+
id: '691f630d56735e5eb61b06e353fe7639',
|
|
1671
|
+
source: 'bitgo',
|
|
1672
|
+
type: 'tss',
|
|
1673
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1674
|
+
},
|
|
1675
|
+
];
|
|
1676
|
+
const baseAddress = '0xc012041dac143a59fa491db3a2b67b69bd78b685';
|
|
1677
|
+
const params = {
|
|
1678
|
+
address: baseAddress,
|
|
1679
|
+
baseAddress: baseAddress,
|
|
1680
|
+
coinSpecific: {
|
|
1681
|
+
salt: '0x0',
|
|
1682
|
+
forwarderVersion: 5,
|
|
1683
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1684
|
+
},
|
|
1685
|
+
keychains,
|
|
1686
|
+
index: 5, // Wrong index - should be 0 for base address
|
|
1687
|
+
walletVersion: 6,
|
|
1688
|
+
};
|
|
1689
|
+
await assert_1.default.rejects(async () => coin.isWalletAddress(params), /Base address verification requires index 0, but got index 5/);
|
|
1690
|
+
});
|
|
1691
|
+
it('should reject base address verification with wrong address', async function () {
|
|
1692
|
+
const coin = bitgo.coin('hteth');
|
|
1693
|
+
const keychains = [
|
|
1694
|
+
{
|
|
1695
|
+
id: '691f630e0c56098288a9b7fa107db144',
|
|
1696
|
+
source: 'user',
|
|
1697
|
+
type: 'tss',
|
|
1698
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
id: '691f630f1d3c9fce8f5a730bff826cf9',
|
|
1702
|
+
source: 'backup',
|
|
1703
|
+
type: 'tss',
|
|
1704
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1705
|
+
},
|
|
1706
|
+
{
|
|
1707
|
+
id: '691f630d56735e5eb61b06e353fe7639',
|
|
1708
|
+
source: 'bitgo',
|
|
1709
|
+
type: 'tss',
|
|
1710
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1711
|
+
},
|
|
1712
|
+
];
|
|
1713
|
+
const wrongAddress = '0x0000000000000000000000000000000000000001';
|
|
1714
|
+
const actualBaseAddress = '0xc012041dac143a59fa491db3a2b67b69bd78b685';
|
|
1715
|
+
const params = {
|
|
1716
|
+
address: wrongAddress,
|
|
1717
|
+
baseAddress: actualBaseAddress,
|
|
1718
|
+
coinSpecific: {
|
|
1719
|
+
salt: '0x0',
|
|
1720
|
+
forwarderVersion: 5,
|
|
1721
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1722
|
+
},
|
|
1723
|
+
keychains,
|
|
1724
|
+
index: 0,
|
|
1725
|
+
walletVersion: 6,
|
|
1726
|
+
};
|
|
1727
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1728
|
+
isWalletAddr.should.equal(false);
|
|
1729
|
+
});
|
|
1730
|
+
it('should verify base address for wallet version 2 (BIP32) using wallet factory', async function () {
|
|
1731
|
+
const coin = bitgo.coin('hteth');
|
|
1732
|
+
const baseAddress = '0xdc485da076ed4a2b19584e9a1fdbb974f89b60f4';
|
|
1733
|
+
const walletSalt = '0x2';
|
|
1734
|
+
const keychains = [
|
|
1735
|
+
{
|
|
1736
|
+
id: '691e8c7b3c8aaa791118d9ce616d3b21',
|
|
1737
|
+
source: 'user',
|
|
1738
|
+
type: 'independent',
|
|
1739
|
+
ethAddress: '0x9d16bb867b792c5e3bf636a0275f2db8601bd7d4',
|
|
1740
|
+
},
|
|
1741
|
+
{
|
|
1742
|
+
id: '691e8c7b1967fd6d9867a22a1a4131a0',
|
|
1743
|
+
source: 'backup',
|
|
1744
|
+
type: 'independent',
|
|
1745
|
+
ethAddress: '0x2dfce5cfeb5c03fbe680cd39ac0d2b25399b7d22',
|
|
1746
|
+
},
|
|
1747
|
+
{
|
|
1748
|
+
id: '68b9ec587d0ba1c7440de551068c36a7',
|
|
1749
|
+
source: 'bitgo',
|
|
1750
|
+
type: 'independent',
|
|
1751
|
+
ethAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1752
|
+
},
|
|
1753
|
+
];
|
|
1754
|
+
const params = {
|
|
1755
|
+
address: baseAddress,
|
|
1756
|
+
baseAddress: baseAddress,
|
|
1757
|
+
coinSpecific: {
|
|
1758
|
+
salt: walletSalt,
|
|
1759
|
+
forwarderVersion: 2,
|
|
1760
|
+
},
|
|
1761
|
+
keychains: keychains,
|
|
1762
|
+
index: 0,
|
|
1763
|
+
walletVersion: 2,
|
|
1764
|
+
};
|
|
1765
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1766
|
+
isWalletAddr.should.equal(true);
|
|
1767
|
+
});
|
|
1768
|
+
it('should verify base address for wallet version 1 (BIP32) using wallet factory', async function () {
|
|
1769
|
+
const coin = bitgo.coin('hteth');
|
|
1770
|
+
const baseAddress = '0xe1253bcce7d87db522fbceec6e55c9f78c376d9f';
|
|
1771
|
+
const walletSalt = '0x5';
|
|
1772
|
+
const keychains = [
|
|
1773
|
+
{
|
|
1774
|
+
id: '691f638f1d3c9fce8f5aa691569a99eb',
|
|
1775
|
+
source: 'user',
|
|
1776
|
+
type: 'independent',
|
|
1777
|
+
ethAddress: '0xf45dadce751a317957f2a247ff37cb764b97620d',
|
|
1778
|
+
pub: 'xpub661MyMwAqRbcGVb3PfCzwiEX94AB1nJQtzVm...',
|
|
1779
|
+
},
|
|
1780
|
+
{
|
|
1781
|
+
id: '691f638f0b74e73b1f440ea4aceda87e',
|
|
1782
|
+
source: 'backup',
|
|
1783
|
+
type: 'independent',
|
|
1784
|
+
ethAddress: '0x5bdf3ae1d2c2fadeeb70a45872bf4f4252312b55',
|
|
1785
|
+
pub: 'xpub661MyMwAqRbcF46pRHda3sZbuPzza9A9MiqA...',
|
|
1786
|
+
},
|
|
1787
|
+
{
|
|
1788
|
+
id: '68b9ec587d0ba1c7440de551068c36a7',
|
|
1789
|
+
source: 'bitgo',
|
|
1790
|
+
type: 'independent',
|
|
1791
|
+
ethAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1792
|
+
pub: 'xpub661MyMwAqRbcGzTn5eyNGDkb18R43nH79Hok...',
|
|
1793
|
+
},
|
|
1794
|
+
];
|
|
1795
|
+
const params = {
|
|
1796
|
+
address: baseAddress,
|
|
1797
|
+
baseAddress: baseAddress,
|
|
1798
|
+
coinSpecific: {
|
|
1799
|
+
salt: walletSalt,
|
|
1800
|
+
forwarderVersion: 1,
|
|
1801
|
+
},
|
|
1802
|
+
keychains: keychains,
|
|
1803
|
+
index: 0,
|
|
1804
|
+
walletVersion: 1,
|
|
1805
|
+
};
|
|
1806
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1807
|
+
isWalletAddr.should.equal(true);
|
|
1808
|
+
});
|
|
1809
|
+
});
|
|
1810
|
+
});
|
|
1811
|
+
});
|
|
1812
|
+
describe('Address Creation', function () {
|
|
1813
|
+
it('should pass walletVersion 6 to isWalletAddress during address creation', async function () {
|
|
1814
|
+
const bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
|
|
1815
|
+
const ethCoin = bitgo.coin('hteth');
|
|
1816
|
+
const walletDataV6 = {
|
|
1817
|
+
id: '598f606cd8fc24710d2ebadb1d9459bb',
|
|
1818
|
+
coinSpecific: {
|
|
1819
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1820
|
+
walletVersion: 6,
|
|
1821
|
+
},
|
|
1822
|
+
coin: 'hteth',
|
|
1823
|
+
keys: [
|
|
1824
|
+
'598f606cd8fc24710d2ebad89dce86c2',
|
|
1825
|
+
'598f606cc8e43aef09fcb785221d9dd2',
|
|
1826
|
+
'5935d59cf660764331bafcade1855fd7',
|
|
1827
|
+
],
|
|
1828
|
+
receiveAddress: {
|
|
1829
|
+
address: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
1830
|
+
},
|
|
1831
|
+
};
|
|
1832
|
+
const ethWalletV6 = new sdk_core_1.Wallet(bitgo, ethCoin, walletDataV6);
|
|
1833
|
+
const isWalletAddressSpy = sinon_1.default.spy(ethCoin, 'isWalletAddress');
|
|
1834
|
+
// Mock keychain requests
|
|
1835
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cd8fc24710d2ebad89dce86c2`).reply(200, {
|
|
1836
|
+
id: '598f606cd8fc24710d2ebad89dce86c2',
|
|
1837
|
+
pub: 'xpub661MyMwAqRbcFXDcWD2vxuebcT1ZpTF4Vke6qmMW8yzddwNYpAPjvYEEL5jLfyYXW2fuxtAxY8TgjPUJLcf1C8qz9N6VgZxArKX4EwB8rH5',
|
|
1838
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1839
|
+
source: 'user',
|
|
1840
|
+
type: 'tss',
|
|
1841
|
+
});
|
|
1842
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cc8e43aef09fcb785221d9dd2`).reply(200, {
|
|
1843
|
+
id: '598f606cc8e43aef09fcb785221d9dd2',
|
|
1844
|
+
pub: 'xpub661MyMwAqRbcGhSaXikpuTC9KU88Xx9LrjKSw1JKsvXNgabpTdgjy7LSovh9ZHhcqhAHQu7uthu7FguNGdcC4aXTKK5gqTcPe4WvLYRbCSG',
|
|
1845
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1846
|
+
source: 'backup',
|
|
1847
|
+
type: 'tss',
|
|
1848
|
+
});
|
|
1849
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/5935d59cf660764331bafcade1855fd7`).reply(200, {
|
|
1850
|
+
id: '5935d59cf660764331bafcade1855fd7',
|
|
1851
|
+
pub: 'xpub661MyMwAqRbcFsXShW8R3hJsHNTYTUwzcejnLkY7KCtaJbDqcGkcBF99BrEJSjNZHeHveiYUrsAdwnjUMGwpgmEbiKcZWRuVA9HxnRaA3r3',
|
|
1852
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
1853
|
+
source: 'bitgo',
|
|
1854
|
+
type: 'tss',
|
|
1855
|
+
});
|
|
1856
|
+
// Mock address creation API
|
|
1857
|
+
(0, nock_1.default)(bgUrl)
|
|
1858
|
+
.post(`/api/v2/hteth/wallet/${ethWalletV6.id()}/address`)
|
|
1859
|
+
.reply(200, {
|
|
1860
|
+
id: '638a48c6c3dba40007a3497fa49a080c',
|
|
1861
|
+
address: '0xc012041dac143a59fa491db3a2b67b69bd78b685',
|
|
1862
|
+
chain: 0,
|
|
1863
|
+
index: 0,
|
|
1864
|
+
coin: 'hteth',
|
|
1865
|
+
wallet: ethWalletV6.id(),
|
|
1866
|
+
coinSpecific: {
|
|
1867
|
+
forwarderVersion: 4,
|
|
1868
|
+
salt: '0x0',
|
|
1869
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1870
|
+
},
|
|
1871
|
+
});
|
|
1872
|
+
await ethWalletV6.createAddress({ chain: 0 });
|
|
1873
|
+
isWalletAddressSpy.calledOnce.should.be.true();
|
|
1874
|
+
const calledParams = isWalletAddressSpy.firstCall.args[0];
|
|
1875
|
+
calledParams.should.have.property('walletVersion', 6);
|
|
1876
|
+
});
|
|
1877
|
+
it('should pass walletVersion 5 to isWalletAddress during address creation', async function () {
|
|
1878
|
+
const bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
|
|
1879
|
+
const ethCoin = bitgo.coin('hteth');
|
|
1880
|
+
const walletDataV5 = {
|
|
1881
|
+
id: '598f606cd8fc24710d2ebadb1d9459bb',
|
|
1882
|
+
coinSpecific: {
|
|
1883
|
+
baseAddress: '0xf1e3d30798acdf3a12fa5beb5fad8efb23d5be11',
|
|
1884
|
+
walletVersion: 5,
|
|
1885
|
+
},
|
|
1886
|
+
coin: 'hteth',
|
|
1887
|
+
keys: [
|
|
1888
|
+
'598f606cd8fc24710d2ebad89dce86c2',
|
|
1889
|
+
'598f606cc8e43aef09fcb785221d9dd2',
|
|
1890
|
+
'5935d59cf660764331bafcade1855fd7',
|
|
1891
|
+
],
|
|
1892
|
+
receiveAddress: {
|
|
1893
|
+
address: '0xf1e3d30798acdf3a12fa5beb5fad8efb23d5be11',
|
|
1894
|
+
},
|
|
1895
|
+
};
|
|
1896
|
+
const ethWalletV5 = new sdk_core_1.Wallet(bitgo, ethCoin, walletDataV5);
|
|
1897
|
+
const isWalletAddressSpy = sinon_1.default.spy(ethCoin, 'isWalletAddress');
|
|
1898
|
+
// Mock keychain requests
|
|
1899
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cd8fc24710d2ebad89dce86c2`).reply(200, {
|
|
1900
|
+
id: '598f606cd8fc24710d2ebad89dce86c2',
|
|
1901
|
+
pub: 'xpub661MyMwAqRbcFXDcWD2vxuebcT1ZpTF4Vke6qmMW8yzddwNYpAPjvYEEL5jLfyYXW2fuxtAxY8TgjPUJLcf1C8qz9N6VgZxArKX4EwB8rH5',
|
|
1902
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1903
|
+
source: 'user',
|
|
1904
|
+
type: 'tss',
|
|
1905
|
+
});
|
|
1906
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cc8e43aef09fcb785221d9dd2`).reply(200, {
|
|
1907
|
+
id: '598f606cc8e43aef09fcb785221d9dd2',
|
|
1908
|
+
pub: 'xpub661MyMwAqRbcGhSaXikpuTC9KU88Xx9LrjKSw1JKsvXNgabpTdgjy7LSovh9ZHhcqhAHQu7uthu7FguNGdcC4aXTKK5gqTcPe4WvLYRbCSG',
|
|
1909
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1910
|
+
source: 'backup',
|
|
1911
|
+
type: 'tss',
|
|
1912
|
+
});
|
|
1913
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/5935d59cf660764331bafcade1855fd7`).reply(200, {
|
|
1914
|
+
id: '5935d59cf660764331bafcade1855fd7',
|
|
1915
|
+
pub: 'xpub661MyMwAqRbcFsXShW8R3hJsHNTYTUwzcejnLkY7KCtaJbDqcGkcBF99BrEJSjNZHeHveiYUrsAdwnjUMGwpgmEbiKcZWRuVA9HxnRaA3r3',
|
|
1916
|
+
commonKeychain: '02c8a496b16abfe2567520a279e2154642fc3c0e08e629775cb4d845c0c5fbf55ab7ba153e886de65748ed18f4ff8f5cee2242e687399ea3297a1f5524fdefd56c',
|
|
1917
|
+
source: 'bitgo',
|
|
1918
|
+
type: 'tss',
|
|
1919
|
+
});
|
|
1920
|
+
// Mock address creation API
|
|
1921
|
+
(0, nock_1.default)(bgUrl)
|
|
1922
|
+
.post(`/api/v2/hteth/wallet/${ethWalletV5.id()}/address`)
|
|
1923
|
+
.reply(200, {
|
|
1924
|
+
id: '638a48c6c3dba40007a3497fa49a080c',
|
|
1925
|
+
address: '0xd63b5e2b8d1b4fba3625460508900bf2a0499a4d',
|
|
1926
|
+
chain: 0,
|
|
1927
|
+
index: 117,
|
|
1928
|
+
coin: 'hteth',
|
|
1929
|
+
wallet: ethWalletV5.id(),
|
|
1930
|
+
coinSpecific: {
|
|
1931
|
+
forwarderVersion: 4,
|
|
1932
|
+
salt: '0x75',
|
|
1933
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1934
|
+
},
|
|
1935
|
+
});
|
|
1936
|
+
await ethWalletV5.createAddress({ chain: 0 });
|
|
1937
|
+
// Verify isWalletAddress was called with walletVersion 5
|
|
1938
|
+
isWalletAddressSpy.calledOnce.should.be.true();
|
|
1939
|
+
const calledParams = isWalletAddressSpy.firstCall.args[0];
|
|
1940
|
+
calledParams.should.have.property('walletVersion', 5);
|
|
1941
|
+
});
|
|
1942
|
+
it('should pass walletVersion 2 to isWalletAddress during address creation', async function () {
|
|
1943
|
+
const bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
|
|
1944
|
+
const ethCoin = bitgo.coin('hteth');
|
|
1945
|
+
const walletDataV2 = {
|
|
1946
|
+
id: '598f606cd8fc24710d2ebadb1d9459bb',
|
|
1947
|
+
coinSpecific: {
|
|
1948
|
+
baseAddress: '0xdc485da076ed4a2b19584e9a1fdbb974f89b60f4',
|
|
1949
|
+
walletVersion: 2,
|
|
1950
|
+
},
|
|
1951
|
+
coin: 'hteth',
|
|
1952
|
+
keys: [
|
|
1953
|
+
'598f606cd8fc24710d2ebad89dce86c2',
|
|
1954
|
+
'598f606cc8e43aef09fcb785221d9dd2',
|
|
1955
|
+
'5935d59cf660764331bafcade1855fd7',
|
|
1956
|
+
],
|
|
1957
|
+
receiveAddress: {
|
|
1958
|
+
address: '0xdc485da076ed4a2b19584e9a1fdbb974f89b60f4',
|
|
1959
|
+
},
|
|
1960
|
+
};
|
|
1961
|
+
const ethWalletV2 = new sdk_core_1.Wallet(bitgo, ethCoin, walletDataV2);
|
|
1962
|
+
const isWalletAddressSpy = sinon_1.default.spy(ethCoin, 'isWalletAddress');
|
|
1963
|
+
// Mock keychain requests
|
|
1964
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cd8fc24710d2ebad89dce86c2`).reply(200, {
|
|
1965
|
+
id: '598f606cd8fc24710d2ebad89dce86c2',
|
|
1966
|
+
pub: 'xpub661MyMwAqRbcGrCxCX39zb3TvYjTqfUGwEUZHjnraRFm1WeMw9gfCD1wwc2wUDmBBZ2TkccJMwf5eBTja8r3z6HMxoTZGW6nvyoJMQFsecv',
|
|
1967
|
+
ethAddress: '0x9d16bb867b792c5e3bf636a0275f2db8601bd7d4',
|
|
1968
|
+
source: 'user',
|
|
1969
|
+
type: 'independent',
|
|
1970
|
+
});
|
|
1971
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cc8e43aef09fcb785221d9dd2`).reply(200, {
|
|
1972
|
+
id: '598f606cc8e43aef09fcb785221d9dd2',
|
|
1973
|
+
pub: 'xpub661MyMwAqRbcGKhdeC4nr1ta8d27xThtfFFHgbxWMrVb595meMS8i3fBMrTz8EdQMWBKHHKzxapGgheoMymVvRcQmaGDykRTBbtXqbiu9ps',
|
|
1974
|
+
ethAddress: '0x2dfce5cfeb5c03fbe680cd39ac0d2b25399b7d22',
|
|
1975
|
+
source: 'backup',
|
|
1976
|
+
type: 'independent',
|
|
1977
|
+
});
|
|
1978
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/5935d59cf660764331bafcade1855fd7`).reply(200, {
|
|
1979
|
+
id: '5935d59cf660764331bafcade1855fd7',
|
|
1980
|
+
pub: 'xpub661MyMwAqRbcGzTn5eyNGDkb18R43nH79HokYLc5PXZM19V8UrbuLdVRaCQMs4EeCAjnqmoYXqfyusTU46WoZMDyLpmTzoUX66ZBwGFjt1a',
|
|
1981
|
+
ethAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
1982
|
+
source: 'bitgo',
|
|
1983
|
+
type: 'independent',
|
|
1984
|
+
});
|
|
1985
|
+
// Mock address creation API
|
|
1986
|
+
(0, nock_1.default)(bgUrl)
|
|
1987
|
+
.post(`/api/v2/hteth/wallet/${ethWalletV2.id()}/address`)
|
|
1988
|
+
.reply(200, {
|
|
1989
|
+
id: '638a48c6c3dba40007a3497fa49a080c',
|
|
1990
|
+
address: '0xf636ceddffe41d106586875c0e56dc8feb6268f7',
|
|
1991
|
+
chain: 0,
|
|
1992
|
+
index: 23,
|
|
1993
|
+
coin: 'hteth',
|
|
1994
|
+
wallet: ethWalletV2.id(),
|
|
1995
|
+
coinSpecific: {
|
|
1996
|
+
forwarderVersion: 2,
|
|
1997
|
+
salt: '0x17',
|
|
1998
|
+
},
|
|
1999
|
+
});
|
|
2000
|
+
await ethWalletV2.createAddress({ chain: 0 });
|
|
2001
|
+
// Verify isWalletAddress was called with walletVersion 2
|
|
2002
|
+
isWalletAddressSpy.calledOnce.should.be.true();
|
|
2003
|
+
const calledParams = isWalletAddressSpy.firstCall.args[0];
|
|
2004
|
+
calledParams.should.have.property('walletVersion', 2);
|
|
2005
|
+
});
|
|
2006
|
+
it('should fail v6 address creation if walletVersion was not passed (simulates old bug)', async function () {
|
|
2007
|
+
const bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
|
|
2008
|
+
const ethCoin = bitgo.coin('hteth');
|
|
2009
|
+
const walletDataV6 = {
|
|
2010
|
+
id: '598f606cd8fc24710d2ebadb1d9459bb',
|
|
2011
|
+
coinSpecific: {
|
|
2012
|
+
baseAddress: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
2013
|
+
walletVersion: 6,
|
|
2014
|
+
},
|
|
2015
|
+
coin: 'hteth',
|
|
2016
|
+
keys: [
|
|
2017
|
+
'598f606cd8fc24710d2ebad89dce86c2',
|
|
2018
|
+
'598f606cc8e43aef09fcb785221d9dd2',
|
|
2019
|
+
'5935d59cf660764331bafcade1855fd7',
|
|
2020
|
+
],
|
|
2021
|
+
receiveAddress: {
|
|
2022
|
+
address: '0xdf07117705a9f8dc4c2a78de66b7f1797dba9d4e',
|
|
2023
|
+
},
|
|
2024
|
+
};
|
|
2025
|
+
const ethWalletV6 = new sdk_core_1.Wallet(bitgo, ethCoin, walletDataV6);
|
|
2026
|
+
// Stub isWalletAddress to simulate the OLD bug where walletVersion was not passed
|
|
2027
|
+
const originalIsWalletAddress = ethCoin.isWalletAddress.bind(ethCoin);
|
|
2028
|
+
const isWalletAddressStub = sinon_1.default.stub(ethCoin, 'isWalletAddress').callsFake(async (params) => {
|
|
2029
|
+
// Remove walletVersion to simulate the old bug
|
|
2030
|
+
const paramsWithoutWalletVersion = { ...params };
|
|
2031
|
+
delete paramsWithoutWalletVersion.walletVersion;
|
|
2032
|
+
return originalIsWalletAddress(paramsWithoutWalletVersion);
|
|
2033
|
+
});
|
|
2034
|
+
// Mock keychain requests
|
|
2035
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cd8fc24710d2ebad89dce86c2`).reply(200, {
|
|
2036
|
+
id: '598f606cd8fc24710d2ebad89dce86c2',
|
|
2037
|
+
pub: 'xpub661MyMwAqRbcFXDcWD2vxuebcT1ZpTF4Vke6qmMW8yzddwNYpAPjvYEEL5jLfyYXW2fuxtAxY8TgjPUJLcf1C8qz9N6VgZxArKX4EwB8rH5',
|
|
2038
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
2039
|
+
source: 'user',
|
|
2040
|
+
type: 'tss',
|
|
2041
|
+
});
|
|
2042
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/598f606cc8e43aef09fcb785221d9dd2`).reply(200, {
|
|
2043
|
+
id: '598f606cc8e43aef09fcb785221d9dd2',
|
|
2044
|
+
pub: 'xpub661MyMwAqRbcGhSaXikpuTC9KU88Xx9LrjKSw1JKsvXNgabpTdgjy7LSovh9ZHhcqhAHQu7uthu7FguNGdcC4aXTKK5gqTcPe4WvLYRbCSG',
|
|
2045
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
2046
|
+
source: 'backup',
|
|
2047
|
+
type: 'tss',
|
|
2048
|
+
});
|
|
2049
|
+
(0, nock_1.default)(bgUrl).get(`/api/v2/hteth/key/5935d59cf660764331bafcade1855fd7`).reply(200, {
|
|
2050
|
+
id: '5935d59cf660764331bafcade1855fd7',
|
|
2051
|
+
pub: 'xpub661MyMwAqRbcFsXShW8R3hJsHNTYTUwzcejnLkY7KCtaJbDqcGkcBF99BrEJSjNZHeHveiYUrsAdwnjUMGwpgmEbiKcZWRuVA9HxnRaA3r3',
|
|
2052
|
+
commonKeychain: '033b02aac4f038fef5118350b77d302ec6202931ca2e7122aad88994ffefcbc70a6069e662436236abb1619195232c41580204cb202c22357ed8f53e69eac5c69e',
|
|
2053
|
+
source: 'bitgo',
|
|
2054
|
+
type: 'tss',
|
|
2055
|
+
});
|
|
2056
|
+
// Mock address creation API
|
|
2057
|
+
(0, nock_1.default)(bgUrl)
|
|
2058
|
+
.post(`/api/v2/hteth/wallet/${ethWalletV6.id()}/address`)
|
|
2059
|
+
.reply(200, {
|
|
2060
|
+
id: '638a48c6c3dba40007a3497fa49a080c',
|
|
2061
|
+
address: '0xc012041dac143a59fa491db3a2b67b69bd78b685',
|
|
2062
|
+
chain: 0,
|
|
2063
|
+
index: 0,
|
|
2064
|
+
coin: 'hteth',
|
|
2065
|
+
wallet: ethWalletV6.id(),
|
|
2066
|
+
coinSpecific: {
|
|
2067
|
+
forwarderVersion: 4,
|
|
2068
|
+
salt: '0x0',
|
|
2069
|
+
feeAddress: '0xb1e725186990b86ca8efed08a3ccda9c9f400f09',
|
|
2070
|
+
},
|
|
2071
|
+
});
|
|
2072
|
+
// Without walletVersion, address creation should fail because
|
|
2073
|
+
// the code doesn't know to use TSS verification for v6 wallets
|
|
2074
|
+
await assert_1.default.rejects(async () => ethWalletV6.createAddress({ chain: 0 }), sdk_core_1.UnexpectedAddressError);
|
|
2075
|
+
isWalletAddressStub.restore();
|
|
2076
|
+
});
|
|
2077
|
+
});
|
|
2078
|
+
describe('EVM Cross Chain Recovery', function () {
|
|
2079
|
+
const baseUrl = sdk_core_1.common.Environments.test.etherscanBaseUrl;
|
|
2080
|
+
it('should build a recovery transaction for hot wallet', async function () {
|
|
2081
|
+
const userKey = '{"iv":"VFZ3jvXhxo1Z+Yaf2MtZnA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
2082
|
+
':"ccm","adata":"","cipher":"aes","salt":"p+fkHuLa/8k=","ct":"hYG7pvljLIgCjZ\n' +
|
|
2083
|
+
'53PBlCde5KZRmlUKKHLtDMk+HJfuU46hW+x+C9WsIAO4gFPnTCvFVmQ8x7czCtcNFub5AO2otOG\n' +
|
|
2084
|
+
'OsX4GE2gXOEmCl1TpWwwNhm7yMUjGJUpgW6ZZgXSXdDitSKi4V/hk78SGSzjFOBSPYRa6I="}\n';
|
|
2085
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
2086
|
+
const bitgoFeeAddress = '0x33a42faea3c6e87021347e51700b48aaf49aa1e7';
|
|
2087
|
+
const destinationAddress = '0xd5ADdE17feD8baed3F32b84AF05B8F2816f7b560';
|
|
2088
|
+
const bitgoDestinationAddress = '0xE5986CE4490Deb67d2950562Ceb930Ddf9be7a14';
|
|
2089
|
+
const walletPassphrase = sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE;
|
|
2090
|
+
const basecoin = bitgo.coin('hteth');
|
|
2091
|
+
(0, nock_1.default)(baseUrl)
|
|
2092
|
+
.get('/api')
|
|
2093
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
2094
|
+
.reply(200, mockData.getTxListResponse);
|
|
2095
|
+
(0, nock_1.default)(baseUrl)
|
|
2096
|
+
.get('/api')
|
|
2097
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
2098
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2099
|
+
(0, nock_1.default)(baseUrl)
|
|
2100
|
+
.get('/api')
|
|
2101
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
2102
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2103
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
2104
|
+
const spy = sinon_1.default.spy(src_1.TransactionBuilder.prototype, 'coinUsesNonPackedEncodingForTxData');
|
|
2105
|
+
await basecoin.recover({
|
|
2106
|
+
userKey: userKey,
|
|
2107
|
+
backupKey: '',
|
|
2108
|
+
walletPassphrase: walletPassphrase,
|
|
2109
|
+
walletContractAddress: walletContractAddress,
|
|
2110
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
2111
|
+
recoveryDestination: destinationAddress,
|
|
2112
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
2113
|
+
gasLimit: 500000,
|
|
2114
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
2115
|
+
intendedChain: 'tarbeth',
|
|
2116
|
+
});
|
|
2117
|
+
(0, assert_1.default)(spy.returned(true));
|
|
2118
|
+
});
|
|
2119
|
+
describe('Non-BitGo Recovery for Hot Wallets (MPCv2)', function () {
|
|
2120
|
+
const baseUrl = sdk_core_1.common.Environments.test.etherscanBaseUrl;
|
|
2121
|
+
let bitgo;
|
|
2122
|
+
let basecoin;
|
|
2123
|
+
before(function () {
|
|
2124
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
2125
|
+
basecoin = bitgo.coin('hteth');
|
|
2126
|
+
});
|
|
2127
|
+
it('should build a recovery transaction for MPCv2 kind of hot wallets', async function () {
|
|
2128
|
+
(0, nock_1.default)(baseUrl)
|
|
2129
|
+
.get('/api')
|
|
2130
|
+
.query(mockData.getTxListRequest(mockData.getNonBitGoRecoveryForHotWalletsMPCv2().bitgoFeeAddress))
|
|
2131
|
+
.reply(200, mockData.getTxListResponse);
|
|
2132
|
+
(0, nock_1.default)(baseUrl)
|
|
2133
|
+
.get('/api')
|
|
2134
|
+
.query(mockData.getBalanceRequest(mockData.getNonBitGoRecoveryForHotWalletsMPCv2().bitgoFeeAddress))
|
|
2135
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2136
|
+
(0, nock_1.default)(baseUrl)
|
|
2137
|
+
.get('/api')
|
|
2138
|
+
.query(mockData.getBalanceRequest(mockData.getNonBitGoRecoveryForHotWalletsMPCv2().walletContractAddress))
|
|
2139
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2140
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
2141
|
+
const params = mockData.getNonBitGoRecoveryForHotWalletsMPCv2();
|
|
2142
|
+
const transaction = await basecoin.recover({
|
|
2143
|
+
userKey: params.userKey,
|
|
2144
|
+
backupKey: params.backupKey,
|
|
2145
|
+
walletPassphrase: params.walletPassphrase,
|
|
2146
|
+
walletContractAddress: params.walletContractAddress,
|
|
2147
|
+
bitgoFeeAddress: params.bitgoFeeAddress,
|
|
2148
|
+
recoveryDestination: params.recoveryDestination,
|
|
2149
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
2150
|
+
gasLimit: 500000,
|
|
2151
|
+
bitgoDestinationAddress: params.bitgoDestinationAddress,
|
|
2152
|
+
intendedChain: params.intendedChain,
|
|
2153
|
+
});
|
|
2154
|
+
should_1.default.exist(transaction);
|
|
2155
|
+
transaction.should.have.property('txHex');
|
|
2156
|
+
});
|
|
2157
|
+
it('should throw an error for invalid user key', async function () {
|
|
2158
|
+
const params = mockData.getInvalidNonBitGoRecoveryParams();
|
|
2159
|
+
await assert_1.default.rejects(async () => {
|
|
2160
|
+
await basecoin.recover({
|
|
2161
|
+
userKey: params.userKey,
|
|
2162
|
+
backupKey: params.backupKey,
|
|
2163
|
+
walletPassphrase: params.walletPassphrase,
|
|
2164
|
+
walletContractAddress: params.walletContractAddress,
|
|
2165
|
+
bitgoFeeAddress: params.bitgoFeeAddress,
|
|
2166
|
+
recoveryDestination: params.recoveryDestination,
|
|
2167
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
2168
|
+
gasLimit: 500000,
|
|
2169
|
+
bitgoDestinationAddress: params.bitgoDestinationAddress,
|
|
2170
|
+
intendedChain: params.intendedChain,
|
|
2171
|
+
});
|
|
2172
|
+
}, Error, 'user key is invalid');
|
|
2173
|
+
});
|
|
2174
|
+
});
|
|
2175
|
+
describe('Build Unsigned Sweep for Self-Custody Cold Wallets (MPCv2)', function () {
|
|
2176
|
+
const baseUrl = sdk_core_1.common.Environments.test.etherscanBaseUrl;
|
|
2177
|
+
let bitgo;
|
|
2178
|
+
let basecoin;
|
|
2179
|
+
before(function () {
|
|
2180
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
2181
|
+
basecoin = bitgo.coin('hteth');
|
|
2182
|
+
});
|
|
2183
|
+
it('should generate an unsigned sweep without derivation seed', async function () {
|
|
2184
|
+
(0, nock_1.default)(baseUrl)
|
|
2185
|
+
.get('/api')
|
|
2186
|
+
.query(mockData.getTxListRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
2187
|
+
.reply(200, mockData.getTxListResponse);
|
|
2188
|
+
(0, nock_1.default)(baseUrl)
|
|
2189
|
+
.get('/api')
|
|
2190
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
2191
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2192
|
+
(0, nock_1.default)(baseUrl)
|
|
2193
|
+
.get('/api')
|
|
2194
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().walletContractAddress))
|
|
2195
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2196
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
2197
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
2198
|
+
const sweepResult = await basecoin.recover({
|
|
2199
|
+
userKey: params.commonKeyChain, // Box A Data
|
|
2200
|
+
backupKey: params.commonKeyChain, // Box B Data
|
|
2201
|
+
derivationSeed: params.derivationSeed, // Key Derivation Seed (optional)
|
|
2202
|
+
recoveryDestination: params.recoveryDestination, // Destination Address
|
|
2203
|
+
gasLimit: 200000, // Gas Limit
|
|
2204
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 }, // Max Fee Per Gas and Max Priority Fee Per Gas
|
|
2205
|
+
walletContractAddress: params.walletContractAddress,
|
|
2206
|
+
isTss: true,
|
|
2207
|
+
replayProtectionOptions: {
|
|
2208
|
+
chain: '42',
|
|
2209
|
+
hardfork: 'london',
|
|
2210
|
+
},
|
|
2211
|
+
});
|
|
2212
|
+
should_1.default.exist(sweepResult);
|
|
2213
|
+
const output = sweepResult;
|
|
2214
|
+
output.should.have.property('txRequests');
|
|
2215
|
+
output.txRequests.should.have.length(1);
|
|
2216
|
+
output.txRequests[0].should.have.property('transactions');
|
|
2217
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
2218
|
+
output.txRequests[0].should.have.property('walletCoin');
|
|
2219
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
2220
|
+
output.txRequests[0].transactions[0].should.have.property('unsignedTx');
|
|
2221
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('serializedTxHex');
|
|
2222
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('signableHex');
|
|
2223
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('derivationPath');
|
|
2224
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('feeInfo');
|
|
2225
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('parsedTx');
|
|
2226
|
+
const parsedTx = output.txRequests[0].transactions[0].unsignedTx.parsedTx;
|
|
2227
|
+
parsedTx.should.have.property('spendAmount');
|
|
2228
|
+
output.txRequests[0].transactions[0].unsignedTx.parsedTx.should.have.property('outputs');
|
|
2229
|
+
});
|
|
2230
|
+
it('should throw an error for invalid address', async function () {
|
|
2231
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
2232
|
+
params.recoveryDestination = 'invalidAddress';
|
|
2233
|
+
// Ensure userKey and backupKey are the same
|
|
2234
|
+
params.userKey =
|
|
2235
|
+
'0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
|
|
2236
|
+
params.backupKey =
|
|
2237
|
+
'0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
|
|
2238
|
+
await assert_1.default.rejects(async () => {
|
|
2239
|
+
await basecoin.recover({
|
|
2240
|
+
recoveryDestination: params.recoveryDestination, // Destination Address
|
|
2241
|
+
gasLimit: 2000, // Gas Limit
|
|
2242
|
+
eip1559: { maxFeePerGas: 200, maxPriorityFeePerGas: 10000 }, // Max Fee Per Gas and Max Priority Fee Per Gas
|
|
2243
|
+
userKey: params.userKey, // Provide the userKey
|
|
2244
|
+
backupKey: params.backupKey, // Provide the backupKey
|
|
2245
|
+
walletContractAddress: params.walletContractAddress, // Provide the walletContractAddress
|
|
2246
|
+
isTss: true,
|
|
2247
|
+
replayProtectionOptions: {
|
|
2248
|
+
chain: '42',
|
|
2249
|
+
hardfork: 'london',
|
|
2250
|
+
},
|
|
2251
|
+
});
|
|
2252
|
+
}, Error, 'Error: invalid address');
|
|
2253
|
+
});
|
|
2254
|
+
});
|
|
2255
|
+
describe('Build Unsigned Consolidation for Self-Custody Cold Wallets (MPCv2)', function () {
|
|
2256
|
+
const baseUrl = sdk_core_1.common.Environments.test.etherscanBaseUrl;
|
|
2257
|
+
let bitgo;
|
|
2258
|
+
let basecoin;
|
|
2259
|
+
before(function () {
|
|
2260
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
2261
|
+
basecoin = bitgo.coin('hteth');
|
|
2262
|
+
});
|
|
2263
|
+
it('should generate an unsigned consolidation for wallet v5', async function () {
|
|
2264
|
+
(0, nock_1.default)(baseUrl)
|
|
2265
|
+
.get('/api')
|
|
2266
|
+
.query(mockData.getTxListRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
2267
|
+
.times(2)
|
|
2268
|
+
.reply(200, mockData.getTxListResponse);
|
|
2269
|
+
(0, nock_1.default)(baseUrl)
|
|
2270
|
+
.get('/api')
|
|
2271
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
2272
|
+
.times(2)
|
|
2273
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2274
|
+
(0, nock_1.default)(baseUrl)
|
|
2275
|
+
.get('/api')
|
|
2276
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().walletContractAddress))
|
|
2277
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2278
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
2279
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
2280
|
+
const consolidationResult = await basecoin.recoverConsolidations({
|
|
2281
|
+
backupKey: params.commonKeyChain, // Box B Data
|
|
2282
|
+
derivationSeed: params.derivationSeed, // Key Derivation Seed (optional)
|
|
2283
|
+
recoveryDestination: params.recoveryDestination, // Destination Address
|
|
2284
|
+
gasLimit: 200000, // Gas Limit
|
|
2285
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 }, // Max Fee Per Gas and Max Priority Fee Per Gas
|
|
2286
|
+
walletContractAddress: params.walletContractAddress,
|
|
2287
|
+
isTss: true,
|
|
2288
|
+
replayProtectionOptions: {
|
|
2289
|
+
chain: '42',
|
|
2290
|
+
hardfork: 'london',
|
|
2291
|
+
},
|
|
2292
|
+
bitgoFeeAddress: '0x33a42faea3c6e87021347e51700b48aaf49aa1e7',
|
|
2293
|
+
startingScanIndex: 1,
|
|
2294
|
+
endingScanIndex: 2,
|
|
2295
|
+
});
|
|
2296
|
+
should_1.default.exist(consolidationResult);
|
|
2297
|
+
const unsignedBuilConsolidation = consolidationResult;
|
|
2298
|
+
unsignedBuilConsolidation.should.have.property('transactions');
|
|
2299
|
+
unsignedBuilConsolidation.transactions.should.have.length(1);
|
|
2300
|
+
const output = unsignedBuilConsolidation.transactions[0];
|
|
2301
|
+
output.should.have.property('txRequests');
|
|
2302
|
+
output.txRequests[0].should.have.property('transactions');
|
|
2303
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
2304
|
+
output.txRequests[0].should.have.property('walletCoin');
|
|
2305
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
2306
|
+
output.txRequests[0].transactions[0].should.have.property('unsignedTx');
|
|
2307
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('serializedTxHex');
|
|
2308
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('signableHex');
|
|
2309
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('derivationPath');
|
|
2310
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('feeInfo');
|
|
2311
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('parsedTx');
|
|
2312
|
+
const parsedTx = output.txRequests[0].transactions[0].unsignedTx.parsedTx;
|
|
2313
|
+
parsedTx.should.have.property('spendAmount');
|
|
2314
|
+
output.txRequests[0].transactions[0].unsignedTx.parsedTx.should.have.property('outputs');
|
|
2315
|
+
});
|
|
2316
|
+
it('should generate an unsigned consolidation for wallet v6', async function () {
|
|
2317
|
+
(0, nock_1.default)(baseUrl)
|
|
2318
|
+
.get('/api')
|
|
2319
|
+
.query(mockData.getTxListRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
2320
|
+
.times(2)
|
|
2321
|
+
.reply(200, mockData.getTxListResponse);
|
|
2322
|
+
(0, nock_1.default)(baseUrl)
|
|
2323
|
+
.get('/api')
|
|
2324
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
2325
|
+
.times(2)
|
|
2326
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2327
|
+
(0, nock_1.default)(baseUrl)
|
|
2328
|
+
.get('/api')
|
|
2329
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().walletContractAddress))
|
|
2330
|
+
.reply(200, mockData.getBalanceResponse);
|
|
2331
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
2332
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
2333
|
+
const consolidationResult = await basecoin.recoverConsolidations({
|
|
2334
|
+
userKey: params.commonKeyChain, // Box A Data
|
|
2335
|
+
backupKey: params.commonKeyChain, // Box B Data
|
|
2336
|
+
derivationSeed: params.derivationSeed, // Key Derivation Seed (optional)
|
|
2337
|
+
recoveryDestination: params.recoveryDestination, // Destination Address
|
|
2338
|
+
gasLimit: 200000, // Gas Limit
|
|
2339
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 }, // Max Fee Per Gas and Max Priority Fee Per Gas
|
|
2340
|
+
isTss: true,
|
|
2341
|
+
walletContractAddress: '123', // Wrong wallet address so that we can skip v5 address generation
|
|
2342
|
+
replayProtectionOptions: {
|
|
2343
|
+
chain: '42',
|
|
2344
|
+
hardfork: 'london',
|
|
2345
|
+
},
|
|
2346
|
+
bitgoFeeAddress: '0x33a42faea3c6e87021347e51700b48aaf49aa1e7',
|
|
2347
|
+
startingScanIndex: 1,
|
|
2348
|
+
endingScanIndex: 2,
|
|
2349
|
+
});
|
|
2350
|
+
should_1.default.exist(consolidationResult);
|
|
2351
|
+
const unsignedBuilConsolidation = consolidationResult;
|
|
2352
|
+
unsignedBuilConsolidation.should.have.property('transactions');
|
|
2353
|
+
unsignedBuilConsolidation.transactions.should.have.length(1);
|
|
2354
|
+
const output = unsignedBuilConsolidation.transactions[0];
|
|
2355
|
+
output.should.have.property('txRequests');
|
|
2356
|
+
output.txRequests[0].should.have.property('transactions');
|
|
2357
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
2358
|
+
output.txRequests[0].should.have.property('walletCoin');
|
|
2359
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
2360
|
+
output.txRequests[0].transactions[0].should.have.property('unsignedTx');
|
|
2361
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('serializedTxHex');
|
|
2362
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('signableHex');
|
|
2363
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('derivationPath');
|
|
2364
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('feeInfo');
|
|
2365
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('parsedTx');
|
|
2366
|
+
const parsedTx = output.txRequests[0].transactions[0].unsignedTx.parsedTx;
|
|
2367
|
+
parsedTx.should.have.property('spendAmount');
|
|
2368
|
+
output.txRequests[0].transactions[0].unsignedTx.parsedTx.should.have.property('outputs');
|
|
2369
|
+
});
|
|
2370
|
+
it('should throw an error for invalid address', async function () {
|
|
2371
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
2372
|
+
params.recoveryDestination = 'invalidAddress';
|
|
2373
|
+
// Ensure userKey and backupKey are the same
|
|
2374
|
+
params.userKey =
|
|
2375
|
+
'0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
|
|
2376
|
+
params.backupKey =
|
|
2377
|
+
'0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
|
|
2378
|
+
await assert_1.default.rejects(async () => {
|
|
2379
|
+
await basecoin.recover({
|
|
2380
|
+
recoveryDestination: params.recoveryDestination, // Destination Address
|
|
2381
|
+
gasLimit: 2000, // Gas Limit
|
|
2382
|
+
eip1559: { maxFeePerGas: 200, maxPriorityFeePerGas: 10000 }, // Max Fee Per Gas and Max Priority Fee Per Gas
|
|
2383
|
+
userKey: params.userKey, // Provide the userKey
|
|
2384
|
+
backupKey: params.backupKey, // Provide the backupKey
|
|
2385
|
+
walletContractAddress: params.walletContractAddress, // Provide the walletContractAddress
|
|
2386
|
+
isTss: true,
|
|
2387
|
+
replayProtectionOptions: {
|
|
2388
|
+
chain: '42',
|
|
2389
|
+
hardfork: 'london',
|
|
2390
|
+
},
|
|
2391
|
+
});
|
|
2392
|
+
}, Error, 'Error: invalid address');
|
|
2393
|
+
});
|
|
2394
|
+
});
|
|
2395
|
+
});
|
|
2396
|
+
describe('RecoveryBlockchainExplorerQuery', () => {
|
|
2397
|
+
it('should override the token parameter with a custom API key', async function () {
|
|
2398
|
+
const coin = bitgo.coin('teth');
|
|
2399
|
+
const query = {
|
|
2400
|
+
module: 'account',
|
|
2401
|
+
action: 'balance',
|
|
2402
|
+
address: '0x1234567890123456789012345678901234567890',
|
|
2403
|
+
};
|
|
2404
|
+
const customApiKey = 'custom-api-key-for-test';
|
|
2405
|
+
// Mock the environment API token
|
|
2406
|
+
const originalApiToken = sdk_core_1.common.Environments.test.etherscanApiToken;
|
|
2407
|
+
sdk_core_1.common.Environments.test.etherscanApiToken = 'default-environment-api-key';
|
|
2408
|
+
// Mock the request.get function to capture the query parameters
|
|
2409
|
+
const originalGet = superagent_1.default.get;
|
|
2410
|
+
let capturedQuery;
|
|
2411
|
+
superagent_1.default.get = function (url) {
|
|
2412
|
+
return {
|
|
2413
|
+
query: function (params) {
|
|
2414
|
+
capturedQuery = params;
|
|
2415
|
+
return {
|
|
2416
|
+
ok: true,
|
|
2417
|
+
body: { result: '100000000' },
|
|
2418
|
+
};
|
|
2419
|
+
},
|
|
2420
|
+
};
|
|
2421
|
+
};
|
|
2422
|
+
try {
|
|
2423
|
+
// Call with default API key
|
|
2424
|
+
await coin.recoveryBlockchainExplorerQuery(query);
|
|
2425
|
+
capturedQuery.should.have.property('apikey', 'default-environment-api-key');
|
|
2426
|
+
// Call with custom API key
|
|
2427
|
+
await coin.recoveryBlockchainExplorerQuery(query, customApiKey);
|
|
2428
|
+
capturedQuery.should.have.property('apikey', customApiKey);
|
|
2429
|
+
}
|
|
2430
|
+
finally {
|
|
2431
|
+
// Restore original function and API token
|
|
2432
|
+
superagent_1.default.get = originalGet;
|
|
2433
|
+
sdk_core_1.common.Environments.test.etherscanApiToken = originalApiToken;
|
|
2434
|
+
}
|
|
2435
|
+
});
|
|
2436
|
+
});
|
|
2437
|
+
describe('Audit Key', () => {
|
|
2438
|
+
let coin;
|
|
2439
|
+
before(() => {
|
|
2440
|
+
coin = bitgo.coin('hteth');
|
|
2441
|
+
});
|
|
2442
|
+
describe('MultiSig', () => {
|
|
2443
|
+
const { key } = ethMultiSigBackupKey_1.ethMultiSigBackupKey;
|
|
2444
|
+
it('should return { isValid: true } for valid inputs', () => {
|
|
2445
|
+
coin.assertIsValidKey({
|
|
2446
|
+
encryptedPrv: key,
|
|
2447
|
+
walletPassphrase: 'ZQ8MhxT84m4P',
|
|
2448
|
+
});
|
|
2449
|
+
});
|
|
2450
|
+
it('should throw error if the walletPassphrase is incorrect', async () => {
|
|
2451
|
+
await assert_1.default.rejects(() => coin.assertIsValidKey({
|
|
2452
|
+
encryptedPrv: key,
|
|
2453
|
+
walletPassphrase: 'foo',
|
|
2454
|
+
}), { message: 'failed to decrypt prv: decrypt: ciphertext is not valid JSON' });
|
|
2455
|
+
});
|
|
2456
|
+
it('should throw error if the key is altered', async () => {
|
|
2457
|
+
const alteredKey = key.replace(/[0-9]/g, '0');
|
|
2458
|
+
await assert_1.default.rejects(() => coin.assertIsValidKey({
|
|
2459
|
+
encryptedPrv: alteredKey,
|
|
2460
|
+
walletPassphrase: 'kAm[EFQ6o=SxlcLFDw%,',
|
|
2461
|
+
}), { message: 'failed to decrypt prv: decrypt: ciphertext is not valid JSON' });
|
|
2462
|
+
});
|
|
2463
|
+
});
|
|
2464
|
+
describe('TSS', () => {
|
|
2465
|
+
const { key: keyString, commonKeychain } = ethTssBackupKey_1.ethTssBackupKey;
|
|
2466
|
+
const key = keyString.replace(/\s/g, '');
|
|
2467
|
+
const walletPassphrase = 'kAm[EFQ6o=SxlcLFDw%,';
|
|
2468
|
+
const multiSigType = 'tss';
|
|
2469
|
+
it('should not throw for valid inputs', () => {
|
|
2470
|
+
coin.assertIsValidKey({
|
|
2471
|
+
encryptedPrv: key,
|
|
2472
|
+
publicKey: commonKeychain,
|
|
2473
|
+
walletPassphrase,
|
|
2474
|
+
multiSigType,
|
|
2475
|
+
});
|
|
2476
|
+
});
|
|
2477
|
+
it('should throw if the commonKeychain is altered', async () => {
|
|
2478
|
+
const alteredCommonKeychain = (0, sdk_core_1.generateRandomPassword)(10);
|
|
2479
|
+
await assert_1.default.rejects(() => coin.assertIsValidKey({
|
|
2480
|
+
encryptedPrv: key,
|
|
2481
|
+
publicKey: alteredCommonKeychain,
|
|
2482
|
+
walletPassphrase,
|
|
2483
|
+
multiSigType,
|
|
2484
|
+
}), { message: 'Invalid common keychain' });
|
|
2485
|
+
});
|
|
2486
|
+
it('should throw error if the walletPassphrase is incorrect', async () => {
|
|
2487
|
+
const incorrectPassphrase = 'foo';
|
|
2488
|
+
await assert_1.default.rejects(() => coin.assertIsValidKey({
|
|
2489
|
+
encryptedPrv: key,
|
|
2490
|
+
publicKey: commonKeychain,
|
|
2491
|
+
walletPassphrase: incorrectPassphrase,
|
|
2492
|
+
multiSigType,
|
|
2493
|
+
}), { message: 'failed to decrypt prv: incorrect password' });
|
|
2494
|
+
});
|
|
2495
|
+
it('should throw error if the key is altered', async () => {
|
|
2496
|
+
const alteredKey = key.replace(/[0-9]/g, '0');
|
|
2497
|
+
await assert_1.default.rejects(() => coin.assertIsValidKey({
|
|
2498
|
+
encryptedPrv: alteredKey,
|
|
2499
|
+
publicKey: commonKeychain,
|
|
2500
|
+
walletPassphrase,
|
|
2501
|
+
multiSigType,
|
|
2502
|
+
}), { message: 'failed to decrypt prv: decrypt: ciphertext is not valid JSON' });
|
|
2503
|
+
});
|
|
2504
|
+
});
|
|
2505
|
+
});
|
|
2506
|
+
describe('getSignablePayload', function () {
|
|
2507
|
+
let coin;
|
|
2508
|
+
before(function () {
|
|
2509
|
+
coin = bitgo.coin('teth');
|
|
2510
|
+
});
|
|
2511
|
+
it('should return a 32-byte keccak256 hash for a Legacy transaction', async function () {
|
|
2512
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('teth');
|
|
2513
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
2514
|
+
txBuilder.fee({ fee: '10000000000', gasLimit: '7000000' });
|
|
2515
|
+
txBuilder.counter(1);
|
|
2516
|
+
txBuilder.contract('0x8Ce59c2d1702844F8EdED451AA103961bC37B4e8');
|
|
2517
|
+
const transferBuilder = txBuilder.transfer();
|
|
2518
|
+
transferBuilder
|
|
2519
|
+
.coin('teth')
|
|
2520
|
+
.expirationTime(Math.floor(Date.now() / 1000) + 3600)
|
|
2521
|
+
.amount('100000')
|
|
2522
|
+
.to('0xeeaf0F05f37891ab4a21208B105A0687d12c5aF7')
|
|
2523
|
+
.contractSequenceId(1);
|
|
2524
|
+
const tx = await txBuilder.build();
|
|
2525
|
+
const serializedTx = tx.toBroadcastFormat();
|
|
2526
|
+
const payload = await coin.getSignablePayload(serializedTx);
|
|
2527
|
+
assert_1.default.ok(Buffer.isBuffer(payload));
|
|
2528
|
+
assert_1.default.strictEqual(payload.length, 32);
|
|
2529
|
+
});
|
|
2530
|
+
it('should return a 32-byte keccak256 hash for an EIP1559 transaction', async function () {
|
|
2531
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('teth');
|
|
2532
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
2533
|
+
txBuilder.fee({
|
|
2534
|
+
fee: '280000000000',
|
|
2535
|
+
gasLimit: '7000000',
|
|
2536
|
+
eip1559: { maxFeePerGas: '7593123', maxPriorityFeePerGas: '150' },
|
|
2537
|
+
});
|
|
2538
|
+
txBuilder.counter(1);
|
|
2539
|
+
txBuilder.contract('0x8Ce59c2d1702844F8EdED451AA103961bC37B4e8');
|
|
2540
|
+
const transferBuilder = txBuilder.transfer();
|
|
2541
|
+
transferBuilder
|
|
2542
|
+
.coin('teth')
|
|
2543
|
+
.expirationTime(Math.floor(Date.now() / 1000) + 3600)
|
|
2544
|
+
.amount('100000')
|
|
2545
|
+
.to('0xeeaf0F05f37891ab4a21208B105A0687d12c5aF7')
|
|
2546
|
+
.contractSequenceId(1);
|
|
2547
|
+
const tx = await txBuilder.build();
|
|
2548
|
+
const serializedTx = tx.toBroadcastFormat();
|
|
2549
|
+
const payload = await coin.getSignablePayload(serializedTx);
|
|
2550
|
+
assert_1.default.ok(Buffer.isBuffer(payload));
|
|
2551
|
+
assert_1.default.strictEqual(payload.length, 32);
|
|
2552
|
+
});
|
|
2553
|
+
});
|
|
2554
|
+
// ---------------------------------------------------------------------------
|
|
2555
|
+
// ERC-7984 token enablement — multisig verifyTransaction (all scenarios)
|
|
2556
|
+
// ---------------------------------------------------------------------------
|
|
2557
|
+
describe('verifyTransaction – ERC-7984 enabletoken (multisig wallet)', function () {
|
|
2558
|
+
// hteth Zama ACL contract (Networks.test.hoodi.zamaAclContractAddress)
|
|
2559
|
+
const ZAMA_ACL_ADDRESS = '0x6d3faf6f86e1ff9f3b0831dda920aba1cbd5bd68';
|
|
2560
|
+
// Simulated wallet base address (what the client sends as the recipient for base-address wallets)
|
|
2561
|
+
const WALLET_BASE_ADDRESS = '0x08e6736e876d772d2fa8f803a076cd6c9f845546';
|
|
2562
|
+
// Simulated forwarder address (what the client sends as recipient for forwarder wallets)
|
|
2563
|
+
const FORWARDER_ADDRESS = '0x1234567890123456789012345678901234567890';
|
|
2564
|
+
const WRONG_ADDRESS = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
|
2565
|
+
const makePrebuild = (recipientAddress) => ({
|
|
2566
|
+
recipients: [{ address: recipientAddress, amount: '0' }],
|
|
2567
|
+
nextContractSequenceId: 0,
|
|
2568
|
+
gasPrice: 20000000000,
|
|
2569
|
+
gasLimit: 300000,
|
|
2570
|
+
isBatch: false,
|
|
2571
|
+
coin: 'hteth',
|
|
2572
|
+
walletId: 'fakeWalletId',
|
|
2573
|
+
});
|
|
2574
|
+
// ── Base-address wallet ──────────────────────────────────────────────────
|
|
2575
|
+
it('base-address, single token: txParams → walletBase, txPrebuild → ACL', async function () {
|
|
2576
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2577
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2578
|
+
const result = await htethCoin.verifyTransaction({
|
|
2579
|
+
txParams: {
|
|
2580
|
+
type: 'enabletoken',
|
|
2581
|
+
recipients: [{ address: WALLET_BASE_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' }],
|
|
2582
|
+
},
|
|
2583
|
+
txPrebuild: makePrebuild(ZAMA_ACL_ADDRESS),
|
|
2584
|
+
wallet,
|
|
2585
|
+
});
|
|
2586
|
+
result.should.equal(true);
|
|
2587
|
+
});
|
|
2588
|
+
it('base-address, multi-token: multiple txParams recipients (same base address), txPrebuild → ACL multicall', async function () {
|
|
2589
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2590
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2591
|
+
const result = await htethCoin.verifyTransaction({
|
|
2592
|
+
txParams: {
|
|
2593
|
+
type: 'enabletoken',
|
|
2594
|
+
recipients: [
|
|
2595
|
+
{ address: WALLET_BASE_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' },
|
|
2596
|
+
{ address: WALLET_BASE_ADDRESS, amount: '0', tokenName: 'hteth:cusdt' },
|
|
2597
|
+
],
|
|
2598
|
+
},
|
|
2599
|
+
txPrebuild: makePrebuild(ZAMA_ACL_ADDRESS),
|
|
2600
|
+
wallet,
|
|
2601
|
+
});
|
|
2602
|
+
result.should.equal(true);
|
|
2603
|
+
});
|
|
2604
|
+
// ── Forwarder wallet ─────────────────────────────────────────────────────
|
|
2605
|
+
it('forwarder, single token: txParams → forwarder, txPrebuild → forwarder', async function () {
|
|
2606
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2607
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2608
|
+
const result = await htethCoin.verifyTransaction({
|
|
2609
|
+
txParams: {
|
|
2610
|
+
type: 'enabletoken',
|
|
2611
|
+
recipients: [{ address: FORWARDER_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' }],
|
|
2612
|
+
},
|
|
2613
|
+
txPrebuild: makePrebuild(FORWARDER_ADDRESS),
|
|
2614
|
+
wallet,
|
|
2615
|
+
});
|
|
2616
|
+
result.should.equal(true);
|
|
2617
|
+
});
|
|
2618
|
+
it('forwarder, multi-token: multiple txParams recipients (same forwarder), txPrebuild → forwarder', async function () {
|
|
2619
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2620
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2621
|
+
const result = await htethCoin.verifyTransaction({
|
|
2622
|
+
txParams: {
|
|
2623
|
+
type: 'enabletoken',
|
|
2624
|
+
recipients: [
|
|
2625
|
+
{ address: FORWARDER_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' },
|
|
2626
|
+
{ address: FORWARDER_ADDRESS, amount: '0', tokenName: 'hteth:cusdt' },
|
|
2627
|
+
],
|
|
2628
|
+
},
|
|
2629
|
+
txPrebuild: makePrebuild(FORWARDER_ADDRESS),
|
|
2630
|
+
wallet,
|
|
2631
|
+
});
|
|
2632
|
+
result.should.equal(true);
|
|
2633
|
+
});
|
|
2634
|
+
// ── Negative cases ───────────────────────────────────────────────────────
|
|
2635
|
+
it('should throw when txPrebuild recipient is neither the ACL contract nor the forwarder from txParams', async function () {
|
|
2636
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2637
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2638
|
+
await htethCoin
|
|
2639
|
+
.verifyTransaction({
|
|
2640
|
+
txParams: {
|
|
2641
|
+
type: 'enabletoken',
|
|
2642
|
+
recipients: [{ address: WALLET_BASE_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' }],
|
|
2643
|
+
},
|
|
2644
|
+
txPrebuild: makePrebuild(WRONG_ADDRESS),
|
|
2645
|
+
wallet,
|
|
2646
|
+
})
|
|
2647
|
+
.should.be.rejectedWith(/token enablement txPrebuild recipient must be/);
|
|
2648
|
+
});
|
|
2649
|
+
it('should throw when txParams recipients have different addresses', async function () {
|
|
2650
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2651
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2652
|
+
await htethCoin
|
|
2653
|
+
.verifyTransaction({
|
|
2654
|
+
txParams: {
|
|
2655
|
+
type: 'enabletoken',
|
|
2656
|
+
recipients: [
|
|
2657
|
+
{ address: WALLET_BASE_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' },
|
|
2658
|
+
{ address: FORWARDER_ADDRESS, amount: '0', tokenName: 'hteth:cusdt' },
|
|
2659
|
+
],
|
|
2660
|
+
},
|
|
2661
|
+
txPrebuild: makePrebuild(ZAMA_ACL_ADDRESS),
|
|
2662
|
+
wallet,
|
|
2663
|
+
})
|
|
2664
|
+
.should.be.rejectedWith(/must all have the same address/);
|
|
2665
|
+
});
|
|
2666
|
+
it('should throw when a txParams recipient has non-zero amount', async function () {
|
|
2667
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2668
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2669
|
+
await htethCoin
|
|
2670
|
+
.verifyTransaction({
|
|
2671
|
+
txParams: {
|
|
2672
|
+
type: 'enabletoken',
|
|
2673
|
+
recipients: [{ address: WALLET_BASE_ADDRESS, amount: '100', tokenName: 'hteth:ctest1' }],
|
|
2674
|
+
},
|
|
2675
|
+
txPrebuild: makePrebuild(ZAMA_ACL_ADDRESS),
|
|
2676
|
+
wallet,
|
|
2677
|
+
})
|
|
2678
|
+
.should.be.rejectedWith(/must all have amount 0/);
|
|
2679
|
+
});
|
|
2680
|
+
it('should throw when txPrebuild recipient has non-zero amount', async function () {
|
|
2681
|
+
const htethCoin = bitgo.coin('hteth');
|
|
2682
|
+
const wallet = new sdk_core_1.Wallet(bitgo, htethCoin, { coinSpecific: { baseAddress: WALLET_BASE_ADDRESS } });
|
|
2683
|
+
await htethCoin
|
|
2684
|
+
.verifyTransaction({
|
|
2685
|
+
txParams: {
|
|
2686
|
+
type: 'enabletoken',
|
|
2687
|
+
recipients: [{ address: WALLET_BASE_ADDRESS, amount: '0', tokenName: 'hteth:ctest1' }],
|
|
2688
|
+
},
|
|
2689
|
+
txPrebuild: {
|
|
2690
|
+
recipients: [{ address: ZAMA_ACL_ADDRESS, amount: '500' }],
|
|
2691
|
+
nextContractSequenceId: 0,
|
|
2692
|
+
coin: 'hteth',
|
|
2693
|
+
walletId: 'fakeWalletId',
|
|
2694
|
+
},
|
|
2695
|
+
wallet,
|
|
2696
|
+
})
|
|
2697
|
+
.should.be.rejectedWith(/expected amount 0 in txPrebuild/);
|
|
2698
|
+
});
|
|
2699
|
+
});
|
|
2700
|
+
});
|
|
2701
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2V0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1EQUErRDtBQUUvRCxnREFBd0I7QUFDeEIsa0RBQTBCO0FBQzFCLHFEQUE4QztBQUM5QyxxREFBdUM7QUFDdkMsNERBQWlDO0FBQ2pDLG1EQVU4QjtBQUM5QixpREFBK0M7QUFDL0MsbUNBV21CO0FBRW5CLG9EQUE0QjtBQUM1Qiw2Q0FBMEM7QUFDMUMsMkRBQTZDO0FBQzdDLDBEQUE0QztBQUM1QyxvREFBNEI7QUFDNUIsb0VBQXlDO0FBQ3pDLDBFQUF1RTtBQUN2RSxnRUFBNkQ7QUFFN0QsY0FBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFFeEIsUUFBUSxDQUFDLE1BQU0sRUFBRTtJQUNmLElBQUksS0FBbUIsQ0FBQztJQUN4QixJQUFJLG1CQUFtQixDQUFDO0lBQ3hCLElBQUksT0FBMkIsQ0FBQztJQUVoQyxNQUFNLFFBQVEsR0FBRyw0Q0FBNEMsQ0FBQztJQUM5RCxNQUFNLFFBQVEsR0FBRyw0Q0FBNEMsQ0FBQztJQUM5RCxNQUFNLGtCQUFrQixHQUFHLDRDQUE0QyxDQUFDO0lBQ3hFLE1BQU0scUJBQXFCLEdBQUcsNENBQTRDLENBQUM7SUFDM0UsTUFBTSxLQUFLLEdBQ1QsOE5BQThOLENBQUM7SUFDak8sTUFBTSxPQUFPLEdBQUcsb0VBQW9FLENBQUM7SUFDckYsTUFBTSxVQUFVLEdBQ2Qsb0lBQW9JLENBQUM7SUFFdkksTUFBTSxjQUFjLEdBQUcsS0FBSyxFQUFFLElBQVksRUFBbUIsRUFBRTtRQUM3RCxNQUFNLFNBQVMsR0FBRyxJQUFBLHVCQUFVLEVBQUMsT0FBTyxDQUF1QixDQUFDO1FBQzVELFNBQVMsQ0FBQyxJQUFJLENBQUMsMEJBQWUsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3QyxTQUFTLENBQUMsR0FBRyxD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LCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcblxuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgYmlwMzIgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0ICogYXMgc2VjcDI1NmsxIGZyb20gJ3NlY3AyNTZrMSc7XG5pbXBvcnQgcmVxdWVzdCBmcm9tICdzdXBlcmFnZW50JztcbmltcG9ydCB7XG4gIGNvbW1vbixcbiAgZ2VuZXJhdGVSYW5kb21QYXNzd29yZCxcbiAgSW52YWxpZEFkZHJlc3NFcnJvcixcbiAgSW52YWxpZEFkZHJlc3NWZXJpZmljYXRpb25PYmplY3RQcm9wZXJ0eUVycm9yLFxuICBNUENTd2VlcFR4cyxcbiAgVHJhbnNhY3Rpb25UeXBlLFxuICBUeEludGVudE1pc21hdGNoUmVjaXBpZW50RXJyb3IsXG4gIFVuZXhwZWN0ZWRBZGRyZXNzRXJyb3IsXG4gIFdhbGxldCxcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgQml0R29BUEkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstYXBpJztcbmltcG9ydCB7XG4gIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zLFxuICBFcmMyMFRva2VuLFxuICBIdGV0aCxcbiAgVGV0aCxcbiAgVHJhbnNhY3Rpb25CdWlsZGVyLFxuICBUcmFuc2ZlckJ1aWxkZXIsXG4gIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zLFxuICBVbnNpZ25lZEJ1aWxDb25zb2xpZGF0aW9uLFxuICBVbnNpZ25lZFN3ZWVwVHhNUEN2MixcbiAgVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnMsXG59IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBFdGhlcmV1bU5ldHdvcmsgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGdldEJ1aWxkZXIgfSBmcm9tICcuL2dldEJ1aWxkZXInO1xuaW1wb3J0ICogYXMgdGVzdERhdGEgZnJvbSAnLi4vcmVzb3VyY2VzL2V0aCc7XG5pbXBvcnQgKiBhcyBtb2NrRGF0YSBmcm9tICcuLi9maXh0dXJlcy9ldGgnO1xuaW1wb3J0IHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IEV0aGVyZXVtQWJpIGZyb20gJ2V0aGVyZXVtanMtYWJpJztcbmltcG9ydCB7IGV0aE11bHRpU2lnQmFja3VwS2V5IH0gZnJvbSAnLi9maXh0dXJlcy9ldGhNdWx0aVNpZ0JhY2t1cEtleSc7XG5pbXBvcnQgeyBldGhUc3NCYWNrdXBLZXkgfSBmcm9tICcuL2ZpeHR1cmVzL2V0aFRzc0JhY2t1cEtleSc7XG5cbm5vY2suZW5hYmxlTmV0Q29ubmVjdCgpO1xuXG5kZXNjcmliZSgnRVRIOicsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBob3BUeEJpdGdvU2lnbmF0dXJlO1xuICBsZXQgc2FuZGJveDogc2lub24uU2lub25TYW5kYm94O1xuXG4gIGNvbnN0IGFkZHJlc3MxID0gJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZSc7XG4gIGNvbnN0IGFkZHJlc3MyID0gJzB4N2U4NWJkYzI3YzA1MGUzOTA1ZWJmNGI4ZTYzNGQ5YWQ2ZWRkMGRlNic7XG4gIGNvbnN0IGhvcENvbnRyYWN0QWRkcmVzcyA9ICcweDQ3Y2U3Y2M4NmVmZWZlZjE5ZjhmYjUxNmIxMTczNWQxODNkYTg2MzUnO1xuICBjb25zdCBob3BEZXN0aW5hdGlvbkFkZHJlc3MgPSAnMHg5YzdlOGNlNjgyNWJENDgyNzhCM0FiNTkyMjhFRTI2ZjhCRTc5MjViJztcbiAgY29uc3QgaG9wVHggPVxuICAgICcweGY4NmI4MDg1MDRhODE3YzhmZjgyNTJmZjk0OWM3ZThjZTY4MjViZDQ4Mjc4YjNhYjU5MjI4ZWUyNmY4YmU3OTI1Yjg3MDM4ZDdlYTRjNjgwMDA4MDFjYTAxMWJjMjJjNjY0NTcwMTMzZGZjYTRmMDhhMGI4ZDAyMzM5Y2Y0NjcwNDZkNmE0MTUyZjA0ZjM2OGQwZWFmOTllYTAxZDZkYzVjZjBjODk3YzhkNGMzZTFkZjUzZDBkMDQyNzg0YzQyNDUzNmE0Y2M1YjgwMjU1MmI3ZDY0ZmVlOGI1JztcbiAgY29uc3QgaG9wVHhpZCA9ICcweDRhZjY1MTQzYmM3N2RhMmI1MGYzNWIzZDEzY2FjYjRkYjE4ZjAyNmJmODRiYzA3NDM1NTBiYzU3YjliNTMzNTEnO1xuICBjb25zdCB1c2VyUmVxU2lnID1cbiAgICAnMHg0MDRkYjMwN2Y2MTQ3ZjBkOGNkMzM4YzM0YzEzOTA2ZWY0NmE2ZmFhN2UwZTExOWQ1MTk0ZWYwNWFlYzE2ZTZmM2Q3MTBmOWI3OTAxNDYwZjk3ZTkyNDA2NmI2MmVmZDc0NDQzYmQzNDQwMmM2ZDQwYjQ5YzIwM2E1NTlmZjJjOCc7XG5cbiAgY29uc3QgYnVpbGREZWZpVHhIZXggPSBhc3luYyAoZGF0YTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAnLCBnYXNMaW1pdDogJzEwMDAwMCcgfSk7XG4gICAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgdHhCdWlsZGVyLmNvbnRyYWN0KGFkZHJlc3MxKTtcbiAgICB0eEJ1aWxkZXIuZGF0YShkYXRhKTtcbiAgICByZXR1cm4gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKS50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICB9O1xuXG4gIGNvbnN0IGRlZmlDYWxsZGF0YSA9IChzaWduYXR1cmU6IHN0cmluZywgdmFsdWVzOiBzdHJpbmdbXSk6IHN0cmluZyA9PiB7XG4gICAgY29uc3QgdHlwZXMgPSBzaWduYXR1cmUuc2xpY2Uoc2lnbmF0dXJlLmluZGV4T2YoJygnKSArIDEsIC0xKS5zcGxpdCgnLCcpO1xuICAgIGNvbnN0IG1ldGhvZElkID0gRXRoZXJldW1BYmkubWV0aG9kSUQoc2lnbmF0dXJlLnNwbGl0KCcoJylbMF0sIHR5cGVzKTtcbiAgICByZXR1cm4gJzB4JyArIEJ1ZmZlci5jb25jYXQoW21ldGhvZElkLCBFdGhlcmV1bUFiaS5yYXdFbmNvZGUodHlwZXMsIHZhbHVlcyldKS50b1N0cmluZygnaGV4Jyk7XG4gIH07XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiaXRnb0tleVhwcnYgPVxuICAgICAgJ3hwcnY5czIxWnJRSDE0M0szdHBXQkhXZTMxc0xvWE5SUTlBdlJZSmdpdGtLeFE0QVRGUU13dnI3aEhOcVlSVW5TN1BzanpCN2FLMVZ4cUhMdU5Ramoxc2NrSjJKd28ycXhtc3ZlandFQ1NwRk1mQyc7XG4gICAgY29uc3QgYml0Z29LZXkgPSBiaXAzMi5mcm9tQmFzZTU4KGJpdGdvS2V5WHBydik7XG4gICAgaWYgKCFiaXRnb0tleS5wcml2YXRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIHByaXZhdGVLZXknKTtcbiAgICB9XG4gICAgY29uc3QgYml0Z29YcHViID0gYml0Z29LZXkubmV1dGVyZWQoKS50b0Jhc2U1OCgpO1xuICAgIGhvcFR4Qml0Z29TaWduYXR1cmUgPVxuICAgICAgJzB4YWEnICtcbiAgICAgIEJ1ZmZlci5mcm9tKHNlY3AyNTZrMS5lY2RzYVNpZ24oQnVmZmVyLmZyb20oaG9wVHhpZC5zbGljZSgyKSwgJ2hleCcpLCBiaXRnb0tleS5wcml2YXRlS2V5KS5zaWduYXR1cmUpLnRvU3RyaW5nKFxuICAgICAgICAnaGV4J1xuICAgICAgKTtcblxuICAgIGNvbnN0IGVudiA9ICd0ZXN0JztcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBFcmMyMFRva2VuLmNyZWF0ZVRva2VuQ29uc3RydWN0b3JzKCkuZm9yRWFjaCgoeyBuYW1lLCBjb2luQ29uc3RydWN0b3IgfSkgPT4ge1xuICAgICAgYml0Z28uc2FmZVJlZ2lzdGVyKG5hbWUsIGNvaW5Db25zdHJ1Y3Rvcik7XG4gICAgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0ZXRoJywgVGV0aC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCdodGV0aCcsIEh0ZXRoLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBjb21tb24uRW52aXJvbm1lbnRzW2Vudl0uaHNtWHB1YiA9IGJpdGdvWHB1YjtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICB9KTtcblxuICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIHNhbmRib3gucmVzdG9yZSgpO1xuICB9KTtcblxuICBkZXNjcmliZSgnRUlQMTU1OScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHNpZ24gYSB0cmFuc2FjdGlvbiB3aXRoIEVJUDE1NTkgZmVlIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcblxuICAgICAgY29uc3QgdXNlcktleWNoYWluID0ge1xuICAgICAgICBwcnY6ICd4cHJ2OXMyMVpyUUgxNDNLM2hla3lOajdUY2lSNFhOWWUxa01qNjhXMmlwakpHTkhFVFdQN280MkFqRG5TUGdLaGRaNHg4TkJBdmFMNzJSclhqdVhOZG1rTXFMRVJaemE3M29ZdWdHdGJMRlhHOGcnLFxuICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjR0JqRTVRRzdwa2Y5Y1pEMzNVVUQ2SzQ2cTdFTHJidUc3RnFYZkxOR2lYWUdIZUVuR0JiNUFXUkVuazFlQTI4ZzhBclp2VVJiaHNoWFdrVHRkZEhSbzU0Zmd5VnZMZGInLFxuICAgICAgICByYXdQdWI6ICcwMjM2MzZlNjhiN2IyMDQ1NzNhYmRhMjYxNmFmZjZiNTg0OTEwZGVjZTI1NDNmMWNjNmQ4NDJjYWFjN2Q3NDk3NGInLFxuICAgICAgICByYXdQcnY6ICc3NDM4YTUwMDEwY2U3YjFkZmQ4NmU2ODA0NmNjNzhiYTFlYmQyNDJkNmQ4NWQ5OTA0ZDNmY2MwODczNGJjMTcyJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIGVpcDE1NTk6IHsgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwLCBtYXhGZWVQZXJHYXM6IDEwIH0sXG4gICAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhbW91bnQ6ICc0MicsXG4gICAgICAgICAgICAgIGFkZHJlc3M6ICcweGM5M2IxMzY0MmQ5M2I0MjE4YmI4NWY2NzMxN2Q2YjM3Mjg2ZTgwMjgnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGV4cGlyZVRpbWU6IDE2Mjc5NDkyMTQsXG4gICAgICAgICAgY29udHJhY3RTZXF1ZW5jZUlkOiAxMixcbiAgICAgICAgICBnYXNMaW1pdDogdW5kZWZpbmVkLFxuICAgICAgICAgIGdhc1ByaWNlOiB1bmRlZmluZWQsXG4gICAgICAgICAgaG9wVHJhbnNhY3Rpb246IHVuZGVmaW5lZCxcbiAgICAgICAgICBiYWNrdXBLZXlOb25jZTogdW5kZWZpbmVkLFxuICAgICAgICAgIHNlcXVlbmNlSWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICB9LFxuICAgICAgICBwcnY6IHVzZXJLZXljaGFpbi5wcnYsXG4gICAgICB9IGFzIGFueSk7XG5cbiAgICAgIChoYWxmU2lnbmVkVHJhbnNhY3Rpb24gYXMgYW55KS5oYWxmU2lnbmVkLmVpcDE1NTkubWF4UHJpb3JpdHlGZWVQZXJHYXMuc2hvdWxkLmVxdWFsKDEwKTtcbiAgICAgIChoYWxmU2lnbmVkVHJhbnNhY3Rpb24gYXMgYW55KS5oYWxmU2lnbmVkLmVpcDE1NTkubWF4RmVlUGVyR2FzLnNob3VsZC5lcXVhbCgxMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNpZ24gYSB0cmFuc2FjdGlvbiB3aXRoIEVJUDE1NTkgZmVlIHBhcmFtcyBmb3IgQ0NSJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCBzaWduVHJhbnNhY3Rpb24gPSBzaW5vbi5zcHkoQWJzdHJhY3RFdGhMaWtlTmV3Q29pbnMucHJvdG90eXBlLCAnc2lnblRyYW5zYWN0aW9uJyk7XG5cbiAgICAgIGNvbnN0IHVzZXJLZXljaGFpbiA9IHtcbiAgICAgICAgcHJ2OiAneHBydjlzMjFaclFIMTQzSzNoZWt5Tmo3VGNpUjRYTlllMWtNajY4VzJpcGpKR05IRVRXUDdvNDJBakRuU1BnS2hkWjR4OE5CQXZhTDcyUnJYanVYTmRta01xTEVSWnphNzNvWXVnR3RiTEZYRzhnJyxcbiAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0dCakU1UUc3cGtmOWNaRDMzVVVENks0NnE3RUxyYnVHN0ZxWGZMTkdpWFlHSGVFbkdCYjVBV1JFbmsxZUEyOGc4QXJadlVSYmhzaFhXa1R0ZGRIUm81NGZneVZ2TGRiJyxcbiAgICAgICAgcmF3UHViOiAnMDIzNjM2ZTY4YjdiMjA0NTczYWJkYTI2MTZhZmY2YjU4NDkxMGRlY2UyNTQzZjFjYzZkODQyY2FhYzdkNzQ5NzRiJyxcbiAgICAgICAgcmF3UHJ2OiAnNzQzOGE1MDAxMGNlN2IxZGZkODZlNjgwNDZjYzc4YmExZWJkMjQyZDZkODVkOTkwNGQzZmNjMDg3MzRiYzE3MicsXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMTAnLFxuICAgICAgICBnYXNMaW1pdDogJzEwMDAnLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBrZXkgPSB0ZXN0RGF0YS5LRVlQQUlSX1BSVi5nZXRLZXlzKCkucHJ2IGFzIHN0cmluZztcbiAgICAgIGNvbnN0IHRyYW5zZmVyQnVpbGRlciA9IHR4QnVpbGRlci50cmFuc2ZlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcbiAgICAgIHRyYW5zZmVyQnVpbGRlclxuICAgICAgICAuYW1vdW50KCcwJylcbiAgICAgICAgLnRvKCcweDE5NjQ1MDMyYzdmMTUzMzM5NWQ0NGE2Mjk0NjJlNzUxMDg0ZDNlNGMnKVxuICAgICAgICAuZXhwaXJhdGlvblRpbWUoMTU5MDA2NjcyOClcbiAgICAgICAgLmNvbnRyYWN0U2VxdWVuY2VJZCg1KVxuICAgICAgICAua2V5KGtleSk7XG4gICAgICB0eEJ1aWxkZXIuY29udHJhY3QoYWRkcmVzczEpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgICAgY29uc3QgaGFsZlNpZ25lZFRyYW5zYWN0aW9uID0gYXdhaXQgY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgZWlwMTU1OTogeyBtYXhQcmlvcml0eUZlZVBlckdhczogMTAsIG1heEZlZVBlckdhczogMTAgfSxcbiAgICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFtb3VudDogJzQyJyxcbiAgICAgICAgICAgICAgYWRkcmVzczogJzB4YzkzYjEzNjQyZDkzYjQyMThiYjg1ZjY3MzE3ZDZiMzcyODZlODAyOCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgZXhwaXJlVGltZTogMTYyNzk0OTIxNCxcbiAgICAgICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IDEyLFxuICAgICAgICAgIGdhc0xpbWl0OiB1bmRlZmluZWQsXG4gICAgICAgICAgZ2FzUHJpY2U6IHVuZGVmaW5lZCxcbiAgICAgICAgICBob3BUcmFuc2FjdGlvbjogdW5kZWZpbmVkLFxuICAgICAgICAgIGJhY2t1cEtleU5vbmNlOiB1bmRlZmluZWQsXG4gICAgICAgICAgc2VxdWVuY2VJZDogdW5kZWZpbmVkLFxuICAgICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgICAgdHhIZXg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogdXNlcktleWNoYWluLnBydixcbiAgICAgICAgaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeTogdHJ1ZSxcbiAgICAgIH0gYXMgYW55KTtcblxuICAgICAgYXNzZXJ0KChoYWxmU2lnbmVkVHJhbnNhY3Rpb24gYXMgYW55KS5oYWxmU2lnbmVkLnR4SGV4KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCgoaGFsZlNpZ25lZFRyYW5zYWN0aW9uIGFzIGFueSkuaGFsZlNpZ25lZC5laXAxNTU5Lm1heEZlZVBlckdhcywgMTApO1xuXG4gICAgICBzYW5kYm94LmFzc2VydC5jYWxsZWRPbmNlKHNpZ25UcmFuc2FjdGlvbik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSBub3JtYWwgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgdGhhdCBtYXRjaGVzIHRoZSBjbGllbnQgdHhQYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAndGV0aCcsXG4gICAgICAgIHdhbGxldDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSBiYXRjaCB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB0aGF0IG1hdGNoZXMgdGhlIGNsaWVudCB0eFBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9LFxuICAgICAgICAgIHsgYW1vdW50OiAnMjUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MyIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMzUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IChjb2luPy5zdGF0aWNzQ29pbj8ubmV0d29yayBhcyBFdGhlcmV1bU5ldHdvcmspLmJhdGNoZXJDb250cmFjdEFkZHJlc3MgfSxcbiAgICAgICAgXSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiB0cnVlLFxuICAgICAgICBjb2luOiAndGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBFTlMgYWRkcmVzcyByZXNvbHV0aW9uIGNoYW5naW5nIHJlY2lwaWVudCBhZGRyZXNzIGluIGNsaWVudCB0eFBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnYml0Z290ZXN0d2FsbGV0LmV0aCcgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDQwYTY2Mzk2MzgxMDQ0OWQ2ZTcyNTMzNjU3YTc0ZjExMmMzYjkwMWEnIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAndGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIGhvcCB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB0aGF0IG1hdGNoZXMgdGhlIGNsaWVudCB0eFBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogMTAwMDAwMDAwMDAwMDAwMCwgYWRkcmVzczogaG9wRGVzdGluYXRpb25BZGRyZXNzIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnNTAwMDAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGhvcENvbnRyYWN0QWRkcmVzcyB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3RldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgICBob3BUcmFuc2FjdGlvbjoge1xuICAgICAgICAgIHR4OiBob3BUeCxcbiAgICAgICAgICBpZDogaG9wVHhpZCxcbiAgICAgICAgICBzaWduYXR1cmU6IGhvcFR4Qml0Z29TaWduYXR1cmUsXG4gICAgICAgICAgcGF5bWVudElkOiAnMjc3MzkyODE5NicsXG4gICAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgICAgYW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgICAgcmVjaXBpZW50OiBob3BEZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgICAgdXNlclJlcVNpZzogdXNlclJlcVNpZyxcbiAgICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgd2hlbiBjbGllbnQgdHhQYXJhbXMgYXJlIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbnVsbDtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAndGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcGFyYW1zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCB0eFByZWJ1aWxkIHRoYXQgaXMgYm90aCBiYXRjaCBhbmQgaG9wJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyNTAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczIgfSxcbiAgICAgICAgXSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIGhvcDogdHJ1ZSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzM1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiB0cnVlLFxuICAgICAgICBjb2luOiAndGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6IGhvcFR4LFxuICAgICAgICAgIGlkOiBob3BUeGlkLFxuICAgICAgICAgIHNpZ25hdHVyZTogaG9wVHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgICBwYXltZW50SWQ6ICcyNzczOTI4MTk2JyxcbiAgICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICByZWNpcGllbnQ6IGhvcERlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgICBub25jZTogMCxcbiAgICAgICAgICB1c2VyUmVxU2lnOiB1c2VyUmVxU2lnLFxuICAgICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCd0eCBjYW5ub3QgYmUgYm90aCBhIGJhdGNoIGFuZCBob3AgdHJhbnNhY3Rpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgdHhQcmVidWlsZCB3aXRoIG1vcmUgdGhhbiBvbmUgcmVjaXBpZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyNTAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczIgfSxcbiAgICAgICAgXSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMiB9LFxuICAgICAgICBdLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IHRydWUsXG4gICAgICAgIGNvaW46ICd0ZXRoJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgYHRldGggZG9lc24ndCBzdXBwb3J0IHNlbmRpbmcgdG8gbW9yZSB0aGFuIDEgZGVzdGluYXRpb24gYWRkcmVzcyB3aXRoaW4gYSBzaW5nbGUgdHJhbnNhY3Rpb24uIFRyeSBhZ2FpbiwgdXNpbmcgb25seSBhIHNpbmdsZSByZWNpcGllbnQuYFxuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSBob3AgdHhQcmVidWlsZCB0aGF0IGRvZXMgbm90IHNlbmQgdG8gaXRzIGhvcCBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGhvcERlc3RpbmF0aW9uQWRkcmVzcyB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIGhvcDogdHJ1ZSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzUwMDAwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3RldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgICBob3BUcmFuc2FjdGlvbjoge1xuICAgICAgICAgIHR4OiBob3BUeCxcbiAgICAgICAgICBpZDogaG9wVHhpZCxcbiAgICAgICAgICBzaWduYXR1cmU6IGhvcFR4Qml0Z29TaWduYXR1cmUsXG4gICAgICAgICAgcGF5bWVudElkOiAnMCcsXG4gICAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgICAgYW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgICAgcmVjaXBpZW50OiBob3BEZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgICAgdXNlclJlcVNpZzogdXNlclJlcVNpZyxcbiAgICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgncmVjaXBpZW50IGFkZHJlc3Mgb2YgdHhQcmVidWlsZCBkb2VzIG5vdCBtYXRjaCBob3AgYWRkcmVzcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSBiYXRjaCB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB3aXRoIHRoZSB3cm9uZyB0b3RhbCBhbW91bnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMiB9LFxuICAgICAgICBdLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzU1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAoY29pbj8uc3RhdGljc0NvaW4/Lm5ldHdvcmsgYXMgRXRoZXJldW1OZXR3b3JrKS5iYXRjaGVyQ29udHJhY3RBZGRyZXNzIH0sXG4gICAgICAgIF0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogdHJ1ZSxcbiAgICAgICAgY29pbjogJ3RldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAnYmF0Y2ggdHJhbnNhY3Rpb24gYW1vdW50IGluIHR4UHJlYnVpbGQgcmVjZWl2ZWQgZnJvbSBCaXRHbyBzZXJ2ZXJzIGRvZXMgbm90IG1hdGNoIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCdcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgYmF0Y2ggdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgdGhhdCBkb2VzIG5vdCBzZW5kIHRvIHRoZSBiYXRjaGVyIGNvbnRyYWN0IGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMiB9LFxuICAgICAgICBdLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzM1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBob3BDb250cmFjdEFkZHJlc3MgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogdHJ1ZSxcbiAgICAgICAgY29pbjogJ3RldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgncmVjaXBpZW50IGFkZHJlc3Mgb2YgdHhQcmVidWlsZCBkb2VzIG5vdCBtYXRjaCBiYXRjaGVyIGFkZHJlc3MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgbm9ybWFsIHR4UHJlYnVpbGQgZnJvbSB0aGUgYml0Z28gc2VydmVyIHdpdGggdGhlIHdyb25nIGFtb3VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcyMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICd0ZXRoJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ25vcm1hbCB0cmFuc2FjdGlvbiBhbW91bnQgaW4gdHhQcmVidWlsZCByZWNlaXZlZCBmcm9tIEJpdEdvIHNlcnZlcnMgZG9lcyBub3QgbWF0Y2ggdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50J1xuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSBub3JtYWwgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgd2l0aCB0aGUgd3JvbmcgcmVjaXBpZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMiB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3RldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAnZGVzdGluYXRpb24gYWRkcmVzcyBpbiBub3JtYWwgdHhQcmVidWlsZCBkb2VzIG5vdCBtYXRjaCB0aGF0IGluIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCdcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdG9rZW4gdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgdGhhdCBtYXRjaGVzIHRoZSBjbGllbnQgdHhQYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGVzdCcpO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3RldGgnLFxuICAgICAgICB0b2tlbjogJ3Rlc3QnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB3aXRoIHRoZSB3cm9uZyBjb2luJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ2J0YycsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdjb2luIGluIHR4UHJlYnVpbGQgZGlkIG5vdCBtYXRjaCB0aGF0IGluIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVFNTIFRyYW5zYWN0aW9uIFZlcmlmaWNhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBleHBlY3REZWZpUmVqZWN0aW9uID0gYXN5bmMgKHA6IFByb21pc2U8dW5rbm93bj4sIG1lc3NhZ2VQYXR0ZXJuOiBSZWdFeHApID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHA7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgZXJyLnNob3VsZC5iZS5pbnN0YW5jZU9mKFR4SW50ZW50TWlzbWF0Y2hSZWNpcGllbnRFcnJvcik7XG4gICAgICAgIChlcnIgYXMgRXJyb3IpLm1lc3NhZ2Uuc2hvdWxkLm1hdGNoKG1lc3NhZ2VQYXR0ZXJuKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RlZCB2ZXJpZnlUcmFuc2FjdGlvbiB0byBiZSByZWplY3RlZCwgYnV0IGl0IHJlc29sdmVkJyk7XG4gICAgfTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyBjb25zb2xpZGF0aW9uIHRyYW5zYWN0aW9uIHdoZW4gdHhQcmVidWlsZCBoYXMgY29uc29saWRhdGVJZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIHR4UGFyYW1zIHdpdGhvdXQgcmVjaXBpZW50cyAoYXMgaW4gY29uc29saWRhdGlvbiBmbG93KVxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgLy8gdHhQcmVidWlsZCB3aXRoIGNvbnNvbGlkYXRlSWQgKHNldCBieSBzZXJ2ZXIgZHVyaW5nIGNvbnNvbGlkYXRpb24gYnVpbGQpXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICBjb25zb2xpZGF0ZUlkOiAnNjhhN2Q1ZDBjNjZlNzRlMjE2Yjk3MTczYmQ1NThjNmQnLFxuICAgICAgICB0eEhleDogJzB4JyxcbiAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIHRyYW5zYWN0aW9uIHdoZW4gdHhQYXJhbXMudHlwZSBpcyBjb25zb2xpZGF0ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICB0eXBlOiAnY29uc29saWRhdGUnLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBUU1MgdHJhbnNhY3Rpb24gd2hlbiB0eFBhcmFtcy5wcmVidWlsZFR4IGhhcyBjb25zb2xpZGF0ZUlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBwcmVidWlsZFR4OiB7XG4gICAgICAgICAgY29uc29saWRhdGVJZDogJzY4YTdkNWQwYzY2ZTc0ZTIxNmI5NzE3M2JkNTU4YzZkJyxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBUU1MgdHJhbnNhY3Rpb24gd2l0aG91dCByZWNpcGllbnRzLCBjb25zb2xpZGF0ZUlkLCBvciB2YWxpZCB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6ICcweCcsXG4gICAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyB0eFBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIHRyYW5zYWN0aW9uIHdpdGggYWNjZWxlcmF0aW9uIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZSc7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgIGJhc2VBZGRyZXNzOiBiYXNlQWRkcmVzcyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgdHlwZTogJ2FjY2VsZXJhdGlvbicsXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6ICcweCcsXG4gICAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyB0cmFuc2FjdGlvbiB3aXRoIGZpbGxOb25jZSB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHR5cGU6ICdmaWxsTm9uY2UnLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBUU1MgdHJhbnNhY3Rpb24gd2l0aCBkZWZpQXBwcm92ZSB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgLy8gRGVGaSBkZXBvc2l0IGZsb3cgaXMgaW50ZW50LWJhc2VkOiByZWNpcGllbnRzL2NhbGxkYXRhIGFyZSBidWlsdCBzZXJ2ZXItc2lkZVxuICAgICAgLy8gZnJvbSBkZWZpUGFyYW1zLCBzbyB0eFBhcmFtcyBoYXMgbm8gcmVjaXBpZW50cyAoc2VlIENHRC0xODE1KS5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICB0eXBlOiAnZGVmaUFwcHJvdmUnLFxuICAgICAgICBkZWZpUGFyYW1zOiB7IHZhdWx0SWQ6ICdodGV0aC11c2RjLXRlc3QnLCBhbW91bnQ6ICcxMCcgfSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogYXdhaXQgYnVpbGREZWZpVHhIZXgoZGVmaUNhbGxkYXRhKCdhcHByb3ZlKGFkZHJlc3MsdWludDI1NiknLCBbYWRkcmVzczEsICcxMCddKSksXG4gICAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyB0cmFuc2FjdGlvbiB3aXRoIHdyYXBBcHByb3ZlIHR5cGUgYW5kIG5vIHJlY2lwaWVudHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgYmFzZUFkZHJlc3M6ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFdQIGRlcml2ZXMgdGhlIHVuZGVybHlpbmcgdG9rZW4gY29udHJhY3QsIHdyYXBwZXIgc3BlbmRlciwgYW5kIGFwcHJvdmVcbiAgICAgIC8vIGNhbGxkYXRhIGZyb20gdG9rZW5OYW1lIGFuZCBhbW91bnQsIHNvIHRoZSBjbGllbnQgaW50ZW50IGhhcyBubyByZWNpcGllbnRzLlxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHR5cGU6ICd3cmFwQXBwcm92ZScsXG4gICAgICAgIHRva2VuTmFtZTogJ2h0ZXRoOmN1c2R0JyxcbiAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6ICcweCcsXG4gICAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb246IHt9LFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuXG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIHRyYW5zYWN0aW9uIHdpdGggZGVmaURlcG9zaXQgdHlwZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICB0eXBlOiAnZGVmaURlcG9zaXQnLFxuICAgICAgICBkZWZpUGFyYW1zOiB7IHZhdWx0SWQ6ICdodGV0aC11c2RjLXRlc3QnLCBhbW91bnQ6ICcxMCcsIG9wZXJhdGlvbklkOiAnZmFrZU9wZXJhdGlvbklkJyB9LFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiBhd2FpdCBidWlsZERlZmlUeEhleChkZWZpQ2FsbGRhdGEoJ2RlcG9zaXQodWludDI1NixhZGRyZXNzKScsIFsnMTAnLCBhZGRyZXNzMV0pKSxcbiAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgRGVGaSBjYWxsZGF0YSB0aGF0IHJlZGlyZWN0cyBmdW5kcyBvciBncmFudHMgZXhjZXNzIGFwcHJvdmFsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7IGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogYWRkcmVzczEgfSB9KTtcbiAgICAgIGNvbnN0IHZlcmlmeSA9IGFzeW5jICh0eXBlOiBzdHJpbmcsIGRlZmlQYXJhbXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkLCBkYXRhOiBzdHJpbmcpID0+XG4gICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7IHR5cGUsIGRlZmlQYXJhbXMsIHdhbGxldCB9IGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4OiBhd2FpdCBidWlsZERlZmlUeEhleChkYXRhKSwgY29pbjogJ2h0ZXRoJywgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnIH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHt9LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KTtcblxuICAgICAgLy8gZGVmaUFwcHJvdmU6IGF0dGFja2VyIGFwcHJvdmUoYXR0YWNrZXIsIE1BWF9VSU5UMjU2KSBkaXNndWlzZWQgYXMgZGVmaUFwcHJvdmVcbiAgICAgIGF3YWl0IGV4cGVjdERlZmlSZWplY3Rpb24oXG4gICAgICAgIHZlcmlmeShcbiAgICAgICAgICAnZGVmaUFwcHJvdmUnLFxuICAgICAgICAgIHsgdmF1bHRJZDogJ3ZhdWx0JywgYW1vdW50OiAnMTAnIH0sXG4gICAgICAgICAgZGVmaUNhbGxkYXRhKCdhcHByb3ZlKGFkZHJlc3MsdWludDI1NiknLCBbYWRkcmVzczIsICcxMDAwMDAwMDAwMDAwMDAwMDAwJ10pXG4gICAgICAgICksXG4gICAgICAgIC9hbW91bnQgZG9lcyBub3QgbWF0Y2gvXG4gICAgICApO1xuICAgICAgLy8gZGVmaURlcG9zaXQ6IGZ1bmRzIHJlZGlyZWN0ZWQgdG8gYXR0YWNrZXIgcmVjZWl2ZXJcbiAgICAgIGF3YWl0IGV4cGVjdERlZmlSZWplY3Rpb24oXG4gICAgICAgIHZlcmlmeShcbiAgICAgICAgICAnZGVmaURlcG9zaXQnLFxuICAgICAgICAgIHsgdmF1bHRJZDogJ3ZhdWx0JywgYW1vdW50OiAnMTAnIH0sXG4gICAgICAgICAgZGVmaUNhbGxkYXRhKCdkZXBvc2l0KHVpbnQyNTYsYWRkcmVzcyknLCBbJzEwJywgYWRkcmVzczJdKVxuICAgICAgICApLFxuICAgICAgICAvcmVjZWl2ZXIgZG9lcyBub3QgbWF0Y2gvXG4gICAgICApO1xuICAgICAgLy8gZGVmaVdpdGhkcmF3OiByZWNlaXZlciBhbmQgb3duZXIgYm90aCBhdHRhY2tlclxuICAgICAgYXdhaXQgZXhwZWN0RGVmaVJlamVjdGlvbihcbiAgICAgICAgdmVyaWZ5KFxuICAgICAgICAgICdkZWZpV2l0aGRyYXcnLFxuICAgICAgICAgIHsgdmF1bHRJZDogJ3ZhdWx0JywgYW1vdW50OiAnMTAnIH0sXG4gICAgICAgICAgZGVmaUNhbGxkYXRhKCdyZWRlZW0odWludDI1NixhZGRyZXNzLGFkZHJlc3MpJywgWyc1JywgYWRkcmVzczIsIGFkZHJlc3MyXSlcbiAgICAgICAgKSxcbiAgICAgICAgL3JlY2VpdmVyIGFuZCBvd25lci9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBEZUZpIGNhbGxkYXRhIHdpdGggd3Jvbmcgc2VsZWN0b3IsIHdyb25nIG93bmVyIGFsb25lLCBvciB3cm9uZyBkZXBvc2l0IGFtb3VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwgeyBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IGFkZHJlc3MxIH0gfSk7XG4gICAgICBjb25zdCB2ZXJpZnkgPSBhc3luYyAodHlwZTogc3RyaW5nLCBkZWZpUGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgZGF0YTogc3RyaW5nKSA9PlxuICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogeyB0eXBlLCBkZWZpUGFyYW1zLCB3YWxsZXQgfSBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleDogYXdhaXQgYnVpbGREZWZpVHhIZXgoZGF0YSksIGNvaW46ICdodGV0aCcsIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyB9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7fSxcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSk7XG4gICAgICBjb25zdCBkZWZpUGFyYW1zID0geyB2YXVsdElkOiAndmF1bHQnLCBhbW91bnQ6ICcxMCcgfTtcblxuICAgICAgLy8gZGVmaUFwcHJvdmUgd2l0aCBhIG5vbi1hcHByb3ZlIHNlbGVjdG9yICh0cmFuc2ZlciBkaXNndWlzZWQgYXMgYXBwcm92ZSlcbiAgICAgIGF3YWl0IGV4cGVjdERlZmlSZWplY3Rpb24oXG4gICAgICAgIHZlcmlmeSgnZGVmaUFwcHJvdmUnLCBkZWZpUGFyYW1zLCBkZWZpQ2FsbGRhdGEoJ3RyYW5zZmVyKGFkZHJlc3MsdWludDI1NiknLCBbYWRkcmVzczIsICcxMCddKSksXG4gICAgICAgIC9hcHByb3ZlXFwoYWRkcmVzcyx1aW50MjU2XFwpL1xuICAgICAgKTtcbiAgICAgIC8vIGRlZmlEZXBvc2l0IHdpdGggYSBub24tZGVwb3NpdCBzZWxlY3RvclxuICAgICAgYXdhaXQgZXhwZWN0RGVmaVJlamVjdGlvbihcbiAgICAgICAgdmVyaWZ5KCdkZWZpRGVwb3NpdCcsIGRlZmlQYXJhbXMsIGRlZmlDYWxsZGF0YSgnYXBwcm92ZShhZGRyZXNzLHVpbnQyNTYpJywgW2FkZHJlc3MxLCAnMTAnXSkpLFxuICAgICAgICAvZGVwb3NpdFxcKHVpbnQyNTYsYWRkcmVzc1xcKS9cbiAgICAgICk7XG4gICAgICAvLyBkZWZpV2l0aGRyYXcgd2l0aCBhIG5vbi1yZWRlZW0gc2VsZWN0b3JcbiAgICAgIGF3YWl0IGV4cGVjdERlZmlSZWplY3Rpb24oXG4gICAgICAgIHZlcmlmeSgnZGVmaVdpdGhkcmF3JywgZGVmaVBhcmFtcywgZGVmaUNhbGxkYXRhKCdhcHByb3ZlKGFkZHJlc3MsdWludDI1NiknLCBbYWRkcmVzczEsICcxMCddKSksXG4gICAgICAgIC9yZWRlZW1cXCh1aW50MjU2LGFkZHJlc3MsYWRkcmVzc1xcKS9cbiAgICAgICk7XG4gICAgICAvLyBkZWZpV2l0aGRyYXc6IHJlY2VpdmVyIG9rIGJ1dCBvd25lciBpcyBhdHRhY2tlclxuICAgICAgYXdhaXQgZXhwZWN0RGVmaVJlamVjdGlvbihcbiAgICAgICAgdmVyaWZ5KCdkZWZpV2l0aGRyYXcnLCBkZWZpUGFyYW1zLCBkZWZpQ2FsbGRhdGEoJ3JlZGVlbSh1aW50MjU2LGFkZHJlc3MsYWRkcmVzcyknLCBbJzEwJywgYWRkcmVzczEsIGFkZHJlc3MyXSkpLFxuICAgICAgICAvcmVjZWl2ZXIgYW5kIG93bmVyL1xuICAgICAgKTtcbiAgICAgIC8vIGRlZmlXaXRoZHJhdzogcmVjZWl2ZXIgYW5kIG93bmVyIG9rIGJ1dCBzaGFyZXMgZG8gbm90IG1hdGNoIGRlZmlQYXJhbXMuYW1vdW50XG4gICAgICBhd2FpdCBleHBlY3REZWZpUmVqZWN0aW9uKFxuICAgICAgICB2ZXJpZnkoXG4gICAgICAgICAgJ2RlZmlXaXRoZHJhdycsXG4gICAgICAgICAgZGVmaVBhcmFtcyxcbiAgICAgICAgICBkZWZpQ2FsbGRhdGEoJ3JlZGVlbSh1aW50MjU2LGFkZHJlc3MsYWRkcmVzcyknLCBbJzk5OScsIGFkZHJlc3MxLCBhZGRyZXNzMV0pXG4gICAgICAgICksXG4gICAgICAgIC9zaGFyZXMgZG8gbm90IG1hdGNoL1xuICAgICAgKTtcbiAgICAgIC8vIGRlZmlEZXBvc2l0OiByZWNlaXZlciBvayBidXQgYW1vdW50IG1pc21hdGNoXG4gICAgICBhd2FpdCBleHBlY3REZWZpUmVqZWN0aW9uKFxuICAgICAgICB2ZXJpZnkoJ2RlZmlEZXBvc2l0JywgZGVmaVBhcmFtcywgZGVmaUNhbGxkYXRhKCdkZXBvc2l0KHVpbnQyNTYsYWRkcmVzcyknLCBbJzk5OScsIGFkZHJlc3MxXSkpLFxuICAgICAgICAvYW1vdW50IGRvZXMgbm90IG1hdGNoL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBjbG9zZWQgd2hlbiBkZWZpIGludGVudCBwYXJhbWV0ZXJzIGFyZSBtaXNzaW5nIG9yIGNhbGxkYXRhIGlzIHNob3J0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7IGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogYWRkcmVzczEgfSB9KTtcbiAgICAgIGNvbnN0IHZlcmlmeSA9IGFzeW5jICh0eXBlOiBzdHJpbmcsIGRlZmlQYXJhbXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkLCBkYXRhOiBzdHJpbmcpID0+XG4gICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7IHR5cGUsIGRlZmlQYXJhbXMsIHdhbGxldCB9IGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4OiBhd2FpdCBidWlsZERlZmlUeEhleChkYXRhKSwgY29pbjogJ2h0ZXRoJywgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnIH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHt9LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KTtcblxuICAgICAgLy8gTWlzc2luZyBkZWZpUGFyYW1zIGZvciBlYWNoIGRlZmkgdHlwZSAtPiBmYWlsIGNsb3NlZFxuICAgICAgYXdhaXQgZXhwZWN0RGVmaVJlamVjdGlvbihcbiAgICAgICAgdmVyaWZ5KCdkZWZpQXBwcm92ZScsIHVuZGVmaW5lZCwgZGVmaUNhbGxkYXRhKCdhcHByb3ZlKGFkZHJlc3MsdWludDI1NiknLCBbYWRkcmVzczEsICcxMCddKSksXG4gICAgICAgIC9taXNzaW5nIHJlcXVpcmVkIGludGVudCBwYXJhbWV0ZXJzL1xuICAgICAgKTtcbiAgICAgIGF3YWl0IGV4cGVjdERlZmlSZWplY3Rpb24oXG4gICAgICAgIHZlcmlmeSgnZGVmaURlcG9zaXQnLCB1bmRlZmluZWQsIGRlZmlDYWxsZGF0YSgnZGVwb3NpdCh1aW50MjU2LGFkZHJlc3MpJywgWycxMCcsIGFkZHJlc3MxXSkpLFxuICAgICAgICAvbWlzc2luZyByZXF1aXJlZCBpbnRlbnQgcGFyYW1ldGVycy9cbiAgICAgICk7XG4gICAgICBhd2FpdCBleHBlY3REZWZpUmVqZWN0aW9uKFxuICAgICAgICB2ZXJpZnkoJ2RlZmlXaXRoZHJhdycsIHVuZGVmaW5lZCwgZGVmaUNhbGxkYXRhKCdyZWRlZW0odWludDI1NixhZGRyZXNzLGFkZHJlc3MpJywgWyc1JywgYWRkcmVzczEsIGFkZHJlc3MxXSkpLFxuICAgICAgICAvbWlzc2luZyByZXF1aXJlZCBpbnRlbnQgcGFyYW1ldGVycy9cbiAgICAgICk7XG4gICAgICAvLyBTaG9ydC9lbXB0eSBjYWxsZGF0YSB3aXRoIG5vIHZhbGlkIHNlbGVjdG9yIHByZWZpeCAtPiBzZWxlY3RvciBtaXNtYXRjaCAoZmFpbCBjbG9zZWQpXG4gICAgICBhd2FpdCBleHBlY3REZWZpUmVqZWN0aW9uKFxuICAgICAgICB2ZXJpZnkoJ2RlZmlBcHByb3ZlJywgeyB2YXVsdElkOiAndmF1bHQnLCBhbW91bnQ6ICcxMCcgfSwgJzB4JyksXG4gICAgICAgIC9hcHByb3ZlXFwoYWRkcmVzcyx1aW50MjU2XFwpL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyB0cmFuc2FjdGlvbiB3aXRoIGRlZmlXaXRoZHJhdyB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7IGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogYWRkcmVzczEgfSB9KTtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICB0eXBlOiAnZGVmaVdpdGhkcmF3JyxcbiAgICAgICAgZGVmaVBhcmFtczogeyB2YXVsdElkOiAnaHRldGgtdXNkYy10ZXN0JywgYW1vdW50OiAnMTAnIH0sXG4gICAgICAgIHdhbGxldCxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogYXdhaXQgYnVpbGREZWZpVHhIZXgoZGVmaUNhbGxkYXRhKCdyZWRlZW0odWludDI1NixhZGRyZXNzLGFkZHJlc3MpJywgWycxMCcsIGFkZHJlc3MxLCBhZGRyZXNzMV0pKSxcbiAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb246IHt9LFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdjb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzcyB2ZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBjb25zb2xpZGF0aW9uIHdoZW4gcmVjaXBpZW50IG1hdGNoZXMgYmFzZSBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcblxuICAgICAgICAvLyBCdWlsZCBhIHJlYWwgdHJhbnNhY3Rpb24gdGhhdCBzZW5kcyB0byB0aGUgYmFzZUFkZHJlc3NcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kKTtcbiAgICAgICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICAgICAgZmVlOiAnMTAnLFxuICAgICAgICAgIGdhc0xpbWl0OiAnMjEwMDAnLFxuICAgICAgICB9KTtcbiAgICAgICAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgICAgIHR4QnVpbGRlci5jb250cmFjdChiYXNlQWRkcmVzcyk7XG4gICAgICAgIHR4QnVpbGRlci52YWx1ZSgnMTAwMDAwMDAwMDAwMDAwMDAwMCcpO1xuICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBjb25zdCB0eEhleCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHR5cGU6ICdjb25zb2xpZGF0ZScsXG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2OGE3ZDVkMGM2NmU3NGUyMTZiOTcxNzNiZDU1OGM2ZCcsXG4gICAgICAgICAgdHhIZXg6IHR4SGV4LFxuICAgICAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHtcbiAgICAgICAgICBjb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzczogdHJ1ZSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IGNvbnNvbGlkYXRpb24gd2hlbiByZWNpcGllbnQgZG9lcyBub3QgbWF0Y2ggYmFzZSBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcbiAgICAgICAgY29uc3Qgd3JvbmdSZWNpcGllbnQgPSAnMHg3ZTg1YmRjMjdjMDUwZTM5MDVlYmY0YjhlNjM0ZDlhZDZlZGQwZGU2JztcblxuICAgICAgICAvLyBCdWlsZCBhIHRyYW5zYWN0aW9uIHRoYXQgc2VuZHMgdG8gYSBESUZGRVJFTlQgYWRkcmVzcyAobm90IGJhc2VBZGRyZXNzKVxuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICAgICAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLlNpbmdsZVNpZ1NlbmQpO1xuICAgICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgICBmZWU6ICcxMCcsXG4gICAgICAgICAgZ2FzTGltaXQ6ICcyMTAwMCcsXG4gICAgICAgIH0pO1xuICAgICAgICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgICAgICAgdHhCdWlsZGVyLmNvbnRyYWN0KHdyb25nUmVjaXBpZW50KTtcbiAgICAgICAgdHhCdWlsZGVyLnZhbHVlKCcxMDAwMDAwMDAwMDAwMDAwMDAwJyk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IHR4SGV4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgICAgdHlwZTogJ2NvbnNvbGlkYXRlJyxcbiAgICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgICAgY29uc29saWRhdGVJZDogJzY4YTdkNWQwYzY2ZTc0ZTIxNmI5NzE3M2JkNTU4YzZkJyxcbiAgICAgICAgICB0eEhleDogdHhIZXgsXG4gICAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge1xuICAgICAgICAgIGNvbnNvbGlkYXRpb25Ub0Jhc2VBZGRyZXNzOiB0cnVlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnQ29uc29saWRhdGlvbiB0cmFuc2FjdGlvbiByZWNpcGllbnQgZG9lcyBub3QgbWF0Y2ggd2FsbGV0IGJhc2UgYWRkcmVzcycpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eEhleCBpcyBtaXNzaW5nIGZvciBjb25zb2xpZGF0aW9uIHZlcmlmaWNhdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZSc7XG5cbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHR5cGU6ICdjb25zb2xpZGF0ZScsXG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2OGE3ZDVkMGM2NmU3NGUyMTZiOTcxNzNiZDU1OGM2ZCcsXG4gICAgICAgICAgLy8gSW50ZW50aW9uYWxseSBtaXNzaW5nIHR4SGV4XG4gICAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge1xuICAgICAgICAgIGNvbnNvbGlkYXRpb25Ub0Jhc2VBZGRyZXNzOiB0cnVlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyB0eEhleCBpbiB0eFByZWJ1aWxkJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgRVJDMjAgdG9rZW4gY29uc29saWRhdGlvbiB3aGVuIGNhbGxkYXRhIHJlY2lwaWVudCBtYXRjaGVzIGJhc2UgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZSc7XG4gICAgICAgIGNvbnN0IHRva2VuQ29udHJhY3RBZGRyZXNzID0gJzB4YTBiODY5OTFjNjIxOGIzNmMxZDE5ZDRhMmU5ZWIwY2UzNjA2ZWI0OCc7XG5cbiAgICAgICAgLy8gQnVpbGQgYW4gRVJDMjAgdHJhbnNmZXIoYWRkcmVzcywgdWludDI1NikgdHgg4oCUIG1pbWljcyB3aGF0IHRoZSBzZXJ2ZXIgcmV0dXJuc1xuICAgICAgICAvLyBmb3IgYSB2NiBUU1Mgd2FsbGV0IHRva2VuIGNvbnNvbGlkYXRpb246IHR4SnNvbi50byA9IHRva2VuIGNvbnRyYWN0LFxuICAgICAgICAvLyBhY3R1YWwgcmVjaXBpZW50IGlzIGVuY29kZWQgaW4gdGhlIDB4YTkwNTljYmIgY2FsbGRhdGFcbiAgICAgICAgY29uc3QgbWV0aG9kSWQgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgndHJhbnNmZXInLCBbJ2FkZHJlc3MnLCAndWludDI1NiddKTtcbiAgICAgICAgY29uc3QgZW5jb2RlZFBhcmFtcyA9IEV0aGVyZXVtQWJpLnJhd0VuY29kZShbJ2FkZHJlc3MnLCAndWludDI1NiddLCBbYmFzZUFkZHJlc3MsICcxMDAwMDAwMCddKTtcbiAgICAgICAgY29uc3QgZXJjMjBUcmFuc2ZlckRhdGEgPSAnMHgnICsgQnVmZmVyLmNvbmNhdChbbWV0aG9kSWQsIGVuY29kZWRQYXJhbXNdKS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICAgICAgICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAnLCBnYXNMaW1pdDogJzYwMDAwJyB9KTtcbiAgICAgICAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgICAgIHR4QnVpbGRlci5jb250cmFjdCh0b2tlbkNvbnRyYWN0QWRkcmVzcyk7XG4gICAgICAgIHR4QnVpbGRlci5kYXRhKGVyYzIwVHJhbnNmZXJEYXRhKTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgY29uc3QgdHhIZXggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3MgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHsgdHlwZTogJ2NvbnNvbGlkYXRlJywgd2FsbGV0LCB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZScgfSBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogeyBjb25zb2xpZGF0ZUlkOiAnYWJjMTIzJywgdHhIZXgsIGNvaW46ICdodGV0aCcsIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyB9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7IGNvbnNvbGlkYXRpb25Ub0Jhc2VBZGRyZXNzOiB0cnVlIH0sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IEVSQzIwIHRva2VuIGNvbnNvbGlkYXRpb24gd2hlbiBjYWxsZGF0YSByZWNpcGllbnQgZG9lcyBub3QgbWF0Y2ggYmFzZSBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcbiAgICAgICAgY29uc3Qgd3JvbmdSZWNpcGllbnQgPSAnMHg3ZTg1YmRjMjdjMDUwZTM5MDVlYmY0YjhlNjM0ZDlhZDZlZGQwZGU2JztcbiAgICAgICAgY29uc3QgdG9rZW5Db250cmFjdEFkZHJlc3MgPSAnMHhhMGI4Njk5MWM2MjE4YjM2YzFkMTlkNGEyZTllYjBjZTM2MDZlYjQ4JztcblxuICAgICAgICAvLyBCdWlsZCBhbiBFUkMyMCB0cmFuc2ZlciB3aGVyZSBjYWxsZGF0YSByZWNpcGllbnQgaXMgYSBXUk9ORyBhZGRyZXNzXG4gICAgICAgIGNvbnN0IG1ldGhvZElkID0gRXRoZXJldW1BYmkubWV0aG9kSUQoJ3RyYW5zZmVyJywgWydhZGRyZXNzJywgJ3VpbnQyNTYnXSk7XG4gICAgICAgIGNvbnN0IGVuY29kZWRQYXJhbXMgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoWydhZGRyZXNzJywgJ3VpbnQyNTYnXSwgW3dyb25nUmVjaXBpZW50LCAnMTAwMDAwMDAnXSk7XG4gICAgICAgIGNvbnN0IGVyYzIwVHJhbnNmZXJEYXRhID0gJzB4JyArIEJ1ZmZlci5jb25jYXQoW21ldGhvZElkLCBlbmNvZGVkUGFyYW1zXSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgICAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwJywgZ2FzTGltaXQ6ICc2MDAwMCcgfSk7XG4gICAgICAgIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgICB0eEJ1aWxkZXIuY29udHJhY3QodG9rZW5Db250cmFjdEFkZHJlc3MpO1xuICAgICAgICB0eEJ1aWxkZXIuZGF0YShlcmMyMFRyYW5zZmVyRGF0YSk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IHR4SGV4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICAgICAgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQYXJhbXM6IHsgdHlwZTogJ2NvbnNvbGlkYXRlJywgd2FsbGV0LCB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZScgfSBhcyBhbnksXG4gICAgICAgICAgICB0eFByZWJ1aWxkOiB7IGNvbnNvbGlkYXRlSWQ6ICdhYmMxMjMnLCB0eEhleCwgY29pbjogJ2h0ZXRoJywgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnIH0gYXMgYW55LFxuICAgICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgICAgdmVyaWZpY2F0aW9uOiB7IGNvbnNvbGlkYXRpb25Ub0Jhc2VBZGRyZXNzOiB0cnVlIH0sXG4gICAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdDb25zb2xpZGF0aW9uIHRyYW5zYWN0aW9uIHJlY2lwaWVudCBkb2VzIG5vdCBtYXRjaCB3YWxsZXQgYmFzZSBhZGRyZXNzJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIHdhbGxldCBpcyBtaXNzaW5nIGJhc2VBZGRyZXNzIGZvciBjb25zb2xpZGF0aW9uIHZlcmlmaWNhdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZSc7XG5cbiAgICAgICAgLy8gQnVpbGQgYSByZWFsIHRyYW5zYWN0aW9uXG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuU2luZ2xlU2lnU2VuZCk7XG4gICAgICAgIHR4QnVpbGRlci5mZWUoe1xuICAgICAgICAgIGZlZTogJzEwJyxcbiAgICAgICAgICBnYXNMaW1pdDogJzIxMDAwJyxcbiAgICAgICAgfSk7XG4gICAgICAgIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgICB0eEJ1aWxkZXIuY29udHJhY3QoYmFzZUFkZHJlc3MpO1xuICAgICAgICB0eEJ1aWxkZXIudmFsdWUoJzEwMDAwMDAwMDAwMDAwMDAwMDAnKTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgY29uc3QgdHhIZXggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICAgIC8vIFdhbGxldCB3aXRob3V0IGJhc2VBZGRyZXNzXG4gICAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHt9LFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgICB0eXBlOiAnY29uc29saWRhdGUnLFxuICAgICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgICBjb25zb2xpZGF0ZUlkOiAnNjhhN2Q1ZDBjNjZlNzRlMjE2Yjk3MTczYmQ1NThjNmQnLFxuICAgICAgICAgIHR4SGV4OiB0eEhleCxcbiAgICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7XG4gICAgICAgICAgY29uc29saWRhdGlvblRvQmFzZUFkZHJlc3M6IHRydWUsXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgY29pblxuICAgICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdVbmFibGUgdG8gZGV0ZXJtaW5lIGJhc2UgYWRkcmVzcyBmb3IgY29uc29saWRhdGlvbicpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdBZGRyZXNzIFZlcmlmaWNhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBkZXNjcmliZSgnaXNXYWxsZXRBZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYW4gYWRkcmVzcyBnZW5lcmF0ZWQgdXNpbmcgZm9yd2FyZGVyIHZlcnNpb24gMScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG5cbiAgICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlkOiAnNjkxZjYzOGYxZDNjOWZjZThmNWFhNjkxNTY5YTk5ZWInLFxuICAgICAgICAgICAgc291cmNlOiAndXNlcicsXG4gICAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0dWYjNQZkN6d2lFWDk0QUIxbkpRdHpWbXNhNVNyaU5yZktaWkFjQXZSZ3hoMUF1Z202czh5b0Q4Z1NrcTJGZFo4WUNkVlhVZ0xqZjlReHZkWUFKSzVVdGhBbXBRc2hVJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlkOiAnNjkxZjYzOGYwYjc0ZTczYjFmNDQwZWE0YWNlZGE4N2UnLFxuICAgICAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjRjQ2cFJIZGEzc1pidVB6emE5QTlNaXFBVTlKUm9kOGh1WXR5VjROWTJvZUpYc2lzN3IyNkwxdm1MbnRmOUJjWkplMW00Q1FOU3ZZV2Z3cGUxaFNwbzZKNHg2WUYxZU4nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgaWQ6ICc2OGI5ZWM1ODdkMGJhMWM3NDQwZGU1NTEwNjhjMzZhNycsXG4gICAgICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0d6VG41ZXlOR0RrYjE4UjQzbkg3OUhva1lMYzVQWFpNMTlWOFVyYnVMZFZSYUNRTXM0RWVDQWpucW1vWVhxZnl1c1RVNDZXb1pNRHlMcG1Uem9VWDY2WkJ3R0ZqdDFhJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHg2MDY5YTRiYWYyMzYwYmY2N2E2ZDAyYTdmYzQzZDhmMzkxMDAxNmFlJyxcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZTEyNTNiY2NlN2Q4N2RiNTIyZmJjZWVjNmU1NWM5Zjc4YzM3NmQ5ZicsXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBzYWx0OiAnMHg3JyxcbiAgICAgICAgICAgIGZvcndhcmRlclZlcnNpb246IDEsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgaW5kZXg6IDcsXG4gICAgICAgICAgd2FsbGV0VmVyc2lvbjogMSxcbiAgICAgICAgfSBhcyB1bmtub3duIGFzIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgIGNvbnN0IGlzV2FsbGV0QWRkciA9IGF3YWl0IGNvaW4uaXNXYWxsZXRBZGRyZXNzKHBhcmFtcyBhcyBhbnkpO1xuICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IGFuIGFkZHJlc3MgZ2VuZXJhdGVkIHVzaW5nIGZvcndhcmRlciB2ZXJzaW9uIDInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuXG4gICAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJzY5MWU4YzdiM2M4YWFhNzkxMTE4ZDljZTYxNmQzYjIxJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICAgICAgdHlwZTogJ2luZGVwZW5kZW50JyxcbiAgICAgICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHckN4Q1gzOXpiM1R2WWpUcWZVR3dFVVpIam5yYVJGbTFXZU13OWdmQ0Qxd3djMndVRG1CQloyVGtjY0pNd2Y1ZUJUamE4cjN6NkhNeG9UWkdXNm52eW9KTVFGc2VjdicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJzY5MWU4YzdiMTk2N2ZkNmQ5ODY3YTIyYTFhNDEzMWEwJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0dLaGRlQzRucjF0YThkMjd4VGh0ZkZGSGdieFdNclZiNTk1bWVNUzhpM2ZCTXJUejhFZFFNV0JLSEhLenhhcEdnaGVvTXltVnZSY1FtYUdEeWtSVEJidFhxYml1OXBzJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlkOiAnNjhiOWVjNTg3ZDBiYTFjNzQ0MGRlNTUxMDY4YzM2YTcnLFxuICAgICAgICAgICAgc291cmNlOiAnYml0Z28nLFxuICAgICAgICAgICAgdHlwZTogJ2luZGVwZW5kZW50JyxcbiAgICAgICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHelRuNWV5TkdEa2IxOFI0M25INzlIb2tZTGM1UFhaTTE5VjhVcmJ1TGRWUmFDUU1zNEVlQ0FqbnFtb1lYcWZ5dXNUVTQ2V29aTUR5THBtVHpvVVg2NlpCd0dGanQxYScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXTtcblxuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgYWRkcmVzczogJzB4ZjYzNmNlZGRmZmU0MWQxMDY1ODY4NzVjMGU1NmRjOGZlYjYyNjhmNycsXG4gICAgICAgICAgYmFzZUFkZHJlc3M6ICcweGRjNDg1ZGEwNzZlZDRhMmIxOTU4NGU5YTFmZGJiOTc0Zjg5YjYwZjQnLFxuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgc2FsdDogJzB4MTcnLFxuICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogMixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgICBpbmRleDogMjMsXG4gICAgICAgICAgd2FsbGV0VmVyc2lvbjogMixcbiAgICAgICAgfSBhcyB1bmtub3duIGFzIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgIGNvbnN0IGlzV2FsbGV0QWRkciA9IGF3YWl0IGNvaW4uaXNXYWxsZXRBZGRyZXNzKHBhcmFtcyBhcyBhbnkpO1xuICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgd2FsbGV0IHZlcnNpb24gNSBmb3J3YXJkZXIgdmVyc2lvbiA0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlkOiAnNjkxZTI0MmQ5M2Y4ZDdhZDA3MDU4ODc0NDk3NjNjOTYnLFxuICAgICAgICAgICAgc291cmNlOiAndXNlcicsXG4gICAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAnMDJjOGE0OTZiMTZhYmZlMjU2NzUyMGEyNzllMjE1NDY0MmZjM2MwZTA4ZTYyOTc3NWNiNGQ4NDVjMGM1ZmJmNTVhYjdiYTE1M2U4ODZkZTY1NzQ4ZWQxOGY0ZmY4ZjVjZWUyMjQyZTY4NzM5OWVhMzI5N2ExZjU1MjRmZGVmZDU2YycsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJzY5MWUyNDJkZjhiNjMyM2Q0YjA4ZGYzNjY4NjRhZjY2JyxcbiAgICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAnMDJjOGE0OTZiMTZhYmZlMjU2NzUyMGEyNzllMjE1NDY0MmZjM2MwZTA4ZTYyOTc3NWNiNGQ4NDVjMGM1ZmJmNTVhYjdiYTE1M2U4ODZkZTY1NzQ4ZWQxOGY0ZmY4ZjVjZWUyMjQyZTY4NzM5OWVhMzI5N2ExZjU1MjRmZGVmZDU2YycsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJzY5MWUyNDJjMDU5NWI0Y2ZlZTZmOTU3YzFkNjQ1OGY3JyxcbiAgICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgICAgICcwMmM4YTQ5NmIxNmFiZmUyNTY3NTIwYTI3OWUyMTU0NjQyZmMzYzBlMDhlNjI5Nzc1Y2I0ZDg0NWMwYzVmYmY1NWFiN2JhMTUzZTg4NmRlNjU3NDhlZDE4ZjRmZjhmNWNlZTIyNDJlNjg3Mzk5ZWEzMjk3YTFmNTUyNGZkZWZkNTZjJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHhkNjNiNWUyYjhkMWI0ZmJhMzYyNTQ2MDUwODkwMGJmMmEwNDk5YTRkJyxcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZjFlM2QzMDc5OGFjZGYzYTEyZmE1YmViNWZhZDhlZmIyM2Q1YmUxMScsXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBzYWx0OiAnMHg3NScsXG4gICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiA0LFxuICAgICAgICAgICAgZmVlQWRkcmVzczogJzB4YjFlNzI1MTg2OTkwYjg2Y2E4ZWZlZDA4YTNjY2RhOWM5ZjQwMGYwOScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgaW5kZXg6IDExNyxcbiAgICAgICAgICB3YWxsZXRWZXJzaW9uOiA1LFxuICAgICAgICB9IGFzIHVua25vd24gYXMgVHNzVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgY29uc3QgaXNXYWxsZXRBZGRyID0gYXdhaXQgY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKTtcbiAgICAgICAgaXNXYWxsZXRBZGRyLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIHdhbGxldCB2ZXJzaW9uIDYgZm9yd2FyZGVyIHZlcnNpb24gNScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJzY5MWY2MzBlMGM1NjA5ODI4OGE5YjdmYTEwN2RiMTQ0JyxcbiAgICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgJzAzM2IwMmFhYzRmMDM4ZmVmNTExODM1MGI3N2QzMDJlYzYyMDI5MzFjYTJlNzEyMmFhZDg4OTk0ZmZlZmNiYzcwYTYwNjllNjYyNDM2MjM2YWJiMTYxOTE5NTIzMmM0MTU4MDIwNGNiMjAyYzIyMzU3ZWQ4ZjUzZTY5ZWFjNWM2OWUnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgaWQ6ICc2OTFmNjMwZjFkM2M5ZmNlOGY1YTczMGJmZjgyNmNmOScsXG4gICAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgJzAzM2IwMmFhYzRmMDM4ZmVmNTExODM1MGI3N2QzMDJlYzYyMDI5MzFjYTJlNzEyMmFhZDg4OTk0ZmZlZmNiYzcwYTYwNjllNjYyNDM2MjM2YWJiMTYxOTE5NTIzMmM0MTU4MDIwNGNiMjAyYzIyMzU3ZWQ4ZjUzZTY5ZWFjNWM2OWUnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgaWQ6ICc2OTFmNjMwZDU2NzM1ZTVlYjYxYjA2ZTM1M2ZlNzYzOScsXG4gICAgICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXTtcblxuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgYWRkcmVzczogJzB4YTMzZjA5NzVmNTNjZGNmY2MwY2I1NjRkMjVmYjViZTAzYjA2NTFjZicsXG4gICAgICAgICAgYmFzZUFkZHJlc3M6ICcweGMwMTIwNDFkYWMxNDNhNTlmYTQ5MWRiM2EyYjY3YjY5YmQ3OGI2ODUnLFxuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogNSxcbiAgICAgICAgICAgIGZlZUFkZHJlc3M6ICcweGIxZTcyNTE4Njk5MGI4NmNhOGVmZWQwOGEzY2NkYTljOWY0MDBmMDknLFxuICAgICAgICAgIH0sXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIGluZGV4OiA3LFxuICAgICAgICAgIHdhbGxldFZlcnNpb246IDYsXG4gICAgICAgIH0gYXMgdW5rbm93biBhcyBUc3NWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucztcblxuICAgICAgICBjb25zdCBpc1dhbGxldEFkZHIgPSBhd2FpdCBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpO1xuICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gYWN0dWFsIGFkZHJlc3MgZGlmZmVycyBmcm9tIGV4cGVjdGVkIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHgyODkwNDU5MWY3MzU5OTRmMDUwODA0ZmRhM2I2MWI4MTNiMTZlMDRjJyxcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZGYwNzExNzcwNWE5ZjhkYzRjMmE3OGRlNjZiN2YxNzk3ZGJhOWQ0ZScsXG4gICAgICAgICAgd2FsbGV0VmVyc2lvbjogMSxcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgIHNhbHQ6ICcweGM1YScsXG4gICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiAxLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0gYXMgdW5rbm93biBhcyBWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucztcblxuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpLCBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHJlamVjdCBpZiBjb2luU3BlY2lmaWMgZmllbGQgaXMgbm90IGFuIG9iamVjdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHhiMGI1NmVlYWUxYjI4MzkxOGNhY2EwMmExNGFkYTJkZjE3YTk4ZTZkJyxcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZGYwNzExNzcwNWE5ZjhkYzRjMmE3OGRlNjZiN2YxNzk3ZGJhOWQ0ZScsXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4gY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zIGFzIGFueSksXG4gICAgICAgICAgSW52YWxpZEFkZHJlc3NWZXJpZmljYXRpb25PYmplY3RQcm9wZXJ0eUVycm9yXG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZWplY3QgaWYgdGhlIGRlcml2ZWQgYWRkcmVzcyBpcyBpbiBpbnZhbGlkIGZvcm1hdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHhlMGI1NmVlYWUxYjI4MzkxOGNhY2EwMmExNGFkYTJkZjE3YTk4YnZmJyxcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZGYwNzExNzcwNWE5ZjhkYzRjMmE3OGRlNjZiN2YxNzk3ZGJhOWQ0ZScsXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBzYWx0OiAnMHhjNWEnLFxuICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9IGFzIHVua25vd24gYXMgVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4gY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKSwgSW52YWxpZEFkZHJlc3NFcnJvcik7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZWplY3QgaWYgYmFzZSBhZGRyZXNzIGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHhiMGI1NmVlYWUxYjI4MzkxOGNhY2EwMmExNGFkYTJkZjE3YTk4ZTZkJyxcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgIHNhbHQ6ICcweGM1YScsXG4gICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiAxLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4gY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zIGFzIGFueSksIEludmFsaWRBZGRyZXNzRXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IGlmIGJhc2UgYWRkcmVzcyBpcyBpbiBpbnZhbGlkIGZvcm1hdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHhiMGI1NmVlYWUxYjI4MzkxOGNhY2EwMmExNGFkYTJkZjE3YTk4ZTZkJyxcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZTBiNTZlZWFlMWIyODM5MThjYWNhMDJhMTRhZGEyZGYxN2E5OGJ2ZicsXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBzYWx0OiAnMHhjNWEnLFxuICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9IGFzIHVua25vd24gYXMgVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4gY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKSwgSW52YWxpZEFkZHJlc3NFcnJvcik7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ01QQyB3YWxsZXQgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjb21tb25LZXljaGFpbiA9XG4gICAgICAgICAgJzAzZjljMmZiMmU1YThiNzhhNDRmNWQxZTRmOTA2ZjhlM2Q3YTBlNmI1YzRkM2UyZjFhMGI5YzhkN2U2ZjVhNGIzYzJkMWUwZjllOGQ3YzZiNWE0JyArXG4gICAgICAgICAgJzkzODI3MTYwNTk0ODU3NDYzNzI4MTkwYTBiMGMwZDBlMGYxMDExMTIxMzE0MTUxNjE3MTgxOTFhMWIxYzFkMWUxZic7XG4gICAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAgICB7IHB1YjogJ3VzZXJfcHViJywgY29tbW9uS2V5Y2hhaW4gfSxcbiAgICAgICAgICB7IHB1YjogJ2JhY2t1cF9wdWInLCBjb21tb25LZXljaGFpbiB9LFxuICAgICAgICAgIHsgcHViOiAnYml0Z29fcHViJywgY29tbW9uS2V5Y2hhaW4gfSxcbiAgICAgICAgXTtcblxuICAgICAgICBpdCgnc2hvdWxkIHZlcmlmeSBhbiBNUEMgd2FsbGV0IGFkZHJlc3Mgd2l0aCBmb3J3YXJkZXIgdmVyc2lvbiAzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcblxuICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICcweDAxMTUzZjNhZGZlNDU0YTcyNTg5Y2E5ZWY3NGYwMTNjMTllNTQ5NjEnLFxuICAgICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICAgIGZvcndhcmRlclZlcnNpb246IDMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICB3YWxsZXRWZXJzaW9uOiAzLFxuICAgICAgICAgIH0gYXMgdW5rbm93biBhcyBUc3NWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucztcblxuICAgICAgICAgIGNvbnN0IGlzV2FsbGV0QWRkciA9IGF3YWl0IGNvaW4uaXNXYWxsZXRBZGRyZXNzKHBhcmFtcyk7XG4gICAgICAgICAgaXNXYWxsZXRBZGRyLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYW4gTVBDIHdhbGxldCBhZGRyZXNzIHdpdGggZm9yd2FyZGVyIHZlcnNpb24gNScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG5cbiAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnMHgwMTE1M2YzYWRmZTQ1NGE3MjU4OWNhOWVmNzRmMDEzYzE5ZTU0OTYxJyxcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiA1LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgICAgd2FsbGV0VmVyc2lvbjogNixcbiAgICAgICAgICB9IGFzIHVua25vd24gYXMgVHNzVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgICBjb25zdCBpc1dhbGxldEFkZHIgPSBhd2FpdCBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpO1xuICAgICAgICAgIGlzV2FsbGV0QWRkci5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgcmVqZWN0IE1QQyB3YWxsZXQgYWRkcmVzcyB3aXRoIHdyb25nIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuXG4gICAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgYWRkcmVzczogJzB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMScsXG4gICAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZGYwNzExNzcwNWE5ZjhkYzRjMmE3OGRlNjZiN2YxNzk3ZGJhOWQ0ZScsXG4gICAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogMyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDMsXG4gICAgICAgICAgfSBhcyB1bmtub3duIGFzIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgICAgY29uc3QgaXNXYWxsZXRBZGRyID0gYXdhaXQgY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKTtcbiAgICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCByZWplY3QgTVBDIHdhbGxldCBhZGRyZXNzIHdpdGggaW52YWxpZCBhZGRyZXNzIGZvcm1hdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG5cbiAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnMHhpbnZhbGlkJyxcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHhkZjA3MTE3NzA1YTlmOGRjNGMyYTc4ZGU2NmI3ZjE3OTdkYmE5ZDRlJyxcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiAzLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgICAgd2FsbGV0VmVyc2lvbjogMyxcbiAgICAgICAgICB9IGFzIHVua25vd24gYXMgVHNzVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpLCBJbnZhbGlkQWRkcmVzc0Vycm9yKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCByZWplY3QgaWYga2V5Y2hhaW5zIGFyZSBtaXNzaW5nIGZvciBNUEMgd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcblxuICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICcweDllN2NlOGMyNGQ5Zjc2YTgxNGUyMzYzM2U2MWJlN2NiOGU2ZTJkNWUnLFxuICAgICAgICAgICAgYmFzZUFkZHJlc3M6ICcweGRmMDcxMTc3MDVhOWY4ZGM0YzJhNzhkZTY2YjdmMTc5N2RiYTlkNGUnLFxuICAgICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICAgIGZvcndhcmRlclZlcnNpb246IDMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICB3YWxsZXRWZXJzaW9uOiAzLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMgYXMgYW55KSwgRXJyb3IpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIHJlamVjdCBpZiBjb21tb25LZXljaGFpbiBpcyBtaXNzaW5nIGZvciBNUEMgd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcblxuICAgICAgICAgIGNvbnN0IGludmFsaWRLZXljaGFpbnMgPSBbeyBwdWI6ICd1c2VyX3B1YicgfSwgeyBwdWI6ICdiYWNrdXBfcHViJyB9LCB7IHB1YjogJ2JpdGdvX3B1YicgfV07XG5cbiAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnMHg5ZTdjZThjMjRkOWY3NmE4MTRlMjM2MzNlNjFiZTdjYjhlNmUyZDVlJyxcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHhkZjA3MTE3NzA1YTlmOGRjNGMyYTc4ZGU2NmI3ZjE3OTdkYmE5ZDRlJyxcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiAzLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGtleWNoYWluczogaW52YWxpZEtleWNoYWlucyxcbiAgICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgICAgd2FsbGV0VmVyc2lvbjogMyxcbiAgICAgICAgICB9IGFzIHVua25vd24gYXMgVHNzVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpLCBFcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCdkZXJpdmVBZGRyZXNzIChNUEMpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBTYW1lIHZlY3RvciBhcyB0aGUgTVBDIGlzV2FsbGV0QWRkcmVzcyB0ZXN0cyBhYm92ZTpcbiAgICAgICAgLy8gY29tbW9uS2V5Y2hhaW4gQCBpbmRleCAwIC0+IDB4MDExNTNmM2FkZmU0NTRhNzI1ODljYTllZjc0ZjAxM2MxOWU1NDk2MVxuICAgICAgICBjb25zdCBjb21tb25LZXljaGFpbiA9XG4gICAgICAgICAgJzAzZjljMmZiMmU1YThiNzhhNDRmNWQxZTRmOTA2ZjhlM2Q3YTBlNmI1YzRkM2UyZjFhMGI5YzhkN2U2ZjVhNGIzYzJkMWUwZjllOGQ3YzZiNWE0JyArXG4gICAgICAgICAgJzkzODI3MTYwNTk0ODU3NDYzNzI4MTkwYTBiMGMwZDBlMGYxMDExMTIxMzE0MTUxNjE3MTgxOTFhMWIxYzFkMWUxZic7XG4gICAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAgICB7IHB1YjogJ3VzZXJfcHViJywgY29tbW9uS2V5Y2hhaW4gfSxcbiAgICAgICAgICB7IHB1YjogJ2JhY2t1cF9wdWInLCBjb21tb25LZXljaGFpbiB9LFxuICAgICAgICAgIHsgcHViOiAnYml0Z29fcHViJywgY29tbW9uS2V5Y2hhaW4gfSxcbiAgICAgICAgXTtcblxuICAgICAgICBpdCgnc2hvdWxkIGRlcml2ZSB0aGUgZXhwZWN0ZWQgTVBDIGFkZHJlc3MgZm9yIGEgY29tbW9uS2V5Y2hhaW4gYXQgaW5kZXggMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi5kZXJpdmVBZGRyZXNzKHsga2V5Y2hhaW5zLCBpbmRleDogMCwgd2FsbGV0VmVyc2lvbjogMyB9KTtcbiAgICAgICAgICByZXN1bHQuYWRkcmVzcy5zaG91bGQuZXF1YWwoJzB4MDExNTNmM2FkZmU0NTRhNzI1ODljYTllZjc0ZjAxM2MxOWU1NDk2MScpO1xuICAgICAgICAgIHJlc3VsdC5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5kZXJpdmF0aW9uUGF0aCwgJ20vMCcpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgncm91bmQtdHJpcHMgd2l0aCBpc1dhbGxldEFkZHJlc3MgKGRlcml2ZWQgYWRkcmVzcyB2ZXJpZmllcyBhcyB0cnVlKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgICAgICAgY29uc3QgZGVyaXZlZCA9IGF3YWl0IGNvaW4uZGVyaXZlQWRkcmVzcyh7IGtleWNoYWlucywgaW5kZXg6IDMsIHdhbGxldFZlcnNpb246IDYgfSk7XG4gICAgICAgICAgY29uc3QgdmVyaWZpZWQgPSBhd2FpdCBjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgICBhZGRyZXNzOiBkZXJpdmVkLmFkZHJlc3MsXG4gICAgICAgICAgICBjb2luU3BlY2lmaWM6IHsgZm9yd2FyZGVyVmVyc2lvbjogNSB9LFxuICAgICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgICAgaW5kZXg6IDMsXG4gICAgICAgICAgICB3YWxsZXRWZXJzaW9uOiA2LFxuICAgICAgICAgIH0gYXMgdW5rbm93biBhcyBUc3NWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucyk7XG4gICAgICAgICAgdmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gbmVpdGhlciBNUEMgbm9yIGZvcndhcmRlciBpbnB1dHMgYXJlIHByb3ZpZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJykgYXMgVGV0aDtcbiAgICAgICAgICAvLyB3YWxsZXRWZXJzaW9uIDEgd2l0aCBubyBjb2luU3BlY2lmaWMuZm9yd2FyZGVyVmVyc2lvbiBhbmQgbm8gYmFzZUFkZHJlc3MgaXMgYW1iaWd1b3VzXG4gICAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgICBhc3luYyAoKSA9PiBjb2luLmRlcml2ZUFkZHJlc3MoeyBrZXljaGFpbnMsIGluZGV4OiAwLCB3YWxsZXRWZXJzaW9uOiAxIH0pLFxuICAgICAgICAgICAgL2NvdWxkIG5vdCBkZXRlcm1pbmUgYW4gRVRIIGRlcml2YXRpb24gc3RyYXRlZ3kvXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBrZXljaGFpbnMgYXJlIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgICAgYXN5bmMgKCkgPT4gY29pbi5kZXJpdmVBZGRyZXNzKHsga2V5Y2hhaW5zOiBbXSwgaW5kZXg6IDAsIHdhbGxldFZlcnNpb246IDMgfSksXG4gICAgICAgICAgICAva2V5Y2hhaW5zL1xuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCdkZXJpdmVBZGRyZXNzIChmb3J3YXJkZXIpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBTYW1lIHZlY3RvcnMgYXMgdGhlIGZvcndhcmRlciBpc1dhbGxldEFkZHJlc3MgdGVzdHMgYWJvdmUgKGNvaW46IGh0ZXRoKS5cbiAgICAgICAgLy8gc2FsdCA9PSBpbmRleCBmb3IgQml0R28gZm9yd2FyZGVycywgc28gZGVyaXZpbmcgYnkgaW5kZXggcmVwcm9kdWNlcyB0aGUgYWRkcmVzcy5cbiAgICAgICAgaXQoJ2Rlcml2ZXMgdGhlIGV4YWN0IHYxIGZvcndhcmRlciBhZGRyZXNzIGFuZCByb3VuZC10cmlwcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweGUxMjUzYmNjZTdkODdkYjUyMmZiY2VlYzZlNTVjOWY3OGMzNzZkOWYnO1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4uZGVyaXZlQWRkcmVzcyh7XG4gICAgICAgICAgICBiYXNlQWRkcmVzcyxcbiAgICAgICAgICAgIGluZGV4OiA3LFxuICAgICAgICAgICAgd2FsbGV0VmVyc2lvbjogMSxcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzogeyBmb3J3YXJkZXJWZXJzaW9uOiAxIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmVzdWx0LmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcweDYwNjlhNGJhZjIzNjBiZjY3YTZkMDJhN2ZjNDNkOGYzOTEwMDE2YWUnKTtcblxuICAgICAgICAgIGNvbnN0IHZlcmlmaWVkID0gYXdhaXQgY29pbi5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICAgICAgYWRkcmVzczogcmVzdWx0LmFkZHJlc3MsXG4gICAgICAgICAgICBiYXNlQWRkcmVzcyxcbiAgICAgICAgICAgIGluZGV4OiA3LFxuICAgICAgICAgICAgd2FsbGV0VmVyc2lvbjogMSxcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzogeyBzYWx0OiAnMHg3JywgZm9yd2FyZGVyVmVyc2lvbjogMSB9LFxuICAgICAgICAgIH0gYXMgdW5rbm93biBhcyBUc3NWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucyk7XG4gICAgICAgICAgdmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnZGVyaXZlcyB0aGUgZXhhY3QgdjIgZm9yd2FyZGVyIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi5kZXJpdmVBZGRyZXNzKHtcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHhkYzQ4NWRhMDc2ZWQ0YTJiMTk1ODRlOWExZmRiYjk3NGY4OWI2MGY0JyxcbiAgICAgICAgICAgIGluZGV4OiAyMyxcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDIsXG4gICAgICAgICAgICBjb2luU3BlY2lmaWM6IHsgZm9yd2FyZGVyVmVyc2lvbjogMiB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJlc3VsdC5hZGRyZXNzLnNob3VsZC5lcXVhbCgnMHhmNjM2Y2VkZGZmZTQxZDEwNjU4Njg3NWMwZTU2ZGM4ZmViNjI2OGY3Jyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdkZXJpdmVzIHRoZSBleGFjdCB2NCBmb3J3YXJkZXIgYWRkcmVzcyAod2FsbGV0IHY1LCBuZWVkcyBmZWVBZGRyZXNzKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLmRlcml2ZUFkZHJlc3Moe1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6ICcweGYxZTNkMzA3OThhY2RmM2ExMmZhNWJlYjVmYWQ4ZWZiMjNkNWJlMTEnLFxuICAgICAgICAgICAgaW5kZXg6IDExNyxcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDUsXG4gICAgICAgICAgICBjb2luU3BlY2lmaWM6IHsgZm9yd2FyZGVyVmVyc2lvbjogNCwgZmVlQWRkcmVzczogJzB4YjFlNzI1MTg2OTkwYjg2Y2E4ZWZlZDA4YTNjY2RhOWM5ZjQwMGYwOScgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXN1bHQuYWRkcmVzcy5zaG91bGQuZXF1YWwoJzB4ZDYzYjVlMmI4ZDFiNGZiYTM2MjU0NjA1MDg5MDBiZjJhMDQ5OWE0ZCcpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgndGhyb3dzIGlmIGJhc2VBZGRyZXNzIGlzIG1pc3NpbmcgZm9yIGEgZm9yd2FyZGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgICAgYXN5bmMgKCkgPT4gY29pbi5kZXJpdmVBZGRyZXNzKHsgaW5kZXg6IDcsIHdhbGxldFZlcnNpb246IDEsIGNvaW5TcGVjaWZpYzogeyBmb3J3YXJkZXJWZXJzaW9uOiAxIH0gfSksXG4gICAgICAgICAgICAvYmFzZUFkZHJlc3MgaXMgcmVxdWlyZWQvXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Rocm93cyBpZiBmZWVBZGRyZXNzIGlzIG1pc3NpbmcgZm9yIGEgdjQgZm9yd2FyZGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgICAgYXN5bmMgKCkgPT5cbiAgICAgICAgICAgICAgY29pbi5kZXJpdmVBZGRyZXNzKHtcbiAgICAgICAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZjFlM2QzMDc5OGFjZGYzYTEyZmE1YmViNWZhZDhlZmIyM2Q1YmUxMScsXG4gICAgICAgICAgICAgICAgaW5kZXg6IDExNyxcbiAgICAgICAgICAgICAgICB3YWxsZXRWZXJzaW9uOiA1LFxuICAgICAgICAgICAgICAgIGNvaW5TcGVjaWZpYzogeyBmb3J3YXJkZXJWZXJzaW9uOiA0IH0sXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgL2ZlZUFkZHJlc3MgaXMgcmVxdWlyZWQvXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Rocm93cyBmb3IgZm9yd2FyZGVyIHZlcnNpb24gMCAobm90IGRlcml2YWJsZSknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgICBhc3luYyAoKSA9PlxuICAgICAgICAgICAgICBjb2luLmRlcml2ZUFkZHJlc3Moe1xuICAgICAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHhlMTI1M2JjY2U3ZDg3ZGI1MjJmYmNlZWM2ZTU1YzlmNzhjMzc2ZDlmJyxcbiAgICAgICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgICAgICB3YWxsZXRWZXJzaW9uOiAxLFxuICAgICAgICAgICAgICAgIGNvaW5TcGVjaWZpYzogeyBmb3J3YXJkZXJWZXJzaW9uOiAwIH0sXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgL3ZlcnNpb24gMCBhZGRyZXNzZXMgY2Fubm90IGJlIGRlcml2ZWQvXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ0Jhc2UgQWRkcmVzcyBWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IGJhc2UgYWRkcmVzcyBmb3Igd2FsbGV0IHZlcnNpb24gNiAoVFNTKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcblxuICAgICAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6ICc2OTFmNjMwZTBjNTYwOTgyODhhOWI3ZmExMDdkYjE0NCcsXG4gICAgICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgICAgICAgJzAzM2IwMmFhYzRmMDM4ZmVmNTExODM1MGI3N2QzMDJlYzYyMDI5MzFjYTJlNzEyMmFhZDg4OTk0ZmZlZmNiYzcwYTYwNjllNjYyNDM2MjM2YWJiMTYxOTE5NTIzMmM0MTU4MDIwNGNiMjAyYzIyMzU3ZWQ4ZjUzZTY5ZWFjNWM2OWUnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6ICc2OTFmNjMwZjFkM2M5ZmNlOGY1YTczMGJmZjgyNmNmOScsXG4gICAgICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogJzY5MWY2MzBkNTY3MzVlNWViNjFiMDZlMzUzZmU3NjM5JyxcbiAgICAgICAgICAgICAgc291cmNlOiAnYml0Z28nLFxuICAgICAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgICAgICAgJzAzM2IwMmFhYzRmMDM4ZmVmNTExODM1MGI3N2QzMDJlYzYyMDI5MzFjYTJlNzEyMmFhZDg4OTk0ZmZlZmNiYzcwYTYwNjllNjYyNDM2MjM2YWJiMTYxOTE5NTIzMmM0MTU4MDIwNGNiMjAyYzIyMzU3ZWQ4ZjUzZTY5ZWFjNWM2OWUnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdO1xuXG4gICAgICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHhjMDEyMDQxZGFjMTQzYTU5ZmE0OTFkYjNhMmI2N2I2OWJkNzhiNjg1JztcblxuICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICAgIHNhbHQ6ICcweDAnLFxuICAgICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiA1LFxuICAgICAgICAgICAgICBmZWVBZGRyZXNzOiAnMHhiMWU3MjUxODY5OTBiODZjYThlZmVkMDhhM2NjZGE5YzlmNDAwZjA5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDYsXG4gICAgICAgICAgfSBhcyB1bmtub3duIGFzIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgICAgY29uc3QgaXNXYWxsZXRBZGRyID0gYXdhaXQgY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKTtcbiAgICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIHZlcmlmeSBiYXNlIGFkZHJlc3MgZm9yIHdhbGxldCB2ZXJzaW9uIDUgKFRTUyknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG5cbiAgICAgICAgICBjb25zdCBrZXljaGFpbnMgPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjkxZTI0MmQ5M2Y4ZDdhZDA3MDU4ODc0NDk3NjNjOTYnLFxuICAgICAgICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAgICcwMmM4YTQ5NmIxNmFiZmUyNTY3NTIwYTI3OWUyMTU0NjQyZmMzYzBlMDhlNjI5Nzc1Y2I0ZDg0NWMwYzVmYmY1NWFiN2JhMTUzZTg4NmRlNjU3NDhlZDE4ZjRmZjhmNWNlZTIyNDJlNjg3Mzk5ZWEzMjk3YTFmNTUyNGZkZWZkNTZjJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjkxZTI0MmRmOGI2MzIzZDRiMDhkZjM2Njg2NGFmNjYnLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgICAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgICAgICAgJzAyYzhhNDk2YjE2YWJmZTI1Njc1MjBhMjc5ZTIxNTQ2NDJmYzNjMGUwOGU2Mjk3NzVjYjRkODQ1YzBjNWZiZjU1YWI3YmExNTNlODg2ZGU2NTc0OGVkMThmNGZmOGY1Y2VlMjI0MmU2ODczOTllYTMyOTdhMWY1NTI0ZmRlZmQ1NmMnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6ICc2OTFlMjQyYzA1OTViNGNmZWU2Zjk1N2MxZDY0NThmNycsXG4gICAgICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAgICcwMmM4YTQ5NmIxNmFiZmUyNTY3NTIwYTI3OWUyMTU0NjQyZmMzYzBlMDhlNjI5Nzc1Y2I0ZDg0NWMwYzVmYmY1NWFiN2JhMTUzZTg4NmRlNjU3NDhlZDE4ZjRmZjhmNWNlZTIyNDJlNjg3Mzk5ZWEzMjk3YTFmNTUyNGZkZWZkNTZjJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXTtcblxuICAgICAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzB4ZjFlM2QzMDc5OGFjZGYzYTEyZmE1YmViNWZhZDhlZmIyM2Q1YmUxMSc7XG5cbiAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiBiYXNlQWRkcmVzcyxcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiBiYXNlQWRkcmVzcyxcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICBzYWx0OiAnMHgwJyxcbiAgICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogNCxcbiAgICAgICAgICAgICAgZmVlQWRkcmVzczogJzB4YjFlNzI1MTg2OTkwYjg2Y2E4ZWZlZDA4YTNjY2RhOWM5ZjQwMGYwOScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICB3YWxsZXRWZXJzaW9uOiA1LFxuICAgICAgICAgIH0gYXMgdW5rbm93biBhcyBUc3NWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucztcblxuICAgICAgICAgIGNvbnN0IGlzV2FsbGV0QWRkciA9IGF3YWl0IGNvaW4uaXNXYWxsZXRBZGRyZXNzKHBhcmFtcyk7XG4gICAgICAgICAgaXNXYWxsZXRBZGRyLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCByZWplY3QgYmFzZSBhZGRyZXNzIHZlcmlmaWNhdGlvbiB3aXRoIG5vbi16ZXJvIGluZGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuXG4gICAgICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogJzY5MWY2MzBlMGM1NjA5ODI4OGE5YjdmYTEwN2RiMTQ0JyxcbiAgICAgICAgICAgICAgc291cmNlOiAndXNlcicsXG4gICAgICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogJzY5MWY2MzBmMWQzYzlmY2U4ZjVhNzMwYmZmODI2Y2Y5JyxcbiAgICAgICAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAgICcwMzNiMDJhYWM0ZjAzOGZlZjUxMTgzNTBiNzdkMzAyZWM2MjAyOTMxY2EyZTcxMjJhYWQ4ODk5NGZmZWZjYmM3MGE2MDY5ZTY2MjQzNjIzNmFiYjE2MTkxOTUyMzJjNDE1ODAyMDRjYjIwMmMyMjM1N2VkOGY1M2U2OWVhYzVjNjllJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjkxZjYzMGQ1NjczNWU1ZWI2MWIwNmUzNTNmZTc2MzknLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF07XG5cbiAgICAgICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweGMwMTIwNDFkYWMxNDNhNTlmYTQ5MWRiM2EyYjY3YjY5YmQ3OGI2ODUnO1xuXG4gICAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgYWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgICAgc2FsdDogJzB4MCcsXG4gICAgICAgICAgICAgIGZvcndhcmRlclZlcnNpb246IDUsXG4gICAgICAgICAgICAgIGZlZUFkZHJlc3M6ICcweGIxZTcyNTE4Njk5MGI4NmNhOGVmZWQwOGEzY2NkYTljOWY0MDBmMDknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgICAgIGluZGV4OiA1LCAvLyBXcm9uZyBpbmRleCAtIHNob3VsZCBiZSAwIGZvciBiYXNlIGFkZHJlc3NcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDYsXG4gICAgICAgICAgfSBhcyB1bmtub3duIGFzIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgICBhc3luYyAoKSA9PiBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpLFxuICAgICAgICAgICAgL0Jhc2UgYWRkcmVzcyB2ZXJpZmljYXRpb24gcmVxdWlyZXMgaW5kZXggMCwgYnV0IGdvdCBpbmRleCA1L1xuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgcmVqZWN0IGJhc2UgYWRkcmVzcyB2ZXJpZmljYXRpb24gd2l0aCB3cm9uZyBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuXG4gICAgICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogJzY5MWY2MzBlMGM1NjA5ODI4OGE5YjdmYTEwN2RiMTQ0JyxcbiAgICAgICAgICAgICAgc291cmNlOiAndXNlcicsXG4gICAgICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogJzY5MWY2MzBmMWQzYzlmY2U4ZjVhNzMwYmZmODI2Y2Y5JyxcbiAgICAgICAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgICAgICcwMzNiMDJhYWM0ZjAzOGZlZjUxMTgzNTBiNzdkMzAyZWM2MjAyOTMxY2EyZTcxMjJhYWQ4ODk5NGZmZWZjYmM3MGE2MDY5ZTY2MjQzNjIzNmFiYjE2MTkxOTUyMzJjNDE1ODAyMDRjYjIwMmMyMjM1N2VkOGY1M2U2OWVhYzVjNjllJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjkxZjYzMGQ1NjczNWU1ZWI2MWIwNmUzNTNmZTc2MzknLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF07XG5cbiAgICAgICAgICBjb25zdCB3cm9uZ0FkZHJlc3MgPSAnMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxJztcbiAgICAgICAgICBjb25zdCBhY3R1YWxCYXNlQWRkcmVzcyA9ICcweGMwMTIwNDFkYWMxNDNhNTlmYTQ5MWRiM2EyYjY3YjY5YmQ3OGI2ODUnO1xuXG4gICAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgYWRkcmVzczogd3JvbmdBZGRyZXNzLFxuICAgICAgICAgICAgYmFzZUFkZHJlc3M6IGFjdHVhbEJhc2VBZGRyZXNzLFxuICAgICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICAgIHNhbHQ6ICcweDAnLFxuICAgICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiA1LFxuICAgICAgICAgICAgICBmZWVBZGRyZXNzOiAnMHhiMWU3MjUxODY5OTBiODZjYThlZmVkMDhhM2NjZGE5YzlmNDAwZjA5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDYsXG4gICAgICAgICAgfSBhcyB1bmtub3duIGFzIFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgICAgY29uc3QgaXNXYWxsZXRBZGRyID0gYXdhaXQgY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKTtcbiAgICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYmFzZSBhZGRyZXNzIGZvciB3YWxsZXQgdmVyc2lvbiAyIChCSVAzMikgdXNpbmcgd2FsbGV0IGZhY3RvcnknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG5cbiAgICAgICAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcweGRjNDg1ZGEwNzZlZDRhMmIxOTU4NGU5YTFmZGJiOTc0Zjg5YjYwZjQnO1xuICAgICAgICAgIGNvbnN0IHdhbGxldFNhbHQgPSAnMHgyJztcblxuICAgICAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6ICc2OTFlOGM3YjNjOGFhYTc5MTExOGQ5Y2U2MTZkM2IyMScsXG4gICAgICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgICAgICBldGhBZGRyZXNzOiAnMHg5ZDE2YmI4NjdiNzkyYzVlM2JmNjM2YTAyNzVmMmRiODYwMWJkN2Q0JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjkxZThjN2IxOTY3ZmQ2ZDk4NjdhMjJhMWE0MTMxYTAnLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgICAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgICAgICBldGhBZGRyZXNzOiAnMHgyZGZjZTVjZmViNWMwM2ZiZTY4MGNkMzlhYzBkMmIyNTM5OWI3ZDIyJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjhiOWVjNTg3ZDBiYTFjNzQ0MGRlNTUxMDY4YzM2YTcnLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICAgICAgICAgIGV0aEFkZHJlc3M6ICcweGIxZTcyNTE4Njk5MGI4NmNhOGVmZWQwOGEzY2NkYTljOWY0MDBmMDknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdO1xuXG4gICAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgYWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgICAgICBiYXNlQWRkcmVzczogYmFzZUFkZHJlc3MsXG4gICAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgICAgc2FsdDogd2FsbGV0U2FsdCxcbiAgICAgICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogMixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBrZXljaGFpbnM6IGtleWNoYWlucyxcbiAgICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgICAgd2FsbGV0VmVyc2lvbjogMixcbiAgICAgICAgICB9IGFzIHVua25vd24gYXMgVmVyaWZ5RXRoQWRkcmVzc09wdGlvbnM7XG5cbiAgICAgICAgICBjb25zdCBpc1dhbGxldEFkZHIgPSBhd2FpdCBjb2luLmlzV2FsbGV0QWRkcmVzcyhwYXJhbXMpO1xuICAgICAgICAgIGlzV2FsbGV0QWRkci5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IGJhc2UgYWRkcmVzcyBmb3Igd2FsbGV0IHZlcnNpb24gMSAoQklQMzIpIHVzaW5nIHdhbGxldCBmYWN0b3J5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuXG4gICAgICAgICAgY29uc3QgYmFzZUFkZHJlc3MgPSAnMHhlMTI1M2JjY2U3ZDg3ZGI1MjJmYmNlZWM2ZTU1YzlmNzhjMzc2ZDlmJztcbiAgICAgICAgICBjb25zdCB3YWxsZXRTYWx0ID0gJzB4NSc7XG5cbiAgICAgICAgICBjb25zdCBrZXljaGFpbnMgPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjkxZjYzOGYxZDNjOWZjZThmNWFhNjkxNTY5YTk5ZWInLFxuICAgICAgICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgICAgICAgICAgdHlwZTogJ2luZGVwZW5kZW50JyxcbiAgICAgICAgICAgICAgZXRoQWRkcmVzczogJzB4ZjQ1ZGFkY2U3NTFhMzE3OTU3ZjJhMjQ3ZmYzN2NiNzY0Yjk3NjIwZCcsXG4gICAgICAgICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHVmIzUGZDendpRVg5NEFCMW5KUXR6Vm0uLi4nLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6ICc2OTFmNjM4ZjBiNzRlNzNiMWY0NDBlYTRhY2VkYTg3ZScsXG4gICAgICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICAgICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICAgICAgICAgIGV0aEFkZHJlc3M6ICcweDViZGYzYWUxZDJjMmZhZGVlYjcwYTQ1ODcyYmY0ZjQyNTIzMTJiNTUnLFxuICAgICAgICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjRjQ2cFJIZGEzc1pidVB6emE5QTlNaXFBLi4uJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiAnNjhiOWVjNTg3ZDBiYTFjNzQ0MGRlNTUxMDY4YzM2YTcnLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICAgICAgICAgIGV0aEFkZHJlc3M6ICcweGIxZTcyNTE4Njk5MGI4NmNhOGVmZWQwOGEzY2NkYTljOWY0MDBmMDknLFxuICAgICAgICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjR3pUbjVleU5HRGtiMThSNDNuSDc5SG9rLi4uJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXTtcblxuICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICAgICAgYmFzZUFkZHJlc3M6IGJhc2VBZGRyZXNzLFxuICAgICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICAgIHNhbHQ6IHdhbGxldFNhbHQsXG4gICAgICAgICAgICAgIGZvcndhcmRlclZlcnNpb246IDEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAga2V5Y2hhaW5zOiBrZXljaGFpbnMsXG4gICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgIHdhbGxldFZlcnNpb246IDEsXG4gICAgICAgICAgfSBhcyB1bmtub3duIGFzIFZlcmlmeUV0aEFkZHJlc3NPcHRpb25zO1xuXG4gICAgICAgICAgY29uc3QgaXNXYWxsZXRBZGRyID0gYXdhaXQgY29pbi5pc1dhbGxldEFkZHJlc3MocGFyYW1zKTtcbiAgICAgICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQWRkcmVzcyBDcmVhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHBhc3Mgd2FsbGV0VmVyc2lvbiA2IHRvIGlzV2FsbGV0QWRkcmVzcyBkdXJpbmcgYWRkcmVzcyBjcmVhdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICAgICAgY29uc3QgZXRoQ29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXREYXRhVjYgPSB7XG4gICAgICAgIGlkOiAnNTk4ZjYwNmNkOGZjMjQ3MTBkMmViYWRiMWQ5NDU5YmInLFxuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZGYwNzExNzcwNWE5ZjhkYzRjMmE3OGRlNjZiN2YxNzk3ZGJhOWQ0ZScsXG4gICAgICAgICAgd2FsbGV0VmVyc2lvbjogNixcbiAgICAgICAgfSxcbiAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAga2V5czogW1xuICAgICAgICAgICc1OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZDg5ZGNlODZjMicsXG4gICAgICAgICAgJzU5OGY2MDZjYzhlNDNhZWYwOWZjYjc4NTIyMWQ5ZGQyJyxcbiAgICAgICAgICAnNTkzNWQ1OWNmNjYwNzY0MzMxYmFmY2FkZTE4NTVmZDcnLFxuICAgICAgICBdLFxuICAgICAgICByZWNlaXZlQWRkcmVzczoge1xuICAgICAgICAgIGFkZHJlc3M6ICcweGRmMDcxMTc3MDVhOWY4ZGM0YzJhNzhkZTY2YjdmMTc5N2RiYTlkNGUnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV0aFdhbGxldFY2ID0gbmV3IFdhbGxldChiaXRnbywgZXRoQ29pbiwgd2FsbGV0RGF0YVY2KTtcbiAgICAgIGNvbnN0IGlzV2FsbGV0QWRkcmVzc1NweSA9IHNpbm9uLnNweShldGhDb2luLCAnaXNXYWxsZXRBZGRyZXNzJyk7XG5cbiAgICAgIC8vIE1vY2sga2V5Y2hhaW4gcmVxdWVzdHNcbiAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi9odGV0aC9rZXkvNTk4ZjYwNmNkOGZjMjQ3MTBkMmViYWQ4OWRjZTg2YzJgKS5yZXBseSgyMDAsIHtcbiAgICAgICAgaWQ6ICc1OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZDg5ZGNlODZjMicsXG4gICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNGWERjV0Qydnh1ZWJjVDFacFRGNFZrZTZxbU1XOHl6ZGR3TllwQVBqdllFRUw1akxmeVlYVzJmdXh0QXhZOFRnalBVSkxjZjFDOHF6OU42VmdaeEFyS1g0RXdCOHJINScsXG4gICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICcwMzNiMDJhYWM0ZjAzOGZlZjUxMTgzNTBiNzdkMzAyZWM2MjAyOTMxY2EyZTcxMjJhYWQ4ODk5NGZmZWZjYmM3MGE2MDY5ZTY2MjQzNjIzNmFiYjE2MTkxOTUyMzJjNDE1ODAyMDRjYjIwMmMyMjM1N2VkOGY1M2U2OWVhYzVjNjllJyxcbiAgICAgICAgc291cmNlOiAndXNlcicsXG4gICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvaHRldGgva2V5LzU5OGY2MDZjYzhlNDNhZWYwOWZjYjc4NTIyMWQ5ZGQyYCkucmVwbHkoMjAwLCB7XG4gICAgICAgIGlkOiAnNTk4ZjYwNmNjOGU0M2FlZjA5ZmNiNzg1MjIxZDlkZDInLFxuICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjR2hTYVhpa3B1VEM5S1U4OFh4OUxyaktTdzFKS3N2WE5nYWJwVGRnank3TFNvdmg5WkhoY3FoQUhRdTd1dGh1N0ZndU5HZGNDNGFYVEtLNWdxVGNQZTRXdkxZUmJDU0cnLFxuICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvaHRldGgva2V5LzU5MzVkNTljZjY2MDc2NDMzMWJhZmNhZGUxODU1ZmQ3YCkucmVwbHkoMjAwLCB7XG4gICAgICAgIGlkOiAnNTkzNWQ1OWNmNjYwNzY0MzMxYmFmY2FkZTE4NTVmZDcnLFxuICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjRnNYU2hXOFIzaEpzSE5UWVRVd3pjZWpuTGtZN0tDdGFKYkRxY0drY0JGOTlCckVKU2pOWkhlSHZlaVlVcnNBZHdualVNR3dwZ21FYmlLY1pXUnVWQTlIeG5SYUEzcjMnLFxuICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICB9KTtcblxuICAgICAgLy8gTW9jayBhZGRyZXNzIGNyZWF0aW9uIEFQSVxuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvaHRldGgvd2FsbGV0LyR7ZXRoV2FsbGV0VjYuaWQoKX0vYWRkcmVzc2ApXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBpZDogJzYzOGE0OGM2YzNkYmE0MDAwN2EzNDk3ZmE0OWEwODBjJyxcbiAgICAgICAgICBhZGRyZXNzOiAnMHhjMDEyMDQxZGFjMTQzYTU5ZmE0OTFkYjNhMmI2N2I2OWJkNzhiNjg1JyxcbiAgICAgICAgICBjaGFpbjogMCxcbiAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICAgIHdhbGxldDogZXRoV2FsbGV0VjYuaWQoKSxcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgIGZvcndhcmRlclZlcnNpb246IDQsXG4gICAgICAgICAgICBzYWx0OiAnMHgwJyxcbiAgICAgICAgICAgIGZlZUFkZHJlc3M6ICcweGIxZTcyNTE4Njk5MGI4NmNhOGVmZWQwOGEzY2NkYTljOWY0MDBmMDknLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBldGhXYWxsZXRWNi5jcmVhdGVBZGRyZXNzKHsgY2hhaW46IDAgfSk7XG5cbiAgICAgIGlzV2FsbGV0QWRkcmVzc1NweS5jYWxsZWRPbmNlLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBjb25zdCBjYWxsZWRQYXJhbXMgPSBpc1dhbGxldEFkZHJlc3NTcHkuZmlyc3RDYWxsLmFyZ3NbMF07XG4gICAgICBjYWxsZWRQYXJhbXMuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldFZlcnNpb24nLCA2KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFzcyB3YWxsZXRWZXJzaW9uIDUgdG8gaXNXYWxsZXRBZGRyZXNzIGR1cmluZyBhZGRyZXNzIGNyZWF0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gICAgICBjb25zdCBldGhDb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldERhdGFWNSA9IHtcbiAgICAgICAgaWQ6ICc1OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZGIxZDk0NTliYicsXG4gICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHhmMWUzZDMwNzk4YWNkZjNhMTJmYTViZWI1ZmFkOGVmYjIzZDViZTExJyxcbiAgICAgICAgICB3YWxsZXRWZXJzaW9uOiA1LFxuICAgICAgICB9LFxuICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICBrZXlzOiBbXG4gICAgICAgICAgJzU5OGY2MDZjZDhmYzI0NzEwZDJlYmFkODlkY2U4NmMyJyxcbiAgICAgICAgICAnNTk4ZjYwNmNjOGU0M2FlZjA5ZmNiNzg1MjIxZDlkZDInLFxuICAgICAgICAgICc1OTM1ZDU5Y2Y2NjA3NjQzMzFiYWZjYWRlMTg1NWZkNycsXG4gICAgICAgIF0sXG4gICAgICAgIHJlY2VpdmVBZGRyZXNzOiB7XG4gICAgICAgICAgYWRkcmVzczogJzB4ZjFlM2QzMDc5OGFjZGYzYTEyZmE1YmViNWZhZDhlZmIyM2Q1YmUxMScsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgZXRoV2FsbGV0VjUgPSBuZXcgV2FsbGV0KGJpdGdvLCBldGhDb2luLCB3YWxsZXREYXRhVjUpO1xuICAgICAgY29uc3QgaXNXYWxsZXRBZGRyZXNzU3B5ID0gc2lub24uc3B5KGV0aENvaW4sICdpc1dhbGxldEFkZHJlc3MnKTtcblxuICAgICAgLy8gTW9jayBrZXljaGFpbiByZXF1ZXN0c1xuICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyL2h0ZXRoL2tleS81OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZDg5ZGNlODZjMmApLnJlcGx5KDIwMCwge1xuICAgICAgICBpZDogJzU5OGY2MDZjZDhmYzI0NzEwZDJlYmFkODlkY2U4NmMyJyxcbiAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0ZYRGNXRDJ2eHVlYmNUMVpwVEY0VmtlNnFtTVc4eXpkZHdOWXBBUGp2WUVFTDVqTGZ5WVhXMmZ1eHRBeFk4VGdqUFVKTGNmMUM4cXo5TjZWZ1p4QXJLWDRFd0I4ckg1JyxcbiAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgJzAyYzhhNDk2YjE2YWJmZTI1Njc1MjBhMjc5ZTIxNTQ2NDJmYzNjMGUwOGU2Mjk3NzVjYjRkODQ1YzBjNWZiZjU1YWI3YmExNTNlODg2ZGU2NTc0OGVkMThmNGZmOGY1Y2VlMjI0MmU2ODczOTllYTMyOTdhMWY1NTI0ZmRlZmQ1NmMnLFxuICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi9odGV0aC9rZXkvNTk4ZjYwNmNjOGU0M2FlZjA5ZmNiNzg1MjIxZDlkZDJgKS5yZXBseSgyMDAsIHtcbiAgICAgICAgaWQ6ICc1OThmNjA2Y2M4ZTQzYWVmMDlmY2I3ODUyMjFkOWRkMicsXG4gICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHaFNhWGlrcHVUQzlLVTg4WHg5THJqS1N3MUpLc3ZYTmdhYnBUZGdqeTdMU292aDlaSGhjcWhBSFF1N3V0aHU3Rmd1TkdkY0M0YVhUS0s1Z3FUY1BlNFd2TFlSYkNTRycsXG4gICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICcwMmM4YTQ5NmIxNmFiZmUyNTY3NTIwYTI3OWUyMTU0NjQyZmMzYzBlMDhlNjI5Nzc1Y2I0ZDg0NWMwYzVmYmY1NWFiN2JhMTUzZTg4NmRlNjU3NDhlZDE4ZjRmZjhmNWNlZTIyNDJlNjg3Mzk5ZWEzMjk3YTFmNTUyNGZkZWZkNTZjJyxcbiAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi9odGV0aC9rZXkvNTkzNWQ1OWNmNjYwNzY0MzMxYmFmY2FkZTE4NTVmZDdgKS5yZXBseSgyMDAsIHtcbiAgICAgICAgaWQ6ICc1OTM1ZDU5Y2Y2NjA3NjQzMzFiYWZjYWRlMTg1NWZkNycsXG4gICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNGc1hTaFc4UjNoSnNITlRZVFV3emNlam5Ma1k3S0N0YUpiRHFjR2tjQkY5OUJyRUpTak5aSGVIdmVpWVVyc0Fkd25qVU1Hd3BnbUViaUtjWldSdVZBOUh4blJhQTNyMycsXG4gICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICcwMmM4YTQ5NmIxNmFiZmUyNTY3NTIwYTI3OWUyMTU0NjQyZmMzYzBlMDhlNjI5Nzc1Y2I0ZDg0NWMwYzVmYmY1NWFiN2JhMTUzZTg4NmRlNjU3NDhlZDE4ZjRmZjhmNWNlZTIyNDJlNjg3Mzk5ZWEzMjk3YTFmNTUyNGZkZWZkNTZjJyxcbiAgICAgICAgc291cmNlOiAnYml0Z28nLFxuICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBNb2NrIGFkZHJlc3MgY3JlYXRpb24gQVBJXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAucG9zdChgL2FwaS92Mi9odGV0aC93YWxsZXQvJHtldGhXYWxsZXRWNS5pZCgpfS9hZGRyZXNzYClcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGlkOiAnNjM4YTQ4YzZjM2RiYTQwMDA3YTM0OTdmYTQ5YTA4MGMnLFxuICAgICAgICAgIGFkZHJlc3M6ICcweGQ2M2I1ZTJiOGQxYjRmYmEzNjI1NDYwNTA4OTAwYmYyYTA0OTlhNGQnLFxuICAgICAgICAgIGNoYWluOiAwLFxuICAgICAgICAgIGluZGV4OiAxMTcsXG4gICAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgICB3YWxsZXQ6IGV0aFdhbGxldFY1LmlkKCksXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiA0LFxuICAgICAgICAgICAgc2FsdDogJzB4NzUnLFxuICAgICAgICAgICAgZmVlQWRkcmVzczogJzB4YjFlNzI1MTg2OTkwYjg2Y2E4ZWZlZDA4YTNjY2RhOWM5ZjQwMGYwOScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IGV0aFdhbGxldFY1LmNyZWF0ZUFkZHJlc3MoeyBjaGFpbjogMCB9KTtcblxuICAgICAgLy8gVmVyaWZ5IGlzV2FsbGV0QWRkcmVzcyB3YXMgY2FsbGVkIHdpdGggd2FsbGV0VmVyc2lvbiA1XG4gICAgICBpc1dhbGxldEFkZHJlc3NTcHkuY2FsbGVkT25jZS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgY29uc3QgY2FsbGVkUGFyYW1zID0gaXNXYWxsZXRBZGRyZXNzU3B5LmZpcnN0Q2FsbC5hcmdzWzBdO1xuICAgICAgY2FsbGVkUGFyYW1zLnNob3VsZC5oYXZlLnByb3BlcnR5KCd3YWxsZXRWZXJzaW9uJywgNSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhc3Mgd2FsbGV0VmVyc2lvbiAyIHRvIGlzV2FsbGV0QWRkcmVzcyBkdXJpbmcgYWRkcmVzcyBjcmVhdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICAgICAgY29uc3QgZXRoQ29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXREYXRhVjIgPSB7XG4gICAgICAgIGlkOiAnNTk4ZjYwNmNkOGZjMjQ3MTBkMmViYWRiMWQ5NDU5YmInLFxuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBiYXNlQWRkcmVzczogJzB4ZGM0ODVkYTA3NmVkNGEyYjE5NTg0ZTlhMWZkYmI5NzRmODliNjBmNCcsXG4gICAgICAgICAgd2FsbGV0VmVyc2lvbjogMixcbiAgICAgICAgfSxcbiAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAga2V5czogW1xuICAgICAgICAgICc1OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZDg5ZGNlODZjMicsXG4gICAgICAgICAgJzU5OGY2MDZjYzhlNDNhZWYwOWZjYjc4NTIyMWQ5ZGQyJyxcbiAgICAgICAgICAnNTkzNWQ1OWNmNjYwNzY0MzMxYmFmY2FkZTE4NTVmZDcnLFxuICAgICAgICBdLFxuICAgICAgICByZWNlaXZlQWRkcmVzczoge1xuICAgICAgICAgIGFkZHJlc3M6ICcweGRjNDg1ZGEwNzZlZDRhMmIxOTU4NGU5YTFmZGJiOTc0Zjg5YjYwZjQnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV0aFdhbGxldFYyID0gbmV3IFdhbGxldChiaXRnbywgZXRoQ29pbiwgd2FsbGV0RGF0YVYyKTtcbiAgICAgIGNvbnN0IGlzV2FsbGV0QWRkcmVzc1NweSA9IHNpbm9uLnNweShldGhDb2luLCAnaXNXYWxsZXRBZGRyZXNzJyk7XG5cbiAgICAgIC8vIE1vY2sga2V5Y2hhaW4gcmVxdWVzdHNcbiAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi9odGV0aC9rZXkvNTk4ZjYwNmNkOGZjMjQ3MTBkMmViYWQ4OWRjZTg2YzJgKS5yZXBseSgyMDAsIHtcbiAgICAgICAgaWQ6ICc1OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZDg5ZGNlODZjMicsXG4gICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHckN4Q1gzOXpiM1R2WWpUcWZVR3dFVVpIam5yYVJGbTFXZU13OWdmQ0Qxd3djMndVRG1CQloyVGtjY0pNd2Y1ZUJUamE4cjN6NkhNeG9UWkdXNm52eW9KTVFGc2VjdicsXG4gICAgICAgIGV0aEFkZHJlc3M6ICcweDlkMTZiYjg2N2I3OTJjNWUzYmY2MzZhMDI3NWYyZGI4NjAxYmQ3ZDQnLFxuICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgICAgdHlwZTogJ2luZGVwZW5kZW50JyxcbiAgICAgIH0pO1xuICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyL2h0ZXRoL2tleS81OThmNjA2Y2M4ZTQzYWVmMDlmY2I3ODUyMjFkOWRkMmApLnJlcGx5KDIwMCwge1xuICAgICAgICBpZDogJzU5OGY2MDZjYzhlNDNhZWYwOWZjYjc4NTIyMWQ5ZGQyJyxcbiAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0dLaGRlQzRucjF0YThkMjd4VGh0ZkZGSGdieFdNclZiNTk1bWVNUzhpM2ZCTXJUejhFZFFNV0JLSEhLenhhcEdnaGVvTXltVnZSY1FtYUdEeWtSVEJidFhxYml1OXBzJyxcbiAgICAgICAgZXRoQWRkcmVzczogJzB4MmRmY2U1Y2ZlYjVjMDNmYmU2ODBjZDM5YWMwZDJiMjUzOTliN2QyMicsXG4gICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICB9KTtcbiAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi9odGV0aC9rZXkvNTkzNWQ1OWNmNjYwNzY0MzMxYmFmY2FkZTE4NTVmZDdgKS5yZXBseSgyMDAsIHtcbiAgICAgICAgaWQ6ICc1OTM1ZDU5Y2Y2NjA3NjQzMzFiYWZjYWRlMTg1NWZkNycsXG4gICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHelRuNWV5TkdEa2IxOFI0M25INzlIb2tZTGM1UFhaTTE5VjhVcmJ1TGRWUmFDUU1zNEVlQ0FqbnFtb1lYcWZ5dXNUVTQ2V29aTUR5THBtVHpvVVg2NlpCd0dGanQxYScsXG4gICAgICAgIGV0aEFkZHJlc3M6ICcweGIxZTcyNTE4Njk5MGI4NmNhOGVmZWQwOGEzY2NkYTljOWY0MDBmMDknLFxuICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICB9KTtcblxuICAgICAgLy8gTW9jayBhZGRyZXNzIGNyZWF0aW9uIEFQSVxuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvaHRldGgvd2FsbGV0LyR7ZXRoV2FsbGV0VjIuaWQoKX0vYWRkcmVzc2ApXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBpZDogJzYzOGE0OGM2YzNkYmE0MDAwN2EzNDk3ZmE0OWEwODBjJyxcbiAgICAgICAgICBhZGRyZXNzOiAnMHhmNjM2Y2VkZGZmZTQxZDEwNjU4Njg3NWMwZTU2ZGM4ZmViNjI2OGY3JyxcbiAgICAgICAgICBjaGFpbjogMCxcbiAgICAgICAgICBpbmRleDogMjMsXG4gICAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgICB3YWxsZXQ6IGV0aFdhbGxldFYyLmlkKCksXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiAyLFxuICAgICAgICAgICAgc2FsdDogJzB4MTcnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBldGhXYWxsZXRWMi5jcmVhdGVBZGRyZXNzKHsgY2hhaW46IDAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBpc1dhbGxldEFkZHJlc3Mgd2FzIGNhbGxlZCB3aXRoIHdhbGxldFZlcnNpb24gMlxuICAgICAgaXNXYWxsZXRBZGRyZXNzU3B5LmNhbGxlZE9uY2Uuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIGNvbnN0IGNhbGxlZFBhcmFtcyA9IGlzV2FsbGV0QWRkcmVzc1NweS5maXJzdENhbGwuYXJnc1swXTtcbiAgICAgIGNhbGxlZFBhcmFtcy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0VmVyc2lvbicsIDIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHY2IGFkZHJlc3MgY3JlYXRpb24gaWYgd2FsbGV0VmVyc2lvbiB3YXMgbm90IHBhc3NlZCAoc2ltdWxhdGVzIG9sZCBidWcpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gICAgICBjb25zdCBldGhDb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldERhdGFWNiA9IHtcbiAgICAgICAgaWQ6ICc1OThmNjA2Y2Q4ZmMyNDcxMGQyZWJhZGIxZDk0NTliYicsXG4gICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHhkZjA3MTE3NzA1YTlmOGRjNGMyYTc4ZGU2NmI3ZjE3OTdkYmE5ZDRlJyxcbiAgICAgICAgICB3YWxsZXRWZXJzaW9uOiA2LFxuICAgICAgICB9LFxuICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICBrZXlzOiBbXG4gICAgICAgICAgJzU5OGY2MDZjZDhmYzI0NzEwZDJlYmFkODlkY2U4NmMyJyxcbiAgICAgICAgICAnNTk4ZjYwNmNjOGU0M2FlZjA5ZmNiNzg1MjIxZDlkZDInLFxuICAgICAgICAgICc1OTM1ZDU5Y2Y2NjA3NjQzMzFiYWZjYWRlMTg1NWZkNycsXG4gICAgICAgIF0sXG4gICAgICAgIHJlY2VpdmVBZGRyZXNzOiB7XG4gICAgICAgICAgYWRkcmVzczogJzB4ZGYwNzExNzcwNWE5ZjhkYzRjMmE3OGRlNjZiN2YxNzk3ZGJhOWQ0ZScsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgZXRoV2FsbGV0VjYgPSBuZXcgV2FsbGV0KGJpdGdvLCBldGhDb2luLCB3YWxsZXREYXRhVjYpO1xuXG4gICAgICAvLyBTdHViIGlzV2FsbGV0QWRkcmVzcyB0byBzaW11bGF0ZSB0aGUgT0xEIGJ1ZyB3aGVyZSB3YWxsZXRWZXJzaW9uIHdhcyBub3QgcGFzc2VkXG4gICAgICBjb25zdCBvcmlnaW5hbElzV2FsbGV0QWRkcmVzcyA9IGV0aENvaW4uaXNXYWxsZXRBZGRyZXNzLmJpbmQoZXRoQ29pbik7XG4gICAgICBjb25zdCBpc1dhbGxldEFkZHJlc3NTdHViID0gc2lub24uc3R1YihldGhDb2luLCAnaXNXYWxsZXRBZGRyZXNzJykuY2FsbHNGYWtlKGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgLy8gUmVtb3ZlIHdhbGxldFZlcnNpb24gdG8gc2ltdWxhdGUgdGhlIG9sZCBidWdcbiAgICAgICAgY29uc3QgcGFyYW1zV2l0aG91dFdhbGxldFZlcnNpb24gPSB7IC4uLnBhcmFtcyB9O1xuICAgICAgICBkZWxldGUgKHBhcmFtc1dpdGhvdXRXYWxsZXRWZXJzaW9uIGFzIGFueSkud2FsbGV0VmVyc2lvbjtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsSXNXYWxsZXRBZGRyZXNzKHBhcmFtc1dpdGhvdXRXYWxsZXRWZXJzaW9uKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBNb2NrIGtleWNoYWluIHJlcXVlc3RzXG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvaHRldGgva2V5LzU5OGY2MDZjZDhmYzI0NzEwZDJlYmFkODlkY2U4NmMyYCkucmVwbHkoMjAwLCB7XG4gICAgICAgIGlkOiAnNTk4ZjYwNmNkOGZjMjQ3MTBkMmViYWQ4OWRjZTg2YzInLFxuICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjRlhEY1dEMnZ4dWViY1QxWnBURjRWa2U2cW1NVzh5emRkd05ZcEFQanZZRUVMNWpMZnlZWFcyZnV4dEF4WThUZ2pQVUpMY2YxQzhxejlONlZnWnhBcktYNEV3QjhySDUnLFxuICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAnMDMzYjAyYWFjNGYwMzhmZWY1MTE4MzUwYjc3ZDMwMmVjNjIwMjkzMWNhMmU3MTIyYWFkODg5OTRmZmVmY2JjNzBhNjA2OWU2NjI0MzYyMzZhYmIxNjE5MTk1MjMyYzQxNTgwMjA0Y2IyMDJjMjIzNTdlZDhmNTNlNjllYWM1YzY5ZScsXG4gICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyL2h0ZXRoL2tleS81OThmNjA2Y2M4ZTQzYWVmMDlmY2I3ODUyMjFkOWRkMmApLnJlcGx5KDIwMCwge1xuICAgICAgICBpZDogJzU5OGY2MDZjYzhlNDNhZWYwOWZjYjc4NTIyMWQ5ZGQyJyxcbiAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0doU2FYaWtwdVRDOUtVODhYeDlMcmpLU3cxSktzdlhOZ2FicFRkZ2p5N0xTb3ZoOVpIaGNxaEFIUXU3dXRodTdGZ3VOR2RjQzRhWFRLSzVncVRjUGU0V3ZMWVJiQ1NHJyxcbiAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgJzAzM2IwMmFhYzRmMDM4ZmVmNTExODM1MGI3N2QzMDJlYzYyMDI5MzFjYTJlNzEyMmFhZDg4OTk0ZmZlZmNiYzcwYTYwNjllNjYyNDM2MjM2YWJiMTYxOTE5NTIzMmM0MTU4MDIwNGNiMjAyYzIyMzU3ZWQ4ZjUzZTY5ZWFjNWM2OWUnLFxuICAgICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyL2h0ZXRoL2tleS81OTM1ZDU5Y2Y2NjA3NjQzMzFiYWZjYWRlMTg1NWZkN2ApLnJlcGx5KDIwMCwge1xuICAgICAgICBpZDogJzU5MzVkNTljZjY2MDc2NDMzMWJhZmNhZGUxODU1ZmQ3JyxcbiAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0ZzWFNoVzhSM2hKc0hOVFlUVXd6Y2VqbkxrWTdLQ3RhSmJEcWNHa2NCRjk5QnJFSlNqTlpIZUh2ZWlZVXJzQWR3bmpVTUd3cGdtRWJpS2NaV1J1VkE5SHhuUmFBM3IzJyxcbiAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgJzAzM2IwMmFhYzRmMDM4ZmVmNTExODM1MGI3N2QzMDJlYzYyMDI5MzFjYTJlNzEyMmFhZDg4OTk0ZmZlZmNiYzcwYTYwNjllNjYyNDM2MjM2YWJiMTYxOTE5NTIzMmM0MTU4MDIwNGNiMjAyYzIyMzU3ZWQ4ZjUzZTY5ZWFjNWM2OWUnLFxuICAgICAgICBzb3VyY2U6ICdiaXRnbycsXG4gICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIE1vY2sgYWRkcmVzcyBjcmVhdGlvbiBBUElcbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KGAvYXBpL3YyL2h0ZXRoL3dhbGxldC8ke2V0aFdhbGxldFY2LmlkKCl9L2FkZHJlc3NgKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgaWQ6ICc2MzhhNDhjNmMzZGJhNDAwMDdhMzQ5N2ZhNDlhMDgwYycsXG4gICAgICAgICAgYWRkcmVzczogJzB4YzAxMjA0MWRhYzE0M2E1OWZhNDkxZGIzYTJiNjdiNjliZDc4YjY4NScsXG4gICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgICB3YWxsZXQ6IGV0aFdhbGxldFY2LmlkKCksXG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBmb3J3YXJkZXJWZXJzaW9uOiA0LFxuICAgICAgICAgICAgc2FsdDogJzB4MCcsXG4gICAgICAgICAgICBmZWVBZGRyZXNzOiAnMHhiMWU3MjUxODY5OTBiODZjYThlZmVkMDhhM2NjZGE5YzlmNDAwZjA5JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgLy8gV2l0aG91dCB3YWxsZXRWZXJzaW9uLCBhZGRyZXNzIGNyZWF0aW9uIHNob3VsZCBmYWlsIGJlY2F1c2VcbiAgICAgIC8vIHRoZSBjb2RlIGRvZXNuJ3Qga25vdyB0byB1c2UgVFNTIHZlcmlmaWNhdGlvbiBmb3IgdjYgd2FsbGV0c1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4gZXRoV2FsbGV0VjYuY3JlYXRlQWRkcmVzcyh7IGNoYWluOiAwIH0pLCBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yKTtcblxuICAgICAgaXNXYWxsZXRBZGRyZXNzU3R1Yi5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFVk0gQ3Jvc3MgQ2hhaW4gUmVjb3ZlcnknLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYmFzZVVybCA9IGNvbW1vbi5FbnZpcm9ubWVudHMudGVzdC5ldGhlcnNjYW5CYXNlVXJsIGFzIHN0cmluZztcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgcmVjb3ZlcnkgdHJhbnNhY3Rpb24gZm9yIGhvdCB3YWxsZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1c2VyS2V5ID1cbiAgICAgICAgJ3tcIml2XCI6XCJWRlozanZYaHhvMVorWWFmMk10Wm5BPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiXFxuJyArXG4gICAgICAgICc6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJwK2ZrSHVMYS84az1cIixcImN0XCI6XCJoWUc3cHZsakxJZ0NqWlxcbicgK1xuICAgICAgICAnNTNQQmxDZGU1S1pSbWxVS0tITHRETWsrSEpmdVU0NmhXK3grQzlXc0lBTzRnRlBuVEN2RlZtUTh4N2N6Q3RjTkZ1YjVBTzJvdE9HXFxuJyArXG4gICAgICAgICdPc1g0R0UyZ1hPRW1DbDFUcFd3d05obTd5TVVqR0pVcGdXNlpaZ1hTWGREaXRTS2k0Vi9oazc4U0dTempGT0JTUFlSYTZJPVwifVxcbic7XG4gICAgICBjb25zdCB3YWxsZXRDb250cmFjdEFkZHJlc3MgPSBUZXN0Qml0R28uVjIuVEVTVF9FVEhfV0FMTEVUX0ZJUlNUX0FERFJFU1MgYXMgc3RyaW5nO1xuICAgICAgY29uc3QgYml0Z29GZWVBZGRyZXNzID0gJzB4MzNhNDJmYWVhM2M2ZTg3MDIxMzQ3ZTUxNzAwYjQ4YWFmNDlhYTFlNyc7XG4gICAgICBjb25zdCBkZXN0aW5hdGlvbkFkZHJlc3MgPSAnMHhkNUFEZEUxN2ZlRDhiYWVkM0YzMmI4NEFGMDVCOEYyODE2ZjdiNTYwJztcbiAgICAgIGNvbnN0IGJpdGdvRGVzdGluYXRpb25BZGRyZXNzID0gJzB4RTU5ODZDRTQ0OTBEZWI2N2QyOTUwNTYyQ2ViOTMwRGRmOWJlN2ExNCc7XG4gICAgICBjb25zdCB3YWxsZXRQYXNzcGhyYXNlID0gVGVzdEJpdEdvLlYyLlRFU1RfUkVDT1ZFUllfUEFTU0NPREUgYXMgc3RyaW5nO1xuXG4gICAgICBjb25zdCBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdCh3YWxsZXRDb250cmFjdEFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKS5nZXQoJy9hcGknKS5xdWVyeShtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXF1ZXN0KS5yZXBseSgyMDAsIG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlc3BvbnNlKTtcblxuICAgICAgY29uc3Qgc3B5ID0gc2lub24uc3B5KFRyYW5zYWN0aW9uQnVpbGRlci5wcm90b3R5cGUsICdjb2luVXNlc05vblBhY2tlZEVuY29kaW5nRm9yVHhEYXRhJyk7XG4gICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogdXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiAnJyxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIGJpdGdvRmVlQWRkcmVzczogYml0Z29GZWVBZGRyZXNzLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGJpdGdvRGVzdGluYXRpb25BZGRyZXNzOiBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgaW50ZW5kZWRDaGFpbjogJ3RhcmJldGgnLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQoc3B5LnJldHVybmVkKHRydWUpKTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdOb24tQml0R28gUmVjb3ZlcnkgZm9yIEhvdCBXYWxsZXRzIChNUEN2MiknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiYXNlVXJsID0gY29tbW9uLkVudmlyb25tZW50cy50ZXN0LmV0aGVyc2NhbkJhc2VVcmwgYXMgc3RyaW5nO1xuICAgICAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gICAgICBsZXQgYmFzZWNvaW46IEh0ZXRoO1xuXG4gICAgICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICAgICAgYmFzZWNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgYnVpbGQgYSByZWNvdmVyeSB0cmFuc2FjdGlvbiBmb3IgTVBDdjIga2luZCBvZiBob3Qgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUeExpc3RSZXF1ZXN0KG1vY2tEYXRhLmdldE5vbkJpdEdvUmVjb3ZlcnlGb3JIb3RXYWxsZXRzTVBDdjIoKS5iaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldFR4TGlzdFJlc3BvbnNlKTtcblxuICAgICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KG1vY2tEYXRhLmdldE5vbkJpdEdvUmVjb3ZlcnlGb3JIb3RXYWxsZXRzTVBDdjIoKS5iaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG5cbiAgICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChtb2NrRGF0YS5nZXROb25CaXRHb1JlY292ZXJ5Rm9ySG90V2FsbGV0c01QQ3YyKCkud2FsbGV0Q29udHJhY3RBZGRyZXNzKSlcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuXG4gICAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0Tm9uQml0R29SZWNvdmVyeUZvckhvdFdhbGxldHNNUEN2MigpO1xuXG4gICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gYXdhaXQgKGJhc2Vjb2luIGFzIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zKS5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IHBhcmFtcy5iYWNrdXBLZXksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICAgIGJpdGdvRmVlQWRkcmVzczogcGFyYW1zLmJpdGdvRmVlQWRkcmVzcyxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwMDAwMDAwMDAsIG1heFByaW9yaXR5RmVlUGVyR2FzOiAxMDAwMDAwMDAwMCB9LFxuICAgICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgICAgYml0Z29EZXN0aW5hdGlvbkFkZHJlc3M6IHBhcmFtcy5iaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgICBpbnRlbmRlZENoYWluOiBwYXJhbXMuaW50ZW5kZWRDaGFpbixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uKTtcbiAgICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBmb3IgaW52YWxpZCB1c2VyIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0SW52YWxpZE5vbkJpdEdvUmVjb3ZlcnlQYXJhbXMoKTtcblxuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCAoYmFzZWNvaW4gYXMgQWJzdHJhY3RFdGhMaWtlTmV3Q29pbnMpLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICAgICAgICBiaXRnb0ZlZUFkZHJlc3M6IHBhcmFtcy5iaXRnb0ZlZUFkZHJlc3MsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwMDAwMDAwMDAsIG1heFByaW9yaXR5RmVlUGVyR2FzOiAxMDAwMDAwMDAwMCB9LFxuICAgICAgICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICAgICAgICBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzczogcGFyYW1zLmJpdGdvRGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICAgICAgICBpbnRlbmRlZENoYWluOiBwYXJhbXMuaW50ZW5kZWRDaGFpbixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgRXJyb3IsXG4gICAgICAgICAgJ3VzZXIga2V5IGlzIGludmFsaWQnXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdCdWlsZCBVbnNpZ25lZCBTd2VlcCBmb3IgU2VsZi1DdXN0b2R5IENvbGQgV2FsbGV0cyAoTVBDdjIpJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmFzZVVybCA9IGNvbW1vbi5FbnZpcm9ubWVudHMudGVzdC5ldGhlcnNjYW5CYXNlVXJsIGFzIHN0cmluZztcbiAgICAgIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICAgICAgbGV0IGJhc2Vjb2luOiBIdGV0aDtcblxuICAgICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgICAgIGJhc2Vjb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGFuIHVuc2lnbmVkIHN3ZWVwIHdpdGhvdXQgZGVyaXZhdGlvbiBzZWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldFR4TGlzdFJlcXVlc3QobW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCkuYWRkcmVzcykpXG4gICAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuXG4gICAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QobW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCkuYWRkcmVzcykpXG4gICAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAgIC5xdWVyeShcbiAgICAgICAgICAgIG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KFxuICAgICAgICAgICAgICBtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKS53YWxsZXRDb250cmFjdEFkZHJlc3NcbiAgICAgICAgICAgIClcbiAgICAgICAgICApXG4gICAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcblxuICAgICAgICBub2NrKGJhc2VVcmwpLmdldCgnL2FwaScpLnF1ZXJ5KG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlcXVlc3QpLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVzcG9uc2UpO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IG1vY2tEYXRhLmdldEJ1aWxkVW5zaWduZWRTd2VlcEZvclNlbGZDdXN0b2R5Q29sZFdhbGxldHNNUEN2MigpO1xuICAgICAgICBjb25zdCBzd2VlcFJlc3VsdCA9IGF3YWl0IChiYXNlY29pbiBhcyBBYnN0cmFjdEV0aExpa2VOZXdDb2lucykucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogcGFyYW1zLmNvbW1vbktleUNoYWluLCAvLyBCb3ggQSBEYXRhXG4gICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuY29tbW9uS2V5Q2hhaW4sIC8vIEJveCBCIERhdGFcbiAgICAgICAgICBkZXJpdmF0aW9uU2VlZDogcGFyYW1zLmRlcml2YXRpb25TZWVkLCAvLyBLZXkgRGVyaXZhdGlvbiBTZWVkIChvcHRpb25hbClcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgLy8gRGVzdGluYXRpb24gQWRkcmVzc1xuICAgICAgICAgIGdhc0xpbWl0OiAyMDAwMDAsIC8vIEdhcyBMaW1pdFxuICAgICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sIC8vIE1heCBGZWUgUGVyIEdhcyBhbmQgTWF4IFByaW9yaXR5IEZlZSBQZXIgR2FzXG4gICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgICAgICBjaGFpbjogJzQyJyxcbiAgICAgICAgICAgIGhhcmRmb3JrOiAnbG9uZG9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHN3ZWVwUmVzdWx0KTtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gc3dlZXBSZXN1bHQgYXMgVW5zaWduZWRTd2VlcFR4TVBDdjI7XG4gICAgICAgIG91dHB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhSZXF1ZXN0cycpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0cy5zaG91bGQuaGF2ZS5sZW5ndGgoMSk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0cmFuc2FjdGlvbnMnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldENvaW4nKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnNob3VsZC5oYXZlLnByb3BlcnR5KCd1bnNpZ25lZFR4Jyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzZXJpYWxpemVkVHhIZXgnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hYmxlSGV4Jyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdkZXJpdmF0aW9uUGF0aCcpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlSW5mbycpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncGFyc2VkVHgnKTtcbiAgICAgICAgY29uc3QgcGFyc2VkVHggPSBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeCBhcyB7IHNwZW5kQW1vdW50OiBzdHJpbmcgfTtcbiAgICAgICAgcGFyc2VkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NwZW5kQW1vdW50Jyk7XG4gICAgICAgIChvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeCBhcyB7IG91dHB1dHM6IGFueVtdIH0pLnNob3VsZC5oYXZlLnByb3BlcnR5KFxuICAgICAgICAgICdvdXRwdXRzJ1xuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3IgZm9yIGludmFsaWQgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCk7XG4gICAgICAgIHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uID0gJ2ludmFsaWRBZGRyZXNzJztcblxuICAgICAgICAvLyBFbnN1cmUgdXNlcktleSBhbmQgYmFja3VwS2V5IGFyZSB0aGUgc2FtZVxuICAgICAgICBwYXJhbXMudXNlcktleSA9XG4gICAgICAgICAgJzAyMzRlYjM5YjIyZmVkNTIzZWNlN2M3OGRhMjliYTFmMWRlNWI2NGE2ZTQ4MDEzZTA5MTRkZTc5M2JjMWRmMDU3MGU3NzlkZTA0NzU4NzMyNzM0ZDk3ZTU0Yjc4MmM4YjMzNjI4MzgxMWFmNmEyYzU3YmQ4MTQzODc5OGUxYzI0NDYnO1xuICAgICAgICBwYXJhbXMuYmFja3VwS2V5ID1cbiAgICAgICAgICAnMDIzNGViMzliMjJmZWQ1MjNlY2U3Yzc4ZGEyOWJhMWYxZGU1YjY0YTZlNDgwMTNlMDkxNGRlNzkzYmMxZGYwNTcwZTc3OWRlMDQ3NTg3MzI3MzRkOTdlNTRiNzgyYzhiMzM2MjgzODExYWY2YTJjNTdiZDgxNDM4Nzk4ZTFjMjQ0Nic7XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgKGJhc2Vjb2luIGFzIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zKS5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sIC8vIERlc3RpbmF0aW9uIEFkZHJlc3NcbiAgICAgICAgICAgICAgZ2FzTGltaXQ6IDIwMDAsIC8vIEdhcyBMaW1pdFxuICAgICAgICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwLCBtYXhQcmlvcml0eUZlZVBlckdhczogMTAwMDAgfSwgLy8gTWF4IEZlZSBQZXIgR2FzIGFuZCBNYXggUHJpb3JpdHkgRmVlIFBlciBHYXNcbiAgICAgICAgICAgICAgdXNlcktleTogcGFyYW1zLnVzZXJLZXksIC8vIFByb3ZpZGUgdGhlIHVzZXJLZXlcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LCAvLyBQcm92aWRlIHRoZSBiYWNrdXBLZXlcbiAgICAgICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLCAvLyBQcm92aWRlIHRoZSB3YWxsZXRDb250cmFjdEFkZHJlc3NcbiAgICAgICAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICAgICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgY2hhaW46ICc0MicsXG4gICAgICAgICAgICAgICAgaGFyZGZvcms6ICdsb25kb24nLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBFcnJvcixcbiAgICAgICAgICAnRXJyb3I6IGludmFsaWQgYWRkcmVzcydcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ0J1aWxkIFVuc2lnbmVkIENvbnNvbGlkYXRpb24gZm9yIFNlbGYtQ3VzdG9keSBDb2xkIFdhbGxldHMgKE1QQ3YyKScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJhc2VVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzLnRlc3QuZXRoZXJzY2FuQmFzZVVybCBhcyBzdHJpbmc7XG4gICAgICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgICAgIGxldCBiYXNlY29pbjogSHRldGg7XG5cbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgICAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCBjb25zb2xpZGF0aW9uIGZvciB3YWxsZXQgdjUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKS5hZGRyZXNzKSlcbiAgICAgICAgICAudGltZXMoMilcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG5cbiAgICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKS5hZGRyZXNzKSlcbiAgICAgICAgICAudGltZXMoMilcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgICAgLnF1ZXJ5KFxuICAgICAgICAgICAgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoXG4gICAgICAgICAgICAgIG1vY2tEYXRhLmdldEJ1aWxkVW5zaWduZWRTd2VlcEZvclNlbGZDdXN0b2R5Q29sZFdhbGxldHNNUEN2MigpLndhbGxldENvbnRyYWN0QWRkcmVzc1xuICAgICAgICAgICAgKVxuICAgICAgICAgIClcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuXG4gICAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCk7XG4gICAgICAgIGNvbnN0IGNvbnNvbGlkYXRpb25SZXN1bHQgPSBhd2FpdCAoYmFzZWNvaW4gYXMgQWJzdHJhY3RFdGhMaWtlTmV3Q29pbnMpLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuY29tbW9uS2V5Q2hhaW4sIC8vIEJveCBCIERhdGFcbiAgICAgICAgICBkZXJpdmF0aW9uU2VlZDogcGFyYW1zLmRlcml2YXRpb25TZWVkLCAvLyBLZXkgRGVyaXZhdGlvbiBTZWVkIChvcHRpb25hbClcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgLy8gRGVzdGluYXRpb24gQWRkcmVzc1xuICAgICAgICAgIGdhc0xpbWl0OiAyMDAwMDAsIC8vIEdhcyBMaW1pdFxuICAgICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sIC8vIE1heCBGZWUgUGVyIEdhcyBhbmQgTWF4IFByaW9yaXR5IEZlZSBQZXIgR2FzXG4gICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgICAgICBjaGFpbjogJzQyJyxcbiAgICAgICAgICAgIGhhcmRmb3JrOiAnbG9uZG9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJpdGdvRmVlQWRkcmVzczogJzB4MzNhNDJmYWVhM2M2ZTg3MDIxMzQ3ZTUxNzAwYjQ4YWFmNDlhYTFlNycsXG4gICAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgICAgZW5kaW5nU2NhbkluZGV4OiAyLFxuICAgICAgICB9KTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KGNvbnNvbGlkYXRpb25SZXN1bHQpO1xuICAgICAgICBjb25zdCB1bnNpZ25lZEJ1aWxDb25zb2xpZGF0aW9uID0gY29uc29saWRhdGlvblJlc3VsdCBhcyBVbnNpZ25lZEJ1aWxDb25zb2xpZGF0aW9uO1xuICAgICAgICB1bnNpZ25lZEJ1aWxDb25zb2xpZGF0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0cmFuc2FjdGlvbnMnKTtcbiAgICAgICAgdW5zaWduZWRCdWlsQ29uc29saWRhdGlvbi50cmFuc2FjdGlvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDEpO1xuXG4gICAgICAgIGNvbnN0IG91dHB1dCA9IHVuc2lnbmVkQnVpbENvbnNvbGlkYXRpb24udHJhbnNhY3Rpb25zWzBdIGFzIE1QQ1N3ZWVwVHhzO1xuICAgICAgICBvdXRwdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4UmVxdWVzdHMnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3RyYW5zYWN0aW9ucycpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDEpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0Q29pbicpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDEpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3Vuc2lnbmVkVHgnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NlcmlhbGl6ZWRUeEhleCcpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc2lnbmFibGVIZXgnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Rlcml2YXRpb25QYXRoJyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVJbmZvJyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdwYXJzZWRUeCcpO1xuICAgICAgICBjb25zdCBwYXJzZWRUeCA9IG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4IGFzIHsgc3BlbmRBbW91bnQ6IHN0cmluZyB9O1xuICAgICAgICBwYXJzZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3BlbmRBbW91bnQnKTtcbiAgICAgICAgKG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4IGFzIHsgb3V0cHV0czogYW55W10gfSkuc2hvdWxkLmhhdmUucHJvcGVydHkoXG4gICAgICAgICAgJ291dHB1dHMnXG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCBjb25zb2xpZGF0aW9uIGZvciB3YWxsZXQgdjYnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKS5hZGRyZXNzKSlcbiAgICAgICAgICAudGltZXMoMilcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG5cbiAgICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKS5hZGRyZXNzKSlcbiAgICAgICAgICAudGltZXMoMilcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgICAgLnF1ZXJ5KFxuICAgICAgICAgICAgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoXG4gICAgICAgICAgICAgIG1vY2tEYXRhLmdldEJ1aWxkVW5zaWduZWRTd2VlcEZvclNlbGZDdXN0b2R5Q29sZFdhbGxldHNNUEN2MigpLndhbGxldENvbnRyYWN0QWRkcmVzc1xuICAgICAgICAgICAgKVxuICAgICAgICAgIClcbiAgICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuXG4gICAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCk7XG4gICAgICAgIGNvbnN0IGNvbnNvbGlkYXRpb25SZXN1bHQgPSBhd2FpdCAoYmFzZWNvaW4gYXMgQWJzdHJhY3RFdGhMaWtlTmV3Q29pbnMpLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgICAgdXNlcktleTogcGFyYW1zLmNvbW1vbktleUNoYWluLCAvLyBCb3ggQSBEYXRhXG4gICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuY29tbW9uS2V5Q2hhaW4sIC8vIEJveCBCIERhdGFcbiAgICAgICAgICBkZXJpdmF0aW9uU2VlZDogcGFyYW1zLmRlcml2YXRpb25TZWVkLCAvLyBLZXkgRGVyaXZhdGlvbiBTZWVkIChvcHRpb25hbClcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgLy8gRGVzdGluYXRpb24gQWRkcmVzc1xuICAgICAgICAgIGdhc0xpbWl0OiAyMDAwMDAsIC8vIEdhcyBMaW1pdFxuICAgICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sIC8vIE1heCBGZWUgUGVyIEdhcyBhbmQgTWF4IFByaW9yaXR5IEZlZSBQZXIgR2FzXG4gICAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnMTIzJywgLy8gV3Jvbmcgd2FsbGV0IGFkZHJlc3Mgc28gdGhhdCB3ZSBjYW4gc2tpcCB2NSBhZGRyZXNzIGdlbmVyYXRpb25cbiAgICAgICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczoge1xuICAgICAgICAgICAgY2hhaW46ICc0MicsXG4gICAgICAgICAgICBoYXJkZm9yazogJ2xvbmRvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBiaXRnb0ZlZUFkZHJlc3M6ICcweDMzYTQyZmFlYTNjNmU4NzAyMTM0N2U1MTcwMGI0OGFhZjQ5YWExZTcnLFxuICAgICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICAgIGVuZGluZ1NjYW5JbmRleDogMixcbiAgICAgICAgfSk7XG4gICAgICAgIHNob3VsZC5leGlzdChjb25zb2xpZGF0aW9uUmVzdWx0KTtcbiAgICAgICAgY29uc3QgdW5zaWduZWRCdWlsQ29uc29saWRhdGlvbiA9IGNvbnNvbGlkYXRpb25SZXN1bHQgYXMgVW5zaWduZWRCdWlsQ29uc29saWRhdGlvbjtcbiAgICAgICAgdW5zaWduZWRCdWlsQ29uc29saWRhdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHJhbnNhY3Rpb25zJyk7XG4gICAgICAgIHVuc2lnbmVkQnVpbENvbnNvbGlkYXRpb24udHJhbnNhY3Rpb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcblxuICAgICAgICBjb25zdCBvdXRwdXQgPSB1bnNpZ25lZEJ1aWxDb25zb2xpZGF0aW9uLnRyYW5zYWN0aW9uc1swXSBhcyBNUENTd2VlcFR4cztcbiAgICAgICAgb3V0cHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eFJlcXVlc3RzJyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0cmFuc2FjdGlvbnMnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldENvaW4nKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnNob3VsZC5oYXZlLnByb3BlcnR5KCd1bnNpZ25lZFR4Jyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzZXJpYWxpemVkVHhIZXgnKTtcbiAgICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hYmxlSGV4Jyk7XG4gICAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdkZXJpdmF0aW9uUGF0aCcpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlSW5mbycpO1xuICAgICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncGFyc2VkVHgnKTtcbiAgICAgICAgY29uc3QgcGFyc2VkVHggPSBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeCBhcyB7IHNwZW5kQW1vdW50OiBzdHJpbmcgfTtcbiAgICAgICAgcGFyc2VkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NwZW5kQW1vdW50Jyk7XG4gICAgICAgIChvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeCBhcyB7IG91dHB1dHM6IGFueVtdIH0pLnNob3VsZC5oYXZlLnByb3BlcnR5KFxuICAgICAgICAgICdvdXRwdXRzJ1xuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3IgZm9yIGludmFsaWQgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCk7XG4gICAgICAgIHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uID0gJ2ludmFsaWRBZGRyZXNzJztcblxuICAgICAgICAvLyBFbnN1cmUgdXNlcktleSBhbmQgYmFja3VwS2V5IGFyZSB0aGUgc2FtZVxuICAgICAgICBwYXJhbXMudXNlcktleSA9XG4gICAgICAgICAgJzAyMzRlYjM5YjIyZmVkNTIzZWNlN2M3OGRhMjliYTFmMWRlNWI2NGE2ZTQ4MDEzZTA5MTRkZTc5M2JjMWRmMDU3MGU3NzlkZTA0NzU4NzMyNzM0ZDk3ZTU0Yjc4MmM4YjMzNjI4MzgxMWFmNmEyYzU3YmQ4MTQzODc5OGUxYzI0NDYnO1xuICAgICAgICBwYXJhbXMuYmFja3VwS2V5ID1cbiAgICAgICAgICAnMDIzNGViMzliMjJmZWQ1MjNlY2U3Yzc4ZGEyOWJhMWYxZGU1YjY0YTZlNDgwMTNlMDkxNGRlNzkzYmMxZGYwNTcwZTc3OWRlMDQ3NTg3MzI3MzRkOTdlNTRiNzgyYzhiMzM2MjgzODExYWY2YTJjNTdiZDgxNDM4Nzk4ZTFjMjQ0Nic7XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgKGJhc2Vjb2luIGFzIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zKS5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sIC8vIERlc3RpbmF0aW9uIEFkZHJlc3NcbiAgICAgICAgICAgICAgZ2FzTGltaXQ6IDIwMDAsIC8vIEdhcyBMaW1pdFxuICAgICAgICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwLCBtYXhQcmlvcml0eUZlZVBlckdhczogMTAwMDAgfSwgLy8gTWF4IEZlZSBQZXIgR2FzIGFuZCBNYXggUHJpb3JpdHkgRmVlIFBlciBHYXNcbiAgICAgICAgICAgICAgdXNlcktleTogcGFyYW1zLnVzZXJLZXksIC8vIFByb3ZpZGUgdGhlIHVzZXJLZXlcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LCAvLyBQcm92aWRlIHRoZSBiYWNrdXBLZXlcbiAgICAgICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLCAvLyBQcm92aWRlIHRoZSB3YWxsZXRDb250cmFjdEFkZHJlc3NcbiAgICAgICAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICAgICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgY2hhaW46ICc0MicsXG4gICAgICAgICAgICAgICAgaGFyZGZvcms6ICdsb25kb24nLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBFcnJvcixcbiAgICAgICAgICAnRXJyb3I6IGludmFsaWQgYWRkcmVzcydcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVjb3ZlcnlCbG9ja2NoYWluRXhwbG9yZXJRdWVyeScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIG92ZXJyaWRlIHRoZSB0b2tlbiBwYXJhbWV0ZXIgd2l0aCBhIGN1c3RvbSBBUEkga2V5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKSBhcyBUZXRoO1xuICAgICAgY29uc3QgcXVlcnkgPSB7XG4gICAgICAgIG1vZHVsZTogJ2FjY291bnQnLFxuICAgICAgICBhY3Rpb246ICdiYWxhbmNlJyxcbiAgICAgICAgYWRkcmVzczogJzB4MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgY3VzdG9tQXBpS2V5ID0gJ2N1c3RvbS1hcGkta2V5LWZvci10ZXN0JztcblxuICAgICAgLy8gTW9jayB0aGUgZW52aXJvbm1lbnQgQVBJIHRva2VuXG4gICAgICBjb25zdCBvcmlnaW5hbEFwaVRva2VuID0gY29tbW9uLkVudmlyb25tZW50cy50ZXN0LmV0aGVyc2NhbkFwaVRva2VuO1xuICAgICAgY29tbW9uLkVudmlyb25tZW50cy50ZXN0LmV0aGVyc2NhbkFwaVRva2VuID0gJ2RlZmF1bHQtZW52aXJvbm1lbnQtYXBpLWtleSc7XG5cbiAgICAgIC8vIE1vY2sgdGhlIHJlcXVlc3QuZ2V0IGZ1bmN0aW9uIHRvIGNhcHR1cmUgdGhlIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgICAgIGNvbnN0IG9yaWdpbmFsR2V0ID0gcmVxdWVzdC5nZXQ7XG4gICAgICBsZXQgY2FwdHVyZWRRdWVyeTtcblxuICAgICAgcmVxdWVzdC5nZXQgPSBmdW5jdGlvbiAodXJsOiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBxdWVyeTogZnVuY3Rpb24gKHBhcmFtczogUmVjb3JkPHN0cmluZywgYW55Pikge1xuICAgICAgICAgICAgY2FwdHVyZWRRdWVyeSA9IHBhcmFtcztcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIG9rOiB0cnVlLFxuICAgICAgICAgICAgICBib2R5OiB7IHJlc3VsdDogJzEwMDAwMDAwMCcgfSxcbiAgICAgICAgICAgIH0gYXMgYW55O1xuICAgICAgICAgIH0sXG4gICAgICAgIH0gYXMgYW55O1xuICAgICAgfTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gQ2FsbCB3aXRoIGRlZmF1bHQgQVBJIGtleVxuICAgICAgICBhd2FpdCBjb2luLnJlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnkocXVlcnkpO1xuICAgICAgICBjYXB0dXJlZFF1ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhcGlrZXknLCAnZGVmYXVsdC1lbnZpcm9ubWVudC1hcGkta2V5Jyk7XG5cbiAgICAgICAgLy8gQ2FsbCB3aXRoIGN1c3RvbSBBUEkga2V5XG4gICAgICAgIGF3YWl0IGNvaW4ucmVjb3ZlcnlCbG9ja2NoYWluRXhwbG9yZXJRdWVyeShxdWVyeSwgY3VzdG9tQXBpS2V5KTtcbiAgICAgICAgY2FwdHVyZWRRdWVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYXBpa2V5JywgY3VzdG9tQXBpS2V5KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIC8vIFJlc3RvcmUgb3JpZ2luYWwgZnVuY3Rpb24gYW5kIEFQSSB0b2tlblxuICAgICAgICByZXF1ZXN0LmdldCA9IG9yaWdpbmFsR2V0O1xuICAgICAgICBjb21tb24uRW52aXJvbm1lbnRzLnRlc3QuZXRoZXJzY2FuQXBpVG9rZW4gPSBvcmlnaW5hbEFwaVRva2VuO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXVkaXQgS2V5JywgKCkgPT4ge1xuICAgIGxldCBjb2luOiBIdGV0aDtcbiAgICBiZWZvcmUoKCkgPT4ge1xuICAgICAgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnTXVsdGlTaWcnLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGtleSB9ID0gZXRoTXVsdGlTaWdCYWNrdXBLZXk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIHsgaXNWYWxpZDogdHJ1ZSB9IGZvciB2YWxpZCBpbnB1dHMnLCAoKSA9PiB7XG4gICAgICAgIGNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgZW5jcnlwdGVkUHJ2OiBrZXksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ1pROE1oeFQ4NG00UCcsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgdGhlIHdhbGxldFBhc3NwaHJhc2UgaXMgaW5jb3JyZWN0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgY29pbi5hc3NlcnRJc1ZhbGlkS2V5KHtcbiAgICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBrZXksXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmb28nLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgeyBtZXNzYWdlOiAnZmFpbGVkIHRvIGRlY3J5cHQgcHJ2OiBkZWNyeXB0OiBjaXBoZXJ0ZXh0IGlzIG5vdCB2YWxpZCBKU09OJyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBpZiB0aGUga2V5IGlzIGFsdGVyZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFsdGVyZWRLZXkgPSBrZXkucmVwbGFjZSgvWzAtOV0vZywgJzAnKTtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgIGNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICAgIGVuY3J5cHRlZFBydjogYWx0ZXJlZEtleSxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2tBbVtFRlE2bz1TeGxjTEZEdyUsJyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIHsgbWVzc2FnZTogJ2ZhaWxlZCB0byBkZWNyeXB0IHBydjogZGVjcnlwdDogY2lwaGVydGV4dCBpcyBub3QgdmFsaWQgSlNPTicgfVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnVFNTJywgKCkgPT4ge1xuICAgICAgY29uc3QgeyBrZXk6IGtleVN0cmluZywgY29tbW9uS2V5Y2hhaW4gfSA9IGV0aFRzc0JhY2t1cEtleTtcbiAgICAgIGNvbnN0IGtleSA9IGtleVN0cmluZy5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICdrQW1bRUZRNm89U3hsY0xGRHclLCc7XG4gICAgICBjb25zdCBtdWx0aVNpZ1R5cGUgPSAndHNzJztcblxuICAgICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgZm9yIHZhbGlkIGlucHV0cycsICgpID0+IHtcbiAgICAgICAgY29pbi5hc3NlcnRJc1ZhbGlkS2V5KHtcbiAgICAgICAgICBlbmNyeXB0ZWRQcnY6IGtleSxcbiAgICAgICAgICBwdWJsaWNLZXk6IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgbXVsdGlTaWdUeXBlLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZSBjb21tb25LZXljaGFpbiBpcyBhbHRlcmVkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBhbHRlcmVkQ29tbW9uS2V5Y2hhaW4gPSBnZW5lcmF0ZVJhbmRvbVBhc3N3b3JkKDEwKTtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgIGNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICAgIGVuY3J5cHRlZFBydjoga2V5LFxuICAgICAgICAgICAgICBwdWJsaWNLZXk6IGFsdGVyZWRDb21tb25LZXljaGFpbixcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgbXVsdGlTaWdUeXBlLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgeyBtZXNzYWdlOiAnSW52YWxpZCBjb21tb24ga2V5Y2hhaW4nIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGlmIHRoZSB3YWxsZXRQYXNzcGhyYXNlIGlzIGluY29ycmVjdCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5jb3JyZWN0UGFzc3BocmFzZSA9ICdmb28nO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgY29pbi5hc3NlcnRJc1ZhbGlkS2V5KHtcbiAgICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBrZXksXG4gICAgICAgICAgICAgIHB1YmxpY0tleTogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IGluY29ycmVjdFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIG11bHRpU2lnVHlwZSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIHsgbWVzc2FnZTogJ2ZhaWxlZCB0byBkZWNyeXB0IHBydjogaW5jb3JyZWN0IHBhc3N3b3JkJyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBpZiB0aGUga2V5IGlzIGFsdGVyZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFsdGVyZWRLZXkgPSBrZXkucmVwbGFjZSgvWzAtOV0vZywgJzAnKTtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgIGNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICAgIGVuY3J5cHRlZFBydjogYWx0ZXJlZEtleSxcbiAgICAgICAgICAgICAgcHVibGljS2V5OiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgbXVsdGlTaWdUeXBlLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgeyBtZXNzYWdlOiAnZmFpbGVkIHRvIGRlY3J5cHQgcHJ2OiBkZWNyeXB0OiBjaXBoZXJ0ZXh0IGlzIG5vdCB2YWxpZCBKU09OJyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldFNpZ25hYmxlUGF5bG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgY29pbjogVGV0aDtcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBjb2luID0gYml0Z28uY29pbigndGV0aCcpIGFzIFRldGg7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBhIDMyLWJ5dGUga2VjY2FrMjU2IGhhc2ggZm9yIGEgTGVnYWN5IHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIHR4QnVpbGRlci5mZWUoeyBmZWU6ICcxMDAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnNzAwMDAwMCcgfSk7XG4gICAgICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgICAgIHR4QnVpbGRlci5jb250cmFjdCgnMHg4Q2U1OWMyZDE3MDI4NDRGOEVkRUQ0NTFBQTEwMzk2MWJDMzdCNGU4Jyk7XG4gICAgICBjb25zdCB0cmFuc2ZlckJ1aWxkZXIgPSB0eEJ1aWxkZXIudHJhbnNmZXIoKSBhcyBUcmFuc2ZlckJ1aWxkZXI7XG4gICAgICB0cmFuc2ZlckJ1aWxkZXJcbiAgICAgICAgLmNvaW4oJ3RldGgnKVxuICAgICAgICAuZXhwaXJhdGlvblRpbWUoTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCkgKyAzNjAwKVxuICAgICAgICAuYW1vdW50KCcxMDAwMDAnKVxuICAgICAgICAudG8oJzB4ZWVhZjBGMDVmMzc4OTFhYjRhMjEyMDhCMTA1QTA2ODdkMTJjNWFGNycpXG4gICAgICAgIC5jb250cmFjdFNlcXVlbmNlSWQoMSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFR4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgcGF5bG9hZCA9IGF3YWl0IGNvaW4uZ2V0U2lnbmFibGVQYXlsb2FkKHNlcmlhbGl6ZWRUeCk7XG4gICAgICBhc3NlcnQub2soQnVmZmVyLmlzQnVmZmVyKHBheWxvYWQpKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXlsb2FkLmxlbmd0aCwgMzIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gYSAzMi1ieXRlIGtlY2NhazI1NiBoYXNoIGZvciBhbiBFSVAxNTU5IHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIHR4QnVpbGRlci5mZWUoe1xuICAgICAgICBmZWU6ICcyODAwMDAwMDAwMDAnLFxuICAgICAgICBnYXNMaW1pdDogJzcwMDAwMDAnLFxuICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogJzc1OTMxMjMnLCBtYXhQcmlvcml0eUZlZVBlckdhczogJzE1MCcgfSxcbiAgICAgIH0pO1xuICAgICAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgICB0eEJ1aWxkZXIuY29udHJhY3QoJzB4OENlNTljMmQxNzAyODQ0RjhFZEVENDUxQUExMDM5NjFiQzM3QjRlOCcpO1xuICAgICAgY29uc3QgdHJhbnNmZXJCdWlsZGVyID0gdHhCdWlsZGVyLnRyYW5zZmVyKCkgYXMgVHJhbnNmZXJCdWlsZGVyO1xuICAgICAgdHJhbnNmZXJCdWlsZGVyXG4gICAgICAgIC5jb2luKCd0ZXRoJylcbiAgICAgICAgLmV4cGlyYXRpb25UaW1lKE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApICsgMzYwMClcbiAgICAgICAgLmFtb3VudCgnMTAwMDAwJylcbiAgICAgICAgLnRvKCcweGVlYWYwRjA1ZjM3ODkxYWI0YTIxMjA4QjEwNUEwNjg3ZDEyYzVhRjcnKVxuICAgICAgICAuY29udHJhY3RTZXF1ZW5jZUlkKDEpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCBjb2luLmdldFNpZ25hYmxlUGF5bG9hZChzZXJpYWxpemVkVHgpO1xuICAgICAgYXNzZXJ0Lm9rKEJ1ZmZlci5pc0J1ZmZlcihwYXlsb2FkKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGF5bG9hZC5sZW5ndGgsIDMyKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEVSQy03OTg0IHRva2VuIGVuYWJsZW1lbnQg4oCUIG11bHRpc2lnIHZlcmlmeVRyYW5zYWN0aW9uIChhbGwgc2NlbmFyaW9zKVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ3ZlcmlmeVRyYW5zYWN0aW9uIOKAkyBFUkMtNzk4NCBlbmFibGV0b2tlbiAobXVsdGlzaWcgd2FsbGV0KScsIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBodGV0aCBaYW1hIEFDTCBjb250cmFjdCAoTmV0d29ya3MudGVzdC5ob29kaS56YW1hQWNsQ29udHJhY3RBZGRyZXNzKVxuICAgIGNvbnN0IFpBTUFfQUNMX0FERFJFU1MgPSAnMHg2ZDNmYWY2Zjg2ZTFmZjlmM2IwODMxZGRhOTIwYWJhMWNiZDViZDY4JztcbiAgICAvLyBTaW11bGF0ZWQgd2FsbGV0IGJhc2UgYWRkcmVzcyAod2hhdCB0aGUgY2xpZW50IHNlbmRzIGFzIHRoZSByZWNpcGllbnQgZm9yIGJhc2UtYWRkcmVzcyB3YWxsZXRzKVxuICAgIGNvbnN0IFdBTExFVF9CQVNFX0FERFJFU1MgPSAnMHgwOGU2NzM2ZTg3NmQ3NzJkMmZhOGY4MDNhMDc2Y2Q2YzlmODQ1NTQ2JztcbiAgICAvLyBTaW11bGF0ZWQgZm9yd2FyZGVyIGFkZHJlc3MgKHdoYXQgdGhlIGNsaWVudCBzZW5kcyBhcyByZWNpcGllbnQgZm9yIGZvcndhcmRlciB3YWxsZXRzKVxuICAgIGNvbnN0IEZPUldBUkRFUl9BRERSRVNTID0gJzB4MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MCc7XG4gICAgY29uc3QgV1JPTkdfQUREUkVTUyA9ICcweGFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEnO1xuXG4gICAgY29uc3QgbWFrZVByZWJ1aWxkID0gKHJlY2lwaWVudEFkZHJlc3M6IHN0cmluZykgPT4gKHtcbiAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IHJlY2lwaWVudEFkZHJlc3MsIGFtb3VudDogJzAnIH1dLFxuICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgIGdhc0xpbWl0OiAzMDAwMDAsXG4gICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgfSk7XG5cbiAgICAvLyDilIDilIAgQmFzZS1hZGRyZXNzIHdhbGxldCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAgIGl0KCdiYXNlLWFkZHJlc3MsIHNpbmdsZSB0b2tlbjogdHhQYXJhbXMg4oaSIHdhbGxldEJhc2UsIHR4UHJlYnVpbGQg4oaSIEFDTCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGh0ZXRoQ29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBodGV0aENvaW4sIHsgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTIH0gfSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGh0ZXRoQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTLCBhbW91bnQ6ICcwJywgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgfSBhcyBhbnksXG4gICAgICAgIHR4UHJlYnVpbGQ6IG1ha2VQcmVidWlsZChaQU1BX0FDTF9BRERSRVNTKSBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdiYXNlLWFkZHJlc3MsIG11bHRpLXRva2VuOiBtdWx0aXBsZSB0eFBhcmFtcyByZWNpcGllbnRzIChzYW1lIGJhc2UgYWRkcmVzcyksIHR4UHJlYnVpbGQg4oaSIEFDTCBtdWx0aWNhbGwnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBodGV0aENvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgaHRldGhDb2luLCB7IGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogV0FMTEVUX0JBU0VfQUREUkVTUyB9IH0pO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBodGV0aENvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgeyBhZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTLCBhbW91bnQ6ICcwJywgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJyB9LFxuICAgICAgICAgICAgeyBhZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTLCBhbW91bnQ6ICcwJywgdG9rZW5OYW1lOiAnaHRldGg6Y3VzZHQnIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSBhcyBhbnksXG4gICAgICAgIHR4UHJlYnVpbGQ6IG1ha2VQcmVidWlsZChaQU1BX0FDTF9BRERSRVNTKSBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIC8vIOKUgOKUgCBGb3J3YXJkZXIgd2FsbGV0IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgaXQoJ2ZvcndhcmRlciwgc2luZ2xlIHRva2VuOiB0eFBhcmFtcyDihpIgZm9yd2FyZGVyLCB0eFByZWJ1aWxkIOKGkiBmb3J3YXJkZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBodGV0aENvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgaHRldGhDb2luLCB7IGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogV0FMTEVUX0JBU0VfQUREUkVTUyB9IH0pO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBodGV0aENvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogRk9SV0FSREVSX0FERFJFU1MsIGFtb3VudDogJzAnLCB0b2tlbk5hbWU6ICdodGV0aDpjdGVzdDEnIH1dLFxuICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgdHhQcmVidWlsZDogbWFrZVByZWJ1aWxkKEZPUldBUkRFUl9BRERSRVNTKSBhcyBhbnksXG4gICAgICAgIHdhbGxldCxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdmb3J3YXJkZXIsIG11bHRpLXRva2VuOiBtdWx0aXBsZSB0eFBhcmFtcyByZWNpcGllbnRzIChzYW1lIGZvcndhcmRlciksIHR4UHJlYnVpbGQg4oaSIGZvcndhcmRlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGh0ZXRoQ29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBodGV0aENvaW4sIHsgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTIH0gfSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGh0ZXRoQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICB7IGFkZHJlc3M6IEZPUldBUkRFUl9BRERSRVNTLCBhbW91bnQ6ICcwJywgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJyB9LFxuICAgICAgICAgICAgeyBhZGRyZXNzOiBGT1JXQVJERVJfQUREUkVTUywgYW1vdW50OiAnMCcsIHRva2VuTmFtZTogJ2h0ZXRoOmN1c2R0JyB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiBtYWtlUHJlYnVpbGQoRk9SV0FSREVSX0FERFJFU1MpIGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgfSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgLy8g4pSA4pSAIE5lZ2F0aXZlIGNhc2VzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHR4UHJlYnVpbGQgcmVjaXBpZW50IGlzIG5laXRoZXIgdGhlIEFDTCBjb250cmFjdCBub3IgdGhlIGZvcndhcmRlciBmcm9tIHR4UGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaHRldGhDb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGh0ZXRoQ29pbiwgeyBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IFdBTExFVF9CQVNFX0FERFJFU1MgfSB9KTtcblxuICAgICAgYXdhaXQgaHRldGhDb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTLCBhbW91bnQ6ICcwJywgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBtYWtlUHJlYnVpbGQoV1JPTkdfQUREUkVTUykgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3Rva2VuIGVuYWJsZW1lbnQgdHhQcmVidWlsZCByZWNpcGllbnQgbXVzdCBiZS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHR4UGFyYW1zIHJlY2lwaWVudHMgaGF2ZSBkaWZmZXJlbnQgYWRkcmVzc2VzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaHRldGhDb2luID0gYml0Z28uY29pbignaHRldGgnKSBhcyBIdGV0aDtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGh0ZXRoQ29pbiwgeyBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IFdBTExFVF9CQVNFX0FERFJFU1MgfSB9KTtcblxuICAgICAgYXdhaXQgaHRldGhDb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHsgYWRkcmVzczogV0FMTEVUX0JBU0VfQUREUkVTUywgYW1vdW50OiAnMCcsIHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScgfSxcbiAgICAgICAgICAgICAgeyBhZGRyZXNzOiBGT1JXQVJERVJfQUREUkVTUywgYW1vdW50OiAnMCcsIHRva2VuTmFtZTogJ2h0ZXRoOmN1c2R0JyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBtYWtlUHJlYnVpbGQoWkFNQV9BQ0xfQUREUkVTUykgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL211c3QgYWxsIGhhdmUgdGhlIHNhbWUgYWRkcmVzcy8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGEgdHhQYXJhbXMgcmVjaXBpZW50IGhhcyBub24temVybyBhbW91bnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBodGV0aENvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpIGFzIEh0ZXRoO1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgaHRldGhDb2luLCB7IGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogV0FMTEVUX0JBU0VfQUREUkVTUyB9IH0pO1xuXG4gICAgICBhd2FpdCBodGV0aENvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFdBTExFVF9CQVNFX0FERFJFU1MsIGFtb3VudDogJzEwMCcsIHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogbWFrZVByZWJ1aWxkKFpBTUFfQUNMX0FERFJFU1MpIGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9tdXN0IGFsbCBoYXZlIGFtb3VudCAwLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHhQcmVidWlsZCByZWNpcGllbnQgaGFzIG5vbi16ZXJvIGFtb3VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGh0ZXRoQ29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoJykgYXMgSHRldGg7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBodGV0aENvaW4sIHsgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzOiBXQUxMRVRfQkFTRV9BRERSRVNTIH0gfSk7XG5cbiAgICAgIGF3YWl0IGh0ZXRoQ29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogV0FMTEVUX0JBU0VfQUREUkVTUywgYW1vdW50OiAnMCcsIHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogWkFNQV9BQ0xfQUREUkVTUywgYW1vdW50OiAnNTAwJyB9XSxcbiAgICAgICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICAgIH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2V4cGVjdGVkIGFtb3VudCAwIGluIHR4UHJlYnVpbGQvKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|