Skip to content

Commit

Permalink
test: jestify sign transaction endpoint
Browse files Browse the repository at this point in the history
Migrated test from Tap to Jest

File Path:
packages/cactus-test-plugin-ledger-connector-besu
/src/test/typescript/integration/
plugin-validator-besu/
sign-transaction-endpoint.test.ts

This is a PARTIAL resolution to issue hyperledger-cacti#238

Signed-off-by: Youngone Lee <youngone.lee@accenture.com>
  • Loading branch information
Leeyoungone authored and petermetz committed Jun 1, 2022
1 parent 89bc365 commit af4cc37
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 150 deletions.
1 change: 0 additions & 1 deletion .taprc
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ files:
- ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/get-block-endpoint.test.ts
- ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/v21-get-transaction-endpoint.test.ts
- ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/v21-sign-transaction-endpoint.test.ts
- ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/sign-transaction-endpoint.test.ts
- ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts
- ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts
- ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts
Expand Down
1 change: 0 additions & 1 deletion jest.config.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import test, { Test } from "tape-promise/tape";

import "jest-extended";
import { v4 as uuidv4 } from "uuid";
import { createServer } from "http";
import KeyEncoder from "key-encoder";
Expand Down Expand Up @@ -36,163 +35,155 @@ import {
import { PluginRegistry } from "@hyperledger/cactus-core";

import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory";
import axios from "axios";

const testCase = "Test sign transaction endpoint";
const logLevel: LogLevelDesc = "TRACE";

test("BEFORE " + testCase, async (t: Test) => {
const pruning = pruneDockerAllIfGithubAction({ logLevel });
await t.doesNotReject(pruning, "Pruning didn't throw OK");
t.end();
});

test(testCase, async (t: Test) => {
const keyEncoder: KeyEncoder = new KeyEncoder("secp256k1");
const keychainId = uuidv4();
const keychainRef = uuidv4();

const { privateKey } = Secp256k1Keys.generateKeyPairsBuffer();
const keyHex = privateKey.toString("hex");
const pem = keyEncoder.encodePrivate(keyHex, KeyFormat.Raw, KeyFormat.PEM);

const keychain = new PluginKeychainMemory({
backend: new Map([[keychainRef, pem]]),
keychainId,
logLevel,
instanceId: uuidv4(),
});
describe(testCase, () => {
const besuTestLedger = new BesuTestLedger();
let apiServer: ApiServer;

const httpServer1 = createServer();
await new Promise((resolve, reject) => {
httpServer1.once("error", reject);
httpServer1.once("listening", resolve);
httpServer1.listen(0, "127.0.0.1");
beforeAll(async () => {
const pruning = pruneDockerAllIfGithubAction({ logLevel });
await expect(pruning).resolves.toBeTruthy();
await besuTestLedger.start();
});
const addressInfo1 = httpServer1.address() as AddressInfo;
t.comment(`HttpServer1 AddressInfo: ${JSON.stringify(addressInfo1)}`);
const node1Host = `http://${addressInfo1.address}:${addressInfo1.port}`;
t.comment(`Cactus Node 1 Host: ${node1Host}`);

const besuTestLedger = new BesuTestLedger();
await besuTestLedger.start();

const tearDown = async () => {
afterAll(async () => {
await besuTestLedger.stop();
await besuTestLedger.destroy();
await pruneDockerAllIfGithubAction({ logLevel });
};

test.onFinish(tearDown);

const rpcApiHttpHost = await besuTestLedger.getRpcApiHttpHost();
const rpcApiWsHost = await besuTestLedger.getRpcApiWsHost();

const jsObjectSignerOptions: IJsObjectSignerOptions = {
privateKey: keyHex,
logLevel,
};
const jsObjectSigner = new JsObjectSigner(jsObjectSignerOptions);

// 2. Instantiate plugin registry which will provide the web service plugin with the key value storage plugin
const pluginRegistry = new PluginRegistry({ plugins: [keychain] });

// 3. Instantiate the web service consortium plugin
const options: IPluginLedgerConnectorBesuOptions = {
instanceId: uuidv4(),
rpcApiHttpHost,
rpcApiWsHost,
pluginRegistry,
logLevel,
};
const pluginValidatorBesu = new PluginLedgerConnectorBesu(options);

// 4. Create the API Server object that we embed in this test
const configService = new ConfigService();
const apiServerOptions = await configService.newExampleConfig();
apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE;
apiServerOptions.configFile = "";
apiServerOptions.apiCorsDomainCsv = "*";
apiServerOptions.apiPort = addressInfo1.port;
apiServerOptions.cockpitPort = 0;
apiServerOptions.grpcPort = 0;
apiServerOptions.apiTlsEnabled = false;
const config = await configService.newExampleConfigConvict(apiServerOptions);

pluginRegistry.add(pluginValidatorBesu);

const apiServer = new ApiServer({
httpServerApi: httpServer1,
config: config.getProperties(),
pluginRegistry,
await apiServer.shutdown();
});

// 5. make sure the API server is shut down when the testing if finished.
test.onFinish(() => apiServer.shutdown());

// 6. Start the API server which is now listening on port A and it's healthcheck works through the main SDK
await apiServer.start();

// 7. Instantiate the main SDK dynamically with whatever port the API server ended up bound to (port 0)
t.comment(`AddressInfo: ${JSON.stringify(addressInfo1)}`);

const web3Provider = new Web3.providers.HttpProvider(rpcApiHttpHost);
const web3 = new Web3(web3Provider);
const web3JsQuorum: IWeb3Quorum = Web3JsQuorum(web3);

const orionKeyPair = await besuTestLedger.getOrionKeyPair();
const besuKeyPair = await besuTestLedger.getBesuKeyPair();

const besuPrivateKey = besuKeyPair.privateKey.toLowerCase().startsWith("0x")
? besuKeyPair.privateKey.substring(2)
: besuKeyPair.privateKey; // besu node's private key

const contractOptions = {
data: `0x123`,
// privateFrom : Orion public key of the sender.
privateFrom: orionKeyPair.publicKey,
// privateFor : Orion public keys of recipients or privacyGroupId: Privacy group to receive the transaction
privateFor: [orionKeyPair.publicKey],
// privateKey: Ethereum private key with which to sign the transaction.
privateKey: besuPrivateKey,
};

const transactionHash = await web3JsQuorum.priv.generateAndSendRawTransaction(
contractOptions,
);

const transaction = await web3.eth.getTransaction(transactionHash);
const singData = jsObjectSigner.sign(transaction.input);
const signDataHex = Buffer.from(singData).toString("hex");

const request: SignTransactionRequest = {
keychainId,
keychainRef,
transactionHash: transactionHash,
};

const configuration = new BesuApiClientOptions({ basePath: node1Host });
const api = new BesuApiClient(configuration);

// Test for 200 valid response test case
const res = await api.signTransactionV1(request);
t.ok(res, "API response object is truthy");
t.deepEquals(signDataHex, res.data.signature, "Signature data are equal");

// Test for 404 Transaction not found test case
try {
const notFoundRequest: SignTransactionRequest = {
keychainId: "fake",
keychainRef: "fake",
transactionHash:
"0x46eac4d1d1ff81837698cbab38862a428ddf042f92855a72010de2771a7b704d",
test(testCase, async () => {
const keyEncoder: KeyEncoder = new KeyEncoder("secp256k1");
const keychainId = uuidv4();
const keychainRef = uuidv4();

const { privateKey } = Secp256k1Keys.generateKeyPairsBuffer();
const keyHex = privateKey.toString("hex");
const pem = keyEncoder.encodePrivate(keyHex, KeyFormat.Raw, KeyFormat.PEM);

const keychain = new PluginKeychainMemory({
backend: new Map([[keychainRef, pem]]),
keychainId,
logLevel,
instanceId: uuidv4(),
});

const httpServer1 = createServer();
await new Promise((resolve, reject) => {
httpServer1.once("error", reject);
httpServer1.once("listening", resolve);
httpServer1.listen(0, "127.0.0.1");
});
const addressInfo1 = httpServer1.address() as AddressInfo;
console.log(`HttpServer1 AddressInfo: ${JSON.stringify(addressInfo1)}`);

const node1Host = `http://${addressInfo1.address}:${addressInfo1.port}`;
console.log(`Cactus Node 1 Host: ${node1Host}`);

const rpcApiHttpHost = await besuTestLedger.getRpcApiHttpHost();
const rpcApiWsHost = await besuTestLedger.getRpcApiWsHost();

const jsObjectSignerOptions: IJsObjectSignerOptions = {
privateKey: keyHex,
logLevel,
};
const jsObjectSigner = new JsObjectSigner(jsObjectSignerOptions);

const pluginRegistry = new PluginRegistry({ plugins: [keychain] });

const options: IPluginLedgerConnectorBesuOptions = {
instanceId: uuidv4(),
rpcApiHttpHost,
rpcApiWsHost,
pluginRegistry,
logLevel,
};
const pluginValidatorBesu = new PluginLedgerConnectorBesu(options);

const configService = new ConfigService();
const apiServerOptions = await configService.newExampleConfig();
apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE;
apiServerOptions.configFile = "";
apiServerOptions.apiCorsDomainCsv = "*";
apiServerOptions.apiPort = addressInfo1.port;
apiServerOptions.cockpitPort = 0;
apiServerOptions.grpcPort = 0;
apiServerOptions.apiTlsEnabled = false;
const config = await configService.newExampleConfigConvict(
apiServerOptions,
);

pluginRegistry.add(pluginValidatorBesu);

apiServer = new ApiServer({
httpServerApi: httpServer1,
config: config.getProperties(),
pluginRegistry,
});

await apiServer.start();

console.log(`AddressInfo: ${JSON.stringify(addressInfo1)}`);

const web3Provider = new Web3.providers.HttpProvider(rpcApiHttpHost);
const web3 = new Web3(web3Provider);
const web3JsQuorum: IWeb3Quorum = Web3JsQuorum(web3);

const orionKeyPair = await besuTestLedger.getOrionKeyPair();
const besuKeyPair = await besuTestLedger.getBesuKeyPair();

const besuPrivateKey = besuKeyPair.privateKey.toLowerCase().startsWith("0x")
? besuKeyPair.privateKey.substring(2)
: besuKeyPair.privateKey; // besu node's private key

const contractOptions = {
data: `0x123`,
// privateFrom : Orion public key of the sender.
privateFrom: orionKeyPair.publicKey,
// privateFor : Orion public keys of recipients or privacyGroupId: Privacy group to receive the transaction
privateFor: [orionKeyPair.publicKey],
// privateKey: Ethereum private key with which to sign the transaction.
privateKey: besuPrivateKey,
};
await api.signTransactionV1(notFoundRequest);
} catch (error) {
t.equal(error.response.status, 404, "HTTP response status are equal");
t.equal(
error.response.statusText,
"Transaction not found",
"Response text are equal",

const transactionHash = await web3JsQuorum.priv.generateAndSendRawTransaction(
contractOptions,
);
}

const transaction = await web3.eth.getTransaction(transactionHash);
const singData = jsObjectSigner.sign(transaction.input);
const signDataHex = Buffer.from(singData).toString("hex");

const request: SignTransactionRequest = {
keychainId,
keychainRef,
transactionHash: transactionHash,
};

const configuration = new BesuApiClientOptions({ basePath: node1Host });
const api = new BesuApiClient(configuration);

const res = await api.signTransactionV1(request);
expect(res).toBeTruthy();
expect(signDataHex).toBe(res.data.signature);

try {
const notFoundRequest: SignTransactionRequest = {
keychainId: "fake",
keychainRef: "fake",
transactionHash:
"0x46eac4d1d1ff81837698cbab38862a428ddf042f92855a72010de2771a7b704d",
};
await api.signTransactionV1(notFoundRequest);
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
expect(error.response?.status).toEqual(404);
expect(error.response?.statusText).toEqual("Transaction not found");
}
}
});
});

0 comments on commit af4cc37

Please sign in to comment.