diff --git a/examples/cactus-example-cbdc-bridging-backend/package.json b/examples/cactus-example-cbdc-bridging-backend/package.json index 10617a652d2..c249c96a243 100644 --- a/examples/cactus-example-cbdc-bridging-backend/package.json +++ b/examples/cactus-example-cbdc-bridging-backend/package.json @@ -73,7 +73,7 @@ "axios": "^0.27.2", "crypto-js": "4.1.1", "dotenv": "^16.0.1", - "fabric-network": "2.2.10", + "fabric-network": "2.2.18", "fs-extra": "10.1.0", "ipfs-http-client": "51.0.1", "knex": "2.5.1", diff --git a/examples/cactus-example-discounted-asset-trade/package.json b/examples/cactus-example-discounted-asset-trade/package.json index 708548c8332..717f295ed6b 100644 --- a/examples/cactus-example-discounted-asset-trade/package.json +++ b/examples/cactus-example-discounted-asset-trade/package.json @@ -28,9 +28,7 @@ "ethereumjs-common": "1.5.2", "ethereumjs-tx": "2.1.2", "express": "4.16.4", - "fabric-ca-client": "1.4.19", - "fabric-client": "1.4.19", - "fabric-network": "1.4.19", + "fabric-network": "2.2.18", "http-errors": "1.6.3", "jsonwebtoken": "9.0.0", "jsrsasign": "10.5.25", diff --git a/examples/cactus-example-discounted-asset-trade/transaction-fabric.ts b/examples/cactus-example-discounted-asset-trade/transaction-fabric.ts index 662b43b7190..250660f957c 100644 --- a/examples/cactus-example-discounted-asset-trade/transaction-fabric.ts +++ b/examples/cactus-example-discounted-asset-trade/transaction-fabric.ts @@ -20,7 +20,7 @@ import { ISocketApiClient } from "@hyperledger/cactus-core-api"; import { Verifier } from "@hyperledger/cactus-verifier-client"; import { signProposal } from "./sign-utils"; -import { FileSystemWallet } from "fabric-network"; +import { Wallets } from "fabric-network"; const config: any = ConfigUtil.getConfig(); import { getLogger } from "log4js"; @@ -50,14 +50,13 @@ export function makeSignedProposal>( let certPem = undefined; let privateKeyPem = undefined; const submitter = config.assetTradeInfo.fabric.submitter.name; - const wallet = new FileSystemWallet( + const wallet = await Wallets.newFileSystemWallet( config.assetTradeInfo.fabric.keystore, ); logger.debug(`Wallet path: ${config.assetTradeInfo.fabric.keystore}`); - const submitterExists = await wallet.exists(submitter); - if (submitterExists) { - const submitterIdentity = await wallet.export(submitter); + const submitterIdentity = await wallet.get(submitter); + if (submitterIdentity) { certPem = (submitterIdentity as any).certificate; privateKeyPem = (submitterIdentity as any).privateKey; } diff --git a/packages/cactus-cmd-api-server/package.json b/packages/cactus-cmd-api-server/package.json index 4f7c28041c3..2d99f138548 100644 --- a/packages/cactus-cmd-api-server/package.json +++ b/packages/cactus-cmd-api-server/package.json @@ -58,7 +58,7 @@ "webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js" }, "dependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "@hyperledger/cactus-common": "2.0.0-alpha.2", "@hyperledger/cactus-core": "2.0.0-alpha.2", diff --git a/packages/cactus-cmd-socketio-server/package.json b/packages/cactus-cmd-socketio-server/package.json index 108143ddf2f..bf28ae9aa67 100644 --- a/packages/cactus-cmd-socketio-server/package.json +++ b/packages/cactus-cmd-socketio-server/package.json @@ -53,8 +53,7 @@ "ethereumjs-common": "1.5.2", "ethereumjs-tx": "2.1.2", "express": "4.16.4", - "fabric-ca-client": "1.4.19", - "fabric-network": "1.4.19", + "fabric-network": "2.2.18", "http-errors": "1.6.3", "js-yaml": "3.14.1", "jsonwebtoken": "9.0.0", diff --git a/packages/cactus-core-api/package.json b/packages/cactus-core-api/package.json index d165d14adf3..0dd7be80098 100644 --- a/packages/cactus-core-api/package.json +++ b/packages/cactus-core-api/package.json @@ -63,7 +63,7 @@ "axios": "0.21.4" }, "devDependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "@types/express": "4.17.13", "@types/google-protobuf": "3.15.5", diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/package.json b/packages/cactus-plugin-ledger-connector-fabric-socketio/package.json index 7e2a19a10f8..144c670ca57 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/package.json +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/package.json @@ -14,6 +14,7 @@ "start": "cd ./dist && node common/core/bin/www.js" }, "dependencies": { + "@grpc/grpc-js": "1.9.5", "@hyperledger/cactus-cmd-socketio-server": "2.0.0-alpha.2", "@hyperledger/cactus-common": "2.0.0-alpha.2", "@types/node": "14.18.54", @@ -21,11 +22,9 @@ "cookie-parser": "1.4.6", "debug": "3.1.0", "express": "4.17.3", - "fabric-ca-client": "1.4.19", - "fabric-client": "1.4.19", - "fabric-network": "1.4.19", + "fabric-ca-client": "2.2.18", + "fabric-network": "2.2.18", "fs-extra": "10.1.0", - "grpc": "1.24.11", "js-yaml": "3.14.1", "jsonwebtoken": "9.0.0", "lodash": "4.17.21", 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 0193c687acb..d5d5ee5192b 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 @@ -29,274 +29,7 @@ import { getLogger } from "log4js"; const logger = getLogger("connector_main[" + process.pid + "]"); logger.level = configRead('logLevel', 'info'); -// implementation class of a part dependent of end-chains (server plugin) -import { ServerPlugin } from "../../../connector/ServerPlugin"; - -// destination dependency (MONITOR) implementation class -import { ServerMonitorPlugin } from "../../../connector/ServerMonitorPlugin"; - -export async function startFabricSocketIOConnector() { - const Splug = new ServerPlugin(); - const Smonitor = new ServerMonitorPlugin(); - - // Get port from environment and store in Express. - const sslport = normalizePort(process.env.PORT || configRead('sslParam.port')); - app.set("port", sslport); - - // Specify private key and certificate - let keyString: string; - let certString: string; - try { - keyString = configRead('sslParam.keyValue'); - certString = configRead('sslParam.certValue'); - } catch { - keyString = fs.readFileSync(configRead('sslParam.key'), "ascii"); - certString = fs.readFileSync(configRead('sslParam.cert'), "ascii"); - } - - // Create HTTPS server. - const server = https.createServer({ - key: keyString, - cert: certString, - }, app); // Start as an https server. - const io = new Server(server); - - // Event listener for HTTPS server "error" event. - server.on("error", (error: any) => { - if (error.syscall !== "listen") { - throw error; - } - - const bind = - typeof sslport === "string" ? "Pipe " + sslport : "Port " + sslport; - - // handle specific listen errors with friendly messages - switch (error.code) { - case "EACCES": - logger.error(bind + " requires elevated privileges"); - process.exit(1); - break; - case "EADDRINUSE": - logger.error(bind + " is already in use"); - process.exit(1); - break; - default: - throw error; - } - }); - - io.on("connection", function (client) { - logger.info("Client " + client.id + " connected."); - - /** - * request: The server plugin's request to execute a function - * @param {JSON} data: Request Body (following format) - * JSON: { - * "func": (string) Function name ,// For example : "transferNumericAsset" - * "args": (Object) argument// for example , {"from" : "xxx" , "to" : "yyy" , "value" : "10,000"} - * } - **/ - client.on("request", function (data) { - const func = data.func; - const 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); - logger.info("Data :" + JSON.stringify(data)); - - // 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 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: unknown) => { - logger.error("*** ERROR ***"); - logger.error("Client ID :" + client.id); - logger.error("Detail :" + JSON.stringify(errObj)); - client.emit("connector_error", errObj); - }); - } else { - // No such function - const emsg = "Function " + func + " not found!"; - logger.error(emsg); - const retObj = { - status: 504, - errorDetail: emsg, - }; - client.emit("connector_error", retObj); - } - }); - - client.on("request2", function (data) { - const func = data.method.method; - 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); - logger.info("Data :" + JSON.stringify(data)); - - // Check for the presence of a request ID. - if ( - data.method.type === "evaluateTransaction" || - data.method.type === "submitTransaction" - ) { - // Call a synchronous method. - Splug.contractTransaction(args) - .then((respObj) => { - logger.info("*** RESPONSE ***"); - logger.info("Client ID :" + client.id); - logger.info("Response :" + JSON.stringify(respObj)); - client.emit("response", respObj); - }) - .catch((errObj) => { - logger.error("*** ERROR ***"); - logger.error("Client ID :" + client.id); - logger.error("Detail :" + JSON.stringify(errObj)); - client.emit("connector_error", errObj); - }); - } else if (data.method.type === "sendSignedTransaction") { - // Call an asynchronous method. - Splug.sendSignedTransaction(args) - .then((respObj) => { - logger.info("*** RESPONSE ***"); - logger.info("Client ID :" + client.id); - logger.info("Response :" + JSON.stringify(respObj)); - client.emit("response", respObj); - }) - .catch((errObj) => { - logger.error("*** ERROR ***"); - logger.error("Client ID :" + client.id); - logger.error("Detail :" + JSON.stringify(errObj)); - client.emit("connector_error", errObj); - }); - } else if (data.method.type === "function") { - const func = args["method"].command; - logger.info(`##method.type: function, function: ${func}`); - // logger.info(`##args: ${JSON.stringify(args)}`); - if (Splug.isExistFunction(func)) { - // Can be called with Server plugin function name. - (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: unknown) => { - logger.error("*** ERROR ***"); - logger.error("Client ID :" + client.id); - logger.error("Detail :" + JSON.stringify(errObj)); - client.emit("connector_error", errObj); - }); - } else { - // No such function - const emsg = "Function " + func + " not found!"; - logger.error(emsg); - const retObj = { - status: 504, - errorDetail: emsg, - }; - client.emit("connector_error", retObj); - } - } else { - // No such function - const emsg = "Function " + func + " not found!"; - logger.error(emsg); - const retObj = { - status: 504, - errorDetail: emsg, - }; - client.emit("connector_error", retObj); - } - }); - - /** - * startMonitor: starting block generation event monitoring - **/ - client.on("startMonitor", function () { - Smonitor.startMonitor(client.id, (event) => { - let emitType = ""; - - if (event.status == 200) { - emitType = "eventReceived"; - logger.info("event data callbacked."); - } else { - emitType = "monitor_error"; - } - - client.emit(emitType, event); - }); - }); - - /** - * stopMonitor: block generation events monitoring stopping - **/ - // I think it is more common to stop from the disconnect described later, but I will prepare for it. - client.on("stopMonitor", function (reason) { - Smonitor.stopMonitor(client.id); - }); - - client.on("disconnect", function (reason) { - // Unexpected disconnect as well as explicit disconnect request can be received here - logger.info("Client " + client.id + " disconnected."); - logger.info("Reason :" + reason); - // Stop monitoring if disconnected client is for event monitoring - Smonitor.stopMonitor(client.id); - }); - }); - - // Listen on provided port, on all network interfaces. - return new Promise((resolve) => server.listen(sslport, () => resolve(server))); -}; - -// Normalize a port into a number, string, or false. -function normalizePort(val: string) { - const port = parseInt(val, 10); - - if (isNaN(port)) { - // named pipe - return val; - } - - if (port >= 0) { - // port number - return port; - } - - return false; -} - -if (require.main === module) { - // When this file executed as a script, not loaded as module - run the connector - startFabricSocketIOConnector().then((server) => { - 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; - logger.debug("Listening on " + bind); - }).catch((err) => { - logger.error("Could not start fabric-socketio connector:", err); - }); +export async function startFabricSocketIOConnector(): Promise { + throw new Error("Not implemented. Code here was removed due to security" + + " reasons (dependence on legacy versions grpc and Fabric)."); } 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 deleted file mode 100644 index be757d199b7..00000000000 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2021 Hyperledger Cactus Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * ServerMonitorPlugin.js - */ - -/* - * Summary: - * Monitoring class of connection destination dependent part of linkage server - * Used when performing continuous monitoring. - * Processing that ends with reception of a single event is supported by implementing a unique function in ServerPlugin. - * Unlike ServerPlugin, it does not basically handle its own functions. - */ - -// Basic package dependency declaration -const process = require("process"); -import FabricClient from "fabric-client"; -// IF declaration for fabric -import { getClientAndChannel, getSubmitterAndEnroll } from "./fabricaccess"; -// config file -import { - configRead, - signMessageJwt, -} from "@hyperledger/cactus-cmd-socketio-server"; -// Log settings -import { getLogger } from "log4js"; -const logger = getLogger("ServerMonitorPlugin[" + process.pid + "]"); -logger.level = configRead("logLevel", "info"); -// utility -import { safeStringifyException } from "@hyperledger/cactus-common"; - -export type MonitorCallback = (callback: { - status: number; - blockData?: string; - errorDetail?: string; -}) => void; - -/* - * ServerMonitorPlugin - * Server monitoring class definition - */ -export class ServerMonitorPlugin { - _filterTable = new Map(); - _eh?: FabricClient.ChannelEventHub; - - /* - * startMonitor - * Start monitoring - * @param {string} clientId : Client ID of the monitoring start request source - * @param {function} cb : Callback function that receives the monitoring result at any time - * @note Always listens on the first peer from config. - */ - startMonitor(clientId: string, cb: MonitorCallback) { - logger.info("*** START MONITOR ***"); - logger.info("Client ID :" + clientId); - const filter = this._filterTable.get(clientId); - let channel: FabricClient.Channel; - - if (!filter) { - getClientAndChannel() - .then((retobj) => { - channel = retobj.channel; //Set the returned channel - this._filterTable.set(clientId, retobj.client); - return getSubmitterAndEnroll(retobj.client); - }) - .then(() => { - this._eh = channel.newChannelEventHub( - channel.getPeers()[0].getPeer(), - ); - logger.info("Connecting the event hub"); - this._eh.registerBlockEvent( - (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 :" + configRead("fabric.channelName"), - ); - logger.info("blocknumber : " + block.header.number); - const len = block.data.data.length; - logger.info("data.data.length :" + len); - console.log("##[HL-BC] Validate transactions(D3)"); - console.log("##[HL-BC] digital sign on valid transaction(D4)"); - for (let i = 0; i < len; i++) { - const payload = block.data.data[i].payload; - const channel_header = payload.header.channel_header; - if (channel_header.type == 3) { - //'ENDORSER_TRANSACTION' - const txid = channel_header.tx_id; - logger.info("transaction id :" + txid); - const transaction = payload.data; - const actionPayload = transaction.actions[0].payload; - const proposalPayload = - actionPayload.chaincode_proposal_payload; - const invocationSpec = proposalPayload.input; - // Can obtain chaincode name and argument list (function name at the beginning) from invocationSpec - const ccid = invocationSpec.chaincode_spec.chaincode_id.name; - logger.info("chaincode id :" + ccid); - // Only notify transactions from the chaincode used in ServerPlugin - if (ccid == configRead("fabric.chaincodeId")) { - const args = invocationSpec.chaincode_spec.input.args; - logger.info("args.length :" + args.length); - for (let j = 0; j < args.length; j++) { - // code must be specified for toString - args[j] = args[j].toString("utf8"); - logger.info("args[" + j + "] :" + args[j]); - } - const func = args[0]; - args.shift(); - - // Interpretation of response - const resp = - actionPayload.action.proposal_response_payload.extension - .response.payload; - logger.info("resp :" + resp); - - //The transaction data should include the following. - txlist.push({ - chaincodeId: ccid, - txId: txid, - func: func, - args: args, - }); - } - } - } - logger.info("*** SEND BLOCK DATA ***"); - logger.debug(`txlist = ${JSON.stringify(txlist)}`); - const signedTxlist = signMessageJwt({ - blockData: txlist, - }); - logger.debug(`signedTxlist = ${signedTxlist}`); - const retObj = { - status: 200, - blockData: signedTxlist, - }; - cb(retObj); - }, - (err) => { - logger.warn(`Monitor error for client ${clientId} - `, err); - }, - ); - this._eh.connect(true); //fullBlock=true - }) - .catch((err) => { - logger.error(err); - const errObj = { - status: 504, - errorDetail: safeStringifyException(err), - }; - cb(errObj); - }); - } else { - logger.info("target filter has already start watching."); - } - } - - /* - * stopMonitor - * Stop monitoring - * @param {string} clientId : Client ID of the monitoring stop request source - */ - stopMonitor(clientId: string) { - const filter = this._filterTable.get(clientId); - - if (filter) { - // Stop filter & remove from table - if (this._eh == null) { - logger.error("EventHub does not exist"); - return; - } - if (this._eh.isconnected()) { - logger.info("Disconnecting the event hub"); - this._eh.disconnect(); - } - 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 deleted file mode 100644 index 6dab5b45e3c..00000000000 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/ServerPlugin.ts +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * Copyright 2021 Hyperledger Cactus Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * ServerPlugin.js - */ - -/* - * Summary: - * Dependent part of the connection destination of the connector - * Define and implement the function independently according to the connection destination dependent part (adapter) on the core side. - */ - -import path from "path"; -import Client, { - Proposal, - ProposalRequest, - ProposalResponse, - Block, -} from "fabric-client"; -import { FileSystemWallet, Gateway } from "fabric-network"; - -import { getClientAndChannel, getSubmitterAndEnroll } from "./fabricaccess"; -import { signProposal } from "./sign-utils"; -import { - ProposalSerializer, - ProposalResponseSerializer, -} from "./fabric-proto-serializers"; - -// Config reading -import { - configRead, - signMessageJwt, -} from "@hyperledger/cactus-cmd-socketio-server"; -const connUserName = configRead("fabric.connUserName"); - -// Log settings -import { getLogger } from "log4js"; -import { safeStringifyException } from "@hyperledger/cactus-common"; -const logger = getLogger("ServerPlugin[" + process.pid + "]"); -logger.level = configRead("logLevel", "info"); - -///////////////////////////// -// API call signatures -///////////////////////////// - -/** - * `generateUnsignedProposal()` input argument type. - */ -type GenerateUnsignedProposalArgs = { - contract: { - channelName: string; - }; - args: { - args: { - transactionProposalReq: Client.ProposalRequest; - certPem: string; - }; - }; - reqID?: string; -}; - -/** - * `generateUnsignedTransaction()` input argument type. - */ -type GenerateUnsignedTransactionArgs = { - contract: { - channelName: string; - }; - args: { - args: { - proposal: string; - proposalResponses: string[]; - }; - }; - reqID?: string; -}; - -/** - * `sendSignedProposal()` input argument type. - */ -type SendSignedProposalArgs = { - contract: { - channelName: string; - }; - args: { - args: { - transactionProposalReq: Client.ProposalRequest; - certPem?: string; - privateKeyPem?: string; - }; - }; - reqID?: string; -}; - -/** - * `sendSignedProposalV2()` input argument type. - */ -type SendSignedProposalV2Args = { - contract: { - channelName: string; - }; - args: { - args: { - signedProposal: Buffer; - }; - }; - reqID?: string; -}; - -/** - * `sendSignedTransactionV2()` input argument type. - */ -type SendSignedTransactionV2Args = { - contract: { - channelName: string; - }; - args: { - args: { - signedCommitProposal: Buffer; - proposal: string; - proposalResponses: string[]; - }; - }; - reqID?: string; -}; - -///////////////////////////// -// ServerPlugin Class -///////////////////////////// - -export class ServerPlugin { - /* - * isExistFunction - * - * @param {String} funcName : The function name you want to determine. - * - * @return {Boolean} true : exist / false : not exist - * - * @desc Determines if the specified function exists in its class. - * 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: string) { - if ((this as any)[funcName]) { - return true; - } else { - return false; - } - } - - /* - * contractTransaction(Sync) - * - * @param {Object} args : JSON Object - * { - * "contract": { - * "channelName": , - * "contractName": - * }, - * "args": { - * "args":[ - * , - * < : >, - * < : > - * ] - * }, - * "method": { - * "method": - * ] - * }, - * "reqID": // option - * } - * @return {Object} JSON object - */ - contractTransaction(args: any) { - return new Promise((resolve, reject) => { - logger.info("evaluateTransaction start"); - // logger.debug(`##evaluateTransaction(A)`); - let retObj: Record; - let reqID = args["reqID"]; - if (reqID === undefined) { - reqID = null; - } - // logger.debug(`##evaluateTransaction(Aa): args: ${JSON.stringify(args.args.args)}, reqID: ${reqID}`); - const reqparam = { - method: args.method, - args: args.args.args, - channelName: args.contract.channelName, - contractName: args.contract.contractName, - }; - // Block generation event monitoring target because it is performed from the operation request by the CC chain code - InvokeSync(reqparam) - .then((returnvalue: any) => { - // logger.debug(`##evaluateTransaction(B)`); - // logger.debug(`##evaluateTransaction(B1), returnvalue: ${returnvalue}`); - if (returnvalue == null) { - logger.debug(`##evaluateTransaction(B2), returnvalue: null`); - } else if (returnvalue == undefined) { - logger.debug(`##evaluateTransaction(B3), returnvalue: undefined`); - } else if (returnvalue == "") { - logger.debug( - `##evaluateTransaction(B4), returnvalue: empty string`, - ); - } - if (returnvalue != null) { - // logger.debug(`##evaluateTransaction(B5)`); - let objRetValue = {}; - if (returnvalue != "") { - // logger.debug(`##evaluateTransaction(B6)`); - objRetValue = JSON.parse(returnvalue); - } - const signedResults = signMessageJwt({ - result: objRetValue, - }); - retObj = { - resObj: { - status: 200, - data: signedResults, - }, - }; - if (reqID !== null) { - retObj["id"] = reqID; - } - logger.debug(`##evaluateTransaction(C1c) retObj: ${retObj}`); - return resolve(retObj); - } - }) - .catch((err) => { - logger.debug(`##evaluateTransaction(D)`); - retObj = { - resObj: { - status: 504, - errorDetail: safeStringifyException(err), - }, - }; - logger.error(err); - return reject(retObj); - }); - }); - } - - /** - * Offline trading - * @param {object} args : JSON Object - * { - * "args": { - * "contract": {"channelName": channelName}, - * "args":[ - * { - * "signedCommitProposal":, - * "commitReq": - * } - * ] - * }, - * "reqID": // option - * } - * @return {Object} JSON object - */ - sendSignedTransaction(args: any) { - return new Promise((resolve, reject) => { - logger.info("sendSignedTransaction start"); - let retObj: Record; - - // parameter check - logger.info("sendSignedTransaction parameter check"); - const channelName = args.contract.channelName; - const signedCommitProposal = args.args.args[0].signedCommitProposal; - const commitReq = args.args.args[0].commitReq; - // logger.debug(`##sendSignedTransaction: channelName = ${channelName}`); - // logger.debug(`##sendSignedTransaction: signedCommitProposal = ${JSON.stringify(signedCommitProposal)}`); - // logger.debug(`##sendSignedTransaction: commitReq = ${JSON.stringify(commitReq)}`); - if (signedCommitProposal == undefined || commitReq == undefined) { - const emsg = "Insufficient parameters."; - logger.info(emsg); - retObj = { - status: 504, - errorDetail: emsg, - }; - return reject(retObj); - } - const reqparam = { - signedCommitProposal: signedCommitProposal, - commitReq: commitReq, - channelName: channelName, - }; - // call chainncode - InvokeSendSignedTransaction(reqparam) - .then((returnvalue) => { - if (returnvalue != null) { - retObj = { - resObj: { - status: 200, - data: returnvalue, - }, - }; - - if (args.reqID) { - retObj["id"] = args.reqID; - } - return resolve(retObj); - } - }) - .catch((err) => { - retObj = { - status: 504, - errorDetail: safeStringifyException(err), - }; - logger.error(err); - return reject(retObj); - }); - }); - } - - /** - * API request to send commit transaction signed on the client side. - * No user cryptographic data is handled by this function. - * Uses Fabric-SDK `channel.sendSignedTransaction` call. - * - * @param args.signedCommitProposal Signed commit proposal buffer. - * @param args.proposal Encoded proposal from `generateUnsignedProposal` API call. - * @param args.proposalResponses Encoded endorsing responses from `sendSignedProposalV2` API call. - * @returns Send status. - */ - async sendSignedTransactionV2(args: SendSignedTransactionV2Args) { - logger.info("sendSignedTransactionV2 start"); - - // Parse arguments - const channelName = args.contract.channelName; - const signedCommitProposal = args.args.args.signedCommitProposal; - const proposal = ProposalSerializer.decode(args.args.args.proposal); - let proposalResponses: any[] = args.args.args.proposalResponses.map((val) => - ProposalResponseSerializer.decode(val), - ); - let reqID = args.reqID; - logger.info(`##sendSignedTransactionV2: reqID: ${reqID}`); - - if ( - !channelName || - !signedCommitProposal || - !proposal || - proposalResponses.length === 0 - ) { - throw { - resObj: { - status: 504, - errorDetail: "sendSignedTransactionV2: Invalid input parameters", - }, - }; - } - - // Logic - try { - const invokeResponse = await InvokeSendSignedTransaction({ - signedCommitProposal, - commitReq: { - proposal, - proposalResponses, - }, - channelName: channelName, - }); - logger.info("sendSignedTransactionV2: done."); - - return { - id: reqID, - resObj: { - status: 200, - data: invokeResponse, - }, - }; - } catch (error) { - logger.error("sendSignedTransactionV2() error:", error); - throw { - resObj: { - status: 504, - errorDetail: safeStringifyException(error), - }, - }; - } - } - - /** - * API request to send transaction endorsment. - * Uses cryptographic data either from input arguments, or from local (connectors) wallet. - * - * @param args.transactionProposalReq Raw transaction that will be turned into proposal. - * @param args.certPem Client public key in PEM format. - * @param args.privateKeyPem Client private key in PEM format. - * @returns signedCommitProposal Signed transaction proposal. - * @returns commitReq Unsigned commit request. - * @returns txId Transaction ID. - */ - async sendSignedProposal(args: SendSignedProposalArgs) { - logger.info("sendSignedProposal start"); - - // Parse arguments - const channelName = args.contract.channelName; - const transactionProposalReq = args.args.args.transactionProposalReq; - let certPem = args.args.args.certPem; - let privateKeyPem = args.args.args.privateKeyPem; - let reqID = args.reqID; - logger.info(`##sendSignedProposal: reqID: ${reqID}`); - - // Logic - try { - let { client, channel } = await getClientAndChannel(channelName); - - if (!certPem || !privateKeyPem) { - // Get identity from connector wallet - const submiterId = await getSubmiterIdentityCrypto(client); - certPem = submiterId.certPem; - privateKeyPem = submiterId.privateKeyPem; - } - - if (!certPem || !privateKeyPem) { - throw Error( - "Could not read certificate and private key of the submitter.", - ); - } - - // Generate endorsement proposal - const { proposal, txId } = InvokeGenerateUnsignedProposal( - channel, - transactionProposalReq, - certPem, - ); - const signedProposal = signProposal(proposal.toBuffer(), privateKeyPem); - - // Send proposal, get endorsment responses - const { - endorsmentStatus, - proposalResponses, - } = await InvokeSendSignedProposalV2(channel, signedProposal as any); - logger.info("sendSignedProposal: done."); - - if (!endorsmentStatus) { - throw new Error( - "Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...", - ); - } - - // Generate commit proposal - const commitProposal = await InvokeGenerateUnsignedTransaction( - channel, - proposalResponses as any, - proposal, - ); - const signedCommitProposal = signProposal( - commitProposal.toBuffer(), - privateKeyPem, - ); - - // Send the response - const signedResults = signMessageJwt({ - result: { - signedCommitProposal, - commitReq: { proposalResponses, proposal }, - txId: txId.getTransactionID(), - }, - }); - - return { - id: reqID, - resObj: { - status: 200, - data: signedResults, - }, - }; - } catch (error) { - logger.error("sendSignedProposal() error:", error); - throw { - resObj: { - status: 504, - errorDetail: safeStringifyException(error), - }, - }; - } - } - - /** - * Get fabric block specified in args. - * - * @param args - * ``` javascript - * { - * "args": { - * "contract": {"channelName": string}, // Fabric channel to execute the request on - * "args": { - * // OneOf following fields is required. First one found will be used. - * "blockNumber"?: number, - * "blockHash"?: Array, - * "txId"?: string, - * // Optional. If true, this function returns an encoded block. - * "skipDecode"?: boolean, - * } - * }, - * "reqID": string // optional requestID from verifier - * } - * ``` - */ - async getBlock(args: any) { - logger.info("getBlock start"); - - const channelName = args.contract.channelName; - const blockNumber = args.args.blockNumber; - const blockHash = args.args.blockHash; - const txId = args.args.txId; - const skipDecode = args.args.skipDecode ?? false; - - const reqID = args.reqID ?? null; - logger.info(`##getBlock: reqID: ${reqID}`); - - let { client, channel } = await getClientAndChannel(channelName); - await getSubmitterAndEnroll(client); - - let block: Block; - if (typeof blockNumber === "number") { - block = await channel.queryBlock( - blockNumber, - undefined, - undefined, - skipDecode, - ); - } else if (blockHash) { - block = await channel.queryBlockByHash( - blockHash, - undefined, - undefined, - skipDecode, - ); - } else if (txId) { - block = await channel.queryBlockByTxID( - txId, - undefined, - undefined, - skipDecode, - ); - } else { - const errObj = { - resObj: { - status: 400, - errorDetail: - "getBlock: Provide either blockNumber, blockHash, or txId", - }, - id: reqID, - }; - logger.error(errObj); - throw errObj; - } - - if (!block) { - const errObj = { - resObj: { - status: 504, - errorDetail: "getBlock: Could not retrieve block", - }, - id: reqID, - }; - logger.error(errObj); - throw errObj; - } - - const signedBlock = signMessageJwt({ - result: block, - }); - - const retObj = { - resObj: { - status: 200, - data: signedBlock, - }, - id: reqID, - }; - logger.debug("##getBlock: response:", retObj); - - return retObj; - } - - /** - * API request to send endorsement proposal signed on the client side. - * No user cryptographic data is handled by this function. - * Uses Fabric-SDK `channel.sendSignedProposal` call. - * - * @param args.signedProposal Signed proposal buffer from `generateUnsignedProposal` API call. - * @returns endorsmentStatus Bool whether endorsment was OK or not. - * @returns proposalResponses Encoded responses to be used to generate commit proposal. - */ - async sendSignedProposalV2(args: SendSignedProposalV2Args) { - logger.info("sendSignedProposalV2 start"); - - // Parse arguments - const channelName = args.contract.channelName; - const signedProposal = args.args.args.signedProposal; - let reqID = args.reqID; - logger.info(`##sendSignedProposalV2: reqID: ${reqID}`); - - // Logic - try { - let { channel } = await getClientAndChannel(channelName); - - const invokeResponse = await InvokeSendSignedProposalV2( - channel, - signedProposal, - ); - logger.info("sendSignedProposalV2: done."); - - let proposalResponses = invokeResponse.proposalResponses.map((val: any) => - ProposalResponseSerializer.encode(val), - ); - logger.debug( - `sendSignedProposalV2: encoded ${proposalResponses.length} proposalResponses.`, - ); - - const signedResults = signMessageJwt({ - result: { - endorsmentStatus: invokeResponse.endorsmentStatus, - proposalResponses, - }, - }); - - return { - id: reqID, - resObj: { - status: 200, - data: signedResults, - }, - }; - } catch (error) { - logger.error("sendSignedProposalV2() error:", error); - throw { - resObj: { - status: 504, - errorDetail: safeStringifyException(error), - }, - }; - } - } - - /** - * API request to generate unsigned endorse proposal. - * Proposal must be signed on the client side. - * Uses Fabric-SDK `channel.generateUnsignedProposal` call. - * - * @param args.transactionProposalReq Raw transaction that will be turned into proposal. - * @param args.certPem Client public key in PEM format. - * @returns proposalBuffer Generated unsigned endorse proposal buffer. - * @returns proposal Encoded proposal to be used in follow-up calls to the connector. - * @returns txId Transaction ID. - */ - async generateUnsignedProposal(args: GenerateUnsignedProposalArgs) { - logger.info("generateUnsignedProposal: start"); - - // Parse arguments - const channelName = args.contract.channelName; - const transactionProposalReq = args.args.args.transactionProposalReq; - const certPem = args.args.args.certPem; - let reqID = args.reqID; - logger.info(`##generateUnsignedProposal: reqID: ${reqID}`); - - // Logic - try { - let { channel } = await getClientAndChannel(channelName); - - let invokeResponse = InvokeGenerateUnsignedProposal( - channel, - transactionProposalReq, - certPem, - ); - if (!invokeResponse.proposal || !invokeResponse.txId) { - throw new Error( - "generateUnsignedProposal: empty proposal or transaction id.", - ); - } - logger.info(`generateUnsignedProposal: done.`); - - const signedResults = signMessageJwt({ - result: { - proposalBuffer: invokeResponse.proposal.toBuffer(), - proposal: ProposalSerializer.encode(invokeResponse.proposal), - txId: invokeResponse.txId.getTransactionID(), - }, - }); - - return { - id: reqID, - resObj: { - status: 200, - data: signedResults, - }, - }; - } catch (error) { - logger.error("generateUnsignedProposal() error:", error); - throw { - resObj: { - status: 504, - errorDetail: safeStringifyException(error), - }, - }; - } - } - - /** - * API request to generate unsigned commit (transaction) proposal. - * Proposal must be signed on the client side. - * Uses Fabric-SDK `channel.generateUnsignedTransaction` call. - * - * @param args.proposal Encoded proposal from `generateUnsignedProposal` API call. - * @param args.proposalResponses Encoded proposal responses from `sendSignedProposalV2` API call. - * @returns txProposalBuffer Unsigned proposal buffer. - */ - async generateUnsignedTransaction(args: GenerateUnsignedTransactionArgs) { - logger.info("generateUnsignedTransaction: start"); - - // Parse arguments - const channelName = args.contract.channelName; - const proposal = ProposalSerializer.decode(args.args.args.proposal); - let proposalResponses: any[] = args.args.args.proposalResponses.map((val) => - ProposalResponseSerializer.decode(val), - ); - logger.debug( - `##generateUnsignedTransaction Received ${proposalResponses.length} proposal responses`, - ); - let reqID = args.reqID; - logger.info(`##generateUnsignedTransaction: reqID: ${reqID}`); - - // Logic - try { - let { channel } = await getClientAndChannel(channelName); - - const txProposal = await InvokeGenerateUnsignedTransaction( - channel, - proposalResponses, - proposal, - ); - logger.info(`generateUnsignedTransaction: done.`); - - const signedResults = signMessageJwt({ - result: { - txProposalBuffer: txProposal.toBuffer(), - }, - }); - - return { - id: reqID, - resObj: { - status: 200, - data: signedResults, - }, - }; - } catch (error) { - logger.error("generateUnsignedTransaction() error:", error); - throw { - resObj: { - status: 504, - errorDetail: safeStringifyException(error), - }, - }; - } - } -} /* class */ - -///////////////////////////// -// Invoke (logic) functions -///////////////////////////// - -/** - * Read public and private keys of the submitter from connector wallet. - * Throws `Error()` when submiters identity is missing. - * - * @param client Fabric-SDK channel client object. - * @returns `certPem`, `privateKeyPem` - */ -async function getSubmiterIdentityCrypto(client: Client) { - const wallet = new FileSystemWallet(configRead("fabric.keystore")); - logger.debug( - `Wallet path: ${path.resolve(configRead("fabric.keystore"))}`, - ); - - let user = await getSubmitterAndEnroll(client); - const submitterName = user.getName(); - const submitterExists = await wallet.exists(submitterName); - if (submitterExists) { - const submitterIdentity = await wallet.export(submitterName); - const certPem = (submitterIdentity as any).certificate as string; - const privateKeyPem = (submitterIdentity as any).privateKey as string; - return { certPem, privateKeyPem }; - } else { - throw new Error( - `No cert/key provided and submitter ${submitterName} is missing in validator wallet!`, - ); - } -} - -/* - * Invoke Sync function - * @param reqBody [json object] {fcn:, args:[arg1>,,,,], channelName:, contractName:} - * @return [string] Success: Chain code execution result - * Failure: Chain code error or internal error - */ -async function InvokeSync(reqBody: any) { - return new Promise(async function (resolve, reject) { - try { - logger.info("##fablicaccess: InvokeSync start"); - // logger.debug(`##InvokeSync(A)`); - - const type = reqBody.method.type; - const fcn = reqBody.method.command; - const args = reqBody.args; - - // Create a new file system based wallet for managing identities. - // logger.debug(`##InvokeSync(B)`); - const wallet = new FileSystemWallet( - configRead("fabric.keystore"), - ); - console.log(`Wallet path: ${configRead("fabric.keystore")}`); - - // Check to see if we've already enrolled the user. - // logger.debug(`##InvokeSync(C)`); - const userExists = await wallet.exists(connUserName); - if (!userExists) { - logger.debug(`##InvokeSync(C1)`); - //logger.error(`An identity for the user ${connUserName} does not exist in the wallet`); - const errMsg = `An identity for the user ${connUserName} does not exist in the wallet`; - logger.error(errMsg); - logger.error("Run the registerUser.js application before retrying"); - return reject(errMsg); - } - - // Create a new gateway for connecting to our peer node. - let { client } = await getClientAndChannel(reqBody.channelName); - await getSubmitterAndEnroll(client); - - const gateway = new Gateway(); - await gateway.connect(client, { - wallet, - identity: connUserName, - discovery: { enabled: false }, - }); - - // Get the network (channel) our contract is deployed to. - // logger.debug(`##InvokeSync(E)`); - const network = await gateway.getNetwork(reqBody.channelName); - - // Get the contract from the network. - // logger.debug(`##InvokeSync(F)`); - const contract = network.getContract(reqBody.contractName); - - // Submit the specified transaction. - // logger.debug(`##InvokeSync(G)`); - logger.info( - `##fablicaccess: InvokeSync Params: type=${type}, fcn=${fcn}, args0=${args[0]}, args1=${args[1]}, args2=${args[2]}`, - ); - // const transaction = contract.createTransaction(fcn); - let result: any = null; - switch (args.length) { - case 0: - // logger.debug(`##InvokeSync(G1): No args.`); - if (type === "evaluateTransaction") { - logger.debug(`##InvokeSync(G1): call evaluateTransaction`); - result = await contract.evaluateTransaction(fcn); - } else { - logger.debug(`##InvokeSync(G1): call submitTransaction`); - result = await contract.submitTransaction(fcn); - } - break; - case 1: - // logger.debug(`##InvokeSync(G2): One arg.`); - if (type === "evaluateTransaction") { - logger.debug(`##InvokeSync(G1): call evaluateTransaction`); - result = await contract.evaluateTransaction(fcn, args[0]); - } else { - logger.debug(`##InvokeSync(G1): call submitTransaction`); - result = await contract.submitTransaction(fcn, args[0]); - } - break; - case 2: - // logger.debug(`##InvokeSync(G3): Two args.`); - if (type === "evaluateTransaction") { - logger.debug(`##InvokeSync(G1): call evaluateTransaction`); - result = await contract.evaluateTransaction(fcn, args[0], args[1]); - } else { - logger.debug(`##InvokeSync(G1): call submitTransaction`); - result = await contract.submitTransaction(fcn, args[0], args[1]); - } - break; - case 3: - // logger.debug(`##InvokeSync(G4): Three args.`); - if (type === "evaluateTransaction") { - logger.debug(`##InvokeSync(G1): call evaluateTransaction`); - result = await contract.evaluateTransaction( - fcn, - args[0], - args[1], - args[2], - ); - } else { - logger.debug(`##InvokeSync(G1): call submitTransaction`); - result = await contract.submitTransaction( - fcn, - args[0], - args[1], - args[2], - ); - } - break; - } - logger.info(`##fablicaccess: InvokeSync result: ${result}`); - console.log(`##fablicaccess: InvokeSync result: ${result}`); - - logger.debug(`##InvokeSync(I)`); - return resolve(result); - } catch (error) { - // logger.debug(`##InvokeSync(Z)`); - const errMsg = `Failed to submit transaction: ${error}`; - logger.error(errMsg); - return reject(errMsg); - } - }); -} - -/** - * Function for InvokeSendSignedTransaction - * @param reqBody [json object] {signedCommitProposal:, commitReq:, channelName:} - * @return [string] Success: Chain code execution result - * Failure: Chain code error or internal error - */ -async function InvokeSendSignedTransaction(reqBody: any) { - return new Promise(async function (resolve, reject) { - logger.info("InvokeSendSignedTransaction start"); - - let invokeResponse1; // Return value from chain code - - try { - //channel object generation - let { client, channel } = await getClientAndChannel(reqBody.channelName); - await getSubmitterAndEnroll(client); - - // logger.debug(`##InvokeSendSignedTransaction: reqBody.signedCommitProposal: ${JSON.stringify(reqBody.signedCommitProposal)}`); - // logger.debug(`##InvokeSendSignedTransaction: reqBody.commitReq: ${JSON.stringify(reqBody.commitReq)}`); - // logger.debug(`##InvokeSendSignedTransaction: (A)`); - 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)); - if (response.status === "SUCCESS") { - // logger.debug(`##InvokeSendSignedTransaction: (C)`); - invokeResponse1 = response; - return resolve(invokeResponse1); - } else { - logger.debug(`##InvokeSendSignedTransaction: (D)`); - throw new Error( - "Failed to order the transaction. Error code: " + response.status, - ); - } - } catch (e) { - logger.debug(`##InvokeSendSignedTransaction: (E)`); - return reject(e); - } - }); -} - -/** - * Call `channel.generateUnsignedProposal` to generate unsigned endorse proposal. - * - * @param channel Fabric-SDK channel object. - * @param txProposal Raw transaction. - * @param certPem Sender public key in PEM format. - * @returns `proposal` - Proposal, `txId` - Transaction object - */ -function InvokeGenerateUnsignedProposal( - channel: Client.Channel, - txProposal: ProposalRequest, - certPem: string, -) { - if (!txProposal || !certPem) { - throw new Error( - "InvokeGenerateUnsignedProposal: Invalid input parameters.", - ); - } - - logger.debug("Call channel.generateUnsignedProposal()"); - - return (channel.generateUnsignedProposal( - txProposal, - configRead("fabric.mspid"), - certPem, - false, - ) as any) as { proposal: any; txId: any }; -} - -/** - * Call `channel.generateUnsignedTransaction` to generate unsigned commit proposal. - * - * @param channel Fabric-SDK channel object. - * @param proposalResponses Proposal responses from endorse step. - * @param proposal Unsigned proposal from `generateUnsignedProposal` - * @returns Unsigned commit proposal. - */ -async function InvokeGenerateUnsignedTransaction( - channel: Client.Channel, - proposalResponses: ProposalResponse[], - proposal: Proposal, -) { - if (!proposal || !proposalResponses || proposalResponses.length === 0) { - throw new Error( - "InvokeGenerateUnsignedTransaction: Invalid input parameters.", - ); - } - - logger.debug("Call channel.generateUnsignedTransaction()"); - - return await channel.generateUnsignedTransaction({ - proposalResponses, - proposal, - }); -} - -/** - * Call `channel.sendSignedProposal`, gather and check the responses. - * - * @param channel Fabric-SDK channel object. - * @param signedProposal Proposal from `generateUnsignedProposal` signed with sender private key. - * @returns `endorsmentStatus`, `proposalResponses` - */ -async function InvokeSendSignedProposalV2( - channel: Client.Channel, - signedProposal: Buffer, -) { - logger.debug(`InvokeSendSignedProposalV2: start`); - - const targets = []; - for (const peerInfo of configRead("fabric.peers")) { - const peer = channel.getPeer(peerInfo.requests.split("//")[1]); - targets.push(peer); - } - const sendSignedProposalReq = { signedProposal, targets } as any; - - const proposalResponses = await channel.sendSignedProposal( - sendSignedProposalReq, - ); - logger.debug( - "##InvokeSendSignedProposalV2: successfully sent signedProposal", - ); - - // Determine endorsment status - let endorsmentStatus = true; - for (const proposalResponse of proposalResponses) { - const propResponse = (proposalResponse as unknown) as Client.ProposalResponse; - if ( - !propResponse || - !propResponse.response || - propResponse.response.status !== 200 - ) { - endorsmentStatus = false; - } - } - - return { - endorsmentStatus, - proposalResponses, - }; -} diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabric-proto-serializers.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabric-proto-serializers.ts index bb9e1ae286b..ee6179499ed 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabric-proto-serializers.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabric-proto-serializers.ts @@ -9,7 +9,6 @@ * fabric packages. */ -import Client from "fabric-client"; import { cloneDeep } from "lodash"; // TS import is using newer protobufjs version typings, use nodejs import for now. @@ -110,53 +109,3 @@ const proposalBuilder = loadFabricProto( const proposalResponseBuilder = loadFabricProto( "fabric-client/lib/protos/peer/proposal_response.proto", ); - -/** - * Client.Proposal serializers - */ -export namespace ProposalSerializer { - export const ProposalType = proposalBuilder.protos.Proposal; - const proposalTypeName = ProposalType["$type"].name; - - export function encode(proposal: Client.Proposal): string { - return encodeMetdata(proposalTypeName, (proposal as any).encodeJSON()); - } - - export function decode(encodedProposal: string): Client.Proposal { - return ProposalType.decodeJSON( - decodeMetdata(proposalTypeName, encodedProposal), - ); - } -} - -/** - * Client.ProposalResponse serializers - */ -export namespace ProposalResponseSerializer { - export const ProposalResponseType = - proposalResponseBuilder.protos.ProposalResponse; - const proposalResponseTypeName = ProposalResponseType["$type"].name; - - export function encode(proposalResponse: Client.ProposalResponse): string { - let proposalResponseCopy = cloneDeep(proposalResponse) as Record< - string, - any - >; - - // Peer is not part of protobuf definition, remove it. - delete proposalResponseCopy.peer; - - let proposalResponseMessage = new ProposalResponseType( - proposalResponseCopy, - ); - const encodedProposalResponse = proposalResponseMessage.encodeJSON(); - return encodeMetdata(proposalResponseTypeName, encodedProposalResponse); - } - - export function decode(encodedProposalResponse: string) { - let decodedProposalResponse = ProposalResponseType.decodeJSON( - decodeMetdata(proposalResponseTypeName, encodedProposalResponse), - ); - return convertToPlainObject(decodedProposalResponse); - } -} 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 deleted file mode 100644 index 5da5ad4f8d0..00000000000 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/fabricaccess.ts +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2021 Hyperledger Cactus Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * fabricaccess.js - */ - -/* - * Summary: - * Request processing library for fabric v1.4.0 - */ - -//Dependent library -import { configRead } from "@hyperledger/cactus-cmd-socketio-server"; -const path = require("path"); -import fs from "fs"; - -//fabric client dependent library -import FabricClient, { User } from "fabric-client"; -import copService, { TLSOptions } from "fabric-ca-client"; - -// list of fabric-client objects -const clients = new Map(); - -// Log settings -import { getLogger } from "log4js"; -const logger = getLogger("fabricaccess[" + process.pid + "]"); -logger.level = configRead("logLevel", "info"); - -// Get user object to send Proposal to EP -export function getSubmitterAndEnroll(cli: FabricClient): Promise { - logger.info("##fabricaccess_getSubmitter"); - const caUrl = configRead("fabric.ca.url"); - const caName = configRead("fabric.ca.name"); - // Returns Promise when checkPersistence is true (poor typing) - return (cli.getUserContext( - configRead("fabric.submitter.name"), - true, - ) as Promise).then((user) => { - return new Promise((resolve, reject) => { - if (user && user.isEnrolled()) { - return resolve(user); - } - const member = new User(configRead("fabric.submitter.name")); - let cryptoSuite = cli.getCryptoSuite(); - if (!cryptoSuite) { - const storePath = path.join( - configRead("fabric.keystore"), - configRead("fabric.submitter.name"), - ); - cryptoSuite = FabricClient.newCryptoSuite(); - cryptoSuite.setCryptoKeyStore( - FabricClient.newCryptoKeyStore({ - path: storePath, - }), - ); - cli.setCryptoSuite(cryptoSuite); - } - member.setCryptoSuite(cryptoSuite); - - const tlsOptions: TLSOptions = { - trustedRoots: Buffer.from([]), - verify: false, - }; - const cop = new copService(caUrl, tlsOptions, caName, cryptoSuite); - return cop - .enroll({ - enrollmentID: configRead("fabric.submitter.name"), - enrollmentSecret: configRead("fabric.submitter.secret"), - }) - .then((enrollment) => { - return member.setEnrollment( - enrollment.key, - enrollment.certificate, - configRead("fabric.mspid"), - ); - }) - .then(() => { - return cli.setUserContext(member, false); - }) - .then(() => { - return resolve(member); - }) - .catch((err) => { - return reject(err); - }); - }); - }); -} - -// fabric-client and Channel object generation -export async function getClientAndChannel( - channelName = configRead("fabric.channelName"), -) { - 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.get(configRead("fabric.ca.name")); - if (!client) { - logger.info("create new fabric-client"); - client = new FabricClient(); - clients.set(configRead("fabric.ca.name"), client); - isNewClient = true; - } - - let channel = null; - - // * If getChannel of v1.0 SDK does not exist, an exception is returned instead of null, so try ~ catch - // Therefore, the error from Client.js will always be output in the log for the first time, but it is not harmful - try { - channel = client.getChannel(channelName); - } catch (e) { - if (channel == null) { - logger.info("create new channel, name=" + channelName); - channel = client.newChannel(channelName); - - let ordererCA: string; - try { - ordererCA = configRead('fabric.orderer.tlscaValue'); - } catch { - ordererCA = fs.readFileSync(configRead('fabric.orderer.tlsca'), 'ascii'); - } - - const orderer = client.newOrderer( - configRead("fabric.orderer.url"), - { - pem: ordererCA, - "ssl-target-name-override": configRead( - "fabric.orderer.name", - ), - }, - ); - channel.addOrderer(orderer); - // EP settings - const peersConfig = configRead("fabric.peers"); - for (let i = 0; i < peersConfig.length; i++) { - let peerCA: string; - if ("tlscaValue" in peersConfig[i]) { - peerCA = peersConfig[i].tlscaValue; - } else { - peerCA = fs.readFileSync(peersConfig[i].tlsca, 'ascii'); - } - - const peer = client.newPeer(peersConfig[i].requests, { - pem: peerCA, - "ssl-target-name-override": peersConfig[i].name, - }); - - channel.addPeer(peer, configRead("fabric.mspid")); - } - - const storePath = path.join( - configRead("fabric.keystore"), - configRead("fabric.submitter.name"), - ); - const cryptoSuite = FabricClient.newCryptoSuite(); - cryptoSuite.setCryptoKeyStore( - FabricClient.newCryptoKeyStore({ - path: storePath, - }), - ); - client.setCryptoSuite(cryptoSuite); - - // Generate enrollment information storage location - let store = await FabricClient.newDefaultKeyValueStore({ - path: storePath, - }); - client.setStateStore(store); - } else { - // Exception when reflecting connection destination information difference - logger.error(e); - } - } - - return { client, channel }; -} diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/sign-utils.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/sign-utils.ts index 699884393f0..620aeabf96e 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/sign-utils.ts +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/main/typescript/connector/sign-utils.ts @@ -5,7 +5,6 @@ * Util tools used for cryptography related to hyperledger fabric (e.g. signing proposals) */ -const hash = require("fabric-client/lib/hash"); import jsrsa from "jsrsasign"; import elliptic from "elliptic"; @@ -71,19 +70,8 @@ function sign( algorithm: string, keySize: number, ) { - const hashAlgorithm = algorithm.toUpperCase(); - const hashFunction = hash[`${hashAlgorithm}_${keySize}`]; - const ecdsaCurve = ellipticCurves[`p${keySize}`]; - const ecdsa = new elliptic.ec(ecdsaCurve); - const key = jsrsa.KEYUTIL.getKey(privateKey) as any; - - const signKey = ecdsa.keyFromPrivate(key.prvKeyHex, "hex"); - const digest = hashFunction(proposalBytes); - - let sig = ecdsa.sign(Buffer.from(digest, "hex"), signKey); - sig = preventMalleability(sig, key.ecparams); - - return Buffer.from(sig.toDER()); + throw new Error("Not implemented. Code here was removed due to" + + " security issues (dependence on legacy versions grpc and Fabric)."); } /** diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/integration/fabric-setup-helpers.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/integration/fabric-setup-helpers.ts deleted file mode 100644 index e580767a4eb..00000000000 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/integration/fabric-setup-helpers.ts +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Fabric helpers to be used by functional tests. - * Works with Fabric SDK 1.4 - that's why it's not included in fabric ledger test class. - * Most functions are based on fabric-samples and utils scripts from tools/docker/fabric-all-in-one/asset-transfer-basic-utils - */ - -import { LoggerProvider, Logger } from "@hyperledger/cactus-common"; -import { FileSystemWallet, Gateway, X509WalletMixin } from "fabric-network"; -import FabricCAServices from "fabric-ca-client"; - -// Unit Test logger setup -const log: Logger = LoggerProvider.getOrCreate({ - label: "fabric-setup-helpers", - level: "info", -}); - -/** - * Enroll admin user on fabric and store it's credential in local filesystem wallet. - * - * @param connectionProfile - Fabric connection profile JSON. - * @param walletPath - Local filesystem wallet path. - * @param enrollmentID - admin username. - * @param enrollmentSecret - admin secret. - */ -export async function enrollAdmin( - connectionProfile: any, - walletPath: string, - enrollmentID: string, - enrollmentSecret: string, -) { - log.info( - `Enroll admin user with enrollmentID='${enrollmentID}' and enrollmentSecret='${enrollmentSecret}'`, - ); - - // Create a new CA client for interacting with the CA. - const caName = connectionProfile.organizations.Org1.certificateAuthorities[0]; - const caInfo = connectionProfile.certificateAuthorities[caName]; - const caTLSCACerts = caInfo.tlsCACerts.pem; - const ca = new FabricCAServices( - caInfo.url, - { trustedRoots: caTLSCACerts, verify: false }, - caInfo.caName, - ); - - // Create a new file system based wallet for managing identities. - const wallet = new FileSystemWallet(walletPath); - - // Enroll admin user if not exist yet - const adminExists = await wallet.exists(enrollmentID); - if (!adminExists) { - const enrollment = await ca.enroll({ - enrollmentID, - enrollmentSecret, - }); - const identity = X509WalletMixin.createIdentity( - connectionProfile.organizations.Org1.mspid, - enrollment.certificate, - enrollment.key.toBytes(), - ); - await wallet.import(enrollmentID, identity); - log.info( - `Successfully enrolled admin user ${enrollmentID} and imported it into the wallet. Current state:`, - await wallet.list(), - ); - } -} - -/** - * Enroll a user on fabric and store it's credential in local filesystem wallet. - * Must be called after `enrollAdmin()` - * - * @param connectionProfile - Fabric connection profile JSON. - * @param walletPath - Local filesystem wallet path. - * @param userName - regular username to enroll. - * @param adminUserName - admin username (must be already enrolled) - */ -export async function enrollUser( - connectionProfile: any, - walletPath: string, - userName: string, - adminUserName: string, -) { - log.info(`Enroll user with userName='${userName}'`); - - // Create a new file system based wallet for managing identities. - const wallet = new FileSystemWallet(walletPath); - - // Check to see if we've already enrolled the user. - const userExists = await wallet.exists(userName); - if (userExists) { - console.log( - "An identity for the user userName already exists in the wallet", - ); - return; - } - - // Check to see if we've already enrolled the admin user. - const adminExists = await wallet.exists(adminUserName); - if (!adminExists) { - throw new Error( - "An identity for the admin user adminUserName does not exist in the wallet", - ); - } - - // Create a new gateway for connecting to our peer node. - const gateway = new Gateway(); - await gateway.connect(connectionProfile, { - wallet, - identity: adminUserName, - discovery: { enabled: true, asLocalhost: true }, - }); - - // Get the CA client object from the gateway for interacting with the CA. - const ca = gateway.getClient().getCertificateAuthority(); - const adminIdentity = gateway.getCurrentIdentity(); - - // Register the user, enroll the user, and import the new identity into the wallet. - const secret = await ca.register( - { - affiliation: "org1.department1", - enrollmentID: userName, - role: "client", - }, - adminIdentity, - ); - const enrollment = await ca.enroll({ - enrollmentID: userName, - enrollmentSecret: secret, - }); - const userIdentity = X509WalletMixin.createIdentity( - connectionProfile.organizations.Org1.mspid, - enrollment.certificate, - enrollment.key.toBytes(), - ); - await wallet.import(userName, userIdentity); - log.info( - `Successfully enrolled user ${userName} and imported it into the wallet. Current state:`, - await wallet.list(), - ); -} - -/** - * Get cryptographic data for specified user from local filesystem wallet. - * Can be used to sign transactions as specified user. - * - * @param name - Username enrolled in wallet. - * @param walletPath - Local filesystem wallet path. - * @returns A tuple [certificatePem, privateKeyPem] - */ -export async function getUserCryptoFromWallet( - name: string, - walletPath: string, -): Promise<[string, string]> { - const wallet = new FileSystemWallet(walletPath); - - const submitterExists = await wallet.exists(name); - if (!submitterExists) { - throw new Error(`User ${name} does not exist in wallet ${walletPath}`); - } - - const submitterIdentity = await wallet.export(name); - const certPem = (submitterIdentity as any).certificate; - const privateKeyPem = (submitterIdentity as any).privateKey; - return [certPem, privateKeyPem]; -} diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/integration/fabric-socketio-connector.test.ts b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/integration/fabric-socketio-connector.test.ts deleted file mode 100644 index 1a70a724e6c..00000000000 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/integration/fabric-socketio-connector.test.ts +++ /dev/null @@ -1,794 +0,0 @@ -/** - * Functional test of basic operations on connector-fabric-socketio (packages/cactus-plugin-ledger-connector-fabric-socketio) - * Assumes sample CC was is deployed on the test ledger. - * Tests include sending and evaluation transactions, and monitoring for events. - * - * You can speed up development or troubleshooting by using same ledger repeatadely. - * 1. Remove fabric wallets from previous runs - `rm -rf /tmp/fabric-test-wallet*`. Repeat this everytime you restart ledger. - * 2. Change variable `leaveLedgerRunning` to true. - * 3. Run this functional test. It will leave the ledger running, and will enroll the users to common wallet location. - * 4. Change `useRunningLedger` to true. The following test runs will not setup the ledger again. - * Note: - * You may get a warning about open SIGNREQUEST handles after the test finishes. - * These are false-positives, and should be fixed in jest v28.1.0 - * More details: https://github.com/facebook/jest/pull/12789 - */ - -import { - DEFAULT_FABRIC_2_AIO_FABRIC_VERSION, - DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, - FabricTestLedgerV1, - pruneDockerAllIfGithubAction, - SelfSignedPkiGenerator, -} from "@hyperledger/cactus-test-tooling"; - -import { - LogLevelDesc, - LoggerProvider, - Logger, -} from "@hyperledger/cactus-common"; - -import { SocketIOApiClient } from "@hyperledger/cactus-api-client"; - -import { signProposal } from "../../../main/typescript/connector/sign-utils"; - -import { - enrollAdmin, - enrollUser, - getUserCryptoFromWallet, -} from "./fabric-setup-helpers"; - -import fs from "fs"; -import path from "path"; -import os from "os"; -import "jest-extended"; -import { Server as HttpsServer } from "https"; - -////////////////////////////////// -// Constants -////////////////////////////////// - -// Ledger settings -const imageName = DEFAULT_FABRIC_2_AIO_IMAGE_NAME; -const imageVersion = DEFAULT_FABRIC_2_AIO_IMAGE_VERSION; -const fabricEnvVersion = DEFAULT_FABRIC_2_AIO_FABRIC_VERSION; -const fabricEnvCAVersion = "1.4.9"; -const ledgerUserName = "appUser"; -const ledgerChannelName = "mychannel"; -const ledgerContractName = "basic"; -const leaveLedgerRunning = false; // default: false -const useRunningLedger = false; // default: false - -// Log settings -const testLogLevel: LogLevelDesc = "debug"; // default: info -const sutLogLevel: LogLevelDesc = "debug"; // default: info - -// Logger setup -const log: Logger = LoggerProvider.getOrCreate({ - label: "fabric-socketio-connector.test", - level: testLogLevel, -}); - -/** - * Main test suite - */ -describe("Fabric-SocketIO connector tests", () => { - let ledger: FabricTestLedgerV1; - let connectorCertValue: string; - let connectorPrivKeyValue: string; - let tmpWalletDir: string; - let connectorModule: typeof import("../../../main/typescript/index"); - let connectorServer: HttpsServer; - let apiClient: SocketIOApiClient; - - ////////////////////////////////// - // Environment Setup - ////////////////////////////////// - - /** - * @param connectionProfile - Fabric connection profile JSON - * @param connectorCert - connector-fabric-socketio server certificate - * @param connectorPrivKey - connector-fabric-socketio server private key - * @param walletDir - connector-fabric-socketio internal wallet path - * @param adminName - ledger admin username - * @param adminSecret - ledger admin secret - * @returns fabric-socketio conenctor config JSON - */ - function createFabricConnectorConfig( - connectionProfile: Record, - connectorCert: string, - connectorPrivKey: string, - jwtAlgo: string, - walletDir: string, - adminName: string, - adminSecret: string, - ) { - // Get Org CA - const caId = connectionProfile.organizations.Org1.certificateAuthorities[0]; - log.debug("Use CA:", caId); - - // Get Orderer ID - const ordererId = connectionProfile.channels[ledgerChannelName].orderers[0]; - log.debug("Use Orderer:", ordererId); - - const connectorConfig: any = { - sslParam: { - port: 0, // random port - keyValue: connectorPrivKey, - certValue: connectorCert, - jwtAlgo: jwtAlgo, - }, - logLevel: sutLogLevel, - fabric: { - mspid: connectionProfile.organizations.Org1.mspid, - keystore: walletDir, - connUserName: ledgerUserName, - contractName: ledgerContractName, - peers: [], // will be filled below - orderer: { - name: - connectionProfile.orderers[ordererId].grpcOptions[ - "ssl-target-name-override" - ], - url: connectionProfile.orderers[ordererId].url, - tlscaValue: connectionProfile.orderers[ordererId].tlsCACerts.pem, - }, - ca: { - name: connectionProfile.certificateAuthorities[caId].caName, - url: connectionProfile.certificateAuthorities[caId].url, - }, - submitter: { - name: adminName, - secret: adminSecret, - }, - channelName: ledgerChannelName, - chaincodeId: ledgerContractName, - }, - }; - - // Add peers - connectionProfile.organizations.Org1.peers.forEach((peerName: string) => { - log.debug("Add Peer:", peerName); - const peer = connectionProfile.peers[peerName]; - connectorConfig.fabric.peers.push({ - name: peer.grpcOptions["ssl-target-name-override"], - requests: peer.url, - tlscaValue: peer.tlsCACerts.pem, - }); - }); - - const configJson = JSON.stringify(connectorConfig); - log.debug("Connector Config:", configJson); - return configJson; - } - - beforeAll(async () => { - log.info("Prune Docker..."); - await pruneDockerAllIfGithubAction({ logLevel: testLogLevel }); - - // Prepare local filesystem wallet path - if (leaveLedgerRunning || useRunningLedger) { - tmpWalletDir = path.join(os.tmpdir(), "fabric-test-wallet-common"); - log.warn("Using common wallet path when re-using the same ledger."); - try { - fs.mkdirSync(tmpWalletDir); - } catch (err) { - if (!err.message.includes("EEXIST")) { - log.error( - "Unexpected exception when creating common wallet dir:", - err, - ); - throw err; - } - } - } else { - log.info("Create temp dir for wallet - will be removed later..."); - tmpWalletDir = fs.mkdtempSync( - path.join(os.tmpdir(), "fabric-test-wallet"), - ); - } - log.info("Wallet path:", tmpWalletDir); - expect(tmpWalletDir).toBeTruthy(); - - log.info("Start FabricTestLedgerV1..."); - log.debug("Version:", fabricEnvVersion, "CA Version:", fabricEnvCAVersion); - ledger = new FabricTestLedgerV1({ - emitContainerLogs: false, - publishAllPorts: true, - logLevel: testLogLevel, - imageName, - imageVersion, - envVars: new Map([ - ["FABRIC_VERSION", fabricEnvVersion], - ["CA_VERSION", fabricEnvCAVersion], - ]), - useRunningLedger, - }); - log.debug("Fabric image:", ledger.getContainerImageName()); - await ledger.start({ omitPull: false }); - - // Get connection profile - log.info("Get fabric connection profile for Org1..."); - const connectionProfile = await ledger.getConnectionProfileOrg1(); - expect(connectionProfile).toBeTruthy(); - - // Get admin credentials - const [adminName, adminSecret] = ledger.adminCredentials; - - // Enroll admin and user - await enrollAdmin(connectionProfile, tmpWalletDir, adminName, adminSecret); - await enrollUser( - connectionProfile, - tmpWalletDir, - ledgerUserName, - adminName, - ); - - // Generate connector private key and certificate - const pkiGenerator = new SelfSignedPkiGenerator(); - const pki = pkiGenerator.create("localhost"); - connectorCertValue = pki.certificatePem; - connectorPrivKeyValue = pki.privateKeyPem; - const jwtAlgo = "RS512"; - - // Get connector config - log.info("Export connector config before loading the module..."); - process.env["NODE_CONFIG"] = createFabricConnectorConfig( - connectionProfile, - connectorCertValue, - connectorPrivKeyValue, - jwtAlgo, - tmpWalletDir, - adminName, - adminSecret, - ); - - // Load connector module - connectorModule = await import("../../../main/typescript/index"); - - // Run the connector - connectorServer = await connectorModule.startFabricSocketIOConnector(); - expect(connectorServer).toBeTruthy(); - const connectorAddress = connectorServer.address(); - if (!connectorAddress || typeof connectorAddress === "string") { - throw new Error("Unexpected fabric connector AddressInfo type"); - } - log.info( - "Fabric-SocketIO Connector started on:", - `${connectorAddress.address}:${connectorAddress.port}`, - ); - - // Create ApiClient instance - const apiConfigOptions = { - validatorID: "fabric-socketio-test", - validatorURL: `https://localhost:${connectorAddress.port}`, - validatorKeyValue: connectorCertValue, - logLevel: sutLogLevel, - maxCounterRequestID: 1000, - syncFunctionTimeoutMillisecond: 10000, - socketOptions: { - rejectUnauthorized: false, - reconnection: false, - timeout: 60000, - }, - }; - log.debug("ApiClient config:", apiConfigOptions); - apiClient = new SocketIOApiClient(apiConfigOptions); - }); - - afterAll(async () => { - log.info("FINISHING THE TESTS"); - - if (ledger && !leaveLedgerRunning && !useRunningLedger) { - log.info("Stop the fabric ledger..."); - await ledger.stop(); - await ledger.destroy(); - } - - if (apiClient) { - log.info("Close ApiClient connection..."); - apiClient.close(); - } - - if (connectorServer) { - log.info("Stop the fabric connector..."); - await new Promise((resolve) => - connectorServer.close(() => resolve()), - ); - } - - if (tmpWalletDir && !leaveLedgerRunning && !useRunningLedger) { - log.info("Remove tmp wallet dir", tmpWalletDir); - fs.rmSync(tmpWalletDir, { recursive: true }); - } - - log.info("Prune Docker..."); - await pruneDockerAllIfGithubAction({ logLevel: testLogLevel }); - }); - - ////////////////////////////////// - // Test Helpers - ////////////////////////////////// - - /** - * Calls `GetAllAssets` from `basic` CC on the ledger using apiClient.sendSyncRequest - * @returns List of assets - */ - async function getAllAssets() { - const contract = { - channelName: ledgerChannelName, - contractName: ledgerContractName, - }; - const method = { - type: "evaluateTransaction", - command: "GetAllAssets", - }; - const args = { args: [] }; - - const results = await apiClient.sendSyncRequest(contract, method, args); - - expect(results).toBeTruthy(); - expect(results.status).toBe(200); - expect(results.data).toBeTruthy(); - expect(results.data.length).toBeGreaterThanOrEqual(5); // we assume at least 5 assets in future tests - return results.data as { ID: string }[]; - } - - /** - * Calls `GetAllAssets` from `basic` CC on the ledger using apiClient.sendSyncRequest - * - * @param assetID - Asset to read from the ledger. - * @returns asset object - */ - async function readAsset(assetID: string) { - const contract = { - channelName: ledgerChannelName, - contractName: ledgerContractName, - }; - const method = { - type: "evaluateTransaction", - command: "ReadAsset", - }; - const args = { args: [assetID] }; - - const results = await apiClient.sendSyncRequest(contract, method, args); - - expect(results).toBeTruthy(); - expect(results.status).toBe(200); - expect(results.data).toBeTruthy(); - return results.data; - } - - /** - * Calls connector function `sendSignedProposal`, assert correct response, and returns signed proposal. - * @param txProposal - Transaction data we want to send (CC function name, arguments, chancode ID, channel ID) - * @returns Signed proposal that can be feed into `sendSignedProposal` - */ - async function getSignedProposal(txProposal: { - fcn: string; - args: string[]; - chaincodeId: string; - channelId: string; - }) { - const [certPem, privateKeyPem] = await getUserCryptoFromWallet( - ledgerUserName, - tmpWalletDir, - ); - const contract = { channelName: ledgerChannelName }; - const method = { type: "function", command: "sendSignedProposal" }; - const argsParam = { - args: { - transactionProposalReq: txProposal, - certPem, - privateKeyPem, - }, - }; - - const response = await apiClient.sendSyncRequest( - contract, - method, - argsParam, - ); - expect(response).toBeTruthy(); - expect(response.status).toBe(200); - expect(response.data).toBeTruthy(); - expect(response.data.signedCommitProposal).toBeTruthy(); - expect(response.data.commitReq).toBeTruthy(); - expect(response.data.txId).toBeTruthy(); - - const { signedCommitProposal, commitReq } = response.data; - - // signedCommitProposal must be Buffer - signedCommitProposal.signature = Buffer.from( - signedCommitProposal.signature, - ); - signedCommitProposal.proposal_bytes = Buffer.from( - signedCommitProposal.proposal_bytes, - ); - - return { signedCommitProposal, commitReq }; - } - - /** - * Calls connector function `generateUnsignedProposal`, assert correct response, and returns unsigned proposal. - * @param txProposal - Transaction data we want to send (CC function name, arguments, chancode ID, channel ID) - * @returns Unsigned proposal that can be signed locally and feed into `sendSignedProposalV2` - */ - async function getUnsignedProposal(txProposal: unknown, certPem: string) { - const contract = { channelName: ledgerChannelName }; - const method = { type: "function", command: "generateUnsignedProposal" }; - const argsParam = { - args: { - transactionProposalReq: txProposal, - certPem, - }, - }; - - log.info("Sending generateUnsignedProposal"); - - const response = await apiClient.sendSyncRequest( - contract, - method, - argsParam, - ); - expect(response).toBeTruthy(); - expect(response.status).toBe(200); - expect(response.data).toBeTruthy(); - expect(response.data.proposal).toBeTruthy(); - expect(response.data.proposalBuffer).toBeTruthy(); - expect(response.data.proposalBuffer.type).toEqual("Buffer"); - expect(response.data.proposalBuffer.data).toBeTruthy(); - expect(response.data.txId).toBeTruthy(); - - const proposalBuffer = Buffer.from(response.data.proposalBuffer); - expect(proposalBuffer).toBeTruthy(); - - log.info("Received correct response from generateUnsignedProposal"); - - return { - proposal: response.data.proposal, - proposalBuffer, - txId: response.data.txId, - }; - } - - /** - * Calls connector function `generateUnsignedTransaction`, assert correct response, and returns unsigned transaction (commit) proposal. - * @param txProposal - Transaction data we want to send (CC function name, arguments, chancode ID, channel ID) - * @param proposalResponses - Proposal resonses of endorsment step from `sendSignedProposalV2` call. - * @returns Unsigned commit proposal that can be signed locally and feed into `sendSignedTransactionV2` - */ - async function getUnsignedCommitProposal( - txProposal: unknown, - proposalResponses: unknown, - ) { - const contract = { channelName: ledgerChannelName }; - const method = { type: "function", command: "generateUnsignedTransaction" }; - const argsParam = { - args: { - proposal: txProposal, - proposalResponses: proposalResponses, - }, - }; - - log.info("Sending generateUnsignedTransaction"); - - const response = await apiClient.sendSyncRequest( - contract, - method, - argsParam, - ); - - expect(response).toBeTruthy(); - expect(response.status).toBe(200); - expect(response.data).toBeTruthy(); - expect(response.data.txProposalBuffer).toBeTruthy(); - expect(response.data.txProposalBuffer.type).toEqual("Buffer"); - expect(response.data.txProposalBuffer.data).toBeTruthy(); - - const commitProposalBuffer = Buffer.from(response.data.txProposalBuffer); - expect(commitProposalBuffer).toBeTruthy(); - - log.info("Received correct response from generateUnsignedTransaction"); - - return commitProposalBuffer; - } - - ////////////////////////////////// - // Tests - ////////////////////////////////// - - /** - * Test signProposal helper function from fabric-socketio connector module. - */ - test("Signing proposal creates a signature", async () => { - const [, privateKeyPem] = await getUserCryptoFromWallet( - ledgerUserName, - tmpWalletDir, - ); - - const proposal = Buffer.from("test test test test"); - const signedProposal = signProposal(proposal, privateKeyPem); - - expect(signedProposal).toBeTruthy(); - expect(signedProposal.proposal_bytes).toBeTruthy(); - expect(signedProposal.signature).toBeTruthy(); - }); - - /** - * Read all assets, get single asset, comapre that they return the same asset value without any errors. - */ - test("Evaluate transaction returns correct data (GetAllAssets and ReadAsset)", async () => { - const allAssets = await getAllAssets(); - const firstAsset = allAssets.pop(); - if (!firstAsset) { - throw new Error("Unexpected missing firstAsset"); - } - const readSingleAsset = await readAsset(firstAsset.ID); - expect(readSingleAsset).toEqual(firstAsset); - }); - - /** - * Get block by number. - */ - test("Get block by it's number works (both decoded and encoded)", async () => { - const contract = { channelName: ledgerChannelName }; - const method = { type: "function", command: "getBlock" }; - const argsParam = { - blockNumber: 0, - }; - - // Get decoded block - const response = await apiClient.sendSyncRequest( - contract, - method, - argsParam, - ); - expect(response).toBeTruthy(); - expect(response.status).toEqual(200); - expect(response.data).toBeTruthy(); - expect(response.data.header).toBeTruthy(); - expect(response.data.data).toBeTruthy(); - expect(response.data.metadata).toBeTruthy(); - - // Get encoded block - const argsParamEncoded = { - ...argsParam, - skipDecode: true, - }; - - const responseEncoded = await apiClient.sendSyncRequest( - contract, - method, - argsParamEncoded, - ); - expect(responseEncoded).toBeTruthy(); - expect(responseEncoded.status).toEqual(200); - expect(responseEncoded.data).toBeTruthy(); - expect(responseEncoded.data.type).toEqual("Buffer"); - expect(responseEncoded.data.data).toBeTruthy(); - }); - - /** - * Test entire process of sending transaction to the ledger without sharing the key with the connector. - * All proposals are signed on BLP (in this case, jest test) side. - * This test prepares proposal, signs it, sends for endorsment, prepares and sign commit proposal, sends commit transaction. - */ - test("Sending transaction signed on BLP side (without sharing the private key) works", async () => { - const [certPem, privateKeyPem] = await getUserCryptoFromWallet( - ledgerUserName, - tmpWalletDir, - ); - - // Prepare raw transaction proposal - const allAssets = await getAllAssets(); - const assetId = allAssets[1].ID; - const newOwnerName = "UnsignedSendTestXXX"; - const txProposal = { - fcn: "TransferAsset", - args: [assetId, newOwnerName], - chaincodeId: ledgerContractName, - channelId: ledgerChannelName, - }; - log.debug("Raw transaction proposal:", txProposal); - - // Get unsigned proposal - const { proposal, proposalBuffer } = await getUnsignedProposal( - txProposal, - certPem, - ); - - // Prepare signed proposal - const signedProposal = signProposal(proposalBuffer, privateKeyPem); - - // Call sendSignedProposalV2 - const contractSignedProposal = { channelName: ledgerChannelName }; - const methodSignedProposal = { - type: "function", - command: "sendSignedProposalV2", - }; - const argsSignedProposal = { - args: { - signedProposal, - }, - }; - - log.info("Sending sendSignedProposalV2"); - const responseSignedProposal = await apiClient.sendSyncRequest( - contractSignedProposal, - methodSignedProposal, - argsSignedProposal, - ); - - expect(responseSignedProposal).toBeTruthy(); - expect(responseSignedProposal.status).toBe(200); - expect(responseSignedProposal.data).toBeTruthy(); - expect(responseSignedProposal.data.endorsmentStatus).toBeTrue(); - expect(responseSignedProposal.data.proposalResponses).toBeTruthy(); - log.info("Received correct response from sendSignedProposalV2"); - const proposalResponses = responseSignedProposal.data.proposalResponses; - - // Get unsigned commit (transaction) proposal - const commitProposalBuffer = await getUnsignedCommitProposal( - proposal, - proposalResponses, - ); - - // Prepare signed commit proposal - const signedCommitProposal = signProposal( - commitProposalBuffer, - privateKeyPem, - ); - - // Call sendSignedTransactionV2 - const contractSignedTransaction = { channelName: ledgerChannelName }; - const methodSignedTransaction = { - type: "function", - command: "sendSignedTransactionV2", - }; - const argsSignedTransaction = { - args: { - signedCommitProposal: signedCommitProposal, - proposal: proposal, - proposalResponses: proposalResponses, - }, - }; - - log.info("Sending sendSignedTransactionV2"); - const responseSignedTransaction = await apiClient.sendSyncRequest( - contractSignedTransaction, - methodSignedTransaction, - argsSignedTransaction, - ); - - expect(responseSignedTransaction).toBeTruthy(); - expect(responseSignedTransaction.status).toBe(200); - expect(responseSignedTransaction.data).toBeTruthy(); - expect(responseSignedTransaction.data.status).toEqual("SUCCESS"); - log.info("Received correct response from sendSignedTransactionV2"); - }); - - /** - * Send transaction proposal to be signed with keys attached to the request (managed by BLP), - * and then send signed transaction to the ledger. - */ - test("Signining proposal and sending it to the ledger works", async () => { - // Get asset data to be transfered - const allAssets = await getAllAssets(); - const assetId = allAssets[1].ID; - const newOwnerName = "SignAndSendXXX"; - - // Prepare signed proposal - const txProposal = { - fcn: "TransferAsset", - args: [assetId, newOwnerName], - chaincodeId: ledgerContractName, - channelId: ledgerChannelName, - }; - const signedProposal = await getSignedProposal(txProposal); - - // Send transaction - const contract = { channelName: ledgerChannelName }; - const method = { type: "sendSignedTransaction" }; - const args = { args: [signedProposal] }; - - const response = await apiClient.sendSyncRequest(contract, method, args); - expect(response).toBeTruthy(); - expect(response.status).toBe(200); - expect(response.data).toBeTruthy(); - expect(response.data.status).toEqual("SUCCESS"); - }); - - /** - * Send transaction proposal to be signed with keys from connector wallet (managed by the connector). - * Verify correct response from the call. - */ - test("Signining proposal with connector wallet keys work", async () => { - // Get asset data to be transfered - const allAssets = await getAllAssets(); - const assetId = allAssets[2].ID; - const newOwnerName = "SignWithConnectorXXX"; - - // Prepare signed proposal - const contract = { channelName: ledgerChannelName }; - const method = { type: "function", command: "sendSignedProposal" }; - const argsParam = { - args: { - transactionProposalReq: { - fcn: "TransferAsset", - args: [assetId, newOwnerName], - chaincodeId: ledgerContractName, - channelId: ledgerChannelName, - }, - }, - }; - - const response = await apiClient.sendSyncRequest( - contract, - method, - argsParam, - ); - expect(response).toBeTruthy(); - expect(response.status).toBe(200); - expect(response.data).toBeTruthy(); - expect(response.data.signedCommitProposal).toBeTruthy(); - expect(response.data.commitReq).toBeTruthy(); - expect(response.data.txId).toBeTruthy(); - }); - - /** - * Start monitoring for fabric events. - * Send new transaction to the ledger (async) - * Finish after receiving event for matching transaction function. - * This function needs separate timeout, in case of error (no event was received). - */ - test( - "Monitoring for transaction sending works", - async () => { - // Get asset data to be transfered - const allAssets = await getAllAssets(); - const assetId = allAssets[3].ID; - const newOwnerName = "MonitorChangedXXX"; - const txFunctionName = "TransferAsset"; - - // Start monitoring - const monitorPromise = new Promise((resolve, reject) => { - apiClient.watchBlocksV1().subscribe({ - next(event) { - expect(event.status).toBe(200); - - const matchingEvents = event.blockData.filter( - (e) => e.func === txFunctionName, - ); - - if (matchingEvents.length > 0) { - resolve(); - } - }, - error(err) { - log.error("watchBlocksV1() error:", err); - reject(err); - }, - }); - }); - - // Get signed proposal - const signedProposal = await getSignedProposal({ - fcn: txFunctionName, - args: [assetId, newOwnerName], - chaincodeId: ledgerContractName, - channelId: ledgerChannelName, - }); - - // Send transaction (async) - const contract = { channelName: ledgerChannelName }; - const method = { type: "sendSignedTransaction" }; - const args = { args: [signedProposal] }; - apiClient.sendAsyncRequest(contract, method, args); - - expect(monitorPromise).toResolve(); - }, - 60 * 1000, - ); -}); diff --git a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/unit-test/package.json b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/unit-test/package.json index 8523041d5a5..2dbfdb32024 100644 --- a/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/unit-test/package.json +++ b/packages/cactus-plugin-ledger-connector-fabric-socketio/src/test/typescript/unit-test/package.json @@ -12,11 +12,11 @@ "dependencies": { "@types/node": "14.18.54", "config": "1.31.0", - "socket.io-client": "4.5.4", - "ts-node": "9.1.1", "fabric-ca-client": "2.2.18", "fabric-network": "2.2.18", - "shelljs": "0.8.5" + "shelljs": "0.8.5", + "socket.io-client": "4.5.4", + "ts-node": "10.9.1" }, "devDependencies": { "typescript": "4.9.5" diff --git a/packages/cactus-plugin-ledger-connector-iroha/package.json b/packages/cactus-plugin-ledger-connector-iroha/package.json index d7efc7a686e..e3704e186c9 100644 --- a/packages/cactus-plugin-ledger-connector-iroha/package.json +++ b/packages/cactus-plugin-ledger-connector-iroha/package.json @@ -55,6 +55,7 @@ "webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js" }, "dependencies": { + "@grpc/grpc-js": "1.9.5", "@hyperledger/cactus-common": "2.0.0-alpha.2", "@hyperledger/cactus-core": "2.0.0-alpha.2", "@hyperledger/cactus-core-api": "2.0.0-alpha.2", @@ -62,7 +63,6 @@ "axios": "0.21.4", "express": "4.17.1", "fast-safe-stringify": "2.1.1", - "grpc": "1.24.11", "iroha-helpers": "1.5.0", "key-encoder": "2.0.3", "openapi-types": "7.0.1", diff --git a/packages/cactus-plugin-ledger-connector-iroha/src/main/typescript/iroha-transaction-wrapper.ts b/packages/cactus-plugin-ledger-connector-iroha/src/main/typescript/iroha-transaction-wrapper.ts index 226bab7d577..ac61109c74e 100644 --- a/packages/cactus-plugin-ledger-connector-iroha/src/main/typescript/iroha-transaction-wrapper.ts +++ b/packages/cactus-plugin-ledger-connector-iroha/src/main/typescript/iroha-transaction-wrapper.ts @@ -13,7 +13,7 @@ import { } from "./generated/openapi/typescript-axios"; import { RuntimeError } from "run-time-error"; -import * as grpc from "grpc"; +import * as grpc from "@grpc/grpc-js"; import { GrantablePermission, diff --git a/packages/cactus-plugin-persistence-fabric/package.json b/packages/cactus-plugin-persistence-fabric/package.json index 64b5ca513b5..b83616f6c66 100644 --- a/packages/cactus-plugin-persistence-fabric/package.json +++ b/packages/cactus-plugin-persistence-fabric/package.json @@ -86,7 +86,7 @@ "@types/uuid": "8.3.4", "body-parser": "1.19.0", "express": "4.17.1", - "fabric-network": "1.4.19", + "fabric-network": "2.2.18", "uuid": "8.3.2" }, "engines": { diff --git a/packages/cactus-plugin-persistence-fabric/src/test/typescript/integration/fabric-setup-helpers.ts b/packages/cactus-plugin-persistence-fabric/src/test/typescript/integration/fabric-setup-helpers.ts deleted file mode 100644 index 55a6c132edb..00000000000 --- a/packages/cactus-plugin-persistence-fabric/src/test/typescript/integration/fabric-setup-helpers.ts +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Fabric helpers to be used by functional tests. - * Works with Fabric SDK 1.4 - that's why it's not included in fabric ledger test class. - * Most functions are based on fabric-samples and utils scripts from tools/docker/fabric-all-in-one/asset-transfer-basic-utils - */ - -import { LoggerProvider, Logger } from "@hyperledger/cactus-common"; -import { FileSystemWallet, Gateway, X509WalletMixin } from "fabric-network"; -import FabricCAServices from "fabric-ca-client"; - -// Unit Test logger setup -const log: Logger = LoggerProvider.getOrCreate({ - label: "fabric-setup-helpers", - level: "info", -}); - -/** - * Enroll admin user on fabric and store it's credential in local filesystem wallet. - * - * @param connectionProfile - Fabric connection profile JSON. - * @param walletPath - Local filesystem wallet path. - * @param enrollmentID - admin username. - * @param enrollmentSecret - admin secret. - */ -export async function enrollAdmin( - connectionProfile: any, - walletPath: string, - enrollmentID: string, - enrollmentSecret: string, -) { - log.info( - `Enroll admin user with enrollmentID='${enrollmentID}' and enrollmentSecret='${enrollmentSecret}'`, - ); - - // Create a new CA client for interacting with the CA. - const caName = connectionProfile.organizations.Org1.certificateAuthorities[0]; - const caInfo = connectionProfile.certificateAuthorities[caName]; - const caTLSCACerts = caInfo.tlsCACerts.pem; - const ca = new FabricCAServices( - caInfo.url, - { trustedRoots: caTLSCACerts, verify: false }, - caInfo.caName, - ); - - // Create a new file system based wallet for managing identities. - const wallet = new FileSystemWallet(walletPath); - - // Enroll admin user if not exist yet - const adminExists = await wallet.exists(enrollmentID); - if (!adminExists) { - const enrollment = await ca.enroll({ - enrollmentID, - enrollmentSecret, - }); - const identity = X509WalletMixin.createIdentity( - connectionProfile.organizations.Org1.mspid, - enrollment.certificate, - enrollment.key.toBytes(), - ); - await wallet.import(enrollmentID, identity); - log.info( - `Successfully enrolled admin user ${enrollmentID} and imported it into the wallet. Current state:`, - await wallet.list(), - ); - } -} - -/** - * Enroll a user on fabric and store it's credential in local filesystem wallet. - * Must be called after `enrollAdmin()` - * - * @param connectionProfile - Fabric connection profile JSON. - * @param walletPath - Local filesystem wallet path. - * @param userName - regular username to enroll. - * @param adminUserName - admin username (must be already enrolled) - */ -export async function enrollUser( - connectionProfile: any, - walletPath: string, - userName: string, - adminUserName: string, -) { - log.info(`Enroll user with userName='${userName}'`); - - // Create a new file system based wallet for managing identities. - const wallet = new FileSystemWallet(walletPath); - - // Check to see if we've already enrolled the user. - const userExists = await wallet.exists(userName); - if (userExists) { - console.log( - "An identity for the user userName already exists in the wallet", - ); - return; - } - - // Check to see if we've already enrolled the admin user. - const adminExists = await wallet.exists(adminUserName); - if (!adminExists) { - throw new Error( - "An identity for the admin user adminUserName does not exist in the wallet", - ); - } - - // Create a new gateway for connecting to our peer node. - const gateway = new Gateway(); - await gateway.connect(connectionProfile, { - wallet, - identity: adminUserName, - discovery: { enabled: true, asLocalhost: true }, - }); - - // Get the CA client object from the gateway for interacting with the CA. - const ca = gateway.getClient().getCertificateAuthority(); - const adminIdentity = gateway.getCurrentIdentity(); - - // Register the user, enroll the user, and import the new identity into the wallet. - const secret = await ca.register( - { - affiliation: "org1.department1", - enrollmentID: userName, - role: "client", - }, - adminIdentity, - ); - const enrollment = await ca.enroll({ - enrollmentID: userName, - enrollmentSecret: secret, - }); - const userIdentity: any = X509WalletMixin.createIdentity( - connectionProfile.organizations.Org1.mspid, - enrollment.certificate, - enrollment.key.toBytes(), - ); - await wallet.import(userName, userIdentity); - log.info( - `Successfully enrolled user ${userName} and imported it into the wallet. Current state:`, - await wallet.list(), - ); - - const identity = { - credentials: { - certificate: userIdentity.certificate, - privateKey: userIdentity.privateKey, - }, - mspId: userIdentity.mspId, - type: userIdentity.type, - }; - return identity; -} - -/** - * Get cryptographic data for specified user from local filesystem wallet. - * Can be used to sign transactions as specified user. - * - * @param name - Username enrolled in wallet. - * @param walletPath - Local filesystem wallet path. - * @returns A tuple [certificatePem, privateKeyPem] - */ -export async function getUserCryptoFromWallet( - name: string, - walletPath: string, -): Promise<[string, string, string, string]> { - const wallet = new FileSystemWallet(walletPath); - - const submitterExists = await wallet.exists(name); - if (!submitterExists) { - throw new Error(`User ${name} does not exist in wallet ${walletPath}`); - } - - const submitterIdentity: any = await wallet.export(name); - const certPem = (submitterIdentity as any).certificate; - const privateKeyPem = (submitterIdentity as any).privateKey; - const mspId = (submitterIdentity as any).mspId; - let certType = ""; - if ((submitterIdentity as any).type == "X509") { - certType = "X.509"; - } - (submitterIdentity as any).type; - return [certPem, privateKeyPem, mspId, certType]; -} diff --git a/packages/cactus-plugin-persistence-fabric/src/test/typescript/integration/persistence-fabric-functional.test.ts b/packages/cactus-plugin-persistence-fabric/src/test/typescript/integration/persistence-fabric-functional.test.ts deleted file mode 100644 index 26e645051ac..00000000000 --- a/packages/cactus-plugin-persistence-fabric/src/test/typescript/integration/persistence-fabric-functional.test.ts +++ /dev/null @@ -1,837 +0,0 @@ -/** - * Functional test of basic operations on connector-fabric-socketio (packages/cactus-plugin-ledger-connector-fabric-socketio) - * Assumes sample CC was is deployed on the test ledger. - * Tests include sending and evaluation transactions, and monitoring for events. - * - * You can speed up development or troubleshooting by using same ledger repeat. - * 1. Remove fabric wallets from previous runs - `rm -rf /tmp/fabric-test-wallet*`. Repeat this everytime you restart ledger. - * 2. Change variable `leaveLedgerRunning` to true. - * 3. Run this functional test. It will leave the ledger running, and will enroll the users to common wallet location. - * 4. Change `useRunningLedger` to true. The following test runs will not setup the ledger again. - * Note: - * You may get a warning about open SIGNREQUEST handles after the test finishes. - * These are false-positives, and should be fixed in jest v28.1.0 - * More details: https://github.com/facebook/jest/pull/12789 - */ - -import fs from "fs"; -import path from "path"; -import os from "os"; -import "jest-extended"; - -import http from "http"; -import { AddressInfo } from "net"; -import { v4 as uuidv4 } from "uuid"; -import bodyParser from "body-parser"; -import express from "express"; -import { Server as SocketIoServer } from "socket.io"; -import { DiscoveryOptions } from "fabric-network"; -import { PluginPersistenceFabric } from "../../../main/typescript"; -import { - DEFAULT_FABRIC_2_AIO_FABRIC_VERSION, - DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - DEFAULT_FABRIC_2_AIO_IMAGE_VERSION, - FabricTestLedgerV1, - pruneDockerAllIfGithubAction, - SelfSignedPkiGenerator, - // PostgresTestContainer, -} from "@hyperledger/cactus-test-tooling"; - -import { - LogLevelDesc, - LoggerProvider, - Logger, - IListenOptions, - Servers, -} from "@hyperledger/cactus-common"; - -import { Constants, Configuration } from "@hyperledger/cactus-core-api"; - -import { PluginRegistry } from "@hyperledger/cactus-core"; - -import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; -import { - PluginLedgerConnectorFabric, - FabricContractInvocationType, - DefaultEventHandlerStrategy, - FabricSigningCredential, - FabricApiClient, - GatewayOptions, -} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; -// Mocked DB setup - -import DatabaseClient from "../../../main/typescript/db-client/db-client"; -jest.mock("../../../main/typescript/db-client/db-client"); -const DatabaseClientMock = (DatabaseClient as unknown) as jest.Mock; - -import { - enrollAdmin, - enrollUser, - getUserCryptoFromWallet, -} from "./fabric-setup-helpers"; - -////////////////////////////////// -// Constants -////////////////////////////////// - -// const postgresImageName = "postgres"; -// const postgresImageVersion = "14.6-alpine"; -const testLogLevel: LogLevelDesc = "info"; -const sutLogLevel: LogLevelDesc = "info"; -const setupTimeout = 1000 * 60; // 1 minute timeout for setup -// const testTimeout = 1000 * 60 * 3; // 3 minutes timeout for some async tests - -const imageName = DEFAULT_FABRIC_2_AIO_IMAGE_NAME; -const imageVersion = DEFAULT_FABRIC_2_AIO_IMAGE_VERSION; -const fabricEnvVersion = DEFAULT_FABRIC_2_AIO_FABRIC_VERSION; -const fabricEnvCAVersion = "1.4.9"; -const ledgerUserName = "appUser"; -const ledgerChannelName = "mychannel"; -const ledgerContractName = "basic"; -const leaveLedgerRunning = false; // default: false -const useRunningLedger = false; // default: false - -///////////////////////////////// - -// Logger setup -const log: Logger = LoggerProvider.getOrCreate({ - label: "persistence-fabric-functional.test", - level: testLogLevel, -}); - -/** - * Main test suite - */ -describe("Persistence Fabric", () => { - let ledger: FabricTestLedgerV1; - let signingCredential: FabricSigningCredential; - let fabricConnectorPlugin: PluginLedgerConnectorFabric; - let connectorServer: http.Server; - let socketioServer: SocketIoServer; - let apiClient: FabricApiClient; - let persistence: PluginPersistenceFabric; - let gatewayOptions: GatewayOptions; - let dbClientInstance: any; - let dbClient: DatabaseClient; - let tmpWalletDir: string; - let connectorCertValue: string; - let connectorPrivKeyValue: string; - - let instanceId: string; - - function insertResponseMock(testData: { - fabric_block_id: string; - fabric_block_num: number; - fabric_block_data: string; - }) { - (dbClientInstance.insertBlockDataEntry as jest.Mock).mockReturnValue( - testData, - ); - } - - function getMaxBlockNumberMock(blockNumber: number) { - (dbClientInstance.getMaxBlockNumber as jest.Mock).mockReturnValue( - blockNumber, - ); - } - - function missBlock10(blockNumber: number) { - if (blockNumber === 10) { - (dbClientInstance.isThisBlockInDB as jest.Mock).mockReturnValue({ - command: "SELECT", - rowCount: 0, - rows: [], - }); - } else { - (dbClientInstance.isThisBlockInDB as jest.Mock).mockReturnValue( - blockNumber, - ); - } - } - - function clearMockTokenMetadata() { - for (const mockMethodName in dbClientInstance) { - const mockMethod = dbClientInstance[mockMethodName]; - if ("mockClear" in mockMethod) { - mockMethod.mockClear; - } - } - } - - function createFabricConnectorConfig( - connectionProfile: Record, - connectorCert: string, - connectorPrivKey: string, - jwtAlgo: string, - walletDir: string, - adminName: string, - adminSecret: string, - ) { - // Get Org CA - const caId = connectionProfile.organizations.Org1.certificateAuthorities[0]; - log.debug("Use CA:", caId); - - // Get Orderer ID - const ordererId = connectionProfile.channels[ledgerChannelName].orderers[0]; - log.debug("Use Orderer:", ordererId); - - const connectorConfig: any = { - sslParam: { - port: 0, // random port - keyValue: connectorPrivKey, - certValue: connectorCert, - jwtAlgo: jwtAlgo, - }, - logLevel: sutLogLevel, - fabric: { - mspid: connectionProfile.organizations.Org1.mspid, - keystore: walletDir, - connUserName: ledgerUserName, - contractName: ledgerContractName, - peers: [], // will be filled below - orderer: { - name: - connectionProfile.orderers[ordererId].grpcOptions[ - "ssl-target-name-override" - ], - url: connectionProfile.orderers[ordererId].url, - tlscaValue: connectionProfile.orderers[ordererId].tlsCACerts.pem, - }, - ca: { - name: connectionProfile.certificateAuthorities[caId].caName, - url: connectionProfile.certificateAuthorities[caId].url, - }, - submitter: { - name: adminName, - secret: adminSecret, - }, - channelName: ledgerChannelName, - chaincodeId: ledgerContractName, - }, - }; - - // Add peers - connectionProfile.organizations.Org1.peers.forEach((peerName: string) => { - log.debug("Add Peer:", peerName); - const peer = connectionProfile.peers[peerName]; - connectorConfig.fabric.peers.push({ - name: peer.grpcOptions["ssl-target-name-override"], - requests: peer.url, - tlscaValue: peer.tlsCACerts.pem, - }); - }); - - const configJson = JSON.stringify(connectorConfig); - log.debug("Connector Config:", configJson); - return configJson; - } - - ////////////////////////////////// - // Environment Setup - ////////////////////////////////// - - beforeAll(async () => { - log.info("Prune Docker..."); - await pruneDockerAllIfGithubAction({ logLevel: testLogLevel }); - // this is to use only if you want to start integration with real container and database - // postgresContainer = new PostgresTestContainer({ - // imageName: postgresImageName, - // imageVersion: postgresImageVersion, - // logLevel: testLogLevel, - // envVars: ["POSTGRES_USER=postgres", "POSTGRES_PASSWORD=postgres"], - // }); - // await postgresContainer.start(); - - // const postgresPort = await postgresContainer.getPostgresPort(); - // expect(postgresPort).toBeTruthy(); - // log.info(`Postgres running at localhost:${postgresPort}`); - - //log.info("Create PostgresDatabaseClient"); - // dbClient = new DatabaseClient({ - // connectionString: `postgresql://postgres:postgres@localhost:${postgresPort}/postgres`, - // logLevel: sutLogLevel, - // }); - - //log.info("Connect the PostgreSQL PostgresDatabaseClient"); - // await dbClient.connect(); - // await dbClient.client.query( - // `CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; - // CREATE ROLE anon NOLOGIN; - // CREATE ROLE authenticated NOLOGIN; - // CREATE ROLE service_role NOLOGIN; - // CREATE ROLE supabase_admin NOLOGIN;`, - // ); - - //log.info("Initialize the test DB Schema"); - // await dbClient.initializePlugin(testPluginName, testPluginInstanceId); - - // Prepare local filesystem wallet path - if (leaveLedgerRunning || useRunningLedger) { - tmpWalletDir = path.join(os.tmpdir(), "fabric-test-wallet-common"); - log.warn("Using common wallet path when re-using the same ledger."); - try { - fs.mkdirSync(tmpWalletDir); - } catch (err: any) { - if (!err.message.includes("EEXIST")) { - log.error( - "Unexpected exception when creating common wallet dir:", - err, - ); - throw err; - } - } - } else { - log.info("Create temp dir for wallet - will be removed later..."); - tmpWalletDir = fs.mkdtempSync( - path.join(os.tmpdir(), "fabric-test-wallet"), - ); - } - log.info("Wallet path:", tmpWalletDir); - expect(tmpWalletDir).toBeTruthy(); - - // Start Ledger - - log.info("Start FabricTestLedgerV1..."); - log.debug("Version:", fabricEnvVersion, "CA Version:", fabricEnvCAVersion); - ledger = new FabricTestLedgerV1({ - emitContainerLogs: false, - publishAllPorts: true, - logLevel: testLogLevel, - imageName, - imageVersion, - envVars: new Map([ - ["FABRIC_VERSION", fabricEnvVersion], - ["CA_VERSION", fabricEnvCAVersion], - ]), - useRunningLedger, - }); - log.debug("Fabric image:", ledger.getContainerImageName()); - await ledger.start({ omitPull: false }); - - // Get connection profile - log.info("Get fabric connection profile for Org1..."); - const connectionProfile = await ledger.getConnectionProfileOrg1(); - expect(connectionProfile).toBeTruthy(); - // Get admin credentials - const [adminName, adminSecret] = ledger.adminCredentials; - - await enrollAdmin(connectionProfile, tmpWalletDir, adminName, adminSecret); - // #useridentity test - await enrollUser( - connectionProfile, - tmpWalletDir, - ledgerUserName, - adminName, - ); - const userIdent = await getUserCryptoFromWallet("appUser", tmpWalletDir); - const identityTest = { - credentials: { - certificate: userIdent[0], - privateKey: userIdent[1], - }, - mspId: userIdent[2], - type: userIdent[3], - }; - const pkiGenerator = new SelfSignedPkiGenerator(); - const pki = pkiGenerator.create("localhost"); - connectorCertValue = pki.certificatePem; - connectorPrivKeyValue = pki.privateKeyPem; - const jwtAlgo = "RS512"; - - log.info("Export connector config before loading the module..."); - process.env["NODE_CONFIG"] = createFabricConnectorConfig( - connectionProfile, - connectorCertValue, - connectorPrivKeyValue, - jwtAlgo, - tmpWalletDir, - adminName, - adminSecret, - ); - - // Create Keychain Plugin - const keychainId = uuidv4(); - const keychainEntryKey = "user2"; - const keychainPlugin = new PluginKeychainMemory({ - instanceId: uuidv4(), - keychainId, - logLevel: sutLogLevel, - backend: new Map([[keychainEntryKey, JSON.stringify(identityTest)]]), - }); - - gatewayOptions = { - identity: keychainEntryKey, - wallet: { - keychain: { - keychainId, - keychainRef: keychainEntryKey, - }, - }, - }; - - signingCredential = { - keychainId, - keychainRef: keychainEntryKey, - }; - log.debug("signingCredential", signingCredential); - - // Create Connector Plugin - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - fabricConnectorPlugin = new PluginLedgerConnectorFabric({ - instanceId: uuidv4(), - pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }), - sshConfig: await ledger.getSshConfig(), - cliContainerEnv: {}, - peerBinary: "/fabric-samples/bin/peer", - logLevel: sutLogLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAnyfortx, - commitTimeout: 300, - }, - }); - - // Run http server - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - connectorServer = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server: connectorServer, - }; - - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - - const apiHost = `http://${addressInfo.address}:${addressInfo.port}`; - - socketioServer = new SocketIoServer(connectorServer, { - path: Constants.SocketIoConnectionPathV1, - }); - - // Register services - await fabricConnectorPlugin.getOrCreateWebServices(); - await fabricConnectorPlugin.registerWebServices(expressApp, socketioServer); - - // Create ApiClient - const apiConfig = new Configuration({ basePath: apiHost }); - apiClient = new FabricApiClient(apiConfig); - log.debug("apiClient", apiClient); - DatabaseClientMock.mockClear(); - persistence = new PluginPersistenceFabric({ - gatewayOptions, - apiClient, - logLevel: testLogLevel, - instanceId, - connectionString: `db-is-mocked`, - }); - expect(DatabaseClientMock).toHaveBeenCalledTimes(1); - dbClientInstance = DatabaseClientMock.mock.instances[0]; - expect(dbClientInstance).toBeTruthy(); - }); - - afterAll(async () => { - log.info("FINISHING THE TESTS"); - - if (ledger && !leaveLedgerRunning && !useRunningLedger) { - log.info("Stop the fabric ledger..."); - await ledger.stop(); - await ledger.destroy(); - } - - if (fabricConnectorPlugin) { - log.info("Close Fabric connector..."); - fabricConnectorPlugin.shutdown(); - } - - if (socketioServer) { - log.info("Stop the SocketIO server connector..."); - await new Promise((resolve) => - socketioServer.close(() => resolve()), - ); - } - - if (apiClient) { - log.info("Close ApiClient connections..."); - apiClient.close(); - } - if (connectorServer) { - log.info("Stop the HTTP server connector..."); - await new Promise((resolve) => - connectorServer.close(() => resolve()), - ); - } - - if (persistence) { - await persistence.shutdown(); - } - - if (tmpWalletDir && !leaveLedgerRunning && !useRunningLedger) { - log.info("Remove tmp wallet dir", tmpWalletDir); - fs.rmSync(tmpWalletDir, { recursive: true }); - } - - if (dbClient) { - log.info("Disconnect the PostgresDatabaseClient"); - await dbClient.shutdown(); - } - - // Wait for monitor to be terminated - await new Promise((resolve) => setTimeout(resolve, 8000)); - - log.info("Prune Docker..."); - await pruneDockerAllIfGithubAction({ logLevel: testLogLevel }); - }); - - beforeEach(() => { - clearMockTokenMetadata(); - }, setupTimeout); - - test("onPluginInit creates DB schema and fetches the monitored tokens", async () => { - await persistence.onPluginInit(); - const initDBCalls = dbClientInstance.initializePlugin.mock.calls; - expect(initDBCalls.length).toBe(1); - expect(persistence).toBeTruthy(); - }); - - test("getblock", async () => { - const blockNumber = "1"; - const block = await persistence.getBlockFromLedger(blockNumber); - log.warn("getBlockFromLedger", JSON.stringify(block)); - expect(block).toBeTruthy(); - expect(block).toMatchObject({ - decodedBlock: { - header: expect.toBeObject(), - data: expect.toBeObject(), - metadata: expect.toBeObject(), - }, - }); - }); - - //creating test transaction on ledger. - test("create test transaction 1", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest1", "green", "111", "someOwner", "299"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 2", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest2", "blue", "111", "someOwner1", "299"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 3", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest3", "blue", "13331", "someOwner3", "299"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 4", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest4", "yellow", "111", "someOwner1", "299"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 5", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest5", "black", "121", "someOwner3", "199"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 6", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest6", "blue", "112", "someOwner1", "219"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 7", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest7", "yellow", "111", "someOwner3", "229"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - - //creating test transaction on ledger. - test("create test transaction 8", async () => { - const createAssetResponse = await apiClient.runTransactionV1({ - signingCredential, - channelName: ledgerChannelName, - invocationType: FabricContractInvocationType.Send, - contractName: ledgerContractName, - methodName: "CreateAsset", - params: ["CactusTransactionsTest8", "blue", "2111", "someOwner3", "2119"], - }); - - expect(createAssetResponse).toBeTruthy(); - expect(createAssetResponse.status).toEqual(200); - expect(createAssetResponse.data).toBeTruthy(); - expect(createAssetResponse.data.success).toBeTrue(); - expect(createAssetResponse.data.transactionId).toBeTruthy(); - }); - // end of helpers - - // getblock method test should return block data from ledger - test("insertBlockDataEntry", async () => { - const dataForInsert = { - fabric_block_id: - "69d35348e3904a2cc5b85134da1e394ae5e4e64282ac577aa7872e12870a8be0", - fabric_block_num: 1, - fabric_block_data: "testData", - }; - insertResponseMock(dataForInsert); - const insertBlockDataEntry = await persistence.insertBlockDataEntry( - dataForInsert, - ); - - expect(insertBlockDataEntry).toBeTruthy(); - log.warn("insertBlockDataEntry", insertBlockDataEntry); - }); - // getblock method test should return block data from ledger - test("getblock", async () => { - const blockNumber = "1"; - const block = await persistence.getBlockFromLedger(blockNumber); - - expect(block).toBeTruthy(); - expect(block).toMatchObject({ - decodedBlock: { - header: expect.toBeObject(), - data: expect.toBeObject(), - metadata: expect.toBeObject(), - }, - }); - }); - - // checks if all blocks from ledger are inserted into DB. If not, returns array with numbers of missing blocks. - test("log all not synchronized blocks", async () => { - getMaxBlockNumberMock(11); - const getMaxBlockNumber = await dbClientInstance.getMaxBlockNumber(11); - const missedBlocks: number[] = []; - let howManyBlocksMissing = 0; - log.warn("getMaxBlockNumber", getMaxBlockNumber); - - for (let i = getMaxBlockNumber; i >= 0; i--) { - try { - missBlock10(i); - - persistence.getBlockFromLedger(`${i}`); - - const isThisBlockInDB = await dbClientInstance.isThisBlockInDB(i); - expect(isThisBlockInDB).toBeTruthy(); - log.info("isThisBlockInDB", isThisBlockInDB); - if (isThisBlockInDB.rowCount === 0) { - howManyBlocksMissing += 1; - missedBlocks.push(i); - } - } catch (err: unknown) { - const isThisBlockInDB = await dbClientInstance.isThisBlockInDB(i); - if (isThisBlockInDB.rowCount === 0) { - howManyBlocksMissing += 1; - missedBlocks.push(i); - } - } - } - log.info(`missedBlocks: ${howManyBlocksMissing}`, missedBlocks); - expect(getMaxBlockNumber).toBeTruthy(); - expect(getMaxBlockNumber).toEqual(11); - expect(missedBlocks).toEqual([10]); - }); - - test("initialBlocksSynchronization", async () => { - const initialBlocksSynchronization = await persistence.initialBlocksSynchronization( - 10, - ); - expect(initialBlocksSynchronization).toBeTruthy(); - expect(initialBlocksSynchronization).toEqual("done"); - }); - - test("get latest block in ledger from within persistence plugin", async () => { - const lastBlockInPlugin = await persistence.lastBlockInLedger( - signingCredential, - ); - log.info( - "latest block in ledger collected from within plugin: ", - lastBlockInPlugin, - ); - - expect(lastBlockInPlugin).toBeTruthy(); - }); - // Those are other test scenarios when we check not missing block but normal synchro - // test("continueBlocksSynchronization", async () => { - // const continuousBlocksSynchronization = await persistence.continueBlocksSynchronization(signingCredential); - // expect(continuousBlocksSynchronization).toEqual("done"); - //}); - - // this test will finish with timout only - //test("continuousBlocksSynchronization", async () => { - // const continuousBlocksSynchronization = await persistence.continuousBlocksSynchronization(signingCredential); - // expect(continuousBlocksSynchronization).toEqual("stopped"); - //}); - - // test("changeSynchronization", async () => { - // const changeSynchronization = await persistence.changeSynchronization(); - // expect(changeSynchronization).toBeTruthy(); - // expect(changeSynchronization).toEqual(true || false); - // }); - - test("LastBlockChanged", async () => { - const LastBlockChanged = persistence.currentLastSeenBlock(); - log.info("Getting Lastblock from plugin for analyze"); - - expect(LastBlockChanged).toBeTruthy(); - }); - - test(" last block setting to 14", async () => { - const LastBlockChanged = persistence.setLastBlockConsidered(14); - log.info("setting Lastblock from plugin for analyze"); - expect(LastBlockChanged).toBeTruthy(); - expect(LastBlockChanged).toEqual(14); - }); - test("currentLastBlock", async () => { - const currentLastBlock = persistence.currentLastBlock(); - log.info("Getting Lastblock from plugin for analyze"); - - expect(currentLastBlock).toBeTruthy(); - expect(currentLastBlock).toBeGreaterThanOrEqual(1); - }); - - test("Migration of 12 block Test", async () => { - const blockTotest = await persistence.migrateBlockNrWithTransactions("12"); - log.info("Getting block from ledger for analyze"); - expect(blockTotest).toBeTruthy(); - expect(blockTotest).toEqual(true); - }); - - test("Check Last block set", async () => { - const LastBlockChanged = persistence.currentLastBlock(); - log.info("Getting Lastblock from plugin for analyze"); - expect(LastBlockChanged).toBeTruthy(); - }); - - test("check missing blocks", async () => { - missBlock10(10); - const missingBlocksCheck = await persistence.whichBlocksAreMissingInDdSimple(); - log.info( - "Getting missing blocks from plugin for analyze", - missingBlocksCheck, - ); - expect(missingBlocksCheck).not.toBe(undefined); - expect(missingBlocksCheck).toBeGreaterThanOrEqual(1); - }); - - test("check missing blocks count", async () => { - const missingBlocksCount = persistence.showHowManyBlocksMissing(); - log.info( - "Getting missingBlocksCount from plugin for analyze", - missingBlocksCount, - ); - - expect(missingBlocksCount).not.toBe(undefined); - expect(missingBlocksCount).toBeGreaterThanOrEqual(1); - }); - - test("fill missing blocks from ledger into database", async () => { - const missingBlocksCheck = await persistence.synchronizeOnlyMissedBlocks(); - log.info( - "Getting missing blocks from plugin for analyze", - missingBlocksCheck, - ); - expect(missingBlocksCheck).toBe(0); - }); - - test("check missing blocks count after fill inside database", async () => { - const missingBlocksCount = persistence.showHowManyBlocksMissing(); - log.info( - "After migration missing blocks getting missingBlocksCount from plugin for analyze", - missingBlocksCount, - ); - expect(missingBlocksCount).toBe(0); - }); -}); diff --git a/tools/docker/fabric-all-in-one/asset-transfer-basic-utils/package.json b/tools/docker/fabric-all-in-one/asset-transfer-basic-utils/package.json index b897d38a6b9..77edf1ce3e8 100644 --- a/tools/docker/fabric-all-in-one/asset-transfer-basic-utils/package.json +++ b/tools/docker/fabric-all-in-one/asset-transfer-basic-utils/package.json @@ -10,7 +10,6 @@ "author": "Hyperledger", "license": "Apache-2.0", "dependencies": { - "fabric-ca-client": "1.4.19", - "fabric-network": "1.4.19" + "fabric-network": "2.2.18" } } diff --git a/weaver/common/protos-js/package.json b/weaver/common/protos-js/package.json index 175730b8e9e..9211433cc75 100644 --- a/weaver/common/protos-js/package.json +++ b/weaver/common/protos-js/package.json @@ -38,10 +38,9 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "google-protobuf": "3.21.2", - "grpc": "1.24.11", "grpc-tools": "1.12.4" }, "devDependencies": { diff --git a/weaver/core/drivers/fabric-driver/package-local.json b/weaver/core/drivers/fabric-driver/package-local.json index adfc7ee3682..406840e14b8 100644 --- a/weaver/core/drivers/fabric-driver/package-local.json +++ b/weaver/core/drivers/fabric-driver/package-local.json @@ -20,7 +20,7 @@ "license": "Apache-2.0", "dependencies": { "@fidm/x509": "1.2.1", - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "file:./protos-js", "@hyperledger/cacti-weaver-sdk-fabric": "file:./cacti-weaver-sdk-fabric", "@typescript-eslint/eslint-plugin": "5.62.0", diff --git a/weaver/core/drivers/fabric-driver/package.json b/weaver/core/drivers/fabric-driver/package.json index dfafc2b4aff..803dc6fc767 100644 --- a/weaver/core/drivers/fabric-driver/package.json +++ b/weaver/core/drivers/fabric-driver/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "@fidm/x509": "1.2.1", - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "2.0.0-alpha.2", "@hyperledger/cacti-weaver-sdk-fabric": "2.0.0-alpha.2", "@typescript-eslint/eslint-plugin": "5.62.0", diff --git a/weaver/core/identity-management/iin-agent/package-local.json b/weaver/core/identity-management/iin-agent/package-local.json index ce60b518a60..4534f34d94e 100644 --- a/weaver/core/identity-management/iin-agent/package-local.json +++ b/weaver/core/identity-management/iin-agent/package-local.json @@ -20,7 +20,7 @@ "license": "Apache-2.0", "dependencies": { "@fidm/x509": "1.2.1", - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "file:./protos-js", "@hyperledger/cacti-weaver-sdk-fabric": "file:./cacti-weaver-sdk-fabric", "@typescript-eslint/eslint-plugin": "3.10.1", diff --git a/weaver/core/identity-management/iin-agent/package.json b/weaver/core/identity-management/iin-agent/package.json index cdd18f35820..ec2b426d43e 100644 --- a/weaver/core/identity-management/iin-agent/package.json +++ b/weaver/core/identity-management/iin-agent/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "@fidm/x509": "1.2.1", - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "2.0.0-alpha.2", "@hyperledger/cacti-weaver-sdk-fabric": "2.0.0-alpha.2", "@typescript-eslint/eslint-plugin": "3.10.1", diff --git a/weaver/samples/fabric/fabric-cli/package-local.json b/weaver/samples/fabric/fabric-cli/package-local.json index d6301896f08..49069a54723 100644 --- a/weaver/samples/fabric/fabric-cli/package-local.json +++ b/weaver/samples/fabric/fabric-cli/package-local.json @@ -51,7 +51,7 @@ "y18n": "4.0.3" }, "devDependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "@types/express": "4.17.17", "@types/jest": "29.5.3", diff --git a/weaver/samples/fabric/fabric-cli/package.json b/weaver/samples/fabric/fabric-cli/package.json index 5fbffb4eb1d..8a66bb8707c 100644 --- a/weaver/samples/fabric/fabric-cli/package.json +++ b/weaver/samples/fabric/fabric-cli/package.json @@ -59,7 +59,7 @@ "y18n": "4.0.3" }, "devDependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "@types/express": "4.17.17", "@types/jest": "29.5.3", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json index 8908e9b293b..54ce96ce33a 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json @@ -27,7 +27,7 @@ "npm": ">=6.0.0 <=8.15.0" }, "dependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "@hyperledger/cacti-weaver-protos-js": "file:./protos-js", "elliptic": "6.5.4", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package.json b/weaver/sdks/fabric/interoperation-node-sdk/package.json index 3033d0bcbce..a0b19d34e97 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package.json @@ -38,7 +38,7 @@ ] }, "dependencies": { - "@grpc/grpc-js": "1.9.0", + "@grpc/grpc-js": "1.9.5", "@grpc/proto-loader": "0.7.8", "@hyperledger/cacti-weaver-protos-js": "2.0.0-alpha.2", "elliptic": "6.5.4", diff --git a/webpack.prod.node.js b/webpack.prod.node.js index 884f7f9e891..a1e8b896900 100644 --- a/webpack.prod.node.js +++ b/webpack.prod.node.js @@ -69,7 +69,6 @@ module.exports = { externals: { "swarm-js": "swarm-js", "node-ssh": "node-ssh", - "grpc": "grpc", npm: "npm", "fabric-client": "fabric-client", "fabric-ca-client": "fabric-ca-client", diff --git a/yarn.lock b/yarn.lock index 24ee6cb6f45..ca61d7a7fc9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5207,23 +5207,13 @@ __metadata: languageName: node linkType: hard -"@grpc/grpc-js@npm:1.9.0": - version: 1.9.0 - resolution: "@grpc/grpc-js@npm:1.9.0" +"@grpc/grpc-js@npm:1.9.5": + version: 1.9.5 + resolution: "@grpc/grpc-js@npm:1.9.5" dependencies: - "@grpc/proto-loader": ^0.7.0 + "@grpc/proto-loader": ^0.7.8 "@types/node": ">=12.12.47" - checksum: 32817c84e4b0eedc523b123cbfce935cafedbf33f94f7609931a878dd6945c4d83b4a781a9d7dedbd4fd273a95e8bd3b0de5f6ca920112331e1c3279fa104b3e - languageName: node - linkType: hard - -"@grpc/grpc-js@npm:^1.3.4": - version: 1.8.14 - resolution: "@grpc/grpc-js@npm:1.8.14" - dependencies: - "@grpc/proto-loader": ^0.7.0 - "@types/node": ">=12.12.47" - checksum: 7b889ae67cde5eb9b4feb92d54e73945d881309b9b879a2dde478fa7850b99835efa7592a8154a0f923851d7a18a177c106f5f52b45061180bb04aef7783c1c9 + checksum: 06834554a0935906652b4b9c5c71f08dd9bdcd4a00d65465c569eae770a9856ecabf7711290bf6d935a8127779c1f35d9cc8cf029693493da02864a330c78e25 languageName: node linkType: hard @@ -5262,7 +5252,7 @@ __metadata: languageName: node linkType: hard -"@grpc/proto-loader@npm:^0.6.1, @grpc/proto-loader@npm:^0.6.2, @grpc/proto-loader@npm:^0.6.4": +"@grpc/proto-loader@npm:^0.6.1, @grpc/proto-loader@npm:^0.6.4": version: 0.6.13 resolution: "@grpc/proto-loader@npm:0.6.13" dependencies: @@ -5292,6 +5282,20 @@ __metadata: languageName: node linkType: hard +"@grpc/proto-loader@npm:^0.7.8": + version: 0.7.10 + resolution: "@grpc/proto-loader@npm:0.7.10" + dependencies: + lodash.camelcase: ^4.3.0 + long: ^5.0.0 + protobufjs: ^7.2.4 + yargs: ^17.7.2 + bin: + proto-loader-gen-types: build/bin/proto-loader-gen-types.js + checksum: 4987e23b57942c2363b6a6a106e63efae636666cefa348778dfafef2ff72da7343c8587667521cb1d52482827bcd001dd535bdc27065110af56d9c7c176334c9 + languageName: node + linkType: hard + "@hapi/hoek@npm:^9.0.0": version: 9.2.1 resolution: "@hapi/hoek@npm:9.2.1" @@ -5343,7 +5347,7 @@ __metadata: autoprefixer: 10.4.8 chart.js: 3.9.1 moment: 2.29.4 - postcss: 8.4.16 + postcss: 8.4.31 solid-apexcharts: 0.1.6 solid-icons: 1.0.4 solid-js: 1.5.7 @@ -5415,7 +5419,7 @@ __metadata: resolution: "@hyperledger/cacti-weaver-driver-fabric@workspace:weaver/core/drivers/fabric-driver" dependencies: "@fidm/x509": 1.2.1 - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@hyperledger/cacti-weaver-protos-js": 2.0.0-alpha.2 "@hyperledger/cacti-weaver-sdk-fabric": 2.0.0-alpha.2 "@types/node": 16.18.41 @@ -5440,7 +5444,7 @@ __metadata: resolution: "@hyperledger/cacti-weaver-fabric-cli@workspace:weaver/samples/fabric/fabric-cli" dependencies: "@fidm/x509": 1.2.1 - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@grpc/proto-loader": 0.7.8 "@hyperledger/cacti-weaver-protos-js": 2.0.0-alpha.2 "@hyperledger/cacti-weaver-sdk-fabric": 2.0.0-alpha.2 @@ -5484,7 +5488,7 @@ __metadata: resolution: "@hyperledger/cacti-weaver-iin-agent@workspace:weaver/core/identity-management/iin-agent" dependencies: "@fidm/x509": 1.2.1 - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@hyperledger/cacti-weaver-protos-js": 2.0.0-alpha.2 "@hyperledger/cacti-weaver-sdk-fabric": 2.0.0-alpha.2 "@types/node": 16.18.41 @@ -5516,10 +5520,9 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperledger/cacti-weaver-protos-js@workspace:weaver/common/protos-js" dependencies: - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@grpc/proto-loader": 0.7.8 google-protobuf: 3.21.2 - grpc: 1.24.11 grpc-tools: 1.12.4 grpc_tools_node_protoc_ts: 5.3.3 languageName: unknown @@ -5559,7 +5562,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperledger/cacti-weaver-sdk-fabric@workspace:weaver/sdks/fabric/interoperation-node-sdk" dependencies: - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@grpc/proto-loader": 0.7.8 "@hyperledger/cacti-weaver-protos-js": 2.0.0-alpha.2 "@types/node": 16.18.41 @@ -5618,7 +5621,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperledger/cactus-cmd-api-server@workspace:packages/cactus-cmd-api-server" dependencies: - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@grpc/proto-loader": 0.7.8 "@hyperledger/cactus-common": 2.0.0-alpha.2 "@hyperledger/cactus-core": 2.0.0-alpha.2 @@ -5705,8 +5708,7 @@ __metadata: ethereumjs-common: 1.5.2 ethereumjs-tx: 2.1.2 express: 4.16.4 - fabric-ca-client: 1.4.19 - fabric-network: 1.4.19 + fabric-network: 2.2.18 http-errors: 1.6.3 http-terminator: 3.2.0 js-yaml: 3.14.1 @@ -5762,7 +5764,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperledger/cactus-core-api@workspace:packages/cactus-core-api" dependencies: - "@grpc/grpc-js": 1.9.0 + "@grpc/grpc-js": 1.9.5 "@grpc/proto-loader": 0.7.8 "@hyperledger/cactus-common": 2.0.0-alpha.2 "@types/express": 4.17.13 @@ -5926,7 +5928,7 @@ __metadata: crypto-js: 4.1.1 cucumber: ^5.0.3 dotenv: ^16.0.1 - fabric-network: 2.2.10 + fabric-network: 2.2.18 fs-extra: 10.1.0 hardhat: 2.17.2 http-status-codes: 2.1.4 @@ -5966,9 +5968,7 @@ __metadata: ethereumjs-common: 1.5.2 ethereumjs-tx: 2.1.2 express: 4.16.4 - fabric-ca-client: 1.4.19 - fabric-client: 1.4.19 - fabric-network: 1.4.19 + fabric-network: 2.2.18 http-errors: 1.6.3 jsonwebtoken: 9.0.0 jsrsasign: 10.5.25 @@ -6505,6 +6505,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperledger/cactus-plugin-ledger-connector-fabric-socketio@workspace:packages/cactus-plugin-ledger-connector-fabric-socketio" dependencies: + "@grpc/grpc-js": 1.9.5 "@hyperledger/cactus-api-client": 2.0.0-alpha.2 "@hyperledger/cactus-cmd-socketio-server": 2.0.0-alpha.2 "@hyperledger/cactus-common": 2.0.0-alpha.2 @@ -6521,11 +6522,9 @@ __metadata: cookie-parser: 1.4.6 debug: 3.1.0 express: 4.17.3 - fabric-ca-client: 1.4.19 - fabric-client: 1.4.19 - fabric-network: 1.4.19 + fabric-ca-client: 2.2.18 + fabric-network: 2.2.18 fs-extra: 10.1.0 - grpc: 1.24.11 js-yaml: 3.14.1 jsonwebtoken: 9.0.0 lodash: 4.17.21 @@ -6657,6 +6656,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperledger/cactus-plugin-ledger-connector-iroha@workspace:packages/cactus-plugin-ledger-connector-iroha" dependencies: + "@grpc/grpc-js": 1.9.5 "@hyperledger/cactus-common": 2.0.0-alpha.2 "@hyperledger/cactus-core": 2.0.0-alpha.2 "@hyperledger/cactus-core-api": 2.0.0-alpha.2 @@ -6668,7 +6668,6 @@ __metadata: axios: 0.21.4 express: 4.17.1 fast-safe-stringify: 2.1.1 - grpc: 1.24.11 internal-ip: 6.2.0 iroha-helpers: 1.5.0 key-encoder: 2.0.3 @@ -6761,7 +6760,7 @@ __metadata: cbor: 6.0.1 config: 3.3.7 cookie-parser: 1.4.6 - debug: 4.1.1 + debug: 4.3.1 express: 4.17.3 js-yaml: 3.14.1 jsonwebtoken: 8.5.1 @@ -6909,7 +6908,7 @@ __metadata: axios: 0.21.4 body-parser: 1.19.0 express: 4.17.1 - fabric-network: 1.4.19 + fabric-network: 2.2.18 fabric-protos: 2.2.18 js-sha256: 0.9.0 pg: 8.8.0 @@ -8211,7 +8210,7 @@ __metadata: languageName: node linkType: hard -"@mapbox/node-pre-gyp@npm:^1.0.0, @mapbox/node-pre-gyp@npm:^1.0.4, @mapbox/node-pre-gyp@npm:^1.0.5": +"@mapbox/node-pre-gyp@npm:^1.0.0, @mapbox/node-pre-gyp@npm:^1.0.5": version: 1.0.9 resolution: "@mapbox/node-pre-gyp@npm:1.0.9" dependencies: @@ -10378,16 +10377,6 @@ __metadata: languageName: node linkType: hard -"@types/bytebuffer@npm:^5.0.34, @types/bytebuffer@npm:^5.0.40": - version: 5.0.43 - resolution: "@types/bytebuffer@npm:5.0.43" - dependencies: - "@types/long": "*" - "@types/node": "*" - checksum: d04ffcec5a25084577362c278e30cf6ee87da2160117a3bae60ff2a5e437e57f730d802806b6e7ba96ebcaf268711a0b1681b09c002ac585d5db5103d0f78a7f - languageName: node - linkType: hard - "@types/cacheable-request@npm:^6.0.2": version: 6.0.3 resolution: "@types/cacheable-request@npm:6.0.3" @@ -10976,7 +10965,7 @@ __metadata: languageName: node linkType: hard -"@types/long@npm:*, @types/long@npm:^4.0.0, @types/long@npm:^4.0.1": +"@types/long@npm:^4.0.0, @types/long@npm:^4.0.1": version: 4.0.1 resolution: "@types/long@npm:4.0.1" checksum: ff9653c33f5000d0f131fd98a950a0343e2e33107dd067a97ac4a3b9678e1a2e39ea44772ad920f54ef6e8f107f76bc92c2584ba905a0dc4253282a4101166d0 @@ -13496,16 +13485,6 @@ __metadata: languageName: node linkType: hard -"ascli@npm:~1": - version: 1.0.1 - resolution: "ascli@npm:1.0.1" - dependencies: - colour: ~0.7.1 - optjs: ~3.2.2 - checksum: 367dcc9a4f7b39d0460d987d5da774a630fddf54d5cb11bacdb5b8627e23d86ed3a8a27e300ecf7b138d1252a35477d5fe9991116bc9feda63659492464d8a25 - languageName: node - linkType: hard - "asn1.js@npm:^5.0.1, asn1.js@npm:^5.2.0": version: 5.4.1 resolution: "asn1.js@npm:5.4.1" @@ -13633,7 +13612,7 @@ __metadata: languageName: node linkType: hard -"async@npm:^1.4.0, async@npm:^1.4.2": +"async@npm:^1.4.2": version: 1.5.2 resolution: "async@npm:1.5.2" checksum: fe5d6214d8f15bd51eee5ae8ec5079b228b86d2d595f47b16369dec2e11b3ff75a567bb5f70d12d79006665fbbb7ee0a7ec0e388524eefd454ecbe651c124ebd @@ -14546,7 +14525,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:4.12.0, bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.0, bn.js@npm:^4.11.3, bn.js@npm:^4.11.6, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": +"bn.js@npm:4.12.0, bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.0, bn.js@npm:^4.11.6, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 @@ -14845,13 +14824,6 @@ __metadata: languageName: node linkType: hard -"browser-request@npm:~0.3.0": - version: 0.3.3 - resolution: "browser-request@npm:0.3.3" - checksum: 8f8db4f95aa33341ffa8d83dd069033310144f439d90bf5aafd4ec0a9495f4cc3fc1515a7d3e15d6968552169f72b7dd90b62efa3647adc4ce9e8be91f907240 - languageName: node - linkType: hard - "browser-stdout@npm:1.3.1": version: 1.3.1 resolution: "browser-stdout@npm:1.3.1" @@ -15234,15 +15206,6 @@ __metadata: languageName: node linkType: hard -"bytebuffer@npm:^5.0.1, bytebuffer@npm:~5": - version: 5.0.1 - resolution: "bytebuffer@npm:5.0.1" - dependencies: - long: ~3 - checksum: d95db66499df77394d6f769b216054b596e492783905f53a06e7c0b7091b24d7b0477de133d08300672e0cd5e140eab81728cdd31ccd9367f7dc4944cdaf913b - languageName: node - linkType: hard - "bytes@npm:2.4.0": version: 2.4.0 resolution: "bytes@npm:2.4.0" @@ -15573,13 +15536,6 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^2.0.1": - version: 2.1.1 - resolution: "camelcase@npm:2.1.1" - checksum: 20a3ef08f348de832631d605362ffe447d883ada89617144a82649363ed5860923b021f8e09681624ef774afb93ff3597cfbcf8aaf0574f65af7648f1aea5e50 - languageName: node - linkType: hard - "camelcase@npm:^3.0.0": version: 3.0.0 resolution: "camelcase@npm:3.0.0" @@ -16178,7 +16134,7 @@ __metadata: languageName: node linkType: hard -"cliui@npm:^3.0.3, cliui@npm:^3.2.0": +"cliui@npm:^3.2.0": version: 3.2.0 resolution: "cliui@npm:3.2.0" dependencies: @@ -16285,19 +16241,6 @@ __metadata: languageName: node linkType: hard -"cloudant-follow@npm:~0.17.0": - version: 0.17.0 - resolution: "cloudant-follow@npm:0.17.0" - dependencies: - browser-request: ~0.3.0 - debug: ^3.0.0 - request: ^2.83.0 - bin: - follow: ./cli.js - checksum: 606f2a238f6aa59b7ae14e9659d6d7dac4634cba8b46e9ffde0c024ac9dd2e6e003de398410aa49c7f37c9f11332474ffa93c8eae4235b2155f1ebeb8667cb18 - languageName: node - linkType: hard - "cmd-shim@npm:^6.0.0": version: 6.0.1 resolution: "cmd-shim@npm:6.0.1" @@ -16458,13 +16401,6 @@ __metadata: languageName: node linkType: hard -"colour@npm:~0.7.1": - version: 0.7.1 - resolution: "colour@npm:0.7.1" - checksum: 1669948efdd0cebca0261476737ccda3ff26f4de789793de604d9f07bf147e2aca21d4ae038cd359d438f39183cf3c50f1b986126509ad30b9d1ad79f75d7199 - languageName: node - linkType: hard - "columnify@npm:^1.6.0": version: 1.6.0 resolution: "columnify@npm:1.6.0" @@ -17900,16 +17836,19 @@ __metadata: languageName: node linkType: hard -"debug@npm:4.1.1": - version: 4.1.1 - resolution: "debug@npm:4.1.1" +"debug@npm:4.3.1": + version: 4.3.1 + resolution: "debug@npm:4.3.1" dependencies: - ms: ^2.1.1 - checksum: 1e681f5cce94ba10f8dde74b20b42e4d8cf0d2a6700f4c165bb3bb6885565ef5ca5885bf07e704974a835f2415ff095a63164f539988a1f07e8a69fe8b1d65ad + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 2c3352e37d5c46b0d203317cd45ea0e26b2c99f2d9dfec8b128e6ceba90dfb65425f5331bf3020fe9929d7da8c16758e737f4f3bfc0fce6b8b3d503bae03298b languageName: node linkType: hard -"debug@npm:^3.0.0, debug@npm:^3.0.1, debug@npm:^3.1.0, debug@npm:^3.2.6, debug@npm:^3.2.7": +"debug@npm:^3.0.1, debug@npm:^3.1.0, debug@npm:^3.2.6, debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" dependencies: @@ -19245,13 +19184,6 @@ __metadata: languageName: node linkType: hard -"errs@npm:^0.3.2": - version: 0.3.2 - resolution: "errs@npm:0.3.2" - checksum: 61f68b59632b1a0123035357cc6168202c54695f8b5644fea0be3b4408053faae692d9a833d23e3bc8a74aa62c1017340ba58c10cad48da7d66f8c09328cce8f - languageName: node - linkType: hard - "es-abstract@npm:^1.18.5, es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.1": version: 1.19.1 resolution: "es-abstract@npm:1.19.1" @@ -21555,19 +21487,6 @@ __metadata: languageName: node linkType: hard -"fabric-ca-client@npm:1.4.19": - version: 1.4.19 - resolution: "fabric-ca-client@npm:1.4.19" - dependencies: - grpc: 1.24.11 - jsrsasign: ^10.4.1 - lodash.clone: 4.5.0 - url: ^0.11.0 - winston: ^2.4.0 - checksum: 6f288f528cc5387d388008629a715aaf1d027e4155d9baa7f10a8f32eafe8689d8085b4bb3c7aa7b43f71658dc890be68dbcbce38282c8662589878433ca8049 - languageName: node - linkType: hard - "fabric-ca-client@npm:2.2.18": version: 2.2.18 resolution: "fabric-ca-client@npm:2.2.18" @@ -21592,64 +21511,6 @@ __metadata: languageName: node linkType: hard -"fabric-client@npm:1.4.19": - version: 1.4.19 - resolution: "fabric-client@npm:1.4.19" - dependencies: - "@types/bytebuffer": ^5.0.34 - bn.js: ^4.11.3 - bytebuffer: ^5.0.1 - callsite: ^1.0.0 - elliptic: ^6.5.4 - fabric-ca-client: 1.4.19 - fs-extra: ^8.1.0 - grpc: 1.24.11 - ignore-walk: ^3.0.0 - js-sha3: ^0.7.0 - js-yaml: ^3.9.0 - jsrsasign: ^10.4.1 - klaw: ^4.0.1 - lodash.clone: 4.5.0 - long: ^4.0.0 - nano: ^6.4.4 - nconf: ^0.10.0 - pkcs11js: ^1.0.6 - promise-settle: ^0.3.0 - protobufjs: 5.0.3 - sjcl: 1.0.7 - tar-stream: ^2.2.0 - url: ^0.11.0 - winston: ^2.4.0 - dependenciesMeta: - pkcs11js: - optional: true - checksum: d5010e699c9898bdf009d7a0d442b6095732d0743484a404b0625672dc9fbb74a199ff0c624ac44a3673b94d0a72f04b88f8be5ca53c1146eb788d7f784d3e96 - languageName: node - linkType: hard - -"fabric-common@npm:2.2.10": - version: 2.2.10 - resolution: "fabric-common@npm:2.2.10" - dependencies: - callsite: ^1.0.0 - elliptic: ^6.5.4 - fabric-protos: 2.2.10 - js-sha3: ^0.8.0 - jsrsasign: ^10.4.1 - long: ^4.0.0 - nconf: ^0.11.2 - pkcs11js: ^1.0.6 - promise-settle: ^0.3.0 - sjcl: ^1.0.8 - winston: ^2.4.5 - yn: ^4.0.0 - dependenciesMeta: - pkcs11js: - optional: true - checksum: aa9a79f749e272a6090fa09511ec1d5e1284dc7451cbd15c671f78b979c40596596eefa374a12a131678c372604c6a7ef7cf0e61adfbd91b7416f017407a408f - languageName: node - linkType: hard - "fabric-common@npm:2.2.18": version: 2.2.18 resolution: "fabric-common@npm:2.2.18" @@ -21694,31 +21555,6 @@ __metadata: languageName: node linkType: hard -"fabric-network@npm:1.4.19": - version: 1.4.19 - resolution: "fabric-network@npm:1.4.19" - dependencies: - fabric-ca-client: 1.4.19 - fabric-client: 1.4.19 - nano: ^6.4.4 - rimraf: ^2.6.2 - winston: ^2.4.0 - checksum: a6a8ed1781cefe18e7377369c653d3290ba0ed3680903a8a5f028d544f7f2bcc1eaa5e7a6469bbf3f400c60481601a1d65693164a815e4eabee2f802f2506065 - languageName: node - linkType: hard - -"fabric-network@npm:2.2.10": - version: 2.2.10 - resolution: "fabric-network@npm:2.2.10" - dependencies: - fabric-common: 2.2.10 - fabric-protos: 2.2.10 - long: ^4.0.0 - nano: ^9.0.3 - checksum: 782435be36fc19daabba079dc71d65d2f8ee03d82b1be99791195ea219bcf68f1f64e9c25864b77e26ed77b5966d106fdeaa27741574a056858d499d0686a4b6 - languageName: node - linkType: hard - "fabric-network@npm:2.2.18": version: 2.2.18 resolution: "fabric-network@npm:2.2.18" @@ -21741,17 +21577,6 @@ __metadata: languageName: node linkType: hard -"fabric-protos@npm:2.2.10": - version: 2.2.10 - resolution: "fabric-protos@npm:2.2.10" - dependencies: - "@grpc/grpc-js": ^1.3.4 - "@grpc/proto-loader": ^0.6.2 - protobufjs: ^6.11.2 - checksum: bdb682a72b366018c1dc32791e28ddefc5ac721170bb74c5d0bdcbe69d47470df853a78145d382d9c9cc71ba5eb237af59a81eeeb70affb6abf1405e837b64b1 - languageName: node - linkType: hard - "fabric-protos@npm:2.2.18": version: 2.2.18 resolution: "fabric-protos@npm:2.2.18" @@ -23912,20 +23737,6 @@ __metadata: languageName: node linkType: hard -"grpc@npm:1.24.11": - version: 1.24.11 - resolution: "grpc@npm:1.24.11" - dependencies: - "@mapbox/node-pre-gyp": ^1.0.4 - "@types/bytebuffer": ^5.0.40 - lodash.camelcase: ^4.3.0 - lodash.clone: ^4.5.0 - nan: ^2.13.2 - protobufjs: ^5.0.3 - checksum: a437525786329ff541d7bbb54e472f52001a4d9b1c2fd896468241e2f070bf558b380b3d19d2b87f401602bd5a319b171e119598f4035958a9519851e91110db - languageName: node - linkType: hard - "grpc_tools_node_protoc_ts@npm:5.3.3": version: 5.3.3 resolution: "grpc_tools_node_protoc_ts@npm:5.3.3" @@ -24867,15 +24678,6 @@ __metadata: languageName: node linkType: hard -"ignore-walk@npm:^3.0.0": - version: 3.0.4 - resolution: "ignore-walk@npm:3.0.4" - dependencies: - minimatch: ^3.0.4 - checksum: 9e9c5ef6c3e0ed7ef5d797991abb554dbb7e60d5fedf6cf05c7129819689eba2b462f625c6e3561e0fc79841904eb829565513eeeab1b44f4fbec4d3146b1a8d - languageName: node - linkType: hard - "ignore-walk@npm:^6.0.0": version: 6.0.2 resolution: "ignore-walk@npm:6.0.2" @@ -25045,7 +24847,7 @@ __metadata: languageName: node linkType: hard -"ini@npm:1.3.8, ini@npm:^1.3.0, ini@npm:^1.3.2, ini@npm:^1.3.4, ini@npm:~1.3.0": +"ini@npm:1.3.8, ini@npm:^1.3.2, ini@npm:^1.3.4, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 @@ -27573,13 +27375,6 @@ __metadata: languageName: node linkType: hard -"js-sha3@npm:^0.7.0": - version: 0.7.0 - resolution: "js-sha3@npm:0.7.0" - checksum: 7a4bdd2ae0b42437cffb8416b3426d85bd8926cf4724b0e91bc04d2f1a57a9f64e35608ae7f127d6a7a4cf73825598932227501c2642b75f9f4c273ae5f95b28 - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -27594,7 +27389,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:3.14.1, js-yaml@npm:^3.13.1, js-yaml@npm:^3.5.1, js-yaml@npm:^3.9.0, js-yaml@npm:^3.9.1": +"js-yaml@npm:3.14.1, js-yaml@npm:^3.13.1, js-yaml@npm:^3.5.1, js-yaml@npm:^3.9.1": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" dependencies: @@ -27968,7 +27763,7 @@ __metadata: languageName: node linkType: hard -"jsrsasign@npm:10.5.25, jsrsasign@npm:^10.4.0, jsrsasign@npm:^10.4.1": +"jsrsasign@npm:10.5.25, jsrsasign@npm:^10.4.0": version: 10.5.25 resolution: "jsrsasign@npm:10.5.25" checksum: e789cd6d5e6e236edebe91936279cdef886aafaab8d4ebc7d40b8ba0c7b7cd0d6d3c53fba26ea96eb33cc77a05368b369ef31fc9182662bce2344143ad50ea0f @@ -28234,13 +28029,6 @@ __metadata: languageName: node linkType: hard -"klaw@npm:^4.0.1": - version: 4.0.1 - resolution: "klaw@npm:4.0.1" - checksum: 7835649ef632f96099d500f94b38c032acf1432ad5e87da596a2509c2f6a63a7fc346fb357e2227091cc433af5c1378ed448e1c0522ed028981dcd446152291e - languageName: node - linkType: hard - "kleur@npm:^3.0.3": version: 3.0.3 resolution: "kleur@npm:3.0.3" @@ -29129,13 +28917,6 @@ __metadata: languageName: node linkType: hard -"lodash.clone@npm:4.5.0, lodash.clone@npm:^4.5.0": - version: 4.5.0 - resolution: "lodash.clone@npm:4.5.0" - checksum: 5839f22acf3a43c026ac4325f7bcd378f34967415cd0b9fd7efa9bbbf38dc665900d36e040944c5afab94a51ff8a24f6cfc3781fe439705cbad5c722e9506b16 - languageName: node - linkType: hard - "lodash.clonedeep@npm:^4.5.0": version: 4.5.0 resolution: "lodash.clonedeep@npm:4.5.0" @@ -29192,13 +28973,6 @@ __metadata: languageName: node linkType: hard -"lodash.isempty@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.isempty@npm:4.4.0" - checksum: a8118f23f7ed72a1dbd176bf27f297d1e71aa1926288449cb8f7cef99ba1bc7527eab52fe7899ab080fa1dc150aba6e4a6367bf49fa4e0b78da1ecc095f8d8c5 - languageName: node - linkType: hard - "lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" @@ -29553,13 +29327,6 @@ __metadata: languageName: node linkType: hard -"long@npm:~3": - version: 3.2.0 - resolution: "long@npm:3.2.0" - checksum: bc27bdeab42cb2f25d0a0faf5fbf77b657bd59236ae0ed649c44f91f35e632230ebd0c62d208bb4e9c69ca558a45e9c9c0810e6b5c0380a1754b8f3b5b7b62d7 - languageName: node - linkType: hard - "loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" @@ -31078,7 +30845,7 @@ __metadata: languageName: node linkType: hard -"nan@npm:^2.13.2, nan@npm:^2.14.1, nan@npm:^2.15.0": +"nan@npm:^2.14.1, nan@npm:^2.15.0": version: 2.15.0 resolution: "nan@npm:2.15.0" dependencies: @@ -31130,20 +30897,7 @@ __metadata: languageName: node linkType: hard -"nano@npm:^6.4.4": - version: 6.4.4 - resolution: "nano@npm:6.4.4" - dependencies: - cloudant-follow: ~0.17.0 - debug: ^2.2.0 - errs: ^0.3.2 - lodash.isempty: ^4.4.0 - request: ^2.85.0 - checksum: 4391a47bbade34dbb25391162bff86b6e48008223634d9a745ed449733268dd703a50fb64698433d68d9125f84e576e0ef9fb3c5e413652d66cb62e44a072070 - languageName: node - linkType: hard - -"nano@npm:^9.0.3, nano@npm:^9.0.5": +"nano@npm:^9.0.5": version: 9.0.5 resolution: "nano@npm:9.0.5" dependencies: @@ -31264,30 +31018,6 @@ __metadata: languageName: node linkType: hard -"nconf@npm:^0.10.0": - version: 0.10.0 - resolution: "nconf@npm:0.10.0" - dependencies: - async: ^1.4.0 - ini: ^1.3.0 - secure-keys: ^1.0.0 - yargs: ^3.19.0 - checksum: 14052553bcde03dbdf11bc3ee95b8cdb7fe776ada550763df75c9683335a937545f62e96972ad2fd4bcc85f928d9880fc74b8c5f93eaddef58d6e0f46c0c836f - languageName: node - linkType: hard - -"nconf@npm:^0.11.2": - version: 0.11.3 - resolution: "nconf@npm:0.11.3" - dependencies: - async: ^1.4.0 - ini: ^2.0.0 - secure-keys: ^1.0.0 - yargs: ^16.1.1 - checksum: 708369c9526618936872fc7db4d257dda59cb55fb9e07949afcfac7cf60cdc840027a6bdf5bf3c5703129bea23090de1aa6f6f41aec004086963706c04bf81f5 - languageName: node - linkType: hard - "nconf@npm:^0.12.0": version: 0.12.0 resolution: "nconf@npm:0.12.0" @@ -32775,13 +32505,6 @@ __metadata: languageName: node linkType: hard -"optjs@npm:~3.2.2": - version: 3.2.2 - resolution: "optjs@npm:3.2.2" - checksum: 0909e160e3ea218982e506750567bc7b6344d223bfb1a850c755ffb54f90f77cf746d94a8956eae614315034ae84ee03322ea00d95a8ac2ec426f4b875e27d86 - languageName: node - linkType: hard - "ora@npm:4.0.2": version: 4.0.2 resolution: "ora@npm:4.0.2" @@ -34257,25 +33980,25 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.16": - version: 8.4.16 - resolution: "postcss@npm:8.4.16" +"postcss@npm:8.4.27": + version: 8.4.27 + resolution: "postcss@npm:8.4.27" dependencies: - nanoid: ^3.3.4 + nanoid: ^3.3.6 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 10eee25efd77868036403858577da0cefaf2e0905feeaba5770d5438ccdddba3d01cba8063e96b8aac4c6daa0ed413dd5ae0554a433a3c4db38df1d134cffc1f + checksum: 1cdd0c298849df6cd65f7e646a3ba36870a37b65f55fd59d1a165539c263e9b4872a402bf4ed1ca1bc31f58b68b2835545e33ea1a23b161a1f8aa6d5ded81e78 languageName: node linkType: hard -"postcss@npm:8.4.27": - version: 8.4.27 - resolution: "postcss@npm:8.4.27" +"postcss@npm:8.4.31": + version: 8.4.31 + resolution: "postcss@npm:8.4.31" dependencies: nanoid: ^3.3.6 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 1cdd0c298849df6cd65f7e646a3ba36870a37b65f55fd59d1a165539c263e9b4872a402bf4ed1ca1bc31f58b68b2835545e33ea1a23b161a1f8aa6d5ded81e78 + checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea languageName: node linkType: hard @@ -34919,20 +34642,6 @@ __metadata: languageName: node linkType: hard -"protobufjs@npm:5.0.3, protobufjs@npm:^5.0.3": - version: 5.0.3 - resolution: "protobufjs@npm:5.0.3" - dependencies: - ascli: ~1 - bytebuffer: ~5 - glob: ^7.0.5 - yargs: ^3.10.0 - bin: - pbjs: ./bin/pbjs - checksum: 3ffb785028696efc642555c8fb7c56b5ecbbe2db42da71997a7d637b15bd555bca0a93b7bc8dd542e1369da214d0a5e669f2ad34ac191c80c1e7e8edc25406c0 - languageName: node - linkType: hard - "protobufjs@npm:6.11.2, protobufjs@npm:^6.10.2, protobufjs@npm:^6.11.2": version: 6.11.2 resolution: "protobufjs@npm:6.11.2" @@ -36236,7 +35945,7 @@ __metadata: languageName: node linkType: hard -"request@npm:^2.79.0, request@npm:^2.83.0, request@npm:^2.85.0, request@npm:^2.88.0": +"request@npm:^2.79.0, request@npm:^2.88.0": version: 2.88.2 resolution: "request@npm:2.88.2" dependencies: @@ -37927,13 +37636,6 @@ __metadata: languageName: node linkType: hard -"sjcl@npm:1.0.7": - version: 1.0.7 - resolution: "sjcl@npm:1.0.7" - checksum: 4eec2df27cf9f9a813c14896d6859ba28fc0234c5a1a3688b7145da309b841b58e8b782b2dbe6bf4f0e01ea2d5ea23c9bb0b9f1300b47d9d54bb135c12e1cccf - languageName: node - linkType: hard - "sjcl@npm:1.0.8, sjcl@npm:^1.0.8": version: 1.0.8 resolution: "sjcl@npm:1.0.8" @@ -39871,7 +39573,7 @@ __metadata: languageName: node linkType: hard -"tar-stream@npm:2.2.0, tar-stream@npm:^2.0.0, tar-stream@npm:^2.1.4, tar-stream@npm:^2.2.0": +"tar-stream@npm:2.2.0, tar-stream@npm:^2.0.0, tar-stream@npm:^2.1.4": version: 2.2.0 resolution: "tar-stream@npm:2.2.0" dependencies: @@ -45242,15 +44944,6 @@ __metadata: languageName: node linkType: hard -"window-size@npm:^0.1.4": - version: 0.1.4 - resolution: "window-size@npm:0.1.4" - bin: - window-size: cli.js - checksum: 409accca0b1373c69897400e3cc6a56a2acc8a6ba9009f0cd8e4adda4ebf308e50425d3bd375c0c08efb803c8f0b09d84d7266faa05422b3fadfe6ee422d0aef - languageName: node - linkType: hard - "window-size@npm:^0.2.0": version: 0.2.0 resolution: "window-size@npm:0.2.0" @@ -45290,7 +44983,7 @@ __metadata: languageName: node linkType: hard -"winston@npm:^2.4.0, winston@npm:^2.4.5": +"winston@npm:^2.4.5": version: 2.4.5 resolution: "winston@npm:2.4.5" dependencies: @@ -45893,7 +45586,7 @@ __metadata: languageName: node linkType: hard -"y18n@npm:^3.2.0, y18n@npm:^3.2.1": +"y18n@npm:^3.2.1": version: 3.2.2 resolution: "y18n@npm:3.2.2" checksum: 6154fd7544f8bbf5b18cdf77692ed88d389be49c87238ecb4e0d6a5276446cd2a5c29cc4bdbdddfc7e4e498b08df9d7e38df4a1453cf75eecfead392246ea74a @@ -46193,21 +45886,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^3.10.0, yargs@npm:^3.19.0": - version: 3.32.0 - resolution: "yargs@npm:3.32.0" - dependencies: - camelcase: ^2.0.1 - cliui: ^3.0.3 - decamelize: ^1.1.1 - os-locale: ^1.4.0 - string-width: ^1.0.1 - window-size: ^0.1.4 - y18n: ^3.2.0 - checksum: 3e0f7fc1bc2052bcaaa7354cbd33d05a86fc0f236432d107ecd088989fbd175174c562d17e762727acbf25d04e8520d43625f7581b2a6ce55ce10034e80675fc - languageName: node - linkType: hard - "yargs@npm:^4.7.1": version: 4.8.1 resolution: "yargs@npm:4.8.1"