diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/app.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/app.ts index 7a1c5cd76d..08fc10de66 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/app.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/app.ts @@ -32,7 +32,7 @@ app.use( err: { message: string; status?: number }, req: Request, res: Response, - next: NextFunction + next: NextFunction, ) => { // set locals, only providing error in development res.locals.message = err.message; @@ -47,7 +47,7 @@ app.use( // render the error page res.status(err.status || 500); res.send(err); - } + }, ); export default app; diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/bin/www.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/bin/www.ts index e7e5e1e07b..ac386726ac 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/bin/www.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/common/core/bin/www.ts @@ -69,7 +69,7 @@ server.on("listening", onListening); * Normalize a port into a number, string, or false. */ -function normalizePort(val) { +function normalizePort(val: string) { const port = parseInt(val, 10); if (isNaN(port)) { @@ -89,7 +89,7 @@ function normalizePort(val) { * Event listener for HTTPS server "error" event. */ -function onError(error) { +function onError(error: any) { if (error.syscall !== "listen") { throw error; } @@ -118,6 +118,12 @@ function onError(error) { function onListening() { const addr = server.address(); + + if (!addr) { + logger.error("Could not get running server address - exit."); + process.exit(1); + } + const bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; debug("Listening on " + bind); } @@ -148,14 +154,14 @@ io.on("connection", function (client) { // Check for the existence of the specified function and call it if it exists. if (Splug.isExistFunction(func)) { // Can be called with Server plugin function name. - Splug[func](args) - .then((respObj) => { + (Splug as any)[func](args) + .then((respObj: unknown) => { logger.info("*** RESPONSE ***"); logger.info("Client ID :" + client.id); logger.info("Response :" + JSON.stringify(respObj)); client.emit("response", respObj); }) - .catch((errObj) => { + .catch((errObj: unknown) => { logger.error("*** ERROR ***"); logger.error("Client ID :" + client.id); logger.error("Detail :" + JSON.stringify(errObj)); @@ -175,14 +181,17 @@ io.on("connection", function (client) { client.on("request2", function (data) { const func = data.method.method; - const args = {}; - args["contract"] = data.contract; - args["method"] = data.method; - args["args"] = data.args; + let args: Record = { + contract: data.contract, + method: data.method, + args: data.args, + }; + if (data.reqID !== undefined) { logger.info(`##add reqID: ${data.reqID}`); args["reqID"] = data.reqID; } + logger.info("##[HL-BC] Invoke smart contract to transfer asset(D1)"); logger.info("*** REQUEST ***"); logger.info("Client ID :" + client.id); @@ -228,14 +237,14 @@ io.on("connection", function (client) { // logger.info(`##args: ${JSON.stringify(args)}`); if (Splug.isExistFunction(func)) { // Can be called with Server plugin function name. - Splug[func](args) - .then((respObj) => { + (Splug as any)[func](args) + .then((respObj: unknown) => { logger.info("*** RESPONSE ***"); logger.info("Client ID :" + client.id); logger.info("Response :" + JSON.stringify(respObj)); client.emit("response", respObj); }) - .catch((errObj) => { + .catch((errObj: unknown) => { logger.error("*** ERROR ***"); logger.error("Client ID :" + client.id); logger.error("Detail :" + JSON.stringify(errObj)); @@ -268,7 +277,7 @@ io.on("connection", function (client) { **/ client.on("startMonitor", function () { // Callback to receive monitoring results - const cb = function (callbackData) { + const cb = function (callbackData: Record) { let emitType = ""; if (callbackData.status == 200) { emitType = "eventReceived"; diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts index 3b34356b6d..13fa736d4b 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts @@ -28,20 +28,19 @@ logger.level = config.read("logLevel", "info"); import { ValidatorAuthentication } from "./ValidatorAuthentication"; import safeStringify from "fast-safe-stringify"; +export type MonitorCallback = (callback: { + status: number; + blockData?: string; + errorDetail?: string; +}) => void; + /* * ServerMonitorPlugin * Server monitoring class definition */ export class ServerMonitorPlugin { - _filterTable: object; - _eh: FabricClient.ChannelEventHub; - - constructor() { - // Define settings specific to the dependent part - // Initializing filter during monitoring - this._filterTable = {}; - this._eh = null; - } + _filterTable = new Map(); + _eh?: FabricClient.ChannelEventHub; /* * startMonitor @@ -50,17 +49,17 @@ export class ServerMonitorPlugin { * @param {function} cb : Callback function that receives the monitoring result at any time * @note Always listens on the first peer from config. */ - startMonitor(clientId, cb) { + startMonitor(clientId: string, cb: MonitorCallback) { logger.info("*** START MONITOR ***"); logger.info("Client ID :" + clientId); - const filter = this._filterTable[clientId]; - let channel: FabricClient.Channel = null; + const filter = this._filterTable.get(clientId); + let channel: FabricClient.Channel; if (!filter) { getClientAndChannel() .then((retobj) => { channel = retobj.channel; //Set the returned channel - this._filterTable[clientId] = retobj.client; + this._filterTable.set(clientId, retobj.client); return getSubmitterAndEnroll(retobj.client); }) .then(() => { @@ -69,9 +68,17 @@ export class ServerMonitorPlugin { ); logger.info("Connecting the event hub"); this._eh.registerBlockEvent( - (block: FabricClient.Block) => { + (block) => { const txlist = []; logger.info("*** Block Event ***"); + + if (!("header" in block && "data" in block)) { + logger.warn( + "Invalid block type fromregisterBlockEvent - expected FabricClient.Block", + ); + return; + } + console.log("##[HL-BC] Notify new block data(D2)"); logger.info( "chain id :" + config.read("fabric.channelName"), @@ -160,8 +167,8 @@ export class ServerMonitorPlugin { * Stop monitoring * @param {string} clientId : Client ID of the monitoring stop request source */ - stopMonitor(clientId) { - const filter = this._filterTable[clientId]; + stopMonitor(clientId: string) { + const filter = this._filterTable.get(clientId); if (filter) { // Stop filter & remove from table @@ -173,7 +180,7 @@ export class ServerMonitorPlugin { logger.info("Disconnecting the event hub"); this._eh.disconnect(); } - delete this._filterTable[clientId]; + this._filterTable.delete(clientId); } } } diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerPlugin.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerPlugin.ts index 5e399dd8fd..63a2604abc 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerPlugin.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerPlugin.ts @@ -21,7 +21,7 @@ import { ValidatorAuthentication } from "./ValidatorAuthentication"; // Read the library, SDK, etc. according to EC specifications as needed import { getClientAndChannel, getSubmitterAndEnroll } from "./fabricaccess.js"; -import { ProposalRequest } from "fabric-client"; +import Client, { ProposalRequest } from "fabric-client"; import safeStringify from "fast-safe-stringify"; const path = require("path"); @@ -61,8 +61,8 @@ export class ServerPlugin { * Make sure that the support status of your class can be determined by your class. * Functions that you do not want to call directly need to be devised such as implemented outside of this class like utilities. */ - isExistFunction(funcName) { - if (this[funcName] != undefined) { + isExistFunction(funcName: string) { + if ((this as any)[funcName]) { return true; } else { return false; @@ -93,11 +93,11 @@ export class ServerPlugin { * } * @return {Object} JSON object */ - contractTransaction(args) { + contractTransaction(args: any) { return new Promise((resolve, reject) => { logger.info("evaluateTransaction start"); // logger.debug(`##evaluateTransaction(A)`); - let retObj = {}; + let retObj: Record; let reqID = args["reqID"]; if (reqID === undefined) { reqID = null; @@ -177,7 +177,7 @@ export class ServerPlugin { * } * @return {Object} JSON object */ - sendSignedTransaction(args) { + sendSignedTransaction(args: any) { return new Promise((resolve, reject) => { logger.info("sendSignedTransaction start"); let retObj = {}; @@ -243,10 +243,10 @@ export class ServerPlugin { * } * @return {Object} JSON object */ - sendSignedProposal(args) { + sendSignedProposal(args: any) { return new Promise((resolve, reject) => { logger.info("sendSignedProposal start"); - let retObj = {}; + let retObj: Record; const channelName = args.contract.channelName; const transactionProposalReq = args.args.args.transactionProposalReq; @@ -305,7 +305,7 @@ export class ServerPlugin { * @return [string] Success: Chain code execution result * Failure: Chain code error or internal error */ -async function Invoke(reqBody) { +async function Invoke(reqBody: any) { let txId = null; const theUser = null; const eventhubs = []; @@ -375,7 +375,7 @@ async function Invoke(reqBody) { * @return [string] Success: Chain code execution result * Failure: Chain code error or internal error */ -async function InvokeSync(reqBody) { +async function InvokeSync(reqBody: any) { return new Promise(async function (resolve, reject) { try { logger.info("##fablicaccess: InvokeSync start"); @@ -387,7 +387,9 @@ async function InvokeSync(reqBody) { // Create a new file system based wallet for managing identities. // logger.debug(`##InvokeSync(B)`); - const wallet = new FileSystemWallet(config.read("fabric.keystore")); + const wallet = new FileSystemWallet( + config.read("fabric.keystore"), + ); console.log(`Wallet path: ${config.read("fabric.keystore")}`); // Check to see if we've already enrolled the user. @@ -502,7 +504,7 @@ async function InvokeSync(reqBody) { // BEGIN Signature process===================================================================================== // this ordersForCurve comes from CryptoSuite_ECDSA_AES.js and will be part of the // stand alone fabric-sig package in future. -const ordersForCurve = { +const ordersForCurve: Record = { secp256r1: { halfOrder: elliptic.curves.p256.n.shrn(1), order: elliptic.curves.p256.n, @@ -515,7 +517,7 @@ const ordersForCurve = { // this function comes from CryptoSuite_ECDSA_AES.js and will be part of the // stand alone fabric-sig package in future. -function preventMalleability(sig, curveParams) { +function preventMalleability(sig: any, curveParams: { name: string }) { const halfOrder = ordersForCurve[curveParams.name].halfOrder; if (!halfOrder) { throw new Error( @@ -543,7 +545,12 @@ function preventMalleability(sig, curveParams) { * @param {string} privateKey PEM encoded private key * @param {Buffer} proposalBytes proposal bytes */ -function sign(privateKey, proposalBytes, algorithm, keySize) { +function sign( + privateKey: string, + proposalBytes: Buffer, + algorithm: string, + keySize: number, +) { const hashAlgorithm = algorithm.toUpperCase(); const hashFunction = hash[`${hashAlgorithm}_${keySize}`]; const ecdsaCurve = elliptic.curves[`p${keySize}`]; @@ -559,7 +566,7 @@ function sign(privateKey, proposalBytes, algorithm, keySize) { return Buffer.from(sig.toDER()); } -function signProposal(proposalBytes, paramPrivateKeyPem) { +function signProposal(proposalBytes: Buffer, paramPrivateKeyPem: string) { logger.debug("signProposal start"); const signature = sign(paramPrivateKeyPem, proposalBytes, "sha2", 256); @@ -574,7 +581,7 @@ function signProposal(proposalBytes, paramPrivateKeyPem) { * @return [string] Success: Chain code execution result * Failure: Chain code error or internal error */ -async function InvokeSendSignedTransaction(reqBody) { +async function InvokeSendSignedTransaction(reqBody: any) { return new Promise(async function (resolve, reject) { logger.info("InvokeSendSignedTransaction start"); @@ -591,7 +598,8 @@ async function InvokeSendSignedTransaction(reqBody) { const response = await channel.sendSignedTransaction({ signedProposal: reqBody.signedCommitProposal, request: reqBody.commitReq, - }); + } as any); + // logger.debug(`##InvokeSendSignedTransaction: (B)`); logger.info("successfully send signedCommitProposal"); // logger.info("response : " + JSON.stringify(response)); @@ -634,7 +642,9 @@ async function InvokeSendSignedProposal( // Low-level access to local-store cert and private key of submitter (in case request is missing those) if (!certPem || !privateKeyPem) { const wallet = new FileSystemWallet(config.read("fabric.keystore")); - logger.debug(`Wallet path: ${path.resolve(config.read("fabric.keystore"))}`); + logger.debug( + `Wallet path: ${path.resolve(config.read("fabric.keystore"))}`, + ); const submitterName = user.getName(); const submitterExists = await wallet.exists(submitterName); @@ -649,11 +659,16 @@ async function InvokeSendSignedProposal( } } + if (!certPem || !privateKeyPem) { + throw Error("Could not read certificate and private key of the submitter."); + } + const { proposal, txId } = channel.generateUnsignedProposal( transactionProposalReq, config.read("fabric.mspid"), certPem, - ); + false, + ) as any; logger.debug(`##InvokeSendSignedProposal; txId: ${txId.getTransactionID()}`); const signedProposal = signProposal(proposal.toBuffer(), privateKeyPem); @@ -662,7 +677,7 @@ async function InvokeSendSignedProposal( const peer = channel.getPeer(peerInfo.requests.split("//")[1]); targets.push(peer); } - const sendSignedProposalReq = { signedProposal, targets } as unknown; + const sendSignedProposalReq = { signedProposal, targets } as any; const proposalResponses = await channel.sendSignedProposal( sendSignedProposalReq, ); @@ -671,13 +686,14 @@ async function InvokeSendSignedProposal( let allGood = true; for (const proposalResponse of proposalResponses) { let oneGood = false; + const propResponse = (proposalResponse as unknown) as Client.ProposalResponse; if ( - proposalResponses && - proposalResponse.response && - proposalResponse.response.status === 200 + propResponse && + propResponse.response && + propResponse.response.status === 200 ) { - if (proposalResponse.response.payload) { - invokeResponse2 = proposalResponse.response.payload; + if (propResponse.response.payload) { + invokeResponse2 = propResponse.response.payload; } oneGood = true; } else { @@ -690,7 +706,7 @@ async function InvokeSendSignedProposal( } // If the return value of invoke is an empty string, store txID - if (invokeResponse2 === "") { + if (!invokeResponse2 || invokeResponse2.length == 0) { invokeResponse2 = txId.getTransactionID(); } @@ -711,7 +727,9 @@ async function InvokeSendSignedProposal( proposal, }; - const commitProposal = channel.generateUnsignedTransaction(commitReq); + const commitProposal = await channel.generateUnsignedTransaction( + commitReq as any, + ); logger.debug( `##InvokeSendSignedProposal: Successfully build commit transaction proposal`, ); diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabricaccess.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabricaccess.ts index 9768b13abe..b6e389ca56 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabricaccess.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabricaccess.ts @@ -20,7 +20,7 @@ import FabricClient, { User } from "fabric-client"; import copService, { TLSOptions } from "fabric-ca-client"; // list of fabric-client objects -const clients = {}; +const clients = new Map(); // Log settings import { getLogger } from "log4js"; @@ -95,11 +95,11 @@ export async function getClientAndChannel( logger.info("##fabricaccess_getClientAndChannel"); // Since only one KVS can be set in the client, management in CA units as well as KVS path let isNewClient = false; - let client = clients[config.read("fabric.ca.name")]; + let client = clients.get(config.read("fabric.ca.name")); if (!client) { logger.info("create new fabric-client"); client = new FabricClient(); - clients[config.read("fabric.ca.name")] = client; + clients.set(config.read("fabric.ca.name"), client); isNewClient = true; } @@ -162,4 +162,4 @@ export async function getClientAndChannel( } return { client, channel }; -} \ No newline at end of file +} diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/tsconfig.json b/packages/cactus-plugin-ledger-connector-fabric-socketio/tsconfig.json index b8299b35b9..ae07705b86 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/tsconfig.json +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/tsconfig.json @@ -4,11 +4,7 @@ "rootDir": "./src/main/typescript", "composite": true, "outDir": "./dist", - "sourceMap": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "tsBuildInfoFile": "../../.build-cache/cactus-plugin-ledger-connector-fabric-socketio.tsbuildinfo", - "strict": false // TODO - True, fix warnings + "tsBuildInfoFile": "../../.build-cache/cactus-plugin-ledger-connector-fabric-socketio.tsbuildinfo" }, "include": [ "./src/main/typescript/common/core/*.ts",