From c3b5cb97bd4a5d4e50c46f50c07fdbfdaacd13b5 Mon Sep 17 00:00:00 2001 From: Bret Harrison Date: Fri, 5 May 2017 13:45:46 -0400 Subject: [PATCH] [FAB-3568] NodeSDK - Remove nonce requirement Autogenerate the generate the nonce and the txId at the same time and return both in a "TransactionID" object. Users will be able to have a transaction value to be used for tracking and SDK will be able to provide the correct 'nonce' for the transaction id. Remove all user API referrences to the 'nonce' and update all test cases required. Change-Id: I6429733c1ee7ecae642f6cd3b0518b3cbddd1691 Signed-off-by: Bret Harrison --- fabric-client/lib/Chain.js | 166 +++++------- fabric-client/lib/Client.js | 92 ++++--- fabric-client/lib/Constants.js | 2 + fabric-client/lib/TransactionID.js | 72 ++++++ test/integration/create-configtx-channel.js | 6 +- test/integration/e2e/create-channel.js | 8 +- test/integration/e2e/e2eUtils.js | 93 +++---- test/integration/e2e/join-channel.js | 13 +- test/integration/e2e/update-channel.js | 6 +- test/integration/e2e/upgrade.js | 1 - test/integration/events.js | 7 +- test/integration/eventutil.js | 6 +- test/integration/get-config.js | 2 - test/integration/grpc.js | 8 +- test/integration/install.js | 8 +- test/integration/marbles.js | 23 +- test/integration/new-chain.js | 2 - test/integration/query.js | 2 - test/integration/upgrade.js | 21 +- test/unit/chain.js | 269 +++++++------------- test/unit/client.js | 124 +++------ test/unit/transactionid.js | 65 +++++ test/unit/user.js | 2 + 23 files changed, 463 insertions(+), 535 deletions(-) create mode 100644 fabric-client/lib/TransactionID.js create mode 100644 test/unit/transactionid.js diff --git a/fabric-client/lib/Chain.js b/fabric-client/lib/Chain.js index a9159b2d67..2c5bd3861b 100755 --- a/fabric-client/lib/Chain.js +++ b/fabric-client/lib/Chain.js @@ -27,6 +27,7 @@ var ChannelConfig = require('./ChannelConfig.js'); var Peer = require('./Peer.js'); var Orderer = require('./Orderer.js'); var BlockDecoder = require('./BlockDecoder.js'); +var TransactionID = require('./TransactionID.js'); var settle = require('promise-settle'); var grpc = require('grpc'); var logger = utils.getLogger('Chain.js'); @@ -414,8 +415,7 @@ var Chain = class { * Will get the genesis block from the defined orderer that may be * used in a join request * @param {Object} request - An object containing the following fields: - *
`txId` : required - String of the transaction id - *
`nonce` : required - Integer of the once time number + *
`txId` : required - {@link TransactionID} object with the transaction id and nonce * * @returns {Promise} A Promise for a protobuf `Block` * @see /protos/peer/proposal_response.proto @@ -432,10 +432,6 @@ var Chain = class { else if(!request.txId) { errorMsg = 'Missing txId input parameter with the required transaction identifier'; } - // verify that we have the nonce - else if(!request.nonce) { - errorMsg = 'Missing nonce input parameter with the required single use number'; - } if(errorMsg) { logger.error('getGenesisBlock - error '+ errorMsg); @@ -472,11 +468,11 @@ var Chain = class { var seekInfoHeader = Chain._buildChannelHeader( _commonProto.HeaderType.DELIVER_SEEK_INFO, self._name, - request.txId, + request.txId.getTransactionID(), self._initial_epoch ); - var seekHeader = Chain._buildHeader(userContext.getIdentity(), seekInfoHeader, request.nonce); + var seekHeader = Chain._buildHeader(userContext.getIdentity(), seekInfoHeader, request.txId.getNonce()); var seekPayload = new _commonProto.Payload(); seekPayload.setHeader(seekHeader); seekPayload.setData(seekInfo.toBuffer()); @@ -503,8 +499,7 @@ var Chain = class { * this channel *
`block` : the genesis block of the channel * see getGenesisBlock() method - *
`txId` : required - String of the transaction id - *
`nonce` : required - Integer of the once time number + *
`txId` : required - {@link TransactionID} object with the transaction id and nonce * @returns {Promise} A Promise for a `ProposalResponse` * @see /protos/peer/proposal_response.proto */ @@ -528,11 +523,6 @@ var Chain = class { errorMsg = 'Missing txId input parameter with the required transaction identifier'; } - // verify that we have the nonce - else if(!request.nonce) { - errorMsg = 'Missing nonce input parameter with the required single use number'; - } - else if(!request.block) { errorMsg = 'Missing block input parameter with the required genesis block'; } @@ -552,7 +542,7 @@ var Chain = class { chaincodeInput.setArgs(args); var chaincodeID = new _ccProto.ChaincodeID(); - chaincodeID.setName('cscc'); + chaincodeID.setName(Constants.CSCC); var chaincodeSpec = new _ccProto.ChaincodeSpec(); chaincodeSpec.setType(_ccProto.ChaincodeSpec.Type.GOLANG); @@ -562,12 +552,12 @@ var Chain = class { var channelHeader = Chain._buildChannelHeader( _commonProto.HeaderType.ENDORSER_TRANSACTION, '', - request.txId, + request.txId.getTransactionID(), null, //no epoch - 'cscc' + Constants.CSCC ); - var header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.nonce); + var header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.txId.getNonce()); var proposal = Chain._buildProposal(chaincodeSpec, header); var signed_proposal = Chain._signProposal(userContext.getSigningIdentity(), proposal); @@ -599,8 +589,7 @@ var Chain = class { var orderer = self.getOrderers()[0]; userContext = this._clientContext.getUserContext(); - var nonce = utils.getNonce(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); // seek the latest block var seekSpecifiedStart = new _abProto.SeekNewest(); @@ -621,11 +610,11 @@ var Chain = class { var seekInfoHeader = Chain._buildChannelHeader( _commonProto.HeaderType.DELIVER_SEEK_INFO, self._name, - tx_id, + txId.getTransactionID(), self._initial_epoch ); - var seekHeader = Chain._buildHeader(userContext.getIdentity(), seekInfoHeader, nonce); + var seekHeader = Chain._buildHeader(userContext.getIdentity(), seekInfoHeader, txId.getNonce()); var seekPayload = new _commonProto.Payload(); seekPayload.setHeader(seekHeader); seekPayload.setData(seekInfo.toBuffer()); @@ -659,8 +648,7 @@ var Chain = class { var last_config = _commonProto.LastConfig.decode(metadata.value); logger.debug('getChannelConfig - latest block has config block of %s',last_config.index); - var nonce = utils.getNonce(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); // now build the seek info to get the block called out // as the latest config block @@ -686,11 +674,11 @@ var Chain = class { var seekInfoHeader = Chain._buildChannelHeader( _commonProto.HeaderType.DELIVER_SEEK_INFO, self._name, - tx_id, + txId.getTransactionID(), self._initial_epoch ); - var seekHeader = Chain._buildHeader(userContext.getIdentity(), seekInfoHeader, nonce); + var seekHeader = Chain._buildHeader(userContext.getIdentity(), seekInfoHeader, txId.getNonce()); var seekPayload = new _commonProto.Payload(); seekPayload.setHeader(seekHeader); seekPayload.setData(seekInfo.toBuffer()); @@ -829,15 +817,13 @@ var Chain = class { queryInfo() { logger.debug('queryInfo - start'); var self = this; - var nonce = utils.getNonce(); var userContext = this._clientContext.getUserContext(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); var request = { targets: [self.getPrimaryPeer()], - chaincodeId : 'qscc', + chaincodeId : Constants.QSCC, chainId: '', - txId: tx_id, - nonce: nonce, + txId: txId, fcn : 'GetChainInfo', args: [ self._name] }; @@ -885,15 +871,13 @@ var Chain = class { return Promise.reject( new Error('Blockhash bytes are required')); } var self = this; - var nonce = utils.getNonce(); var userContext = this._clientContext.getUserContext(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); var request = { targets: [self.getPrimaryPeer()], - chaincodeId : 'qscc', + chaincodeId : Constants.QSCC, chainId: '', - txId: tx_id, - nonce: nonce, + txId: txId, fcn : 'GetBlockByHash', args: [ self._name], argbytes : blockHash @@ -946,15 +930,13 @@ var Chain = class { return Promise.reject( new Error('Block number must be a postive integer')); } var self = this; - var nonce = utils.getNonce(); var userContext = self._clientContext.getUserContext(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); var request = { targets: [self.getPrimaryPeer()], - chaincodeId : 'qscc', + chaincodeId : Constants.QSCC, chainId: '', - txId: tx_id, - nonce: nonce, + txId: txId, fcn : 'GetBlockByNumber', args: [ self._name, block_number] }; @@ -994,29 +976,27 @@ var Chain = class { /** * Queries the ledger for Transaction by number. * This query will be made to the primary peer. - * @param {number} transactionID + * @param tx_id The id of the transaction * @returns {object} Transaction information containing the transaction. */ - queryTransaction(transactionID) { - logger.debug('queryTransaction - start transactionID %s',transactionID); + queryTransaction(tx_id) { + logger.debug('queryTransaction - start transactionID %s',tx_id); var transaction_id = null; - if(transactionID) { - transaction_id = transactionID.toString(); + if(tx_id) { + tx_id = tx_id.toString(); } else { - return Promise.reject( new Error('Transaction id is required')); + return Promise.reject( new Error('Missing "tx_id" parameter')); } var self = this; - var nonce = utils.getNonce(); var userContext = self._clientContext.getUserContext(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); var request = { targets: [self.getPrimaryPeer()], - chaincodeId : 'qscc', + chaincodeId : Constants.QSCC, chainId: '', - txId: tx_id, - nonce: nonce, + txId: txId, fcn : 'GetTransactionByID', - args: [ self._name, transaction_id] + args: [ self._name, tx_id] }; return self.sendTransactionProposal(request) .then( @@ -1057,15 +1037,13 @@ var Chain = class { queryInstantiatedChaincodes() { logger.debug('queryInstantiatedChaincodes - start'); var self = this; - var nonce = utils.getNonce(); var userContext = self._clientContext.getUserContext(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(userContext); var request = { targets: [self.getPrimaryPeer()], chaincodeId : Constants.LSCC, chainId: self._name, - txId: tx_id, - nonce: nonce, + txId: txId, fcn : 'getchaincodes', args: [] }; @@ -1118,11 +1096,10 @@ var Chain = class { * the source code of the chaincode *
`chaincodeId` : required - String of the name of the chaincode *
`chaincodeVersion` : required - String of the version of the chaincode - *
`txId` : required - String of the transaction id + *
`txId` : required - {@link TransactionID} object with the transaction id and nonce *
`transientMap` : optional - map that can be used by * the chaincode but not saved in the ledger, such as cryptographic information * for encryption - *
`nonce` : required - Integer of the once time number *
`fcn` : optional - String of the function to be called on * the chaincode once instantiated (default 'init') *
`args` : optional - String Array arguments specific to @@ -1174,11 +1151,10 @@ var Chain = class { * the source code of the chaincode *
`chaincodeId` : required - String of the name of the chaincode *
`chaincodeVersion` : required - String of the version of the chaincode - *
`txId` : required - String of the transaction id + *
`txId` : required - {@link TransactionID} object with the transaction id and nonce *
`transientMap` : optional - map that can be used by * the chaincode but not saved in the ledger, such as cryptographic information * for encryption - *
`nonce` : required - Integer of the once time number *
`fcn` : optional - String of the function to be called on * the chaincode once instantiated (default 'init') *
`args` : optional - String Array arguments specific to @@ -1269,11 +1245,11 @@ var Chain = class { var channelHeader = Chain._buildChannelHeader( _commonProto.HeaderType.ENDORSER_TRANSACTION, self._name, - request.txId, + request.txId.getTransactionID(), null, Constants.LSCC ); - header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.nonce); + header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.txId.getNonce()); proposal = Chain._buildProposal(lcccSpec, header, request.transientMap); let signed_proposal = Chain._signProposal(userContext.getSigningIdentity(), proposal); @@ -1290,11 +1266,9 @@ var Chain = class { * * @param {Object} request *
`targets` : optional -- The peers that will receive this request, - * when not provided the peers assigned to this channel will - * be used. + * when not provided the peers assigned to this channel will be used. *
`chaincodeId` : The id of the chaincode to perform the transaction proposal - *
`txId` : required - String of the transaction id - *
`nonce` : required - Integer of the once time number + *
`txId` : required - {@link TransactionID} object with the transaction id and nonce *
`transientMap` : optional - map that can be used by * the chaincode but not saved in the ledger, such as cryptographic information * for encryption @@ -1377,11 +1351,11 @@ var Chain = class { var channelHeader = Chain._buildChannelHeader( _commonProto.HeaderType.ENDORSER_TRANSACTION, channelId, - request.txId, + request.txId.getTransactionID(), null, request.chaincodeId ); - header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.nonce); + header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.txId.getNonce()); proposal = Chain._buildProposal(invokeSpec, header, request.transientMap); let signed_proposal = Chain._signProposal(userContext.getSigningIdentity(), proposal); @@ -1529,14 +1503,30 @@ var Chain = class { * @returns {Promise} A Promise for an array of byte array results from the chaincode on all Endorsing Peers */ queryByChaincode(request) { - logger.debug('Chain.sendQueryProposal - start'); + logger.debug('queryByChaincodel - start'); + if(!request) { + return Promise.reject(new Error('Missing request object for this queryByChaincode call.')); + } + var userContext = this._clientContext.getUserContext(); + var txId = new TransactionID(userContext); + // make a new request object so we can add in the txId and not change the user's + var trans_request = { + targets : request.targets, + chaincodeId : request.chaincodeId, + chaincodeVersion : request.chaincodeVersion, + chainId : request.chainId, + fcn : request.fcn, + args : request.args, + transientMap : request.transientMap, + txId : txId + }; - return this.sendTransactionProposal(request) + return this.sendTransactionProposal(trans_request) .then( function(results) { var responses = results[0]; var proposal = results[1]; - logger.debug('Chain-queryByChaincode - results received'); + logger.debug('queryByChaincode - results received'); if(responses && Array.isArray(responses)) { var results = []; for(let i = 0; i < responses.length; i++) { @@ -1686,8 +1676,12 @@ var Chain = class { cc_payload.setInput(cciSpec.toBuffer()); if (typeof transientMap === 'object') { + logger.debug('_buildProposal - adding in transientMap %j',transientMap); cc_payload.setTransientMap(transientMap); } + else { + logger.debug('_buildProposal - not adding a transientMap'); + } // proposal -- will switch to building the proposal once the signProposal is used let proposal = new _proposalProto.Proposal(); @@ -1773,17 +1767,14 @@ var Chain = class { /* * @private */ - static _checkProposalRequest(request) { + static _checkProposalRequest(request, skip) { var errorMsg = null; if(request) { - var isQuery = (request.chaincodeId == 'qscc' || request.chaincodeId == 'cscc'); if(!request.chaincodeId) { errorMsg = 'Missing "chaincodeId" parameter in the proposal request'; - } else if(!request.txId) { + } else if(!request.txId && !skip) { errorMsg = 'Missing "txId" parameter in the proposal request'; - } else if(!request.nonce) { - errorMsg = 'Missing "nonce" parameter in the proposal request'; } } else { errorMsg = 'Missing input request object on the proposal request'; @@ -1807,25 +1798,6 @@ var Chain = class { return errorMsg; } - /** - * Utility method to build an unique transaction id - * based on a nonce and this chain's user. - * @param {int} nonce - a one time use number - * @param {User} userContext - the user context - * @returns {string} An unique string - */ - static buildTransactionID(nonce, userContext) { - logger.debug('buildTransactionID - start'); - var creator_bytes = userContext.getIdentity().serialize();//same as signatureHeader.Creator - var nonce_bytes = nonce;//nonce is already in bytes - var trans_bytes = Buffer.concat([nonce_bytes, creator_bytes]); - var trans_hash = hashPrimitives.sha2_256(trans_bytes); - var transaction_id = Buffer.from(trans_hash).toString(); - logger.debug('buildTransactionID - transaction_id %s',transaction_id); - return transaction_id; - } - - //utility method to build a common chain header static _buildChannelHeader(type, chain_id, tx_id, epoch, chaincode_id, time_stamp) { logger.debug('buildChannelHeader - type %s chain_id %s tx_id %d epoch % chaincode_id %s', diff --git a/fabric-client/lib/Client.js b/fabric-client/lib/Client.js index 5396010aab..436eba929d 100644 --- a/fabric-client/lib/Client.js +++ b/fabric-client/lib/Client.js @@ -26,6 +26,7 @@ var ChannelConfig = require('./ChannelConfig.js'); var Packager = require('./Packager.js'); var Peer = require('./Peer.js'); var Orderer = require('./Orderer.js'); +var TransactionID = require('./TransactionID.js'); var MSP = require('./msp/msp.js'); var logger = sdkUtils.getLogger('Client.js'); @@ -228,7 +229,7 @@ var Client = class { } /** - * Build a new MSP with the definition. + * Create a new MSP with the definition. * @parm {Object} which has the following the following fields: *
`id`: {string} value for the identifier of this instance *
`rootCerts`: array of {@link Identity} representing trust anchors for validating @@ -252,6 +253,23 @@ var Client = class { return msp; } + /** + * Create a new transaction id object with an unique transaction id + * based on included nonce and the user context. + * Requires this client instance to have an assigned user context. + * @returns {@link TransactionID} An object that contains a transaction id + * based on the user context and also contains + * the generated nonce value. + */ + newTransactionID() { + if (typeof this._userContext === 'undefined' || this._userContext === null) { + throw new Error('This client instance must be assigned an user context'); + } + let trans_id = new TransactionID(this._userContext); + + return trans_id; + } + /* * For test only * @@ -455,9 +473,7 @@ var Client = class { if(!request.txId && !have_envelope) { errorMsg = 'Missing txId request parameter'; } - if(!request.nonce && !have_envelope) { - errorMsg = 'Missing nonce request parameter'; - } + // verify that we have an orderer configured if(!request.orderer) { errorMsg = 'Missing orderer request parameter'; @@ -498,10 +514,10 @@ var Client = class { var proto_channel_header = Chain._buildChannelHeader( _commonProto.HeaderType.CONFIG_UPDATE, request.name, - request.txId + request.txId.getTransactionID() ); - var proto_header = Chain._buildHeader(userContext.getIdentity(), proto_channel_header, request.nonce); + var proto_header = Chain._buildHeader(userContext.getIdentity(), proto_channel_header, request.txId.getNonce()); var proto_payload = new _commonProto.Payload(); proto_payload.setHeader(proto_header); proto_payload.setData(proto_config_Update_envelope.toBuffer()); @@ -567,14 +583,11 @@ var Client = class { return Promise.reject( new Error('Peer is required')); } var self = this; - var nonce = sdkUtils.getNonce(); - var userContext = this.getUserContext(); - var txId = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(this._userContext); var request = { targets: [peer], - chaincodeId : 'cscc', + chaincodeId : Constants.CSCC, txId: txId, - nonce: nonce, fcn : 'GetChannels', args: [] }; @@ -627,14 +640,11 @@ var Client = class { return Promise.reject( new Error('Peer is required')); } var self = this; - var nonce = sdkUtils.getNonce(); - var userContext = self.getUserContext(); - var tx_id = Chain.buildTransactionID(nonce, userContext); + var txId = new TransactionID(this._userContext); var request = { targets: [peer], chaincodeId : Constants.LSCC, - txId: tx_id, - nonce: nonce, + txId: txId, fcn : 'getinstalledchaincodes', args: [] }; @@ -678,21 +688,19 @@ var Client = class { * Sends an install proposal to one or more endorsing peers. * * @param {Object} request - An object containing the following fields: - *
`chaincodePath` : required - String of the path to location of - * the source code of the chaincode - *
`chaincodeId` : required - String of the name of the chaincode - *
`chaincodeVersion` : required - String of the version of the chaincode - *
`chaincodePackage` : optional - Byte array of the archive content for - * the chaincode source. The archive must have a 'src' - * folder containing subfolders corresponding to the - * 'chaincodePath' field. For instance, if the chaincodePath - * is 'mycompany/myproject', then the archive must contain a - * folder at the path 'src/mycompany/myproject', where the - * GO source code resides. - *
`chaincodeType` : optional - Type of chaincode ['golang', 'car', 'java'] - * (default 'golang') - *
`txId` : required - String of the transaction id - *
`nonce` : required - Integer of the once time number + *
`chaincodePath` : required - String of the path to location of + * the source code of the chaincode + *
`chaincodeId` : required - String of the name of the chaincode + *
`chaincodeVersion` : required - String of the version of the chaincode + *
`chaincodePackage` : optional - Byte array of the archive content for + * the chaincode source. The archive must have a 'src' + * folder containing subfolders corresponding to the + * 'chaincodePath' field. For instance, if the chaincodePath + * is 'mycompany/myproject', then the archive must contain a + * folder at the path 'src/mycompany/myproject', where the + * GO source code resides. + *
`chaincodeType` : optional - Type of chaincode ['golang', 'car', 'java'] + * (default 'golang') * @returns {Promise} A Promise for a `ProposalResponse` * @see /protos/peer/proposal_response.proto */ @@ -716,8 +724,7 @@ var Client = class { errorMsg = 'Missing input request object on install chaincode request'; } - - if (!errorMsg) errorMsg = Chain._checkProposalRequest(request); + if (!errorMsg) errorMsg = Chain._checkProposalRequest(request, true); if (!errorMsg) errorMsg = Chain._checkInstallRequest(request); if (errorMsg) { @@ -764,15 +771,15 @@ var Client = class { var header, proposal; var userContext = self.getUserContext(); - var txId = Chain.buildTransactionID(request.nonce, userContext); + var txId = new TransactionID(userContext); var channelHeader = Chain._buildChannelHeader( _commonProto.HeaderType.ENDORSER_TRANSACTION, '', //install does not target a channel - txId, + txId.getTransactionID(), null, Constants.LSCC ); - header = Chain._buildHeader(userContext.getIdentity(), channelHeader, request.nonce); + header = Chain._buildHeader(userContext.getIdentity(), channelHeader, txId.getNonce()); proposal = Chain._buildProposal(lcccSpec, header); let signed_proposal = Chain._signProposal(userContext.getSigningIdentity(), proposal); @@ -856,7 +863,7 @@ var Client = class { } /** - * Sets an instance of the User class as the security context of self client instance. This user’s + * Sets an instance of the User class as the security context of this client instance. This user’s * credentials (ECert), or special transaction certificates that are derived from the user's ECert, * will be used to conduct transactions and queries with the blockchain network. * Upon setting the user context, the SDK saves the object in a persistence cache if the “state store” @@ -1024,17 +1031,6 @@ var Client = class { return this._stateStore; } - /** - * Utility method to build an unique transaction id - * based on a nonce and the user context. - * @param {int} nonce - a one time use number - * @param {User} userContext - the user context - * @returns {string} An unique string - */ - static buildTransactionID(nonce, userContext) { - return Chain.buildTransactionID(nonce, userContext); - } - /** * Returns an authorized user loaded using the * private key and pre-enrolled certificate from files diff --git a/fabric-client/lib/Constants.js b/fabric-client/lib/Constants.js index 1c27e30e70..5329a769ba 100755 --- a/fabric-client/lib/Constants.js +++ b/fabric-client/lib/Constants.js @@ -17,4 +17,6 @@ 'use strict'; module.exports.LSCC = 'lscc'; +module.exports.QSCC = 'qscc'; +module.exports.CSCC = 'cscc'; module.exports.SYSTEM_CHANNEL_NAME = 'testchainid'; \ No newline at end of file diff --git a/fabric-client/lib/TransactionID.js b/fabric-client/lib/TransactionID.js new file mode 100644 index 0000000000..2302cfb944 --- /dev/null +++ b/fabric-client/lib/TransactionID.js @@ -0,0 +1,72 @@ +/* + Copyright 2017 IBM All Rights Reserved. + + 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'; + +var sdkUtils = require('./utils.js'); +var logger = sdkUtils.getLogger('TransactionID.js'); +var User = require('./User.js'); +var hashPrimitives = require('./hash.js'); + + +/** + * The class representing the transaction identifier. Provides for + * automatically creating the `nonce` value when an instance of this + * object is created. + * + * @class + */ +var TransactionID = class { + + /** + * Builds a new tranaction Id based on a user's certificate and an automatically + * generated nonce value. + * @param {Client} clientContext An instance of {@link Client} that provides an unique + * base for this transaction id. + */ + constructor(userContext) { + logger.debug('const - start'); + if (typeof userContext === 'undefined' || userContext === null) { + throw new Error('Missing userContext parameter'); + } + if(!(userContext instanceof User)) { + throw new Error('Parameter "userContext" must be an instance of the "User" class'); + } + this._nonce = sdkUtils.getNonce(); //nonce is in bytes + let creator_bytes = userContext.getIdentity().serialize();//same as signatureHeader.Creator + let trans_bytes = Buffer.concat([this._nonce, creator_bytes]); + let trans_hash = hashPrimitives.sha2_256(trans_bytes); + this._transaction_id = Buffer.from(trans_hash).toString(); + logger.debug('const - transaction_id %s',this._transaction_id); + } + + /** + * The transaction ID + */ + getTransactionID() { + return this._transaction_id; + } + + /** + * The nonce value + */ + getNonce() { + return this._nonce; + } +}; + +module.exports = TransactionID; + diff --git a/test/integration/create-configtx-channel.js b/test/integration/create-configtx-channel.js index d6fc446229..a06c62f0e0 100644 --- a/test/integration/create-configtx-channel.js +++ b/test/integration/create-configtx-channel.js @@ -131,15 +131,13 @@ test('\n\n***** Configtx Built config create flow *****\n\n', function(t) { logger.debug('\n***\n done signing \n***\n'); // build up the create request - let nonce = utils.getNonce(); - let tx_id = Client.buildTransactionID(nonce, the_user); + let tx_id = client.newTransactionID(); var request = { config: config, signatures : signatures, name : channel_name, orderer : orderer, - txId : tx_id, - nonce : nonce + txId : tx_id }; // send to create request to orderer diff --git a/test/integration/e2e/create-channel.js b/test/integration/e2e/create-channel.js index ab1a31254f..fb87759e1d 100644 --- a/test/integration/e2e/create-channel.js +++ b/test/integration/e2e/create-channel.js @@ -333,18 +333,16 @@ test('\n\n***** SDK Built config update create flow *****\n\n', function(t) { logger.debug('\n***\n done signing \n***\n'); // build up the create request - let nonce = utils.getNonce(); - let tx_id = Client.buildTransactionID(nonce, the_user); + let tx_id = client.newTransactionID(); var request = { config: config, signatures : signatures, name : channel_name, orderer : orderer, - txId : tx_id, - nonce : nonce + txId : tx_id }; - // send to create request to orderer + // send create request to orderer return client.createChannel(request); }) .then((result) => { diff --git a/test/integration/e2e/e2eUtils.js b/test/integration/e2e/e2eUtils.js index b4c901316f..51eaf3d146 100644 --- a/test/integration/e2e/e2eUtils.js +++ b/test/integration/e2e/e2eUtils.js @@ -28,25 +28,24 @@ var path = require('path'); var fs = require('fs'); var util = require('util'); -var hfc = require('fabric-client'); +var Client = require('fabric-client'); var EventHub = require('fabric-client/lib/EventHub.js'); var testUtil = require('../../unit/util.js'); var e2e = testUtil.END2END; -hfc.addConfigFile(path.join(__dirname, './config.json')); -var ORGS = hfc.getConfigSetting('test-network'); +Client.addConfigFile(path.join(__dirname, './config.json')); +var ORGS = Client.getConfigSetting('test-network'); var grpc = require('grpc'); var tx_id = null; -var nonce = null; var the_user = null; function installChaincode(org, chaincode_path, version, t) { - hfc.setConfigSetting('request-timeout', 60000); - var channel_name = hfc.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); + Client.setConfigSetting('request-timeout', 60000); + var channel_name = Client.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); - var client = new hfc(); + var client = new Client(); var chain = client.newChain(channel_name); var orgName = ORGS[org].name; @@ -87,7 +86,7 @@ function installChaincode(org, chaincode_path, version, t) { } } - return hfc.newDefaultKeyValueStore({ + return Client.newDefaultKeyValueStore({ path: testUtil.storePathForOrg(orgName) }).then((store) => { client.setStateStore(store); @@ -98,17 +97,12 @@ function installChaincode(org, chaincode_path, version, t) { t.pass('Successfully enrolled user \'admin\''); the_user = admin; - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); - // send proposal to endorser var request = { targets: targets, chaincodePath: chaincode_path, chaincodeId: e2e.chaincodeId, - chaincodeVersion: version, - txId: tx_id, - nonce: nonce + chaincodeVersion: version }; return client.installChaincode(request); @@ -150,8 +144,8 @@ module.exports.installChaincode = installChaincode; function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ - hfc.setConfigSetting('request-timeout', 60000); - var channel_name = hfc.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); + Client.setConfigSetting('request-timeout', 60000); + var channel_name = Client.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); var targets = [], eventhubs = []; @@ -172,7 +166,7 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ }; })(t, eventhubs, t.end); - var client = new hfc(); + var client = new Client(); var chain = client.newChain(channel_name); var orgName = ORGS[userOrg].name; @@ -198,7 +192,7 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ var badTransientMap = { 'test1': 'transientValue' }; // have a different key than what the chaincode example_cc1.go expects in Init() var transientMap = { 'test': 'transientValue' }; - return hfc.newDefaultKeyValueStore({ + return Client.newDefaultKeyValueStore({ path: testUtil.storePathForOrg(orgName) }).then((store) => { @@ -256,9 +250,8 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ // the v1 chaincode has Init() method that expects a transient map if (upgrade) { // first test that a bad transient map would get the chaincode to return an error - let request = buildChaincodeProposal(the_user, chaincode_path, version, upgrade, badTransientMap); - tx_id = request.tx_id; - request = request.request; + let request = buildChaincodeProposal(client, the_user, chaincode_path, version, upgrade, badTransientMap); + tx_id = request.txId; return chain.sendUpgradeProposal(request) .then((results) => { @@ -280,9 +273,8 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ if (success) { // successfully tested the negative conditions caused by // the bad transient map, now send the good transient map - request = buildChaincodeProposal(the_user, chaincode_path, version, upgrade, transientMap); - tx_id = request.tx_id; - request = request.request; + request = buildChaincodeProposal(client, the_user, chaincode_path, version, upgrade, transientMap); + tx_id = request.txId; return chain.sendUpgradeProposal(request); } else { @@ -290,9 +282,8 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ } }); } else { - let request = buildChaincodeProposal(the_user, chaincode_path, version, upgrade, transientMap); - tx_id = request.tx_id; - request = request.request; + let request = buildChaincodeProposal(client, the_user, chaincode_path, version, upgrade, transientMap); + tx_id = request.txId; return chain.sendInstantiateProposal(request); } @@ -331,7 +322,7 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ // set the transaction listener and set a timeout of 30sec // if the transaction did not get committed within the timeout period, // fail the test - var deployId = tx_id.toString(); + var deployId = tx_id.getTransactionID(); var eventPromises = []; eventhubs.forEach((eh) => { @@ -352,7 +343,7 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ } }); }); - logger.info('register eventhub %s with tx=%s',eh.ep._endpoint.addr,tx_id); + logger.info('register eventhub %s with tx=%s',eh.ep._endpoint.addr,deployId); eventPromises.push(txPromise); }); @@ -395,9 +386,8 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ }); }; -function buildChaincodeProposal(the_user, chaincode_path, version, upgrade, transientMap) { - let nonce = utils.getNonce(); - let tx_id = hfc.buildTransactionID(nonce, the_user); +function buildChaincodeProposal(client, the_user, chaincode_path, version, upgrade, transientMap) { + var tx_id = client.newTransactionID(the_user); // send proposal to endorser var request = { @@ -407,7 +397,6 @@ function buildChaincodeProposal(the_user, chaincode_path, version, upgrade, tran fcn: 'init', args: ['a', '100', 'b', '200'], txId: tx_id, - nonce: nonce, // use this to demonstrate the following policy: // 'if signed by org1 admin, then that's the only signature required, // but if that signature is missing, then the policy can also be fulfilled @@ -432,15 +421,15 @@ function buildChaincodeProposal(the_user, chaincode_path, version, upgrade, tran request.transientMap = transientMap; } - return { request: request, tx_id: tx_id }; + return request; } module.exports.instantiateChaincode = instantiateChaincode; function invokeChaincode(userOrg, version, t){ - hfc.setConfigSetting('request-timeout', 60000); - var channel_name = hfc.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); + Client.setConfigSetting('request-timeout', 60000); + var channel_name = Client.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); var targets = [], eventhubs = []; @@ -465,7 +454,7 @@ function invokeChaincode(userOrg, version, t){ // submit the request. intentionally we are using a different org // than the one that instantiated the chaincode, although either org // should work properly - var client = new hfc(); + var client = new Client(); var chain = client.newChain(channel_name); var orgName = ORGS[userOrg].name; @@ -487,7 +476,9 @@ function invokeChaincode(userOrg, version, t){ ) ); - return hfc.newDefaultKeyValueStore({ + var orgName = ORGS[userOrg].name; + + return Client.newDefaultKeyValueStore({ path: testUtil.storePathForOrg(orgName) }).then((store) => { @@ -531,11 +522,10 @@ function invokeChaincode(userOrg, version, t){ return chain.initialize(); }).then((nothing) => { - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); - utils.setConfigSetting('E2E_TX_ID', tx_id); - logger.info('setConfigSetting("E2E_TX_ID") = %s', tx_id); - t.comment(util.format('Sending transaction "%s"', tx_id)); + tx_id = client.newTransactionID(the_user); + utils.setConfigSetting('E2E_TX_ID', tx_id.getTransactionID()); + logger.info('setConfigSetting("E2E_TX_ID") = %s', tx_id.getTransactionID()); + t.comment(util.format('Sending transaction "%s"', tx_id.getTransactionID())); // send proposal to endorser var request = { @@ -544,7 +534,6 @@ function invokeChaincode(userOrg, version, t){ fcn: 'invoke', args: ['move', 'a', 'b','100'], txId: tx_id, - nonce: nonce }; return chain.sendTransactionProposal(request); @@ -611,7 +600,7 @@ function invokeChaincode(userOrg, version, t){ // set the transaction listener and set a timeout of 30sec // if the transaction did not get committed within the timeout period, // fail the test - var deployId = tx_id.toString(); + var deployId = tx_id.getTransactionID(); var eventPromises = []; eventhubs.forEach((eh) => { @@ -671,7 +660,7 @@ function invokeChaincode(userOrg, version, t){ t.pass('Successfully sent transaction to the orderer.'); t.comment('******************************************************************'); t.comment('To manually run /test/integration/query.js, set the following environment variables:'); - t.comment('export E2E_TX_ID='+'\''+tx_id+'\''); + t.comment('export E2E_TX_ID='+'\''+tx_id.getTransactionID()+'\''); t.comment('******************************************************************'); return true; } else { @@ -689,14 +678,14 @@ function invokeChaincode(userOrg, version, t){ module.exports.invokeChaincode = invokeChaincode; function queryChaincode(org, version, value, t, transientMap) { - hfc.setConfigSetting('request-timeout', 60000); - var channel_name = hfc.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); + Client.setConfigSetting('request-timeout', 60000); + var channel_name = Client.getConfigSetting('E2E_CONFIGTX_CHANNEL_NAME', testUtil.END2END.channel); // this is a transaction, will just use org's identity to // submit the request. intentionally we are using a different org // than the one that submitted the "move" transaction, although either org // should work properly - var client = new hfc(); + var client = new Client(); var chain = client.newChain(channel_name); var orgName = ORGS[org].name; @@ -720,7 +709,7 @@ function queryChaincode(org, version, value, t, transientMap) { } } - return hfc.newDefaultKeyValueStore({ + return Client.newDefaultKeyValueStore({ path: testUtil.storePathForOrg(orgName) }).then((store) => { @@ -730,15 +719,11 @@ function queryChaincode(org, version, value, t, transientMap) { }).then((admin) => { the_user = admin; - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); - // send query var request = { chaincodeId : e2e.chaincodeId, chaincodeVersion : version, txId: tx_id, - nonce: nonce, fcn: 'invoke', args: ['query','b'] }; diff --git a/test/integration/e2e/join-channel.js b/test/integration/e2e/join-channel.js index 0a3f5e6eb4..3c4c9a8d04 100644 --- a/test/integration/e2e/join-channel.js +++ b/test/integration/e2e/join-channel.js @@ -33,7 +33,6 @@ var testUtil = require('../../unit/util.js'); var the_user = null; var tx_id = null; -var nonce = null; Client.addConfigFile(path.join(__dirname, './config.json')); var ORGS = Client.getConfigSetting('test-network'); @@ -118,11 +117,9 @@ function joinChannel(org, t) { return testUtil.getOrderAdminSubmitter(client, t); }).then((admin) => { t.pass('Successfully enrolled orderer \'admin\''); - nonce = utils.getNonce(); - tx_id = Client.buildTransactionID(nonce, admin); + tx_id = client.newTransactionID(); let request = { - txId : tx_id, - nonce : nonce + txId : tx_id }; return chain.getGenesisBlock(request); @@ -194,13 +191,11 @@ function joinChannel(org, t) { eventPromises.push(txPromise); }); - nonce = utils.getNonce(); - tx_id = Client.buildTransactionID(nonce, the_user); + tx_id = client.newTransactionID(); let request = { targets : targets, block : genesis_block, - txId : tx_id, - nonce : nonce + txId : tx_id }; let sendPromise = chain.joinChannel(request); return Promise.all([sendPromise].concat(eventPromises)); diff --git a/test/integration/e2e/update-channel.js b/test/integration/e2e/update-channel.js index 82ac523fed..9d47c40b99 100644 --- a/test/integration/e2e/update-channel.js +++ b/test/integration/e2e/update-channel.js @@ -183,15 +183,13 @@ test('\n\n***** U P D A T E C H A N N E L flow: update channel *****\n\n', (t) = signatures.push(signature); // build up the update request - let nonce = utils.getNonce(); - let tx_id = Client.buildTransactionID(nonce, the_user); + let tx_id = client.newTransactionID(); var request = { config : config_update, signatures : signatures, name : channel_name, orderer : orderer, - txId : tx_id, - nonce : nonce + txId : tx_id }; // send to update request to orderer diff --git a/test/integration/e2e/upgrade.js b/test/integration/e2e/upgrade.js index 75df1fcc5e..e453832cda 100644 --- a/test/integration/e2e/upgrade.js +++ b/test/integration/e2e/upgrade.js @@ -110,7 +110,6 @@ test('\n\n***** TransientMap Support in Proposals *****', (t) => { var transient = { 'test': Buffer.from('dummyValue') // string <-> byte[] }; - e2eUtils.queryChaincode('org2', 'v1', '410', t, transient) .then((result) => { if(result){ diff --git a/test/integration/events.js b/test/integration/events.js index 98fd812973..473ae71a08 100644 --- a/test/integration/events.js +++ b/test/integration/events.js @@ -75,7 +75,6 @@ for (let key in ORGS[org]) { var chaincode_id = testUtil.getUniqueVersion('events_unit_test'); var chaincode_version = testUtil.getUniqueVersion(); var request = null; -var nonce = null; var the_user = null; var steps = []; @@ -175,7 +174,7 @@ test('Test chaincode instantiate with event, transaction invocation with chainco t.end(); }).then((results) => { var tmo = 50000; - return Promise.all([eputil.registerTxEvent(eh, request.txId.toString(), tmo), + return Promise.all([eputil.registerTxEvent(eh, request.txId.getTransactionID().toString(), tmo), eputil.sendTransaction(chain, results)]); }, (err) => { @@ -228,8 +227,8 @@ test('Test chaincode instantiate with event, transaction invocation with chainco }).then(([results1, results2]) => { t.comment('sendTransactionProposal received [results1, results2]'); var tmo = 20000; - return Promise.all([eputil.registerTxEvent(eh, req1.txId.toString(), tmo), - eputil.registerTxEvent(eh, req2.txId.toString(), tmo), + return Promise.all([eputil.registerTxEvent(eh, req1.txId.getTransactionID().toString(), tmo), + eputil.registerTxEvent(eh, req2.txId.getTransactionID().toString(), tmo), eputil.sendTransaction(chain, results1), eputil.sendTransaction(chain, results2) ]); diff --git a/test/integration/eventutil.js b/test/integration/eventutil.js index 0db093bfaf..1fea7d0b4d 100644 --- a/test/integration/eventutil.js +++ b/test/integration/eventutil.js @@ -57,16 +57,14 @@ module.exports.registerCCEvent = function(eh, ccid, enregex, timeout) { }; module.exports.createRequest = function(client, chain, user, chaincode_id, targets, fcn, args) { - var nonce = utils.getNonce(); - var tx_id = hfc.buildTransactionID(nonce, user); + var tx_id = client.newTransactionID(); var request = { targets : targets, chaincodeId: chaincode_id, chaincodeVersion: '', fcn: fcn, args: args, - txId: tx_id.toString(), - nonce: nonce + txId: tx_id }; return request; }; diff --git a/test/integration/get-config.js b/test/integration/get-config.js index 43bfb423e5..1f3a0a074d 100644 --- a/test/integration/get-config.js +++ b/test/integration/get-config.js @@ -86,8 +86,6 @@ for (let key in ORGS[org]) { } var the_user = null; -var tx_id = null; -var nonce = null; var querys = []; if (process.argv.length > 2) { diff --git a/test/integration/grpc.js b/test/integration/grpc.js index e1b08515c0..0cc914aaac 100644 --- a/test/integration/grpc.js +++ b/test/integration/grpc.js @@ -116,7 +116,7 @@ test('\n\n*** GRPC communication tests ***\n\n', (t) => { } ); - return chain.sendTransactionProposal(buildEchoRequest(admin, peer)); + return chain.sendTransactionProposal(buildEchoRequest(client, peer)); }, (err) => { @@ -146,7 +146,7 @@ test('\n\n*** GRPC communication tests ***\n\n', (t) => { } ); - return chain.sendTransactionProposal(buildEchoRequest(submitter, peer)); + return chain.sendTransactionProposal(buildEchoRequest(client, peer)); }).then((response) => { if (response[0] && response[0][0] && response[0][0].response && response[0][0].response.status === 200) t.pass('Successfully tested grpc receive message limit'); @@ -160,9 +160,9 @@ test('\n\n*** GRPC communication tests ***\n\n', (t) => { }); }); -function buildEchoRequest(submitter, peer) { +function buildEchoRequest(client, peer) { let nonce = utils.getNonce(); - let tx_id = hfc.buildTransactionID(nonce, submitter); + let tx_id = client.newTransactionID(); return { targets: [peer], diff --git a/test/integration/install.js b/test/integration/install.js index 7b7addfcae..dd0ef1d7fa 100644 --- a/test/integration/install.js +++ b/test/integration/install.js @@ -41,7 +41,6 @@ hfc.addConfigFile(path.join(__dirname, 'e2e', 'config.json')); var ORGS = hfc.getConfigSetting('test-network'); var tx_id = null; -var nonce = null; var the_user = null; testUtil.setupChaincodeDeploy(); @@ -214,18 +213,13 @@ function installChaincode(params, t) { t.pass(params.testDesc+' - Successfully enrolled user \'admin\''); the_user = admin; - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); - // send proposal to endorser var request = { targets: targets, chaincodePath: params.chaincodePath, chaincodeId: params.chaincodeId, chaincodeVersion: params.chaincodeVersion, - chaincodePackage: params.chaincodePackage, - txId: tx_id, - nonce: nonce + chaincodePackage: params.chaincodePackage }; return client.installChaincode(request); diff --git a/test/integration/marbles.js b/test/integration/marbles.js index 3bcae5552a..38d246d31c 100644 --- a/test/integration/marbles.js +++ b/test/integration/marbles.js @@ -34,13 +34,12 @@ var http = require('http'); var hfc = require('fabric-client'); var util = require('util'); var testUtil = require('./util.js'); - +var client = new hfc(); var chain = hfc.newChain('testChain-e2e'); var webUser; var chaincode_id = 'marblescc'; var chain_id = '**TEST_CHAINID**'; var tx_id = null; -var nonce = null; var steps = []; if (process.argv.length > 2) { @@ -59,7 +58,7 @@ chain.setKeyValueStore(hfc.newKeyValueStore({ chain.setOrderer('grpc://localhost:7050'); test('End-to-end flow of chaincode instantiate, transaction invocation, and query', function(t) { - var promise = testUtil.getSubmitter(chain, t); + var promise = testUtil.getSubmitter(client, t); if (steps.length === 0 || steps.indexOf('step1') >= 0) { logger.info('Executing step1'); @@ -68,8 +67,7 @@ test('End-to-end flow of chaincode instantiate, transaction invocation, and quer function(admin) { t.pass('Successfully enrolled user \'admin\''); webUser = admin; - tx_id = hfc.buildTransactionID({length:12}); - nonce = hfc.getNonce(); + tx_id = client.newTransactionID(); // send proposal to endorser var request = { @@ -78,8 +76,7 @@ test('End-to-end flow of chaincode instantiate, transaction invocation, and quer chaincodeId: chaincode_id, fcn: 'init', args: ['1'], - txId: tx_id, - nonce: nonce + txId: tx_id }; return admin.sendInstantiateProposal(request); @@ -156,16 +153,14 @@ test('End-to-end flow of chaincode instantiate, transaction invocation, and quer } ).then( function() { - tx_id = hfc.buildTransactionID({length:12}); - nonce = hfc.getNonce(); + tx_id = client.newTransactionID(); // send proposal to endorser var request = { targets: [hfc.getPeer('grpc://localhost:7051'), hfc.getPeer('grpc://localhost:7056')], chaincodeId : chaincode_id, fcn: 'init_marble', args: ['marble1','blue','35','tom'], - txId: tx_id, - nonce: nonce + txId: tx_id }; return webUser.sendTransactionProposal(request); }, @@ -248,8 +243,7 @@ test('End-to-end flow of chaincode instantiate, transaction invocation, and quer } ).then( function() { - tx_id = hfc.buildTransactionID({length:12}); - nonce = hfc.getNonce(); + tx_id = client.newTransactionID(); // send proposal to endorser var request = { targets: [hfc.getPeer('grpc://localhost:7051'), hfc.getPeer('grpc://localhost:7056')], @@ -257,8 +251,7 @@ test('End-to-end flow of chaincode instantiate, transaction invocation, and quer fcn: 'set_owner', args: ['marble1','jerry'], chainId: chain_id, - txId: tx_id, - nonce: nonce + txId: tx_id }; return webUser.sendTransactionProposal(request); }, diff --git a/test/integration/new-chain.js b/test/integration/new-chain.js index e42e191835..5ddf8af707 100644 --- a/test/integration/new-chain.js +++ b/test/integration/new-chain.js @@ -74,8 +74,6 @@ hfc.setConfigSetting('hfc-logging', '{"debug":"console"}'); var keyValStorePath = testUtil.KVS; var the_user = null; -var tx_id = null; -var nonce = null; // //Orderer via member send chain create diff --git a/test/integration/query.js b/test/integration/query.js index 40e3c9c3ea..971e95b81b 100644 --- a/test/integration/query.js +++ b/test/integration/query.js @@ -53,8 +53,6 @@ var e2e = testUtil.END2END; var the_user = null; var tx_id = null; -var nonce = null; - var querys = []; if (process.argv.length > 2) { for (let i=2; i { let caroots = Buffer.from(data).toString(); var tx_id = null; - var nonce = null; var the_user = null; var allEventhubs = []; @@ -99,19 +98,16 @@ test('\n\n **** E R R O R T E S T I N G on upgrade call', (t) => { }) .then((nothing) => { t.pass('Successfully initialized channel'); - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); + tx_id = client.newTransactionID(); // send proposal to endorser var request = { chaincodePath: testUtil.CHAINCODE_UPGRADE_PATH, chaincodeId : e2e.chaincodeId, chaincodeVersion : version, - chainId: e2e.channel, fcn: 'init', args: ['a', '500', 'b', '600'], - txId: tx_id, - nonce: nonce + txId: tx_id }; return chain.sendUpgradeProposal(request); @@ -125,8 +121,7 @@ test('\n\n **** E R R O R T E S T I N G on upgrade call', (t) => { t.fail('This should not have thrown an Error ::'+ err); return Promise.resolve(true); }).then((nothing) => { - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); + tx_id = client.newTransactionID(); // send proposal to endorser var request = { @@ -135,9 +130,7 @@ test('\n\n **** E R R O R T E S T I N G on upgrade call', (t) => { chaincodeVersion: version, fcn: 'init', args: ['a', '500', 'b', '600'], - chainId: e2e.channel, - txId: tx_id, - nonce: nonce + txId: tx_id }; return chain.sendUpgradeProposal(request); @@ -148,8 +141,7 @@ test('\n\n **** E R R O R T E S T I N G on upgrade call', (t) => { return Promise.resolve(true); }).then((nothing) => { - nonce = utils.getNonce(); - tx_id = hfc.buildTransactionID(nonce, the_user); + tx_id = client.newTransactionID(); // send proposal to endorser var request = { @@ -158,8 +150,7 @@ test('\n\n **** E R R O R T E S T I N G on upgrade call', (t) => { chaincodeVersion: 'v333333333', fcn: 'init', args: ['a', '500', 'b', '600'], - txId: tx_id, - nonce: nonce + txId: tx_id }; return chain.sendUpgradeProposal(request); diff --git a/test/unit/chain.js b/test/unit/chain.js index d44a74b8f7..9b55e1506c 100644 --- a/test/unit/chain.js +++ b/test/unit/chain.js @@ -34,6 +34,7 @@ var Peer = require('fabric-client/lib/Peer.js'); var Chain = require('fabric-client/lib/Chain.js'); var Packager = require('fabric-client/lib/Packager.js'); var Orderer = require('fabric-client/lib/Orderer.js'); +var User = require('fabric-client/lib/User.js'); var MSP = require('fabric-client/lib/msp/msp.js'); var MSPManager = require('fabric-client/lib/msp/msp-manager.js'); var idModule = require('fabric-client/lib/msp/identity.js'); @@ -317,30 +318,7 @@ test('\n\n ** Chain joinChannel() tests **\n\n', function (t) { } }); - var p5 = c.joinChannel({targets: 'targets' , txId : 'txId' } - ).then(function () { - t.fail('Should not have been able to resolve the promise because of nonce request parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing nonce') >= 0) { - t.pass('Successfully caught missing nonce request error'); - } else { - t.fail('Failed to catch the missing nonce request error. Error: '); - logger.error(err.stack ? err.stack : err); - } - }); - - var p5a = c.getGenesisBlock({targets: 'targets' , txId : 'txId' } - ).then(function () { - t.fail('Should not have been able to resolve the promise because of nonce request parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing nonce') >= 0) { - t.pass('Successfully caught missing nonce request error'); - } else { - t.fail('Failed to catch the missing nonce request error. Error: '); - logger.error(err.stack ? err.stack : err); - } - }); - Promise.all([p1, p2, p3, p4, p4a, p5, p5a]) + Promise.all([p1, p2, p3, p4, p4a]) .then( function (data) { t.end(); @@ -652,8 +630,7 @@ test('\n\n ** Chain sendInstantiateProposal() tests **\n\n', function (t) { chaincodeId: 'blah', fcn: 'init', args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + txId: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "chaincodeVersion" parameter'); }).catch(function (err) { @@ -671,8 +648,7 @@ test('\n\n ** Chain sendInstantiateProposal() tests **\n\n', function (t) { chaincodeVersion: 'blah', fcn: 'init', args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + txId: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "chaincodeId" parameter'); }).catch(function (err) { @@ -690,8 +666,7 @@ test('\n\n ** Chain sendInstantiateProposal() tests **\n\n', function (t) { chaincodeVersion: 'blah', fcn: 'init', args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + txId: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "peer" objects on chain'); }).catch(function (err) { @@ -710,8 +685,7 @@ test('\n\n ** Chain sendInstantiateProposal() tests **\n\n', function (t) { chaincodeId: 'blah', chaincodeVersion: 'blah', fcn: 'init', - args: ['a', '100', 'b', '200'], - nonce: 'blah' + args: ['a', '100', 'b', '200'] }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "txId" parameter'); }).catch(function (err) { @@ -722,24 +696,6 @@ test('\n\n ** Chain sendInstantiateProposal() tests **\n\n', function (t) { } }); - var p6 = c.sendInstantiateProposal({ - targets: [new Peer('grpc://localhost:7051')], - chaincodePath: 'blah', - chaincodeId: 'blah', - chaincodeVersion: 'blah', - fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "nonce" parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing "nonce" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing nonce error'); - } else { - t.fail('Failed to catch the missing nonce error. Error: ' + err.stack ? err.stack : err); - } - }); - var p7 = c.sendInstantiateProposal().then(function () { t.fail('Should not have been able to resolve the promise because of missing request parameter'); }).catch(function (err) { @@ -750,7 +706,7 @@ test('\n\n ** Chain sendInstantiateProposal() tests **\n\n', function (t) { } }); - Promise.all([p1, p3, p4, p6, p7]) + Promise.all([p1, p3, p4, p7]) .then( function (data) { t.end(); @@ -771,8 +727,7 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { var p1 = c.sendTransactionProposal({ chaincodeId : 'blah', fcn: 'invoke', - txId: 'blah', - nonce: 'blah' + txId: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "args" parameter'); }).catch(function (err) { @@ -787,8 +742,7 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { var p3 = c.sendTransactionProposal({ fcn: 'init', args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + txId: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "chaincodeId" parameter'); }).catch(function (err) { @@ -804,8 +758,7 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { chaincodeId: 'blah', fcn: 'init', args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + txId: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "peer" objects on chain'); }).catch(function (err) { @@ -821,8 +774,7 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { var p5 = c.sendTransactionProposal({ chaincodeId: 'blah', fcn: 'init', - args: ['a', '100', 'b', '200'], - nonce: 'blah' + args: ['a', '100', 'b', '200'] }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "txId" parameter'); }).catch(function (err) { @@ -833,21 +785,6 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { } }); - var p6 = c.sendTransactionProposal({ - chaincodeId: 'blah', - fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "nonce" parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing "nonce" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing nonce error'); - } else { - t.fail('Failed to catch the missing nonce error. Error: ' + err.stack ? err.stack : err); - } - }); - var p7 = c.sendTransactionProposal().then(function () { t.fail('Should not have been able to resolve the promise because of missing request parameter'); }).catch(function (err) { @@ -858,7 +795,7 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { } }); - Promise.all([p1, p3, p4, p5, p6, p7]) + Promise.all([p1, p3, p4, p5, p7]) .then( function (data) { t.end(); @@ -871,113 +808,103 @@ test('\n\n ** Chain sendTransactionProposal() tests **\n\n', function (t) { ); }); -test('\n\n ** Client queryByChaincode() tests **\n\n', function (t) { - var c = client.newChain('any chain goes'); - var peer = new Peer('grpc://localhost:7051'); - c.addPeer(peer); +test('\n\n ** Chain queryByChaincode() tests **\n\n', function (t) { + var TEST_CERT_PEM = require('./user.js').TEST_CERT_PEM; + var member = new User('admin'); - var p1 = c.queryByChaincode({ - chaincodeId : 'blah', - fcn: 'invoke', - txId: 'blah', - nonce: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "args" parameter in queryByChaincode'); - }).catch(function (err) { - var msg = 'Missing "args" in Transaction proposal request'; - if (err.message.indexOf(msg) >= 0 ) { - t.pass('Successfully caught error: '+msg); - } else { - t.fail('Failed to catch queryByChaincode error: '+msg+'. Error: ' + err.stack ? err.stack : err); - } - }); - - var p3 = c.queryByChaincode({ - fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "chaincodeId" parameter in queryByChaincode'); - }).catch(function (err) { - if (err.message.indexOf('Missing "chaincodeId" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing chaincodeId error'); - } else { - t.fail('Failed to catch the queryByChaincode missing chaincodeId error. Error: ' + err.stack ? err.stack : err); - } - }); + // do some setup for following test + utils.setConfigSetting('key-value-store', 'fabric-client/lib/impl/FileKeyValueStore.js'); + hfc.newDefaultKeyValueStore({ + path: testutil.KVS + }).then ( function (store) { + client.setStateStore(store); + var cryptoUtils = utils.newCryptoSuite(); + return cryptoUtils.generateKey({ephemeral : true}); + }).then( function (key) { + // the private key and cert don't match, but it's ok, the code doesn't check + return member.setEnrollment(key, TEST_CERT_PEM, 'DEFAULT'); + }).then( function () { + client.setUserContext(member, true); + var chain = client.newChain('any chain goes'); + var peer = client.newPeer('grpc://localhost:7051'); + chain.addPeer(peer); + + var p1 = chain.queryByChaincode({ + chaincodeId : 'blah', + fcn: 'invoke' + }).then(function () { + t.fail('Should not have been able to resolve the promise because of missing "args" parameter in queryByChaincode'); + }).catch(function (err) { + var msg = 'Missing "args" in Transaction proposal request'; + if (err.message.indexOf(msg) >= 0 ) { + t.pass('Successfully caught error: '+msg); + } else { + t.fail('Failed to catch queryByChaincode error: '+msg+'. Error: ' + err.stack ? err.stack : err); + } + }); - c.removePeer(peer); - var p4 = c.queryByChaincode({ - chaincodeId: 'blah', - fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "peers" on chain in queryByChaincode'); - }).catch(function (err) { - var msg = 'Missing peer objects in Transaction proposal'; - if (err.message.indexOf(msg) >= 0) { - t.pass('Successfully caught error: '+msg); - } else { - t.fail('Failed to catch queryByChaincode error: '+msg+'. Error: ' + err.stack ? err.stack : err); - } - }); + var p3 = chain.queryByChaincode({ + fcn: 'init', + args: ['a', '100', 'b', '200'] + }).then(function () { + t.fail('Should not have been able to resolve the promise because of missing "chaincodeId" parameter in queryByChaincode'); + }).catch(function (err) { + if (err.message.indexOf('Missing "chaincodeId" parameter in the proposal request') >= 0) { + t.pass('Successfully caught missing chaincodeId error'); + } else { + t.fail('Failed to catch the queryByChaincode missing chaincodeId error. Error: ' + err.stack ? err.stack : err); + } + }); - c.addPeer(peer); - var p5 = c.queryByChaincode({ - chaincodeId: 'blah', - fcn: 'init', - args: ['a', '100', 'b', '200'], - nonce: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "txId" parameter in queryByChaincode'); - }).catch(function (err) { - if (err.message.indexOf('Missing "txId" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing txId error'); - } else { - t.fail('Failed to catch the queryByChaincode missing txId error. Error: ' + err.stack ? err.stack : err); - } - }); + chain.removePeer(peer); + var p4 = chain.queryByChaincode({ + chaincodeId: 'blah', + fcn: 'init', + args: ['a', '100', 'b', '200'] + }).then(function () { + t.fail('Should not have been able to resolve the promise because of missing "peers" on chain in queryByChaincode'); + }).catch(function (err) { + var msg = 'Missing peer objects in Transaction proposal'; + if (err.message.indexOf(msg) >= 0) { + t.pass('Successfully caught error: '+msg); + } else { + t.fail('Failed to catch queryByChaincode error: '+msg+'. Error: ' + err.stack ? err.stack : err); + } + }); - var p6 = c.queryByChaincode({ - chaincodeId: 'blah', - fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "nonce" parameter in queryByChaincode'); - }).catch(function (err) { - if (err.message.indexOf('Missing "nonce" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing nonce error'); - } else { - t.fail('Failed to catch the queryByChaincode missing nonce error. Error: ' + err.stack ? err.stack : err); - } - }); + chain.addPeer(peer); - var p7 = c.queryByChaincode().then(function () { - t.fail('Should not have been able to resolve the promise because of missing request parameter in queryByChaincode'); - }).catch(function (err) { - if (err.message.indexOf('Missing request object for this transaction proposal') >= 0) { - t.pass('Successfully caught missing request error'); - } else { - t.fail('Failed to catch the queryByChaincode missing request error. Error: ' + err.stack ? err.stack : err); - } - }); + var p7 = chain.queryByChaincode().then(function () { + t.fail('Should not have been able to resolve the promise because of missing request parameter in queryByChaincode'); + }).catch(function (err) { + if (err.message.indexOf('Missing request object for this queryByChaincode') >= 0) { + t.pass('Successfully caught missing request error'); + } else { + t.fail('Failed to catch the queryByChaincode missing request error. Error: ' + err.stack ? err.stack : err); + } + }); - Promise.all([p1, p3, p4, p5, p6, p7]) - .then( - function (data) { - t.end(); - } - ).catch( + Promise.all([p1, p3, p4, p7]) + .then( + function (data) { + t.pass('all test done'); + t.end(); + } + ).catch( + function (err) { + t.fail('Chain queryByChaincode() tests, Promise.all: '); + logger.error(err.stack ? err.stack : err); + t.end(); + } + ); + }).catch( function (err) { - t.fail('Client queryByChaincode() tests, Promise.all: '); + t.fail('Chain queryByChaincode() failed '); logger.error(err.stack ? err.stack : err); t.end(); } ); + }); test('\n\n ** Chain sendTransaction() tests **\n\n', function (t) { diff --git a/test/unit/client.js b/test/unit/client.js index a9ec0d3372..2080bbffd1 100644 --- a/test/unit/client.js +++ b/test/unit/client.js @@ -336,6 +336,19 @@ test('\n\n ** testing get and new orderer calls on client **\n\n', function (t) t.end(); }); +test('\n\n ** testing get transaction ID call on client **\n\n', function (t) { + t.equals(typeof hfc, 'function'); + var client = new Client(); + + t.throws(function() { + client.newTransactionID(); + }, + /This client instance must be assigned an user context/, + 'Test This client instance must be assigned an user context'); + + t.end(); +}); + /* * This test assumes that there is a ./config directory from the running location * and that there is file called 'config.json'. @@ -368,33 +381,29 @@ test('\n\n ** client installChaincode() tests **\n\n', function (t) { chaincodeId: 'blah', chaincodeVersion: 'blah', fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + args: ['a', '100', 'b', '200'] }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "chaincodePath" parameter'); }).catch(function (err) { if (err.message.indexOf('Missing chaincodePath parameter') >= 0) { - t.pass('Successfully caught missing chaincodePath error'); + t.pass('P1 - Successfully caught missing chaincodePath error'); } else { t.fail('Failed to catch the missing chaincodePath error. Error: '); console.log(err.stack ? err.stack : err); } }); - var p1a = client.installChaincode({ + var p2 = client.installChaincode({ targets: [peer], chaincodeId: 'blahp1a', chaincodePath: 'blah', fcn: 'init', - args: ['a', '100', 'b', '200'], - txId: 'blah', - nonce: 'blah' + args: ['a', '100', 'b', '200'] }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "chaincodeVersion" parameter'); }).catch(function (err) { if (err.message.indexOf('Missing "chaincodeVersion" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing chaincodeVersion error'); + t.pass('P2 - Successfully caught missing chaincodeVersion error'); } else { t.fail('Failed to catch the missing chaincodeVersion error. Error: '); console.log(err.stack ? err.stack : err); @@ -404,14 +413,12 @@ test('\n\n ** client installChaincode() tests **\n\n', function (t) { var p3 = client.installChaincode({ targets: [peer], chaincodePath: 'blahp3', - chaincodeVersion: 'blah', - txId: 'blah', - nonce: 'blah' + chaincodeVersion: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "chaincodeId" parameter'); }).catch(function (err) { if (err.message.indexOf('Missing "chaincodeId" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing chaincodeId error'); + t.pass('P3 - Successfully caught missing chaincodeId error'); } else { t.fail('Failed to catch the missing chaincodeId error. Error: ' + err.stack ? err.stack : err); } @@ -420,63 +427,29 @@ test('\n\n ** client installChaincode() tests **\n\n', function (t) { var p4 = client.installChaincode({ chaincodePath: 'blahp4', chaincodeId: 'blah', - chaincodeVersion: 'blah', - txId: 'blah', - nonce: 'blah' + chaincodeVersion: 'blah' }).then(function () { t.fail('Should not have been able to resolve the promise because of missing "peer" objects on request'); }).catch(function (err) { var msg = 'Missing peer objects in install chaincode request'; if (err.message.indexOf(msg) >= 0) { - t.pass('Successfully caught error: '+msg); + t.pass('P4 - Successfully caught error: '+msg); } else { t.fail('Failed to catch error: '+msg+'. Error: ' + err.stack ? err.stack : err); } }); - var p5 = client.installChaincode({ - targets: [peer], - chaincodePath: 'blahp5', - chaincodeId: 'blah', - chaincodeVersion: 'blah', - nonce: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "txId" parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing "txId" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing txId error'); - } else { - t.fail('Failed to catch the missing txId error. Error: ' + err.stack ? err.stack : err); - } - }); - - var p6 = client.installChaincode({ - targets: [peer], - chaincodePath: 'blahp6', - chaincodeId: 'blah', - chaincodeVersion: 'blah', - txId: 'blah' - }).then(function () { - t.fail('Should not have been able to resolve the promise because of missing "nonce" parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing "nonce" parameter in the proposal request') >= 0) { - t.pass('Successfully caught missing nonce error'); - } else { - t.fail('Failed to catch the missing nonce error. Error: ' + err.stack ? err.stack : err); - } - }); - - var p7 = client.installChaincode().then(function () { + var p5 = client.installChaincode().then(function () { t.fail('Should not have been able to resolve the promise because of missing request parameter'); }).catch(function (err) { if (err.message.indexOf('Missing input request object on install chaincode request') >= 0) { - t.pass('Successfully caught missing request error'); + t.pass('P5 - Successfully caught missing request error'); } else { t.fail('Failed to catch the missing request error. Error: ' + err.stack ? err.stack : err); } }); - Promise.all([p1, p1a, p3, p4, p6, p7]) + Promise.all([p1, p2, p3, p4, p5]) .then( function (data) { t.end(); @@ -518,7 +491,7 @@ test('\n\n ** Client createChannel() tests **\n\n', function (t) { } }); - var p3 = c.createChannel({orderer : orderer, name : 'name', nonce : 'something', txId : '777', signatures : []} + var p3 = c.createChannel({orderer : orderer, name : 'name', txId : '777', signatures : []} ).then(function () { t.fail('Should not have been able to resolve the promise because of envelope request parameter'); }).catch(function (err) { @@ -542,7 +515,7 @@ test('\n\n ** Client createChannel() tests **\n\n', function (t) { } }); - var p5 = c.createChannel({config : {}, orderer : orderer, name: 'name', txId : 'fff', nonce : 'fff'} + var p5 = c.createChannel({config : {}, orderer : orderer, name: 'name', txId : 'fff'} ).then(function () { t.fail('Should not have been able to resolve the promise because of missing signatures request parameter'); }).catch(function (err) { @@ -554,7 +527,7 @@ test('\n\n ** Client createChannel() tests **\n\n', function (t) { } }); - var p6 = c.createChannel({config : {}, orderer : orderer, name: 'name', signatures : {}, txId : 'fff', nonce : 'fff'} + var p6 = c.createChannel({config : {}, orderer : orderer, name: 'name', signatures : {}, txId : 'fff'} ).then(function () { t.fail('Should not have been able to resolve the promise because of missing signatures request parameter'); }).catch(function (err) { @@ -566,7 +539,7 @@ test('\n\n ** Client createChannel() tests **\n\n', function (t) { } }); - var p7 = c.createChannel({config : {}, orderer : orderer, name: 'name', signatures : [], nonce : 'fff'} + var p7 = c.createChannel({config : {}, orderer : orderer, name: 'name', signatures : []} ).then(function () { t.fail('Should not have been able to resolve the promise because of missing txId request parameter'); }).catch(function (err) { @@ -578,19 +551,7 @@ test('\n\n ** Client createChannel() tests **\n\n', function (t) { } }); - var p8 = c.createChannel({config : {}, orderer : orderer, name: 'name', signatures : [], txId : 'fff'} - ).then(function () { - t.fail('Should not have been able to resolve the promise because of missing nonce request parameter'); - }).catch(function (err) { - if (err.message.indexOf('Missing nonce') >= 0) { - t.pass('Successfully caught request parameter must have nonce error'); - } else { - t.fail('Failed to catch request parameter must have nonce error. Error: '); - console.log(err.stack ? err.stack : err); - } - }); - - Promise.all([p1, p2, p3, p4, p5, p6, p7, p8]) + Promise.all([p1, p2, p3, p4, p5, p6, p7]) .then( function (data) { t.end(); @@ -975,7 +936,7 @@ test('\n\n ** test related APIs for create channel **\n\n', function (t) { console.log(err.stack ? err.stack : err); } }); - var p3a= client.updateChannel({config : 'a', txId : 'a', nonce : 'a', orderer : 'a', name : 'a' } + var p3a= client.updateChannel({config : 'a', txId : 'a', orderer : 'a', name : 'a' } ).then(function () { t.fail('Should not have been able to resolve the promise'); }).catch(function (err) { @@ -987,7 +948,7 @@ test('\n\n ** test related APIs for create channel **\n\n', function (t) { console.log(err.stack ? err.stack : err); } }); - var p3b= client.updateChannel({config : 'a', signatures : 'a', txId : 'a', nonce : 'a', orderer : 'a', name : 'a'} + var p3b= client.updateChannel({config : 'a', signatures : 'a', txId : 'a', orderer : 'a', name : 'a'} ).then(function () { t.fail('Should not have been able to resolve the promise'); }).catch(function (err) { @@ -1000,7 +961,7 @@ test('\n\n ** test related APIs for create channel **\n\n', function (t) { } }); - var p4= client.updateChannel({config : 'a', signatures : [], nonce : 'a', orderer : 'a', name : 'a'} + var p4= client.updateChannel({config : 'a', signatures : [], orderer : 'a', name : 'a'} ).then(function () { t.fail('Should not have been able to resolve the promise'); }).catch(function (err) { @@ -1012,19 +973,8 @@ test('\n\n ** test related APIs for create channel **\n\n', function (t) { console.log(err.stack ? err.stack : err); } }); - var p5= client.updateChannel({config : 'a', signatures : [], txId : 'a', orderer : 'a', name : 'a'} - ).then(function () { - t.fail('Should not have been able to resolve the promise'); - }).catch(function (err) { - let msg = 'Missing nonce request parameter'; - if (err.message.indexOf(msg) >= 0) { - t.pass('Successfully caught the ' + msg ); - } else { - t.fail('Failed to catch the ' + msg + ' Error: '); - console.log(err.stack ? err.stack : err); - } - }); - var p6= client.updateChannel({config : 'a', signatures : [], txId : 'a', nonce : 'a', name : 'a'} + + var p6= client.updateChannel({config : 'a', signatures : [], txId : 'a', name : 'a'} ).then(function () { t.fail('Should not have been able to resolve the promise'); }).catch(function (err) { @@ -1036,7 +986,7 @@ test('\n\n ** test related APIs for create channel **\n\n', function (t) { console.log(err.stack ? err.stack : err); } }); - var p7= client.updateChannel({config : 'a', signatures : [], txId : 'a', nonce : 'a', orderer : 'a'} + var p7= client.updateChannel({config : 'a', signatures : [], txId : 'a', orderer : 'a'} ).then(function () { t.fail('Should not have been able to resolve the promise'); }).catch(function (err) { @@ -1060,7 +1010,7 @@ test('\n\n ** test related APIs for create channel **\n\n', function (t) { console.log(err.stack ? err.stack : err); } }); - Promise.all([p1, p1a, p2, p3a, p3b, p4, p5, p6, p7, p8]) + Promise.all([p1, p1a, p2, p3a, p3b, p4, p6, p7, p8]) .then( function (data) { t.end(); diff --git a/test/unit/transactionid.js b/test/unit/transactionid.js new file mode 100644 index 0000000000..5dd261dcfa --- /dev/null +++ b/test/unit/transactionid.js @@ -0,0 +1,65 @@ +/** + * Copyright 2017 IBM All Rights Reserved. + * + * 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'; + +var tape = require('tape'); +var _test = require('tape-promise'); +var test = _test(tape); + +var TransactionID = require('fabric-client/lib/TransactionID.js'); +var User = require('fabric-client/lib/User.js'); +var utils = require('fabric-client/lib/utils.js'); + +var enrollmentID = 123454321; +var roles = ['admin', 'user']; +var memberCfg = { + 'enrollmentID': enrollmentID, + 'roles': roles +}; + +var TEST_CERT_PEM = require('./user.js').TEST_CERT_PEM; + +test('\n\n ** Transaction - constructor set get tests **\n\n', function (t) { + t.throws(function() { + new TransactionID(); + }, + /Missing userContext parameter/, + 'Test Missing userContext parameter'); + + t.throws(function() { + new TransactionID({}); + }, + /Parameter "userContext" must be an instance of the "User" class/, + 'Test Parameter "userContext" must be an instance of the "User" class'); + + var member = new User('admin'); + // test set enrollment for identity and signing identity + var cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.generateKey({ephemeral : true}) + .then(function (key) { + // the private key and cert don't match, but it's ok, the code doesn't check + return member.setEnrollment(key, TEST_CERT_PEM, 'DEFAULT'); + }).then(() =>{ + var trans_id = new TransactionID(member); + t.pass('Successfully created a new TransactionID'); + t.end(); + }).catch((err) => { + t.fail(err.stack ? err.stack : err); + t.end(); + }); + +}); \ No newline at end of file diff --git a/test/unit/user.js b/test/unit/user.js index fa18189467..720cf7408a 100644 --- a/test/unit/user.js +++ b/test/unit/user.js @@ -57,6 +57,8 @@ var TEST_CERT_PEM = '-----BEGIN CERTIFICATE-----' + 'UWUxIC0CIQDNyHQAwzhw+512meXRwG92GfpzSBssDKLdwlrqiHOu5A==' + '-----END CERTIFICATE-----'; +module.exports.TEST_CERT_PEM = TEST_CERT_PEM; + test('\n\n ** User - constructor set get tests **\n\n', function (t) { utils.setConfigSetting('crypto-hsm', false);