Skip to content

Commit

Permalink
[FAB-5363] NodeSDK - common config part 1
Browse files Browse the repository at this point in the history
The NodeSDK use of the common network configuration.
This is using the latest yaml schema as described in
the FAB. This demonstrates how the SDK would load a
configuration and build a channel instance based on the
network configuration. This starts the use of how peers
would be automatically selected.

Change-Id: I0b1479d12684aa13bc052e872fbf118166004453
Signed-off-by: Bret Harrison <[email protected]>
  • Loading branch information
harrisob authored and jimthematrix committed Aug 24, 2017
1 parent febff14 commit 1e61110
Show file tree
Hide file tree
Showing 19 changed files with 2,544 additions and 28 deletions.
8 changes: 6 additions & 2 deletions fabric-client/config/default.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
{
"request-timeout" : 45000,
"crypto-hash-algo": "SHA2",
"crypto-keysize": 256,
Expand All @@ -10,8 +10,12 @@
"EC": "fabric-client/lib/impl/bccsp_pkcs11.js"
},
"key-value-store": "fabric-client/lib/impl/FileKeyValueStore.js",
"certificate-authority-client": "fabric-ca-client",
"nonce-size" : 24,
"grpc-ssl-cipher-suites": "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384",
"grpc-max-receive-message-length": 0,
"grpc-max-send-message-length": 0
"grpc-max-send-message-length": 0,
"network-config-schema" : {
"1.0": "./impl/NetworkConfig_1_0.js"
}
}
112 changes: 112 additions & 0 deletions fabric-client/lib/CertificateAuthority.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
Copyright 2017 IBM All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var api = require('./api.js');
var utils = require('./utils.js');
var util = require('util');

var logger = utils.getLogger('CertificateAuthority.js');

/**
* The CertificateAuthority class represents an Certificate Authority in the target blockchain network.
*
* @class
*/
var CertificateAuthority = class {

/**
* Construct a CertificateAuthority object
* @param {string} name - The name of this Certificate Authority
* @returns {string} The url of this CertificateAuthority
* @returns {CertificateAuthority} The CertificateAuthority instance.
*/
constructor(name, url, connection_options, tlsCACerts, registrar) {
logger.debug('CertificateAuthority.const ');
logger.debug('Organization.const ');
if (typeof name === 'undefined' || name === null) {
throw new Error('Missing name parameter');
}
if (typeof url === 'undefined' || url === null) {
throw new Error('Missing url parameter');
}
this._name = name;
this._url = url;
this._connection_options = connection_options;
this._tlsCACerts = tlsCACerts;;
this._registrar = registrar;
}

/**
* Gets the name of this CertificateAuthority
*
* @returns {string} The name of this CertificateAuthority
*/
getName() {
return this._name;
}

/**
* Gets the url of this CertificateAuthority
*
* @returns {string} The url of this CertificateAuthority
*/
getUrl() {
return this._url;
}

/**
* Gets the connection options of this CertificateAuthority
*
* @returns {object} The connection options of this CertificateAuthority
*/
getConnectionOptions() {
return this._connection_options;
}

/**
* Gets the TLS CA Cert of this CertificateAuthority
*
* @returns {string} The TLS CA Cert PEM string of this CertificateAuthority
*/
getTlsCACerts() {
return this._tlsCACerts;
}

/**
* Gets the registrar of this CertificateAuthority
*
* @returns {object} The registrar of this CertificateAuthority
*/
getRegistrar() {
return this._registrar;
}

/**
* return a printable representation of this object
*/
toString() {
return ' CertificateAuthority : {' +
'name : ' + this._name +
', url : ' + this._url +
'}';
}

};

module.exports = CertificateAuthority;
142 changes: 141 additions & 1 deletion fabric-client/lib/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,57 @@ var Channel = class {
}
}

/*
* utility method to decide on the target for queries that only need ledger access
*/
_getTargetForQuery(target) {
if (Array.isArray(target)) {
return new Error('"target" parameter is an array, but should be a singular peer object');
}

var targets = this._getTargets(target, Constants.NetworkConfig.LEDGER_QUERY_ROLE);
if(Array.isArray(targets)) {
targets = targets[0];
}

return targets;
}

