Skip to content

Commit

Permalink
feat(connector-iroha2): update to the new LTS image as of 28.07.2023
Browse files Browse the repository at this point in the history
- Change iroha2 setup docker and helper classes to work with the new LTS image.
- Update Iroha SDK packages to the newest.
- Fix some tests that were failing after upgrade.
- Adjust SDK usage (new version doesn't create Torii client,
  arguments are provided with each method instead)
- Use pinned iroha2 container version in all in one image.
- Use skopeo to pre-download pinend image version.

Signed-off-by: Michal Bajer <michal.bajer@fujitsu.com>
  • Loading branch information
outSH authored and petermetz committed Aug 8, 2023
1 parent 9b48c59 commit ccdaa12
Show file tree
Hide file tree
Showing 21 changed files with 682 additions and 287 deletions.
6 changes: 4 additions & 2 deletions packages/cactus-plugin-ledger-connector-iroha2/package.json
Expand Up @@ -49,14 +49,16 @@
"@hyperledger/cactus-common": "2.0.0-alpha.1",
"@hyperledger/cactus-core": "2.0.0-alpha.1",
"@hyperledger/cactus-core-api": "2.0.0-alpha.1",
"@iroha2/client": "3.0.0",
"@iroha2/client": "4.0.0",
"@iroha2/crypto-core": "0.1.1",
"@iroha2/crypto-target-node": "0.4.0",
"@iroha2/data-model": "3.0.0",
"@iroha2/data-model": "4.0.0",
"express": "4.17.1",
"fast-safe-stringify": "2.1.1",
"hada": "0.0.8",
"rxjs": "7.8.1",
"sanitize-html": "2.7.0",
"socket.io": "4.4.1",
"socket.io-client": "4.5.4",
"undici": "5.19.1"
},
Expand Down
Expand Up @@ -7,11 +7,10 @@ import {
Signer,
Torii,
setCrypto,
CreateToriiProps,
makeTransactionPayload,
executableIntoSignedTransaction,
computeTransactionHash,
makeSignedTransaction,
makeVersionedSignedTransaction,
} from "@iroha2/client";
import {
AssetDefinitionId,
Expand Down Expand Up @@ -44,21 +43,17 @@ import {
TransferBox,
TransactionPayload,
AccountId,
VersionedTransaction,
RejectionReason,
FilterBox,
PipelineEventFilter,
OptionPipelineEntityKind,
PipelineEntityKind,
OptionPipelineStatusKind,
OptionHash,
VersionedSignedTransaction,
} from "@iroha2/data-model";
import { Key, KeyPair } from "@iroha2/crypto-core";

// This module can't be imported unless we use `nodenext` moduleResolution
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { adapter: irohaWSAdapter } = require("@iroha2/client/web-socket/node");

import {
Checks,
Logger,
Expand All @@ -67,7 +62,6 @@ import {
} from "@hyperledger/cactus-common";

import { bytesToHex, hexToBytes } from "hada";
import { fetch as undiciFetch } from "undici";

import { CactusIrohaV2QueryClient } from "./query";
import {
Expand All @@ -79,7 +73,9 @@ import {
import {
TransactResponseV1,
TransactionStatusV1,
Iroha2BaseConfigTorii,
} from "../generated/openapi/typescript-axios";
import { IrohaV2PrerequisitesProvider } from "./prerequisites-provider";

setCrypto(crypto);

Expand Down Expand Up @@ -149,11 +145,7 @@ export type TransactionPayloadParameters = Exclude<
export class CactusIrohaV2Client {
private readonly log: Logger;
private readonly transactions: Array<NamedIrohaV2Instruction> = [];

/**
* Iroha Torii client used to send transactions to the ledger.
*/
public readonly irohaToriiClient: Torii;
private readonly prerequisitesProvider: IrohaV2PrerequisitesProvider;

/**
* Iroha signer used to sign transaction with user private key and account.
Expand All @@ -166,21 +158,13 @@ export class CactusIrohaV2Client {
public readonly query: CactusIrohaV2QueryClient;

constructor(
public readonly toriiOptions: Omit<CreateToriiProps, "ws" | "fetch">,
public readonly toriiOptions: Iroha2BaseConfigTorii,
public readonly accountId: AccountId,
private readonly keyPair?: KeyPair,
private readonly logLevel: LogLevelDesc = "info",
) {
Checks.truthy(toriiOptions.apiURL, "toriiOptions apiURL");
Checks.truthy(toriiOptions.telemetryURL, "toriiOptions telemetryURL");
Checks.truthy(accountId, "signerOptions accountId");

this.irohaToriiClient = new Torii({
...toriiOptions,
ws: irohaWSAdapter,
fetch: undiciFetch as any,
});

const label = this.constructor.name;
this.log = LoggerProvider.getOrCreate({ level: this.logLevel, label });
this.log.debug(`${label} created`);
Expand All @@ -190,8 +174,12 @@ export class CactusIrohaV2Client {
this.irohaSigner = new Signer(accountId, keyPair);
}

this.prerequisitesProvider = new IrohaV2PrerequisitesProvider(
toriiOptions.apiURL,
);

this.query = new CactusIrohaV2QueryClient(
this.irohaToriiClient,
this.prerequisitesProvider,
this.irohaSigner ?? this.accountId,
this.log,
);
Expand Down Expand Up @@ -717,19 +705,22 @@ export class CactusIrohaV2Client {
const txHashHex = bytesToHex([...txHash]);
this.log.debug("waitForTransactionStatus() - hash:", txHashHex);

const monitor = await this.irohaToriiClient.listenForEvents({
filter: FilterBox(
"Pipeline",
PipelineEventFilter({
entity_kind: OptionPipelineEntityKind(
"Some",
PipelineEntityKind("Transaction"),
),
status_kind: OptionPipelineStatusKind("None"),
hash: OptionHash("Some", txHash),
}),
),
});
const monitor = await Torii.listenForEvents(
this.prerequisitesProvider.getApiWebSocketProperties(),
{
filter: FilterBox(
"Pipeline",
PipelineEventFilter({
entity_kind: OptionPipelineEntityKind(
"Some",
PipelineEntityKind("Transaction"),
),
status_kind: OptionPipelineStatusKind("None"),
hash: OptionHash("Some", txHash),
}),
),
},
);
this.log.debug("waitForTransactionStatus() - monitoring started.");

const txStatusPromise = new Promise<TransactResponseV1>(
Expand Down Expand Up @@ -821,8 +812,14 @@ export class CactusIrohaV2Client {
statusPromise = this.waitForTransactionStatus(hash);
}

const signedTx = makeSignedTransaction(txPayload, this.irohaSigner);
await this.irohaToriiClient.submit(signedTx);
const signedTx = makeVersionedSignedTransaction(
txPayload,
this.irohaSigner,
);
await Torii.submit(
this.prerequisitesProvider.getApiHttpProperties(),
signedTx,
);
this.clear();

if (statusPromise) {
Expand All @@ -838,28 +835,34 @@ export class CactusIrohaV2Client {
/**
* Send signed transaction payload to the ledger.
*
* @param signedPayload Encoded or plain `VersionedTransaction`
* @param signedPayload Encoded or plain `VersionedSignedTransaction`
* @param waitForCommit If `true` - block and return the final transaction status. Otherwise - return immediately.
*
* @returns `TransactResponseV1`
*/
public async sendSignedPayload(
signedPayload: VersionedTransaction | ArrayBufferView,
signedPayload: VersionedSignedTransaction | ArrayBufferView,
waitForCommit = false,
): Promise<TransactResponseV1> {
Checks.truthy(signedPayload, "sendSigned arg signedPayload");

if (ArrayBuffer.isView(signedPayload)) {
signedPayload = VersionedTransaction.fromBuffer(signedPayload);
signedPayload = VersionedSignedTransaction.fromBuffer(signedPayload);
}

const hash = computeTransactionHash(signedPayload.as("V1").payload);
if (waitForCommit) {
const statusPromise = this.waitForTransactionStatus(hash);
await this.irohaToriiClient.submit(signedPayload);
await Torii.submit(
this.prerequisitesProvider.getApiHttpProperties(),
signedPayload,
);
return await statusPromise;
} else {
await this.irohaToriiClient.submit(signedPayload);
await Torii.submit(
this.prerequisitesProvider.getApiHttpProperties(),
signedPayload,
);
return {
hash: bytesToHex([...hash]),
status: TransactionStatusV1.Submitted,
Expand Down
@@ -0,0 +1,67 @@
/**
* Provider for IrohaV2 ToriiRequirements needed by Iroha2 SDK.
*/

import {
IsomorphicWebSocketAdapter,
ToriiRequirementsForApiWebSocket,
ToriiRequirementsForApiHttp,
} from "@iroha2/client";

// This module can't be imported unless we use `nodenext` moduleResolution
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { adapter: irohaWSAdapter } = require("@iroha2/client/web-socket/node");
import { fetch as undiciFetch } from "undici";

/**
* Helper class that returns ToriiRequirements for different Iroha2 commands.
* Can be created with missing parameters, if they are required for requested requirement
* an exception will be thrown.
*/
export class IrohaV2PrerequisitesProvider {
/**
* IrohaV2 isomorphic ws adapter
*/
public webSocketAdapter: IsomorphicWebSocketAdapter = irohaWSAdapter;

/**
* IrohaV2 isomorphic fetch adapter
*/
public fetchAdapter = (undiciFetch as any) as typeof fetch;

constructor(public apiURL?: string, public telemetryURL?: string) {}

/**
* Get requirements for executing API calls on web socket protocol.
* @returns `ToriiRequirementsForApiWebSocket`
*/
getApiWebSocketProperties(): ToriiRequirementsForApiWebSocket {
if (!this.apiURL || !this.webSocketAdapter) {
throw new Error(
"Missing required arguments: apiURL and iroha ws adapter",
);
}

return {
apiURL: this.apiURL,
ws: this.webSocketAdapter,
};
}

/**
* Get requirements for executing API calls on HTTP protocol.
* @returns `ToriiRequirementsForApiHttp`
*/
getApiHttpProperties(): ToriiRequirementsForApiHttp {
if (!this.apiURL || !this.fetchAdapter) {
throw new Error(
"Missing required arguments: apiURL and iroha fetch adapter",
);
}

return {
apiURL: this.apiURL,
fetch: this.fetchAdapter,
};
}
}
Expand Up @@ -8,7 +8,7 @@ import {
Signer,
ToriiQueryResult,
makeQueryPayload,
makeSignedQuery,
makeVersionedSignedQuery,
} from "@iroha2/client";
import {
DomainId,
Expand Down Expand Up @@ -42,6 +42,7 @@ import {
createAssetDefinitionId,
createAssetId,
} from "./data-factories";
import { IrohaV2PrerequisitesProvider } from "./prerequisites-provider";

/**
* Action context for specific query.
Expand Down Expand Up @@ -81,13 +82,13 @@ interface QueryContext<
*/
export class CactusIrohaV2QueryClient {
constructor(
public readonly irohaToriiClient: Torii,
private readonly prerequisitesProvider: IrohaV2PrerequisitesProvider,
public readonly irohaSigner: Signer | AccountId,
private readonly log: Logger,
) {
Checks.truthy(
irohaToriiClient,
"CactusIrohaV2QueryClient irohaToriiClient",
prerequisitesProvider,
"CactusIrohaV2QueryClient prerequisitesProvider",
);
Checks.truthy(irohaSigner, "CactusIrohaV2QueryClient irohaSigner");
Checks.truthy(log, "CactusIrohaV2QueryClient log");
Expand Down Expand Up @@ -152,9 +153,15 @@ export class CactusIrohaV2QueryClient {
accountId: this.signerAccountId,
query: args.getQueryBox(...params),
});
const signedQuery = makeSignedQuery(queryPayload, this.irohaSigner);
const signedQuery = makeVersionedSignedQuery(
queryPayload,
this.irohaSigner,
);

const result = await this.irohaToriiClient.request(signedQuery);
const result = await Torii.request(
this.prerequisitesProvider.getApiHttpProperties(),
signedQuery,
);

return args.parseQueryResponse(result);
};
Expand All @@ -177,7 +184,10 @@ export class CactusIrohaV2QueryClient {
signedPayload = VersionedSignedQueryRequest.fromBuffer(signedPayload);
}

const result = await this.irohaToriiClient.request(signedPayload);
const result = await Torii.request(
this.prerequisitesProvider.getApiHttpProperties(),
signedPayload,
);
return args.parseQueryResponse(result);
};

Expand Down Expand Up @@ -484,7 +494,9 @@ export class CactusIrohaV2QueryClient {
result,
"findAllTransactions",
);
const transactions = vectorResult.map((i) => i.as("TransactionValue"));
const transactions = vectorResult.map(
(i) => i.as("TransactionQueryResult").tx_value,
);

this.log.debug("findAllTransactions:", transactions);
return transactions;
Expand Down
Expand Up @@ -6,12 +6,16 @@
* Remember to free key objects supplied to the signing methods.
*/

import { Signer, makeSignedTransaction, makeSignedQuery } from "@iroha2/client";
import {
Signer,
makeVersionedSignedTransaction,
makeVersionedSignedQuery,
} from "@iroha2/client";
import {
QueryPayload,
TransactionPayload,
VersionedSignedQueryRequest,
VersionedTransaction,
VersionedSignedTransaction,
} from "@iroha2/data-model";

import { generateIrohaV2KeyPair } from "./cactus-iroha-sdk-wrapper/client";
Expand Down Expand Up @@ -59,8 +63,8 @@ export function signIrohaV2Transaction(
): Uint8Array {
const unsignedTx = TransactionPayload.fromBuffer(serializedTx);
const signer = getSigner(accountName, domainName, keyPair);
const signedTx = makeSignedTransaction(unsignedTx, signer);
return VersionedTransaction.toBuffer(signedTx);
const signedTx = makeVersionedSignedTransaction(unsignedTx, signer);
return VersionedSignedTransaction.toBuffer(signedTx);
}

/**
Expand All @@ -81,6 +85,6 @@ export function signIrohaV2Query(
): Uint8Array {
const unsignedQueryReq = QueryPayload.fromBuffer(serializedQuery);
const signer = getSigner(accountName, domainName, keyPair);
const queryReq = makeSignedQuery(unsignedQueryReq, signer);
const queryReq = makeVersionedSignedQuery(unsignedQueryReq, signer);
return VersionedSignedQueryRequest.toBuffer(queryReq);
}

0 comments on commit ccdaa12

Please sign in to comment.