UNPKG

@bitgo-beta/utxo-lib

Version:

Client-side Bitcoin JavaScript library

404 lines (401 loc) • 40.6 kB
"use strict"; /* The values for the various fork coins can be found in these files: property filename varname notes ------------------------------------------------------------------------------------------------------------------------ messagePrefix src/validation.cpp strMessageMagic Format `${CoinName} Signed Message` bech32_hrp src/chainparams.cpp bech32_hrp Only for some networks bip32.public src/chainparams.cpp base58Prefixes[EXT_PUBLIC_KEY] Mainnets have same value, testnets have same value bip32.private src/chainparams.cpp base58Prefixes[EXT_SECRET_KEY] Mainnets have same value, testnets have same value pubKeyHash src/chainparams.cpp base58Prefixes[PUBKEY_ADDRESS] scriptHash src/chainparams.cpp base58Prefixes[SCRIPT_ADDRESS] wif src/chainparams.cpp base58Prefixes[SECRET_KEY] Testnets have same value forkId src/script/interpreter.h FORKID_* */ Object.defineProperty(exports, "__esModule", { value: true }); exports.supportsTaproot = exports.supportsSegwit = exports.isValidNetwork = exports.isZcash = exports.isLitecoin = exports.isDogecoin = exports.isDash = exports.isBitcoinSV = exports.isBitcoinGold = exports.isBitcoinCash = exports.isBitcoin = exports.getTestnet = exports.isSameCoin = exports.isTestnet = exports.isMainnet = exports.getMainnet = exports.getNetworkName = exports.getNetworkList = exports.networks = void 0; /** * @deprecated */ const coins = { BCH: 'bch', BSV: 'bsv', BTC: 'btc', BTG: 'btg', LTC: 'ltc', ZEC: 'zec', DASH: 'dash', DOGE: 'doge', }; function getDefaultBip32Mainnet() { return { // base58 'xpub' public: 0x0488b21e, // base58 'xprv' private: 0x0488ade4, }; } function getDefaultBip32Testnet() { return { // base58 'tpub' public: 0x043587cf, // base58 'tprv' private: 0x04358394, }; } exports.networks = { // https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp // https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.cpp bitcoin: { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'bc', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x00, scriptHash: 0x05, wif: 0x80, coin: coins.BTC, }, testnet: { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'tb', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x6f, scriptHash: 0xc4, wif: 0xef, coin: coins.BTC, }, // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/src/validation.cpp // https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/src/chainparams.cpp // https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md bitcoincash: { messagePrefix: '\x18Bitcoin Signed Message:\n', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x00, scriptHash: 0x05, wif: 0x80, coin: coins.BCH, forkId: 0x00, cashAddr: { prefix: 'bitcoincash', pubKeyHash: 0x00, scriptHash: 0x08, }, }, bitcoincashTestnet: { messagePrefix: '\x18Bitcoin Signed Message:\n', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x6f, scriptHash: 0xc4, wif: 0xef, coin: coins.BCH, cashAddr: { prefix: 'bchtest', pubKeyHash: 0x00, scriptHash: 0x08, }, }, // https://github.com/BTCGPU/BTCGPU/blob/master/src/validation.cpp // https://github.com/BTCGPU/BTCGPU/blob/master/src/chainparams.cpp // https://github.com/BTCGPU/BTCGPU/blob/master/src/script/interpreter.h bitcoingold: { messagePrefix: '\x18Bitcoin Gold Signed Message:\n', bech32: 'btg', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x26, scriptHash: 0x17, wif: 0x80, forkId: 79, coin: coins.BTG, }, bitcoingoldTestnet: { messagePrefix: '\x18Bitcoin Gold Signed Message:\n', bech32: 'tbtg', bip32: getDefaultBip32Testnet(), pubKeyHash: 111, scriptHash: 196, wif: 0xef, forkId: 79, coin: coins.BTG, }, // https://github.com/bitcoin-sv/bitcoin-sv/blob/master/src/validation.cpp // https://github.com/bitcoin-sv/bitcoin-sv/blob/master/src/chainparams.cpp bitcoinsv: { messagePrefix: '\x18Bitcoin Signed Message:\n', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x00, scriptHash: 0x05, wif: 0x80, coin: coins.BSV, forkId: 0x00, }, bitcoinsvTestnet: { messagePrefix: '\x18Bitcoin Signed Message:\n', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x6f, scriptHash: 0xc4, wif: 0xef, coin: coins.BSV, forkId: 0x00, }, // https://github.com/dashpay/dash/blob/master/src/validation.cpp // https://github.com/dashpay/dash/blob/master/src/chainparams.cpp dash: { messagePrefix: '\x19DarkCoin Signed Message:\n', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x4c, scriptHash: 0x10, wif: 0xcc, coin: coins.DASH, }, dashTest: { messagePrefix: '\x19DarkCoin Signed Message:\n', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x8c, scriptHash: 0x13, wif: 0xef, coin: coins.DASH, }, // https://github.com/dogecoin/dogecoin/blob/master/src/validation.cpp // https://github.com/dogecoin/dogecoin/blob/master/src/chainparams.cpp // Mainnet bip32 here does not match dogecoin core, this is intended (see BG-53241) dogecoin: { messagePrefix: '\x19Dogecoin Signed Message:\n', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x1e, scriptHash: 0x16, wif: 0x9e, coin: coins.DOGE, }, dogecoinTest: { messagePrefix: '\x19Dogecoin Signed Message:\n', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x71, scriptHash: 0xc4, wif: 0xf1, coin: coins.DOGE, }, // https://github.com/litecoin-project/litecoin/blob/master/src/validation.cpp // https://github.com/litecoin-project/litecoin/blob/master/src/chainparams.cpp litecoin: { messagePrefix: '\x19Litecoin Signed Message:\n', bech32: 'ltc', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x30, scriptHash: 0x32, wif: 0xb0, coin: coins.LTC, }, litecoinTest: { messagePrefix: '\x19Litecoin Signed Message:\n', bech32: 'tltc', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x6f, scriptHash: 0x3a, wif: 0xef, coin: coins.LTC, }, // https://github.com/zcash/zcash/blob/master/src/validation.cpp // https://github.com/zcash/zcash/blob/master/src/chainparams.cpp zcash: { messagePrefix: '\x18ZCash Signed Message:\n', bip32: getDefaultBip32Mainnet(), pubKeyHash: 0x1cb8, scriptHash: 0x1cbd, wif: 0x80, coin: coins.ZEC, }, zcashTest: { messagePrefix: '\x18ZCash Signed Message:\n', bip32: getDefaultBip32Testnet(), pubKeyHash: 0x1d25, scriptHash: 0x1cba, wif: 0xef, coin: coins.ZEC, }, }; /** * @returns {Network[]} all known networks as array */ function getNetworkList() { return Object.values(exports.networks); } exports.getNetworkList = getNetworkList; /** * @param {Network} network * @returns {string} the name of the network. Returns undefined if network is not a value * of `networks` */ function getNetworkName(network) { return Object.keys(exports.networks).find((n) => exports.networks[n] === network); } exports.getNetworkName = getNetworkName; /** * @param {Network} network * @returns {Object} the mainnet corresponding to a testnet */ function getMainnet(network) { switch (network) { case exports.networks.bitcoin: case exports.networks.testnet: return exports.networks.bitcoin; case exports.networks.bitcoincash: case exports.networks.bitcoincashTestnet: return exports.networks.bitcoincash; case exports.networks.bitcoingold: case exports.networks.bitcoingoldTestnet: return exports.networks.bitcoingold; case exports.networks.bitcoinsv: case exports.networks.bitcoinsvTestnet: return exports.networks.bitcoinsv; case exports.networks.dash: case exports.networks.dashTest: return exports.networks.dash; case exports.networks.litecoin: case exports.networks.litecoinTest: return exports.networks.litecoin; case exports.networks.zcash: case exports.networks.zcashTest: return exports.networks.zcash; case exports.networks.dogecoin: case exports.networks.dogecoinTest: return exports.networks.dogecoin; } throw new TypeError(`invalid network`); } exports.getMainnet = getMainnet; /** * @param {Network} network * @returns {boolean} true iff network is a mainnet */ function isMainnet(network) { return getMainnet(network) === network; } exports.isMainnet = isMainnet; /** * @param {Network} network * @returns {boolean} true iff network is a testnet */ function isTestnet(network) { return getMainnet(network) !== network; } exports.isTestnet = isTestnet; /** * * @param {Network} network * @param {Network} otherNetwork * @returns {boolean} true iff both networks are for the same coin */ function isSameCoin(network, otherNetwork) { return getMainnet(network) === getMainnet(otherNetwork); } exports.isSameCoin = isSameCoin; const mainnets = getNetworkList().filter(isMainnet); const testnets = getNetworkList().filter(isTestnet); /** * Map where keys are mainnet networks and values are testnet networks * @type {Map<Network, Network[]>} */ const mainnetTestnetPairs = new Map(mainnets.map((m) => [m, testnets.filter((t) => getMainnet(t) === m)])); /** * @param {Network} network * @returns {Network|undefined} - The testnet corresponding to a mainnet. * Returns undefined if a network has no testnet. */ function getTestnet(network) { if (isTestnet(network)) { return network; } const testnets = mainnetTestnetPairs.get(network); if (testnets === undefined) { throw new Error(`invalid argument`); } if (testnets.length === 0) { return; } if (testnets.length === 1) { return testnets[0]; } throw new Error(`more than one testnet for ${getNetworkName(network)}`); } exports.getTestnet = getTestnet; /** * @param {Network} network * @returns {boolean} true iff network bitcoin or testnet */ function isBitcoin(network) { return getMainnet(network) === exports.networks.bitcoin; } exports.isBitcoin = isBitcoin; /** * @param {Network} network * @returns {boolean} true iff network is bitcoincash or bitcoincashTestnet */ function isBitcoinCash(network) { return getMainnet(network) === exports.networks.bitcoincash; } exports.isBitcoinCash = isBitcoinCash; /** * @param {Network} network * @returns {boolean} true iff network is bitcoingold */ function isBitcoinGold(network) { return getMainnet(network) === exports.networks.bitcoingold; } exports.isBitcoinGold = isBitcoinGold; /** * @param {Network} network * @returns {boolean} true iff network is bitcoinsv or bitcoinsvTestnet */ function isBitcoinSV(network) { return getMainnet(network) === exports.networks.bitcoinsv; } exports.isBitcoinSV = isBitcoinSV; /** * @param {Network} network * @returns {boolean} true iff network is dash or dashTest */ function isDash(network) { return getMainnet(network) === exports.networks.dash; } exports.isDash = isDash; /** * @param {Network} network * @returns {boolean} true iff network is dogecoin or dogecoinTest */ function isDogecoin(network) { return getMainnet(network) === exports.networks.dogecoin; } exports.isDogecoin = isDogecoin; /** * @param {Network} network * @returns {boolean} true iff network is litecoin or litecoinTest */ function isLitecoin(network) { return getMainnet(network) === exports.networks.litecoin; } exports.isLitecoin = isLitecoin; /** * @param {Network} network * @returns {boolean} true iff network is zcash or zcashTest */ function isZcash(network) { return getMainnet(network) === exports.networks.zcash; } exports.isZcash = isZcash; /** * @param {unknown} network * @returns {boolean} returns true iff network is any of the network stated in the argument */ function isValidNetwork(network) { return getNetworkList().includes(network); } exports.isValidNetwork = isValidNetwork; function supportsSegwit(network) { return [exports.networks.bitcoin, exports.networks.litecoin, exports.networks.bitcoingold].includes(getMainnet(network)); } exports.supportsSegwit = supportsSegwit; function supportsTaproot(network) { return getMainnet(network) === exports.networks.bitcoin; } exports.supportsTaproot = supportsTaproot; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmV0d29ya3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7RUFlRTs7O0FBRUY7O0dBRUc7QUFDSCxNQUFNLEtBQUssR0FBRztJQUNaLEdBQUcsRUFBRSxLQUFLO0lBQ1YsR0FBRyxFQUFFLEtBQUs7SUFDVixHQUFHLEVBQUUsS0FBSztJQUNWLEdBQUcsRUFBRSxLQUFLO0lBQ1YsR0FBRyxFQUFFLEtBQUs7SUFDVixHQUFHLEVBQUUsS0FBSztJQUNWLElBQUksRUFBRSxNQUFNO0lBQ1osSUFBSSxFQUFFLE1BQU07Q0FDSixDQUFDO0FBMENYLFNBQVMsc0JBQXNCO0lBQzdCLE9BQU87UUFDTCxnQkFBZ0I7UUFDaEIsTUFBTSxFQUFFLFVBQVU7UUFDbEIsZ0JBQWdCO1FBQ2hCLE9BQU8sRUFBRSxVQUFVO0tBQ3BCLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxzQkFBc0I7SUFDN0IsT0FBTztRQUNMLGdCQUFnQjtRQUNoQixNQUFNLEVBQUUsVUFBVTtRQUNsQixnQkFBZ0I7UUFDaEIsT0FBTyxFQUFFLFVBQVU7S0FDcEIsQ0FBQztBQUNKLENBQUM7QUFFWSxRQUFBLFFBQVEsR0FBaUM7SUFDcEQsb0VBQW9FO0lBQ3BFLHFFQUFxRTtJQUNyRSxPQUFPLEVBQUU7UUFDUCxhQUFhLEVBQUUsK0JBQStCO1FBQzlDLE1BQU0sRUFBRSxJQUFJO1FBQ1osS0FBSyxFQUFFLHNCQUFzQixFQUFFO1FBQy9CLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLEdBQUcsRUFBRSxJQUFJO1FBQ1QsSUFBSSxFQUFFLEtBQUssQ0FBQyxHQUFHO0tBQ2hCO0lBQ0QsT0FBTyxFQUFFO1FBQ1AsYUFBYSxFQUFFLCtCQUErQjtRQUM5QyxNQUFNLEVBQUUsSUFBSTtRQUNaLEtBQUssRUFBRSxzQkFBc0IsRUFBRTtRQUMvQixVQUFVLEVB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QUM7QUFGRCx3Q0FFQztBQUVELFNBQWdCLGNBQWMsQ0FBQyxPQUFnQjtJQUM3QyxPQUFRLENBQUMsZ0JBQVEsQ0FBQyxPQUFPLEVBQUUsZ0JBQVEsQ0FBQyxRQUFRLEVBQUUsZ0JBQVEsQ0FBQyxXQUFXLENBQWUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDbEgsQ0FBQztBQUZELHdDQUVDO0FBRUQsU0FBZ0IsZUFBZSxDQUFDLE9BQWdCO0lBQzlDLE9BQU8sVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLGdCQUFRLENBQUMsT0FBTyxDQUFDO0FBQ2xELENBQUM7QUFGRCwwQ0FFQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5cblRoZSB2YWx1ZXMgZm9yIHRoZSB2YXJpb3VzIGZvcmsgY29pbnMgY2FuIGJlIGZvdW5kIGluIHRoZXNlIGZpbGVzOlxuXG5wcm9wZXJ0eSAgICAgICBmaWxlbmFtZSAgICAgICAgICAgICAgICAgIHZhcm5hbWUgICAgICAgICAgICAgICAgICAgICAgICAgICBub3Rlc1xuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5tZXNzYWdlUHJlZml4ICBzcmMvdmFsaWRhdGlvbi5jcHAgICAgICAgIHN0ck1lc3NhZ2VNYWdpYyAgICAgICAgICAgICAgICAgICBGb3JtYXQgYCR7Q29pbk5hbWV9IFNpZ25lZCBNZXNzYWdlYFxuYmVjaDMyX2hycCAgICAgc3JjL2NoYWlucGFyYW1zLmNwcCAgICAgICBiZWNoMzJfaHJwICAgICAgICAgICAgICAgICAgICAgICAgT25seSBmb3Igc29tZSBuZXR3b3Jrc1xuYmlwMzIucHVibGljICAgc3JjL2NoYWlucGFyYW1zLmNwcCAgICAgICBiYXNlNThQcmVmaXhlc1tFWFRfUFVCTElDX0tFWV0gICAgTWFpbm5ldHMgaGF2ZSBzYW1lIHZhbHVlLCB0ZXN0bmV0cyBoYXZlIHNhbWUgdmFsdWVcbmJpcDMyLnByaXZhdGUgIHNyYy9jaGFpbnBhcmFtcy5jcHAgICAgICAgYmFzZTU4UHJlZml4ZXNbRVhUX1NFQ1JFVF9LRVldICAgIE1haW5uZXRzIGhhdmUgc2FtZSB2YWx1ZSwgdGVzdG5ldHMgaGF2ZSBzYW1lIHZhbHVlXG5wdWJLZXlIYXNoICAgICBzcmMvY2hhaW5wYXJhbXMuY3BwICAgICAgIGJhc2U1OFByZWZpeGVzW1BVQktFWV9BRERSRVNTXVxuc2NyaXB0SGFzaCAgICAgc3JjL2NoYWlucGFyYW1zLmNwcCAgICAgICBiYXNlNThQcmVmaXhlc1tTQ1JJUFRfQUREUkVTU11cbndpZiAgICAgICAgICAgIHNyYy9jaGFpbnBhcmFtcy5jcHAgICAgICAgYmFzZTU4UHJlZml4ZXNbU0VDUkVUX0tFWV0gICAgICAgIFRlc3RuZXRzIGhhdmUgc2FtZSB2YWx1ZVxuZm9ya0lkICAgICAgICAgc3JjL3NjcmlwdC9pbnRlcnByZXRlci5oICBGT1JLSURfKlxuXG4qL1xuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKi9cbmNvbnN0IGNvaW5zID0ge1xuICBCQ0g6ICdiY2gnLFxuICBCU1Y6ICdic3YnLFxuICBCVEM6ICdidGMnLFxuICBCVEc6ICdidGcnLFxuICBMVEM6ICdsdGMnLFxuICBaRUM6ICd6ZWMnLFxuICBEQVNIOiAnZGFzaCcsXG4gIERPR0U6ICdkb2dlJyxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIE5ldHdvcmtOYW1lID1cbiAgfCAnYml0Y29pbidcbiAgfCAndGVzdG5ldCdcbiAgfCAnYml0Y29pbmNhc2gnXG4gIHwgJ2JpdGNvaW5jYXNoVGVzdG5ldCdcbiAgfCAnYml0Y29pbmdvbGQnXG4gIHwgJ2JpdGNvaW5nb2xkVGVzdG5ldCdcbiAgfCAnYml0Y29pbnN2J1xuICB8ICdiaXRjb2luc3ZUZXN0bmV0J1xuICB8ICdkYXNoJ1xuICB8ICdkYXNoVGVzdCdcbiAgfCAnZG9nZWNvaW4nXG4gIHwgJ2RvZ2Vjb2luVGVzdCdcbiAgfCAnbGl0ZWNvaW4nXG4gIHwgJ2xpdGVjb2luVGVzdCdcbiAgfCAnemNhc2gnXG4gIHwgJ3pjYXNoVGVzdCc7XG5cbmV4cG9ydCB0eXBlIE5ldHdvcmsgPSB7XG4gIG1lc3NhZ2VQcmVmaXg6IHN0cmluZztcbiAgcHViS2V5SGFzaDogbnVtYmVyO1xuICBzY3JpcHRIYXNoOiBudW1iZXI7XG4gIHdpZjogbnVtYmVyO1xuICBiaXAzMjoge1xuICAgIHB1YmxpYzogbnVtYmVyO1xuICAgIHByaXZhdGU6IG51bWJlcjtcbiAgfTtcbiAgY2FzaEFkZHI/OiB7XG4gICAgcHJlZml4OiBzdHJpbmc7XG4gICAgcHViS2V5SGFzaDogbnVtYmVyO1xuICAgIHNjcmlwdEhhc2g6IG51bWJlcjtcbiAgfTtcbiAgYmVjaDMyPzogc3RyaW5nO1xuICBmb3JrSWQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZFxuICAgKi9cbiAgY29pbjogc3RyaW5nO1xufTtcblxuZnVuY3Rpb24gZ2V0RGVmYXVsdEJpcDMyTWFpbm5ldCgpIHtcbiAgcmV0dXJuIHtcbiAgICAvLyBiYXNlNTggJ3hwdWInXG4gICAgcHVibGljOiAweDA0ODhiMjFlLFxuICAgIC8vIGJhc2U1OCAneHBydidcbiAgICBwcml2YXRlOiAweDA0ODhhZGU0LFxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXREZWZhdWx0QmlwMzJUZXN0bmV0KCkge1xuICByZXR1cm4ge1xuICAgIC8vIGJhc2U1OCAndHB1YidcbiAgICBwdWJsaWM6IDB4MDQzNTg3Y2YsXG4gICAgLy8gYmFzZTU4ICd0cHJ2J1xuICAgIHByaXZhdGU6IDB4MDQzNTgzOTQsXG4gIH07XG59XG5cbmV4cG9ydCBjb25zdCBuZXR3b3JrczogUmVjb3JkPE5ldHdvcmtOYW1lLCBOZXR3b3JrPiA9IHtcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2JpdGNvaW4vYml0Y29pbi9ibG9iL21hc3Rlci9zcmMvdmFsaWRhdGlvbi5jcHBcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2JpdGNvaW4vYml0Y29pbi9ibG9iL21hc3Rlci9zcmMvY2hhaW5wYXJhbXMuY3BwXG4gIGJpdGNvaW46IHtcbiAgICBtZXNzYWdlUHJlZml4OiAnXFx4MThCaXRjb2luIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmVjaDMyOiAnYmMnLFxuICAgIGJpcDMyOiBnZXREZWZhdWx0QmlwMzJNYWlubmV0KCksXG4gICAgcHViS2V5SGFzaDogMHgwMCxcbiAgICBzY3JpcHRIYXNoOiAweDA1LFxuICAgIHdpZjogMHg4MCxcbiAgICBjb2luOiBjb2lucy5CVEMsXG4gIH0sXG4gIHRlc3RuZXQ6IHtcbiAgICBtZXNzYWdlUHJlZml4OiAnXFx4MThCaXRjb2luIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmVjaDMyOiAndGInLFxuICAgIGJpcDMyOiBnZXREZWZhdWx0QmlwMzJUZXN0bmV0KCksXG4gICAgcHViS2V5SGFzaDogMHg2ZixcbiAgICBzY3JpcHRIYXNoOiAweGM0LFxuICAgIHdpZjogMHhlZixcbiAgICBjb2luOiBjb2lucy5CVEMsXG4gIH0sXG5cbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL0JpdGNvaW4tQUJDL2JpdGNvaW4tYWJjL2Jsb2IvbWFzdGVyL3NyYy92YWxpZGF0aW9uLmNwcFxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vQml0Y29pbi1BQkMvYml0Y29pbi1hYmMvYmxvYi9tYXN0ZXIvc3JjL2NoYWlucGFyYW1zLmNwcFxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vYml0Y29pbmNhc2hvcmcvYml0Y29pbmNhc2gub3JnL2Jsb2IvbWFzdGVyL3NwZWMvY2FzaGFkZHIubWRcbiAgYml0Y29pbmNhc2g6IHtcbiAgICBtZXNzYWdlUHJlZml4OiAnXFx4MThCaXRjb2luIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmlwMzI6IGdldERlZmF1bHRCaXAzMk1haW5uZXQoKSxcbiAgICBwdWJLZXlIYXNoOiAweDAwLFxuICAgIHNjcmlwdEhhc2g6IDB4MDUsXG4gICAgd2lmOiAweDgwLFxuICAgIGNvaW46IGNvaW5zLkJDSCxcbiAgICBmb3JrSWQ6IDB4MDAsXG4gICAgY2FzaEFkZHI6IHtcbiAgICAgIHByZWZpeDogJ2JpdGNvaW5jYXNoJyxcbiAgICAgIHB1YktleUhhc2g6IDB4MDAsXG4gICAgICBzY3JpcHRIYXNoOiAweDA4LFxuICAgIH0sXG4gIH0sXG4gIGJpdGNvaW5jYXNoVGVzdG5ldDoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOEJpdGNvaW4gU2lnbmVkIE1lc3NhZ2U6XFxuJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyVGVzdG5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4NmYsXG4gICAgc2NyaXB0SGFzaDogMHhjNCxcbiAgICB3aWY6IDB4ZWYsXG4gICAgY29pbjogY29pbnMuQkNILFxuICAgIGNhc2hBZGRyOiB7XG4gICAgICBwcmVmaXg6ICdiY2h0ZXN0JyxcbiAgICAgIHB1YktleUhhc2g6IDB4MDAsXG4gICAgICBzY3JpcHRIYXNoOiAweDA4LFxuICAgIH0sXG4gIH0sXG5cbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL0JUQ0dQVS9CVENHUFUvYmxvYi9tYXN0ZXIvc3JjL3ZhbGlkYXRpb24uY3BwXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9CVENHUFUvQlRDR1BVL2Jsb2IvbWFzdGVyL3NyYy9jaGFpbnBhcmFtcy5jcHBcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL0JUQ0dQVS9CVENHUFUvYmxvYi9tYXN0ZXIvc3JjL3NjcmlwdC9pbnRlcnByZXRlci5oXG4gIGJpdGNvaW5nb2xkOiB7XG4gICAgbWVzc2FnZVByZWZpeDogJ1xceDE4Qml0Y29pbiBHb2xkIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmVjaDMyOiAnYnRnJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyTWFpbm5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4MjYsXG4gICAgc2NyaXB0SGFzaDogMHgxNyxcbiAgICB3aWY6IDB4ODAsXG4gICAgZm9ya0lkOiA3OSxcbiAgICBjb2luOiBjb2lucy5CVEcsXG4gIH0sXG4gIGJpdGNvaW5nb2xkVGVzdG5ldDoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOEJpdGNvaW4gR29sZCBTaWduZWQgTWVzc2FnZTpcXG4nLFxuICAgIGJlY2gzMjogJ3RidGcnLFxuICAgIGJpcDMyOiBnZXREZWZhdWx0QmlwMzJUZXN0bmV0KCksXG4gICAgcHViS2V5SGFzaDogMTExLFxuICAgIHNjcmlwdEhhc2g6IDE5NixcbiAgICB3aWY6IDB4ZWYsXG4gICAgZm9ya0lkOiA3OSxcbiAgICBjb2luOiBjb2lucy5CVEcsXG4gIH0sXG5cbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2JpdGNvaW4tc3YvYml0Y29pbi1zdi9ibG9iL21hc3Rlci9zcmMvdmFsaWRhdGlvbi5jcHBcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2JpdGNvaW4tc3YvYml0Y29pbi1zdi9ibG9iL21hc3Rlci9zcmMvY2hhaW5wYXJhbXMuY3BwXG4gIGJpdGNvaW5zdjoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOEJpdGNvaW4gU2lnbmVkIE1lc3NhZ2U6XFxuJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyTWFpbm5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4MDAsXG4gICAgc2NyaXB0SGFzaDogMHgwNSxcbiAgICB3aWY6IDB4ODAsXG4gICAgY29pbjogY29pbnMuQlNWLFxuICAgIGZvcmtJZDogMHgwMCxcbiAgfSxcbiAgYml0Y29pbnN2VGVzdG5ldDoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOEJpdGNvaW4gU2lnbmVkIE1lc3NhZ2U6XFxuJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyVGVzdG5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4NmYsXG4gICAgc2NyaXB0SGFzaDogMHhjNCxcbiAgICB3aWY6IDB4ZWYsXG4gICAgY29pbjogY29pbnMuQlNWLFxuICAgIGZvcmtJZDogMHgwMCxcbiAgfSxcblxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vZGFzaHBheS9kYXNoL2Jsb2IvbWFzdGVyL3NyYy92YWxpZGF0aW9uLmNwcFxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vZGFzaHBheS9kYXNoL2Jsb2IvbWFzdGVyL3NyYy9jaGFpbnBhcmFtcy5jcHBcbiAgZGFzaDoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOURhcmtDb2luIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmlwMzI6IGdldERlZmF1bHRCaXAzMk1haW5uZXQoKSxcbiAgICBwdWJLZXlIYXNoOiAweDRjLFxuICAgIHNjcmlwdEhhc2g6IDB4MTAsXG4gICAgd2lmOiAweGNjLFxuICAgIGNvaW46IGNvaW5zLkRBU0gsXG4gIH0sXG4gIGRhc2hUZXN0OiB7XG4gICAgbWVzc2FnZVByZWZpeDogJ1xceDE5RGFya0NvaW4gU2lnbmVkIE1lc3NhZ2U6XFxuJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyVGVzdG5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4OGMsXG4gICAgc2NyaXB0SGFzaDogMHgxMyxcbiAgICB3aWY6IDB4ZWYsXG4gICAgY29pbjogY29pbnMuREFTSCxcbiAgfSxcblxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vZG9nZWNvaW4vZG9nZWNvaW4vYmxvYi9tYXN0ZXIvc3JjL3ZhbGlkYXRpb24uY3BwXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9kb2dlY29pbi9kb2dlY29pbi9ibG9iL21hc3Rlci9zcmMvY2hhaW5wYXJhbXMuY3BwXG4gIC8vIE1haW5uZXQgYmlwMzIgaGVyZSBkb2VzIG5vdCBtYXRjaCBkb2dlY29pbiBjb3JlLCB0aGlzIGlzIGludGVuZGVkIChzZWUgQkctNTMyNDEpXG4gIGRvZ2Vjb2luOiB7XG4gICAgbWVzc2FnZVByZWZpeDogJ1xceDE5RG9nZWNvaW4gU2lnbmVkIE1lc3NhZ2U6XFxuJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyTWFpbm5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4MWUsXG4gICAgc2NyaXB0SGFzaDogMHgxNixcbiAgICB3aWY6IDB4OWUsXG4gICAgY29pbjogY29pbnMuRE9HRSxcbiAgfSxcbiAgZG9nZWNvaW5UZXN0OiB7XG4gICAgbWVzc2FnZVByZWZpeDogJ1xceDE5RG9nZWNvaW4gU2lnbmVkIE1lc3NhZ2U6XFxuJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyVGVzdG5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4NzEsXG4gICAgc2NyaXB0SGFzaDogMHhjNCxcbiAgICB3aWY6IDB4ZjEsXG4gICAgY29pbjogY29pbnMuRE9HRSxcbiAgfSxcblxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vbGl0ZWNvaW4tcHJvamVjdC9saXRlY29pbi9ibG9iL21hc3Rlci9zcmMvdmFsaWRhdGlvbi5jcHBcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2xpdGVjb2luLXByb2plY3QvbGl0ZWNvaW4vYmxvYi9tYXN0ZXIvc3JjL2NoYWlucGFyYW1zLmNwcFxuICBsaXRlY29pbjoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOUxpdGVjb2luIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmVjaDMyOiAnbHRjJyxcbiAgICBiaXAzMjogZ2V0RGVmYXVsdEJpcDMyTWFpbm5ldCgpLFxuICAgIHB1YktleUhhc2g6IDB4MzAsXG4gICAgc2NyaXB0SGFzaDogMHgzMixcbiAgICB3aWY6IDB4YjAsXG4gICAgY29pbjogY29pbnMuTFRDLFxuICB9LFxuICBsaXRlY29pblRlc3Q6IHtcbiAgICBtZXNzYWdlUHJlZml4OiAnXFx4MTlMaXRlY29pbiBTaWduZWQgTWVzc2FnZTpcXG4nLFxuICAgIGJlY2gzMjogJ3RsdGMnLFxuICAgIGJpcDMyOiBnZXREZWZhdWx0QmlwMzJUZXN0bmV0KCksXG4gICAgcHViS2V5SGFzaDogMHg2ZixcbiAgICBzY3JpcHRIYXNoOiAweDNhLFxuICAgIHdpZjogMHhlZixcbiAgICBjb2luOiBjb2lucy5MVEMsXG4gIH0sXG5cbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3pjYXNoL3pjYXNoL2Jsb2IvbWFzdGVyL3NyYy92YWxpZGF0aW9uLmNwcFxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vemNhc2gvemNhc2gvYmxvYi9tYXN0ZXIvc3JjL2NoYWlucGFyYW1zLmNwcFxuICB6Y2FzaDoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOFpDYXNoIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmlwMzI6IGdldERlZmF1bHRCaXAzMk1haW5uZXQoKSxcbiAgICBwdWJLZXlIYXNoOiAweDFjYjgsXG4gICAgc2NyaXB0SGFzaDogMHgxY2JkLFxuICAgIHdpZjogMHg4MCxcbiAgICBjb2luOiBjb2lucy5aRUMsXG4gIH0sXG4gIHpjYXNoVGVzdDoge1xuICAgIG1lc3NhZ2VQcmVmaXg6ICdcXHgxOFpDYXNoIFNpZ25lZCBNZXNzYWdlOlxcbicsXG4gICAgYmlwMzI6IGdldERlZmF1bHRCaXAzMlRlc3RuZXQoKSxcbiAgICBwdWJLZXlIYXNoOiAweDFkMjUsXG4gICAgc2NyaXB0SGFzaDogMHgxY2JhLFxuICAgIHdpZjogMHhlZixcbiAgICBjb2luOiBjb2lucy5aRUMsXG4gIH0sXG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHtOZXR3b3JrW119IGFsbCBrbm93biBuZXR3b3JrcyBhcyBhcnJheVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TmV0d29ya0xpc3QoKTogTmV0d29ya1tdIHtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXMobmV0d29ya3MpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHJldHVybnMge3N0cmluZ30gdGhlIG5hbWUgb2YgdGhlIG5ldHdvcmsuIFJldHVybnMgdW5kZWZpbmVkIGlmIG5ldHdvcmsgaXMgbm90IGEgdmFsdWVcbiAqICAgICAgICAgICAgICAgICAgIG9mIGBuZXR3b3Jrc2BcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE5ldHdvcmtOYW1lKG5ldHdvcms6IE5ldHdvcmspOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gT2JqZWN0LmtleXMobmV0d29ya3MpLmZpbmQoKG4pID0+IChuZXR3b3JrcyBhcyBSZWNvcmQ8c3RyaW5nLCBOZXR3b3JrPilbbl0gPT09IG5ldHdvcmspO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHJldHVybnMge09iamVjdH0gdGhlIG1haW5uZXQgY29ycmVzcG9uZGluZyB0byBhIHRlc3RuZXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1haW5uZXQobmV0d29yazogTmV0d29yayk6IE5ldHdvcmsge1xuICBzd2l0Y2ggKG5ldHdvcmspIHtcbiAgICBjYXNlIG5ldHdvcmtzLmJpdGNvaW46XG4gICAgY2FzZSBuZXR3b3Jrcy50ZXN0bmV0OlxuICAgICAgcmV0dXJuIG5ldHdvcmtzLmJpdGNvaW47XG5cbiAgICBjYXNlIG5ldHdvcmtzLmJpdGNvaW5jYXNoOlxuICAgIGNhc2UgbmV0d29ya3MuYml0Y29pbmNhc2hUZXN0bmV0OlxuICAgICAgcmV0dXJuIG5ldHdvcmtzLmJpdGNvaW5jYXNoO1xuXG4gICAgY2FzZSBuZXR3b3Jrcy5iaXRjb2luZ29sZDpcbiAgICBjYXNlIG5ldHdvcmtzLmJpdGNvaW5nb2xkVGVzdG5ldDpcbiAgICAgIHJldHVybiBuZXR3b3Jrcy5iaXRjb2luZ29sZDtcblxuICAgIGNhc2UgbmV0d29ya3MuYml0Y29pbnN2OlxuICAgIGNhc2UgbmV0d29ya3MuYml0Y29pbnN2VGVzdG5ldDpcbiAgICAgIHJldHVybiBuZXR3b3Jrcy5iaXRjb2luc3Y7XG5cbiAgICBjYXNlIG5ldHdvcmtzLmRhc2g6XG4gICAgY2FzZSBuZXR3b3Jrcy5kYXNoVGVzdDpcbiAgICAgIHJldHVybiBuZXR3b3Jrcy5kYXNoO1xuXG4gICAgY2FzZSBuZXR3b3Jrcy5saXRlY29pbjpcbiAgICBjYXNlIG5ldHdvcmtzLmxpdGVjb2luVGVzdDpcbiAgICAgIHJldHVybiBuZXR3b3Jrcy5saXRlY29pbjtcblxuICAgIGNhc2UgbmV0d29ya3MuemNhc2g6XG4gICAgY2FzZSBuZXR3b3Jrcy56Y2FzaFRlc3Q6XG4gICAgICByZXR1cm4gbmV0d29ya3MuemNhc2g7XG5cbiAgICBjYXNlIG5ldHdvcmtzLmRvZ2Vjb2luOlxuICAgIGNhc2UgbmV0d29ya3MuZG9nZWNvaW5UZXN0OlxuICAgICAgcmV0dXJuIG5ldHdvcmtzLmRvZ2Vjb2luO1xuICB9XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgbmV0d29ya2ApO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWZmIG5ldHdvcmsgaXMgYSBtYWlubmV0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01haW5uZXQobmV0d29yazogTmV0d29yayk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0TWFpbm5ldChuZXR3b3JrKSA9PT0gbmV0d29yaztcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05ldHdvcmt9IG5ldHdvcmtcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmZiBuZXR3b3JrIGlzIGEgdGVzdG5ldFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNUZXN0bmV0KG5ldHdvcms6IE5ldHdvcmspOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldE1haW5uZXQobmV0d29yaykgIT09IG5ldHdvcms7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHBhcmFtIHtOZXR3b3JrfSBvdGhlck5ldHdvcmtcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmZiBib3RoIG5ldHdvcmtzIGFyZSBmb3IgdGhlIHNhbWUgY29pblxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTYW1lQ29pbihuZXR3b3JrOiBOZXR3b3JrLCBvdGhlck5ldHdvcms6IE5ldHdvcmspOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldE1haW5uZXQobmV0d29yaykgPT09IGdldE1haW5uZXQob3RoZXJOZXR3b3JrKTtcbn1cblxuY29uc3QgbWFpbm5ldHMgPSBnZXROZXR3b3JrTGlzdCgpLmZpbHRlcihpc01haW5uZXQpO1xuY29uc3QgdGVzdG5ldHMgPSBnZXROZXR3b3JrTGlzdCgpLmZpbHRlcihpc1Rlc3RuZXQpO1xuXG4vKipcbiAqIE1hcCB3aGVyZSBrZXlzIGFyZSBtYWlubmV0IG5ldHdvcmtzIGFuZCB2YWx1ZXMgYXJlIHRlc3RuZXQgbmV0d29ya3NcbiAqIEB0eXBlIHtNYXA8TmV0d29yaywgTmV0d29ya1tdPn1cbiAqL1xuY29uc3QgbWFpbm5ldFRlc3RuZXRQYWlycyA9IG5ldyBNYXAobWFpbm5ldHMubWFwKChtKSA9PiBbbSwgdGVzdG5ldHMuZmlsdGVyKCh0KSA9PiBnZXRNYWlubmV0KHQpID09PSBtKV0pKTtcblxuLyoqXG4gKiBAcGFyYW0ge05ldHdvcmt9IG5ldHdvcmtcbiAqIEByZXR1cm5zIHtOZXR3b3JrfHVuZGVmaW5lZH0gLSBUaGUgdGVzdG5ldCBjb3JyZXNwb25kaW5nIHRvIGEgbWFpbm5ldC5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJldHVybnMgdW5kZWZpbmVkIGlmIGEgbmV0d29yayBoYXMgbm8gdGVzdG5ldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRlc3RuZXQobmV0d29yazogTmV0d29yayk6IE5ldHdvcmsgfCB1bmRlZmluZWQge1xuICBpZiAoaXNUZXN0bmV0KG5ldHdvcmspKSB7XG4gICAgcmV0dXJuIG5ldHdvcms7XG4gIH1cbiAgY29uc3QgdGVzdG5ldHMgPSBtYWlubmV0VGVzdG5ldFBhaXJzLmdldChuZXR3b3JrKTtcbiAgaWYgKHRlc3RuZXRzID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgYXJndW1lbnRgKTtcbiAgfVxuICBpZiAodGVzdG5ldHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0ZXN0bmV0cy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gdGVzdG5ldHNbMF07XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKGBtb3JlIHRoYW4gb25lIHRlc3RuZXQgZm9yICR7Z2V0TmV0d29ya05hbWUobmV0d29yayl9YCk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtOZXR3b3JrfSBuZXR3b3JrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZmYgbmV0d29yayBiaXRjb2luIG9yIHRlc3RuZXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQml0Y29pbihuZXR3b3JrOiBOZXR3b3JrKTogYm9vbGVhbiB7XG4gIHJldHVybiBnZXRNYWlubmV0KG5ldHdvcmspID09PSBuZXR3b3Jrcy5iaXRjb2luO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWZmIG5ldHdvcmsgaXMgYml0Y29pbmNhc2ggb3IgYml0Y29pbmNhc2hUZXN0bmV0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0JpdGNvaW5DYXNoKG5ldHdvcms6IE5ldHdvcmspOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldE1haW5uZXQobmV0d29yaykgPT09IG5ldHdvcmtzLmJpdGNvaW5jYXNoO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWZmIG5ldHdvcmsgaXMgYml0Y29pbmdvbGRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQml0Y29pbkdvbGQobmV0d29yazogTmV0d29yayk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0TWFpbm5ldChuZXR3b3JrKSA9PT0gbmV0d29ya3MuYml0Y29pbmdvbGQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHtOZXR3b3JrfSBuZXR3b3JrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZmYgbmV0d29yayBpcyBiaXRjb2luc3Ygb3IgYml0Y29pbnN2VGVzdG5ldFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCaXRjb2luU1YobmV0d29yazogTmV0d29yayk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0TWFpbm5ldChuZXR3b3JrKSA9PT0gbmV0d29ya3MuYml0Y29pbnN2O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7TmV0d29ya30gbmV0d29ya1xuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWZmIG5ldHdvcmsgaXMgZGFzaCBvciBkYXNoVGVzdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEYXNoKG5ldHdvcms6IE5ldHdvcmspOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldE1haW5uZXQobmV0d29yaykgPT09IG5ldHdvcmtzLmRhc2g7XG59XG5cbi8qKlxuICogQHBhcmFtIHtOZXR3b3JrfSBuZXR3b3JrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZmYgbmV0d29yayBpcyBkb2dlY29pbiBvciBkb2dlY29pblRlc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRG9nZWNvaW4obmV0d29yazogTmV0d29yayk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0TWFpbm5ldChuZXR3b3JrKSA9PT0gbmV0d29ya3MuZG9nZWNvaW47XG59XG5cbi8qKlxuICogQHBhcmFtIHtOZXR3b3JrfSBuZXR3b3JrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZmYgbmV0d29yayBpcyBsaXRlY29pbiBvciBsaXRlY29pblRlc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTGl0ZWNvaW4obmV0d29yazogTmV0d29yayk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0TWFpbm5ldChuZXR3b3JrKSA9PT0gbmV0d29ya3MubGl0ZWNvaW47XG59XG5cbi8qKlxuICogQHBhcmFtIHtOZXR3b3JrfSBuZXR3b3JrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZmYgbmV0d29yayBpcyB6Y2FzaCBvciB6Y2FzaFRlc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzWmNhc2gobmV0d29yazogTmV0d29yayk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0TWFpbm5ldChuZXR3b3JrKSA9PT0gbmV0d29ya3MuemNhc2g7XG59XG5cbi8qKlxuICogQHBhcmFtIHt1bmtub3dufSBuZXR3b3JrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gcmV0dXJucyB0cnVlIGlmZiBuZXR3b3JrIGlzIGFueSBvZiB0aGUgbmV0d29yayBzdGF0ZWQgaW4gdGhlIGFyZ3VtZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkTmV0d29yayhuZXR3b3JrOiB1bmtub3duKTogbmV0d29yayBpcyBOZXR3b3JrIHtcbiAgcmV0dXJuIGdldE5ldHdvcmtMaXN0KCkuaW5jbHVkZXMobmV0d29yayBhcyBOZXR3b3JrKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN1cHBvcnRzU2Vnd2l0KG5ldHdvcms6IE5ldHdvcmspOiBib29sZWFuIHtcbiAgcmV0dXJuIChbbmV0d29ya3MuYml0Y29pbiwgbmV0d29ya3MubGl0ZWNvaW4sIG5ldHdvcmtzLmJpdGNvaW5nb2xkXSBhcyBOZXR3b3JrW10pLmluY2x1ZGVzKGdldE1haW5uZXQobmV0d29yaykpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3VwcG9ydHNUYXByb290KG5ldHdvcms6IE5ldHdvcmspOiBib29sZWFuIHtcbiAgcmV0dXJuIGdldE1haW5uZXQobmV0d29yaykgPT09IG5ldHdvcmtzLmJpdGNvaW47XG59XG4iXX0=