Skip to content

Commit

Permalink
Check for duplicates when adding peers to the chain
Browse files Browse the repository at this point in the history
Prior to this fix, it was possible to add duplicate peers
to the chain.  This fix now adds check to the addPeer method
and throws a DuplicatePeer error if a peer with the same URL is
already a member of the chain.  Also added a test for adding multiple
valid peers to the chain

Fixes FAB-264

Change-Id: I575200325bf8e8aedc72e1f41419099689c3a6fc
Signed-off-by: Gari Singh <gari.r.singh@gmail.com>
  • Loading branch information
mastersingh24 committed Sep 7, 2016
1 parent dc2d339 commit 4203ea8
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 76 deletions.
12 changes: 12 additions & 0 deletions sdk/node/src/hfc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,18 @@ export class Chain {
* @returns {Peer} Returns a new peer.
*/
addPeer(url:string, pem?:string):Peer {

//check to see if the peer is already part of the chain
this.peers.forEach(function(peer){
if (peer.getUrl()===url)
{
var error = new Error();
error.name = "DuplicatePeer";
error.message = "Peer with URL " + url + " is already a member of the chain";
throw error;
}
})

let peer = new Peer(url, this, pem);
this.peers.push(peer);
return peer;
Expand Down
238 changes: 162 additions & 76 deletions sdk/node/test/unit/chain-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ chain.addPeer("grpc://localhost:7051");
// or network mode (code package built and sent to the peer).
//

var mode = process.env['DEPLOY_MODE'];
var mode = process.env['DEPLOY_MODE'];
console.log("$DEPLOY_MODE: " + mode);
if (mode === 'dev') {
chain.setDevMode(true);
Expand Down Expand Up @@ -104,7 +104,7 @@ var deltaAB = "1";
function getUser(name, cb) {
chain.getUser(name, function (err, user) {
if (err) return cb(err);
if (user.isEnrolled()) return cb(null,user);
if (user.isEnrolled()) return cb(null, user);
// User is not enrolled yet, so perform both registration and enrollment
// The chain registrar is already set inside 'Set chain registrar' test
var registrationRequest = {
Expand Down Expand Up @@ -201,6 +201,92 @@ test('Add valid peer URLs to the chain', function (t) {

});

//
// Test adding multiple peers to the chain
//
test('Add multiple peers to the chain', function (t) {

t.plan(1);

var chain_multiple = hfc.newChain("chain_multiple");

var peers = [
"grpc://localhost:7051",
"grpc://localhost:7052",
"grpc://localhost:7053",
"grpc://localhost:7054"
];

peers.forEach(function (peer) {

try {
chain_multiple.addPeer(peer);
}
catch (err) {
t.fail("Failed to add multiple peers to the chain");
}

})

//check to see we have the correct number of peers
if (chain_multiple.getPeers().length == peers.length) {
t.pass("Successfully added multiple peers to the chain(" + peers.length +
" expected | " + chain_multiple.getPeers().length + " found)");

}
else {
t.fail("Failed to add multiple peers to the chain(" + peers.length +
" expected | " + chain_multiple.getPeers().length + " found)");
}
});

//
// Test adding duplicate peers to the chain
//
test('Catch duplicate peer added to chain', function (t) {

t.plan(2);

var chain_duplicate = hfc.newChain("chain_duplicate");

var peers = [
"grpc://localhost:7051",
"grpc://localhost:7052",
"grpc://localhost:7053",
"grpc://localhost:7051"
];

//we have one duplicate to set the expected value
var expected = peers.length - 1;

peers.forEach(function (peer) {

try {
chain_duplicate.addPeer(peer);
}
catch (err) {
if (err.name != "DuplicatePeer"){
t.fail("Unexpected error " + err.toString());
}
else {
t.pass("Expected error message 'DuplicatePeer' thrown");
}
}

})

//check to see we have the correct number of peers
if (chain_duplicate.getPeers().length == expected) {
t.pass("Duplicate peer not added to the chain(" + expected +
" expected | " + chain_duplicate.getPeers().length + " found)");

}
else {
t.fail("Failed to detect duplicate peer (" + expected +
" expected | " + chain_duplicate.getPeers().length + " found)");
}
});

//
// Set Invalid security level and hash algorithm.
//
Expand Down Expand Up @@ -363,35 +449,35 @@ test('Register and enroll a new user', function (t) {
// the missing parameter.
//

test('Deploy with missing chaincodeName or chaincodePath', function(t) {
t.plan(1);

// Construct the deploy request with a missing chaincodeName/chaincodePath
var deployRequest = {
// Function to trigger
fcn: "init",
// Arguments to the initializing function
args: ["a", initA, "b", initB]
};

// Trigger the deploy transaction
var deployTx = test_user_Member1.deploy(deployRequest);

// Print the deploy results
deployTx.on('complete', function(results) {
// Deploy request completed successfully
console.log(util.format("deploy results: %j",results));
// Set the testChaincodeID for subsequent tests
testChaincodeID = results.chaincodeID;
console.log("testChaincodeID:" + testChaincodeID);
t.fail(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results));
// Exit the test script after a failure
process.exit(1);
});
deployTx.on('error', function(err) {
// Deploy request failed
t.pass(util.format("Failed to deploy chaincode: request=%j, error=%j",deployRequest,err));
});
test('Deploy with missing chaincodeName or chaincodePath', function (t) {
t.plan(1);

// Construct the deploy request with a missing chaincodeName/chaincodePath
var deployRequest = {
// Function to trigger
fcn: "init",
// Arguments to the initializing function
args: ["a", initA, "b", initB]
};

// Trigger the deploy transaction
var deployTx = test_user_Member1.deploy(deployRequest);

// Print the deploy results
deployTx.on('complete', function (results) {
// Deploy request completed successfully
console.log(util.format("deploy results: %j", results));
// Set the testChaincodeID for subsequent tests
testChaincodeID = results.chaincodeID;
console.log("testChaincodeID:" + testChaincodeID);
t.fail(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results));
// Exit the test script after a failure
process.exit(1);
});
deployTx.on('error', function (err) {
// Deploy request failed
t.pass(util.format("Failed to deploy chaincode: request=%j, error=%j", deployRequest, err));
});
});

//
Expand All @@ -400,43 +486,43 @@ test('Deploy with missing chaincodeName or chaincodePath', function(t) {
// a local directory in the user's $GOPATH.
//

test('Deploy a chaincode by enrolled user', function(t) {
t.plan(1);

// Construct the deploy request
var deployRequest = {
// Function to trigger
fcn: "init",
// Arguments to the initializing function
args: ["a", initA, "b", initB]
};

if (mode === 'dev') {
// Name required for deploy in development mode
deployRequest.chaincodeName = testChaincodeName;
} else {
// Path (under $GOPATH) required for deploy in network mode
deployRequest.chaincodePath = testChaincodePath;
}

// Trigger the deploy transaction
var deployTx = test_user_Member1.deploy(deployRequest);

// Print the deploy results
deployTx.on('complete', function(results) {
// Deploy request completed successfully
console.log(util.format("deploy results: %j",results));
// Set the testChaincodeID for subsequent tests
testChaincodeID = results.chaincodeID;
console.log("testChaincodeID:" + testChaincodeID);
t.pass(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results));
});
deployTx.on('error', function(err) {
// Deploy request failed
t.fail(util.format("Failed to deploy chaincode: request=%j, error=%j",deployRequest,err));
// Exit the test script after a failure
process.exit(1);
});
test('Deploy a chaincode by enrolled user', function (t) {
t.plan(1);

// Construct the deploy request
var deployRequest = {
// Function to trigger
fcn: "init",
// Arguments to the initializing function
args: ["a", initA, "b", initB]
};

if (mode === 'dev') {
// Name required for deploy in development mode
deployRequest.chaincodeName = testChaincodeName;
} else {
// Path (under $GOPATH) required for deploy in network mode
deployRequest.chaincodePath = testChaincodePath;
}

// Trigger the deploy transaction
var deployTx = test_user_Member1.deploy(deployRequest);

// Print the deploy results
deployTx.on('complete', function (results) {
// Deploy request completed successfully
console.log(util.format("deploy results: %j", results));
// Set the testChaincodeID for subsequent tests
testChaincodeID = results.chaincodeID;
console.log("testChaincodeID:" + testChaincodeID);
t.pass(util.format("Successfully deployed chaincode: request=%j, response=%j", deployRequest, results));
});
deployTx.on('error', function (err) {
// Deploy request failed
t.fail(util.format("Failed to deploy chaincode: request=%j, error=%j", deployRequest, err));
// Exit the test script after a failure
process.exit(1);
});
});

//
Expand Down Expand Up @@ -538,10 +624,10 @@ test('Query existing chaincode state by enrolled user with batch size of 100', f
t.pass(util.format("Successfully queried existing chaincode state: request=%j, response=%j, value=%s", queryRequest, results, results.result.toString()));
});
queryTx.on('error', function (err) {
// Query failed
t.fail(util.format("Failed to query existing chaincode state: request=%j, error=%j", queryRequest, err));
// Exit the test script after a failure
process.exit(1);
// Query failed
t.fail(util.format("Failed to query existing chaincode state: request=%j, error=%j", queryRequest, err));
// Exit the test script after a failure
process.exit(1);
});
});

Expand Down Expand Up @@ -576,7 +662,7 @@ test('Query non-existing chaincode state by enrolled user', function (t) {
});
queryTx.on('error', function (err) {
// Query failed
t.pass(util.format("Failed to query non-existing chaincode state: request=%j, error=%j",queryRequest,err));
t.pass(util.format("Failed to query non-existing chaincode state: request=%j, error=%j", queryRequest, err));
});
});

Expand Down Expand Up @@ -611,7 +697,7 @@ test('Query non-existing chaincode function by enrolled user', function (t) {
});
queryTx.on('error', function (err) {
// Query failed
t.pass(util.format("Failed to query non-existing chaincode function: request=%j, error=%j",queryRequest,err));
t.pass(util.format("Failed to query non-existing chaincode function: request=%j, error=%j", queryRequest, err));
});
});

Expand All @@ -638,7 +724,7 @@ test('Invoke with missing chaincodeID', function (t) {
// Print the invoke results
invokeTx.on('submitted', function (results) {
// Invoke transaction submitted successfully
t.fail(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest,results));
t.fail(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest, results));
// Exit the test script after a failure
process.exit(1);
});
Expand Down Expand Up @@ -672,7 +758,7 @@ test('Invoke a chaincode by enrolled user', function (t) {
// Print the invoke results
invokeTx.on('submitted', function (results) {
// Invoke transaction submitted successfully
t.pass(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest,results));
t.pass(util.format("Successfully submitted chaincode invoke transaction: request=%j, response=%j", invokeRequest, results));
});
invokeTx.on('error', function (err) {
// Invoke transaction submission failed
Expand Down

0 comments on commit 4203ea8

Please sign in to comment.