@coolwallet/kas
Version:
228 lines (221 loc) • 35.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.addressToOutScript = addressToOutScript;
exports.decodeAddress = decodeAddress;
exports.decodeAddressVersion = decodeAddressVersion;
exports.getAddressByPublicKeyOrScriptHash = getAddressByPublicKeyOrScriptHash;
exports.getAddressVersion = getAddressVersion;
exports.getPubkeyOrScriptHash = getPubkeyOrScriptHash;
exports.getScriptType = getScriptType;
exports.pubkeyOrScriptHashToPayment = pubkeyOrScriptHashToPayment;
exports.toXOnly = toXOnly;
var _core = require("@coolwallet/core");
var _types = require("../config/types");
var _base = require("./base32");
var _checksum = require("./checksum");
var _convertBits = require("./convertBits");
var _utils = require("./utils");
var _validate = require("./validate");
/*
MIT License
Copyright (c) 2023 OKX.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Modified by coolbitx in 2024
function toXOnly(pubKey) {
if (typeof pubKey === 'string') {
pubKey = Buffer.from(pubKey, 'hex');
}
var result = pubKey.length === 32 ? pubKey : pubKey.slice(1, 33);
return result.toString('hex');
}
function getAddressByPublicKeyOrScriptHash(pubKeyOrScriptHash) {
var version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _types.AddressVersion.PUBKEY;
var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'kaspa';
var eight0 = [0, 0, 0, 0, 0, 0, 0, 0];
var prefixData = (0, _utils.prefixToArray)(prefix).concat([0]);
if (version === 0 || version === 8) {
(0, _validate.validate)(pubKeyOrScriptHash.length === 64, getAddressByPublicKeyOrScriptHash.name, "Invalid pubkey hex length: ".concat(pubKeyOrScriptHash.length));
} else if (version === 1) {
(0, _validate.validate)(pubKeyOrScriptHash.length === 66, getAddressByPublicKeyOrScriptHash.name, "Invalid pubkey hex length: ".concat(pubKeyOrScriptHash.length));
} else {
throw new _core.error.SDKError(getAddressByPublicKeyOrScriptHash.name, "Unsupported version: ".concat(version));
}
var pubKeyArray = Array.prototype.slice.call((0, _utils.fromHex)(pubKeyOrScriptHash), 0);
var payloadData = (0, _convertBits.convert)(new Uint8Array([version].concat(pubKeyArray)), 8, 5, false);
var checksumData = new Uint8Array(prefixData.length + payloadData.length + eight0.length);
checksumData.set(prefixData);
checksumData.set(payloadData, prefixData.length);
checksumData.set(eight0, prefixData.length + payloadData.length);
var polymodData = (0, _checksum.checksumToArray)((0, _checksum.polymod)(checksumData));
var payload = new Uint8Array(payloadData.length + polymodData.length);
payload.set(payloadData);
payload.set(polymodData, payloadData.length);
return "".concat(prefix, ":") + (0, _base.encode)(payload);
}
function getType(versionByte) {
switch (versionByte & 120) {
case 0:
return 'pubkey';
case 8:
return 'scripthash';
default:
throw new _core.error.SDKError(getType.name, 'Invalid address type with version:' + versionByte);
}
}
function getScriptType(addressVersion) {
switch (addressVersion) {
case _types.AddressVersion.PUBKEY:
return _types.ScriptType.P2PK_SCHNORR;
case _types.AddressVersion.PUBKEY_ECDSA:
return _types.ScriptType.P2PK_ECDSA;
case _types.AddressVersion.SCRIPT_HASH:
return _types.ScriptType.P2SH;
default:
throw new _core.error.SDKError(getScriptType.name, "Unsupported addressVersion: ".concat(addressVersion));
}
}
function hasSingleCase(string) {
return string === string.toLowerCase() || string === string.toUpperCase();
}
function decodeAddressVersion(address) {
(0, _validate.validate)(hasSingleCase(address), decodeAddressVersion.name, 'Mixed case');
address = address.toLowerCase();
var pieces = address.split(':');
(0, _validate.validate)(pieces.length === 2, decodeAddressVersion.name, 'Invalid format: ' + address);
var prefix = pieces[0];
(0, _validate.validate)(prefix === 'kaspa', decodeAddressVersion.name, 'Invalid prefix: ' + address);
var encodedPayload = pieces[1];
var payload = (0, _base.decode)(encodedPayload);
(0, _validate.validate)((0, _validate.validChecksum)(prefix, payload), decodeAddressVersion.name, 'Invalid checksum: ' + address);
var convertedBits = (0, _convertBits.convert)(payload.slice(0, -8), 5, 8, true);
return convertedBits[0];
}
function decodeAddress(address) {
var addressVersion = decodeAddressVersion(address);
var pieces = address.split(':');
var prefix = pieces[0];
var encodedPayload = pieces[1];
var payload = (0, _base.decode)(encodedPayload);
var convertedBits = (0, _convertBits.convert)(payload.slice(0, -8), 5, 8, true);
var hashOrPublicKey = convertedBits.slice(1);
var byteLength = (0, _utils.getBitLength)(hashOrPublicKey) / 8;
var expectedByteLength = addressVersion === 1 ? 33 : 32;
if (addressVersion === 0 || addressVersion === 1 || addressVersion === 8) {
(0, _validate.validate)(byteLength === expectedByteLength, decodeAddress.name, "Invalid hash or public key byteLength: ".concat(byteLength, ", version: ").concat(addressVersion));
} else {
throw new _core.error.SDKError(decodeAddress.name, "Unsupported version: ".concat(addressVersion, " with address:").concat(address));
}
var type = getType(addressVersion);
var hashOrPublicKeyBuffer = Buffer.from(hashOrPublicKey);
(0, _validate.validate)(getAddressByPublicKeyOrScriptHash(hashOrPublicKeyBuffer.toString('hex'), addressVersion) === address, decodeAddress.name, 'Wrong public key from address: ' + address);
return {
payload: hashOrPublicKeyBuffer,
prefix: prefix,
type: type,
addressVersion: addressVersion
};
}
var OP_CODE = /*#__PURE__*/function (OP_CODE) {
OP_CODE[OP_CODE["OP_CHECKSIG"] = 172] = "OP_CHECKSIG";
OP_CODE[OP_CODE["OP_CODESEPARATOR"] = 171] = "OP_CODESEPARATOR";
OP_CODE[OP_CODE["OP_EQUAL"] = 135] = "OP_EQUAL";
OP_CODE[OP_CODE["OP_HASH256"] = 170] = "OP_HASH256";
return OP_CODE;
}(OP_CODE || {});
function getEndingOpCode(version) {
switch (version) {
case 0:
return Buffer.from([OP_CODE.OP_CHECKSIG]);
case 1:
return Buffer.from([OP_CODE.OP_CODESEPARATOR]);
case 8:
return Buffer.from([OP_CODE.OP_EQUAL]);
default:
throw new Error("Unsupport getEndingOpCode version: ".concat(version));
}
}
function getScriptPublicKey(publicKeyOrScripthash, addressVersion) {
var endingOpCode = getEndingOpCode(addressVersion);
var length = publicKeyOrScripthash.length;
var lengthByte = Buffer.from([length]);
var prefixOpCode = Buffer.from([OP_CODE.OP_HASH256]);
switch (addressVersion) {
case 0:
case 1:
return Buffer.concat([lengthByte, publicKeyOrScripthash, endingOpCode], length + 2);
case 8:
return Buffer.concat([prefixOpCode, lengthByte, publicKeyOrScripthash, endingOpCode], length + 3);
default:
throw new Error("Unsupported payToAddrScript address version: ".concat(addressVersion));
}
}
function addressToOutScript(address) {
var _decodeAddress = decodeAddress(address),
publicKeyOrScripthash = _decodeAddress.payload,
addressVersion = _decodeAddress.addressVersion;
var scriptType = getScriptType(addressVersion);
var outScript = getScriptPublicKey(publicKeyOrScripthash, addressVersion);
return {
scriptType: scriptType,
outScript: outScript,
outPubkeyOrHash: publicKeyOrScripthash
};
}
function getAddressVersion(scriptType) {
switch (scriptType) {
case _types.ScriptType.P2PK_SCHNORR:
return _types.AddressVersion.PUBKEY;
case _types.ScriptType.P2PK_ECDSA:
return _types.AddressVersion.PUBKEY_ECDSA;
case _types.ScriptType.P2SH:
return _types.AddressVersion.SCRIPT_HASH;
default:
throw new _core.error.SDKError(getAddressVersion.name, "Unsupported scriptType: ".concat(scriptType));
}
}
function getPubkeyOrScriptHash(scriptType, publicKey) {
var pubkeyHex = Buffer.isBuffer(publicKey) ? publicKey.toString('hex') : publicKey;
var addressVersion = getAddressVersion(scriptType);
switch (scriptType) {
case _types.ScriptType.P2PK_ECDSA:
return {
pubkeyOrScriptHash: pubkeyHex,
addressVersion: addressVersion
};
case _types.ScriptType.P2PK_SCHNORR:
return {
pubkeyOrScriptHash: toXOnly(pubkeyHex),
addressVersion: addressVersion
};
default:
throw new _core.error.SDKError(getPubkeyOrScriptHash.name, "Unsupported scriptType: ".concat(scriptType, ", publicKey: ").concat(pubkeyHex));
}
}
function pubkeyOrScriptHashToPayment(publicKeyOrScriptHash, addressVersion) {
var address = getAddressByPublicKeyOrScriptHash(publicKeyOrScriptHash, addressVersion);
var outScript = getScriptPublicKey(Buffer.from(publicKeyOrScriptHash, 'hex'), addressVersion);
var payment = {
address: address,
outScript: outScript
};
(0, _validate.validatePayment)(payment, pubkeyOrScriptHashToPayment.name, addressVersion);
return payment;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29yZSIsInJlcXVpcmUiLCJfdHlwZXMiLCJfYmFzZSIsIl9jaGVja3N1bSIsIl9jb252ZXJ0Qml0cyIsIl91dGlscyIsIl92YWxpZGF0ZSIsInRvWE9ubHkiLCJwdWJLZXkiLCJCdWZmZXIiLCJmcm9tIiwicmVzdWx0IiwibGVuZ3RoIiwic2xpY2UiLCJ0b1N0cmluZyIsImdldEFkZHJlc3NCeVB1YmxpY0tleU9yU2NyaXB0SGFzaCIsInB1YktleU9yU2NyaXB0SGFzaCIsInZlcnNpb24iLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJBZGRyZXNzVmVyc2lvbiIsIlBVQktFWSIsInByZWZpeCIsImVpZ2h0MCIsInByZWZpeERhdGEiLCJwcmVmaXhUb0FycmF5IiwiY29uY2F0IiwidmFsaWRhdGUiLCJuYW1lIiwiZXJyb3IiLCJTREtFcnJvciIsInB1YktleUFycmF5IiwiQXJyYXkiLCJwcm90b3R5cGUiLCJjYWxsIiwiZnJvbUhleCIsInBheWxvYWREYXRhIiwiY29udmVydCIsIlVpbnQ4QXJyYXkiLCJjaGVja3N1bURhdGEiLCJzZXQiLCJwb2x5bW9kRGF0YSIsImNoZWNrc3VtVG9BcnJheSIsInBvbHltb2QiLCJwYXlsb2FkIiwiZW5jb2RlIiwiZ2V0VHlwZSIsInZlcnNpb25CeXRlIiwiZ2V0U2NyaXB0VHlwZSIsImFkZHJlc3NWZXJzaW9uIiwiU2NyaXB0VHlwZSIsIlAyUEtfU0NITk9SUiIsIlBVQktFWV9FQ0RTQSIsIlAyUEtfRUNEU0EiLCJTQ1JJUFRfSEFTSCIsIlAyU0giLCJoYXNTaW5nbGVDYXNlIiwic3RyaW5nIiwidG9Mb3dlckNhc2UiLCJ0b1VwcGVyQ2FzZSIsImRlY29kZUFkZHJlc3NWZXJzaW9uIiwiYWRkcmVzcyIsInBpZWNlcyIsInNwbGl0IiwiZW5jb2RlZFBheWxvYWQiLCJkZWNvZGUiLCJ2YWxpZENoZWNrc3VtIiwiY29udmVydGVkQml0cyIsImRlY29kZUFkZHJlc3MiLCJoYXNoT3JQdWJsaWNLZXkiLCJieXRlTGVuZ3RoIiwiZ2V0Qml0TGVuZ3RoIiwiZXhwZWN0ZWRCeXRlTGVuZ3RoIiwidHlwZSIsImhhc2hPclB1YmxpY0tleUJ1ZmZlciIsIk9QX0NPREUiLCJnZXRFbmRpbmdPcENvZGUiLCJPUF9DSEVDS1NJRyIsIk9QX0NPREVTRVBBUkFUT1IiLCJPUF9FUVVBTCIsIkVycm9yIiwiZ2V0U2NyaXB0UHVibGljS2V5IiwicHVibGljS2V5T3JTY3JpcHRoYXNoIiwiZW5kaW5nT3BDb2RlIiwibGVuZ3RoQnl0ZSIsInByZWZpeE9wQ29kZSIsIk9QX0hBU0gyNTYiLCJhZGRyZXNzVG9PdXRTY3JpcHQiLCJfZGVjb2RlQWRkcmVzcyIsInNjcmlwdFR5cGUiLCJvdXRTY3JpcHQiLCJvdXRQdWJrZXlPckhhc2giLCJnZXRBZGRyZXNzVmVyc2lvbiIsImdldFB1YmtleU9yU2NyaXB0SGFzaCIsInB1YmxpY0tleSIsInB1YmtleUhleCIsImlzQnVmZmVyIiwicHVia2V5T3JTY3JpcHRIYXNoIiwicHVia2V5T3JTY3JpcHRIYXNoVG9QYXltZW50IiwicHVibGljS2V5T3JTY3JpcHRIYXNoIiwicGF5bWVudCIsInZhbGlkYXRlUGF5bWVudCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9hZGRyZXNzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5NSVQgTGljZW5zZVxuXG5Db3B5cmlnaHQgKGMpIDIwMjMgT0tYLmNvbVxuXG5QZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG5vZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG5pbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG50byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG5jb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbmZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG5GSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbkxJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG5PVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRVxuU09GVFdBUkUuXG4qL1xuXG4vLyBNb2RpZmllZCBieSBjb29sYml0eCBpbiAyMDI0XG5pbXBvcnQgeyBlcnJvciB9IGZyb20gJ0Bjb29sd2FsbGV0L2NvcmUnO1xuaW1wb3J0IHsgQWRkcmVzc1ZlcnNpb24sIFBheW1lbnQsIFNjcmlwdCwgU2NyaXB0VHlwZSB9IGZyb20gJy4uL2NvbmZpZy90eXBlcyc7XG5pbXBvcnQgeyBkZWNvZGUsIGVuY29kZSB9IGZyb20gJy4vYmFzZTMyJztcbmltcG9ydCB7IGNoZWNrc3VtVG9BcnJheSwgcG9seW1vZCB9IGZyb20gJy4vY2hlY2tzdW0nO1xuaW1wb3J0IHsgY29udmVydCB9IGZyb20gJy4vY29udmVydEJpdHMnO1xuaW1wb3J0IHsgZnJvbUhleCwgZ2V0Qml0TGVuZ3RoLCBwcmVmaXhUb0FycmF5IH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgeyB2YWxpZGF0ZSwgdmFsaWRhdGVQYXltZW50LCB2YWxpZENoZWNrc3VtIH0gZnJvbSAnLi92YWxpZGF0ZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiB0b1hPbmx5KHB1YktleTogQnVmZmVyIHwgc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBwdWJLZXkgPT09ICdzdHJpbmcnKSB7XG4gICAgcHViS2V5ID0gQnVmZmVyLmZyb20ocHViS2V5LCAnaGV4Jyk7XG4gIH1cbiAgY29uc3QgcmVzdWx0ID0gcHViS2V5Lmxlbmd0aCA9PT0gMzIgPyBwdWJLZXkgOiBwdWJLZXkuc2xpY2UoMSwgMzMpO1xuICByZXR1cm4gcmVzdWx0LnRvU3RyaW5nKCdoZXgnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFkZHJlc3NCeVB1YmxpY0tleU9yU2NyaXB0SGFzaChcbiAgcHViS2V5T3JTY3JpcHRIYXNoOiBzdHJpbmcsXG4gIHZlcnNpb24gPSBBZGRyZXNzVmVyc2lvbi5QVUJLRVksXG4gIHByZWZpeCA9ICdrYXNwYSdcbik6IHN0cmluZyB7XG4gIGNvbnN0IGVpZ2h0MCA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwXTtcbiAgY29uc3QgcHJlZml4RGF0YSA9IHByZWZpeFRvQXJyYXkocHJlZml4KS5jb25jYXQoWzBdKTtcblxuICBpZiAodmVyc2lvbiA9PT0gMCB8fCB2ZXJzaW9uID09PSA4KSB7XG4gICAgdmFsaWRhdGUoXG4gICAgICBwdWJLZXlPclNjcmlwdEhhc2gubGVuZ3RoID09PSA2NCxcbiAgICAgIGdldEFkZHJlc3NCeVB1YmxpY0tleU9yU2NyaXB0SGFzaC5uYW1lLFxuICAgICAgYEludmFsaWQgcHVia2V5IGhleCBsZW5ndGg6ICR7cHViS2V5T3JTY3JpcHRIYXNoLmxlbmd0aH1gXG4gICAgKTtcbiAgfSBlbHNlIGlmICh2ZXJzaW9uID09PSAxKSB7XG4gICAgdmFsaWRhdGUoXG4gICAgICBwdWJLZXlPclNjcmlwdEhhc2gubGVuZ3RoID09PSA2NixcbiAgICAgIGdldEFkZHJlc3NCeVB1YmxpY0tleU9yU2NyaXB0SGFzaC5uYW1lLFxuICAgICAgYEludmFsaWQgcHVia2V5IGhleCBsZW5ndGg6ICR7cHViS2V5T3JTY3JpcHRIYXNoLmxlbmd0aH1gXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgZXJyb3IuU0RLRXJyb3IoZ2V0QWRkcmVzc0J5UHVibGljS2V5T3JTY3JpcHRIYXNoLm5hbWUsIGBVbnN1cHBvcnRlZCB2ZXJzaW9uOiAke3ZlcnNpb259YCk7XG4gIH1cblxuICBjb25zdCBwdWJLZXlBcnJheSA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb21IZXgocHViS2V5T3JTY3JpcHRIYXNoKSwgMCk7XG4gIGNvbnN0IHBheWxvYWREYXRhID0gY29udmVydChuZXcgVWludDhBcnJheShbdmVyc2lvbl0uY29uY2F0KHB1YktleUFycmF5KSksIDgsIDUsIGZhbHNlKTtcbiAgY29uc3QgY2hlY2tzdW1EYXRhID0gbmV3IFVpbnQ4QXJyYXkocHJlZml4RGF0YS5sZW5ndGggKyBwYXlsb2FkRGF0YS5sZW5ndGggKyBlaWdodDAubGVuZ3RoKTtcbiAgY2hlY2tzdW1EYXRhLnNldChwcmVmaXhEYXRhKTtcbiAgY2hlY2tzdW1EYXRhLnNldChwYXlsb2FkRGF0YSwgcHJlZml4RGF0YS5sZW5ndGgpO1xuICBjaGVja3N1bURhdGEuc2V0KGVpZ2h0MCwgcHJlZml4RGF0YS5sZW5ndGggKyBwYXlsb2FkRGF0YS5sZW5ndGgpO1xuICBjb25zdCBwb2x5bW9kRGF0YSA9IGNoZWNrc3VtVG9BcnJheShwb2x5bW9kKGNoZWNrc3VtRGF0YSkpO1xuXG4gIGNvbnN0IHBheWxvYWQgPSBuZXcgVWludDhBcnJheShwYXlsb2FkRGF0YS5sZW5ndGggKyBwb2x5bW9kRGF0YS5sZW5ndGgpO1xuICBwYXlsb2FkLnNldChwYXlsb2FkRGF0YSk7XG4gIHBheWxvYWQuc2V0KHBvbHltb2REYXRhLCBwYXlsb2FkRGF0YS5sZW5ndGgpO1xuICByZXR1cm4gYCR7cHJlZml4fTpgICsgZW5jb2RlKHBheWxvYWQpO1xufVxuXG5mdW5jdGlvbiBnZXRUeXBlKHZlcnNpb25CeXRlOiBudW1iZXIpIHtcbiAgc3dpdGNoICh2ZXJzaW9uQnl0ZSAmIDEyMCkge1xuICAgIGNhc2UgMDpcbiAgICAgIHJldHVybiAncHVia2V5JztcbiAgICBjYXNlIDg6XG4gICAgICByZXR1cm4gJ3NjcmlwdGhhc2gnO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgZXJyb3IuU0RLRXJyb3IoZ2V0VHlwZS5uYW1lLCAnSW52YWxpZCBhZGRyZXNzIHR5cGUgd2l0aCB2ZXJzaW9uOicgKyB2ZXJzaW9uQnl0ZSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNjcmlwdFR5cGUoYWRkcmVzc1ZlcnNpb246IEFkZHJlc3NWZXJzaW9uKTogU2NyaXB0VHlwZSB7XG4gIHN3aXRjaCAoYWRkcmVzc1ZlcnNpb24pIHtcbiAgICBjYXNlIEFkZHJlc3NWZXJzaW9uLlBVQktFWTpcbiAgICAgIHJldHVybiBTY3JpcHRUeXBlLlAyUEtfU0NITk9SUjtcbiAgICBjYXNlIEFkZHJlc3NWZXJzaW9uLlBVQktFWV9FQ0RTQTpcbiAgICAgIHJldHVybiBTY3JpcHRUeXBlLlAyUEtfRUNEU0E7XG4gICAgY2FzZSBBZGRyZXNzVmVyc2lvbi5TQ1JJUFRfSEFTSDpcbiAgICAgIHJldHVybiBTY3JpcHRUeXBlLlAyU0g7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBlcnJvci5TREtFcnJvcihnZXRTY3JpcHRUeXBlLm5hbWUsIGBVbnN1cHBvcnRlZCBhZGRyZXNzVmVyc2lvbjogJHthZGRyZXNzVmVyc2lvbn1gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYXNTaW5nbGVDYXNlKHN0cmluZzogc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcgPT09IHN0cmluZy50b0xvd2VyQ2FzZSgpIHx8IHN0cmluZyA9PT0gc3RyaW5nLnRvVXBwZXJDYXNlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVBZGRyZXNzVmVyc2lvbihhZGRyZXNzOiBzdHJpbmcpOiBudW1iZXIge1xuICB2YWxpZGF0ZShoYXNTaW5nbGVDYXNlKGFkZHJlc3MpLCBkZWNvZGVBZGRyZXNzVmVyc2lvbi5uYW1lLCAnTWl4ZWQgY2FzZScpO1xuICBhZGRyZXNzID0gYWRkcmVzcy50b0xvd2VyQ2FzZSgpO1xuXG4gIGNvbnN0IHBpZWNlcyA9IGFkZHJlc3Muc3BsaXQoJzonKTtcbiAgdmFsaWRhdGUocGllY2VzLmxlbmd0aCA9PT0gMiwgZGVjb2RlQWRkcmVzc1ZlcnNpb24ubmFtZSwgJ0ludmFsaWQgZm9ybWF0OiAnICsgYWRkcmVzcyk7XG5cbiAgY29uc3QgcHJlZml4ID0gcGllY2VzWzBdO1xuICB2YWxpZGF0ZShwcmVmaXggPT09ICdrYXNwYScsIGRlY29kZUFkZHJlc3NWZXJzaW9uLm5hbWUsICdJbnZhbGlkIHByZWZpeDogJyArIGFkZHJlc3MpO1xuICBjb25zdCBlbmNvZGVkUGF5bG9hZCA9IHBpZWNlc1sxXTtcbiAgY29uc3QgcGF5bG9hZCA9IGRlY29kZShlbmNvZGVkUGF5bG9hZCk7XG4gIHZhbGlkYXRlKHZhbGlkQ2hlY2tzdW0ocHJlZml4LCBwYXlsb2FkKSwgZGVjb2RlQWRkcmVzc1ZlcnNpb24ubmFtZSwgJ0ludmFsaWQgY2hlY2tzdW06ICcgKyBhZGRyZXNzKTtcblxuICBjb25zdCBjb252ZXJ0ZWRCaXRzID0gY29udmVydChwYXlsb2FkLnNsaWNlKDAsIC04KSwgNSwgOCwgdHJ1ZSk7XG4gIHJldHVybiBjb252ZXJ0ZWRCaXRzWzBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpIHtcbiAgY29uc3QgYWRkcmVzc1ZlcnNpb24gPSBkZWNvZGVBZGRyZXNzVmVyc2lvbihhZGRyZXNzKTtcbiAgY29uc3QgcGllY2VzID0gYWRkcmVzcy5zcGxpdCgnOicpO1xuICBjb25zdCBwcmVmaXggPSBwaWVjZXNbMF07XG4gIGNvbnN0IGVuY29kZWRQYXlsb2FkID0gcGllY2VzWzFdO1xuICBjb25zdCBwYXlsb2FkID0gZGVjb2RlKGVuY29kZWRQYXlsb2FkKTtcblxuICBjb25zdCBjb252ZXJ0ZWRCaXRzID0gY29udmVydChwYXlsb2FkLnNsaWNlKDAsIC04KSwgNSwgOCwgdHJ1ZSk7XG4gIGNvbnN0IGhhc2hPclB1YmxpY0tleSA9IGNvbnZlcnRlZEJpdHMuc2xpY2UoMSk7XG4gIGNvbnN0IGJ5dGVMZW5ndGggPSBnZXRCaXRMZW5ndGgoaGFzaE9yUHVibGljS2V5KSAvIDg7XG5cbiAgY29uc3QgZXhwZWN0ZWRCeXRlTGVuZ3RoID0gYWRkcmVzc1ZlcnNpb24gPT09IDEgPyAzMyA6IDMyO1xuICBpZiAoYWRkcmVzc1ZlcnNpb24gPT09IDAgfHwgYWRkcmVzc1ZlcnNpb24gPT09IDEgfHwgYWRkcmVzc1ZlcnNpb24gPT09IDgpIHtcbiAgICB2YWxpZGF0ZShcbiAgICAgIGJ5dGVMZW5ndGggPT09IGV4cGVjdGVkQnl0ZUxlbmd0aCxcbiAgICAgIGRlY29kZUFkZHJlc3MubmFtZSxcbiAgICAgIGBJbnZhbGlkIGhhc2ggb3IgcHVibGljIGtleSBieXRlTGVuZ3RoOiAke2J5dGVMZW5ndGh9LCB2ZXJzaW9uOiAke2FkZHJlc3NWZXJzaW9ufWBcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBlcnJvci5TREtFcnJvcihkZWNvZGVBZGRyZXNzLm5hbWUsIGBVbnN1cHBvcnRlZCB2ZXJzaW9uOiAke2FkZHJlc3NWZXJzaW9ufSB3aXRoIGFkZHJlc3M6JHthZGRyZXNzfWApO1xuICB9XG5cbiAgY29uc3QgdHlwZSA9IGdldFR5cGUoYWRkcmVzc1ZlcnNpb24pO1xuXG4gIGNvbnN0IGhhc2hPclB1YmxpY0tleUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGhhc2hPclB1YmxpY0tleSk7XG4gIHZhbGlkYXRlKFxuICAgIGdldEFkZHJlc3NCeVB1YmxpY0tleU9yU2NyaXB0SGFzaChoYXNoT3JQdWJsaWNLZXlCdWZmZXIudG9TdHJpbmcoJ2hleCcpLCBhZGRyZXNzVmVyc2lvbikgPT09IGFkZHJlc3MsXG4gICAgZGVjb2RlQWRkcmVzcy5uYW1lLFxuICAgICdXcm9uZyBwdWJsaWMga2V5IGZyb20gYWRkcmVzczogJyArIGFkZHJlc3NcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHBheWxvYWQ6IGhhc2hPclB1YmxpY0tleUJ1ZmZlcixcbiAgICBwcmVmaXgsXG4gICAgdHlwZSxcbiAgICBhZGRyZXNzVmVyc2lvbixcbiAgfTtcbn1cblxuZW51bSBPUF9DT0RFIHtcbiAgT1BfQ0hFQ0tTSUcgPSAweGFjLFxuICBPUF9DT0RFU0VQQVJBVE9SID0gMHhhYixcbiAgT1BfRVFVQUwgPSAweDg3LFxuICBPUF9IQVNIMjU2ID0gMHhhYSxcbn1cblxuZnVuY3Rpb24gZ2V0RW5kaW5nT3BDb2RlKHZlcnNpb246IG51bWJlcikge1xuICBzd2l0Y2ggKHZlcnNpb24pIHtcbiAgICBjYXNlIDA6XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oW09QX0NPREUuT1BfQ0hFQ0tTSUddKTtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oW09QX0NPREUuT1BfQ09ERVNFUEFSQVRPUl0pO1xuICAgIGNhc2UgODpcbiAgICAgIHJldHVybiBCdWZmZXIuZnJvbShbT1BfQ09ERS5PUF9FUVVBTF0pO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydCBnZXRFbmRpbmdPcENvZGUgdmVyc2lvbjogJHt2ZXJzaW9ufWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFNjcmlwdFB1YmxpY0tleShwdWJsaWNLZXlPclNjcmlwdGhhc2g6IEJ1ZmZlciwgYWRkcmVzc1ZlcnNpb246IEFkZHJlc3NWZXJzaW9uKTogQnVmZmVyIHtcbiAgY29uc3QgZW5kaW5nT3BDb2RlID0gZ2V0RW5kaW5nT3BDb2RlKGFkZHJlc3NWZXJzaW9uKTtcbiAgY29uc3QgbGVuZ3RoID0gcHVibGljS2V5T3JTY3JpcHRoYXNoLmxlbmd0aDtcbiAgY29uc3QgbGVuZ3RoQnl0ZSA9IEJ1ZmZlci5mcm9tKFtsZW5ndGhdKTtcbiAgY29uc3QgcHJlZml4T3BDb2RlID0gQnVmZmVyLmZyb20oW09QX0NPREUuT1BfSEFTSDI1Nl0pO1xuICBzd2l0Y2ggKGFkZHJlc3NWZXJzaW9uKSB7XG4gICAgY2FzZSAwOlxuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtsZW5ndGhCeXRlLCBwdWJsaWNLZXlPclNjcmlwdGhhc2gsIGVuZGluZ09wQ29kZV0sIGxlbmd0aCArIDIpO1xuICAgIGNhc2UgODpcbiAgICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtwcmVmaXhPcENvZGUsIGxlbmd0aEJ5dGUsIHB1YmxpY0tleU9yU2NyaXB0aGFzaCwgZW5kaW5nT3BDb2RlXSwgbGVuZ3RoICsgMyk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgcGF5VG9BZGRyU2NyaXB0IGFkZHJlc3MgdmVyc2lvbjogJHthZGRyZXNzVmVyc2lvbn1gKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkcmVzc1RvT3V0U2NyaXB0KGFkZHJlc3M6IHN0cmluZyk6IFNjcmlwdCB7XG4gIGNvbnN0IHsgcGF5bG9hZDogcHVibGljS2V5T3JTY3JpcHRoYXNoLCBhZGRyZXNzVmVyc2lvbiB9ID0gZGVjb2RlQWRkcmVzcyhhZGRyZXNzKTtcbiAgY29uc3Qgc2NyaXB0VHlwZSA9IGdldFNjcmlwdFR5cGUoYWRkcmVzc1ZlcnNpb24pO1xuICBjb25zdCBvdXRTY3JpcHQgPSBnZXRTY3JpcHRQdWJsaWNLZXkocHVibGljS2V5T3JTY3JpcHRoYXNoLCBhZGRyZXNzVmVyc2lvbik7XG4gIHJldHVybiB7XG4gICAgc2NyaXB0VHlwZSxcbiAgICBvdXRTY3JpcHQsXG4gICAgb3V0UHVia2V5T3JIYXNoOiBwdWJsaWNLZXlPclNjcmlwdGhhc2gsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRyZXNzVmVyc2lvbihzY3JpcHRUeXBlOiBTY3JpcHRUeXBlKTogQWRkcmVzc1ZlcnNpb24ge1xuICBzd2l0Y2ggKHNjcmlwdFR5cGUpIHtcbiAgICBjYXNlIFNjcmlwdFR5cGUuUDJQS19TQ0hOT1JSOlxuICAgICAgcmV0dXJuIEFkZHJlc3NWZXJzaW9uLlBVQktFWTtcbiAgICBjYXNlIFNjcmlwdFR5cGUuUDJQS19FQ0RTQTpcbiAgICAgIHJldHVybiBBZGRyZXNzVmVyc2lvbi5QVUJLRVlfRUNEU0E7XG4gICAgY2FzZSBTY3JpcHRUeXBlLlAyU0g6XG4gICAgICByZXR1cm4gQWRkcmVzc1ZlcnNpb24uU0NSSVBUX0hBU0g7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBlcnJvci5TREtFcnJvcihnZXRBZGRyZXNzVmVyc2lvbi5uYW1lLCBgVW5zdXBwb3J0ZWQgc2NyaXB0VHlwZTogJHtzY3JpcHRUeXBlfWApO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQdWJrZXlPclNjcmlwdEhhc2goXG4gIHNjcmlwdFR5cGU6IFNjcmlwdFR5cGUsXG4gIHB1YmxpY0tleTogc3RyaW5nIHwgQnVmZmVyXG4pOiB7IHB1YmtleU9yU2NyaXB0SGFzaDogc3RyaW5nOyBhZGRyZXNzVmVyc2lvbjogQWRkcmVzc1ZlcnNpb24gfSB7XG4gIGNvbnN0IHB1YmtleUhleCA9IEJ1ZmZlci5pc0J1ZmZlcihwdWJsaWNLZXkpID8gcHVibGljS2V5LnRvU3RyaW5nKCdoZXgnKSA6IHB1YmxpY0tleTtcbiAgY29uc3QgYWRkcmVzc1ZlcnNpb24gPSBnZXRBZGRyZXNzVmVyc2lvbihzY3JpcHRUeXBlKTtcbiAgc3dpdGNoIChzY3JpcHRUeXBlKSB7XG4gICAgY2FzZSBTY3JpcHRUeXBlLlAyUEtfRUNEU0E6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwdWJrZXlPclNjcmlwdEhhc2g6IHB1YmtleUhleCxcbiAgICAgICAgYWRkcmVzc1ZlcnNpb24sXG4gICAgICB9O1xuICAgIGNhc2UgU2NyaXB0VHlwZS5QMlBLX1NDSE5PUlI6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwdWJrZXlPclNjcmlwdEhhc2g6IHRvWE9ubHkocHVia2V5SGV4KSxcbiAgICAgICAgYWRkcmVzc1ZlcnNpb24sXG4gICAgICB9O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgZXJyb3IuU0RLRXJyb3IoXG4gICAgICAgIGdldFB1YmtleU9yU2NyaXB0SGFzaC5uYW1lLFxuICAgICAgICBgVW5zdXBwb3J0ZWQgc2NyaXB0VHlwZTogJHtzY3JpcHRUeXBlfSwgcHVibGljS2V5OiAke3B1YmtleUhleH1gXG4gICAgICApO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwdWJrZXlPclNjcmlwdEhhc2hUb1BheW1lbnQocHVibGljS2V5T3JTY3JpcHRIYXNoOiBzdHJpbmcsIGFkZHJlc3NWZXJzaW9uOiBBZGRyZXNzVmVyc2lvbik6IFBheW1lbnQge1xuICBjb25zdCBhZGRyZXNzID0gZ2V0QWRkcmVzc0J5UHVibGljS2V5T3JTY3JpcHRIYXNoKHB1YmxpY0tleU9yU2NyaXB0SGFzaCwgYWRkcmVzc1ZlcnNpb24pO1xuICBjb25zdCBvdXRTY3JpcHQgPSBnZXRTY3JpcHRQdWJsaWNLZXkoQnVmZmVyLmZyb20ocHVibGljS2V5T3JTY3JpcHRIYXNoLCAnaGV4JyksIGFkZHJlc3NWZXJzaW9uKTtcbiAgY29uc3QgcGF5bWVudDogUGF5bWVudCA9IHtcbiAgICBhZGRyZXNzLFxuICAgIG91dFNjcmlwdCxcbiAgfTtcbiAgdmFsaWRhdGVQYXltZW50KHBheW1lbnQsIHB1YmtleU9yU2NyaXB0SGFzaFRvUGF5bWVudC5uYW1lLCBhZGRyZXNzVmVyc2lvbik7XG4gIHJldHVybiBwYXltZW50O1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQXlCQSxJQUFBQSxLQUFBLEdBQUFDLE9BQUE7QUFDQSxJQUFBQyxNQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxLQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxTQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxZQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxNQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxTQUFBLEdBQUFOLE9BQUE7QUEvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFTTyxTQUFTTyxPQUFPQSxDQUFDQyxNQUF1QixFQUFVO0VBQ3ZELElBQUksT0FBT0EsTUFBTSxLQUFLLFFBQVEsRUFBRTtJQUM5QkEsTUFBTSxHQUFHQyxNQUFNLENBQUNDLElBQUksQ0FBQ0YsTUFBTSxFQUFFLEtBQUssQ0FBQztFQUNyQztFQUNBLElBQU1HLE1BQU0sR0FBR0gsTUFBTSxDQUFDSSxNQUFNLEtBQUssRUFBRSxHQUFHSixNQUFNLEdBQUdBLE1BQU0sQ0FBQ0ssS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7RUFDbEUsT0FBT0YsTUFBTSxDQUFDRyxRQUFRLENBQUMsS0FBSyxDQUFDO0FBQy9CO0FBRU8sU0FBU0MsaUNBQWlDQSxDQUMvQ0Msa0JBQTBCLEVBR2xCO0VBQUEsSUFGUkMsT0FBTyxHQUFBQyxTQUFBLENBQUFOLE1BQUEsUUFBQU0sU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBR0UscUJBQWMsQ0FBQ0MsTUFBTTtFQUFBLElBQy9CQyxNQUFNLEdBQUFKLFNBQUEsQ0FBQU4sTUFBQSxRQUFBTSxTQUFBLFFBQUFDLFNBQUEsR0FBQUQs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