From 1f08e8491ba6f704edd5b469515064f1c660e47b Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Wed, 30 Nov 2016 15:07:58 -0500 Subject: [PATCH] FAB-1084 Move MemberServices out of HFC To support the new member service aka COP, MemberService.js has been moved to it's own directory, hfc-cop, so that it can be published as a separate npmjs package. This also required the remaining HFC code to be moved to a new directory, hfc. The build tasks were modified to run against both directories. The readthedocs files remain in the root fabric-node-sdk directory. FAB-1084 Patch set 1: Move hfc src to hfc directory and add hfc-cop directory. Patch set 2: Readme update in root. Patch set 3: Remove MemberServices and references in hfc and headless-tests. Pare down package.json in root which is needed to npm install test dependencies. Patch set 4: Update commit message. Patch set 5: Move FabricCOPImpl to hfc-cop. Patch set 6: Change root package.json to point to hfc and hfc-cop directories and remove relative path to hfc from hfc-cop FabricCOPImpl requires. Patch set 7: the following changes were made - use 'hfc' and 'hfc-cop' modules instead of relative paths so that each package's dependencies can be properly found by npm - added gulp watch for hfc-cop's dependencies in the hfc folder - added gulp watch to update installed hfc and hfc-cop modules from source code changes during development - set required node and npm versions to earlier - updated how User object is obtained in tests with test/unit/unit.js -> getSubmitter() - updated README with the new developer workflow Change-Id: I16c85d2e3b73dca883b56e106e35bf4fceb97a8b Signed-off-by: cdaughtr Signed-off-by: Jim Zhang --- .gitignore | 10 + README.md | 24 +- build/tasks/cop.js | 23 ++ build/tasks/doc.js | 21 +- build/tasks/eslint.js | 2 +- build/tasks/test.js | 20 +- build/tasks/watch.js | 17 ++ hfc-cop/README.md | 3 + hfc-cop/config/default.json | 8 + {lib/impl => hfc-cop/lib}/FabricCOPImpl.js | 4 +- hfc-cop/package.json | 35 +++ hfc/README.md | 3 + {config => hfc/config}/default.json | 0 index.js => hfc/index.js | 0 {lib => hfc/lib}/Chain.js | 168 +---------- {lib => hfc/lib}/Config.js | 0 {lib => hfc/lib}/Member.js | 140 +-------- {lib => hfc/lib}/Orderer.js | 0 {lib => hfc/lib}/Peer.js | 0 {lib => hfc/lib}/Remote.js | 0 {lib => hfc/lib}/X509Certificate.js | 0 {lib => hfc/lib}/api.js | 103 ------- {lib => hfc/lib}/hash.js | 0 .../lib}/impl/CryptoSuite_ECDSA_AES.js | 0 {lib => hfc/lib}/impl/FileKeyValueStore.js | 0 {lib => hfc/lib}/impl/ecdsa/key.js | 0 {lib => hfc/lib}/protos/.protoroot | 0 {lib => hfc/lib}/protos/ca.proto | 0 {lib => hfc/lib}/protos/common/common.proto | 0 .../lib}/protos/common/configuration.proto | 0 .../lib}/protos/google/protobuf/empty.proto | 0 .../protos/google/protobuf/timestamp.proto | 0 {lib => hfc/lib}/protos/orderer/ab.proto | 0 {lib => hfc/lib}/protos/peer/api.proto | 0 {lib => hfc/lib}/protos/peer/chaincode.proto | 0 .../lib}/protos/peer/chaincode_proposal.proto | 0 .../protos/peer/chaincode_transaction.proto | 0 .../lib}/protos/peer/chaincodeevent.proto | 0 {lib => hfc/lib}/protos/peer/devops.proto | 0 {lib => hfc/lib}/protos/peer/events.proto | 0 {lib => hfc/lib}/protos/peer/fabric.proto | 0 .../lib}/protos/peer/fabric_block.proto | 0 .../lib}/protos/peer/fabric_message.proto | 0 .../lib}/protos/peer/fabric_proposal.proto | 0 .../peer/fabric_proposal_response.proto | 0 .../lib}/protos/peer/fabric_service.proto | 0 .../lib}/protos/peer/fabric_transaction.proto | 0 .../peer/fabric_transaction_header.proto | 0 .../lib}/protos/peer/server_admin.proto | 0 {lib => hfc/lib}/utils-x509cert.js | 0 {lib => hfc/lib}/utils.js | 28 +- hfc/package.json | 70 +++++ lib/impl/MemberServices.js | 270 ------------------ package.json | 41 +-- test/unit/ca-tests.js | 4 +- test/unit/chain-fabriccop-tests.js | 61 ++-- test/unit/end-to-end.js | 8 +- test/unit/endorser-tests.js | 19 +- test/unit/fabriccopservices-tests.js | 12 +- test/unit/headless-tests.js | 90 ++---- test/unit/marbles.js | 12 +- test/unit/orderer-member-tests.js | 25 +- test/unit/orderer-tests.js | 6 +- test/unit/util.js | 47 ++- 64 files changed, 376 insertions(+), 898 deletions(-) create mode 100644 build/tasks/cop.js create mode 100644 build/tasks/watch.js create mode 100644 hfc-cop/README.md create mode 100644 hfc-cop/config/default.json rename {lib/impl => hfc-cop/lib}/FabricCOPImpl.js (99%) create mode 100644 hfc-cop/package.json create mode 100644 hfc/README.md rename {config => hfc/config}/default.json (100%) rename index.js => hfc/index.js (100%) rename {lib => hfc/lib}/Chain.js (56%) rename {lib => hfc/lib}/Config.js (100%) rename {lib => hfc/lib}/Member.js (88%) rename {lib => hfc/lib}/Orderer.js (100%) rename {lib => hfc/lib}/Peer.js (100%) rename {lib => hfc/lib}/Remote.js (100%) rename {lib => hfc/lib}/X509Certificate.js (100%) rename {lib => hfc/lib}/api.js (69%) rename {lib => hfc/lib}/hash.js (100%) rename {lib => hfc/lib}/impl/CryptoSuite_ECDSA_AES.js (100%) rename {lib => hfc/lib}/impl/FileKeyValueStore.js (100%) rename {lib => hfc/lib}/impl/ecdsa/key.js (100%) rename {lib => hfc/lib}/protos/.protoroot (100%) rename {lib => hfc/lib}/protos/ca.proto (100%) rename {lib => hfc/lib}/protos/common/common.proto (100%) rename {lib => hfc/lib}/protos/common/configuration.proto (100%) rename {lib => hfc/lib}/protos/google/protobuf/empty.proto (100%) rename {lib => hfc/lib}/protos/google/protobuf/timestamp.proto (100%) rename {lib => hfc/lib}/protos/orderer/ab.proto (100%) rename {lib => hfc/lib}/protos/peer/api.proto (100%) rename {lib => hfc/lib}/protos/peer/chaincode.proto (100%) rename {lib => hfc/lib}/protos/peer/chaincode_proposal.proto (100%) rename {lib => hfc/lib}/protos/peer/chaincode_transaction.proto (100%) rename {lib => hfc/lib}/protos/peer/chaincodeevent.proto (100%) rename {lib => hfc/lib}/protos/peer/devops.proto (100%) rename {lib => hfc/lib}/protos/peer/events.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_block.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_message.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_proposal.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_proposal_response.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_service.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_transaction.proto (100%) rename {lib => hfc/lib}/protos/peer/fabric_transaction_header.proto (100%) rename {lib => hfc/lib}/protos/peer/server_admin.proto (100%) rename {lib => hfc/lib}/utils-x509cert.js (100%) rename {lib => hfc/lib}/utils.js (93%) create mode 100644 hfc/package.json delete mode 100644 lib/impl/MemberServices.js diff --git a/.gitignore b/.gitignore index 1312d8890c..03720d3cda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,14 @@ coverage docs/gen node_modules/* +hfc/node_modules/* +hfc-cop/node_modules/* +hfc-cop/lib/api.js +hfc-cop/lib/utils.js +hfc-cop/lib/Config.js +hfc-cop/lib/Remote.js +hfc-cop/lib/hash.js +hfc-cop/lib/impl/* test/fixtures/src/github.com/example_cc/Dockerfile test/fixtures/src/github.com/marbles_cc/Dockerfile npm-shrinkwrap.json @@ -8,3 +16,5 @@ npm-debug.log tmp .project .DS_Store +hfc/.DS_Store +hfc-cop/.DS_Store diff --git a/README.md b/README.md index ffad5eceb8..3fbf10753f 100644 --- a/README.md +++ b/README.md @@ -3,28 +3,38 @@ [![Build Status](https://jenkins.hyperledger.org/buildStatus/icon?job=fabric-sdk-node-merge-x86_64)](https://jenkins.hyperledger.org/view/fabric-sdk-node/job/fabric-sdk-node-merge-x86_64/) [![Documentation Status](https://readthedocs.org/projects/fabric-sdk-node/badge/?version=master)](http://fabric-sdk-node.readthedocs.io/en/master/?badge=master) -The Hyperledger Fabric Client SDK (HFC) provides a powerful and easy to use API to interact with a Hyperledger Fabric blockchain. +The Hyperledger Fabric Client SDK (HFC) makes it easy to use APIs to interact with a Hyperledger Fabric blockchain. As an application developer, to learn about how to install and use the Node.js SDK, please visit the [fabric documentation](http://hyperledger-fabric.readthedocs.io/en/latest/Setup/NodeSDK-setup). -The following section targets a current or future contributor to this project itself. It describes the main object hierarchy, plus HFC's pluggability and extensibility design. +The following section targets a current or future contributor to this project itself. ### Build and Test To build and test, the following pre-requisites must be installed first: -* node runtime version 4.3 or later (which also installs the npm tool) +* node runtime version 4.5 or later (which also installs the npm tool) +* npm tool version 2.15.9 or later * gulp command * docker (not required if you only want to run the headless tests with `npm test`, see below) -Clone the project and launch the following commands in the project root folder to install the dependencies and perform various tasks: -* `npm install` to install all dependencies +Clone the project and launch the following commands to install the dependencies and perform various tasks. + +This project publishes two separate npm packages: +* `hfc` - main client for the Hyperledger Fabric. Applications can use this package to deploy chaincodes, submit transactions and make queries against a Hyperledger Fabric-based blockchain network. +* `hfc-cop` - client for the optional component in Hyperledger Fabric, [COP](https://github.com/hyperledger/fabric-cop). The COP component allows applications to enroll Peers and application users to establish trusted identities on the blockchain network. It also provides support for pseudonymous transaction submissions with Transaction Certificates. If the target blockchain network is configured with standard Certificate Authorities for trust anchors, then the application does not need to use this package. + +In the project root folder: +* `npm install` to install dependencies +* `gulp cop` to copy common dependent modules from the `hfc` folder to the `hfc-cop` folder +* `gulp watch` to set up watch that updates hfc-cop's shared dependencies from hfc/lib and updates installed hfc and hfc-cop modules in node_modules * `gulp doc` to generate API docs * `npm test` to run the headless tests that do not require any additional set up The following tests require setting up a local blockchain network as the target. Because v1.0 is still in active development, you still need the vagrant environment to build the necessary Docker images needed to run the network. Follow the steps below to set it up. * `cd fabric/devenv` * Open the file `Vagrantfile` and insert the following statement below the existing `config.vm.network` statements: - * ` config.vm.network :forwarded_port, guest: 7056, host: 7056 # gRPC services port for peer vp1` - * ` config.vm.network :forwarded_port, guest: 8888, host: 8888 # http port for COP server` + * ` config.vm.network :forwarded_port, guest: 7056, host: 7056 # Openchain gRPC services` + * ` config.vm.network :forwarded_port, guest: 7058, host: 7058 # GRPCCient gRPC services` + * ` config.vm.network :forwarded_port, guest: 8888, host: 8888 # COP services` * run `vagrant up` to launch the vagrant VM * Once inside vagrant, `cd $GOPATH/src/github.com/hyperledger/fabric` diff --git a/build/tasks/cop.js b/build/tasks/cop.js new file mode 100644 index 0000000000..0e1eafb894 --- /dev/null +++ b/build/tasks/cop.js @@ -0,0 +1,23 @@ +'use strict'; + +var gulp = require('gulp'); +var debug = require('gulp-debug'); + +const DEPS = [ + 'hfc/lib/api.js', + 'hfc/lib/hash.js', + 'hfc/lib/utils.js', + 'hfc/lib/Config.js', + 'hfc/lib/Remote.js', + 'hfc/lib/impl/CryptoSuite_ECDSA_AES.js', + 'hfc/lib/impl/ecdsa/*', + 'hfc/lib/impl/FileKeyValueStore.js' +]; + +gulp.task('cop', function() { + return gulp.src(DEPS, { base: 'hfc/' }) + .pipe(debug()) + .pipe(gulp.dest('hfc-cop/')); +}); + +module.exports.DEPS = DEPS; diff --git a/build/tasks/doc.js b/build/tasks/doc.js index af56198ab0..42e09e5069 100644 --- a/build/tasks/doc.js +++ b/build/tasks/doc.js @@ -20,17 +20,16 @@ var jsdoc = require('gulp-jsdoc3'); gulp.task('doc', function () { gulp.src([ 'README.md', - 'index.js', - './lib/api.js', - './lib/impl/FileKeyValueStore.js', - './lib/impl/CryptoSuite_ECDSA_AES.js', - './lib/impl/ecdsa/key.js', - './lib/impl/MemberServices.js', - './lib/impl/FabricCOPImpl.js', - './lib/Chain.js', - './lib/Member.js', - './lib/Peer.js', - './lib/X509Certificate.js' + 'hfc/index.js', + 'hfc/lib/api.js', + 'hfc/lib/impl/FileKeyValueStore.js', + 'hfc/lib/impl/CryptoSuite_ECDSA_AES.js', + 'hfc/lib/impl/ecdsa/key.js', + 'hfc/lib/impl/FabricCOPImpl.js', + 'hfc/lib/Chain.js', + 'hfc/lib/Member.js', + 'hfc/lib/Peer.js', + 'hfc/lib/X509Certificate.js' ], {read: false}) .pipe(jsdoc()) .pipe(gulp.dest('./docs/gen')); diff --git a/build/tasks/eslint.js b/build/tasks/eslint.js index 5ac410d75f..19a57e1f24 100644 --- a/build/tasks/eslint.js +++ b/build/tasks/eslint.js @@ -2,7 +2,7 @@ var gulp = require('gulp'); var eslint = require('gulp-eslint'); gulp.task('lint', function () { - return gulp.src(['**/*.js', '!node_modules/**', '!docs/**', '!coverage/**', '!tmp/**']) + return gulp.src(['**/*.js', 'hfc/**/*.js', '!node_modules/**', '!docs/**', '!coverage/**', '!tmp/**', 'hfc-cop/lib/*.js']) .pipe(eslint( { env: ['es6', 'node'], diff --git a/build/tasks/test.js b/build/tasks/test.js index 1f0bd988ea..30cfd52eb3 100644 --- a/build/tasks/test.js +++ b/build/tasks/test.js @@ -6,7 +6,7 @@ var tapColorize = require('tap-colorize'); var istanbul = require('gulp-istanbul'); gulp.task('pre-test', function() { - return gulp.src(['lib/**/*.js']) + return gulp.src(['hfc/lib/**/*.js','hfc-cop/lib/**/*.js']) .pipe(istanbul()) .pipe(istanbul.hookRequire()); }); @@ -17,11 +17,19 @@ gulp.task('test', ['pre-test'], function() { // enrollment scenarios (good and bad calls). then the rest of the // tests will re-used the same key value store that has saved the // user certificates so they can interact with the network - return gulp.src(['test/unit/ca-tests.js', 'test/unit/endorser-tests.js', 'test/unit/orderer-tests.js', 'test/unit/orderer-member-tests.js', 'test/unit/end-to-end.js', 'test/unit/headless-tests.js']) - .pipe(tape({ - reporter: tapColorize() - })) - .pipe(istanbul.writeReports()); + return gulp.src([ + // 'test/unit/ca-tests.js', + 'test/unit/chain-fabriccop-tests.js', + 'test/unit/endorser-tests.js', + 'test/unit/orderer-tests.js', + 'test/unit/orderer-member-tests.js', + 'test/unit/end-to-end.js', + 'test/unit/headless-tests.js' + ]) + .pipe(tape({ + reporter: tapColorize() + })) + .pipe(istanbul.writeReports()); }); gulp.task('test-headless', ['pre-test'], function() { diff --git a/build/tasks/watch.js b/build/tasks/watch.js new file mode 100644 index 0000000000..ba58a15171 --- /dev/null +++ b/build/tasks/watch.js @@ -0,0 +1,17 @@ +var gulp = require('gulp'), + watch = require('gulp-watch'), + debug = require('gulp-debug'), + cop = require('./cop.js'); + +gulp.task('watch', function () { + watch(cop.DEPS, { ignoreInitial: false, base: 'hfc/' }) + .pipe(debug()) + .pipe(gulp.dest('hfc-cop/')); + + watch([ + 'hfc/lib/**/*', + 'hfc-cop/lib/**/*' + ], { ignoreInitial: false, base: './' }) + .pipe(debug()) + .pipe(gulp.dest('node_modules')); +}); \ No newline at end of file diff --git a/hfc-cop/README.md b/hfc-cop/README.md new file mode 100644 index 0000000000..8c40240f6f --- /dev/null +++ b/hfc-cop/README.md @@ -0,0 +1,3 @@ +## Hyperledger Fabric Client SDK for Node.js, Membership Services (aka `COP`) + +See hyperledger\fabric-sdk-node root README.md for more information. \ No newline at end of file diff --git a/hfc-cop/config/default.json b/hfc-cop/config/default.json new file mode 100644 index 0000000000..f9d144448a --- /dev/null +++ b/hfc-cop/config/default.json @@ -0,0 +1,8 @@ +{ + "request-timeout" : 3000, + "tcert-batch-size" : 10, + "crypto-asymmetric-key-algo": "ECDSA", + "crypto-hash-algo": "SHA3", + "crypto-keysize": 384, + "crypto-suite": "./impl/CryptoSuite_ECDSA_AES.js", +} diff --git a/lib/impl/FabricCOPImpl.js b/hfc-cop/lib/FabricCOPImpl.js similarity index 99% rename from lib/impl/FabricCOPImpl.js rename to hfc-cop/lib/FabricCOPImpl.js index 4b8ce004b6..284b8d65bf 100644 --- a/lib/impl/FabricCOPImpl.js +++ b/hfc-cop/lib/FabricCOPImpl.js @@ -16,8 +16,8 @@ 'use strict'; -var api = require('../api.js'); -var utils = require('../utils'); +var api = require('./api.js'); +var utils = require('./utils.js'); var util = require('util'); var jsrsa = require('jsrsasign'); var asn1 = jsrsa.asn1; diff --git a/hfc-cop/package.json b/hfc-cop/package.json new file mode 100644 index 0000000000..9ca6ca35e2 --- /dev/null +++ b/hfc-cop/package.json @@ -0,0 +1,35 @@ +{ + "name": "hfc-cop", + "version": "0.0.1", + "main": "./lib/FabricCOPImpl.js", + "repository": { + "type": "gerrit", + "url": "http://gerrit.hyperledger.org/r/fabric-sdk-node" + }, + "engines": { + "node": ">=4.5.0", + "npm": ">=2.15.9" + }, + "engine-strict": true, + "engineStrict": true, + "dependencies": { + "asn1": "https://github.com/mcavage/node-asn1", + "elliptic": "^6.2.3", + "fs-extra": ">=0.30.0 <0.31.0", + "grpc": "^1.0.0", + "js-sha3": "^0.5.1", + "jsrsasign": "^6.2.2", + "jssha": "^2.1.0", + "nconf": "^0.8.4", + "sjcl": "1.0.3", + "sjcl-codec": "0.1.1", + "tar-fs": "^1.13.0", + "url": "^0.11.0", + "util": "^0.10.3" + }, + "license": "Apache-2.0", + "licenses": [{ + "type": "Apache-2.0", + "url": "https://github.com/hyperledger/fabric/blob/master/LICENSE" + }] +} diff --git a/hfc/README.md b/hfc/README.md new file mode 100644 index 0000000000..e8900b633d --- /dev/null +++ b/hfc/README.md @@ -0,0 +1,3 @@ +## Hyperledger Fabric Client SDK for Node.js + +See hyperledger\fabric-sdk-node root README.md for more information. diff --git a/config/default.json b/hfc/config/default.json similarity index 100% rename from config/default.json rename to hfc/config/default.json diff --git a/index.js b/hfc/index.js similarity index 100% rename from index.js rename to hfc/index.js diff --git a/lib/Chain.js b/hfc/lib/Chain.js similarity index 56% rename from lib/Chain.js rename to hfc/lib/Chain.js index 2ec771a0ef..6c48a0893e 100644 --- a/lib/Chain.js +++ b/hfc/lib/Chain.js @@ -21,7 +21,6 @@ var utils = require('./utils.js'); var urlParser = require('url'); var net = require('net'); var util = require('util'); -var MemberServices = utils.getMemberService(); var Member = require('./Member.js'); var Orderer = require('./Orderer.js'); @@ -52,12 +51,6 @@ var Chain = class { // The number of tcerts to get in each batch this._tcertBatchSize = utils.getConfigSetting('tcert-batch-size',200); - // The registrar (if any) that registers & enrolls new members/users - this._registrar = null; // Member - - // The member services used for this chain - this._memberServices = null; // MemberServices - // The key-val store used for this chain this._keyValStore = null; // KeyValueStore; @@ -90,55 +83,11 @@ var Chain = class { return this._name; } - /** - * Get the member whose credentials are used to register and enroll other users, or undefined if not set. - * @returns [Member]{@link module:api.Member} The member whose credentials are used to perform registration, or undefined if not set. - */ - getRegistrar() { - return this._registrar; - } - - /** - * Set the member whose credentials are used to register and enroll other users. - * @param [Member]{@link module:api.Member} registrar The member whose credentials are used to perform registration. - */ - setRegistrar(registrar) { - this._registrar = registrar; - } - - /** - * Set the member services URL - * @param {string} url Member services URL of the form: 'grpc://host:port' or 'grpcs://host:port' - * @param {Object} opts Object with all connections settings including the 'pem' value of the TLS certificate for the local client - */ - setMemberServicesUrl(url, opts) { - this.setMemberServices(new MemberServices(url, opts)); - } - - /** - * Get the member service associated this chain. - * @returns [MemberService]{@link module:api.MemberService} Return the current member service, or undefined if not set. - */ - getMemberServices() { - return this._memberServices; - } - - /** - * Set the member service associated this chain. This allows the default implementation of member service to be overridden. - * @param [MemberService]{@link module:api.MemberService} an instance of the MemberServices class - */ - setMemberServices(memberServices) { - this._memberServices = memberServices; - if (memberServices instanceof MemberServices) { - this.cryptoPrimitives = memberServices.getCrypto(); - } - } - /** * Determine if security is enabled. */ isSecurityEnabled() { - return this._memberServices !== undefined; + return this._keyValStore !== undefined; } /** @@ -211,11 +160,6 @@ var Chain = class { return reject(new Error('No key value store was found. You must first call Chain.configureKeyValueStore or Chain.setKeyValueStore')); } - if (!self._memberServices) { - logger.error('No member services was found on this Chain instance: name - "%s"', self._name); - return reject(new Error('No member services was found. You must first call Chain.configureMemberServices or Chain.setMemberServices')); - } - self._getMemberHelper(name).then( function(member) { logger.debug('Requested member "%s" resolved successfully on this Chain instance: name - %s', name, self._name); @@ -277,116 +221,6 @@ var Chain = class { }); } - /** - * Register a user or other member type with the chain. - * @param registrationRequest Registration information. - * @returns Promise for a 'true' status on successful registration - */ - register(registrationRequest) { - if (!registrationRequest.enrollmentID) { - logger.error('Invalid parameter to "register()" function, object must include property "enrollmentID"'); - return Promise.reject(new Error('Invalid parameter to "register()" function, object must include property "enrollmentID"')); - } - - var self = this; - - return new Promise(function(resolve, reject) { - self.getMember(registrationRequest.enrollmentID) - .then( - function(member) { - if (member.isRegistered()) { - return resolve(member._enrollmentSecret); - } else { - return member.register(registrationRequest); - } - } - ).then( - function(enrollmentSecret) { - return resolve(enrollmentSecret); - } - ).catch( - function(err) { - logger.error('Failed to register member "%s". Error: %s', registrationRequest.enrollmentID, err.stack ? err.stack : err); - reject(err); - } - ); - }); - } - - /** - * Enroll a user or other identity which has already been registered. - * If the user has already been enrolled, this will still succeed. - * @param name The name of the user or other member to enroll. - * @param secret The secret of the user or other member to enroll. - * @param cb The callback to return the user or other member. - */ - enroll(name, secret) { - logger.debug('Chain.enroll - start name:'+name); - var self = this; - - return new Promise(function(resolve, reject) { - var _member; - self.getMember(name) - .then( - function(member) { - _member = member; - logger.debug('Chain.enroll - call member.enroll'); - return _member.enroll(secret); - } - ).then( - function() { - logger.debug('Chain.enroll - resolved - member:'+name); - return resolve(_member); - } - ).catch( - function(err) { - logger.error('Failed to enroll member "%s". Error: %s', name, err.stack ? err.stack : err); - reject(err); - } - ); - }); - } - - /** - * Register and enroll a user or other member type. - * This assumes that a registrar with sufficient privileges has been set. - * @param registrationRequest Registration information. - * @params - */ - registerAndEnroll(registrationRequest) { - if (!registrationRequest.enrollmentID) { - logger.error('Invalid parameter to "registerAndEnroll()" function, object must include property "enrollmentID"'); - return Promise.reject(new Error('Invalid parameter to "registerAndEnroll()" function, object must include property "enrollmentID"')); - } - - var self = this; - - return new Promise(function(resolve, reject) { - var _member; - - self.getMember(registrationRequest.enrollmentID) - .then( - function(member) { - if (member.isEnrolled()) { - return resolve(member); - } - - _member = member; - return _member.registerAndEnroll(registrationRequest); - } - ).then( - function() { - return resolve(_member); - } - ).catch( - function(err) { - logger.error('Failed to register and enroll member "%s". Error: %s', registrationRequest.enrollmentID, err.stack ? err.stack : err); - reject(err); - } - ); - }); - } - /** * Set the orderer given an endpoint specification. * Will replace the existing orderer if one exists. diff --git a/lib/Config.js b/hfc/lib/Config.js similarity index 100% rename from lib/Config.js rename to hfc/lib/Config.js diff --git a/lib/Member.js b/hfc/lib/Member.js similarity index 88% rename from lib/Member.js rename to hfc/lib/Member.js index 44875946dc..b46e749ce8 100644 --- a/lib/Member.js +++ b/hfc/lib/Member.js @@ -72,7 +72,6 @@ var Member = class { } this._chain = chain; - this._memberServices = chain.getMemberServices(); this._keyValStore = chain.getKeyValueStore(); this._keyValStoreName = toKeyValueStoreName(this._name); this._tcertBatchSize = chain.getTCertBatchSize(); @@ -98,14 +97,6 @@ var Member = class { return this._chain; } - /** - * Get the member services. - * @returns {MemberServices} The member services. - */ - getMemberServices() { - return this._memberServices; - } - /** * Get the roles. * @returns {string[]} The roles. @@ -159,22 +150,6 @@ var Member = class { this._tcertBatchSize = batchSize; } - /** - * Get the enrollment info. - * @returns {Enrollment} The enrollment. - */ - getEnrollment() { - return this._enrollment; - } - - /** - * Determine if this name has been registered. - * @returns {boolean} True if registered; otherwise, false. - */ - isRegistered() { - return this._enrollmentSecret !== ''; - } - /** * Determine if this name has been enrolled. * @returns {boolean} True if enrolled; otherwise, false. @@ -183,117 +158,6 @@ var Member = class { return this._enrollment !== null; } - /** - * Register the member. - * @param {Object} registrationRequest - */ - register(registrationRequest) { - var self = this; - - return new Promise(function(resolve, reject) { - if (registrationRequest.enrollmentID !== self.getName()) { - reject(new Error('registration enrollment ID and member name are not equal')); - } - - var enrollmentSecret = self._enrollmentSecret; - if (enrollmentSecret && enrollmentSecret !== '') { - return resolve(enrollmentSecret); - } else { - self._memberServices.register(registrationRequest, self._chain.getRegistrar()) - .then( - function(enrollmentSecret) { - - self._enrollmentSecret = enrollmentSecret; - return self.saveState(); - } - ).then( - function(data) { - return resolve(self._enrollmentSecret); - } - ).catch( - function(err) { - logger.error('Failed to register user "%s". Error: %s', registrationRequest.enrollmentID, err.stack ? err.stack : err); - reject(err); - } - ); - } - }); - } - - /** - * Enroll the member and return the enrollment results. - * @param {Object} enrollmentSecret The password or enrollment secret as returned by register. - */ - enroll(enrollmentSecret) { - var self = this; - - return new Promise(function(resolve, reject) { - var enrollment = self._enrollment; - if (self.isEnrolled()) { - return resolve(self.getEnrollment()); - } else { - var req = { - enrollmentID: self.getName(), - enrollmentSecret: enrollmentSecret - }; - - self._memberServices.enroll(req) - .then( - function(enrollment) { - - self._enrollment = enrollment; - - // Save state - return self.saveState() - .then(function() { - return resolve(enrollment); - }); - } - ).then( - function(enrollment) { - return resolve(enrollment); - } - ).catch( - function(err) { - logger.error('Failed to enroll user "%s". Error: %s', self.getName(), err.stack ? err.stack : err); - reject(err); - } - ); - } - }); - } - - /** - * Perform both registration and enrollment. - * @param {Object} registrationRequest - */ - registerAndEnroll(registrationRequest) { - var self = this; - - return new Promise(function(resolve, reject) { - var enrollment = self._enrollment; - if (enrollment) { - return resolve(enrollment); - } else { - self.register(registrationRequest) - .then( - function(enrollmentSecret) { - return self.enroll(enrollmentSecret); - } - ).then( - function(enrollment) { - return resolve(enrollment); - } - ).catch( - function(err) { - logger.error('Failed to register and enroll user "%s". Error: %s', self.getName(), err.stack ? err.stack : err); - reject(err); - } - ); - } - }); - } - /** * Save the state of this member to the key value store. * @returns {Promise} A Promise for a 'true' upon successful save @@ -310,6 +174,10 @@ var Member = class { var self = this; return new Promise(function(resolve, reject) { + if (!self._keyValStore.getValue) { + logger.error('KeyValueStore.getValue function is undefined. Need to setValue on KeyValueStore.'); + reject(new Error('KeyValueStore.getValue function is undefined. Need to setValue on KeyValueStore.')); + } self._keyValStore.getValue(self._keyValStoreName) .then( function(memberStr) { diff --git a/lib/Orderer.js b/hfc/lib/Orderer.js similarity index 100% rename from lib/Orderer.js rename to hfc/lib/Orderer.js diff --git a/lib/Peer.js b/hfc/lib/Peer.js similarity index 100% rename from lib/Peer.js rename to hfc/lib/Peer.js diff --git a/lib/Remote.js b/hfc/lib/Remote.js similarity index 100% rename from lib/Remote.js rename to hfc/lib/Remote.js diff --git a/lib/X509Certificate.js b/hfc/lib/X509Certificate.js similarity index 100% rename from lib/X509Certificate.js rename to hfc/lib/X509Certificate.js diff --git a/lib/api.js b/hfc/lib/api.js similarity index 69% rename from lib/api.js rename to hfc/lib/api.js index 5bd799c5ff..ed14fa0efe 100644 --- a/lib/api.js +++ b/hfc/lib/api.js @@ -234,109 +234,6 @@ module.exports.Enrollment = class { } }; -/** - * The member services client. Can add new users to the member service's user registry ("Register"), - * and exchange one-time passwords for enrollment certificates ("Enroll"). It also downloads TCerts - * for an enrolled user. - * - * @class - */ -module.exports.MemberServices = class extends Remote { - - /** - * Get the key length of the asymmetric key algorithm in effect - * - * @returns {number} The key length, for instance "256" or "384" - */ - getSecurityLevel() {} - - /** - * Set the key length of the asymmetric key algorithm in effect, it must be one that is supported - * by the current crypto suite. - * - * @params {number} securityLevel The key length for the asymmetric key algorithm, for instance "256" or "384" - */ - setSecurityLevel(securityLevel) {} - - /** - * Get the secure hash algorithm in effect, for instance "SHA2" or "SHA3" - * - * @returns {string} The secure hash algorithm - */ - getHashAlgorithm() {} - - /** - * Set the secure hash algorithm in effect, for instance "SHA2" or "SHA3". It must be one that is - * supported by the current crypto suite. - * - * @params {string} securityLevel The secure hash algorithm - */ - setHashAlgorithm(hashAlgorithm) {} - - /** - * Add the member to the user registry and return an enrollment secret to be used later one to exchange - * for enrollment certificate. - * - * @param {Object} req Registration request with the following fields: - * - * enrollmentID: {string} The enrollment ID of the member, - * - * roles: {string[]} Roles associated with this member. One of 'client', 'peer', 'validator', 'auditor'. Default: ["client"], - * - * affiliation: {string} what organization this user belongs to, - * - * registrar: {Object} registrar enables this identity to register other members and can delegate the 'delegationRoles' roles - * - * roles: {string[]} The allowable roles which this member can register - * - * delegateRoles: {string[]} The allowable roles which can be registered by members registered by this member - * - * @param {Member} registrar The identity of the registar (i.e. who is performing the registration) - * @returns Promise for the enrollment secret - */ - register(req, registrar) {} - - /** - * Exchange the one-time password, a.k.a the enrollment secrete, for enrollment certificate. - * - * User enrollment is a two step process. - * 1) Send a create Certificate request to the server with two public keys: - * - A signature key that will be used to verify the signature of the keys - * - An encryption key that will be used to encrypt the data - * - * In response to this request, server creates a challenge and sends it to the client after encrypting it with - * the encryption public key to ensure that the client is in possession of the encryption private key - * - * 2) Client decrypts the token returned by the server in step 1, adds it to the request, creates the signature - * with the signing private key and sends another Create Certificate request to the server. Server verifies that - * signature and decrypted token is correct, server sends enrollment certificates to the client. - * - * @param {Object} req Enrollment request with the following fields: - * - * enrollmentID: {string} The enrollment ID, - * - * enrollmentSecret: {string} The enrollment secret (a one-time password) - * - * @returns Promise for [Enrollment]{@link module:api.Enrollment} - */ - enroll(req) {} - - /** - * Get an array of transaction certificates (tcerts). - * - * @param {Object} req A request object with the following fields: - * - * name: {string} name of the user - * enrollment: [Enrollment]{@link module:api.Enrollment} an object representing the user to get the TCerts for, - * num: {number} batch size, - * attrs: {string[]} the list of user attributes to include in the TCerts - * - * @returns Promise for array of [TCert]{@link module:api.TCert} - */ - getTCertBatch(req) {} - -}; - /** * @class */ diff --git a/lib/hash.js b/hfc/lib/hash.js similarity index 100% rename from lib/hash.js rename to hfc/lib/hash.js diff --git a/lib/impl/CryptoSuite_ECDSA_AES.js b/hfc/lib/impl/CryptoSuite_ECDSA_AES.js similarity index 100% rename from lib/impl/CryptoSuite_ECDSA_AES.js rename to hfc/lib/impl/CryptoSuite_ECDSA_AES.js diff --git a/lib/impl/FileKeyValueStore.js b/hfc/lib/impl/FileKeyValueStore.js similarity index 100% rename from lib/impl/FileKeyValueStore.js rename to hfc/lib/impl/FileKeyValueStore.js diff --git a/lib/impl/ecdsa/key.js b/hfc/lib/impl/ecdsa/key.js similarity index 100% rename from lib/impl/ecdsa/key.js rename to hfc/lib/impl/ecdsa/key.js diff --git a/lib/protos/.protoroot b/hfc/lib/protos/.protoroot similarity index 100% rename from lib/protos/.protoroot rename to hfc/lib/protos/.protoroot diff --git a/lib/protos/ca.proto b/hfc/lib/protos/ca.proto similarity index 100% rename from lib/protos/ca.proto rename to hfc/lib/protos/ca.proto diff --git a/lib/protos/common/common.proto b/hfc/lib/protos/common/common.proto similarity index 100% rename from lib/protos/common/common.proto rename to hfc/lib/protos/common/common.proto diff --git a/lib/protos/common/configuration.proto b/hfc/lib/protos/common/configuration.proto similarity index 100% rename from lib/protos/common/configuration.proto rename to hfc/lib/protos/common/configuration.proto diff --git a/lib/protos/google/protobuf/empty.proto b/hfc/lib/protos/google/protobuf/empty.proto similarity index 100% rename from lib/protos/google/protobuf/empty.proto rename to hfc/lib/protos/google/protobuf/empty.proto diff --git a/lib/protos/google/protobuf/timestamp.proto b/hfc/lib/protos/google/protobuf/timestamp.proto similarity index 100% rename from lib/protos/google/protobuf/timestamp.proto rename to hfc/lib/protos/google/protobuf/timestamp.proto diff --git a/lib/protos/orderer/ab.proto b/hfc/lib/protos/orderer/ab.proto similarity index 100% rename from lib/protos/orderer/ab.proto rename to hfc/lib/protos/orderer/ab.proto diff --git a/lib/protos/peer/api.proto b/hfc/lib/protos/peer/api.proto similarity index 100% rename from lib/protos/peer/api.proto rename to hfc/lib/protos/peer/api.proto diff --git a/lib/protos/peer/chaincode.proto b/hfc/lib/protos/peer/chaincode.proto similarity index 100% rename from lib/protos/peer/chaincode.proto rename to hfc/lib/protos/peer/chaincode.proto diff --git a/lib/protos/peer/chaincode_proposal.proto b/hfc/lib/protos/peer/chaincode_proposal.proto similarity index 100% rename from lib/protos/peer/chaincode_proposal.proto rename to hfc/lib/protos/peer/chaincode_proposal.proto diff --git a/lib/protos/peer/chaincode_transaction.proto b/hfc/lib/protos/peer/chaincode_transaction.proto similarity index 100% rename from lib/protos/peer/chaincode_transaction.proto rename to hfc/lib/protos/peer/chaincode_transaction.proto diff --git a/lib/protos/peer/chaincodeevent.proto b/hfc/lib/protos/peer/chaincodeevent.proto similarity index 100% rename from lib/protos/peer/chaincodeevent.proto rename to hfc/lib/protos/peer/chaincodeevent.proto diff --git a/lib/protos/peer/devops.proto b/hfc/lib/protos/peer/devops.proto similarity index 100% rename from lib/protos/peer/devops.proto rename to hfc/lib/protos/peer/devops.proto diff --git a/lib/protos/peer/events.proto b/hfc/lib/protos/peer/events.proto similarity index 100% rename from lib/protos/peer/events.proto rename to hfc/lib/protos/peer/events.proto diff --git a/lib/protos/peer/fabric.proto b/hfc/lib/protos/peer/fabric.proto similarity index 100% rename from lib/protos/peer/fabric.proto rename to hfc/lib/protos/peer/fabric.proto diff --git a/lib/protos/peer/fabric_block.proto b/hfc/lib/protos/peer/fabric_block.proto similarity index 100% rename from lib/protos/peer/fabric_block.proto rename to hfc/lib/protos/peer/fabric_block.proto diff --git a/lib/protos/peer/fabric_message.proto b/hfc/lib/protos/peer/fabric_message.proto similarity index 100% rename from lib/protos/peer/fabric_message.proto rename to hfc/lib/protos/peer/fabric_message.proto diff --git a/lib/protos/peer/fabric_proposal.proto b/hfc/lib/protos/peer/fabric_proposal.proto similarity index 100% rename from lib/protos/peer/fabric_proposal.proto rename to hfc/lib/protos/peer/fabric_proposal.proto diff --git a/lib/protos/peer/fabric_proposal_response.proto b/hfc/lib/protos/peer/fabric_proposal_response.proto similarity index 100% rename from lib/protos/peer/fabric_proposal_response.proto rename to hfc/lib/protos/peer/fabric_proposal_response.proto diff --git a/lib/protos/peer/fabric_service.proto b/hfc/lib/protos/peer/fabric_service.proto similarity index 100% rename from lib/protos/peer/fabric_service.proto rename to hfc/lib/protos/peer/fabric_service.proto diff --git a/lib/protos/peer/fabric_transaction.proto b/hfc/lib/protos/peer/fabric_transaction.proto similarity index 100% rename from lib/protos/peer/fabric_transaction.proto rename to hfc/lib/protos/peer/fabric_transaction.proto diff --git a/lib/protos/peer/fabric_transaction_header.proto b/hfc/lib/protos/peer/fabric_transaction_header.proto similarity index 100% rename from lib/protos/peer/fabric_transaction_header.proto rename to hfc/lib/protos/peer/fabric_transaction_header.proto diff --git a/lib/protos/peer/server_admin.proto b/hfc/lib/protos/peer/server_admin.proto similarity index 100% rename from lib/protos/peer/server_admin.proto rename to hfc/lib/protos/peer/server_admin.proto diff --git a/lib/utils-x509cert.js b/hfc/lib/utils-x509cert.js similarity index 100% rename from lib/utils-x509cert.js rename to hfc/lib/utils-x509cert.js diff --git a/lib/utils.js b/hfc/lib/utils.js similarity index 93% rename from lib/utils.js rename to hfc/lib/utils.js index ecc50ee65d..b74a96aa93 100644 --- a/lib/utils.js +++ b/hfc/lib/utils.js @@ -1,4 +1,4 @@ -/** + /** * Copyright 2016 IBM All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,12 +31,6 @@ var Config = require('./Config.js'); var sha3_256 = require('js-sha3').sha3_256; -// -// Load required protobufs. -// - -var _timeStampProto = grpc.load(__dirname + '/protos/google/protobuf/timestamp.proto').google.protobuf.Timestamp; - // // The following methods are for loading the proper implementation of an extensible APIs. // @@ -58,26 +52,6 @@ module.exports.newKeyValueStore = function(options) { return new store(options); }; -module.exports.getMemberService = function() { - // expecting a path to an alternative implementation - var msEnv = this.getConfigSetting('member-service'); - var ms = require(msEnv); - return ms; -}; - -// -// Other methods -// - -// -// generateTimestamp returns the current time in the google/protobuf/timestamp.proto -// structure. -// -module.exports.generateTimestamp = function() { - var timestamp = new _timeStampProto({ seconds: Date.now() / 1000, nanos: 0 }); - return timestamp; -}; - const LOGGING_LEVELS = ['debug', 'info', 'warn', 'error']; // diff --git a/hfc/package.json b/hfc/package.json new file mode 100644 index 0000000000..b56600ff65 --- /dev/null +++ b/hfc/package.json @@ -0,0 +1,70 @@ +{ + "name": "hfc", + "version": "0.0.2", + "main": "index.js", + "repository": { + "type": "gerrit", + "url": "http://gerrit.hyperledger.org/r/fabric-sdk-node" + }, + "scripts": { + "test": "node test/unit/headless-tests.js" + }, + "engines": { + "node": ">=4.5.0", + "npm": ">=2.15.9" + }, + "engine-strict": true, + "engineStrict": true, + "dependencies": { + "aes-js": "^1.0.0", + "asn1": "https://github.com/mcavage/node-asn1", + "asn1js": "^1.2.12", + "bn.js": "^4.11.3", + "crypto": "0.0.3", + "elliptic": "^6.2.3", + "events": "^1.1.0", + "fs": "0.0.2", + "fs-extra": ">=0.30.0 <0.31.0", + "grpc": "^1.0.0", + "js-sha3": "^0.5.1", + "json-stringify-safe": "^5.0.1", + "jsrsasign": "6.2.2", + "jssha": "^2.1.0", + "lodash": "^4.15.0", + "nconf": "^0.8.4", + "node-uuid": "^1.4.7", + "node.extend": "^1.1.5", + "path": "^0.12.7", + "pkijs": "^1.3.19", + "promise-settle": "^0.3.0", + "sjcl": "1.0.3", + "sjcl-codec": "0.1.1", + "sleep": "^3.0.1", + "tar-fs": "^1.13.0", + "url": "^0.11.0", + "util": "^0.10.3", + "uuidv4": "^0.3.1" + }, + "devDependencies": { + "bunyan": "^1.8.1", + "gulp": "^3.9.1", + "gulp-eslint": "^3.0.1", + "gulp-istanbul": "^1.1.1", + "gulp-jsdoc3": "^0.3.0", + "gulp-tape": "0.0.9", + "intercept-stdout": "^0.1.2", + "log4js": "^0.6.38", + "require-dir": "^0.3.0", + "tap-colorize": "^1.2.0", + "tape": "^4.5.1", + "tape-promise": "^1.1.0", + "winston": "^2.2.0" + }, + "license": "Apache-2.0", + "licenses": [ + { + "type": "Apache-2.0", + "url": "https://github.com/hyperledger/fabric/blob/master/LICENSE" + } + ] +} diff --git a/lib/impl/MemberServices.js b/lib/impl/MemberServices.js deleted file mode 100644 index 9a64110e9b..0000000000 --- a/lib/impl/MemberServices.js +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright 2016 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 api = require('../api.js'); -var utils = require('../utils'); -var jsrsa = require('jsrsasign'); -var asn1 = jsrsa.asn1; -var path = require('path'); -var grpc = require('grpc'); -var _caProto = grpc.load(path.join(__dirname, '../../lib/protos/ca.proto')).protos; - -var logger = utils.getLogger('MemberServices.js'); - -/** - * This is the default implementation of a member services client. - * - * @class - */ -var MemberServices = class extends api.MemberServices { - - /** - * constructor - * - * @param {string} url The endpoint URL for the member services of the form: "grpc://host:port" or "grpcs://host:port" - * @param {Object} options for the connection to the member services - */ - constructor(url, opts) { - super(url, opts); - - this._ecaaClient = new _caProto.ECAA(this._endpoint.addr, this._endpoint.creds, this._options); - this._ecapClient = new _caProto.ECAP(this._endpoint.addr, this._endpoint.creds, this._options); - this._tcapClient = new _caProto.TCAP(this._endpoint.addr, this._endpoint.creds, this._options); - this._tlscapClient = new _caProto.TLSCAP(this._endpoint.addr, this._endpoint.creds, this._options); - this.cryptoPrimitives = utils.getCryptoSuite(); - - logger.info('Successfully constructed member service client: endpoint - %j', this._endpoint); - this._asymmetricKeyAlgo = utils.getConfigSetting('crypto-asymmetric-key-algo'); - } - - getCrypto() { - return this.cryptoPrimitives; - } - - /** - * Register the member and return an enrollment secret. - * @param {Object} req Registration request with the following fields: enrollmentID, roles, registrar - * @param {Member} registrar The identity of the registrar (i.e. who is performing the registration) - * @returns Promise for the enrollmentSecret - * @ignore - */ - register(req, registrar) { - var self = this; - - return new Promise(function(resolve, reject) { - if (!req.enrollmentID) { - logger.error('Invalid register request, missing enrollmentID'); - return reject(new Error('missing req.enrollmentID')); - } - - if (!registrar) { - logger.error('Invalid register call, missing registrar parameter'); - return reject(new Error('chain registrar is not set')); - } - - var protoReq = new _caProto.RegisterUserReq(); - protoReq.setId({id:req.enrollmentID}); - protoReq.setRole(MemberServices._rolesToMask(req.roles)); - protoReq.setAffiliation(req.affiliation); - - // Create registrar info - var protoRegistrar = new _caProto.Registrar(); - protoRegistrar.setId({id:registrar.getName()}); - if (req.registrar) { - if (req.registrar.roles) { - protoRegistrar.setRoles(req.registrar.roles); - } - if (req.registrar.delegateRoles) { - protoRegistrar.setDelegateRoles(req.registrar.delegateRoles); - } - } - - protoReq.setRegistrar(protoRegistrar); - - // Sign the registration request - var buf = protoReq.toBuffer(); - var signKey = registrar.getEnrollment().privateKey; - var sig = self.cryptoPrimitives.sign(signKey, buf); - protoReq.setSig( new _caProto.Signature( - { - type: _caProto.CryptoType[self._asymmetricKeyAlgo], - r: new Buffer(sig.r.toString()), - s: new Buffer(sig.s.toString()) - } - )); - - // Send the registration request - self._ecaaClient.registerUser(protoReq, function (err, token) { - if (err) { - logger.error('Received error from server on the register request. %s', err); - return reject(err); - } else { - logger.info('Successfully registered user "%s"', protoReq.getId().id); - return resolve(token ? token.tok.toString() : null); - } - }); - }); - } - - /** - * Enroll the member and return an opaque member object. - * @param req Enrollment request with the following fields: name, enrollmentSecret - * @returns Promise for [Enrollment]{@link module:api.Enrollment} - * @ignore - */ - enroll(req) { - var self = this; - - return new Promise(function(resolve, reject) { - if (!req.enrollmentID) { - logger.error('Invalid enroll request, missing enrollmentID'); - return reject(new Error('req.enrollmentID is not set')); - } - - if (!req.enrollmentSecret) { - logger.error('Invalid enroll request, missing enrollmentSecret'); - return reject(new Error('req.enrollmentSecret is not set')); - } - - // generate certificate pairs for signing and encryption - // 1) signature verifcation key - var spki, spki2, signingKey; - self.cryptoPrimitives.generateKey() - .then( - function(result) { - signingKey = result; - - spki = new asn1.x509.SubjectPublicKeyInfo(signingKey.getPublicKey()._key); - // 2) encryption key - return self.cryptoPrimitives.generateKey(); - }) - .then( - function(encryptionKey) { - spki2 = new asn1.x509.SubjectPublicKeyInfo(encryptionKey.getPublicKey()._key); - - // create the proto message - var eCertCreateRequest = new _caProto.ECertCreateReq(); - var timestamp = utils.generateTimestamp(); - eCertCreateRequest.setTs(timestamp); - eCertCreateRequest.setId({id: req.enrollmentID}); - eCertCreateRequest.setTok({tok: new Buffer(req.enrollmentSecret)}); - - // public signature verification key - var signPubKey = new _caProto.PublicKey( - { - type: _caProto.CryptoType[self._asymmetricKeyAlgo], - key: new Buffer(spki.getASN1Object().getEncodedHex(), 'hex') - }); - eCertCreateRequest.setSign(signPubKey); - - // public encryption key - var encPubKey = new _caProto.PublicKey( - { - type: _caProto.CryptoType[self._asymmetricKeyAlgo], - key: new Buffer(spki2.getASN1Object().getEncodedHex(), 'hex') - }); - eCertCreateRequest.setEnc(encPubKey); - - self._ecapClient.createCertificatePair(eCertCreateRequest, function (err, eCertCreateResp) { - if (err) { - logger.error('Failed to receive challenge response from CA. Error: %s', err.stack ? err.stack : err); - return reject(err); - } - - // response from the member service on a certificate request is a challenge to prove - // possession of the private key. Use the private key to decrypt the token that has - // been encrypted by the member service with the encryption public key included in the - // certificate request - var cipherText = eCertCreateResp.tok.tok; - var decryptedTokBytes = self.cryptoPrimitives.decrypt(encryptionKey, cipherText); - - eCertCreateRequest.setTok({tok: decryptedTokBytes}); - eCertCreateRequest.setSig(null); - - var buf = eCertCreateRequest.toBuffer(); - - var sig = self.cryptoPrimitives.sign(signingKey, buf); - - eCertCreateRequest.setSig(new _caProto.Signature( - { - type: _caProto.CryptoType[self._asymmetricKeyAlgo], - r: new Buffer(sig.r.toString()), - s: new Buffer(sig.s.toString()) - } - )); - self._ecapClient.createCertificatePair(eCertCreateRequest, function (err, eCertCreateResp) { - if (err) { - logger.error('Failed to receive certificate issuance response from CA. Error: %s', err.stack ? err.stack : err); - return reject(err); - } - - var enrollment = new api.Enrollment(signingKey, eCertCreateResp.certs.sign.toString('hex')); - - logger.info('Successfully enrolled user "%s"', eCertCreateRequest.getId().id); - return resolve(enrollment); - }); - }); - }); - }); - } - - - /* - * Utility method to Convert a list of member type names to the role mask currently used by the peer - */ - static _rolesToMask(roles /*string[]*/) { - var mask = 0; - - if (roles) { - for (var role in roles) { - switch (roles[role]) { - case 'client': - mask |= 1; - break; // Client mask - case 'peer': - mask |= 2; - break; // Peer mask - case 'validator': - mask |= 4; - break; // Validator mask - case 'auditor': - mask |= 8; - break; // Auditor mask - } - } - } - - if (mask === 0) - mask = 1; // Client - - return mask; - } - - /** - * return a printable representation of this object - */ - toString() { - return ' MemberServices : {' + - 'url:' + this._url + - '}'; - } -}; - - -module.exports = MemberServices; - diff --git a/package.json b/package.json index 2a8a6d9d64..f03dfa5372 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "hfc", + "name": "fabric-sdk-node", "version": "0.0.2", "main": "index.js", "repository": { @@ -10,49 +10,24 @@ "test": "node test/unit/headless-tests.js" }, "engines": { - "node": ">=6.7.0", - "npm": ">=3.0.0" + "node": ">=4.5.0", + "npm": ">=2.15.9" }, "engine-strict": true, "engineStrict": true, - "dependencies": { - "aes-js": "^1.0.0", - "asn1": "https://github.com/mcavage/node-asn1", - "asn1js": "^1.2.12", - "bn.js": "^4.11.3", - "crypto": "0.0.3", - "elliptic": "^6.2.3", - "events": "^1.1.0", - "fs": "0.0.2", - "fs-extra": ">=0.30.0 <0.31.0", - "grpc": "^1.0.0", - "js-sha3": "^0.5.1", - "json-stringify-safe": "^5.0.1", - "jsrsasign": "^6.2.2", - "jssha": "^2.1.0", - "lodash": "^4.15.0", - "nconf": "^0.8.4", - "node-uuid": "^1.4.7", - "node.extend": "^1.1.5", - "path": "^0.12.7", - "pkijs": "^1.3.19", - "promise-settle": "^0.3.0", - "sjcl": "1.0.3", - "sjcl-codec": "0.1.1", - "sleep": "^3.0.1", - "tar-fs": "^1.13.0", - "url": "^0.11.0", - "util": "^0.10.3", - "uuidv4": "^0.3.1" - }, "devDependencies": { "bunyan": "^1.8.1", "gulp": "^3.9.1", + "gulp-debug": "^3.0.0", "gulp-eslint": "^3.0.1", "gulp-istanbul": "^1.1.1", "gulp-jsdoc3": "^0.3.0", "gulp-tape": "0.0.9", + "gulp-watch": "^4.3.11", + "hfc": "file:./hfc", + "hfc-cop": "file:./hfc-cop", "intercept-stdout": "^0.1.2", + "jsrsasign": "6.2.2", "log4js": "^0.6.38", "require-dir": "^0.3.0", "tap-colorize": "^1.2.0", diff --git a/test/unit/ca-tests.js b/test/unit/ca-tests.js index e3b573c93d..9865396071 100644 --- a/test/unit/ca-tests.js +++ b/test/unit/ca-tests.js @@ -18,11 +18,11 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); -var hfc = require('../..'); +var hfc = require('hfc'); var util = require('util'); var fs = require('fs'); var testUtil = require('./util.js'); -var utils = require('../../lib/utils.js'); +var utils = require('hfc/lib/utils.js'); var keyValStorePath = testUtil.KVS; var keyValStorePath2 = keyValStorePath + '2'; diff --git a/test/unit/chain-fabriccop-tests.js b/test/unit/chain-fabriccop-tests.js index db5622dc5f..580a3120ca 100644 --- a/test/unit/chain-fabriccop-tests.js +++ b/test/unit/chain-fabriccop-tests.js @@ -18,40 +18,67 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); -var hfc = require('../..'); -var FabricCOPServices = require('../../lib/impl/FabricCOPImpl'); +var hfc = require('hfc'); +var FabricCOPServices = require('hfc-cop/lib/FabricCOPImpl'); -var utils = require('../../lib/utils.js'); +var utils = require('hfc/lib/utils.js'); +var Member = require('hfc/lib/Member.js'); var testUtil = require('./util.js'); var keyValStorePath = testUtil.KVS; - +// this test uses the FabricCOPImpl to enroll a user, and +// saves the enrollment materials into a key value store. +// then uses the Chain class to load the member from the +// key value store test('Attempt to use FabricCOPServices',function(t){ - var chain = hfc.newChain('copTest'); utils.setConfigSetting('crypto-keysize', 256); - chain.setKeyValueStore(hfc.newKeyValueStore({ + + var kvs = hfc.newKeyValueStore({ path: keyValStorePath - })); + }); + chain.setKeyValueStore(kvs); var copService = new FabricCOPServices('http://localhost:8888'); - - chain.setMemberServices(copService); - - chain.enroll('admin', 'adminpw') + copService.enroll({ + enrollmentID: 'admin', + enrollmentSecret: 'adminpw' + }) .then( function(admin) { console.log(admin); - t.pass('Successfully enrolled admin'); + t.pass('Successfully enrolled admin with COP server'); + + var member = new Member('admin', chain); + member._enrollment = admin; + return member.saveState(); }, function(err){ - t.fail(err); + t.fail('Failed to enroll admin with COP server. Error: ' + err); + t.end(); + } + ).then( + function(success) { + // attempt to load the persisted member from the kvs using the Chain object + return chain.getUser('admin'); + }, + function(err) { + t.fail('Failed to save member to key value store. Error: ' + err); + t.end(); + } + ).then( + function(user) { + if (user.getName() === 'admin') { + t.pass('Successfully loaded the user from key value store'); + t.end(); + } + }, + function(err) { + t.fail('Failed to load the user admin from key value store. Error: ' + err); + t.end(); } ); - - t.end(); - -}); \ No newline at end of file +}); diff --git a/test/unit/end-to-end.js b/test/unit/end-to-end.js index 3a58e54ff9..a04e088902 100644 --- a/test/unit/end-to-end.js +++ b/test/unit/end-to-end.js @@ -24,11 +24,10 @@ var test = _test(tape); var path = require('path'); -var hfc = require('../..'); +var hfc = require('hfc'); var util = require('util'); -var grpc = require('grpc'); var testUtil = require('./util.js'); -var utils = require('../../lib/utils.js'); +var utils = require('hfc/lib/utils.js'); var chain = hfc.newChain('testChain-e2e'); var webUser; @@ -45,11 +44,10 @@ chain.setKeyValueStore(hfc.newKeyValueStore({ path: testUtil.KVS })); -chain.setMemberServicesUrl('http://localhost:8888'); chain.setOrderer('grpc://localhost:7050'); test('End-to-end flow of chaincode deploy, transaction invocation, and query', function(t) { - chain.enroll('admin', 'adminpw') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); diff --git a/test/unit/endorser-tests.js b/test/unit/endorser-tests.js index 83795eab33..510e184f75 100644 --- a/test/unit/endorser-tests.js +++ b/test/unit/endorser-tests.js @@ -19,11 +19,12 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); -var hfc = require('../..'); +var hfc = require('hfc'); +var copService = require('hfc-cop'); var util = require('util'); var fs = require('fs'); var testUtil = require('./util.js'); -var utils = require('../../lib/utils.js'); +var utils = require('hfc/lib/utils.js'); var keyValStorePath = testUtil.KVS; @@ -45,12 +46,10 @@ test('\n\n** TEST ** endorser test - missing targets', function(t) { path: keyValStorePath })); - chain.setMemberServicesUrl('http://localhost:8888'); - - chain.enroll('admin', 'adminpw') + testUtil.getSubmitter(chain, t) .then( function(admin) { - t.pass('Successfully enrolled user \'admin\''); + t.pass('Successfully obtained enrolled member admin'); // send proposal to endorser var request = { @@ -98,9 +97,7 @@ test('\n\n** TEST ** endorse transaction missing chaincodeId test', function(t) path: keyValStorePath })); - chain.setMemberServicesUrl('http://localhost:8888'); - - chain.enroll('admin', 'adminpw') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); @@ -152,9 +149,7 @@ test('\n\n** TEST ** endorse chaincode deployment good test', function(t) { path: keyValStorePath })); - chain.setMemberServicesUrl('http://localhost:8888'); - - chain.enroll('admin', 'adminpw') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); diff --git a/test/unit/fabriccopservices-tests.js b/test/unit/fabriccopservices-tests.js index 0a7914dc0c..abb1ff5e38 100644 --- a/test/unit/fabriccopservices-tests.js +++ b/test/unit/fabriccopservices-tests.js @@ -18,17 +18,17 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); -var hfc = require('../..'); +var hfc = require('hfc'); var util = require('util'); var fs = require('fs'); var path = require('path'); var testUtil = require('./util.js'); -var utils = require('../../lib/utils.js'); +var utils = require('hfc/lib/utils.js'); var keyValStorePath = testUtil.KVS; -var FabricCOPServices = require('../../lib/impl/FabricCOPImpl'); +var FabricCOPServices = require('hfc-cop/lib/FabricCOPImpl'); var FabricCOPClient = FabricCOPServices.FabricCOPClient; /** @@ -174,8 +174,8 @@ test('FabricCOPClient: Test enroll with missing parameters', function (t) { }); }); -var enrollmentID = 'testUser'; -var enrollmentSecret = 'user1'; +var enrollmentID = 'sdk'; +var enrollmentSecret = 'sdkpw'; var csr = fs.readFileSync(path.resolve(__dirname, '../fixtures/fabriccop/enroll-csr.pem')); @@ -299,4 +299,4 @@ test('FabricCOPServices: Test enroll()', function (t) { } ); -}); \ No newline at end of file +}); diff --git a/test/unit/headless-tests.js b/test/unit/headless-tests.js index 4cdaea68ee..ed46710006 100644 --- a/test/unit/headless-tests.js +++ b/test/unit/headless-tests.js @@ -22,17 +22,17 @@ var test = _test(tape); var path = require('path'); var util = require('util'); -var hfc = require('../..'); +var hfc = require('hfc'); var fs = require('fs'); var execSync = require('child_process').execSync; -var utils = require('../../lib/utils.js'); -var cryptoSuiteReq = require('../../lib/impl/CryptoSuite_ECDSA_AES.js'); +var utils = require('hfc/lib/utils.js'); +var cryptoSuiteReq = require('hfc/lib/impl/CryptoSuite_ECDSA_AES.js'); var bunyan = require('bunyan'); var log4js = require('log4js'); var intercept = require('intercept-stdout'); // FileKeyValueStore tests ///////////// -var FileKeyValueStore = require('../../lib/impl/FileKeyValueStore.js'); +var FileKeyValueStore = require('hfc/lib/impl/FileKeyValueStore.js'); var keyValStorePath = path.join(getUserHome(), 'kvsTemp'); //Note: unix relative path does not start with '/' @@ -48,7 +48,7 @@ var store2 = ''; // End: FileKeyValueStore tests //////// // Chain tests ///////////// -var Chain = require('../../lib/Chain.js'); +var Chain = require('hfc/lib/Chain.js'); var _chain = null; var chainName = 'testChain'; var chainKeyValStorePath = 'tmp/chainKeyValStorePath'; @@ -56,7 +56,7 @@ var store3 = ''; // End: Chain tests //////// // Member tests ////////// -var Member = require('../../lib/Member.js'); +var Member = require('hfc/lib/Member.js'); var memberName = 'Donald T. Duck'; var enrollmentID = 123454321; var roles = ['admin', 'user']; @@ -68,11 +68,10 @@ var memberCfg = { }; // GRPC Options tests /////////////// -var Remote = require('../../lib/Remote.js'); -var Peer = require('../../lib/Peer.js'); -var Orderer = require('../../lib/Orderer.js'); -var Config = require('../../lib/Config.js'); -var MemberServices = require('../../lib/impl/MemberServices.js'); +var Remote = require('hfc/lib/Remote.js'); +var Peer = require('hfc/lib/Peer.js'); +var Orderer = require('hfc/lib/Orderer.js'); +var Config = require('hfc/lib/Config.js'); var aPem = '-----BEGIN CERTIFICATE-----' + 'MIIBwTCCAUegAwIBAgIBATAKBggqhkjOPQQDAzApMQswCQYDVQQGEwJVUzEMMAoG' + 'A1UEChMDSUJNMQwwCgYDVQQDEwNPQkMwHhcNMTYwMTIxMjI0OTUxWhcNMTYwNDIw' + @@ -91,7 +90,7 @@ var aHostnameOverride = 'atesthostnameoverride'; // specifically set the values to defaults because they may have been overridden when // running in the overall test bucket ('gulp test') function resetDefaults() { - var defaultSettings = require('../../config/default.json'); + var defaultSettings = require('hfc/config/default.json'); for (var setting in defaultSettings) { hfc.setConfigSetting(setting, defaultSettings[setting]); } @@ -393,12 +392,17 @@ test('\n\n ** Chain - constructor test **\n\n', function (t) { t.fail('Should not have Successfully resolved a member without having member services configured first'); t.end(); }, function (err) { - if (err.message && err.message.indexOf('No member services was found') === 0) { - t.pass('Successfully rejected a "getMember()" call on a chain without member services'); + if (err.message && err.message.indexOf('KeyValueStore.getValue function is undefined') === 0) { + t.pass('Successfully rejected a "getMember()" call on a chain without KeyValueStore getValue defined'); } else { - t.fail('Error: ' + err.stack ? err.stack : err); + t.fail('Failed with unexpected error: ' + err.stack ? err.stack : err); } t.end(); + }) + .catch( + function (err) { + t.fail('Failed with unexpected error: ' + err.stack ? err.stack : err); + t.end(); }); }); @@ -434,59 +438,7 @@ test('\n\n ** Chain - setKeyValueStore getKeyValueStore test **\n\n', function ( }); }); -test('\n\n ** Chain register methods parameters tests **\n\n', function (t) { - let chain = new Chain('testChain1'); - - chain.register({}) - .then(function () { - t.fail('Should not have worked becaused the input param was missing user enrollmentID'); - }, function (err) { - if (err.message && err.message.indexOf('Invalid parameter to "register()" function') === 0) { - t.pass('Successfully rejected call to "register()" method with invalid parameter missing enrollmentID'); - } else { - t.fail('Something unexpected happened. Error: ' + err.stack ? err.stack : err); - } - }) - .then(function () { - return chain.registerAndEnroll({}); - }) - .then(function () { - t.fail('Should not have worked becaused the input param was missing user enrollmentID'); - t.end(); - }, function (err) { - if (err.message && err.message.indexOf('Invalid parameter to "registerAndEnroll()" function') === 0) { - t.pass('Successfully rejected call to "registerAndEnroll()" method with invalid parameter missing enrollmentID'); - } else { - t.fail('Something unexpected happened. Error: ' + err.stack ? err.stack : err); - } - t.end(); - }); -}); - test('\n\n ** Chain - method tests **\n\n', function (t) { - t.doesNotThrow( - function () { - _chain.setRegistrar('something'); - }, - null, - 'checking the setRegistrar' - ); - t.equal(_chain.getRegistrar(), 'something', 'checking the getRegistrar'); - t.doesNotThrow( - function () { - _chain.setMemberServicesUrl('http://somehost.com:9999'); - }, - null, - 'checking the setMemberServicesUrl' - ); - t.doesNotThrow( - function () { - _chain.setMemberServicesUrl('https://somehost.com:9999'); - }, - null, - 'checking the setMemberServicesUrl' - ); - t.equal(_chain.getMemberServices().toString(), ' FabricCOPServices : {hostname: somehost.com, port: 9999}', 'checking the getMemberServices'); t.equal(_chain.isSecurityEnabled(), true, 'checking security setting'); t.doesNotThrow( function () { @@ -852,7 +804,7 @@ var KEYUTIL = jsrsa.KEYUTIL; var ECDSA = jsrsa.ECDSA; var asn1 = jsrsa.asn1; -var ecdsaKey = require('../../lib/impl/ecdsa/key.js'); +var ecdsaKey = require('hfc/lib/impl/ecdsa/key.js'); test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { resetDefaults(); @@ -1170,7 +1122,7 @@ test('\n\n ** ECDSA Key Impl tests **\n\n', function (t) { csrObject = asn1.csr.CSRUtil.getInfo(csrPEM); } catch (err) { - t.fail('Failed to generate a CSR: ' + err); + t.fail('Failed to generate a CSR: ' + err.stack ? err.stack : err); }; t.equal(asn1.x509.X500Name.onelineToLDAP(csrObject.subject.name), subjectDN, diff --git a/test/unit/marbles.js b/test/unit/marbles.js index 77ce7f4bf1..53edcb3dc5 100644 --- a/test/unit/marbles.js +++ b/test/unit/marbles.js @@ -25,11 +25,10 @@ var test = _test(tape); var path = require('path'); var http = require('http'); -var hfc = require('../..'); +var hfc = require('hfc'); var util = require('util'); -var grpc = require('grpc'); var testUtil = require('./util.js'); -var utils = require('../../lib/utils.js'); +var utils = require('hfc/lib/utils.js'); var chain = hfc.newChain('testChain-e2e'); var webUser; @@ -42,15 +41,18 @@ testUtil.setupChaincodeDeploy(); utils.setConfigSetting('crypto-hash-algo', 'SHA2'); utils.setConfigSetting('crypto-keysize', 256); +// need to override the default hash algorithm (SHA3) to SHA2 (aka SHA256 when combined +// with the key size 256 above), in order to match what the peer and COP use +utils.setConfigSetting('crypto-hash-algo', 'SHA2'); + chain.setKeyValueStore(hfc.newKeyValueStore({ path: testUtil.KVS })); -chain.setMemberServicesUrl('http://localhost:8888'); chain.setOrderer('grpc://localhost:7050'); test('End-to-end flow of chaincode deploy, transaction invocation, and query', function(t) { - chain.enroll('admin', 'adminpw') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); diff --git a/test/unit/orderer-member-tests.js b/test/unit/orderer-member-tests.js index aefe2d061d..016d962e3f 100644 --- a/test/unit/orderer-member-tests.js +++ b/test/unit/orderer-member-tests.js @@ -18,13 +18,13 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); -var hfc = require('../..'); +var hfc = require('hfc'); var util = require('util'); var fs = require('fs'); var testUtil = require('./util.js'); -var Orderer = require('../../lib/Orderer.js'); -var Member = require('../../lib/Member.js'); +var Orderer = require('hfc/lib/Orderer.js'); +var Member = require('hfc/lib/Member.js'); var keyValStorePath = testUtil.KVS; @@ -41,7 +41,7 @@ test('\n\n** TEST ** orderer via chain setOrderer/getOrderer', function(t) { // var chain = hfc.getChain('testChain-orderer-member', true); try { - var order_address = 'grpc://localhost:5151'; + var order_address = 'grpc://localhost:7050'; chain.setOrderer(order_address); t.pass('Successfully set the new orderer URL'); t.end(); @@ -145,9 +145,7 @@ test('\n\n** TEST ** orderer via member missing orderer', function(t) { path: keyValStorePath })); - chain.setMemberServicesUrl('grpc://localhost:7054'); - - chain.enroll('admin', 'Xurw3yU9zI0l') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); @@ -198,10 +196,9 @@ test('\n\n** TEST ** orderer via member null data', function(t) { path: keyValStorePath })); - chain.setMemberServicesUrl('grpc://localhost:7054'); - chain.setOrderer('grpc://localhost:5151'); + chain.setOrderer('grpc://localhost:7050'); - chain.enroll('admin', 'Xurw3yU9zI0l') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); @@ -252,11 +249,10 @@ test('\n\n** TEST ** orderer via member bad orderer address', function(t) { path: keyValStorePath })); - chain.setMemberServicesUrl('grpc://localhost:7054'); // Set bad orderer address here chain.setOrderer('grpc://localhost:5199'); - chain.enroll('admin', 'Xurw3yU9zI0l') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); @@ -305,10 +301,9 @@ test('\n\n** TEST ** orderer via member bad data', function(t) { path: keyValStorePath })); - chain.setMemberServicesUrl('grpc://localhost:7054'); - chain.setOrderer('grpc://localhost:5151'); + chain.setOrderer('grpc://localhost:7050'); - chain.enroll('admin', 'Xurw3yU9zI0l') + testUtil.getSubmitter(chain, t) .then( function(admin) { t.pass('Successfully enrolled user \'admin\''); diff --git a/test/unit/orderer-tests.js b/test/unit/orderer-tests.js index 5953a25317..dac71ea1ee 100644 --- a/test/unit/orderer-tests.js +++ b/test/unit/orderer-tests.js @@ -18,12 +18,12 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); -var hfc = require('../..'); +var hfc = require('hfc'); var util = require('util'); var fs = require('fs'); var testUtil = require('./util.js'); -var Orderer = require('../../lib/Orderer.js'); +var Orderer = require('hfc/lib/Orderer.js'); var keyValStorePath = testUtil.KVS; @@ -34,7 +34,7 @@ var keyValStorePath = testUtil.KVS; // expected in this case. // test('orderer happy path test', function(t) { - var client = new Orderer('grpc://127.0.0.1:5151'); + var client = new Orderer('grpc://127.0.0.1:7050'); client.sendBroadcast('some data') .then( diff --git a/test/unit/util.js b/test/unit/util.js index 1892db68b1..935f8ba02a 100644 --- a/test/unit/util.js +++ b/test/unit/util.js @@ -7,4 +7,49 @@ module.exports.KVS = '/tmp/hfc-test-kvs'; // temporarily set $GOPATH to the test fixture folder module.exports.setupChaincodeDeploy = function() { process.env.GOPATH = path.join(__dirname, '../fixtures'); -}; \ No newline at end of file +}; + +function getSubmitter(username, password, chain, t) { + return chain.getUser(username) + .then( + function(user) { + if (user.isEnrolled()) { + t.pass('Successfully loaded member from persistence'); + return Promise.resolve(user); + } else { + // need to enroll it with COP server + var cop = new copService('http://localhost:8888'); + + return cop.enroll({ + enrollmentID: username, + enrollmentSecret: password + }).then( + function(enrollment) { + t.pass('Successfully enrolled user \'' + username + '\''); + + var member = new Member(username, chain); + member._enrollment = enrollment; + return member.saveState(); + } + ).then( + function(success) { + return chain.getUser(username); + } + ).catch( + function(err) { + t.fail('Failed to enroll and persist user. Error: ' + err); + t.end(); + } + ); + } + }, + function(err) { + t.fail('Failed to obtain a member object for user. Error: ' + err); + t.end(); + } + ); +} + +module.exports.getSubmitter = function(chain, test) { + return getSubmitter('admin', 'adminpw', chain, test); +};