PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-lib/dist/test/bitgo/psbt
Просмотр файла: Musig2Util.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.invalidPartialSig = exports.invalidParticipantPubKeys = exports.invalidTxHash = exports.invalidTapInputKey = exports.invalidTapOutputKey = exports.dummyPartialSig = exports.dummyPrivateKey = exports.dummyAggNonce = exports.dummyPubNonce = exports.dummyParticipantPubKeys = exports.dummyTapInternalKey = exports.dummyTapOutputKey = exports.rootWalletKeys = exports.network = void 0;
exports.constructPsbt = constructPsbt;
exports.getUnspents = getUnspents;
exports.validatePsbtP2trMusig2Input = validatePsbtP2trMusig2Input;
exports.validatePsbtP2trMusig2Output = validatePsbtP2trMusig2Output;
exports.validateNoncesKeyVals = validateNoncesKeyVals;
exports.validatePartialSigKeyVals = validatePartialSigKeyVals;
exports.validateParticipantsKeyVals = validateParticipantsKeyVals;
exports.validateFinalizedInput = validateFinalizedInput;
exports.validateParsedTaprootKeyPathPsbt = validateParsedTaprootKeyPathPsbt;
exports.validateParsedTaprootScriptPathPsbt = validateParsedTaprootScriptPathPsbt;
exports.validateParsedTaprootKeyPathTxInput = validateParsedTaprootKeyPathTxInput;
exports.validateParsedTaprootScriptPathTxInput = validateParsedTaprootScriptPathTxInput;
const assert = require("assert");
const bitgo_1 = require("../../../src/bitgo");
const outputScripts_1 = require("../../../src/bitgo/outputScripts");
const testutil_1 = require("../../../src/testutil");
const src_1 = require("../../../src");
const PsbtUtil_1 = require("../../../src/bitgo/PsbtUtil");
exports.network = src_1.networks.bitcoin;
const outputType = 'p2trMusig2';
const CHANGE_INDEX = 100;
const FEE = BigInt(100);
const keys = [1, 2, 3].map((v) => src_1.bip32.fromSeed(Buffer.alloc(16, `test/2/${v}`), exports.network));
exports.rootWalletKeys = new bitgo_1.RootWalletKeys([keys[0], keys[1], keys[2]]);
const dummyKey1 = exports.rootWalletKeys.deriveForChainAndIndex(50, 200);
const dummyKey2 = exports.rootWalletKeys.deriveForChainAndIndex(60, 201);
exports.dummyTapOutputKey = dummyKey1.user.publicKey.subarray(1, 33);
exports.dummyTapInternalKey = dummyKey1.bitgo.publicKey.subarray(1, 33);
exports.dummyParticipantPubKeys = [dummyKey1.user.publicKey, dummyKey1.backup.publicKey];
exports.dummyPubNonce = Buffer.concat([dummyKey2.user.publicKey, dummyKey2.bitgo.publicKey]);
exports.dummyAggNonce = Buffer.concat([dummyKey2.backup.publicKey, dummyKey2.bitgo.publicKey]);
exports.dummyPrivateKey = dummyKey2.user.privateKey;
exports.dummyPartialSig = dummyKey2.backup.privateKey;
exports.invalidTapOutputKey = Buffer.allocUnsafe(1);
exports.invalidTapInputKey = Buffer.allocUnsafe(1);
exports.invalidTxHash = Buffer.allocUnsafe(1);
exports.invalidParticipantPubKeys = [Buffer.allocUnsafe(1), Buffer.allocUnsafe(1)];
exports.invalidPartialSig = Buffer.allocUnsafe(1);
function constructPsbt(unspents, rootWalletKeys, signer, cosigner, outputs) {
const psbt = (0, bitgo_1.createPsbtForNetwork)({ network: exports.network });
if (Array.isArray(outputs)) {
outputs.forEach((output) => (0, bitgo_1.addWalletOutputToPsbt)(psbt, rootWalletKeys, output.chain, output.index, output.value));
}
else {
const total = BigInt((0, bitgo_1.unspentSum)(unspents, 'bigint'));
(0, bitgo_1.addWalletOutputToPsbt)(psbt, rootWalletKeys, (0, bitgo_1.getInternalChainCode)(outputs), CHANGE_INDEX, total - FEE);
}
unspents.forEach((u) => {
if ((0, bitgo_1.isWalletUnspent)(u)) {
(0, bitgo_1.addWalletUnspentToPsbt)(psbt, u, rootWalletKeys, signer, cosigner);
}
else {
const { redeemScript } = (0, outputScripts_1.createOutputScriptP2shP2pk)(testutil_1.replayProtectionKeyPair.publicKey);
assert.ok(redeemScript);
(0, bitgo_1.addReplayProtectionUnspentToPsbt)(psbt, u, redeemScript);
}
});
return psbt;
}
function getUnspents(inputScriptTypes, rootWalletKeys) {
return inputScriptTypes.map((t, i) => {
if (!bitgo_1.outputScripts.isScriptType2Of3(t)) {
throw new Error(`invalid input type ${t}`);
}
const unspent = (0, testutil_1.mockWalletUnspent)(exports.network, BigInt('10000000000000000'), {
keys: rootWalletKeys,
chain: (0, bitgo_1.getExternalChainCode)(t),
vout: i,
});
if ((0, bitgo_1.isWalletUnspent)(unspent)) {
return unspent;
}
throw new Error('Invalid unspent');
});
}
function validatePsbtP2trMusig2Input(psbt, index, unspent, spendType) {
const input = psbt.data.inputs[index];
assert.strictEqual(input.tapBip32Derivation?.length, 2);
let leafHashesCount = 0;
if (spendType === 'keyPath') {
const inputWalletKeys = exports.rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
const { internalPubkey, taptreeRoot } = (0, outputScripts_1.createKeyPathP2trMusig2)(inputWalletKeys.publicKeys);
assert.ok(!input.tapLeafScript);
assert.ok(input.tapInternalKey);
assert.ok(input.tapMerkleRoot);
assert.ok(input.tapInternalKey.equals(internalPubkey));
assert.ok(input.tapMerkleRoot.equals(taptreeRoot));
}
else {
assert.ok(input.tapLeafScript);
assert.ok(!input.tapInternalKey);
assert.ok(!input.tapMerkleRoot);
leafHashesCount = 1;
}
input.tapBip32Derivation?.forEach((bv) => {
assert.strictEqual(bv.leafHashes.length, leafHashesCount);
});
}
function validatePsbtP2trMusig2Output(psbt, index) {
const outputWalletKeys = exports.rootWalletKeys.deriveForChainAndIndex((0, bitgo_1.getInternalChainCode)(outputType), CHANGE_INDEX);
const payment = (0, outputScripts_1.createPaymentP2trMusig2)(outputWalletKeys.publicKeys);
const output = psbt.data.outputs[index];
assert.ok(!!payment.internalPubkey);
assert.ok(!!output.tapInternalKey);
assert.ok(output.tapInternalKey.equals(payment.internalPubkey));
assert.strictEqual(output.tapBip32Derivation?.length, 3);
output.tapBip32Derivation?.forEach((bv) => {
const leafHashesCount = bv.pubkey.equals((0, outputScripts_1.toXOnlyPublicKey)(outputWalletKeys.backup.publicKey)) ? 2 : 1;
assert.strictEqual(bv.leafHashes.length, leafHashesCount);
});
}
function validateNoncesKeyVals(psbt, index, unspent) {
const keyVals = psbt.getProprietaryKeyVals(index);
const walletKeys = exports.rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
const { outputPubkey } = (0, outputScripts_1.createKeyPathP2trMusig2)(walletKeys.publicKeys);
const participantPubKeys = [walletKeys.user.publicKey, walletKeys.bitgo.publicKey];
const nonces = keyVals.filter((kv) => kv.key.subtype === bitgo_1.ProprietaryKeySubtype.MUSIG2_PUB_NONCE);
assert.strictEqual(nonces.length, 2);
const nonceKeydata = participantPubKeys.map((p) => {
const keydata = Buffer.alloc(65);
p.copy(keydata);
outputPubkey.copy(keydata, 33);
return keydata;
});
nonces.forEach((kv) => {
assert.strictEqual(kv.key.identifier, bitgo_1.PSBT_PROPRIETARY_IDENTIFIER);
assert.strictEqual(kv.value.length, 66);
assert.strictEqual(nonceKeydata.filter((kd) => kd.equals(kv.key.keydata)).length, 1);
});
}
function validatePartialSigKeyVals(psbt, index, unspent) {
const keyVals = psbt.getProprietaryKeyVals(index);
const inputWalletKeys = exports.rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
const { outputPubkey } = (0, outputScripts_1.createKeyPathP2trMusig2)(inputWalletKeys.publicKeys);
const participantPubKeys = [inputWalletKeys.user.publicKey, inputWalletKeys.bitgo.publicKey];
const partialSigs = keyVals.filter((kv) => kv.key.subtype === bitgo_1.ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG);
assert.strictEqual(partialSigs.length, 2);
const partialSigKeydata = participantPubKeys.map((p) => {
const keydata = Buffer.alloc(65);
p.copy(keydata);
outputPubkey.copy(keydata, 33);
return keydata;
});
partialSigs.forEach((kv) => {
assert.strictEqual(kv.key.identifier, bitgo_1.PSBT_PROPRIETARY_IDENTIFIER);
assert.strictEqual(kv.value.length, 32);
assert.strictEqual(partialSigKeydata.filter((kd) => kd.equals(kv.key.keydata)).length, 1);
});
}
function validateParticipantsKeyVals(psbt, index, unspent) {
const keyVals = psbt.getProprietaryKeyVals(index);
const walletKeys = exports.rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
const { internalPubkey, outputPubkey } = (0, outputScripts_1.createKeyPathP2trMusig2)(walletKeys.publicKeys);
const participantPubKeys = [walletKeys.user.publicKey, walletKeys.bitgo.publicKey];
const participantsKeyVals = keyVals.filter((kv) => kv.key.subtype === bitgo_1.ProprietaryKeySubtype.MUSIG2_PARTICIPANT_PUB_KEYS);
assert.strictEqual(participantsKeyVals.length, 1);
const kv = participantsKeyVals[0];
assert.strictEqual(kv.key.identifier, bitgo_1.PSBT_PROPRIETARY_IDENTIFIER);
assert.ok(Buffer.concat([outputPubkey, internalPubkey]).equals(kv.key.keydata));
const valueMatch = [Buffer.concat(participantPubKeys), Buffer.concat(participantPubKeys.reverse())].some((pks) => {
return pks.equals(kv.value);
});
assert.ok(valueMatch);
}
function validateFinalizedInput(psbt, index, unspent, spendType) {
const input = psbt.data.inputs[index];
assert.ok((0, PsbtUtil_1.isPsbtInputFinalized)(input));
if ((0, bitgo_1.scriptTypeForChain)(unspent.chain) === 'p2trMusig2' && spendType === 'keyPath') {
assert.strictEqual(input.finalScriptWitness?.length, 66);
}
assert.ok(!input.unknownKeyVals?.length);
}
function validateParsedTaprootKeyPathPsbt(psbt, index, signature) {
const parsed = (0, bitgo_1.parsePsbtInput)(psbt.data.inputs[0]);
assert.ok(parsed.scriptType === 'taprootKeyPathSpend');
assert.strictEqual(parsed.pubScript.length, 34);
assert.strictEqual(parsed.publicKeys.length, 1);
assert.strictEqual(parsed.publicKeys[0].length, 32);
if (signature === 'unsigned') {
assert.strictEqual(parsed.signatures, undefined);
assert.strictEqual(parsed.participantPublicKeys, undefined);
}
else {
const expected = signature === 'halfsigned' ? 1 : 2;
assert.strictEqual(parsed.signatures?.length, expected);
parsed.signatures.forEach((sig) => {
assert.strictEqual(sig.length, 32);
});
assert.strictEqual(parsed.participantPublicKeys?.length, expected);
parsed.participantPublicKeys.forEach((pk) => {
assert.strictEqual(pk.length, 33);
});
}
}
function validateParsedTaprootScriptPathPsbt(psbt, index, signature) {
const input = psbt.data.inputs[index];
const parsed = (0, bitgo_1.parsePsbtInput)(psbt.data.inputs[0]);
assert.ok(parsed.scriptType === 'taprootScriptPathSpend');
assert.ok(input.tapLeafScript);
assert.ok(parsed.pubScript.equals(input.tapLeafScript[0].script));
assert.ok(parsed.controlBlock.equals(input.tapLeafScript[0].controlBlock));
assert.strictEqual(parsed.scriptPathLevel, 1);
assert.strictEqual(parsed.leafVersion, input.tapLeafScript[0].leafVersion);
parsed.publicKeys.forEach((pk) => {
assert.strictEqual(pk.length, 32);
});
if (signature === 'unsigned') {
assert.strictEqual(parsed.signatures, undefined);
}
else {
const expected = signature === 'halfsigned' ? 1 : 2;
assert.strictEqual(parsed.signatures?.length, expected);
parsed.signatures.forEach((sig) => {
assert.strictEqual(sig.length, 64);
});
}
}
function validateParsedTaprootKeyPathTxInput(psbt, tx) {
const parsedTxInput = (0, bitgo_1.parseSignatureScript2Of3)(tx.ins[0]);
assert.ok(parsedTxInput.scriptType === 'taprootKeyPathSpend');
assert.strictEqual(parsedTxInput.signatures.length, 1);
assert.strictEqual(parsedTxInput.signatures[0].length, 64);
}
function validateParsedTaprootScriptPathTxInput(psbt, tx, index) {
const input = psbt.data.inputs[index];
const parsedTxInput = (0, bitgo_1.parseSignatureScript2Of3)(tx.ins[0]);
assert.ok(parsedTxInput);
assert.ok(parsedTxInput.scriptType === 'taprootScriptPathSpend');
assert.ok(input.tapLeafScript);
assert.ok(parsedTxInput.pubScript.equals(input.tapLeafScript[0].script));
assert.ok(parsedTxInput.controlBlock.equals(input.tapLeafScript[0].controlBlock));
assert.strictEqual(parsedTxInput.scriptPathLevel, 1);
assert.strictEqual(parsedTxInput.leafVersion, input.tapLeafScript[0].leafVersion);
parsedTxInput.publicKeys.forEach((pk) => {
assert.strictEqual(pk.length, 32);
});
assert.strictEqual(parsedTxInput.signatures?.length, 2);
parsedTxInput.signatures.forEach((sig) => {
assert.strictEqual(sig.length, 64);
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTXVzaWcyVXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Rlc3QvYml0Z28vcHNidC9NdXNpZzJVdGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQStEQSxzQ0F5QkM7QUFFRCxrQ0FtQkM7QUFFRCxrRUE0QkM7QUFFRCxvRUFZQztBQUVELHNEQXlCQztBQUVELDhEQXlCQztBQUVELGtFQXNCQztBQUVELHdEQVlDO0FBRUQsNEVBeUJDO0FBRUQsa0ZBeUJDO0FBRUQsa0ZBUUM7QUFFRCx3RkFxQkM7QUE1VUQsaUNBQWlDO0FBRWpDLDhDQXVCNEI7QUFDNUIsb0VBTTBDO0FBQzFDLG9EQUFtRjtBQUNuRixzQ0FBK0M7QUFFL0MsMERBQW1FO0FBRXRELFFBQUEsT0FBTyxHQUFHLGNBQVEsQ0FBQyxPQUFPLENBQUM7QUFDeEMsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDO0FBQ2hDLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQztBQUN6QixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7QUFFeEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsV0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsZUFBTyxDQUFDLENBQXFCLENBQUM7QUFDbkcsUUFBQSxjQUFjLEdBQUcsSUFBSSxzQkFBYyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRTlFLE1BQU0sU0FBUyxHQUFHLHNCQUFjLENBQUMsc0JBQXNCLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ2pFLE1B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LEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUNsRixNQUFNLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDckQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDbEYsYUFBYSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRTtRQUN0QyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEMsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hELGFBQWEsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDdkMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5pbXBvcnQge1xuICBhZGRSZXBsYXlQcm90ZWN0aW9uVW5zcGVudFRvUHNidCxcbiAgYWRkV2FsbGV0T3V0cHV0VG9Qc2J0LFxuICBhZGRXYWxsZXRVbnNwZW50VG9Qc2J0LFxuICBjcmVhdGVQc2J0Rm9yTmV0d29yayxcbiAgZ2V0RXh0ZXJuYWxDaGFpbkNvZGUsXG4gIGdldEludGVybmFsQ2hhaW5Db2RlLFxuICBpc1dhbGxldFVuc3BlbnQsXG4gIEtleU5hbWUsXG4gIG91dHB1dFNjcmlwdHMsXG4gIHBhcnNlUHNidElucHV0LFxuICBwYXJzZVNpZ25hdHVyZVNjcmlwdDJPZjMsXG4gIFByb3ByaWV0YXJ5S2V5U3VidHlwZSxcbiAgUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSLFxuICBSb290V2FsbGV0S2V5cyxcbiAgc2NyaXB0VHlwZUZvckNoYWluLFxuICBUdXBsZSxcbiAgVW5zcGVudCxcbiAgdW5zcGVudFN1bSxcbiAgVXR4b1BzYnQsXG4gIFV0eG9UcmFuc2FjdGlvbixcbiAgV2FsbGV0VW5zcGVudCxcbiAgQ2hhaW5Db2RlLFxufSBmcm9tICcuLi8uLi8uLi9zcmMvYml0Z28nO1xuaW1wb3J0IHtcbiAgY3JlYXRlS2V5UGF0aFAydHJNdXNpZzIsXG4gIGNyZWF0ZU91dHB1dFNjcmlwdFAyc2hQMnBrLFxuICBjcmVhdGVQYXltZW50UDJ0ck11c2lnMixcbiAgU2NyaXB0VHlwZTJPZjMsXG4gIHRvWE9ubHlQdWJsaWNLZXksXG59IGZyb20gJy4uLy4uLy4uL3NyYy9iaXRnby9vdXRwdXRTY3JpcHRzJztcbmltcG9ydCB7IG1vY2tXYWxsZXRVbnNwZW50LCByZXBsYXlQcm90ZWN0aW9uS2V5UGFpciB9IGZyb20gJy4uLy4uLy4uL3NyYy90ZXN0dXRpbCc7XG5pbXBvcnQgeyBiaXAzMiwgbmV0d29ya3MgfSBmcm9tICcuLi8uLi8uLi9zcmMnO1xuaW1wb3J0IHsgQklQMzJJbnRlcmZhY2UgfSBmcm9tICdiaXAzMic7XG5pbXBvcnQgeyBpc1BzYnRJbnB1dEZpbmFsaXplZCB9IGZyb20gJy4uLy4uLy4uL3NyYy9iaXRnby9Qc2J0VXRpbCc7XG5cbmV4cG9ydCBjb25zdCBuZXR3b3JrID0gbmV0d29ya3MuYml0Y29pbjtcbmNvbnN0IG91dHB1dFR5cGUgPSAncDJ0ck11c2lnMic7XG5jb25zdCBDSEFOR0VfSU5ERVggPSAxMDA7XG5jb25zdCBGRUUgPSBCaWdJbnQoMTAwKTtcblxuY29uc3Qga2V5cyA9IFsxLCAyLCAzXS5tYXAoKHYpID0+IGJpcDMyLmZyb21TZWVkKEJ1ZmZlci5hbGxvYygxNiwgYHRlc3QvMi8ke3Z9YCksIG5ldHdvcmspKSBhcyBCSVAzMkludGVyZmFjZVtdO1xuZXhwb3J0IGNvbnN0IHJvb3RXYWxsZXRLZXlzID0gbmV3IFJvb3RXYWxsZXRLZXlzKFtrZXlzWzBdLCBrZXlzWzFdLCBrZXlzWzJdXSk7XG5cbmNvbnN0IGR1bW15S2V5MSA9IHJvb3RXYWxsZXRLZXlzLmRlcml2ZUZvckNoYWluQW5kSW5kZXgoNTAsIDIwMCk7XG5jb25zdCBkdW1teUtleTIgPSByb290V2FsbGV0S2V5cy5kZXJpdmVGb3JDaGFpbkFuZEluZGV4KDYwLCAyMDEpO1xuXG5leHBvcnQgY29uc3QgZHVtbXlUYXBPdXRwdXRLZXkgPSBkdW1teUtleTEudXNlci5wdWJsaWNLZXkuc3ViYXJyYXkoMSwgMzMpO1xuZXhwb3J0IGNvbnN0IGR1bW15VGFwSW50ZXJuYWxLZXkgPSBkdW1teUtleTEuYml0Z28ucHVibGljS2V5LnN1YmFycmF5KDEsIDMzKTtcbmV4cG9ydCBjb25zdCBkdW1teVBhcnRpY2lwYW50UHViS2V5czogVHVwbGU8QnVmZmVyPiA9IFtkdW1teUtleTEudXNlci5wdWJsaWNLZXksIGR1bW15S2V5MS5iYWNrdXAucHVibGljS2V5XTtcbmV4cG9ydCBjb25zdCBkdW1teVB1Yk5vbmNlID0gQnVmZmVyLmNvbmNhdChbZHVtbXlLZXkyLnVzZXIucHVibGljS2V5LCBkdW1teUtleTIuYml0Z28ucHVibGljS2V5XSk7XG5leHBvcnQgY29uc3QgZHVtbXlBZ2dOb25jZSA9IEJ1ZmZlci5jb25jYXQoW2R1bW15S2V5Mi5iYWNrdXAucHVibGljS2V5LCBkdW1teUtleTIuYml0Z28ucHVibGljS2V5XSk7XG5leHBvcnQgY29uc3QgZHVtbXlQcml2YXRlS2V5ID0gZHVtbXlLZXkyLnVzZXIucHJpdmF0ZUtleSE7XG5leHBvcnQgY29uc3QgZHVtbXlQYXJ0aWFsU2lnID0gZHVtbXlLZXkyLmJhY2t1cC5wcml2YXRlS2V5ITtcblxuZXhwb3J0IGNvbnN0IGludmFsaWRUYXBPdXRwdXRLZXkgPSBCdWZmZXIuYWxsb2NVbnNhZmUoMSk7XG5leHBvcnQgY29uc3QgaW52YWxpZFRhcElucHV0S2V5ID0gQnVmZmVyLmFsbG9jVW5zYWZlKDEpO1xuZXhwb3J0IGNvbnN0IGludmFsaWRUeEhhc2ggPSBCdWZmZXIuYWxsb2NVbnNhZmUoMSk7XG5leHBvcnQgY29uc3QgaW52YWxpZFBhcnRpY2lwYW50UHViS2V5czogVHVwbGU8QnVmZmVyPiA9IFtCdWZmZXIuYWxsb2NVbnNhZmUoMSksIEJ1ZmZlci5hbGxvY1Vuc2FmZSgxKV07XG5leHBvcnQgY29uc3QgaW52YWxpZFBhcnRpYWxTaWcgPSBCdWZmZXIuYWxsb2NVbnNhZmUoMSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBjb25zdHJ1Y3RQc2J0KFxuICB1bnNwZW50czogKFVuc3BlbnQ8YmlnaW50PiAmIHsgcHJldlR4PzogQnVmZmVyIH0pW10sXG4gIHJvb3RXYWxsZXRLZXlzOiBSb290V2FsbGV0S2V5cyxcbiAgc2lnbmVyOiBLZXlOYW1lLFxuICBjb3NpZ25lcjogS2V5TmFtZSxcbiAgb3V0cHV0czogeyBjaGFpbjogQ2hhaW5Db2RlOyBpbmRleDogbnVtYmVyOyB2YWx1ZTogYmlnaW50IH1bXSB8IG91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTJPZjNcbik6IFV0eG9Qc2J0IHtcbiAgY29uc3QgcHNidCA9IGNyZWF0ZVBzYnRGb3JOZXR3b3JrKHsgbmV0d29yayB9KTtcblxuICBpZiAoQXJyYXkuaXNBcnJheShvdXRwdXRzKSkge1xuICAgIG91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiBhZGRXYWxsZXRPdXRwdXRUb1BzYnQocHNidCwgcm9vdFdhbGxldEtleXMsIG91dHB1dC5jaGFpbiwgb3V0cHV0LmluZGV4LCBvdXRwdXQudmFsdWUpKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB0b3RhbCA9IEJpZ0ludCh1bnNwZW50U3VtPGJpZ2ludD4odW5zcGVudHMsICdiaWdpbnQnKSk7XG4gICAgYWRkV2FsbGV0T3V0cHV0VG9Qc2J0KHBzYnQsIHJvb3RXYWxsZXRLZXlzLCBnZXRJbnRlcm5hbENoYWluQ29kZShvdXRwdXRzKSwgQ0hBTkdFX0lOREVYLCB0b3RhbCAtIEZFRSk7XG4gIH1cbiAgdW5zcGVudHMuZm9yRWFjaCgodSkgPT4ge1xuICAgIGlmIChpc1dhbGxldFVuc3BlbnQodSkpIHtcbiAgICAgIGFkZFdhbGxldFVuc3BlbnRUb1BzYnQocHNidCwgdSwgcm9vdFdhbGxldEtleXMsIHNpZ25lciwgY29zaWduZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB7IHJlZGVlbVNjcmlwdCB9ID0gY3JlYXRlT3V0cHV0U2NyaXB0UDJzaFAycGsocmVwbGF5UHJvdGVjdGlvbktleVBhaXIucHVibGljS2V5KTtcbiAgICAgIGFzc2VydC5vayhyZWRlZW1TY3JpcHQpO1xuICAgICAgYWRkUmVwbGF5UHJvdGVjdGlvblVuc3BlbnRUb1BzYnQocHNidCwgdSwgcmVkZWVtU2NyaXB0KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gcHNidDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVuc3BlbnRzKFxuICBpbnB1dFNjcmlwdFR5cGVzOiBTY3JpcHRUeXBlMk9mM1tdLFxuICByb290V2FsbGV0S2V5czogUm9vdFdhbGxldEtleXNcbik6IFdhbGxldFVuc3BlbnQ8YmlnaW50PltdIHtcbiAgcmV0dXJuIGlucHV0U2NyaXB0VHlwZXMubWFwKCh0LCBpKTogV2FsbGV0VW5zcGVudDxiaWdpbnQ+ID0+IHtcbiAgICBpZiAoIW91dHB1dFNjcmlwdHMuaXNTY3JpcHRUeXBlMk9mMyh0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGlucHV0IHR5cGUgJHt0fWApO1xuICAgIH1cbiAgICBjb25zdCB1bnNwZW50ID0gbW9ja1dhbGxldFVuc3BlbnQobmV0d29yaywgQmlnSW50KCcxMDAwMDAwMDAwMDAwMDAwMCcpLCB7XG4gICAgICBrZXlzOiByb290V2FsbGV0S2V5cyxcbiAgICAgIGNoYWluOiBnZXRFeHRlcm5hbENoYWluQ29kZSh0KSxcbiAgICAgIHZvdXQ6IGksXG4gICAgfSk7XG5cbiAgICBpZiAoaXNXYWxsZXRVbnNwZW50KHVuc3BlbnQpKSB7XG4gICAgICByZXR1cm4gdW5zcGVudDtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHVuc3BlbnQnKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBzYnRQMnRyTXVzaWcySW5wdXQoXG4gIHBzYnQ6IFV0eG9Qc2J0PFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+PixcbiAgaW5kZXg6IG51bWJlcixcbiAgdW5zcGVudDogV2FsbGV0VW5zcGVudDxiaWdpbnQ+LFxuICBzcGVuZFR5cGU6ICdrZXlQYXRoJyB8ICdzY3JpcHRQYXRoJ1xuKTogdm9pZCB7XG4gIGNvbnN0IGlucHV0ID0gcHNidC5kYXRhLmlucHV0c1tpbmRleF07XG4gIGFzc2VydC5zdHJpY3RFcXVhbChpbnB1dC50YXBCaXAzMkRlcml2YXRpb24/Lmxlbmd0aCwgMik7XG4gIGxldCBsZWFmSGFzaGVzQ291bnQgPSAwO1xuXG4gIGlmIChzcGVuZFR5cGUgPT09ICdrZXlQYXRoJykge1xuICAgIGNvbnN0IGlucHV0V2FsbGV0S2V5cyA9IHJvb3RXYWxsZXRLZXlzLmRlcml2ZUZvckNoYWluQW5kSW5kZXgodW5zcGVudC5jaGFpbiwgdW5zcGVudC5pbmRleCk7XG4gICAgY29uc3QgeyBpbnRlcm5hbFB1YmtleSwgdGFwdHJlZVJvb3QgfSA9IGNyZWF0ZUtleVBhdGhQMnRyTXVzaWcyKGlucHV0V2FsbGV0S2V5cy5wdWJsaWNLZXlzKTtcblxuICAgIGFzc2VydC5vayghaW5wdXQudGFwTGVhZlNjcmlwdCk7XG4gICAgYXNzZXJ0Lm9rKGlucHV0LnRhcEludGVybmFsS2V5KTtcbiAgICBhc3NlcnQub2soaW5wdXQudGFwTWVya2xlUm9vdCk7XG4gICAgYXNzZXJ0Lm9rKGlucHV0LnRhcEludGVybmFsS2V5LmVxdWFscyhpbnRlcm5hbFB1YmtleSkpO1xuICAgIGFzc2VydC5vayhpbnB1dC50YXBNZXJrbGVSb290LmVxdWFscyh0YXB0cmVlUm9vdCkpO1xuICB9IGVsc2Uge1xuICAgIGFzc2VydC5vayhpbnB1dC50YXBMZWFmU2NyaXB0KTtcbiAgICBhc3NlcnQub2soIWlucHV0LnRhcEludGVybmFsS2V5KTtcbiAgICBhc3NlcnQub2soIWlucHV0LnRhcE1lcmtsZVJvb3QpO1xuICAgIGxlYWZIYXNoZXNDb3VudCA9IDE7XG4gIH1cbiAgaW5wdXQudGFwQmlwMzJEZXJpdmF0aW9uPy5mb3JFYWNoKChidikgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChidi5sZWFmSGFzaGVzLmxlbmd0aCwgbGVhZkhhc2hlc0NvdW50KTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBzYnRQMnRyTXVzaWcyT3V0cHV0KHBzYnQ6IFV0eG9Qc2J0PFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+PiwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICBjb25zdCBvdXRwdXRXYWxsZXRLZXlzID0gcm9vdFdhbGxldEtleXMuZGVyaXZlRm9yQ2hhaW5BbmRJbmRleChnZXRJbnRlcm5hbENoYWluQ29kZShvdXRwdXRUeXBlKSwgQ0hBTkdFX0lOREVYKTtcbiAgY29uc3QgcGF5bWVudCA9IGNyZWF0ZVBheW1lbnRQMnRyTXVzaWcyKG91dHB1dFdhbGxldEtleXMucHVibGljS2V5cyk7XG4gIGNvbnN0IG91dHB1dCA9IHBzYnQuZGF0YS5vdXRwdXRzW2luZGV4XTtcbiAgYXNzZXJ0Lm9rKCEhcGF5bWVudC5pbnRlcm5hbFB1YmtleSk7XG4gIGFzc2VydC5vayghIW91dHB1dC50YXBJbnRlcm5hbEtleSk7XG4gIGFzc2VydC5vayhvdXRwdXQudGFwSW50ZXJuYWxLZXkuZXF1YWxzKHBheW1lbnQuaW50ZXJuYWxQdWJrZXkpKTtcbiAgYXNzZXJ0LnN0cmljdEVxdWFsKG91dHB1dC50YXBCaXAzMkRlcml2YXRpb24/Lmxlbmd0aCwgMyk7XG4gIG91dHB1dC50YXBCaXAzMkRlcml2YXRpb24/LmZvckVhY2goKGJ2KSA9PiB7XG4gICAgY29uc3QgbGVhZkhhc2hlc0NvdW50ID0gYnYucHVia2V5LmVxdWFscyh0b1hPbmx5UHVibGljS2V5KG91dHB1dFdhbGxldEtleXMuYmFja3VwLnB1YmxpY0tleSkpID8gMiA6IDE7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJ2LmxlYWZIYXNoZXMubGVuZ3RoLCBsZWFmSGFzaGVzQ291bnQpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTm9uY2VzS2V5VmFscyhcbiAgcHNidDogVXR4b1BzYnQ8VXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+LFxuICBpbmRleDogbnVtYmVyLFxuICB1bnNwZW50OiBXYWxsZXRVbnNwZW50PGJpZ2ludD5cbik6IHZvaWQge1xuICBjb25zdCBrZXlWYWxzID0gcHNidC5nZXRQcm9wcmlldGFyeUtleVZhbHMoaW5kZXgpO1xuICBjb25zdCB3YWxsZXRLZXlzID0gcm9vdFdhbGxldEtleXMuZGVyaXZlRm9yQ2hhaW5BbmRJbmRleCh1bnNwZW50LmNoYWluLCB1bnNwZW50LmluZGV4KTtcbiAgY29uc3QgeyBvdXRwdXRQdWJrZXkgfSA9IGNyZWF0ZUtleVBhdGhQMnRyTXVzaWcyKHdhbGxldEtleXMucHVibGljS2V5cyk7XG4gIGNvbnN0IHBhcnRpY2lwYW50UHViS2V5cyA9IFt3YWxsZXRLZXlzLnVzZXIucHVibGljS2V5LCB3YWxsZXRLZXlzLmJpdGdvLnB1YmxpY0tleV07XG5cbiAgY29uc3Qgbm9uY2VzID0ga2V5VmFscy5maWx0ZXIoKGt2KSA9PiBrdi5rZXkuc3VidHlwZSA9PT0gUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QVUJfTk9OQ0UpO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwobm9uY2VzLmxlbmd0aCwgMik7XG5cbiAgY29uc3Qgbm9uY2VLZXlkYXRhID0gcGFydGljaXBhbnRQdWJLZXlzLm1hcCgocCkgPT4ge1xuICAgIGNvbnN0IGtleWRhdGEgPSBCdWZmZXIuYWxsb2MoNjUpO1xuICAgIHAuY29weShrZXlkYXRhKTtcbiAgICBvdXRwdXRQdWJrZXkuY29weShrZXlkYXRhLCAzMyk7XG4gICAgcmV0dXJuIGtleWRhdGE7XG4gIH0pO1xuXG4gIG5vbmNlcy5mb3JFYWNoKChrdikgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChrdi5rZXkuaWRlbnRpZmllciwgUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoa3YudmFsdWUubGVuZ3RoLCA2Nik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKG5vbmNlS2V5ZGF0YS5maWx0ZXIoKGtkKSA9PiBrZC5lcXVhbHMoa3Yua2V5LmtleWRhdGEpKS5sZW5ndGgsIDEpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUGFydGlhbFNpZ0tleVZhbHMoXG4gIHBzYnQ6IFV0eG9Qc2J0PFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+PixcbiAgaW5kZXg6IG51bWJlcixcbiAgdW5zcGVudDogV2FsbGV0VW5zcGVudDxiaWdpbnQ+XG4pOiB2b2lkIHtcbiAgY29uc3Qga2V5VmFscyA9IHBzYnQuZ2V0UHJvcHJpZXRhcnlLZXlWYWxzKGluZGV4KTtcbiAgY29uc3QgaW5wdXRXYWxsZXRLZXlzID0gcm9vdFdhbGxldEtleXMuZGVyaXZlRm9yQ2hhaW5BbmRJbmRleCh1bnNwZW50LmNoYWluLCB1bnNwZW50LmluZGV4KTtcbiAgY29uc3QgeyBvdXRwdXRQdWJrZXkgfSA9IGNyZWF0ZUtleVBhdGhQMnRyTXVzaWcyKGlucHV0V2FsbGV0S2V5cy5wdWJsaWNLZXlzKTtcbiAgY29uc3QgcGFydGljaXBhbnRQdWJLZXlzID0gW2lucHV0V2FsbGV0S2V5cy51c2VyLnB1YmxpY0tleSwgaW5wdXRXYWxsZXRLZXlzLmJpdGdvLnB1YmxpY0tleV07XG5cbiAgY29uc3QgcGFydGlhbFNpZ3MgPSBrZXlWYWxzLmZpbHRlcigoa3YpID0+IGt2LmtleS5zdWJ0eXBlID09PSBQcm9wcmlldGFyeUtleVN1YnR5cGUuTVVTSUcyX1BBUlRJQUxfU0lHKTtcbiAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnRpYWxTaWdzLmxlbmd0aCwgMik7XG5cbiAgY29uc3QgcGFydGlhbFNpZ0tleWRhdGEgPSBwYXJ0aWNpcGFudFB1YktleXMubWFwKChwKSA9PiB7XG4gICAgY29uc3Qga2V5ZGF0YSA9IEJ1ZmZlci5hbGxvYyg2NSk7XG4gICAgcC5jb3B5KGtleWRhdGEpO1xuICAgIG91dHB1dFB1YmtleS5jb3B5KGtleWRhdGEsIDMzKTtcbiAgICByZXR1cm4ga2V5ZGF0YTtcbiAgfSk7XG5cbiAgcGFydGlhbFNpZ3MuZm9yRWFjaCgoa3YpID0+IHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoa3Yua2V5LmlkZW50aWZpZXIsIFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGt2LnZhbHVlLmxlbmd0aCwgMzIpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJ0aWFsU2lnS2V5ZGF0YS5maWx0ZXIoKGtkKSA9PiBrZC5lcXVhbHMoa3Yua2V5LmtleWRhdGEpKS5sZW5ndGgsIDEpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUGFydGljaXBhbnRzS2V5VmFscyhcbiAgcHNidDogVXR4b1BzYnQ8VXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+LFxuICBpbmRleDogbnVtYmVyLFxuICB1bnNwZW50OiBXYWxsZXRVbnNwZW50PGJpZ2ludD5cbik6IHZvaWQge1xuICBjb25zdCBrZXlWYWxzID0gcHNidC5nZXRQcm9wcmlldGFyeUtleVZhbHMoaW5kZXgpO1xuICBjb25zdCB3YWxsZXRLZXlzID0gcm9vdFdhbGxldEtleXMuZGVyaXZlRm9yQ2hhaW5BbmRJbmRleCh1bnNwZW50LmNoYWluLCB1bnNwZW50LmluZGV4KTtcbiAgY29uc3QgeyBpbnRlcm5hbFB1YmtleSwgb3V0cHV0UHVia2V5IH0gPSBjcmVhdGVLZXlQYXRoUDJ0ck11c2lnMih3YWxsZXRLZXlzLnB1YmxpY0tleXMpO1xuICBjb25zdCBwYXJ0aWNpcGFudFB1YktleXMgPSBbd2FsbGV0S2V5cy51c2VyLnB1YmxpY0tleSwgd2FsbGV0S2V5cy5iaXRnby5wdWJsaWNLZXldO1xuXG4gIGNvbnN0IHBhcnRpY2lwYW50c0tleVZhbHMgPSBrZXlWYWxzLmZpbHRlcihcbiAgICAoa3YpID0+IGt2LmtleS5zdWJ0eXBlID09PSBQcm9wcmlldGFyeUtleVN1YnR5cGUuTVVTSUcyX1BBUlRJQ0lQQU5UX1BVQl9LRVlTXG4gICk7XG4gIGFzc2VydC5zdHJpY3RFcXVhbChwYXJ0aWNpcGFudHNLZXlWYWxzLmxlbmd0aCwgMSk7XG5cbiAgY29uc3Qga3YgPSBwYXJ0aWNpcGFudHNLZXlWYWxzWzBdO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwoa3Yua2V5LmlkZW50aWZpZXIsIFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUik7XG4gIGFzc2VydC5vayhCdWZmZXIuY29uY2F0KFtvdXRwdXRQdWJrZXksIGludGVybmFsUHVia2V5XSkuZXF1YWxzKGt2LmtleS5rZXlkYXRhKSk7XG4gIGNvbnN0IHZhbHVlTWF0Y2ggPSBbQnVmZmVyLmNvbmNhdChwYXJ0aWNpcGFudFB1YktleXMpLCBCdWZmZXIuY29uY2F0KHBhcnRpY2lwYW50UHViS2V5cy5yZXZlcnNlKCkpXS5zb21lKChwa3MpID0+IHtcbiAgICByZXR1cm4gcGtzLmVxdWFscyhrdi52YWx1ZSk7XG4gIH0pO1xuICBhc3NlcnQub2sodmFsdWVNYXRjaCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUZpbmFsaXplZElucHV0KFxuICBwc2J0OiBVdHhvUHNidDxVdHhvVHJhbnNhY3Rpb248YmlnaW50Pj4sXG4gIGluZGV4OiBudW1iZXIsXG4gIHVuc3BlbnQ6IFdhbGxldFVuc3BlbnQ8YmlnaW50PixcbiAgc3BlbmRUeXBlPzogJ2tleVBhdGgnIHwgJ3NjcmlwdFBhdGgnXG4pOiB2b2lkIHtcbiAgY29uc3QgaW5wdXQgPSBwc2J0LmRhdGEuaW5wdXRzW2luZGV4XTtcbiAgYXNzZXJ0Lm9rKGlzUHNidElucHV0RmluYWxpemVkKGlucHV0KSk7XG4gIGlmIChzY3JpcHRUeXBlRm9yQ2hhaW4odW5zcGVudC5jaGFpbikgPT09ICdwMnRyTXVzaWcyJyAmJiBzcGVuZFR5cGUgPT09ICdrZXlQYXRoJykge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChpbnB1dC5maW5hbFNjcmlwdFdpdG5lc3M/Lmxlbmd0aCwgNjYpO1xuICB9XG4gIGFzc2VydC5vayghaW5wdXQudW5rbm93bktleVZhbHM/Lmxlbmd0aCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBhcnNlZFRhcHJvb3RLZXlQYXRoUHNidChcbiAgcHNidDogVXR4b1BzYnQ8VXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+LFxuICBpbmRleDogbnVtYmVyLFxuICBzaWduYXR1cmU6ICd1bnNpZ25lZCcgfCAnaGFsZnNpZ25lZCcgfCAnZnVsbHlzaWduZWQnXG4pOiB2b2lkIHtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VQc2J0SW5wdXQocHNidC5kYXRhLmlucHV0c1swXSk7XG4gIGFzc2VydC5vayhwYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnKTtcbiAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5wdWJTY3JpcHQubGVuZ3RoLCAzNCk7XG4gIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQucHVibGljS2V5cy5sZW5ndGgsIDEpO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnB1YmxpY0tleXNbMF0ubGVuZ3RoLCAzMik7XG5cbiAgaWYgKHNpZ25hdHVyZSA9PT0gJ3Vuc2lnbmVkJykge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQuc2lnbmF0dXJlcywgdW5kZWZpbmVkKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnBhcnRpY2lwYW50UHVibGljS2V5cywgdW5kZWZpbmVkKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBleHBlY3RlZCA9IHNpZ25hdHVyZSA9PT0gJ2hhbGZzaWduZWQnID8gMSA6IDI7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5zaWduYXR1cmVzPy5sZW5ndGgsIGV4cGVjdGVkKTtcbiAgICBwYXJzZWQuc2lnbmF0dXJlcy5mb3JFYWNoKChzaWcpID0+IHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWcubGVuZ3RoLCAzMik7XG4gICAgfSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5wYXJ0aWNpcGFudFB1YmxpY0tleXM/Lmxlbmd0aCwgZXhwZWN0ZWQpO1xuICAgIHBhcnNlZC5wYXJ0aWNpcGFudFB1YmxpY0tleXMuZm9yRWFjaCgocGspID0+IHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChway5sZW5ndGgsIDMzKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVQYXJzZWRUYXByb290U2NyaXB0UGF0aFBzYnQoXG4gIHBzYnQ6IFV0eG9Qc2J0PFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+PixcbiAgaW5kZXg6IG51bWJlcixcbiAgc2lnbmF0dXJlOiAndW5zaWduZWQnIHwgJ2hhbGZzaWduZWQnIHwgJ2Z1bGx5c2lnbmVkJ1xuKTogdm9pZCB7XG4gIGNvbnN0IGlucHV0ID0gcHNidC5kYXRhLmlucHV0c1tpbmRleF07XG4gIGNvbnN0IHBhcnNlZCA9IHBhcnNlUHNidElucHV0KHBzYnQuZGF0YS5pbnB1dHNbMF0pO1xuICBhc3NlcnQub2socGFyc2VkLnNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJyk7XG4gIGFzc2VydC5vayhpbnB1dC50YXBMZWFmU2NyaXB0KTtcbiAgYXNzZXJ0Lm9rKHBhcnNlZC5wdWJTY3JpcHQuZXF1YWxzKGlucHV0LnRhcExlYWZTY3JpcHRbMF0uc2NyaXB0KSk7XG4gIGFzc2VydC5vayhwYXJzZWQuY29udHJvbEJsb2NrLmVxdWFscyhpbnB1dC50YXBMZWFmU2NyaXB0WzBdLmNvbnRyb2xCbG9jaykpO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnNjcmlwdFBhdGhMZXZlbCwgMSk7XG4gIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubGVhZlZlcnNpb24sIGlucHV0LnRhcExlYWZTY3JpcHRbMF0ubGVhZlZlcnNpb24pO1xuICBwYXJzZWQucHVibGljS2V5cy5mb3JFYWNoKChwaykgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChway5sZW5ndGgsIDMyKTtcbiAgfSk7XG4gIGlmIChzaWduYXR1cmUgPT09ICd1bnNpZ25lZCcpIHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnNpZ25hdHVyZXMsIHVuZGVmaW5lZCk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgZXhwZWN0ZWQgPSBzaWduYXR1cmUgPT09ICdoYWxmc2lnbmVkJyA/IDEgOiAyO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQuc2lnbmF0dXJlcz8ubGVuZ3RoLCBleHBlY3RlZCk7XG4gICAgcGFyc2VkLnNpZ25hdHVyZXMuZm9yRWFjaCgoc2lnKSA9PiB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnLmxlbmd0aCwgNjQpO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBhcnNlZFRhcHJvb3RLZXlQYXRoVHhJbnB1dChcbiAgcHNidDogVXR4b1BzYnQ8VXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+LFxuICB0eDogVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD5cbik6IHZvaWQge1xuICBjb25zdCBwYXJzZWRUeElucHV0ID0gcGFyc2VTaWduYXR1cmVTY3JpcHQyT2YzKHR4Lmluc1swXSk7XG4gIGFzc2VydC5vayhwYXJzZWRUeElucHV0LnNjcmlwdFR5cGUgPT09ICd0YXByb290S2V5UGF0aFNwZW5kJyk7XG4gIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWRUeElucHV0LnNpZ25hdHVyZXMubGVuZ3RoLCAxKTtcbiAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZFR4SW5wdXQuc2lnbmF0dXJlc1swXS5sZW5ndGgsIDY0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUGFyc2VkVGFwcm9vdFNjcmlwdFBhdGhUeElucHV0KFxuICBwc2J0OiBVdHhvUHNidDxVdHhvVHJhbnNhY3Rpb248YmlnaW50Pj4sXG4gIHR4OiBVdHhvVHJhbnNhY3Rpb248YmlnaW50PixcbiAgaW5kZXg6IG51bWJlclxuKTogdm9pZCB7XG4gIGNvbnN0IGlucHV0ID0gcHNidC5kYXRhLmlucHV0c1tpbmRleF07XG4gIGNvbnN0IHBhcnNlZFR4SW5wdXQgPSBwYXJzZVNpZ25hdHVyZVNjcmlwdDJPZjModHguaW5zWzBdKTtcbiAgYXNzZXJ0Lm9rKHBhcnNlZFR4SW5wdXQpO1xuICBhc3NlcnQub2socGFyc2VkVHhJbnB1dC5zY3JpcHRUeXBlID09PSAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCcpO1xuICBhc3NlcnQub2soaW5wdXQudGFwTGVhZlNjcmlwdCk7XG4gIGFzc2VydC5vayhwYXJzZWRUeElucHV0LnB1YlNjcmlwdC5lcXVhbHMoaW5wdXQudGFwTGVhZlNjcmlwdFswXS5zY3JpcHQpKTtcbiAgYXNzZXJ0Lm9rKHBhcnNlZFR4SW5wdXQuY29udHJvbEJsb2NrLmVxdWFscyhpbnB1dC50YXBMZWFmU2NyaXB0WzBdLmNvbnRyb2xCbG9jaykpO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkVHhJbnB1dC5zY3JpcHRQYXRoTGV2ZWwsIDEpO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkVHhJbnB1dC5sZWFmVmVyc2lvbiwgaW5wdXQudGFwTGVhZlNjcmlwdFswXS5sZWFmVmVyc2lvbik7XG4gIHBhcnNlZFR4SW5wdXQucHVibGljS2V5cy5mb3JFYWNoKChwaykgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChway5sZW5ndGgsIDMyKTtcbiAgfSk7XG4gIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWRUeElucHV0LnNpZ25hdHVyZXM/Lmxlbmd0aCwgMik7XG4gIHBhcnNlZFR4SW5wdXQuc2lnbmF0dXJlcy5mb3JFYWNoKChzaWcpID0+IHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnLmxlbmd0aCwgNjQpO1xuICB9KTtcbn1cbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!