PHP WebShell

Текущая директория: /opt/BitGoJS/modules/utxo-lib/dist/src/bitgo/zcash

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBlake2bHash = getBlake2bHash;
exports.getPrevoutsDigest = getPrevoutsDigest;
exports.getSequenceDigest = getSequenceDigest;
exports.getOutputsDigest = getOutputsDigest;
exports.getTxidDigest = getTxidDigest;
exports.getSignatureDigest = getSignatureDigest;
/**
 * Implements hashing methods described in https://zips.z.cash/zip-0244.
 * Only supports full transparent transactions without shielded inputs or outputs.
 */
const bitcoinjs_lib_1 = require("bitcoinjs-lib");
const bufferutils_1 = require("bitcoinjs-lib/src/bufferutils");
const blake2b = require('@bitgo/blake2b');
const UtxoTransaction_1 = require("../UtxoTransaction");
/**
 * Blake2b hashing algorithm for Zcash
 * @param buffer
 * @param personalization
 * @returns 256-bit BLAKE2b hash
 */
function getBlake2bHash(buffer, personalization) {
    const out = Buffer.allocUnsafe(32);
    personalization = Buffer.from(personalization);
    return blake2b(out.length, null, null, personalization).update(buffer).digest(out);
}
function getHeaderDigest(tx) {
    // https://zips.z.cash/zip-0244#t-1-header-digest
    const mask = tx.overwintered ? 1 : 0;
    const writer = bufferutils_1.BufferWriter.withCapacity(4 * 5);
    writer.writeInt32(tx.version | (mask << 31)); // Set overwinter bit
    writer.writeUInt32(tx.versionGroupId);
    writer.writeUInt32(tx.consensusBranchId);
    writer.writeUInt32(tx.locktime);
    writer.writeUInt32(tx.expiryHeight);
    return getBlake2bHash(writer.end(), 'ZTxIdHeadersHash');
}
function getPrevoutsDigest(ins, tag = 'ZTxIdPrevoutHash', sigParams) {
    if (sigParams) {
        if (sigParams.hashType & bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY) {
            return getPrevoutsDigest([]);
        }
    }
    const bufferWriter = new bufferutils_1.BufferWriter(Buffer.allocUnsafe(36 * ins.length));
    ins.forEach(function (txIn) {
        bufferWriter.writeSlice(txIn.hash);
        bufferWriter.writeUInt32(txIn.index);
    });
    return getBlake2bHash(bufferWriter.end(), tag);
}
function getSequenceDigest(ins, tag = 'ZTxIdSequencHash', sigParams) {
    // txid: https://zips.z.cash/zip-0244#t-2b-sequence-digest
    // sig: https://zips.z.cash/zip-0244#s-2b-sequence-sig-digest
    // https://github.com/zcash-hackworks/zcash-test-vectors/blob/dd8fdb/zip_0244.py#L263
    if (sigParams) {
        const { hashType } = sigParams;
        if (hashType & bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY ||
            (hashType & 0x1f) === bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE ||
            (hashType & 0x1f) === bitcoinjs_lib_1.Transaction.SIGHASH_NONE) {
            return getSequenceDigest([]);
        }
    }
    const bufferWriter = new bufferutils_1.BufferWriter(Buffer.allocUnsafe(4 * ins.length));
    ins.forEach(function (txIn) {
        bufferWriter.writeUInt32(txIn.sequence);
    });
    return getBlake2bHash(bufferWriter.end(), tag);
}
function getOutputsDigest(outs, tag = 'ZTxIdOutputsHash', sigParams) {
    // txid: https://zips.z.cash/zip-0244#t-2c-outputs-digest
    // sig: https://zips.z.cash/zip-0244#s-2c-outputs-sig-digest
    // https://github.com/zcash-hackworks/zcash-test-vectors/blob/dd8fdb/zip_0244.py#L275
    if (sigParams) {
        let { hashType } = sigParams;
        hashType = hashType & 0x1f;
        if (hashType === bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE) {
            if (sigParams.inIndex === undefined) {
                throw new Error();
            }
            if (outs[sigParams.inIndex] === undefined) {
                return getOutputsDigest(outs);
            }
            return getOutputsDigest([outs[sigParams.inIndex]]);
        }
        if (hashType === bitcoinjs_lib_1.Transaction.SIGHASH_NONE) {
            return getOutputsDigest([]);
        }
        return getOutputsDigest(outs, tag);
    }
    // Find out the size of the outputs and write them
    const txOutsSize = outs.reduce(function (sum, output) {
        return sum + 8 + (0, UtxoTransaction_1.varSliceSize)(output.script);
    }, 0);
    const bufferWriter = new bufferutils_1.BufferWriter(Buffer.allocUnsafe(txOutsSize));
    outs.forEach(function (out) {
        bufferWriter.writeUInt64(out.value);
        bufferWriter.writeVarSlice(out.script);
    });
    return getBlake2bHash(bufferWriter.end(), tag);
}
function getTxinDigest(input, sigParams) {
    // https://zips.z.cash/zip-0244#s-2d-txin-sig-digest
    // https://github.com/zcash-hackworks/zcash-test-vectors/blob/dd8fdb/zip_0244.py#L291
    const writer = bufferutils_1.BufferWriter.withCapacity(32 /* prevout hash */ +
        4 /* prevout vin */ +
        (0, UtxoTransaction_1.varSliceSize)(sigParams.prevOutScript) +
        8 /* value */ +
        4 /* sequence */);
    writer.writeSlice(input.hash);
    writer.writeUInt32(input.index);
    writer.writeVarSlice(sigParams.prevOutScript);
    writer.writeUInt64(sigParams.value);
    writer.writeUInt32(input.sequence);
    return getBlake2bHash(writer.end(), 'Zcash___TxInHash');
}
function getTransparentDigest(tx, sigParams) {
    // txid: https://zips.z.cash/zip-0244#t-2-transparent-digest
    // sig: https://zips.z.cash/zip-0244#s-2a-prevouts-sig-digest
    if (sigParams) {
        if (sigParams.inIndex === undefined) {
            return getTransparentDigest(tx);
        }
    }
    let buffer;
    if (tx.ins.length || tx.outs.length) {
        const writer = bufferutils_1.BufferWriter.withCapacity(32 * (sigParams ? 4 : 3));
        writer.writeSlice(getPrevoutsDigest(tx.ins, undefined, sigParams));
        writer.writeSlice(getSequenceDigest(tx.ins, undefined, sigParams));
        writer.writeSlice(getOutputsDigest(tx.outs, undefined, sigParams));
        if (sigParams) {
            if (sigParams.inIndex === undefined) {
                throw new Error();
            }
            writer.writeSlice(getTxinDigest(tx.ins[sigParams.inIndex], sigParams));
        }
        buffer = writer.end();
    }
    else {
        buffer = Buffer.of();
    }
    return getBlake2bHash(buffer, 'ZTxIdTranspaHash');
}
function getSaplingDigest(tx) {
    // https://zips.z.cash/zip-0244#t-3-sapling-digest
    return getBlake2bHash(Buffer.of(), 'ZTxIdSaplingHash');
}
function getOrchardDigest(tx) {
    // https://zips.z.cash/zip-0244#t-4-orchard-digest
    return getBlake2bHash(Buffer.of(), 'ZTxIdOrchardHash');
}
/**
 * @param tx
 * @param signatureParams - calculates txid when undefined
 */
