Skip to content

Commit

Permalink
Merge "[FAB-5375] SDK support for node.js chaincode"
Browse files Browse the repository at this point in the history
  • Loading branch information
jimthematrix authored and Gerrit Code Review committed Sep 22, 2017
2 parents cf7757a + 0c8b91e commit 895364f
Show file tree
Hide file tree
Showing 32 changed files with 1,355 additions and 385 deletions.
13 changes: 7 additions & 6 deletions build/tasks/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ gulp.task('lint', function () {
'!fabric-ca-client/node_modules/**',
'!docs/**',
'!coverage/**',
'!tmp/**'
'!tmp/**',
])
.pipe(eslint(
{
Expand All @@ -42,12 +42,13 @@ gulp.task('lint', function () {
'ignoreUrls': true,
'ignoreStrings': true,
'ignoreTemplateLiterals': true,
'ignoreRegExpLiterals': true
}
]
}
'ignoreRegExpLiterals': true,
},
],
},
fix: true,
}
))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
});
5 changes: 4 additions & 1 deletion build/tasks/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ gulp.task('test', ['clean-up', 'lint', 'pre-test', 'docker-ready', 'ca'], functi
'test/integration/invoke.js',
'test/integration/perf/orderer.js',
'test/integration/perf/peer.js',
'test/integration/network-config.js'
'test/integration/network-config.js',
// channel: mychannel, chaincode: e2enodecc:v0
'test/integration/nodechaincode/e2e.js'

]))
.pipe(addsrc.append(
'test/unit/logger.js' // put this to the last so the debugging levels are not mixed up
Expand Down
4 changes: 2 additions & 2 deletions fabric-client/lib/BlockDecoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ function decodeConfigValue(proto_config_value) {
var proto_chain_creation_policy_names = _ordererConfigurationProto.ChainCreationPolicyNames.decode(proto_config_value.value.value);
var names = [];
var proto_names = proto_chain_creation_policy_names.getNames();
if(proto_names) for(var i in proto_names) {
if(proto_names) for(let i in proto_names) {
names.push(proto_names[i]); //string
}
config_value.value.names = names;
Expand All @@ -842,7 +842,7 @@ function decodeConfigValue(proto_config_value) {
var orderer_addresses = _commonConfigurationProto.OrdererAddresses.decode(proto_config_value.value.value);
var addresses = [];
var proto_addresses = orderer_addresses.getAddresses();
if(proto_addresses) for(var i in proto_addresses) {
if(proto_addresses) for(let i in proto_addresses) {
addresses.push(proto_addresses[i]); //string
}
config_value.value.addresses = addresses;
Expand Down
11 changes: 6 additions & 5 deletions fabric-client/lib/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ var Channel = class {

//to do update logger
logger.debug('Constructed Channel instance: name - %s, ' +
'network mode: %s',
'network mode: %s',
this._name,
!this._devMode);
}
Expand Down Expand Up @@ -1183,7 +1183,8 @@ var Channel = class {
}

let lcccSpec = {
type: _ccProto.ChaincodeSpec.Type.GOLANG,
// type: _ccProto.ChaincodeSpec.Type.GOLANG,
type: clientUtils.translateCCType(request.chaincodeType),
chaincode_id: { name: Constants.LSCC },
input: { args : lcccSpec_args}
};
Expand Down Expand Up @@ -1525,7 +1526,7 @@ var Channel = class {
var proposal = results[1];
logger.debug('queryByChaincode - results received');
if(responses && Array.isArray(responses)) {
var results = [];
let results = [];
for(let i = 0; i < responses.length; i++) {
let response = responses[i];
if(response instanceof Error) {
Expand Down Expand Up @@ -1569,7 +1570,7 @@ var Channel = class {
* @returns {boolean} A boolean value of true when both the identity and
* the signature are valid, false otherwise.
*/
verifyProposalResponse(proposal_response) {
verifyProposalResponse(proposal_response) {
logger.debug('verifyProposalResponse - start');
if(!proposal_response) {
throw new Error('Missing proposal response');
Expand Down Expand Up @@ -1623,7 +1624,7 @@ var Channel = class {

logger.debug('verifyProposalResponse - This endorsement has both a valid identity and valid signature');
return true;
}
}

/**
* Utility method to examine a set of proposals to check they contain
Expand Down
4 changes: 2 additions & 2 deletions fabric-client/lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ var Client = class extends BaseClient {
* 'mycompany.com/myproject/mypackage/mychaincode', then the archive must contain a
* folder 'src/mycompany.com/myproject/mypackage/mychaincode', where the
* GO source code resides.
* @property {string} chaincodeType - Optional. Type of chaincode. One of 'golang', 'car' or 'java'.
* @property {string} chaincodeType - Optional. Type of chaincode. One of 'golang', 'car', 'node' or 'java'.
* Default is 'golang'. Note that 'java' is not supported as of v1.0.
*/

Expand Down Expand Up @@ -841,7 +841,7 @@ var Client = class extends BaseClient {

// TODO add ESCC/VSCC info here ??????
let lcccSpec = {
type: _ccProto.ChaincodeSpec.Type.GOLANG,
type: ccSpec.type,
chaincode_id: {
name: Constants.LSCC
},
Expand Down
14 changes: 9 additions & 5 deletions fabric-client/lib/Packager.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

var Golang = require('./packager/Golang.js');
var Car = require('./packager/Car.js');
var Node = require('./packager/Node.js');
var utils = require('./utils.js');

var logger = utils.getLogger('packager');
Expand All @@ -26,7 +27,7 @@ var logger = utils.getLogger('packager');
* @param {Object} chaincodePath required - String of the path to location of
* the source code of the chaincode
* @param {Object} chaincodeType optional - String of the type of chaincode
* ['golang', 'car', 'java'] (default 'golang')
* ['golang', 'node', 'car', 'java'] (default 'golang')
* @param {boolean} devmode optional - True if using dev mode
* @returns {Promise} A promise for the data as a byte array
*/
Expand All @@ -48,14 +49,17 @@ module.exports.package = function(chaincodePath, chaincodeType, devmode) {

let handler;

switch (type) {
switch (type.toLowerCase()) {
case 'car':
handler = Car.package;
handler = new Car();
break;
case 'node':
handler = new Node();
break;
default:
handler = Golang.package;
handler = new Golang();
}

return resolve(handler(chaincodePath));
return resolve(handler.package(chaincodePath));
});
};
101 changes: 55 additions & 46 deletions fabric-client/lib/client-utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* Copyright 2016 IBM All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -33,14 +33,16 @@ var Orderer = require('./Orderer.js');

var grpc = require('grpc');
var _commonProto = grpc.load(__dirname + '/protos/common/common.proto').common;
var _proposalProto = grpc.load(__dirname + '/protos/peer/proposal.proto').protos;
var _proposalProto = grpc.load(__dirname +
'/protos/peer/proposal.proto').protos;
var _ccProto = grpc.load(__dirname + '/protos/peer/chaincode.proto').protos;
var _timestampProto = grpc.load(__dirname + '/protos/google/protobuf/timestamp.proto').google.protobuf;
var _timestampProto = grpc.load(__dirname +
'/protos/google/protobuf/timestamp.proto').google.protobuf;

/*
* This function will build the proposal
*/
module.exports.buildProposal = function(invokeSpec, header, transientMap) {
module.exports.buildProposal = function (invokeSpec, header, transientMap) {
// construct the ChaincodeInvocationSpec
let cciSpec = new _ccProto.ChaincodeInvocationSpec();
cciSpec.setChaincodeSpec(invokeSpec);
Expand All @@ -49,7 +51,7 @@ module.exports.buildProposal = function(invokeSpec, header, transientMap) {
cc_payload.setInput(cciSpec.toBuffer());

if (typeof transientMap === 'object') {
logger.debug('buildProposal - adding in transientMap %j',transientMap);
logger.debug('buildProposal - adding in transientMap %j', transientMap);
cc_payload.setTransientMap(transientMap);
}
else {
Expand All @@ -67,21 +69,21 @@ module.exports.buildProposal = function(invokeSpec, header, transientMap) {
/*
* This function will return one Promise when sending a proposal to many peers
*/
module.exports.sendPeersProposal = function(peers, proposal, timeout) {
if(!Array.isArray(peers)) {
module.exports.sendPeersProposal = function (peers, proposal, timeout) {
if (!Array.isArray(peers)) {
peers = [peers];
}
// make function to return an individual promise
var fn = function(peer) {
return new Promise(function(resolve,reject) {
peer.sendProposal(proposal, timeout)
.then(
function(result) {
var fn = function (peer) {
return new Promise(function (resolve, reject) {
peer.sendProposal(proposal, timeout).then(
function (result) {
resolve(result);
}
).catch(
function(err) {
logger.error('sendPeersProposal - Promise is rejected: %s',err.stack ? err.stack : err);
function (err) {
logger.error('sendPeersProposal - Promise is rejected: %s',
err.stack ? err.stack : err);
return reject(err);
}
);
Expand All @@ -91,21 +93,22 @@ module.exports.sendPeersProposal = function(peers, proposal, timeout) {
// settle all the promises and return array of responses
var promises = peers.map(fn);
var responses = [];
return settle(promises)
.then(function (results) {
return settle(promises).then(function (results) {
results.forEach(function (result) {
if (result.isFulfilled()) {
logger.debug('sendPeersProposal - Promise is fulfilled: '+result.value());
responses.push(result.value());
} else {
logger.debug('sendPeersProposal - Promise is rejected: '+result.reason());
if(result.reason() instanceof Error) {
responses.push(result.reason());
}
else {
responses.push(new Error(result.reason()));
if (result.isFulfilled()) {
logger.debug('sendPeersProposal - Promise is fulfilled: ' +
result.value());
responses.push(result.value());
} else {
logger.debug('sendPeersProposal - Promise is rejected: ' +
result.reason());
if (result.reason() instanceof Error) {
responses.push(result.reason());
}
else {
responses.push(new Error(result.reason()));
}
}
}
});
return responses;
});
Expand All @@ -114,39 +117,41 @@ module.exports.sendPeersProposal = function(peers, proposal, timeout) {
/*
* This function will sign the proposal
*/
module.exports.signProposal = function(signingIdentity, proposal) {
module.exports.signProposal = function (signingIdentity, proposal) {
let proposal_bytes = proposal.toBuffer();
// sign the proposal
let sig = signingIdentity.sign(proposal_bytes);
let signature = Buffer.from(sig);

// build manually for now
let signedProposal = {
signature : signature,
proposal_bytes : proposal_bytes
signature: signature,
proposal_bytes: proposal_bytes
};
return signedProposal;
};

/*
* This function will build a common channel header
*/
module.exports.buildChannelHeader = function(type, channel_id, tx_id, epoch, chaincode_id, time_stamp) {
logger.debug('buildChannelHeader - type %s channel_id %s tx_id %d epoch % chaincode_id %s',
type, channel_id, tx_id, epoch, chaincode_id);
module.exports.buildChannelHeader = function (
type, channel_id, tx_id, epoch, chaincode_id, time_stamp) {
logger.debug(
'buildChannelHeader - type %s channel_id %s tx_id %d epoch % chaincode_id %s',
type, channel_id, tx_id, epoch, chaincode_id);
var channelHeader = new _commonProto.ChannelHeader();
channelHeader.setType(type); // int32
channelHeader.setVersion(1); // int32
if(!time_stamp) {
if (!time_stamp) {
time_stamp = module.exports.buildCurrentTimestamp();
}
channelHeader.setTimestamp(time_stamp); // google.protobuf.Timestamp
channelHeader.setChannelId(channel_id); //string
channelHeader.setTxId(tx_id.toString()); //string
if(epoch) {
if (epoch) {
channelHeader.setEpoch(epoch); // uint64
}
if(chaincode_id) {
if (chaincode_id) {
let chaincodeID = new _ccProto.ChaincodeID();
chaincodeID.setName(chaincode_id);

Expand All @@ -161,7 +166,7 @@ module.exports.buildChannelHeader = function(type, channel_id, tx_id, epoch, cha
/*
* This function will build the common header
*/
module.exports.buildHeader = function(creator, channelHeader, nonce) {
module.exports.buildHeader = function (creator, channelHeader, nonce) {
let signatureHeader = new _commonProto.SignatureHeader();
signatureHeader.setCreator(creator.serialize());
signatureHeader.setNonce(nonce);
Expand All @@ -173,13 +178,13 @@ module.exports.buildHeader = function(creator, channelHeader, nonce) {
return header;
};

module.exports.checkProposalRequest = function(request, skip) {
module.exports.checkProposalRequest = function (request, skip) {
var errorMsg = null;

if(request) {
if(!request.chaincodeId) {
if (request) {
if (!request.chaincodeId) {
errorMsg = 'Missing "chaincodeId" parameter in the proposal request';
} else if(!request.txId && !skip) {
} else if (!request.txId && !skip) {
errorMsg = 'Missing "txId" parameter in the proposal request';
}
} else {
Expand All @@ -188,11 +193,11 @@ module.exports.checkProposalRequest = function(request, skip) {
return errorMsg;
};

module.exports.checkInstallRequest = function(request) {
module.exports.checkInstallRequest = function (request) {
var errorMsg = null;

if (request) {
if(!request.chaincodeVersion) {
if (!request.chaincodeVersion) {
errorMsg = 'Missing "chaincodeVersion" parameter in the proposal request';
}
} else {
Expand All @@ -201,22 +206,26 @@ module.exports.checkInstallRequest = function(request) {
return errorMsg;
};

module.exports.translateCCType = function(type) {
switch (type) {
module.exports.translateCCType = function (type) {
let chaincodeType = type ? type : 'golang';

switch (chaincodeType.toLowerCase()) {
case 'golang':
default:
return _ccProto.ChaincodeSpec.Type.GOLANG;
case 'car':
return _ccProto.ChaincodeSpec.Type.CAR;
case 'java':
return _ccProto.ChaincodeSpec.Type.JAVA;
case 'node':
return _ccProto.ChaincodeSpec.Type.NODE;
}
};

/*
* This function will create a timestamp from the current time
*/
module.exports.buildCurrentTimestamp = function() {
module.exports.buildCurrentTimestamp = function () {
var now = new Date();
var timestamp = new _timestampProto.Timestamp();
timestamp.setSeconds(now.getTime() / 1000);
Expand Down
Loading

0 comments on commit 895364f

Please sign in to comment.