PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-coin-cspr/dist/test/unit

Просмотр файла: cspr.js

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const CsprAccountLib = __importStar(require("../../src/lib"));
const sdk_test_1 = require("@bitgo/sdk-test");
const cspr_1 = require("../../src/cspr");
const tcspr_1 = require("../../src/tcspr");
const crypto_1 = require("crypto");
const should = __importStar(require("should"));
const cspr_2 = require("../fixtures/cspr");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_api_1 = require("@bitgo/sdk-api");
const statics_1 = require("@bitgo/statics");
const assert_1 = __importDefault(require("assert"));
describe('Casper', function () {
    const coinName = 'tcspr';
    let bitgo;
    let basecoin;
    before(function () {
        bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, {
            env: 'mock',
        });
        bitgo.initializeTestVars();
        bitgo.safeRegister('cspr', cspr_1.Cspr.createInstance);
        bitgo.safeRegister('tcspr', tcspr_1.Tcspr.createInstance);
        basecoin = bitgo.coin(coinName);
    });
    it('should instantiate the coin', function () {
        let localBasecoin = bitgo.coin('tcspr');
        localBasecoin.should.be.an.instanceof(tcspr_1.Tcspr);
        localBasecoin = bitgo.coin('cspr');
        localBasecoin.should.be.an.instanceof(cspr_1.Cspr);
    });
    it('should return tcspr', function () {
        basecoin.getChain().should.equal('tcspr');
    });
    it('should return full name', function () {
        basecoin.getFullName().should.equal('Testnet Casper');
    });
    describe('Keypairs:', () => {
        it('should generate a keypair from random seed', function () {
            const keyPair = basecoin.generateKeyPair();
            keyPair.should.have.property('pub');
            keyPair.should.have.property('prv');
        });
        it('should generate a keypair from a seed', function () {
            const seedText = '80350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f';
            const seed = Buffer.from(seedText, 'hex');
            const keyPair = basecoin.generateKeyPair(seed);
            keyPair.pub.should.equal('xpub661MyMwAqRbcFnJi3mvSpYNYyXUcjq7spqHg9GhpcWqs3wF4S8forUeJ3K8XfpUumpY4mLhaGPWAxAJETCnJM56w5f25g6kvLh5Bxb3ZEbD');
            keyPair.prv.should.equal('xprv9s21ZrQH143K3JEEwkPSTQRpRVe8LNQ2TcN5LtJD4BJtB8uutbMZJgKpC3EPHMPGn97Y9aXFYeFegFsPdZXu6BF5XB7yXhZDUE5d6keTHyV');
        });
        it('should validate a public key', function () {
            const keyPair = basecoin.generateKeyPair();
            keyPair.should.have.property('pub');
            keyPair.should.have.property('prv');
            basecoin.isValidPub(keyPair.pub).should.equal(true);
        });
        it('should validate a private key', function () {
            const keyPair = basecoin.generateKeyPair();
            keyPair.should.have.property('pub');
            keyPair.should.have.property('prv');
            basecoin.isValidPrv(keyPair.prv).should.equal(true);
        });
        it('Should supplement wallet generation', async function () {
            const details = await basecoin.supplementGenerateWallet({});
            details.should.have.property('rootPrivateKey');
            basecoin.isValidPrv(details.rootPrivateKey).should.equal(true);
        });
        it('Should supplement wallet generation with provided private key', async function () {
            const rootPrivateKey = 'e0c5c347fc67a46aa5104ece454882315fe5d70af286dbd3d2e04227ebd2927d';
            const details = await basecoin.supplementGenerateWallet({ rootPrivateKey });
            details.should.have.property('rootPrivateKey');
            details.rootPrivateKey.should.equal(rootPrivateKey);
        });
    });
    describe('Sign Transaction', () => {
        const factory = new CsprAccountLib.TransactionBuilderFactory(statics_1.coins.get(coinName));
        const sourceKeyPairObject = new CsprAccountLib.KeyPair();
        const sourceKeyPair = sourceKeyPairObject.getKeys();
        const targetKeyPairObject = new CsprAccountLib.KeyPair();
        const extendedSourceKeyPair = sourceKeyPairObject.getExtendedKeys();
        it('should be performed', async () => {
            const bitgoKeyPairObject = new CsprAccountLib.KeyPair();
            const bitgoKeyPair = bitgoKeyPairObject.getKeys();
            const builder = factory.getTransferBuilder();
            builder
                .fee({ gasLimit: '10000', gasPrice: '10' })
                .source({ address: sourceKeyPairObject.getAddress() })
                .to(targetKeyPairObject.getAddress())
                .amount('2500000000')
                .transferId(123);
            const tx = (await builder.build());
            tx.casperTx.approvals.length.should.equals(0);
            const params = {
                txPrebuild: {
                    txHex: tx.toBroadcastFormat(),
                },
                prv: sourceKeyPair.prv,
            };
            let signedTransaction = await basecoin.signTransaction(params);
            signedTransaction.should.have.property('halfSigned');
            const halfSignedTx = JSON.parse(signedTransaction.halfSigned.txHex);
            halfSignedTx.deploy.approvals.length.should.equals(1);
            halfSignedTx.deploy.approvals[0].signer
                .toUpperCase()
                .should.equals(sourceKeyPairObject.getAddress().toUpperCase());
            CsprAccountLib.Utils.isValidTransactionSignature(halfSignedTx.deploy.approvals[0].signature, halfSignedTx.deploy.hash, sourceKeyPair.pub).should.equals(true);
            params.txPrebuild.txHex = signedTransaction.halfSigned.txHex;
            params.prv = bitgoKeyPair.prv;
            signedTransaction = await basecoin.signTransaction(params);
            signedTransaction.should.not.have.property('halfSigned');
            signedTransaction.should.have.property('txHex');
            const twiceSignedTx = JSON.parse(signedTransaction.txHex);
            twiceSignedTx.deploy.approvals.length.should.equals(2);
            twiceSignedTx.deploy.approvals[0].signer
                .toUpperCase()
                .should.equals(sourceKeyPairObject.getAddress().toUpperCase());
            twiceSignedTx.deploy.approvals[1].signer
                .toUpperCase()
                .should.equals(bitgoKeyPairObject.getAddress().toUpperCase());
            CsprAccountLib.Utils.isValidTransactionSignature(twiceSignedTx.deploy.approvals[0].signature, twiceSignedTx.deploy.hash, sourceKeyPair.pub).should.equals(true);
            CsprAccountLib.Utils.isValidTransactionSignature(twiceSignedTx.deploy.approvals[1].signature, twiceSignedTx.deploy.hash, bitgoKeyPair.pub).should.equals(true);
        });
        it('should be performed with extended keys', async () => {
            const bitgoKeyPairObject = new CsprAccountLib.KeyPair();
            const bitgoKeyPair = bitgoKeyPairObject.getKeys();
            const extendedBitgoKeyPair = bitgoKeyPairObject.getExtendedKeys();
            const builder = factory.getTransferBuilder();
            builder
                .fee({ gasLimit: '10000', gasPrice: '10' })
                .source({ address: sourceKeyPairObject.getAddress() })
                .to(targetKeyPairObject.getAddress())
                .amount('2500000000')
                .transferId(123);
            const tx = (await builder.build());
            tx.casperTx.approvals.length.should.equals(0);
            const params = {
                txPrebuild: {
                    txHex: tx.toBroadcastFormat(),
                },
                prv: extendedSourceKeyPair.xprv,
            };
            let signedTransaction = await basecoin.signTransaction(params);
            signedTransaction.should.have.property('halfSigned');
            const halfSignedTx = JSON.parse(signedTransaction.halfSigned.txHex);
            halfSignedTx.deploy.approvals.length.should.equals(1);
            halfSignedTx.deploy.approvals[0].signer
                .toUpperCase()
                .should.equals(sourceKeyPairObject.getAddress().toUpperCase());
            CsprAccountLib.Utils.isValidTransactionSignature(halfSignedTx.deploy.approvals[0].signature, halfSignedTx.deploy.hash, sourceKeyPair.pub).should.equals(true);
            params.txPrebuild.txHex = signedTransaction.halfSigned.txHex;
            params.prv = extendedBitgoKeyPair.xprv;
            signedTransaction = await basecoin.signTransaction(params);
            signedTransaction.should.not.have.property('halfSigned');
            signedTransaction.should.have.property('txHex');
            const twiceSignedTxHex = JSON.parse(signedTransaction.txHex);
            twiceSignedTxHex.deploy.approvals.length.should.equals(2);
            twiceSignedTxHex.deploy.approvals[0].signer
                .toUpperCase()
                .should.equals(sourceKeyPairObject.getAddress().toUpperCase());
            twiceSignedTxHex.deploy.approvals[1].signer
                .toUpperCase()
                .should.equals(bitgoKeyPairObject.getAddress().toUpperCase());
            CsprAccountLib.Utils.isValidTransactionSignature(twiceSignedTxHex.deploy.approvals[0].signature, twiceSignedTxHex.deploy.hash, sourceKeyPair.pub).should.equals(true);
            CsprAccountLib.Utils.isValidTransactionSignature(twiceSignedTxHex.deploy.approvals[1].signature, twiceSignedTxHex.deploy.hash, bitgoKeyPair.pub).should.equals(true);
        });
        it('should be rejected if invalid key', async () => {
            const sourceKeyPairObject = new CsprAccountLib.KeyPair();
            const targetKeyPairObject = new CsprAccountLib.KeyPair();
            const invalidPrivateKey = 'AAAAA';
            const builder = factory.getTransferBuilder();
            builder
                .fee({ gasLimit: '10000', gasPrice: '10' })
                .source({ address: sourceKeyPairObject.getAddress() })
                .to(targetKeyPairObject.getAddress())
                .amount('2500000000')
                .transferId(123);
            const tx = (await builder.build());
            tx.casperTx.approvals.length.should.equals(0);
            const params = {
                txPrebuild: {
                    txHex: tx.toBroadcastFormat(),
                },
                prv: invalidPrivateKey,
            };
            await basecoin.signTransaction(params).should.be.rejected();
        });
    });
    describe('Sign Message', () => {
        it('should be performed', async () => {
            const keyPair = new CsprAccountLib.KeyPair().getKeys();
            const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
            const signature = await basecoin.signMessage(keyPair, messageToSign);
            CsprAccountLib.Utils.isValidMessageSignature(signature.toString('hex'), messageToSign, keyPair.pub).should.equals(true);
        });
        it('should be performed with extended keys', async () => {
            const keyPairToSign = new CsprAccountLib.KeyPair();
            const keyPairExtendedKeys = keyPairToSign.getExtendedKeys();
            const keyPair = keyPairToSign.getKeys();
            const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
            const signature = await basecoin.signMessage({ pub: keyPairExtendedKeys.xpub, prv: keyPairExtendedKeys.xprv }, messageToSign);
            CsprAccountLib.Utils.isValidMessageSignature(signature.toString('hex'), messageToSign, keyPair.pub).should.equals(true);
        });
        it('should fail with missing private key', async () => {
            const keyPair = new CsprAccountLib.KeyPair({
                pub: '029F697A02355839A02157E87721F7C44EE45DE9B891266BE065FD7F9B4EB31B88',
            }).getKeys();
            const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
            basecoin.signMessage(keyPair, messageToSign).should.be.rejectedWith('Invalid key pair options');
        });
    });
    describe('Explain Transaction', () => {
        const factory = new CsprAccountLib.TransactionBuilderFactory(statics_1.coins.get(coinName));
        const sourceKeyPairObject = new CsprAccountLib.KeyPair();
        const sourceKeyPair = sourceKeyPairObject.getKeys();
        const targetKeyPairObject = new CsprAccountLib.KeyPair();
        let txBuilder;
        let dgBuilder;
        let udgBuilder;
        const transferAmount = '2500000000';
        const delegateAmount = '250000000';
        const undelegateAmount = '250000000';
        const transferId = 123;
        before(function () {
            txBuilder = factory.getTransferBuilder();
            txBuilder
                .fee({ gasLimit: '10000', gasPrice: '10' })
                .source({ address: sourceKeyPairObject.getAddress() })
                .to(targetKeyPairObject.getAddress())
                .amount(transferAmount)
                .transferId(transferId);
            dgBuilder = factory.getDelegateBuilder();
            dgBuilder
                .fee({ gasLimit: '3000000000', gasPrice: '1' })
                .source({ address: sourceKeyPairObject.getAddress() })
                .amount(delegateAmount)
                .validator('0115c9b40c06ff99b0cbadf1140b061b5dbf92103e66a6330fbcc7768f5219c1ce');
            udgBuilder = factory.getUndelegateBuilder();
            udgBuilder
                .fee({ gasLimit: '3000000000', gasPrice: '1' })
                .source({ address: sourceKeyPairObject.getAddress() })
                .amount(undelegateAmount)
                .validator('0115c9b40c06ff99b0cbadf1140b061b5dbf92103e66a6330fbcc7768f5219c1ce');
        });
        it('should explain a half signed transfer transaction', async () => {
            const tx = (await txBuilder.build());
            const signTxparams = {
                txPrebuild: {
                    txHex: tx.toBroadcastFormat(),
                },
                prv: sourceKeyPair.prv,
            };
            const { halfSigned } = await basecoin.signTransaction(signTxparams);
            const feeInfo = {
                gasLimit: '1',
                gasPrice: '11000',
            };
            const explainTxParams = {
                halfSigned: {
                    txHex: halfSigned.txHex,
                },
                feeInfo,
            };
            const explainedTx = await basecoin.explainTransaction(explainTxParams);
            explainedTx.should.have.properties([
                'displayOrder',
                'id',
                'outputs',
                'outputAmount',
                'transferId',
                'fee',
                'changeOutputs',
                'changeAmount',
            ]);
            explainedTx.fee.should.equal(feeInfo);
            explainedTx.outputs.length.should.equal(1);
            explainedTx.outputs.forEach((output) => {
                output.amount.should.equal(transferAmount);
                output.address.should.equal(targetKeyPairObject.getAddress());
                output.coin.should.equal(basecoin.getChain());
            });
            explainedTx.outputAmount.should.equal(transferAmount);
            explainedTx.transferId.should.equal(transferId.toString());
        });
        it('should explain a signed transfer transaction', async () => {
            const builtTxInfo = {
                txHex: cspr_2.signedRawTransferTx,
                txInfo: {
                    hash: 'cf7eac1a10f350f393163c8254770649b953dcd3cf8e180aaba463816fbd0a0b',
                    fee: {
                        gasLimit: '11000',
                        gasPrice: '1',
                    },
                    from: '02cc8f78c41d334ad2aaae6da7a88537f9686245761aaddf36d4b2dfbf913bb873',
                    startTime: '2021-12-14T00:53:32.836Z',
                    expiration: 7200000,
                    deployType: 'Send',
                    to: '0202227faa327bb6607f1b6245d275b0c9aef32db568986b5252323fd498923f1ef1',
                    amount: '2500000000',
                    transferId: '123',
                },
                feeInfo: {
                    gasLimit: '11000',
                    gasPrice: '1',
                },
                recipients: [
                    {
                        address: '0202fba9e5705a8860fc1b5563b981a4c2c94af03fc10916eb7819b183056c43d3b0',
                        amount: '2500000000',
                    },
                ],
            };
            const explainTxParams = builtTxInfo;
            const explainedTx = await basecoin.explainTransaction(explainTxParams);
            explainedTx.should.have.properties([
                'displayOrder',
                'id',
                'outputs',
                'outputAmount',
                'transferId',
                'fee',
                'changeOutputs',
                'changeAmount',
            ]);
            explainedTx.fee.should.equal(builtTxInfo.feeInfo);
            explainedTx.id.should.equal(builtTxInfo.txInfo.hash);
            explainedTx.outputs.length.should.equal(1);
            explainedTx.outputs[0].amount.should.equal(builtTxInfo.txInfo.amount);
            explainedTx.outputs[0].address.should.equal(builtTxInfo.txInfo.to);
            explainedTx.outputs[0].coin.should.equal(basecoin.getChain());
            explainedTx.outputAmount.should.equal(builtTxInfo.txInfo.amount);
            explainedTx.transferId.should.equal(builtTxInfo.txInfo.transferId);
        });
        it('should explain a half signed delegate transaction', async () => {
            const tx = (await dgBuilder.build());
            const signTxparams = {
                txPrebuild: {
                    txHex: tx.toBroadcastFormat(),
                },
                prv: sourceKeyPair.prv,
            };
            const { halfSigned } = await basecoin.signTransaction(signTxparams);
            const feeInfo = {
                gasLimit: '1',
                gasPrice: '3000000000',
            };
            const explainTxParams = {
                halfSigned: {
                    txHex: halfSigned.txHex,
                },
                feeInfo,
            };
            const txInfo = {
                hash: 'b47ca168a2c6ec864c5923a98bb8bca8cb78f0141bdeb37f9ad74705f8c40636',
                fee: {
                    gasLimit: '3000000000',
                    gasPrice: '1',
                },
                from: '0202cc8f78c41d334ad2aaae6da7a88537f9686245761aaddf36d4b2dfbf913bb873',
                deployType: sdk_core_1.TransactionType.StakingLock,
                amount: delegateAmount,
                validator: '0115c9b40c06ff99b0cbadf1140b061b5dbf92103e66a6330fbcc7768f5219c1ce',
            };
            const explainedTx = await basecoin.explainTransaction(explainTxParams);
            explainedTx.should.have.properties([
                'displayOrder',
                'id',
                'outputs',
                'outputAmount',
                'transferId',
                'fee',
                'changeOutputs',
                'changeAmount',
                'operations',
            ]);
            explainedTx.fee.should.equal(explainTxParams.feeInfo);
            explainedTx.outputs.length.should.equal(0);
            explainedTx.operations.length.should.equal(1);
            explainedTx.operations[0].amount.should.equal(txInfo.amount);
            explainedTx.operations[0].validator.should.equal(txInfo.validator);
            explainedTx.operations[0].coin.should.equal(basecoin.getChain());
            explainedTx.operations[0].type.should.equal(txInfo.deployType);
        });
        it('should explain a signed delegate transaction', async () => {
            const builtTxInfo = {
                txHex: cspr_2.signedRawDelegateTx,
                txInfo: {
                    hash: '771a192224097faf0f1b18295a50e4bf190728cf365711b030cb083d0785e993',
                    fee: {
                        gasLimit: '100000000',
                        gasPrice: '1',
                    },
                    from: '0202cc8f78c41d334ad2aaae6da7a88537f9686245761aaddf36d4b2dfbf913bb873',
                    deployType: sdk_core_1.TransactionType.StakingLock,
                    amount: delegateAmount,
                    validator: '0115c9b40c06ff99b0cbadf1140b061b5dbf92103e66a6330fbcc7768f5219c1ce',
                },
                feeInfo: {
                    gasLimit: '100000000',
                    gasPrice: '1',
                },
            };
            const explainTxParams = builtTxInfo;
            const explainedTx = await basecoin.explainTransaction(explainTxParams);
            explainedTx.should.have.properties([
                'displayOrder',
                'id',
                'outputs',
                'outputAmount',
                'transferId',
                'fee',
                'changeOutputs',
                'changeAmount',
                'operations',
            ]);
            explainedTx.fee.should.equal(builtTxInfo.feeInfo);
            explainedTx.outputs.length.should.equal(0);
            explainedTx.operations.length.should.equal(1);
            explainedTx.operations[0].amount.should.equal(builtTxInfo.txInfo.amount);
            explainedTx.operations[0].validator.should.equal(builtTxInfo.txInfo.validator);
            explainedTx.operations[0].coin.should.equal(basecoin.getChain());
            explainedTx.operations[0].type.should.equal(builtTxInfo.txInfo.deployType);
        });
        it('should explain a half signed undelegate transaction', async () => {
            const tx = (await udgBuilder.build());
            const signTxparams = {
                txPrebuild: {
                    txHex: tx.toBroadcastFormat(),
                },
                prv: sourceKeyPair.prv,
            };
            const { halfSigned } = await basecoin.signTransaction(signTxparams);
            const feeInfo = {
                gasLimit: '1',
                gasPrice: '3000000000',
            };
            const explainTxParams = {
                halfSigned: {
                    txHex: halfSigned.txHex,
                },
                feeInfo,
            };
            const txInfo = {
                hash: 'b47ca168a2c6ec864c5923a98bb8bca8cb78f0141bdeb37f9ad74705f8c40636',
                fee: {
                    gasLimit: '3000000000',
                    gasPrice: '1',
                },
                from: '0202cc8f78c41d334ad2aaae6da7a88537f9686245761aaddf36d4b2dfbf913bb873',
                deployType: sdk_core_1.TransactionType.StakingUnlock,
                amount: undelegateAmount,
                validator: '0115c9b40c06ff99b0cbadf1140b061b5dbf92103e66a6330fbcc7768f5219c1ce',
            };
            const explainedTx = await basecoin.explainTransaction(explainTxParams);
            explainedTx.should.have.properties([
                'displayOrder',
                'id',
                'outputs',
                'outputAmount',
                'transferId',
                'fee',
                'changeOutputs',
                'changeAmount',
                'operations',
            ]);
            explainedTx.fee.should.equal(explainTxParams.feeInfo);
            explainedTx.outputs.length.should.equal(0);
            explainedTx.operations.length.should.equal(1);
            explainedTx.operations[0].amount.should.equal(txInfo.amount);
            explainedTx.operations[0].validator.should.equal(txInfo.validator);
            explainedTx.operations[0].coin.should.equal(basecoin.getChain());
            explainedTx.operations[0].type.should.equal(txInfo.deployType);
        });
        it('should explain a signed undelegate transaction', async () => {
            const builtTxInfo = {
                txHex: cspr_2.signedRawUndelegateTx,
                txInfo: {
                    hash: 'aead2e9e9a43e3d545908e1b995628cb9c37e712d7467b63c052fe63bed8cf17',
                    fee: {
                        gasLimit: '100000000',
                        gasPrice: '1',
                    },
                    from: '0202cc8f78c41d334ad2aaae6da7a88537f9686245761aaddf36d4b2dfbf913bb873',
                    deployType: sdk_core_1.TransactionType.StakingUnlock,
                    amount: undelegateAmount,
                    validator: '0115c9b40c06ff99b0cbadf1140b061b5dbf92103e66a6330fbcc7768f5219c1ce',
                },
                feeInfo: {
                    gasLimit: '100000000',
                    gasPrice: '1',
                },
            };
            const explainTxParams = builtTxInfo;
            const explainedTx = await basecoin.explainTransaction(explainTxParams);
            explainedTx.should.have.properties([
                'displayOrder',
                'id',
                'outputs',
                'outputAmount',
                'transferId',
                'fee',
                'changeOutputs',
                'changeAmount',
                'operations',
            ]);
            explainedTx.fee.should.equal(builtTxInfo.feeInfo);
            explainedTx.outputs.length.should.equal(0);
            explainedTx.operations.length.should.equal(1);
            explainedTx.operations[0].amount.should.equal(builtTxInfo.txInfo.amount);
            explainedTx.operations[0].validator.should.equal(builtTxInfo.txInfo.validator);
            explainedTx.operations[0].coin.should.equal(basecoin.getChain());
            explainedTx.operations[0].type.should.equal(builtTxInfo.txInfo.deployType);
        });
        it('should fail when a tx is not passed as parameter', async () => {
            const explainTxParams = {
                fee: {
                    gasLimit: '1',
                    gasPrice: '11000',
                },
            };
            await basecoin.explainTransaction(explainTxParams).should.be.rejectedWith('missing explain tx parameters');
        });
    });
    describe('Validation', function () {
        it('should fail to validate invalid address with payment id', function () {
            const invalidAddresses = [
                '0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?transferId=x',
                '0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?memoId=1',
                'X0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?transferId=1',
            ];
            for (const address of invalidAddresses) {
                should.doesNotThrow(() => basecoin.isValidAddress(address));
                basecoin.isValidAddress(address).should.be.false();
            }
        });
        it('should validate address with payment id', function () {
            const validAddresses = [
                '0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?transferId=0',
                '020385D724A9A3E7E32BADF40F3279AF5A190CB2CFCAB6639BF532A0069E0E3824D0?transferId=1',
                '01513fa90c1a74c34a8958dd86055e9736edb1ead918bd4d4d750ca851946be7aa?transferId=999999999', // ed25519
            ];
            for (const address of validAddresses) {
                basecoin.isValidAddress(address).should.be.true();
            }
        });
        it('should fail to verify invalid address with payment id', async function () {
            const invalidAddresses = [
                '0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?transferId=x',
                '0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?memoId=1',
                'X0203DC13CBBF29765C7745578D9E091280522F37684EF0E400B86B1C409BC454F1F3?transferId=1',
            ];
            for (const address of invalidAddresses) {
                await assert_1.default.rejects(async () => basecoin.verifyAddress(address));
            }
        });
        it('should verify address with payment id', async function () {
            const rootAddress = '020250fe213706e46aaa32cb23f0705833c6d3ce7652e8e5a1349dde102aadf014b7';
            const keychains = [
                {
                    id: '624f0dcc93cbcc0008d88df2369a565e',
                    pub: 'xpub661MyMwAqRbcEeRkBciuaUfF4C1jgBcnj2RXdnt9gokx4CFRBUp4bsbk5hXHC1BrBDZLDNecVsUCMmoLpPhWdPZhPiTsHSoxNoGVW9KtiEQ',
                    ethAddress: '0xcfbf38770af3a95da7998537a481434e2cb9b2fa',
                    source: 'user',
                    type: 'independent',
                    encryptedPrv: '{"iv":"Z2XySTRNipFZ06/EXynwvA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"KGRPbZ2jt1g=","ct":"szpCbDLFIlRZvCBV60SWBEMYXvny7YlBtu4ffjlctDQGjR4/+vfCkovgGHs+Xvf/eIlUM3Kicubg+Sdp61MImjMT/umZ3IJT1E2I9mM0QDqpzXlohTGnJ4vgfHgCz3QkB4uYm5mqaD4LtRbvZbGhGrc5jzrLzqQ="}',
                },
                {
                    id: '624f0dcd93cbcc0008d88e0fc4261a38',
                    pub: 'xpub661MyMwAqRbcGeqZVFgQfcD8zLoxaZL7y4cVAjhE8ybMTpvbppP6rc22a69BgcNVo74yL8fWPzNM5vAozBE7chzGYoPDJMyJ39F2HeAsGcn',
                    ethAddress: '0xbf37f39208d77e3254b7efbcab1432b9c353e337',
                    source: 'backup',
                    type: 'independent',
                    encryptedPrv: '{"iv":"T9gdJnSAEWFsLZ4cg9VA8g==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"FaLlns3mPiI=","ct":"QW5Zq9qJoDxDrK60zTAM6Lg+S4KP9FcEn9AHw5UIyakSBlD0XjVTluZ9PlTABjIlp9cQvMef/SH8Em1d4ash0PACoqBz2IxPwhW9h6uyQBdqk97iPrnM2rOQobsy9p0ILJM10fOgB+EEFYX5yQ5gyfEcK060j/Q="}',
                },
                {
                    id: '624f0dce10610a0007fc5282353187ae',
                    pub: 'xpub661MyMwAqRbcFVMAYJe51sgXaiFLeUb1v4u3B63CgBNMmMjtWBo32AS3bunsBUZMdi37pzovtEg5mVf6wBKayTYapGQRxymQjcmHaVmSPz8',
                    ethAddress: '0x7527720b5638d2f5e2b272b20fc96d2223528d0e',
                    source: 'bitgo',
                    type: 'independent',
                    isBitGo: true,
                },
            ];
            const validAddresses = [
                {
                    address: '020250fe213706e46aaa32cb23f0705833c6d3ce7652e8e5a1349dde102aadf014b7',
                    keychains,
                    rootAddress,
                },
                {
                    address: '020250FE213706E46AAA32CB23F0705833C6D3CE7652E8E5A1349DDE102AADF014B7?transferId=0',
                    keychains,
                    rootAddress,
                },
                {
                    address: '020250fe213706e46aaa32cb23f0705833c6d3ce7652e8e5a1349dde102aadf014b7?transferId=5555',
                    keychains,
                    rootAddress,
                },
            ];
            for (const addressParams of validAddresses) {
                (await basecoin.verifyAddress(addressParams)).should.be.true();
            }
        });
    });
    describe('isWalletAddress', function () {
        const rootAddress = '0203d4c6ed4a40f5aa7371a73c79dd208a646ebc8c9f5c7fe0b4c73844365f0e62e5?transferId=4';
        it('should be valid', async function () {
            await basecoin
                .isWalletAddress({
                address: '0203d4c6ed4a40f5aa7371a73c79dd208a646ebc8c9f5c7fe0b4c73844365f0e62e5?transferId=5',
                rootAddress,
            })
                .should.be.resolvedWith(true);
            await basecoin
                .isWalletAddress({
                address: '0203d4c6ed4a40f5aa7371a73c79dd208a646ebc8c9f5c7fe0b4c73844365f0e62e5?transferId=500',
                rootAddress,
            })
                .should.be.resolvedWith(true);
            await basecoin
                .isWalletAddress({
                address: '0203d4c6ed4a40f5aa7371a73c79dd208a646ebc8c9f5c7fe0b4c73844365f0e62e5',
                rootAddress,
            })
                .should.be.resolvedWith(true);
            await basecoin
                .isWalletAddress({
                address: '0203d4c6ed4a40f5aa7371a73c79dd208a646ebc8c9f5c7fe0b4c73844365f0e62e5?transferId=1',
                rootAddress,
            })
                .should.be.resolvedWith(true);
        });
        it('should be invalid', async function () {
            await basecoin
                .isWalletAddress({
                address: '0203d4c6ed4a40f5aa7371a73c79dd208a646ebc8c9f5c7fe0b4c73844365f0e62e6',
                rootAddress,
            })
                .should.be.rejected();
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3Nwci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9jc3ByLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOERBQWdEO0FBQ2hELDhDQUEwRDtBQUMxRCx5Q0FBaUY7QUFDakYsMkNBQXdDO0FBQ3hDLG1DQUFxQztBQUNyQywrQ0FBaUM7QUFDakMsMkNBQW1HO0FBQ25HLDhDQUFrRDtBQUNsRCw0Q0FBMEM7QUFDMUMsNENBQXVDO0FBQ3ZDLG9EQUE0QjtBQUk1QixRQUFRLENBQUMsUUFBUSxFQUFFO0lBQ2pCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQztJQUN6QixJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFRLENBQUM7SUFFYixNQUFNLENBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRTtZQUNuQyxHQUFHLEVBQUUsTUFBTTtTQUNaLENBQUMsQ0FBQztRQUNILEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzNCLEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFdBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNoRCxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxhQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDbEQsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUU7UUFDaEMsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4QyxhQUFhLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLGFBQUssQ0FBQyxDQUFDO1FBRTdDLGFBQWEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25DLGFBQWEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsV0FBSSxDQUFDLENBQUM7SUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMscUJBQXFCLEVBQUU7UUFDeEIsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMseUJBQXlCLEVBQUU7UUFDNUIsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN4RCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFO1FBQ3pCLEVBQUUsQ0FBQyw0Q0FBNEMsRUFBRTtZQUMvQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDM0MsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRTtZQUMxQyxNQUFNLFFBQVEsR0FBRyxrRUFBa0UsQ0FBQztZQUNwRixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMxQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRS9DLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDdEIsaUhBQWlILENBQ2xILENBQUM7WUFDRixPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3RCLGlIQUFpSCxDQUNsSCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOEJBQThCLEVBQUU7WUFDakMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQzNDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFcEMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywrQkFBK0IsRUFBRTtZQUNsQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDM0MsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVwQyxRQUFRLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHFDQUFxQyxFQUFFLEtBQUs7WUFDN0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxRQUFRLENBQUMsd0JBQXdCLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDL0MsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywrREFBK0QsRUFBRSxLQUFLO1lBQ3ZFLE1BQU0sY0FBYyxHQUFHLGtFQUFrRSxDQUFDO1lBQzFGLE1BQU0sT0FBTyxHQUFHLE1BQU0sUUFBUSxDQUFDLHdCQUF3QixDQUFDLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztZQUM1RSxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUMvQyxPQUFPLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7UUFDaEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxjQUFjLENBQUMseUJBQXlCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDekQsTUFBTSxhQUFhLEdBQUcsbUJBQW1CLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN6RCxNQUFNLHFCQUFxQixHQUFHLG1CQUFtQixDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXBFLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuQyxNQUFNLGtCQUFrQixHQUFHLElBQUksY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3hELE1BQU0sWUFBWSxHQUFHLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzdDLE9BQU87aUJBQ0osR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQzFDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO2lCQUNyRCxFQUFFLENBQUMsbUJBQW1CLENBQUMsVUFBVSxFQUFFLENBQUM7aUJBQ3BDLE1BQU0sQ0FBQyxZQUFZLENBQUM7aUJBQ3BCLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVuQixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFnQixDQUFDO1lBQ2xELEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTlDLE1BQU0sTUFBTSxHQUFHO2dCQUNiLFVBQVUsRUFBRTtvQkFDVixLQUFLLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixFQUFFO2lCQUM5QjtnQkFDRCxHQUFHLEVBQUUsYUFBYSxDQUFDLEdBQUc7YUFDdkIsQ0FBQztZQUVGLElBQUksaUJBQWlCLEdBQUcsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQy9ELGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRXJELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BFLFlBQVksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RELFlBQVksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07aUJBQ3BDLFdBQVcsRUFBRTtpQkFDYixNQUFNLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDakUsY0FBYyxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FDOUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUMxQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksRUFDeEIsYUFBYSxDQUFDLEdBQUcsQ0FDbEIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRXRCLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxHQUFHLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUM7WUFDN0QsTUFBTSxDQUFDLEdBQUcsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDO1lBQzlCLGlCQUFpQixHQUFHLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMzRCxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDekQsaUJBQWlCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFaEQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMxRCxhQUFhLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2RCxhQUFhLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNO2lCQUNyQyxXQUFXLEVBQUU7aUJBQ2IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLGFBQWEsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07aUJBQ3JDLFdBQVcsRUFBRTtpQkFDYixNQUFNLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFFaEUsY0FBYyxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FDOUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUMzQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksRUFDekIsYUFBYSxDQUFDLEdBQUcsQ0FDbEIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RCLGNBQWMsQ0FBQyxLQUFLLENBQUMsMkJBQTJCLENBQzlDLGFBQWEsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFDM0MsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQ3pCLFlBQVksQ0FBQyxHQUFHLENBQ2pCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx3Q0FBd0MsRUFBRSxLQUFLLElBQUksRUFBRTtZQUN0RCxNQUFNLGtCQUFrQixHQUFHLElBQUksY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3hELE1BQU0sWUFBWSxHQUFHLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xELE1BQU0sb0JBQW9CLEdBQUcsa0JBQWtCLENBQUMsZUFBZSxFQUFFLENBQUM7WUFFbEUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDN0MsT0FBTztpQkFDSixHQUFHLENBQUMsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQztpQkFDMUMsTUFBTSxDQUFDLEVBQUUsT0FBTyxFQUFFLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUM7aUJBQ3JELEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQztpQkFDcEMsTUFBTSxDQUFDLFlBQVksQ0FBQztpQkFDcEIsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRW5CLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQWdCLENBQUM7WUFDbEQsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFOUMsTUFBTSxNQUFNLEdBQUc7Z0JBQ2IsVUFBVSxFQUFFO29CQUNWLEtBQUssRUFBRSxFQUFFLENBQUMsaUJBQWlCLEVBQUU7aUJBQzlCO2dCQUNELEdBQUcsRUFBRSxxQkFBcUIsQ0FBQyxJQUFJO2FBQ2hDLENBQUM7WUFFRixJQUFJLGlCQUFpQixHQUFHLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMvRCxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUVyRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwRSxZQUFZLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN0RCxZQUFZLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNO2lCQUNwQyxXQUFXLEVBQUU7aUJBQ2IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLGNBQWMsQ0FBQyxLQUFLLENBQUMsMkJBQTJCLENBQzlDLFlBQVksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFDMUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQ3hCLGFBQWEsQ0FBQyxHQUFHLENBQ2xCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUV0QixNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1lBQzdELE1BQU0sQ0FBQyxHQUFHLEdBQUcsb0JBQW9CLENBQUMsSUFBSSxDQUFDO1lBQ3ZDLGlCQUFpQixHQUFHLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMzRCxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDekQsaUJBQWlCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFaEQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzdELGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUQsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNO2lCQUN4QyxXQUFXLEVBQUU7aUJBQ2IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTTtpQkFDeEMsV0FBVyxFQUFFO2lCQUNiLE1BQU0sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsVUFBVSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUVoRSxjQUFjLENBQUMsS0FBSyxDQUFDLDJCQUEyQixDQUM5QyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFDOUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLElBQUksRUFDNUIsYUFBYSxDQUFDLEdBQUcsQ0FDbEIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RCLGNBQWMsQ0FBQyxLQUFLLENBQUMsMkJBQTJCLENBQzlDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUM5QyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUM1QixZQUFZLENBQUMsR0FBRyxDQUNqQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEIsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsbUNBQW1DLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDakQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6RCxNQUFNLG1CQUFtQixHQUFHLElBQUksY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pELE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDO1lBQ2xDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzdDLE9BQU87aUJBQ0osR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQzFDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO2lCQUNyRCxFQUFFLENBQUMsbUJBQW1CLENBQUMsVUFBVSxFQUFFLENBQUM7aUJBQ3BDLE1BQU0sQ0FBQyxZQUFZLENBQUM7aUJBQ3BCLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVuQixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFnQixDQUFDO1lBQ2xELEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTlDLE1BQU0sTUFBTSxHQUFHO2dCQUNiLFVBQVUsRUFBRTtvQkFDVixLQUFLLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixFQUFFO2lCQUM5QjtnQkFDRCxHQUFHLEVBQUUsaUJBQWlCO2FBQ3ZCLENBQUM7WUFFRixNQUFNLFFBQVEsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGNBQWMsRUFBRSxHQUFHLEVBQUU7UUFDNUIsRUFBRSxDQUFDLHFCQUFxQixFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ25DLE1BQU0sT0FBTyxHQUFHLElBQUksY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3ZELE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBQSxvQkFBVyxFQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25FLE1BQU0sU0FBUyxHQUFHLE1BQU0sUUFBUSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDckUsY0FBYyxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FDL0csSUFBSSxDQUNMLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx3Q0FBd0MsRUFBRSxLQUFLLElBQUksRUFBRTtZQUN0RCxNQUFNLGFBQWEsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNuRCxNQUFNLG1CQUFtQixHQUFHLGFBQWEsQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUM1RCxNQUFNLE9BQU8sR0FBRyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEMsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFBLG9CQUFXLEVBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkUsTUFBTSxTQUFTLEdBQUcsTUFBTSxRQUFRLENBQUMsV0FBVyxDQUMxQyxFQUFFLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLG1CQUFtQixDQUFDLElBQUksRUFBRSxFQUNoRSxhQUFhLENBQ2QsQ0FBQztZQUNGLGNBQWMsQ0FBQyxLQUFLLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxhQUFhLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQy9HLElBQUksQ0FDTCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsc0NBQXNDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDcEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxjQUFjLENBQUMsT0FBTyxDQUFDO2dCQUN6QyxHQUFHLEVBQUUsb0VBQW9FO2FBQzFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBQSxvQkFBVyxFQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25FLFFBQVEsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDbEcsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7UUFDbkMsTUFBTSxPQUFPLEdBQUcsSUFBSSxjQUFjLENBQUMseUJBQXlCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDekQsTUFBTSxhQUFhLEdBQUcsbUJBQW1CLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN6RCxJQUFJLFNBQVMsQ0FBQztRQUNkLElBQUksU0FBUyxDQUFDO1FBQ2QsSUFBSSxVQUFVLENBQUM7UUFDZixNQUFNLGNBQWMsR0FBRyxZQUFZLENBQUM7UUFDcEMsTUFBTSxjQUFjLEdBQUcsV0FBVyxDQUFDO1FBQ25DLE1BQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDO1FBQ3JDLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQztRQUV2QixNQUFNLENBQUM7WUFDTCxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDekMsU0FBUztpQkFDTixHQUFHLENBQUMsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQztpQkFDMUMsTUFBTSxDQUFDLEVBQUUsT0FBTyxFQUFFLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUM7aUJBQ3JELEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQztpQkFDcEMsTUFBTSxDQUFDLGNBQWMsQ0FBQztpQkFDdEIsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRTFCLFNBQVMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUN6QyxTQUFTO2lCQUNOLEdBQUcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUM5QyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsbUJBQW1CLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztpQkFDckQsTUFBTSxDQUFDLGNBQWMsQ0FBQztpQkFDdEIsU0FBUyxDQUFDLG9FQUFvRSxDQUFDLENBQUM7WUFFbkYsVUFBVSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQzVDLFVBQVU7aUJBQ1AsR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUM7aUJBQzlDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO2lCQUNyRCxNQUFNLENBQUMsZ0JBQWdCLENBQUM7aUJBQ3hCLFNBQVMsQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO1FBQ3JGLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLG1EQUFtRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2pFLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQWdCLENBQUM7WUFDcEQsTUFBTSxZQUFZLEdBQUc7Z0JBQ25CLFVBQVUsRUFBRTtvQkFDVixLQUFLLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixFQUFFO2lCQUM5QjtnQkFDRCxHQUFHLEVBQUUsYUFBYSxDQUFDLEdBQUc7YUFDdkIsQ0FBQztZQUNGLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7WUFFcEUsTUFBTSxPQUFPLEdBQW1CO2dCQUM5QixRQUFRLEVBQUUsR0FBRztnQkFDYixRQUFRLEVBQUUsT0FBTzthQUNsQixDQUFDO1lBQ0YsTUFBTSxlQUFlLEdBQThCO2dCQUNqRCxVQUFVLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLO2lCQUN4QjtnQkFDRCxPQUFPO2FBQ1IsQ0FBQztZQUNGLE1BQU0sV0FBVyxHQUFHLE1BQU0sUUFBUSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3ZFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDakMsY0FBYztnQkFDZCxJQUFJO2dCQUNKLFNBQVM7Z0JBQ1QsY0FBYztnQkFDZCxZQUFZO2dCQUNaLEtBQUs7Z0JBQ0wsZUFBZTtnQkFDZixjQUFjO2FBQ2YsQ0FBQyxDQUFDO1lBQ0gsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3RDLFdBQVcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDM0MsV0FBVyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDckMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztnQkFDOUQsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ2hELENBQUMsQ0FBQyxDQUFDO1lBQ0gsV0FBVyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3RELFdBQVcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUM1RCxNQUFNLFdBQVcsR0FBRztnQkFDbEIsS0FBSyxFQUFFLDBCQUFtQjtnQkFDMUIsTUFBTSxFQUFFO29CQUNOLElBQUksRUFBRSxrRUFBa0U7b0JBQ3hFLEdBQUcsRUFBRTt3QkFDSCxRQUFRLEVBQUUsT0FBTzt3QkFDakIsUUFBUSxFQUFFLEdBQUc7cUJBQ2Q7b0JBQ0QsSUFBSSxFQUFFLG9FQUFvRTtvQkFDMUUsU0FBUyxFQUFFLDBCQUEwQjtvQkFDckMsVUFBVSxFQUFFLE9BQU87b0JBQ25CLFVBQVUsRUFBRSxNQUFNO29CQUNsQixFQUFFLEVBQUUsc0VBQXNFO29CQUMxRSxNQUFNLEVBQUUsWUFBWTtvQkFDcEIsVUFBVSxFQUFFLEtBQUs7aUJBQ2xCO2dCQUNELE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsT0FBTztvQkFDakIsUUFBUSxFQUFFLEdBQUc7aUJBQ2Q7Z0JBQ0QsVUFBVSxFQUFFO29CQUNWO3dCQUNFLE9BQU8sRUFBRSxzRUFBc0U7d0JBQy9FLE1BQU0sRUFBRSxZQUFZO3FCQUNyQjtpQkFDRjthQUNGLENBQUM7WUFDRixNQUFNLGVBQWUsR0FBOEIsV0FBVyxDQUFDO1lBQy9ELE1BQU0sV0FBVyxHQUFHLE1BQU0sUUFBUSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3ZFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDakMsY0FBYztnQkFDZCxJQUFJO2dCQUNKLFNBQVM7Z0JBQ1QsY0FBYztnQkFDZCxZQUFZO2dCQUNaLEtBQUs7Z0JBQ0wsZUFBZTtnQkFDZixjQUFjO2FBQ2YsQ0FBQyxDQUFDO1lBQ0gsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNsRCxXQUFXLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNyRCxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN0RSxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbkUsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUM5RCxXQUFXLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNqRSxXQUFXLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNyRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxtREFBbUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNqRSxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFnQixDQUFDO1lBQ3BELE1BQU0sWUFBWSxHQUFHO2dCQUNuQixVQUFVLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRTtpQkFDOUI7Z0JBQ0QsR0FBRyxFQUFFLGFBQWEsQ0FBQyxHQUFHO2FBQ3ZCLENBQUM7WUFDRixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRXBFLE1BQU0sT0FBTyxHQUFtQjtnQkFDOUIsUUFBUSxFQUFFLEdBQUc7Z0JBQ2IsUUFBUSxFQUFFLFlBQVk7YUFDdkIsQ0FBQztZQUNGLE1BQU0sZUFBZSxHQUE4QjtnQkFDakQsVUFBVSxFQUFFO29CQUNWLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztpQkFDeEI7Z0JBQ0QsT0FBTzthQUNSLENBQUM7WUFDRixNQUFNLE1BQU0sR0FBRztnQkFDYixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxHQUFHLEVBQUU7b0JBQ0gsUUFBUSxFQUFFLFlBQVk7b0JBQ3RCLFFBQVEsRUFBRSxHQUFHO2lCQUNkO2dCQUNELElBQUksRUFBRSxzRUFBc0U7Z0JBQzVFLFVBQVUsRUFBRSwwQkFBZSxDQUFDLFdBQVc7Z0JBQ3ZDLE1BQU0sRUFBRSxjQUFjO2dCQUN0QixTQUFTLEVBQUUsb0VBQW9FO2FBQ2hGLENBQUM7WUFDRixNQUFNLFdBQVcsR0FBRyxNQUFNLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUN2RSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7Z0JBQ2pDLGNBQWM7Z0JBQ2QsSUFBSTtnQkFDSixTQUFTO2dCQUNULGNBQWM7Z0JBQ2QsWUFBWTtnQkFDWixLQUFLO2dCQUNMLGVBQWU7Z0JBQ2YsY0FBYztnQkFDZCxZQUFZO2FBQ2IsQ0FBQyxDQUFDO1lBQ0gsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0RCxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNDLFdBQVcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDN0QsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDbkUsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUNqRSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUM1RCxNQUFNLFdBQVcsR0FBRztnQkFDbEIsS0FBSyxFQUFFLDBCQUFtQjtnQkFDMUIsTUFBTSxFQUFFO29CQUNOLElBQUksRUFBRSxrRUFBa0U7b0JBQ3hFLEdBQUcsRUFBRTt3QkFDSCxRQUFRLEVBQUUsV0FBVzt3QkFDckIsUUFBUSxFQUFFLEdBQUc7cUJBQ2Q7b0JBQ0QsSUFBSSxFQUFFLHNFQUFzRTtvQkFDNUUsVUFBVSxFQUFFLDBCQUFlLENBQUMsV0FBVztvQkFDdkMsTUFBTSxFQUFFLGNBQWM7b0JBQ3RCLFNBQVMsRUFBRSxvRUFBb0U7aUJBQ2hGO2dCQUNELE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsV0FBVztvQkFDckIsUUFBUSxFQUFFLEdBQUc7aUJBQ2Q7YUFDRixDQUFDO1lBQ0YsTUFBTSxlQUFlLEdBQThCLFdBQVcsQ0FBQztZQUMvRCxNQUFNLFdBQVcsR0FBRyxNQUFNLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUN2RSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7Z0JBQ2pDLGNBQWM7Z0JBQ2QsSUFBSTtnQkFDSixTQUFTO2dCQUNULGNBQWM7Z0JBQ2QsWUFBWTtnQkFDWixLQUFLO2dCQUNMLGVBQWU7Z0JBQ2YsY0FBYztnQkFDZCxZQUFZO2FBQ2IsQ0FBQyxDQUFDO1lBQ0gsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNsRCxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNDLFdBQVcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pFLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMvRSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUM3RSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxxREFBcUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRSxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFnQixDQUFDO1lBQ3JELE1BQU0sWUFBWSxHQUFHO2dCQUNuQixVQUFVLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRTtpQkFDOUI7Z0JBQ0QsR0FBRyxFQUFFLGFBQWEsQ0FBQyxHQUFHO2FBQ3ZCLENBQUM7WUFDRixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRXBFLE1BQU0sT0FBTyxHQUFtQjtnQkFDOUIsUUFBUSxFQUFFLEdBQUc7Z0JBQ2IsUUFBUSxFQUFFLFlBQVk7YUFDdkIsQ0FBQztZQUNGLE1BQU0sZUFBZSxHQUE4QjtnQkFDakQsVUFBVSxFQUFFO29CQUNWLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztpQkFDeEI7Z0JBQ0QsT0FBTzthQUNSLENBQUM7WUFDRixNQUFNLE1BQU0sR0FBRztnQkFDYixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxHQUFHLEVBQUU7b0JBQ0gsUUFBUSxFQUFFLFlBQVk7b0JBQ3RCLFFBQVEsRUFBRSxHQUFHO2lCQUNkO2dCQUNELElBQUksRUFBRSxzRUFBc0U7Z0JBQzVFLFVBQVUsRUFBRSwwQkFBZSxDQUFDLGFBQWE7Z0JBQ3pDLE1BQU0sRUFBRSxnQkFBZ0I7Z0JBQ3hCLFNBQVMsRUFBRSxvRUFBb0U7YUFDaEYsQ0FBQztZQUNGLE1BQU0sV0FBVyxHQUFHLE1BQU0sUUFBUSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3ZFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDakMsY0FBYztnQkFDZCxJQUFJO2dCQUNKLFNBQVM7Z0JBQ1QsY0FBYztnQkFDZCxZQUFZO2dCQUNaLEtBQUs7Z0JBQ0wsZUFBZTtnQkFDZixjQUFjO2dCQUNkLFlBQVk7YUFDYixDQUFDLENBQUM7WUFDSCxXQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3RELFdBQVcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDM0MsV0FBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5QyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM3RCxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNuRSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ2pFLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2pFLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGdEQUFnRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzlELE1BQU0sV0FBVyxHQUFHO2dCQUNsQixLQUFLLEVBQUUsNEJBQXFCO2dCQUM1QixNQUFNLEVBQUU7b0JBQ04sSUFBSSxFQUFFLGtFQUFrRTtvQkFDeEUsR0FBRyxFQUFFO3dCQUNILFFBQVEsRUFBRSxXQUFXO3dCQUNyQixRQUFRLEVBQUUsR0FBRztxQkFDZDtvQkFDRCxJQUFJLEVBQUUsc0VBQXNFO29CQUM1RSxVQUFVLEVBQUUsMEJBQWUsQ0FBQyxhQUFhO29CQUN6QyxNQUFNLEVBQUUsZ0JBQWdCO29CQUN4QixTQUFTLEVBQUUsb0VBQW9FO2lCQUNoRjtnQkFDRCxPQUFPLEVBQUU7b0JBQ1AsUUFBUSxFQUFFLFdBQVc7b0JBQ3JCLFFBQVEsRUFBRSxHQUFHO2lCQUNkO2FBQ0YsQ0FBQztZQUNGLE1BQU0sZUFBZSxHQUE4QixXQUFXLENBQUM7WUFDL0QsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsa0JBQWtCLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDdkUsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO2dCQUNqQyxjQUFjO2dCQUNkLElBQUk7Z0JBQ0osU0FBUztnQkFDVCxjQUFjO2dCQUNkLFlBQVk7Z0JBQ1osS0FBSztnQkFDTCxlQUFlO2dCQUNmLGNBQWM7Z0JBQ2QsWUFBWTthQUNiLENBQUMsQ0FBQztZQUNILFdBQVcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEQsV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzQyxXQUFXLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlDLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN6RSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDL0UsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUNqRSxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDN0UsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsa0RBQWtELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDaEUsTUFBTSxlQUFlLEdBQUc7Z0JBQ3RCLEdBQUcsRUFBRTtvQkFDSCxRQUFRLEVBQUUsR0FBRztvQkFDYixRQUFRLEVBQUUsT0FBTztpQkFDbEI7YUFDRixDQUFDO1lBQ0YsTUFBTSxRQUFRLENBQUMsa0JBQWtCLENBQUMsZUFBZSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUM3RyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFlBQVksRUFBRTtRQUNyQixFQUFFLENBQUMseURBQXlELEVBQUU7WUFDNUQsTUFBTSxnQkFBZ0IsR0FBRztnQkFDdkIsbUZBQW1GO2dCQUNuRiwrRUFBK0U7Z0JBQy9FLG9GQUFvRjthQUNyRixDQUFDO1lBRUYsS0FBSyxNQUFNLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN2QyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDNUQsUUFBUSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx5Q0FBeUMsRUFBRTtZQUM1QyxNQUFNLGNBQWMsR0FBRztnQkFDckIsbUZBQW1GO2dCQUNuRixtRkFBbUY7Z0JBQ25GLHlGQUF5RixFQUFFLFVBQVU7YUFDdEcsQ0FBQztZQUVGLEtBQUssTUFBTSxPQUFPLElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ3JDLFFBQVEsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNwRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsdURBQXVELEVBQUUsS0FBSztZQUMvRCxNQUFNLGdCQUFnQixHQUFHO2dCQUN2QixtRkFBbUY7Z0JBQ25GLCtFQUErRTtnQkFDL0Usb0ZBQW9GO2FBQ3JGLENBQUM7WUFFRixLQUFLLE1BQU0sT0FBTyxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDcEUsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHVDQUF1QyxFQUFFLEtBQUs7WUFDL0MsTUFBTSxXQUFXLEdBQUcsc0VBQXNFLENBQUM7WUFDM0YsTUFBTSxTQUFTLEdBQUc7Z0JBQ2hCO29CQUNFLEVBQUUsRUFBRSxrQ0FBa0M7b0JBQ3RDLEdBQUcsRUFBRSxpSEFBaUg7b0JBQ3RILFVBQVUsRUFBRSw0Q0FBNEM7b0JBQ3hELE1BQU0sRUFBRSxNQUFNO29CQUNkLElBQUksRUFBRSxhQUFhO29CQUNuQixZQUFZLEVBQ1YsNFNBQTRTO2lCQUMvUztnQkFDRDtvQkFDRSxFQUFFLEVBQUUsa0NBQWtDO29CQUN0QyxHQUFHLEVBQUUsaUhBQWlIO29CQUN0SCxVQUFVLEVBQUUsNENBQTRDO29CQUN4RCxNQUFNLEVBQUUsUUFBUTtvQkFDaEIsSUFBSSxFQUFFLGFBQWE7b0JBQ25CLFlBQVksRUFDViw0U0FBNFM7aUJBQy9TO2dCQUNEO29CQUNFLEVBQUUsRUFBRSxrQ0FBa0M7b0JBQ3RDLEdBQUcsRUFBRSxpSEFBaUg7b0JBQ3RILFVBQVUsRUFBRSw0Q0FBNEM7b0JBQ3hELE1BQU0sRUFBRSxPQUFPO29CQUNmLElBQUksRUFBRSxhQUFhO29CQUNuQixPQUFPLEVBQUUsSUFBSTtpQkFDZDthQUNGLENBQUM7WUFFRixNQUFNLGNBQWMsR0FBRztnQkFDckI7b0JBQ0UsT0FBTyxFQUFFLHNFQUFzRTtvQkFDL0UsU0FBUztvQkFDVCxXQUFXO2lCQUNaO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxtRkFBbUY7b0JBQzVGLFNBQVM7b0JBQ1QsV0FBVztpQkFDWjtnQkFDRDtvQkFDRSxPQUFPLEVBQUUsc0ZBQXNGO29CQUMvRixTQUFTO29CQUNULFdBQVc7aUJBQ1o7YUFDRixDQUFDO1lBRUYsS0FBSyxNQUFNLGFBQWEsSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDM0MsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pFLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGlCQUFpQixFQUFFO1FBQzFCLE1BQU0sV0FBVyxHQUFHLG1GQUFtRixDQUFDO1FBRXhHLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxLQUFLO1lBQ3pCLE1BQU0sUUFBUTtpQkFDWCxlQUFlLENBQUM7Z0JBQ2YsT0FBTyxFQUFFLG1GQUFtRjtnQkFDNUYsV0FBVzthQUNaLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDaEMsTUFBTSxRQUFRO2lCQUNYLGVBQWUsQ0FBQztnQkFDZixPQUFPLEVBQUUscUZBQXFGO2dCQUM5RixXQUFXO2FBQ1osQ0FBQztpQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNoQyxNQUFNLFFBQVE7aUJBQ1gsZUFBZSxDQUFDO2dCQUNmLE9BQU8sRUFBRSxzRUFBc0U7Z0JBQy9FLFdBQVc7YUFDWixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLE1BQU0sUUFBUTtpQkFDWCxlQUFlLENBQUM7Z0JBQ2YsT0FBTyxFQUFFLG1GQUFtRjtnQkFDNUYsV0FBVzthQUNaLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsbUJBQW1CLEVBQUUsS0FBSztZQUMzQixNQUFNLFFBQVE7aUJBQ1gsZUFBZSxDQUFDO2dCQUNmLE9BQU8sRUFBRSxzRUFBc0U7Z0JBQy9FLFdBQVc7YUFDWixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgQ3NwckFjY291bnRMaWIgZnJvbSAnLi4vLi4vc3JjL2xpYic7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBDc3ByLCBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zLCBUcmFuc2FjdGlvbkZlZSB9IGZyb20gJy4uLy4uL3NyYy9jc3ByJztcbmltcG9ydCB7IFRjc3ByIH0gZnJvbSAnLi4vLi4vc3JjL3Rjc3ByJztcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IHsgc2lnbmVkUmF3RGVsZWdhdGVUeCwgc2lnbmVkUmF3VHJhbnNmZXJUeCwgc2lnbmVkUmF3VW5kZWxlZ2F0ZVR4IH0gZnJvbSAnLi4vZml4dHVyZXMvY3Nwcic7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblR5cGUgfSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgQml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLWFwaSc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcblxudHlwZSBUcmFuc2FjdGlvbiA9IENzcHJBY2NvdW50TGliLlRyYW5zYWN0aW9uO1xuXG5kZXNjcmliZSgnQ2FzcGVyJywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBjb2luTmFtZSA9ICd0Y3Nwcic7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgYmFzZWNvaW47XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwge1xuICAgICAgZW52OiAnbW9jaycsXG4gICAgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCdjc3ByJywgQ3Nwci5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0Y3NwcicsIFRjc3ByLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oY29pbk5hbWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGluc3RhbnRpYXRlIHRoZSBjb2luJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBsb2NhbEJhc2Vjb2luID0gYml0Z28uY29pbigndGNzcHInKTtcbiAgICBsb2NhbEJhc2Vjb2luLnNob3VsZC5iZS5hbi5pbnN0YW5jZW9mKFRjc3ByKTtcblxuICAgIGxvY2FsQmFzZWNvaW4gPSBiaXRnby5jb2luKCdjc3ByJyk7XG4gICAgbG9jYWxCYXNlY29pbi5zaG91bGQuYmUuYW4uaW5zdGFuY2VvZihDc3ByKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gdGNzcHInLCBmdW5jdGlvbiAoKSB7XG4gICAgYmFzZWNvaW4uZ2V0Q2hhaW4oKS5zaG91bGQuZXF1YWwoJ3Rjc3ByJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGZ1bGwgbmFtZScsIGZ1bmN0aW9uICgpIHtcbiAgICBiYXNlY29pbi5nZXRGdWxsTmFtZSgpLnNob3VsZC5lcXVhbCgnVGVzdG5ldCBDYXNwZXInKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0tleXBhaXJzOicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGEga2V5cGFpciBmcm9tIHJhbmRvbSBzZWVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5UGFpciA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcigpO1xuICAgICAga2V5UGFpci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHViJyk7XG4gICAgICBrZXlQYWlyLnNob3VsZC5oYXZlLnByb3BlcnR5KCdwcnYnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgYSBrZXlwYWlyIGZyb20gYSBzZWVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VlZFRleHQgPSAnODAzNTBiNDIwOGQzODFmYmZlMjI3NmEzMjY2MDMwNDlmZTUwMDczMWM0NmQzYzk5MzZiNWNlMDM2YjUxMzc3Zic7XG4gICAgICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oc2VlZFRleHQsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBiYXNlY29pbi5nZW5lcmF0ZUtleVBhaXIoc2VlZCk7XG5cbiAgICAgIGtleVBhaXIucHViLnNob3VsZC5lcXVhbChcbiAgICAgICAgJ3hwdWI2NjFNeU13QXFSYmNGbkppM212U3BZTll5WFVjanE3c3BxSGc5R2hwY1dxczN3RjRTOGZvclVlSjNLOFhmcFV1bXBZNG1MaGFHUFdBeEFKRVRDbkpNNTZ3NWYyNWc2a3ZMaDVCeGIzWkViRCdcbiAgICAgICk7XG4gICAgICBrZXlQYWlyLnBydi5zaG91bGQuZXF1YWwoXG4gICAgICAgICd4cHJ2OXMyMVpyUUgxNDNLM0pFRXdrUFNUUVJwUlZlOExOUTJUY041THRKRDRCSnRCOHV1dGJNWkpnS3BDM0VQSE1QR245N1k5YVhGWWVGZWdGc1BkWlh1NkJGNVhCN3lYaFpEVUU1ZDZrZVRIeVYnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhIHB1YmxpYyBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gYmFzZWNvaW4uZ2VuZXJhdGVLZXlQYWlyKCk7XG4gICAgICBrZXlQYWlyLnNob3VsZC5oYXZlLnByb3BlcnR5KCdwdWInKTtcbiAgICAgIGtleVBhaXIuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3BydicpO1xuXG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHViKGtleVBhaXIucHViKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGEgcHJpdmF0ZSBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gYmFzZWNvaW4uZ2VuZXJhdGVLZXlQYWlyKCk7XG4gICAgICBrZXlQYWlyLnNob3VsZC5oYXZlLnByb3BlcnR5KCdwdWInKTtcbiAgICAgIGtleVBhaXIuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3BydicpO1xuXG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHJ2KGtleVBhaXIucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnU2hvdWxkIHN1cHBsZW1lbnQgd2FsbGV0IGdlbmVyYXRpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBkZXRhaWxzID0gYXdhaXQgYmFzZWNvaW4uc3VwcGxlbWVudEdlbmVyYXRlV2FsbGV0KHt9KTtcbiAgICAgIGRldGFpbHMuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3Jvb3RQcml2YXRlS2V5Jyk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHJ2KGRldGFpbHMucm9vdFByaXZhdGVLZXkpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdTaG91bGQgc3VwcGxlbWVudCB3YWxsZXQgZ2VuZXJhdGlvbiB3aXRoIHByb3ZpZGVkIHByaXZhdGUga2V5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgcm9vdFByaXZhdGVLZXkgPSAnZTBjNWMzNDdmYzY3YTQ2YWE1MTA0ZWNlNDU0ODgyMzE1ZmU1ZDcwYWYyODZkYmQzZDJlMDQyMjdlYmQyOTI3ZCc7XG4gICAgICBjb25zdCBkZXRhaWxzID0gYXdhaXQgYmFzZWNvaW4uc3VwcGxlbWVudEdlbmVyYXRlV2FsbGV0KHsgcm9vdFByaXZhdGVLZXkgfSk7XG4gICAgICBkZXRhaWxzLnNob3VsZC5oYXZlLnByb3BlcnR5KCdyb290UHJpdmF0ZUtleScpO1xuICAgICAgZGV0YWlscy5yb290UHJpdmF0ZUtleS5zaG91bGQuZXF1YWwocm9vdFByaXZhdGVLZXkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiBUcmFuc2FjdGlvbicsICgpID0+IHtcbiAgICBjb25zdCBmYWN0b3J5ID0gbmV3IENzcHJBY2NvdW50TGliLlRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KGNvaW5OYW1lKSk7XG4gICAgY29uc3Qgc291cmNlS2V5UGFpck9iamVjdCA9IG5ldyBDc3ByQWNjb3VudExpYi5LZXlQYWlyKCk7XG4gICAgY29uc3Qgc291cmNlS2V5UGFpciA9IHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0S2V5cygpO1xuICAgIGNvbnN0IHRhcmdldEtleVBhaXJPYmplY3QgPSBuZXcgQ3NwckFjY291bnRMaWIuS2V5UGFpcigpO1xuICAgIGNvbnN0IGV4dGVuZGVkU291cmNlS2V5UGFpciA9IHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0RXh0ZW5kZWRLZXlzKCk7XG5cbiAgICBpdCgnc2hvdWxkIGJlIHBlcmZvcm1lZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJpdGdvS2V5UGFpck9iamVjdCA9IG5ldyBDc3ByQWNjb3VudExpYi5LZXlQYWlyKCk7XG4gICAgICBjb25zdCBiaXRnb0tleVBhaXIgPSBiaXRnb0tleVBhaXJPYmplY3QuZ2V0S2V5cygpO1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5mZWUoeyBnYXNMaW1pdDogJzEwMDAwJywgZ2FzUHJpY2U6ICcxMCcgfSlcbiAgICAgICAgLnNvdXJjZSh7IGFkZHJlc3M6IHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0QWRkcmVzcygpIH0pXG4gICAgICAgIC50byh0YXJnZXRLZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKSlcbiAgICAgICAgLmFtb3VudCgnMjUwMDAwMDAwMCcpXG4gICAgICAgIC50cmFuc2ZlcklkKDEyMyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNhY3Rpb247XG4gICAgICB0eC5jYXNwZXJUeC5hcHByb3ZhbHMubGVuZ3RoLnNob3VsZC5lcXVhbHMoMCk7XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgICAgICB9LFxuICAgICAgICBwcnY6IHNvdXJjZUtleVBhaXIucHJ2LFxuICAgICAgfTtcblxuICAgICAgbGV0IHNpZ25lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHBhcmFtcyk7XG4gICAgICBzaWduZWRUcmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaGFsZlNpZ25lZCcpO1xuXG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHggPSBKU09OLnBhcnNlKHNpZ25lZFRyYW5zYWN0aW9uLmhhbGZTaWduZWQudHhIZXgpO1xuICAgICAgaGFsZlNpZ25lZFR4LmRlcGxveS5hcHByb3ZhbHMubGVuZ3RoLnNob3VsZC5lcXVhbHMoMSk7XG4gICAgICBoYWxmU2lnbmVkVHguZGVwbG95LmFwcHJvdmFsc1swXS5zaWduZXJcbiAgICAgICAgLnRvVXBwZXJDYXNlKClcbiAgICAgICAgLnNob3VsZC5lcXVhbHMoc291cmNlS2V5UGFpck9iamVjdC5nZXRBZGRyZXNzKCkudG9VcHBlckNhc2UoKSk7XG4gICAgICBDc3ByQWNjb3VudExpYi5VdGlscy5pc1ZhbGlkVHJhbnNhY3Rpb25TaWduYXR1cmUoXG4gICAgICAgIGhhbGZTaWduZWRUeC5kZXBsb3kuYXBwcm92YWxzWzBdLnNpZ25hdHVyZSxcbiAgICAgICAgaGFsZlNpZ25lZFR4LmRlcGxveS5oYXNoLFxuICAgICAgICBzb3VyY2VLZXlQYWlyLnB1YlxuICAgICAgKS5zaG91bGQuZXF1YWxzKHRydWUpO1xuXG4gICAgICBwYXJhbXMudHhQcmVidWlsZC50eEhleCA9IHNpZ25lZFRyYW5zYWN0aW9uLmhhbGZTaWduZWQudHhIZXg7XG4gICAgICBwYXJhbXMucHJ2ID0gYml0Z29LZXlQYWlyLnBydjtcbiAgICAgIHNpZ25lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHBhcmFtcyk7XG4gICAgICBzaWduZWRUcmFuc2FjdGlvbi5zaG91bGQubm90LmhhdmUucHJvcGVydHkoJ2hhbGZTaWduZWQnKTtcbiAgICAgIHNpZ25lZFRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuXG4gICAgICBjb25zdCB0d2ljZVNpZ25lZFR4ID0gSlNPTi5wYXJzZShzaWduZWRUcmFuc2FjdGlvbi50eEhleCk7XG4gICAgICB0d2ljZVNpZ25lZFR4LmRlcGxveS5hcHByb3ZhbHMubGVuZ3RoLnNob3VsZC5lcXVhbHMoMik7XG4gICAgICB0d2ljZVNpZ25lZFR4LmRlcGxveS5hcHByb3ZhbHNbMF0uc2lnbmVyXG4gICAgICAgIC50b1VwcGVyQ2FzZSgpXG4gICAgICAgIC5zaG91bGQuZXF1YWxzKHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0QWRkcmVzcygpLnRvVXBwZXJDYXNlKCkpO1xuICAgICAgdHdpY2VTaWduZWRUeC5kZXBsb3kuYXBwcm92YWxzWzFdLnNpZ25lclxuICAgICAgICAudG9VcHBlckNhc2UoKVxuICAgICAgICAuc2hvdWxkLmVxdWFscyhiaXRnb0tleVBhaXJPYmplY3QuZ2V0QWRkcmVzcygpLnRvVXBwZXJDYXNlKCkpO1xuXG4gICAgICBDc3ByQWNjb3VudExpYi5VdGlscy5pc1ZhbGlkVHJhbnNhY3Rpb25TaWduYXR1cmUoXG4gICAgICAgIHR3aWNlU2lnbmVkVHguZGVwbG95LmFwcHJvdmFsc1swXS5zaWduYXR1cmUsXG4gICAgICAgIHR3aWNlU2lnbmVkVHguZGVwbG95Lmhhc2gsXG4gICAgICAgIHNvdXJjZUtleVBhaXIucHViXG4gICAgICApLnNob3VsZC5lcXVhbHModHJ1ZSk7XG4gICAgICBDc3ByQWNjb3VudExpYi5VdGlscy5pc1ZhbGlkVHJhbnNhY3Rpb25TaWduYXR1cmUoXG4gICAgICAgIHR3aWNlU2lnbmVkVHguZGVwbG95LmFwcHJvdmFsc1sxXS5zaWduYXR1cmUsXG4gICAgICAgIHR3aWNlU2lnbmVkVHguZGVwbG95Lmhhc2gsXG4gICAgICAgIGJpdGdvS2V5UGFpci5wdWJcbiAgICAgICkuc2hvdWxkLmVxdWFscyh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgcGVyZm9ybWVkIHdpdGggZXh0ZW5kZWQga2V5cycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJpdGdvS2V5UGFpck9iamVjdCA9IG5ldyBDc3ByQWNjb3VudExpYi5LZXlQYWlyKCk7XG4gICAgICBjb25zdCBiaXRnb0tleVBhaXIgPSBiaXRnb0tleVBhaXJPYmplY3QuZ2V0S2V5cygpO1xuICAgICAgY29uc3QgZXh0ZW5kZWRCaXRnb0tleVBhaXIgPSBiaXRnb0tleVBhaXJPYmplY3QuZ2V0RXh0ZW5kZWRLZXlzKCk7XG5cbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuZmVlKHsgZ2FzTGltaXQ6ICcxMDAwMCcsIGdhc1ByaWNlOiAnMTAnIH0pXG4gICAgICAgIC5zb3VyY2UoeyBhZGRyZXNzOiBzb3VyY2VLZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKSB9KVxuICAgICAgICAudG8odGFyZ2V0S2V5UGFpck9iamVjdC5nZXRBZGRyZXNzKCkpXG4gICAgICAgIC5hbW91bnQoJzI1MDAwMDAwMDAnKVxuICAgICAgICAudHJhbnNmZXJJZCgxMjMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgdHguY2FzcGVyVHguYXBwcm92YWxzLmxlbmd0aC5zaG91bGQuZXF1YWxzKDApO1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogdHgudG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgICAgcHJ2OiBleHRlbmRlZFNvdXJjZUtleVBhaXIueHBydixcbiAgICAgIH07XG5cbiAgICAgIGxldCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbihwYXJhbXMpO1xuICAgICAgc2lnbmVkVHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2hhbGZTaWduZWQnKTtcblxuICAgICAgY29uc3QgaGFsZlNpZ25lZFR4ID0gSlNPTi5wYXJzZShzaWduZWRUcmFuc2FjdGlvbi5oYWxmU2lnbmVkLnR4SGV4KTtcbiAgICAgIGhhbGZTaWduZWRUeC5kZXBsb3kuYXBwcm92YWxzLmxlbmd0aC5zaG91bGQuZXF1YWxzKDEpO1xuICAgICAgaGFsZlNpZ25lZFR4LmRlcGxveS5hcHByb3ZhbHNbMF0uc2lnbmVyXG4gICAgICAgIC50b1VwcGVyQ2FzZSgpXG4gICAgICAgIC5zaG91bGQuZXF1YWxzKHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0QWRkcmVzcygpLnRvVXBwZXJDYXNlKCkpO1xuICAgICAgQ3NwckFjY291bnRMaWIuVXRpbHMuaXNWYWxpZFRyYW5zYWN0aW9uU2lnbmF0dXJlKFxuICAgICAgICBoYWxmU2lnbmVkVHguZGVwbG95LmFwcHJvdmFsc1swXS5zaWduYXR1cmUsXG4gICAgICAgIGhhbGZTaWduZWRUeC5kZXBsb3kuaGFzaCxcbiAgICAgICAgc291cmNlS2V5UGFpci5wdWJcbiAgICAgICkuc2hvdWxkLmVxdWFscyh0cnVlKTtcblxuICAgICAgcGFyYW1zLnR4UHJlYnVpbGQudHhIZXggPSBzaWduZWRUcmFuc2FjdGlvbi5oYWxmU2lnbmVkLnR4SGV4O1xuICAgICAgcGFyYW1zLnBydiA9IGV4dGVuZGVkQml0Z29LZXlQYWlyLnhwcnY7XG4gICAgICBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbihwYXJhbXMpO1xuICAgICAgc2lnbmVkVHJhbnNhY3Rpb24uc2hvdWxkLm5vdC5oYXZlLnByb3BlcnR5KCdoYWxmU2lnbmVkJyk7XG4gICAgICBzaWduZWRUcmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcblxuICAgICAgY29uc3QgdHdpY2VTaWduZWRUeEhleCA9IEpTT04ucGFyc2Uoc2lnbmVkVHJhbnNhY3Rpb24udHhIZXgpO1xuICAgICAgdHdpY2VTaWduZWRUeEhleC5kZXBsb3kuYXBwcm92YWxzLmxlbmd0aC5zaG91bGQuZXF1YWxzKDIpO1xuICAgICAgdHdpY2VTaWduZWRUeEhleC5kZXBsb3kuYXBwcm92YWxzWzBdLnNpZ25lclxuICAgICAgICAudG9VcHBlckNhc2UoKVxuICAgICAgICAuc2hvdWxkLmVxdWFscyhzb3VyY2VLZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKS50b1VwcGVyQ2FzZSgpKTtcbiAgICAgIHR3aWNlU2lnbmVkVHhIZXguZGVwbG95LmFwcHJvdmFsc1sxXS5zaWduZXJcbiAgICAgICAgLnRvVXBwZXJDYXNlKClcbiAgICAgICAgLnNob3VsZC5lcXVhbHMoYml0Z29LZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKS50b1VwcGVyQ2FzZSgpKTtcblxuICAgICAgQ3NwckFjY291bnRMaWIuVXRpbHMuaXNWYWxpZFRyYW5zYWN0aW9uU2lnbmF0dXJlKFxuICAgICAgICB0d2ljZVNpZ25lZFR4SGV4LmRlcGxveS5hcHByb3ZhbHNbMF0uc2lnbmF0dXJlLFxuICAgICAgICB0d2ljZVNpZ25lZFR4SGV4LmRlcGxveS5oYXNoLFxuICAgICAgICBzb3VyY2VLZXlQYWlyLnB1YlxuICAgICAgKS5zaG91bGQuZXF1YWxzKHRydWUpO1xuICAgICAgQ3NwckFjY291bnRMaWIuVXRpbHMuaXNWYWxpZFRyYW5zYWN0aW9uU2lnbmF0dXJlKFxuICAgICAgICB0d2ljZVNpZ25lZFR4SGV4LmRlcGxveS5hcHByb3ZhbHNbMV0uc2lnbmF0dXJlLFxuICAgICAgICB0d2ljZVNpZ25lZFR4SGV4LmRlcGxveS5oYXNoLFxuICAgICAgICBiaXRnb0tleVBhaXIucHViXG4gICAgICApLnNob3VsZC5lcXVhbHModHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJlIHJlamVjdGVkIGlmIGludmFsaWQga2V5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc291cmNlS2V5UGFpck9iamVjdCA9IG5ldyBDc3ByQWNjb3VudExpYi5LZXlQYWlyKCk7XG4gICAgICBjb25zdCB0YXJnZXRLZXlQYWlyT2JqZWN0ID0gbmV3IENzcHJBY2NvdW50TGliLktleVBhaXIoKTtcbiAgICAgIGNvbnN0IGludmFsaWRQcml2YXRlS2V5ID0gJ0FBQUFBJztcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuZmVlKHsgZ2FzTGltaXQ6ICcxMDAwMCcsIGdhc1ByaWNlOiAnMTAnIH0pXG4gICAgICAgIC5zb3VyY2UoeyBhZGRyZXNzOiBzb3VyY2VLZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKSB9KVxuICAgICAgICAudG8odGFyZ2V0S2V5UGFpck9iamVjdC5nZXRBZGRyZXNzKCkpXG4gICAgICAgIC5hbW91bnQoJzI1MDAwMDAwMDAnKVxuICAgICAgICAudHJhbnNmZXJJZCgxMjMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgdHguY2FzcGVyVHguYXBwcm92YWxzLmxlbmd0aC5zaG91bGQuZXF1YWxzKDApO1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogdHgudG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgICAgcHJ2OiBpbnZhbGlkUHJpdmF0ZUtleSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbihwYXJhbXMpLnNob3VsZC5iZS5yZWplY3RlZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiBNZXNzYWdlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgYmUgcGVyZm9ybWVkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qga2V5UGFpciA9IG5ldyBDc3ByQWNjb3VudExpYi5LZXlQYWlyKCkuZ2V0S2V5cygpO1xuICAgICAgY29uc3QgbWVzc2FnZVRvU2lnbiA9IEJ1ZmZlci5mcm9tKHJhbmRvbUJ5dGVzKDMyKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2Uoa2V5UGFpciwgbWVzc2FnZVRvU2lnbik7XG4gICAgICBDc3ByQWNjb3VudExpYi5VdGlscy5pc1ZhbGlkTWVzc2FnZVNpZ25hdHVyZShzaWduYXR1cmUudG9TdHJpbmcoJ2hleCcpLCBtZXNzYWdlVG9TaWduLCBrZXlQYWlyLnB1Yikuc2hvdWxkLmVxdWFscyhcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgcGVyZm9ybWVkIHdpdGggZXh0ZW5kZWQga2V5cycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXJUb1NpZ24gPSBuZXcgQ3NwckFjY291bnRMaWIuS2V5UGFpcigpO1xuICAgICAgY29uc3Qga2V5UGFpckV4dGVuZGVkS2V5cyA9IGtleVBhaXJUb1NpZ24uZ2V0RXh0ZW5kZWRLZXlzKCk7XG4gICAgICBjb25zdCBrZXlQYWlyID0ga2V5UGFpclRvU2lnbi5nZXRLZXlzKCk7XG4gICAgICBjb25zdCBtZXNzYWdlVG9TaWduID0gQnVmZmVyLmZyb20ocmFuZG9tQnl0ZXMoMzIpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBiYXNlY29pbi5zaWduTWVzc2FnZShcbiAgICAgICAgeyBwdWI6IGtleVBhaXJFeHRlbmRlZEtleXMueHB1YiwgcHJ2OiBrZXlQYWlyRXh0ZW5kZWRLZXlzLnhwcnYgfSxcbiAgICAgICAgbWVzc2FnZVRvU2lnblxuICAgICAgKTtcbiAgICAgIENzcHJBY2NvdW50TGliLlV0aWxzLmlzVmFsaWRNZXNzYWdlU2lnbmF0dXJlKHNpZ25hdHVyZS50b1N0cmluZygnaGV4JyksIG1lc3NhZ2VUb1NpZ24sIGtleVBhaXIucHViKS5zaG91bGQuZXF1YWxzKFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdpdGggbWlzc2luZyBwcml2YXRlIGtleScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgQ3NwckFjY291bnRMaWIuS2V5UGFpcih7XG4gICAgICAgIHB1YjogJzAyOUY2OTdBMDIzNTU4MzlBMDIxNTdFODc3MjFGN0M0NEVFNDVERTlCODkxMjY2QkUwNjVGRDdGOUI0RUIzMUI4OCcsXG4gICAgICB9KS5nZXRLZXlzKCk7XG4gICAgICBjb25zdCBtZXNzYWdlVG9TaWduID0gQnVmZmVyLmZyb20ocmFuZG9tQnl0ZXMoMzIpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBiYXNlY29pbi5zaWduTWVzc2FnZShrZXlQYWlyLCBtZXNzYWdlVG9TaWduKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIGtleSBwYWlyIG9wdGlvbnMnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0V4cGxhaW4gVHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgY29uc3QgZmFjdG9yeSA9IG5ldyBDc3ByQWNjb3VudExpYi5UcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldChjb2luTmFtZSkpO1xuICAgIGNvbnN0IHNvdXJjZUtleVBhaXJPYmplY3QgPSBuZXcgQ3NwckFjY291bnRMaWIuS2V5UGFpcigpO1xuICAgIGNvbnN0IHNvdXJjZUtleVBhaXIgPSBzb3VyY2VLZXlQYWlyT2JqZWN0LmdldEtleXMoKTtcbiAgICBjb25zdCB0YXJnZXRLZXlQYWlyT2JqZWN0ID0gbmV3IENzcHJBY2NvdW50TGliLktleVBhaXIoKTtcbiAgICBsZXQgdHhCdWlsZGVyO1xuICAgIGxldCBkZ0J1aWxkZXI7XG4gICAgbGV0IHVkZ0J1aWxkZXI7XG4gICAgY29uc3QgdHJhbnNmZXJBbW91bnQgPSAnMjUwMDAwMDAwMCc7XG4gICAgY29uc3QgZGVsZWdhdGVBbW91bnQgPSAnMjUwMDAwMDAwJztcbiAgICBjb25zdCB1bmRlbGVnYXRlQW1vdW50ID0gJzI1MDAwMDAwMCc7XG4gICAgY29uc3QgdHJhbnNmZXJJZCA9IDEyMztcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyXG4gICAgICAgIC5mZWUoeyBnYXNMaW1pdDogJzEwMDAwJywgZ2FzUHJpY2U6ICcxMCcgfSlcbiAgICAgICAgLnNvdXJjZSh7IGFkZHJlc3M6IHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0QWRkcmVzcygpIH0pXG4gICAgICAgIC50byh0YXJnZXRLZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKSlcbiAgICAgICAgLmFtb3VudCh0cmFuc2ZlckFtb3VudClcbiAgICAgICAgLnRyYW5zZmVySWQodHJhbnNmZXJJZCk7XG5cbiAgICAgIGRnQnVpbGRlciA9IGZhY3RvcnkuZ2V0RGVsZWdhdGVCdWlsZGVyKCk7XG4gICAgICBkZ0J1aWxkZXJcbiAgICAgICAgLmZlZSh7IGdhc0xpbWl0OiAnMzAwMDAwMDAwMCcsIGdhc1ByaWNlOiAnMScgfSlcbiAgICAgICAgLnNvdXJjZSh7IGFkZHJlc3M6IHNvdXJjZUtleVBhaXJPYmplY3QuZ2V0QWRkcmVzcygpIH0pXG4gICAgICAgIC5hbW91bnQoZGVsZWdhdGVBbW91bnQpXG4gICAgICAgIC52YWxpZGF0b3IoJzAxMTVjOWI0MGMwNmZmOTliMGNiYWRmMTE0MGIwNjFiNWRiZjkyMTAzZTY2YTYzMzBmYmNjNzc2OGY1MjE5YzFjZScpO1xuXG4gICAgICB1ZGdCdWlsZGVyID0gZmFjdG9yeS5nZXRVbmRlbGVnYXRlQnVpbGRlcigpO1xuICAgICAgdWRnQnVpbGRlclxuICAgICAgICAuZmVlKHsgZ2FzTGltaXQ6ICczMDAwMDAwMDAwJywgZ2FzUHJpY2U6ICcxJyB9KVxuICAgICAgICAuc291cmNlKHsgYWRkcmVzczogc291cmNlS2V5UGFpck9iamVjdC5nZXRBZGRyZXNzKCkgfSlcbiAgICAgICAgLmFtb3VudCh1bmRlbGVnYXRlQW1vdW50KVxuICAgICAgICAudmFsaWRhdG9yKCcwMTE1YzliNDBjMDZmZjk5YjBjYmFkZjExNDBiMDYxYjVkYmY5MjEwM2U2NmE2MzMwZmJjYzc3NjhmNTIxOWMxY2UnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIGhhbGYgc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3Qgc2lnblR4cGFyYW1zID0ge1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogc291cmNlS2V5UGFpci5wcnYsXG4gICAgICB9O1xuICAgICAgY29uc3QgeyBoYWxmU2lnbmVkIH0gPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oc2lnblR4cGFyYW1zKTtcblxuICAgICAgY29uc3QgZmVlSW5mbzogVHJhbnNhY3Rpb25GZWUgPSB7XG4gICAgICAgIGdhc0xpbWl0OiAnMScsXG4gICAgICAgIGdhc1ByaWNlOiAnMTEwMDAnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4cGxhaW5UeFBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyA9IHtcbiAgICAgICAgaGFsZlNpZ25lZDoge1xuICAgICAgICAgIHR4SGV4OiBoYWxmU2lnbmVkLnR4SGV4LFxuICAgICAgICB9LFxuICAgICAgICBmZWVJbmZvLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFR4ID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5UeFBhcmFtcyk7XG4gICAgICBleHBsYWluZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKFtcbiAgICAgICAgJ2Rpc3BsYXlPcmRlcicsXG4gICAgICAgICdpZCcsXG4gICAgICAgICdvdXRwdXRzJyxcbiAgICAgICAgJ291dHB1dEFtb3VudCcsXG4gICAgICAgICd0cmFuc2ZlcklkJyxcbiAgICAgICAgJ2ZlZScsXG4gICAgICAgICdjaGFuZ2VPdXRwdXRzJyxcbiAgICAgICAgJ2NoYW5nZUFtb3VudCcsXG4gICAgICBdKTtcbiAgICAgIGV4cGxhaW5lZFR4LmZlZS5zaG91bGQuZXF1YWwoZmVlSW5mbyk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzLmZvckVhY2goKG91dHB1dCkgPT4ge1xuICAgICAgICBvdXRwdXQuYW1vdW50LnNob3VsZC5lcXVhbCh0cmFuc2ZlckFtb3VudCk7XG4gICAgICAgIG91dHB1dC5hZGRyZXNzLnNob3VsZC5lcXVhbCh0YXJnZXRLZXlQYWlyT2JqZWN0LmdldEFkZHJlc3MoKSk7XG4gICAgICAgIG91dHB1dC5jb2luLnNob3VsZC5lcXVhbChiYXNlY29pbi5nZXRDaGFpbigpKTtcbiAgICAgIH0pO1xuICAgICAgZXhwbGFpbmVkVHgub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCh0cmFuc2ZlckFtb3VudCk7XG4gICAgICBleHBsYWluZWRUeC50cmFuc2ZlcklkLnNob3VsZC5lcXVhbCh0cmFuc2ZlcklkLnRvU3RyaW5nKCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGEgc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbHRUeEluZm8gPSB7XG4gICAgICAgIHR4SGV4OiBzaWduZWRSYXdUcmFuc2ZlclR4LFxuICAgICAgICB0eEluZm86IHtcbiAgICAgICAgICBoYXNoOiAnY2Y3ZWFjMWExMGYzNTBmMzkzMTYzYzgyNTQ3NzA2NDliOTUzZGNkM2NmOGUxODBhYWJhNDYzODE2ZmJkMGEwYicsXG4gICAgICAgICAgZmVlOiB7XG4gICAgICAgICAgICBnYXNMaW1pdDogJzExMDAwJyxcbiAgICAgICAgICAgIGdhc1ByaWNlOiAnMScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBmcm9tOiAnMDJjYzhmNzhjNDFkMzM0YWQyYWFhZTZkYTdhODg1MzdmOTY4NjI0NTc2MWFhZGRmMzZkNGIyZGZiZjkxM2JiODczJyxcbiAgICAgICAgICBzdGFydFRpbWU6ICcyMDIxLTEyLTE0VDAwOjUzOjMyLjgzNlonLFxuICAgICAgICAgIGV4cGlyYXRpb246IDcyMDAwMDAsXG4gICAgICAgICAgZGVwbG95VHlwZTogJ1NlbmQnLFxuICAgICAgICAgIHRvOiAnMDIwMjIyN2ZhYTMyN2JiNjYwN2YxYjYyNDVkMjc1YjBjOWFlZjMyZGI1Njg5ODZiNTI1MjMyM2ZkNDk4OTIzZjFlZjEnLFxuICAgICAgICAgIGFtb3VudDogJzI1MDAwMDAwMDAnLFxuICAgICAgICAgIHRyYW5zZmVySWQ6ICcxMjMnLFxuICAgICAgICB9LFxuICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgZ2FzTGltaXQ6ICcxMTAwMCcsXG4gICAgICAgICAgZ2FzUHJpY2U6ICcxJyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICcwMjAyZmJhOWU1NzA1YTg4NjBmYzFiNTU2M2I5ODFhNGMyYzk0YWYwM2ZjMTA5MTZlYjc4MTliMTgzMDU2YzQzZDNiMCcsXG4gICAgICAgICAgICBhbW91bnQ6ICcyNTAwMDAwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4cGxhaW5UeFBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyA9IGJ1aWx0VHhJbmZvO1xuICAgICAgY29uc3QgZXhwbGFpbmVkVHggPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oZXhwbGFpblR4UGFyYW1zKTtcbiAgICAgIGV4cGxhaW5lZFR4LnNob3VsZC5oYXZlLnByb3BlcnRpZXMoW1xuICAgICAgICAnZGlzcGxheU9yZGVyJyxcbiAgICAgICAgJ2lkJyxcbiAgICAgICAgJ291dHB1dHMnLFxuICAgICAgICAnb3V0cHV0QW1vdW50JyxcbiAgICAgICAgJ3RyYW5zZmVySWQnLFxuICAgICAgICAnZmVlJyxcbiAgICAgICAgJ2NoYW5nZU91dHB1dHMnLFxuICAgICAgICAnY2hhbmdlQW1vdW50JyxcbiAgICAgIF0pO1xuICAgICAgZXhwbGFpbmVkVHguZmVlLnNob3VsZC5lcXVhbChidWlsdFR4SW5mby5mZWVJbmZvKTtcbiAgICAgIGV4cGxhaW5lZFR4LmlkLnNob3VsZC5lcXVhbChidWlsdFR4SW5mby50eEluZm8uaGFzaCk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoYnVpbHRUeEluZm8udHhJbmZvLmFtb3VudCk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKGJ1aWx0VHhJbmZvLnR4SW5mby50byk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzWzBdLmNvaW4uc2hvdWxkLmVxdWFsKGJhc2Vjb2luLmdldENoYWluKCkpO1xuICAgICAgZXhwbGFpbmVkVHgub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbChidWlsdFR4SW5mby50eEluZm8uYW1vdW50KTtcbiAgICAgIGV4cGxhaW5lZFR4LnRyYW5zZmVySWQuc2hvdWxkLmVxdWFsKGJ1aWx0VHhJbmZvLnR4SW5mby50cmFuc2ZlcklkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIGhhbGYgc2lnbmVkIGRlbGVnYXRlIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHggPSAoYXdhaXQgZGdCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3Qgc2lnblR4cGFyYW1zID0ge1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogc291cmNlS2V5UGFpci5wcnYsXG4gICAgICB9O1xuICAgICAgY29uc3QgeyBoYWxmU2lnbmVkIH0gPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oc2lnblR4cGFyYW1zKTtcblxuICAgICAgY29uc3QgZmVlSW5mbzogVHJhbnNhY3Rpb25GZWUgPSB7XG4gICAgICAgIGdhc0xpbWl0OiAnMScsXG4gICAgICAgIGdhc1ByaWNlOiAnMzAwMDAwMDAwMCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgZXhwbGFpblR4UGFyYW1zOiBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zID0ge1xuICAgICAgICBoYWxmU2lnbmVkOiB7XG4gICAgICAgICAgdHhIZXg6IGhhbGZTaWduZWQudHhIZXgsXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm8sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhJbmZvID0ge1xuICAgICAgICBoYXNoOiAnYjQ3Y2ExNjhhMmM2ZWM4NjRjNTkyM2E5OGJiOGJjYThjYjc4ZjAxNDFiZGViMzdmOWFkNzQ3MDVmOGM0MDYzNicsXG4gICAgICAgIGZlZToge1xuICAgICAgICAgIGdhc0xpbWl0OiAnMzAwMDAwMDAwMCcsXG4gICAgICAgICAgZ2FzUHJpY2U6ICcxJyxcbiAgICAgICAgfSxcbiAgICAgICAgZnJvbTogJzAyMDJjYzhmNzhjNDFkMzM0YWQyYWFhZTZkYTdhODg1MzdmOTY4NjI0NTc2MWFhZGRmMzZkNGIyZGZiZjkxM2JiODczJyxcbiAgICAgICAgZGVwbG95VHlwZTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdMb2NrLFxuICAgICAgICBhbW91bnQ6IGRlbGVnYXRlQW1vdW50LFxuICAgICAgICB2YWxpZGF0b3I6ICcwMTE1YzliNDBjMDZmZjk5YjBjYmFkZjExNDBiMDYxYjVkYmY5MjEwM2U2NmE2MzMwZmJjYzc3NjhmNTIxOWMxY2UnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFR4ID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5UeFBhcmFtcyk7XG4gICAgICBleHBsYWluZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKFtcbiAgICAgICAgJ2Rpc3BsYXlPcmRlcicsXG4gICAgICAgICdpZCcsXG4gICAgICAgICdvdXRwdXRzJyxcbiAgICAgICAgJ291dHB1dEFtb3VudCcsXG4gICAgICAgICd0cmFuc2ZlcklkJyxcbiAgICAgICAgJ2ZlZScsXG4gICAgICAgICdjaGFuZ2VPdXRwdXRzJyxcbiAgICAgICAgJ2NoYW5nZUFtb3VudCcsXG4gICAgICAgICdvcGVyYXRpb25zJyxcbiAgICAgIF0pO1xuICAgICAgZXhwbGFpbmVkVHguZmVlLnNob3VsZC5lcXVhbChleHBsYWluVHhQYXJhbXMuZmVlSW5mbyk7XG4gICAgICBleHBsYWluZWRUeC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBleHBsYWluZWRUeC5vcGVyYXRpb25zLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBleHBsYWluZWRUeC5vcGVyYXRpb25zWzBdLmFtb3VudC5zaG91bGQuZXF1YWwodHhJbmZvLmFtb3VudCk7XG4gICAgICBleHBsYWluZWRUeC5vcGVyYXRpb25zWzBdLnZhbGlkYXRvci5zaG91bGQuZXF1YWwodHhJbmZvLnZhbGlkYXRvcik7XG4gICAgICBleHBsYWluZWRUeC5vcGVyYXRpb25zWzBdLmNvaW4uc2hvdWxkLmVxdWFsKGJhc2Vjb2luLmdldENoYWluKCkpO1xuICAgICAgZXhwbGFpbmVkVHgub3BlcmF0aW9uc1swXS50eXBlLnNob3VsZC5lcXVhbCh0eEluZm8uZGVwbG95VHlwZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBzaWduZWQgZGVsZWdhdGUgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsdFR4SW5mbyA9IHtcbiAgICAgICAgdHhIZXg6IHNpZ25lZFJhd0RlbGVnYXRlVHgsXG4gICAgICAgIHR4SW5mbzoge1xuICAgICAgICAgIGhhc2g6ICc3NzFhMTkyMjI0MDk3ZmFmMGYxYjE4Mjk1YTUwZTRiZjE5MDcyOGNmMzY1NzExYjAzMGNiMDgzZDA3ODVlOTkzJyxcbiAgICAgICAgICBmZWU6IHtcbiAgICAgICAgICAgIGdhc0xpbWl0OiAnMTAwMDAwMDAwJyxcbiAgICAgICAgICAgIGdhc1ByaWNlOiAnMScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBmcm9tOiAnMDIwMmNjOGY3OGM0MWQzMzRhZDJhYWFlNmRhN2E4ODUzN2Y5Njg2MjQ1NzYxYWFkZGYzNmQ0YjJkZmJmOTEzYmI4NzMnLFxuICAgICAgICAgIGRlcGxveVR5cGU6IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nTG9jayxcbiAgICAgICAgICBhbW91bnQ6IGRlbGVnYXRlQW1vdW50LFxuICAgICAgICAgIHZhbGlkYXRvcjogJzAxMTVjOWI0MGMwNmZmOTliMGNiYWRmMTE0MGIwNjFiNWRiZjkyMTAzZTY2YTYzMzBmYmNjNzc2OGY1MjE5YzFjZScsXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICBnYXNMaW1pdDogJzEwMDAwMDAwMCcsXG4gICAgICAgICAgZ2FzUHJpY2U6ICcxJyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBjb25zdCBleHBsYWluVHhQYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMgPSBidWlsdFR4SW5mbztcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFR4ID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5UeFBhcmFtcyk7XG4gICAgICBleHBsYWluZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKFtcbiAgICAgICAgJ2Rpc3BsYXlPcmRlcicsXG4gICAgICAgICdpZCcsXG4gICAgICAgICdvdXRwdXRzJyxcbiAgICAgICAgJ291dHB1dEFtb3VudCcsXG4gICAgICAgICd0cmFuc2ZlcklkJyxcbiAgICAgICAgJ2ZlZScsXG4gICAgICAgICdjaGFuZ2VPdXRwdXRzJyxcbiAgICAgICAgJ2NoYW5nZUFtb3VudCcsXG4gICAgICAgICdvcGVyYXRpb25zJyxcbiAgICAgIF0pO1xuICAgICAgZXhwbGFpbmVkVHguZmVlLnNob3VsZC5lcXVhbChidWlsdFR4SW5mby5mZWVJbmZvKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0uYW1vdW50LnNob3VsZC5lcXVhbChidWlsdFR4SW5mby50eEluZm8uYW1vdW50KTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0udmFsaWRhdG9yLnNob3VsZC5lcXVhbChidWlsdFR4SW5mby50eEluZm8udmFsaWRhdG9yKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0uY29pbi5zaG91bGQuZXF1YWwoYmFzZWNvaW4uZ2V0Q2hhaW4oKSk7XG4gICAgICBleHBsYWluZWRUeC5vcGVyYXRpb25zWzBdLnR5cGUuc2hvdWxkLmVxdWFsKGJ1aWx0VHhJbmZvLnR4SW5mby5kZXBsb3lUeXBlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIGhhbGYgc2lnbmVkIHVuZGVsZWdhdGUgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eCA9IChhd2FpdCB1ZGdCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3Qgc2lnblR4cGFyYW1zID0ge1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogc291cmNlS2V5UGFpci5wcnYsXG4gICAgICB9O1xuICAgICAgY29uc3QgeyBoYWxmU2lnbmVkIH0gPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oc2lnblR4cGFyYW1zKTtcblxuICAgICAgY29uc3QgZmVlSW5mbzogVHJhbnNhY3Rpb25GZWUgPSB7XG4gICAgICAgIGdhc0xpbWl0OiAnMScsXG4gICAgICAgIGdhc1ByaWNlOiAnMzAwMDAwMDAwMCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgZXhwbGFpblR4UGFyYW1zOiBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zID0ge1xuICAgICAgICBoYWxmU2lnbmVkOiB7XG4gICAgICAgICAgdHhIZXg6IGhhbGZTaWduZWQudHhIZXgsXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm8sXG4gICAgICB9O1xuICAgICAgY29uc3QgdHhJbmZvID0ge1xuICAgICAgICBoYXNoOiAnYjQ3Y2ExNjhhMmM2ZWM4NjRjNTkyM2E5OGJiOGJjYThjYjc4ZjAxNDFiZGViMzdmOWFkNzQ3MDVmOGM0MDYzNicsXG4gICAgICAgIGZlZToge1xuICAgICAgICAgIGdhc0xpbWl0OiAnMzAwMDAwMDAwMCcsXG4gICAgICAgICAgZ2FzUHJpY2U6ICcxJyxcbiAgICAgICAgfSxcbiAgICAgICAgZnJvbTogJzAyMDJjYzhmNzhjNDFkMzM0YWQyYWFhZTZkYTdhODg1MzdmOTY4NjI0NTc2MWFhZGRmMzZkNGIyZGZiZjkxM2JiODczJyxcbiAgICAgICAgZGVwbG95VHlwZTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2ssXG4gICAgICAgIGFtb3VudDogdW5kZWxlZ2F0ZUFtb3VudCxcbiAgICAgICAgdmFsaWRhdG9yOiAnMDExNWM5YjQwYzA2ZmY5OWIwY2JhZGYxMTQwYjA2MWI1ZGJmOTIxMDNlNjZhNjMzMGZiY2M3NzY4ZjUyMTljMWNlJyxcbiAgICAgIH07XG4gICAgICBjb25zdCBleHBsYWluZWRUeCA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbihleHBsYWluVHhQYXJhbXMpO1xuICAgICAgZXhwbGFpbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydGllcyhbXG4gICAgICAgICdkaXNwbGF5T3JkZXInLFxuICAgICAgICAnaWQnLFxuICAgICAgICAnb3V0cHV0cycsXG4gICAgICAgICdvdXRwdXRBbW91bnQnLFxuICAgICAgICAndHJhbnNmZXJJZCcsXG4gICAgICAgICdmZWUnLFxuICAgICAgICAnY2hhbmdlT3V0cHV0cycsXG4gICAgICAgICdjaGFuZ2VBbW91bnQnLFxuICAgICAgICAnb3BlcmF0aW9ucycsXG4gICAgICBdKTtcbiAgICAgIGV4cGxhaW5lZFR4LmZlZS5zaG91bGQuZXF1YWwoZXhwbGFpblR4UGFyYW1zLmZlZUluZm8pO1xuICAgICAgZXhwbGFpbmVkVHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuICAgICAgZXhwbGFpbmVkVHgub3BlcmF0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgZXhwbGFpbmVkVHgub3BlcmF0aW9uc1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKHR4SW5mby5hbW91bnQpO1xuICAgICAgZXhwbGFpbmVkVHgub3BlcmF0aW9uc1swXS52YWxpZGF0b3Iuc2hvdWxkLmVxdWFsKHR4SW5mby52YWxpZGF0b3IpO1xuICAgICAgZXhwbGFpbmVkVHgub3BlcmF0aW9uc1swXS5jb2luLnNob3VsZC5lcXVhbChiYXNlY29pbi5nZXRDaGFpbigpKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0udHlwZS5zaG91bGQuZXF1YWwodHhJbmZvLmRlcGxveVR5cGUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGEgc2lnbmVkIHVuZGVsZWdhdGUgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsdFR4SW5mbyA9IHtcbiAgICAgICAgdHhIZXg6IHNpZ25lZFJhd1VuZGVsZWdhdGVUeCxcbiAgICAgICAgdHhJbmZvOiB7XG4gICAgICAgICAgaGFzaDogJ2FlYWQyZTllOWE0M2UzZDU0NTkwOGUxYjk5NTYyOGNiOWMzN2U3MTJkNzQ2N2I2M2MwNTJmZTYzYmVkOGNmMTcnLFxuICAgICAgICAgIGZlZToge1xuICAgICAgICAgICAgZ2FzTGltaXQ6ICcxMDAwMDAwMDAnLFxuICAgICAgICAgICAgZ2FzUHJpY2U6ICcxJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZyb206ICcwMjAyY2M4Zjc4YzQxZDMzNGFkMmFhYWU2ZGE3YTg4NTM3Zjk2ODYyNDU3NjFhYWRkZjM2ZDRiMmRmYmY5MTNiYjg3MycsXG4gICAgICAgICAgZGVwbG95VHlwZTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2ssXG4gICAgICAgICAgYW1vdW50OiB1bmRlbGVnYXRlQW1vdW50LFxuICAgICAgICAgIHZhbGlkYXRvcjogJzAxMTVjOWI0MGMwNmZmOTliMGNiYWRmMTE0MGIwNjFiNWRiZjkyMTAzZTY2YTYzMzBmYmNjNzc2OGY1MjE5YzFjZScsXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICBnYXNMaW1pdDogJzEwMDAwMDAwMCcsXG4gICAgICAgICAgZ2FzUHJpY2U6ICcxJyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBjb25zdCBleHBsYWluVHhQYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMgPSBidWlsdFR4SW5mbztcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFR4ID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5UeFBhcmFtcyk7XG4gICAgICBleHBsYWluZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKFtcbiAgICAgICAgJ2Rpc3BsYXlPcmRlcicsXG4gICAgICAgICdpZCcsXG4gICAgICAgICdvdXRwdXRzJyxcbiAgICAgICAgJ291dHB1dEFtb3VudCcsXG4gICAgICAgICd0cmFuc2ZlcklkJyxcbiAgICAgICAgJ2ZlZScsXG4gICAgICAgICdjaGFuZ2VPdXRwdXRzJyxcbiAgICAgICAgJ2NoYW5nZUFtb3VudCcsXG4gICAgICAgICdvcGVyYXRpb25zJyxcbiAgICAgIF0pO1xuICAgICAgZXhwbGFpbmVkVHguZmVlLnNob3VsZC5lcXVhbChidWlsdFR4SW5mby5mZWVJbmZvKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0uYW1vdW50LnNob3VsZC5lcXVhbChidWlsdFR4SW5mby50eEluZm8uYW1vdW50KTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0udmFsaWRhdG9yLnNob3VsZC5lcXVhbChidWlsdFR4SW5mby50eEluZm8udmFsaWRhdG9yKTtcbiAgICAgIGV4cGxhaW5lZFR4Lm9wZXJhdGlvbnNbMF0uY29pbi5zaG91bGQuZXF1YWwoYmFzZWNvaW4uZ2V0Q2hhaW4oKSk7XG4gICAgICBleHBsYWluZWRUeC5vcGVyYXRpb25zWzBdLnR5cGUuc2hvdWxkLmVxdWFsKGJ1aWx0VHhJbmZvLnR4SW5mby5kZXBsb3lUeXBlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB3aGVuIGEgdHggaXMgbm90IHBhc3NlZCBhcyBwYXJhbWV0ZXInLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBleHBsYWluVHhQYXJhbXMgPSB7XG4gICAgICAgIGZlZToge1xuICAgICAgICAgIGdhc0xpbWl0OiAnMScsXG4gICAgICAgICAgZ2FzUHJpY2U6ICcxMTAwMCcsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5UeFBhcmFtcykuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyBleHBsYWluIHR4IHBhcmFtZXRlcnMnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1ZhbGlkYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHZhbGlkYXRlIGludmFsaWQgYWRkcmVzcyB3aXRoIHBheW1lbnQgaWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnZhbGlkQWRkcmVzc2VzID0gW1xuICAgICAgICAnMDIwM0RDMTNDQkJGMjk3NjVDNzc0NTU3OEQ5RTA5MTI4MDUyMkYzNzY4NEVGMEU0MDBCODZCMUM0MDlCQzQ1NEYxRjM/dHJhbnNmZXJJZD14JyxcbiAgICAgICAgJzAyMDNEQzEzQ0JCRjI5NzY1Qzc3NDU1NzhEOUUwOTEyODA1MjJGMzc2ODRFRjBFNDAwQjg2QjFDNDA5QkM0NTRGMUYzP21lbW9JZD0xJyxcbiAgICAgICAgJ1gwMjAzREMxM0NCQkYyOTc2NUM3NzQ1NTc4RDlFMDkxMjgwNTIyRjM3Njg0RUYwRTQwMEI4NkIxQzQwOUJDNDU0RjFGMz90cmFuc2ZlcklkPTEnLFxuICAgICAgXTtcblxuICAgICAgZm9yIChjb25zdCBhZGRyZXNzIG9mIGludmFsaWRBZGRyZXNzZXMpIHtcbiAgICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdygoKSA9PiBiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKSk7XG4gICAgICAgIGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpLnNob3VsZC5iZS5mYWxzZSgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhZGRyZXNzIHdpdGggcGF5bWVudCBpZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHZhbGlkQWRkcmVzc2VzID0gW1xuICAgICAgICAnMDIwM0RDMTNDQkJGMjk3NjVDNzc0NTU3OEQ5RTA5MTI4MDUyMkYzNzY4NEVGMEU0MDBCODZCMUM0MDlCQzQ1NEYxRjM/dHJhbnNmZXJJZD0wJyxcbiAgICAgICAgJzAyMDM4NUQ3MjRBOUEzRTdFMzJCQURGNDBGMzI3OUFGNUExOTBDQjJDRkNBQjY2MzlCRjUzMkEwMDY5RTBFMzgyNEQwP3RyYW5zZmVySWQ9MScsXG4gICAgICAgICcwMTUxM2ZhOTBjMWE3NGMzNGE4OTU4ZGQ4NjA1NWU5NzM2ZWRiMWVhZDkxOGJkNGQ0ZDc1MGNhODUxOTQ2YmU3YWE/dHJhbnNmZXJJZD05OTk5OTk5OTknLCAvLyBlZDI1NTE5XG4gICAgICBdO1xuXG4gICAgICBmb3IgKGNvbnN0IGFkZHJlc3Mgb2YgdmFsaWRBZGRyZXNzZXMpIHtcbiAgICAgICAgYmFzZWNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byB2ZXJpZnkgaW52YWxpZCBhZGRyZXNzIHdpdGggcGF5bWVudCBpZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGludmFsaWRBZGRyZXNzZXMgPSBbXG4gICAgICAgICcwMjAzREMxM0NCQkYyOTc2NUM3NzQ1NTc4RDlFMDkxMjgwNTIyRjM3Njg0RUYwRTQwMEI4NkIxQzQwOUJDNDU0RjFGMz90cmFuc2ZlcklkPXgnLFxuICAgICAgICAnMDIwM0RDMTNDQkJGMjk3NjVDNzc0NTU3OEQ5RTA5MTI4MDUyMkYzNzY4NEVGMEU0MDBCODZCMUM0MDlCQzQ1NEYxRjM/bWVtb0lkPTEnLFxuICAgICAgICAnWDAyMDNEQzEzQ0JCRjI5NzY1Qzc3NDU1NzhEOUUwOTEyODA1MjJGMzc2ODRFRjBFNDAwQjg2QjFDNDA5QkM0NTRGMUYzP3RyYW5zZmVySWQ9MScsXG4gICAgICBdO1xuXG4gICAgICBmb3IgKGNvbnN0IGFkZHJlc3Mgb2YgaW52YWxpZEFkZHJlc3Nlcykge1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBiYXNlY29pbi52ZXJpZnlBZGRyZXNzKGFkZHJlc3MpKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGFkZHJlc3Mgd2l0aCBwYXltZW50IGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgcm9vdEFkZHJlc3MgPSAnMDIwMjUwZmUyMTM3MDZlNDZhYWEzMmNiMjNmMDcwNTgzM2M2ZDNjZTc2NTJlOGU1YTEzNDlkZGUxMDJhYWRmMDE0YjcnO1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICc2MjRmMGRjYzkzY2JjYzAwMDhkODhkZjIzNjlhNTY1ZScsXG4gICAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0VlUmtCY2l1YVVmRjRDMWpnQmNuajJSWGRudDlnb2t4NENGUkJVcDRic2JrNWhYSEMxQnJCRFpMRE5lY1ZzVUNNbW9McFBoV2RQWmhQaVRzSFNveE5vR1ZXOUt0aUVRJyxcbiAgICAgICAgICBldGhBZGRyZXNzOiAnMHhjZmJmMzg3NzBhZjNhOTVkYTc5OTg1MzdhNDgxNDM0ZTJjYjliMmZhJyxcbiAgICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgIGVuY3J5cHRlZFBydjpcbiAgICAgICAgICAgICd7XCJpdlwiOlwiWjJYeVNUUk5pcEZaMDYvRVh5bnd2QT09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MjU2LFwidHNcIjo2NCxcIm1vZGVcIjpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIktHUlBiWjJqdDFnPVwiLFwiY3RcIjpcInN6cENiRExGSWxSWnZDQlY2MFNXQkVNWVh2bnk3WWxCdHU0ZmZqbGN0RFFHalI0Lyt2ZkNrb3ZnR0hzK1h2Zi9lSWxVTTNLaWN1YmcrU2RwNjFNSW1qTVQvdW1aM0lKVDFFMkk5bU0wUURxcHpYbG9oVEduSjR2Z2ZIZ0N6M1FrQjR1WW01bXFhRDRMdFJidlpiR2hHcmM1anpyTHpxUT1cIn0nLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICc2MjRmMGRjZDkzY2JjYzAwMDhkODhlMGZjNDI2MWEzOCcsXG4gICAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0dlcVpWRmdRZmNEOHpMb3hhWkw3eTRjVkFqaEU4eWJNVHB2YnBwUDZyYzIyYTY5QmdjTlZvNzR5TDhmV1B6Tk01dkFvekJFN2NoekdZb1BESk15SjM5RjJIZUFzR2NuJyxcbiAgICAgICAgICBldGhBZGRyZXNzOiAnMHhiZjM3ZjM5MjA4ZDc3ZTMyNTRiN2VmYmNhYjE0MzJiOWMzNTNlMzM3JyxcbiAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICAgICAgZW5jcnlwdGVkUHJ2OlxuICAgICAgICAgICAgJ3tcIml2XCI6XCJUOWdkSm5TQUVXRnNMWjRjZzlWQThnPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiRmFMbG5zM21QaUk9XCIsXCJjdFwiOlwiUVc1WnE5cUpvRHhEcks2MHpUQU02TGcrUzRLUDlGY0VuOUFIdzVVSXlha1NCbEQwWGpWVGx1WjlQbFRBQmpJbHA5Y1F2TWVmL1NIOEVtMWQ0YXNoMFBBQ29xQnoySXhQd2hXOWg2dXlRQmRxazk3aVBybk0yck9Rb2JzeTlwMElMSk0xMGZPZ0IrRUVGWVg1eVE1Z3lmRWNLMDYwai9RPVwifScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzYyNGYwZGNlMTA2MTBhMDAwN2ZjNTI4MjM1MzE4N2FlJyxcbiAgICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjRlZNQVlKZTUxc2dYYWlGTGVVYjF2NHUzQjYzQ2dCTk1tTWp0V0JvMzJBUzNidW5zQlVaTWRpMzdwem92dEVnNW1WZjZ3QktheVRZYXBHUVJ4eW1RamNtSGFWbVNQejgnLFxuICAgICAgICAgIGV0aEFkZHJlc3M6ICcweDc1Mjc3MjBiNTYzOGQyZjVlMmIyNzJiMjBmYzk2ZDIyMjM1MjhkMGUnLFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgICAgIGlzQml0R286IHRydWUsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCB2YWxpZEFkZHJlc3NlcyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwMjAyNTBmZTIxMzcwNmU0NmFhYTMyY2IyM2YwNzA1ODMzYzZkM2NlNzY1MmU4ZTVhMTM0OWRkZTEwMmFhZGYwMTRiNycsXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAyMDI1MEZFMjEzNzA2RTQ2QUFBMzJDQjIzRjA3MDU4MzNDNkQzQ0U3NjUyRThFNUExMzQ5RERFMTAyQUFERjAxNEI3P3RyYW5zZmVySWQ9MCcsXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAyMDI1MGZlMjEzNzA2ZTQ2YWFhMzJjYjIzZjA3MDU4MzNjNmQzY2U3NjUyZThlNWExMzQ5ZGRlMTAyYWFkZjAxNGI3P3RyYW5zZmVySWQ9NTU1NScsXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgZm9yIChjb25zdCBhZGRyZXNzUGFyYW1zIG9mIHZhbGlkQWRkcmVzc2VzKSB7XG4gICAgICAgIChhd2FpdCBiYXNlY29pbi52ZXJpZnlBZGRyZXNzKGFkZHJlc3NQYXJhbXMpKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNXYWxsZXRBZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gJzAyMDNkNGM2ZWQ0YTQwZjVhYTczNzFhNzNjNzlkZDIwOGE2NDZlYmM4YzlmNWM3ZmUwYjRjNzM4NDQzNjVmMGU2MmU1P3RyYW5zZmVySWQ9NCc7XG5cbiAgICBpdCgnc2hvdWxkIGJlIHZhbGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzczogJzAyMDNkNGM2ZWQ0YTQwZjVhYTczNzFhNzNjNzlkZDIwOGE2NDZlYmM4YzlmNWM3ZmUwYjRjNzM4NDQzNjVmMGU2MmU1P3RyYW5zZmVySWQ9NScsXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVzb2x2ZWRXaXRoKHRydWUpO1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzczogJzAyMDNkNGM2ZWQ0YTQwZjVhYTczNzFhNzNjNzlkZDIwOGE2NDZlYmM4YzlmNWM3ZmUwYjRjNzM4NDQzNjVmMGU2MmU1P3RyYW5zZmVySWQ9NTAwJyxcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZXNvbHZlZFdpdGgodHJ1ZSk7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAuaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgICBhZGRyZXNzOiAnMDIwM2Q0YzZlZDRhNDBmNWFhNzM3MWE3M2M3OWRkMjA4YTY0NmViYzhjOWY1YzdmZTBiNGM3Mzg0NDM2NWYwZTYyZTUnLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlc29sdmVkV2l0aCh0cnVlKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICAgIGFkZHJlc3M6ICcwMjAzZDRjNmVkNGE0MGY1YWE3MzcxYTczYzc5ZGQyMDhhNjQ2ZWJjOGM5ZjVjN2ZlMGI0YzczODQ0MzY1ZjBlNjJlNT90cmFuc2ZlcklkPTEnLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlc29sdmVkV2l0aCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgaW52YWxpZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICAgIGFkZHJlc3M6ICcwMjAzZDRjNmVkNGE0MGY1YWE3MzcxYTczYzc5ZGQyMDhhNjQ2ZWJjOGM5ZjVjN2ZlMGI0YzczODQ0MzY1ZjBlNjJlNicsXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWQoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==

Выполнить команду


Для локальной разработки. Не используйте в интернете!