Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 25fa4b0

Browse files
author
Dave Kelsey
committed
FABN-826 restore backward compatibility for errors
Error handling was still not backward compatible with previous release of fabric for invoke, install, instantiate, upgrade. This fix should restore backward compatibility Change-Id: I70dc50261e8cd3acf20c58590006defa699e6251 Signed-off-by: Dave Kelsey <d_kelsey@uk.ibm.com>
1 parent f4793ec commit 25fa4b0

File tree

12 files changed

+124
-92
lines changed

12 files changed

+124
-92
lines changed

fabric-client/lib/Peer.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,18 @@ var Peer = class extends Remote {
107107
} else {
108108
if (proposalResponse) {
109109
logger.debug('%s - Received proposal response from peer "%s": status - %s', method, self._url, proposalResponse.response.status);
110-
resolve(proposalResponse);
110+
// 400 is the error threshold level, anything below that the endorser will endorse it.
111+
if (proposalResponse.response && proposalResponse.response.status < 400) {
112+
resolve(proposalResponse);
113+
} else if (proposalResponse.response && proposalResponse.response.message) {
114+
reject(new Error(proposalResponse.response.message));
115+
} else {
116+
logger.error('GRPC client failed to get a proper response from the peer "%s".', self._url);
117+
reject(new Error(util.format('GRPC client failed to get a proper response from the peer "%s".', self._url)));
118+
}
111119
} else {
112-
logger.error('GRPC client failed to get a proper response from the peer "%s".', self._url);
113-
reject(new Error(util.format('GRPC client failed to get a proper response from the peer "%s".', self._url)));
120+
logger.error('GRPC client got a null or undefined response from the peer "%s".', self._url);
121+
reject(new Error(util.format('GRPC client got a null or undefined response from the peer "%s".', self._url)));
114122
}
115123
}
116124
});

test/fixtures/src/github.com/example_cc/example_cc.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
8787
return t.query(stub, args)
8888
}
8989

90-
if function == "queryError" {
91-
return t.queryError(stub, args)
90+
if function == "throwError" {
91+
return t.throwError(stub, args)
9292
}
9393

9494
if function == "move" {
@@ -203,8 +203,8 @@ func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string)
203203
return shim.Success(Avalbytes)
204204
}
205205

206-
func (t *SimpleChaincode) queryError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
207-
err := fmt.Errorf("queryError: an error occurred")
206+
func (t *SimpleChaincode) throwError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
207+
err := fmt.Errorf("throwError: an error occurred")
208208
return shim.Error(err.Error())
209209
}
210210

test/fixtures/src/github.com/example_cc1/example_cc1.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
5656
return t.query(stub, args)
5757
}
5858

59-
if function == "queryError" {
60-
return t.queryError(stub, args)
59+
if function == "throwError" {
60+
return t.throwError(stub, args)
6161
}
6262

6363
if function == "move" {
@@ -178,8 +178,8 @@ func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string)
178178
return shim.Success(Avalbytes)
179179
}
180180

181-
func (t *SimpleChaincode) queryError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
182-
err := fmt.Errorf("queryError: an error occurred")
181+
func (t *SimpleChaincode) throwError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
182+
err := fmt.Errorf("throwError: an error occurred")
183183
return shim.Error(err.Error())
184184
}
185185

test/fixtures/src/node_cc/example_cc/chaincode.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ var Chaincode = class {
7575
return this.query(stub, args);
7676
}
7777

