Skip to content

Commit

Permalink
FABN-856 submitTransaction API
Browse files Browse the repository at this point in the history
created fabric-network package
network, channel, contract API classes
does not wait for any commit notifications
implementation of in-memory wallet
logger
unit and integration tests - 100% coverage

Change-Id: Ic3c8f8b116028536a48ca6bcb537762483b2e88b
Signed-off-by: andrew-coleman <andrew_coleman@uk.ibm.com>
  • Loading branch information
andrew-coleman committed Aug 17, 2018
1 parent 74d8a1d commit c680a30
Show file tree
Hide file tree
Showing 27 changed files with 2,330 additions and 3 deletions.
3 changes: 3 additions & 0 deletions build/tasks/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ const eslint = require('gulp-eslint');
gulp.task('lint', () => {
return gulp.src([
'**/*.js',
'fabric-network/**/*.js',
'fabric-client/**/*.js',
'fabric-ca-client/lib/*.js',
'!fabric-network/coverage/**',
'!fabric-ca-client/coverage/**',
'!test/typescript/*.js',
'!node_modules/**',
'!fabric-network/node_modules/**',
'!fabric-client/node_modules/**',
'!fabric-ca-client/node_modules/**',
'!docs/**',
Expand Down
13 changes: 11 additions & 2 deletions build/tasks/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ process.env.THIRDPARTY_IMG_TAG = thirdpartyImageTag;

gulp.task('pre-test', () => {
return gulp.src([
'fabric-network/lib/**/*.js',
'fabric-client/lib/**/*.js',
'fabric-ca-client/lib/FabricCAClientImpl.js',
'fabric-ca-client/lib/helper.js',
Expand Down Expand Up @@ -133,14 +134,21 @@ gulp.task('mocha-fabric-client',
}
);

gulp.task('run-test', ['run-full', 'mocha-fabric-client'],
gulp.task('mocha-fabric-network',
() => {
return gulp.src(['./fabric-network/test/**/*.js'], { read: false })
.pipe(mocha({ reporter: 'list', exit: true }));
}
);

gulp.task('run-test', ['run-full', 'mocha-fabric-client', 'mocha-fabric-network'],
() => {
return gulp.src(['./fabric-ca-client/test/**/*.js'], { read: false })
.pipe(mocha({ reporter: 'list', exit: true }));
}
);

gulp.task('run-test-headless', ['run-headless', 'mocha-fabric-client'],
gulp.task('run-test-headless', ['run-headless', 'mocha-fabric-client', 'mocha-fabric-network'],
() => {
return gulp.src(['./fabric-ca-client/test/**/*.js'], { read: false })
.pipe(mocha({ reporter: 'list', exit: true }));
Expand All @@ -163,6 +171,7 @@ gulp.task('run-full', ['clean-up', 'lint', 'pre-test', 'compile', 'docker-ready'
'!test/unit/logger.js',
// channel: mychannel, chaincode: e2enodecc:v0
'test/integration/nodechaincode/e2e.js',
'test/integration/network-e2e/e2e.js',
// channel: mychannel, chaincode: end2endnodesdk:v0/v1
'test/integration/e2e.js',
'test/integration/query.js',
Expand Down
Empty file added fabric-network/README.md
Empty file.
9 changes: 9 additions & 0 deletions fabric-network/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright 2018 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/

module.exports.Network = require('./lib/network');
module.exports.InMemoryWallet = require('./lib/impl/wallet/inmemorywallet');
module.exports.X509WalletMixin = require('./lib/impl/wallet/x509walletmixin');
48 changes: 48 additions & 0 deletions fabric-network/lib/api/wallet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright 2018 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/

'use strict';

class Wallet {

// ===============================================
// SPI Methods
// ===============================================

async setUserContext(client, label) {
throw new Error('Not implemented');
}

async configureClientStores(client, label) {
throw new Error('Not implemented');
}

//=========================================================
// End user APIs
//=========================================================

async import(label, identity) {
throw new Error('Not implemented');
}

async export(label) {
throw new Error('Not implemented');
}

async list() {
throw new Error('Not implemented');
}

async delete(label) {
throw new Error('Not implemented');
}

async exists(label) {
throw new Error('Not implemented');
}
}

module.exports = Wallet;
169 changes: 169 additions & 0 deletions fabric-network/lib/channel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/**
* Copyright 2018 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/

'use strict';
const FabricConstants = require('fabric-client/lib/Constants');
const Contract = require('./contract');
const logger = require('./logger').getLogger('channel.js');
const util = require('util');

class Channel {

/**
* Channel constructor for internal use only
* @param network
* @param channel
* @private
*/
constructor(network, channel) {
logger.debug('in Channel constructor');

this.network = network;
this.channel = channel;
this.contracts = new Map();
this.initialized = false;
}

/**
* create a map of mspId's and the channel peers in those mspIds
* @private
* @memberof Network
*/
_mapPeersToMSPid() {
logger.debug('in _mapPeersToMSPid');

// TODO: assume 1-1 mapping of mspId to org as the node-sdk makes that assumption
// otherwise we would need to find the channel peer in the network config collection or however SD
// stores things

const peerMap = new Map();
const channelPeers = this.channel.getPeers();

// bug in service discovery, peers don't have the associated mspid
if (channelPeers.length > 0) {
for (const channelPeer of channelPeers) {
const mspId = channelPeer.getMspid();
if (mspId) {
let peerList = peerMap.get(mspId);
if (!peerList) {
peerList = [];
peerMap.set(mspId, peerList);
}
peerList.push(channelPeer);
}
}
}
if (peerMap.size === 0) {
const msg = 'no suitable peers associated with mspIds were found';
logger.error('_mapPeersToMSPid: ' + msg);
throw new Error(msg);
}
return peerMap;
}

/**
* initialize the channel if it hasn't been done
* @private
*/
async _initializeInternalChannel() {
logger.debug('in _initializeInternalChannel');

//TODO: Should this work across all peers or just orgs peers ?
//TODO: should sort peer list to the identity org initializing the channel.
//TODO: Candidate to push to low level node-sdk.

const ledgerPeers = this.channel.getPeers().filter((cPeer) => {
return cPeer.isInRole(FabricConstants.NetworkConfig.LEDGER_QUERY_ROLE);
});

if (ledgerPeers.length === 0) {
const msg = 'no suitable peers available to initialize from';
logger.error('_initializeInternalChannel: ' + msg);
throw new Error(msg);
}

let ledgerPeerIndex = 0;
let success = false;

while (!success) {
try {
const initOptions = {
target: ledgerPeers[ledgerPeerIndex]
};

await this.channel.initialize(initOptions);
success = true;
} catch(error) {
if (ledgerPeerIndex >= ledgerPeers.length - 1) {
const msg = util.format('Unable to initialize channel. Attempted to contact %j Peers. Last error was %s', ledgerPeers.length, error);
logger.error('_initializeInternalChannel: ' + msg);
throw new Error(msg);
}
ledgerPeerIndex++;
}
}
}

async _initialize() {
logger.debug('in initialize');

if (this.initialized) {
return;
}

await this._initializeInternalChannel();
this.peerMap = this._mapPeersToMSPid();

this.initialized = true;
}

getInternalChannel() {
logger.debug('in getInternalChannel');

return this.channel;
}

getPeerMap() {
logger.debug('in getPeerMap');

return this.peerMap;
}

/**
* Returns an instance of a contract (chaincode) on the current channel
* @param chaincodeId
* @returns {Contract}
* @api
*/
getContract(chaincodeId) {
logger.debug('in getContract');

// check initialized flag
// Create the new Contract
let contract = this.contracts.get(chaincodeId);
if (!contract) {
contract = new Contract(
this.channel,
chaincodeId,
this.network
);
}
return contract;
}

_dispose() {
logger.debug('in _dispose');

// Danger as this cached in network, and also async so how would
// channel._dispose() followed by channel.initialize() be safe ?
// make this private is the safest option.
this.contracts.clear();
this.initialized = false;
}

}

module.exports = Channel;
Loading

0 comments on commit c680a30

Please sign in to comment.