UNPKG

@bitgo-beta/utxo-lib

Version:

Client-side Bitcoin JavaScript library

442 lines • 71.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UtxoPsbt = void 0; const UtxoTransaction_1 = require("./UtxoTransaction"); const __1 = require("../"); const utils_1 = require("bip174/src/lib/utils"); const bip174_1 = require("bip174"); const __2 = require(".."); const opcodes = require("bitcoin-ops"); const bufferutils_1 = require("bitcoinjs-lib/src/bufferutils"); // TODO: upstream does `checkInputsForPartialSigs` before doing things like // `setVersion`. Our inputs could have tapscriptsigs (or in future tapkeysigs) // and not fail that check. Do we want to do anything about that? class UtxoPsbt extends __1.Psbt { static transactionFromBuffer(buffer, network) { return UtxoTransaction_1.UtxoTransaction.fromBuffer(buffer, false, 'bigint', network); } static createPsbt(opts, data) { return new UtxoPsbt(opts, data || new bip174_1.Psbt(new __1.PsbtTransaction({ tx: new UtxoTransaction_1.UtxoTransaction(opts.network) }))); } static fromBuffer(buffer, opts) { const transactionFromBuffer = (buffer) => { const tx = this.transactionFromBuffer(buffer, opts.network); return new __1.PsbtTransaction({ tx }); }; const psbtBase = bip174_1.Psbt.fromBuffer(buffer, transactionFromBuffer); const psbt = this.createPsbt(opts, psbtBase); // Upstream checks for duplicate inputs here, but it seems to be of dubious value. return psbt; } static async fromTransactionComplete(transaction, prevOutputs, fetchTransactions) { const psbt = this.fromTransaction(transaction, prevOutputs); const txidToIndex = {}; psbt.data.inputs.forEach((input, index) => { if (!input.tapLeafScript && !input.witnessScript) { txidToIndex[bufferutils_1.reverseBuffer(transaction.ins[index].hash).toString('hex')] = index; } }); const txHexs = await fetchTransactions(Object.keys(txidToIndex)); Object.entries(txidToIndex).forEach(([txid, index]) => { psbt.updateInput(index, { nonWitnessUtxo: txHexs[txid] }); }); return psbt; } static fromTransaction(transaction, prevOutputs) { if (prevOutputs.length !== transaction.ins.length) { throw new Error(`Transaction has ${transaction.ins.length} inputs, but ${prevOutputs.length} previous outputs provided`); } const clonedTransaction = transaction.clone(); const updates = unsign(clonedTransaction, prevOutputs); const psbtBase = new bip174_1.Psbt(new __1.PsbtTransaction({ tx: clonedTransaction })); clonedTransaction.ins.forEach(() => psbtBase.inputs.push({ unknownKeyVals: [] })); clonedTransaction.outs.forEach(() => psbtBase.outputs.push({ unknownKeyVals: [] })); const psbt = this.createPsbt({ network: transaction.network }, psbtBase); updates.forEach((update, index) => { psbt.updateInput(index, update); psbt.updateInput(index, { witnessUtxo: prevOutputs[index] }); }); return psbt; } static newTransaction(network) { return new UtxoTransaction_1.UtxoTransaction(network); } get tx() { return this.data.globalMap.unsignedTx.tx; } checkForSignatures(propName) { this.data.inputs.forEach((input) => { var _a, _b; if (((_a = input.tapScriptSig) === null || _a === void 0 ? void 0 : _a.length) || input.tapKeySig || ((_b = input.partialSig) === null || _b === void 0 ? void 0 : _b.length)) { throw new Error(`Cannot modify ${propName !== null && propName !== void 0 ? propName : 'transaction'} - signatures exist.`); } }); } /** * Mostly copied from bitcoinjs-lib/ts_src/psbt.ts */ finalizeAllInputs() { utils_1.checkForInput(this.data.inputs, 0); // making sure we have at least one this.data.inputs.map((input, idx) => { var _a; return ((_a = input.tapScriptSig) === null || _a === void 0 ? void 0 : _a.length) ? this.finalizeTaprootInput(idx) : this.finalizeInput(idx); }); return this; } finalizeTaprootInput(inputIndex) { var _a, _b; const input = utils_1.checkForInput(this.data.inputs, inputIndex); // witness = control-block script first-sig second-sig if (((_a = input.tapLeafScript) === null || _a === void 0 ? void 0 : _a.length) !== 1) { throw new Error('Only one leaf script supported for finalizing'); } const { controlBlock, script } = input.tapLeafScript[0]; const witness = [script, controlBlock]; const decompiled = __2.script.decompile(script); if (!decompiled || (decompiled === null || decompiled === void 0 ? void 0 : decompiled.length) !== 4) { throw new Error('Not a valid bitgo n-of-n script.'); } const [pubkey1, op_checksigverify, pubkey2, op_checksig] = decompiled; if (!Buffer.isBuffer(pubkey1) || !Buffer.isBuffer(pubkey2)) { throw new Error('Public Keys are not buffers.'); } if (op_checksigverify !== opcodes.OP_CHECKSIGVERIFY || op_checksig !== opcodes.OP_CHECKSIG) { throw new Error('Opcodes do not correspond to a valid bitgo script'); } for (const pk of [pubkey1, pubkey2]) { const sig = (_b = input.tapScriptSig) === null || _b === void 0 ? void 0 : _b.find(({ pubkey }) => pubkey.equals(pk)); if (!sig) { throw new Error('Could not find signatures in Script Sig.'); } witness.unshift(sig.signature); } const witnessLength = witness.reduce((s, b) => s + b.length + bufferutils_1.varuint.encodingLength(b.length), 1); const bufferWriter = bufferutils_1.BufferWriter.withCapacity(witnessLength); bufferWriter.writeVector(witness); const finalScriptWitness = bufferWriter.end(); this.data.updateInput(inputIndex, { finalScriptWitness }); this.data.clearFinalizedInput(inputIndex); return this; } /** * Mostly copied from bitcoinjs-lib/ts_src/psbt.ts * * Unlike the function it overrides, this does not take a validator. In BitGo * context, we know how we want to validate so we just hard code the right * validator. */ validateSignaturesOfAllInputs() { utils_1.checkForInput(this.data.inputs, 0); // making sure we have at least one const results = this.data.inputs.map((input, idx) => { var _a; return ((_a = input.tapScriptSig) === null || _a === void 0 ? void 0 : _a.length) ? this.validateTaprootSignaturesOfInput(idx) : this.validateSignaturesOfInput(idx, (p, m, s) => __2.ecc.verify(m, p, s)); }); return results.reduce((final, res) => res && final, true); } validateTaprootSignaturesOfInput(inputIndex) { const input = this.data.inputs[inputIndex]; const mySigs = (input || {}).tapScriptSig; if (!input || !mySigs || mySigs.length < 1) throw new Error('No signatures to validate'); const results = []; for (const pSig of mySigs) { const { signature, leafHash, pubkey } = pSig; let sigHashType; let sig; if (signature.length === 65) { sigHashType = signature[64]; sig = signature.slice(0, 64); } else { sigHashType = __1.Transaction.SIGHASH_DEFAULT; sig = signature; } const { hash } = this.getTaprootHashForSig(inputIndex, true, [sigHashType], leafHash); results.push(__2.ecc.verifySchnorr(hash, pubkey, sig)); } return results.every((res) => res === true); } /** * Mostly copied from bitcoinjs-lib/ts_src/psbt.ts */ signAllInputsHD(hdKeyPair, sighashTypes = [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL]) { var _a; if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) { throw new Error('Need HDSigner to sign input'); } const results = []; for (let i = 0; i < this.data.inputs.length; i++) { try { if ((_a = this.data.inputs[i].tapBip32Derivation) === null || _a === void 0 ? void 0 : _a.length) { this.signTaprootInputHD(i, hdKeyPair, sighashTypes); } else { this.signInputHD(i, hdKeyPair, sighashTypes); } results.push(true); } catch (err) { results.push(false); } } if (results.every((v) => v === false)) { throw new Error('No inputs were signed'); } return this; } /** * Mostly copied from bitcoinjs-lib/ts_src/psbt.ts:signInputHD */ signTaprootInputHD(inputIndex, hdKeyPair, sighashTypes = [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL]) { if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) { throw new Error('Need HDSigner to sign input'); } const input = utils_1.checkForInput(this.data.inputs, inputIndex); if (!input.tapBip32Derivation || input.tapBip32Derivation.length === 0) { throw new Error('Need tapBip32Derivation to sign Taproot with HD'); } const myDerivations = input.tapBip32Derivation .map((bipDv) => { if (bipDv.masterFingerprint.equals(hdKeyPair.fingerprint)) { return bipDv; } }) .filter((v) => !!v); if (myDerivations.length === 0) { throw new Error('Need one tapBip32Derivation masterFingerprint to match the HDSigner fingerprint'); } const signers = myDerivations.map((bipDv) => { const node = hdKeyPair.derivePath(bipDv.path); if (!bipDv.pubkey.equals(node.publicKey.slice(1))) { throw new Error('pubkey did not match tapBip32Derivation'); } return { signer: node, leafHashes: bipDv.leafHashes }; }); signers.forEach(({ signer, leafHashes }) => this.signTaprootInput(inputIndex, signer, leafHashes, sighashTypes)); return this; } signTaprootInput(inputIndex, signer, leafHashes, sighashTypes = [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL]) { var _a; const input = utils_1.checkForInput(this.data.inputs, inputIndex); // Figure out if this is script path or not, if not, tweak the private key if (!((_a = input.tapLeafScript) === null || _a === void 0 ? void 0 : _a.length)) { // See BitGo/BitGoJS/modules/utxo_lib/src/transaction_builder.ts:trySign for how to support it. throw new Error('Taproot key path signing is not supported.'); } if (input.tapLeafScript.length !== 1) { throw new Error('Only one leaf script supported for signing'); } const tapLeafScript = input.tapLeafScript[0]; const parsedControlBlock = __1.taproot.parseControlBlock(__2.ecc, tapLeafScript.controlBlock); const { leafVersion } = parsedControlBlock; if (leafVersion !== tapLeafScript.leafVersion) { throw new Error('Tap script leaf version mismatch with control block'); } const leafHash = __1.taproot.getTapleafHash(__2.ecc, parsedControlBlock, tapLeafScript.script); if (!leafHashes.find((l) => l.equals(leafHash))) { throw new Error(`Signer cannot sign for leaf hash ${leafHash.toString('hex')}`); } const { hash, sighashType } = this.getTaprootHashForSig(inputIndex, false, sighashTypes, leafHash); let signature = signer.signSchnorr(hash); if (sighashType !== __1.Transaction.SIGHASH_DEFAULT) { signature = Buffer.concat([signature, Buffer.of(sighashType)]); } this.data.updateInput(inputIndex, { tapScriptSig: [ { pubkey: signer.publicKey.slice(1), signature, leafHash, }, ], }); return this; } getTaprootHashForSig(inputIndex, forValidate, sighashTypes, leafHash) { const unsignedTx = this.tx; const sighashType = this.data.inputs[inputIndex].sighashType || __1.Transaction.SIGHASH_DEFAULT; if (sighashTypes && sighashTypes.indexOf(sighashType) < 0) { throw new Error(`Sighash type is not allowed. Retry the sign method passing the ` + `sighashTypes array of whitelisted types. Sighash type: ${sighashType}`); } const prevoutScripts = []; const prevoutValues = []; for (const input of this.data.inputs) { let prevout; if (input.nonWitnessUtxo) { // TODO: This could be costly, either cache it here, or find a way to share with super const nonWitnessUtxoTx = this.constructor.transactionFromBuffer(input.nonWitnessUtxo, unsignedTx.network); const prevoutHash = unsignedTx.ins[inputIndex].hash; const utxoHash = nonWitnessUtxoTx.getHash(); // If a non-witness UTXO is provided, its hash must match the hash specified in the prevout if (!prevoutHash.equals(utxoHash)) { throw new Error(`Non-witness UTXO hash for input #${inputIndex} doesn't match the hash specified in the prevout`); } const prevoutIndex = unsignedTx.ins[inputIndex].index; prevout = nonWitnessUtxoTx.outs[prevoutIndex]; } else if (input.witnessUtxo) { prevout = input.witnessUtxo; } else { throw new Error('Need a Utxo input item for signing'); } prevoutScripts.push(prevout.script); prevoutValues.push(prevout.value); } const hash = unsignedTx.hashForWitnessV1(inputIndex, prevoutScripts, prevoutValues, sighashType, leafHash); return { hash, sighashType }; } } exports.UtxoPsbt = UtxoPsbt; /** * Takes a partially signed transaction and removes the scripts and signatures. * * Inputs must be one of: * * P2PKH * * P2SH 2-of-3 * * P2WSH 2-of-3 * * P2WPKH * * P2SH -> P2WSH 2-of-3 * * P2SH -> P2WPKH * * P2TR script path 2-of-2 * * @param tx the partially signed transaction * * @return the removed scripts and signatures, ready to be added to a PSBT */ function unsign(tx, prevOuts) { const ret = tx.ins.map((input, vin) => { const prevOut = prevOuts[vin]; const update = {}; let redeemScript; if (input.script && input.script.length) { const decompiledScriptSig = __2.script.decompile(input.script); if (!decompiledScriptSig) { throw new Error('Invalid scriptSig, failed to decompile'); } if ((!input.witness || !input.witness.length) && decompiledScriptSig.length === 2) { // P2PKH const pubkey = decompiledScriptSig.pop(); const signature = decompiledScriptSig.pop(); if (!Buffer.isBuffer(pubkey) || !Buffer.isBuffer(signature)) { throw new Error('Invalid pubkey or signature'); } update.partialSig = [{ pubkey, signature }]; return update; } redeemScript = decompiledScriptSig.pop(); if (!Buffer.isBuffer(redeemScript)) { throw new Error('Invalid redeem script'); } update.redeemScript = redeemScript; if (opcodes.OP_0 !== redeemScript[0] || ![22, 34].includes(redeemScript.length)) { // P2SH -> 2-of-3 const hashFn = (hashType) => tx.hashForSignature(vin, redeemScript, hashType, prevOut.value); update.partialSig = matchSignatures(hashFn, redeemScript, decompiledScriptSig); return update; } } if (input.witness && input.witness.length) { const witness = input.witness; if (witness.length > 2 && witness[witness.length - 1][0] === 0x50) { throw new Error('Annex not supported'); } if (witness.length === 1) { // Taproot key path update.tapKeySig = witness.pop(); return update; } const witnessProgramCandidate = redeemScript !== null && redeemScript !== void 0 ? redeemScript : prevOut.script; if (witnessProgramCandidate.length === 34 && witnessProgramCandidate[0] === opcodes.OP_1) { // Taproot script path const controlBlock = witness.pop(); const script = witness.pop(); if (!controlBlock || !script) throw new Error('Unexpected witness structure'); const leafVersion = controlBlock[0] & 0xfe; update.tapLeafScript = [{ controlBlock, script, leafVersion }]; const publicKeys = __2.payments.p2tr_ns({ output: script }, { eccLib: __2.ecc }).pubkeys; if (!publicKeys || publicKeys.length !== 2) { throw new Error('expected 2 pubkeys'); } if (witness.length !== 2) { throw new Error(`expected exactly 2 signatures, got ${witness.length}`); } update.tapScriptSig = []; let signature; while ((signature = witness.pop()) !== undefined) { if (signature.length === 0) { publicKeys.shift(); // No signature for this key continue; } const leafHash = __1.taproot.getTapleafHash(__2.ecc, controlBlock, script); const pubkey = publicKeys.shift(); if (!pubkey) throw new Error("Impossible, known 2-length things didn't match"); update.tapScriptSig.push({ signature, pubkey, leafHash }); } } else if (witnessProgramCandidate.length === 34 && witnessProgramCandidate[0] === opcodes.OP_0) { // P2WSH const witnessScript = witness.pop(); if (!witnessScript) throw new Error('Invalid witness structure'); update.witnessScript = witnessScript; const decompiledWitnessScript = __2.script.decompile(witnessScript); if (!decompiledWitnessScript) { throw new Error('Invalid witnessScript, failed to decompile'); } const hashFn = (hashType) => tx.hashForWitnessV0(vin, witnessScript, prevOut.value, hashType); update.partialSig = matchSignatures(hashFn, witnessScript, witness); } else if (witnessProgramCandidate.length === 22 && witnessProgramCandidate[0] === opcodes.OP_0) { // P2WPKH if (witness.length === 2) { const pubkey = witness.pop(); const signature = witness.pop(); if (!Buffer.isBuffer(pubkey) || !Buffer.isBuffer(signature)) { throw new Error('Invalid pubkey or signature'); } update.partialSig = [{ pubkey, signature }]; } return update; } } return update; }); tx.ins.forEach((input) => { input.witness = []; input.script = Buffer.alloc(0); }); return ret; } function matchSignatures(hashFn, script, stack) { const partialSig = []; const publicKeys = __2.payments.p2ms({ output: script }).pubkeys; if (!publicKeys || publicKeys.length !== 3) { throw new Error('Invalid multisig script'); } for (const sig of stack.slice(1)) { // Ignore extra empty element re MULTISIG bug if (!Buffer.isBuffer(sig) || sig.length === 0) continue; const { signature, hashType } = __1.ScriptSignature.decode(sig); const hash = hashFn(hashType); let signatureMatched = false; for (const pubkey of publicKeys) { if (__2.ecc.verify(hash, pubkey, signature)) { signatureMatched = true; partialSig.push({ pubkey, signature: sig }); break; } } if (!signatureMatched) { throw new Error('Invalid signature in partially signed transaction'); } } return partialSig; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXR4b1BzYnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYml0Z28vVXR4b1BzYnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdURBQW9EO0FBQ3BELDJCQUE4RztBQVE5RyxnREFBcUQ7QUFDckQsbUNBQTBDO0FBRTFDLDBCQUFnRTtBQUNoRSx1Q0FBdUM7QUFDdkMsK0RBQXFGO0FBNkJyRiwyRUFBMkU7QUFDM0UsOEVBQThFO0FBQzlFLGlFQUFpRTtBQUNqRSxNQUFhLFFBQTZDLFNBQVEsUUFBSTtJQUMxRCxNQUFNLENBQUMscUJBQXFCLENBQUMsTUFBYyxFQUFFLE9BQWdCO1FBQ3JFLE9BQU8saUNBQWUsQ0FBQyxVQUFVLENBQVMsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBYyxFQUFFLElBQWM7UUFDOUMsT0FBTyxJQUFJLFFBQVEsQ0FDakIsSUFBSSxFQUNKLElBQUksSUFBSSxJQUFJLGFBQVEsQ0FBQyxJQUFJLG1CQUFlLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxpQ0FBZSxDQUFTLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FDN0YsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQWMsRUFBRSxJQUFjO1FBQzlDLE1BQU0scUJBQXFCLEdBQTBCLENBQUMsTUFBYyxFQUFnQixFQUFFO1lBQ3BGLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVELE9BQU8sSUFBSSxtQkFBZSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUM7UUFDRixNQUFNLFFBQVEsR0FBRyxhQUFRLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxxQkFB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RSxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztnQkFDNUMsTUFBTTthQUNQO1NBQ0Y7UUFDRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO1NBQ3RFO0tBQ0Y7SUFDRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVXR4b1RyYW5zYWN0aW9uIH0gZnJvbSAnLi9VdHhvVHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgdGFwcm9vdCwgSERTaWduZXIsIFBzYnQsIFBzYnRUcmFuc2FjdGlvbiwgU2NyaXB0U2lnbmF0dXJlLCBTdGFjaywgVHJhbnNhY3Rpb24sIFR4T3V0cHV0IH0gZnJvbSAnLi4vJztcbmltcG9ydCB7XG4gIFBhcnRpYWxTaWcsXG4gIFBzYnRJbnB1dFVwZGF0ZSxcbiAgVGFwQmlwMzJEZXJpdmF0aW9uLFxuICBUcmFuc2FjdGlvbiBhcyBJVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uRnJvbUJ1ZmZlcixcbn0gZnJvbSAnYmlwMTc0L3NyYy9saWIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBjaGVja0ZvcklucHV0IH0gZnJvbSAnYmlwMTc0L3NyYy9saWIvdXRpbHMnO1xuaW1wb3J0IHsgUHNidCBhcyBQc2J0QmFzZSB9IGZyb20gJ2JpcDE3NCc7XG5pbXBvcnQgeyBOZXR3b3JrIH0gZnJvbSAnLi4nO1xuaW1wb3J0IHsgZWNjIGFzIGVjY0xpYiwgc2NyaXB0IGFzIGJzY3JpcHQsIHBheW1lbnRzIH0gZnJvbSAnLi4nO1xuaW1wb3J0ICogYXMgb3Bjb2RlcyBmcm9tICdiaXRjb2luLW9wcyc7XG5pbXBvcnQgeyBCdWZmZXJXcml0ZXIsIHZhcnVpbnQsIHJldmVyc2VCdWZmZXIgfSBmcm9tICdiaXRjb2luanMtbGliL3NyYy9idWZmZXJ1dGlscyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSERUYXByb290U2lnbmVyIGV4dGVuZHMgSERTaWduZXIge1xuICAvKipcbiAgICogVGhlIHBhdGggc3RyaW5nIG11c3QgbWF0Y2ggL15tKFxcL1xcZCsnPykrJC9cbiAgICogZXguIG0vNDQnLzAnLzAnLzEvMjMgbGV2ZWxzIHdpdGggJyBtdXN0IGJlIGhhcmQgZGVyaXZhdGlvbnNcbiAgICovXG4gIGRlcml2ZVBhdGgocGF0aDogc3RyaW5nKTogSERUYXByb290U2lnbmVyO1xuICAvKipcbiAgICogSW5wdXQgaGFzaCAodGhlIFwibWVzc2FnZSBkaWdlc3RcIikgZm9yIHRoZSBzaWduYXR1cmUgYWxnb3JpdGhtXG4gICAqIFJldHVybiBhIDY0IGJ5dGUgc2lnbmF0dXJlICgzMiBieXRlIHIgYW5kIDMyIGJ5dGUgcyBpbiB0aGF0IG9yZGVyKVxuICAgKi9cbiAgc2lnblNjaG5vcnIoaGFzaDogQnVmZmVyKTogQnVmZmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNjaG5vcnJTaWduZXIge1xuICBwdWJsaWNLZXk6IEJ1ZmZlcjtcbiAgc2lnblNjaG5vcnIoaGFzaDogQnVmZmVyKTogQnVmZmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRhcHJvb3RTaWduZXIge1xuICBsZWFmSGFzaGVzOiBCdWZmZXJbXTtcbiAgc2lnbmVyOiBTY2hub3JyU2lnbmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBzYnRPcHRzIHtcbiAgbmV0d29yazogTmV0d29yaztcbn1cblxuLy8gVE9ETzogdXBzdHJlYW0gZG9lcyBgY2hlY2tJbnB1dHNGb3JQYXJ0aWFsU2lnc2AgYmVmb3JlIGRvaW5nIHRoaW5ncyBsaWtlXG4vLyBgc2V0VmVyc2lvbmAuIE91ciBpbnB1dHMgY291bGQgaGF2ZSB0YXBzY3JpcHRzaWdzIChvciBpbiBmdXR1cmUgdGFwa2V5c2lncylcbi8vIGFuZCBub3QgZmFpbCB0aGF0IGNoZWNrLiBEbyB3ZSB3YW50IHRvIGRvIGFueXRoaW5nIGFib3V0IHRoYXQ/XG5leHBvcnQgY2xhc3MgVXR4b1BzYnQ8VHggZXh0ZW5kcyBVdHhvVHJhbnNhY3Rpb248YmlnaW50Pj4gZXh0ZW5kcyBQc2J0IHtcbiAgcHJvdGVjdGVkIHN0YXRpYyB0cmFuc2FjdGlvbkZyb21CdWZmZXIoYnVmZmVyOiBCdWZmZXIsIG5ldHdvcms6IE5ldHdvcmspOiBVdHhvVHJhbnNhY3Rpb248YmlnaW50PiB7XG4gICAgcmV0dXJuIFV0eG9UcmFuc2FjdGlvbi5mcm9tQnVmZmVyPGJpZ2ludD4oYnVmZmVyLCBmYWxzZSwgJ2JpZ2ludCcsIG5ldHdvcmspO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZVBzYnQob3B0czogUHNidE9wdHMsIGRhdGE6IFBzYnRCYXNlKTogVXR4b1BzYnQ8VXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+IHtcbiAgICByZXR1cm4gbmV3IFV0eG9Qc2J0PFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+PihcbiAgICAgIG9wdHMsXG4gICAgICBkYXRhIHx8IG5ldyBQc2J0QmFzZShuZXcgUHNidFRyYW5zYWN0aW9uKHsgdHg6IG5ldyBVdHhvVHJhbnNhY3Rpb248YmlnaW50PihvcHRzLm5ldHdvcmspIH0pKVxuICAgICk7XG4gIH1cblxuICBzdGF0aWMgZnJvbUJ1ZmZlcihidWZmZXI6IEJ1ZmZlciwgb3B0czogUHNidE9wdHMpOiBVdHhvUHNidDxVdHhvVHJhbnNhY3Rpb248YmlnaW50Pj4ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uRnJvbUJ1ZmZlcjogVHJhbnNhY3Rpb25Gcm9tQnVmZmVyID0gKGJ1ZmZlcjogQnVmZmVyKTogSVRyYW5zYWN0aW9uID0+IHtcbiAgICAgIGNvbnN0IHR4ID0gdGhpcy50cmFuc2FjdGlvbkZyb21CdWZmZXIoYnVmZmVyLCBvcHRzLm5ldHdvcmspO1xuICAgICAgcmV0dXJuIG5ldyBQc2J0VHJhbnNhY3Rpb24oeyB0eCB9KTtcbiAgICB9O1xuICAgIGNvbnN0IHBzYnRCYXNlID0gUHNidEJhc2UuZnJvbUJ1ZmZlcihidWZmZXIsIHRyYW5zYWN0aW9uRnJvbUJ1ZmZlcik7XG4gICAgY29uc3QgcHNidCA9IHRoaXMuY3JlYXRlUHNidChvcHRzLCBwc2J0QmFzZSk7XG4gICAgLy8gVXBzdHJlYW0gY2hlY2tzIGZvciBkdXBsaWNhdGUgaW5wdXRzIGhlcmUsIGJ1dCBpdCBzZWVtcyB0byBiZSBvZiBkdWJpb3VzIHZhbHVlLlxuICAgIHJldHVybiBwc2J0O1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGZyb21UcmFuc2FjdGlvbkNvbXBsZXRlKFxuICAgIHRyYW5zYWN0aW9uOiBVdHhvVHJhbnNhY3Rpb248YmlnaW50PixcbiAgICBwcmV2T3V0cHV0czogVHhPdXRwdXQ8YmlnaW50PltdLFxuICAgIGZldGNoVHJhbnNhY3Rpb25zOiAodHhpZHM6IHN0cmluZ1tdKSA9PiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIEJ1ZmZlcj4+XG4gICk6IFByb21pc2U8VXR4b1BzYnQ8VXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+PiB7XG4gICAgY29uc3QgcHNidCA9IHRoaXMuZnJvbVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uLCBwcmV2T3V0cHV0cyk7XG5cbiAgICBjb25zdCB0eGlkVG9JbmRleDogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgIHBzYnQuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGluZGV4KSA9PiB7XG4gICAgICBpZiAoIWlucHV0LnRhcExlYWZTY3JpcHQgJiYgIWlucHV0LndpdG5lc3NTY3JpcHQpIHtcbiAgICAgICAgdHhpZFRvSW5kZXhbcmV2ZXJzZUJ1ZmZlcih0cmFuc2FjdGlvbi5pbnNbaW5kZXhdLmhhc2gpLnRvU3RyaW5nKCdoZXgnKV0gPSBpbmRleDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnN0IHR4SGV4cyA9IGF3YWl0IGZldGNoVHJhbnNhY3Rpb25zKE9iamVjdC5rZXlzKHR4aWRUb0luZGV4KSk7XG4gICAgT2JqZWN0LmVudHJpZXModHhpZFRvSW5kZXgpLmZvckVhY2goKFt0eGlkLCBpbmRleF0pID0+IHtcbiAgICAgIHBzYnQudXBkYXRlSW5wdXQoaW5kZXgsIHsgbm9uV2l0bmVzc1V0eG86IHR4SGV4c1t0eGlkXSB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiBwc2J0O1xuICB9XG5cbiAgc3RhdGljIGZyb21UcmFuc2FjdGlvbihcbiAgICB0cmFuc2FjdGlvbjogVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4sXG4gICAgcHJldk91dHB1dHM6IFR4T3V0cHV0PGJpZ2ludD5bXVxuICApOiBVdHhvUHNidDxVdHhvVHJhbnNhY3Rpb248YmlnaW50Pj4ge1xuICAgIGlmIChwcmV2T3V0cHV0cy5sZW5ndGggIT09IHRyYW5zYWN0aW9uLmlucy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRyYW5zYWN0aW9uIGhhcyAke3RyYW5zYWN0aW9uLmlucy5sZW5ndGh9IGlucHV0cywgYnV0ICR7cHJldk91dHB1dHMubGVuZ3RofSBwcmV2aW91cyBvdXRwdXRzIHByb3ZpZGVkYFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgY2xvbmVkVHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbi5jbG9uZSgpO1xuICAgIGNvbnN0IHVwZGF0ZXMgPSB1bnNpZ24oY2xvbmVkVHJhbnNhY3Rpb24sIHByZXZPdXRwdXRzKTtcblxuICAgIGNvbnN0IHBzYnRCYXNlID0gbmV3IFBzYnRCYXNlKG5ldyBQc2J0VHJhbnNhY3Rpb24oeyB0eDogY2xvbmVkVHJhbnNhY3Rpb24gfSkpO1xuICAgIGNsb25lZFRyYW5zYWN0aW9uLmlucy5mb3JFYWNoKCgpID0+IHBzYnRCYXNlLmlucHV0cy5wdXNoKHsgdW5rbm93bktleVZhbHM6IFtdIH0pKTtcbiAgICBjbG9uZWRUcmFuc2FjdGlvbi5vdXRzLmZvckVhY2goKCkgPT4gcHNidEJhc2Uub3V0cHV0cy5wdXNoKHsgdW5rbm93bktleVZhbHM6IFtdIH0pKTtcbiAgICBjb25zdCBwc2J0ID0gdGhpcy5jcmVhdGVQc2J0KHsgbmV0d29yazogdHJhbnNhY3Rpb24ubmV0d29yayB9LCBwc2J0QmFzZSk7XG5cbiAgICB1cGRhdGVzLmZvckVhY2goKHVwZGF0ZSwgaW5kZXgpID0+IHtcbiAgICAgIHBzYnQudXBkYXRlSW5wdXQoaW5kZXgsIHVwZGF0ZSk7XG4gICAgICBwc2J0LnVwZGF0ZUlucHV0KGluZGV4LCB7IHdpdG5lc3NVdHhvOiBwcmV2T3V0cHV0c1tpbmRleF0gfSk7XG4gICAgfSk7XG5cbiAgI