@bitgo/utxo-lib
Version:
Client-side Bitcoin JavaScript library
130 lines • 15.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProprietaryKeySubtype = exports.PSBT_PROPRIETARY_IDENTIFIER = void 0;
exports.getPsbtInputProprietaryKeyVals = getPsbtInputProprietaryKeyVals;
exports.getPsbtOutputProprietaryKeyVals = getPsbtOutputProprietaryKeyVals;
exports.getPsbtInputSignatureCount = getPsbtInputSignatureCount;
exports.isPsbtInputFinalized = isPsbtInputFinalized;
exports.isPsbt = isPsbt;
exports.toPsbtBuffer = toPsbtBuffer;
exports.withUnsafeNonSegwit = withUnsafeNonSegwit;
const ProprietaryKeyValUtils_1 = require("./ProprietaryKeyValUtils");
/**
* bitgo proprietary key identifier
*/
exports.PSBT_PROPRIETARY_IDENTIFIER = 'BITGO';
/**
* subtype for proprietary keys that bitgo uses
*/
var ProprietaryKeySubtype;
(function (ProprietaryKeySubtype) {
ProprietaryKeySubtype[ProprietaryKeySubtype["ZEC_CONSENSUS_BRANCH_ID"] = 0] = "ZEC_CONSENSUS_BRANCH_ID";
ProprietaryKeySubtype[ProprietaryKeySubtype["MUSIG2_PARTICIPANT_PUB_KEYS"] = 1] = "MUSIG2_PARTICIPANT_PUB_KEYS";
ProprietaryKeySubtype[ProprietaryKeySubtype["MUSIG2_PUB_NONCE"] = 2] = "MUSIG2_PUB_NONCE";
ProprietaryKeySubtype[ProprietaryKeySubtype["MUSIG2_PARTIAL_SIG"] = 3] = "MUSIG2_PARTIAL_SIG";
ProprietaryKeySubtype[ProprietaryKeySubtype["PAYGO_ADDRESS_ATTESTATION_PROOF"] = 4] = "PAYGO_ADDRESS_ATTESTATION_PROOF";
})(ProprietaryKeySubtype || (exports.ProprietaryKeySubtype = ProprietaryKeySubtype = {}));
/**
* Search any data from psbt proprietary key value against keydata.
* Default identifierEncoding is utf-8 for identifier.
*/
function getPsbtInputProprietaryKeyVals(input, keySearch) {
if (!input.unknownKeyVals?.length) {
return [];
}
return (0, ProprietaryKeyValUtils_1.getProprietaryKeyValuesFromUnknownKeyValues)(input, keySearch);
}
function getPsbtOutputProprietaryKeyVals(output, keySearch) {
if (!output.unknownKeyVals?.length) {
return [];
}
return (0, ProprietaryKeyValUtils_1.getProprietaryKeyValuesFromUnknownKeyValues)(output, keySearch);
}
/**
* @return partialSig/tapScriptSig/MUSIG2_PARTIAL_SIG count iff input is not finalized
*/
function getPsbtInputSignatureCount(input) {
if (isPsbtInputFinalized(input)) {
throw new Error('Input is already finalized');
}
return Math.max(Array.isArray(input.partialSig) ? input.partialSig.length : 0, Array.isArray(input.tapScriptSig) ? input.tapScriptSig.length : 0, getPsbtInputProprietaryKeyVals(input, {
identifier: exports.PSBT_PROPRIETARY_IDENTIFIER,
subtype: ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG,
}).length);
}
/**
* @return true iff PSBT input is finalized
*/
function isPsbtInputFinalized(input) {
return Buffer.isBuffer(input.finalScriptSig) || Buffer.isBuffer(input.finalScriptWitness);
}
/**
* @return true iff data starts with magic PSBT byte sequence
* @param data byte array or hex string
* */
function isPsbt(data) {
// https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#specification
// 0x70736274 - ASCII for 'psbt'. 0xff - separator
if (typeof data === 'string') {
if (data.length < 10) {
return false;
}
data = Buffer.from(data.slice(0, 10), 'hex');
}
return 5 <= data.length && data.readUInt32BE(0) === 0x70736274 && data.readUInt8(4) === 0xff;
}
/**
* First checks if the input is already a buffer that starts with the magic PSBT byte sequence.
* If not, it checks if the input is a base64- or hex-encoded string that starts with PSBT header.
*
* This function is useful when reading a file that could be in any of the above formats or when
* dealing with a request that could contain a hex or base64 encoded PSBT.
*
* @param data
* @return buffer that starts with the magic PSBT byte sequence
* @throws Error when conversion is not possible
*/
function toPsbtBuffer(data) {
if (Buffer.isBuffer(data)) {
// we are dealing with a buffer that looks like a psbt already
if (isPsbt(data)) {
return data;
}
// we could be dealing with a buffer that could be a hex or base64 encoded psbt
data = data.toString('ascii');
}
if (typeof data === 'string') {
const encodings = ['hex', 'base64'];
for (const encoding of encodings) {
let buffer;
try {
buffer = Buffer.from(data, encoding);
}
catch (e) {
continue;
}
if (isPsbt(buffer)) {
return buffer;
}
}
throw new Error(`data is not in any of the following formats: ${encodings.join(', ')}`);
}
throw new Error('data must be a buffer or a string');
}
/**
* This function allows signing or validating a psbt with non-segwit inputs those do not contain nonWitnessUtxo.
*/
function withUnsafeNonSegwit(psbt, fn, unsafe = true) {
const prevValue = psbt.__CACHE.__UNSAFE_SIGN_NONSEGWIT;
const prevValueWarn = psbt.__CACHE.__WARN_UNSAFE_SIGN_NONSEGWIT;
psbt.__CACHE.__UNSAFE_SIGN_NONSEGWIT = unsafe;
psbt.__CACHE.__WARN_UNSAFE_SIGN_NONSEGWIT = !unsafe;
try {
return fn();
}
finally {
psbt.__CACHE.__UNSAFE_SIGN_NONSEGWIT = prevValue;
psbt.__CACHE.__WARN_UNSAFE_SIGN_NONSEGWIT = prevValueWarn;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHNidFV0aWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYml0Z28vUHNidFV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBNkJBLHdFQVFDO0FBRUQsMEVBUUM7QUFLRCxnRUFZQztBQUtELG9EQUVDO0FBTUQsd0JBVUM7QUFhRCxvQ0E2QkM7QUFLRCxrREFXQztBQTlJRCxxRUFJa0M7QUFFbEM7O0dBRUc7QUFDVSxRQUFBLDJCQUEyQixHQUFHLE9BQU8sQ0FBQztBQUVuRDs7R0FFRztBQUNILElBQVkscUJBTVg7QUFORCxXQUFZLHFCQUFxQjtJQUMvQix1R0FBOEIsQ0FBQTtJQUM5QiwrR0FBa0MsQ0FBQTtJQUNsQyx5RkFBdUIsQ0FBQTtJQUN2Qiw2RkFBeUIsQ0FBQTtJQUN6Qix1SEFBc0MsQ0FBQTtBQUN4QyxDQUFDLEVBTlcscUJBQXFCLHFDQUFyQixxQkFBcUIsUUFNaEM7QUFFRDs7O0dBR0c7QUFDSCxTQUFnQiw4QkFBOEIsQ0FDNUMsS0FBZ0IsRUFDaEIsU0FBZ0M7SUFFaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDbEMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBQ0QsT0FBTyxJQUFBLG9FQUEyQyxFQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztBQUN2RSxDQUFDO0FBRUQsU0FBZ0IsK0JBQStCLENBQzdDLE1BQWtCLEVBQ2xCLFNBQWdDO0lBRWhDLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQ25DLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUNELE9BQU8sSUFBQSxvRUFBMkMsRUFBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDeEUsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQUMsS0FBZ0I7SUFDekQsSUFBSSxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxD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LENBQUksSUFBVSxFQUFFLEVBQVcsRUFBRSxNQUFNLEdBQUcsSUFBSTtJQUMzRSxNQUFNLFNBQVMsR0FBSSxJQUFZLENBQUMsT0FBTyxDQUFDLHVCQUF1QixDQUFDO0lBQ2hFLE1BQU0sYUFBYSxHQUFJLElBQVksQ0FBQyxPQUFPLENBQUMsNEJBQTRCLENBQUM7SUFDeEUsSUFBWSxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsR0FBRyxNQUFNLENBQUM7SUFDdEQsSUFBWSxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUM3RCxJQUFJLENBQUM7UUFDSCxPQUFPLEVBQUUsRUFBRSxDQUFDO0lBQ2QsQ0FBQztZQUFTLENBQUM7UUFDUixJQUFZLENBQUMsT0FBTyxDQUFDLHVCQUF1QixHQUFHLFNBQVMsQ0FBQztRQUN6RCxJQUFZLENBQUMsT0FBTyxDQUFDLDRCQUE0QixHQUFHLGFBQWEsQ0FBQztJQUNyRSxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBzYnRJbnB1dCwgUHNidE91dHB1dCB9IGZyb20gJ2JpcDE3NC9zcmMvbGliL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgUHNidCB9IGZyb20gJ2JpdGNvaW5qcy1saWIvc3JjL3BzYnQnO1xuXG5pbXBvcnQge1xuICBnZXRQcm9wcmlldGFyeUtleVZhbHVlc0Zyb21Vbmtub3duS2V5VmFsdWVzLFxuICBQcm9wcmlldGFyeUtleVNlYXJjaCxcbiAgUHJvcHJpZXRhcnlLZXlWYWx1ZSxcbn0gZnJvbSAnLi9Qcm9wcmlldGFyeUtleVZhbFV0aWxzJztcblxuLyoqXG4gKiBiaXRnbyBwcm9wcmlldGFyeSBrZXkgaWRlbnRpZmllclxuICovXG5leHBvcnQgY29uc3QgUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSID0gJ0JJVEdPJztcblxuLyoqXG4gKiBzdWJ0eXBlIGZvciBwcm9wcmlldGFyeSBrZXlzIHRoYXQgYml0Z28gdXNlc1xuICovXG5leHBvcnQgZW51bSBQcm9wcmlldGFyeUtleVN1YnR5cGUge1xuICBaRUNfQ09OU0VOU1VTX0JSQU5DSF9JRCA9IDB4MDAsXG4gIE1VU0lHMl9QQVJUSUNJUEFOVF9QVUJfS0VZUyA9IDB4MDEsXG4gIE1VU0lHMl9QVUJfTk9OQ0UgPSAweDAyLFxuICBNVVNJRzJfUEFSVElBTF9TSUcgPSAweDAzLFxuICBQQVlHT19BRERSRVNTX0FUVEVTVEFUSU9OX1BST09GID0gMHgwNCxcbn1cblxuLyoqXG4gKiBTZWFyY2ggYW55IGRhdGEgZnJvbSBwc2J0IHByb3ByaWV0YXJ5IGtleSB2YWx1ZSBhZ2FpbnN0IGtleWRhdGEuXG4gKiBEZWZhdWx0IGlkZW50aWZpZXJFbmNvZGluZyBpcyB1dGYtOCBmb3IgaWRlbnRpZmllci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFBzYnRJbnB1dFByb3ByaWV0YXJ5S2V5VmFscyhcbiAgaW5wdXQ6IFBzYnRJbnB1dCxcbiAga2V5U2VhcmNoPzogUHJvcHJpZXRhcnlLZXlTZWFyY2hcbik6IFByb3ByaWV0YXJ5S2V5VmFsdWVbXSB7XG4gIGlmICghaW5wdXQudW5rbm93bktleVZhbHM/Lmxlbmd0aCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICByZXR1cm4gZ2V0UHJvcHJpZXRhcnlLZXlWYWx1ZXNGcm9tVW5rbm93bktleVZhbHVlcyhpbnB1dCwga2V5U2VhcmNoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFBzYnRPdXRwdXRQcm9wcmlldGFyeUtleVZhbHMoXG4gIG91dHB1dDogUHNidE91dHB1dCxcbiAga2V5U2VhcmNoPzogUHJvcHJpZXRhcnlLZXlTZWFyY2hcbik6IFByb3ByaWV0YXJ5S2V5VmFsdWVbXSB7XG4gIGlmICghb3V0cHV0LnVua25vd25LZXlWYWxzPy5sZW5ndGgpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIGdldFByb3ByaWV0YXJ5S2V5VmFsdWVzRnJvbVVua25vd25LZXlWYWx1ZXMob3V0cHV0LCBrZXlTZWFyY2gpO1xufVxuXG4vKipcbiAqIEByZXR1cm4gcGFydGlhbFNpZy90YXBTY3JpcHRTaWcvTVVTSUcyX1BBUlRJQUxfU0lHIGNvdW50IGlmZiBpbnB1dCBpcyBub3QgZmluYWxpemVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQc2J0SW5wdXRTaWduYXR1cmVDb3VudChpbnB1dDogUHNidElucHV0KTogbnVtYmVyIHtcbiAgaWYgKGlzUHNidElucHV0RmluYWxpemVkKGlucHV0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgaXMgYWxyZWFkeSBmaW5hbGl6ZWQnKTtcbiAgfVxuICByZXR1cm4gTWF0aC5tYXgoXG4gICAgQXJyYXkuaXNBcnJheShpbnB1dC5wYXJ0aWFsU2lnKSA/IGlucHV0LnBhcnRpYWxTaWcubGVuZ3RoIDogMCxcbiAgICBBcnJheS5pc0FycmF5KGlucHV0LnRhcFNjcmlwdFNpZykgPyBpbnB1dC50YXBTY3JpcHRTaWcubGVuZ3RoIDogMCxcbiAgICBnZXRQc2J0SW5wdXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXQsIHtcbiAgICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICAgIHN1YnR5cGU6IFByb3ByaWV0YXJ5S2V5U3VidHlwZS5NVVNJRzJfUEFSVElBTF9TSUcsXG4gICAgfSkubGVuZ3RoXG4gICk7XG59XG5cbi8qKlxuICogQHJldHVybiB0cnVlIGlmZiBQU0JUIGlucHV0IGlzIGZpbmFsaXplZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQc2J0SW5wdXRGaW5hbGl6ZWQoaW5wdXQ6IFBzYnRJbnB1dCk6IGJvb2xlYW4ge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKGlucHV0LmZpbmFsU2NyaXB0U2lnKSB8fCBCdWZmZXIuaXNCdWZmZXIoaW5wdXQuZmluYWxTY3JpcHRXaXRuZXNzKTtcbn1cblxuLyoqXG4gKiBAcmV0dXJuIHRydWUgaWZmIGRhdGEgc3RhcnRzIHdpdGggbWFnaWMgUFNCVCBieXRlIHNlcXVlbmNlXG4gKiBAcGFyYW0gZGF0YSBieXRlIGFycmF5IG9yIGhleCBzdHJpbmdcbiAqICovXG5leHBvcnQgZnVuY3Rpb24gaXNQc2J0KGRhdGE6IEJ1ZmZlciB8IHN0cmluZyk6IGJvb2xlYW4ge1xuICAvLyBodHRwczovL2dpdGh1Yi5jb20vYml0Y29pbi9iaXBzL2Jsb2IvbWFzdGVyL2JpcC0wMTc0Lm1lZGlhd2lraSNzcGVjaWZpY2F0aW9uXG4gIC8vIDB4NzA3MzYyNzQgLSBBU0NJSSBmb3IgJ3BzYnQnLiAweGZmIC0gc2VwYXJhdG9yXG4gIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAoZGF0YS5sZW5ndGggPCAxMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBkYXRhID0gQnVmZmVyLmZyb20oZGF0YS5zbGljZSgwLCAxMCksICdoZXgnKTtcbiAgfVxuICByZXR1cm4gNSA8PSBkYXRhLmxlbmd0aCAmJiBkYXRhLnJlYWRVSW50MzJCRSgwKSA9PT0gMHg3MDczNjI3NCAmJiBkYXRhLnJlYWRVSW50OCg0KSA9PT0gMHhmZjtcbn1cblxuLyoqXG4gKiBGaXJzdCBjaGVja3MgaWYgdGhlIGlucHV0IGlzIGFscmVhZHkgYSBidWZmZXIgdGhhdCBzdGFydHMgd2l0aCB0aGUgbWFnaWMgUFNCVCBieXRlIHNlcXVlbmNlLlxuICogSWYgbm90LCBpdCBjaGVja3MgaWYgdGhlIGlucHV0IGlzIGEgYmFzZTY0LSBvciBoZXgtZW5jb2RlZCBzdHJpbmcgdGhhdCBzdGFydHMgd2l0aCBQU0JUIGhlYWRlci5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWZ1bCB3aGVuIHJlYWRpbmcgYSBmaWxlIHRoYXQgY291bGQgYmUgaW4gYW55IG9mIHRoZSBhYm92ZSBmb3JtYXRzIG9yIHdoZW5cbiAqIGRlYWxpbmcgd2l0aCBhIHJlcXVlc3QgdGhhdCBjb3VsZCBjb250YWluIGEgaGV4IG9yIGJhc2U2NCBlbmNvZGVkIFBTQlQuXG4gKlxuICogQHBhcmFtIGRhdGFcbiAqIEByZXR1cm4gYnVmZmVyIHRoYXQgc3RhcnRzIHdpdGggdGhlIG1hZ2ljIFBTQlQgYnl0ZSBzZXF1ZW5jZVxuICogQHRocm93cyBFcnJvciB3aGVuIGNvbnZlcnNpb24gaXMgbm90IHBvc3NpYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1BzYnRCdWZmZXIoZGF0YTogQnVmZmVyIHwgc3RyaW5nKTogQnVmZmVyIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihkYXRhKSkge1xuICAgIC8vIHdlIGFyZSBkZWFsaW5nIHdpdGggYSBidWZmZXIgdGhhdCBsb29rcyBsaWtlIGEgcHNidCBhbHJlYWR5XG4gICAgaWYgKGlzUHNidChkYXRhKSkge1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgLy8gd2UgY291bGQgYmUgZGVhbGluZyB3aXRoIGEgYnVmZmVyIHRoYXQgY291bGQgYmUgYSBoZXggb3IgYmFzZTY0IGVuY29kZWQgcHNidFxuICAgIGRhdGEgPSBkYXRhLnRvU3RyaW5nKCdhc2NpaScpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGVuY29kaW5ncyA9IFsnaGV4JywgJ2Jhc2U2NCddIGFzIGNvbnN0O1xuICAgIGZvciAoY29uc3QgZW5jb2Rpbmcgb2YgZW5jb2RpbmdzKSB7XG4gICAgICBsZXQgYnVmZmVyOiBCdWZmZXI7XG4gICAgICB0cnkge1xuICAgICAgICBidWZmZXIgPSBCdWZmZXIuZnJvbShkYXRhLCBlbmNvZGluZyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGlzUHNidChidWZmZXIpKSB7XG4gICAgICAgIHJldHVybiBidWZmZXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBkYXRhIGlzIG5vdCBpbiBhbnkgb2YgdGhlIGZvbGxvd2luZyBmb3JtYXRzOiAke2VuY29kaW5ncy5qb2luKCcsICcpfWApO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdkYXRhIG11c3QgYmUgYSBidWZmZXIgb3IgYSBzdHJpbmcnKTtcbn1cblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGFsbG93cyBzaWduaW5nIG9yIHZhbGlkYXRpbmcgYSBwc2J0IHdpdGggbm9uLXNlZ3dpdCBpbnB1dHMgdGhvc2UgZG8gbm90IGNvbnRhaW4gbm9uV2l0bmVzc1V0eG8uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aXRoVW5zYWZlTm9uU2Vnd2l0PFQ+KHBzYnQ6IFBzYnQsIGZuOiAoKSA9PiBULCB1bnNhZmUgPSB0cnVlKTogVCB7XG4gIGNvbnN0IHByZXZWYWx1ZSA9IChwc2J0IGFzIGFueSkuX19DQUNIRS5fX1VOU0FGRV9TSUdOX05PTlNFR1dJVDtcbiAgY29uc3QgcHJldlZhbHVlV2FybiA9IChwc2J0IGFzIGFueSkuX19DQUNIRS5fX1dBUk5fVU5TQUZFX1NJR05fTk9OU0VHV0lUO1xuICAocHNidCBhcyBhbnkpLl9fQ0FDSEUuX19VTlNBRkVfU0lHTl9OT05TRUdXSVQgPSB1bnNhZmU7XG4gIChwc2J0IGFzIGFueSkuX19DQUNIRS5fX1dBUk5fVU5TQUZFX1NJR05fTk9OU0VHV0lUID0gIXVuc2FmZTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZm4oKTtcbiAgfSBmaW5hbGx5IHtcbiAgICAocHNidCBhcyBhbnkpLl9fQ0FDSEUuX19VTlNBRkVfU0lHTl9OT05TRUdXSVQgPSBwcmV2VmFsdWU7XG4gICAgKHBzYnQgYXMgYW55KS5fX0NBQ0hFLl9fV0FSTl9VTlNBRkVfU0lHTl9OT05TRUdXSVQgPSBwcmV2VmFsdWVXYXJuO1xuICB9XG59XG4iXX0=