From d11a26208da3509c740b03cb78c8c9abe32eea27 Mon Sep 17 00:00:00 2001 From: Rinish Sam <36656347+CaptainIRS@users.noreply.github.com> Date: Thu, 21 Jul 2022 00:33:50 +0530 Subject: [PATCH] Remove channel and chaincode ops from Fabric v1 (#1411) Signed-off-by: CaptainIRS <36656347+CaptainIRS@users.noreply.github.com> Signed-off-by: eravatee --- .../v1/FabricChaincodeOperations.js | 490 ------------------ .../v1/FabricChannelOperations.js | 401 -------------- .../connector-versions/v1/FabricGateway.js | 8 +- .../connector-versions/v1/FabricNonGateway.js | 8 +- packages/caliper-fabric/package.json | 5 +- .../connector-versions/v1/FabricGateway.js | 8 - .../connector-versions/v1/FabricNonGateway.js | 8 - 7 files changed, 3 insertions(+), 925 deletions(-) delete mode 100644 packages/caliper-fabric/lib/connector-versions/v1/FabricChaincodeOperations.js delete mode 100644 packages/caliper-fabric/lib/connector-versions/v1/FabricChannelOperations.js diff --git a/packages/caliper-fabric/lib/connector-versions/v1/FabricChaincodeOperations.js b/packages/caliper-fabric/lib/connector-versions/v1/FabricChaincodeOperations.js deleted file mode 100644 index 5478090a0..000000000 --- a/packages/caliper-fabric/lib/connector-versions/v1/FabricChaincodeOperations.js +++ /dev/null @@ -1,490 +0,0 @@ -/* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -const { CaliperUtils, ConfigUtil } = require('@hyperledger/caliper-core'); -const ClientCreator = require('./ClientCreator'); - -const logger = CaliperUtils.getLogger('connectors/v1/FabricChaincodeOperations'); - -/** */ -class FabricChaincodeOperations { - - /** - * @param {*} connectorConfiguration the connector configuration - */ - constructor(connectorConfiguration) { - - this.connectorConfiguration = connectorConfiguration; - this.aliasNameToFabricClientMap = null; - - this.configSleepAfterInstantiateContract = ConfigUtil.get(ConfigUtil.keys.Fabric.SleepAfter.InstantiateContract, 5000); - this.configOverwriteGopath = ConfigUtil.get(ConfigUtil.keys.Fabric.OverwriteGopath, true); - this.configContractInstantiateTimeout = ConfigUtil.get(ConfigUtil.keys.Fabric.Timeout.ContractInstantiate, 300000); - this.configContractInstantiateEventTimeout = ConfigUtil.get(ConfigUtil.keys.Fabric.Timeout.ContractInstantiateEvent, 300000); - } - - /** - * install and instantiate all chaincodes as required that are defined in the connector configuration - * @async - */ - async installAndInstantiateChaincodes() { - await this._installChaincodes(); - const atLeastOneChaincodeInstantiated = await this._instantiateChaincodes(); - if (atLeastOneChaincodeInstantiated) { - logger.info(`Sleeping ${this.configSleepAfterInstantiateContract / 1000.0}s...`); - await CaliperUtils.sleep(this.configSleepAfterInstantiateContract); - } - } - - /** - * Install All the defined chaincodes that are requested to be installed in the connector configuration - * @async - * @private - */ - async _installChaincodes() { - if (this.configOverwriteGopath) { - process.env.GOPATH = CaliperUtils.resolvePath('.'); - } - - const channelNames = this.connectorConfiguration.getAllChannelNames(); - for (const channelName of channelNames) { - logger.info(`Installing contracts for ${channelName}...`); - - // proceed cc by cc for the channel - const contractDefinitions = this.connectorConfiguration.getContractDefinitionsForChannelName(channelName); - for (const contractDefinition of contractDefinitions) { - - if (!contractDefinition.install) { - continue; - } - - const peersInChannelByOrganizationMap = await this.connectorConfiguration.getEndorsingPeersInChannelByOrganizationMap(); - const peersInOrganizationMap = peersInChannelByOrganizationMap.get(channelName); - const allChaincodeInstallErrors = []; - - for (const [organization, peersInOrganization] of peersInOrganizationMap) { - const adminForOrganization = await this._getAdminClientForOrganization(organization); - const queryInstalledErrors = []; - const listOfPeersInOrganizationToInstallOn = []; - - // TODO: support contractDefinitions.install.targetPeers ? they would need to go through the check of whether - // the chaincode has already been installed - for (const peerInOrganization of peersInOrganization) { - try { - /** {@link ChaincodeQueryResponse} */ - const resp = await adminForOrganization.queryInstalledChaincodes(peerInOrganization, true); - if (resp.chaincodes.some(cc => cc.name === contractDefinition.id && cc.version === contractDefinition.install.version)) { - logger.info(`${contractDefinition.id}@${contractDefinition.install.version} is already installed on ${peerInOrganization}`); - continue; - } - - listOfPeersInOrganizationToInstallOn.push(peerInOrganization); - } catch (err) { - queryInstalledErrors.push(new Error(`Couldn't query installed contracts on ${peerInOrganization}: ${err.message}`)); - } - } - - if (queryInstalledErrors.length > 0) { - let errorMsg = `Could not query whether ${contractDefinition.id}@${contractDefinition.install.version} is installed on some peers of ${channelName}:`; - for (const err of queryInstalledErrors) { - errorMsg += `\n\t- ${err.message}`; - } - - logger.error(errorMsg); - throw new Error(`Could not query whether ${contractDefinition.id}@${contractDefinition.install.version} is installed on some peers of ${channelName}`); - } - - if (listOfPeersInOrganizationToInstallOn.length < 1) { - logger.info(`No Peers found to need ${contractDefinition.id}@${contractDefinition.install.version} to be installed for ${channelName}, skipping it`); - continue; - } - - const chaincodeInstallErrorsForOrganization = await this._installChaincodeOntoOrganizationPeers(adminForOrganization, contractDefinition, listOfPeersInOrganizationToInstallOn); - - if (chaincodeInstallErrorsForOrganization.length === 0) { - logger.info(`${contractDefinition.id}@${contractDefinition.install.version} successfully installed on ${organization}'s peers: ${listOfPeersInOrganizationToInstallOn.toString()}`); - } - - allChaincodeInstallErrors.push(...chaincodeInstallErrorsForOrganization); - } - - if (allChaincodeInstallErrors.length > 0) { - let errorMsg = `Could not install ${contractDefinition.id}@${contractDefinition.install.version} on some peers of ${channelName}:`; - for (const err of allChaincodeInstallErrors) { - errorMsg += `\n\t- ${err.message}`; - } - - logger.error(errorMsg); - throw new Error(`Could not install ${contractDefinition.id}@${contractDefinition.install.version} on some peers of ${channelName}`); - } - } - } - } - - /** - * Install chaincode onto the appropriate Peers for a specific organization - * @param {*} adminForOrganization the admin fabric client for the organization - * @param {*} contractDefinition the contract definition that defines the install requirements for the chaincode - * @param {*} listOfPeersInOrganizationToInstallOn the list of peers in the organization to install on - * @returns {Promise<[Error]>} Errors encountered during install if any - * @async - * @private - */ - async _installChaincodeOntoOrganizationPeers(adminForOrganization, contractDefinition, listOfPeersInOrganizationToInstallOn) { - const txId = adminForOrganization.newTransactionID(true); - /** @{ChaincodeInstallRequest} */ - const request = { - targets: listOfPeersInOrganizationToInstallOn, - chaincodePath: contractDefinition.install.language === 'golang' ? contractDefinition.install.path : CaliperUtils.resolvePath(contractDefinition.install.path), - chaincodeId: contractDefinition.id, - chaincodeVersion: contractDefinition.install.version, - chaincodeType: contractDefinition.install.language, - txId: txId - }; - - // metadata (like CouchDB indices) are only supported since Fabric v1.1 - if (CaliperUtils.checkProperty(contractDefinition.install, 'metadataPath')) { - request.metadataPath = CaliperUtils.resolvePath(contractDefinition.install.metadataPath); - } - - // install to necessary peers of org and process the results - try { - /** @link{ProposalResponseObject} */ - const propRespObject = await adminForOrganization.installChaincode(request); - CaliperUtils.assertDefined(propRespObject); - - /** Array of @link{ProposalResponse} objects */ - const proposalResponses = propRespObject[0]; - CaliperUtils.assertDefined(proposalResponses); - - const errors = []; - - proposalResponses.forEach((propResponse, index) => { - if (propResponse instanceof Error) { - const errMsg = `Install proposal error for ${contractDefinition.id}@${contractDefinition.install.version} on ${listOfPeersInOrganizationToInstallOn[index]}: ${propResponse.message}`; - errors.push(new Error(errMsg)); - return; - } - - /** @link{ProposalResponse} */ - CaliperUtils.assertProperty(propResponse, 'propResponse', 'response'); - - /** @link{ResponseObject} */ - const response = propResponse.response; - CaliperUtils.assertProperty(response, 'response', 'status'); - - if (response.status !== 200) { - const errMsg = `Unsuccessful install status for ${contractDefinition.id}@${contractDefinition.install.version} on ${listOfPeersInOrganizationToInstallOn[index]}: ${propResponse.response.message}`; - errors.push(new Error(errMsg)); - } - }); - - return errors; - - } catch (err) { - throw new Error(`Couldn't install ${contractDefinition.id}@${contractDefinition.install.version} on peers ${listOfPeersInOrganizationToInstallOn.toString()}: ${err.message}`); - } - } - - /** - * Instantiates the contracts on their channels. - * @return {boolean} True, if at least one contract was instantiated. Otherwise, false. - * @private - * @async - */ - async _instantiateChaincodes() { - let atLeastOneChaincodeInstantiated = false; - const channelNames = this.connectorConfiguration.getAllChannelNames(); - for (const channelName of channelNames) { - - // proceed cc by cc for the channel - const contractDefinitions = this.connectorConfiguration.getContractDefinitionsForChannelName(channelName); - for (const contractDefinition of contractDefinitions) { - - if (!contractDefinition.install) { - continue; - } - - logger.info(`Instantiating ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName}. This might take some time...`); - - const peersInChannelByOrganizationMap = await this.connectorConfiguration.getEndorsingPeersInChannelByOrganizationMap(); - const peersInOrganizationMap = peersInChannelByOrganizationMap.get(channelName); - const mainOrganization = peersInOrganizationMap.keys().next().value; - const endorsingPeersInChannel = await this._getEndorsingPeersInChannel(channelName); - const adminForMainOrganization = await this._getAdminClientForOrganization(mainOrganization); - - await this._instantiateChaincodeOnChannel(adminForMainOrganization, channelName, contractDefinition, endorsingPeersInChannel); - atLeastOneChaincodeInstantiated = true; - } - } - - return atLeastOneChaincodeInstantiated; - } - - /** - * Instantiate a specific chaincode on a specific channel - * @param {*} organizationAdminInChannel An Admin whose organization is in the channel - * @param {*} channelName The name of the channel - * @param {*} contractDefinition The contract definition that defined the chaincode that was installed and optionally instantiation parameters - * @param {*} endorsingPeersInChannel All channel endorsing peers that will endorse the instantiation (ensures ) - * @returns {Promise} true if the chaincode was successfully instantiated - */ - async _instantiateChaincodeOnChannel(organizationAdminInChannel, channelName, contractDefinition, endorsingPeersInChannel) { - /** @link{ChaincodeQueryResponse} */ - let queryResponse; - try { - queryResponse = await organizationAdminInChannel.getChannel(channelName, true).queryInstantiatedChaincodes(endorsingPeersInChannel[0], true); - } catch (err) { - throw new Error(`Couldn't query whether ${contractDefinition.id}@${contractDefinition.install.version} is instantiated on ${endorsingPeersInChannel[0]}: ${err.message}`); - } - - CaliperUtils.assertDefined(queryResponse); - CaliperUtils.assertProperty(queryResponse, 'queryResponse', 'chaincodes'); - - if (queryResponse.chaincodes.some( - cc => cc.name === contractDefinition.id && cc.version === contractDefinition.install.version)) { - logger.info(`${contractDefinition.id}@${contractDefinition.install.version} is already instantiated in ${channelName}`); - return; - } - - const txId = organizationAdminInChannel.newTransactionID(true); - /** @link{ContractInstantiateUpgradeRequest} */ - const request = { - targets: endorsingPeersInChannel, - chaincodeId: contractDefinition.id, - chaincodeVersion: contractDefinition.install.version, - chaincodeType: contractDefinition.install.language, // TODO: is this required ? - args: contractDefinition.instantiate && contractDefinition.instantiate.initArguments ? contractDefinition.instantiate.initArguments : [], - fcn: contractDefinition.instantiate && contractDefinition.instantiate.initFunction ? contractDefinition.instantiate.initFunction : 'init', - transientMap: this._createTransientMap(contractDefinition), - txId: txId - }; - - // check contract language - // other contracts types are not supported in every version - // TODO: maybe this should be in install - if (!['golang', 'node', 'java'].includes(contractDefinition.install.language)) { - throw new Error(`${contractDefinition.id}@${contractDefinition.version} in ${channelName}: unknown contract type ${contractDefinition.install.language}`); - } - - // check private collection configuration - if (contractDefinition.instantiate && CaliperUtils.checkProperty(contractDefinition.instantiate, 'collectionsConfig')) { - request['collections-config'] = contractDefinition.instantiate.collectionsConfig; - } - - if (contractDefinition.instantiate && CaliperUtils.checkProperty(contractDefinition.instantiate, 'endorsementPolicy')) { - request['endorsement-policy'] = contractDefinition.instantiate.endorsementPolicy; - // this.networkUtil.getDefaultEndorsementPolicy(channel, { id: ccObject.id, version: ccObject.version }), // TODO - } - - /** @link{ProposalResponseObject} */ - let response; - try { - response = await organizationAdminInChannel.getChannel(channelName, true).sendInstantiateProposal(request, this.configContractInstantiateTimeout); - } catch (err) { - throw new Error(`Couldn't endorse ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName} on peers [${endorsingPeersInChannel.toString()}]: ${err.message}`); - } - - CaliperUtils.assertDefined(response); - - /** @link{Array} */ - const proposalResponses = response[0]; - /** @link{Proposal} */ - const proposal = response[1]; - CaliperUtils.assertDefined(proposalResponses); - CaliperUtils.assertDefined(proposal); - - // check each response - proposalResponses.forEach((propResp, index) => { - CaliperUtils.assertDefined(propResp); - // an Error is returned for a rejected proposal - if (propResp instanceof Error) { - throw new Error(`Invalid endorsement for ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName} from ${endorsingPeersInChannel[index]}: ${propResp.message}`); - } else if (propResp.response.status !== 200) { - throw new Error(`Invalid endorsement for ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName} from ${endorsingPeersInChannel[index]}: status code ${propResp.response.status}`); - } - }); - - // connect to every event source of every org in the channel - const eventSources = this._assembleTargetEventSources(organizationAdminInChannel, channelName, endorsingPeersInChannel); - const eventPromises = []; - - try { - // NOTE: everything is resolved, errors are signaled through an Error object - // this makes error handling and reporting easier - eventSources.forEach((channelEventHub) => { - const promise = new Promise((resolve) => { - const timeoutHandle = setTimeout(() => { - // unregister manually - channelEventHub.unregisterTxEvent(txId.getTransactionID(), false); - resolve(new Error(`Commit timeout for ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName} from ${channelEventHub.getName()}`)); - }, this.configContractInstantiateEventTimeout); - - channelEventHub.registerTxEvent(txId.getTransactionID(), (tx, code) => { - clearTimeout(timeoutHandle); - if (code !== 'VALID') { - resolve(new Error(`Invalid commit code for ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName} from ${channelEventHub.getName()}: ${code}`)); - } else { - resolve(code); - } - }, /* Error handler */ (err) => { - clearTimeout(timeoutHandle); - resolve(new Error(`Event hub error from ${channelEventHub.getName()} during instantiating ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName}: ${err.message}`)); - }); - - channelEventHub.connect(); - }); - - eventPromises.push(promise); - }); - - /** @link{TransactionRequest} */ - const ordererRequest = { - txId: txId, - proposalResponses: proposalResponses, - proposal: proposal - }; - - /** @link{BroadcastResponse} */ - let broadcastResponse; - try { - broadcastResponse = await organizationAdminInChannel.getChannel(channelName, true).sendTransaction(ordererRequest); - } catch (err) { - throw new Error(`Orderer error for instantiating ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName}: ${err.message}`); - } - - CaliperUtils.assertDefined(broadcastResponse); - CaliperUtils.assertProperty(broadcastResponse, 'broadcastResponse', 'status'); - - if (broadcastResponse.status !== 'SUCCESS') { - throw new Error(`Orderer error for instantiating ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName}: ${broadcastResponse.status}`); - } - - // since every event promise is resolved, this shouldn't throw an error - const eventResults = await Promise.all(eventPromises); - - // if we received an error, propagate it - if (eventResults.some(er => er instanceof Error)) { - let errMsg = `The following errors occured while instantiating ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName}:`; - let err; // keep the last error - for (const eventResult of eventResults) { - if (eventResult instanceof Error) { - err = eventResult; - errMsg += `\n\t- ${eventResult.message}`; - } - } - - logger.error(errMsg); - throw err; - } - - logger.info(`Successfully instantiated ${contractDefinition.id}@${contractDefinition.install.version} in ${channelName}`); - return true; - } finally { - eventSources.forEach(channelEventHub => { - if (channelEventHub.isconnected()) { - channelEventHub.disconnect(); - } - }); - } - } - - /** - * Assembles the event sources based on explicitly given target peers. - * @param {Client} organizationAdminInChannel a fabric client - * @param {string} channelName The name of channel containing the target peers. Doesn't matter if peer-level event service is used in compatibility mode. - * @param {string[]} targetPeers The list of peers to connect to. - * @return {ChannelEventHub[]} The list of event sources. - * @private - */ - _assembleTargetEventSources(organizationAdminInChannel, channelName, targetPeers) { - const eventSources = []; - for (const peer of targetPeers) { - const eventHub = organizationAdminInChannel.getChannel(channelName, true).newChannelEventHub(peer); - eventSources.push(eventHub); - } - - return eventSources; - } - - /** - * Create a transient map from initTransientMap definition in a contract definition - * @param {*} contractDefinition The contract definition. - * @returns {Map} the transient Map - * @private - */ - _createTransientMap(contractDefinition) { - const map = {}; - - if (!contractDefinition.instantiate || !CaliperUtils.checkProperty(contractDefinition.instantiate, 'initTransientMap')) { - return map; - } - - for (const key in contractDefinition.instantiate.initTransientMap) { - if (!contractDefinition.instantiate.initTransientMap.hasOwnProperty(key)) { - continue; - } - - const value = contractDefinition.instantiate.initTransientMap[key]; - map[key.toString()] = Buffer.from(value.toString()); - } - - return map; - } - - /** - * get a list of all the endorsing peers in the channel by looking at one of the connection profiles for an organization - * in the channel - * @param {*} channelName The name of the channel - * @async - * @private - */ - async _getEndorsingPeersInChannel(channelName) { - const peersInChannelByOrganizationMap = await this.connectorConfiguration.getEndorsingPeersInChannelByOrganizationMap(); - const peersInOrganizationMap = peersInChannelByOrganizationMap.get(channelName); - - if (peersInOrganizationMap.size === 0) { - throw new Error(`could not find any organisations with peers for channel ${channelName}`); - } - - const mainOrganization = peersInOrganizationMap.keys().next().value; - const connectionProfileDefinition = await this.connectorConfiguration.getConnectionProfileDefinitionForOrganization(mainOrganization); - return connectionProfileDefinition.getEndorsingPeersInChannel(channelName); - } - - /** - * get an admin client instance for the specified organization - * - * @param {*} organization organization - * @async - * @private - */ - async _getAdminClientForOrganization(organization) { - if (!this.aliasNameToFabricClientMap) { - const clientCreator = new ClientCreator(this.connectorConfiguration); - this.aliasNameToFabricClientMap = await clientCreator.createFabricClientsForAllIdentities(); - } - - const adminAliasNames = this.connectorConfiguration.getAdminAliasNamesForOrganization(organization); - if (adminAliasNames.length === 0) { - throw new Error(`No Organization admin for ${organization} has been declared in the network configuration`); - } - - return this.aliasNameToFabricClientMap.get(adminAliasNames[0]); - } -} - -module.exports = FabricChaincodeOperations; diff --git a/packages/caliper-fabric/lib/connector-versions/v1/FabricChannelOperations.js b/packages/caliper-fabric/lib/connector-versions/v1/FabricChannelOperations.js deleted file mode 100644 index 0950e39ef..000000000 --- a/packages/caliper-fabric/lib/connector-versions/v1/FabricChannelOperations.js +++ /dev/null @@ -1,401 +0,0 @@ -/* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -const FabricClient = require('fabric-client'); -const { google, common } = require('fabric-protos'); -const { CaliperUtils, ConfigUtil } = require('@hyperledger/caliper-core'); -const fs = require('fs'); -const ClientCreator = require('./ClientCreator'); - -const logger = CaliperUtils.getLogger('connectors/v1/FabricChannelOperations'); - -/** */ -class FabricChannelOperations { - - /** - * @param {*} connectorConfiguration v - * @param {*} aliasNameToClientMap v - */ - constructor(connectorConfiguration) { - this.connectorConfiguration = connectorConfiguration; - this.aliasNameToFabricClientMap = null; - - this.configSleepAfterCreateChannel = ConfigUtil.get(ConfigUtil.keys.Fabric.SleepAfter.CreateChannel, 5000); - this.configSleepAfterJoinChannel = ConfigUtil.get(ConfigUtil.keys.Fabric.SleepAfter.JoinChannel, 5000); - } - - /** - * Create all the channels and join the required peers to those created channels - */ - async createChannelsAndJoinPeers() { - const channelCreated = await this._createChannels(); - if (channelCreated) { - logger.info(`Sleeping ${this.configSleepAfterCreateChannel / 1000.0}s...`); - await CaliperUtils.sleep(this.configSleepAfterCreateChannel); - await this._joinPeersToCreatedChannels(); - logger.info(`Sleeping ${this.configSleepAfterJoinChannel / 1000.0}s...`); - await CaliperUtils.sleep(this.configSleepAfterJoinChannel); - } - } - - /** - * Creates the specified channels if necessary. - * @return {boolean} True, if at least one channel was created. Otherwise, false. - * @private - * @async - */ - async _createChannels() { - let atLeastOneChannelCreated = false; - const channelNamesToCreate = this.connectorConfiguration.getChannelNamesForCreation(); - - for (const channelNameToCreate of channelNamesToCreate) { - const channelCreationDefinition = this.connectorConfiguration.getCreationDefinitionForChannelName(channelNameToCreate); - - if (ConfigUtil.get(ConfigUtil.keys.Fabric.SkipCreateChannelPrefix + channelNameToCreate, false)) { - logger.info(`Creation of Channel '${channelNameToCreate}' is configured to skip`); - continue; - } - - let configUpdate; - if (CaliperUtils.checkProperty(channelCreationDefinition, 'prebuiltTransaction')) { - logger.info(`Channel '${channelNameToCreate}' definiton being retrieved from file`); - configUpdate = this._getChannelConfigFromFile(channelCreationDefinition.prebuiltTransaction, channelNameToCreate); - } - else if (CaliperUtils.checkProperty(channelCreationDefinition, 'buildTransaction')) { - logger.info(`Channel '${channelNameToCreate}' definiton being generated from description`); - const channelTx = this._createChannelTxEnvelope(channelCreationDefinition.buildTransaction, channelNameToCreate); - const payload = common.Payload.decode(channelTx.getPayload().toBuffer()); - const configtx = common.ConfigUpdateEnvelope.decode(payload.getData().toBuffer()); - configUpdate = configtx.getConfigUpdate().toBuffer(); - } else { - throw new Error('Channel creation specified but no prebuiltTransaction or buildTransaction provided'); - } - - // NOTE: without knowing the system channel policies, signing with every org admin is a safe bet - const peersInChannelByOrganizationMap = await this.connectorConfiguration.getEndorsingPeersInChannelByOrganizationMap(); - const peersInOrganizationMap = peersInChannelByOrganizationMap.get(channelNameToCreate); - - const signatures = []; - - let admin; - for (const organization of peersInOrganizationMap.keys()) { - admin = await this._getAdminClientForOrganization(organization); - try { - signatures.push(admin.signChannelConfig(configUpdate)); - } catch (err) { - throw new Error(`${organization}'s admin couldn't sign the configuration update of Channel '${channelNameToCreate}': ${err.message}`); - } - } - - const txId = admin.newTransactionID(true); - const request = { - config: configUpdate, - signatures: signatures, - name: channelNameToCreate, - txId: txId - }; - - try { - /** @link{BroadcastResponse} */ - const broadcastResponse = await admin.createChannel(request); - - CaliperUtils.assertDefined(broadcastResponse, `The returned broadcast response for creating Channel '${channelNameToCreate}' is undefined`); - CaliperUtils.assertProperty(broadcastResponse, 'broadcastResponse', 'status'); - - if (broadcastResponse.status !== 'SUCCESS') { - throw new Error(`Orderer response indicated unsuccessful Channel '${channelNameToCreate}' creation: ${broadcastResponse.status}`); - } - } catch (err) { - throw new Error(`Couldn't create Channel '${channelNameToCreate}': ${err.message}`); - } - - logger.info(`Channel '${channelNameToCreate}' successfully created`); - atLeastOneChannelCreated = true; - } - - return atLeastOneChannelCreated; - } - - /** - * Populate an envelope with a channel creation transaction - * @param {object} channelDefinition The channel configuration object. - * @param {string} channelName The name of the channel. - * @return {Buffer} The extracted channel configuration bytes. - * @private - */ - _createChannelTxEnvelope(channelDefinition, channelName) { - // Versioning - const readVersion = 0; - const writeVersion = 0; - const appVersion = 1; - const policyVersion = 0; - - // Build the readSet - const readValues = {}; - readValues.Consortium = new common.ConfigValue(); - - const readAppGroup = {}; - for (const mspId of channelDefinition.msps) { - readAppGroup[mspId] = new common.ConfigGroup(); - } - const readGroups = {}; - readGroups.Application = new common.ConfigGroup({ groups: readAppGroup }); - - const readSet = new common.ConfigGroup({ version: readVersion, groups: readGroups, values: readValues }); - - // Build the writeSet (based on consortium name and passed Capabiliites) - const modPolicy = 'Admins'; - const writeValues = {}; - - const consortium = new common.Consortium({ name: channelDefinition.consortium }); - writeValues.Consortium = new common.ConfigValue({ version: writeVersion, value: consortium.toBuffer() }); - - if (channelDefinition.capabilities) { - const capabilities = this._populateCapabilities(channelDefinition.capabilities); - writeValues.Capabilities = new common.ConfigValue({ version: writeVersion, value: capabilities.toBuffer(), mod_policy: modPolicy }); - } - - // Write Policy - const writePolicies = this._generateWritePolicy(policyVersion, modPolicy); - - // Write Application Groups - const writeAppGroup = {}; - for (const mspId of channelDefinition.msps) { - writeAppGroup[mspId] = new common.ConfigGroup(); - } - - const writeGroups = {}; - writeGroups.Application = new common.ConfigGroup({ version: appVersion, groups: writeAppGroup, policies: writePolicies, mod_policy: modPolicy }); - - const writeSet = new common.ConfigGroup({ version: writeVersion, groups: writeGroups, values: writeValues }); - - // Now create the configUpdate and configUpdateEnv - const configUpdate = new common.ConfigUpdate({ channel_id: channelName, read_set: readSet, write_set: writeSet}); - const configUpdateEnv= new common.ConfigUpdateEnvelope({ config_update: configUpdate.toBuffer(), signatures: [] }); - - // Channel header - const channelTimestamp = new google.protobuf.Timestamp({ seconds: Date.now()/1000, nanos: 0 }); // Date.now() is millis since 1970 epoch, we need seconds - const channelEpoch = 0; - const chHeader = new common.ChannelHeader({ type: common.HeaderType.CONFIG_UPDATE, version: channelDefinition.version, timestamp: channelTimestamp, channel_id: channelName, epoch: channelEpoch }); - - // Common header - const header = new common.Header({ channel_header: chHeader.toBuffer() }); - - // Form the payload header/data - const payload = new common.Payload({ header: header, data: configUpdateEnv.toBuffer() }); - - // Form and return the envelope - const envelope = new common.Envelope({ payload: payload.toBuffer() }); - return envelope; - } - - /** - * Populate a Capabilities protobuf - * @param {Array} applicationCapabilities the application capability keys - * @returns {common.Capabilities} Capabilities in a protobuff - */ - _populateCapabilities(applicationCapabilities) { - const capabilities = {}; - for (const capability of applicationCapabilities) { - capabilities[capability] = new common.Capability(); - } - return new common.Capabilities({ capabilities: capabilities }); - } - - /** - * Form a populted Poicy protobuf that contains an ImplicitMetaPolicy - * @param {String} subPolicyName the sub policy name - * @param {common.Policy.PolicyType} rule the rule type - * @returns {common.Policy} the policy protobuf - */ - _makeImplicitMetaPolicy(subPolicyName, rule){ - const metaPolicy = new common.ImplicitMetaPolicy({ sub_policy: subPolicyName, rule: rule }); - const policy= new common.Policy({ type: common.Policy.PolicyType.IMPLICIT_META, value: metaPolicy.toBuffer() }); - return policy; - } - - /** - * Generate a write policy - * @param {number} version the policy version - * @param {string} modPolicy the modification policy - * @returns {Object} an object of Admin/Reader/Writer keys mapping to populated ConfigPolicy protobuffs - */ - _generateWritePolicy(version, modPolicy) { - // Write Policy - const writePolicies = {}; - // admins - const adminsPolicy = this._makeImplicitMetaPolicy('Admins', common.ImplicitMetaPolicy.Rule.MAJORITY); // majority - writePolicies.Admins = new common.ConfigPolicy({ version: version, policy: adminsPolicy, mod_policy: modPolicy }); - // Readers - const readersPolicy = this._makeImplicitMetaPolicy('Readers', common.ImplicitMetaPolicy.Rule.ANY); // Any - writePolicies.Readers = new common.ConfigPolicy({ version: version, policy: readersPolicy, mod_policy: modPolicy }); - // Writers - const writersPolicy = this._makeImplicitMetaPolicy('Writers', common.ImplicitMetaPolicy.Rule.ANY); // Any - writePolicies.Writers = new common.ConfigPolicy({ version: version, policy: writersPolicy, mod_policy: modPolicy }); - return writePolicies; - } - - /** - * Extracts the channel configuration from the configured file. - * @param {object} prebuiltTransactionFile The channel configuration file - * @param {string} channelName The name of the channel. - * @return {Buffer} The extracted channel configuration bytes. - * @private - */ - _getChannelConfigFromFile(prebuiltTransactionFile, channelName) { - // extracting the config from the binary file - const binaryPath = CaliperUtils.resolvePath(prebuiltTransactionFile); - let envelopeBytes; - - try { - envelopeBytes = fs.readFileSync(binaryPath); - } catch (err) { - throw new Error(`Couldn't read configuration binary for ${channelName}: ${err.message}`); - } - - try { - return new FabricClient().extractChannelConfig(envelopeBytes); - } catch (err) { - throw new Error(`Couldn't extract configuration object for ${channelName}: ${err.message}`); - } - } - - /** - * Join peers to the created channels - * @async - * @private - */ - async _joinPeersToCreatedChannels() { - const channelNamesForCreation = this.connectorConfiguration.getChannelNamesForCreation(); - const errors = []; - - for (const channelNameToJoin of channelNamesForCreation) { - let genesisBlock = null; - const peersInChannelByOrganizationMap = await this.connectorConfiguration.getEndorsingPeersInChannelByOrganizationMap(); - const peersInOrganizationMap = peersInChannelByOrganizationMap.get(channelNameToJoin); - - for (const [organization, peersInOrganization] of peersInOrganizationMap) { - const admin = await this._getAdminClientForOrganization(organization); - const channelObject = admin.getChannel(channelNameToJoin, true); - - const peersToJoin = []; - - for (const peerInOrganization of peersInOrganization) { - try { - /** {@link ChannelQueryResponse} */ - const resp = await admin.queryChannels(peerInOrganization, true); - - if (resp.channels.some(ch => ch.channel_id === channelNameToJoin)) { - logger.info(`${peerInOrganization} has already joined ${channelNameToJoin}`); - continue; - } - - peersToJoin.push(peerInOrganization); - } catch (err) { - errors.push(new Error(`Couldn't query ${channelNameToJoin} information from ${peerInOrganization}: ${err.message}`)); - } - } - - if (errors.length > 0) { - let errMsg = `The following errors occurred while querying ${channelNameToJoin} information from ${organization}'s peers:`; - for (const err of errors) { - errMsg += `\n\t- ${err.message}`; - } - - logger.error(errMsg); - throw new Error(`Couldn't query ${channelNameToJoin} information from ${organization}'s peers`); - } - - // all target peers of the org have already joined the channel - if (peersToJoin.length < 1) { - continue; - } - - // only retrieve the genesis block once, and "cache" it - if (genesisBlock === null) { - try { - const genesisTxId = admin.newTransactionID(true); - /** @link{OrdererRequest} */ - const genesisRequest = { - txId: genesisTxId - }; - genesisBlock = await channelObject.getGenesisBlock(genesisRequest); - } catch (err) { - throw new Error(`Couldn't retrieve the genesis block for ${channelNameToJoin}: ${err.message}`); - } - } - - const joinTxId = admin.newTransactionID(true); - const joinRequest = { - block: genesisBlock, - txId: joinTxId, - targets: peersToJoin - }; - - try { - /**{@link ProposalResponse} array*/ - const joinRespArray = await channelObject.joinChannel(joinRequest); - CaliperUtils.assertDefined(joinRespArray); - - // Some errors are returned as Error instances, some as error messages - joinRespArray.forEach((propResponse, index) => { - if (propResponse instanceof Error) { - errors.push(new Error(`${peersToJoin[index]} could not join ${channelNameToJoin}: ${propResponse.message}`)); - } else if (propResponse.response.status !== 200) { - errors.push(new Error(`${peersToJoin[index]} could not join ${channelNameToJoin}: ${propResponse.response.message}`)); - } - }); - } catch (err) { - throw new Error(`Couldn't join peers ${peersToJoin.toString()} to ${channelNameToJoin}: ${err.message}`); - } - - if (errors.length > 0) { - let errMsg = `The following errors occurred while ${organization}'s peers tried to join ${channelNameToJoin}:`; - for (const err of errors) { - errMsg += `\n\t- ${err.message}`; - } - - logger.error(errMsg); - throw new Error(`${organization}'s peers couldn't join ${channelNameToJoin}`); - } - - logger.info(`${organization}'s peers successfully joined ${channelNameToJoin}: ${peersToJoin}`); - } - } - } - - /** - * get an admin client instance for the specified organization - * - * @param {*} organization organization - * @async - */ - async _getAdminClientForOrganization(organization) { - if (!this.aliasNameToFabricClientMap) { - const clientCreator = new ClientCreator(this.connectorConfiguration); - this.aliasNameToFabricClientMap = await clientCreator.createFabricClientsForAllIdentities(); - } - - const adminAliasNames = this.connectorConfiguration.getAdminAliasNamesForOrganization(organization); - if (adminAliasNames.length === 0) { - throw new Error(`No Organization admin for ${organization} has been declared in the network configuration`); - } - - return this.aliasNameToFabricClientMap.get(adminAliasNames[0]); - } -} - -module.exports = FabricChannelOperations; diff --git a/packages/caliper-fabric/lib/connector-versions/v1/FabricGateway.js b/packages/caliper-fabric/lib/connector-versions/v1/FabricGateway.js index 96246d015..924b1eb3d 100644 --- a/packages/caliper-fabric/lib/connector-versions/v1/FabricGateway.js +++ b/packages/caliper-fabric/lib/connector-versions/v1/FabricGateway.js @@ -17,8 +17,6 @@ const semver = require('semver'); const { DefaultEventHandlerStrategies, DefaultQueryHandlerStrategies, Gateway } = require('fabric-network'); const { ConnectorBase, CaliperUtils, TxStatus, ConfigUtil } = require('@hyperledger/caliper-core'); const FabricConnectorContext = require('../../FabricConnectorContext'); -const FabricChannelOperations = require('./FabricChannelOperations'); -const FabricChaincodeOperations = require('./FabricChaincodeOperations'); const logger = CaliperUtils.getLogger('connectors/v1/FabricGateway'); @@ -133,9 +131,6 @@ class V1FabricGateway extends ConnectorBase { const tlsInfo = this.connectorConfiguration.isMutualTLS() ? 'mutual' : ((await this.connectorConfiguration.getConnectionProfileDefinitionForOrganization(defaultOrganization)).isTLSEnabled() ? 'server' : 'none'); logger.info(`Fabric SDK version: ${this.fabricNetworkVersion.toString()}; TLS based on ${defaultOrganization}: ${tlsInfo}`); - - const fabricChannelOperations = new FabricChannelOperations(this.connectorConfiguration); - await fabricChannelOperations.createChannelsAndJoinPeers(); } /** @@ -143,8 +138,7 @@ class V1FabricGateway extends ConnectorBase { * @async */ async installSmartContract() { - const fabricChaincodeOperations = new FabricChaincodeOperations(this.connectorConfiguration); - await fabricChaincodeOperations.installAndInstantiateChaincodes(); + logger.warn(`Install smart contract not available with Fabric SDK version: ${this.fabricNetworkVersion.toString()}`); } /** diff --git a/packages/caliper-fabric/lib/connector-versions/v1/FabricNonGateway.js b/packages/caliper-fabric/lib/connector-versions/v1/FabricNonGateway.js index a62ba9b40..ee93b0611 100644 --- a/packages/caliper-fabric/lib/connector-versions/v1/FabricNonGateway.js +++ b/packages/caliper-fabric/lib/connector-versions/v1/FabricNonGateway.js @@ -18,8 +18,6 @@ const FabricConstants = require('fabric-client/lib/Constants'); const {ConnectorBase, CaliperUtils, TxStatus, Version, ConfigUtil} = require('@hyperledger/caliper-core'); const FabricConnectorContext = require('../../FabricConnectorContext'); const ClientCreator = require('./ClientCreator'); -const FabricChannelOperations = require('./FabricChannelOperations'); -const FabricChaincodeOperations = require('./FabricChaincodeOperations'); const logger = CaliperUtils.getLogger('connectors/v1/FabricNonGateway'); /** @@ -129,9 +127,6 @@ class V1Fabric extends ConnectorBase { const tlsInfo = this.connectorConfiguration.isMutualTLS() ? 'mutual' : ((await this.connectorConfiguration.getConnectionProfileDefinitionForOrganization(defaultOrganization)).isTLSEnabled() ? 'server' : 'none'); logger.info(`Fabric SDK version: ${this.fabricNetworkVersion.toString()}; TLS based on ${defaultOrganization}: ${tlsInfo}`); - - const fabricChannelOperations = new FabricChannelOperations(this.connectorConfiguration); - await fabricChannelOperations.createChannelsAndJoinPeers(); } /** @@ -139,8 +134,7 @@ class V1Fabric extends ConnectorBase { * @async */ async installSmartContract() { - const fabricChaincodeOperations = new FabricChaincodeOperations(this.connectorConfiguration); - await fabricChaincodeOperations.installAndInstantiateChaincodes(); + logger.warn(`Install smart contract not available with Fabric SDK version: ${this.fabricNetworkVersion.toString()}`); } /** diff --git a/packages/caliper-fabric/package.json b/packages/caliper-fabric/package.json index 71631fb4e..e120d7a16 100644 --- a/packages/caliper-fabric/package.json +++ b/packages/caliper-fabric/package.json @@ -27,7 +27,6 @@ "semver": "7.1.1" }, "devDependencies": { - "fabric-protos": "2.1.0", "chai": "^3.5.0", "chai-as-promised": "^7.1.1", "eslint": "^5.16.0", @@ -88,8 +87,6 @@ "lib/identity-management/IWallet*", "lib/connector-versions/v1/fabric-gateway.js", "lib/connector-versions/v1/fabric.js", - "lib/connector-versions/v1/FabricChaincodeOperations.js", - "lib/connector-versions/v1/FabricChannelOperations.js", "lib/connector-versions/v2/fabric-gateway.js", "lib/connector-versions/v2/registrarHelper.js" ], @@ -105,4 +102,4 @@ "lines": 1 }, "license": "Apache-2.0" -} \ No newline at end of file +} diff --git a/packages/caliper-fabric/test/connector-versions/v1/FabricGateway.js b/packages/caliper-fabric/test/connector-versions/v1/FabricGateway.js index f673d45a8..8bdb20720 100644 --- a/packages/caliper-fabric/test/connector-versions/v1/FabricGateway.js +++ b/packages/caliper-fabric/test/connector-versions/v1/FabricGateway.js @@ -57,14 +57,6 @@ describe('A Node-SDK V1 Fabric Gateway', () => { mockery.registerMock('fabric-client', Client); mockery.registerMock('fabric-client/lib/Constants', Constants); mockery.registerMock('fabric-network/package', {version: '1.4.11'}); - mockery.registerMock('./FabricChannelOperations', class { - /** */ - async createChannelsAndJoinPeers() {} - }); - mockery.registerMock('./FabricChaincodeOperations', class { - /** */ - async installAndInstantiateChaincodes() {} - }); FabricGateway = require('../../../lib/connector-versions/v1/FabricGateway'); GenerateWallet = require('../../utils/GenerateWallet'); diff --git a/packages/caliper-fabric/test/connector-versions/v1/FabricNonGateway.js b/packages/caliper-fabric/test/connector-versions/v1/FabricNonGateway.js index 916431255..7a563735a 100644 --- a/packages/caliper-fabric/test/connector-versions/v1/FabricNonGateway.js +++ b/packages/caliper-fabric/test/connector-versions/v1/FabricNonGateway.js @@ -46,14 +46,6 @@ describe('A Node-SDK V1 Fabric Non Gateway', () => { mockery.registerMock('fabric-client', Client); mockery.registerMock('fabric-client/lib/Constants', Constants); mockery.registerMock('fabric-client/package', {version: '1.4.11'}); - mockery.registerMock('./FabricChannelOperations', class { - /** */ - async createChannelsAndJoinPeers() {} - }); - mockery.registerMock('./FabricChaincodeOperations', class { - /** */ - async installAndInstantiateChaincodes() {} - }); FabricNonGateway = require('../../../lib/connector-versions/v1/FabricNonGateway'); FabricConnectorContext = require('../../../lib/FabricConnectorContext');