/*
* utility method to decide on the targets for requests
*/
_getTargets(request_targets, role) {
var targets = null;
if (request_targets) {
// first check to see if they have passed a peer or peer name
try {
targets = this._clientContext.getTargetPeers(request_targets);
} catch(err) {
return err;
}
}
// so nothing passed in
// see if we can find in the network configuration
if (!targets || targets.length < 1 ) try {
targets = this._getTargetsFromConfig(role);
} catch(err) {
return err;
}

// nothing yet
// maybe there are peers on the channel
if (!targets || targets.length < 1 ) {
var targets = this.getPeers();
if (this.getPeers().length < 1) {
return new Error('"targets" parameter not specified and no peers are set on Channel.');
} else {
targets = this.getPeers();
}
}

return targets;
}

/**
* Queries the ledger on the target peer for a Block by block hash.
*
Expand Down Expand Up @@ -1703,7 +1754,96 @@ var Channel = class {
}

return true;
}
}

/*
* Utility method to return a list of targets from the network configuration
* that are in this role of operation
*/
_getTargetsFromConfig(role) {
var method = '_getTargetsFromConfig';
logger.debug('%s - start ::role %s',method,role);
var targets = [];
if(role) {
var found = false;
for(let i in Constants.NetworkConfig.ROLES) {
if(role === Constants.NetworkConfig.ROLES[i]) {
found = true;
break;
}
}
if(!found) {
throw Error('Target role is unknown');
}
}

/*
* Need to list all the organizations from the network configuration.
* Check each peer in each organization to see if it is on the channel.
* If peer is on the channel and in the role, add this peer to a new list
* of peers for this organization. Keep all these new lists in a list keyed
* by the organization name. Once we have all the peers on the channel
* sorted by organization, then we can randomly take one of those peers
* for each organization and add it to the final target list.
*/
if (this._clientContext._network_config) {
var orgs = this._clientContext._network_config.getOrganizations();
if(orgs) {
//first get all the peers on the channel divided up by orgs
var peers_by_org = {};
for(let i in orgs) {
let org = orgs[i];
var peers_in_org_and_in_channel = [];
peers_by_org[org.getName()] = peers_in_org_and_in_channel;
var org_peers = org.getPeers();
logger.debug('%s - org:%s has %s peers',method,org.getName(), org_peers.length);
for(let j in org_peers) {
let org_peer = org_peers[j];
var channel_peers = this.getPeers();
for(let k in channel_peers) {
let channel_peer = channel_peers[k];
if(!channel_peer) {
logger.debug('%s - no peers on this channel',method);
break;
}
if(!org_peer) {
logger.debug('%s - null peer on this org',method);
break;
}
logger.debug('%s - comparing channel peer:%s to org peer:%s',method, channel_peer.getName(), org_peer.getName());
if(channel_peer.getName() === org_peer.getName()) {
// only peers in the request role get added
if(channel_peer.isInRole(role)) {
peers_in_org_and_in_channel.push(channel_peer);
logger.debug('%s - added peer %s',method,channel_peer.toString());
}
break;
}
}
}
}
// now add just one peer from each org to targets if in role
for(let org_name in peers_by_org) {
let peers_org = peers_by_org[org_name];
if(peers_org && peers_org.length > 0) {
logger.debug('%s - orgs %s has %s peers',method, org_name, peers_org.length);
let which_peer = Math.floor(Math.random() * peers_org.length);
logger.debug('%s - peer index:%s',method,which_peer);
let peer_org = peers_org[which_peer];
targets.push(peer_org);
logger.debug('%s - added target peer %s',method,peer_org.toString());
} else {
logger.debug('%s - no peers in this org %s',method,org_name);
}
}
}

if(targets.length == 0) {
logger.warn('No peers found in the loaded network configuration that can be used as the target of this operation');
}
return targets;
}
}

// internal utility method to build chaincode policy
_buildEndorsementPolicy(policy) {
Expand Down
Loading

0 comments on commit 1e61110

Please sign in to comment.