From 6b2799e6208c421347b07ac19bc9783018693540 Mon Sep 17 00:00:00 2001 From: Bret Harrison Date: Thu, 19 Oct 2017 20:22:03 -0400 Subject: [PATCH] [FAB-6568] Fabric-Samples - update fabcar Update the fabcar sample with an easier flow Remove hardcoded fields in the invoke program Change-Id: I9a06cdd317c2afec80720ac7d728d38fc62c6f63 Signed-off-by: Bret Harrison Signed-off-by: Nick Gaski --- basic-network/docker-compose.yml | 4 +- fabcar/creds/PeerAdmin | 1 - ...e62130f8008a0bf996e4e4b84cd097a747fec-priv | 5 - ...1e62130f8008a0bf996e4e4b84cd097a747fec-pub | 14 - fabcar/enrollAdmin.js | 75 +++++ fabcar/invoke.js | 281 +++++++++--------- fabcar/package.json | 5 +- fabcar/query.js | 111 +++---- fabcar/registerUser.js | 82 +++++ fabcar/startFabric.sh | 10 +- 10 files changed, 373 insertions(+), 215 deletions(-) delete mode 100644 fabcar/creds/PeerAdmin delete mode 100755 fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-priv delete mode 100644 fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-pub create mode 100644 fabcar/enrollAdmin.js create mode 100644 fabcar/registerUser.js diff --git a/basic-network/docker-compose.yml b/basic-network/docker-compose.yml index 8c38a4e951..bfad9d952a 100644 --- a/basic-network/docker-compose.yml +++ b/basic-network/docker-compose.yml @@ -14,9 +14,11 @@ services: environment: - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server - FABRIC_CA_SERVER_CA_NAME=ca.example.com + - FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem + - FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/4239aa0dcd76daeeb8ba0cda701851d14504d31aad1b2ddddbac6a57365e497c_sk ports: - "7054:7054" - command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/a22daf356b2aab5792ea53e35f66fccef1d7f1aa2b3a2b92dbfbf96a448ea26a_sk -b admin:adminpw -d' + command: sh -c 'fabric-ca-server start -b admin:adminpw -d' volumes: - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config container_name: ca.example.com diff --git a/fabcar/creds/PeerAdmin b/fabcar/creds/PeerAdmin deleted file mode 100644 index 47b48be79c..0000000000 --- a/fabcar/creds/PeerAdmin +++ /dev/null @@ -1 +0,0 @@ -{"name":"PeerAdmin","mspid":"Org1MSP","roles":null,"affiliation":"","enrollmentSecret":"","enrollment":{"signingIdentity":"cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec","identity":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICGDCCAb+gAwIBAgIQFSxnLAGsu04zrFkAEwzn6zAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0xNzA4MzEwOTE0MzJaFw0yNzA4MjkwOTE0MzJa\nMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMR8wHQYDVQQDDBZBZG1pbkBvcmcxLmV4YW1wbGUuY29tMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV1dfmKxsFKWo7o6DNBIaIVebCCPAM9C/\nsLBt4pJRre9pWE987DjXZoZ3glc4+DoPMtTmBRqbPVwYcUvpbYY8p6NNMEswDgYD\nVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgQjmqDc122u64\nugzacBhR0UUE0xqtGy3d26xqVzZeSXwwCgYIKoZIzj0EAwIDRwAwRAIgXMy26AEU\n/GUMPfCMs/nQjQME1ZxBHAYZtKEuRR361JsCIEg9BOZdIoioRivJC+ZUzvJUnkXu\no2HkWiuxLsibGxtE\n-----END CERTIFICATE-----\n"}}} \ No newline at end of file diff --git a/fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-priv b/fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-priv deleted file mode 100755 index 838716ac7d..0000000000 --- a/fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-priv +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgRgQr347ij6cjwX7m -KjzbbD8Tlwdfu6FaubjWJWLGyqahRANCAARXV1+YrGwUpajujoM0EhohV5sII8Az -0L+wsG3iklGt72lYT3zsONdmhneCVzj4Og8y1OYFGps9XBhxS+lthjyn ------END PRIVATE KEY----- diff --git a/fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-pub b/fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-pub deleted file mode 100644 index df8f568c11..0000000000 --- a/fabcar/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-pub +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICGDCCAb+gAwIBAgIQFSxnLAGsu04zrFkAEwzn6zAKBggqhkjOPQQDAjBzMQsw -CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy -YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu -b3JnMS5leGFtcGxlLmNvbTAeFw0xNzA4MzEwOTE0MzJaFw0yNzA4MjkwOTE0MzJa -MFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T -YW4gRnJhbmNpc2NvMR8wHQYDVQQDDBZBZG1pbkBvcmcxLmV4YW1wbGUuY29tMFkw -EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV1dfmKxsFKWo7o6DNBIaIVebCCPAM9C/ -sLBt4pJRre9pWE987DjXZoZ3glc4+DoPMtTmBRqbPVwYcUvpbYY8p6NNMEswDgYD -VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgQjmqDc122u64 -ugzacBhR0UUE0xqtGy3d26xqVzZeSXwwCgYIKoZIzj0EAwIDRwAwRAIgXMy26AEU -/GUMPfCMs/nQjQME1ZxBHAYZtKEuRR361JsCIEg9BOZdIoioRivJC+ZUzvJUnkXu -o2HkWiuxLsibGxtE ------END CERTIFICATE----- diff --git a/fabcar/enrollAdmin.js b/fabcar/enrollAdmin.js new file mode 100644 index 0000000000..9798479e49 --- /dev/null +++ b/fabcar/enrollAdmin.js @@ -0,0 +1,75 @@ +'use strict'; +/* +* Copyright IBM Corp All Rights Reserved +* +* SPDX-License-Identifier: Apache-2.0 +*/ +/* + * Enroll the admin user + */ + +var Fabric_Client = require('fabric-client'); +var Fabric_CA_Client = require('fabric-ca-client'); + +var path = require('path'); +var util = require('util'); +var os = require('os'); + +// +var fabric_client = new Fabric_Client(); +var fabric_ca_client = null; +var admin_user = null; +var member_user = null; +var store_path = path.join(__dirname, 'hfc-key-store'); +console.log(' Store path:'+store_path); + +// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting +Fabric_Client.newDefaultKeyValueStore({ path: store_path +}).then((state_store) => { + // assign the store to the fabric client + fabric_client.setStateStore(state_store); + var crypto_suite = Fabric_Client.newCryptoSuite(); + // use the same location for the state store (where the users' certificate are kept) + // and the crypto store (where the users' keys are kept) + var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path}); + crypto_suite.setCryptoKeyStore(crypto_store); + fabric_client.setCryptoSuite(crypto_suite); + var tlsOptions = { + trustedRoots: [], + verify: false + }; + // be sure to change the http to https when the CA is running TLS enabled + fabric_ca_client = new Fabric_CA_Client('http://localhost:7054', tlsOptions , 'ca.example.com', crypto_suite); + + // first check to see if the admin is already enrolled + return fabric_client.getUserContext('admin', true); +}).then((user_from_store) => { + if (user_from_store && user_from_store.isEnrolled()) { + console.log('Successfully loaded admin from persistence'); + admin_user = user_from_store; + return null; + } else { + // need to enroll it with CA server + return fabric_ca_client.enroll({ + enrollmentID: 'admin', + enrollmentSecret: 'adminpw' + }).then((enrollment) => { + console.log('Successfully enrolled admin user "admin"'); + return fabric_client.createUser( + {username: 'admin', + mspid: 'Org1MSP', + cryptoContent: { privateKeyPEM: enrollment.key.toBytes(), signedCertPEM: enrollment.certificate } + }); + }).then((user) => { + admin_user = user; + return fabric_client.setUserContext(admin_user); + }).catch((err) => { + console.error('Failed to enroll and persist admin. Error: ' + err.stack ? err.stack : err); + throw new Error('Failed to enroll admin'); + }); + } +}).then(() => { + console.log('Assigned the admin user to the fabric client ::' + admin_user.toString()); +}).catch((err) => { + console.error('Failed to enroll admin: ' + err); +}); diff --git a/fabcar/invoke.js b/fabcar/invoke.js index bd541f321f..ad3fd2d905 100644 --- a/fabcar/invoke.js +++ b/fabcar/invoke.js @@ -8,145 +8,154 @@ * Chaincode Invoke */ -var hfc = require('fabric-client'); +var Fabric_Client = require('fabric-client'); var path = require('path'); var util = require('util'); +var os = require('os'); -var options = { - wallet_path: path.join(__dirname, './creds'), - user_id: 'PeerAdmin', - channel_id: 'mychannel', - chaincode_id: 'fabcar', - peer_url: 'grpc://localhost:7051', - event_url: 'grpc://localhost:7053', - orderer_url: 'grpc://localhost:7050' -}; - -var channel = {}; -var client = null; -var targets = []; +// +var fabric_client = new Fabric_Client(); + +// setup the fabric network +var channel = fabric_client.newChannel('mychannel'); +var peer = fabric_client.newPeer('grpc://localhost:7051'); +channel.addPeer(peer); +var order = fabric_client.newOrderer('grpc://localhost:7050') +channel.addOrderer(order); + +// +var member_user = null; +var store_path = path.join(__dirname, 'hfc-key-store'); +console.log('Store path:'+store_path); var tx_id = null; -Promise.resolve().then(() => { - console.log("Create a client and set the wallet location"); - client = new hfc(); - return hfc.newDefaultKeyValueStore({ path: options.wallet_path }); -}).then((wallet) => { - console.log("Set wallet path, and associate user ", options.user_id, " with application"); - client.setStateStore(wallet); - return client.getUserContext(options.user_id, true); -}).then((user) => { - console.log("Check user is enrolled, and set a query URL in the network"); - if (user === undefined || user.isEnrolled() === false) { - console.error("User not defined, or not enrolled - error"); - } - channel = client.newChannel(options.channel_id); - var peerObj = client.newPeer(options.peer_url); - channel.addPeer(peerObj); - channel.addOrderer(client.newOrderer(options.orderer_url)); - targets.push(peerObj); - return; -}).then(() => { - tx_id = client.newTransactionID(); - console.log("Assigning transaction_id: ", tx_id._transaction_id); - // createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'], - // changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'], - // send proposal to endorser - var request = { - targets: targets, - chaincodeId: options.chaincode_id, - fcn: 'createCar', - args: ['CAR10', 'Chevy', 'Volt', 'Red', 'Nick'], - chainId: options.channel_id, - txId: tx_id - }; - return channel.sendTransactionProposal(request); + +// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting +Fabric_Client.newDefaultKeyValueStore({ path: store_path +}).then((state_store) => { + // assign the store to the fabric client + fabric_client.setStateStore(state_store); + var crypto_suite = Fabric_Client.newCryptoSuite(); + // use the same location for the state store (where the users' certificate are kept) + // and the crypto store (where the users' keys are kept) + var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path}); + crypto_suite.setCryptoKeyStore(crypto_store); + fabric_client.setCryptoSuite(crypto_suite); + + // get the enrolled user from persistence, this user will sign all requests + return fabric_client.getUserContext('user1', true); +}).then((user_from_store) => { + if (user_from_store && user_from_store.isEnrolled()) { + console.log('Successfully loaded user1 from persistence'); + member_user = user_from_store; + } else { + throw new Error('Failed to get user1.... run registerUser.js'); + } + + // get a transaction id object based on the current user assigned to fabric client + tx_id = fabric_client.newTransactionID(); + console.log("Assigning transaction_id: ", tx_id._transaction_id); + + // createCar chaincode function - requires 5 args, ex: args: ['CAR12', 'Honda', 'Accord', 'Black', 'Tom'], + // changeCarOwner chaincode function - requires 2 args , ex: args: ['CAR10', 'Barry'], + // must send the proposal to endorsing peers + var request = { + //targets: let default to the peer assigned to the client + chaincodeId: 'fabcar', + fcn: '', + args: [''], + chainId: 'mychannel', + txId: tx_id + }; + + // send the transaction proposal to the peers + return channel.sendTransactionProposal(request); +}).then((results) => { + var proposalResponses = results[0]; + var proposal = results[1]; + let isProposalGood = false; + if (proposalResponses && proposalResponses[0].response && + proposalResponses[0].response.status === 200) { + isProposalGood = true; + console.log('Transaction proposal was good'); + } else { + console.error('Transaction proposal was bad'); + } + if (isProposalGood) { + console.log(util.format( + 'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s"', + proposalResponses[0].response.status, proposalResponses[0].response.message)); + + // build up the request for the orderer to have the transaction committed + var request = { + proposalResponses: proposalResponses, + proposal: proposal + }; + + // set the transaction listener and set a timeout of 30 sec + // if the transaction did not get committed within the timeout period, + // report a TIMEOUT status + var transaction_id_string = tx_id.getTransactionID(); //Get the transaction ID string to be used by the event processing + var promises = []; + + var sendPromise = channel.sendTransaction(request); + promises.push(sendPromise); //we want the send transaction first, so that we know where to check status + + // get an eventhub once the fabric client has a user assigned. The user + // is required bacause the event registration must be signed + let event_hub = fabric_client.newEventHub(); + event_hub.setPeerAddr('grpc://localhost:7053'); + + // using resolve the promise so that result status may be processed + // under the then clause rather than having the catch clause process + // the status + let txPromise = new Promise((resolve, reject) => { + let handle = setTimeout(() => { + event_hub.disconnect(); + resolve({event_status : 'TIMEOUT'}); //we could use reject(new Error('Trnasaction did not complete within 30 seconds')); + }, 3000); + event_hub.connect(); + event_hub.registerTxEvent(transaction_id_string, (tx, code) => { + // this is the callback for transaction event status + // first some clean up of event listener + clearTimeout(handle); + event_hub.unregisterTxEvent(transaction_id_string); + event_hub.disconnect(); + + // now let the application know what happened + var return_status = {event_status : code, tx_id : transaction_id_string}; + if (code !== 'VALID') { + console.error('The transaction was invalid, code = ' + code); + resolve(return_status); // we could use reject(new Error('Problem with the tranaction, event status ::'+code)); + } else { + console.log('The transaction has been committed on peer ' + event_hub._ep._endpoint.addr); + resolve(return_status); + } + }, (err) => { + //this is the callback if something goes wrong with the event registration or processing + reject(new Error('There was a problem with the eventhub ::'+err)); + }); + }); + promises.push(txPromise); + + return Promise.all(promises); + } else { + console.error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...'); + throw new Error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...'); + } }).then((results) => { - var proposalResponses = results[0]; - var proposal = results[1]; - var header = results[2]; - let isProposalGood = false; - if (proposalResponses && proposalResponses[0].response && - proposalResponses[0].response.status === 200) { - isProposalGood = true; - console.log('transaction proposal was good'); - } else { - console.error('transaction proposal was bad'); - } - if (isProposalGood) { - console.log(util.format( - 'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s", metadata - "%s", endorsement signature: %s', - proposalResponses[0].response.status, proposalResponses[0].response.message, - proposalResponses[0].response.payload, proposalResponses[0].endorsement.signature)); - var request = { - proposalResponses: proposalResponses, - proposal: proposal, - header: header - }; - // 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 transactionID = tx_id.getTransactionID(); - var eventPromises = []; - let eh = client.newEventHub(); - eh.setPeerAddr(options.event_url); - eh.connect(); - - let txPromise = new Promise((resolve, reject) => { - let handle = setTimeout(() => { - eh.disconnect(); - reject(); - }, 30000); - - eh.registerTxEvent(transactionID, (tx, code) => { - clearTimeout(handle); - eh.unregisterTxEvent(transactionID); - eh.disconnect(); - - if (code !== 'VALID') { - console.error( - 'The transaction was invalid, code = ' + code); - reject(); - } else { - console.log( - 'The transaction has been committed on peer ' + - eh._ep._endpoint.addr); - resolve(); - } - }); - }); - eventPromises.push(txPromise); - var sendPromise = channel.sendTransaction(request); - return Promise.all([sendPromise].concat(eventPromises)).then((results) => { - console.log(' event promise all complete and testing complete'); - return results[0]; // the first returned value is from the 'sendPromise' which is from the 'sendTransaction()' call - }).catch((err) => { - console.error( - 'Failed to send transaction and get notifications within the timeout period.' - ); - return 'Failed to send transaction and get notifications within the timeout period.'; - }); - } else { - console.error( - 'Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...' - ); - return 'Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...'; - } -}, (err) => { - console.error('Failed to send proposal due to error: ' + err.stack ? err.stack : - err); - return 'Failed to send proposal due to error: ' + err.stack ? err.stack : - err; -}).then((response) => { - if (response.status === 'SUCCESS') { - console.log('Successfully sent transaction to the orderer.'); - return tx_id.getTransactionID(); - } else { - console.error('Failed to order the transaction. Error code: ' + response.status); - return 'Failed to order the transaction. Error code: ' + response.status; - } -}, (err) => { - console.error('Failed to send transaction due to error: ' + err.stack ? err - .stack : err); - return 'Failed to send transaction due to error: ' + err.stack ? err.stack : - err; + console.log('Send transaction promise and event listener promise have completed'); + // check the results in the order the promises were added to the promise all list + if (results && results[0] && results[0].status === 'SUCCESS') { + console.log('Successfully sent transaction to the orderer.'); + } else { + console.error('Failed to order the transaction. Error code: ' + response.status); + } + + if(results && results[1] && results[1].event_status === 'VALID') { + console.log('Successfully committed the change to the ledger by the peer'); + } else { + console.log('Transaction failed to be committed to the ledger due to ::'+results[1].event_status); + } +}).catch((err) => { + console.error('Failed to invoke successfully :: ' + err); }); diff --git a/fabcar/package.json b/fabcar/package.json index 481773ab0f..cd0cdbcd55 100644 --- a/fabcar/package.json +++ b/fabcar/package.json @@ -7,8 +7,9 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "fabric-ca-client": "unstable", - "fabric-client": "unstable" + "fabric-ca-client": "^1.0.2", + "fabric-client": "^1.0.2", + "grpc": "^1.6.0" }, "author": "Anthony O'Dowd", "license": "Apache-2.0", diff --git a/fabcar/query.js b/fabcar/query.js index 65021508f2..ba57ac3fb9 100644 --- a/fabcar/query.js +++ b/fabcar/query.js @@ -5,64 +5,73 @@ * SPDX-License-Identifier: Apache-2.0 */ /* - * Hyperledger Fabric Sample Query Program + * Chaincode query */ -var hfc = require('fabric-client'); +var Fabric_Client = require('fabric-client'); var path = require('path'); +var util = require('util'); +var os = require('os'); -var options = { - wallet_path: path.join(__dirname, './creds'), - user_id: 'PeerAdmin', - channel_id: 'mychannel', - chaincode_id: 'fabcar', - network_url: 'grpc://localhost:7051', -}; +// +var fabric_client = new Fabric_Client(); -var channel = {}; -var client = null; +// setup the fabric network +var channel = fabric_client.newChannel('mychannel'); +var peer = fabric_client.newPeer('grpc://localhost:7051'); +channel.addPeer(peer); -Promise.resolve().then(() => { - console.log("Create a client and set the wallet location"); - client = new hfc(); - return hfc.newDefaultKeyValueStore({ path: options.wallet_path }); -}).then((wallet) => { - console.log("Set wallet path, and associate user ", options.user_id, " with application"); - client.setStateStore(wallet); - return client.getUserContext(options.user_id, true); -}).then((user) => { - console.log("Check user is enrolled, and set a query URL in the network"); - if (user === undefined || user.isEnrolled() === false) { - console.error("User not defined, or not enrolled - error"); - } - channel = client.newChannel(options.channel_id); - channel.addPeer(client.newPeer(options.network_url)); - return; -}).then(() => { - console.log("Make query"); - var transaction_id = client.newTransactionID(); - console.log("Assigning transaction_id: ", transaction_id._transaction_id); +// +var member_user = null; +var store_path = path.join(__dirname, 'hfc-key-store'); +console.log('Store path:'+store_path); +var tx_id = null; - // queryCar - requires 1 argument, ex: args: ['CAR4'], - // queryAllCars - requires no arguments , ex: args: [''], - const request = { - chaincodeId: options.chaincode_id, - txId: transaction_id, - fcn: 'queryAllCars', - args: [''] - }; - return channel.queryByChaincode(request); +// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting +Fabric_Client.newDefaultKeyValueStore({ path: store_path +}).then((state_store) => { + // assign the store to the fabric client + fabric_client.setStateStore(state_store); + var crypto_suite = Fabric_Client.newCryptoSuite(); + // use the same location for the state store (where the users' certificate are kept) + // and the crypto store (where the users' keys are kept) + var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path}); + crypto_suite.setCryptoKeyStore(crypto_store); + fabric_client.setCryptoSuite(crypto_suite); + + // get the enrolled user from persistence, this user will sign all requests + return fabric_client.getUserContext('user1', true); +}).then((user_from_store) => { + if (user_from_store && user_from_store.isEnrolled()) { + console.log('Successfully loaded user1 from persistence'); + member_user = user_from_store; + } else { + throw new Error('Failed to get user1.... run registerUser.js'); + } + + // queryCar chaincode function - requires 1 argument, ex: args: ['CAR4'], + // queryAllCars chaincode function - requires no arguments , ex: args: [''], + const request = { + //targets : --- letting this default to the peers assigned to the channel + chaincodeId: 'fabcar', + fcn: 'queryAllCars', + args: [''] + }; + + // send the query proposal to the peer + return channel.queryByChaincode(request); }).then((query_responses) => { - console.log("returned from query"); - if (!query_responses.length) { - console.log("No payloads were returned from query"); - } else { - console.log("Query result count = ", query_responses.length) - } - if (query_responses[0] instanceof Error) { - console.error("error from query = ", query_responses[0]); - } - console.log("Response is ", query_responses[0].toString()); + console.log("Query has completed, checking results"); + // query_responses could have more than one results if there multiple peers were used as targets + if (query_responses && query_responses.length == 1) { + if (query_responses[0] instanceof Error) { + console.error("error from query = ", query_responses[0]); + } else { + console.log("Response is ", query_responses[0].toString()); + } + } else { + console.log("No payloads were returned from query"); + } }).catch((err) => { - console.error("Caught Error", err); + console.error('Failed to query successfully :: ' + err); }); diff --git a/fabcar/registerUser.js b/fabcar/registerUser.js new file mode 100644 index 0000000000..2baf8d1cd2 --- /dev/null +++ b/fabcar/registerUser.js @@ -0,0 +1,82 @@ +'use strict'; +/* +* Copyright IBM Corp All Rights Reserved +* +* SPDX-License-Identifier: Apache-2.0 +*/ +/* + * Register and Enroll a user + */ + +var Fabric_Client = require('fabric-client'); +var Fabric_CA_Client = require('fabric-ca-client'); + +var path = require('path'); +var util = require('util'); +var os = require('os'); + +// +var fabric_client = new Fabric_Client(); +var fabric_ca_client = null; +var admin_user = null; +var member_user = null; +var store_path = path.join(__dirname, 'hfc-key-store'); +console.log(' Store path:'+store_path); + +// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting +Fabric_Client.newDefaultKeyValueStore({ path: store_path +}).then((state_store) => { + // assign the store to the fabric client + fabric_client.setStateStore(state_store); + var crypto_suite = Fabric_Client.newCryptoSuite(); + // use the same location for the state store (where the users' certificate are kept) + // and the crypto store (where the users' keys are kept) + var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path}); + crypto_suite.setCryptoKeyStore(crypto_store); + fabric_client.setCryptoSuite(crypto_suite); + var tlsOptions = { + trustedRoots: [], + verify: false + }; + // be sure to change the http to https when the CA is running TLS enabled + fabric_ca_client = new Fabric_CA_Client('http://localhost:7054', null , '', crypto_suite); + + // first check to see if the admin is already enrolled + return fabric_client.getUserContext('admin', true); +}).then((user_from_store) => { + if (user_from_store && user_from_store.isEnrolled()) { + console.log('Successfully loaded admin from persistence'); + admin_user = user_from_store; + } else { + throw new Error('Failed to get admin.... run enrollAdmin.js'); + } + + // at this point we should have the admin user + // first need to register the user with the CA server + return fabric_ca_client.register({enrollmentID: 'user1', affiliation: 'org1.department1'}, admin_user); +}).then((secret) => { + // next we need to enroll the user with CA server + console.log('Successfully registered user1 - secret:'+ secret); + + return fabric_ca_client.enroll({enrollmentID: 'user1', enrollmentSecret: secret}); +}).then((enrollment) => { + console.log('Successfully enrolled member user "user1" '); + return fabric_client.createUser( + {username: 'user1', + mspid: 'Org1MSP', + cryptoContent: { privateKeyPEM: enrollment.key.toBytes(), signedCertPEM: enrollment.certificate } + }); +}).then((user) => { + member_user = user; + + return fabric_client.setUserContext(member_user); +}).then(()=>{ + console.log('User1 was successfully registered and enrolled and is ready to intreact with the fabric network'); + +}).catch((err) => { + console.error('Failed to register: ' + err); + if(err.toString().indexOf('Authorization') > -1) { + console.error('Authorization failures may be caused by having admin credentials from a previous CA instance.\n' + + 'Try again after deleting the contents of the store directory '+store_path); + } +}); diff --git a/fabcar/startFabric.sh b/fabcar/startFabric.sh index a9e68b142a..c1eef0502f 100755 --- a/fabcar/startFabric.sh +++ b/fabcar/startFabric.sh @@ -16,10 +16,6 @@ if [ "$LANGUAGE" = "node" -o "$LANGUAGE" = "NODE" ]; then CC_SRC_PATH=/opt/gopath/src/github.com/fabcar/node fi -if [ ! -d ~/.hfc-key-store/ ]; then - mkdir ~/.hfc-key-store/ -fi -cp $PWD/creds/* ~/.hfc-key-store/ # launch network; create channel and join peer to channel cd ../basic-network ./start.sh @@ -33,4 +29,8 @@ docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/g sleep 10 docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" cli peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n fabcar -c '{"function":"initLedger","Args":[""]}' -printf "\nTotal execution time : $(($(date +%s) - starttime)) secs ...\n\n" +printf "\nTotal setup execution time : $(($(date +%s) - starttime)) secs ...\n\n\n" +printf "Start by installing required packages run 'npm install'\n" +printf "Then run 'node enrollAdmin.js', then 'node registerUser'\n\n" +printf "The 'node invoke.js' will fail until it has been updated with valid arguments\n" +printf "The 'node query.js' may be run at anytime once the user has been registered\n\n"