function getDigest(tx, signatureParams) {
    // txid: https://zips.z.cash/zip-0244#id4
    // sig: https://zips.z.cash/zip-0244#id13
    const writer = bufferutils_1.BufferWriter.withCapacity(32 * 4);
    writer.writeSlice(getHeaderDigest(tx));
    writer.writeSlice(getTransparentDigest(tx, signatureParams));
    writer.writeSlice(getSaplingDigest(tx));
    writer.writeSlice(getOrchardDigest(tx));
    const tag = 'ZcashTxHash_';
    const personalization = bufferutils_1.BufferWriter.withCapacity(tag.length + 4 /* UInt32 */);
    personalization.writeSlice(Buffer.from(tag));
    personalization.writeUInt32(tx.consensusBranchId);
    return getBlake2bHash(writer.end(), personalization.end());
}
function getTxidDigest(tx) {
    // https://zips.z.cash/zip-0244#id4
    return getDigest(tx);
}
function getSignatureDigest(tx, inIndex, prevOutScript, value, hashType) {
    // https://zips.z.cash/zip-0244#id13
    return getDigest(tx, {
        inIndex,
        prevOutScript,
        value,
        hashType,
    });
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFzaFppcDAyNDQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYml0Z28vemNhc2gvaGFzaFppcDAyNDQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF5QkEsd0NBSUM7QUFjRCw4Q0FpQkM7QUFFRCw4Q0EwQkM7QUFFRCw0Q0EwQ0M7QUFvRkQsc0NBR0M7QUFFRCxnREFjQztBQTNPRDs7O0dBR0c7QUFDSCxpREFBK0Q7QUFDL0QsK0RBQTZEO0FBRTdELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBRzFDLHdEQUFrRDtBQVNsRDs7Ozs7R0FLRztBQUNILFNBQWdCLGNBQWMsQ0FBQyxNQUFjLEVBQUUsZUFBZ0M7SUFDN0UsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuQyxlQUFlLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUMvQyxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsZUFBZSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNyRixDQUFDO0FBRUQsU0FBUyxlQUFlLENBQWtDLEVBQTZCO0lBQ3JGLGlEQUFpRDtJQUNqRCxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyQyxNQUFNLE1BQU0sR0FBRywwQkFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDaEQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxxQkFBcUI7SUFDbkUsTUFBTSxDQUFDLFdB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QUU7UUFDbkIsT0FBTztRQUNQLGFBQWE7UUFDYixLQUFLO1FBQ0wsUUFBUTtLQUNULENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEltcGxlbWVudHMgaGFzaGluZyBtZXRob2RzIGRlc2NyaWJlZCBpbiBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0LlxuICogT25seSBzdXBwb3J0cyBmdWxsIHRyYW5zcGFyZW50IHRyYW5zYWN0aW9ucyB3aXRob3V0IHNoaWVsZGVkIGlucHV0cyBvciBvdXRwdXRzLlxuICovXG5pbXBvcnQgeyBUcmFuc2FjdGlvbiwgVHhJbnB1dCwgVHhPdXRwdXQgfSBmcm9tICdiaXRjb2luanMtbGliJztcbmltcG9ydCB7IEJ1ZmZlcldyaXRlciB9IGZyb20gJ2JpdGNvaW5qcy1saWIvc3JjL2J1ZmZlcnV0aWxzJztcblxuY29uc3QgYmxha2UyYiA9IHJlcXVpcmUoJ0BiaXRnby9ibGFrZTJiJyk7XG5cbmltcG9ydCB7IFpjYXNoVHJhbnNhY3Rpb24gfSBmcm9tICcuL1pjYXNoVHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgdmFyU2xpY2VTaXplIH0gZnJvbSAnLi4vVXR4b1RyYW5zYWN0aW9uJztcblxudHlwZSBTaWduYXR1cmVQYXJhbXM8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludCA9IG51bWJlcj4gPSB7XG4gIGluSW5kZXg/OiBudW1iZXI7XG4gIHByZXZPdXRTY3JpcHQ6IEJ1ZmZlcjtcbiAgdmFsdWU6IFROdW1iZXI7XG4gIGhhc2hUeXBlOiBudW1iZXI7XG59O1xuXG4vKipcbiAqIEJsYWtlMmIgaGFzaGluZyBhbGdvcml0aG0gZm9yIFpjYXNoXG4gKiBAcGFyYW0gYnVmZmVyXG4gKiBAcGFyYW0gcGVyc29uYWxpemF0aW9uXG4gKiBAcmV0dXJucyAyNTYtYml0IEJMQUtFMmIgaGFzaFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Qmxha2UyYkhhc2goYnVmZmVyOiBCdWZmZXIsIHBlcnNvbmFsaXphdGlvbjogc3RyaW5nIHwgQnVmZmVyKTogQnVmZmVyIHtcbiAgY29uc3Qgb3V0ID0gQnVmZmVyLmFsbG9jVW5zYWZlKDMyKTtcbiAgcGVyc29uYWxpemF0aW9uID0gQnVmZmVyLmZyb20ocGVyc29uYWxpemF0aW9uKTtcbiAgcmV0dXJuIGJsYWtlMmIob3V0Lmxlbmd0aCwgbnVsbCwgbnVsbCwgcGVyc29uYWxpemF0aW9uKS51cGRhdGUoYnVmZmVyKS5kaWdlc3Qob3V0KTtcbn1cblxuZnVuY3Rpb24gZ2V0SGVhZGVyRGlnZXN0PFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KHR4OiBaY2FzaFRyYW5zYWN0aW9uPFROdW1iZXI+KTogQnVmZmVyIHtcbiAgLy8gaHR0cHM6Ly96aXBzLnouY2FzaC96aXAtMDI0NCN0LTEtaGVhZGVyLWRpZ2VzdFxuICBjb25zdCBtYXNrID0gdHgub3ZlcndpbnRlcmVkID8gMSA6IDA7XG4gIGNvbnN0IHdyaXRlciA9IEJ1ZmZlcldyaXRlci53aXRoQ2FwYWNpdHkoNCAqIDUpO1xuICB3cml0ZXIud3JpdGVJbnQzMih0eC52ZXJzaW9uIHwgKG1hc2sgPDwgMzEpKTsgLy8gU2V0IG92ZXJ3aW50ZXIgYml0XG4gIHdyaXRlci53cml0ZVVJbnQzMih0eC52ZXJzaW9uR3JvdXBJZCk7XG4gIHdyaXRlci53cml0ZVVJbnQzMih0eC5jb25zZW5zdXNCcmFuY2hJZCk7XG4gIHdyaXRlci53cml0ZVVJbnQzMih0eC5sb2NrdGltZSk7XG4gIHdyaXRlci53cml0ZVVJbnQzMih0eC5leHBpcnlIZWlnaHQpO1xuICByZXR1cm4gZ2V0Qmxha2UyYkhhc2god3JpdGVyLmVuZCgpLCAnWlR4SWRIZWFkZXJzSGFzaCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJldm91dHNEaWdlc3Q8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oXG4gIGluczogVHhJbnB1dFtdLFxuICB0YWcgPSAnWlR4SWRQcmV2b3V0SGFzaCcsXG4gIHNpZ1BhcmFtcz86IFNpZ25hdHVyZVBhcmFtczxUTnVtYmVyPlxuKTogQnVmZmVyIHtcbiAgaWYgKHNpZ1BhcmFtcykge1xuICAgIGlmIChzaWdQYXJhbXMuaGFzaFR5cGUgJiBUcmFuc2FjdGlvbi5TSUdIQVNIX0FOWU9ORUNBTlBBWSkge1xuICAgICAgcmV0dXJuIGdldFByZXZvdXRzRGlnZXN0KFtdKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBidWZmZXJXcml0ZXIgPSBuZXcgQnVmZmVyV3JpdGVyKEJ1ZmZlci5hbGxvY1Vuc2FmZSgzNiAqIGlucy5sZW5ndGgpKTtcbiAgaW5zLmZvckVhY2goZnVuY3Rpb24gKHR4SW4pIHtcbiAgICBidWZmZXJXcml0ZXIud3JpdGVTbGljZSh0eEluLmhhc2gpO1xuICAgIGJ1ZmZlcldyaXRlci53cml0ZVVJbnQzMih0eEluLmluZGV4KTtcbiAgfSk7XG4gIHJldHVybiBnZXRCbGFrZTJiSGFzaChidWZmZXJXcml0ZXIuZW5kKCksIHRhZyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZXF1ZW5jZURpZ2VzdDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgaW5zOiBUeElucHV0W10sXG4gIHRhZyA9ICdaVHhJZFNlcXVlbmNIYXNoJyxcbiAgc2lnUGFyYW1zPzogU2lnbmF0dXJlUGFyYW1zPFROdW1iZXI+XG4pOiBCdWZmZXIge1xuICAvLyB0eGlkOiBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0I3QtMmItc2VxdWVuY2UtZGlnZXN0XG4gIC8vIHNpZzogaHR0cHM6Ly96aXBzLnouY2FzaC96aXAtMDI0NCNzLTJiLXNlcXVlbmNlLXNpZy1kaWdlc3RcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3pjYXNoLWhhY2t3b3Jrcy96Y2FzaC10ZXN0LXZlY3RvcnMvYmxvYi9kZDhmZGIvemlwXzAyNDQucHkjTDI2M1xuICBpZiAoc2lnUGFyYW1zKSB7XG4gICAgY29uc3QgeyBoYXNoVHlwZSB9ID0gc2lnUGFyYW1zO1xuICAgIGlmIChcbiAgICAgIGhhc2hUeXBlICYgVHJhbnNhY3Rpb24uU0lHSEFTSF9BTllPTkVDQU5QQVkgfHxcbiAgICAgIChoYXNoVHlwZSAmIDB4MWYpID09PSBUcmFuc2FjdGlvbi5TSUdIQVNIX1NJTkdMRSB8fFxuICAgICAgKGhhc2hUeXBlICYgMHgxZikgPT09IFRyYW5zYWN0aW9uLlNJR0hBU0hfTk9ORVxuICAgICkge1xuICAgICAgcmV0dXJuIGdldFNlcXVlbmNlRGlnZXN0KFtdKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBidWZmZXJXcml0ZXIgPSBuZXcgQnVmZmVyV3JpdGVyKEJ1ZmZlci5hbGxvY1Vuc2FmZSg0ICogaW5zLmxlbmd0aCkpO1xuXG4gIGlucy5mb3JFYWNoKGZ1bmN0aW9uICh0eEluKSB7XG4gICAgYnVmZmVyV3JpdGVyLndyaXRlVUludDMyKHR4SW4uc2VxdWVuY2UpO1xuICB9KTtcblxuICByZXR1cm4gZ2V0Qmxha2UyYkhhc2goYnVmZmVyV3JpdGVyLmVuZCgpLCB0YWcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0T3V0cHV0c0RpZ2VzdDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgb3V0czogVHhPdXRwdXQ8VE51bWJlcj5bXSxcbiAgdGFnID0gJ1pUeElkT3V0cHV0c0hhc2gnLFxuICBzaWdQYXJhbXM/OiBTaWduYXR1cmVQYXJhbXM8VE51bWJlcj5cbik6IEJ1ZmZlciB7XG4gIC8vIHR4aWQ6IGh0dHBzOi8vemlwcy56LmNhc2gvemlwLTAyNDQjdC0yYy1vdXRwdXRzLWRpZ2VzdFxuICAvLyBzaWc6IGh0dHBzOi8vemlwcy56LmNhc2gvemlwLTAyNDQjcy0yYy1vdXRwdXRzLXNpZy1kaWdlc3RcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3pjYXNoLWhhY2t3b3Jrcy96Y2FzaC10ZXN0LXZlY3RvcnMvYmxvYi9kZDhmZGIvemlwXzAyNDQucHkjTDI3NVxuICBpZiAoc2lnUGFyYW1zKSB7XG4gICAgbGV0IHsgaGFzaFR5cGUgfSA9IHNpZ1BhcmFtcztcbiAgICBoYXNoVHlwZSA9IGhhc2hUeXBlICYgMHgxZjtcblxuICAgIGlmIChoYXNoVHlwZSA9PT0gVHJhbnNhY3Rpb24uU0lHSEFTSF9TSU5HTEUpIHtcbiAgICAgIGlmIChzaWdQYXJhbXMuaW5JbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigpO1xuICAgICAgfVxuICAgICAgaWYgKG91dHNbc2lnUGFyYW1zLmluSW5kZXhdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGdldE91dHB1dHNEaWdlc3Qob3V0cyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZ2V0T3V0cHV0c0RpZ2VzdChbb3V0c1tzaWdQYXJhbXMuaW5JbmRleF1dKTtcbiAgICB9XG5cbiAgICBpZiAoaGFzaFR5cGUgPT09IFRyYW5zYWN0aW9uLlNJR0hBU0hfTk9ORSkge1xuICAgICAgcmV0dXJuIGdldE91dHB1dHNEaWdlc3QoW10pO1xuICAgIH1cblxuICAgIHJldHVybiBnZXRPdXRwdXRzRGlnZXN0KG91dHMsIHRhZyk7XG4gIH1cblxuICAvLyBGaW5kIG91dCB0aGUgc2l6ZSBvZiB0aGUgb3V0cHV0cyBhbmQgd3JpdGUgdGhlbVxuICBjb25zdCB0eE91dHNTaXplID0gb3V0cy5yZWR1Y2UoZnVuY3Rpb24gKHN1bSwgb3V0cHV0KSB7XG4gICAgcmV0dXJuIHN1bSArIDggKyB2YXJTbGljZVNpemUob3V0cHV0LnNjcmlwdCk7XG4gIH0sIDApO1xuXG4gIGNvbnN0IGJ1ZmZlcldyaXRlciA9IG5ldyBCdWZmZXJXcml0ZXIoQnVmZmVyLmFsbG9jVW5zYWZlKHR4T3V0c1NpemUpKTtcblxuICBvdXRzLmZvckVhY2goZnVuY3Rpb24gKG91dCkge1xuICAgIGJ1ZmZlcldyaXRlci53cml0ZVVJbnQ2NChvdXQudmFsdWUpO1xuICAgIGJ1ZmZlcldyaXRlci53cml0ZVZhclNsaWNlKG91dC5zY3JpcHQpO1xuICB9KTtcblxuICByZXR1cm4gZ2V0Qmxha2UyYkhhc2goYnVmZmVyV3JpdGVyLmVuZCgpLCB0YWcpO1xufVxuXG5mdW5jdGlvbiBnZXRUeGluRGlnZXN0PFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KGlucHV0OiBUeElucHV0LCBzaWdQYXJhbXM6IFNpZ25hdHVyZVBhcmFtczxUTnVtYmVyPikge1xuICAvLyBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0I3MtMmQtdHhpbi1zaWctZGlnZXN0XG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS96Y2FzaC1oYWNrd29ya3MvemNhc2gtdGVzdC12ZWN0b3JzL2Jsb2IvZGQ4ZmRiL3ppcF8wMjQ0LnB5I0wyOTFcbiAgY29uc3Qgd3JpdGVyID0gQnVmZmVyV3JpdGVyLndpdGhDYXBhY2l0eShcbiAgICAzMiAvKiBwcmV2b3V0IGhhc2ggKi8gK1xuICAgICAgNCAvKiBwcmV2b3V0IHZpbiAqLyArXG4gICAgICB2YXJTbGljZVNpemUoc2lnUGFyYW1zLnByZXZPdXRTY3JpcHQpICtcbiAgICAgIDggLyogdmFsdWUgKi8gK1xuICAgICAgNCAvKiBzZXF1ZW5jZSAqL1xuICApO1xuICB3cml0ZXIud3JpdGVTbGljZShpbnB1dC5oYXNoKTtcbiAgd3JpdGVyLndyaXRlVUludDMyKGlucHV0LmluZGV4KTtcbiAgd3JpdGVyLndyaXRlVmFyU2xpY2Uoc2lnUGFyYW1zLnByZXZPdXRTY3JpcHQpO1xuICB3cml0ZXIud3JpdGVVSW50NjQoc2lnUGFyYW1zLnZhbHVlKTtcbiAgd3JpdGVyLndyaXRlVUludDMyKGlucHV0LnNlcXVlbmNlKTtcbiAgcmV0dXJuIGdldEJsYWtlMmJIYXNoKHdyaXRlci5lbmQoKSwgJ1pjYXNoX19fVHhJbkhhc2gnKTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNwYXJlbnREaWdlc3Q8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oXG4gIHR4OiB7IGluczogVHhJbnB1dFtdOyBvdXRzOiBUeE91dHB1dDxUTnVtYmVyPltdIH0sXG4gIHNpZ1BhcmFtcz86IFNpZ25hdHVyZVBhcmFtczxUTnVtYmVyPlxuKTogQnVmZmVyIHtcbiAgLy8gdHhpZDogaHR0cHM6Ly96aXBzLnouY2FzaC96aXAtMDI0NCN0LTItdHJhbnNwYXJlbnQtZGlnZXN0XG4gIC8vIHNpZzogaHR0cHM6Ly96aXBzLnouY2FzaC96aXAtMDI0NCNzLTJhLXByZXZvdXRzLXNpZy1kaWdlc3RcbiAgaWYgKHNpZ1BhcmFtcykge1xuICAgIGlmIChzaWdQYXJhbXMuaW5JbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZ2V0VHJhbnNwYXJlbnREaWdlc3QodHgpO1xuICAgIH1cbiAgfVxuXG4gIGxldCBidWZmZXI7XG4gIGlmICh0eC5pbnMubGVuZ3RoIHx8IHR4Lm91dHMubGVuZ3RoKSB7XG4gICAgY29uc3Qgd3JpdGVyID0gQnVmZmVyV3JpdGVyLndpdGhDYXBhY2l0eSgzMiAqIChzaWdQYXJhbXMgPyA0IDogMykpO1xuICAgIHdyaXRlci53cml0ZVNsaWNlKGdldFByZXZvdXRzRGlnZXN0KHR4LmlucywgdW5kZWZpbmVkLCBzaWdQYXJhbXMpKTtcbiAgICB3cml0ZXIud3JpdGVTbGljZShnZXRTZXF1ZW5jZURpZ2VzdCh0eC5pbnMsIHVuZGVmaW5lZCwgc2lnUGFyYW1zKSk7XG4gICAgd3JpdGVyLndyaXRlU2xpY2UoZ2V0T3V0cHV0c0RpZ2VzdCh0eC5vdXRzLCB1bmRlZmluZWQsIHNpZ1BhcmFtcykpO1xuICAgIGlmIChzaWdQYXJhbXMpIHtcbiAgICAgIGlmIChzaWdQYXJhbXMuaW5JbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigpO1xuICAgICAgfVxuICAgICAgd3JpdGVyLndyaXRlU2xpY2UoZ2V0VHhpbkRpZ2VzdCh0eC5pbnNbc2lnUGFyYW1zLmluSW5kZXhdLCBzaWdQYXJhbXMpKTtcbiAgICB9XG4gICAgYnVmZmVyID0gd3JpdGVyLmVuZCgpO1xuICB9IGVsc2Uge1xuICAgIGJ1ZmZlciA9IEJ1ZmZlci5vZigpO1xuICB9XG4gIHJldHVybiBnZXRCbGFrZTJiSGFzaChidWZmZXIsICdaVHhJZFRyYW5zcGFIYXNoJyk7XG59XG5cbmZ1bmN0aW9uIGdldFNhcGxpbmdEaWdlc3Q8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4odHg6IFpjYXNoVHJhbnNhY3Rpb248VE51bWJlcj4pOiBCdWZmZXIge1xuICAvLyBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0I3QtMy1zYXBsaW5nLWRpZ2VzdFxuICByZXR1cm4gZ2V0Qmxha2UyYkhhc2goQnVmZmVyLm9mKCksICdaVHhJZFNhcGxpbmdIYXNoJyk7XG59XG5cbmZ1bmN0aW9uIGdldE9yY2hhcmREaWdlc3Q8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4odHg6IFpjYXNoVHJhbnNhY3Rpb248VE51bWJlcj4pOiBCdWZmZXIge1xuICAvLyBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0I3QtNC1vcmNoYXJkLWRpZ2VzdFxuICByZXR1cm4gZ2V0Qmxha2UyYkhhc2goQnVmZmVyLm9mKCksICdaVHhJZE9yY2hhcmRIYXNoJyk7XG59XG5cbi8qKlxuICogQHBhcmFtIHR4XG4gKiBAcGFyYW0gc2lnbmF0dXJlUGFyYW1zIC0gY2FsY3VsYXRlcyB0eGlkIHdoZW4gdW5kZWZpbmVkXG4gKi9cbmZ1bmN0aW9uIGdldERpZ2VzdDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgdHg6IFpjYXNoVHJhbnNhY3Rpb248VE51bWJlcj4sXG4gIHNpZ25hdHVyZVBhcmFtcz86IFNpZ25hdHVyZVBhcmFtczxUTnVtYmVyPlxuKTogQnVmZmVyIHtcbiAgLy8gdHhpZDogaHR0cHM6Ly96aXBzLnouY2FzaC96aXAtMDI0NCNpZDRcbiAgLy8gc2lnOiBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0I2lkMTNcbiAgY29uc3Qgd3JpdGVyID0gQnVmZmVyV3JpdGVyLndpdGhDYXBhY2l0eSgzMiAqIDQpO1xuICB3cml0ZXIud3JpdGVTbGljZShnZXRIZWFkZXJEaWdlc3QodHgpKTtcbiAgd3JpdGVyLndyaXRlU2xpY2UoZ2V0VHJhbnNwYXJlbnREaWdlc3QodHgsIHNpZ25hdHVyZVBhcmFtcykpO1xuICB3cml0ZXIud3JpdGVTbGljZShnZXRTYXBsaW5nRGlnZXN0KHR4KSk7XG4gIHdyaXRlci53cml0ZVNsaWNlKGdldE9yY2hhcmREaWdlc3QodHgpKTtcblxuICBjb25zdCB0YWcgPSAnWmNhc2hUeEhhc2hfJztcbiAgY29uc3QgcGVyc29uYWxpemF0aW9uID0gQnVmZmVyV3JpdGVyLndpdGhDYXBhY2l0eSh0YWcubGVuZ3RoICsgNCAvKiBVSW50MzIgKi8pO1xuICBwZXJzb25hbGl6YXRpb24ud3JpdGVTbGljZShCdWZmZXIuZnJvbSh0YWcpKTtcbiAgcGVyc29uYWxpemF0aW9uLndyaXRlVUludDMyKHR4LmNvbnNlbnN1c0JyYW5jaElkKTtcbiAgcmV0dXJuIGdldEJsYWtlMmJIYXNoKHdyaXRlci5lbmQoKSwgcGVyc29uYWxpemF0aW9uLmVuZCgpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFR4aWREaWdlc3Q8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4odHg6IFpjYXNoVHJhbnNhY3Rpb248VE51bWJlcj4pOiBCdWZmZXIge1xuICAvLyBodHRwczovL3ppcHMuei5jYXNoL3ppcC0wMjQ0I2lkNFxuICByZXR1cm4gZ2V0RGlnZXN0KHR4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNpZ25hdHVyZURpZ2VzdDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgdHg6IFpjYXNoVHJhbnNhY3Rpb248VE51bWJlcj4sXG4gIGluSW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgcHJldk91dFNjcmlwdDogQnVmZmVyLFxuICB2YWx1ZTogVE51bWJlcixcbiAgaGFzaFR5cGU6IG51bWJlclxuKTogQnVmZmVyIHtcbiAgLy8gaHR0cHM6Ly96aXBzLnouY2FzaC96aXAtMDI0NCNpZDEzXG4gIHJldHVybiBnZXREaWdlc3QodHgsIHtcbiAgICBpbkluZGV4LFxuICAgIHByZXZPdXRTY3JpcHQsXG4gICAgdmFsdWUsXG4gICAgaGFzaFR5cGUsXG4gIH0pO1xufVxuIl19

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


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