@bitgo-beta/utxo-lib
Version:
Client-side Bitcoin JavaScript library
198 lines • 24.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSpendScriptP2tr = exports.createPaymentP2tr = exports.toXOnlyPublicKey = exports.createOutputScript2of3 = exports.createOutputScriptP2shP2pk = exports.scriptType2Of3AsPrevOutType = exports.isSupportedScriptType = exports.isScriptType2Of3 = exports.scriptTypes2Of3 = exports.scriptTypeP2shP2pk = exports.scriptTypeForChain = void 0;
const assert = require("assert");
const bitcoinjs = require("bitcoinjs-lib");
const __1 = require("..");
const types_1 = require("./types");
const noble_ecc_1 = require("../noble_ecc");
var chains_1 = require("./wallet/chains");
Object.defineProperty(exports, "scriptTypeForChain", { enumerable: true, get: function () { return chains_1.scriptTypeForChain; } });
exports.scriptTypeP2shP2pk = 'p2shP2pk';
exports.scriptTypes2Of3 = ['p2sh', 'p2shP2wsh', 'p2wsh', 'p2tr'];
function isScriptType2Of3(t) {
return exports.scriptTypes2Of3.includes(t);
}
exports.isScriptType2Of3 = isScriptType2Of3;
/**
* @param network
* @param scriptType
* @return true iff script type is supported for network
*/
function isSupportedScriptType(network, scriptType) {
switch (scriptType) {
case 'p2sh':
case 'p2shP2pk':
return true;
case 'p2shP2wsh':
case 'p2wsh':
return __1.supportsSegwit(network);
case 'p2tr':
return __1.supportsTaproot(network);
}
/* istanbul ignore next */
throw new Error(`unexpected script type ${scriptType}`);
}
exports.isSupportedScriptType = isSupportedScriptType;
/**
* @param t
* @return string prevOut as defined in PREVOUT_TYPES (bitcoinjs-lib/.../transaction_builder.js)
*/
function scriptType2Of3AsPrevOutType(t) {
switch (t) {
case 'p2sh':
return 'p2sh-p2ms';
case 'p2shP2wsh':
return 'p2sh-p2wsh-p2ms';
case 'p2wsh':
return 'p2wsh-p2ms';
case 'p2tr':
return 'p2tr-p2ns';
}
/* istanbul ignore next */
throw new Error(`unsupported script type ${t}`);
}
exports.scriptType2Of3AsPrevOutType = scriptType2Of3AsPrevOutType;
/**
* Return scripts for p2sh-p2pk (used for BCH/BSV replay protection)
* @param pubkey
*/
function createOutputScriptP2shP2pk(pubkey) {
const p2pk = bitcoinjs.payments.p2pk({ pubkey });
const p2sh = bitcoinjs.payments.p2sh({ redeem: p2pk });
if (!p2sh.output || !p2pk.output) {
throw new Error(`invalid state`);
}
return {
scriptPubKey: p2sh.output,
redeemScript: p2pk.output,
};
}
exports.createOutputScriptP2shP2pk = createOutputScriptP2shP2pk;
/**
* Return scripts for 2-of-3 multisig output
* @param pubkeys - the key triple for multisig
* @param scriptType
* @param network - if set, performs sanity check for scriptType support
* @returns {{redeemScript, witnessScript, scriptPubKey}}
*/
function createOutputScript2of3(pubkeys, scriptType, network) {
if (network) {
if (!isSupportedScriptType(network, scriptType)) {
throw new Error(`unsupported script type ${scriptType} for network`);
}
}
if (!types_1.isTriple(pubkeys)) {
throw new Error(`must provide pubkey triple`);
}
pubkeys.forEach((key) => {
if (key.length !== 33) {
throw new Error(`Unexpected key length ${key.length}. Must use compressed keys.`);
}
});
if (scriptType === 'p2tr') {
// p2tr addresses use a combination of 2 of 2 multisig scripts distinct from
// the 2 of 3 multisig used for other script types
return createTaprootScript2of3(pubkeys);
}
const script2of3 = bitcoinjs.payments.p2ms({ m: 2, pubkeys });
assert(script2of3.output);
let scriptPubKey;
let redeemScript;
let witnessScript;
switch (scriptType) {
case 'p2sh':
redeemScript = script2of3;
scriptPubKey = bitcoinjs.payments.p2sh({ redeem: script2of3 });
break;
case 'p2shP2wsh':
witnessScript = script2of3;
redeemScript = bitcoinjs.payments.p2wsh({ redeem: script2of3 });
scriptPubKey = bitcoinjs.payments.p2sh({ redeem: redeemScript });
break;
case 'p2wsh':
witnessScript = script2of3;
scriptPubKey = bitcoinjs.payments.p2wsh({ redeem: witnessScript });
break;
default:
throw new Error(`unknown multisig script type ${scriptType}`);
}
assert(scriptPubKey);
assert(scriptPubKey.output);
return {
scriptPubKey: scriptPubKey.output,
redeemScript: redeemScript === null || redeemScript === void 0 ? void 0 : redeemScript.output,
witnessScript: witnessScript === null || witnessScript === void 0 ? void 0 : witnessScript.output,
};
}
exports.createOutputScript2of3 = createOutputScript2of3;
function toXOnlyPublicKey(b) {
if (b.length === 33) {
return b.slice(1);
}
if (b.length === 32) {
return b;
}
throw new Error(`invalid key size ${b.length}`);
}
exports.toXOnlyPublicKey = toXOnlyPublicKey;
function getTaptreeKeyCombinations(keys) {
const [userKey, backupKey, bitGoKey] = keys.map((k) => toXOnlyPublicKey(k));
return [
[userKey, bitGoKey],
[userKey, backupKey],
[backupKey, bitGoKey],
];
}
function createPaymentP2tr(pubkeys, redeemIndex) {
const keyCombinations2of2 = getTaptreeKeyCombinations(pubkeys);
const redeems = keyCombinations2of2.map((pubkeys, index) => bitcoinjs.payments.p2tr_ns({
pubkeys,
depth: index === 0 ? 1 : 2,
}, { eccLib: noble_ecc_1.ecc }));
return bitcoinjs.payments.p2tr({
pubkeys: keyCombinations2of2[0],
redeems,
redeemIndex,
}, { eccLib: noble_ecc_1.ecc });
}
exports.createPaymentP2tr = createPaymentP2tr;
function createSpendScriptP2tr(pubkeys, keyCombination) {
const keyCombinations = getTaptreeKeyCombinations(pubkeys);
const [a, b] = keyCombination.map((k) => toXOnlyPublicKey(k));
const redeemIndex = keyCombinations.findIndex(([c, d]) => (a.equals(c) && b.equals(d)) || (a.equals(d) && b.equals(c)));
if (redeemIndex < 0) {
throw new Error(`could not find redeemIndex for key combination`);
}
const payment = createPaymentP2tr(pubkeys, redeemIndex);
const { controlBlock } = payment;
assert(Buffer.isBuffer(controlBlock));
assert(payment.redeem);
const leafScript = payment.redeem.output;
assert(Buffer.isBuffer(leafScript));
const parsedControlBlock = __1.taproot.parseControlBlock(noble_ecc_1.ecc, controlBlock);
const { leafVersion } = parsedControlBlock;
const leafHash = __1.taproot.getTapleafHash(noble_ecc_1.ecc, parsedControlBlock, leafScript);
return {
controlBlock,
witnessScript: leafScript,
leafVersion,
leafHash,
};
}
exports.createSpendScriptP2tr = createSpendScriptP2tr;
/**
* Creates and returns a taproot output script using the user and bitgo keys for the aggregate
* public key and a taptree containing a user+bitgo 2-of-2 script at the first depth level of the
* tree and user+backup and bitgo+backup 2-of-2 scripts one level deeper.
* @param pubkeys - a pubkey array containing the user key, backup key, and bitgo key in that order
* @returns {{scriptPubKey}}
*/
function createTaprootScript2of3(pubkeys) {
const { output } = createPaymentP2tr(pubkeys);
assert(Buffer.isBuffer(output));
return {
scriptPubKey: output,
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0cHV0U2NyaXB0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iaXRnby9vdXRwdXRTY3JpcHRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUFpQztBQUNqQywyQ0FBMkM7QUFFM0MsMEJBQXVFO0FBRXZFLG1DQUFrRDtBQUVsRCw0Q0FBNkM7QUFFN0MsMENBQXFEO0FBQTVDLDRHQUFBLGtCQUFrQixPQUFBO0FBRWQsUUFBQSxrQkFBa0IsR0FBRyxVQUFVLENBQUM7QUFHaEMsUUFBQSxlQUFlLEdBQUcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQVUsQ0FBQztBQUcvRSxTQUFnQixnQkFBZ0IsQ0FBQyxDQUFTO0lBQ3hDLE9BQU8sdUJBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBbUIsQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFGRCw0Q0FFQztBQUlEOzs7O0dBSUc7QUFDSCxTQUFnQixxQkFBcUIsQ0FBQyxPQUFnQixFQUFFLFVBQXNCO0lBQzVFLFFBQVEsVUFBVSxFQUFFO1FBQ2xCLEtBQUssTUFBTSxDQUFDO1FBQ1osS0FBSyxVQUFVO1lBQ2IsT0FBTyxJQUFJLENBQUM7UUFDZCxLQUFLLFdBQVcsQ0FBQztRQUNqQixLQUFLLE9BQU87WUFDVixPQUFPLGtCQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakMsS0FBSyxNQUFNO1lBQ1QsT0FBTyxtQkFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0tBQ25DO0lBRUQsMEJBQTBCO0lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLFVBQVUsRUFBRSxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQWRELHNEQWNDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZ0IsMkJBQTJCLENBQUMsQ0FBaUI7SUFDM0QsUUFBUSxDQUFDLEVBQUU7UUFDVCxLQUFLLE1BQU07WUFDVCxPQUFPLFdBQVcsQ0FBQztRQUNyQixLQUFLLFdBQVc7WUFDZCxP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QUFDLENBQUMsQ0FBQztJQUNoQyxPQUFPO1FBQ0wsWUFBWSxFQUFFLE1BQU07S0FDckIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCAqIGFzIGJpdGNvaW5qcyBmcm9tICdiaXRjb2luanMtbGliJztcblxuaW1wb3J0IHsgTmV0d29yaywgc3VwcG9ydHNTZWd3aXQsIHN1cHBvcnRzVGFwcm9vdCwgdGFwcm9vdCB9IGZyb20gJy4uJztcblxuaW1wb3J0IHsgaXNUcmlwbGUsIFRyaXBsZSwgVHVwbGUgfSBmcm9tICcuL3R5cGVzJztcblxuaW1wb3J0IHsgZWNjIGFzIGVjY0xpYiB9IGZyb20gJy4uL25vYmxlX2VjYyc7XG5cbmV4cG9ydCB7IHNjcmlwdFR5cGVGb3JDaGFpbiB9IGZyb20gJy4vd2FsbGV0L2NoYWlucyc7XG5cbmV4cG9ydCBjb25zdCBzY3JpcHRUeXBlUDJzaFAycGsgPSAncDJzaFAycGsnO1xuZXhwb3J0IHR5cGUgU2NyaXB0VHlwZVAyc2hQMnBrID0gdHlwZW9mIHNjcmlwdFR5cGVQMnNoUDJwaztcblxuZXhwb3J0IGNvbnN0IHNjcmlwdFR5cGVzMk9mMyA9IFsncDJzaCcsICdwMnNoUDJ3c2gnLCAncDJ3c2gnLCAncDJ0ciddIGFzIGNvbnN0O1xuZXhwb3J0IHR5cGUgU2NyaXB0VHlwZTJPZjMgPSB0eXBlb2Ygc2NyaXB0VHlwZXMyT2YzW251bWJlcl07XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1NjcmlwdFR5cGUyT2YzKHQ6IHN0cmluZyk6IHQgaXMgU2NyaXB0VHlwZTJPZjMge1xuICByZXR1cm4gc2NyaXB0VHlwZXMyT2YzLmluY2x1ZGVzKHQgYXMgU2NyaXB0VHlwZTJPZjMpO1xufVxuXG5leHBvcnQgdHlwZSBTY3JpcHRUeXBlID0gU2NyaXB0VHlwZVAyc2hQMnBrIHwgU2NyaXB0VHlwZTJPZjM7XG5cbi8qKlxuICogQHBhcmFtIG5ldHdvcmtcbiAqIEBwYXJhbSBzY3JpcHRUeXBlXG4gKiBAcmV0dXJuIHRydWUgaWZmIHNjcmlwdCB0eXBlIGlzIHN1cHBvcnRlZCBmb3IgbmV0d29ya1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTdXBwb3J0ZWRTY3JpcHRUeXBlKG5ldHdvcms6IE5ldHdvcmssIHNjcmlwdFR5cGU6IFNjcmlwdFR5cGUpOiBib29sZWFuIHtcbiAgc3dpdGNoIChzY3JpcHRUeXBlKSB7XG4gICAgY2FzZSAncDJzaCc6XG4gICAgY2FzZSAncDJzaFAycGsnOlxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgY2FzZSAncDJzaFAyd3NoJzpcbiAgICBjYXNlICdwMndzaCc6XG4gICAgICByZXR1cm4gc3VwcG9ydHNTZWd3aXQobmV0d29yayk7XG4gICAgY2FzZSAncDJ0cic6XG4gICAgICByZXR1cm4gc3VwcG9ydHNUYXByb290KG5ldHdvcmspO1xuICB9XG5cbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgdGhyb3cgbmV3IEVycm9yKGB1bmV4cGVjdGVkIHNjcmlwdCB0eXBlICR7c2NyaXB0VHlwZX1gKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gdFxuICogQHJldHVybiBzdHJpbmcgcHJldk91dCBhcyBkZWZpbmVkIGluIFBSRVZPVVRfVFlQRVMgKGJpdGNvaW5qcy1saWIvLi4uL3RyYW5zYWN0aW9uX2J1aWxkZXIuanMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzY3JpcHRUeXBlMk9mM0FzUHJldk91dFR5cGUodDogU2NyaXB0VHlwZTJPZjMpOiBzdHJpbmcge1xuICBzd2l0Y2ggKHQpIHtcbiAgICBjYXNlICdwMnNoJzpcbiAgICAgIHJldHVybiAncDJzaC1wMm1zJztcbiAgICBjYXNlICdwMnNoUDJ3c2gnOlxuICAgICAgcmV0dXJuICdwMnNoLXAyd3NoLXAybXMnO1xuICAgIGNhc2UgJ3Ayd3NoJzpcbiAgICAgIHJldHVybiAncDJ3c2gtcDJtcyc7XG4gICAgY2FzZSAncDJ0cic6XG4gICAgICByZXR1cm4gJ3AydHItcDJucyc7XG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHNjcmlwdCB0eXBlICR7dH1gKTtcbn1cblxuZXhwb3J0IHR5cGUgU3BlbmRhYmxlU2NyaXB0ID0ge1xuICBzY3JpcHRQdWJLZXk6IEJ1ZmZlcjtcbiAgLyoqIEBkZXByZWNhdGVkIC0gdXNlIGNyZWF0ZVNwZW5kU2NyaXB0czJvZjMgKi9cbiAgcmVkZWVtU2NyaXB0PzogQnVmZmVyO1xuICAvKiogQGRlcHJlY2F0ZWQgLSB1c2UgY3JlYXRlU3BlbmRTY3JpcHQyb2YzICovXG4gIHdpdG5lc3NTY3JpcHQ/OiBCdWZmZXI7XG59O1xuXG5leHBvcnQgdHlwZSBTcGVuZFNjcmlwdFAydHIgPSB7XG4gIGNvbnRyb2xCbG9jazogQnVmZmVyO1xuICB3aXRuZXNzU2NyaXB0OiBCdWZmZXI7XG4gIGxlYWZWZXJzaW9uOiBudW1iZXI7XG4gIGxlYWZIYXNoOiBCdWZmZXI7XG59O1xuXG4vKipcbiAqIFJldHVybiBzY3JpcHRzIGZvciBwMnNoLXAycGsgKHVzZWQgZm9yIEJDSC9CU1YgcmVwbGF5IHByb3RlY3Rpb24pXG4gKiBAcGFyYW0gcHVia2V5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPdXRwdXRTY3JpcHRQMnNoUDJwayhwdWJrZXk6IEJ1ZmZlcik6IFNwZW5kYWJsZVNjcmlwdCB7XG4gIGNvbnN0IHAycGsgPSBiaXRjb2luanMucGF5bWVudHMucDJwayh7IHB1YmtleSB9KTtcbiAgY29uc3QgcDJzaCA9IGJpdGNvaW5qcy5wYXltZW50cy5wMnNoKHsgcmVkZWVtOiBwMnBrIH0pO1xuICBpZiAoIXAyc2gub3V0cHV0IHx8ICFwMnBrLm91dHB1dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBzdGF0ZWApO1xuICB9XG4gIHJldHVybiB7XG4gICAgc2NyaXB0UHViS2V5OiBwMnNoLm91dHB1dCxcbiAgICByZWRlZW1TY3JpcHQ6IHAycGsub3V0cHV0LFxuICB9O1xufVxuXG4vKipcbiAqIFJldHVybiBzY3JpcHRzIGZvciAyLW9mLTMgbXVsdGlzaWcgb3V0cHV0XG4gKiBAcGFyYW0gcHVia2V5cyAtIHRoZSBrZXkgdHJpcGxlIGZvciBtdWx0aXNpZ1xuICogQHBhcmFtIHNjcmlwdFR5cGVcbiAqIEBwYXJhbSBuZXR3b3JrIC0gaWYgc2V0LCBwZXJmb3JtcyBzYW5pdHkgY2hlY2sgZm9yIHNjcmlwdFR5cGUgc3VwcG9ydFxuICogQHJldHVybnMge3tyZWRlZW1TY3JpcHQsIHdpdG5lc3NTY3JpcHQsIHNjcmlwdFB1YktleX19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPdXRwdXRTY3JpcHQyb2YzKFxuICBwdWJrZXlzOiBCdWZmZXJbXSxcbiAgc2NyaXB0VHlwZTogU2NyaXB0VHlwZTJPZjMsXG4gIG5ldHdvcms/OiBOZXR3b3JrXG4pOiBTcGVuZGFibGVTY3JpcHQge1xuICBpZiAobmV0d29yaykge1xuICAgIGlmICghaXNTdXBwb3J0ZWRTY3JpcHRUeXBlKG5ldHdvcmssIHNjcmlwdFR5cGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHNjcmlwdCB0eXBlICR7c2NyaXB0VHlwZX0gZm9yIG5ldHdvcmtgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIWlzVHJpcGxlKHB1YmtleXMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBtdXN0IHByb3ZpZGUgcHVia2V5IHRyaXBsZWApO1xuICB9XG5cbiAgcHVia2V5cy5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBpZiAoa2V5Lmxlbmd0aCAhPT0gMzMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBrZXkgbGVuZ3RoICR7a2V5Lmxlbmd0aH0uIE11c3QgdXNlIGNvbXByZXNzZWQga2V5cy5gKTtcbiAgICB9XG4gIH0pO1xuXG4gIGlmIChzY3JpcHRUeXBlID09PSAncDJ0cicpIHtcbiAgICAvLyBwMnRyIGFkZHJlc3NlcyB1c2UgYSBjb21iaW5hdGlvbiBvZiAyIG9mIDIgbXVsdGlzaWcgc2NyaXB0cyBkaXN0aW5jdCBmcm9tXG4gICAgLy8gdGhlIDIgb2YgMyBtdWx0aXNpZyB1c2VkIGZvciBvdGhlciBzY3JpcHQgdHlwZXNcbiAgICByZXR1cm4gY3JlYXRlVGFwcm9vdFNjcmlwdDJvZjMocHVia2V5cyk7XG4gIH1cblxuICBjb25zdCBzY3JpcHQyb2YzID0gYml0Y29pbmpzLnBheW1lbnRzLnAybXMoeyBtOiAyLCBwdWJrZXlzIH0pO1xuICBhc3NlcnQoc2NyaXB0Mm9mMy5vdXRwdXQpO1xuXG4gIGxldCBzY3JpcHRQdWJLZXk6IGJpdGNvaW5qcy5QYXltZW50O1xuICBsZXQgcmVkZWVtU2NyaXB0OiBiaXRjb2luanMuUGF5bWVudCB8IHVuZGVmaW5lZDtcbiAgbGV0IHdpdG5lc3NTY3JpcHQ6IGJpdGNvaW5qcy5QYXltZW50IHwgdW5kZWZpbmVkO1xuICBzd2l0Y2ggKHNjcmlwdFR5cGUpIHtcbiAgICBjYXNlICdwMnNoJzpcbiAgICAgIHJlZGVlbVNjcmlwdCA9IHNjcmlwdDJvZjM7XG4gICAgICBzY3JpcHRQdWJLZXkgPSBiaXRjb2luanMucGF5bWVudHMucDJzaCh7IHJlZGVlbTogc2NyaXB0Mm9mMyB9KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3Ayc2hQMndzaCc6XG4gICAgICB3aXRuZXNzU2NyaXB0ID0gc2NyaXB0Mm9mMztcbiAgICAgIHJlZGVlbVNjcmlwdCA9IGJpdGNvaW5qcy5wYXltZW50cy5wMndzaCh7IHJlZGVlbTogc2NyaXB0Mm9mMyB9KTtcbiAgICAgIHNjcmlwdFB1YktleSA9IGJpdGNvaW5qcy5wYXltZW50cy5wMnNoKHsgcmVkZWVtOiByZWRlZW1TY3JpcHQgfSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdwMndzaCc6XG4gICAgICB3aXRuZXNzU2NyaXB0ID0gc2NyaXB0Mm9mMztcbiAgICAgIHNjcmlwdFB1YktleSA9IGJpdGNvaW5qcy5wYXltZW50cy5wMndzaCh7IHJlZGVlbTogd2l0bmVzc1NjcmlwdCB9KTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gbXVsdGlzaWcgc2NyaXB0IHR5cGUgJHtzY3JpcHRUeXBlfWApO1xuICB9XG5cbiAgYXNzZXJ0KHNjcmlwdFB1YktleSk7XG4gIGFzc2VydChzY3JpcHRQdWJLZXkub3V0cHV0KTtcblxuICByZXR1cm4ge1xuICAgIHNjcmlwdFB1YktleTogc2NyaXB0UHViS2V5Lm91dHB1dCxcbiAgICByZWRlZW1TY3JpcHQ6IHJlZGVlbVNjcmlwdD8ub3V0cHV0LFxuICAgIHdpdG5lc3NTY3JpcHQ6IHdpdG5lc3NTY3JpcHQ/Lm91dHB1dCxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvWE9ubHlQdWJsaWNLZXkoYjogQnVmZmVyKTogQnVmZmVyIHtcbiAgaWYgKGIubGVuZ3RoID09PSAzMykge1xuICAgIHJldHVybiBiLnNsaWNlKDEpO1xuICB9XG4gIGlmIChiLmxlbmd0aCA9PT0gMzIpIHtcbiAgICByZXR1cm4gYjtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQga2V5IHNpemUgJHtiLmxlbmd0aH1gKTtcbn1cblxuZnVuY3Rpb24gZ2V0VGFwdHJlZUtleUNvbWJpbmF0aW9ucyhrZXlzOiBUcmlwbGU8QnVmZmVyPik6IFR1cGxlPEJ1ZmZlcj5bXSB7XG4gIGNvbnN0IFt1c2VyS2V5LCBiYWNrdXBLZXksIGJpdEdvS2V5XSA9IGtleXMubWFwKChrKSA9PiB0b1hPbmx5UHVibGljS2V5KGspKTtcbiAgcmV0dXJuIFtcbiAgICBbdXNlcktleSwgYml0R29LZXldLFxuICAgIFt1c2VyS2V5LCBiYWNrdXBLZXldLFxuICAgIFtiYWNrdXBLZXksIGJpdEdvS2V5XSxcbiAgXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVBheW1lbnRQMnRyKHB1YmtleXM6IFRyaXBsZTxCdWZmZXI+LCByZWRlZW1JbmRleD86IG51bWJlcik6IGJpdGNvaW5qcy5QYXltZW50IHtcbiAgY29uc3Qga2V5Q29tYmluYXRpb25zMm9mMiA9IGdldFRhcHRyZWVLZXlDb21iaW5hdGlvbnMocHVia2V5cyk7XG4gIGNvbnN0IHJlZGVlbXMgPSBrZXlDb21iaW5hdGlvbnMyb2YyLm1hcCgocHVia2V5cywgaW5kZXgpID0+XG4gICAgYml0Y29pbmpzLnBheW1lbnRzLnAydHJfbnMoXG4gICAgICB7XG4gICAgICAgIHB1YmtleXMsXG4gICAgICAgIGRlcHRoOiBpbmRleCA9PT0gMCA/IDEgOiAyLFxuICAgICAgfSxcbiAgICAgIHsgZWNjTGliIH1cbiAgICApXG4gICk7XG5cbiAgcmV0dXJuIGJpdGNvaW5qcy5wYXltZW50cy5wMnRyKFxuICAgIHtcbiAgICAgIHB1YmtleXM6IGtleUNvbWJpbmF0aW9uczJvZjJbMF0sXG4gICAgICByZWRlZW1zLFxuICAgICAgcmVkZWVtSW5kZXgsXG4gICAgfSxcbiAgICB7IGVjY0xpYiB9XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTcGVuZFNjcmlwdFAydHIocHVia2V5czogVHJpcGxlPEJ1ZmZlcj4sIGtleUNvbWJpbmF0aW9uOiBUdXBsZTxCdWZmZXI+KTogU3BlbmRTY3JpcHRQMnRyIHtcbiAgY29uc3Qga2V5Q29tYmluYXRpb25zID0gZ2V0VGFwdHJlZUtleUNvbWJpbmF0aW9ucyhwdWJrZXlzKTtcbiAgY29uc3QgW2EsIGJdID0ga2V5Q29tYmluYXRpb24ubWFwKChrKSA9PiB0b1hPbmx5UHVibGljS2V5KGspKTtcbiAgY29uc3QgcmVkZWVtSW5kZXggPSBrZXlDb21iaW5hdGlvbnMuZmluZEluZGV4KFxuICAgIChbYywgZF0pID0+IChhLmVxdWFscyhjKSAmJiBiLmVxdWFscyhkKSkgfHwgKGEuZXF1YWxzKGQpICYmIGIuZXF1YWxzKGMpKVxuICApO1xuXG4gIGlmIChyZWRlZW1JbmRleCA8IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGNvdWxkIG5vdCBmaW5kIHJlZGVlbUluZGV4IGZvciBrZXkgY29tYmluYXRpb25gKTtcbiAgfVxuXG4gIGNvbnN0IHBheW1lbnQgPSBjcmVhdGVQYXltZW50UDJ0cihwdWJrZXlzLCByZWRlZW1JbmRleCk7XG4gIGNvbnN0IHsgY29udHJvbEJsb2NrIH0gPSBwYXltZW50O1xuICBhc3NlcnQoQnVmZmVyLmlzQnVmZmVyKGNvbnRyb2xCbG9jaykpO1xuXG4gIGFzc2VydChwYXltZW50LnJlZGVlbSk7XG4gIGNvbnN0IGxlYWZTY3JpcHQgPSBwYXltZW50LnJlZGVlbS5vdXRwdXQ7XG4gIGFzc2VydChCdWZmZXIuaXNCdWZmZXIobGVhZlNjcmlwdCkpO1xuXG4gIGNvbnN0IHBhcnNlZENvbnRyb2xCbG9jayA9IHRhcHJvb3QucGFyc2VDb250cm9sQmxvY2soZWNjTGliLCBjb250cm9sQmxvY2spO1xuICBjb25zdCB7IGxlYWZWZXJzaW9uIH0gPSBwYXJzZWRDb250cm9sQmxvY2s7XG4gIGNvbnN0IGxlYWZIYXNoID0gdGFwcm9vdC5nZXRUYXBsZWFmSGFzaChlY2NMaWIsIHBhcnNlZENvbnRyb2xCbG9jaywgbGVhZlNjcmlwdCk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb250cm9sQmxvY2ssXG4gICAgd2l0bmVzc1NjcmlwdDogbGVhZlNjcmlwdCxcbiAgICBsZWFmVmVyc2lvbixcbiAgICBsZWFmSGFzaCxcbiAgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgdGFwcm9vdCBvdXRwdXQgc2NyaXB0IHVzaW5nIHRoZSB1c2VyIGFuZCBiaXRnbyBrZXlzIGZvciB0aGUgYWdncmVnYXRlXG4gKiBwdWJsaWMga2V5IGFuZCBhIHRhcHRyZWUgY29udGFpbmluZyBhIHVzZXIrYml0Z28gMi1vZi0yIHNjcmlwdCBhdCB0aGUgZmlyc3QgZGVwdGggbGV2ZWwgb2YgdGhlXG4gKiB0cmVlIGFuZCB1c2VyK2JhY2t1cCBhbmQgYml0Z28rYmFja3VwIDItb2YtMiBzY3JpcHRzIG9uZSBsZXZlbCBkZWVwZXIuXG4gKiBAcGFyYW0gcHVia2V5cyAtIGEgcHVia2V5IGFycmF5IGNvbnRhaW5pbmcgdGhlIHVzZXIga2V5LCBiYWNrdXAga2V5LCBhbmQgYml0Z28ga2V5IGluIHRoYXQgb3JkZXJcbiAqIEByZXR1cm5zIHt7c2NyaXB0UHViS2V5fX1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlVGFwcm9vdFNjcmlwdDJvZjMocHVia2V5czogVHJpcGxlPEJ1ZmZlcj4pOiBTcGVuZGFibGVTY3JpcHQge1xuICBjb25zdCB7IG91dHB1dCB9ID0gY3JlYXRlUGF5bWVudFAydHIocHVia2V5cyk7XG4gIGFzc2VydChCdWZmZXIuaXNCdWZmZXIob3V0cHV0KSk7XG4gIHJldHVybiB7XG4gICAgc2NyaXB0UHViS2V5OiBvdXRwdXQsXG4gIH07XG59XG4iXX0=