PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-lib/dist/test/bitgo/psbt
Просмотр файла: psbtUtil.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validatePsbtParsing = validatePsbtParsing;
exports.assertEqualTransactions = assertEqualTransactions;
exports.toBigInt = toBigInt;
exports.signPsbt = signPsbt;
exports.signTxBuilder = signTxBuilder;
exports.constructTransactionUsingTxBuilder = constructTransactionUsingTxBuilder;
const bitgo_1 = require("../../../src/bitgo");
const Psbt_1 = require("../../../src/bitgo/wallet/Psbt");
const assert = require("assert");
function validateScript(psbtParsed, txParsed) {
if (txParsed === undefined) {
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.pubScript), true);
if (psbtParsed.scriptType === 'p2sh') {
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.redeemScript), true);
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.witnessScript), false);
}
else if (psbtParsed.scriptType === 'p2wsh') {
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.redeemScript), false);
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.witnessScript), true);
}
else if (psbtParsed.scriptType === 'p2shP2wsh') {
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.redeemScript), true);
assert.deepStrictEqual(Buffer.isBuffer(psbtParsed.witnessScript), true);
}
else if (psbtParsed.scriptType === 'taprootScriptPathSpend') {
assert.deepStrictEqual((0, bitgo_1.isValidControlBock)(psbtParsed.controlBlock), true);
assert.deepStrictEqual(psbtParsed.scriptPathLevel, (0, bitgo_1.calculateScriptPathLevel)(psbtParsed.controlBlock));
assert.deepStrictEqual(psbtParsed.leafVersion, (0, bitgo_1.getLeafVersion)(psbtParsed.controlBlock));
}
}
else {
assert.ok(txParsed.scriptType !== 'taprootKeyPathSpend');
assert.deepStrictEqual(txParsed.scriptType, psbtParsed.scriptType);
assert.deepStrictEqual(txParsed.pubScript, psbtParsed.pubScript);
if ((txParsed.scriptType === 'p2sh' && psbtParsed.scriptType === 'p2sh') ||
(txParsed.scriptType === 'p2wsh' && psbtParsed.scriptType === 'p2wsh') ||
(txParsed.scriptType === 'p2shP2wsh' && psbtParsed.scriptType === 'p2shP2wsh')) {
assert.deepStrictEqual(txParsed.redeemScript, psbtParsed.redeemScript);
assert.deepStrictEqual(txParsed.witnessScript, psbtParsed.witnessScript);
}
else if (txParsed.scriptType === 'taprootScriptPathSpend' && psbtParsed.scriptType === 'taprootScriptPathSpend') {
// To ensure script path p2tr
assert.deepStrictEqual(txParsed.publicKeys, psbtParsed.publicKeys);
const txParsedP2trScriptPath = txParsed;
assert.deepStrictEqual(txParsedP2trScriptPath.controlBlock, psbtParsed.controlBlock);
assert.deepStrictEqual(txParsedP2trScriptPath.scriptPathLevel, psbtParsed.scriptPathLevel);
assert.deepStrictEqual(txParsedP2trScriptPath.leafVersion, psbtParsed.leafVersion);
}
}
}
function validatePublicKeys(psbtParsed, txParsed) {
if (txParsed === undefined) {
assert.deepStrictEqual(psbtParsed.publicKeys.length, 3);
psbtParsed.publicKeys.forEach((publicKey) => {
assert.deepStrictEqual(Buffer.isBuffer(publicKey), true);
});
}
else {
assert.ok(txParsed.scriptType !== 'taprootKeyPathSpend');
assert.deepStrictEqual(txParsed.publicKeys.length, psbtParsed.publicKeys?.length);
const pubKeyMatch = txParsed.publicKeys.every((txPubKey) => psbtParsed.publicKeys?.some((psbtPubKey) => psbtPubKey.equals(txPubKey)));
assert.deepStrictEqual(pubKeyMatch, true);
}
}
function validateSignature(psbtParsed, txParsed) {
if (txParsed === undefined) {
assert.deepStrictEqual(psbtParsed.signatures, undefined);
}
else {
const txSignatures = txParsed.signatures.filter((txSig) => Buffer.isBuffer(txSig) && !(0, bitgo_1.isPlaceholderSignature)(txSig));
assert.deepStrictEqual(txSignatures.length, psbtParsed.signatures?.length);
if (txSignatures.length < 1) {
return;
}
const sigMatch = txSignatures.every((txSig) => Buffer.isBuffer(txSig) ? psbtParsed.signatures?.some((psbtSig) => psbtSig.equals(txSig)) : true);
assert.deepStrictEqual(sigMatch, true);
}
}
function validatePsbtParsing(tx, psbt, unspents, signatureTarget) {
unspents.forEach((u, i) => {
if (!(0, bitgo_1.isWalletUnspent)(u)) {
return;
}
const scriptType = (0, bitgo_1.scriptTypeForChain)(u.chain);
if (signatureTarget === 'unsigned') {
if (scriptType === 'p2tr') {
assert.throws(() => (0, Psbt_1.parsePsbtInput)(psbt.data.inputs[i]), (e) => e.message === 'could not parse input');
}
else {
const psbtParsed = (0, Psbt_1.parsePsbtInput)(psbt.data.inputs[i]);
assert.deepStrictEqual(psbtParsed.scriptType, scriptType);
validateScript(psbtParsed, undefined);
validatePublicKeys(psbtParsed, undefined);
validateSignature(psbtParsed, undefined);
}
}
else {
const psbtParsed = (0, Psbt_1.parsePsbtInput)(psbt.data.inputs[i]);
assert.strictEqual(psbtParsed.scriptType, scriptType === 'p2tr' ? 'taprootScriptPathSpend' : scriptType);
const txParsed = (0, bitgo_1.parseSignatureScript2Of3)(tx.ins[i]);
validateScript(psbtParsed, txParsed);
validatePublicKeys(psbtParsed, txParsed);
validateSignature(psbtParsed, txParsed);
}
});
}
function assertEqualTransactions(txOne, txTwo) {
assert.ok(txOne.network === txTwo.network);
assert.ok(txOne.getId() === txTwo.getId());
assert.ok(txOne.toHex() === txTwo.toHex());
assert.ok(txOne.virtualSize() === txTwo.virtualSize());
assert.ok(txOne.locktime === txTwo.locktime);
assert.ok(txOne.version === txTwo.version);
assert.ok(txOne.weight() === txTwo.weight());
assert.ok(txOne.ins.length === txTwo.ins.length);
assert.ok(txOne.outs.length === txTwo.outs.length);
txOne.ins.forEach((_, i) => {
const parsedInputOne = (0, bitgo_1.parseSignatureScript2Of3)(txOne.ins[i]);
const parsedInputTwo = (0, bitgo_1.parseSignatureScript2Of3)(txTwo.ins[i]);
assert.deepStrictEqual(parsedInputOne, parsedInputTwo);
});
txOne.outs.forEach((_, i) => {
assert.deepStrictEqual(txOne.outs[i], txTwo.outs[i]);
});
assert.ok(txOne.toBuffer().equals(txTwo.toBuffer()));
}
function toBigInt(unspents) {
return unspents.map((u) => {
if ((0, bitgo_1.isWalletUnspent)(u)) {
return { ...u, value: BigInt(u.value) };
}
throw new Error('invalid unspent');
});
}
function signPsbt(psbt, unspents, rootWalletKeys, signer, cosigner, signatureTarget) {
unspents.forEach((u, i) => {
if (!(0, bitgo_1.isWalletUnspent)(u)) {
throw new Error('invalid unspent');
}
try {
if (signatureTarget === 'unsigned') {
(0, Psbt_1.signWalletPsbt)(psbt, i, rootWalletKeys[signer], u);
}
(0, Psbt_1.signWalletPsbt)(psbt, i, rootWalletKeys[cosigner], u);
}
catch (err) {
assert.deepStrictEqual(signatureTarget, 'unsigned');
assert.deepStrictEqual((0, bitgo_1.scriptTypeForChain)(u.chain), 'p2tr');
assert.deepStrictEqual(psbt.data.inputs[i].tapLeafScript, undefined);
assert.deepStrictEqual(psbt.data.inputs[i].tapBip32Derivation, undefined);
assert.deepStrictEqual(psbt.data.inputs[i].tapScriptSig, undefined);
assert.ok(psbt.data.inputs[i].witnessUtxo);
}
});
}
function signTxBuilder(txb, unspents, rootWalletKeys, signer, cosigner, signatureTarget) {
let walletUnspentSigners = [];
if (signatureTarget === 'halfsigned') {
walletUnspentSigners = [bitgo_1.WalletUnspentSigner.from(rootWalletKeys, rootWalletKeys[signer], rootWalletKeys[cosigner])];
}
else if (signatureTarget === 'fullsigned') {
walletUnspentSigners = [
bitgo_1.WalletUnspentSigner.from(rootWalletKeys, rootWalletKeys[signer], rootWalletKeys[cosigner]),
bitgo_1.WalletUnspentSigner.from(rootWalletKeys, rootWalletKeys[cosigner], rootWalletKeys[signer]),
];
}
walletUnspentSigners.forEach((walletSigner, nSignature) => {
unspents.forEach((u, i) => {
if ((0, bitgo_1.isWalletUnspent)(u)) {
(0, bitgo_1.signInputWithUnspent)(txb, i, u, walletSigner);
}
else {
throw new Error(`unexpected unspent ${u.id}`);
}
});
});
return signatureTarget === 'fullsigned' ? txb.build() : txb.buildIncomplete();
}
function constructTransactionUsingTxBuilder(unspents, rootWalletKeys, params) {
const txb = (0, bitgo_1.createTransactionBuilderForNetwork)(params.network);
const total = BigInt((0, bitgo_1.unspentSum)(unspents, params.amountType));
// Kinda weird, treating entire value as change, but tests the relevant paths
txb.addOutput((0, bitgo_1.getWalletAddress)(rootWalletKeys, (0, bitgo_1.getInternalChainCode)(params.outputType), params.changeIndex, params.network), (0, bitgo_1.toTNumber)(total - params.fee, params.amountType));
unspents.forEach((u) => {
(0, bitgo_1.addToTransactionBuilder)(txb, u);
});
return signTxBuilder(txb, unspents, rootWalletKeys, params.signer, params.cosigner, params.signatureTarget).clone('bigint');
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHNidFV0aWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L2JpdGdvL3BzYnQvcHNidFV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF1SEEsa0RBa0NDO0FBRUQsMERBdUJDO0FBRUQsNEJBT0M7QUFFRCw0QkEwQkM7QUFFRCxzQ0E4QkM7QUFFRCxnRkFpQ0M7QUExUkQsOENBNkI0QjtBQUM1Qix5REFBZ0Y7QUFDaEYsaUNBQWlDO0FBSWpDLFNBQVMsY0FBYyxDQUNyQixVQUE4QyxFQUM5QyxRQUE4RTtJQUU5RSxJQUFJLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMzQixNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXBFLElBQUksVUFBVSxDQUFDLFVBQVUsS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUNyQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3ZFLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDM0UsQ0FBQzthQUFNLElBQUksVUFBVSxDQUFDLFVBQVUsS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUM3QyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3hFLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDMUUsQ0FBQzthQUFNLElBQUksVUFBVSxDQUFDLFVBQVUsS0FBSyxXQUFXLEVBQUUs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QUFHLElBQUEsMENBQWtDLEVBQVUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hFLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFBLGtCQUFVLEVBQVUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3ZFLDZFQUE2RTtJQUM3RSxHQUFHLENBQUMsU0FBUyxDQUNYLElBQUEsd0JBQWdCLEVBQUMsY0FBYyxFQUFFLElBQUEsNEJBQW9CLEVBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUM3RyxJQUFBLGlCQUFTLEVBQVUsS0FBSyxHQUFHLE1BQU0sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUMxRCxDQUFDO0lBQ0YsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3JCLElBQUEsK0JBQXVCLEVBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxhQUFhLENBQ2xCLEdBQUcsRUFDSCxRQUFRLEVBQ1IsY0FBYyxFQUNkLE1BQU0sQ0FBQyxNQUFNLEVBQ2IsTUFBTSxDQUFDLFFBQVEsRUFDZixNQUFNLENBQUMsZUFBZSxDQUN2QixDQUFDLEtBQUssQ0FBUyxRQUFRLENBQUMsQ0FBQztBQUM1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgYWRkVG9UcmFuc2FjdGlvbkJ1aWxkZXIsXG4gIGdldExlYWZWZXJzaW9uLFxuICBjYWxjdWxhdGVTY3JpcHRQYXRoTGV2ZWwsXG4gIGNyZWF0ZVRyYW5zYWN0aW9uQnVpbGRlckZvck5ldHdvcmssXG4gIGdldEludGVybmFsQ2hhaW5Db2RlLFxuICBnZXRXYWxsZXRBZGRyZXNzLFxuICBpc1BsYWNlaG9sZGVyU2lnbmF0dXJlLFxuICBpc1ZhbGlkQ29udHJvbEJvY2ssXG4gIGlzV2FsbGV0VW5zcGVudCxcbiAgb3V0cHV0U2NyaXB0cyxcbiAgUGFyc2VkU2lnbmF0dXJlU2NyaXB0UDJtcyxcbiAgUGFyc2VkU2lnbmF0dXJlU2NyaXB0VGFwcm9vdCxcbiAgUGFyc2VkU2lnbmF0dXJlU2NyaXB0VGFwcm9vdFNjcmlwdFBhdGgsXG4gIHBhcnNlU2lnbmF0dXJlU2NyaXB0Mk9mMyxcbiAgUm9vdFdhbGxldEtleXMsXG4gIHNjcmlwdFR5cGVGb3JDaGFpbixcbiAgc2lnbklucHV0V2l0aFVuc3BlbnQsXG4gIHRvVE51bWJlcixcbiAgVW5zcGVudCxcbiAgdW5zcGVudFN1bSxcbiAgVXR4b1BzYnQsXG4gIFV0eG9UcmFuc2FjdGlvbixcbiAgVXR4b1RyYW5zYWN0aW9uQnVpbGRlcixcbiAgV2FsbGV0VW5zcGVudCxcbiAgV2FsbGV0VW5zcGVudFNpZ25lcixcbiAgS2V5TmFtZSxcbiAgUGFyc2VkUHNidFAybXMsXG4gIFBhcnNlZFBzYnRUYXByb290LFxufSBmcm9tICcuLi8uLi8uLi9zcmMvYml0Z28nO1xuaW1wb3J0IHsgcGFyc2VQc2J0SW5wdXQsIHNpZ25XYWxsZXRQc2J0IH0gZnJvbSAnLi4vLi4vLi4vc3JjL2JpdGdvL3dhbGxldC9Qc2J0JztcbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgU2lnbmF0dXJlVGFyZ2V0VHlwZSB9IGZyb20gJy4vUHNidCc7XG5pbXBvcnQgeyBOZXR3b3JrIH0gZnJvbSAnLi4vLi4vLi4vc3JjJztcblxuZnVuY3Rpb24gdmFsaWRhdGVTY3JpcHQoXG4gIHBzYnRQYXJzZWQ6IFBhcnNlZFBzYnRQMm1zIHwgUGFyc2VkUHNidFRhcHJvb3QsXG4gIHR4UGFyc2VkOiBQYXJzZWRTaWduYXR1cmVTY3JpcHRQMm1zIHwgUGFyc2VkU2lnbmF0dXJlU2NyaXB0VGFwcm9vdCB8IHVuZGVmaW5lZFxuKSB7XG4gIGlmICh0eFBhcnNlZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChCdWZmZXIuaXNCdWZmZXIocHNidFBhcnNlZC5wdWJTY3JpcHQpLCB0cnVlKTtcblxuICAgIGlmIChwc2J0UGFyc2VkLnNjcmlwdFR5cGUgPT09ICdwMnNoJykge1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChCdWZmZXIuaXNCdWZmZXIocHNidFBhcnNlZC5yZWRlZW1TY3JpcHQpLCB0cnVlKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoQnVmZmVyLmlzQnVmZmVyKHBzYnRQYXJzZWQud2l0bmVzc1NjcmlwdCksIGZhbHNlKTtcbiAgICB9IGVsc2UgaWYgKHBzYnRQYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3Ayd3NoJykge1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChCdWZmZXIuaXNCdWZmZXIocHNidFBhcnNlZC5yZWRlZW1TY3JpcHQpLCBmYWxzZSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKEJ1ZmZlci5pc0J1ZmZlcihwc2J0UGFyc2VkLndpdG5lc3NTY3JpcHQpLCB0cnVlKTtcbiAgICB9IGVsc2UgaWYgKHBzYnRQYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMndzaCcpIHtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoQnVmZmVyLmlzQnVmZmVyKHBzYnRQYXJzZWQucmVkZWVtU2NyaXB0KSwgdHJ1ZSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKEJ1ZmZlci5pc0J1ZmZlcihwc2J0UGFyc2VkLndpdG5lc3NTY3JpcHQpLCB0cnVlKTtcbiAgICB9IGVsc2UgaWYgKHBzYnRQYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RTY3JpcHRQYXRoU3BlbmQnKSB7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGlzVmFsaWRDb250cm9sQm9jayhwc2J0UGFyc2VkLmNvbnRyb2xCbG9jayksIHRydWUpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwc2J0UGFyc2VkLnNjcmlwdFBhdGhMZXZlbCwgY2FsY3VsYXRlU2NyaXB0UGF0aExldmVsKHBzYnRQYXJzZWQuY29udHJvbEJsb2NrKSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBzYnRQYXJzZWQubGVhZlZlcnNpb24sIGdldExlYWZWZXJzaW9uKHBzYnRQYXJzZWQuY29udHJvbEJsb2NrKSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGFzc2VydC5vayh0eFBhcnNlZC5zY3JpcHRUeXBlICE9PSAndGFwcm9vdEtleVBhdGhTcGVuZCcpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWQuc2NyaXB0VHlwZSwgcHNidFBhcnNlZC5zY3JpcHRUeXBlKTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHR4UGFyc2VkLnB1YlNjcmlwdCwgcHNidFBhcnNlZC5wdWJTY3JpcHQpO1xuXG4gICAgaWYgKFxuICAgICAgKHR4UGFyc2VkLnNjcmlwdFR5cGUgPT09ICdwMnNoJyAmJiBwc2J0UGFyc2VkLnNjcmlwdFR5cGUgPT09ICdwMnNoJykgfHxcbiAgICAgICh0eFBhcnNlZC5zY3JpcHRUeXBlID09PSAncDJ3c2gnICYmIHBzYnRQYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3Ayd3NoJykgfHxcbiAgICAgICh0eFBhcnNlZC5zY3JpcHRUeXBlID09PSAncDJzaFAyd3NoJyAmJiBwc2J0UGFyc2VkLnNjcmlwdFR5cGUgPT09ICdwMnNoUDJ3c2gnKVxuICAgICkge1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0eFBhcnNlZC5yZWRlZW1TY3JpcHQsIHBzYnRQYXJzZWQucmVkZWVtU2NyaXB0KTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWQud2l0bmVzc1NjcmlwdCwgcHNidFBhcnNlZC53aXRuZXNzU2NyaXB0KTtcbiAgICB9IGVsc2UgaWYgKHR4UGFyc2VkLnNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJyAmJiBwc2J0UGFyc2VkLnNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJykge1xuICAgICAgLy8gVG8gZW5zdXJlIHNjcmlwdCBwYXRoIHAydHJcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWQucHVibGljS2V5cywgcHNidFBhcnNlZC5wdWJsaWNLZXlzKTtcbiAgICAgIGNvbnN0IHR4UGFyc2VkUDJ0clNjcmlwdFBhdGggPSB0eFBhcnNlZCBhcyBQYXJzZWRTaWduYXR1cmVTY3JpcHRUYXByb290U2NyaXB0UGF0aDtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWRQMnRyU2NyaXB0UGF0aC5jb250cm9sQmxvY2ssIHBzYnRQYXJzZWQuY29udHJvbEJsb2NrKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWRQMnRyU2NyaXB0UGF0aC5zY3JpcHRQYXRoTGV2ZWwsIHBzYnRQYXJzZWQuc2NyaXB0UGF0aExldmVsKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWRQMnRyU2NyaXB0UGF0aC5sZWFmVmVyc2lvbiwgcHNidFBhcnNlZC5sZWFmVmVyc2lvbik7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlUHVibGljS2V5cyhcbiAgcHNidFBhcnNlZDogUGFyc2VkUHNidFAybXMgfCBQYXJzZWRQc2J0VGFwcm9vdCxcbiAgdHhQYXJzZWQ6IFBhcnNlZFNpZ25hdHVyZVNjcmlwdFAybXMgfCBQYXJzZWRTaWduYXR1cmVTY3JpcHRUYXByb290IHwgdW5kZWZpbmVkXG4pIHtcbiAgaWYgKHR4UGFyc2VkID09PSB1bmRlZmluZWQpIHtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBzYnRQYXJzZWQucHVibGljS2V5cy5sZW5ndGgsIDMpO1xuICAgIHBzYnRQYXJzZWQucHVibGljS2V5cy5mb3JFYWNoKChwdWJsaWNLZXkpID0+IHtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoQnVmZmVyLmlzQnVmZmVyKHB1YmxpY0tleSksIHRydWUpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGFzc2VydC5vayh0eFBhcnNlZC5zY3JpcHRUeXBlICE9PSAndGFwcm9vdEtleVBhdGhTcGVuZCcpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhQYXJzZWQucHVibGljS2V5cy5sZW5ndGgsIHBzYnRQYXJzZWQucHVibGljS2V5cz8ubGVuZ3RoKTtcbiAgICBjb25zdCBwdWJLZXlNYXRjaCA9IHR4UGFyc2VkLnB1YmxpY0tleXMuZXZlcnkoKHR4UHViS2V5KSA9PlxuICAgICAgcHNidFBhcnNlZC5wdWJsaWNLZXlzPy5zb21lKChwc2J0UHViS2V5KSA9PiBwc2J0UHViS2V5LmVxdWFscyh0eFB1YktleSkpXG4gICAgKTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHB1YktleU1hdGNoLCB0cnVlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZVNpZ25hdHVyZShcbiAgcHNidFBhcnNlZDogUGFyc2VkUHNidFAybXMgfCBQYXJzZWRQc2J0VGFwcm9vdCxcbiAgdHhQYXJzZWQ6IFBhcnNlZFNpZ25hdHVyZVNjcmlwdFAybXMgfCBQYXJzZWRTaWduYXR1cmVTY3JpcHRUYXByb290IHwgdW5kZWZpbmVkXG4pIHtcbiAgaWYgKHR4UGFyc2VkID09PSB1bmRlZmluZWQpIHtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBzYnRQYXJzZWQuc2lnbmF0dXJlcywgdW5kZWZpbmVkKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB0eFNpZ25hdHVyZXMgPSB0eFBhcnNlZC5zaWduYXR1cmVzLmZpbHRlcihcbiAgICAgICh0eFNpZykgPT4gQnVmZmVyLmlzQnVmZmVyKHR4U2lnKSAmJiAhaXNQbGFjZWhvbGRlclNpZ25hdHVyZSh0eFNpZylcbiAgICApO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHhTaWduYXR1cmVzLmxlbmd0aCwgcHNidFBhcnNlZC5zaWduYXR1cmVzPy5sZW5ndGgpO1xuICAgIGlmICh0eFNpZ25hdHVyZXMubGVuZ3RoIDwgMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzaWdNYXRjaCA9IHR4U2lnbmF0dXJlcy5ldmVyeSgodHhTaWcpID0+XG4gICAgICBCdWZmZXIuaXNCdWZmZXIodHhTaWcpID8gcHNidFBhcnNlZC5zaWduYXR1cmVzPy5zb21lKChwc2J0U2lnKSA9PiBwc2J0U2lnLmVxdWFscyh0eFNpZykpIDogdHJ1ZVxuICAgICk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChzaWdNYXRjaCwgdHJ1ZSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUHNidFBhcnNpbmcoXG4gIHR4OiBVdHhvVHJhbnNhY3Rpb248YmlnaW50PixcbiAgcHNidDogVXR4b1BzYnQsXG4gIHVuc3BlbnRzOiBXYWxsZXRVbnNwZW50PGJpZ2ludD5bXSxcbiAgc2lnbmF0dXJlVGFyZ2V0OiBTaWduYXR1cmVUYXJnZXRUeXBlXG4pOiB2b2lkIHtcbiAgdW5zcGVudHMuZm9yRWFjaCgodSwgaSkgPT4ge1xuICAgIGlmICghaXNXYWxsZXRVbnNwZW50KHUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdFR5cGUgPSBzY3JpcHRUeXBlRm9yQ2hhaW4odS5jaGFpbik7XG5cbiAgICBpZiAoc2lnbmF0dXJlVGFyZ2V0ID09PSAndW5zaWduZWQnKSB7XG4gICAgICBpZiAoc2NyaXB0VHlwZSA9PT0gJ3AydHInKSB7XG4gICAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICAgKCkgPT4gcGFyc2VQc2J0SW5wdXQocHNidC5kYXRhLmlucHV0c1tpXSksXG4gICAgICAgICAgKGU6IGFueSkgPT4gZS5tZXNzYWdlID09PSAnY291bGQgbm90IHBhcnNlIGlucHV0J1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcHNidFBhcnNlZCA9IHBhcnNlUHNidElucHV0KHBzYnQuZGF0YS5pbnB1dHNbaV0pO1xuICAgICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBzYnRQYXJzZWQuc2NyaXB0VHlwZSwgc2NyaXB0VHlwZSk7XG4gICAgICAgIHZhbGlkYXRlU2NyaXB0KHBzYnRQYXJzZWQsIHVuZGVmaW5lZCk7XG4gICAgICAgIHZhbGlkYXRlUHVibGljS2V5cyhwc2J0UGFyc2VkLCB1bmRlZmluZWQpO1xuICAgICAgICB2YWxpZGF0ZVNpZ25hdHVyZShwc2J0UGFyc2VkLCB1bmRlZmluZWQpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBwc2J0UGFyc2VkID0gcGFyc2VQc2J0SW5wdXQocHNidC5kYXRhLmlucHV0c1tpXSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocHNidFBhcnNlZC5zY3JpcHRUeXBlLCBzY3JpcHRUeXBlID09PSAncDJ0cicgPyAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCcgOiBzY3JpcHRUeXBlKTtcbiAgICAgIGNvbnN0IHR4UGFyc2VkID0gcGFyc2VTaWduYXR1cmVTY3JpcHQyT2YzKHR4Lmluc1tpXSk7XG4gICAgICB2YWxpZGF0ZVNjcmlwdChwc2J0UGFyc2VkLCB0eFBhcnNlZCk7XG4gICAgICB2YWxpZGF0ZVB1YmxpY0tleXMocHNidFBhcnNlZCwgdHhQYXJzZWQpO1xuICAgICAgdmFsaWRhdGVTaWduYXR1cmUocHNidFBhcnNlZCwgdHhQYXJzZWQpO1xuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRFcXVhbFRyYW5zYWN0aW9uczxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgdHhPbmU6IFV0eG9UcmFuc2FjdGlvbjxUTnVtYmVyPixcbiAgdHhUd286IFV0eG9UcmFuc2FjdGlvbjxUTnVtYmVyPlxuKTogdm9pZCB7XG4gIGFzc2VydC5vayh0eE9uZS5uZXR3b3JrID09PSB0eFR3by5uZXR3b3JrKTtcbiAgYXNzZXJ0Lm9rKHR4T25lLmdldElkKCkgPT09IHR4VHdvLmdldElkKCkpO1xuICBhc3NlcnQub2sodHhPbmUudG9IZXgoKSA9PT0gdHhUd28udG9IZXgoKSk7XG4gIGFzc2VydC5vayh0eE9uZS52aXJ0dWFsU2l6ZSgpID09PSB0eFR3by52aXJ0dWFsU2l6ZSgpKTtcbiAgYXNzZXJ0Lm9rKHR4T25lLmxvY2t0aW1lID09PSB0eFR3by5sb2NrdGltZSk7XG4gIGFzc2VydC5vayh0eE9uZS52ZXJzaW9uID09PSB0eFR3by52ZXJzaW9uKTtcbiAgYXNzZXJ0Lm9rKHR4T25lLndlaWdodCgpID09PSB0eFR3by53ZWlnaHQoKSk7XG5cbiAgYXNzZXJ0Lm9rKHR4T25lLmlucy5sZW5ndGggPT09IHR4VHdvLmlucy5sZW5ndGgpO1xuICBhc3NlcnQub2sodHhPbmUub3V0cy5sZW5ndGggPT09IHR4VHdvLm91dHMubGVuZ3RoKTtcbiAgdHhPbmUuaW5zLmZvckVhY2goKF8sIGkpID0+IHtcbiAgICBjb25zdCBwYXJzZWRJbnB1dE9uZSA9IHBhcnNlU2lnbmF0dXJlU2NyaXB0Mk9mMyh0eE9uZS5pbnNbaV0pO1xuICAgIGNvbnN0IHBhcnNlZElucHV0VHdvID0gcGFyc2VTaWduYXR1cmVTY3JpcHQyT2YzKHR4VHdvLmluc1tpXSk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWRJbnB1dE9uZSwgcGFyc2VkSW5wdXRUd28pO1xuICB9KTtcbiAgdHhPbmUub3V0cy5mb3JFYWNoKChfLCBpKSA9PiB7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0eE9uZS5vdXRzW2ldLCB0eFR3by5vdXRzW2ldKTtcbiAgfSk7XG4gIGFzc2VydC5vayh0eE9uZS50b0J1ZmZlcigpLmVxdWFscyh0eFR3by50b0J1ZmZlcigpKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0JpZ0ludDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50Pih1bnNwZW50czogVW5zcGVudDxUTnVtYmVyPltdKTogV2FsbGV0VW5zcGVudDxiaWdpbnQ+W10ge1xuICByZXR1cm4gdW5zcGVudHMubWFwKCh1KSA9PiB7XG4gICAgaWYgKGlzV2FsbGV0VW5zcGVudCh1KSkge1xuICAgICAgcmV0dXJuIHsgLi4udSwgdmFsdWU6IEJpZ0ludCh1LnZhbHVlKSB9O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgdW5zcGVudCcpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNpZ25Qc2J0KFxuICBwc2J0OiBVdHhvUHNidCxcbiAgdW5zcGVudHM6IFVuc3BlbnQ8YmlnaW50PltdLFxuICByb290V2FsbGV0S2V5czogUm9vdFdhbGxldEtleXMsXG4gIHNpZ25lcjogc3RyaW5nLFxuICBjb3NpZ25lcjogc3RyaW5nLFxuICBzaWduYXR1cmVUYXJnZXQ6IFNpZ25hdHVyZVRhcmdldFR5cGVcbik6IHZvaWQge1xuICB1bnNwZW50cy5mb3JFYWNoKCh1LCBpKSA9PiB7XG4gICAgaWYgKCFpc1dhbGxldFVuc3BlbnQodSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCB1bnNwZW50Jyk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBpZiAoc2lnbmF0dXJlVGFyZ2V0ID09PSAndW5zaWduZWQnKSB7XG4gICAgICAgIHNpZ25XYWxsZXRQc2J0KHBzYnQsIGksIHJvb3RXYWxsZXRLZXlzW3NpZ25lcl0sIHUpO1xuICAgICAgfVxuICAgICAgc2lnbldhbGxldFBzYnQocHNidCwgaSwgcm9vdFdhbGxldEtleXNbY29zaWduZXJdLCB1KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2lnbmF0dXJlVGFyZ2V0LCAndW5zaWduZWQnKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0VHlwZUZvckNoYWluKHUuY2hhaW4pLCAncDJ0cicpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwc2J0LmRhdGEuaW5wdXRzW2ldLnRhcExlYWZTY3JpcHQsIHVuZGVmaW5lZCk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBzYnQuZGF0YS5pbnB1dHNbaV0udGFwQmlwMzJEZXJpdmF0aW9uLCB1bmRlZmluZWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwc2J0LmRhdGEuaW5wdXRzW2ldLnRhcFNjcmlwdFNpZywgdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5vayhwc2J0LmRhdGEuaW5wdXRzW2ldLndpdG5lc3NVdHhvKTtcbiAgICB9XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2lnblR4QnVpbGRlcjxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgdHhiOiBVdHhvVHJhbnNhY3Rpb25CdWlsZGVyPFROdW1iZXIsIFV0eG9UcmFuc2FjdGlvbjxUTnVtYmVyPj4sXG4gIHVuc3BlbnRzOiBVbnNwZW50PFROdW1iZXI+W10sXG4gIHJvb3RXYWxsZXRLZXlzOiBSb290V2FsbGV0S2V5cyxcbiAgc2lnbmVyOiBzdHJpbmcsXG4gIGNvc2lnbmVyOiBzdHJpbmcsXG4gIHNpZ25hdHVyZVRhcmdldDogU2lnbmF0dXJlVGFyZ2V0VHlwZVxuKTogVXR4b1RyYW5zYWN0aW9uPFROdW1iZXI+IHtcbiAgbGV0IHdhbGxldFVuc3BlbnRTaWduZXJzOiBXYWxsZXRVbnNwZW50U2lnbmVyPFJvb3RXYWxsZXRLZXlzPltdID0gW107XG5cbiAgaWYgKHNpZ25hdHVyZVRhcmdldCA9PT0gJ2hhbGZzaWduZWQnKSB7XG4gICAgd2FsbGV0VW5zcGVudFNpZ25lcnMgPSBbV2FsbGV0VW5zcGVudFNpZ25lci5mcm9tKHJvb3RXYWxsZXRLZXlzLCByb290V2FsbGV0S2V5c1tzaWduZXJdLCByb290V2FsbGV0S2V5c1tjb3NpZ25lcl0pXTtcbiAgfSBlbHNlIGlmIChzaWduYXR1cmVUYXJnZXQgPT09ICdmdWxsc2lnbmVkJykge1xuICAgIHdhbGxldFVuc3BlbnRTaWduZXJzID0gW1xuICAgICAgV2FsbGV0VW5zcGVudFNpZ25lci5mcm9tKHJvb3RXYWxsZXRLZXlzLCByb290V2FsbGV0S2V5c1tzaWduZXJdLCByb290V2FsbGV0S2V5c1tjb3NpZ25lcl0pLFxuICAgICAgV2FsbGV0VW5zcGVudFNpZ25lci5mcm9tKHJvb3RXYWxsZXRLZXlzLCByb290V2FsbGV0S2V5c1tjb3NpZ25lcl0sIHJvb3RXYWxsZXRLZXlzW3NpZ25lcl0pLFxuICAgIF07XG4gIH1cblxuICB3YWxsZXRVbnNwZW50U2lnbmVycy5mb3JFYWNoKCh3YWxsZXRTaWduZXIsIG5TaWduYXR1cmUpID0+IHtcbiAgICB1bnNwZW50cy5mb3JFYWNoKCh1LCBpKSA9PiB7XG4gICAgICBpZiAoaXNXYWxsZXRVbnNwZW50KHUpKSB7XG4gICAgICAgIHNpZ25JbnB1dFdpdGhVbnNwZW50KHR4YiwgaSwgdSwgd2FsbGV0U2lnbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5leHBlY3RlZCB1bnNwZW50ICR7dS5pZH1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHNpZ25hdHVyZVRhcmdldCA9PT0gJ2Z1bGxzaWduZWQnID8gdHhiLmJ1aWxkKCkgOiB0eGIuYnVpbGRJbmNvbXBsZXRlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb25zdHJ1Y3RUcmFuc2FjdGlvblVzaW5nVHhCdWlsZGVyPFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KFxuICB1bnNwZW50czogVW5zcGVudDxUTnVtYmVyPltdLFxuICByb290V2FsbGV0S2V5czogUm9vdFdhbGxldEtleXMsXG4gIHBhcmFtczoge1xuICAgIHNpZ25lcjogS2V5TmFtZTtcbiAgICBjb3NpZ25lcjogS2V5TmFtZTtcbiAgICBhbW91bnRUeXBlOiAnbnVtYmVyJyB8ICdiaWdpbnQnO1xuICAgIG91dHB1dFR5cGU6IG91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTJPZjM7XG4gICAgc2lnbmF0dXJlVGFyZ2V0OiBTaWduYXR1cmVUYXJnZXRUeXBlO1xuICAgIG5ldHdvcms6IE5ldHdvcms7XG4gICAgY2hhbmdlSW5kZXg6IG51bWJlcjtcbiAgICBmZWU6IGJpZ2ludDtcbiAgfVxuKTogVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4ge1xuICBjb25zdCB0eGIgPSBjcmVhdGVUcmFuc2FjdGlvbkJ1aWxkZXJGb3JOZXR3b3JrPFROdW1iZXI+KHBhcmFtcy5uZXR3b3JrKTtcbiAgY29uc3QgdG90YWwgPSBCaWdJbnQodW5zcGVudFN1bTxUTnVtYmVyPih1bnNwZW50cywgcGFyYW1zLmFtb3VudFR5cGUpKTtcbiAgLy8gS2luZGEgd2VpcmQsIHRyZWF0aW5nIGVudGlyZSB2YWx1ZSBhcyBjaGFuZ2UsIGJ1dCB0ZXN0cyB0aGUgcmVsZXZhbnQgcGF0aHNcbiAgdHhiLmFkZE91dHB1dChcbiAgICBnZXRXYWxsZXRBZGRyZXNzKHJvb3RXYWxsZXRLZXlzLCBnZXRJbnRlcm5hbENoYWluQ29kZShwYXJhbXMub3V0cHV0VHlwZSksIHBhcmFtcy5jaGFuZ2VJbmRleCwgcGFyYW1zLm5ldHdvcmspLFxuICAgIHRvVE51bWJlcjxUTnVtYmVyPih0b3RhbCAtIHBhcmFtcy5mZWUsIHBhcmFtcy5hbW91bnRUeXBlKVxuICApO1xuICB1bnNwZW50cy5mb3JFYWNoKCh1KSA9PiB7XG4gICAgYWRkVG9UcmFuc2FjdGlvbkJ1aWxkZXIodHhiLCB1KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHNpZ25UeEJ1aWxkZXI8VE51bWJlcj4oXG4gICAgdHhiLFxuICAgIHVuc3BlbnRzLFxuICAgIHJvb3RXYWxsZXRLZXlzLFxuICAgIHBhcmFtcy5zaWduZXIsXG4gICAgcGFyYW1zLmNvc2lnbmVyLFxuICAgIHBhcmFtcy5zaWduYXR1cmVUYXJnZXRcbiAgKS5jbG9uZTxiaWdpbnQ+KCdiaWdpbnQnKTtcbn1cbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!