78-
if (fcn === 'queryError') {
79-
return this.queryError(stub, args);
78+
if (fcn === 'throwError') {
79+
return this.throwError(stub, args);
8080
}
8181

8282
if (fcn === 'move') {
@@ -183,8 +183,8 @@ var Chaincode = class {
183183
return shim.success(Buffer.from(Aval.toString()));
184184
}
185185

186-
async queryError(stub, args) {
187-
return shim.error(new Error('queryError: an error occurred'));
186+
async throwError(stub, args) {
187+
return shim.error(new Error('throwError: an error occurred'));
188188
}
189189
};
190190

test/fixtures/src/node_cc/example_cc1/chaincode.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ var Chaincode = class {
4646
return this.query(stub, args);
4747
}
4848

49-
if (fcn === 'queryError') {
50-
return this.queryError(stub, args);
49+
if (fcn === 'throwError') {
50+
return this.throwError(stub, args);
5151
}
5252

5353
if (fcn === 'move') {
@@ -160,8 +160,8 @@ var Chaincode = class {
160160
return shim.success(Buffer.from(Aval.toString()));
161161
}
162162

163-
async queryError(stub, args) {
164-
return shim.error(new Error('queryError: an error occurred'));
163+
async throwError(stub, args) {
164+
return shim.error(new Error('throwError: an error occurred'));
165165
}
166166

167167
async testTransient(stub) {

test/integration/e2e/e2eUtils.js

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ function instantiateChaincodeWithId(userOrg, chaincode_id, chaincode_path, versi
287287
let success = false;
288288
if (proposalResponses && proposalResponses.length > 0) {
289289
proposalResponses.forEach((response) => {
290-
if (response &&
291-
response.response.message.indexOf('Did not find expected key "test" in the transient map of the proposal')) {
290+
if (response && response instanceof Error &&
291+
response.message.includes('Did not find expected key "test" in the transient map of the proposal')) {
292292
success = true;
293293
} else {
294294
success = false;
@@ -577,28 +577,38 @@ function invokeChaincode(userOrg, version, chaincodeId, t, useStore, fcn, args,
577577
for(let i in proposalResponses) {
578578
let one_good = false;
579579
let proposal_response = proposalResponses[i];
580-
logger.debug('invoke chaincode, proposal response: ' + util.inspect(proposal_response, {depth: null}));
581-
if( proposal_response.response && proposal_response.response.status === 200) {
582-
t.pass('transaction proposal has response status of good');
583-
one_good = channel.verifyProposalResponse(proposal_response);
584-
if(one_good) {
585-
t.pass('transaction proposal signature and endorser are valid');
586-
}
587580

588-
// check payload
589-
let payload = proposal_response.response.payload.toString();
590-
// verify payload is equal to expectedResult
591-
if (payload === expectedResult){
592-
t.pass('transaction proposal payloads are valid');
581+
if (expectedResult instanceof Error) {
582+
t.true((proposal_response instanceof Error), 'proposal response should be an instance of error');
583+
t.true(proposal_response.message.includes(expectedResult.message), 'error should contain the correct message: ' + expectedResult.message);
584+
} else {
585+
logger.debug('invoke chaincode, proposal response: ' + util.inspect(proposal_response, {depth: null}));
586+
if( proposal_response.response && proposal_response.response.status === 200) {
587+
t.pass('transaction proposal has response status of good');
588+
one_good = channel.verifyProposalResponse(proposal_response);
589+
if(one_good) {
590+
t.pass('transaction proposal signature and endorser are valid');
591+
}
592+
593+
// check payload
594+
let payload = proposal_response.response.payload.toString();
595+
// verify payload is equal to expectedResult
596+
if (payload === expectedResult){
597+
t.pass('transaction proposal payloads are valid');
598+
} else {
599+
one_good = false;
600+
t.fail('transaction proposal payloads are invalid, expect ' + expectedResult + ', but got ' + payload);
601+
}
593602
} else {
594-
one_good = false;
595-
t.fail('transaction proposal payloads are invalid, expect ' + expectedResult + ', but got ' + payload);
603+
t.fail('invokeChaincode: transaction proposal was bad');
596604
}
597-
} else {
598-
t.fail('invokeChaincode: transaction proposal was bad');
605+
all_good = all_good & one_good;
599606
}
600-
all_good = all_good & one_good;
601607
}
608+
if (expectedResult instanceof Error) {
609+
return;
610+
}
611+
602612
if (all_good) {
603613
// check all the read/write sets to see if the same, verify that each peer
604614
// got the same results on the proposal
@@ -679,6 +689,11 @@ function invokeChaincode(userOrg, version, chaincodeId, t, useStore, fcn, args,
679689
throw new Error('Failed to send proposal due to error: ' + err.stack ? err.stack : err);
680690

681691
}).then((response) => {
692+
if (expectedResult instanceof Error) {
693+
channel.close();
694+
t.pass('Successfully closed all connections');
695+
return true;
696+
}
682697

683698
if (response.status === 'SUCCESS') {
684699
t.pass('Successfully sent transaction to the orderer.');

test/integration/e2e/invoke-transaction.js

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,30 @@ const e2eUtils = require('./e2eUtils.js');
1515
const testUtils = require('../../unit/util');
1616
const chaincodeId = testUtils.END2END.chaincodeId;
1717

18-
test('\n\n***** End-to-end flow: invoke transaction to move money *****\n\n', (t) => {
18+
test('\n\n***** End-to-end flow: invoke transaction to move money *****\n\n', async (t) => {
1919
const fcn = 'move';
2020
const args = ['a', 'b','100'];
21-
const expectedResult = 'move succeed';
22-
e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult)
23-
.then((result) => {
24-
if(result){
25-
t.pass('Successfully invoke transaction chaincode on channel');
26-
return sleep(5000);
27-
}
28-
else {
29-
t.fail('Failed to invoke transaction chaincode ');
30-
t.end();
31-
}
32-
}, (err) => {
33-
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
34-
t.end();
35-
}).then(() => {
36-
t.end();
37-
}).catch((err) => {
38-
t.fail('Test failed due to unexpected reasons. ' + err.stack ? err.stack : err);
39-
t.end();
40-
});
21+
let expectedResult = 'move succeed';
22+
try {
23+
let result = await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult);
24+
if(result){
25+
t.pass('Successfully invoke transaction chaincode on channel');
26+
await sleep(5000);
27+
}
28+
else {
29+
t.fail('Failed to invoke transaction chaincode ');
30+
}
31+
} catch(err) {
32+
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
33+
}
34+
35+
try {
36+
expectedResult = new Error('throwError: an error occurred');
37+
await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, 'throwError', args, expectedResult);
38+
} catch(err) {
39+
t.fail('Failed to query chaincode on the channel. ' + err.stack ? err.stack : err);
40+
}
41+
t.end();
4142
});
4243

4344
function sleep(ms) {

test/integration/e2e/query.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ test('\n\n***** End-to-end flow: query chaincode *****\n\n', async (t) => {
3333
}
3434

3535
try {
36-
expectedResult = new Error('queryError: an error occurred');
37-
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'queryError', args, expectedResult, chaincodeId, t);
36+
expectedResult = new Error('throwError: an error occurred');
37+
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'throwError', args, expectedResult, chaincodeId, t);
3838
if(result){
39-
t.pass('Successfully query chaincode on the channel');
39+
t.pass('Successfully handled error from query');
4040
}
4141
else {
4242
t.fail('Failed to query chaincode ');

test/integration/install.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ test('\n\n** Test chaincode install using chaincodePath to create chaincodePacka
6262
params.testDesc = params.testDesc+'0';
6363
installChaincode(params, t)
6464
.then((info) => {
65-
if (info && info.response.message.indexOf('install.'+params.chaincodeVersion+' exists') > 0) {
65+
if (info && info instanceof Error && info.message.includes('install.'+params.chaincodeVersion+' exists')) {
6666
t.pass('passed check for exists on install again');
6767
t.end();
6868
} else {
@@ -115,7 +115,7 @@ test('\n\n** Test chaincode install using chaincodePackage[byte] **\n\n', (t) =>
115115
params.testDesc = params.testDesc+'0';
116116
installChaincode(params, t)
117117
.then((info) => {
118-
if (info && info.response.message.indexOf('install-package.'+params.chaincodeVersion+' exists') > 0) {
118+
if (info && info instanceof Error && info.message.includes('install-package.'+params.chaincodeVersion+' exists')) {
119119
t.pass('passed check for exists same code again');
120120
t.end();
121121
} else {

test/integration/nodechaincode/invoke.js

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,37 @@ var e2eUtils = require('../e2e/e2eUtils.js');
1515
var testUtils = require('../../unit/util');
1616
var chaincodeId = testUtils.NODE_END2END.chaincodeId;
1717

18-
test('\n\n***** Node-Chaincode End-to-end flow: invoke transaction to move money *****\n\n', (t) => {
18+
test('\n\n***** Node-Chaincode End-to-end flow: invoke transaction to move money *****\n\n', async (t) => {
1919
const fcn = 'move';
2020
const args = ['a', 'b','100'];
21-
const expectedResult = 'move succeed';
22-
e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult)
23-
.then((result) => {
24-
if(result){
25-
t.pass('Successfully invoke transaction chaincode on channel');
26-
return sleep(5000);
27-
}
28-
else {
29-
t.fail('Failed to invoke transaction chaincode ');
30-
t.end();
31-
}
32-
}, (err) => {
33-
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
34-
t.end();
35-
}).then(() => {
36-
t.end();
37-
}).catch((err) => {
38-
t.fail('Test failed due to unexpected reasons. ' + err.stack ? err.stack : err);
39-
t.end();
40-
});
21+
let expectedResult = 'move succeed';
22+
try {
23+
let result = await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult);
24+
if(result){
25+
t.pass('Successfully invoke transaction chaincode on channel');
26+
await sleep(5000);
27+
}
28+
else {
29+
t.fail('Failed to invoke transaction chaincode ');
30+
}
31+
} catch(err) {
32+
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
33+
}
34+
35+
try {
36+
expectedResult = new Error('throwError: an error occurred');
37+
let result = await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, 'throwError', args, expectedResult);
38+
if(result){
39+
t.pass('Successfully handled invocation errors');
40+
}
41+
else {
42+
t.fail('Failed to invoke transaction chaincode ');
43+
}
44+
45+
} catch(err) {
46+
t.fail('Failed to query chaincode on the channel. ' + err.stack ? err.stack : err);
47+
}
48+
t.end();
4149
});
4250

4351
function sleep(ms) {

test/integration/nodechaincode/query.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ test('\n\n***** Node-Chaincode End-to-end flow: query chaincode *****\n\n', asyn
3333
}
3434

3535
try {
36-
expectedResult = new Error('queryError: an error occurred');
37-
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'queryError', args, expectedResult, chaincodeId, t);
36+
expectedResult = new Error('throwError: an error occurred');
37+
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'throwError', args, expectedResult, chaincodeId, t);
3838
if(result){
39-
t.pass('Successfully query chaincode on the channel');
39+
t.pass('Sucessfully handled error from a query');
4040
}
4141
else {
4242
t.fail('Failed to query chaincode ');

test/unit/util.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,15 @@ module.exports.checkResults = function(results, error_snip, t) {
266266
var proposalResponses = results[0];
267267
for(var i in proposalResponses) {
268268
let proposal_response = proposalResponses[i];
269-
if(proposal_response.response && proposal_response.response.message) {
270-
if(proposal_response.response.message.indexOf(error_snip) > -1) {
269+
if(proposal_response instanceof Error) {
270+
if(proposal_response.message.includes(error_snip)) {
271271
t.pass('Successfully got the error' + error_snip);
272272
} else {
273-
t.fail( 'Failed to get error with ' + error_snip + ' :: response message ' + proposal_response.response.message);
273+
t.fail( 'Failed to get error with ' + error_snip + ' :: response message ' + proposal_response.message);
274274
}
275275
}
276276
else {
277-
t.fail(' Failed :: no response message found and should have had an error with '+ error_snip);
277+
t.fail(' Failed :: no Error response message found and should have had an error with '+ error_snip);
278278
}
279279
}
280280
};

0 commit comments

Comments
 (0)