From 449a0c9629ea9ae247e6226984bb5f7ddee7a295 Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Wed, 20 Sep 2023 11:10:28 -0700 Subject: [PATCH 1/2] build(plugin-keychain-x): fix tsc compiler errors - missing V1 suffix This was caused by the bumping of the references in the openapi.json files which had been pointing to older versions of the openapi.json files through git direct links but now we have upgraded to them. Previously the keychain request/response entities were missing the V1 suffix and the cross-references were still using these older versions prior to us making the bumps. [skip ci] Signed-off-by: Peter Somogyvari --- .../web-services/get-keychain-entry-endpoint.ts | 4 ++-- .../web-services/set-keychain-entry-endpoint.ts | 4 ++-- .../web-services/get-keychain-entry-endpoint-v1.ts | 6 +++--- .../integration/openapi/openapi-validation.test.ts | 14 +++++++------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/get-keychain-entry-endpoint.ts b/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/get-keychain-entry-endpoint.ts index e20e4ea417..5bf5259805 100644 --- a/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/get-keychain-entry-endpoint.ts +++ b/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/get-keychain-entry-endpoint.ts @@ -17,7 +17,7 @@ import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; import { PluginKeychainAzureKv } from "../plugin-keychain-azure-kv"; import OAS from "../../json/openapi.json"; -import { GetKeychainEntryRequest } from "../generated/openapi/typescript-axios"; +import { GetKeychainEntryRequestV1 } from "../generated/openapi/typescript-axios"; export interface IGetKeychainEntryEndpointOptions { logLevel?: LogLevelDesc; @@ -87,7 +87,7 @@ export class GetKeychainEntryEndpoint implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const { key } = req.body as GetKeychainEntryRequest; + const { key } = req.body as GetKeychainEntryRequestV1; try { const value = await this.options.connector.get(key); res.json({ diff --git a/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/set-keychain-entry-endpoint.ts b/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/set-keychain-entry-endpoint.ts index c8ff9c6743..40590ce5f5 100644 --- a/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/set-keychain-entry-endpoint.ts +++ b/packages/cactus-plugin-keychain-azure-kv/src/main/typescript/web-services/set-keychain-entry-endpoint.ts @@ -17,7 +17,7 @@ import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; import { PluginKeychainAzureKv } from "../plugin-keychain-azure-kv"; import OAS from "../../json/openapi.json"; -import { SetKeychainEntryRequest } from "../generated/openapi/typescript-axios"; +import { SetKeychainEntryRequestV1 } from "../generated/openapi/typescript-axios"; export interface ISetKeychainEntryEndpointOptions { logLevel?: LogLevelDesc; @@ -88,7 +88,7 @@ export class SetKeychainEntryEndpoint implements IWebServiceEndpoint { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); try { - const { key, value } = req.body as SetKeychainEntryRequest; + const { key, value } = req.body as SetKeychainEntryRequestV1; const resBody = await this.options.connector.set(key, value); res.json(resBody); } catch (ex) { diff --git a/packages/cactus-plugin-keychain-vault/src/main/typescript/web-services/get-keychain-entry-endpoint-v1.ts b/packages/cactus-plugin-keychain-vault/src/main/typescript/web-services/get-keychain-entry-endpoint-v1.ts index 1d2f22d67f..9504555cfb 100644 --- a/packages/cactus-plugin-keychain-vault/src/main/typescript/web-services/get-keychain-entry-endpoint-v1.ts +++ b/packages/cactus-plugin-keychain-vault/src/main/typescript/web-services/get-keychain-entry-endpoint-v1.ts @@ -16,7 +16,7 @@ import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; import OAS from "../../json/openapi.json"; import { PluginKeychainVault } from "../plugin-keychain-vault"; -import { GetKeychainEntryResponse } from "../generated/openapi/typescript-axios"; +import { GetKeychainEntryResponseV1 } from "../generated/openapi/typescript-axios"; export interface IGetKeychainEntryEndpointV1Options { logLevel?: LogLevelDesc; @@ -50,7 +50,7 @@ export class GetKeychainEntryEndpointV1 implements IWebServiceEndpoint { this.log.debug(`Instantiated ${this.className} OK`); } - public get oasPath(): typeof OAS.paths["/api/v1/plugins/@hyperledger/cactus-plugin-keychain-vault/get-keychain-entry"] { + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-keychain-vault/get-keychain-entry"] { return OAS.paths[ "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-vault/get-keychain-entry" ]; @@ -94,7 +94,7 @@ export class GetKeychainEntryEndpointV1 implements IWebServiceEndpoint { try { this.log.debug(`${tag} %o`, req.body); const value = await this.plugin.get(req.body.key); - const resBody: GetKeychainEntryResponse = { + const resBody: GetKeychainEntryResponseV1 = { key: req.body.key, value: value as string, }; diff --git a/packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts b/packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts index c7a296ef34..66a63d3c00 100644 --- a/packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts +++ b/packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts @@ -21,11 +21,11 @@ import { import { Configuration, DeleteKeychainEntryRequestV1, - GetKeychainEntryRequest, + GetKeychainEntryRequestV1, HasKeychainEntryRequestV1, IPluginKeychainVaultOptions, PluginKeychainVault, - SetKeychainEntryRequest, + SetKeychainEntryRequestV1, } from "../../../../main/typescript/public-api"; import { DefaultApi as KeychainVaultApi } from "../../../../main/typescript/public-api"; @@ -138,7 +138,7 @@ test(`${testCase}`, async (t: Test) => { try { await apiClient.setKeychainEntryV1({ value: value1, - } as SetKeychainEntryRequest); + } as SetKeychainEntryRequestV1); } catch (err) { const e = err as AxiosError<{ path: string }[]>; t2.equal( @@ -174,7 +174,7 @@ test(`${testCase}`, async (t: Test) => { test(`${testCase} - ${fGet} - ${cWithoutParams}`, async (t2: Test) => { try { - await apiClient.getKeychainEntryV1({} as GetKeychainEntryRequest); + await apiClient.getKeychainEntryV1({} as GetKeychainEntryRequestV1); } catch (err) { const e = err as AxiosError<{ path: string }[]>; t2.equal( @@ -214,7 +214,7 @@ test(`${testCase}`, async (t: Test) => { key: key1, value: value1, fake: 4, - } as SetKeychainEntryRequest); + } as SetKeychainEntryRequestV1); } catch (err) { const e = err as AxiosError<{ path: string }[]>; t2.equal( @@ -262,7 +262,7 @@ test(`${testCase}`, async (t: Test) => { await apiClient.getKeychainEntryV1({ key: key1, fake: 4, - } as GetKeychainEntryRequest); + } as GetKeychainEntryRequestV1); } catch (err) { const e = err as AxiosError<{ path: string }[]>; t2.equal( @@ -286,7 +286,7 @@ test(`${testCase}`, async (t: Test) => { await apiClient.deleteKeychainEntryV1({ key: key1, fake: 4, - } as GetKeychainEntryRequest); + } as GetKeychainEntryRequestV1); } catch (err) { const e = err as AxiosError; t2.equal( From d517efeaf3e3590c10d061f267a6ade89a997061 Mon Sep 17 00:00:00 2001 From: Tomasz Awramski Date: Thu, 6 Jul 2023 10:50:09 +0200 Subject: [PATCH 2/2] feat(connector-quorum): add WebsocketProvider options to quorum LP - add WebsocketProvider options to quorum LP - add test for calling getBlock with verifier Depends on https://github.com/hyperledger/cacti/pull/2709 Co-authored-by: Peter Somogyvari Signed-off-by: Tomasz Awramski Signed-off-by: Peter Somogyvari --- .../package.json | 1 + .../plugin-ledger-connector-quorum.ts | 23 +++++++++-- .../v21.4.1-invoke-web3-method-v1.test.ts | 4 +- ...-integration-with-quorum-connector.test.ts | 32 +++++++++++++++ .../typescript/quorum/quorum-test-ledger.ts | 39 +++++++++++++++++-- .../constructor-validates-options.test.ts | 2 +- .../docker/quorum-all-in-one/start-quorum.sh | 5 +++ yarn.lock | 1 + 8 files changed, 99 insertions(+), 8 deletions(-) diff --git a/packages/cactus-plugin-ledger-connector-quorum/package.json b/packages/cactus-plugin-ledger-connector-quorum/package.json index e2ae8b9e4d..e62e8f0d5c 100644 --- a/packages/cactus-plugin-ledger-connector-quorum/package.json +++ b/packages/cactus-plugin-ledger-connector-quorum/package.json @@ -70,6 +70,7 @@ "socket.io-client": "4.5.4", "typescript-optional": "2.0.1", "web3": "1.6.1", + "web3-core-helpers": "1.6.1", "web3-eth-contract": "1.6.1", "web3-utils": "1.6.1", "web3js-quorum": "22.4.0" diff --git a/packages/cactus-plugin-ledger-connector-quorum/src/main/typescript/plugin-ledger-connector-quorum.ts b/packages/cactus-plugin-ledger-connector-quorum/src/main/typescript/plugin-ledger-connector-quorum.ts index 5884e95770..8ee1bec286 100644 --- a/packages/cactus-plugin-ledger-connector-quorum/src/main/typescript/plugin-ledger-connector-quorum.ts +++ b/packages/cactus-plugin-ledger-connector-quorum/src/main/typescript/plugin-ledger-connector-quorum.ts @@ -12,6 +12,10 @@ import Web3JsQuorum, { ISendRawTransaction, IPrivateTransactionReceipt, } from "web3js-quorum"; +import { + WebsocketProviderOptions, + HttpProviderOptions, +} from "web3-core-helpers"; import { AbiItem } from "web3-utils"; import { Contract } from "web3-eth-contract"; import { ContractSendMethod } from "web3-eth-contract"; @@ -84,6 +88,8 @@ export interface IPluginLedgerConnectorQuorumOptions prometheusExporter?: PrometheusExporter; pluginRegistry: PluginRegistry; privateUrl?: string; + wsProviderOptions?: WebsocketProviderOptions; + httpProviderOptions?: HttpProviderOptions; } export class PluginLedgerConnectorQuorum @@ -113,9 +119,20 @@ export class PluginLedgerConnectorQuorum private getWeb3Provider() { if (!this.options.rpcApiWsHost) { - return new Web3.providers.HttpProvider(this.options.rpcApiHttpHost); - } - return new Web3.providers.WebsocketProvider(this.options.rpcApiWsHost); + return this.options.httpProviderOptions + ? new Web3.providers.HttpProvider( + this.options.rpcApiHttpHost, + this.options.httpProviderOptions, + ) + : new Web3.providers.HttpProvider(this.options.rpcApiHttpHost); + } + + return this.options.wsProviderOptions + ? new Web3.providers.WebsocketProvider( + this.options.rpcApiWsHost, + this.options.wsProviderOptions, + ) + : new Web3.providers.WebsocketProvider(this.options.rpcApiWsHost); } constructor(public readonly options: IPluginLedgerConnectorQuorumOptions) { diff --git a/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-web3-method-v1.test.ts b/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-web3-method-v1.test.ts index 5b897746fa..6ff2ee0cbb 100644 --- a/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-web3-method-v1.test.ts +++ b/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-web3-method-v1.test.ts @@ -51,7 +51,9 @@ describe("invokeRawWeb3EthMethod Tests", () => { await quorumTestLedger.start(); const rpcApiHttpHost = await quorumTestLedger.getRpcApiHttpHost(); - log.debug("rpcApiHttpHost:", rpcApiHttpHost); + const getRpcApiWsHost = await quorumTestLedger.getRpcApiWsHost(); + log.warn("rpcApiHttpHost:", rpcApiHttpHost); + log.warn("getRpcApiWsHost:", getRpcApiWsHost); log.info("Create PluginLedgerConnectorQuorum..."); connector = new PluginLedgerConnectorQuorum({ diff --git a/packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/api-client/verifier-integration-with-quorum-connector.test.ts b/packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/api-client/verifier-integration-with-quorum-connector.test.ts index d0fae5441a..1e86af0deb 100644 --- a/packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/api-client/verifier-integration-with-quorum-connector.test.ts +++ b/packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/api-client/verifier-integration-with-quorum-connector.test.ts @@ -18,6 +18,7 @@ import "jest-extended"; import lodash from "lodash"; import { v4 as uuidv4 } from "uuid"; import Web3 from "web3"; +import { WebsocketProviderOptions } from "web3-core-helpers"; import { AbiItem } from "web3-utils"; import { PluginRegistry } from "@hyperledger/cactus-core"; import { @@ -112,9 +113,19 @@ describe("Verifier integration with quorum connector tests", () => { plugins.push(keychainPlugin); log.info("Create PluginLedgerConnectorQuorum..."); + + const wsProviderOptions: WebsocketProviderOptions = { + clientConfig: { + // Useful if requests are large + maxReceivedFrameSize: 100000000, + maxReceivedMessageSize: 100000000, + }, + }; + connector = new PluginLedgerConnectorQuorum({ rpcApiHttpHost: connectionProfile.quorum.member1.url, rpcApiWsHost: connectionProfile.quorum.member1.wsUrl, + wsProviderOptions: wsProviderOptions, logLevel: sutLogLevel, instanceId: uuidv4(), pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }), @@ -270,6 +281,26 @@ describe("Verifier integration with quorum connector tests", () => { }; }); + test("Using verifier for calling getBlock method works", async () => { + const correctContract = {}; + const correctMethod = { + type: "web3Eth", + command: "getBlock", + }; + + const correctArgs: any = { args: ["latest"] }; + + const resultCorrect = await verifier.sendSyncRequest( + correctContract, + correctMethod, + correctArgs, + ); + + log.warn("verifier", verifier); + log.warn("###Results", resultCorrect); + // expect(resultCorrect.status).toEqual(200); + }); + test("Invalid web3EthContract calls are rejected by QuorumApiClient", async () => { // Define correct input parameters const correctContract: Record = lodash.clone( @@ -500,6 +531,7 @@ describe("Verifier integration with quorum connector tests", () => { methodCall, argsCall, ); + log.error(resultsCall); expect(resultsCall.status).toEqual(200); expect(resultsCall.data).toEqual(newName); }); diff --git a/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts b/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts index eb28870515..d89e7dfebe 100644 --- a/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts +++ b/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts @@ -23,6 +23,7 @@ export interface IQuorumTestLedgerConstructorOptions { containerImageVersion?: string; containerImageName?: string; rpcApiHttpPort?: number; + rpcApiWsPort?: number; logLevel?: LogLevelDesc; emitContainerLogs?: boolean; readonly envVars?: string[]; @@ -32,6 +33,7 @@ export const QUORUM_TEST_LEDGER_DEFAULT_OPTIONS = Object.freeze({ containerImageVersion: "2021-01-08-7a055c3", containerImageName: "ghcr.io/hyperledger/cactus-quorum-all-in-one", rpcApiHttpPort: 8545, + rpcApiWsPort: 8546, }); export const QUORUM_TEST_LEDGER_OPTIONS_JOI_SCHEMA: Joi.Schema = Joi.object().keys( @@ -51,6 +53,7 @@ export class QuorumTestLedger implements ITestLedger { public readonly containerImageVersion: string; public readonly containerImageName: string; public readonly rpcApiHttpPort: number; + public readonly rpcApiWsPort: number; public readonly emitContainerLogs: boolean; private readonly log: Logger; @@ -73,6 +76,8 @@ export class QuorumTestLedger implements ITestLedger { this.rpcApiHttpPort = options.rpcApiHttpPort || QUORUM_TEST_LEDGER_DEFAULT_OPTIONS.rpcApiHttpPort; + this.rpcApiWsPort = + options.rpcApiWsPort || QUORUM_TEST_LEDGER_DEFAULT_OPTIONS.rpcApiWsPort; this.envVars = options.envVars || []; @@ -102,9 +107,14 @@ export class QuorumTestLedger implements ITestLedger { public async getRpcApiHttpHost(): Promise { const ipAddress = "127.0.0.1"; - const hostPort = await this.getRpcApiPublicPort(); + const hostPort = await this.getRpcHttpApiPublicPort(); return `http://${ipAddress}:${hostPort}`; } + public async getRpcApiWsHost(): Promise { + const ipAddress = "127.0.0.1"; + const hostPort = await this.getRpcWsApiPublicPort(); + return `ws://${ipAddress}:${hostPort}`; + } public async getFileContents(filePath: string): Promise { const response: NodeJS.ReadableStream = await this.getContainer().getArchive( @@ -221,7 +231,7 @@ export class QuorumTestLedger implements ITestLedger { Env: this.envVars, ExposedPorts: { [`${this.rpcApiHttpPort}/tcp`]: {}, // quorum RPC - HTTP - "8546/tcp": {}, // quorum RPC - WebSocket + [`${this.rpcApiWsPort}/tcp`]: {}, // quorum RPC - WebSocket "8888/tcp": {}, // orion Client Port - HTTP "8080/tcp": {}, // orion Node Port - HTTP "9001/tcp": {}, // supervisord - HTTP @@ -339,7 +349,7 @@ export class QuorumTestLedger implements ITestLedger { } } - public async getRpcApiPublicPort(): Promise { + public async getRpcHttpApiPublicPort(): Promise { const fnTag = "QuorumTestLedger#getRpcApiPublicPort()"; const aContainerInfo = await this.getContainerInfo(); const { rpcApiHttpPort: thePort } = this; @@ -362,6 +372,29 @@ export class QuorumTestLedger implements ITestLedger { } } + public async getRpcWsApiPublicPort(): Promise { + const fnTag = "QuorumTestLedger#getRpcWsApiPublicPort()"; + const aContainerInfo = await this.getContainerInfo(); + const { rpcApiWsPort: thePort } = this; + const { Ports: ports } = aContainerInfo; + + if (ports.length < 1) { + throw new Error(`${fnTag} no ports exposed or mapped at all`); + } + const mapping = ports.find((x) => x.PrivatePort === thePort); + if (mapping) { + if (!mapping.PublicPort) { + throw new Error(`${fnTag} port ${thePort} mapped but not public`); + } else if (mapping.IP !== "0.0.0.0") { + throw new Error(`${fnTag} port ${thePort} mapped to localhost`); + } else { + return mapping.PublicPort; + } + } else { + throw new Error(`${fnTag} no mapping found for ${thePort}`); + } + } + public async getContainerIpAddress(): Promise { const fnTag = "QuorumTestLedger#getContainerIpAddress()"; const aContainerInfo = await this.getContainerInfo(); diff --git a/packages/cactus-test-tooling/src/test/typescript/integration/quorum/quorum-test-ledger/constructor-validates-options.test.ts b/packages/cactus-test-tooling/src/test/typescript/integration/quorum/quorum-test-ledger/constructor-validates-options.test.ts index 42cb3d4110..0668843b1c 100644 --- a/packages/cactus-test-tooling/src/test/typescript/integration/quorum/quorum-test-ledger/constructor-validates-options.test.ts +++ b/packages/cactus-test-tooling/src/test/typescript/integration/quorum/quorum-test-ledger/constructor-validates-options.test.ts @@ -35,7 +35,7 @@ tap.test("starts/stops/destroys a docker container", async (assert: any) => { assert.ok(ipAddress); assert.ok(ipAddress.length); - const hostPort: number = await ledger.getRpcApiPublicPort(); + const hostPort: number = await ledger.getRpcHttpApiPublicPort(); assert.ok(hostPort, "getRpcApiPublicPort() returns truthy OK"); assert.ok(isFinite(hostPort), "getRpcApiPublicPort() returns finite OK"); diff --git a/tools/docker/quorum-all-in-one/start-quorum.sh b/tools/docker/quorum-all-in-one/start-quorum.sh index 86e593616c..8ada58b928 100755 --- a/tools/docker/quorum-all-in-one/start-quorum.sh +++ b/tools/docker/quorum-all-in-one/start-quorum.sh @@ -43,6 +43,11 @@ geth \ --http.vhosts "*" \ --http.addr 0.0.0.0 \ --http.port 8545 \ + --ws \ + --wsaddr "0.0.0.0" \ + --wsport "8546" \ + --wsapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,${QUORUM_CONSENSUS:-raft} \ + --wsorigins "*" \ --http.api admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,${QUORUM_CONSENSUS:-raft} \ --port 21000 \ --allow-insecure-unlock \ diff --git a/yarn.lock b/yarn.lock index e0106dfccd..2ed4c756cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6702,6 +6702,7 @@ __metadata: socket.io-client: 4.5.4 typescript-optional: 2.0.1 web3: 1.6.1 + web3-core-helpers: 1.6.1 web3-eth: 1.6.1 web3-eth-contract: 1.6.1 web3-utils: 1.6.1