@decaf-ts/fabric-weaver
Version:
template for ts projects
186 lines • 36.3 kB
JavaScript
import path from "path";
import fs from "fs";
import { Logging } from "@decaf-ts/logging";
import { FabricPeerConfigBuilder } from "../../fabric/peer/fabric-peer-config-builder";
import { FabricPeerNodeCommandBuilder } from "../../fabric/peer/fabric-peer-node-command-builder";
import { PeerChannelCommands, PeerLifecycleChaincodeCommands, PeerNodeCommands, } from "../../fabric/constants/fabric-peer";
import { FabricPeerChannelCommandBuilder } from "../../fabric/peer/fabric-peer-channel-command-builder";
import { FabricPeerLifecycleChaincodeCommandBuilder } from "../../fabric/peer/fabric-peer-lifecycle-chaincode-command-builder";
import { execSync } from "child_process";
export function issuePeer(log, cpath, gossip, tls, authTimeWindow, keepAlive, gateway, general, bccsp, msp, clientConnectionTimeout, delivery, profile, handlers, discovery, limits, msgSize, chaincode, state, blockchain, enableLedgerHistoryDatabase, pvtData, ledgerSnapshosRootDir, operation, metrics, vm) {
const logger = Logging.for(issuePeer);
log.debug(`Issuing Peer...`);
log.debug(`Writing configuration to ${cpath}`);
const builder = new FabricPeerConfigBuilder(logger);
builder
.setGossip(gossip)
.setTLS(tls)
.setLedgerSnapshotsRootDir(ledgerSnapshosRootDir)
.setOperations(operation)
.setMetrics(metrics)
.enableLedgerHistoryDatabase(enableLedgerHistoryDatabase)
.setLedgerPvtDataStore(pvtData)
.setHandlers(handlers)
.setDiscovery(discovery)
.setLimits(limits)
.setMessageSize(msgSize)
.setChaincode(chaincode)
.setLedgerState(state)
.setLegerBlockchain(blockchain)
.setAuthentication(authTimeWindow)
.setKeepAlice(keepAlive)
.setGateway(gateway)
.setGeneral(general)
.setBCCSP(bccsp)
.setMspConfig(msp)
.setConnTimeoutClient(clientConnectionTimeout)
.setDeliveryClient(delivery)
.setProfile(profile)
.setVMOptions(vm)
.save(cpath);
}
export async function startPeer(logger) {
const log = logger.for(startPeer);
log.debug(`Starting Peer`);
const builder = new FabricPeerNodeCommandBuilder(log);
builder.setCommand(PeerNodeCommands.START).execute();
}
export async function bootPeer(log, cpath, gossip, tls, authTimeWindow, keepAlive, gateway, general, bccsp, msp, clientConnectionTimeout, delivery, profile, handlers, discovery, limits, msgSize, chaincode, state, blockchain, enableLedgerHistoryDatabase, pvtData, ledgerSnapshosRootDir, operation, metrics, vm) {
const logger = Logging.for(bootPeer);
log.debug(`Booting Peer...`);
if (!hasPeerInitialized(cpath))
issuePeer(logger, cpath, gossip, tls, authTimeWindow, keepAlive, gateway, general, bccsp, msp, clientConnectionTimeout, delivery, profile, handlers, discovery, limits, msgSize, chaincode, state, blockchain, enableLedgerHistoryDatabase, pvtData, ledgerSnapshosRootDir, operation, metrics, vm);
startPeer(logger);
}
export function hasPeerInitialized(fileLocation) {
const log = Logging.for(hasPeerInitialized);
const defaultFileLocation = path.join(__dirname, "../../../peer/core.yaml");
if (!fileLocation) {
log.debug(`No file location provided, using default file location: ${defaultFileLocation}`);
fileLocation = defaultFileLocation;
}
else {
if (!fileLocation.endsWith(".yaml"))
fileLocation = path.join(fileLocation, "core.yaml");
log.debug(`Using provided file location: ${fileLocation}`);
}
const booted = fs.existsSync(fileLocation);
log.debug(`Peer has been booted: ${booted}`);
return booted;
}
export function peerFetchGenesisBlock(logger, channelID, ordererAddress, blockNumber, outputFile, tlsEnabled, tlsCACertFile) {
const log = Logging.for(peerFetchGenesisBlock);
log.debug(`Fetching Genesis Block`);
const builder = new FabricPeerChannelCommandBuilder(logger);
builder
.enableTLS(tlsEnabled)
.setCommand(PeerChannelCommands.FETCH)
.setBlockReference(blockNumber)
.setDestination(outputFile)
.setOrderer(ordererAddress)
.setChannelID(channelID)
.setTLSCAFile(tlsCACertFile)
.execute();
}
export async function peerJoinChannel(logger, blockPath) {
const log = Logging.for(peerJoinChannel);
log.debug(`Joining Channel`);
const builder = new FabricPeerChannelCommandBuilder(logger);
builder
.setCommand(PeerChannelCommands.JOIN)
.setBlockPath(blockPath)
.execute();
}
export function packageChaincode(logger, outputFile, contractPath, lang, contractName, contractVersion) {
const log = Logging.for(packageChaincode);
log.debug(`Packaging Chaincode`);
const builder = new FabricPeerLifecycleChaincodeCommandBuilder(logger);
builder
.setCommand(PeerLifecycleChaincodeCommands.PACKAGE)
.setDestination(outputFile)
.setContractPath(contractPath)
.setLang(lang)
.setLabel(`${contractName}_${contractVersion}`)
.execute();
}
export function installChaincode(logger, contractLocation) {
const log = Logging.for(installChaincode);
log.debug(`Installing Chaincode`);
const builder = new FabricPeerLifecycleChaincodeCommandBuilder(logger);
builder
.setCommand(PeerLifecycleChaincodeCommands.INSTALL)
.setDestination(contractLocation)
.execute();
}
export function approveChaincode(logger, ordererAddress, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile, collectionConfigPath, ordererTLSHostnameOverride) {
const log = Logging.for(installChaincode);
log.debug(`Approve Chaincode`);
const builder = new FabricPeerLifecycleChaincodeCommandBuilder(logger);
const id = execSync(builder.setCommand(PeerLifecycleChaincodeCommands.QUERYINSTALLED).build());
log.debug(`Using id: ${id}`);
builder
.setCommand(PeerLifecycleChaincodeCommands.APPROVEFORMYORG)
.setOrdererAddress(ordererAddress)
.setChannelID(channelID)
.setContractName(chaincodeName)
.setVersion(version)
.setSequence(sequence)
.enableTLS(enableTLS)
.setTLSCAFile(tlsCACertFile)
.setOrdererTLSHostnameOverride(ordererTLSHostnameOverride)
.setCollectionsConfigPath(collectionConfigPath)
.setPackageID(id
.toString()
.split(",")[0]
.split("\n")[1]
.split(":")
.slice(1)
.map((s) => s.trim())
.join(":"))
.execute();
}
export async function commitChainCode(logger, ordererAddress, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile, collectionConfigPath, ordererTLSHostnameOverride, peerAddresses, peerTLSRoots) {
const log = Logging.for(commitChainCode);
log.info(`Commiting chaincode`);
const checkChaincodeReadiness = function (logger, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile) {
const verificationBuilder = new FabricPeerLifecycleChaincodeCommandBuilder(logger);
const approvalData = execSync(verificationBuilder
.setCommand(PeerLifecycleChaincodeCommands.CHECKCOMMITREADINESS)
.setChannelID(channelID)
.setContractName(chaincodeName)
.setVersion(version)
.setSequence(sequence)
.enableTLS(enableTLS)
.setTLSCAFile(tlsCACertFile)
.setOutput("json")
.build()).toString();
const approvalJSON = JSON.parse(approvalData);
log.info(JSON.stringify(approvalJSON, null, 2));
return (Object.keys(approvalJSON.approvals).filter((key) => approvalJSON.approvals[key] == true).length >
Object.keys(approvalJSON.approvals).length / 2);
};
const commitWhenReady = function (logger, ordererAddress, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile, collectionConfigPath, ordererTLSHostnameOverride, peerAddresses, peerTLSRoots) {
if (!checkChaincodeReadiness(logger, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile)) {
log.info("Chaincode not ready, waiting...");
return setTimeout(() => {
commitWhenReady(logger, ordererAddress, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile, collectionConfigPath, ordererTLSHostnameOverride, peerAddresses, peerTLSRoots);
}, 30000);
}
new FabricPeerLifecycleChaincodeCommandBuilder(logger)
.setCommand(PeerLifecycleChaincodeCommands.COMMIT)
.setOrdererAddress(ordererAddress)
.setChannelID(channelID)
.setContractName(chaincodeName)
.setVersion(version)
.setSequence(sequence)
.enableTLS(enableTLS)
.setTLSCAFile(tlsCACertFile)
.setCollectionsConfigPath(collectionConfigPath)
.setOrdererTLSHostnameOverride(ordererTLSHostnameOverride)
.setPeerAddresses(peerAddresses)
.setPeerTLSRoots(peerTLSRoots)
.execute();
};
commitWhenReady(logger, ordererAddress, channelID, chaincodeName, version, sequence, enableTLS, tlsCACertFile, collectionConfigPath, ordererTLSHostnameOverride, peerAddresses, peerTLSRoots);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL3NjcmlwdHMvcGVlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sRUFBVSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQXdCdkYsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0RBQW9ELENBQUM7QUFDbEcsT0FBTyxFQUNMLG1CQUFtQixFQUNuQiw4QkFBOEIsRUFDOUIsZ0JBQWdCLEdBQ2pCLE1BQU0sb0NBQW9DLENBQUM7QUFDNUMsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sdURBQXVELENBQUM7QUFDeEcsT0FBTyxFQUFFLDBDQUEwQyxFQUFFLE1BQU0sbUVBQW1FLENBQUM7QUFDL0gsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV6QyxNQUFNLFVBQVUsU0FBUyxDQUN2QixHQUFXLEVBQ1gsS0FBYSxFQUNiLE1BQXFCLEVBQ3JCLEdBQWUsRUFDZixjQUF1QixFQUN2QixTQUEyQixFQUMzQixPQUF1QixFQUN2QixPQUF1QixFQUN2QixLQUFtQixFQUNuQixHQUFlLEVBQ2YsdUJBQWdDLEVBQ2hDLFFBQStCLEVBQy9CLE9BQXVCLEVBQ3ZCLFFBQXlCLEVBQ3pCLFNBQTJCLEVBQzNCLE1BQXFCLEVBQ3JCLE9BQXVCLEVBQ3ZCLFNBQTJCLEVBQzNCLEtBQXlCLEVBQ3pCLFVBQWdCLEVBQ2hCLDJCQUFxQyxFQUNyQyxPQUFnQyxFQUNoQyxxQkFBOEIsRUFDOUIsU0FBNEIsRUFDNUIsT0FBdUIsRUFDdkIsRUFBYTtJQUViLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7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QVMsRUFDVCxhQUFhLEVBQ2IsT0FBTyxFQUNQLFFBQVEsRUFDUixTQUFTLEVBQ1QsYUFBYSxFQUNiLG9CQUFvQixFQUNwQiwwQkFBMEIsRUFDMUIsYUFBYSxFQUNiLFlBQVksQ0FDYixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IEZhYnJpY1BlZXJDb25maWdCdWlsZGVyIH0gZnJvbSBcIi4uLy4uL2ZhYnJpYy9wZWVyL2ZhYnJpYy1wZWVyLWNvbmZpZy1idWlsZGVyXCI7XG5pbXBvcnQge1xuICBCQ0NTUENvbmZpZyxcbiAgQ2hhaW5jb2RlQ29uZmlnLFxuICBEZWxpdmVyeUNsaWVudENvbmZpZyxcbiAgRGlzY292ZXJ5Q29uZmlnLFxuICBHYXRld2F5Q29uZmlnLFxuICBHZW5lcmFsQ29uZmlnLFxuICBHb3NzaXBDb25maWcsXG4gIEhhbmRsZXJzQ29uZmlnLFxuICBLZWVwQWxpdmVDb25maWcsXG4gIExlZGdlclN0YXRlQ29uZmlnLFxuICBMaW1pdHNDb25maWcsXG4gIE1TR1NpemVDb25maWcsXG4gIE1TUENvbmZpZyxcbiAgUHJpdmF0ZURhdGFTdG9yZUNvbmZpZyxcbiAgUHJvZmlsZUNvbmZpZyxcbiAgVExTQ29uZmlnLFxuICBWTUNvbmZpZyxcbn0gZnJvbSBcIi4uLy4uL2ZhYnJpYy9pbnRlcmZhY2VzL2ZhYnJpYy9wZWVyLWNvbmZpZ1wiO1xuaW1wb3J0IHtcbiAgTWV0cmljc0NvbmZpZyxcbiAgT3BlcmF0aW9uc0NvbmZpZyxcbn0gZnJvbSBcIi4uLy4uL2ZhYnJpYy9pbnRlcmZhY2VzL2ZhYnJpYy9nZW5lcmFsLWNvbmZpZ3NcIjtcbmltcG9ydCB7IEZhYnJpY1BlZXJOb2RlQ29tbWFuZEJ1aWxkZXIgfSBmcm9tIFwiLi4vLi4vZmFicmljL3BlZXIvZmFicmljLXBlZXItbm9kZS1jb21tYW5kLWJ1aWxkZXJcIjtcbmltcG9ydCB7XG4gIFBlZXJDaGFubmVsQ29tbWFuZHMsXG4gIFBlZXJMaWZlY3ljbGVDaGFpbmNvZGVDb21tYW5kcyxcbiAgUGVlck5vZGVDb21tYW5kcyxcbn0gZnJvbSBcIi4uLy4uL2ZhYnJpYy9jb25zdGFudHMvZmFicmljLXBlZXJcIjtcbmltcG9ydCB7IEZhYnJpY1BlZXJDaGFubmVsQ29tbWFuZEJ1aWxkZXIgfSBmcm9tIFwiLi4vLi4vZmFicmljL3BlZXIvZmFicmljLXBlZXItY2hhbm5lbC1jb21tYW5kLWJ1aWxkZXJcIjtcbmltcG9ydCB7IEZhYnJpY1BlZXJMaWZlY3ljbGVDaGFpbmNvZGVDb21tYW5kQnVpbGRlciB9IGZyb20gXCIuLi8uLi9mYWJyaWMvcGVlci9mYWJyaWMtcGVlci1saWZlY3ljbGUtY2hhaW5jb2RlLWNvbW1hbmQtYnVpbGRlclwiO1xuaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNzdWVQZWVyKFxuICBsb2c6IExvZ2dlcixcbiAgY3BhdGg6IHN0cmluZyxcbiAgZ29zc2lwPzogR29zc2lwQ29uZmlnLFxuICB0bHM/OiBUTFNDb25maWcsXG4gIGF1dGhUaW1lV2luZG93Pzogc3RyaW5nLFxuICBrZWVwQWxpdmU/OiBLZWVwQWxpdmVDb25maWcsXG4gIGdhdGV3YXk/OiBHYXRld2F5Q29uZmlnLFxuICBnZW5lcmFsPzogR2VuZXJhbENvbmZpZyxcbiAgYmNjc3A/OiBCQ0NTUENvbmZpZyxcbiAgbXNwPzogTVNQQ29uZmlnLFxuICBjbGllbnRDb25uZWN0aW9uVGltZW91dD86IHN0cmluZyxcbiAgZGVsaXZlcnk/OiBEZWxpdmVyeUNsaWVudENvbmZpZyxcbiAgcHJvZmlsZT86IFByb2ZpbGVDb25maWcsXG4gIGhhbmRsZXJzPzogSGFuZGxlcnNDb25maWcsXG4gIGRpc2NvdmVyeT86IERpc2NvdmVyeUNvbmZpZyxcbiAgbGltaXRzPzogTGltaXRzQ29uZmlnLFxuICBtc2dTaXplPzogTVNHU2l6ZUNvbmZpZyxcbiAgY2hhaW5jb2RlPzogQ2hhaW5jb2RlQ29uZmlnLFxuICBzdGF0ZT86IExlZGdlclN0YXRlQ29uZmlnLFxuICBibG9ja2NoYWluPzogYW55LFxuICBlbmFibGVMZWRnZXJIaXN0b3J5RGF0YWJhc2U/OiBib29sZWFuLFxuICBwdnREYXRhPzogUHJpdmF0ZURhdGFTdG9yZUNvbmZpZyxcbiAgbGVkZ2VyU25hcHNob3NSb290RGlyPzogc3RyaW5nLFxuICBvcGVyYXRpb24/OiBPcGVyYXRpb25zQ29uZmlnLFxuICBtZXRyaWNzPzogTWV0cmljc0NvbmZpZyxcbiAgdm0/OiBWTUNvbmZpZ1xuKSB7XG4gIGNvbnN0IGxvZ2dlciA9IExvZ2dpbmcuZm9yKGlzc3VlUGVlcik7XG4gIGxvZy5kZWJ1ZyhgSXNzdWluZyBQZWVyLi4uYCk7XG4gIGxvZy5kZWJ1ZyhgV3JpdGluZyBjb25maWd1cmF0aW9uIHRvICR7Y3BhdGh9YCk7XG5cbiAgY29uc3QgYnVpbGRlciA9IG5ldyBGYWJyaWNQZWVyQ29uZmlnQnVpbGRlcihsb2dnZXIpO1xuXG4gIGJ1aWxkZXJcbiAgICAuc2V0R29zc2lwKGdvc3NpcClcbiAgICAuc2V0VExTKHRscylcbiAgICAuc2V0TGVkZ2VyU25hcHNob3RzUm9vdERpcihsZWRnZXJTbmFwc2hvc1Jvb3REaXIpXG4gICAgLnNldE9wZXJhdGlvbnMob3BlcmF0aW9uKVxuICAgIC5zZXRNZXRyaWNzKG1ldHJpY3MpXG4gICAgLmVuYWJsZUxlZGdlckhpc3RvcnlEYXRhYmFzZShlbmFibGVMZWRnZXJIaXN0b3J5RGF0YWJhc2UpXG4gICAgLnNldExlZGdlclB2dERhdGFTdG9yZShwdnREYXRhKVxuICAgIC5zZXRIYW5kbGVycyhoYW5kbGVycylcbiAgICAuc2V0RGlzY292ZXJ5KGRpc2NvdmVyeSlcbiAgICAuc2V0TGltaXRzKGxpbWl0cylcbiAgICAuc2V0TWVzc2FnZVNpemUobXNnU2l6ZSlcbiAgICAuc2V0Q2hhaW5jb2RlKGNoYWluY29kZSlcbiAgICAuc2V0TGVkZ2VyU3RhdGUoc3RhdGUpXG4gICAgLnNldExlZ2VyQmxvY2tjaGFpbihibG9ja2NoYWluKVxuICAgIC5zZXRBdXRoZW50aWNhdGlvbihhdXRoVGltZVdpbmRvdylcbiAgICAuc2V0S2VlcEFsaWNlKGtlZXBBbGl2ZSlcbiAgICAuc2V0R2F0ZXdheShnYXRld2F5KVxuICAgIC5zZXRHZW5lcmFsKGdlbmVyYWwpXG4gICAgLnNldEJDQ1NQKGJjY3NwKVxuICAgIC5zZXRNc3BDb25maWcobXNwKVxuICAgIC5zZXRDb25uVGltZW91dENsaWVudChjbGllbnRDb25uZWN0aW9uVGltZW91dClcbiAgICAuc2V0RGVsaXZlcnlDbGllbnQoZGVsaXZlcnkpXG4gICAgLnNldFByb2ZpbGUocHJvZmlsZSlcbiAgICAuc2V0Vk1PcHRpb25zKHZtKVxuICAgIC5zYXZlKGNwYXRoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0UGVlcihsb2dnZXI6IExvZ2dlcikge1xuICBjb25zdCBsb2c6IExvZ2dlciA9IGxvZ2dlci5mb3Ioc3RhcnRQZWVyKTtcbiAgbG9nLmRlYnVnKGBTdGFydGluZyBQZWVyYCk7XG5cbiAgY29uc3QgYnVpbGRlciA9IG5ldyBGYWJyaWNQZWVyTm9kZUNvbW1hbmRCdWlsZGVyKGxvZyk7XG5cbiAgYnVpbGRlci5zZXRDb21tYW5kKFBlZXJOb2RlQ29tbWFuZHMuU1RBUlQpLmV4ZWN1dGUoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJvb3RQZWVyKFxuICBsb2c6IExvZ2dlcixcbiAgY3BhdGg6IHN0cmluZyxcbiAgZ29zc2lwPzogR29zc2lwQ29uZmlnLFxuICB0bHM/OiBUTFNDb25maWcsXG4gIGF1dGhUaW1lV2luZG93Pzogc3RyaW5nLFxuICBrZWVwQWxpdmU/OiBLZWVwQWxpdmVDb25maWcsXG4gIGdhdGV3YXk/OiBHYXRld2F5Q29uZmlnLFxuICBnZW5lcmFsPzogR2VuZXJhbENvbmZpZyxcbiAgYmNjc3A/OiBCQ0NTUENvbmZpZyxcbiAgbXNwPzogTVNQQ29uZmlnLFxuICBjbGllbnRDb25uZWN0aW9uVGltZW91dD86IHN0cmluZyxcbiAgZGVsaXZlcnk/OiBEZWxpdmVyeUNsaWVudENvbmZpZyxcbiAgcHJvZmlsZT86IFByb2ZpbGVDb25maWcsXG4gIGhhbmRsZXJzPzogSGFuZGxlcnNDb25maWcsXG4gIGRpc2NvdmVyeT86IERpc2NvdmVyeUNvbmZpZyxcbiAgbGltaXRzPzogTGltaXRzQ29uZmlnLFxuICBtc2dTaXplPzogTVNHU2l6ZUNvbmZpZyxcbiAgY2hhaW5jb2RlPzogQ2hhaW5jb2RlQ29uZmlnLFxuICBzdGF0ZT86IExlZGdlclN0YXRlQ29uZmlnLFxuICBibG9ja2NoYWluPzogYW55LFxuICBlbmFibGVMZWRnZXJIaXN0b3J5RGF0YWJhc2U/OiBib29sZWFuLFxuICBwdnREYXRhPzogUHJpdmF0ZURhdGFTdG9yZUNvbmZpZyxcbiAgbGVkZ2VyU25hcHNob3NSb290RGlyPzogc3RyaW5nLFxuICBvcGVyYXRpb24/OiBPcGVyYXRpb25zQ29uZmlnLFxuICBtZXRyaWNzPzogTWV0cmljc0NvbmZpZyxcbiAgdm0/OiBWTUNvbmZpZ1xuKSB7XG4gIGNvbnN0IGxvZ2dlciA9IExvZ2dpbmcuZm9yKGJvb3RQZWVyKTtcbiAgbG9nLmRlYnVnKGBCb290aW5nIFBlZXIuLi5gKTtcblxuICBpZiAoIWhhc1BlZXJJbml0aWFsaXplZChjcGF0aCkpXG4gICAgaXNzdWVQZWVyKFxuICAgICAgbG9nZ2VyLFxuICAgICAgY3BhdGgsXG4gICAgICBnb3NzaXAsXG4gICAgICB0bHMsXG4gICAgICBhdXRoVGltZVdpbmRvdyxcbiAgICAgIGtlZXBBbGl2ZSxcbiAgICAgIGdhdGV3YXksXG4gICAgICBnZW5lcmFsLFxuICAgICAgYmNjc3AsXG4gICAgICBtc3AsXG4gICAgICBjbGllbnRDb25uZWN0aW9uVGltZW91dCxcbiAgICAgIGRlbGl2ZXJ5LFxuICAgICAgcHJvZmlsZSxcbiAgICAgIGhhbmRsZXJzLFxuICAgICAgZGlzY292ZXJ5LFxuICAgICAgbGltaXRzLFxuICAgICAgbXNnU2l6ZSxcbiAgICAgIGNoYWluY29kZSxcbiAgICAgIHN0YXRlLFxuICAgICAgYmxvY2tjaGFpbixcbiAgICAgIGVuYWJsZUxlZGdlckhpc3RvcnlEYXRhYmFzZSxcbiAgICAgIHB2dERhdGEsXG4gICAgICBsZWRnZXJTbmFwc2hvc1Jvb3REaXIsXG4gICAgICBvcGVyYXRpb24sXG4gICAgICBtZXRyaWNzLFxuICAgICAgdm1cbiAgICApO1xuXG4gIHN0YXJ0UGVlcihsb2dnZXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzUGVlckluaXRpYWxpemVkKGZpbGVMb2NhdGlvbj86IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBsb2c6IExvZ2dlciA9IExvZ2dpbmcuZm9yKGhhc1BlZXJJbml0aWFsaXplZCk7XG5cbiAgY29uc3QgZGVmYXVsdEZpbGVMb2NhdGlvbiA9IHBhdGguam9pbihfX2Rpcm5hbWUsIFwiLi4vLi4vLi4vcGVlci9jb3JlLnlhbWxcIik7XG5cbiAgaWYgKCFmaWxlTG9jYXRpb24pIHtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgTm8gZmlsZSBsb2NhdGlvbiBwcm92aWRlZCwgdXNpbmcgZGVmYXVsdCBmaWxlIGxvY2F0aW9uOiAke2RlZmF1bHRGaWxlTG9jYXRpb259YFxuICAgICk7XG4gICAgZmlsZUxvY2F0aW9uID0gZGVmYXVsdEZpbGVMb2NhdGlvbjtcbiAgfSBlbHNlIHtcbiAgICBpZiAoIWZpbGVMb2NhdGlvbi5lbmRzV2l0aChcIi55YW1sXCIpKVxuICAgICAgZmlsZUxvY2F0aW9uID0gcGF0aC5qb2luKGZpbGVMb2NhdGlvbiwgXCJjb3JlLnlhbWxcIik7XG4gICAgbG9nLmRlYnVnKGBVc2luZyBwcm92aWRlZCBmaWxlIGxvY2F0aW9uOiAke2ZpbGVMb2NhdGlvbn1gKTtcbiAgfVxuXG4gIGNvbnN0IGJvb3RlZCA9IGZzLmV4aXN0c1N5bmMoZmlsZUxvY2F0aW9uKTtcblxuICBsb2cuZGVidWcoYFBlZXIgaGFzIGJlZW4gYm9vdGVkOiAke2Jvb3RlZH1gKTtcblxuICByZXR1cm4gYm9vdGVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGVlckZldGNoR2VuZXNpc0Jsb2NrKFxuICBsb2dnZXI/OiBMb2dnZXIsXG4gIGNoYW5uZWxJRD86IHN0cmluZyxcbiAgb3JkZXJlckFkZHJlc3M/OiBzdHJpbmcsXG4gIGJsb2NrTnVtYmVyPzogc3RyaW5nLFxuICBvdXRwdXRGaWxlPzogc3RyaW5nLFxuICB0bHNFbmFibGVkPzogYm9vbGVhbixcbiAgdGxzQ0FDZXJ0RmlsZT86IHN0cmluZ1xuKSB7XG4gIGNvbnN0IGxvZzogTG9nZ2VyID0gTG9nZ2luZy5mb3IocGVlckZldGNoR2VuZXNpc0Jsb2NrKTtcbiAgbG9nLmRlYnVnKGBGZXRjaGluZyBHZW5lc2lzIEJsb2NrYCk7XG5cbiAgY29uc3QgYnVpbGRlciA9IG5ldyBGYWJyaWNQZWVyQ2hhbm5lbENvbW1hbmRCdWlsZGVyKGxvZ2dlcik7XG5cbiAgYnVpbGRlclxuICAgIC5lbmFibGVUTFModGxzRW5hYmxlZClcbiAgICAuc2V0Q29tbWFuZChQZWVyQ2hhbm5lbENvbW1hbmRzLkZFVENIKVxuICAgIC5zZXRCbG9ja1JlZmVyZW5jZShibG9ja051bWJlcilcbiAgICAuc2V0RGVzdGluYXRpb24ob3V0cHV0RmlsZSlcbiAgICAuc2V0T3JkZXJlcihvcmRlcmVyQWRkcmVzcylcbiAgICAuc2V0Q2hhbm5lbElEKGNoYW5uZWxJRClcbiAgICAuc2V0VExTQ0FGaWxlKHRsc0NBQ2VydEZpbGUpXG4gICAgLmV4ZWN1dGUoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBlZXJKb2luQ2hhbm5lbChsb2dnZXI/OiBMb2dnZXIsIGJsb2NrUGF0aD86IHN0cmluZykge1xuICBjb25zdCBsb2c6IExvZ2dlciA9IExvZ2dpbmcuZm9yKHBlZXJKb2luQ2hhbm5lbCk7XG4gIGxvZy5kZWJ1ZyhgSm9pbmluZyBDaGFubmVsYCk7XG5cbiAgY29uc3QgYnVpbGRlciA9IG5ldyBGYWJyaWNQZWVyQ2hhbm5lbENvbW1hbmRCdWlsZGVyKGxvZ2dlcik7XG5cbiAgYnVpbGRlclxuICAgIC5zZXRDb21tYW5kKFBlZXJDaGFubmVsQ29tbWFuZHMuSk9JTilcbiAgICAuc2V0QmxvY2tQYXRoKGJsb2NrUGF0aClcbiAgICAuZXhlY3V0ZSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFja2FnZUNoYWluY29kZShcbiAgbG9nZ2VyPzogTG9nZ2VyLFxuICBvdXRwdXRGaWxlPzogc3RyaW5nLFxuICBjb250cmFjdFBhdGg/OiBzdHJpbmcsXG4gIGxhbmc/OiBzdHJpbmcsXG4gIGNvbnRyYWN0TmFtZT86IHN0cmluZyxcbiAgY29udHJhY3RWZXJzaW9uPzogc3RyaW5nXG4pIHtcbiAgY29uc3QgbG9nOiBMb2dnZXIgPSBMb2dnaW5nLmZvcihwYWNrYWdlQ2hhaW5jb2RlKTtcbiAgbG9nLmRlYnVnKGBQYWNrYWdpbmcgQ2hhaW5jb2RlYCk7XG5cbiAgY29uc3QgYnVpbGRlciA9IG5ldyBGYWJyaWNQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZEJ1aWxkZXIobG9nZ2VyKTtcblxuICBidWlsZGVyXG4gICAgLnNldENvbW1hbmQoUGVlckxpZmVjeWNsZUNoYWluY29kZUNvbW1hbmRzLlBBQ0tBR0UpXG4gICAgLnNldERlc3RpbmF0aW9uKG91dHB1dEZpbGUpXG4gICAgLnNldENvbnRyYWN0UGF0aChjb250cmFjdFBhdGgpXG4gICAgLnNldExhbmcobGFuZylcbiAgICAuc2V0TGFiZWwoYCR7Y29udHJhY3ROYW1lfV8ke2NvbnRyYWN0VmVyc2lvbn1gKVxuICAgIC5leGVjdXRlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnN0YWxsQ2hhaW5jb2RlKGxvZ2dlcjogTG9nZ2VyLCBjb250cmFjdExvY2F0aW9uPzogc3RyaW5nKSB7XG4gIGNvbnN0IGxvZzogTG9nZ2VyID0gTG9nZ2luZy5mb3IoaW5zdGFsbENoYWluY29kZSk7XG4gIGxvZy5kZWJ1ZyhgSW5zdGFsbGluZyBDaGFpbmNvZGVgKTtcblxuICBjb25zdCBidWlsZGVyID0gbmV3IEZhYnJpY1BlZXJMaWZlY3ljbGVDaGFpbmNvZGVDb21tYW5kQnVpbGRlcihsb2dnZXIpO1xuXG4gIGJ1aWxkZXJcbiAgICAuc2V0Q29tbWFuZChQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZHMuSU5TVEFMTClcbiAgICAuc2V0RGVzdGluYXRpb24oY29udHJhY3RMb2NhdGlvbilcbiAgICAuZXhlY3V0ZSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwcm92ZUNoYWluY29kZShcbiAgbG9nZ2VyOiBMb2dnZXIsXG4gIG9yZGVyZXJBZGRyZXNzPzogc3RyaW5nLFxuICBjaGFubmVsSUQ/OiBzdHJpbmcsXG4gIGNoYWluY29kZU5hbWU/OiBzdHJpbmcsXG4gIHZlcnNpb24/OiBzdHJpbmcsXG4gIHNlcXVlbmNlPzogc3RyaW5nLFxuICBlbmFibGVUTFM/OiBib29sZWFuLFxuICB0bHNDQUNlcnRGaWxlPzogc3RyaW5nLFxuICBjb2xsZWN0aW9uQ29uZmlnUGF0aD86IHN0cmluZyxcbiAgb3JkZXJlclRMU0hvc3RuYW1lT3ZlcnJpZGU/OiBzdHJpbmdcbikge1xuICBjb25zdCBsb2c6IExvZ2dlciA9IExvZ2dpbmcuZm9yKGluc3RhbGxDaGFpbmNvZGUpO1xuICBsb2cuZGVidWcoYEFwcHJvdmUgQ2hhaW5jb2RlYCk7XG5cbiAgY29uc3QgYnVpbGRlciA9IG5ldyBGYWJyaWNQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZEJ1aWxkZXIobG9nZ2VyKTtcblxuICBjb25zdCBpZCA9IGV4ZWNTeW5jKFxuICAgIGJ1aWxkZXIuc2V0Q29tbWFuZChQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZHMuUVVFUllJTlNUQUxMRUQpLmJ1aWxkKClcbiAgKTtcblxuICBsb2cuZGVidWcoYFVzaW5nIGlkOiAke2lkfWApO1xuXG4gIGJ1aWxkZXJcbiAgICAuc2V0Q29tbWFuZChQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZHMuQVBQUk9WRUZPUk1ZT1JHKVxuICAgIC5zZXRPcmRlcmVyQWRkcmVzcyhvcmRlcmVyQWRkcmVzcylcbiAgICAuc2V0Q2hhbm5lbElEKGNoYW5uZWxJRClcbiAgICAuc2V0Q29udHJhY3ROYW1lKGNoYWluY29kZU5hbWUpXG4gICAgLnNldFZlcnNpb24odmVyc2lvbilcbiAgICAuc2V0U2VxdWVuY2Uoc2VxdWVuY2UpXG4gICAgLmVuYWJsZVRMUyhlbmFibGVUTFMpXG4gICAgLnNldFRMU0NBRmlsZSh0bHNDQUNlcnRGaWxlKVxuICAgIC5zZXRPcmRlcmVyVExTSG9zdG5hbWVPdmVycmlkZShvcmRlcmVyVExTSG9zdG5hbWVPdmVycmlkZSlcbiAgICAuc2V0Q29sbGVjdGlvbnNDb25maWdQYXRoKGNvbGxlY3Rpb25Db25maWdQYXRoKVxuICAgIC5zZXRQYWNrYWdlSUQoXG4gICAgICBpZFxuICAgICAgICAudG9TdHJpbmcoKVxuICAgICAgICAuc3BsaXQoXCIsXCIpWzBdXG4gICAgICAgIC5zcGxpdChcIlxcblwiKVsxXVxuICAgICAgICAuc3BsaXQoXCI6XCIpXG4gICAgICAgIC5zbGljZSgxKVxuICAgICAgICAubWFwKChzKSA9PiBzLnRyaW0oKSlcbiAgICAgICAgLmpvaW4oXCI6XCIpXG4gICAgKVxuICAgIC5leGVjdXRlKCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb21taXRDaGFpbkNvZGUoXG4gIGxvZ2dlcjogTG9nZ2VyLFxuICBvcmRlcmVyQWRkcmVzcz86IHN0cmluZyxcbiAgY2hhbm5lbElEPzogc3RyaW5nLFxuICBjaGFpbmNvZGVOYW1lPzogc3RyaW5nLFxuICB2ZXJzaW9uPzogc3RyaW5nLFxuICBzZXF1ZW5jZT86IHN0cmluZyxcbiAgZW5hYmxlVExTPzogYm9vbGVhbixcbiAgdGxzQ0FDZXJ0RmlsZT86IHN0cmluZyxcbiAgY29sbGVjdGlvbkNvbmZpZ1BhdGg/OiBzdHJpbmcsXG4gIG9yZGVyZXJUTFNIb3N0bmFtZU92ZXJyaWRlPzogc3RyaW5nLFxuICBwZWVyQWRkcmVzc2VzPzogc3RyaW5nW10sXG4gIHBlZXJUTFNSb290cz86IHN0cmluZ1tdXG4pIHtcbiAgY29uc3QgbG9nOiBMb2dnZXIgPSBMb2dnaW5nLmZvcihjb21taXRDaGFpbkNvZGUpO1xuICBsb2cuaW5mbyhgQ29tbWl0aW5nIGNoYWluY29kZWApO1xuXG4gIGNvbnN0IGNoZWNrQ2hhaW5jb2RlUmVhZGluZXNzID0gZnVuY3Rpb24gKFxuICAgIGxvZ2dlcjogTG9nZ2VyLFxuICAgIGNoYW5uZWxJRD86IHN0cmluZyxcbiAgICBjaGFpbmNvZGVOYW1lPzogc3RyaW5nLFxuICAgIHZlcnNpb24/OiBzdHJpbmcsXG4gICAgc2VxdWVuY2U/OiBzdHJpbmcsXG4gICAgZW5hYmxlVExTPzogYm9vbGVhbixcbiAgICB0bHNDQUNlcnRGaWxlPzogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IHZlcmlmaWNhdGlvbkJ1aWxkZXIgPSBuZXcgRmFicmljUGVlckxpZmVjeWNsZUNoYWluY29kZUNvbW1hbmRCdWlsZGVyKFxuICAgICAgbG9nZ2VyXG4gICAgKTtcblxuICAgIGNvbnN0IGFwcHJvdmFsRGF0YSA9IGV4ZWNTeW5jKFxuICAgICAgdmVyaWZpY2F0aW9uQnVpbGRlclxuICAgICAgICAuc2V0Q29tbWFuZChQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZHMuQ0hFQ0tDT01NSVRSRUFESU5FU1MpXG4gICAgICAgIC5zZXRDaGFubmVsSUQoY2hhbm5lbElEKVxuICAgICAgICAuc2V0Q29udHJhY3ROYW1lKGNoYWluY29kZU5hbWUpXG4gICAgICAgIC5zZXRWZXJzaW9uKHZlcnNpb24pXG4gICAgICAgIC5zZXRTZXF1ZW5jZShzZXF1ZW5jZSlcbiAgICAgICAgLmVuYWJsZVRMUyhlbmFibGVUTFMpXG4gICAgICAgIC5zZXRUTFNDQUZpbGUodGxzQ0FDZXJ0RmlsZSlcbiAgICAgICAgLnNldE91dHB1dChcImpzb25cIilcbiAgICAgICAgLmJ1aWxkKClcbiAgICApLnRvU3RyaW5nKCk7XG5cbiAgICBjb25zdCBhcHByb3ZhbEpTT04gPSBKU09OLnBhcnNlKGFwcHJvdmFsRGF0YSk7XG5cbiAgICBsb2cuaW5mbyhKU09OLnN0cmluZ2lmeShhcHByb3ZhbEpTT04sIG51bGwsIDIpKTtcblxuICAgIHJldHVybiAoXG4gICAgICBPYmplY3Qua2V5cyhhcHByb3ZhbEpTT04uYXBwcm92YWxzKS5maWx0ZXIoXG4gICAgICAgIChrZXkpID0+IGFwcHJvdmFsSlNPTi5hcHByb3ZhbHNba2V5XSA9PSB0cnVlXG4gICAgICApLmxlbmd0aCA+XG4gICAgICBPYmplY3Qua2V5cyhhcHByb3ZhbEpTT04uYXBwcm92YWxzKS5sZW5ndGggLyAyXG4gICAgKTtcbiAgfTtcblxuICBjb25zdCBjb21taXRXaGVuUmVhZHkgPSBmdW5jdGlvbiAoXG4gICAgbG9nZ2VyOiBMb2dnZXIsXG4gICAgb3JkZXJlckFkZHJlc3M/OiBzdHJpbmcsXG4gICAgY2hhbm5lbElEPzogc3RyaW5nLFxuICAgIGNoYWluY29kZU5hbWU/OiBzdHJpbmcsXG4gICAgdmVyc2lvbj86IHN0cmluZyxcbiAgICBzZXF1ZW5jZT86IHN0cmluZyxcbiAgICBlbmFibGVUTFM/OiBib29sZWFuLFxuICAgIHRsc0NBQ2VydEZpbGU/OiBzdHJpbmcsXG4gICAgY29sbGVjdGlvbkNvbmZpZ1BhdGg/OiBzdHJpbmcsXG4gICAgb3JkZXJlclRMU0hvc3RuYW1lT3ZlcnJpZGU/OiBzdHJpbmcsXG4gICAgcGVlckFkZHJlc3Nlcz86IHN0cmluZ1tdLFxuICAgIHBlZXJUTFNSb290cz86IHN0cmluZ1tdXG4gICkge1xuICAgIGlmIChcbiAgICAgICFjaGVja0NoYWluY29kZVJlYWRpbmVzcyhcbiAgICAgICAgbG9nZ2VyLFxuICAgICAgICBjaGFubmVsSUQsXG4gICAgICAgIGNoYWluY29kZU5hbWUsXG4gICAgICAgIHZlcnNpb24sXG4gICAgICAgIHNlcXVlbmNlLFxuICAgICAgICBlbmFibGVUTFMsXG4gICAgICAgIHRsc0NBQ2VydEZpbGVcbiAgICAgIClcbiAgICApIHtcbiAgICAgIGxvZy5pbmZvKFwiQ2hhaW5jb2RlIG5vdCByZWFkeSwgd2FpdGluZy4uLlwiKTtcbiAgICAgIHJldHVybiBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29tbWl0V2hlblJlYWR5KFxuICAgICAgICAgIGxvZ2dlcixcbiAgICAgICAgICBvcmRlcmVyQWRkcmVzcyxcbiAgICAgICAgICBjaGFubmVsSUQsXG4gICAgICAgICAgY2hhaW5jb2RlTmFtZSxcbiAgICAgICAgICB2ZXJzaW9uLFxuICAgICAgICAgIHNlcXVlbmNlLFxuICAgICAgICAgIGVuYWJsZVRMUyxcbiAgICAgICAgICB0bHNDQUNlcnRGaWxlLFxuICAgICAgICAgIGNvbGxlY3Rpb25Db25maWdQYXRoLFxuICAgICAgICAgIG9yZGVyZXJUTFNIb3N0bmFtZU92ZXJyaWRlLFxuICAgICAgICAgIHBlZXJBZGRyZXNzZXMsXG4gICAgICAgICAgcGVlclRMU1Jvb3RzXG4gICAgICAgICk7XG4gICAgICB9LCAzMDAwMCk7XG4gICAgfVxuXG4gICAgbmV3IEZhYnJpY1BlZXJMaWZlY3ljbGVDaGFpbmNvZGVDb21tYW5kQnVpbGRlcihsb2dnZXIpXG4gICAgICAuc2V0Q29tbWFuZChQZWVyTGlmZWN5Y2xlQ2hhaW5jb2RlQ29tbWFuZHMuQ09NTUlUKVxuICAgICAgLnNldE9yZGVyZXJBZGRyZXNzKG9yZGVyZXJBZGRyZXNzKVxuICAgICAgLnNldENoYW5uZWxJRChjaGFubmVsSUQpXG4gICAgICAuc2V0Q29udHJhY3ROYW1lKGNoYWluY29kZU5hbWUpXG4gICAgICAuc2V0VmVyc2lvbih2ZXJzaW9uKVxuICAgICAgLnNldFNlcXVlbmNlKHNlcXVlbmNlKVxuICAgICAgLmVuYWJsZVRMUyhlbmFibGVUTFMpXG4gICAgICAuc2V0VExTQ0FGaWxlKHRsc0NBQ2VydEZpbGUpXG4gICAgICAuc2V0Q29sbGVjdGlvbnNDb25maWdQYXRoKGNvbGxlY3Rpb25Db25maWdQYXRoKVxuICAgICAgLnNldE9yZGVyZXJUTFNIb3N0bmFtZU92ZXJyaWRlKG9yZGVyZXJUTFNIb3N0bmFtZU92ZXJyaWRlKVxuICAgICAgLnNldFBlZXJBZGRyZXNzZXMocGVlckFkZHJlc3NlcylcbiAgICAgIC5zZXRQZWVyVExTUm9vdHMocGVlclRMU1Jvb3RzKVxuICAgICAgLmV4ZWN1dGUoKTtcbiAgfTtcblxuICBjb21taXRXaGVuUmVhZHkoXG4gICAgbG9nZ2VyLFxuICAgIG9yZGVyZXJBZGRyZXNzLFxuICAgIGNoYW5uZWxJRCxcbiAgICBjaGFpbmNvZGVOYW1lLFxuICAgIHZlcnNpb24sXG4gICAgc2VxdWVuY2UsXG4gICAgZW5hYmxlVExTLFxuICAgIHRsc0NBQ2VydEZpbGUsXG4gICAgY29sbGVjdGlvbkNvbmZpZ1BhdGgsXG4gICAgb3JkZXJlclRMU0hvc3RuYW1lT3ZlcnJpZGUsXG4gICAgcGVlckFkZHJlc3NlcyxcbiAgICBwZWVyVExTUm9vdHNcbiAgKTtcbn1cbiJdfQ==