PHP WebShell
Текущая директория: /opt/BitGoJS/modules/bitgo/dist/test/v2/unit/coins
Просмотр файла: abstractUtxoCoin.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const should = require("should");
const sinon = require("sinon");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_test_1 = require("@bitgo/sdk-test");
const bitgo_1 = require("../../../../src/bitgo");
describe('Abstract UTXO Coin:', () => {
describe('Parse Transaction:', () => {
const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
const coin = bitgo.coin('tbtc');
/*
* mock objects which get passed into parse transaction.
* These objects are structured to force parse transaction into a
* particular execution path for these tests.
*/
const verification = {
disableNetworking: true,
keychains: {
user: { id: '0', pub: 'aaa', type: 'independent' },
backup: { id: '1', pub: 'bbb', type: 'independent' },
bitgo: { id: '2', pub: 'ccc', type: 'independent' },
},
};
const wallet = sinon.createStubInstance(sdk_core_1.Wallet, {
migratedFrom: '2MzJxAENaesCFu3orrCdj22c69tLEsKXQoR',
});
const outputAmount = (0.01 * 1e8).toString();
async function runClassifyOutputsTest(outputAddress, verification, expectExternal, txParams = {}) {
sinon.stub(coin, 'explainTransaction').resolves({
outputs: [],
changeOutputs: [
{
address: outputAddress,
amount: outputAmount,
},
],
});
if (!txParams.changeAddress) {
sinon.stub(coin, 'verifyAddress').throws(new sdk_core_1.UnexpectedAddressError('test error'));
}
const parsedTransaction = await coin.parseTransaction({
txParams,
txPrebuild: { txHex: '' },
wallet: wallet,
verification,
});
should.exist(parsedTransaction.outputs[0]);
parsedTransaction.outputs[0].should.deepEqual({
address: outputAddress,
amount: outputAmount,
external: expectExternal,
});
const isExplicit = txParams.recipients !== undefined &&
txParams.recipients.some((recipient) => recipient.address === outputAddress);
should.equal(parsedTransaction.explicitExternalSpendAmount, isExplicit && expectExternal ? outputAmount : '0');
should.equal(parsedTransaction.implicitExternalSpendAmount, !isExplicit && expectExternal ? outputAmount : '0');
coin.explainTransaction.restore();
if (!txParams.changeAddress) {
coin.verifyAddress.restore();
}
}
it('should classify outputs which spend change back to a v1 wallet base address as internal', async function () {
return runClassifyOutputsTest(wallet.migratedFrom(), verification, false);
});
it('should classify outputs which spend change back to a v1 wallet base address as external ' +
'if considerMigratedFromAddressInternal is set and false', async function () {
return runClassifyOutputsTest(wallet.migratedFrom(), { ...verification, considerMigratedFromAddressInternal: false }, true);
});
it('should classify outputs which spend to addresses not on the wallet as external', async function () {
return runClassifyOutputsTest('2Mxjx4E2EEe4yJuLvdEuAdMUd4id1emPCZs', verification, true);
});
it('should accept a custom change address', async function () {
const changeAddress = '2NAuziD75WnPPHJVwnd4ckgY4SuJaDVVbMD';
return runClassifyOutputsTest(changeAddress, verification, false, { changeAddress, recipients: [] });
});
it('should classify outputs with external address in recipients as explicit', async function () {
const externalAddress = '2NAuziD75WnPPHJVwnd4ckgY4SuJaDVVbMD';
return runClassifyOutputsTest(externalAddress, verification, true, {
recipients: [{ address: externalAddress, amount: outputAmount }],
});
});
});
describe('Custom Change Wallets', () => {
const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
const coin = bitgo.coin('tbtc');
const keys = {
send: {
user: { id: '0', key: coin.keychains().create() },
backup: { id: '1', key: coin.keychains().create() },
bitgo: { id: '2', key: coin.keychains().create() },
},
change: {
user: { id: '3', key: coin.keychains().create() },
backup: { id: '4', key: coin.keychains().create() },
bitgo: { id: '5', key: coin.keychains().create() },
},
};
const customChangeKeySignatures = {
user: '',
backup: '',
bitgo: '',
};
const addressData = {
chain: 11,
index: 1,
addressType: 'p2shP2wsh',
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
keychains: [
{ pub: keys.change.user.key.pub },
{ pub: keys.change.backup.key.pub },
{ pub: keys.change.bitgo.key.pub },
],
threshold: 2,
};
const { address: changeAddress, coinSpecific } = coin.generateAddress(addressData);
const changeWalletId = 'changeWalletId';
const stubData = {
signedSendingWallet: {
keyIds: sinon.stub().returns([keys.send.user.id, keys.send.backup.id, keys.send.bitgo.id]),
coinSpecific: sinon.stub().returns({ customChangeWalletId: changeWalletId }),
},
changeWallet: {
keyIds: sinon.stub().returns([keys.change.user.id, keys.change.backup.id, keys.change.bitgo.id]),
createAddress: sinon.stub().resolves(changeAddress),
},
};
before(async () => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const sign = async ({ key }) => (await coin.signMessage({ prv: keys.send.user.key.prv }, key.pub)).toString('hex');
customChangeKeySignatures.user = await sign(keys.change.user);
customChangeKeySignatures.backup = await sign(keys.change.backup);
customChangeKeySignatures.bitgo = await sign(keys.change.bitgo);
});
it('should consider addresses derived from the custom change keys as internal spends', async () => {
const signedSendingWallet = sinon.createStubInstance(sdk_core_1.Wallet, stubData.signedSendingWallet);
const changeWallet = sinon.createStubInstance(sdk_core_1.Wallet, stubData.changeWallet);
sinon.stub(coin, 'keychains').returns({
get: sinon.stub().callsFake(({ id }) => {
switch (id) {
case keys.send.user.id:
return Promise.resolve({ id, ...keys.send.user.key });
case keys.send.backup.id:
return Promise.resolve({ id, ...keys.send.backup.key });
case keys.send.bitgo.id:
return Promise.resolve({ id, ...keys.send.bitgo.key });
case keys.change.user.id:
return Promise.resolve({ id, ...keys.change.user.key });
case keys.change.backup.id:
return Promise.resolve({ id, ...keys.change.backup.key });
case keys.change.bitgo.id:
return Promise.resolve({ id, ...keys.change.bitgo.key });
}
}),
});
sinon.stub(coin, 'wallets').returns({
get: sinon.stub().callsFake(() => Promise.resolve(changeWallet)),
});
const outputAmount = 10000;
const recipients = [];
sinon.stub(coin, 'explainTransaction').resolves({
outputs: [],
changeOutputs: [
{
address: changeAddress,
amount: outputAmount,
},
],
});
signedSendingWallet._wallet = signedSendingWallet._wallet || { customChangeKeySignatures };
const parsedTransaction = await coin.parseTransaction({
txParams: { changeAddress, recipients },
txPrebuild: { txHex: '' },
wallet: signedSendingWallet,
verification: {
addresses: {
[changeAddress]: {
coinSpecific,
chain: addressData.chain,
index: addressData.index,
},
},
},
});
should.exist(parsedTransaction.outputs[0]);
parsedTransaction.outputs[0].should.deepEqual({
address: changeAddress,
amount: outputAmount,
external: false,
needsCustomChangeKeySignatureVerification: true,
});
coin.explainTransaction.restore();
coin.wallets.restore();
coin.keychains.restore();
});
});
describe('Verify Transaction', () => {
const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
const coin = bitgo.coin('tbtc');
const userKeychain = coin.keychains().create();
const otherKeychain = coin.keychains().create();
const changeKeys = {
user: coin.keychains().create(),
backup: coin.keychains().create(),
bitgo: coin.keychains().create(),
};
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const sign = async (key, keychain) => (await coin.signMessage(keychain, key.pub)).toString('hex');
const signUser = (key) => sign(key, userKeychain);
const signOther = (key) => sign(key, otherKeychain);
const passphrase = 'test_passphrase';
const stubData = {
unsignedSendingWallet: {
keyIds: sinon.stub().returns(['0', '1', '2']),
},
parseTransactionData: {
badKey: {
keychains: {
// user public key swapped out
user: {
pub: otherKeychain.pub,
encryptedPrv: bitgo.encrypt({ input: userKeychain.prv, password: passphrase }),
},
},
needsCustomChangeKeySignatureVerification: true,
},
noCustomChange: {
keychains: { user: userKeychain },
needsCustomChangeKeySignatureVerification: true,
},
emptyCustomChange: {
keychains: { user: userKeychain },
needsCustomChangeKeySignatureVerification: true,
customChange: {},
},
// needs to be async function to create signatures
badSigs: async () => ({
keychains: { user: userKeychain },
needsCustomChangeKeySignatureVerification: true,
customChange: {
keys: [changeKeys.user, changeKeys.backup, changeKeys.bitgo],
signatures: [
await signOther(changeKeys.user),
await signOther(changeKeys.backup),
await signOther(changeKeys.bitgo),
],
},
}),
goodSigs: async () => ({
keychains: { user: userKeychain },
needsCustomChangeKeySignatureVerification: true,
customChange: {
keys: [changeKeys.user, changeKeys.backup, changeKeys.bitgo],
signatures: [
await signUser(changeKeys.user),
await signUser(changeKeys.backup),
await signUser(changeKeys.bitgo),
],
},
missingOutputs: 1,
}),
},
};
const unsignedSendingWallet = sinon.createStubInstance(sdk_core_1.Wallet, stubData.unsignedSendingWallet);
it('should fail if the user private key cannot be verified to match the user public key', async () => {
sinon.stub(coin, 'parseTransaction').resolves(stubData.parseTransactionData.badKey);
const verifyWallet = sinon.createStubInstance(sdk_core_1.Wallet, {});
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {},
wallet: verifyWallet,
verification: {},
})
.should.be.rejectedWith(/transaction requires verification of user public key, but it was unable to be verified/);
coin.parseTransaction.restore();
});
it('should fail if the custom change verification data is required but missing', async () => {
sinon.stub(coin, 'parseTransaction').resolves(stubData.parseTransactionData.noCustomChange);
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {},
wallet: unsignedSendingWallet,
verification: {},
})
.should.be.rejectedWith(/parsed transaction is missing required custom change verification data/);
coin.parseTransaction.restore();
});
it('should fail if the custom change keys or key signatures are missing', async () => {
sinon.stub(coin, 'parseTransaction').resolves(stubData.parseTransactionData.emptyCustomChange);
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {},
wallet: unsignedSendingWallet,
verification: {},
})
.should.be.rejectedWith(/customChange property is missing keys or signatures/);
coin.parseTransaction.restore();
});
it('should fail if the custom change key signatures cannot be verified', async () => {
sinon.stub(coin, 'parseTransaction').resolves((await stubData.parseTransactionData.badSigs()));
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {},
wallet: unsignedSendingWallet,
verification: {},
})
.should.be.rejectedWith(/transaction requires verification of custom change key signatures, but they were unable to be verified/);
coin.parseTransaction.restore();
});
it('should successfully verify a custom change transaction when change keys and signatures are valid', async () => {
sinon.stub(coin, 'parseTransaction').resolves((await stubData.parseTransactionData.goodSigs()));
// if verify transaction gets rejected with the outputs missing error message,
// then we know that the verification of the custom change key signatures was successful
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {},
wallet: unsignedSendingWallet,
verification: {},
})
.should.be.rejectedWith(/expected outputs missing in transaction prebuild/);
coin.parseTransaction.restore();
});
it('should not allow more than 150 basis points of implicit external outputs (for paygo outputs)', async () => {
const coinMock = sinon.stub(coin, 'parseTransaction').resolves({
keychains: {},
keySignatures: {},
outputs: [],
missingOutputs: [],
explicitExternalOutputs: [],
implicitExternalOutputs: [],
changeOutputs: [],
explicitExternalSpendAmount: 10000,
implicitExternalSpendAmount: 151,
needsCustomChangeKeySignatureVerification: false,
});
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {},
wallet: unsignedSendingWallet,
})
.should.be.rejectedWith('prebuild attempts to spend to unintended external recipients');
coinMock.restore();
});
it('should allow 150 basis points of implicit external outputs (for paygo outputs)', async () => {
const coinMock = sinon.stub(coin, 'parseTransaction').resolves({
keychains: {},
keySignatures: {},
outputs: [],
missingOutputs: [],
explicitExternalOutputs: [],
implicitExternalOutputs: [],
changeOutputs: [],
explicitExternalSpendAmount: 1000,
implicitExternalSpendAmount: 15,
needsCustomChangeKeySignatureVerification: false,
});
const bitcoinMock = sinon
.stub(coin, 'createTransactionFromHex')
.returns({ ins: [] });
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {
txHex: '00',
},
wallet: unsignedSendingWallet,
})
.should.eventually.be.true();
coinMock.restore();
bitcoinMock.restore();
});
it('should not allow any implicit external outputs if paygo outputs are disallowed', async () => {
const coinMock = sinon.stub(coin, 'parseTransaction').resolves({
keychains: {},
keySignatures: {},
outputs: [],
missingOutputs: [],
explicitExternalOutputs: [],
implicitExternalOutputs: [],
changeOutputs: [],
explicitExternalSpendAmount: 0,
implicitExternalSpendAmount: 10,
needsCustomChangeKeySignatureVerification: false,
});
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {
txHex: '00',
},
wallet: unsignedSendingWallet,
verification: {
allowPaygoOutput: false,
},
})
.should.be.rejectedWith('prebuild attempts to spend to unintended external recipients');
coinMock.restore();
});
it('should allow paygo outputs if empty verification object is passed', async () => {
const coinMock = sinon.stub(coin, 'parseTransaction').resolves({
keychains: {},
keySignatures: {},
outputs: [],
missingOutputs: [],
explicitExternalOutputs: [],
implicitExternalOutputs: [],
changeOutputs: [],
explicitExternalSpendAmount: 1000,
implicitExternalSpendAmount: 15,
needsCustomChangeKeySignatureVerification: false,
});
const bitcoinMock = sinon
.stub(coin, 'createTransactionFromHex')
.returns({ ins: [] });
await coin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {
txHex: '00',
},
wallet: unsignedSendingWallet,
verification: {},
})
.should.eventually.be.true();
coinMock.restore();
bitcoinMock.restore();
});
it('should work with bigint amounts', async () => {
// need a coin that uses bigint
const bigintCoin = bitgo.coin('tdoge');
const coinMock = sinon.stub(bigintCoin, 'parseTransaction').resolves({
keychains: {},
keySignatures: {},
outputs: [],
missingOutputs: [],
explicitExternalOutputs: [
{
address: 'external_address',
amount: '10000',
},
],
implicitExternalOutputs: [
{
address: 'external_address_2',
amount: '15',
},
],
changeOutputs: [],
explicitExternalSpendAmount: BigInt(10000),
implicitExternalSpendAmount: BigInt(15),
needsCustomChangeKeySignatureVerification: false,
});
const bitcoinMock = sinon
.stub(bigintCoin, 'createTransactionFromHex')
.returns({ ins: [] });
await bigintCoin
.verifyTransaction({
txParams: {
walletPassphrase: passphrase,
},
txPrebuild: {
txHex: '00',
},
wallet: unsignedSendingWallet,
verification: {},
})
.should.eventually.be.true();
coinMock.restore();
bitcoinMock.restore();
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3RVdHhvQ29pbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdjIvdW5pdC9jb2lucy9hYnN0cmFjdFV0eG9Db2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0EsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQiw4Q0FBc0Y7QUFDdEYsOENBQTRDO0FBQzVDLGlEQUE4QztBQUc5QyxRQUFRLENBQUMscUJBQXFCLEVBQUUsR0FBRyxFQUFFO0lBQ25DLFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7UUFDbEMsTUFBTSxLQUFLLEdBQVUsb0JBQVMsQ0FBQyxRQUFRLENBQUMsYUFBSyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDaEUsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQXFCLENBQUM7UUFFcEQ7Ozs7V0FJRztRQUNILE1BQU0sWUFBWSxHQUF3QjtZQUN4QyxpQkFBaUIsRUFBRSxJQUFJO1lBQ3ZCLFNBQVMsRUFBRTtnQkFDVCxJQUFJLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRTtnQkFDbEQsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUU7Z0JBQ3BELEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFO2FBQ3BEO1NBQ0YsQ0FBQztRQUVGLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxpQkFBTSxFQUFFO1lBQzlDLFlBQVksRUFBRSxxQ0FBcUM7U0FDcEQsQ0FBQyxDQUFDO1FBRUgsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFJLEdBQUcsR0FB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RTtvQkFDUixnQkFBZ0IsRUFBRSxVQUFVO2lCQUM3QjtnQkFDRCxVQUFVLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLElBQUk7aUJBQ1o7Z0JBQ0QsTUFBTSxFQUFFLHFCQUE0QjtnQkFDcEMsWUFBWSxFQUFFLEVBQUU7YUFDakIsQ0FBQztpQkFDRCxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUUvQixRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbkIsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3hCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHV0eG9saWIgZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgV2FsbGV0LCBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yLCBWZXJpZmljYXRpb25PcHRpb25zIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IFRlc3RCaXRHbyB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uLy4uLy4uL3NyYy9iaXRnbyc7XG5pbXBvcnQgeyBBYnN0cmFjdFV0eG9Db2luLCBVdHhvV2FsbGV0LCBPdXRwdXQsIFRyYW5zYWN0aW9uRXhwbGFuYXRpb24sIFRyYW5zYWN0aW9uUGFyYW1zIH0gZnJvbSAnQGJpdGdvL2Fic3RyYWN0LXV0eG8nO1xuXG5kZXNjcmliZSgnQWJzdHJhY3QgVVRYTyBDb2luOicsICgpID0+IHtcbiAgZGVzY3JpYmUoJ1BhcnNlIFRyYW5zYWN0aW9uOicsICgpID0+IHtcbiAgICBjb25zdCBiaXRnbzogQml0R28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RidGMnKSBhcyBBYnN0cmFjdFV0eG9Db2luO1xuXG4gICAgLypcbiAgICAgKiBtb2NrIG9iamVjdHMgd2hpY2ggZ2V0IHBhc3NlZCBpbnRvIHBhcnNlIHRyYW5zYWN0aW9uLlxuICAgICAqIFRoZXNlIG9iamVjdHMgYXJlIHN0cnVjdHVyZWQgdG8gZm9yY2UgcGFyc2UgdHJhbnNhY3Rpb24gaW50byBhXG4gICAgICogcGFydGljdWxhciBleGVjdXRpb24gcGF0aCBmb3IgdGhlc2UgdGVzdHMuXG4gICAgICovXG4gICAgY29uc3QgdmVyaWZpY2F0aW9uOiBWZXJpZmljYXRpb25PcHRpb25zID0ge1xuICAgICAgZGlzYWJsZU5ldHdvcmtpbmc6IHRydWUsXG4gICAgICBrZXljaGFpbnM6IHtcbiAgICAgICAgdXNlcjogeyBpZDogJzAnLCBwdWI6ICdhYWEnLCB0eXBlOiAnaW5kZXBlbmRlbnQnIH0sXG4gICAgICAgIGJhY2t1cDogeyBpZDogJzEnLCBwdWI6ICdiYmInLCB0eXBlOiAnaW5kZXBlbmRlbnQnIH0sXG4gICAgICAgIGJpdGdvOiB7IGlkOiAnMicsIHB1YjogJ2NjYycsIHR5cGU6ICdpbmRlcGVuZGVudCcgfSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGNvbnN0IHdhbGxldCA9IHNpbm9uLmNyZWF0ZVN0dWJJbnN0YW5jZShXYWxsZXQsIHtcbiAgICAgIG1pZ3JhdGVkRnJvbTogJzJNekp4QUVOYWVzQ0Z1M29yckNkajIyYzY5dExFc0tYUW9SJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IG91dHB1dEFtb3VudCA9ICgwLjAxICogMWU4KS50b1N0cmluZygpO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gcnVuQ2xhc3NpZnlPdXRwdXRzVGVzdChcbiAgICAgIG91dHB1dEFkZHJlc3MsXG4gICAgICB2ZXJpZmljYXRpb24sXG4gICAgICBleHBlY3RFeHRlcm5hbCxcbiAgICAgIHR4UGFyYW1zOiBUcmFuc2FjdGlvblBhcmFtcyA9IHt9XG4gICAgKSB7XG4gICAgICBzaW5vbi5zdHViKGNvaW4sICdleHBsYWluVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh7XG4gICAgICAgIG91dHB1dHM6IFtdIGFzIE91dHB1dFtdLFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogb3V0cHV0QWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogb3V0cHV0QW1vdW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9IGFzIFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pO1xuXG4gICAgICBpZiAoIXR4UGFyYW1zLmNoYW5nZUFkZHJlc3MpIHtcbiAgICAgICAgc2lub24uc3R1Yihjb2luLCAndmVyaWZ5QWRkcmVzcycpLnRocm93cyhuZXcgVW5leHBlY3RlZEFkZHJlc3NFcnJvcigndGVzdCBlcnJvcicpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGFyc2VkVHJhbnNhY3Rpb24gPSBhd2FpdCBjb2luLnBhcnNlVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleDogJycgfSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQgYXMgdW5rbm93biBhcyBVdHhvV2FsbGV0LFxuICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICB9KTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZFRyYW5zYWN0aW9uLm91dHB1dHNbMF0pO1xuICAgICAgcGFyc2VkVHJhbnNhY3Rpb24ub3V0cHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogb3V0cHV0QWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiBvdXRwdXRBbW91bnQsXG4gICAgICAgIGV4dGVybmFsOiBleHBlY3RFeHRlcm5hbCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpc0V4cGxpY2l0ID1cbiAgICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMuc29tZSgocmVjaXBpZW50KSA9PiByZWNpcGllbnQuYWRkcmVzcyA9PT0gb3V0cHV0QWRkcmVzcyk7XG4gICAgICBzaG91bGQuZXF1YWwocGFyc2VkVHJhbnNhY3Rpb24uZXhwbGljaXRFeHRlcm5hbFNwZW5kQW1vdW50LCBpc0V4cGxpY2l0ICYmIGV4cGVjdEV4dGVybmFsID8gb3V0cHV0QW1vdW50IDogJzAnKTtcbiAgICAgIHNob3VsZC5lcXVhbChwYXJzZWRUcmFuc2FjdGlvbi5pbXBsaWNpdEV4dGVybmFsU3BlbmRBbW91bnQsICFpc0V4cGxpY2l0ICYmIGV4cGVjdEV4dGVybmFsID8gb3V0cHV0QW1vdW50IDogJzAnKTtcblxuICAgICAgKGNvaW4uZXhwbGFpblRyYW5zYWN0aW9uIGFzIGFueSkucmVzdG9yZSgpO1xuXG4gICAgICBpZiAoIXR4UGFyYW1zLmNoYW5nZUFkZHJlc3MpIHtcbiAgICAgICAgKGNvaW4udmVyaWZ5QWRkcmVzcyBhcyBhbnkpLnJlc3RvcmUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpdCgnc2hvdWxkIGNsYXNzaWZ5IG91dHB1dHMgd2hpY2ggc3BlbmQgY2hhbmdlIGJhY2sgdG8gYSB2MSB3YWxsZXQgYmFzZSBhZGRyZXNzIGFzIGludGVybmFsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHJ1bkNsYXNzaWZ5T3V0cHV0c1Rlc3Qod2FsbGV0Lm1pZ3JhdGVkRnJvbSgpLCB2ZXJpZmljYXRpb24sIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KFxuICAgICAgJ3Nob3VsZCBjbGFzc2lmeSBvdXRwdXRzIHdoaWNoIHNwZW5kIGNoYW5nZSBiYWNrIHRvIGEgdjEgd2FsbGV0IGJhc2UgYWRkcmVzcyBhcyBleHRlcm5hbCAnICtcbiAgICAgICAgJ2lmIGNvbnNpZGVyTWlncmF0ZWRGcm9tQWRkcmVzc0ludGVybmFsIGlzIHNldCBhbmQgZmFsc2UnLFxuICAgICAgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcnVuQ2xhc3NpZnlPdXRwdXRzVGVzdChcbiAgICAgICAgICB3YWxsZXQubWlncmF0ZWRGcm9tKCksXG4gICAgICAgICAgeyAuLi52ZXJpZmljYXRpb24sIGNvbnNpZGVyTWlncmF0ZWRGcm9tQWRkcmVzc0ludGVybmFsOiBmYWxzZSB9LFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgaXQoJ3Nob3VsZCBjbGFzc2lmeSBvdXRwdXRzIHdoaWNoIHNwZW5kIHRvIGFkZHJlc3NlcyBub3Qgb24gdGhlIHdhbGxldCBhcyBleHRlcm5hbCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBydW5DbGFzc2lmeU91dHB1dHNUZXN0KCcyTXhqeDRFMkVFZTR5SnVMdmRFdUFkTVVkNGlkMWVtUENacycsIHZlcmlmaWNhdGlvbiwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFjY2VwdCBhIGN1c3RvbSBjaGFuZ2UgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNoYW5nZUFkZHJlc3MgPSAnMk5BdXppRDc1V25QUEhKVnduZDRja2dZNFN1SmFEVlZiTUQnO1xuICAgICAgcmV0dXJuIHJ1bkNsYXNzaWZ5T3V0cHV0c1Rlc3QoY2hhbmdlQWRkcmVzcywgdmVyaWZpY2F0aW9uLCBmYWxzZSwgeyBjaGFuZ2VBZGRyZXNzLCByZWNpcGllbnRzOiBbXSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2xhc3NpZnkgb3V0cHV0cyB3aXRoIGV4dGVybmFsIGFkZHJlc3MgaW4gcmVjaXBpZW50cyBhcyBleHBsaWNpdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4dGVybmFsQWRkcmVzcyA9ICcyTkF1emlENzVXblBQSEpWd25kNGNrZ1k0U3VKYURWVmJNRCc7XG4gICAgICByZXR1cm4gcnVuQ2xhc3NpZnlPdXRwdXRzVGVzdChleHRlcm5hbEFkZHJlc3MsIHZlcmlmaWNhdGlvbiwgdHJ1ZSwge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBleHRlcm5hbEFkZHJlc3MsIGFtb3VudDogb3V0cHV0QW1vdW50IH1dLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdDdXN0b20gQ2hhbmdlIFdhbGxldHMnLCAoKSA9PiB7XG4gICAgY29uc3QgYml0Z286IEJpdEdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0YnRjJykgYXMgQWJzdHJhY3RVdHhvQ29pbjtcblxuICAgIGNvbnN0IGtleXMgPSB7XG4gICAgICBzZW5kOiB7XG4gICAgICAgIHVzZXI6IHsgaWQ6ICcwJywga2V5OiBjb2luLmtleWNoYWlucygpLmNyZWF0ZSgpIH0sXG4gICAgICAgIGJhY2t1cDogeyBpZDogJzEnLCBrZXk6IGNvaW4ua2V5Y2hhaW5zKCkuY3JlYXRlKCkgfSxcbiAgICAgICAgYml0Z286IHsgaWQ6ICcyJywga2V5OiBjb2luLmtleWNoYWlucygpLmNyZWF0ZSgpIH0sXG4gICAgICB9LFxuICAgICAgY2hhbmdlOiB7XG4gICAgICAgIHVzZXI6IHsgaWQ6ICczJywga2V5OiBjb2luLmtleWNoYWlucygpLmNyZWF0ZSgpIH0sXG4gICAgICAgIGJhY2t1cDogeyBpZDogJzQnLCBrZXk6IGNvaW4ua2V5Y2hhaW5zKCkuY3JlYXRlKCkgfSxcbiAgICAgICAgYml0Z286IHsgaWQ6ICc1Jywga2V5OiBjb2luLmtleWNoYWlucygpLmNyZWF0ZSgpIH0sXG4gICAgICB9LFxuICAgIH07XG5cbiAgICBjb25zdCBjdXN0b21DaGFuZ2VLZXlTaWduYXR1cmVzID0ge1xuICAgICAgdXNlcjogJycsXG4gICAgICBiYWNrdXA6ICcnLFxuICAgICAgYml0Z286ICcnLFxuICAgIH07XG5cbiAgICBjb25zdCBhZGRyZXNzRGF0YSA9IHtcbiAgICAgIGNoYWluOiAxMSxcbiAgICAgIGluZGV4OiAxLFxuICAgICAgYWRkcmVzc1R5cGU6ICdwMnNoUDJ3c2gnIGFzIGNvbnN0LFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgIGtleWNoYWluczogW1xuICAgICAgICB7IHB1Yjoga2V5cy5jaGFuZ2UudXNlci5rZXkucHViISB9LFxuICAgICAgICB7IHB1Yjoga2V5cy5jaGFuZ2UuYmFja3VwLmtleS5wdWIhIH0sXG4gICAgICAgIHsgcHViOiBrZXlzLmNoYW5nZS5iaXRnby5rZXkucHViISB9LFxuICAgICAgXSxcbiAgICAgIHRocmVzaG9sZDogMixcbiAgICB9O1xuXG4gICAgY29uc3QgeyBhZGRyZXNzOiBjaGFuZ2VBZGRyZXNzLCBjb2luU3BlY2lmaWMgfSA9IGNvaW4uZ2VuZXJhdGVBZGRyZXNzKGFkZHJlc3NEYXRhKTtcblxuICAgIGNvbnN0IGNoYW5nZVdhbGxldElkID0gJ2NoYW5nZVdhbGxldElkJztcbiAgICBjb25zdCBzdHViRGF0YSA9IHtcbiAgICAgIHNpZ25lZFNlbmRpbmdXYWxsZXQ6IHtcbiAgICAgICAga2V5SWRzOiBzaW5vbi5zdHViKCkucmV0dXJucyhba2V5cy5zZW5kLnVzZXIuaWQsIGtleXMuc2VuZC5iYWNrdXAuaWQsIGtleXMuc2VuZC5iaXRnby5pZF0pLFxuICAgICAgICBjb2luU3BlY2lmaWM6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKHsgY3VzdG9tQ2hhbmdlV2FsbGV0SWQ6IGNoYW5nZVdhbGxldElkIH0pLFxuICAgICAgfSxcbiAgICAgIGNoYW5nZVdhbGxldDoge1xuICAgICAgICBrZXlJZHM6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKFtrZXlzLmNoYW5nZS51c2VyLmlkLCBrZXlzLmNoYW5nZS5iYWNrdXAuaWQsIGtleXMuY2hhbmdlLmJpdGdvLmlkXSksXG4gICAgICAgIGNyZWF0ZUFkZHJlc3M6IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyhjaGFuZ2VBZGRyZXNzKSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGJlZm9yZShhc3luYyAoKSA9PiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3Qgc2lnbiA9IGFzeW5jICh7IGtleSB9KSA9PlxuICAgICAgICAoYXdhaXQgY29pbi5zaWduTWVzc2FnZSh7IHBydjoga2V5cy5zZW5kLnVzZXIua2V5LnBydiB9LCBrZXkucHViISkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGN1c3RvbUNoYW5nZUtleVNpZ25hdHVyZXMudXNlciA9IGF3YWl0IHNpZ24oa2V5cy5jaGFuZ2UudXNlcik7XG4gICAgICBjdXN0b21DaGFuZ2VLZXlTaWduYXR1cmVzLmJhY2t1cCA9IGF3YWl0IHNpZ24oa2V5cy5jaGFuZ2UuYmFja3VwKTtcbiAgICAgIGN1c3RvbUNoYW5nZUtleVNpZ25hdHVyZXMuYml0Z28gPSBhd2FpdCBzaWduKGtleXMuY2hhbmdlLmJpdGdvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY29uc2lkZXIgYWRkcmVzc2VzIGRlcml2ZWQgZnJvbSB0aGUgY3VzdG9tIGNoYW5nZSBrZXlzIGFzIGludGVybmFsIHNwZW5kcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNpZ25lZFNlbmRpbmdXYWxsZXQgPSBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UoV2FsbGV0LCBzdHViRGF0YS5zaWduZWRTZW5kaW5nV2FsbGV0IGFzIGFueSk7XG4gICAgICBjb25zdCBjaGFuZ2VXYWxsZXQgPSBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UoV2FsbGV0LCBzdHViRGF0YS5jaGFuZ2VXYWxsZXQgYXMgYW55KTtcblxuICAgICAgc2lub24uc3R1Yihjb2luLCAna2V5Y2hhaW5zJykucmV0dXJucyh7XG4gICAgICAgIGdldDogc2lub24uc3R1YigpLmNhbGxzRmFrZSgoeyBpZCB9KSA9PiB7XG4gICAgICAgICAgc3dpdGNoIChpZCkge1xuICAgICAgICAgICAgY2FzZSBrZXlzLnNlbmQudXNlci5pZDpcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGlkLCAuLi5rZXlzLnNlbmQudXNlci5rZXkgfSk7XG4gICAgICAgICAgICBjYXNlIGtleXMuc2VuZC5iYWNrdXAuaWQ6XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBpZCwgLi4ua2V5cy5zZW5kLmJhY2t1cC5rZXkgfSk7XG4gICAgICAgICAgICBjYXNlIGtleXMuc2VuZC5iaXRnby5pZDpcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGlkLCAuLi5rZXlzLnNlbmQuYml0Z28ua2V5IH0pO1xuICAgICAgICAgICAgY2FzZSBrZXlzLmNoYW5nZS51c2VyLmlkOlxuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgaWQsIC4uLmtleXMuY2hhbmdlLnVzZXIua2V5IH0pO1xuICAgICAgICAgICAgY2FzZSBrZXlzLmNoYW5nZS5iYWNrdXAuaWQ6XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBpZCwgLi4ua2V5cy5jaGFuZ2UuYmFja3VwLmtleSB9KTtcbiAgICAgICAgICAgIGNhc2Uga2V5cy5jaGFuZ2UuYml0Z28uaWQ6XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBpZCwgLi4ua2V5cy5jaGFuZ2UuYml0Z28ua2V5IH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICB9IGFzIGFueSk7XG5cbiAgICAgIHNpbm9uLnN0dWIoY29pbiwgJ3dhbGxldHMnKS5yZXR1cm5zKHtcbiAgICAgICAgZ2V0OiBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKCgpID0+IFByb21pc2UucmVzb2x2ZShjaGFuZ2VXYWxsZXQpKSxcbiAgICAgIH0gYXMgYW55KTtcblxuICAgICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gMTAwMDA7XG4gICAgICBjb25zdCByZWNpcGllbnRzID0gW107XG5cbiAgICAgIHNpbm9uLnN0dWIoY29pbiwgJ2V4cGxhaW5UcmFuc2FjdGlvbicpLnJlc29sdmVzKHtcbiAgICAgICAgb3V0cHV0czogW10sXG4gICAgICAgIGNoYW5nZU91dHB1dHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiBjaGFuZ2VBZGRyZXNzLFxuICAgICAgICAgICAgYW1vdW50OiBvdXRwdXRBbW91bnQsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0gYXMgYW55KTtcblxuICAgICAgc2lnbmVkU2VuZGluZ1dhbGxldC5fd2FsbGV0ID0gc2lnbmVkU2VuZGluZ1dhbGxldC5fd2FsbGV0IHx8IHsgY3VzdG9tQ2hhbmdlS2V5U2lnbmF0dXJlcyB9O1xuXG4gICAgICBjb25zdCBwYXJzZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGNvaW4ucGFyc2VUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7IGNoYW5nZUFkZHJlc3MsIHJlY2lwaWVudHMgfSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleDogJycgfSxcbiAgICAgICAgd2FsbGV0OiBzaWduZWRTZW5kaW5nV2FsbGV0IGFzIGFueSxcbiAgICAgICAgdmVyaWZpY2F0aW9uOiB7XG4gICAgICAgICAgYWRkcmVzc2VzOiB7XG4gICAgICAgICAgICBbY2hhbmdlQWRkcmVzc106IHtcbiAgICAgICAgICAgICAgY29pblNwZWNpZmljLFxuICAgICAgICAgICAgICBjaGFpbjogYWRkcmVzc0RhdGEuY2hhaW4sXG4gICAgICAgICAgICAgIGluZGV4OiBhZGRyZXNzRGF0YS5pbmRleCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkVHJhbnNhY3Rpb24ub3V0cHV0c1swXSk7XG4gICAgICBwYXJzZWRUcmFuc2FjdGlvbi5vdXRwdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiBjaGFuZ2VBZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IG91dHB1dEFtb3VudCxcbiAgICAgICAgZXh0ZXJuYWw6IGZhbHNlLFxuICAgICAgICBuZWVkc0N1c3RvbUNoYW5nZUtleVNpZ25hdHVyZVZlcmlmaWNhdGlvbjogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICAoY29pbi5leHBsYWluVHJhbnNhY3Rpb24gYXMgYW55KS5yZXN0b3JlKCk7XG4gICAgICAoY29pbi53YWxsZXRzIGFzIGFueSkucmVzdG9yZSgpO1xuICAgICAgKGNvaW4ua2V5Y2hhaW5zIGFzIGFueSkucmVzdG9yZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IFRyYW5zYWN0aW9uJywgKCkgPT4ge1xuICAgIGNvbnN0IGJpdGdvOiBCaXRHbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndGJ0YycpIGFzIEFic3RyYWN0VXR4b0NvaW47XG5cbiAgICBjb25zdCB1c2VyS2V5Y2hhaW4gPSBjb2luLmtleWNoYWlucygpLmNyZWF0ZSgpO1xuICAgIGNvbnN0IG90aGVyS2V5Y2hhaW4gPSBjb2luLmtleWNoYWlucygpLmNyZWF0ZSgpO1xuXG4gICAgY29uc3QgY2hhbmdlS2V5cyA9IHtcbiAgICAgIHVzZXI6IGNvaW4ua2V5Y2hhaW5zKCkuY3JlYXRlKCksXG4gICAgICBiYWNrdXA6IGNvaW4ua2V5Y2hhaW5zKCkuY3JlYXRlKCksXG4gICAgICBiaXRnbzogY29pbi5rZXljaGFpbnMoKS5jcmVhdGUoKSxcbiAgICB9O1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICBjb25zdCBzaWduID0gYXN5bmMgKGtleSwga2V5Y2hhaW4pID0+IChhd2FpdCBjb2luLnNpZ25NZXNzYWdlKGtleWNoYWluLCBrZXkucHViISkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBzaWduVXNlciA9IChrZXkpID0+IHNpZ24oa2V5LCB1c2VyS2V5Y2hhaW4pO1xuICAgIGNvbnN0IHNpZ25PdGhlciA9IChrZXkpID0+IHNpZ24oa2V5LCBvdGhlcktleWNoYWluKTtcbiAgICBjb25zdCBwYXNzcGhyYXNlID0gJ3Rlc3RfcGFzc3BocmFzZSc7XG5cbiAgICBjb25zdCBzdHViRGF0YSA9IHtcbiAgICAgIHVuc2lnbmVkU2VuZGluZ1dhbGxldDoge1xuICAgICAgICBrZXlJZHM6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKFsnMCcsICcxJywgJzInXSksXG4gICAgICB9LFxuICAgICAgcGFyc2VUcmFuc2FjdGlvbkRhdGE6IHtcbiAgICAgICAgYmFkS2V5OiB7XG4gICAgICAgICAga2V5Y2hhaW5zOiB7XG4gICAgICAgICAgICAvLyB1c2VyIHB1YmxpYyBrZXkgc3dhcHBlZCBvdXRcbiAgICAgICAgICAgIHVzZXI6IHtcbiAgICAgICAgICAgICAgcHViOiBvdGhlcktleWNoYWluLnB1YixcbiAgICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6IHVzZXJLZXljaGFpbi5wcnYsIHBhc3N3b3JkOiBwYXNzcGhyYXNlIH0pLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIG5lZWRzQ3VzdG9tQ2hhbmdlS2V5U2lnbmF0dXJlVmVyaWZpY2F0aW9uOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBub0N1c3RvbUNoYW5nZToge1xuICAgICAgICAgIGtleWNoYWluczogeyB1c2VyOiB1c2VyS2V5Y2hhaW4gfSxcbiAgICAgICAgICBuZWVkc0N1c3RvbUNoYW5nZUtleVNpZ25hdHVyZVZlcmlmaWNhdGlvbjogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgZW1wdHlDdXN0b21DaGFuZ2U6IHtcbiAgICAgICAgICBrZXljaGFpbnM6IHsgdXNlcjogdXNlcktleWNoYWluIH0sXG4gICAgICAgICAgbmVlZHNDdXN0b21DaGFuZ2VLZXlTaWduYXR1cmVWZXJpZmljYXRpb246IHRydWUsXG4gICAgICAgICAgY3VzdG9tQ2hhbmdlOiB7fSxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gbmVlZHMgdG8gYmUgYXN5bmMgZnVuY3Rpb24gdG8gY3JlYXRlIHNpZ25hdHVyZXNcbiAgICAgICAgYmFkU2lnczogYXN5bmMgKCkgPT4gKHtcbiAgICAgICAgICBrZXljaGFpbnM6IHsgdXNlcjogdXNlcktleWNoYWluIH0sXG4gICAgICAgICAgbmVlZHNDdXN0b21DaGFuZ2VLZXlTaWduYXR1cmVWZXJpZmljYXRpb246IHRydWUsXG4gICAgICAgICAgY3VzdG9tQ2hhbmdlOiB7XG4gICAgICAgICAgICBrZXlzOiBbY2hhbmdlS2V5cy51c2VyLCBjaGFuZ2VLZXlzLmJhY2t1cCwgY2hhbmdlS2V5cy5iaXRnb10sXG4gICAgICAgICAgICBzaWduYXR1cmVzOiBbXG4gICAgICAgICAgICAgIGF3YWl0IHNpZ25PdGhlcihjaGFuZ2VLZXlzLnVzZXIpLFxuICAgICAgICAgICAgICBhd2FpdCBzaWduT3RoZXIoY2hhbmdlS2V5cy5iYWNrdXApLFxuICAgICAgICAgICAgICBhd2FpdCBzaWduT3RoZXIoY2hhbmdlS2V5cy5iaXRnbyksXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgICBnb29kU2lnczogYXN5bmMgKCkgPT4gKHtcbiAgICAgICAgICBrZXljaGFpbnM6IHsgdXNlcjogdXNlcktleWNoYWluIH0sXG4gICAgICAgICAgbmVlZHNDdXN0b21DaGFuZ2VLZXlTaWduYXR1cmVWZXJpZmljYXRpb246IHRydWUsXG4gICAgICAgICAgY3VzdG9tQ2hhbmdlOiB7XG4gICAgICAgICAgICBrZXlzOiBbY2hhbmdlS2V5cy51c2VyLCBjaGFuZ2VLZXlzLmJhY2t1cCwgY2hhbmdlS2V5cy5iaXRnb10sXG4gICAgICAgICAgICBzaWduYXR1cmVzOiBbXG4gICAgICAgICAgICAgIGF3YWl0IHNpZ25Vc2VyKGNoYW5nZUtleXMudXNlciksXG4gICAgICAgICAgICAgIGF3YWl0IHNpZ25Vc2VyKGNoYW5nZUtleXMuYmFja3VwKSxcbiAgICAgICAgICAgICAgYXdhaXQgc2lnblVzZXIoY2hhbmdlS2V5cy5iaXRnbyksXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgbWlzc2luZ091dHB1dHM6IDEsXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgY29uc3QgdW5zaWduZWRTZW5kaW5nV2FsbGV0ID0gc2lub24uY3JlYXRlU3R1Ykluc3RhbmNlKFdhbGxldCwgc3R1YkRhdGEudW5zaWduZWRTZW5kaW5nV2FsbGV0IGFzIGFueSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIHVzZXIgcHJpdmF0ZSBrZXkgY2Fubm90IGJlIHZlcmlmaWVkIHRvIG1hdGNoIHRoZSB1c2VyIHB1YmxpYyBrZXknLCBhc3luYyAoKSA9PiB7XG4gICAgICBzaW5vbi5zdHViKGNvaW4sICdwYXJzZVRyYW5zYWN0aW9uJykucmVzb2x2ZXMoc3R1YkRhdGEucGFyc2VUcmFuc2FjdGlvbkRhdGEuYmFkS2V5IGFzIGFueSk7XG4gICAgICBjb25zdCB2ZXJpZnlXYWxsZXQgPSBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UoV2FsbGV0LCB7fSk7XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFzc3BocmFzZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHt9LFxuICAgICAgICAgIHdhbGxldDogdmVyaWZ5V2FsbGV0IGFzIGFueSxcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHt9LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAvdHJhbnNhY3Rpb24gcmVxdWlyZXMgdmVyaWZpY2F0aW9uIG9mIHVzZXIgcHVibGljIGtleSwgYnV0IGl0IHdhcyB1bmFibGUgdG8gYmUgdmVyaWZpZWQvXG4gICAgICAgICk7XG5cbiAgICAgIChjb2luLnBhcnNlVHJhbnNhY3Rpb24gYXMgYW55KS5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIGN1c3RvbSBjaGFuZ2UgdmVyaWZpY2F0aW9uIGRhdGEgaXMgcmVxdWlyZWQgYnV0IG1pc3NpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBzaW5vbi5zdHViKGNvaW4sICdwYXJzZVRyYW5zYWN0aW9uJykucmVzb2x2ZXMoc3R1YkRhdGEucGFyc2VUcmFuc2FjdGlvbkRhdGEubm9DdXN0b21DaGFuZ2UgYXMgYW55KTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXNzcGhyYXNlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge30sXG4gICAgICAgICAgd2FsbGV0OiB1bnNpZ25lZFNlbmRpbmdXYWxsZXQgYXMgYW55LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbjoge30sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9wYXJzZWQgdHJhbnNhY3Rpb24gaXMgbWlzc2luZyByZXF1aXJlZCBjdXN0b20gY2hhbmdlIHZlcmlmaWNhdGlvbiBkYXRhLyk7XG5cbiAgICAgIChjb2luLnBhcnNlVHJhbnNhY3Rpb24gYXMgYW55KS5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIGN1c3RvbSBjaGFuZ2Uga2V5cyBvciBrZXkgc2lnbmF0dXJlcyBhcmUgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICAgIHNpbm9uLnN0dWIoY29pbiwgJ3BhcnNlVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyhzdHViRGF0YS5wYXJzZVRyYW5zYWN0aW9uRGF0YS5lbXB0eUN1c3RvbUNoYW5nZSBhcyBhbnkpO1xuXG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHBhc3NwaHJhc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7fSxcbiAgICAgICAgICB3YWxsZXQ6IHVuc2lnbmVkU2VuZGluZ1dhbGxldCBhcyBhbnksXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7fSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2N1c3RvbUNoYW5nZSBwcm9wZXJ0eSBpcyBtaXNzaW5nIGtleXMgb3Igc2lnbmF0dXJlcy8pO1xuXG4gICAgICAoY29pbi5wYXJzZVRyYW5zYWN0aW9uIGFzIGFueSkucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGlmIHRoZSBjdXN0b20gY2hhbmdlIGtleSBzaWduYXR1cmVzIGNhbm5vdCBiZSB2ZXJpZmllZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIHNpbm9uLnN0dWIoY29pbiwgJ3BhcnNlVHJhbnNhY3Rpb24nKS5yZXNvbHZlcygoYXdhaXQgc3R1YkRhdGEucGFyc2VUcmFuc2FjdGlvbkRhdGEuYmFkU2lncygpKSBhcyBhbnkpO1xuXG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHBhc3NwaHJhc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7fSxcbiAgICAgICAgICB3YWxsZXQ6IHVuc2lnbmVkU2VuZGluZ1dhbGxldCBhcyBhbnksXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7fSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgL3RyYW5zYWN0aW9uIHJlcXVpcmVzIHZlcmlmaWNhdGlvbiBvZiBjdXN0b20gY2hhbmdlIGtleSBzaWduYXR1cmVzLCBidXQgdGhleSB3ZXJlIHVuYWJsZSB0byBiZSB2ZXJpZmllZC9cbiAgICAgICAgKTtcblxuICAgICAgKGNvaW4ucGFyc2VUcmFuc2FjdGlvbiBhcyBhbnkpLnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3VjY2Vzc2Z1bGx5IHZlcmlmeSBhIGN1c3RvbSBjaGFuZ2UgdHJhbnNhY3Rpb24gd2hlbiBjaGFuZ2Uga2V5cyBhbmQgc2lnbmF0dXJlcyBhcmUgdmFsaWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBzaW5vbi5zdHViKGNvaW4sICdwYXJzZVRyYW5zYWN0aW9uJykucmVzb2x2ZXMoKGF3YWl0IHN0dWJEYXRhLnBhcnNlVHJhbnNhY3Rpb25EYXRhLmdvb2RTaWdzKCkpIGFzIGFueSk7XG5cbiAgICAgIC8vIGlmIHZlcmlmeSB0cmFuc2FjdGlvbiBnZXRzIHJlamVjdGVkIHdpdGggdGhlIG91dHB1dHMgbWlzc2luZyBlcnJvciBtZXNzYWdlLFxuICAgICAgLy8gdGhlbiB3ZSBrbm93IHRoYXQgdGhlIHZlcmlmaWNhdGlvbiBvZiB0aGUgY3VzdG9tIGNoYW5nZSBrZXkgc2lnbmF0dXJlcyB3YXMgc3VjY2Vzc2Z1bFxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXNzcGhyYXNlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge30sXG4gICAgICAgICAgd2FsbGV0OiB1bnNpZ25lZFNlbmRpbmdXYWxsZXQgYXMgYW55LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbjoge30sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9leHBlY3RlZCBvdXRwdXRzIG1pc3NpbmcgaW4gdHJhbnNhY3Rpb24gcHJlYnVpbGQvKTtcblxuICAgICAgKGNvaW4ucGFyc2VUcmFuc2FjdGlvbiBhcyBhbnkpLnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IGFsbG93IG1vcmUgdGhhbiAxNTAgYmFzaXMgcG9pbnRzIG9mIGltcGxpY2l0IGV4dGVybmFsIG91dHB1dHMgKGZvciBwYXlnbyBvdXRwdXRzKScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNvaW5Nb2NrID0gc2lub24uc3R1Yihjb2luLCAncGFyc2VUcmFuc2FjdGlvbicpLnJlc29sdmVzKHtcbiAgICAgICAga2V5Y2hhaW5zOiB7fSBhcyBhbnksXG4gICAgICAgIGtleVNpZ25hdHVyZXM6IHt9LFxuICAgICAgICBvdXRwdXRzOiBbXSxcbiAgICAgICAgbWlzc2luZ091dHB1dHM6IFtdLFxuICAgICAgICBleHBsaWNpdEV4dGVybmFsT3V0cHV0czogW10sXG4gICAgICAgIGltcGxpY2l0RXh0ZXJuYWxPdXRwdXRzOiBbXSxcbiAgICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICAgIGV4cGxpY2l0RXh0ZXJuYWxTcGVuZEFtb3VudDogMTAwMDAsXG4gICAgICAgIGltcGxpY2l0RXh0ZXJuYWxTcGVuZEFtb3VudDogMTUxLFxuICAgICAgICBuZWVkc0N1c3RvbUNoYW5nZUtleVNpZ25hdHVyZVZlcmlmaWNhdGlvbjogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXNzcGhyYXNlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge30sXG4gICAgICAgICAgd2FsbGV0OiB1bnNpZ25lZFNlbmRpbmdXYWxsZXQgYXMgYW55LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgncHJlYnVpbGQgYXR0ZW1wdHMgdG8gc3BlbmQgdG8gdW5pbnRlbmRlZCBleHRlcm5hbCByZWNpcGllbnRzJyk7XG5cbiAgICAgIGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYWxsb3cgMTUwIGJhc2lzIHBvaW50cyBvZiBpbXBsaWNpdCBleHRlcm5hbCBvdXRwdXRzIChmb3IgcGF5Z28gb3V0cHV0cyknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjb2luTW9jayA9IHNpbm9uLnN0dWIoY29pbiwgJ3BhcnNlVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh7XG4gICAgICAgIGtleWNoYWluczoge30gYXMgYW55LFxuICAgICAgICBrZXlTaWduYXR1cmVzOiB7fSxcbiAgICAgICAgb3V0cHV0czogW10sXG4gICAgICAgIG1pc3NpbmdPdXRwdXRzOiBbXSxcbiAgICAgICAgZXhwbGljaXRFeHRlcm5hbE91dHB1dHM6IFtdLFxuICAgICAgICBpbXBsaWNpdEV4dGVybmFsT3V0cHV0czogW10sXG4gICAgICAgIGNoYW5nZU91dHB1dHM6IFtdLFxuICAgICAgICBleHBsaWNpdEV4dGVybmFsU3BlbmRBbW91bnQ6IDEwMDAsXG4gICAgICAgIGltcGxpY2l0RXh0ZXJuYWxTcGVuZEFtb3VudDogMTUsXG4gICAgICAgIG5lZWRzQ3VzdG9tQ2hhbmdlS2V5U2lnbmF0dXJlVmVyaWZpY2F0aW9uOiBmYWxzZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBiaXRjb2luTW9jayA9IHNpbm9uXG4gICAgICAgIC5zdHViKGNvaW4sICdjcmVhdGVUcmFuc2FjdGlvbkZyb21IZXgnKVxuICAgICAgICAucmV0dXJucyh7IGluczogW10gfSBhcyB1bmtub3duIGFzIHV0eG9saWIuYml0Z28uVXR4b1RyYW5zYWN0aW9uKTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXNzcGhyYXNlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6ICcwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3YWxsZXQ6IHVuc2lnbmVkU2VuZGluZ1dhbGxldCBhcyBhbnksXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuZXZlbnR1YWxseS5iZS50cnVlKCk7XG5cbiAgICAgIGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICAgIGJpdGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IGFsbG93IGFueSBpbXBsaWNpdCBleHRlcm5hbCBvdXRwdXRzIGlmIHBheWdvIG91dHB1dHMgYXJlIGRpc2FsbG93ZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjb2luTW9jayA9IHNpbm9uLnN0dWIoY29pbiwgJ3BhcnNlVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh7XG4gICAgICAgIGtleWNoYWluczoge30gYXMgYW55LFxuICAgICAgICBrZXlTaWduYXR1cmVzOiB7fSxcbiAgICAgICAgb3V0cHV0czogW10sXG4gICAgICAgIG1pc3NpbmdPdXRwdXRzOiBbXSxcbiAgICAgICAgZXhwbGljaXRFeHRlcm5hbE91dHB1dHM6IFtdLFxuICAgICAgICBpbXBsaWNpdEV4dGVybmFsT3V0cHV0czogW10sXG4gICAgICAgIGNoYW5nZU91dHB1dHM6IFtdLFxuICAgICAgICBleHBsaWNpdEV4dGVybmFsU3BlbmRBbW91bnQ6IDAsXG4gICAgICAgIGltcGxpY2l0RXh0ZXJuYWxTcGVuZEFtb3VudDogMTAsXG4gICAgICAgIG5lZWRzQ3VzdG9tQ2hhbmdlS2V5U2lnbmF0dXJlVmVyaWZpY2F0aW9uOiBmYWxzZSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHBhc3NwaHJhc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogJzAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdhbGxldDogdW5zaWduZWRTZW5kaW5nV2FsbGV0IGFzIGFueSxcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHtcbiAgICAgICAgICAgIGFsbG93UGF5Z29PdXRwdXQ6IGZhbHNlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdwcmVidWlsZCBhdHRlbXB0cyB0byBzcGVuZCB0byB1bmludGVuZGVkIGV4dGVybmFsIHJlY2lwaWVudHMnKTtcblxuICAgICAgY29pbk1vY2sucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyBwYXlnbyBvdXRwdXRzIGlmIGVtcHR5IHZlcmlmaWNhdGlvbiBvYmplY3QgaXMgcGFzc2VkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY29pbk1vY2sgPSBzaW5vbi5zdHViKGNvaW4sICdwYXJzZVRyYW5zYWN0aW9uJykucmVzb2x2ZXMoe1xuICAgICAgICBrZXljaGFpbnM6IHt9IGFzIGFueSxcbiAgICAgICAga2V5U2lnbmF0dXJlczoge30sXG4gICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgICBtaXNzaW5nT3V0cHV0czogW10sXG4gICAgICAgIGV4cGxpY2l0RXh0ZXJuYWxPdXRwdXRzOiBbXSxcbiAgICAgICAgaW1wbGljaXRFeHRlcm5hbE91dHB1dHM6IFtdLFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgICAgZXhwbGljaXRFeHRlcm5hbFNwZW5kQW1vdW50OiAxMDAwLFxuICAgICAgICBpbXBsaWNpdEV4dGVybmFsU3BlbmRBbW91bnQ6IDE1LFxuICAgICAgICBuZWVkc0N1c3RvbUNoYW5nZUtleVNpZ25hdHVyZVZlcmlmaWNhdGlvbjogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgYml0Y29pbk1vY2sgPSBzaW5vblxuICAgICAgICAuc3R1Yihjb2luLCAnY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4JylcbiAgICAgICAgLnJldHVybnMoeyBpbnM6IFtdIH0gYXMgdW5rbm93biBhcyB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbik7XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFzc3BocmFzZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiAnMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgd2FsbGV0OiB1bnNpZ25lZFNlbmRpbmdXYWxsZXQgYXMgYW55LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbjoge30sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuZXZlbnR1YWxseS5iZS50cnVlKCk7XG5cbiAgICAgIGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICAgIGJpdGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgd29yayB3aXRoIGJpZ2ludCBhbW91bnRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gbmVlZCBhIGNvaW4gdGhhdCB1c2VzIGJpZ2ludFxuICAgICAgY29uc3QgYmlnaW50Q29pbiA9IGJpdGdvLmNvaW4oJ3Rkb2dlJykgYXMgQWJzdHJhY3RVdHhvQ29pbjtcblxuICAgICAgY29uc3QgY29pbk1vY2sgPSBzaW5vbi5zdHViKGJpZ2ludENvaW4sICdwYXJzZVRyYW5zYWN0aW9uJykucmVzb2x2ZXMoe1xuICAgICAgICBrZXljaGFpbnM6IHt9IGFzIGFueSxcbiAgICAgICAga2V5U2lnbmF0dXJlczoge30sXG4gICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgICBtaXNzaW5nT3V0cHV0czogW10sXG4gICAgICAgIGV4cGxpY2l0RXh0ZXJuYWxPdXRwdXRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJ2V4dGVybmFsX2FkZHJlc3MnLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGltcGxpY2l0RXh0ZXJuYWxPdXRwdXRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJ2V4dGVybmFsX2FkZHJlc3NfMicsXG4gICAgICAgICAgICBhbW91bnQ6ICcxNScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICAgIGV4cGxpY2l0RXh0ZXJuYWxTcGVuZEFtb3VudDogQmlnSW50KDEwMDAwKSxcbiAgICAgICAgaW1wbGljaXRFeHRlcm5hbFNwZW5kQW1vdW50OiBCaWdJbnQoMTUpLFxuICAgICAgICBuZWVkc0N1c3RvbUNoYW5nZUtleVNpZ25hdHVyZVZlcmlmaWNhdGlvbjogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgYml0Y29pbk1vY2sgPSBzaW5vblxuICAgICAgICAuc3R1YihiaWdpbnRDb2luLCAnY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4JylcbiAgICAgICAgLnJldHVybnMoeyBpbnM6IFtdIH0gYXMgdW5rbm93biBhcyB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbik7XG5cbiAgICAgIGF3YWl0IGJpZ2ludENvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFzc3BocmFzZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiAnMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgd2FsbGV0OiB1bnNpZ25lZFNlbmRpbmdXYWxsZXQgYXMgYW55LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbjoge30sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuZXZlbnR1YWxseS5iZS50cnVlKCk7XG5cbiAgICAgIGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICAgIGJpdGNvaW5Nb2NrLnJlc3RvcmUoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!