@bitgo-beta/utxo-lib
Version:
Client-side Bitcoin JavaScript library
404 lines (401 loc) • 40.6 kB
JavaScript
;
/*
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=