Skip to content

Commit a81935a

Browse files
author
Simon Stone
authored
FABCN-395: Use @grpc/grpc-js for Node.js chaincode (#143) (#144)
Signed-off-by: Simon Stone <[email protected]>
1 parent 8de8a6e commit a81935a

File tree

8 files changed

+981
-699
lines changed

8 files changed

+981
-699
lines changed

common/config/rush/pnpm-lock.yaml

Lines changed: 929 additions & 668 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libraries/fabric-shim/lib/handler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
process.env.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';
1010

1111
const protoLoader = require('@grpc/proto-loader');
12-
const grpc = require('grpc');
12+
const grpc = require('@grpc/grpc-js');
1313
const fabprotos = require('../bundle');
1414
const path = require('path');
1515
const {URL} = require('url');

libraries/fabric-shim/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@
5858
},
5959
"dependencies": {
6060
"@fidm/x509": "^1.2.1",
61-
"@grpc/proto-loader": "^0.5.1",
61+
"@grpc/grpc-js": "^1.0.3",
62+
"@grpc/proto-loader": "^0.5.4",
6263
"@types/node": "^8.9.4",
6364
"ajv": "^6.5.5",
6465
"fabric-contract-api": "2.1.2-unstable",
6566
"fabric-shim-api": "2.1.2-unstable",
6667
"fs-extra": "8.1.0",
67-
"grpc": "^1.23.3",
6868
"reflect-metadata": "^0.1.12",
6969
"winston": "^3.2.1",
7070
"yargs": "^13.3.0 ",

libraries/fabric-shim/test/unit/chaincode.js

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,22 @@ const expect = chai.expect;
1212
const rewire = require('rewire');
1313
const fabprotos = require('../../bundle');
1414
const path = require('path');
15+
const fs = require('fs');
1516

1617
const Logger = require('../../lib/logger');
1718

1819
const Stub = require('../../lib/stub');
1920
const chaincodePath = '../../lib/chaincode.js';
2021
const StartCommand = require('../../lib/cmds/startCommand.js');
2122

23+
const caPath = path.join(__dirname, 'test-ca.pem');
24+
const certPath = path.join(__dirname, 'test-cert.pem');
25+
const keyPath = path.join(__dirname, 'test-key.pem');
26+
27+
const ca = fs.readFileSync(caPath, 'utf8');
28+
const key = fs.readFileSync(keyPath, 'utf8');
29+
const cert = fs.readFileSync(certPath, 'utf8');
30+
2231
describe('Chaincode', () => {
2332
let Chaincode;
2433
let sandbox;
@@ -159,15 +168,13 @@ describe('Chaincode', () => {
159168
});
160169

161170
describe ('TLS handling', () => {
162-
const testfile = path.join(__dirname, '../../../../package.json');
163-
164171
const myYargs = {'argv': {'$0': 'fabric-chaincode-node', 'peer.address': 'localhost:7051', 'chaincode-id-name': 'mycc'}};
165172

166173
let getArgsStub;
167174

168175
before(() => {
169176
process.env.CORE_PEER_TLS_ENABLED = true;
170-
process.env.CORE_PEER_TLS_ROOTCERT_FILE = testfile;
177+
process.env.CORE_PEER_TLS_ROOTCERT_FILE = caPath;
171178
});
172179

173180
beforeEach(() => {
@@ -198,7 +205,7 @@ describe('Chaincode', () => {
198205
});
199206

200207
it ('should throw an error when CORE_TLS_CLIENT_KEY_PATH env var set but CORE_TLS_CLIENT_CERT_PATH env var not set', () => {
201-
process.env.CORE_TLS_CLIENT_KEY_PATH = testfile;
208+
process.env.CORE_TLS_CLIENT_KEY_PATH = keyPath;
202209
expect(() => {
203210
Chaincode.start({Init: function() {}, Invoke: function() {}});
204211
}).to.throw(/The client key and cert are needed when TLS is enabled, but environment variables specifying the paths to these files are missing/);
@@ -209,8 +216,8 @@ describe('Chaincode', () => {
209216
const handlerClass = Chaincode.__get__('Handler');
210217
const chat = sandbox.stub(handlerClass.prototype, 'chat');
211218

212-
process.env.CORE_TLS_CLIENT_KEY_PATH = testfile;
213-
process.env.CORE_TLS_CLIENT_CERT_PATH = testfile;
219+
process.env.CORE_TLS_CLIENT_KEY_PATH = keyPath;
220+
process.env.CORE_TLS_CLIENT_CERT_PATH = certPath;
214221

215222
Chaincode.start({Init: function() {}, Invoke: function() {}});
216223

@@ -243,22 +250,17 @@ describe('Chaincode', () => {
243250
const handlerClass = Chaincode.__get__('Handler');
244251
Chaincode.__set__('Handler', MockHandler);
245252

246-
process.env.CORE_TLS_CLIENT_KEY_PATH = testfile;
247-
process.env.CORE_TLS_CLIENT_CERT_PATH = testfile;
253+
process.env.CORE_TLS_CLIENT_KEY_PATH = keyPath;
254+
process.env.CORE_TLS_CLIENT_CERT_PATH = certPath;
248255

249256
Chaincode.start({Init: function() {}, Invoke: function() {}});
250257

251258
sinon.assert.calledOnce(getArgsStub);
252259
sinon.assert.calledWith(getArgsStub, myYargs);
253260

254-
const attributes = ['pem', 'cert', 'key'];
255-
256-
attributes.forEach((attr) => {
257-
expect(typeof testOpts[attr]).to.deep.equal('string');
258-
259-
const json = JSON.parse(testOpts[attr]);
260-
expect(json.name).to.deep.equal('fabric-chaincode-node');
261-
});
261+
testOpts.pem.should.equal(ca);
262+
testOpts.cert.should.equal(cert);
263+
testOpts.key.should.equal(key);
262264

263265
Chaincode.__set__('Handler', handlerClass);
264266
});

libraries/fabric-shim/test/unit/handler.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ const StateQueryIterator = require('../../../fabric-shim/lib/iterators.js').Stat
2121
const HistoryQueryIterator = require('../../../fabric-shim/lib/iterators.js').HistoryQueryIterator;
2222

2323
const fabprotos = require('../../bundle');
24-
const grpc = require('grpc');
24+
const grpc = require('@grpc/grpc-js');
25+
const fs = require('fs');
26+
const path = require('path');
2527

2628
const sandbox = sinon.createSandbox();
2729

@@ -30,10 +32,14 @@ const mockChaincodeImpl = {
3032
Invoke: function() {}
3133
};
3234

35+
const ca = fs.readFileSync(path.join(__dirname, 'test-ca.pem'), 'utf8');
36+
const key = fs.readFileSync(path.join(__dirname, 'test-key.pem'), 'utf8');
37+
const cert = fs.readFileSync(path.join(__dirname, 'test-cert.pem'), 'utf8');
38+
3339
const mockOpts = {
34-
pem: 'dummy pem string',
35-
key: 'dummy key',
36-
cert: 'dummy cert'
40+
pem: ca,
41+
key: key,
42+
cert: cert
3743
};
3844

3945
const mockPeerAddress = {
@@ -401,8 +407,8 @@ describe('Handler', () => {
401407
expect(handler._request_timeout).to.deep.equal(30000);
402408
expect(handler._endpoint.addr).to.deep.equal(mockPeerAddress.base);
403409
expect(credsSpy.calledOnce).to.be.true;
404-
expect(handler._endpoint.creds.constructor.name).to.deep.equal('ChannelCredentials');
405-
expect(handler._client.constructor.name).to.deep.equal('ServiceClient');
410+
expect(handler._endpoint.creds.constructor.name).to.deep.equal('InsecureChannelCredentialsImpl');
411+
expect(handler._client.constructor.name).to.deep.equal('ServiceClientImpl');
406412

407413
credsSpy.restore();
408414
});
@@ -450,16 +456,16 @@ describe('Handler', () => {
450456
it ('should throw an error if connection secure encoded private key not passed as opt', () => {
451457
expect(() => {
452458
new Handler(mockChaincodeImpl, mockPeerAddress.secure, {
453-
pem: 'dummy pem string'
459+
pem: ca
454460
});
455461
}).to.throw(/encoded Private key is required./);
456462
});
457463

458464
it ('should throw an error if connection secure encoded private key not passed as opt', () => {
459465
expect(() => {
460466
new Handler(mockChaincodeImpl, mockPeerAddress.secure, {
461-
pem: 'dummy pem string',
462-
key: 'dummy key'
467+
pem: ca,
468+
key: key
463469
});
464470
}).to.throw(/encoded client certificate is required./);
465471
});
@@ -474,8 +480,8 @@ describe('Handler', () => {
474480
expect(handler._endpoint.addr).to.deep.equal(mockPeerAddress.base);
475481
expect(credsSpy.calledOnce).to.be.true;
476482
expect(credsSpy.calledWith(Buffer.from(mockOpts.pem), Buffer.from(mockOpts.key, 'base64'), Buffer.from(mockOpts.cert, 'base64'))).to.be.true;
477-
expect(handler._endpoint.creds.constructor.name).to.deep.equal('ChannelCredentials');
478-
expect(handler._client.constructor.name).to.deep.equal('ServiceClient');
483+
expect(handler._endpoint.creds.constructor.name).to.deep.equal('SecureChannelCredentialsImpl');
484+
expect(handler._client.constructor.name).to.deep.equal('ServiceClientImpl');
479485
});
480486

481487
it ('should set grpc ssl options when ssl-target-name-override passed', () => {
@@ -1681,7 +1687,7 @@ describe('Handler', () => {
16811687
const createStub = Handler.__get__('createStub');
16821688
createStub({}, 'channelID', 'txID', 'some input', 'some proposal');
16831689

1684-
expect(mockStub.calledWithNew).to.be.ok; //believe wrong
1690+
expect(mockStub.calledWithNew).to.be.ok; // believe wrong
16851691
expect(mockStub.calledWithNew()).to.be.false;
16861692
expect(mockStub.firstCall.args[0]).to.deep.equal({});
16871693
expect(mockStub.firstCall.args[1]).to.deep.equal('channelID');
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIBkzCB9QIJAJ0Z8jFiPPi9MAoGCCqGSM49BAMCMA4xDDAKBgNVBAMMA3RsczAe
3+
Fw0yMDA1MDcxNjM0MjFaFw0zMDA1MDUxNjM0MjFaMA4xDDAKBgNVBAMMA3RsczCB
4+
mzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEACoUS3zg9Qj5CgQeNCY+9sPM2YWYHUUQ
5+
SBE/oYpgrWV8E8TqtWkWchwXP4OoZAq7bMJ2bNQE5Sq6IY+bZrYpOKjfASpyS4qR
6+
4xJfCun7BIZAjYHvVqmcuF8aJafh8F93GBjkILHgHTrtLLsAq6sBpzEuVJlsuf1h
7+
LhKnCAqvfEtC1IBVMAoGCCqGSM49BAMCA4GMADCBiAJCANGUp459P3aMhtTZdXFq
8+
mc8QVM7rHR3Zli9kmWsGVdJvbUbuHcX6+0AU1S8R2DhPA8oeBuQT7dbovYfweuVb
9+
QfR3AkIApaKesiN9LNy9arSBGXTFKJquBT63v4bi4fyCNhhdC3wxKetsJ1DCpIdr
10+
Bl8ZncJxUMjCrd7BNlkBNP7jCGdKpPk=
11+
-----END CERTIFICATE-----
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrakNCOVFJSkFPZTRqL3NqV3ltRE1Bb0dDQ3FHU000OUJBTUNNQTR4RERBS0JnTlZCQU1NQTNSc2N6QWUKRncweU1EQTFNRGN4TmpNek5UUmFGdzB6TURBMU1EVXhOak16TlRSYU1BNHhEREFLQmdOVkJBTU1BM1JzY3pDQgptekFRQmdjcWhrak9QUUlCQmdVcmdRUUFJd09CaGdBRUFPcllIem5BZmVXZ3pVM3dVZ1Q1Ylk5NkUvT2ZMb3p4CitlUUFIL2Y5cDV3TUxuUzliMTJZczBHWitTNEdjSEYva1FBNlpoMVZBcFdKYnJ6MjFYVWhSbU5QQVRibDd3K2cKbytyazJ2cVZ5Y0E3dU1tUERlL0J2MVlldEh1WXZCd05vajVLVm9vVnVpUnJPOUlkU2N3ZUxkai9WOXoyQUkvQgpmUC9iN01aYWFwbUdUQjVFTUFvR0NDcUdTTTQ5QkFNQ0E0R0xBRENCaHdKQmVZQ1ZPclFWR3dmb1Q3OWRqRWpqCm1YVkVIL3hWcGk4b1ZhWkxVRm0yN2RldkYwb1ViZHowZSt2MzhZdkx6aERnWWh2MUtMQzhnYWxxaFdleTI2MmkKVVcwQ1FnRWRrUHFOYUZlbjF0WEQ5RWJoTjhSdVRyQWE3RGphNzZ3SWVMZUZSdFloZ0hCZlMvZmM0VWR3N1hWbgpQcG9nQ0xhM0ZMNkNDSUZIQWEyTU9kc3VMeld4V2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1JSGNBZ0VCQkVJQmZXcmJQam9pdHcwd3AwUjA3dHdKeDhxaDZGenhpVFArekpFNEZHZ3EvTXh6Sy9kdUhIN2YKRjNzOWtmM1dkcWxYNlkwTnM2K3VRR2hmK2laODZtd01zaU9nQndZRks0RUVBQ09oZ1lrRGdZWUFCQURxMkI4NQp3SDNsb00xTjhGSUUrVzJQZWhQem55Nk04Zm5rQUIvMy9hZWNEQzUwdlc5ZG1MTkJtZmt1Qm5CeGY1RUFPbVlkClZRS1ZpVzY4OXRWMUlVWmpUd0UyNWU4UG9LUHE1TnI2bGNuQU83akpqdzN2d2I5V0hyUjdtTHdjRGFJK1NsYUsKRmJva2F6dlNIVW5NSGkzWS8xZmM5Z0NQd1h6LzIrekdXbXFaaGt3ZVJBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQ==

0 commit comments

Comments
 (0)