@bitgo/utxo-lib
Version:
Client-side Bitcoin JavaScript library
122 lines • 18.8 kB
JavaScript
;
/**
* Contains helper methods for getting and sorting root nodes from a PSBT.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorNoMultiSigInputFound = void 0;
exports.getUnsortedRootNodes = getUnsortedRootNodes;
exports.sortRootNodes = sortRootNodes;
exports.getSortedRootNodes = getSortedRootNodes;
const assert_1 = require("assert");
const bs58check = require("bs58check");
const types_1 = require("../../types");
const secp256k1_1 = require("@bitgo/secp256k1");
const outputScripts_1 = require("../../outputScripts");
const transaction_1 = require("../../transaction");
const Psbt_1 = require("../Psbt");
/**
* Error thrown when no multi-sig input is found in a PSBT.
* */
class ErrorNoMultiSigInputFound extends Error {
constructor(message) {
super(message);
}
}
exports.ErrorNoMultiSigInputFound = ErrorNoMultiSigInputFound;
/**
* Retrieves unsorted root BIP32Interface nodes from a PSBT if available.
* @param psbt - The PSBT from which to extract the global Xpubs.
* @returns An array of BIP32Interface objects or undefined if not available.
*/
function getUnsortedRootNodes(psbt) {
const bip32s = psbt.data.globalMap.globalXpub?.map((xpub) => (0, secp256k1_1.BIP32Factory)(secp256k1_1.ecc).fromBase58(bs58check.encode(xpub.extendedPubkey)));
(0, assert_1.ok)(!bip32s || (0, types_1.isTriple)(bip32s), `Invalid globalXpubs in PSBT. Expected 3 or none. Got ${bip32s?.length}`);
return bip32s;
}
/**
* Determines if the given public keys' permutation matches a specified script.
* @param params - Object containing public keys, permutation, script public key, script type, and network.
* @returns A boolean indicating if the permutation matches the script.
*/
function matchesScript({ pubKeys, perm, scriptPubKey, parsedScriptType, network, }) {
const pubKeysPerm = [pubKeys[perm[0]], pubKeys[perm[1]], pubKeys[perm[2]]];
const scriptTypes = (0, Psbt_1.toScriptType2Of3s)(parsedScriptType);
return scriptTypes.some((scriptType) => (0, outputScripts_1.createOutputScript2of3)(pubKeysPerm, scriptType, network).scriptPubKey.equals(scriptPubKey));
}
/**
* Finds the correct order of public keys to match a given script.
* @param pubKeys - Array of public keys involved in the script.
* @param scriptPubKey - The script public key to match against.
* @param parsedScriptType - The parsed script type.
* @param network - Bitcoin network.
* @returns The order of public keys that match the script.
*/
function findSortOrderOfPubKeys(pubKeys, scriptPubKey, parsedScriptType, network) {
const permutations = [
[0, 1, 2],
[0, 2, 1],
[1, 0, 2],
[1, 2, 0],
[2, 0, 1],
[2, 1, 0],
];
const order = permutations.find((perm) => matchesScript({ pubKeys, perm, scriptPubKey, parsedScriptType, network }));
(0, assert_1.ok)(order, 'Could not find sort order of multi sig public keys');
return order;
}
/**
* Extracts multi-sig input data, including script type, script public key, and derivation path, from the first relevant PSBT input.
* @param psbt - The PSBT to extract data from.
* @returns An object containing the parsed script type, script public key, and derivation path.
*/
function getFirstMultiSigInputData(psbt) {
function getScriptPubKey(input, prevOutIndex) {
const scriptPubKey = input.witnessUtxo?.script ??
(input.nonWitnessUtxo
? (0, transaction_1.createTransactionFromBuffer)(input.nonWitnessUtxo, psbt.network, { amountType: 'bigint' }).outs[prevOutIndex]
.script
: undefined);
(0, assert_1.ok)(scriptPubKey, 'Input scriptPubKey can not be found');
return scriptPubKey;
}
function getDerivationPath(input) {
const bip32Dv = input?.bip32Derivation ?? input?.tapBip32Derivation;
(0, assert_1.ok)(bip32Dv?.length, 'Input Bip32Derivation can not be found');
return bip32Dv[0].path;
}
const txInputs = psbt.txInputs;
for (let i = 0; i < psbt.data.inputs.length; i++) {
const input = psbt.data.inputs[i];
const parsedScriptType = (0, Psbt_1.getPsbtInputScriptType)(input);
if (parsedScriptType === 'p2shP2pk') {
continue;
}
const scriptPubKey = getScriptPubKey(input, txInputs[i].index);
const derivationPath = getDerivationPath(input);
return { parsedScriptType, scriptPubKey, derivationPath };
}
throw new ErrorNoMultiSigInputFound('No multi sig input found');
}
/**
* Sorts given root nodes based on the script compatibility with the PSBT's multi-sig inputs.
* @param psbt - The PSBT containing multi-sig inputs.
* @param rootNodes - Array of root nodes to sort.
* @returns An array of BIP32Interface objects in the order that matches the multi-sig script.
*/
function sortRootNodes(psbt, rootNodes) {
const { parsedScriptType, scriptPubKey, derivationPath } = getFirstMultiSigInputData(psbt);
const pubKeys = rootNodes.map((rootNode) => rootNode.derivePath(derivationPath).publicKey);
const order = findSortOrderOfPubKeys(pubKeys, scriptPubKey, parsedScriptType, psbt.network);
return order.map((i) => rootNodes[i]);
}
/**
* Retrieves sorted root nodes from a PSBT, ensuring they are ordered according to script compatibility.
* @param psbt - The PSBT to extract and sort root nodes from.
* @returns An array of sorted BIP32Interface root nodes.
*/
function getSortedRootNodes(psbt) {
const unsortedRootNodes = getUnsortedRootNodes(psbt);
(0, assert_1.ok)(unsortedRootNodes, 'Could not find root nodes in PSBT');
return sortRootNodes(psbt, unsortedRootNodes);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUm9vdE5vZGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3dhbGxldC9wc2J0L1Jvb3ROb2Rlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7OztBQTZCSCxvREFNQztBQXdHRCxzQ0FLQztBQU9ELGdEQUlDO0FBekpELG1DQUFzQztBQUN0Qyx1Q0FBdUM7QUFHdkMsdUNBQStDO0FBQy9DLGdEQUErRTtBQUcvRSx1REFBNkQ7QUFFN0QsbURBQWdFO0FBQ2hFLGtDQUFvRTtBQUVwRTs7S0FFSztBQUNMLE1BQWEseUJBQTBCLFNBQVEsS0FBSztJQUNsRCxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pCLENBQUM7Q0FDRjtBQUpELDhEQUlDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLG9CQUFvQixDQUFDLElBQWM7SUFDakQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQzFELElBQUEsd0JBQVksRUFBQyxlQUFNLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FDdkUsQ0FBQztJQUNGLElBQUEsV0FBTSxFQUFDLENBQUMsTUFBTSxJQUFJLElBQUEsZ0JBQVEsRUFBQyxNQUFNLENBQUMsRUFBRSx3REFBd0QsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDOUcsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGFBQWEsQ0FBQyxFQUNyQixPQUFPLEVBQ1AsSUFBSSxFQUNKLFlBQVksRUFDWixnQkFBZ0IsRUFDaEIsT0FBTyxHQU9SO0lBQ0MsTUFBTSxXQUFXLEdBQW1CLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxD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QyxDQUFDO0FBQ2hELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnRhaW5zIGhlbHBlciBtZXRob2RzIGZvciBnZXR0aW5nIGFuZCBzb3J0aW5nIHJvb3Qgbm9kZXMgZnJvbSBhIFBTQlQuXG4gKi9cblxuaW1wb3J0IHsgb2sgYXMgYXNzZXJ0IH0gZnJvbSAnYXNzZXJ0JztcbmltcG9ydCAqIGFzIGJzNThjaGVjayBmcm9tICdiczU4Y2hlY2snO1xuXG5pbXBvcnQgeyBVdHhvUHNidCB9IGZyb20gJy4uLy4uL1V0eG9Qc2J0JztcbmltcG9ydCB7IGlzVHJpcGxlLCBUcmlwbGUgfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQgeyBCSVAzMkZhY3RvcnksIEJJUDMySW50ZXJmYWNlLCBlY2MgYXMgZWNjTGliIH0gZnJvbSAnQGJpdGdvL3NlY3AyNTZrMSc7XG5pbXBvcnQgeyBQYXJzZWRTY3JpcHRUeXBlMk9mMyB9IGZyb20gJy4uLy4uL3BhcnNlSW5wdXQnO1xuaW1wb3J0IHsgTmV0d29yayB9IGZyb20gJy4uLy4uLy4uL25ldHdvcmtzJztcbmltcG9ydCB7IGNyZWF0ZU91dHB1dFNjcmlwdDJvZjMgfSBmcm9tICcuLi8uLi9vdXRwdXRTY3JpcHRzJztcbmltcG9ydCB7IFBzYnRJbnB1dCB9IGZyb20gJ2JpcDE3NC9zcmMvbGliL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyIH0gZnJvbSAnLi4vLi4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgZ2V0UHNidElucHV0U2NyaXB0VHlwZSwgdG9TY3JpcHRUeXBlMk9mM3MgfSBmcm9tICcuLi9Qc2J0JztcblxuLyoqXG4gKiBFcnJvciB0aHJvd24gd2hlbiBubyBtdWx0aS1zaWcgaW5wdXQgaXMgZm91bmQgaW4gYSBQU0JULlxuICogKi9cbmV4cG9ydCBjbGFzcyBFcnJvck5vTXVsdGlTaWdJbnB1dEZvdW5kIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgfVxufVxuXG4vKipcbiAqIFJldHJpZXZlcyB1bnNvcnRlZCByb290IEJJUDMySW50ZXJmYWNlIG5vZGVzIGZyb20gYSBQU0JUIGlmIGF2YWlsYWJsZS5cbiAqIEBwYXJhbSBwc2J0IC0gVGhlIFBTQlQgZnJvbSB3aGljaCB0byBleHRyYWN0IHRoZSBnbG9iYWwgWHB1YnMuXG4gKiBAcmV0dXJucyBBbiBhcnJheSBvZiBCSVAzMkludGVyZmFjZSBvYmplY3RzIG9yIHVuZGVmaW5lZCBpZiBub3QgYXZhaWxhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VW5zb3J0ZWRSb290Tm9kZXMocHNidDogVXR4b1BzYnQpOiBUcmlwbGU8QklQMzJJbnRlcmZhY2U+IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgYmlwMzJzID0gcHNidC5kYXRhLmdsb2JhbE1hcC5nbG9iYWxYcHViPy5tYXAoKHhwdWIpID0+XG4gICAgQklQMzJGYWN0b3J5KGVjY0xpYikuZnJvbUJhc2U1OChiczU4Y2hlY2suZW5jb2RlKHhwdWIuZXh0ZW5kZWRQdWJrZXkpKVxuICApO1xuICBhc3NlcnQoIWJpcDMycyB8fCBpc1RyaXBsZShiaXAzMnMpLCBgSW52YWxpZCBnbG9iYWxYcHVicyBpbiBQU0JULiBFeHBlY3RlZCAzIG9yIG5vbmUuIEdvdCAke2JpcDMycz8ubGVuZ3RofWApO1xuICByZXR1cm4gYmlwMzJzO1xufVxuXG4vKipcbiAqIERldGVybWluZXMgaWYgdGhlIGdpdmVuIHB1YmxpYyBrZXlzJyBwZXJtdXRhdGlvbiBtYXRjaGVzIGEgc3BlY2lmaWVkIHNjcmlwdC5cbiAqIEBwYXJhbSBwYXJhbXMgLSBPYmplY3QgY29udGFpbmluZyBwdWJsaWMga2V5cywgcGVybXV0YXRpb24sIHNjcmlwdCBwdWJsaWMga2V5LCBzY3JpcHQgdHlwZSwgYW5kIG5ldHdvcmsuXG4gKiBAcmV0dXJucyBBIGJvb2xlYW4gaW5kaWNhdGluZyBpZiB0aGUgcGVybXV0YXRpb24gbWF0Y2hlcyB0aGUgc2NyaXB0LlxuICovXG5mdW5jdGlvbiBtYXRjaGVzU2NyaXB0KHtcbiAgcHViS2V5cyxcbiAgcGVybSxcbiAgc2NyaXB0UHViS2V5LFxuICBwYXJzZWRTY3JpcHRUeXBlLFxuICBuZXR3b3JrLFxufToge1xuICBwdWJLZXlzOiBCdWZmZXJbXTtcbiAgcGVybTogVHJpcGxlPG51bWJlcj47XG4gIHNjcmlwdFB1YktleTogQnVmZmVyO1xuICBwYXJzZWRTY3JpcHRUeXBlOiBQYXJzZWRTY3JpcHRUeXBlMk9mMztcbiAgbmV0d29yazogTmV0d29yaztcbn0pOiBib29sZWFuIHtcbiAgY29uc3QgcHViS2V5c1Blcm06IFRyaXBsZTxCdWZmZXI+ID0gW3B1YktleXNbcGVybVswXV0sIHB1YktleXNbcGVybVsxXV0sIHB1YktleXNbcGVybVsyXV1dO1xuICBjb25zdCBzY3JpcHRUeXBlcyA9IHRvU2NyaXB0VHlwZTJPZjNzKHBhcnNlZFNjcmlwdFR5cGUpO1xuICByZXR1cm4gc2NyaXB0VHlwZXMuc29tZSgoc2NyaXB0VHlwZSkgPT5cbiAgICBjcmVhdGVPdXRwdXRTY3JpcHQyb2YzKHB1YktleXNQZXJtLCBzY3JpcHRUeXBlLCBuZXR3b3JrKS5zY3JpcHRQdWJLZXkuZXF1YWxzKHNjcmlwdFB1YktleSlcbiAgKTtcbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgY29ycmVjdCBvcmRlciBvZiBwdWJsaWMga2V5cyB0byBtYXRjaCBhIGdpdmVuIHNjcmlwdC5cbiAqIEBwYXJhbSBwdWJLZXlzIC0gQXJyYXkgb2YgcHVibGljIGtleXMgaW52b2x2ZWQgaW4gdGhlIHNjcmlwdC5cbiAqIEBwYXJhbSBzY3JpcHRQdWJLZXkgLSBUaGUgc2NyaXB0IHB1YmxpYyBrZXkgdG8gbWF0Y2ggYWdhaW5zdC5cbiAqIEBwYXJhbSBwYXJzZWRTY3JpcHRUeXBlIC0gVGhlIHBhcnNlZCBzY3JpcHQgdHlwZS5cbiAqIEBwYXJhbSBuZXR3b3JrIC0gQml0Y29pbiBuZXR3b3JrLlxuICogQHJldHVybnMgVGhlIG9yZGVyIG9mIHB1YmxpYyBrZXlzIHRoYXQgbWF0Y2ggdGhlIHNjcmlwdC5cbiAqL1xuZnVuY3Rpb24gZmluZFNvcnRPcmRlck9mUHViS2V5cyhcbiAgcHViS2V5czogVHJpcGxlPEJ1ZmZlcj4sXG4gIHNjcmlwdFB1YktleTogQnVmZmVyLFxuICBwYXJzZWRTY3JpcHRUeXBlOiBQYXJzZWRTY3JpcHRUeXBlMk9mMyxcbiAgbmV0d29yazogTmV0d29ya1xuKTogVHJpcGxlPG51bWJlcj4ge1xuICBjb25zdCBwZXJtdXRhdGlvbnM6IEFycmF5PFRyaXBsZTxudW1iZXI+PiA9IFtcbiAgICBbMCwgMSwgMl0sXG4gICAgWzAsIDIsIDFdLFxuICAgIFsxLCAwLCAyXSxcbiAgICBbMSwgMiwgMF0sXG4gICAgWzIsIDAsIDFdLFxuICAgIFsyLCAxLCAwXSxcbiAgXTtcblxuICBjb25zdCBvcmRlciA9IHBlcm11dGF0aW9ucy5maW5kKChwZXJtKSA9PiBtYXRjaGVzU2NyaXB0KHsgcHViS2V5cywgcGVybSwgc2NyaXB0UHViS2V5LCBwYXJzZWRTY3JpcHRUeXBlLCBuZXR3b3JrIH0pKTtcbiAgYXNzZXJ0KG9yZGVyLCAnQ291bGQgbm90IGZpbmQgc29ydCBvcmRlciBvZiBtdWx0aSBzaWcgcHVibGljIGtleXMnKTtcbiAgcmV0dXJuIG9yZGVyO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIG11bHRpLXNpZyBpbnB1dCBkYXRhLCBpbmNsdWRpbmcgc2NyaXB0IHR5cGUsIHNjcmlwdCBwdWJsaWMga2V5LCBhbmQgZGVyaXZhdGlvbiBwYXRoLCBmcm9tIHRoZSBmaXJzdCByZWxldmFudCBQU0JUIGlucHV0LlxuICogQHBhcmFtIHBzYnQgLSBUaGUgUFNCVCB0byBleHRyYWN0IGRhdGEgZnJvbS5cbiAqIEByZXR1cm5zIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBwYXJzZWQgc2NyaXB0IHR5cGUsIHNjcmlwdCBwdWJsaWMga2V5LCBhbmQgZGVyaXZhdGlvbiBwYXRoLlxuICovXG5mdW5jdGlvbiBnZXRGaXJzdE11bHRpU2lnSW5wdXREYXRhKHBzYnQ6IFV0eG9Qc2J0KToge1xuICBwYXJzZWRTY3JpcHRUeXBlOiBQYXJzZWRTY3JpcHRUeXBlMk9mMztcbiAgc2NyaXB0UHViS2V5OiBCdWZmZXI7XG4gIGRlcml2YXRpb25QYXRoOiBzdHJpbmc7XG59IHtcbiAgZnVuY3Rpb24gZ2V0U2NyaXB0UHViS2V5KGlucHV0OiBQc2J0SW5wdXQsIHByZXZPdXRJbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3Qgc2NyaXB0UHViS2V5ID1cbiAgICAgIGlucHV0LndpdG5lc3NVdHhvPy5zY3JpcHQgPz9cbiAgICAgIChpbnB1dC5ub25XaXRuZXNzVXR4b1xuICAgICAgICA/IGNyZWF0ZVRyYW5zYWN0aW9uRnJvbUJ1ZmZlcihpbnB1dC5ub25XaXRuZXNzVXR4bywgcHNidC5uZXR3b3JrLCB7IGFtb3VudFR5cGU6ICdiaWdpbnQnIH0pLm91dHNbcHJldk91dEluZGV4XVxuICAgICAgICAgICAgLnNjcmlwdFxuICAgICAgICA6IHVuZGVmaW5lZCk7XG4gICAgYXNzZXJ0KHNjcmlwdFB1YktleSwgJ0lucHV0IHNjcmlwdFB1YktleSBjYW4gbm90IGJlIGZvdW5kJyk7XG4gICAgcmV0dXJuIHNjcmlwdFB1YktleTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERlcml2YXRpb25QYXRoKGlucHV0OiBQc2J0SW5wdXQpIHtcbiAgICBjb25zdCBiaXAzMkR2ID0gaW5wdXQ/LmJpcDMyRGVyaXZhdGlvbiA/PyBpbnB1dD8udGFwQmlwMzJEZXJpdmF0aW9uO1xuICAgIGFzc2VydChiaXAzMkR2Py5sZW5ndGgsICdJbnB1dCBCaXAzMkRlcml2YXRpb24gY2FuIG5vdCBiZSBmb3VuZCcpO1xuICAgIHJldHVybiBiaXAzMkR2WzBdLnBhdGg7XG4gIH1cblxuICBjb25zdCB0eElucHV0cyA9IHBzYnQudHhJbnB1dHM7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwc2J0LmRhdGEuaW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgaW5wdXQgPSBwc2J0LmRhdGEuaW5wdXRzW2ldO1xuICAgIGNvbnN0IHBhcnNlZFNjcmlwdFR5cGUgPSBnZXRQc2J0SW5wdXRTY3JpcHRUeXBlKGlucHV0KTtcbiAgICBpZiAocGFyc2VkU2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMnBrJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdFB1YktleSA9IGdldFNjcmlwdFB1YktleShpbnB1dCwgdHhJbnB1dHNbaV0uaW5kZXgpO1xuICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gZ2V0RGVyaXZhdGlvblBhdGgoaW5wdXQpO1xuICAgIHJldHVybiB7IHBhcnNlZFNjcmlwdFR5cGUsIHNjcmlwdFB1YktleSwgZGVyaXZhdGlvblBhdGggfTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvck5vTXVsdGlTaWdJbnB1dEZvdW5kKCdObyBtdWx0aSBzaWcgaW5wdXQgZm91bmQnKTtcbn1cblxuLyoqXG4gKiBTb3J0cyBnaXZlbiByb290IG5vZGVzIGJhc2VkIG9uIHRoZSBzY3JpcHQgY29tcGF0aWJpbGl0eSB3aXRoIHRoZSBQU0JUJ3MgbXVsdGktc2lnIGlucHV0cy5cbiAqIEBwYXJhbSBwc2J0IC0gVGhlIFBTQlQgY29udGFpbmluZyBtdWx0aS1zaWcgaW5wdXRzLlxuICogQHBhcmFtIHJvb3ROb2RlcyAtIEFycmF5IG9mIHJvb3Qgbm9kZXMgdG8gc29ydC5cbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIEJJUDMySW50ZXJmYWNlIG9iamVjdHMgaW4gdGhlIG9yZGVyIHRoYXQgbWF0Y2hlcyB0aGUgbXVsdGktc2lnIHNjcmlwdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvcnRSb290Tm9kZXMocHNidDogVXR4b1BzYnQsIHJvb3ROb2RlczogVHJpcGxlPEJJUDMySW50ZXJmYWNlPik6IFRyaXBsZTxCSVAzMkludGVyZmFjZT4ge1xuICBjb25zdCB7IHBhcnNlZFNjcmlwdFR5cGUsIHNjcmlwdFB1YktleSwgZGVyaXZhdGlvblBhdGggfSA9IGdldEZpcnN0TXVsdGlTaWdJbnB1dERhdGEocHNidCk7XG4gIGNvbnN0IHB1YktleXMgPSByb290Tm9kZXMubWFwKChyb290Tm9kZSkgPT4gcm9vdE5vZGUuZGVyaXZlUGF0aChkZXJpdmF0aW9uUGF0aCkucHVibGljS2V5KSBhcyBUcmlwbGU8QnVmZmVyPjtcbiAgY29uc3Qgb3JkZXIgPSBmaW5kU29ydE9yZGVyT2ZQdWJLZXlzKHB1YktleXMsIHNjcmlwdFB1YktleSwgcGFyc2VkU2NyaXB0VHlwZSwgcHNidC5uZXR3b3JrKTtcbiAgcmV0dXJuIG9yZGVyLm1hcCgoaSkgPT4gcm9vdE5vZGVzW2ldKSBhcyBUcmlwbGU8QklQMzJJbnRlcmZhY2U+O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyBzb3J0ZWQgcm9vdCBub2RlcyBmcm9tIGEgUFNCVCwgZW5zdXJpbmcgdGhleSBhcmUgb3JkZXJlZCBhY2NvcmRpbmcgdG8gc2NyaXB0IGNvbXBhdGliaWxpdHkuXG4gKiBAcGFyYW0gcHNidCAtIFRoZSBQU0JUIHRvIGV4dHJhY3QgYW5kIHNvcnQgcm9vdCBub2RlcyBmcm9tLlxuICogQHJldHVybnMgQW4gYXJyYXkgb2Ygc29ydGVkIEJJUDMySW50ZXJmYWNlIHJvb3Qgbm9kZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTb3J0ZWRSb290Tm9kZXMocHNidDogVXR4b1BzYnQpOiBUcmlwbGU8QklQMzJJbnRlcmZhY2U+IHtcbiAgY29uc3QgdW5zb3J0ZWRSb290Tm9kZXMgPSBnZXRVbnNvcnRlZFJvb3ROb2Rlcyhwc2J0KTtcbiAgYXNzZXJ0KHVuc29ydGVkUm9vdE5vZGVzLCAnQ291bGQgbm90IGZpbmQgcm9vdCBub2RlcyBpbiBQU0JUJyk7XG4gIHJldHVybiBzb3J0Um9vdE5vZGVzKHBzYnQsIHVuc29ydGVkUm9vdE5vZGVzKTtcbn1cbiJdfQ==