@bitgo-beta/sdk-coin-polyx 1.0.1-beta.13 → 1.0.1-beta.1300
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/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/lib/baseBuilder.d.ts +24 -0
- package/dist/src/lib/baseBuilder.d.ts.map +1 -0
- package/dist/src/lib/baseBuilder.js +31 -0
- package/dist/src/lib/batchStakingBuilder.d.ts +79 -0
- package/dist/src/lib/batchStakingBuilder.d.ts.map +1 -0
- package/dist/src/lib/batchStakingBuilder.js +302 -0
- package/dist/src/lib/batchUnstakingBuilder.d.ts +39 -0
- package/dist/src/lib/batchUnstakingBuilder.d.ts.map +1 -0
- package/dist/src/lib/batchUnstakingBuilder.js +129 -0
- package/dist/src/lib/bondExtraBuilder.d.ts +37 -0
- package/dist/src/lib/bondExtraBuilder.d.ts.map +1 -0
- package/dist/src/lib/bondExtraBuilder.js +103 -0
- package/dist/src/lib/constants.d.ts +21 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +24 -0
- package/dist/src/lib/hexTokenTransferBuilder.d.ts +24 -0
- package/dist/src/lib/hexTokenTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/hexTokenTransferBuilder.js +46 -0
- package/dist/src/lib/hexTransferBuilder.d.ts +28 -0
- package/dist/src/lib/hexTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/hexTransferBuilder.js +51 -0
- package/dist/src/lib/iface.d.ts +252 -2
- package/dist/src/lib/iface.d.ts.map +1 -1
- package/dist/src/lib/iface.js +48 -1
- package/dist/src/lib/index.d.ts +40 -7
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +86 -36
- package/dist/src/lib/nominateBuilder.d.ts +18 -0
- package/dist/src/lib/nominateBuilder.d.ts.map +1 -0
- package/dist/src/lib/nominateBuilder.js +101 -0
- package/dist/src/lib/preApproveAssetBuilder.d.ts +33 -0
- package/dist/src/lib/preApproveAssetBuilder.d.ts.map +1 -0
- package/dist/src/lib/preApproveAssetBuilder.js +77 -0
- package/dist/src/lib/registerDidWithCDDBuilder.d.ts +34 -0
- package/dist/src/lib/registerDidWithCDDBuilder.d.ts.map +1 -0
- package/dist/src/lib/registerDidWithCDDBuilder.js +86 -0
- package/dist/src/lib/rejectInstructionBuilder.d.ts +29 -0
- package/dist/src/lib/rejectInstructionBuilder.d.ts.map +1 -0
- package/dist/src/lib/rejectInstructionBuilder.js +89 -0
- package/dist/src/lib/tokenTransferBuilder.d.ts +64 -0
- package/dist/src/lib/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/tokenTransferBuilder.js +167 -0
- package/dist/src/lib/transaction.d.ts +26 -4
- package/dist/src/lib/transaction.d.ts.map +1 -1
- package/dist/src/lib/transaction.js +201 -7
- package/dist/src/lib/transactionBuilderFactory.d.ts +67 -5
- package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilderFactory.js +323 -8
- package/dist/src/lib/transferBuilder.d.ts +51 -3
- package/dist/src/lib/transferBuilder.d.ts.map +1 -1
- package/dist/src/lib/transferBuilder.js +111 -3
- package/dist/src/lib/txnSchema.d.ts +70 -0
- package/dist/src/lib/txnSchema.d.ts.map +1 -0
- package/dist/src/lib/txnSchema.js +244 -0
- package/dist/src/lib/unbondBuilder.d.ts +37 -0
- package/dist/src/lib/unbondBuilder.d.ts.map +1 -0
- package/dist/src/lib/unbondBuilder.js +100 -0
- package/dist/src/lib/utils.d.ts +44 -14
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +95 -20
- package/dist/src/lib/v8BatchStakingBuilder.d.ts +85 -0
- package/dist/src/lib/v8BatchStakingBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8BatchStakingBuilder.js +266 -0
- package/dist/src/lib/v8BatchUnstakingBuilder.d.ts +11 -0
- package/dist/src/lib/v8BatchUnstakingBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8BatchUnstakingBuilder.js +21 -0
- package/dist/src/lib/v8BondExtraBuilder.d.ts +11 -0
- package/dist/src/lib/v8BondExtraBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8BondExtraBuilder.js +21 -0
- package/dist/src/lib/v8HexTokenTransferBuilder.d.ts +20 -0
- package/dist/src/lib/v8HexTokenTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8HexTokenTransferBuilder.js +42 -0
- package/dist/src/lib/v8HexTransferBuilder.d.ts +11 -0
- package/dist/src/lib/v8HexTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8HexTransferBuilder.js +21 -0
- package/dist/src/lib/v8NominateBuilder.d.ts +11 -0
- package/dist/src/lib/v8NominateBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8NominateBuilder.js +21 -0
- package/dist/src/lib/v8PreApproveAssetBuilder.d.ts +11 -0
- package/dist/src/lib/v8PreApproveAssetBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8PreApproveAssetBuilder.js +21 -0
- package/dist/src/lib/v8RegisterDidBuilder.d.ts +47 -0
- package/dist/src/lib/v8RegisterDidBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8RegisterDidBuilder.js +96 -0
- package/dist/src/lib/v8RegisterDidWithCDDBuilder.d.ts +11 -0
- package/dist/src/lib/v8RegisterDidWithCDDBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8RegisterDidWithCDDBuilder.js +21 -0
- package/dist/src/lib/v8TokenTransferBuilder.d.ts +24 -0
- package/dist/src/lib/v8TokenTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8TokenTransferBuilder.js +101 -0
- package/dist/src/lib/v8TransferBuilder.d.ts +11 -0
- package/dist/src/lib/v8TransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8TransferBuilder.js +21 -0
- package/dist/src/lib/v8UnbondBuilder.d.ts +11 -0
- package/dist/src/lib/v8UnbondBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8UnbondBuilder.js +21 -0
- package/dist/src/lib/v8WithdrawUnbondedBuilder.d.ts +11 -0
- package/dist/src/lib/v8WithdrawUnbondedBuilder.d.ts.map +1 -0
- package/dist/src/lib/v8WithdrawUnbondedBuilder.js +21 -0
- package/dist/src/lib/withdrawUnbondedBuilder.d.ts +35 -0
- package/dist/src/lib/withdrawUnbondedBuilder.d.ts.map +1 -0
- package/dist/src/lib/withdrawUnbondedBuilder.js +91 -0
- package/dist/src/polyx.d.ts +51 -9
- package/dist/src/polyx.d.ts.map +1 -1
- package/dist/src/polyx.js +296 -16
- package/dist/src/polyxToken.d.ts +20 -0
- package/dist/src/polyxToken.d.ts.map +1 -0
- package/dist/src/polyxToken.js +55 -0
- package/dist/src/register.d.ts.map +1 -1
- package/dist/src/register.js +5 -1
- package/dist/src/resources/index.d.ts +5 -0
- package/dist/src/resources/index.d.ts.map +1 -0
- package/dist/src/resources/index.js +21 -0
- package/dist/src/resources/mainnet.d.ts +13 -0
- package/dist/src/resources/mainnet.d.ts.map +1 -0
- package/dist/src/resources/mainnet.js +16 -0
- package/dist/src/resources/mainnetV8.d.ts +13 -0
- package/dist/src/resources/mainnetV8.d.ts.map +1 -0
- package/dist/src/resources/mainnetV8.js +24 -0
- package/dist/src/resources/testnet.d.ts +13 -0
- package/dist/src/resources/testnet.d.ts.map +1 -0
- package/dist/src/resources/testnet.js +16 -0
- package/dist/src/resources/testnetV8.d.ts +13 -0
- package/dist/src/resources/testnetV8.d.ts.map +1 -0
- package/dist/src/resources/testnetV8.js +16 -0
- package/dist/src/tpolyx.d.ts +7 -0
- package/dist/src/tpolyx.d.ts.map +1 -1
- package/dist/src/tpolyx.js +11 -1
- package/dist/test/integration/index.d.ts +1 -0
- package/dist/test/integration/index.d.ts.map +1 -0
- package/dist/test/integration/index.js +1 -0
- package/dist/test/resources/index.d.ts +139 -0
- package/dist/test/resources/index.d.ts.map +1 -0
- package/dist/test/resources/index.js +150 -0
- package/dist/test/resources/mainnet.d.ts +2 -0
- package/dist/test/resources/mainnet.d.ts.map +1 -0
- package/dist/test/resources/mainnet.js +5 -0
- package/dist/test/resources/materialData.json +8 -0
- package/dist/test/resources/materialDataModified.json +8 -0
- package/dist/test/resources/testnet.d.ts +2 -0
- package/dist/test/resources/testnet.d.ts.map +1 -0
- package/dist/test/resources/testnet.js +5 -0
- package/dist/test/resources/wrwUsers.d.ts +19 -0
- package/dist/test/resources/wrwUsers.d.ts.map +1 -0
- package/dist/test/resources/wrwUsers.js +60 -0
- package/dist/test/unit/polyx.d.ts +2 -0
- package/dist/test/unit/polyx.d.ts.map +1 -0
- package/dist/test/unit/polyx.js +603 -0
- package/dist/test/unit/transactionBuilder/base.d.ts +4 -0
- package/dist/test/unit/transactionBuilder/base.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/base.js +245 -0
- package/dist/test/unit/transactionBuilder/batchStakingBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/batchStakingBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/batchStakingBuilder.js +309 -0
- package/dist/test/unit/transactionBuilder/batchUnstakingBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/batchUnstakingBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/batchUnstakingBuilder.js +159 -0
- package/dist/test/unit/transactionBuilder/bondExtraBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/bondExtraBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/bondExtraBuilder.js +158 -0
- package/dist/test/unit/transactionBuilder/hexTokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/hexTokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/hexTokenTransferBuilder.js +261 -0
- package/dist/test/unit/transactionBuilder/hexTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/hexTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/hexTransferBuilder.js +389 -0
- package/dist/test/unit/transactionBuilder/nominateBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/nominateBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/nominateBuilder.js +226 -0
- package/dist/test/unit/transactionBuilder/preApproveAssetBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/preApproveAssetBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/preApproveAssetBuilder.js +115 -0
- package/dist/test/unit/transactionBuilder/registerDidWithCDDBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/registerDidWithCDDBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/registerDidWithCDDBuilder.js +302 -0
- package/dist/test/unit/transactionBuilder/rejectInstructionBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/rejectInstructionBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/rejectInstructionBuilder.js +128 -0
- package/dist/test/unit/transactionBuilder/singletonRegistry.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/singletonRegistry.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/singletonRegistry.js +59 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +140 -0
- package/dist/test/unit/transactionBuilder/transactionBuilderFactory.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/transactionBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/transactionBuilderFactory.js +240 -0
- package/dist/test/unit/transactionBuilder/transferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/transferBuilder.js +326 -0
- package/dist/test/unit/transactionBuilder/unbondBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/unbondBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/unbondBuilder.js +144 -0
- package/dist/test/unit/transactionBuilder/v8BatchStakingBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8BatchStakingBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8BatchStakingBuilder.js +252 -0
- package/dist/test/unit/transactionBuilder/v8HexTokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8HexTokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8HexTokenTransferBuilder.js +90 -0
- package/dist/test/unit/transactionBuilder/v8HexTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8HexTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8HexTransferBuilder.js +62 -0
- package/dist/test/unit/transactionBuilder/v8PreApproveAssetBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8PreApproveAssetBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8PreApproveAssetBuilder.js +45 -0
- package/dist/test/unit/transactionBuilder/v8RegisterDidBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8RegisterDidBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8RegisterDidBuilder.js +87 -0
- package/dist/test/unit/transactionBuilder/v8RegisterDidWithCDDBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8RegisterDidWithCDDBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8RegisterDidWithCDDBuilder.js +45 -0
- package/dist/test/unit/transactionBuilder/v8TokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8TokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8TokenTransferBuilder.js +114 -0
- package/dist/test/unit/transactionBuilder/v8TransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/v8TransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/v8TransferBuilder.js +107 -0
- package/dist/test/unit/transactionBuilder/withdrawUnbondedBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/withdrawUnbondedBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/withdrawUnbondedBuilder.js +138 -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 +143 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +20 -10
- package/.eslintignore +0 -4
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -0
- package/dist/src/lib/keyPair.d.ts +0 -12
- package/dist/src/lib/keyPair.d.ts.map +0 -1
- package/dist/src/lib/keyPair.js +0 -24
- package/dist/src/lib/transactionBuilder.d.ts +0 -43
- package/dist/src/lib/transactionBuilder.d.ts.map +0 -1
- package/dist/src/lib/transactionBuilder.js +0 -78
|
@@ -0,0 +1,603 @@
|
|
|
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 should_1 = __importDefault(require("should"));
|
|
40
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
41
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
42
|
+
const src_1 = require("../../src");
|
|
43
|
+
const constants_1 = require("../../src/lib/constants");
|
|
44
|
+
const utils_1 = __importDefault(require("../../src/lib/utils"));
|
|
45
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
46
|
+
const sinon = __importStar(require("sinon"));
|
|
47
|
+
const testData = __importStar(require("../resources/wrwUsers"));
|
|
48
|
+
const mocha_1 = require("mocha");
|
|
49
|
+
const resources_1 = require("../resources");
|
|
50
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
51
|
+
const lib_1 = require("../../src/lib");
|
|
52
|
+
const resources_2 = require("../../src/resources");
|
|
53
|
+
const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
|
|
54
|
+
describe('Polyx:', function () {
|
|
55
|
+
let bitgo;
|
|
56
|
+
let baseCoin;
|
|
57
|
+
before(function () {
|
|
58
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
59
|
+
bitgo.safeRegister('polyx', src_1.Polyx.createInstance);
|
|
60
|
+
bitgo.safeRegister('tpolyx', src_1.Tpolyx.createInstance);
|
|
61
|
+
bitgo.initializeTestVars();
|
|
62
|
+
baseCoin = bitgo.coin('tpolyx');
|
|
63
|
+
});
|
|
64
|
+
describe('Address Format Constants', function () {
|
|
65
|
+
it('should have the correct address format constants', function () {
|
|
66
|
+
// Verify the constants are defined correctly
|
|
67
|
+
constants_1.POLYX_ADDRESS_FORMAT.should.equal(12);
|
|
68
|
+
constants_1.TPOLYX_ADDRESS_FORMAT.should.equal(42);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('Recover Transactions:', function () {
|
|
72
|
+
const sandBox = sinon.createSandbox();
|
|
73
|
+
const recoveryDestination = '5H56f31hSYGCRV3URjQHv2Cc4ZSkJNHTM8MKGtkkV6hzCqN7';
|
|
74
|
+
const nonce = 0;
|
|
75
|
+
let accountInfoCB;
|
|
76
|
+
let headerInfoCB;
|
|
77
|
+
let getFeeCB;
|
|
78
|
+
let getMaterialCB;
|
|
79
|
+
beforeEach(function () {
|
|
80
|
+
accountInfoCB = sandBox.stub(src_1.Polyx.prototype, 'getAccountInfo');
|
|
81
|
+
headerInfoCB = sandBox.stub(src_1.Polyx.prototype, 'getHeaderInfo');
|
|
82
|
+
getFeeCB = sandBox.stub(src_1.Polyx.prototype, 'getFee');
|
|
83
|
+
getMaterialCB = sandBox.stub(src_1.Polyx.prototype, 'getMaterial');
|
|
84
|
+
getMaterialCB.resolves(utils_1.default.getMaterial(statics_1.coins.get('tpolyx').network.type));
|
|
85
|
+
});
|
|
86
|
+
(0, mocha_1.afterEach)(function () {
|
|
87
|
+
sandBox.restore();
|
|
88
|
+
});
|
|
89
|
+
it('should generate unsigned sweep correctly', async function () {
|
|
90
|
+
accountInfoCB
|
|
91
|
+
.withArgs(testData.unsignedSweepUser.walletAddress)
|
|
92
|
+
.resolves({ nonce: 0, freeBalance: 100007000000 });
|
|
93
|
+
headerInfoCB.resolves({
|
|
94
|
+
headerNumber: testData.testnetBlock.blockNumber,
|
|
95
|
+
headerHash: testData.testnetBlock.hash,
|
|
96
|
+
});
|
|
97
|
+
getFeeCB.withArgs(recoveryDestination, testData.unsignedSweepUser.walletAddress, 100007000000).resolves(74401);
|
|
98
|
+
const commonKeyChain = testData.unsignedSweepUser.bitgoKey;
|
|
99
|
+
const unsigned = await baseCoin.recover({ bitgoKey: commonKeyChain, recoveryDestination });
|
|
100
|
+
unsigned.txRequests.should.not.be.undefined();
|
|
101
|
+
unsigned.txRequests.length.should.equal(1);
|
|
102
|
+
unsigned.txRequests[0].transactions.length.should.equal(1);
|
|
103
|
+
unsigned.txRequests[0].walletCoin.should.equal('tpolyx');
|
|
104
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.should.not.be.undefined();
|
|
105
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.serializedTx.should.not.be.undefined();
|
|
106
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.scanIndex.should.equal(0);
|
|
107
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.coin.should.equal('tpolyx');
|
|
108
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.signableHex.should.not.be.undefined();
|
|
109
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.derivationPath.should.equal('m/0');
|
|
110
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.should.not.be.undefined();
|
|
111
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs.should.not.be.undefined();
|
|
112
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs.length.should.equal(1);
|
|
113
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs[0].address.should.equal('5DnZQqbxtB3CWkLgfA6wpqdkCd9Bq7AX49RpLPJwW9mzoT7s');
|
|
114
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs[0].valueString.should.equal('100006255990');
|
|
115
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs[0].value.should.equal(100006255990);
|
|
116
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs.should.not.be.undefined();
|
|
117
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs.length.should.equal(1);
|
|
118
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs[0].address.should.equal('5H56f31hSYGCRV3URjQHv2Cc4ZSkJNHTM8MKGtkkV6hzCqN7');
|
|
119
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs[0].valueString.should.equal('100006255990');
|
|
120
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs[0].coinName.should.equal('tpolyx');
|
|
121
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.parsedTx.type.should.equal('');
|
|
122
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.feeInfo.should.not.be.undefined();
|
|
123
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.feeInfo.fee.should.equal(0);
|
|
124
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.feeInfo.feeString.should.equal('0');
|
|
125
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.should.not.be.undefined();
|
|
126
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.firstValid.should.not.be.undefined();
|
|
127
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.maxDuration.should.equal(2400);
|
|
128
|
+
unsigned.txRequests[0].transactions[0].unsignedTx.coinSpecific.commonKeychain.should.equal('97d9da8bf544d07f3c7ae8ee06bb12a63f74478d0c461201ab94421a9c81d5b379553f0332daaa85cb8c65e1fe7e6907c62268c00812b08a4e1361178e304ddb');
|
|
129
|
+
});
|
|
130
|
+
it('should recover a tx for non-bitgo recoveries', async function () {
|
|
131
|
+
accountInfoCB.withArgs(testData.wrwUser.walletAddress).resolves({ nonce: 0, freeBalance: 100007000000 });
|
|
132
|
+
headerInfoCB.resolves({
|
|
133
|
+
headerNumber: testData.testnetBlock.blockNumber,
|
|
134
|
+
headerHash: testData.testnetBlock.hash,
|
|
135
|
+
});
|
|
136
|
+
getFeeCB.withArgs(recoveryDestination, testData.wrwUser.walletAddress, 100007000000).resolves(74401);
|
|
137
|
+
const res = await baseCoin.recover({
|
|
138
|
+
userKey: testData.wrwUser.userKey,
|
|
139
|
+
backupKey: testData.wrwUser.backupKey,
|
|
140
|
+
bitgoKey: testData.wrwUser.bitgoKey,
|
|
141
|
+
walletPassphrase: testData.wrwUser.walletPassphrase,
|
|
142
|
+
recoveryDestination: recoveryDestination,
|
|
143
|
+
});
|
|
144
|
+
res.should.not.be.empty();
|
|
145
|
+
res.should.hasOwnProperty('serializedTx');
|
|
146
|
+
res.should.hasOwnProperty('scanIndex');
|
|
147
|
+
const txBuilder = baseCoin.getBuilder().from(res.serializedTx);
|
|
148
|
+
txBuilder
|
|
149
|
+
.validity({
|
|
150
|
+
firstValid: testData.testnetBlock.blockNumber,
|
|
151
|
+
maxDuration: baseCoin.SWEEP_TXN_DURATION,
|
|
152
|
+
})
|
|
153
|
+
.referenceBlock(testData.testnetBlock.hash);
|
|
154
|
+
const tx = await txBuilder.build();
|
|
155
|
+
const txJson = tx.toJson();
|
|
156
|
+
should_1.default.deepEqual(txJson.sender, testData.wrwUser.walletAddress);
|
|
157
|
+
should_1.default.deepEqual(txJson.blockNumber, testData.testnetBlock.blockNumber);
|
|
158
|
+
should_1.default.deepEqual(txJson.referenceBlock, testData.testnetBlock.hash);
|
|
159
|
+
should_1.default.deepEqual(txJson.genesisHash, resources_1.genesisHash);
|
|
160
|
+
should_1.default.deepEqual(txJson.specVersion, resources_1.specVersion);
|
|
161
|
+
should_1.default.deepEqual(txJson.nonce, nonce);
|
|
162
|
+
should_1.default.deepEqual(txJson.tip, 0);
|
|
163
|
+
should_1.default.deepEqual(txJson.transactionVersion, resources_1.txVersion);
|
|
164
|
+
should_1.default.deepEqual(txJson.eraPeriod, baseCoin.SWEEP_TXN_DURATION);
|
|
165
|
+
});
|
|
166
|
+
it('should recover a txn for unsigned-sweep recoveries', async function () {
|
|
167
|
+
accountInfoCB
|
|
168
|
+
.withArgs(testData.unsignedSweepUser.walletAddress)
|
|
169
|
+
.resolves({ nonce: 0, freeBalance: 100007000000 });
|
|
170
|
+
headerInfoCB.resolves({
|
|
171
|
+
headerNumber: testData.testnetBlock.blockNumber,
|
|
172
|
+
headerHash: testData.testnetBlock.hash,
|
|
173
|
+
});
|
|
174
|
+
getFeeCB.withArgs(recoveryDestination, testData.unsignedSweepUser.walletAddress, 100007000000).resolves(74401);
|
|
175
|
+
const res = await baseCoin.recover({
|
|
176
|
+
bitgoKey: testData.unsignedSweepUser.bitgoKey,
|
|
177
|
+
recoveryDestination: recoveryDestination,
|
|
178
|
+
});
|
|
179
|
+
res.should.not.be.empty();
|
|
180
|
+
res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
|
|
181
|
+
res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('scanIndex');
|
|
182
|
+
const txBuilder = baseCoin.getBuilder().from(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
|
|
183
|
+
txBuilder
|
|
184
|
+
.validity({
|
|
185
|
+
firstValid: testData.testnetBlock.blockNumber,
|
|
186
|
+
maxDuration: baseCoin.SWEEP_TXN_DURATION,
|
|
187
|
+
})
|
|
188
|
+
.referenceBlock(testData.testnetBlock.hash)
|
|
189
|
+
.sender({ address: testData.unsignedSweepUser.walletAddress });
|
|
190
|
+
const tx = await txBuilder.build();
|
|
191
|
+
const txJson = tx.toJson();
|
|
192
|
+
should_1.default.deepEqual(txJson.sender, testData.unsignedSweepUser.walletAddress);
|
|
193
|
+
should_1.default.deepEqual(txJson.blockNumber, testData.testnetBlock.blockNumber);
|
|
194
|
+
should_1.default.deepEqual(txJson.referenceBlock, testData.testnetBlock.hash);
|
|
195
|
+
should_1.default.deepEqual(txJson.genesisHash, resources_1.genesisHash);
|
|
196
|
+
should_1.default.deepEqual(txJson.specVersion, resources_1.specVersion);
|
|
197
|
+
should_1.default.deepEqual(txJson.nonce, 0);
|
|
198
|
+
should_1.default.deepEqual(txJson.tip, 0);
|
|
199
|
+
should_1.default.deepEqual(txJson.transactionVersion, resources_1.txVersion);
|
|
200
|
+
should_1.default.deepEqual(txJson.eraPeriod, baseCoin.SWEEP_TXN_DURATION);
|
|
201
|
+
});
|
|
202
|
+
describe('MPCv2 signed recovery', function () {
|
|
203
|
+
const walletPassphrase = 'test-passphrase-mpcv2';
|
|
204
|
+
let mpcV2UserKey;
|
|
205
|
+
let mpcV2BackupKey;
|
|
206
|
+
let mpcV2CommonKeyChain;
|
|
207
|
+
let mpcV2RecoverParams;
|
|
208
|
+
before(async function () {
|
|
209
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
210
|
+
mpcV2CommonKeyChain = userDkg.getCommonKeychain();
|
|
211
|
+
mpcV2UserKey = await (0, sdk_api_1.encrypt)(walletPassphrase, userDkg.getReducedKeyShare().toString('base64'));
|
|
212
|
+
mpcV2BackupKey = await (0, sdk_api_1.encrypt)(walletPassphrase, backupDkg.getReducedKeyShare().toString('base64'));
|
|
213
|
+
mpcV2RecoverParams = {
|
|
214
|
+
userKey: mpcV2UserKey,
|
|
215
|
+
backupKey: mpcV2BackupKey,
|
|
216
|
+
bitgoKey: mpcV2CommonKeyChain,
|
|
217
|
+
recoveryDestination,
|
|
218
|
+
walletPassphrase,
|
|
219
|
+
};
|
|
220
|
+
});
|
|
221
|
+
beforeEach(function () {
|
|
222
|
+
// Use unrestricted resolves (not .withArgs) since the mismatched-bitgoKey test
|
|
223
|
+
// derives a different sender address than mpcV2WalletAddress.
|
|
224
|
+
accountInfoCB.resolves({ nonce: 0, freeBalance: 100007000000 });
|
|
225
|
+
headerInfoCB.resolves({
|
|
226
|
+
headerNumber: testData.testnetBlock.blockNumber,
|
|
227
|
+
headerHash: testData.testnetBlock.hash,
|
|
228
|
+
});
|
|
229
|
+
getFeeCB.resolves(74401);
|
|
230
|
+
});
|
|
231
|
+
it('should recover a tx using MPCv2 signing material', async function () {
|
|
232
|
+
const getTSSSignatureSpy = sandBox.spy(sdk_core_1.EDDSAMethods, 'getTSSSignature');
|
|
233
|
+
const addSignatureSpy = sandBox.spy(lib_1.TransferBuilder.prototype, 'addSignature');
|
|
234
|
+
const result = (await baseCoin.recover(mpcV2RecoverParams));
|
|
235
|
+
result.should.not.be.empty();
|
|
236
|
+
result.should.hasOwnProperty('serializedTx');
|
|
237
|
+
result.should.hasOwnProperty('scanIndex');
|
|
238
|
+
should_1.default.equal(result.scanIndex, 0);
|
|
239
|
+
result.serializedTx.should.be.a.String().and.not.be.empty();
|
|
240
|
+
sandBox.assert.notCalled(getTSSSignatureSpy);
|
|
241
|
+
sandBox.assert.calledOnce(addSignatureSpy);
|
|
242
|
+
const signature = addSignatureSpy.firstCall.args[1];
|
|
243
|
+
// constructSignedPayload prepends the 0x00 Ed25519 discriminant internally;
|
|
244
|
+
// recover() must pass the raw 64-byte signature unchanged.
|
|
245
|
+
signature.length.should.equal(64);
|
|
246
|
+
});
|
|
247
|
+
it('should produce a cryptographically valid Ed25519 signature', async function () {
|
|
248
|
+
const addSignatureSpy = sandBox.spy(lib_1.TransferBuilder.prototype, 'addSignature');
|
|
249
|
+
const signRecoverySpy = sandBox.spy(baseCoin, 'signSubstrateMpcV2Recovery');
|
|
250
|
+
await baseCoin.recover(mpcV2RecoverParams);
|
|
251
|
+
// 65-byte sig: 0x00 discriminant + 64-byte Ed25519 sig; signatureVerify handles the prefix.
|
|
252
|
+
const signature = addSignatureSpy.firstCall.args[1];
|
|
253
|
+
// Capture the exact bytes signed by the DSG protocol inside signSubstrateMpcV2Recovery.
|
|
254
|
+
const signablePayload = signRecoverySpy.firstCall.args[0].message;
|
|
255
|
+
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
256
|
+
const accountId = MPC.deriveUnhardened(mpcV2CommonKeyChain, 'm/0').slice(0, 64);
|
|
257
|
+
const senderAddr = baseCoin.getAddressFromPublicKey(accountId);
|
|
258
|
+
const isValid = utils_1.default.verifySignature(`0x${signablePayload.toString('hex')}`, `0x${signature.toString('hex')}`, senderAddr);
|
|
259
|
+
isValid.should.be.true();
|
|
260
|
+
});
|
|
261
|
+
it('should use MPCv1 path when signing material is MPCv1 format', async function () {
|
|
262
|
+
const userPrv = JSON.stringify({ uShare: { seed: 'aa' }, bitgoYShare: { u: 'bb' }, backupYShare: { u: 'cc' } });
|
|
263
|
+
sandBox
|
|
264
|
+
.stub(baseCoin, 'getEddsaSigningMaterial')
|
|
265
|
+
.resolves({ version: 'v1', userPrv });
|
|
266
|
+
const getTSSSignatureStub = sandBox
|
|
267
|
+
.stub(sdk_core_1.EDDSAMethods, 'getTSSSignature')
|
|
268
|
+
.resolves(Buffer.from('1baafa0d62174bf0c78f3256318613ffc44b6dd54ab1a63c2185232f92ede9da' +
|
|
269
|
+
'e1b2818dbeb52a8215fd56f5a5f2a9f94c079ce89e4dc3b1ce6ed6e84ce71857', 'hex'));
|
|
270
|
+
sandBox
|
|
271
|
+
.stub(bitgo, 'decrypt')
|
|
272
|
+
.withArgs(sinon.match({ input: mpcV2BackupKey.replace(/\s/g, '') }))
|
|
273
|
+
.resolves(JSON.stringify({ bShare: {}, yShares: {} }));
|
|
274
|
+
const result = (await baseCoin.recover(mpcV2RecoverParams));
|
|
275
|
+
result.should.not.be.empty();
|
|
276
|
+
result.should.hasOwnProperty('serializedTx');
|
|
277
|
+
result.should.hasOwnProperty('scanIndex');
|
|
278
|
+
should_1.default.equal(result.scanIndex, 0);
|
|
279
|
+
result.serializedTx.should.be.a.String().and.not.be.empty();
|
|
280
|
+
sandBox.assert.calledOnce(getTSSSignatureStub);
|
|
281
|
+
});
|
|
282
|
+
it('should throw a descriptive error when user keychain decryption fails on the MPCv1 path', async function () {
|
|
283
|
+
sandBox.stub(bitgo, 'decrypt').rejects(new Error('password error'));
|
|
284
|
+
await baseCoin.recover(mpcV2RecoverParams).should.be.rejectedWith(/Error decrypting user keychain/);
|
|
285
|
+
});
|
|
286
|
+
it('should throw when commonKeyChain from MPCv2 keycard does not match bitgoKey', async function () {
|
|
287
|
+
const mismatchedBitgoKey = mpcV2CommonKeyChain.slice(0, -8) + '00000000';
|
|
288
|
+
const mismatchedParams = {
|
|
289
|
+
...mpcV2RecoverParams,
|
|
290
|
+
bitgoKey: mismatchedBitgoKey,
|
|
291
|
+
};
|
|
292
|
+
await baseCoin
|
|
293
|
+
.recover(mismatchedParams)
|
|
294
|
+
.should.be.rejectedWith('EdDSA MPCv2 recovery: commonKeyChain from keycard does not match bitgoKey');
|
|
295
|
+
});
|
|
296
|
+
it('should throw missing userKey when backupKey and walletPassphrase are present but userKey is not', async function () {
|
|
297
|
+
const paramsWithoutUserKey = { ...mpcV2RecoverParams, userKey: undefined };
|
|
298
|
+
await baseCoin.recover(paramsWithoutUserKey).should.be.rejectedWith('missing userKey');
|
|
299
|
+
});
|
|
300
|
+
it('should throw missing backupKey when userKey and walletPassphrase are present but backupKey is not', async function () {
|
|
301
|
+
const paramsWithoutBackupKey = { ...mpcV2RecoverParams, backupKey: undefined };
|
|
302
|
+
await baseCoin.recover(paramsWithoutBackupKey).should.be.rejectedWith('missing backupKey');
|
|
303
|
+
});
|
|
304
|
+
it('should throw missing wallet passphrase when userKey and backupKey are present but walletPassphrase is not', async function () {
|
|
305
|
+
const paramsWithoutPassphrase = { ...mpcV2RecoverParams, walletPassphrase: undefined };
|
|
306
|
+
await baseCoin.recover(paramsWithoutPassphrase).should.be.rejectedWith('missing wallet passphrase');
|
|
307
|
+
});
|
|
308
|
+
it('should pass the raw 64-byte signature to addSignature on MPCv2 path', async function () {
|
|
309
|
+
// Regression: previously wrapped rawSig with a manual Ed25519 discriminant (0x00)
|
|
310
|
+
// before addSignature. constructSignedPayload already prepends that discriminant,
|
|
311
|
+
// so wrapping here caused a double prefix that shifted the on-wire signature by
|
|
312
|
+
// one byte, dropping the last byte of sigma and producing
|
|
313
|
+
// `1010: Bad signature` on-chain.
|
|
314
|
+
const rawSig = Buffer.alloc(64, 0xab);
|
|
315
|
+
sandBox
|
|
316
|
+
.stub(baseCoin, 'signSubstrateMpcV2Recovery')
|
|
317
|
+
.resolves(rawSig);
|
|
318
|
+
const addSignatureSpy = sandBox.spy(lib_1.TransferBuilder.prototype, 'addSignature');
|
|
319
|
+
await baseCoin.recover(mpcV2RecoverParams);
|
|
320
|
+
sandBox.assert.calledOnce(addSignatureSpy);
|
|
321
|
+
const sig = addSignatureSpy.firstCall.args[1];
|
|
322
|
+
sig.length.should.equal(64);
|
|
323
|
+
sig.should.deepEqual(rawSig);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
describe('Recover Transaction Failures:', function () {
|
|
328
|
+
const sandBox = sinon.createSandbox();
|
|
329
|
+
const recoveryDestination = '5H56f31hSYGCRV3URjQHv2Cc4ZSkJNHTM8MKGtkkV6hzCqN7';
|
|
330
|
+
beforeEach(function () {
|
|
331
|
+
sandBox.stub(src_1.Polyx.prototype, 'getAccountInfo').resolves({ nonce: 0, freeBalance: 0 });
|
|
332
|
+
sandBox.stub(src_1.Polyx.prototype, 'getFee').resolves(74401);
|
|
333
|
+
});
|
|
334
|
+
(0, mocha_1.afterEach)(function () {
|
|
335
|
+
sandBox.restore();
|
|
336
|
+
});
|
|
337
|
+
it('should fail to recover due to not finding an address with funds', async function () {
|
|
338
|
+
await baseCoin
|
|
339
|
+
.recover({
|
|
340
|
+
userKey: testData.wrwUser.userKey,
|
|
341
|
+
backupKey: testData.wrwUser.backupKey,
|
|
342
|
+
bitgoKey: testData.wrwUser.bitgoKey,
|
|
343
|
+
walletPassphrase: testData.wrwUser.walletPassphrase,
|
|
344
|
+
recoveryDestination,
|
|
345
|
+
})
|
|
346
|
+
.should.rejectedWith(sdk_core_1.ErrorNoInputToRecover);
|
|
347
|
+
});
|
|
348
|
+
it('should throw RecoveryProviderError when account info query fails', async function () {
|
|
349
|
+
src_1.Polyx.prototype.getAccountInfo.rejects(new Error('network failure'));
|
|
350
|
+
await baseCoin
|
|
351
|
+
.recover({
|
|
352
|
+
userKey: testData.wrwUser.userKey,
|
|
353
|
+
backupKey: testData.wrwUser.backupKey,
|
|
354
|
+
bitgoKey: testData.wrwUser.bitgoKey,
|
|
355
|
+
walletPassphrase: testData.wrwUser.walletPassphrase,
|
|
356
|
+
recoveryDestination,
|
|
357
|
+
})
|
|
358
|
+
.should.be.rejectedWith(sdk_core_1.RecoveryProviderError);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
describe('Token Enablement:', function () {
|
|
362
|
+
it('should have correct token enablement config', function () {
|
|
363
|
+
const config = baseCoin.getTokenEnablementConfig();
|
|
364
|
+
should_1.default.exist(config);
|
|
365
|
+
config.requiresTokenEnablement.should.equal(true);
|
|
366
|
+
config.supportsMultipleTokenEnablements.should.equal(false);
|
|
367
|
+
});
|
|
368
|
+
it('should validate wallet type for token enablement', function () {
|
|
369
|
+
const config = baseCoin.getTokenEnablementConfig();
|
|
370
|
+
(() => config.validateWallet('custodial')).should.not.throw();
|
|
371
|
+
(() => config.validateWallet('hot')).should.throw(/Token enablement for Polymesh \(polyx\) is only supported for custodial wallets/);
|
|
372
|
+
(() => config.validateWallet('cold')).should.throw(/Token enablement for Polymesh \(polyx\) is only supported for custodial wallets/);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
describe('verifyTransaction', function () {
|
|
376
|
+
const transferTo = '5F8jxKE81GhFrphyfMFr5UjeAz5wS4AaZFmeFPnf8wTetD72';
|
|
377
|
+
const transferAmount = '2000000000';
|
|
378
|
+
const wrongAddress = '5GhbC6n2pUFrX98DwyPit67fB5AwQvVCwZ4j2HKA7a4dUK4y';
|
|
379
|
+
describe('transfer transaction', function () {
|
|
380
|
+
it('should return true when address and amount match', async function () {
|
|
381
|
+
const result = await baseCoin.verifyTransaction({
|
|
382
|
+
txPrebuild: { txHex: resources_1.rawTx.transfer.signed },
|
|
383
|
+
txParams: { recipients: [{ address: transferTo, amount: transferAmount }] },
|
|
384
|
+
});
|
|
385
|
+
result.should.be.true();
|
|
386
|
+
});
|
|
387
|
+
it('should throw TxIntentMismatchRecipientError for address mismatch', async function () {
|
|
388
|
+
await baseCoin
|
|
389
|
+
.verifyTransaction({
|
|
390
|
+
txPrebuild: { txHex: resources_1.rawTx.transfer.signed },
|
|
391
|
+
txParams: { recipients: [{ address: wrongAddress, amount: transferAmount }] },
|
|
392
|
+
})
|
|
393
|
+
.should.be.rejectedWith(sdk_core_1.TxIntentMismatchRecipientError);
|
|
394
|
+
});
|
|
395
|
+
it('should throw TxIntentMismatchRecipientError for amount mismatch', async function () {
|
|
396
|
+
await baseCoin
|
|
397
|
+
.verifyTransaction({
|
|
398
|
+
txPrebuild: { txHex: resources_1.rawTx.transfer.signed },
|
|
399
|
+
txParams: { recipients: [{ address: transferTo, amount: '1' }] },
|
|
400
|
+
})
|
|
401
|
+
.should.be.rejectedWith(sdk_core_1.TxIntentMismatchRecipientError);
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
describe('guard cases', function () {
|
|
405
|
+
it('should throw when txHex is missing', async function () {
|
|
406
|
+
await baseCoin
|
|
407
|
+
.verifyTransaction({
|
|
408
|
+
txPrebuild: {},
|
|
409
|
+
txParams: { recipients: [{ address: transferTo, amount: transferAmount }] },
|
|
410
|
+
})
|
|
411
|
+
.should.be.rejectedWith('missing txHex in txPrebuild');
|
|
412
|
+
});
|
|
413
|
+
it('should throw when recipients has more than 1 entry', async function () {
|
|
414
|
+
await baseCoin
|
|
415
|
+
.verifyTransaction({
|
|
416
|
+
txPrebuild: { txHex: resources_1.rawTx.transfer.signed },
|
|
417
|
+
txParams: {
|
|
418
|
+
recipients: [
|
|
419
|
+
{ address: transferTo, amount: transferAmount },
|
|
420
|
+
{ address: wrongAddress, amount: transferAmount },
|
|
421
|
+
],
|
|
422
|
+
},
|
|
423
|
+
})
|
|
424
|
+
.should.be.rejectedWith(/support sending to more than 1 destination address/);
|
|
425
|
+
});
|
|
426
|
+
it('should throw when recipients is an empty array', async function () {
|
|
427
|
+
await baseCoin
|
|
428
|
+
.verifyTransaction({
|
|
429
|
+
txPrebuild: { txHex: resources_1.rawTx.transfer.signed },
|
|
430
|
+
txParams: { recipients: [] },
|
|
431
|
+
})
|
|
432
|
+
.should.be.rejectedWith('missing recipients in txParams');
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
describe('token enablement (preApproveAsset) transaction', function () {
|
|
436
|
+
it('should return true for enabletoken type with recipients (wallet root address)', async function () {
|
|
437
|
+
// buildTokenEnablements sets recipients[0].address = wallet rootAddress and type = 'enabletoken'.
|
|
438
|
+
// verifyTransaction must short-circuit before the _to check since preApproveAsset has no destination.
|
|
439
|
+
const walletAddress = '5F8jxKE81GhFrphyfMFr5UjeAz5wS4AaZFmeFPnf8wTetD72';
|
|
440
|
+
const result = await baseCoin.verifyTransaction({
|
|
441
|
+
txPrebuild: { txHex: resources_1.rawTx.preApproveAsset.signed },
|
|
442
|
+
txParams: {
|
|
443
|
+
type: 'enabletoken',
|
|
444
|
+
recipients: [{ address: walletAddress, amount: '0', tokenName: 'tpolyx:sometoken' }],
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
result.should.be.true();
|
|
448
|
+
});
|
|
449
|
+
it('should return true for enabletoken type with no recipients', async function () {
|
|
450
|
+
const result = await baseCoin.verifyTransaction({
|
|
451
|
+
txPrebuild: { txHex: resources_1.rawTx.preApproveAsset.signed },
|
|
452
|
+
txParams: { type: 'enabletoken' },
|
|
453
|
+
});
|
|
454
|
+
result.should.be.true();
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
describe('v8 transfer with coinSpecific.material', function () {
|
|
458
|
+
const v8Amount = '1000000';
|
|
459
|
+
const v8Receiver = resources_1.accounts.account2;
|
|
460
|
+
const v8Sender = resources_1.accounts.account1;
|
|
461
|
+
let v8SignedTxHex;
|
|
462
|
+
before(async function () {
|
|
463
|
+
// Build a signed v8 transfer tx using testnetV8Material.
|
|
464
|
+
// The server embeds this material in coinSpecific during prebuild so that
|
|
465
|
+
// verifyTransaction can decode txHex built against a chain spec newer than
|
|
466
|
+
// the SDK's hardcoded v7 material (CECHO-1471).
|
|
467
|
+
const builder = new lib_1.V8TransferBuilder(statics_1.coins.get('tpolyx'))
|
|
468
|
+
.amount(v8Amount)
|
|
469
|
+
.to({ address: v8Receiver.address })
|
|
470
|
+
.sender({ address: v8Sender.address })
|
|
471
|
+
.memo('0')
|
|
472
|
+
.validity({ firstValid: 3933, maxDuration: 64 })
|
|
473
|
+
.referenceBlock('0x149799bc9602cb5cf201f3425fb8d253b2d4e61fc119dcab3249f307f594754d')
|
|
474
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 1 })
|
|
475
|
+
.fee({ amount: 0, type: 'tip' });
|
|
476
|
+
builder.addSignature({ pub: v8Sender.publicKey }, Buffer.from(resources_1.mockTssSignature, 'hex'));
|
|
477
|
+
const tx = await builder.build();
|
|
478
|
+
v8SignedTxHex = tx.toBroadcastFormat();
|
|
479
|
+
});
|
|
480
|
+
it('verifies a v8 transfer when coinSpecific.material is provided', async function () {
|
|
481
|
+
const result = await baseCoin.verifyTransaction({
|
|
482
|
+
txPrebuild: {
|
|
483
|
+
txHex: v8SignedTxHex,
|
|
484
|
+
coinSpecific: { material: resources_2.testnetV8Material },
|
|
485
|
+
},
|
|
486
|
+
txParams: { recipients: [{ address: v8Receiver.address, amount: v8Amount }] },
|
|
487
|
+
});
|
|
488
|
+
result.should.be.true();
|
|
489
|
+
});
|
|
490
|
+
it('throws TxIntentMismatchRecipientError for address mismatch on v8 transfer', async function () {
|
|
491
|
+
await baseCoin
|
|
492
|
+
.verifyTransaction({
|
|
493
|
+
txPrebuild: {
|
|
494
|
+
txHex: v8SignedTxHex,
|
|
495
|
+
coinSpecific: { material: resources_2.testnetV8Material },
|
|
496
|
+
},
|
|
497
|
+
txParams: { recipients: [{ address: wrongAddress, amount: v8Amount }] },
|
|
498
|
+
})
|
|
499
|
+
.should.be.rejectedWith(sdk_core_1.TxIntentMismatchRecipientError);
|
|
500
|
+
});
|
|
501
|
+
it('throws TxIntentMismatchRecipientError for amount mismatch on v8 transfer', async function () {
|
|
502
|
+
await baseCoin
|
|
503
|
+
.verifyTransaction({
|
|
504
|
+
txPrebuild: {
|
|
505
|
+
txHex: v8SignedTxHex,
|
|
506
|
+
coinSpecific: { material: resources_2.testnetV8Material },
|
|
507
|
+
},
|
|
508
|
+
txParams: { recipients: [{ address: v8Receiver.address, amount: '1' }] },
|
|
509
|
+
})
|
|
510
|
+
.should.be.rejectedWith(sdk_core_1.TxIntentMismatchRecipientError);
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
describe('createBroadcastableSweepTransaction (MPCv2):', () => {
|
|
515
|
+
const sandBox = sinon.createSandbox();
|
|
516
|
+
let userKeyShare;
|
|
517
|
+
let backupKeyShare;
|
|
518
|
+
let commonKeychain;
|
|
519
|
+
let mpcv2SweepTxRequest;
|
|
520
|
+
let mpcv2SignatureHex;
|
|
521
|
+
before(async function () {
|
|
522
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
523
|
+
commonKeychain = userDkg.getCommonKeychain();
|
|
524
|
+
userKeyShare = userDkg.getKeyShare();
|
|
525
|
+
backupKeyShare = backupDkg.getKeyShare();
|
|
526
|
+
const recoveryDestination = '5H56f31hSYGCRV3URjQHv2Cc4ZSkJNHTM8MKGtkkV6hzCqN7';
|
|
527
|
+
const mpc = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
528
|
+
const walletAddress = baseCoin.getAddressFromPublicKey(mpc.deriveUnhardened(commonKeychain, 'm/0').slice(0, 64));
|
|
529
|
+
const accountInfoCB = sandBox.stub(src_1.Polyx.prototype, 'getAccountInfo');
|
|
530
|
+
accountInfoCB.withArgs(walletAddress).resolves({ nonce: 0, freeBalance: 100007000000 });
|
|
531
|
+
const headerInfoCB = sandBox.stub(src_1.Polyx.prototype, 'getHeaderInfo');
|
|
532
|
+
headerInfoCB.resolves({
|
|
533
|
+
headerNumber: testData.testnetBlock.blockNumber,
|
|
534
|
+
headerHash: testData.testnetBlock.hash,
|
|
535
|
+
});
|
|
536
|
+
const getFeeCB = sandBox.stub(src_1.Polyx.prototype, 'getFee');
|
|
537
|
+
getFeeCB.withArgs(recoveryDestination, walletAddress, 100007000000).resolves(74401);
|
|
538
|
+
const getMaterialCB = sandBox.stub(src_1.Polyx.prototype, 'getMaterial');
|
|
539
|
+
getMaterialCB.resolves(utils_1.default.getMaterial(statics_1.coins.get('tpolyx').network.type));
|
|
540
|
+
// no walletPassphrase -> unsigned sweep path returns MPCSweepTxs
|
|
541
|
+
const sweep = (await baseCoin.recover({
|
|
542
|
+
bitgoKey: commonKeychain,
|
|
543
|
+
recoveryDestination,
|
|
544
|
+
}));
|
|
545
|
+
sandBox.restore();
|
|
546
|
+
mpcv2SweepTxRequest = sweep.txRequests[0];
|
|
547
|
+
const unsignedTx = mpcv2SweepTxRequest.transactions[0].unsignedTx;
|
|
548
|
+
const signature = await (0, sdk_core_1.signRecoveryEddsaMPCv2)(Buffer.from(unsignedTx.signableHex, 'hex'), unsignedTx.derivationPath, userKeyShare, backupKeyShare, commonKeychain);
|
|
549
|
+
mpcv2SignatureHex = signature.toString('hex');
|
|
550
|
+
});
|
|
551
|
+
// createBroadcastableSweepTransaction calls getMaterial() to re-encode the signed
|
|
552
|
+
// transaction; stub it with the same testnet material the sweep was built with.
|
|
553
|
+
beforeEach(function () {
|
|
554
|
+
const getMaterialCB = sandBox.stub(src_1.Polyx.prototype, 'getMaterial');
|
|
555
|
+
getMaterialCB.resolves(utils_1.default.getMaterial(statics_1.coins.get('tpolyx').network.type));
|
|
556
|
+
});
|
|
557
|
+
(0, mocha_1.afterEach)(function () {
|
|
558
|
+
sandBox.restore();
|
|
559
|
+
});
|
|
560
|
+
function buildParams(ovc) {
|
|
561
|
+
return {
|
|
562
|
+
signatureShares: [
|
|
563
|
+
{
|
|
564
|
+
txRequest: mpcv2SweepTxRequest,
|
|
565
|
+
tssVersion: '0.0.1',
|
|
566
|
+
ovc: [ovc],
|
|
567
|
+
},
|
|
568
|
+
],
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
it('should take MPCv2 OVC output and generate a signed sweep transaction', async function () {
|
|
572
|
+
const params = buildParams({ eddsaMpcv2Signature: mpcv2SignatureHex });
|
|
573
|
+
const recoveryTxn = await baseCoin.createBroadcastableSweepTransaction(params);
|
|
574
|
+
recoveryTxn.transactions[0].serializedTx.should.not.equal(mpcv2SweepTxRequest.transactions[0].unsignedTx.serializedTx);
|
|
575
|
+
recoveryTxn.transactions[0].serializedTx.should.not.be.empty();
|
|
576
|
+
(recoveryTxn.transactions[0].scanIndex ?? 0).should.equal(0);
|
|
577
|
+
(recoveryTxn.lastScanIndex ?? 0).should.equal(0);
|
|
578
|
+
});
|
|
579
|
+
it('should reject a tampered MPCv2 signature', async function () {
|
|
580
|
+
const unsignedTx = mpcv2SweepTxRequest.transactions[0].unsignedTx;
|
|
581
|
+
const tamperedMessage = Buffer.concat([Buffer.from(unsignedTx.signableHex, 'hex'), Buffer.from('00', 'hex')]);
|
|
582
|
+
const tamperedSignature = await (0, sdk_core_1.signRecoveryEddsaMPCv2)(tamperedMessage, unsignedTx.derivationPath, userKeyShare, backupKeyShare, commonKeychain);
|
|
583
|
+
await baseCoin
|
|
584
|
+
.createBroadcastableSweepTransaction(buildParams({ eddsaMpcv2Signature: tamperedSignature.toString('hex') }))
|
|
585
|
+
.should.be.rejectedWith('Invalid signature');
|
|
586
|
+
});
|
|
587
|
+
it('should throw when MPCv2 OVC is missing signature(s)', async function () {
|
|
588
|
+
await baseCoin
|
|
589
|
+
.createBroadcastableSweepTransaction(buildParams({}))
|
|
590
|
+
.should.be.rejectedWith('Missing signature(s)');
|
|
591
|
+
});
|
|
592
|
+
it('should route MPCv1-shaped ovc to the MPCv1 verify branch and reject an invalid signature', async function () {
|
|
593
|
+
const mpc = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
594
|
+
const derivedPubKey = mpc.deriveUnhardened(commonKeychain, 'm/0').slice(0, 64);
|
|
595
|
+
await baseCoin
|
|
596
|
+
.createBroadcastableSweepTransaction(buildParams({
|
|
597
|
+
eddsaSignature: { R: '00'.repeat(32), sigma: '00'.repeat(32), y: derivedPubKey },
|
|
598
|
+
}))
|
|
599
|
+
.should.be.rejectedWith('Invalid signature');
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9seXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvcG9seXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsbURBQStEO0FBQy9ELGlEQUF3RDtBQUN4RCxtQ0FBMEM7QUFDMUMsdURBQXNGO0FBQ3RGLGdFQUF3QztBQUN4QyxpREFBNEM7QUFDNUMsNkNBQStCO0FBQy9CLGdFQUFrRDtBQUNsRCxpQ0FBa0M7QUFDbEMsNENBQXNHO0FBQ3RHLG1EQVU4QjtBQUM5Qix1Q0FBbUU7QUFDbkUsbURBQXdEO0FBQ3hELHlEQUFrRDtBQUVsRCxRQUFRLENBQUMsUUFBUSxFQUFFO0lBQ2pCLElBQUksS0FBbUIsQ0FBQztJQUN4QixJQUFJLFFBQVEsQ0FBQztJQUViLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsV0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2xELEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLFlBQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNwRCxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMzQixRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQVcsQ0FBQztJQUM1QyxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQywwQkFBMEIsRUFBRTtRQUNuQyxFQUFFLENBQUMsa0RBQWtELEVBQUU7WUFDckQsNkNBQTZDO1lBQzdDLGdDQUFvQixDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEMsaUNBQXFCLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFF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QyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDekYsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM5RSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3hGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNyRixRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3JGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzVGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3pGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN2RixrREFBa0QsQ0FDbkQsQ0FBQztZQUNGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzlHLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3RHLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzdGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN4RixrREFBa0QsQ0FDbkQsQ0FBQztZQUNGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQy9HLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3RHLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDakYsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNwRixRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdEYsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN6RixRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNwRyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzlGLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3hGLGtJQUFrSSxDQUNuSSxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUUsS0FBSztZQUN0RCxhQUFhLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztZQUN6RyxZQUFZLENBQUMsUUFBUSxDQUFDO2dCQUNwQixZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxXQUFXO2dCQUMvQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJO2FBQ3ZDLENBQUMsQ0FBQztZQUNILFFBQVEsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRXJHLE1BQU0sR0FBRyxHQUFHLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQztnQkFDakMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTztnQkFDakMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsU0FBUztnQkFDckMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUTtnQkFDbkMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0I7Z0JBQ25ELG1CQUFtQixFQUFFLG1CQUFtQjthQUN6QyxDQUFDLENBQUM7WUFFSCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDMUIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDMUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFdkMsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDL0QsU0FBUztpQkFDTixRQUFRLENBQUM7Z0JBQ1IsVUFBVSxFQUFFLFFBQVEsQ0FBQyxZQUFZLENBQUMsV0FBVztnQkFDN0MsV0FBVyxFQUFFLFFBQVEsQ0FBQyxrQkFBa0I7YUFDekMsQ0FBQztpQkFDRCxjQUFjLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUU5QyxNQUFNLEVBQUUsR0FBRyxNQUFNLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNuQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDM0IsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2hFLGdCQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxnQkFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEUsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSx1QkFBVyxDQUFDLENBQUM7WUFDbEQsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSx1QkFBVyxDQUFDLENBQUM7WUFDbEQsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN0QyxnQkFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLGdCQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxxQkFBUyxDQUFDLENBQUM7WUFDdkQsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNsRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxvREFBb0QsRUFBRSxLQUFLO1lBQzVELGFBQWE7aUJBQ1YsUUFBUSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUM7aUJBQ2xELFFBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7WUFDckQsWUFBWSxDQUFDLFFBQVEsQ0FBQztnQkFDcEIsWUFBWSxFQUFFLFFBQVEsQ0FBQyxZQUFZLENBQUMsV0FBVztnQkFDL0MsVUFBVSxFQUFFLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSTthQUN2QyxDQUFDLENBQUM7WUFDSCxRQUFRLENBQUMsUUFBUSxDQUFDLG1CQUFtQixFQUFFLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRS9HLE1BQU0sR0FBRyxHQUFHLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQztnQkFDakMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRO2dCQUM3QyxtQkFBbUIsRUFBRSxtQkFBbUI7YUFDekMsQ0FBQyxDQUFDO1lBRUgsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzFCLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ25GLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRWhGLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3hHLFNBQVM7aUJBQ04sUUFBUSxDQUFDO2dCQUNSLFVBQVUsRUFBRSxRQUFRLENBQUMsWUFBWSxDQUFDLFdBQVc7Z0JBQzdDLFdBQVcsRUFBRSxRQUFRLENBQUMsa0JBQWtCO2FBQ3pDLENBQUM7aUJBQ0QsY0FBYyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDO2lCQUMxQyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7WUFFakUsTUFBTSxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkMsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzNCLGdCQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQzFFLGdCQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxnQkFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEUsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSx1QkFBVyxDQUFDLENBQUM7WUFDbEQsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSx1QkFBVyxDQUFDLENBQUM7WUFDbEQsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNsQyxnQkFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLGdCQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxxQkFBUyxDQUFDLENBQUM7WUFDdkQsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNsRSxDQUFDLENBQUMsQ0FBQztRQUVILFFBQVEsQ0FBQyx1QkFBdUIsRUFBRTtZQUNoQyxNQUFNLGdCQUFnQixHQUFHLHVCQUF1QixDQUFDO1lBQ2pELElBQUksWUFBb0IsQ0FBQztZQUN6QixJQUFJLGNBQXNCLENBQUM7WUFDM0IsSUFBSSxtQkFBMkIsQ0FBQztZQUNoQyxJQUFJLGtCQUFzQyxDQUFDO1lBRTNDLE1BQU0sQ0FBQyxLQUFLO2dCQUNWLE1BQU0sQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLEdBQUcsTUFBTSxxQkFBTyxDQUFDLHlCQUF5QixFQUFFLENBQUM7Z0JBQ3ZFLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUNsRCxZQUFZLEdBQUcsTUFBTSxJQUFBLGlCQUFPLEVBQUMsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hHLGNBQWMsR0FBRyxNQUFNLElBQUEsaUJBQU8sRUFBQyxnQkFBZ0IsRUFBRSxTQUFTLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztnQkFFcEcsa0JBQWtCLEdBQUc7b0JBQ25CLE9BQU8sRUFBRSxZQUFZO29CQUNyQixTQUFTLEVBQUUsY0FBYztvQkFDekIsUUFBUSxFQUFFLG1CQUFtQjtvQkFDN0IsbUJBQW1CO29CQUNuQixnQkFBZ0I7aUJBQ2pCLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztZQUVILFVBQVUsQ0FBQztnQkFDVCwrRUFBK0U7Z0JBQy9FLDhEQUE4RDtnQkFDOUQsYUFBYSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7Z0JBQ2hFLFlBQVksQ0FBQyxRQUFRLENBQUM7b0JBQ3BCLFlBQVksRUFBRSxRQUFRLENBQUMsWUFBWSxDQUFDLFdBQVc7b0JBQy9DLFVBQVUsRUFBRSxRQUFRLENBQUMsWUFBWSxDQUFDLElBQUk7aUJBQ3ZDLENBQUMsQ0FBQztnQkFDSCxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzNCLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLGtEQUFrRCxFQUFFLEtBQUs7Z0JBQzFELE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBWSxFQUFFLGlCQUFpQixDQUFDLENBQUM7Z0JBQ3hFLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQWUsQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDLENBQUM7Z0JBRS9FLE1BQU0sTUFBTSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQVUsQ0FBQztnQkFFckUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUM3QixNQUFNLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDN0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQzFDLGdCQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pDLE1BQU0sQ0FBQyxZQUF1QixDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUN4RSxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO2dCQUU3QyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDM0MsTUFBTSxTQUFTLEdBQVcsZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzVELDRFQUE0RTtnQkFDNUUsMkRBQTJEO2dCQUMzRCxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEMsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsNERBQTRELEVBQUUsS0FBSztnQkFDcEUsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBZSxDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUMsQ0FBQztnQkFDL0UsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FDakMsUUFBOEQsRUFDOUQsNEJBQTRCLENBQzdCLENBQUM7Z0JBRUYsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7Z0JBRTNDLDRGQUE0RjtnQkFDNUYsTUFBTSxTQUFTLEdBQVcsZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRTVELHdGQUF3RjtnQkFDeEYsTUFBTSxlQUFlLEdBQVksZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUF5QixDQUFDLE9BQU8sQ0FBQztnQkFFbkcsTUFBTSxHQUFHLEdBQUcsTUFBTSx1QkFBWSxDQUFDLHlCQUF5QixFQUFFLENBQUM7Z0JBQzNELE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUVoRixNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQy9ELE1BQU0sT0FBTyxHQUFHLGVBQUssQ0FBQyxlQUFlLENBQ25DLEtBQUssZUFBZSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUN0QyxLQUFLLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFDaEMsVUFBVSxDQUNYLENBQUM7Z0JBQ0YsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDM0IsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsNkRBQTZELEVBQUUsS0FBSztnQkFDckUsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRSxXQUFXLEVBQUUsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDaEgsT0FBTztxQkFDSixJQUFJLENBQUMsUUFBMkQsRUFBRSx5QkFBeUIsQ0FBQztxQkFDNUYsUUFBUSxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUV4QyxNQUFNLG1CQUFtQixHQUFHLE9BQU87cUJBQ2hDLElBQUksQ0FBQyx1QkFBWSxFQUFFLGlCQUFpQixDQUFDO3FCQUNyQyxRQUFRLENBQ1AsTUFBTSxDQUFDLElBQUksQ0FDVCxrRUFBa0U7b0JBQ2hFLGtFQUFrRSxFQUNwRSxLQUFLLENBQ04sQ0FDRixDQUFDO2dCQUVKLE9BQU87cUJBQ0osSUFBSSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUM7cUJBQ3RCLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztxQkFDbkUsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBRXpELE1BQU0sTUFBTSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQVUsQ0FBQztnQkFFckUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUM3QixNQUFNLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDN0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQzFDLGdCQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pDLE1BQU0sQ0FBQyxZQUF1QixDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUN4RSxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQ2pELENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHdGQUF3RixFQUFFLEtBQUs7Z0JBQ2hHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7Z0JBRXBFLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGdDQUFnQyxDQUFDLENBQUM7WUFDdEcsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsNkVBQTZFLEVBQUUsS0FBSztnQkFDckYsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDO2dCQUN6RSxNQUFNLGdCQUFnQixHQUFHO29CQUN2QixHQUFHLGtCQUFrQjtvQkFDckIsUUFBUSxFQUFFLGtCQUFrQjtpQkFDN0IsQ0FBQztnQkFFRixNQUFNLFFBQVE7cUJBQ1gsT0FBTyxDQUFDLGdCQUFnQixDQUFDO3FCQUN6QixNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQywyRUFBMkUsQ0FBQyxDQUFDO1lBQ3pHLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLGlHQUFpRyxFQUFFLEtBQUs7Z0JBQ3pHLE1BQU0sb0JBQW9CLEdBQUcsRUFBRSxHQUFHLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQztnQkFDM0UsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUN6RixDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyxtR0FBbUcsRUFBRSxLQUFLO2dCQUMzRyxNQUFNLHNCQUFzQixHQUFHLEVBQUUsR0FBRyxrQkFBa0IsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUM7Z0JBQy9FLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDN0YsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsMkdBQTJHLEVBQUUsS0FBSztnQkFDbkgsTUFBTSx1QkFBdUIsR0FBRyxFQUFFLEdBQUcsa0JBQWtCLEVBQUUsZ0JBQWdCLEVBQUUsU0FBUyxFQUFFLENBQUM7Z0JBQ3ZGLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFDdEcsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMscUVBQXFFLEVBQUUsS0FBSztnQkFDN0Usa0ZBQWtGO2dCQUNsRixrRkFBa0Y7Z0JBQ2xGLGdGQUFnRjtnQkFDaEYsMERBQTBEO2dCQUMxRCxrQ0FBa0M7Z0JBQ2xDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUN0QyxPQUFPO3FCQUNKLElBQUksQ0FBQyxRQUE4RCxFQUFFLDRCQUE0QixDQUFDO3FCQUNsRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3BCLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQWUsQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDLENBQUM7Z0JBRS9FLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO2dCQUUzQyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDM0MsTUFBTSxHQUFHLEdBQVcsZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3RELEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDNUIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLCtCQUErQixFQUFFO1FBQ3hDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN0QyxNQUFNLG1CQUFtQixHQUFHLGtEQUFrRCxDQUFDO1FBRS9FLFVBQVUsQ0FBQztZQUNULE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBSyxDQUFDLFNBQVMsRUFBRSxnQkFBK0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEcsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFLLENBQUMsU0FBUyxFQUFFLFFBQXVCLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekUsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLGlCQUFTLEVBQUM7WUFDUixPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsaUVBQWlFLEVBQUUsS0FBSztZQUN6RSxNQUFNLFFBQVE7aUJBQ1gsT0FBTyxDQUFDO2dCQUNQLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLE9BQU87Z0JBQ2pDLFNBQVMsRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVM7Z0JBQ3JDLFFBQVEsRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVE7Z0JBQ25DLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO2dCQUNuRCxtQkFBbUI7YUFDcEIsQ0FBQztpQkFDRCxNQUFNLENBQUMsWUFBWSxDQUFDLGdDQUFxQixDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsa0VBQWtFLEVBQUUsS0FBSztZQUN6RSxXQUFLLENBQUMsU0FBNEQsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUN4RixJQUFJLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUM3QixDQUFDO1lBQ0YsTUFBTSxRQUFRO2lCQUNYLE9BQU8sQ0FBQztnQkFDUCxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxPQUFPO2dCQUNqQyxTQUFTLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxTQUFTO2dCQUNyQyxRQUFRLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRO2dCQUNuQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtnQkFDbkQsbUJBQW1CO2FBQ3BCLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsZ0NBQXFCLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLEVBQUUsQ0FBQyw2Q0FBNkMsRUFBRTtZQUNoRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUNuRCxnQkFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNyQixNQUFNLENBQUMsdUJBQXVCLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsRCxNQUFNLENBQUMsZ0NBQWdDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxrREFBa0QsRUFBRTtZQUNyRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUNuRCxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzlELENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQy9DLGlGQUFpRixDQUNsRixDQUFDO1lBQ0YsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDaEQsaUZBQWlGLENBQ2xGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLE1BQU0sVUFBVSxHQUFHLGtEQUFrRCxDQUFDO1FBQ3RFLE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztRQUNwQyxNQUFNLFlBQVksR0FBRyxrREFBa0QsQ0FBQztRQUV4RSxRQUFRLENBQUMsc0JBQXNCLEVBQUU7WUFDL0IsRUFBRSxDQUFDLGtEQUFrRCxFQUFFLEtBQUs7Z0JBQzFELE1BQU0sTUFBTSxHQUFHLE1BQU0sUUFBUSxDQUFDLGlCQUFpQixDQUFDO29CQUM5QyxVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUUsaUJBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFO29CQUM1QyxRQUFRLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxDQUFDLEVBQUU7aUJBQzVFLENBQUMsQ0FBQztnQkFDSCxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMxQixDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyxrRUFBa0UsRUFBRSxLQUFLO2dCQUMxRSxNQUFNLFFBQVE7cUJBQ1gsaUJBQWlCLENBQUM7b0JBQ2pCLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRSxpQkFBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUU7b0JBQzVDLFFBQVEsRUFBRSxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLENBQUMsRUFBRTtpQkFDOUUsQ0FBQztxQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyx5Q0FBOEIsQ0FBQyxDQUFDO1lBQzVELENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLGlFQUFpRSxFQUFFLEtBQUs7Z0JBQ3pFLE1BQU0sUUFBUTtxQkFDWCxpQkFBaUIsQ0FBQztvQkFDakIsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLGlCQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRTtvQkFDNUMsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFO2lCQUNqRSxDQUFDO3FCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLHlDQUE4QixDQUFDLENBQUM7WUFDNUQsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILFFBQVEsQ0FBQyxhQUFhLEVBQUU7WUFDdEIsRUFBRSxDQUFDLG9DQUFvQyxFQUFFLEtBQUs7Z0JBQzVDLE1BQU0sUUFBUTtxQkFDWCxpQkFBaUIsQ0FBQztvQkFDakIsVUFBVSxFQUFFLEVBQUU7b0JBQ2QsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsQ0FBQyxFQUFFO2lCQUM1RSxDQUFDO3FCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLDZCQUE2QixDQUFDLENBQUM7WUFDM0QsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsb0RBQW9ELEVBQUUsS0FBSztnQkFDNUQsTUFBTSxRQUFRO3FCQUNYLGlCQUFpQixDQUFDO29CQUNqQixVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUUsaUJBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFO29CQUM1QyxRQUFRLEVBQUU7d0JBQ1IsVUFBVSxFQUFFOzRCQUNWLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFOzRCQUMvQyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRTt5QkFDbEQ7cUJBQ0Y7aUJBQ0YsQ0FBQztxQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1lBQ2xGLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLGdEQUFnRCxFQUFFLEtBQUs7Z0JBQ3hELE1BQU0sUUFBUTtxQkFDWCxpQkFBaUIsQ0FBQztvQkFDakIsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLGlCQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRTtvQkFDNUMsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRTtpQkFDN0IsQ0FBQztxQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1lBQzlELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMsZ0RBQWdELEVBQUU7WUFDekQsRUFBRSxDQUFDLCtFQUErRSxFQUFFLEtBQUs7Z0JBQ3ZGLGtHQUFrRztnQkFDbEcsc0dBQXNHO2dCQUN0RyxNQUFNLGFBQWEsR0FBRyxrREFBa0QsQ0FBQztnQkFDekUsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsaUJBQWlCLENBQUM7b0JBQzlDLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRSxpQkFBSyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUU7b0JBQ25ELFFBQVEsRUFBRTt3QkFDUixJQUFJLEVBQUUsYUFBYTt3QkFDbkIsVUFBVSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLENBQUM7cUJBQ3JGO2lCQUNGLENBQUMsQ0FBQztnQkFDSCxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMxQixDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyw0REFBNEQsRUFBRSxLQUFLO2dCQUNwRSxNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQztvQkFDOUMsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLGlCQUFLLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRTtvQkFDbkQsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRTtpQkFDbEMsQ0FBQyxDQUFDO2dCQUNILE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzFCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMsd0NBQXdDLEVBQUU7WUFDakQsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDO1lBQzNCLE1BQU0sVUFBVSxHQUFHLG9CQUFRLENBQUMsUUFBUSxDQUFDO1lBQ3JDLE1BQU0sUUFBUSxHQUFHLG9CQUFRLENBQUMsUUFBUSxDQUFDO1lBQ25DLElBQUksYUFBcUIsQ0FBQztZQUUxQixNQUFNLENBQUMsS0FBSztnQkFDVix5REFBeUQ7Z0JBQ3pELDBFQUEwRTtnQkFDMUUsMkVBQTJFO2dCQUMzRSxnREFBZ0Q7Z0JBQ2hELE1BQU0sT0FBTyxHQUFHLElBQUksdUJBQWlCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztxQkFDdkQsTUFBTSxDQUFDLFFBQVEsQ0FBQztxQkFDaEIsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztxQkFDbkMsTUFBTSxDQUFDLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztxQkFDckMsSUFBSSxDQUFDLEdBQUcsQ0FBQztxQkFDVCxRQUFRLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsQ0FBQztxQkFDL0MsY0FBYyxDQUFDLG9FQUFvRSxDQUFDO3FCQUNwRixVQUFVLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDO3FCQUN6RCxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNuQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsR0FBRyxFQUFFLFFBQVEsQ0FBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUFnQixFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQ3hGLE1BQU0sRUFBRSxHQUFHLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNqQyxhQUFhLEdBQUcsRUFBRSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDekMsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsK0RBQStELEVBQUUsS0FBSztnQkFDdkUsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsaUJBQWlCLENBQUM7b0JBQzlDLFVBQVUsRUFBRTt3QkFDVixLQUFLLEVBQUUsYUFBYTt3QkFDcEIsWUFBWSxFQUFFLEVBQUUsUUFBUSxFQUFFLDZCQUFpQixFQUFFO3FCQUM5QztvQkFDRCxRQUFRLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFO2lCQUM5RSxDQUFDLENBQUM7Z0JBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDMUIsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsMkVBQTJFLEVBQUUsS0FBSztnQkFDbkYsTUFBTSxRQUFRO3FCQUNYLGlCQUFpQixDQUFDO29CQUNqQixVQUFVLEVBQUU7d0JBQ1YsS0FBSyxFQUFFLGFBQWE7d0JBQ3BCLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSw2QkFBaUIsRUFBRTtxQkFDOUM7b0JBQ0QsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFO2lCQUN4RSxDQUFDO3FCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLHlDQUE4QixDQUFDLENBQUM7WUFDNUQsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsMEVBQTBFLEVBQUUsS0FBSztnQkFDbEYsTUFBTSxRQUFRO3FCQUNYLGlCQUFpQixDQUFDO29CQUNqQixVQUFVLEVBQUU7d0JBQ1YsS0FBSyxFQUFFLGFBQWE7d0JBQ3BCLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSw2QkFBaUIsRUFBRTtxQkFDOUM7b0JBQ0QsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRTtpQkFDekUsQ0FBQztxQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyx5Q0FBOEIsQ0FBQyxDQUFDO1lBQzVELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyw4Q0FBOEMsRUFBRSxHQUFHLEVBQUU7UUFDNUQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3RDLElBQUksWUFBb0IsQ0FBQztRQUN6QixJQUFJLGNBQXNCLENBQUM7UUFDM0IsSUFBSSxjQUFzQixDQUFDO1FBQzNCLElBQUksbUJBQXdCLENBQUM7UUFDN0IsSUFBSSxpQkFBeUIsQ0FBQztRQUU5QixNQUFNLENBQUMsS0FBSztZQUNWLE1BQU0sQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLEdBQUcsTUFBTSxxQkFBTyxDQUFDLHlCQUF5QixFQUFFLENBQUM7WUFDdkUsY0FBYyxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzdDLFlBQVksR0FBRyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckMsY0FBYyxHQUFHLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUV6QyxNQUFNLG1CQUFtQixHQUFHLGtEQUFrRCxDQUFDO1lBQy9FLE1BQU0sR0FBRyxHQUFHLE1BQU0sdUJBQVksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQzNELE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNqSCxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQUssQ0FBQyxTQUFTLEVBQUUsZ0JBQStCLENBQUMsQ0FBQztZQUNyRixhQUFhLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7WUFDeEYsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFLLENBQUMsU0FBUyxFQUFFLGVBQThCLENBQUMsQ0FBQztZQUNuRixZQUFZLENBQUMsUUFBUSxDQUFDO2dCQUNwQixZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxXQUFXO2dCQUMvQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJO2FBQ3ZDLENBQUMsQ0FBQztZQUNILE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBSyxDQUFDLFNBQVMsRUFBRSxRQUF1QixDQUFDLENBQUM7WUFDeEUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BGLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBSyxDQUFDLFNBQVMsRUFBRSxhQUE0QixDQUFDLENBQUM7WUFDbEYsYUFBYSxDQUFDLFFBQVEsQ0FBQyxlQUFLLENBQUMsV0FBVyxDQUFDLGVBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFFNUUsaUVBQWlFO1lBQ2pFLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDO2dCQUNwQyxRQUFRLEVBQUUsY0FBYztnQkFDeEIsbUJBQW1CO2FBQ3BCLENBQUMsQ0FBZ0IsQ0FBQztZQUNuQixPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFFbEIsbUJBQW1CLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxQyxNQUFNLFVBQVUsR0FBRyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO1lBQ2xFLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBQSxpQ0FBc0IsRUFDNUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxFQUMxQyxVQUFVLENBQUMsY0FBYyxFQUN6QixZQUFZLEVBQ1osY0FBYyxFQUNkLGNBQWMsQ0FDZixDQUFDO1lBQ0YsaUJBQWlCLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztRQUVILGtGQUFrRjtRQUNsRixnRkFBZ0Y7UUFDaEYsVUFBVSxDQUFDO1lBQ1QsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFLLENBQUMsU0FBUyxFQUFFLGFBQTRCLENBQUMsQ0FBQztZQUNsRixhQUFhLENBQUMsUUFBUSxDQUFDLGVBQUssQ0FBQyxXQUFXLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM5RSxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsaUJBQVMsRUFBQztZQUNSLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQUMsQ0FBQztRQUVILFNBQVMsV0FBVyxDQUFDLEdBQVE7WUFDM0IsT0FBTztnQkFDTCxlQUFlLEVBQUU7b0JBQ2Y7d0JBQ0UsU0FBUyxFQUFFLG1CQUFtQjt3QkFDOUIsVUFBVSxFQUFFLE9BQU87d0JBQ25CLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQztxQkFDWDtpQkFDRjthQUN5QixDQUFDO1FBQy9CLENBQUM7UUFFRCxFQUFFLENBQUMsc0VBQXNFLEVBQUUsS0FBSztZQUM5RSxNQUFNLE1BQU0sR0FBRyxXQUFXLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLENBQUM7WUFDdkUsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsbUNBQW1DLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFL0UsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQ3ZELG1CQUFtQixDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUM1RCxDQUFDO1lBQ0YsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDL0QsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdELENBQUMsV0FBVyxDQUFDLGFBQWEsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDBDQUEwQyxFQUFFLEtBQUs7WUFDbEQsTUFBTSxVQUFVLEdBQUcsbUJBQW1CLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztZQUNsRSxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5RyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sSUFBQSxpQ0FBc0IsRUFDcEQsZUFBZSxFQUNmLFVBQVUsQ0FBQyxjQUFjLEVBQ3pCLFlBQVksRUFDWixjQUFjLEVBQ2QsY0FBYyxDQUNmLENBQUM7WUFFRixNQUFNLFFBQVE7aUJBQ1gsbUNBQW1DLENBQUMsV0FBVyxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDNUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqRCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxxREFBcUQsRUFBRSxLQUFLO1lBQzdELE1BQU0sUUFBUTtpQkFDWCxtQ0FBbUMsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7aUJBQ3BELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsMEZBQTBGLEVBQUUsS0FBSztZQUNsRyxNQUFNLEdBQUcsR0FBRyxNQUFNLHVCQUFZLENBQUMseUJBQXlCLEVBQUUsQ0FBQztZQUMzRCxNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDL0UsTUFBTSxRQUFRO2lCQUNYLG1DQUFtQyxDQUNsQyxXQUFXLENBQUM7Z0JBQ1YsY0FBYyxFQUFFLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLGFBQWEsRUFBRTthQUNqRixDQUFDLENBQ0g7aUJBQ0EsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvQVBJLCBlbmNyeXB0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWFwaSc7XG5pbXBvcnQgeyBQb2x5eCwgVHBvbHl4IH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IFBPTFlYX0FERFJFU1NfRk9STUFULCBUUE9MWVhfQUREUkVTU19GT1JNQVQgfSBmcm9tICcuLi8uLi9zcmMvbGliL2NvbnN0YW50cyc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vLi4vc3JjL2xpYi91dGlscyc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0ICogYXMgdGVzdERhdGEgZnJvbSAnLi4vcmVzb3VyY2VzL3dyd1VzZXJzJztcbmltcG9ydCB7IGFmdGVyRWFjaCB9IGZyb20gJ21vY2hhJztcbmltcG9ydCB7IGdlbmVzaXNIYXNoLCBzcGVjVmVyc2lvbiwgdHhWZXJzaW9uLCByYXdUeCwgYWNjb3VudHMsIG1vY2tUc3NTaWduYXR1cmUgfSBmcm9tICcuLi9yZXNvdXJjZXMnO1xuaW1wb3J0IHtcbiAgRUREU0FNZXRob2RzLFxuICBFcnJvck5vSW5wdXRUb1JlY292ZXIsXG4gIE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zLFxuICBNUENTd2VlcFR4cyxcbiAgTVBDUmVjb3ZlcnlPcHRpb25zLFxuICBNUENUeCxcbiAgUmVjb3ZlcnlQcm92aWRlckVycm9yLFxuICBzaWduUmVjb3ZlcnlFZGRzYU1QQ3YyLFxuICBUeEludGVudE1pc21hdGNoUmVjaXBpZW50RXJyb3IsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IFRyYW5zZmVyQnVpbGRlciwgVjhUcmFuc2ZlckJ1aWxkZXIgfSBmcm9tICcuLi8uLi9zcmMvbGliJztcbmltcG9ydCB7IHRlc3RuZXRWOE1hdGVyaWFsIH0gZnJvbSAnLi4vLi4vc3JjL3Jlc291cmNlcyc7XG5pbXBvcnQgeyBNUFNVdGlsIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWxpYi1tcGMnO1xuXG5kZXNjcmliZSgnUG9seXg6JywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGJhc2VDb2luO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCdwb2x5eCcsIFBvbHl4LmNyZWF0ZUluc3RhbmNlKTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3Rwb2x5eCcsIFRwb2x5eC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYmFzZUNvaW4gPSBiaXRnby5jb2luKCd0cG9seXgnKSBhcyBUcG9seXg7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdBZGRyZXNzIEZvcm1hdCBDb25zdGFudHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBoYXZlIHRoZSBjb3JyZWN0IGFkZHJlc3MgZm9ybWF0IGNvbnN0YW50cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFZlcmlmeSB0aGUgY29uc3RhbnRzIGFyZSBkZWZpbmVkIGNvcnJlY3RseVxuICAgICAgUE9MWVhfQUREUkVTU19GT1JNQVQuc2hvdWxkLmVxdWFsKDEyKTtcbiAgICAgIFRQT0xZWF9BRERSRVNTX0ZPUk1BVC5zaG91bGQuZXF1YWwoNDIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVjb3ZlciBUcmFuc2FjdGlvbnM6JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgY29uc3QgcmVjb3ZlcnlEZXN0aW5hdGlvbiA9ICc1SDU2ZjMxaFNZR0NSVjNVUmpRSHYyQ2M0WlNrSk5IVE04TUtHdGtrVjZoekNxTjcnO1xuICAgIGNvbnN0IG5vbmNlID0gMDtcbiAgICBsZXQgYWNjb3VudEluZm9DQjtcbiAgICBsZXQgaGVhZGVySW5mb0NCO1xuICAgIGxldCBnZXRGZWVDQjtcbiAgICBsZXQgZ2V0TWF0ZXJpYWxDQjtcblxuICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgYWNjb3VudEluZm9DQiA9IHNhbmRCb3guc3R1YihQb2x5eC5wcm90b3R5cGUsICdnZXRBY2NvdW50SW5mbycgYXMga2V5b2YgUG9seXgpO1xuICAgICAgaGVhZGVySW5mb0NCID0gc2FuZEJveC5zdHViKFBvbHl4LnByb3RvdHlwZSwgJ2dldEhlYWRlckluZm8nIGFzIGtleW9mIFBvbHl4KTtcbiAgICAgIGdldEZlZUNCID0gc2FuZEJveC5zdHViKFBvbHl4LnByb3RvdHlwZSwgJ2dldEZlZScgYXMga2V5b2YgUG9seXgpO1xuICAgICAgZ2V0TWF0ZXJpYWxDQiA9IHNhbmRCb3guc3R1YihQb2x5eC5wcm90b3R5cGUsICdnZXRNYXRlcmlhbCcgYXMga2V5b2YgUG9seXgpO1xuICAgICAgZ2V0TWF0ZXJpYWxDQi5yZXNvbHZlcyh1dGlscy5nZXRNYXRlcmlhbChjb2lucy5nZXQoJ3Rwb2x5eCcpLm5ldHdvcmsudHlwZSkpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSB1bnNpZ25lZCBzd2VlcCBjb3JyZWN0bHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhY2NvdW50SW5mb0NCXG4gICAgICAgIC53aXRoQXJncyh0ZXN0RGF0YS51bnNpZ25lZFN3ZWVwVXNlci53YWxsZXRBZGRyZXNzKVxuICAgICAgICAucmVzb2x2ZXMoeyBub25jZTogMCwgZnJlZUJhbGFuY2U6IDEwMDAwNzAwMDAwMCB9KTtcbiAgICAgIGhlYWRlckluZm9DQi5yZXNvbHZlcyh7XG4gICAgICAgIGhlYWRlck51bWJlcjogdGVzdERhdGEudGVzdG5ldEJsb2NrLmJsb2NrTnVtYmVyLFxuICAgICAgICBoZWFkZXJIYXNoOiB0ZXN0RGF0YS50ZXN0bmV0QmxvY2suaGFzaCxcbiAgICAgIH0pO1xuICAgICAgZ2V0RmVlQ0Iud2l0aEFyZ3MocmVjb3ZlcnlEZXN0aW5hdGlvbiwgdGVzdERhdGEudW5zaWduZWRTd2VlcFVzZXIud2FsbGV0QWRkcmVzcywgMTAwMDA3MDAwMDAwKS5yZXNvbHZlcyg3NDQwMSk7XG5cbiAgICAgIGNvbnN0IGNvbW1vbktleUNoYWluID0gdGVzdERhdGEudW5zaWduZWRTd2VlcFVzZXIuYml0Z29LZXk7XG5cbiAgICAgIGNvbnN0IHVuc2lnbmVkID0gYXdhaXQgYmFzZUNvaW4ucmVjb3Zlcih7IGJpdGdvS2V5OiBjb21tb25LZXlDaGFpbiwgcmVjb3ZlcnlEZXN0aW5hdGlvbiB9KTtcblxuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0cy5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0ud2FsbGV0Q29pbi5zaG91bGQuZXF1YWwoJ3Rwb2x5eCcpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zZXJpYWxpemVkVHguc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2NhbkluZGV4LnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguY29pbi5zaG91bGQuZXF1YWwoJ3Rwb2x5eCcpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaWduYWJsZUhleC5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5kZXJpdmF0aW9uUGF0aC5zaG91bGQuZXF1YWwoJ20vMCcpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5pbnB1dHMuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHgucGFyc2VkVHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB1bnNpZ25lZC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4LmlucHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChcbiAgICAgICAgJzVEblpRcWJ4dEIzQ1drTGdmQTZ3cHFka0NkOUJxN0FYNDlScExQSndXOW16b1Q3cydcbiAgICAgICk7XG4gICAgICB1bnNpZ25lZC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4LmlucHV0c1swXS52YWx1ZVN0cmluZy5zaG91bGQuZXF1YWwoJzEwMDAwNjI1NTk5MCcpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5pbnB1dHNbMF0udmFsdWUuc2hvdWxkLmVxdWFsKDEwMDAwNjI1NTk5MCk7XG4gICAgICB1bnNpZ25lZC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4Lm91dHB1dHMuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHgucGFyc2VkVHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKFxuICAgICAgICAnNUg1NmYzMWhTWUdDUlYzVVJqUUh2MkNjNFpTa0pOSFRNOE1LR3Rra1Y2aHpDcU43J1xuICAgICAgKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHgucGFyc2VkVHgub3V0cHV0c1swXS52YWx1ZVN0cmluZy5zaG91bGQuZXF1YWwoJzEwMDAwNjI1NTk5MCcpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5vdXRwdXRzWzBdLmNvaW5OYW1lLnNob3VsZC5lcXVhbCgndHBvbHl4Jyk7XG4gICAgICB1bnNpZ25lZC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4LnR5cGUuc2hvdWxkLmVxdWFsKCcnKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguZmVlSW5mby5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5mZWVJbmZvLmZlZS5zaG91bGQuZXF1YWwoMCk7XG4gICAgICB1bnNpZ25lZC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmZlZUluZm8uZmVlU3RyaW5nLnNob3VsZC5lcXVhbCgnMCcpO1xuICAgICAgdW5zaWduZWQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWMuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguY29pblNwZWNpZmljLmZpcnN0VmFsaWQuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguY29pblNwZWNpZmljLm1heER1cmF0aW9uLnNob3VsZC5lcXVhbCgyNDAwKTtcbiAgICAgIHVuc2lnbmVkLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguY29pblNwZWNpZmljLmNvbW1vbktleWNoYWluLnNob3VsZC5lcXVhbChcbiAgICAgICAgJzk3ZDlkYThiZjU0NGQwN2YzYzdhZThlZTA2YmIxMmE2M2Y3NDQ3OGQwYzQ2MTIwMWFiOTQ0MjFhOWM4MWQ1YjM3OTU1M2YwMzMyZGFhYTg1Y2I4YzY1ZTFmZTdlNjkwN2M2MjI2OGMwMDgxMmIwOGE0ZTEzNjExNzhlMzA0ZGRiJ1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBhIHR4IGZvciBub24tYml0Z28gcmVjb3ZlcmllcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFjY291bnRJbmZvQ0Iud2l0aEFyZ3ModGVzdERhdGEud3J3VXNlci53YWxsZXRBZGRyZXNzKS5yZXNvbHZlcyh7IG5vbmNlOiAwLCBmcmVlQmFsYW5jZTogMTAwMDA3MDAwMDAwIH0pO1xuICAgICAgaGVhZGVySW5mb0NCLnJlc29sdmVzKHtcbiAgICAgICAgaGVhZGVyTnVtYmVyOiB0ZXN0RGF0YS50ZXN0bmV0QmxvY2suYmxvY2tOdW1iZXIsXG4gICAgICAgIGhlYWRlckhhc2g6IHRlc3REYXRhLnRlc3RuZXRCbG9jay5oYXNoLFxuICAgICAgfSk7XG4gICAgICBnZXRGZWVDQi53aXRoQXJncyhyZWNvdmVyeURlc3RpbmF0aW9uLCB0ZXN0RGF0YS53cndVc2VyLndhbGxldEFkZHJlc3MsIDEwMDAwNzAwMDAwMCkucmVzb2x2ZXMoNzQ0MDEpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlQ29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogdGVzdERhdGEud3J3VXNlci51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IHRlc3REYXRhLndyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogdGVzdERhdGEud3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogdGVzdERhdGEud3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgfSk7XG5cbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHJlcy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NjYW5JbmRleCcpO1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBiYXNlQ29pbi5nZXRCdWlsZGVyKCkuZnJvbShyZXMuc2VyaWFsaXplZFR4KTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAudmFsaWRpdHkoe1xuICAgICAgICAgIGZpcnN0VmFsaWQ6IHRlc3REYXRhLnRlc3RuZXRCbG9jay5ibG9ja051bWJlcixcbiAgICAgICAgICBtYXhEdXJhdGlvbjogYmFzZUNvaW4uU1dFRVBfVFhOX0RVUkFUSU9OLFxuICAgICAgICB9KVxuICAgICAgICAucmVmZXJlbmNlQmxvY2sodGVzdERhdGEudGVzdG5ldEJsb2NrLmhhc2gpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5zZW5kZXIsIHRlc3REYXRhLndyd1VzZXIud2FsbGV0QWRkcmVzcyk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5ibG9ja051bWJlciwgdGVzdERhdGEudGVzdG5ldEJsb2NrLmJsb2NrTnVtYmVyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLnJlZmVyZW5jZUJsb2NrLCB0ZXN0RGF0YS50ZXN0bmV0QmxvY2suaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5nZW5lc2lzSGFzaCwgZ2VuZXNpc0hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uc3BlY1ZlcnNpb24sIHNwZWNWZXJzaW9uKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLm5vbmNlLCBub25jZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi50aXAsIDApO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24udHJhbnNhY3Rpb25WZXJzaW9uLCB0eFZlcnNpb24pO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uZXJhUGVyaW9kLCBiYXNlQ29pbi5TV0VFUF9UWE5fRFVSQVRJT04pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciB1bnNpZ25lZC1zd2VlcCByZWNvdmVyaWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYWNjb3VudEluZm9DQlxuICAgICAgICAud2l0aEFyZ3ModGVzdERhdGEudW5zaWduZWRTd2VlcFVzZXIud2FsbGV0QWRkcmVzcylcbiAgICAgICAgLnJlc29sdmVzKHsgbm9uY2U6IDAsIGZyZWVCYWxhbmNlOiAxMDAwMDcwMDAwMDAgfSk7XG4gICAgICBoZWFkZXJJbmZvQ0IucmVzb2x2ZXMoe1xuICAgICAgICBoZWFkZXJOdW1iZXI6IHRlc3REYXRhLnRlc3RuZXRCbG9jay5ibG9ja051bWJlcixcbiAgICAgICAgaGVhZGVySGFzaDogdGVzdERhdGEudGVzdG5ldEJsb2NrLmhhc2gsXG4gICAgICB9KTtcbiAgICAgIGdldEZlZUNCLndpdGhBcmdzKHJlY292ZXJ5RGVzdGluYXRpb24sIHRlc3REYXRhLnVuc2lnbmVkU3dlZXBVc2VyLndhbGxldEFkZHJlc3MsIDEwMDAwNzAwMDAwMCkucmVzb2x2ZXMoNzQ0MDEpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlQ29pbi5yZWNvdmVyKHtcbiAgICAgICAgYml0Z29LZXk6IHRlc3REYXRhLnVuc2lnbmVkU3dlZXBVc2VyLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgfSk7XG5cbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuICAgICAgcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhc093blByb3BlcnR5KCdzY2FuSW5kZXgnKTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gYmFzZUNvaW4uZ2V0QnVpbGRlcigpLmZyb20ocmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2VyaWFsaXplZFR4KTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAudmFsaWRpdHkoe1xuICAgICAgICAgIGZpcnN0VmFsaWQ6IHRlc3REYXRhLnRlc3RuZXRCbG9jay5ibG9ja051bWJlcixcbiAgICAgICAgICBtYXhEdXJhdGlvbjogYmFzZUNvaW4uU1dFRVBfVFhOX0RVUkFUSU9OLFxuICAgICAgICB9KVxuICAgICAgICAucmVmZXJlbmNlQmxvY2sodGVzdERhdGEudGVzdG5ldEJsb2NrLmhhc2gpXG4gICAgICAgIC5zZW5kZXIoeyBhZGRyZXNzOiB0ZXN0RGF0YS51bnNpZ25lZFN3ZWVwVXNlci53YWxsZXRBZGRyZXNzIH0pO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5zZW5kZXIsIHRlc3REYXRhLnVuc2lnbmVkU3dlZXBVc2VyLndhbGxldEFkZHJlc3MpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uYmxvY2tOdW1iZXIsIHRlc3REYXRhLnRlc3RuZXRCbG9jay5ibG9ja051bWJlcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5yZWZlcmVuY2VCbG9jaywgdGVzdERhdGEudGVzdG5ldEJsb2NrLmhhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uZ2VuZXNpc0hhc2gsIGdlbmVzaXNIYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLnNwZWNWZXJzaW9uLCBzcGVjVmVyc2lvbik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5ub25jZSwgMCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi50aXAsIDApO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24udHJhbnNhY3Rpb25WZXJzaW9uLCB0eFZlcnNpb24pO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uZXJhUGVyaW9kLCBiYXNlQ29pbi5TV0VFUF9UWE5fRFVSQVRJT04pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ01QQ3YyIHNpZ25lZCByZWNvdmVyeScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdC1wYXNzcGhyYXNlLW1wY3YyJztcbiAgICAgIGxldCBtcGNWMlVzZXJLZXk6IHN0cmluZztcbiAgICAgIGxldCBtcGNWMkJhY2t1cEtleTogc3RyaW5nO1xuICAgICAgbGV0IG1wY1YyQ29tbW9uS2V5Q2hhaW46IHN0cmluZztcbiAgICAgIGxldCBtcGNWMlJlY292ZXJQYXJhbXM6IE1QQ1JlY292ZXJ5T3B0aW9ucztcblxuICAgICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgW3VzZXJEa2csIGJhY2t1cERrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICAgICAgbXBjVjJDb21tb25LZXlDaGFpbiA9IHVzZXJEa2cuZ2V0Q29tbW9uS2V5Y2hhaW4oKTtcbiAgICAgICAgbXBjVjJVc2VyS2V5ID0gYXdhaXQgZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCB1c2VyRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLnRvU3RyaW5nKCdiYXNlNjQnKSk7XG4gICAgICAgIG1wY1YyQmFja3VwS2V5ID0gYXdhaXQgZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCBiYWNrdXBEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcblxuICAgICAgICBtcGNWMlJlY292ZXJQYXJhbXMgPSB7XG4gICAgICAgICAgdXNlcktleTogbXBjVjJVc2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogbXBjVjJCYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IG1wY1YyQ29tbW9uS2V5Q2hhaW4sXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICB9O1xuICAgICAgfSk7XG5cbiAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBVc2UgdW5yZXN0cmljdGVkIHJlc29sdmVzIChub3QgLndpdGhBcmdzKSBzaW5jZSB0aGUgbWlzbWF0Y2hlZC1iaXRnb0tleSB0ZXN0XG4gICAgICAgIC8vIGRlcml2ZXMgYSBkaWZmZXJlbnQgc2VuZGVyIGFkZHJlc3MgdGhhbiBtcGNWMldhbGxldEFkZHJlc3MuXG4gICAgICAgIGFjY291bnRJbmZvQ0IucmVzb2x2ZXMoeyBub25jZTogMCwgZnJlZUJhbGFuY2U6IDEwMDAwNzAwMDAwMCB9KTtcbiAgICAgICAgaGVhZGVySW5mb0NCLnJlc29sdmVzKHtcbiAgICAgICAgICBoZWFkZXJOdW1iZXI6IHRlc3REYXRhLnRlc3RuZXRCbG9jay5ibG9ja051bWJlcixcbiAgICAgICAgICBoZWFkZXJIYXNoOiB0ZXN0RGF0YS50ZXN0bmV0QmxvY2suaGFzaCxcbiAgICAgICAgfSk7XG4gICAgICAgIGdldEZlZUNCLnJlc29sdmVzKDc0NDAxKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHJlY292ZXIgYSB0eCB1c2luZyBNUEN2MiBzaWduaW5nIG1hdGVyaWFsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBnZXRUU1NTaWduYXR1cmVTcHkgPSBzYW5kQm94LnNweShFRERTQU1ldGhvZHMsICdnZXRUU1NTaWduYXR1cmUnKTtcbiAgICAgICAgY29uc3QgYWRkU2lnbmF0dXJlU3B5ID0gc2FuZEJveC5zcHkoVHJhbnNmZXJCdWlsZGVyLnByb3RvdHlwZSwgJ2FkZFNpZ25hdHVyZScpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IChhd2FpdCBiYXNlQ29pbi5yZWNvdmVyKG1wY1YyUmVjb3ZlclBhcmFtcykpIGFzIE1QQ1R4O1xuXG4gICAgICAgIHJlc3VsdC5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICAgIHJlc3VsdC5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuICAgICAgICByZXN1bHQuc2hvdWxkLmhhc093blByb3BlcnR5KCdzY2FuSW5kZXgnKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHJlc3VsdC5zY2FuSW5kZXgsIDApO1xuICAgICAgICAocmVzdWx0LnNlcmlhbGl6ZWRUeCBhcyBzdHJpbmcpLnNob3VsZC5iZS5hLlN0cmluZygpLmFuZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgICAgc2FuZEJveC5hc3NlcnQubm90Q2FsbGVkKGdldFRTU1NpZ25hdHVyZVNweSk7XG5cbiAgICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbGVkT25jZShhZGRTaWduYXR1cmVTcHkpO1xuICAgICAgICBjb25zdCBzaWduYXR1cmU6IEJ1ZmZlciA9IGFkZFNpZ25hdHVyZVNweS5maXJzdENhbGwuYXJnc1sxXTtcbiAgICAgICAgLy8gY29uc3RydWN0U2lnbmVkUGF5bG9hZCBwcmVwZW5kcyB0aGUgMHgwMCBFZDI1NTE5IGRpc2NyaW1pbmFudCBpbnRlcm5hbGx5O1xuICAgICAgICAvLyByZWNvdmVyKCkgbXVzdCBwYXNzIHRoZSByYXcgNjQtYnl0ZSBzaWduYXR1cmUgdW5jaGFuZ2VkLlxuICAgICAgICBzaWduYXR1cmUubGVuZ3RoLnNob3VsZC5lcXVhbCg2NCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGEgY3J5cHRvZ3JhcGhpY2FsbHkgdmFsaWQgRWQyNTUxOSBzaWduYXR1cmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGFkZFNpZ25hdHVyZVNweSA9IHNhbmRCb3guc3B5KFRyYW5zZmVyQnVpbGRlci5wcm90b3R5cGUsICdhZGRTaWduYXR1cmUnKTtcbiAgICAgICAgY29uc3Qgc2lnblJlY292ZXJ5U3B5ID0gc2FuZEJveC5zcHkoXG4gICAgICAgICAgYmFzZUNvaW4gYXMgdW5rbm93biBhcyB7IHNpZ25TdWJzdHJhdGVNcGNWMlJlY292ZXJ5OiB1bmtub3duIH0sXG4gICAgICAgICAgJ3NpZ25TdWJzdHJhdGVNcGNWMlJlY292ZXJ5J1xuICAgICAgICApO1xuXG4gICAgICAgIGF3YWl0IGJhc2VDb2luLnJlY292ZXIobXBjVjJSZWNvdmVyUGFyYW1zKTtcblxuICAgICAgICAvLyA2NS1ieXRlIHNpZzogMHgwMCBkaXNjcmltaW5hbnQgKyA2NC1ieXRlIEVkMjU1MTkgc2lnOyBzaWduYXR1cmVWZXJpZnkgaGFuZGxlcyB0aGUgcHJlZml4LlxuICAgICAgICBjb25zdCBzaWduYXR1cmU6IEJ1ZmZlciA9IGFkZFNpZ25hdHVyZVNweS5maXJzdENhbGwuYXJnc1sxXTtcblxuICAgICAgICAvLyBDYXB0dXJlIHRoZSBleGFjdCBieXRlcyBzaWduZWQgYnkgdGhlIERTRyBwcm90b2NvbCBpbnNpZGUgc2lnblN1YnN0cmF0ZU1wY1YyUmVjb3ZlcnkuXG4gICAgICAgIGNvbnN0IHNpZ25hYmxlUGF5bG9hZDogQnVmZmVyID0gKHNpZ25SZWNvdmVyeVNweS5maXJzdENhbGwuYXJnc1swXSBhcyB7IG1lc3NhZ2U6IEJ1ZmZlciB9KS5tZXNzYWdlO1xuXG4gICAgICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgICAgIGNvbnN0IGFjY291bnRJZCA9IE1QQy5kZXJpdmVVbmhhcmRlbmVkKG1wY1YyQ29tbW9uS2V5Q2hhaW4sICdtLzAnKS5zbGljZSgwLCA2NCk7XG5cbiAgICAgICAgY29uc3Qgc2VuZGVyQWRkciA9IGJhc2VDb2luLmdldEFkZHJlc3NGcm9tUHVibGljS2V5KGFjY291bnRJZCk7XG4gICAgICAgIGNvbnN0IGlzVmFsaWQgPSB1dGlscy52ZXJpZnlTaWduYXR1cmUoXG4gICAgICAgICAgYDB4JHtzaWduYWJsZVBheWxvYWQudG9TdHJpbmcoJ2hleCcpfWAsXG4gICAgICAgICAgYDB4JHtzaWduYXR1cmUudG9TdHJpbmcoJ2hleCcpfWAsXG4gICAgICAgICAgc2VuZGVyQWRkclxuICAgICAgICApO1xuICAgICAgICBpc1ZhbGlkLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB1c2UgTVBDdjEgcGF0aCB3aGVuIHNpZ25pbmcgbWF0ZXJpYWwgaXMgTVBDdjEgZm9ybWF0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB1c2VyUHJ2ID0gSlNPTi5zdHJpbmdpZnkoeyB1U2hhcmU6IHsgc2VlZDogJ2FhJyB9LCBiaXRnb1lTaGFyZTogeyB1OiAnYmInIH0sIGJhY2t1cFlTaGFyZTogeyB1OiAnY2MnIH0gfSk7XG4gICAgICAgIHNhbmRCb3hcbiAgICAgICAgICAuc3R1YihiYXNlQ29pbiBhcyB1bmtub3duIGFzIHsgZ2V0RWRkc2FTaWduaW5nTWF0ZXJpYWw6IHVua25vd24gfSwgJ2dldEVkZHNhU2lnbmluZ01hdGVyaWFsJylcbiAgICAgICAgICAucmVzb2x2ZXMoeyB2ZXJzaW9uOiAndjEnLCB1c2VyUHJ2IH0pO1xuXG4gICAgICAgIGNvbnN0IGdldFRTU1NpZ25hdHVyZVN0dWIgPSBzYW5kQm94XG4gICAgICAgICAgLnN0dWIoRUREU0FNZXRob2RzLCAnZ2V0VFNTU2lnbmF0dXJlJylcbiAgICAgICAgICAucmVzb2x2ZXMoXG4gICAgICAgICAgICBCdWZmZXIuZnJvbShcbiAgICAgICAgICAgICAgJzFiYWFmYTBkNjIxNzRiZjBjNzhmMzI1NjMxODYxM2ZmYzQ0YjZkZDU0YWIxYTYzYzIxODUyMzJmOTJlZGU5ZGEnICtcbiAgICAgICAgICAgICAgICAnZTFiMjgxOGRiZWI1MmE4MjE1ZmQ1NmY1YTVmMmE5Zjk0YzA3OWNlODllNGRjM2IxY2U2ZWQ2ZTg0Y2U3MTg1NycsXG4gICAgICAgICAgICAgICdoZXgnXG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcblxuICAgICAgICBzYW5kQm94XG4gICAgICAgICAgLnN0dWIoYml0Z28sICdkZWNyeXB0JylcbiAgICAgICAgICAud2l0aEFyZ3Moc2lub24ubWF0Y2goeyBpbnB1dDogbXBjVjJCYWNrdXBLZXkucmVwbGFjZSgvXFxzL2csICcnKSB9KSlcbiAgICAgICAgICAucmVzb2x2ZXMoSlNPTi5zdHJpbmdpZnkoeyBiU2hhcmU6IHt9LCB5U2hhcmVzOiB7fSB9KSk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gKGF3YWl0IGJhc2VDb2luLnJlY292ZXIobXBjVjJSZWNvdmVyUGFyYW1zKSkgYXMgTVBDVHg7XG5cbiAgICAgICAgcmVzdWx0LnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgICAgcmVzdWx0LnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICAgIHJlc3VsdC5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NjYW5JbmRleCcpO1xuICAgICAgICBzaG91bGQuZXF1YWwocmVzdWx0LnNjYW5JbmRleCwgMCk7XG4gICAgICAgIChyZXN1bHQuc2VyaWFsaXplZFR4IGFzIHN0cmluZykuc2hvdWxkLmJlLmEuU3RyaW5nKCkuYW5kLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRPbmNlKGdldFRTU1NpZ25hdHVyZVN0dWIpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgYSBkZXNjcmlwdGl2ZSBlcnJvciB3aGVuIHVzZXIga2V5Y2hhaW4gZGVjcnlwdGlvbiBmYWlscyBvbiB0aGUgTVBDdjEgcGF0aCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2FuZEJveC5zdHViKGJpdGdvLCAnZGVjcnlwdCcpLnJlamVjdHMobmV3IEVycm9yKCdwYXNzd29yZCBlcnJvcicpKTtcblxuICAgICAgICBhd2FpdCBiYXNlQ29pbi5yZWNvdmVyKG1wY1YyUmVjb3ZlclBhcmFtcykuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGNvbW1vbktleUNoYWluIGZyb20gTVBDdjIga2V5Y2FyZCBkb2VzIG5vdCBtYXRjaCBiaXRnb0tleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgbWlzbWF0Y2hlZEJpdGdvS2V5ID0gbXBjVjJDb21tb25LZXlDaGFpbi5zbGljZSgwLCAtOCkgKyAnMDAwMDAwMDAnO1xuICAgICAgICBjb25zdCBtaXNtYXRjaGVkUGFyYW1zID0ge1xuICAgICAgICAgIC4uLm1wY1YyUmVjb3ZlclBhcmFtcyxcbiAgICAgICAgICBiaXRnb0tleTogbWlzbWF0Y2hlZEJpdGdvS2V5LFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGJhc2VDb2luXG4gICAgICAgICAgLnJlY292ZXIobWlzbWF0Y2hlZFBhcmFtcylcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnRWREU0EgTVBDdjIgcmVjb3Zlcnk6IGNvbW1vbktleUNoYWluIGZyb20ga2V5Y2FyZCBkb2VzIG5vdCBtYXRjaCBiaXRnb0tleScpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgbWlzc2luZyB1c2VyS2V5IHdoZW4gYmFja3VwS2V5IGFuZCB3YWxsZXRQYXNzcGhyYXNlIGFyZSBwcmVzZW50IGJ1dCB1c2VyS2V5IGlzIG5vdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zV2l0aG91dFVzZXJLZXkgPSB7IC4uLm1wY1YyUmVjb3ZlclBhcmFtcywgdXNlcktleTogdW5kZWZpbmVkIH07XG4gICAgICAgIGF3YWl0IGJhc2VDb2luLnJlY292ZXIocGFyYW1zV2l0aG91dFVzZXJLZXkpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgdXNlcktleScpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgbWlzc2luZyBiYWNrdXBLZXkgd2hlbiB1c2VyS2V5IGFuZCB3YWxsZXRQYXNzcGhyYXNlIGFyZSBwcmVzZW50IGJ1dCBiYWNrdXBLZXkgaXMgbm90JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBwYXJhbXNXaXRob3V0QmFja3VwS2V5ID0geyAuLi5tcGNWMlJlY292ZXJQYXJhbXMsIGJhY2t1cEtleTogdW5kZWZpbmVkIH07XG4gICAgICAgIGF3YWl0IGJhc2VDb2luLnJlY292ZXIocGFyYW1zV2l0aG91dEJhY2t1cEtleSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyBiYWNrdXBLZXknKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IG1pc3Npbmcgd2FsbGV0IHBhc3NwaHJhc2Ugd2hlbiB1c2VyS2V5IGFuZCBiYWNrdXBLZXkgYXJlIHByZXNlbnQgYnV0IHdhbGxldFBhc3NwaHJhc2UgaXMgbm90JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBwYXJhbXNXaXRob3V0UGFzc3BocmFzZSA9IHsgLi4ubXBjVjJSZWNvdmVyUGFyYW1zLCB3YWxsZXRQYXNzcGhyYXNlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgYXdhaXQgYmFzZUNvaW4ucmVjb3ZlcihwYXJhbXNXaXRob3V0UGFzc3BocmFzZSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyB3YWxsZXQgcGFzc3BocmFzZScpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcGFzcyB0aGUgcmF3IDY0LWJ5dGUgc2lnbmF0dXJlIHRvIGFkZFNpZ25hdHVyZSBvbiBNUEN2MiBwYXRoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBSZWdyZXNzaW9uOiBwcmV2aW91c2x5IHdyYXBwZWQgcmF3U2lnIHdpdGggYSBtYW51YWwgRWQyNTUxOSBkaXNjcmltaW5hbnQgKDB4MDApXG4gICAgICAgIC8vIGJlZm9yZSBhZGRTaWduYXR1cmUuIGNvbnN0cnVjdFNpZ25lZFBheWxvYWQgYWxyZWFkeSBwcmVwZW5kcyB0aGF0IGRpc2NyaW1pbmFudCxcbiAgICAgICAgLy8gc28gd3JhcHBpbmcgaGVyZSBjYXVzZWQgYSBkb3VibGUgcHJlZml4IHRoYXQgc2hpZnRlZCB0aGUgb24td2lyZSBzaWduYXR1cmUgYnlcbiAgICAgICAgLy8gb25lIGJ5dGUsIGRyb3BwaW5nIHRoZSBsYXN0IGJ5dGUgb2Ygc2lnbWEgYW5kIHByb2R1Y2luZ1xuICAgICAgICAvLyBgMTAxMDogQmFkIHNpZ25hdHVyZWAgb24tY2hhaW4uXG4gICAgICAgIGNvbnN0IHJhd1NpZyA9IEJ1ZmZlci5hbGxvYyg2NCwgMHhhYik7XG4gICAgICAgIHNhbmRCb3hcbiAgICAgICAgICAuc3R1YihiYXNlQ29pbiBhcyB1bmtub3duIGFzIHsgc2lnblN1YnN0cmF0ZU1wY1YyUmVjb3Zlcnk6IHVua25vd24gfSwgJ3NpZ25TdWJzdHJhdGVNcGNWMlJlY292ZXJ5JylcbiAgICAgICAgICAucmVzb2x2ZXMocmF3U2lnKTtcbiAgICAgICAgY29uc3QgYWRkU2lnbmF0dXJlU3B5ID0gc2FuZEJveC5zcHkoVHJhbnNmZXJCdWlsZGVyLnByb3RvdHlwZSwgJ2FkZFNpZ25hdHVyZScpO1xuXG4gICAgICAgIGF3YWl0IGJhc2VDb2luLnJlY292ZXIobXBjVjJSZWNvdmVyUGFyYW1zKTtcblxuICAgICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRPbmNlKGFkZFNpZ25hdHVyZVNweSk7XG4gICAgICAgIGNvbnN0IHNpZzogQnVmZmVyID0gYWRkU2lnbmF0dXJlU3B5LmZpcnN0Q2FsbC5hcmdzWzFdO1xuICAgICAgICBzaWcubGVuZ3RoLnNob3VsZC5lcXVhbCg2NCk7XG4gICAgICAgIHNpZy5zaG91bGQuZGVlcEVxdWFsKHJhd1NpZyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXIgVHJhbnNhY3Rpb24gRmFpbHVyZXM6JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgY29uc3QgcmVjb3ZlcnlEZXN0aW5hdGlvbiA9ICc1SDU2ZjMxaFNZR0NSVjNVUmpRSHYyQ2M0WlNrSk5IVE04TUtHdGtrVjZoekNxTjcnO1xuXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnN0dWIoUG9seXgucHJvdG90eXBlLCAnZ2V0QWNjb3VudEluZm8nIGFzIGtleW9mIFBvbHl4KS5yZXNvbHZlcyh7IG5vbmNlOiAwLCBmcmVlQmFsYW5jZTogMCB9KTtcbiAgICAgIHNhbmRCb3guc3R1YihQb2x5eC5wcm90b3R5cGUsICdnZXRGZWUnIGFzIGtleW9mIFBvbHl4KS5yZXNvbHZlcyg3NDQwMSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZEJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gcmVjb3ZlciBkdWUgdG8gbm90IGZpbmRpbmcgYW4gYWRkcmVzcyB3aXRoIGZ1bmRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYmFzZUNvaW5cbiAgICAgICAgLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IHRlc3REYXRhLndyd1VzZXIudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IHRlc3REYXRhLndyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiB0ZXN0RGF0YS53cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHRlc3REYXRhLndyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLnJlamVjdGVkV2l0aChFcnJvck5vSW5wdXRUb1JlY292ZXIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBSZWNvdmVyeVByb3ZpZGVyRXJyb3Igd2hlbiBhY2NvdW50IGluZm8gcXVlcnkgZmFpbHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAoUG9seXgucHJvdG90eXBlIGFzIHVua25vd24gYXMgeyBnZXRBY2NvdW50SW5mbzogc2lub24uU2lub25TdHViIH0pLmdldEFjY291bnRJbmZvLnJlamVjdHMoXG4gICAgICAgIG5ldyBFcnJvcignbmV0d29yayBmYWlsdXJlJylcbiAgICAgICk7XG4gICAgICBhd2FpdCBiYXNlQ29pblxuICAgICAgICAucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogdGVzdERhdGEud3J3VXNlci51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogdGVzdERhdGEud3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IHRlc3REYXRhLndyd1VzZXIuYml0Z29LZXksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogdGVzdERhdGEud3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFJlY292ZXJ5UHJvdmlkZXJFcnJvcik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUb2tlbiBFbmFibGVtZW50OicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCB0b2tlbiBlbmFibGVtZW50IGNvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IGJhc2VDb2luLmdldFRva2VuRW5hYmxlbWVudENvbmZpZygpO1xuICAgICAgc2hvdWxkLmV4aXN0KGNvbmZpZyk7XG4gICAgICBjb25maWcucmVxdWlyZXNUb2tlbkVuYWJsZW1lbnQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgY29uZmlnLnN1cHBvcnRzTXVsdGlwbGVUb2tlbkVuYWJsZW1lbnRzLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHdhbGxldCB0eXBlIGZvciB0b2tlbiBlbmFibGVtZW50JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY29uZmlnID0gYmFzZUNvaW4uZ2V0VG9rZW5FbmFibGVtZW50Q29uZmlnKCk7XG4gICAgICAoKCkgPT4gY29uZmlnLnZhbGlkYXRlV2FsbGV0KCdjdXN0b2RpYWwnKSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgKCgpID0+IGNvbmZpZy52YWxpZGF0ZVdhbGxldCgnaG90JykpLnNob3VsZC50aHJvdyhcbiAgICAgICAgL1Rva2VuIGVuYWJsZW1lbnQgZm9yIFBvbHltZXNoIFxcKHBvbHl4XFwpIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBjdXN0b2RpYWwgd2FsbGV0cy9cbiAgICAgICk7XG4gICAgICAoKCkgPT4gY29uZmlnLnZhbGlkYXRlV2FsbGV0KCdjb2xkJykpLnNob3VsZC50aHJvdyhcbiAgICAgICAgL1Rva2VuIGVuYWJsZW1lbnQgZm9yIFBvbHltZXNoIFxcKHBvbHl4XFwpIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBjdXN0b2RpYWwgd2FsbGV0cy9cbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2ZXJpZnlUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0cmFuc2ZlclRvID0gJzVGOGp4S0U4MUdoRnJwaHlmTUZyNVVqZUF6NXdTNEFhWkZtZUZQbmY4d1RldEQ3Mic7XG4gICAgY29uc3QgdHJhbnNmZXJBbW91bnQgPSAnMjAwMDAwMDAwMCc7XG4gICAgY29uc3Qgd3JvbmdBZGRyZXNzID0gJzVHaGJDNm4ycFVGclg5OER3eVBpdDY3ZkI1QXdRdlZDd1o0ajJIS0E3YTRkVUs0eSc7XG5cbiAgICBkZXNjcmliZSgndHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIHdoZW4gYWRkcmVzcyBhbmQgYW1vdW50IG1hdGNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleDogcmF3VHgudHJhbnNmZXIuc2lnbmVkIH0sXG4gICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogdHJhbnNmZXJUbywgYW1vdW50OiB0cmFuc2ZlckFtb3VudCB9XSB9LFxuICAgICAgICB9KTtcbiAgICAgICAgcmVzdWx0LnNob3VsZC5iZS50cnVlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBUeEludGVudE1pc21hdGNoUmVjaXBpZW50RXJyb3IgZm9yIGFkZHJlc3MgbWlzbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGJhc2VDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnNpZ25lZCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogd3JvbmdBZGRyZXNzLCBhbW91bnQ6IHRyYW5zZmVyQW1vdW50IH1dIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChUeEludGVudE1pc21hdGNoUmVjaXBpZW50RXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgVHhJbnRlbnRNaXNtYXRjaFJlY2lwaWVudEVycm9yIGZvciBhbW91bnQgbWlzbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGJhc2VDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnNpZ25lZCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogdHJhbnNmZXJUbywgYW1vdW50OiAnMScgfV0gfSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFR4SW50ZW50TWlzbWF0Y2hSZWNpcGllbnRFcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdndWFyZCBjYXNlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiB0eEhleCBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBhd2FpdCBiYXNlQ29pblxuICAgICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICB0eFByZWJ1aWxkOiB7fSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7IHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IHRyYW5zZmVyVG8sIGFtb3VudDogdHJhbnNmZXJBbW91bnQgfV0gfSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHR4SGV4IGluIHR4UHJlYnVpbGQnKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50cyBoYXMgbW9yZSB0aGFuIDEgZW50cnknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGJhc2VDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnNpZ25lZCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICAgIHsgYWRkcmVzczogdHJhbnNmZXJUbywgYW1vdW50OiB0cmFuc2ZlckFtb3VudCB9LFxuICAgICAgICAgICAgICAgIHsgYWRkcmVzczogd3JvbmdBZGRyZXNzLCBhbW91bnQ6IHRyYW5zZmVyQW1vdW50IH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3N1cHBvcnQgc2VuZGluZyB0byBtb3JlIHRoYW4gMSBkZXN0aW5hdGlvbiBhZGRyZXNzLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHJlY2lwaWVudHMgaXMgYW4gZW1wdHkgYXJyYXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGJhc2VDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnNpZ25lZCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW10gfSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHJlY2lwaWVudHMgaW4gdHhQYXJhbXMnKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3Rva2VuIGVuYWJsZW1lbnQgKHByZUFwcHJvdmVBc3NldCkgdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBlbmFibGV0b2tlbiB0eXBlIHdpdGggcmVjaXBpZW50cyAod2FsbGV0IHJvb3QgYWRkcmVzcyknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGJ1aWxkVG9rZW5FbmFibGVtZW50cyBzZXRzIHJlY2lwaWVudHNbMF0uYWRkcmVzcyA9IHdhbGxldCByb290QWRkcmVzcyBhbmQgdHlwZSA9ICdlbmFibGV0b2tlbicuXG4gICAgICAgIC8vIHZlcmlmeVRyYW5zYWN0aW9uIG11c3Qgc2hvcnQtY2lyY3VpdCBiZWZvcmUgdGhlIF90byBjaGVjayBzaW5jZSBwcmVBcHByb3ZlQXNzZXQgaGFzIG5vIGRlc3RpbmF0aW9uLlxuICAgICAgICBjb25zdCB3YWxsZXRBZGRyZXNzID0gJzVGOGp4S0U4MUdoRnJwaHlmTUZyNVVqZUF6NXdTNEFhWkZtZUZQbmY4d1RldEQ3Mic7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2VDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4OiByYXdUeC5wcmVBcHByb3ZlQXNzZXQuc2lnbmVkIH0sXG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiB3YWxsZXRBZGRyZXNzLCBhbW91bnQ6ICcwJywgdG9rZW5OYW1lOiAndHBvbHl4OnNvbWV0b2tlbicgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGVuYWJsZXRva2VuIHR5cGUgd2l0aCBubyByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleDogcmF3VHgucHJlQXBwcm92ZUFzc2V0LnNpZ25lZCB9LFxuICAgICAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICdlbmFibGV0b2tlbicgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgndjggdHJhbnNmZXIgd2l0aCBjb2luU3BlY2lmaWMubWF0ZXJpYWwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2OEFtb3VudCA9ICcxMDAwMDAwJztcbiAgICAgIGNvbnN0IHY4UmVjZWl2ZXIgPSBhY2NvdW50cy5hY2NvdW50MjtcbiAgICAgIGNvbnN0IHY4U2VuZGVyID0gYWNjb3VudHMuYWNjb3VudDE7XG4gICAgICBsZXQgdjhTaWduZWRUeEhleDogc3RyaW5nO1xuXG4gICAgICBiZWZvcmUoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBCdWlsZCBhIHNpZ25lZCB2OCB0cmFuc2ZlciB0eCB1c2luZyB0ZXN0bmV0VjhNYXRlcmlhbC5cbiAgICAgICAgLy8gVGhlIHNlcnZlciBlbWJlZHMgdGhpcyBtYXRlcmlhbCBpbiBjb2luU3BlY2lmaWMgZHVyaW5nIHByZWJ1aWxkIHNvIHRoYXRcbiAgICAgICAgLy8gdmVyaWZ5VHJhbnNhY3Rpb24gY2FuIGRlY29kZSB0eEhleCBidWlsdCBhZ2FpbnN0IGEgY2hhaW4gc3BlYyBuZXdlciB0aGFuXG4gICAgICAgIC8vIHRoZSBTREsncyBoYXJkY29kZWQgdjcgbWF0ZXJpYWwgKENFQ0hPLTE0NzEpLlxuICAgICAgICBjb25zdCBidWlsZGVyID0gbmV3IFY4VHJhbnNmZXJCdWlsZGVyKGNvaW5zLmdldCgndHBvbHl4JykpXG4gICAgICAgICAgLmFtb3VudCh2OEFtb3VudClcbiAgICAgICAgICAudG8oeyBhZGRyZXNzOiB2OFJlY2VpdmVyLmFkZHJlc3MgfSlcbiAgICAgICAgICAuc2VuZGVyKHsgYWRkcmVzczogdjhTZW5kZXIuYWRkcmVzcyB9KVxuICAgICAgICAgIC5tZW1vKCcwJylcbiAgICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiAzOTMzLCBtYXhEdXJhdGlvbjogNjQgfSlcbiAgICAgICAgICAucmVmZXJlbmNlQmxvY2soJzB4MTQ5Nzk5YmM5NjAyY2I1Y2YyMDFmMzQyNWZiOGQyNTNiMmQ0ZTYxZmMxMTlkY2FiMzI0OWYzMDdmNTk0NzU0ZCcpXG4gICAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMSB9KVxuICAgICAgICAgIC5mZWUoeyBhbW91bnQ6IDAsIHR5cGU6ICd0aXAnIH0pO1xuICAgICAgICBidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdjhTZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKG1vY2tUc3NTaWduYXR1cmUsICdoZXgnKSk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRlci5idWlsZCgpO1xuICAgICAgICB2OFNpZ25lZFR4SGV4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgndmVyaWZpZXMgYSB2OCB0cmFuc2ZlciB3aGVuIGNvaW5TcGVjaWZpYy5tYXRlcmlhbCBpcyBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZUNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiB2OFNpZ25lZFR4SGV4LFxuICAgICAgICAgICAgY29pblNwZWNpZmljOiB7IG1hdGVyaWFsOiB0ZXN0bmV0VjhNYXRlcmlhbCB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogdjhSZWNlaXZlci5hZGRyZXNzLCBhbW91bnQ6IHY4QW1vdW50IH1dIH0sXG4gICAgICAgIH0pO1xuICAgICAgICByZXN1bHQuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgndGhyb3dzIFR4SW50ZW50TWlzbWF0Y2hSZWNpcGllbnRFcnJvciBmb3IgYWRkcmVzcyBtaXNtYXRjaCBvbiB2OCB0cmFuc2ZlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgYmFzZUNvaW5cbiAgICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgICB0eEhleDogdjhTaWduZWRUeEhleCxcbiAgICAgICAgICAgICAgY29pblNwZWNpZmljOiB7IG1hdGVyaWFsOiB0ZXN0bmV0VjhNYXRlcmlhbCB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7IHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IHdyb25nQWRkcmVzcywgYW1vdW50OiB2OEFtb3VudCB9XSB9LFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoVHhJbnRlbnRNaXNtYXRjaFJlY2lwaWVudEVycm9yKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgndGhyb3dzIFR4SW50ZW50TWlzbWF0Y2hSZWNpcGllbnRFcnJvciBmb3IgYW1vdW50IG1pc21hdGNoIG9uIHY4IHRyYW5zZmVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBhd2FpdCBiYXNlQ29pblxuICAgICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICAgIHR4SGV4OiB2OFNpZ25lZFR4SGV4LFxuICAgICAgICAgICAgICBjb2luU3BlY2lmaWM6IHsgbWF0ZXJpYWw6IHRlc3RuZXRWOE1hdGVyaWFsIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogdjhSZWNlaXZlci5hZGRyZXNzLCBhbW91bnQ6ICcxJyB9XSB9LFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoVHhJbnRlbnRNaXNtYXRjaFJlY2lwaWVudEVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24gKE1QQ3YyKTonLCAoKSA9PiB7XG4gICAgY29uc3Qgc2FuZEJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcbiAgICBsZXQgdXNlcktleVNoYXJlOiBCdWZmZXI7XG4gICAgbGV0IGJhY2t1cEtleVNoYXJlOiBCdWZmZXI7XG4gICAgbGV0IGNvbW1vbktleWNoYWluOiBzdHJpbmc7XG4gICAgbGV0IG1wY3YyU3dlZXBUeFJlcXVlc3Q6IGFueTtcbiAgICBsZXQgbXBjdjJTaWduYXR1cmVIZXg6IHN0cmluZztcblxuICAgIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBbdXNlckRrZywgYmFja3VwRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgICAgY29tbW9uS2V5Y2hhaW4gPSB1c2VyRGtnLmdldENvbW1vbktleWNoYWluKCk7XG4gICAgICB1c2VyS2V5U2hhcmUgPSB1c2VyRGtnLmdldEtleVNoYXJlKCk7XG4gICAgICBiYWNrdXBLZXlTaGFyZSA9IGJhY2t1cERrZy5nZXRLZXlTaGFyZSgpO1xuXG4gICAgICBjb25zdCByZWNvdmVyeURlc3RpbmF0aW9uID0gJzVINTZmMzFoU1lHQ1JWM1VSalFIdjJDYzRaU2tKTkhUTThNS0d0a2tWNmh6Q3FONyc7XG4gICAgICBjb25zdCBtcGMgPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpO1xuICAgICAgY29uc3Qgd2FsbGV0QWRkcmVzcyA9IGJhc2VDb2luLmdldEFkZHJlc3NGcm9tUHVibGljS2V5KG1wYy5kZXJpdmVVbmhhcmRlbmVkKGNvbW1vbktleWNoYWluLCAnbS8wJykuc2xpY2UoMCwgNjQpKTtcbiAgICAgIGNvbnN0IGFjY291bnRJbmZvQ0IgPSBzYW5kQm94LnN0dWIoUG9seXgucHJvdG90eXBlLCAnZ2V0QWNjb3VudEluZm8nIGFzIGtleW9mIFBvbHl4KTtcbiAgICAgIGFjY291bnRJbmZvQ0Iud2l0aEFyZ3Mod2FsbGV0QWRkcmVzcykucmVzb2x2ZXMoeyBub25jZTogMCwgZnJlZUJhbGFuY2U6IDEwMDAwNzAwMDAwMCB9KTtcbiAgICAgIGNvbnN0IGhlYWRlckluZm9DQiA9IHNhbmRCb3guc3R1YihQb2x5eC5wcm90b3R5cGUsICdnZXRIZWFkZXJJbmZvJyBhcyBrZXlvZiBQb2x5eCk7XG4gICAgICBoZWFkZXJJbmZvQ0IucmVzb2x2ZXMoe1xuICAgICAgICBoZWFkZXJOdW1iZXI6IHRlc3REYXRhLnRlc3RuZXRCbG9jay5ibG9ja051bWJlcixcbiAgICAgICAgaGVhZGVySGFzaDogdGVzdERhdGEudGVzdG5ldEJsb2NrLmhhc2gsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGdldEZlZUNCID0gc2FuZEJveC5zdHViKFBvbHl4LnByb3RvdHlwZSwgJ2dldEZlZScgYXMga2V5b2YgUG9seXgpO1xuICAgICAgZ2V0RmVlQ0Iud2l0aEFyZ3MocmVjb3ZlcnlEZXN0aW5hdGlvbiwgd2FsbGV0QWRkcmVzcywgMTAwMDA3MDAwMDAwKS5yZXNvbHZlcyg3NDQwMSk7XG4gICAgICBjb25zdCBnZXRNYXRlcmlhbENCID0gc2FuZEJveC5zdHViKFBvbHl4LnByb3RvdHlwZSwgJ2dldE1hdGVyaWFsJyBhcyBrZXlvZiBQb2x5eCk7XG4gICAgICBnZXRNYXRlcmlhbENCLnJlc29sdmVzKHV0aWxzLmdldE1hdGVyaWFsKGNvaW5zLmdldCgndHBvbHl4JykubmV0d29yay50eXBlKSk7XG5cbiAgICAgIC8vIG5vIHdhbGxldFBhc3NwaHJhc2UgLT4gdW5zaWduZWQgc3dlZXAgcGF0aCByZXR1cm5zIE1QQ1N3ZWVwVHhzXG4gICAgICBjb25zdCBzd2VlcCA9IChhd2FpdCBiYXNlQ29pbi5yZWNvdmVyKHtcbiAgICAgICAgYml0Z29LZXk6IGNvbW1vbktleWNoYWluLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgfSkpIGFzIE1QQ1N3ZWVwVHhzO1xuICAgICAgc2FuZEJveC5yZXN0b3JlKCk7XG5cbiAgICAgIG1wY3YyU3dlZXBUeFJlcXVlc3QgPSBzd2VlcC50eFJlcXVlc3RzWzBdO1xuICAgICAgY29uc3QgdW5zaWduZWRUeCA9IG1wY3YyU3dlZXBUeFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBzaWduUmVjb3ZlcnlFZGRzYU1QQ3YyKFxuICAgICAgICBCdWZmZXIuZnJvbSh1bnNpZ25lZFR4LnNpZ25hYmxlSGV4LCAnaGV4JyksXG4gICAgICAgIHVuc2lnbmVkVHguZGVyaXZhdGlvblBhdGgsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGNvbW1vbktleWNoYWluXG4gICAgICApO1xuICAgICAgbXBjdjJTaWduYXR1cmVIZXggPSBzaWduYXR1cmUudG9TdHJpbmcoJ2hleCcpO1xuICAgIH0pO1xuXG4gICAgLy8gY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24gY2FsbHMgZ2V0TWF0ZXJpYWwoKSB0byByZS1lbmNvZGUgdGhlIHNpZ25lZFxuICAgIC8vIHRyYW5zYWN0aW9uOyBzdHViIGl0IHdpdGggdGhlIHNhbWUgdGVzdG5ldCBtYXRlcmlhbCB0aGUgc3dlZXAgd2FzIGJ1aWx0IHdpdGguXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBnZXRNYXRlcmlhbENCID0gc2FuZEJveC5zdHViKFBvbHl4LnByb3RvdHlwZSwgJ2dldE1hdGVyaWFsJyBhcyBrZXlvZiBQb2x5eCk7XG4gICAgICBnZXRNYXRlcmlhbENCLnJlc29sdmVzKHV0aWxzLmdldE1hdGVyaWFsKGNvaW5zLmdldCgndHBvbHl4JykubmV0d29yay50eXBlKSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZEJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBidWlsZFBhcmFtcyhvdmM6IGFueSk6IE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNpZ25hdHVyZVNoYXJlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR4UmVxdWVzdDogbXBjdjJTd2VlcFR4UmVxdWVzdCxcbiAgICAgICAgICAgIHRzc1ZlcnNpb246ICcwLjAuMScsXG4gICAgICAgICAgICBvdmM6IFtvdmNdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9IGFzIE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zO1xuICAgIH1cblxuICAgIGl0KCdzaG91bGQgdGFrZSBNUEN2MiBPVkMgb3V0cHV0IGFuZCBnZW5lcmF0ZSBhIHNpZ25lZCBzd2VlcCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IGJ1aWxkUGFyYW1zKHsgZWRkc2FNcGN2MlNpZ25hdHVyZTogbXBjdjJTaWduYXR1cmVIZXggfSk7XG4gICAgICBjb25zdCByZWNvdmVyeVR4biA9IGF3YWl0IGJhc2VDb2luLmNyZWF0ZUJyb2FkY2FzdGFibGVTd2VlcFRyYW5zYWN0aW9uKHBhcmFtcyk7XG5cbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1swXS5zZXJpYWxpemVkVHguc2hvdWxkLm5vdC5lcXVhbChcbiAgICAgICAgbXBjdjJTd2VlcFR4UmVxdWVzdC50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zZXJpYWxpemVkVHhcbiAgICAgICk7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMF0uc2VyaWFsaXplZFR4LnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIChyZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMF0uc2NhbkluZGV4ID8/IDApLnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIChyZWNvdmVyeVR4bi5sYXN0U2NhbkluZGV4ID8/IDApLnNob3VsZC5lcXVhbCgwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgdGFtcGVyZWQgTVBDdjIgc2lnbmF0dXJlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdW5zaWduZWRUeCA9IG1wY3YyU3dlZXBUeFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICBjb25zdCB0YW1wZXJlZE1lc3NhZ2UgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbSh1bnNpZ25lZFR4LnNpZ25hYmxlSGV4LCAnaGV4JyksIEJ1ZmZlci5mcm9tKCcwMCcsICdoZXgnKV0pO1xuICAgICAgY29uc3QgdGFtcGVyZWRTaWduYXR1cmUgPSBhd2FpdCBzaWduUmVjb3ZlcnlFZGRzYU1QQ3YyKFxuICAgICAgICB0YW1wZXJlZE1lc3NhZ2UsXG4gICAgICAgIHVuc2lnbmVkVHguZGVyaXZhdGlvblBhdGgsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGNvbW1vbktleWNoYWluXG4gICAgICApO1xuXG4gICAgICBhd2FpdCBiYXNlQ29pblxuICAgICAgICAuY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24oYnVpbGRQYXJhbXMoeyBlZGRzYU1wY3YyU2lnbmF0dXJlOiB0YW1wZXJlZFNpZ25hdHVyZS50b1N0cmluZygnaGV4JykgfSkpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIHNpZ25hdHVyZScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIE1QQ3YyIE9WQyBpcyBtaXNzaW5nIHNpZ25hdHVyZShzKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2VDb2luXG4gICAgICAgIC5jcmVhdGVCcm9hZGNhc3RhYmxlU3dlZXBUcmFuc2FjdGlvbihidWlsZFBhcmFtcyh7fSkpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdNaXNzaW5nIHNpZ25hdHVyZShzKScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByb3V0ZSBNUEN2MS1zaGFwZWQgb3ZjIHRvIHRoZSBNUEN2MSB2ZXJpZnkgYnJhbmNoIGFuZCByZWplY3QgYW4gaW52YWxpZCBzaWduYXR1cmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtcGMgPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpO1xuICAgICAgY29uc3QgZGVyaXZlZFB1YktleSA9IG1wYy5kZXJpdmVVbmhhcmRlbmVkKGNvbW1vbktleWNoYWluLCAnbS8wJykuc2xpY2UoMCwgNjQpO1xuICAgICAgYXdhaXQgYmFzZUNvaW5cbiAgICAgICAgLmNyZWF0ZUJyb2FkY2FzdGFibGVTd2VlcFRyYW5zYWN0aW9uKFxuICAgICAgICAgIGJ1aWxkUGFyYW1zKHtcbiAgICAgICAgICAgIGVkZHNhU2lnbmF0dXJlOiB7IFI6ICcwMCcucmVwZWF0KDMyKSwgc2lnbWE6ICcwMCcucmVwZWF0KDMyKSwgeTogZGVyaXZlZFB1YktleSB9LFxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|