Skip to content

Commit

Permalink
Adding Member Wrapper For Orderer
Browse files Browse the repository at this point in the history
Adding the sendTransaction API, which is the member
wrapper for the request being sent to the ordering
service. Adding the associated unit tests.

Change-Id: Ic65d8e519ce36775c7816ebb8e60edbe872e2841
Signed-off-by: Anna D Derbakova <[email protected]>
Signed-off-by: Bret E Harrison <[email protected]>
  • Loading branch information
Mr. Angry committed Oct 14, 2016
1 parent e5d06ea commit dbcdb46
Show file tree
Hide file tree
Showing 4 changed files with 442 additions and 27 deletions.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ module.exports.getChain = function(chainName, create) {
var chain = _chains[chainName];

if (!chain && create) {
chain = newChain(chainName);
chain = this.newChain(chainName);
}

return chain;
Expand Down
77 changes: 64 additions & 13 deletions lib/Chain.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
Copyright 2016 IBM All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
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,
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.
Expand All @@ -23,6 +23,11 @@ var net = require('net');
var util = require('util');
var MemberServices = require('./impl/MemberServices.js');
var Member = require('./Member.js');
var Orderer = require('./Orderer.js');

var debugModule = require('debug');
var debug = debugModule('hfc');
var isDebug = debugModule.enabled('hfc');

/**
* The class representing a chain with which the client SDK interacts.
Expand All @@ -36,12 +41,10 @@ var Chain = class {
* is completely at the client application's discretion.
*/
constructor(name) {
debug('Chain.constructor');
// Name of the chain is only meaningful to the client
this._name = name;

// The peers on this chain to which the client can connect
this._peers = []; // Peer[]

// Security enabled flag
this._securityEnabled = true;

Expand Down Expand Up @@ -106,7 +109,7 @@ var Chain = class {

/**
* Set the member services URL
* @param {string} url Member services URL of the form: "grpc://host:port" or "grpcs://host:port"
* @param {string} url Member services URL of the form: 'grpc://host:port' or 'grpcs://host:port'
* @param {string} pem String value of the TLS certificate for the local client
*/
setMemberServicesUrl(url, pem) {
Expand All @@ -126,6 +129,7 @@ var Chain = class {
* @param [MemberService]{@link module:api.MemberService} an instance of the MemberServices class
*/
setMemberServices(memberServices) {
debug('Chain.setMemberServices -' + memberServices);
this._memberServices = memberServices;
if (memberServices instanceof MemberServices) {
this.cryptoPrimitives = memberServices.getCrypto();
Expand Down Expand Up @@ -179,6 +183,7 @@ var Chain = class {
* Set the key value store implementation.
*/
setKeyValueStore(keyValStore) {
debug('Chain.setKeyValueStore -' + keyValStore);
this._keyValStore = keyValStore;
}

Expand All @@ -202,25 +207,28 @@ var Chain = class {
* @returns Promise for the Member object
*/
getMember(name) {
debug('Chain.getMember - start - name:' + name);
var self = this;
return new Promise(function(resolve, reject) {
if (!self._keyValStore) {
debug('Chain.getMember - reject -no key value store');
reject(new Error('No key value store was found. You must first call Chain.configureKeyValueStore or Chain.setKeyValueStore'));
}

if (!self._memberServices) {
debug('Chain.getMember - reject -no members services');
reject(new Error('No member services was found. You must first call Chain.configureMemberServices or Chain.setMemberServices'));
}

self._getMemberHelper(name).then(
function(member) {

debug('Chain.getMember - resolve -member found name:'+name);
return resolve(member);

}
).catch(
function(err) {

debug('Chain.getMember - reject - ERROR::'+err);
reject(err);

}
Expand All @@ -245,26 +253,30 @@ var Chain = class {
// If there are no errors and member is not found in the key value store,
// return the new member.
_getMemberHelper(name) {
debug('Chain._getMemberHelper - start name:'+name);
var self = this;

return new Promise(function(resolve, reject) {
// Try to get the member state from the cache
var member = self._members[name];
if (member) {
debug('Chain._getMemberHelper - resolve found in _members - name:'+name);
return resolve(member);
}

// Create the member and try to restore it's state from the key value store (if found).
member = new Member(name, self);
debug('Chain._getMemberHelper - create new member - will try to restoreState -name:'+name);
member.restoreState()
.then(
function() {
self._members[name] = member;

debug('Chain._getMemberHelper - resolved restored name:'+name);
return resolve(member);
}
).catch(
function(err) {
debug('Chain._getMemberHelper - reject - ERROR::'+err);
reject(err);
}
);
Expand All @@ -274,21 +286,23 @@ 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
* @returns Promise for a 'true' status on successful registration
*/
register(registrationRequest) {

debug('Chain.register - start registrationRequest:'+registrationRequest);
var self = this;

return new Promise(function(resolve, reject) {
self.getMember(registrationRequest.enrollmentID)
.then(
function(member) {
function(member) {
member.register(registrationRequest);
debug('Chain.register - resolve registrationRequest:'+registrationRequest);
return resolve(true);
}
).catch(
function(err) {
debug('Chain.register - reject - ERROR::'+err);
reject(err);
}
);
Expand All @@ -303,6 +317,7 @@ var Chain = class {
* @param cb The callback to return the user or other member.
*/
enroll(name, secret) {
debug('Chain.enroll - start name:'+name);
var self = this;

return new Promise(function(resolve, reject) {
Expand All @@ -311,14 +326,17 @@ var Chain = class {
.then(
function(member) {
_member = member;
debug('Chain.enroll - call member.enroll');
return _member.enroll(secret);
}
).then(
function() {
debug('Chain.enroll - resolved - member:'+name);
return resolve(_member);
}
).catch(
function(err) {
debug('Chain.enroll - reject - ERROR::'+err);
reject(err);
}
);
Expand Down Expand Up @@ -358,7 +376,40 @@ var Chain = class {
);
});
}

/**
* Set the orderer given an endpoint specification.
* Will replace the existing orderer if one exists.
* @param url The URL of the orderer.
* @param opts Optional GRPC options.
* @returns {Orderer} Returns the new Orderer.
*/
setOrderer(url, opts) {
debug('Chain.setOrderer - start url:'+url);
var orderer = new Orderer(url, this, opts);
this._orderer = orderer;
return orderer;
}

/**
* Get the current orderer for this chain.
*/
getOrderer() {
return this._orderer;
}

/**
* return a printable representation of this object
*/
toString() {
var state = {
name: this._name,
orderer: this._orderer ? this._orderer._url : 'N/A'
};

return JSON.stringify(state);
}

};

module.exports = Chain;

55 changes: 42 additions & 13 deletions lib/Member.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
Copyright 2016 IBM All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
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,
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.
Expand All @@ -27,6 +27,10 @@ var grpc = require('grpc');
var _ccProto = grpc.load(__dirname + '/protos/chaincode.proto').protos;
var _fabricProto = grpc.load(__dirname + '/protos/fabric_next.proto').protos;

var debugModule = require('debug');
var debug = debugModule('hfc');
var isDebug = debugModule.enabled('hfc');

/**
* Represents an authenticated user of the application or an entity used by a Peer node.
* A member can be in any of these following states:
Expand All @@ -38,7 +42,7 @@ var _fabricProto = grpc.load(__dirname + '/protos/fabric_next.proto').protos;
* with a one-time password, but it has not been enrolled
*
* - enrolled: the user has used the one-time password to exchange for an Enrollment Certificate (ECert)
* which can be used to identify him/herself to the member services
* which can be used to identify him/herself to the member services
*
* @class
*/
Expand All @@ -49,6 +53,7 @@ var Member = class {
* @param cfg {string | RegistrationRequest} The member name or registration request.
*/
constructor(cfg, chain) {
debug('Member.constructor - '+chain);
if (util.isString(cfg)) {
this._name = cfg;
this._roles = null; //string[]
Expand Down Expand Up @@ -286,15 +291,15 @@ var Member = class {

/**
* Save the state of this member to the key value store.
* @returns Promise for a "true" upon successful save
* @returns Promise for a 'true' upon successful save
*/
saveState() {
return this._keyValStore.setValue(this._keyValStoreName, this.toString());
}

/**
* Restore the state of this member from the key value store (if found). If not found, do nothing.
* @returns Promise for a "true" upon successful restore
* @returns Promise for a 'true' upon successful restore
*/
restoreState() {
var self = this;
Expand All @@ -317,6 +322,32 @@ var Member = class {
});
}

/**
* Sends the orderer an endorsed proposal.
*
* @param {Object} request An object containing the data:
* TODO explain data object
* @returns Promise for the sendTransaction
*/
sendTransaction(data) {
debug('Member.sendTransaction - start');
// Verify that data is being passed in
if (!data) {
debug('Member.sendTransaction - input data missing');
return Promise.reject(new Error('missing data in broadcast request'));
}
// verify that we have an orderer configured
if(!this._chain.getOrderer()) {
debug('Member.sendTransaction - no orderer defined');
return Promise.reject(new Error('no Orderer defined'));
}

debug('Member.sendTransaction - chain ::'+this._chain);

var orderer = this._chain.getOrderer();
return orderer.sendBroadcast(data);
}

/**
* Sends a deployment proposal to an endorser.
*
Expand Down Expand Up @@ -364,12 +395,12 @@ var Member = class {
let chaincodeDeploymentSpec = new _ccProto.ChaincodeDeploymentSpec();
chaincodeDeploymentSpec.setChaincodeSpec(ccSpec);

fs.readFile(targzFilePath, function(err, data) {
if(err) {
reject(new Error(util.format('Error reading deployment archive [%s]: %s', targzFilePath, err)));
}
fs.readFile(targzFilePath, function(err, data) {
if(err) {
reject(new Error(util.format('Error reading deployment archive [%s]: %s', targzFilePath, err)));
}

chaincodeDeploymentSpec.setCodePackage(data);
chaincodeDeploymentSpec.setCodePackage(data);

let lcccSpec = {
type: _ccProto.ChaincodeSpec.Type.GOLANG,
Expand All @@ -394,7 +425,7 @@ var Member = class {
let peer = new Peer(request.endorserUrl);
return peer.sendProposal(proposal);
});
},
},
function(err) {
reject(err);
}
Expand Down Expand Up @@ -490,5 +521,3 @@ function packageChaincode(chaincodePath, fcn, args) {
}

module.exports = Member;


Loading

0 comments on commit dbcdb46

Please sign in to comment.