Skip to content

Commit

Permalink
feat(cactus-plugin-ledger-connector-ethereum): add json-rpc proxy
Browse files Browse the repository at this point in the history
- Add proxy endpoint handling. Requests sent to this endpoint will be passed
    directly to the ethereum node.
- Add test to verify that proxy is working.
- Update README of ethereum connector.

Co-authored-by: Peter Somogyvari <[email protected]>

Signed-off-by: Michal Bajer <[email protected]>
Signed-off-by: Peter Somogyvari <[email protected]>
  • Loading branch information
outSH authored and petermetz committed Oct 16, 2023
1 parent 18ed520 commit ed04201
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 13 deletions.
13 changes: 13 additions & 0 deletions packages/cactus-plugin-ledger-connector-ethereum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ args: {
},
```
## JSON-RPC Proxy
- Connector can be used with web3js to send any JSON-RPC request to the ethereum node.
### Example
``` typescript
const proxyUrl = new URL(
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-ethereum/json-rpc",
apiHost,
);
const web3ProxyClient = new Web3(proxyUrl.toString());
const gasPrice = await web3ProxyClient.eth.getGasPrice();
```
## Running the tests
To check that all has been installed correctly and that the pugin has no errors run jest test suites.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"@hyperledger/cactus-core-api": "2.0.0-alpha.2",
"axios": "0.21.4",
"express": "4.17.3",
"http-proxy-middleware": "2.0.6",
"minimist": "1.2.8",
"prom-client": "13.2.0",
"run-time-error": "1.4.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,9 @@
}
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-ethereum/json-rpc": {
"summary": "Proxy endpoint to pass JSON-RPC requests to remote ethereum node."
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ import {
} from "./types/model-type-guards";
import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter";
import { RuntimeError } from "run-time-error";
import { createProxyMiddleware, fixRequestBody } from "http-proxy-middleware";

import {
Web3StringReturnFormat,
convertWeb3ReceiptStatusToBool,
Expand Down Expand Up @@ -339,6 +341,26 @@ export class PluginLedgerConnectorEthereum
});
}

// Register JSON-RPC proxy to pass requests directly to ethereum node
if (this.options.rpcApiHttpHost) {
const proxyUrl =
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-ethereum/json-rpc";
const targetUrl = this.options.rpcApiHttpHost;
app.use(
proxyUrl,
createProxyMiddleware({
target: targetUrl,
changeOrigin: true,
pathRewrite: {
[".*"]: "",
},
onProxyReq: fixRequestBody,
logLevel: "error",
}),
);
this.log.info(`Registered proxy from ${proxyUrl} to ${targetUrl}`);
}

return webServices;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
address: string,
port: number,
contractAddress: string,
apiHost,
apiHost: string,
apiConfig,
ledger: GethTestLedger,
apiClient: EthereumApi,
Expand Down Expand Up @@ -129,6 +129,9 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
logLevel: testLogLevel,
pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }),
});

await connector.getOrCreateWebServices();
await connector.registerWebServices(expressApp, wsApi);
});

afterAll(async () => {
Expand All @@ -143,9 +146,6 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
test("setup ethereum connector", async () => {
// Instantiate connector with the keychain plugin that already has the
// private key we want to use for one of our tests
await connector.getOrCreateWebServices();
await connector.registerWebServices(expressApp, wsApi);

const initTransferValue = web3.utils.toWei(5000, "ether");
await apiClient.runTransactionV1({
web3SigningCredential: {
Expand Down Expand Up @@ -360,6 +360,7 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
maxPriorityFeePerGas: 0,
maxFeePerGas: 0x40000000,
gasLimit: 21000,
type: 2,
},
testEthAccount.privateKey,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,29 @@ const testLogLevel = "info";
const sutLogLevel = "info";

import "jest-extended";
import express from "express";
import bodyParser from "body-parser";
import http from "http";
import Web3 from "web3";
import { v4 as uuidv4 } from "uuid";
import { Server as SocketIoServer } from "socket.io";
import { AddressInfo } from "net";

import { PluginRegistry } from "@hyperledger/cactus-core";
import { PluginLedgerConnectorEthereum } from "../../../main/typescript/index";
import { Constants } from "@hyperledger/cactus-core-api";
import {
IListenOptions,
Logger,
LoggerProvider,
Servers,
} from "@hyperledger/cactus-common";
import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling";
import { Logger, LoggerProvider } from "@hyperledger/cactus-common";
import {
GethTestLedger,
WHALE_ACCOUNT_ADDRESS,
} from "@hyperledger/cactus-test-geth-ledger";
import Web3 from "web3";

import { PluginLedgerConnectorEthereum } from "../../../main/typescript/index";

// Unit Test logger setup
const log: Logger = LoggerProvider.getOrCreate({
Expand All @@ -36,6 +49,13 @@ describe("invokeRawWeb3EthMethod Tests", () => {
let ethereumTestLedger: GethTestLedger;
let connector: PluginLedgerConnectorEthereum;
let web3: Web3;
let apiHost: string;
const expressApp = express();
expressApp.use(bodyParser.json({ limit: "250mb" }));
const server = http.createServer(expressApp);
const wsApi = new SocketIoServer(server, {
path: Constants.SocketIoConnectionPathV1,
});

//////////////////////////////////
// Environment Setup
Expand Down Expand Up @@ -64,21 +84,51 @@ describe("invokeRawWeb3EthMethod Tests", () => {
pluginRegistry: new PluginRegistry(),
});

const listenOptions: IListenOptions = {
hostname: "0.0.0.0",
port: 0,
server,
};
const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo;
const { address, port } = addressInfo;
apiHost = `http://${address}:${port}`;

await connector.getOrCreateWebServices();
await connector.registerWebServices(expressApp, wsApi);

web3 = new Web3(rpcApiHttpHost);
});

afterAll(async () => {
log.info("Shutdown connector");
await connector.shutdown();
log.info("Shutdown server");
await Servers.shutdown(server);

log.info("Stop and destroy the test ledger...");
await ethereumTestLedger.stop();
await ethereumTestLedger.destroy();
if (connector) {
log.info("Shutdown connector");
await connector.shutdown();
}

if (ethereumTestLedger) {
log.info("Stop and destroy the test ledger...");
await ethereumTestLedger.stop();
await ethereumTestLedger.destroy();
}

log.info("Prune docker...");
await pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
});

test("invoke method using json-rpc proxy", async () => {
const proxyUrl = new URL(
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-ethereum/json-rpc",
apiHost,
);
const web3ProxyClient = new Web3(proxyUrl.toString());
const gasPrice = await web3ProxyClient.eth.getGasPrice();
expect(gasPrice).toBeTruthy();
expect(Number(gasPrice)).toBeGreaterThan(0);
});

test("invokeRawWeb3EthMethod with 0-argument method works (getGasPrice)", async () => {
const connectorResponse = await connector.invokeRawWeb3EthMethod({
methodName: "getGasPrice",
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6488,6 +6488,7 @@ __metadata:
axios: 0.21.4
chalk: 4.1.2
express: 4.17.3
http-proxy-middleware: 2.0.6
js-yaml: 4.1.0
minimist: 1.2.8
prom-client: 13.2.0
Expand Down Expand Up @@ -24695,7 +24696,7 @@ __metadata:
languageName: node
linkType: hard

"http-proxy-middleware@npm:^2.0.3":
"http-proxy-middleware@npm:2.0.6, http-proxy-middleware@npm:^2.0.3":
version: 2.0.6
resolution: "http-proxy-middleware@npm:2.0.6"
dependencies:
Expand Down

0 comments on commit ed04201

Please sign in to comment.