UNPKG

@bitgo/unspents

Version:

Defines the chain codes used for different unspent types and methods to calculate bitcoin transaction sizes

233 lines 35.3 kB
"use strict"; /* eslint-disable @typescript-eslint/ban-ts-comment */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.runSignedTransactions = exports.runCombinations = exports.Histogram = exports.TxCombo = exports.createScriptPubKey = void 0; const utxolib = __importStar(require("@bitgo/utxo-lib")); const utxo_lib_1 = require("@bitgo/utxo-lib"); const lodash_1 = __importDefault(require("lodash")); require("lodash.combinations"); const src_1 = require("../../src"); const testutils_1 = require("../testutils"); function createUnspent(pubkeys, inputType, value) { let spendableScript; const scriptType = inputType === 'taprootKeyPathSpend' ? 'p2trMusig2' : inputType; if (scriptType === testutils_1.UnspentTypeP2shP2pk) { spendableScript = utxolib.bitgo.outputScripts.createOutputScriptP2shP2pk(pubkeys[0]); } else if (utxolib.bitgo.outputScripts.isScriptType2Of3(scriptType)) { spendableScript = utxolib.bitgo.outputScripts.createOutputScript2of3(pubkeys, scriptType); } else { throw new Error(`unexpected inputType ${scriptType}`); } return { ...spendableScript, value, inputType: scriptType, }; } /** * * @param keys - Pubkeys to use for generating the address. * If unspentType is one of UnspentTypePubKeyHash is used, the first key will be used. * @param unspentType {String} - one of UnspentTypeScript2of3 or UnspentTypePubKeyHash * @return {String} address */ const createScriptPubKey = (keys, unspentType) => { const pubkeys = keys.map((key) => key.publicKey); if (typeof unspentType === 'string' && unspentType in testutils_1.UnspentTypeScript2of3) { return createUnspent(pubkeys, unspentType, 0).scriptPubKey; } const pkHash = utxolib.crypto.hash160(pubkeys[0]); switch (unspentType) { case testutils_1.UnspentTypePubKeyHash.p2pkh: return utxolib.payments.p2pkh({ hash: pkHash }).output; case testutils_1.UnspentTypePubKeyHash.p2wpkh: return utxolib.payments.p2wpkh({ hash: pkHash }).output; } if (unspentType instanceof testutils_1.UnspentTypeOpReturn) { const payload = Buffer.alloc(unspentType.size).fill(pubkeys[0]); return utxolib.script.compile([0x6a, payload]); } throw new Error(`unsupported output type ${unspentType}`); }; exports.createScriptPubKey = createScriptPubKey; const createInputTx = (unspents, inputValue) => { const txInputBuilder = new utxolib.bitgo.UtxoTransactionBuilder(utxolib.networks.bitcoin); txInputBuilder.addInput(Array(32).fill('01').join(''), 0); unspents.forEach(({ scriptPubKey }) => txInputBuilder.addOutput(scriptPubKey, inputValue)); return txInputBuilder.buildIncomplete(); }; function signInput(txBuilder, index, walletKeys, unspent, signKeys = unspent.inputType === 'p2shP2pk' ? [walletKeys[0]] : [walletKeys[0], walletKeys[2]]) { signKeys.forEach((keyPair) => { if (unspent.inputType === 'p2shP2pk') { utxolib.bitgo.signInputP2shP2pk(txBuilder, index, keyPair); } else { if (signKeys.length !== 2) { throw new Error(`invalid signKeys length`); } const cosigner = keyPair === signKeys[0] ? signKeys[1] : signKeys[0]; utxolib.bitgo.signInput2Of3(txBuilder, index, unspent.inputType, walletKeys.map((k) => k.publicKey), keyPair, cosigner.publicKey, unspent.value); } }); } class TxCombo { constructor(walletKeys, inputTypes, outputTypes, expectedDims = src_1.Dimensions.ZERO, signKeys, inputValue = 10) { this.walletKeys = walletKeys; this.inputTypes = inputTypes; this.outputTypes = outputTypes; this.expectedDims = expectedDims; this.signKeys = signKeys; this.inputValue = inputValue; this.unspents = inputTypes.map((inputType) => createUnspent(walletKeys.map((key) => key.publicKey), inputType, this.inputValue)); this.inputTx = createInputTx(this.unspents, inputValue); } getBuilderWithUnsignedTx() { const txBuilder = utxolib.bitgo.createTransactionBuilderForNetwork(utxolib.networks.bitcoin); this.inputTx.outs.forEach(({}, i) => txBuilder.addInput(this.inputTx, i)); this.outputTypes.forEach((unspentType) => txBuilder.addOutput((0, exports.createScriptPubKey)(this.walletKeys, unspentType), this.inputValue)); return txBuilder; } getUnsignedTx() { return this.getBuilderWithUnsignedTx().buildIncomplete(); } getSignedTx() { const txBuilder = this.getBuilderWithUnsignedTx(); this.unspents.forEach((unspent, i) => { signInput(txBuilder, i, this.walletKeys, unspent, this.signKeys); }); return txBuilder.build(); } } exports.TxCombo = TxCombo; const runCombinations = ({ inputTypes, maxNInputs, outputTypes, maxNOutputs, }, callback) => { // Create combinations of different input and output types. Length between 1 and 3. const inputCombinations = lodash_1.default.flatten( // @ts-ignore [...Array(maxNInputs)].map((__, i) => lodash_1.default.combinations(inputTypes, i + 1))); const outputCombinations = lodash_1.default.flatten( // @ts-ignore [...Array(maxNOutputs)].map((__, i) => lodash_1.default.combinations(outputTypes, i + 1))); inputCombinations.forEach((inputTypeCombo) => outputCombinations.forEach((outputTypeCombo) => { callback(inputTypeCombo, outputTypeCombo); })); }; exports.runCombinations = runCombinations; class Histogram { constructor(map = new Map()) { this.map = map; this.total = 0; } add(size) { this.map.set(size, (this.map.get(size) || 0) + 1); this.total++; } asSortedArray() { return [...this.map.entries()].sort(([a], [b]) => a - b); } asFullSortedArray() { return lodash_1.default.range(this.getPercentile(0), this.getPercentile(1)).map((v) => [v, this.map.get(v) || 0]); } getPercentile(p) { if (0 > p || p > 1) { throw new Error(`p must be between 0 and 1`); } let sum = 0; for (const [k, v] of this.asSortedArray()) { sum += v; if (sum / this.total >= p) { return k; } } throw new Error('could not find percentile'); } toString() { const keys = [...this.map.keys()].sort((a, b) => a - b); return `[${keys.map((k) => `[${k}, ${this.map.get(k)}]`).join(' ')}]`; } } exports.Histogram = Histogram; const getKeyTriplets = (prefix, count) => [...Array(count)].map((v, i) => [1, 2, 3].map((j) => utxo_lib_1.bip32.fromSeed(Buffer.alloc(16, `${prefix}/${i}/${j}`), utxolib.networks.bitcoin))); /** * * Calls `callback` with a variety of signed txs, based on input parameters * Callback arguments are * inputType, inputCount, outputType, txs * where `txs` implements `forEach()` * * @param inputTypes - input types to test * @param nInputKeyTriplets - number of different input key triples to cycle through * @param outputTypes - output types to test * @param nOutputKeyTriplets - number of different output key triplets to cycle through * @param callback */ const runSignedTransactions = ({ inputTypes, nInputKeyTriplets, outputTypes, nOutputKeyTriplets, }, callback) => { const inputKeyTriplets = getKeyTriplets('test/input/', nInputKeyTriplets); const outputKeyTriplets = getKeyTriplets('test/output/', nOutputKeyTriplets); const outputValue = 1e8; inputTypes.forEach(({ inputType, count: inputCount }) => { const inputTxs = inputKeyTriplets.map((inputKeys) => { const unspents = [...Array(inputCount)].map(() => createUnspent(inputKeys.map((key) => key.publicKey), inputType, outputValue)); const inputTx = createInputTx(unspents, outputValue); return { inputKeys, unspents, inputTx }; }); outputTypes.forEach((outputType) => { const outputs = outputKeyTriplets.map((outputKeys) => (0, exports.createScriptPubKey)(outputKeys, outputType)); const txs = { forEach(cb) { inputTxs.forEach(({ inputKeys, unspents, inputTx }) => { outputs.forEach((scriptPubKey) => { const txBuilder = utxolib.bitgo.createTransactionBuilderForNetwork(utxolib.networks.bitcoin); inputTx.outs.forEach((v, i) => txBuilder.addInput(inputTx, i)); txBuilder.addOutput(scriptPubKey, outputValue); unspents.forEach((unspent, i) => { signInput(txBuilder, i, inputKeys, unspent); }); cb(txBuilder.build()); }); }); }, }; callback(inputType, inputCount, outputType, txs); }); }); }; exports.runSignedTransactions = runSignedTransactions; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhHZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3NpZ25lZFR4L3R4R2VuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxzREFBc0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV0RCx5REFBMkM7QUFDM0MsOENBQXdEO0FBQ3hELG9EQUF1QjtBQUN2QiwrQkFBNkI7QUFDN0IsbUNBQXVDO0FBQ3ZDLDRDQU9zQjtBQVV0QixTQUFTLGFBQWEsQ0FBQyxPQUFpQixFQUFFLFNBQWlCLEVBQUUsS0FBYTtJQUN4RSxJQUFJLGVBQWUsQ0FBQztJQUNwQixNQUFNLFVBQVUsR0FBRyxTQUFTLEtBQUsscUJBQXFCLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ2xGLElBQUksVUFBVSxLQUFLLCtCQUFtQixFQUFFLENBQUM7UUFDdkMsZUFBZSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7U0FBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDcEUsZUFBZSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUM1RixDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELE9BQU87UUFDTCxHQUFHLGVBQWU7UUFDbEIsS0FBSztRQUNMLFNBQVMsRUFBRSxVQUFVO0tBQ3RCLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0ksTUFBTSxrQkFBa0IsR0FBRyxDQUFDLElBQXNCLEVB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LENBQUMsS0FBSyxDQUFDLGtDQUFrQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7NEJBQzdGLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBTSxFQUFFLENBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDNUUsU0FBUyxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsV0FBVyxDQUFDLENBQUM7NEJBQy9DLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0NBQzlCLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQzs0QkFDOUMsQ0FBQyxDQUFDLENBQUM7NEJBRUgsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO3dCQUN4QixDQUFDLENBQUMsQ0FBQztvQkFDTCxDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDO2FBQ0YsQ0FBQztZQUVGLFFBQVEsQ0FBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBRTRDLHNEQUFxQiIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudCAqL1xuXG5pbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby91dHhvLWxpYic7XG5pbXBvcnQgeyBiaXAzMiwgQklQMzJJbnRlcmZhY2UgfSBmcm9tICdAYml0Z28vdXR4by1saWInO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCAnbG9kYXNoLmNvbWJpbmF0aW9ucyc7XG5pbXBvcnQgeyBEaW1lbnNpb25zIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7XG4gIElucHV0U2NyaXB0VHlwZSxcbiAgVGVzdFVuc3BlbnRUeXBlLFxuICBVbnNwZW50VHlwZU9wUmV0dXJuLFxuICBVbnNwZW50VHlwZVAyc2hQMnBrLFxuICBVbnNwZW50VHlwZVB1YktleUhhc2gsXG4gIFVuc3BlbnRUeXBlU2NyaXB0Mm9mMyxcbn0gZnJvbSAnLi4vdGVzdHV0aWxzJztcblxuaW50ZXJmYWNlIElVbnNwZW50IHtcbiAgc2NyaXB0UHViS2V5OiBCdWZmZXI7XG4gIHJlZGVlbVNjcmlwdD86IEJ1ZmZlcjtcbiAgd2l0bmVzc1NjcmlwdD86IEJ1ZmZlcjtcbiAgdmFsdWU6IG51bWJlcjtcbiAgaW5wdXRUeXBlOiB1dHhvbGliLmJpdGdvLm91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlVW5zcGVudChwdWJrZXlzOiBCdWZmZXJbXSwgaW5wdXRUeXBlOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIpOiBJVW5zcGVudCB7XG4gIGxldCBzcGVuZGFibGVTY3JpcHQ7XG4gIGNvbnN0IHNjcmlwdFR5cGUgPSBpbnB1dFR5cGUgPT09ICd0YXByb290S2V5UGF0aFNwZW5kJyA/ICdwMnRyTXVzaWcyJyA6IGlucHV0VHlwZTtcbiAgaWYgKHNjcmlwdFR5cGUgPT09IFVuc3BlbnRUeXBlUDJzaFAycGspIHtcbiAgICBzcGVuZGFibGVTY3JpcHQgPSB1dHhvbGliLmJpdGdvLm91dHB1dFNjcmlwdHMuY3JlYXRlT3V0cHV0U2NyaXB0UDJzaFAycGsocHVia2V5c1swXSk7XG4gIH0gZWxzZSBpZiAodXR4b2xpYi5iaXRnby5vdXRwdXRTY3JpcHRzLmlzU2NyaXB0VHlwZTJPZjMoc2NyaXB0VHlwZSkpIHtcbiAgICBzcGVuZGFibGVTY3JpcHQgPSB1dHhvbGliLmJpdGdvLm91dHB1dFNjcmlwdHMuY3JlYXRlT3V0cHV0U2NyaXB0Mm9mMyhwdWJrZXlzLCBzY3JpcHRUeXBlKTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHVuZXhwZWN0ZWQgaW5wdXRUeXBlICR7c2NyaXB0VHlwZX1gKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uc3BlbmRhYmxlU2NyaXB0LFxuICAgIHZhbHVlLFxuICAgIGlucHV0VHlwZTogc2NyaXB0VHlwZSxcbiAgfTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGtleXMgLSBQdWJrZXlzIHRvIHVzZSBmb3IgZ2VuZXJhdGluZyB0aGUgYWRkcmVzcy5cbiAqICAgICAgICAgICAgICAgSWYgdW5zcGVudFR5cGUgaXMgb25lIG9mIFVuc3BlbnRUeXBlUHViS2V5SGFzaCBpcyB1c2VkLCB0aGUgZmlyc3Qga2V5IHdpbGwgYmUgdXNlZC5cbiAqIEBwYXJhbSB1bnNwZW50VHlwZSB7U3RyaW5nfSAtIG9uZSBvZiBVbnNwZW50VHlwZVNjcmlwdDJvZjMgb3IgVW5zcGVudFR5cGVQdWJLZXlIYXNoXG4gKiBAcmV0dXJuIHtTdHJpbmd9IGFkZHJlc3NcbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVNjcmlwdFB1YktleSA9IChrZXlzOiBCSVAzMkludGVyZmFjZVtdLCB1bnNwZW50VHlwZTogVGVzdFVuc3BlbnRUeXBlKTogQnVmZmVyID0+IHtcbiAgY29uc3QgcHVia2V5cyA9IGtleXMubWFwKChrZXkpID0+IGtleS5wdWJsaWNLZXkpO1xuICBpZiAodHlwZW9mIHVuc3BlbnRUeXBlID09PSAnc3RyaW5nJyAmJiB1bnNwZW50VHlwZSBpbiBVbnNwZW50VHlwZVNjcmlwdDJvZjMpIHtcbiAgICByZXR1cm4gY3JlYXRlVW5zcGVudChwdWJrZXlzLCB1bnNwZW50VHlwZSwgMCkuc2NyaXB0UHViS2V5O1xuICB9XG5cbiAgY29uc3QgcGtIYXNoID0gdXR4b2xpYi5jcnlwdG8uaGFzaDE2MChwdWJrZXlzWzBdKTtcbiAgc3dpdGNoICh1bnNwZW50VHlwZSkge1xuICAgIGNhc2UgVW5zcGVudFR5cGVQdWJLZXlIYXNoLnAycGtoOlxuICAgICAgcmV0dXJuIHV0eG9saWIucGF5bWVudHMucDJwa2goeyBoYXNoOiBwa0hhc2ggfSkub3V0cHV0ITtcbiAgICBjYXNlIFVuc3BlbnRUeXBlUHViS2V5SGFzaC5wMndwa2g6XG4gICAgICByZXR1cm4gdXR4b2xpYi5wYXltZW50cy5wMndwa2goeyBoYXNoOiBwa0hhc2ggfSkub3V0cHV0ITtcbiAgfVxuXG4gIGlmICh1bnNwZW50VHlwZSBpbnN0YW5jZW9mIFVuc3BlbnRUeXBlT3BSZXR1cm4pIHtcbiAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmFsbG9jKHVuc3BlbnRUeXBlLnNpemUpLmZpbGwocHVia2V5c1swXSk7XG4gICAgcmV0dXJuIHV0eG9saWIuc2NyaXB0LmNvbXBpbGUoWzB4NmEsIHBheWxvYWRdKTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgb3V0cHV0IHR5cGUgJHt1bnNwZW50VHlwZX1gKTtcbn07XG5cbmNvbnN0IGNyZWF0ZUlucHV0VHggPSAodW5zcGVudHM6IGFueVtdLCBpbnB1dFZhbHVlOiBudW1iZXIpID0+IHtcbiAgY29uc3QgdHhJbnB1dEJ1aWxkZXIgPSBuZXcgdXR4b2xpYi5iaXRnby5VdHhvVHJhbnNhY3Rpb25CdWlsZGVyKHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gIHR4SW5wdXRCdWlsZGVyLmFkZElucHV0KEFycmF5KDMyKS5maWxsKCcwMScpLmpvaW4oJycpLCAwKTtcbiAgdW5zcGVudHMuZm9yRWFjaCgoeyBzY3JpcHRQdWJLZXkgfSkgPT4gdHhJbnB1dEJ1aWxkZXIuYWRkT3V0cHV0KHNjcmlwdFB1YktleSwgaW5wdXRWYWx1ZSkpO1xuICByZXR1cm4gdHhJbnB1dEJ1aWxkZXIuYnVpbGRJbmNvbXBsZXRlKCk7XG59O1xuXG5mdW5jdGlvbiBzaWduSW5wdXQoXG4gIHR4QnVpbGRlcjogdXR4b2xpYi5iaXRnby5VdHhvVHJhbnNhY3Rpb25CdWlsZGVyLFxuICBpbmRleDogbnVtYmVyLFxuICB3YWxsZXRLZXlzOiBCSVAzMkludGVyZmFjZVtdLFxuICB1bnNwZW50OiBJVW5zcGVudCxcbiAgc2lnbktleXM6IEJJUDMySW50ZXJmYWNlW10gPSB1bnNwZW50LmlucHV0VHlwZSA9PT0gJ3Ayc2hQMnBrJyA/IFt3YWxsZXRLZXlzWzBdXSA6IFt3YWxsZXRLZXlzWzBdLCB3YWxsZXRLZXlzWzJdXVxuKSB7XG4gIHNpZ25LZXlzLmZvckVhY2goKGtleVBhaXIpID0+IHtcbiAgICBpZiAodW5zcGVudC5pbnB1dFR5cGUgPT09ICdwMnNoUDJwaycpIHtcbiAgICAgIHV0eG9saWIuYml0Z28uc2lnbklucHV0UDJzaFAycGsodHhCdWlsZGVyLCBpbmRleCwga2V5UGFpcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzaWduS2V5cy5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIHNpZ25LZXlzIGxlbmd0aGApO1xuICAgICAgfVxuICAgICAgY29uc3QgY29zaWduZXIgPSBrZXlQYWlyID09PSBzaWduS2V5c1swXSA/IHNpZ25LZXlzWzFdIDogc2lnbktleXNbMF07XG4gICAgICB1dHhvbGliLmJpdGdvLnNpZ25JbnB1dDJPZjMoXG4gICAgICAgIHR4QnVpbGRlcixcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIHVuc3BlbnQuaW5wdXRUeXBlLFxuICAgICAgICB3YWxsZXRLZXlzLm1hcCgoaykgPT4gay5wdWJsaWNLZXkpIGFzIHV0eG9saWIuYml0Z28uVHJpcGxlPEJ1ZmZlcj4sXG4gICAgICAgIGtleVBhaXIsXG4gICAgICAgIGNvc2lnbmVyLnB1YmxpY0tleSxcbiAgICAgICAgdW5zcGVudC52YWx1ZVxuICAgICAgKTtcbiAgICB9XG4gIH0pO1xufVxuXG5jbGFzcyBUeENvbWJvIHtcbiAgcHVibGljIHVuc3BlbnRzOiBJVW5zcGVudFtdO1xuICBwdWJsaWMgaW5wdXRUeDogYW55O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyB3YWxsZXRLZXlzOiBCSVAzMkludGVyZmFjZVtdLFxuICAgIHB1YmxpYyBpbnB1dFR5cGVzOiBzdHJpbmdbXSxcbiAgICBwdWJsaWMgb3V0cHV0VHlwZXM6IFRlc3RVbnNwZW50VHlwZVtdLFxuICAgIHB1YmxpYyBleHBlY3RlZERpbXM6IFJlYWRvbmx5PERpbWVuc2lvbnM+ID0gRGltZW5zaW9ucy5aRVJPLFxuICAgIHB1YmxpYyBzaWduS2V5cz86IEJJUDMySW50ZXJmYWNlW10sXG4gICAgcHVibGljIGlucHV0VmFsdWU6IG51bWJlciA9IDEwXG4gICkge1xuICAgIHRoaXMudW5zcGVudHMgPSBpbnB1dFR5cGVzLm1hcCgoaW5wdXRUeXBlKSA9PlxuICAgICAgY3JlYXRlVW5zcGVudChcbiAgICAgICAgd2FsbGV0S2V5cy5tYXAoKGtleSkgPT4ga2V5LnB1YmxpY0tleSksXG4gICAgICAgIGlucHV0VHlwZSxcbiAgICAgICAgdGhpcy5pbnB1dFZhbHVlXG4gICAgICApXG4gICAgKTtcbiAgICB0aGlzLmlucHV0VHggPSBjcmVhdGVJbnB1dFR4KHRoaXMudW5zcGVudHMsIGlucHV0VmFsdWUpO1xuICB9XG5cbiAgcHVibGljIGdldEJ1aWxkZXJXaXRoVW5zaWduZWRUeCgpOiB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbkJ1aWxkZXIge1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRm9yTmV0d29yayh1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgIHRoaXMuaW5wdXRUeC5vdXRzLmZvckVhY2goKHt9LCBpOiBudW1iZXIpID0+IHR4QnVpbGRlci5hZGRJbnB1dCh0aGlzLmlucHV0VHgsIGkpKTtcbiAgICB0aGlzLm91dHB1dFR5cGVzLmZvckVhY2goKHVuc3BlbnRUeXBlKSA9PlxuICAgICAgdHhCdWlsZGVyLmFkZE91dHB1dChjcmVhdGVTY3JpcHRQdWJLZXkodGhpcy53YWxsZXRLZXlzLCB1bnNwZW50VHlwZSksIHRoaXMuaW5wdXRWYWx1ZSlcbiAgICApO1xuICAgIHJldHVybiB0eEJ1aWxkZXI7XG4gIH1cblxuICBwdWJsaWMgZ2V0VW5zaWduZWRUeCgpOiB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QnVpbGRlcldpdGhVbnNpZ25lZFR4KCkuYnVpbGRJbmNvbXBsZXRlKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0U2lnbmVkVHgoKTogdXR4b2xpYi5UcmFuc2FjdGlvbiB7XG4gICAgY29uc3QgdHhCdWlsZGVyID0gdGhpcy5nZXRCdWlsZGVyV2l0aFVuc2lnbmVkVHgoKTtcbiAgICB0aGlzLnVuc3BlbnRzLmZvckVhY2goKHVuc3BlbnQsIGkpID0+IHtcbiAgICAgIHNpZ25JbnB1dCh0eEJ1aWxkZXIsIGksIHRoaXMud2FsbGV0S2V5cywgdW5zcGVudCwgdGhpcy5zaWduS2V5cyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHR4QnVpbGRlci5idWlsZCgpO1xuICB9XG59XG5cbmNvbnN0IHJ1bkNvbWJpbmF0aW9ucyA9IChcbiAge1xuICAgIGlucHV0VHlwZXMsXG4gICAgbWF4TklucHV0cyxcbiAgICBvdXRwdXRUeXBlcyxcbiAgICBtYXhOT3V0cHV0cyxcbiAgfToge1xuICAgIGlucHV0VHlwZXM6IElucHV0U2NyaXB0VHlwZVtdO1xuICAgIG1heE5JbnB1dHM6IG51bWJlcjtcbiAgICBvdXRwdXRUeXBlczogVGVzdFVuc3BlbnRUeXBlW107XG4gICAgbWF4Tk91dHB1dHM6IG51bWJlcjtcbiAgfSxcbiAgY2FsbGJhY2s6IChpbnB1dENvbWJvOiBJbnB1dFNjcmlwdFR5cGVbXSwgb3V0cHV0Q29tYm86IFRlc3RVbnNwZW50VHlwZVtdKSA9PiB2b2lkXG4pOiB2b2lkID0+IHtcbiAgLy8gQ3JlYXRlIGNvbWJpbmF0aW9ucyBvZiBkaWZmZXJlbnQgaW5wdXQgYW5kIG91dHB1dCB0eXBlcy4gTGVuZ3RoIGJldHdlZW4gMSBhbmQgMy5cbiAgY29uc3QgaW5wdXRDb21iaW5hdGlvbnMgPSBfLmZsYXR0ZW4oXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIFsuLi5BcnJheShtYXhOSW5wdXRzKV0ubWFwKChfXywgaSkgPT4gXy5jb21iaW5hdGlvbnMoaW5wdXRUeXBlcywgaSArIDEpKVxuICApO1xuICBjb25zdCBvdXRwdXRDb21iaW5hdGlvbnMgPSBfLmZsYXR0ZW4oXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIFsuLi5BcnJheShtYXhOT3V0cHV0cyldLm1hcCgoX18sIGkpID0+IF8uY29tYmluYXRpb25zKG91dHB1dFR5cGVzLCBpICsgMSkpXG4gICk7XG5cbiAgaW5wdXRDb21iaW5hdGlvbnMuZm9yRWFjaCgoaW5wdXRUeXBlQ29tYm8pID0+XG4gICAgb3V0cHV0Q29tYmluYXRpb25zLmZvckVhY2goKG91dHB1dFR5cGVDb21ibykgPT4ge1xuICAgICAgY2FsbGJhY2soaW5wdXRUeXBlQ29tYm8sIG91dHB1dFR5cGVDb21ibyk7XG4gICAgfSlcbiAgKTtcbn07XG5cbmNsYXNzIEhpc3RvZ3JhbSB7XG4gIHB1YmxpYyB0b3RhbCA9IDA7XG5cbiAgY29uc3RydWN0b3IocHVibGljIG1hcDogTWFwPG51bWJlciwgbnVtYmVyPiA9IG5ldyBNYXAoKSkge31cblxuICBwdWJsaWMgYWRkKHNpemU6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMubWFwLnNldChzaXplLCAodGhpcy5tYXAuZ2V0KHNpemUpIHx8IDApICsgMSk7XG4gICAgdGhpcy50b3RhbCsrO1xuICB9XG5cbiAgcHVibGljIGFzU29ydGVkQXJyYXkoKTogbnVtYmVyW11bXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLm1hcC5lbnRyaWVzKCldLnNvcnQoKFthXSwgW2JdKSA9PiBhIC0gYik7XG4gIH1cblxuICBwdWJsaWMgYXNGdWxsU29ydGVkQXJyYXkoKTogbnVtYmVyW11bXSB7XG4gICAgcmV0dXJuIF8ucmFuZ2UodGhpcy5nZXRQZXJjZW50aWxlKDApLCB0aGlzLmdldFBlcmNlbnRpbGUoMSkpLm1hcCgodikgPT4gW3YsIHRoaXMubWFwLmdldCh2KSB8fCAwXSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGVyY2VudGlsZShwOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmICgwID4gcCB8fCBwID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBwIG11c3QgYmUgYmV0d2VlbiAwIGFuZCAxYCk7XG4gICAgfVxuXG4gICAgbGV0IHN1bSA9IDA7XG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgdGhpcy5hc1NvcnRlZEFycmF5KCkpIHtcbiAgICAgIHN1bSArPSB2O1xuICAgICAgaWYgKHN1bSAvIHRoaXMudG90YWwgPj0gcCkge1xuICAgICAgICByZXR1cm4gaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCBmaW5kIHBlcmNlbnRpbGUnKTtcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIGNvbnN0IGtleXMgPSBbLi4udGhpcy5tYXAua2V5cygpXS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gICAgcmV0dXJuIGBbJHtrZXlzLm1hcCgoaykgPT4gYFske2t9LCAke3RoaXMubWFwLmdldChrKX1dYCkuam9pbignICcpfV1gO1xuICB9XG59XG5cbmNvbnN0IGdldEtleVRyaXBsZXRzID0gKHByZWZpeDogc3RyaW5nLCBjb3VudDogbnVtYmVyKSA9PlxuICBbLi4uQXJyYXkoY291bnQpXS5tYXAoKHYsIGkpID0+XG4gICAgWzEsIDIsIDNdLm1hcCgoaikgPT4gYmlwMzIuZnJvbVNlZWQoQnVmZmVyLmFsbG9jKDE2LCBgJHtwcmVmaXh9LyR7aX0vJHtqfWApLCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pKVxuICApO1xuXG4vKipcbiAqXG4gKiBDYWxscyBgY2FsbGJhY2tgIHdpdGggYSB2YXJpZXR5IG9mIHNpZ25lZCB0eHMsIGJhc2VkIG9uIGlucHV0IHBhcmFtZXRlcnNcbiAqIENhbGxiYWNrIGFyZ3VtZW50cyBhcmVcbiAqICAgaW5wdXRUeXBlLCBpbnB1dENvdW50LCBvdXRwdXRUeXBlLCB0eHNcbiAqICB3aGVyZSBgdHhzYCBpbXBsZW1lbnRzIGBmb3JFYWNoKClgXG4gKlxuICogQHBhcmFtIGlucHV0VHlwZXMgLSBpbnB1dCB0eXBlcyB0byB0ZXN0XG4gKiBAcGFyYW0gbklucHV0S2V5VHJpcGxldHMgLSBudW1iZXIgb2YgZGlmZmVyZW50IGlucHV0IGtleSB0cmlwbGVzIHRvIGN5Y2xlIHRocm91Z2hcbiAqIEBwYXJhbSBvdXRwdXRUeXBlcyAtIG91dHB1dCB0eXBlcyB0byB0ZXN0XG4gKiBAcGFyYW0gbk91dHB1dEtleVRyaXBsZXRzIC0gbnVtYmVyIG9mIGRpZmZlcmVudCBvdXRwdXQga2V5IHRyaXBsZXRzIHRvIGN5Y2xlIHRocm91Z2hcbiAqIEBwYXJhbSBjYWxsYmFja1xuICovXG5jb25zdCBydW5TaWduZWRUcmFuc2FjdGlvbnMgPSAoXG4gIHtcbiAgICBpbnB1dFR5cGVzLFxuICAgIG5JbnB1dEtleVRyaXBsZXRzLFxuICAgIG91dHB1dFR5cGVzLFxuICAgIG5PdXRwdXRLZXlUcmlwbGV0cyxcbiAgfToge1xuICAgIGlucHV0VHlwZXM6IEFycmF5PHsgaW5wdXRUeXBlOiBzdHJpbmc7IGNvdW50OiBudW1iZXIgfT47XG4gICAgbklucHV0S2V5VHJpcGxldHM6IG51bWJlcjtcbiAgICBvdXRwdXRUeXBlczogVGVzdFVuc3BlbnRUeXBlW107XG4gICAgbk91dHB1dEtleVRyaXBsZXRzOiBudW1iZXI7XG4gIH0sXG4gIGNhbGxiYWNrOiAoaW5wdXRUeXBlOiBzdHJpbmcsIGlucHV0Q291bnQ6IG51bWJlciwgb3V0cHV0VHlwZTogVGVzdFVuc3BlbnRUeXBlLCB0eHM6IGFueSkgPT4gdm9pZFxuKTogdm9pZCA9PiB7XG4gIGNvbnN0IGlucHV0S2V5VHJpcGxldHMgPSBnZXRLZXlUcmlwbGV0cygndGVzdC9pbnB1dC8nLCBuSW5wdXRLZXlUcmlwbGV0cyk7XG4gIGNvbnN0IG91dHB1dEtleVRyaXBsZXRzID0gZ2V0S2V5VHJpcGxldHMoJ3Rlc3Qvb3V0cHV0LycsIG5PdXRwdXRLZXlUcmlwbGV0cyk7XG4gIGNvbnN0IG91dHB1dFZhbHVlID0gMWU4O1xuXG4gIGlucHV0VHlwZXMuZm9yRWFjaCgoeyBpbnB1dFR5cGUsIGNvdW50OiBpbnB1dENvdW50IH0pID0+IHtcbiAgICBjb25zdCBpbnB1dFR4cyA9IGlucHV0S2V5VHJpcGxldHMubWFwKChpbnB1dEtleXMpID0+IHtcbiAgICAgIGNvbnN0IHVuc3BlbnRzID0gWy4uLkFycmF5KGlucHV0Q291bnQpXS5tYXAoKCkgPT5cbiAgICAgICAgY3JlYXRlVW5zcGVudChcbiAgICAgICAgICBpbnB1dEtleXMubWFwKChrZXkpID0+IGtleS5wdWJsaWNLZXkpLFxuICAgICAgICAgIGlucHV0VHlwZSxcbiAgICAgICAgICBvdXRwdXRWYWx1ZVxuICAgICAgICApXG4gICAgICApO1xuICAgICAgY29uc3QgaW5wdXRUeCA9IGNyZWF0ZUlucHV0VHgodW5zcGVudHMsIG91dHB1dFZhbHVlKTtcbiAgICAgIHJldHVybiB7IGlucHV0S2V5cywgdW5zcGVudHMsIGlucHV0VHggfTtcbiAgICB9KTtcblxuICAgIG91dHB1dFR5cGVzLmZvckVhY2goKG91dHB1dFR5cGUpID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dHMgPSBvdXRwdXRLZXlUcmlwbGV0cy5tYXAoKG91dHB1dEtleXMpID0+IGNyZWF0ZVNjcmlwdFB1YktleShvdXRwdXRLZXlzLCBvdXRwdXRUeXBlKSk7XG5cbiAgICAgIGNvbnN0IHR4cyA9IHtcbiAgICAgICAgZm9yRWFjaChjYjogKHR4OiB1dHhvbGliLlRyYW5zYWN0aW9uKSA9PiB2b2lkKSB7XG4gICAgICAgICAgaW5wdXRUeHMuZm9yRWFjaCgoeyBpbnB1dEtleXMsIHVuc3BlbnRzLCBpbnB1dFR4IH0pID0+IHtcbiAgICAgICAgICAgIG91dHB1dHMuZm9yRWFjaCgoc2NyaXB0UHViS2V5KSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRm9yTmV0d29yayh1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgICAgICAgICBpbnB1dFR4Lm91dHMuZm9yRWFjaCgodjogYW55LCBpOiBudW1iZXIpID0+IHR4QnVpbGRlci5hZGRJbnB1dChpbnB1dFR4LCBpKSk7XG4gICAgICAgICAgICAgIHR4QnVpbGRlci5hZGRPdXRwdXQoc2NyaXB0UHViS2V5LCBvdXRwdXRWYWx1ZSk7XG4gICAgICAgICAgICAgIHVuc3BlbnRzLmZvckVhY2goKHVuc3BlbnQsIGkpID0+IHtcbiAgICAgICAgICAgICAgICBzaWduSW5wdXQodHhCdWlsZGVyLCBpLCBpbnB1dEtleXMsIHVuc3BlbnQpO1xuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBjYih0eEJ1aWxkZXIuYnVpbGQoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNhbGxiYWNrKGlucHV0VHlwZSwgaW5wdXRDb3VudCwgb3V0cHV0VHlwZSwgdHhzKTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG5leHBvcnQgeyBUeENvbWJvLCBIaXN0b2dyYW0sIHJ1bkNvbWJpbmF0aW9ucywgcnVuU2lnbmVkVHJhbnNhY3Rpb25zIH07XG4iXX0=