Skip to content

Commit

Permalink
FABN-1544 Update gRPC to pure js version (#247)
Browse files Browse the repository at this point in the history
Replace the grpc package with a pure javascript implementation.
The change involves changing the grpc message building and decoding.
Include and use the generated typescript for the protobufs.

Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
  • Loading branch information
harrisob authored Jun 12, 2020
1 parent 6f29724 commit d22e1a1
Show file tree
Hide file tree
Showing 57 changed files with 93,053 additions and 27,796 deletions.
2,589 changes: 0 additions & 2,589 deletions fabric-ca-client/package-lock.json

This file was deleted.

1,261 changes: 631 additions & 630 deletions fabric-common/lib/BlockDecoder.js

Large diffs are not rendered by default.

82 changes: 56 additions & 26 deletions fabric-common/lib/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const DiscoveryService = require('./DiscoveryService.js');
const Endorsement = require('./Endorsement.js');
const Commit = require('./Commit.js');
const Query = require('./Query.js');
const fabprotos = require('fabric-protos');
const fabproto6 = require('fabric-protos');
const {checkParameter, getLogger} = require('./Utils.js');

const logger = getLogger(TYPE);
Expand Down Expand Up @@ -147,10 +147,10 @@ const Channel = class {
* @property {string} name - The name for this MSP, Typically the
* organization name. To avoid confusion the name and ID should be
* the same. This will be key to finding this MSP configuration.
* @property {string[]} organizational_unit_identifiers
* @property {string[]} root_certs - List of root certificates trusted by
* @property {string[]} organizationalUnitIdentifiers
* @property {string[]} rootCerts - List of root certificates trusted by
* this MSP. They are used upon certificate validation.
* @property {string[]} intermediate_certs - List of intermediate
* @property {string[]} intermediateCerts - List of intermediate
* certificates trusted by this MSP. They are used upon certificate
* validation as follows:
* Validation attempts to build a path from the certificate to be
Expand All @@ -160,9 +160,9 @@ const Channel = class {
* searched within the Intermediate Certificates pool.
* @property {string} admins - Identity denoting the administrator
* of this MSP
* @property {string} tls_root_certs - TLS root certificates
* @property {string} tlsRootCerts - TLS root certificates
* trusted by this MSP
* @property {string} tls_intermediate_certs - TLS intermediate certificates
* @property {string} tlsIntermediateCerts - TLS intermediate certificates
* trusted by this MSP
*/

Expand Down Expand Up @@ -413,7 +413,7 @@ const Channel = class {
results.push(remote);
logger.debug(`${method} - ${type} mspid matched, added ${remote.name}`);
} else {
logger.debug(`${method} - ${type} mpsid not matched, not added ${remote.name} - ${remote.mspid}`);
logger.debug(`${method} - ${type} mspid not matched, not added ${remote.name} - ${remote.mspid}`);
}
} else {
results.push(remote);
Expand Down Expand Up @@ -470,30 +470,53 @@ const Channel = class {
}

/*
* This function will build a common channel header
*/
* This function will build a common channel header
*/
buildChannelHeader(type = checkParameter('type'), chaincode_id = checkParameter('chaincode_id'), tx_id = checkParameter('tx_id')) {
const method = `buildChannelHeader[${this.name}]`;
logger.debug(`${method} - start - type ${type} chaincode_id ${chaincode_id} tx_id ${tx_id}`);
const channelHeader = new fabprotos.common.ChannelHeader();
channelHeader.setType(type); // int32
channelHeader.setVersion(1); // int32

channelHeader.setChannelId(this.name); // string
channelHeader.setTxId(tx_id.toString()); // string
// channelHeader.setEpoch(epoch); // uint64
const chaincodeID = fabproto6.protos.ChaincodeID.create({
name: chaincode_id
});

logger.debug('%s - chaincodeID %j', method, chaincodeID);

let fields = {
chaincode_id: chaincodeID
};

let check = fabproto6.protos.ChaincodeHeaderExtension.verify(fields);
if (check) {
logger.error('%s - channel header is not valid =>%s<=', method, check);
throw Error(`Not able to build channel header ${check}`);
}

const chaincodeHeaderExtension = fabproto6.protos.ChaincodeHeaderExtension.create(fields);
const chaincodeHeaderExtensionBuf = fabproto6.protos.ChaincodeHeaderExtension.encode(chaincodeHeaderExtension).finish();

const chaincodeID = new fabprotos.protos.ChaincodeID();
chaincodeID.setName(chaincode_id);
logger.debug('%s - ChaincodeHeaderExtension %j', method, chaincodeHeaderExtensionBuf);

const headerExt = new fabprotos.protos.ChaincodeHeaderExtension();
headerExt.setChaincodeId(chaincodeID);
fields = {
type: type,
version: 1,
channel_id: this.name,
tx_id: tx_id,
extension: chaincodeHeaderExtensionBuf,
timestamp: buildCurrentTimestamp(),
tls_cert_hash: this.client.getClientCertHash()
};

channelHeader.setExtension(headerExt.toBuffer());
channelHeader.setTimestamp(buildCurrentTimestamp()); // google.protobuf.Timestamp
channelHeader.setTlsCertHash(this.client.getClientCertHash());
check = fabproto6.common.ChannelHeader.verify(fields);
if (check) {
logger.error('%s - channel header is not valid =>%s<=', method, check);
throw Error(`Not able to build channel header ${check}`);
}

const channelHeader = fabproto6.common.ChannelHeader.create(fields);
const channelHeaderBuf = fabproto6.common.ChannelHeader.encode(channelHeader).finish();

return channelHeader;
return channelHeaderBuf;
}

/**
Expand Down Expand Up @@ -521,10 +544,17 @@ const Channel = class {
};

function buildCurrentTimestamp() {
const method = `buildCurrentTimestamp[${this.name}]`;
logger.debug(`${method} - start`);
const now = new Date();
const timestamp = new fabprotos.google.protobuf.Timestamp();
timestamp.setSeconds(now.getTime() / 1000);
timestamp.setNanos((now.getTime() % 1000) * 1000000);
const seconds = parseInt(now.getTime() / 1000);
const nanos = (now.getTime() % 1000) * 1000000;
logger.debug('%s - seconds %s nanos %s', method, seconds, nanos);
const timestamp = fabproto6.google.protobuf.Timestamp.create({
seconds: seconds,
nanos: nanos
});

return timestamp;
}

Expand Down
74 changes: 47 additions & 27 deletions fabric-common/lib/Commit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ const {checkParameter, getLogger} = require('./Utils.js');
const logger = getLogger(TYPE);

const Proposal = require('./Proposal.js');
const fabprotos = require('fabric-protos');

const fabproto6 = require('fabric-protos');

/**
* @classdesc
Expand Down Expand Up @@ -71,11 +70,11 @@ class Commit extends Proposal {
this._reset();
const endorsements = [];
for (const proposalResponse of this._endorsement._proposalResponses) {

logger.debug('proposalResponse is:', proposalResponse.status);

if (proposalResponse && proposalResponse.response && proposalResponse.endorsement) {
logger.debug('%s - proposalResponse endorsement added to commit:', method, proposalResponse.status);
endorsements.push(proposalResponse.endorsement);
} else {
logger.debug('%s - proposalResponse endorsement not added to commit:', method, proposalResponse.status);
}
}

Expand All @@ -85,38 +84,59 @@ class Commit extends Proposal {
}
const proposalResponse = this._endorsement._proposalResponses[0];

const chaincodeEndorsedAction = new fabprotos.protos.ChaincodeEndorsedAction();
chaincodeEndorsedAction.setProposalResponsePayload(proposalResponse.payload);
chaincodeEndorsedAction.setEndorsements(endorsements);

const chaincodeActionPayload = new fabprotos.protos.ChaincodeActionPayload();
chaincodeActionPayload.setAction(chaincodeEndorsedAction);
const chaincodeEndorsedAction = fabproto6.protos.ChaincodeEndorsedAction.create({
proposal_response_payload: proposalResponse.payload,
endorsements: endorsements
});

// the TransientMap field inside the original proposal payload is only meant for the
// endorsers to use from inside the chaincode. This must be taken out before sending
// to the committer, otherwise the transaction will be rejected by the validators when
// it compares the proposal hash calculated by the endorsers and returned in the
// proposal response, which was calculated without the TransientMap
const originalChaincodeProposalPayload = fabprotos.protos.ChaincodeProposalPayload.decode(this._endorsement._action.proposal.getPayload());
const chaincodeProposalPayloadNoTrans = new fabprotos.protos.ChaincodeProposalPayload();
chaincodeProposalPayloadNoTrans.setInput(originalChaincodeProposalPayload.input); // only set the input field, skipping the TransientMap
chaincodeActionPayload.setChaincodeProposalPayload(chaincodeProposalPayloadNoTrans.toBuffer());

const transactionAction = new fabprotos.protos.TransactionAction();
transactionAction.setHeader(this._endorsement._action.header.getSignatureHeader());
transactionAction.setPayload(chaincodeActionPayload.toBuffer());
const originalChaincodeProposalPayload = fabproto6.protos.ChaincodeProposalPayload.decode(
this._endorsement._action.proposal.payload
);
const chaincodeProposalPayloadNoTrans = fabproto6.protos.ChaincodeProposalPayload.create({
input: originalChaincodeProposalPayload.input // only set the input field, skipping the TransientMap
});

const chaincodeProposalPayloadNoTransBuf = fabproto6.protos.ChaincodeProposalPayload.encode(
chaincodeProposalPayloadNoTrans
).finish();

const chaincodeActionPayload = fabproto6.protos.ChaincodeActionPayload.create({
action: chaincodeEndorsedAction,
chaincode_proposal_payload: chaincodeProposalPayloadNoTransBuf
});
const chaincodeActionPayloadBuf = fabproto6.protos.ChaincodeActionPayload.encode(
chaincodeActionPayload
).finish();

const transactionAction = fabproto6.protos.TransactionAction.create({
header: this._endorsement._action.header.signature_header,
payload: chaincodeActionPayloadBuf
});

const actions = [];
actions.push(transactionAction);

const transaction = new fabprotos.protos.Transaction();
transaction.setActions(actions);

this._action.payload = new fabprotos.common.Payload();
this._action.payload.setHeader(this._endorsement._action.header);
this._action.payload.setData(transaction.toBuffer());
this._payload = this._action.payload.toBuffer();

const transaction = fabproto6.protos.Transaction.create({
actions: actions
});
const transactionBuf = fabproto6.protos.Transaction.encode(
transaction
).finish();

this._action.payload = fabproto6.common.Payload.create({
header: this._endorsement._action.header,
data: transactionBuf
});
this._payload = fabproto6.common.Payload.encode(
this._action.payload
).finish();

logger.debug('%s - end - %s', method, idContext.name);
return this._payload;
}

Expand Down
12 changes: 9 additions & 3 deletions fabric-common/lib/Committer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const TYPE = 'Committer';
const {checkParameter, getLogger} = require('./Utils.js');
const ServiceEndpoint = require('./ServiceEndpoint');

const fabprotos = require('fabric-protos');
const fabproto6 = require('fabric-protos');
const logger = getLogger(TYPE);

/**
Expand Down Expand Up @@ -79,7 +79,7 @@ class Committer extends ServiceEndpoint {
this.mspid = mspid;
this.type = TYPE;

this.serviceClass = fabprotos.orderer.AtomicBroadcast;
this.serviceClass = fabproto6.services.orderer.AtomicBroadcast;
}

/**
Expand Down Expand Up @@ -132,13 +132,19 @@ class Committer extends ServiceEndpoint {
}, rto);

broadcast.on('data', (response) => {
logger.debug(`${method} - on data response: ${response}`);
logger.debug('%s - on data response: %j', method, response);
broadcast.end();
if (response && response.info) {
logger.debug(`${method} - response info :: ${response.info}`);
}
if (response && response.status) {
logger.debug(`${method} - response status ${response.status}`);
// convert to string enum (depending on how the protobuf code has been gennerated)
if (typeof response.status === 'number') {
response.status = fabproto6.common.Status[response.status];
}
logger.debug('%s - on data response: %j', method, response);

return resolve(response);
} else {
logger.error(`${this.name} ERROR - ${method} reject with invalid response from the committer`);
Expand Down
4 changes: 2 additions & 2 deletions fabric-common/lib/Discoverer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const TYPE = 'Discoverer';

const {checkParameter, getLogger} = require('./Utils.js');
const ServiceEndpoint = require('./ServiceEndpoint');
const fabprotos = require('fabric-protos');
const fabproto6 = require('fabric-protos').services;

const logger = getLogger(TYPE);

Expand All @@ -33,7 +33,7 @@ class Discoverer extends ServiceEndpoint {
super(name, client, mspid);

this.type = TYPE;
this.serviceClass = fabprotos.discovery.Discovery;
this.serviceClass = fabproto6.discovery.Discovery;
}

/**
Expand Down
26 changes: 13 additions & 13 deletions fabric-common/lib/DiscoveryHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ class DiscoveryHandler extends ServiceHandler {
for (const group_name in endorsement_plan.groups) {
const group = endorsement_plan.groups[group_name];
for (const peer of group.peers) {
peer.ledger_height = new Long(peer.ledger_height.low, peer.ledger_height.high);
peer.ledgerHeight = new Long(peer.ledgerHeight.low, peer.ledgerHeight.high);
}
// remove ignored and non-required
const clean_list = this._removePeers(ignored, ignored_orgs, required, required_orgs, group.peers);
Expand Down Expand Up @@ -465,8 +465,8 @@ class DiscoveryHandler extends ServiceHandler {
let highest = Long.fromValue(0);
for (const peer of peers) {
try {
if (peer.ledger_height.greaterThan(highest)) {
highest = peer.ledger_height;
if (peer.ledgerHeight.greaterThan(highest)) {
highest = peer.ledgerHeight;
}
} catch (error) {
logger.error('problem finding highest block with %s', error);
Expand All @@ -486,17 +486,17 @@ class DiscoveryHandler extends ServiceHandler {
if (sort === BLOCK_HEIGHT) {
sorted = peers.sort((a, b) => {
logger.debug('%s - sorting descending', method);
if (a.ledger_height && !b.ledger_height) {
logger.debug('%s - a exist (%s) - b does not exist', method, a.ledger_height);
if (a.ledgerHeight && !b.ledgerHeight) {
logger.debug('%s - a exist (%s) - b does not exist', method, a.ledgerHeight);

return -1;
} else if (!a.ledger_height && b.ledger_height) {
logger.debug('%s - a does not exist - b exist (%s)', method, b.ledger_height);
} else if (!a.ledgerHeight && b.ledgerHeight) {
logger.debug('%s - a does not exist - b exist (%s)', method, b.ledgerHeight);

return 1;
} else {
const result = -1 * a.ledger_height.compare(b.ledger_height);
logger.debug('%s - compare result: %s for a:(%s) b:(%s) ', method, result, a.ledger_height.toString(), b.ledger_height.toString());
const result = -1 * a.ledgerHeight.compare(b.ledgerHeight);
logger.debug('%s - compare result: %s for a:(%s) b:(%s) ', method, result, a.ledgerHeight.toString(), b.ledgerHeight.toString());

return result;
}
Expand Down Expand Up @@ -535,18 +535,18 @@ class DiscoveryHandler extends ServiceHandler {
// because it has a low gap, meaning it should be up to date on with ledger
// changes compared with other peers
if (!found && highest && preferred_height_gap) {
if (peer.ledger_height) {
if (peer.ledgerHeight) {
logger.debug('%s - checking preferred gap of %s', method, preferred_height_gap);
logger.debug('%s - peer.ledger_height %s', method, peer.ledger_height);
if (highest.subtract(peer.ledger_height).greaterThan(preferred_height_gap)) {
logger.debug('%s - peer.ledgerHeight %s', method, peer.ledgerHeight);
if (highest.subtract(peer.ledgerHeight).greaterThan(preferred_height_gap)) {
found = false; // this peer should not be on the priority list
logger.debug('%s -gap too big, peer should not be on priority list', method, peer.name);
} else {
found = true; // this peer should not be on the priority list
logger.debug('%s - gap is OK, peer should be on priority list', method, peer.name);
}
} else {
logger.debug('%s - peer has no ledger_height, not a priority peer');
logger.debug('%s - peer has no ledgerHeight, not a priority peer');
found = false;
}

Expand Down
Loading

0 comments on commit d22e1a1

Please sign in to comment.