From cfa8db6c96e314bcefd6958b9823c4e0a5cf9620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Augusto?= Date: Mon, 21 Mar 2022 01:53:37 +0000 Subject: [PATCH] feat(odap-plugin): addition of client endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementation of client endpoints Refactorization and addition of more tests Addition of more checks on the server side when receiving messages Signed-off-by: AndrĂ© Augusto --- .taprc | 2 +- jest.config.js | 2 +- .../src/main/json/openapi.json | 286 +++- .../typescript/gateway/client/commit-final.ts | 196 +++ .../gateway/client/commit-preparation.ts | 188 +++ .../gateway/client/lock-evidence.ts | 198 +++ .../gateway/client/transfer-commence.ts | 198 +++ .../gateway/client/transfer-complete.ts | 77 + .../gateway/client/transfer-initialization.ts | 207 +++ .../gateway/common/commit-final-helper.ts | 214 --- .../typescript/gateway/plugin-odap-gateway.ts | 1415 ++++------------- .../typescript/gateway/server/commit-final.ts | 215 +++ .../commit-preparation.ts} | 187 ++- .../lock-evidence.ts} | 198 ++- .../transfer-commence.ts} | 196 ++- .../transfer-complete.ts} | 118 +- .../transfer-initialization.ts} | 176 +- .../generated/openapi/typescript-axios/api.ts | 756 ++++++--- .../client-side/client-request-endpoint.ts | 99 ++ .../commit-final-response-endpoint.ts} | 27 +- .../commite-prepare-response-endpoint.ts} | 30 +- .../lock-evidence-response-endpoint.ts} | 26 +- .../transfer-commence-response-endpoint.ts | 104 ++ .../transfer-initiation-response-endpoint.ts} | 31 +- .../commit-final-request-endpoint.ts | 102 ++ .../commite-prepare-request-endpoint.ts | 104 ++ .../lock-evidence-request-endpoint.ts} | 26 +- .../transfer-commence-request-endpoint.ts} | 28 +- .../transfer-complete-request-endpoint.ts} | 30 +- .../transfer-initiation-request-endpoint.ts | 106 ++ ...dap-api-call-with-ledger-connector.test.ts | 23 +- .../{odap => }/odap-api-call.test.ts | 38 +- .../odap/transfer-initiation.test.ts | 228 --- .../unit/client/commit-final.test.ts | 141 ++ .../unit/client/commit-preparation.test.ts | 152 ++ .../unit/client/lock-evidence.test.ts | 146 ++ .../unit/client/transfer-commence.test.ts | 147 ++ .../unit/client/transfer-initiation.test.ts | 163 ++ .../odap => unit/server}/commit-final.test.ts | 80 +- .../server}/commit-preparation.test.ts | 77 +- .../server}/lock-evidence.test.ts | 85 +- .../server}/transfer-commence.test.ts | 122 +- .../server}/transfer-complete.test.ts | 20 +- .../unit/server/transfer-initiation.test.ts | 180 +++ 44 files changed, 4578 insertions(+), 2566 deletions(-) create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-final.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-preparation.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/lock-evidence.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-commence.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-complete.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-initialization.ts delete mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-final-helper.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-final.ts rename packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/{common/commit-prepare-helper.ts => server/commit-preparation.ts} (53%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/{common/lock-evidence-helper.ts => server/lock-evidence.ts} (54%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/{common/transfer-commence-helper.ts => server/transfer-commence.ts} (53%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/{common/transfer-complete-helper.ts => server/transfer-complete.ts} (56%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/{common/initiate-transfer-helper.ts => server/transfer-initialization.ts} (67%) create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/client-request-endpoint.ts rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{commit-final-endpoint.ts => client-side/commit-final-response-endpoint.ts} (77%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{commite-prepare-endpoint.ts => client-side/commite-prepare-response-endpoint.ts} (76%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{lock-evidence-endpoint.ts => client-side/lock-evidence-response-endpoint.ts} (78%) create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-commence-response-endpoint.ts rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{transfer-initiation-endpoint.ts => client-side/transfer-initiation-response-endpoint.ts} (75%) create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commit-final-request-endpoint.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commite-prepare-request-endpoint.ts rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{send-client-request.ts => server-side/lock-evidence-request-endpoint.ts} (71%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{transfer-commence-endpoint.ts => server-side/transfer-commence-request-endpoint.ts} (78%) rename packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/{transfer-complete-endpoint.ts => server-side/transfer-complete-request-endpoint.ts} (75%) create mode 100644 packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-initiation-request-endpoint.ts rename packages/cactus-plugin-odap-hermes/src/test/typescript/integration/{odap => }/odap-api-call-with-ledger-connector.test.ts (97%) rename packages/cactus-plugin-odap-hermes/src/test/typescript/integration/{odap => }/odap-api-call.test.ts (93%) delete mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-initiation.test.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-final.test.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-preparation.test.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/lock-evidence.test.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-commence.test.ts create mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-initiation.test.ts rename packages/cactus-plugin-odap-hermes/src/test/typescript/{integration/odap => unit/server}/commit-final.test.ts (73%) rename packages/cactus-plugin-odap-hermes/src/test/typescript/{integration/odap => unit/server}/commit-preparation.test.ts (73%) rename packages/cactus-plugin-odap-hermes/src/test/typescript/{integration/odap => unit/server}/lock-evidence.test.ts (77%) rename packages/cactus-plugin-odap-hermes/src/test/typescript/{integration/odap => unit/server}/transfer-commence.test.ts (73%) rename packages/cactus-plugin-odap-hermes/src/test/typescript/{integration/odap => unit/server}/transfer-complete.test.ts (88%) create mode 100644 packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-initiation.test.ts diff --git a/.taprc b/.taprc index ef9190345a..f7214c55a8 100644 --- a/.taprc +++ b/.taprc @@ -6,7 +6,7 @@ timeout: 900 ts: true files: - ./packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/openapi/openapi-validation.test.ts - - ./packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call-with-ledger-connector.test.ts + - ./packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call-with-ledger-connector.test.ts - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-lock-asset.test.ts - ./packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/lock-contract.test.ts - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-ws-ids.test.ts diff --git a/jest.config.js b/jest.config.js index 3d805f4ed4..2deeedd651 100644 --- a/jest.config.js +++ b/jest.config.js @@ -11,7 +11,7 @@ module.exports = { // Ignore the tests that are still using tap/tape for as their test runner testPathIgnorePatterns: [ `./packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/openapi/openapi-validation.test.ts`, - `./packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call-with-ledger-connector.test.ts`, + `./packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call-with-ledger-connector.test.ts`, `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-lock-asset.test.ts`, `./packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/lock-contract.test.ts`, `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-ws-ids.test.ts`, diff --git a/packages/cactus-plugin-odap-hermes/src/main/json/openapi.json b/packages/cactus-plugin-odap-hermes/src/main/json/openapi.json index 04c681a55c..56a6506ffb 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/json/openapi.json +++ b/packages/cactus-plugin-odap-hermes/src/main/json/openapi.json @@ -251,6 +251,9 @@ }, "sequenceNumber":{ "type":"integer" + }, + "sourceGatewayPath": { + "type": "string" } }, "required": [ @@ -348,6 +351,12 @@ "assetProfile": { "$ref":"#/components/schemas/AssetProfile" }, + "sourceBasePath": { + "type":"string" + }, + "recipientBasePath": { + "type":"string" + }, "originatorPubkey": { "type":"string" }, @@ -547,6 +556,9 @@ "TransferCommenceV1Response":{ "type":"object", "properties": { + "sessionID": { + "type":"string" + }, "clientIdentityPubkey":{ "type":"string" }, @@ -574,6 +586,7 @@ } }, "required": [ + "sessionID", "messageType", "serverIdentityPubkey", "clientIdentityPubkey", @@ -639,6 +652,9 @@ "LockEvidenceV1Response":{ "type":"object", "properties": { + "sessionID":{ + "type": "string" + }, "clientIdentityPubkey":{ "type":"string" }, @@ -663,6 +679,7 @@ } }, "required": [ + "sessionID", "messageType", "clientIdentityPubkey", "serverIdentityPubkey", @@ -712,6 +729,9 @@ "CommitPreparationV1Response":{ "type":"object", "properties": { + "sessionID":{ + "type": "string" + }, "messageType":{ "type":"string" }, @@ -735,6 +755,7 @@ } }, "required": [ + "sessionID", "messageType", "clientIdentityPubkey", "serverIdentityPubkey", @@ -792,6 +813,9 @@ "CommitFinalV1Response":{ "type":"object", "properties": { + "sessionID":{ + "type": "string" + }, "messageType":{ "type":"string" }, @@ -821,6 +845,7 @@ } }, "required": [ + "sessionID", "messageType", "ClientIdentityPubkey", "serverIdentityPubkey", @@ -873,18 +898,7 @@ "sequenceNumber" ] }, - "TransferCompleteV1Response":{ - "type":"object", - "properties": { - "ok":{ - "type":"string" - } - }, - "required": [ - "ok" - ] - }, - "SendClientV1Request":{ + "ClientV1Request":{ "type":"object", "properties": { "version":{ @@ -935,6 +949,17 @@ "serverDltSystem": { "type":"string" }, + "clientGatewayConfiguration": { + "type":"object", + "properties": { + "apiHost":{ + "type": "string" + } + }, + "required": [ + "apiHost" + ] + }, "serverGatewayConfiguration": { "type":"object", "properties": { @@ -948,7 +973,6 @@ } }, "required": [ - "serverGatewayConfiguration", "version", "loggingProfile", "accessControlProfile", @@ -965,7 +989,9 @@ "serverIdentityPubkey", "clientDltSystem", "serverDltSystem", - "serverGatewayInstanceID" + "serverGatewayInstanceID", + "clientGatewayConfiguration", + "serverGatewayConfiguration" ] }, "OdapMessage":{ @@ -1040,15 +1066,15 @@ } }, "paths": { - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiation":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationrequest":{ "post":{ "x-hyperledger-cactus": { "http": { "verbLowerCase": "post", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiation" + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationrequest" } }, - "operationId": "phase1TransferInitiationV1", + "operationId": "phase1TransferInitiationRequestV1", "description":"", "requestBody":{ "content": { @@ -1060,28 +1086,21 @@ } }, "responses": { - "201": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TransferInitializationV1Response" - } - } - } + "200": { + "description": "OK" } } } }, - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommence":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommencerequest":{ "post":{ "x-hyperledger-cactus": { "http": { "verbLowerCase": "post", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommence" + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommencerequest" } }, - "operationId": "phase2TransferCommenceV1", + "operationId": "phase2TransferCommenceRequestV1", "description":"", "requestBody":{ "content": { @@ -1093,28 +1112,21 @@ } }, "responses": { - "201": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TransferCommenceV1Response" - } - } - } + "200": { + "description": "OK" } } } }, - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidence":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidencerequest":{ "post":{ "x-hyperledger-cactus": { "http": { "verbLowerCase": "post", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidence" + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidencerequest" } }, - "operationId": "phase2LockEvidenceV1", + "operationId": "phase2LockEvidenceRequestV1", "description":"", "requestBody":{ "content": { @@ -1126,78 +1138,115 @@ } }, "responses": { - "201": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LockEvidenceV1Response" - } + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationrequest":{ + "post":{ + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationrequest" + } + }, + "operationId": "phase3CommitPreparationRequestV1", + "description":"", + "requestBody":{ + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommitPreparationV1Request" } } } + }, + "responses": { + "200": { + "description": "OK" + } } } }, - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparation":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalrequest":{ "post":{ "x-hyperledger-cactus": { "http": { "verbLowerCase": "post", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparation" + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalrequest" } }, - "operationId": "phase3CommitPreparationV1", + "operationId": "phase3CommitFinalRequestV1", "description":"", "requestBody":{ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CommitPreparationV1Request" + "$ref": "#/components/schemas/CommitFinalV1Request" } } } }, "responses": { - "201": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommitPreparationV1Response" - } + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercompleterequest":{ + "get":{ + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercompleterequest" + } + }, + "operationId": "phase3TransferCompleteRequestV1", + "description":"", + "requestBody":{ + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransferCompleteV1Request" } } } + }, + "responses": { + "200": { + "description": "OK" + } } } }, - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinal":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/clientrequest":{ "post":{ "x-hyperledger-cactus": { "http": { "verbLowerCase": "post", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinal" + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/clientrequest" } }, - "operationId": "phase3CommitFinalV1", + "operationId": "clientRequestV1", "description":"", "requestBody":{ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CommitFinalV1Request" + "$ref": "#/components/schemas/ClientV1Request" } } } }, "responses": { - "201": { + "200": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CommitFinalV1Response" } } } @@ -1205,70 +1254,135 @@ } } }, - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercomplete":{ - "get":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationresponse":{ + "post":{ "x-hyperledger-cactus": { "http": { - "verbLowerCase": "get", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercomplete" + "verbLowerCase": "post", + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationresponse" } }, - "operationId": "phase3TransferCompleteV1", + "operationId": "phase1TransferInitiationResponseV1", "description":"", "requestBody":{ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TransferCompleteV1Request" + "$ref": "#/components/schemas/TransferInitializationV1Response" } } } }, "responses": { "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - } + "description": "OK" + } + } + } + }, + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommenceresponse":{ + "post":{ + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommenceresponse" + } + }, + "operationId": "phase2TransferCommenceResponseV1", + "description":"", + "requestBody":{ + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransferCommenceV1Response" } } } + }, + "responses": { + "200": { + "description": "OK" + } } } }, - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/sendclientrequest":{ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidenceresponse":{ "post":{ "x-hyperledger-cactus": { "http": { "verbLowerCase": "post", - "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/sendclientrequest" + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidenceresponse" } }, - "operationId": "sendClientRequestV1", + "operationId": "phase2LockEvidenceResponseV1", "description":"", "requestBody":{ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SendClientV1Request" + "$ref": "#/components/schemas/LockEvidenceV1Response" } } } }, "responses": { "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - } + "description": "OK" + } + } + } + }, + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationresponse":{ + "post":{ + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationresponse" + } + }, + "operationId": "phase3CommitPreparationResponseV1", + "description":"", + "requestBody":{ + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommitPreparationV1Response" + } + } + } + }, + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalresponse":{ + "post":{ + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalresponse" + } + }, + "operationId": "phase3CommitFinalResponseV1", + "description":"", + "requestBody":{ + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommitFinalV1Response" } } } + }, + "responses": { + "200": { + "description": "OK" + } } } } - } } diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-final.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-final.ts new file mode 100644 index 0000000000..4dd0bcc6ab --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-final.ts @@ -0,0 +1,196 @@ +import { + CommitFinalV1Request, + CommitFinalV1Response, +} from "../../generated/openapi/typescript-axios"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "client-commit-final-helper", +}); + +export async function sendCommitFinalRequest( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendCommitFinalRequest()`; + + const sessionData = odap.sessions.get(sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.recipientBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.commitPrepareResponseMessageHash == undefined + ) { + throw new Error(`${fnTag}, session data is not correctly initialized`); + } + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "init", + operation: "commit-final", + nodes: `${odap.pubKey}->${sessionData.recipientGatewayPubkey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + const fabricDeleteAssetProof = await odap.deleteFabricAsset(sessionID); + sessionData.commitFinalClaim = fabricDeleteAssetProof; + + const commitFinalRequestMessage: CommitFinalV1Request = { + sessionID: sessionID, + messageType: OdapMessageType.CommitFinalRequest, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + commitFinalClaim: fabricDeleteAssetProof, + // commit final claim format + hashCommitPrepareAck: sessionData.commitPrepareResponseMessageHash, + clientSignature: "", + sequenceNumber: ++sessionData.lastSequenceNumber, + }; + + const messageSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(commitFinalRequestMessage)), + ); + + commitFinalRequestMessage.clientSignature = messageSignature; + + sessionData.commitFinalRequestMessageHash = SHA256( + JSON.stringify(commitFinalRequestMessage), + ).toString(); + + sessionData.clientSignatureCommitFinalRequestMessage = messageSignature; + + odap.sessions.set(sessionID, sessionData); + + log.info(`${fnTag}, sending CommitFinalRequest...`); + + const response = await odap + .getOdapAPI(sessionData.recipientBasePath) + .phase3CommitFinalRequestV1(commitFinalRequestMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, CommitFinalRequest message failed`); + } +} + +export async function checkValidCommitFinalResponse( + response: CommitFinalV1Response, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidCommitFinalResponse`; + + const sessionID = response.sessionID; + const sessionData = odap.sessions.get(sessionID); + if (sessionData == undefined) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + if (response.messageType != OdapMessageType.CommitFinalResponse) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, wrong message type for CommitFinalResponse`); + } + + if (response.sequenceNumber != sessionData.lastSequenceNumber) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, CommitFinalResponse sequence number incorrect`); + } + + if (response.commitAcknowledgementClaim == undefined) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, the claim provided is not valid`); + } + + if (sessionData.commitFinalRequestMessageHash != response.hashCommitFinal) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalResponse previous message hash does not match the one that was sent`, + ); + } + + if (sessionData.recipientGatewayPubkey != response.serverIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalResponse serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != response.clientIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalResponse clientIdentity public key does not match the one that was sent`, + ); + } + + const commitFinalResponseMessageDataSignature = response.serverSignature; + + const sourceServerSignature = new Uint8Array( + Buffer.from(commitFinalResponseMessageDataSignature, "hex"), + ); + + const sourceServerPubkey = new Uint8Array( + Buffer.from(sessionData.recipientGatewayPubkey, "hex"), + ); + + response.serverSignature = ""; + + if ( + !odap.verifySignature( + JSON.stringify(response), + sourceServerSignature, + sourceServerPubkey, + ) + ) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalResponse message signature verification failed`, + ); + } + + response.serverSignature = commitFinalResponseMessageDataSignature; + + storeSessionData(response, odap); + + log.info(`CommitFinalResponse passed all checks.`); +} + +function storeSessionData( + response: CommitFinalV1Response, + odap: PluginOdapGateway, +): void { + const fnTag = `${odap.className}#storeSessionData`; + const sessionData = odap.sessions.get(response.sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.id == undefined + ) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + sessionData.step++; + + sessionData.commitAcknowledgementClaim = response.commitAcknowledgementClaim; + + sessionData.commitFinalResponseMessageHash = SHA256( + JSON.stringify(response), + ).toString(); + + sessionData.serverSignatureCommitFinalResponseMessage = + response.serverSignature; + + odap.sessions.set(sessionData.id, sessionData); +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-preparation.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-preparation.ts new file mode 100644 index 0000000000..d5706709de --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/commit-preparation.ts @@ -0,0 +1,188 @@ +import { + CommitPreparationV1Request, + CommitPreparationV1Response, +} from "../../generated/openapi/typescript-axios"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "client-commit-preparation-helper", +}); + +export async function sendCommitPreparationRequest( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendCommitPreparationRequest()`; + + const sessionData = odap.sessions.get(sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.recipientBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.lockEvidenceResponseMessageHash == undefined + ) { + throw new Error(`${fnTag}, session data is not correctly initialized`); + } + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "init", + operation: "commit-prepare", + nodes: `${odap.pubKey}->${sessionData.recipientGatewayPubkey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + const commitPrepareRequestMessage: CommitPreparationV1Request = { + sessionID: sessionID, + messageType: OdapMessageType.CommitPreparationRequest, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + hashLockEvidenceAck: sessionData.lockEvidenceResponseMessageHash, + clientSignature: "", + sequenceNumber: ++sessionData.lastSequenceNumber, + }; + + const messageSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(commitPrepareRequestMessage)), + ); + + commitPrepareRequestMessage.clientSignature = messageSignature; + + sessionData.commitPrepareRequestMessageHash = SHA256( + JSON.stringify(commitPrepareRequestMessage), + ).toString(); + + sessionData.clientSignatureCommitPreparationRequestMessage = messageSignature; + + odap.sessions.set(sessionID, sessionData); + + log.info(`${fnTag}, sending CommitPreparationRequest...`); + + const response = await odap + .getOdapAPI(sessionData.recipientBasePath) + .phase3CommitPreparationRequestV1(commitPrepareRequestMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, CommitPreparationRequest message failed`); + } +} + +export async function checkValidCommitPreparationResponse( + response: CommitPreparationV1Response, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidCommitPreparationResponse`; + + const sessionID = response.sessionID; + const sessionData = odap.sessions.get(sessionID); + if (sessionData == undefined) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + if (response.messageType != OdapMessageType.CommitPreparationResponse) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, wrong message type for CommitPreparationResponse`, + ); + } + + if (response.sequenceNumber != sessionData.lastSequenceNumber) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationResponse sequence number incorrect`, + ); + } + + if (sessionData.commitPrepareRequestMessageHash != response.hashCommitPrep) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationResponse previous message hash does not match the one that was sent`, + ); + } + + if (sessionData.recipientGatewayPubkey != response.serverIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationResponse serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != response.clientIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationResponse clientIdentity public key does not match the one that was sent`, + ); + } + + const commitPrepareResponseMessageDataSignature = response.serverSignature; + + const sourceServerSignature = new Uint8Array( + Buffer.from(commitPrepareResponseMessageDataSignature, "hex"), + ); + + const sourceServerPubkey = new Uint8Array( + Buffer.from(sessionData.recipientGatewayPubkey, "hex"), + ); + + response.serverSignature = ""; + + if ( + !odap.verifySignature( + JSON.stringify(response), + sourceServerSignature, + sourceServerPubkey, + ) + ) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationResponse message signature verification failed`, + ); + } + + response.serverSignature = commitPrepareResponseMessageDataSignature; + + storeSessionData(response, odap); + + log.info(`CommitPreparationResponse passed all checks.`); +} + +function storeSessionData( + response: CommitPreparationV1Response, + odap: PluginOdapGateway, +): void { + const fnTag = `${odap.className}#storeSessionData`; + const sessionData = odap.sessions.get(response.sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.id == undefined + ) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + sessionData.step++; + + sessionData.commitPrepareResponseMessageHash = SHA256( + JSON.stringify(response), + ).toString(); + + sessionData.serverSignatureCommitPreparationResponseMessage = + response.serverSignature; + + odap.sessions.set(sessionData.id, sessionData); +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/lock-evidence.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/lock-evidence.ts new file mode 100644 index 0000000000..6bbbf9ebd9 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/lock-evidence.ts @@ -0,0 +1,198 @@ +import { + LockEvidenceV1Request, + LockEvidenceV1Response, +} from "../../generated/openapi/typescript-axios"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "client-lock-evidence-helper", +}); + +export async function sendLockEvidenceRequest( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendLockEvidenceRequest()`; + + const sessionData = odap.sessions.get(sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.recipientBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.transferCommenceMessageResponseHash == undefined + ) { + throw new Error(`${fnTag}, session data is not correctly initialized`); + } + + await odap.storeOdapLog( + { + phase: "p2", + step: sessionData.step.toString(), + type: "init", + operation: "lock", + nodes: `${odap.pubKey}->${sessionData.recipientGatewayPubkey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + const fabricLockAssetProof = await odap.lockFabricAsset(sessionID); + + log.info(`${fnTag}, proof of the asset lock: ${fabricLockAssetProof}`); + + const lockEvidenceRequestMessage: LockEvidenceV1Request = { + sessionID: sessionID, + messageType: OdapMessageType.LockEvidenceRequest, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + lockEvidenceClaim: fabricLockAssetProof, + // lock claim format + lockEvidenceExpiration: new Date() + .setDate(new Date().getDate() + 1) + .toString(), // a day from now + hashCommenceAckRequest: sessionData.transferCommenceMessageResponseHash, + clientSignature: "", + sequenceNumber: ++sessionData.lastSequenceNumber, + }; + + const messageSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(lockEvidenceRequestMessage)), + ); + + lockEvidenceRequestMessage.clientSignature = messageSignature; + + sessionData.lockEvidenceRequestMessageHash = SHA256( + JSON.stringify(lockEvidenceRequestMessage), + ).toString(); + + sessionData.clientSignatureLockEvidenceRequestMessage = messageSignature; + + sessionData.lockEvidenceClaim = fabricLockAssetProof; + + odap.sessions.set(sessionID, sessionData); + + log.info(`${fnTag}, sending LockEvidenceRequest...`); + + const response = await odap + .getOdapAPI(sessionData.recipientBasePath) + .phase2LockEvidenceRequestV1(lockEvidenceRequestMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, LockEvidenceRequest message failed`); + } +} + +export async function checkValidLockEvidenceResponse( + response: LockEvidenceV1Response, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidLockEvidenceResponse`; + + const sessionID = response.sessionID; + const sessionData = odap.sessions.get(sessionID); + if (sessionData == undefined) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + if (response.messageType != OdapMessageType.LockEvidenceResponse) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, wrong message type for LockEvidenceResponse`); + } + + if (response.sequenceNumber != sessionData.lastSequenceNumber) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, LockEvidenceResponse sequence number incorrect`); + } + + if ( + sessionData.lockEvidenceRequestMessageHash != + response.hashLockEvidenceRequest + ) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceResponse previous message hash does not match the one that was sent`, + ); + } + + if (sessionData.recipientGatewayPubkey != response.serverIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceResponse serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != response.clientIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceResponse clientIdentity public key does not match the one that was sent`, + ); + } + + const lockEvidenceResponseMesssageDataSignature = response.serverSignature; + + const sourceServerSignature = new Uint8Array( + Buffer.from(lockEvidenceResponseMesssageDataSignature, "hex"), + ); + + const sourceServerPubkey = new Uint8Array( + Buffer.from(sessionData.recipientGatewayPubkey, "hex"), + ); + + response.serverSignature = ""; + + if ( + !odap.verifySignature( + JSON.stringify(response), + sourceServerSignature, + sourceServerPubkey, + ) + ) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceResponse message signature verification failed`, + ); + } + + response.serverSignature = lockEvidenceResponseMesssageDataSignature; + + storeSessionData(response, odap); + + log.info(`LockEvidenceResponse passed all checks.`); +} + +function storeSessionData( + response: LockEvidenceV1Response, + odap: PluginOdapGateway, +): void { + const fnTag = `${odap.className}#storeSessionData`; + const sessionData = odap.sessions.get(response.sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.id == undefined + ) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + sessionData.step++; + + sessionData.lockEvidenceResponseMessageHash = SHA256( + JSON.stringify(response), + ).toString(); + + sessionData.serverSignatureLockEvidenceResponseMessage = + response.serverSignature; + + odap.sessions.set(sessionData.id, sessionData); +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-commence.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-commence.ts new file mode 100644 index 0000000000..3069dc1203 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-commence.ts @@ -0,0 +1,198 @@ +import { + TransferCommenceV1Request, + TransferCommenceV1Response, +} from "../../generated/openapi/typescript-axios"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "client-transfer-commence-helper", +}); + +export async function sendTransferCommenceRequest( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendTransferCommenceRequest()`; + + const sessionData = odap.sessions.get(sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.assetProfile == undefined || + sessionData.recipientBasePath == undefined || + sessionData.originatorPubkey == undefined || + sessionData.beneficiaryPubkey == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.sourceGatewayDltSystem == undefined || + sessionData.recipientGatewayDltSystem == undefined || + sessionData.initializationResponseMessageHash == undefined + ) { + throw new Error(`${fnTag}, session data is not correctly initialized`); + } + + await odap.storeOdapLog( + { + phase: "p2", + step: sessionData.step.toString(), + type: "init", + operation: "commence", + nodes: `${odap.pubKey}->${sessionData.recipientGatewayPubkey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + const hashAssetProfile = SHA256( + JSON.stringify(sessionData.assetProfile), + ).toString(); + + const transferCommenceRequestMessage: TransferCommenceV1Request = { + messageType: OdapMessageType.TransferCommenceRequest, + originatorPubkey: sessionData.originatorPubkey, + beneficiaryPubkey: sessionData.beneficiaryPubkey, + senderDltSystem: sessionData.sourceGatewayDltSystem, + recipientDltSystem: sessionData.recipientGatewayDltSystem, + sessionID: sessionID, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + hashAssetProfile: hashAssetProfile, + hashPrevMessage: sessionData.initializationResponseMessageHash, + // clientTransferNumber + clientSignature: "", + sequenceNumber: ++sessionData.lastSequenceNumber, + }; + + const messageSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(transferCommenceRequestMessage)), + ); + + transferCommenceRequestMessage.clientSignature = messageSignature; + + sessionData.transferCommenceMessageRequestHash = SHA256( + JSON.stringify(transferCommenceRequestMessage), + ).toString(); + + sessionData.clientSignatureTransferCommenceRequestMessage = messageSignature; + + odap.sessions.set(sessionID, sessionData); + + log.info(`${fnTag}, sending TransferCommenceRequest...`); + + const response = await odap + .getOdapAPI(sessionData.recipientBasePath) + .phase2TransferCommenceRequestV1(transferCommenceRequestMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, TransferCommenceRequest message failed`); + } +} + +export async function checkValidTransferCommenceResponse( + response: TransferCommenceV1Response, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidTransferCommenceResponse`; + + const sessionID = response.sessionID; + const sessionData = odap.sessions.get(sessionID); + if (sessionData == undefined) { + throw new Error(`${fnTag}, session data is undefined`); + } + + if (response.messageType != OdapMessageType.TransferCommenceResponse) { + throw new Error( + `${fnTag}, wrong message type for TransferCommenceResponse`, + ); + } + + if (response.sequenceNumber != sessionData.lastSequenceNumber) { + throw new Error( + `${fnTag}, TransferCommenceResponse sequence number incorrect`, + ); + } + + if ( + sessionData.transferCommenceMessageRequestHash != + response.hashCommenceRequest + ) { + throw new Error( + `${fnTag}, TransferCommenceResponse previous message hash does not match the one that was sent`, + ); + } + + if (sessionData.recipientGatewayPubkey != response.serverIdentityPubkey) { + throw new Error( + `${fnTag}, TransferCommenceResponse serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != response.clientIdentityPubkey) { + throw new Error( + `${fnTag}, TransferCommenceResponse clientIdentity public key does not match the one that was sent`, + ); + } + + const transferCommenceResponseDataSignature = response.serverSignature; + + const sourceServerSignature = new Uint8Array( + Buffer.from(transferCommenceResponseDataSignature, "hex"), + ); + + const sourceServerPubkey = new Uint8Array( + Buffer.from(sessionData.recipientGatewayPubkey, "hex"), + ); + + response.serverSignature = ""; + + if ( + !odap.verifySignature( + JSON.stringify(response), + sourceServerSignature, + sourceServerPubkey, + ) + ) { + throw new Error( + `${fnTag}, TransferCommenceResponse message signature verification failed`, + ); + } + + response.serverSignature = transferCommenceResponseDataSignature; + + storeSessionData(response, odap); + + log.info(`TransferCommenceResponse passed all checks.`); +} + +function storeSessionData( + response: TransferCommenceV1Response, + odap: PluginOdapGateway, +): void { + const fnTag = `${odap.className}#storeSessionData`; + const sessionData = odap.sessions.get(response.sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.id == undefined + ) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + sessionData.step++; + + sessionData.transferCommenceMessageResponseHash = SHA256( + JSON.stringify(response), + ).toString(); + + sessionData.serverSignatureTransferCommenceResponseMessage = + response.serverSignature; + + odap.sessions.set(sessionData.id, sessionData); +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-complete.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-complete.ts new file mode 100644 index 0000000000..a88ef0be7b --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-complete.ts @@ -0,0 +1,77 @@ +import { TransferCompleteV1Request } from "../../generated/openapi/typescript-axios"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "client-transfer-complete-helper", +}); + +export async function sendTransferCompleteRequest( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendTransferCompleteRequest()`; + + const sessionData = odap.sessions.get(sessionID); + + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.recipientBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.commitFinalResponseMessageHash == undefined || + sessionData.transferCommenceMessageRequestHash == undefined + ) { + throw new Error(`${fnTag}, session data is not correctly initialized`); + } + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "init", + operation: "complete", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + const transferCompleteRequestMessage: TransferCompleteV1Request = { + sessionID: sessionID, + messageType: OdapMessageType.TransferCompleteRequest, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + hashCommitFinalAck: sessionData.commitFinalResponseMessageHash, + hashTransferCommence: sessionData.transferCommenceMessageRequestHash, + clientSignature: "", + sequenceNumber: ++sessionData.lastSequenceNumber, + }; + + const messageSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(transferCompleteRequestMessage)), + ); + + transferCompleteRequestMessage.clientSignature = messageSignature; + + sessionData.transferCompleteMessageHash = SHA256( + JSON.stringify(transferCompleteRequestMessage), + ).toString(); + + sessionData.clientSignatureTransferCompleteMessage = messageSignature; + + odap.sessions.set(sessionID, sessionData); + + log.info(`${fnTag}, sending TransferCompleteRequest...`); + + const response = await odap + .getOdapAPI(sessionData.recipientBasePath) + .phase3TransferCompleteRequestV1(transferCompleteRequestMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, TransferCompleteRequest message failed`); + } +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-initialization.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-initialization.ts new file mode 100644 index 0000000000..5ad5632354 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/client/transfer-initialization.ts @@ -0,0 +1,207 @@ +import { + TransferInitializationV1Request, + TransferInitializationV1Response, +} from "../../generated/openapi/typescript-axios"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "client-transfer-initialization-helper", +}); + +export async function sendTransferInitializationRequest( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendTransferInitializationRequest()`; + + const sessionData = odap.sessions.get(sessionID); + + if ( + sessionData == undefined || + sessionData.id == undefined || + sessionData.step == undefined || + sessionData.version == undefined || + sessionData.payloadProfile == undefined || + sessionData.loggingProfile == undefined || + sessionData.recipientBasePath == undefined || + sessionData.accessControlProfile == undefined || + sessionData.applicationProfile == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayDltSystem == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.recipientGatewayDltSystem == undefined + ) { + throw new Error(`${fnTag}, session data is not correctly initialized`); + } + + if (!odap.supportedDltIDs.includes(sessionData.recipientGatewayDltSystem)) { + throw new Error( + `${fnTag}, recipient gateway dlt system is not supported by this gateway`, + ); + } + + await odap.storeOdapLog( + { + phase: "p1", + step: sessionData.step.toString(), + type: "init", + operation: "validate", + nodes: `${odap.pubKey}->${sessionData.recipientGatewayPubkey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + const initializationRequestMessage: TransferInitializationV1Request = { + messageType: OdapMessageType.InitializationRequest, + sessionID: sessionData.id, + version: sessionData.version, + // developer urn + // credential profile + payloadProfile: sessionData.payloadProfile, + applicationProfile: sessionData.applicationProfile, + loggingProfile: sessionData.loggingProfile, + accessControlProfile: sessionData.accessControlProfile, + clientSignature: "", + sourceGatewayPubkey: odap.pubKey, + sourceGatewayDltSystem: sessionData.sourceGatewayDltSystem, + recipientGatewayPubkey: sessionData.recipientGatewayPubkey, + recipientGatewayDltSystem: sessionData.recipientGatewayDltSystem, + sequenceNumber: sessionData.lastSequenceNumber, + sourceGatewayPath: sessionData.sourceBasePath, + // escrow type + // expiry time (related to the escrow) + // multiple claims allowed + // multiple cancels allowed + // permissions + }; + + const messageSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(initializationRequestMessage)), + ); + + initializationRequestMessage.clientSignature = messageSignature; + + sessionData.initializationRequestMessageHash = SHA256( + JSON.stringify(initializationRequestMessage), + ).toString(); + + sessionData.clientSignatureInitializationRequestMessage = messageSignature; + + odap.sessions.set(sessionID, sessionData); + + log.info(`${fnTag}, sending TransferInitializationRequest...`); + + const response = await odap + .getOdapAPI(sessionData.recipientBasePath) + .phase1TransferInitiationRequestV1(initializationRequestMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, TransferInitializationRequest message failed`); + } +} + +export async function checkValidInitializationResponse( + response: TransferInitializationV1Response, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidInitializationResponse`; + + const sessionID = response.sessionID; + const sessionData = odap.sessions.get(sessionID); + if (sessionData == undefined) { + throw new Error(`${fnTag}, session data is undefined`); + } + + if (response.messageType != OdapMessageType.InitializationResponse) { + throw new Error( + `${fnTag}, wrong message type for TransferInitializationResponse`, + ); + } + + if (response.sequenceNumber != sessionData.lastSequenceNumber) { + throw new Error( + `${fnTag}, TransferInitializationResponse sequence number incorrect`, + ); + } + + if ( + response.initialRequestMessageHash != + sessionData.initializationRequestMessageHash + ) { + throw new Error( + `${fnTag}, TransferInitializationResponse previous message hash does not match the one that was sent`, + ); + } + + if (response.serverIdentityPubkey != sessionData.recipientGatewayPubkey) { + throw new Error( + `${fnTag}, TransferInitializationResponse serverIdentity public key does not match the one that was sent`, + ); + } + + const transferInitiationResponseDataSignature = response.serverSignature; + + const sourceServerSignature = new Uint8Array( + Buffer.from(transferInitiationResponseDataSignature, "hex"), + ); + + const sourceServerPubkey = new Uint8Array( + Buffer.from(sessionData.recipientGatewayPubkey, "hex"), + ); + + response.serverSignature = ""; + + if ( + !odap.verifySignature( + JSON.stringify(response), + sourceServerSignature, + sourceServerPubkey, + ) + ) { + throw new Error( + `${fnTag}, TransferInitializationResponse message signature verification failed`, + ); + } + + response.serverSignature = transferInitiationResponseDataSignature; + + storeSessionData(response, odap); + + log.info(`TransferInitializationResponse passed all checks.`); +} + +async function storeSessionData( + response: TransferInitializationV1Response, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#storeSessionData`; + const sessionData = odap.sessions.get(response.sessionID); + + if (sessionData == undefined || sessionData.step == undefined) { + throw new Error( + `${fnTag}, reverting transfer because session data is undefined`, + ); + } + + const serverIdentityPubkey = response.serverIdentityPubkey; + + sessionData.step++; + + sessionData.id = response.sessionID; + + sessionData.recipientGatewayPubkey = serverIdentityPubkey; + + sessionData.initializationResponseMessageHash = SHA256( + JSON.stringify(response), + ).toString(); + + sessionData.serverSignatureInitializationResponseMessage = + response.serverSignature; + + sessionData.fabricAssetSize = "1"; + + odap.sessions.set(sessionData.id, sessionData); +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-final-helper.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-final-helper.ts deleted file mode 100644 index 389f00f64a..0000000000 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-final-helper.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; -import { SHA256 } from "crypto-js"; -import { LoggerProvider } from "@hyperledger/cactus-common"; -import { - CommitFinalV1Request, - CommitFinalV1Response, -} from "../../generated/openapi/typescript-axios"; -import { - EthContractInvocationType, - InvokeContractV1Request as BesuInvokeContractV1Request, -} from "@hyperledger/cactus-plugin-ledger-connector-besu"; - -const log = LoggerProvider.getOrCreate({ - level: "INFO", - label: "odap-lock-evidence-helper", -}); - -export async function commitFinal( - request: CommitFinalV1Request, - odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#commitFinal()`; - log.info( - `server gateway receives CommitFinalRequestMessage: ${JSON.stringify( - request, - )}`, - ); - - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData == undefined || sessionData.step == undefined) { - await odap.Revert(request.sessionID); - throw new Error( - `${fnTag}, session Id does not correspond to any open session`, - ); - } - - await odap.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "exec", - operation: "commit-final", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - // Calculate the hash here to avoid changing the object and the hash - const commitFinalRequestMessageHash = SHA256( - JSON.stringify(request), - ).toString(); - - log.info( - `CommitFinalRequestMessage hash is: ${commitFinalRequestMessageHash}`, - ); - - const besuCreateAssetProof = await checkValidCommitFinalRequest( - request, - odap, - ); - - const commitFinalResponseMessage: CommitFinalV1Response = { - messageType: OdapMessageType.CommitFinalResponse, - clientIdentityPubkey: request.clientIdentityPubkey, - serverIdentityPubkey: request.serverIdentityPubkey, - commitAcknowledgementClaim: besuCreateAssetProof, - hashCommitFinal: commitFinalRequestMessageHash, - serverSignature: "", - sequenceNumber: request.sequenceNumber, - }; - - commitFinalResponseMessage.serverSignature = odap.bufArray2HexStr( - await odap.sign(JSON.stringify(commitFinalResponseMessage)), - ); - - storeSessionData(request, commitFinalResponseMessage, odap); - - await odap.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "ack", - operation: "commit-prepare", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - sessionData.step++; - - return commitFinalResponseMessage; -} - -async function checkValidCommitFinalRequest( - request: CommitFinalV1Request, - odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#checkValidCommitFinalRequest()`; - - if (request.messageType != OdapMessageType.CommitFinalRequest) { - await odap.Revert(request.sessionID); - throw new Error(`${fnTag}, wrong message type for CommitFinalRequest`); - } - - const sourceClientSignature = new Uint8Array( - Buffer.from(request.clientSignature, "hex"), - ); - - const sourceClientPubkey = new Uint8Array( - Buffer.from(request.clientIdentityPubkey, "hex"), - ); - - const signature = request.clientSignature; - request.clientSignature = ""; - if ( - !odap.verifySignature( - JSON.stringify(request), - sourceClientSignature, - sourceClientPubkey, - ) - ) { - await odap.Revert(request.sessionID); - throw new Error( - `${fnTag}, CommitFinalRequest message signature verification failed`, - ); - } - request.clientSignature = signature; - - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData === undefined) { - throw new Error(`${fnTag}, sessionID non exist`); - } - - // We need to check somewhere if this phase is completed within the asset-lock duration. - if ( - sessionData.commitPrepareResponseMessageHash != request.hashCommitPrepareAck - ) { - await odap.Revert(request.sessionID); - throw new Error(`${fnTag}, previous message hash does not match`); - } - - let besuCreateAssetProof = ""; - - if (odap.besuApi != undefined) { - const besuCreateRes = await odap.besuApi.invokeContractV1({ - contractName: odap.besuContractName, - invocationType: EthContractInvocationType.Send, - methodName: "createAsset", - gas: 1000000, - params: [odap.besuAssetID, 100], //the second is size, may need to pass this from client? - signingCredential: odap.besuWeb3SigningCredential, - keychainId: odap.besuKeychainId, - } as BesuInvokeContractV1Request); - - if (besuCreateRes.status != 200) { - await odap.Revert(request.sessionID); - throw new Error(`${fnTag}, besu create asset error`); - } - - const besuCreateResDataJson = JSON.parse( - JSON.stringify(besuCreateRes.data), - ); - - if (besuCreateResDataJson.out == undefined) { - throw new Error(`${fnTag}, besu res data out undefined`); - } - - if (besuCreateResDataJson.out.transactionReceipt == undefined) { - throw new Error(`${fnTag}, undefined besu transact receipt`); - } - - const besuCreateAssetReceipt = besuCreateResDataJson.out.transactionReceipt; - besuCreateAssetProof = JSON.stringify(besuCreateAssetReceipt); - const besuCreateProofID = `${request.sessionID}-proof-of-create`; - - await odap.publishOdapProof( - besuCreateProofID, - JSON.stringify(besuCreateAssetReceipt), - ); - - sessionData.isBesuAssetCreated = true; - } - - odap.sessions.set(request.sessionID, sessionData); - - return besuCreateAssetProof; -} -async function storeSessionData( - request: CommitFinalV1Request, - response: CommitFinalV1Response, - odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#()storeDataAfterCommitFinalRequest`; - const sessionData = odap.sessions.get(request.sessionID); - - if (sessionData == undefined) { - throw new Error(`${fnTag}, session data is undefined`); - } - - sessionData.commitFinalClaim = request.commitFinalClaim; - - sessionData.commitAcknowledgementClaim = response.commitAcknowledgementClaim; - - sessionData.clientSignatureCommitFinalRequestMessage = - request.clientSignature; - sessionData.serverSignatureCommitFinalResponseMessage = - response.serverSignature; - - sessionData.commitFinalRequestMessageHash = response.hashCommitFinal; - sessionData.commitFinalResponseMessageHash = SHA256( - JSON.stringify(response), - ).toString(); - - odap.sessions.set(request.sessionID, sessionData); -} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/plugin-odap-gateway.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/plugin-odap-gateway.ts index f180ea1f0e..794b66d31b 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/plugin-odap-gateway.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/plugin-odap-gateway.ts @@ -3,6 +3,7 @@ import type { Server } from "http"; import type { Server as SecureServer } from "https"; import { Optional } from "typescript-optional"; import type { Express } from "express"; +import { v4 as uuidV4 } from "uuid"; import OAS from "../../json/openapi.json"; import { Secp256k1Keys, @@ -13,7 +14,10 @@ import { IJsObjectSignerOptions, } from "@hyperledger/cactus-common"; import { DefaultApi as ObjectStoreIpfsApi } from "@hyperledger/cactus-plugin-object-store-ipfs"; -import { initiateTransfer } from "./common/initiate-transfer-helper"; +import { + checkValidInitializationRequest, + sendTransferInitializationResponse, +} from "./server/transfer-initialization"; import { ICactusPlugin, IPluginWebService, @@ -21,30 +25,22 @@ import { Configuration, } from "@hyperledger/cactus-core-api"; import { - CommitFinalV1Request, - CommitFinalV1Response, - CommitPreparationV1Request, - CommitPreparationV1Response, - TransferInitializationV1Request, TransferInitializationV1Response, - LockEvidenceV1Request, - LockEvidenceV1Response, - SendClientV1Request, + DefaultApi as OdapApi, + SessionData, + ClientV1Request, TransferCommenceV1Request, TransferCommenceV1Response, + LockEvidenceV1Request, + LockEvidenceV1Response, + CommitPreparationV1Request, + CommitFinalV1Request, + CommitPreparationV1Response, + CommitFinalV1Response, TransferCompleteV1Request, - DefaultApi as OdapApi, - SessionData, - TransferCompleteV1Response, + TransferInitializationV1Request, } from "../generated/openapi/typescript-axios"; -import { SHA256 } from "crypto-js"; -import { CommitFinalEndpointV1 } from "../web-services/commit-final-endpoint"; -import { CommitPrepareEndpointV1 } from "../web-services/commite-prepare-endpoint"; -import { LockEvidenceEndpointV1 } from "../web-services/lock-evidence-endpoint"; -import { TransferCommenceEndpointV1 } from "../web-services/transfer-commence-endpoint"; -import { TransferCompleteEndpointV1 } from "../web-services/transfer-complete-endpoint"; -import { TransferInitiationEndpointV1 } from "../web-services/transfer-initiation-endpoint"; -import { SendClientRequestEndpointV1 } from "../web-services/send-client-request"; +import { CommitFinalRequestEndpointV1 } from "../web-services/server-side/commit-final-request-endpoint"; import { PluginRegistry } from "@hyperledger/cactus-core"; import { DefaultApi as FabricApi, @@ -58,13 +54,56 @@ import { EthContractInvocationType, InvokeContractV1Request as BesuInvokeContractV1Request, } from "@hyperledger/cactus-plugin-ledger-connector-besu"; -import { lockEvidence } from "./common/lock-evidence-helper"; -import { commitFinal } from "./common/commit-final-helper"; -import { transferComplete } from "./common/transfer-complete-helper"; -import { v4 as uuidV4 } from "uuid"; -import { transferCommence } from "./common/transfer-commence-helper"; -import { commitPrepare } from "./common/commit-prepare-helper"; +import { CommitFinalResponseEndpointV1 } from "../web-services/client-side/commit-final-response-endpoint"; +import { CommitPreparationResponseEndpointV1 } from "../web-services/client-side/commite-prepare-response-endpoint"; +import { LockEvidenceResponseEndpointV1 } from "../web-services/client-side/lock-evidence-response-endpoint"; +import { TransferCommenceResponseEndpointV1 } from "../web-services/client-side/transfer-commence-response-endpoint"; +import { TransferInitiationResponseEndpointV1 } from "../web-services/client-side/transfer-initiation-response-endpoint"; +import { LockEvidenceRequestEndpointV1 } from "../web-services/server-side/lock-evidence-request-endpoint"; +import { TransferCommenceRequestEndpointV1 } from "../web-services/server-side/transfer-commence-request-endpoint"; +import { TransferCompleteRequestEndpointV1 } from "../web-services/server-side/transfer-complete-request-endpoint"; +import { TransferInitiationRequestEndpointV1 } from "../web-services/server-side/transfer-initiation-request-endpoint"; +import { CommitPreparationRequestEndpointV1 } from "../web-services/server-side/commite-prepare-request-endpoint"; import { randomInt } from "crypto"; +import { + checkValidInitializationResponse, + sendTransferInitializationRequest, +} from "./client/transfer-initialization"; +import { ClientRequestEndpointV1 } from "../web-services/client-side/client-request-endpoint"; +import { + checkValidTransferCommenceResponse, + sendTransferCommenceRequest, +} from "./client/transfer-commence"; +import { + checkValidtransferCommenceRequest, + sendTransferCommenceResponse, +} from "./server/transfer-commence"; +import { + checkValidLockEvidenceResponse, + sendLockEvidenceRequest, +} from "./client/lock-evidence"; +import { + checkValidLockEvidenceRequest, + sendLockEvidenceResponse, +} from "./server/lock-evidence"; +import { + checkValidCommitFinalResponse, + sendCommitFinalRequest, +} from "./client/commit-final"; +import { + checkValidCommitPreparationResponse, + sendCommitPreparationRequest, +} from "./client/commit-preparation"; +import { + checkValidCommitFinalRequest, + sendCommitFinalResponse, +} from "./server/commit-final"; +import { sendTransferCompleteRequest } from "./client/transfer-complete"; +import { checkValidTransferCompleteRequest } from "./server/transfer-complete"; +import { + checkValidCommitPreparationRequest, + sendCommitPreparationResponse, +} from "./server/commit-preparation"; export enum OdapMessageType { InitializationRequest = "urn:ietf:odap:msgtype:init-transfer-msg", @@ -110,6 +149,7 @@ interface IOdapHermesLog { operation: string; nodes: string; } + export class PluginOdapGateway implements ICactusPlugin, IPluginWebService { name: string; sessions: Map; @@ -319,18 +359,23 @@ export class PluginOdapGateway implements ICactusPlugin, IPluginWebService { } return; } + public get className(): string { return PluginOdapGateway.CLASS_NAME; } + public getOpenApiSpec(): unknown { return OAS; } + /*public getAspect(): PluginAspect { return PluginAspect.WEB_SERVICE; }*/ + public async onPluginInit(): Promise { return; } + async registerWebServices(app: Express): Promise { const webServices = await this.getOrCreateWebServices(); await Promise.all(webServices.map((ws) => ws.registerExpress(app))); @@ -342,31 +387,73 @@ export class PluginOdapGateway implements ICactusPlugin, IPluginWebService { return this.endpoints; } - const transferinitiation = new TransferInitiationEndpointV1({ + // Server endpoints + const transferInitiationRequestEndpoint = new TransferInitiationRequestEndpointV1( + { + gateway: this, + }, + ); + const transferCommenceRequestEndpoint = new TransferCommenceRequestEndpointV1( + { + gateway: this, + }, + ); + const lockEvidenceRequestEndpoint = new LockEvidenceRequestEndpointV1({ gateway: this, }); - const lockEvidencePreparation = new TransferCommenceEndpointV1({ + const commitPreparationRequestEndpoint = new CommitPreparationRequestEndpointV1( + { + gateway: this, + }, + ); + const commitFinalRequestEndpoint = new CommitFinalRequestEndpointV1({ gateway: this, }); - const lockEvidence = new LockEvidenceEndpointV1({ gateway: this }); - const commitPreparation = new CommitPrepareEndpointV1({ + const transferCompleteRequestEndpoint = new TransferCompleteRequestEndpointV1( + { + gateway: this, + }, + ); + + // Client endpoints + const clientRequestEndpoint = new ClientRequestEndpointV1({ gateway: this, }); - const commitFinal = new CommitFinalEndpointV1({ gateway: this }); - const transferComplete = new TransferCompleteEndpointV1({ + const transferInitiationResponseEndpoint = new TransferInitiationResponseEndpointV1( + { + gateway: this, + }, + ); + const transferCommenceResponseEndpoint = new TransferCommenceResponseEndpointV1( + { + gateway: this, + }, + ); + const lockEvidenceResponseEndpoint = new LockEvidenceResponseEndpointV1({ gateway: this, }); - const sendClientrequest = new SendClientRequestEndpointV1({ + const commitPreparationResponseEndpoint = new CommitPreparationResponseEndpointV1( + { + gateway: this, + }, + ); + const commitFinalResponseEndpoint = new CommitFinalResponseEndpointV1({ gateway: this, }); + this.endpoints = [ - transferinitiation, - lockEvidencePreparation, - lockEvidence, - commitPreparation, - commitFinal, - transferComplete, - sendClientrequest, + transferInitiationRequestEndpoint, + transferCommenceRequestEndpoint, + lockEvidenceRequestEndpoint, + commitPreparationRequestEndpoint, + commitFinalRequestEndpoint, + transferCompleteRequestEndpoint, + clientRequestEndpoint, + transferInitiationResponseEndpoint, + transferCommenceResponseEndpoint, + lockEvidenceResponseEndpoint, + commitPreparationResponseEndpoint, + commitFinalResponseEndpoint, ]; return this.endpoints; } @@ -433,111 +520,188 @@ export class PluginOdapGateway implements ICactusPlugin, IPluginWebService { } } - public async initiateTransferReceived( + public getOdapAPI(basePath: string): OdapApi { + const odapServerApiConfig = new Configuration({ + basePath: basePath, + }); + + return new OdapApi(odapServerApiConfig); + } + + //Server-side + public async onTransferInitiationRequestReceived( request: TransferInitializationV1Request, - ): Promise { - const fnTag = `${this.className}#initiateTransferReceived()`; + ): Promise { + const fnTag = `${this.className}#onTransferInitiationRequestReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - const initiateTransferResponse = await initiateTransfer(request, this); - this.log.info(`${fnTag}, complete processing, time: ${Date.now()}`); - return initiateTransferResponse; + this.log.info( + `server gateway received TransferInitializationRequest: ${JSON.stringify( + request, + )}`, + ); + + await checkValidInitializationRequest(request, this); + await sendTransferInitializationResponse(request.sessionID, this); } - public async transferCommenceReceived( + public async onTransferCommenceRequestReceived( request: TransferCommenceV1Request, - ): Promise { - const fnTag = `${this.className}#transferCommenceReceived()`; + ): Promise { + const fnTag = `${this.className}#onTransferCommenceRequestReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - const TransferCommenceResponse = await transferCommence(request, this); - this.log.info(`${fnTag}, complete processing, time: ${Date.now()}`); - return TransferCommenceResponse; + this.log.info( + `server gateway received TransferCommenceRequest: ${JSON.stringify( + request, + )}`, + ); + + await checkValidtransferCommenceRequest(request, this); + await sendTransferCommenceResponse(request.sessionID, this); } - public async lockEvidenceReceived( + public async onLockEvidenceRequestReceived( request: LockEvidenceV1Request, - ): Promise { - const fnTag = `${this.className}#LockEvidence()`; + ): Promise { + const fnTag = `${this.className}#onLockEvidenceRequestReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - const lockEvidenceResponse = await lockEvidence(request, this); - this.log.info(`${fnTag}, complete processing, time: ${Date.now()}`); - return lockEvidenceResponse; + this.log.info( + `server gateway received LockEvidenceRequest: ${JSON.stringify(request)}`, + ); + + await checkValidLockEvidenceRequest(request, this); + await sendLockEvidenceResponse(request.sessionID, this); } - public async commitPrepareReceived( + public async onCommitPrepareRequestReceived( request: CommitPreparationV1Request, - ): Promise { - const fnTag = `${this.className}#CommitPrepare()`; + ): Promise { + const fnTag = `${this.className}#onCommitPrepareRequestReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - const commitPrepareResponse = await commitPrepare(request, this); - this.log.info(`${fnTag}, complete processing, time: ${Date.now()}`); - return commitPrepareResponse; + this.log.info( + `server gateway received CommitPrepareRequest: ${JSON.stringify( + request, + )}`, + ); + + await checkValidCommitPreparationRequest(request, this); + await sendCommitPreparationResponse(request.sessionID, this); } - public async commitFinalReceived( + public async onCommitFinalRequestReceived( request: CommitFinalV1Request, - ): Promise { - const fnTag = `${this.className}#CommitFinal()`; + ): Promise { + const fnTag = `${this.className}#onCommitFinalRequestReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - const commitFinalResponse = await commitFinal(request, this); - this.log.info(`${fnTag}, complete processing, time: ${Date.now()}`); - return commitFinalResponse; + this.log.info( + `server gateway received CommitFinalRequest: ${JSON.stringify(request)}`, + ); + + await checkValidCommitFinalRequest(request, this); + await sendCommitFinalResponse(request.sessionID, this); } - public async transferCompleteReceived( + public async onTransferCompleteRequestReceived( request: TransferCompleteV1Request, - ): Promise { - const fnTag = `${this.className}#transferCompleteRequest()`; + ): Promise { + const fnTag = `${this.className}#onTransferCompleteRequestReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - const transferCompleteResponse = await transferComplete(request, this); - this.log.info(`${fnTag}, complete processing, time: ${Date.now()}`); - return transferCompleteResponse; + this.log.info( + `server gateway received TransferCompleteRequest: ${JSON.stringify( + request, + )}`, + ); + + await checkValidTransferCompleteRequest(request, this); } - public async runOdap(request: SendClientV1Request): Promise { - const fnTag = `${this.className}#runOdap()`; + //Client-side + public async onTransferInitiationResponseReceived( + request: TransferInitializationV1Response, + ): Promise { + const fnTag = `${this.className}#onTransferInitiationResponseReceived()`; this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); - - const { sessionID, odapServerApiClient } = this.configureOdapSession( - request, + this.log.info( + `client gateway received TransferInitiationResponse: ${JSON.stringify( + request, + )}`, ); - if (sessionID == undefined) { - throw new Error( - `${fnTag}, session id undefined after TransferInitiationMessages`, - ); - } - - // Phase 1 - await this.sendInitiationRequestMessage(sessionID, odapServerApiClient); + await checkValidInitializationResponse(request, this); + await sendTransferCommenceRequest(request.sessionID, this); + } - // Phase 2 - await this.sendTransferCommenceRequestMessage( - sessionID, - odapServerApiClient, + public async onTransferCommenceResponseReceived( + request: TransferCommenceV1Response, + ): Promise { + const fnTag = `${this.className}#onTransferCommenceResponseReceived()`; + this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); + this.log.info( + `client gateway received TransferCommenceResponse: ${JSON.stringify( + request, + )}`, ); - await this.sendLockEvidenceRequestMessage(sessionID, odapServerApiClient); + await checkValidTransferCommenceResponse(request, this); + await sendLockEvidenceRequest(request.sessionID, this); + } - // Phase 3 - await this.sendCommitPreparationRequestMessage( - sessionID, - odapServerApiClient, + public async onLockEvidenceResponseReceived( + request: LockEvidenceV1Response, + ): Promise { + const fnTag = `${this.className}#onLockEvidenceResponseReceived()`; + this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); + this.log.info( + `client gateway received LockEvidenceResponse: ${JSON.stringify( + request, + )}`, ); - await this.sendCommitFinalRequestMessage(sessionID, odapServerApiClient); + await checkValidLockEvidenceResponse(request, this); + await sendCommitPreparationRequest(request.sessionID, this); + } + + public async onCommitPrepareResponseReceived( + request: CommitPreparationV1Response, + ): Promise { + const fnTag = `${this.className}#onCommitPrepareResponseReceived()`; + this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); + + await checkValidCommitPreparationResponse(request, this); + await sendCommitFinalRequest(request.sessionID, this); + } - await this.sendTransferCompleteRequestMessage( - sessionID, - odapServerApiClient, + public async onCommitFinalResponseReceived( + request: CommitFinalV1Response, + ): Promise { + const fnTag = `${this.className}#onCommitFinalResponseReceived()`; + this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); + this.log.info( + `client gateway received CommitFinalResponse: ${JSON.stringify(request)}`, ); + + await checkValidCommitFinalResponse(request, this); + await sendTransferCompleteRequest(request.sessionID, this); } - private configureOdapSession(request: SendClientV1Request) { - const odapServerApiConfig = new Configuration({ - basePath: request.serverGatewayConfiguration.apiHost, - }); + public async runOdap(request: ClientV1Request): Promise { + const fnTag = `${this.className}#runOdap()`; + this.log.info(`${fnTag}, start processing, time: ${Date.now()}`); + this.log.info( + `client gateway received ClientRequest: ${JSON.stringify(request)}`, + ); + + const sessionID = this.configureOdapSession(request); + + if (sessionID == undefined) { + throw new Error( + `${fnTag}, session id undefined after session configuration`, + ); + } + + await sendTransferInitializationRequest(sessionID, this); + } - const odapServerApiClient = new OdapApi(odapServerApiConfig); + private configureOdapSession(request: ClientV1Request) { const sessionData: SessionData = {}; const sessionID = uuidV4(); @@ -546,6 +710,8 @@ export class PluginOdapGateway implements ICactusPlugin, IPluginWebService { sessionData.step = 1; sessionData.version = request.version; sessionData.lastSequenceNumber = randomInt(4294967295); + sessionData.sourceBasePath = request.clientGatewayConfiguration.apiHost; + sessionData.recipientBasePath = request.serverGatewayConfiguration.apiHost; sessionData.payloadProfile = request.payloadProfile; sessionData.loggingProfile = request.loggingProfile; @@ -561,1006 +727,109 @@ export class PluginOdapGateway implements ICactusPlugin, IPluginWebService { this.sessions.set(sessionID, sessionData); - return { sessionID, odapServerApiClient }; + return sessionID; } - private async sendInitiationRequestMessage( - sessionID: string, - odapServerApiClient: OdapApi, - ): Promise { - const fnTag = `${this.className}#sendInitiationRequestMessage()`; + public async lockFabricAsset(sessionID: string) { + const fnTag = `${this.className}#lockFabricAsset()`; const sessionData = this.sessions.get(sessionID); - if ( - sessionData == undefined || - sessionData.id == undefined || - sessionData.step == undefined || - sessionData.version == undefined || - sessionData.payloadProfile == undefined || - sessionData.loggingProfile == undefined || - sessionData.accessControlProfile == undefined || - sessionData.applicationProfile == undefined || - sessionData.lastSequenceNumber == undefined || - sessionData.sourceGatewayDltSystem == undefined || - sessionData.recipientGatewayPubkey == undefined || - sessionData.recipientGatewayDltSystem == undefined - ) { + if (sessionData == undefined) { throw new Error(`${fnTag}, session data is not correctly initialized`); } - await this.storeOdapLog( - { - phase: "p1", - step: sessionData.step.toString(), - type: "init", - operation: "validate", - nodes: `${this.pubKey}->${sessionData.recipientGatewayPubkey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - const initializationRequestMessage: TransferInitializationV1Request = { - messageType: OdapMessageType.InitializationRequest, - sessionID: sessionData.id, - version: sessionData.version, - // developer urn - // credential profile - payloadProfile: sessionData.payloadProfile, - applicationProfile: sessionData.applicationProfile, - loggingProfile: sessionData.loggingProfile, - accessControlProfile: sessionData.accessControlProfile, - clientSignature: "", - sourceGatewayPubkey: this.pubKey, - sourceGatewayDltSystem: sessionData.sourceGatewayDltSystem, - recipientGatewayPubkey: sessionData.recipientGatewayPubkey, - recipientGatewayDltSystem: sessionData.recipientGatewayDltSystem, - sequenceNumber: sessionData.lastSequenceNumber, - // escrow type - // expiry time (related to the escrow) - // multiple claims allowed - // multiple cancels allowed - // permissions - }; - - if (!this.supportedDltIDs.includes(sessionData.recipientGatewayDltSystem)) { - throw new Error( - `${fnTag}, recipient gateway dlt system is not supported by this gateway`, - ); + if (this.fabricApi == undefined) { + //throw new Error(`${fnTag}, connection to Fabric is not defined`); + return ""; } - this.log.info( - `${fnTag}, creating TransferInitializationRequest message signature`, - ); + const lockRes = await this.fabricApi.runTransactionV1({ + signingCredential: this.fabricSigningCredential, + channelName: this.fabricChannelName, + contractName: this.fabricContractName, + invocationType: FabricContractInvocationType.Send, + methodName: "LockAsset", + params: [this.fabricAssetID], + } as FabricRunTransactionRequest); - const messageSignature = this.bufArray2HexStr( - this.sign(JSON.stringify(initializationRequestMessage)), - ); + const receiptLockRes = await this.fabricApi.getTransactionReceiptByTxIDV1({ + signingCredential: this.fabricSigningCredential, + channelName: this.fabricChannelName, + contractName: "qscc", + invocationType: FabricContractInvocationType.Call, + methodName: "GetBlockByTxID", + params: [this.fabricChannelName, lockRes.data.transactionId], + } as FabricRunTransactionRequest); - this.log.info( - `${fnTag}, created TransferInitializationRequest message signature with value: ${messageSignature}`, - ); + this.log.warn(receiptLockRes.data); + const fabricLockAssetProof = JSON.stringify(receiptLockRes.data); - initializationRequestMessage.clientSignature = messageSignature; + sessionData.isFabricAssetLocked = true; - this.log.info( - `${fnTag}, TransferInitializationRequest message sent, time: ${Date.now()}`, - ); + return fabricLockAssetProof; + } - const transferInitiationResponse = await odapServerApiClient.phase1TransferInitiationV1( - initializationRequestMessage, - ); + public async createBesuAsset(sessionID: string) { + const fnTag = `${this.className}#createBesuAsset()`; - this.log.info( - `${fnTag}, TransferInitializationResponse message received, time: ${Date.now()}`, - ); + const sessionData = this.sessions.get(sessionID); - if (transferInitiationResponse.status != 200) { - throw new Error( - `${fnTag}, TransferInitializationResponse message failed`, - ); + if (sessionData == undefined) { + throw new Error(`${fnTag}, session data is not correctly initialized`); } - const transferInitiationResponseData: TransferInitializationV1Response = - transferInitiationResponse.data; - - if ( - transferInitiationResponseData.messageType != - OdapMessageType.InitializationResponse - ) { - throw new Error( - `${fnTag}, wrong message type for TransferInitializationResponse`, - ); + if (this.besuApi == undefined) { + //throw new Error(`${fnTag}, connection to Fabric is not defined`); + return ""; } - const sentMessageHash = SHA256( - JSON.stringify(initializationRequestMessage), - ).toString(); + let besuCreateAssetProof = ""; - if ( - transferInitiationResponseData.sequenceNumber != - initializationRequestMessage.sequenceNumber - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse sequence number incorrect`, - ); - } + if (this.besuApi != undefined) { + const besuCreateRes = await this.besuApi.invokeContractV1({ + contractName: this.besuContractName, + invocationType: EthContractInvocationType.Send, + methodName: "createAsset", + gas: 1000000, + params: [this.besuAssetID, 100], //the second is size, may need to pass this from client? + signingCredential: this.besuWeb3SigningCredential, + keychainId: this.besuKeychainId, + } as BesuInvokeContractV1Request); - if ( - transferInitiationResponseData.initialRequestMessageHash != - sentMessageHash - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse previous message hash does not match the one that was sent`, - ); - } + if (besuCreateRes.status != 200) { + //await this.Revert(sessionID); + throw new Error(`${fnTag}, besu create asset error`); + } - if ( - transferInitiationResponseData.serverIdentityPubkey != - initializationRequestMessage.recipientGatewayPubkey - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse serverIdentity public key does not match the one that was sent`, + const besuCreateResDataJson = JSON.parse( + JSON.stringify(besuCreateRes.data), ); - } - - const transferInitiationResponseDataSignature = - transferInitiationResponseData.serverSignature; - const sourceServerSignature = new Uint8Array( - Buffer.from(transferInitiationResponseDataSignature, "hex"), - ); + if (besuCreateResDataJson.out == undefined) { + throw new Error(`${fnTag}, besu res data out undefined`); + } - const sourceServerPubkey = new Uint8Array( - Buffer.from(initializationRequestMessage.recipientGatewayPubkey, "hex"), - ); + if (besuCreateResDataJson.out.transactionReceipt == undefined) { + throw new Error(`${fnTag}, undefined besu transact receipt`); + } - transferInitiationResponseData.serverSignature = ""; + const besuCreateAssetReceipt = + besuCreateResDataJson.out.transactionReceipt; + besuCreateAssetProof = JSON.stringify(besuCreateAssetReceipt); + const besuCreateProofID = `${sessionID}-proof-of-create`; - if ( - !this.verifySignature( - JSON.stringify(transferInitiationResponseData), - sourceServerSignature, - sourceServerPubkey, - ) - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse message signature verification failed`, + await this.publishOdapProof( + besuCreateProofID, + JSON.stringify(besuCreateAssetReceipt), ); - } - - const serverIdentityPubkey = - transferInitiationResponseData.serverIdentityPubkey; - - sessionData.step++; - - sessionData.id = transferInitiationResponseData.sessionID; - - sessionData.recipientGatewayPubkey = serverIdentityPubkey; - - sessionData.initializationRequestMessageHash = sentMessageHash; - - sessionData.initializationResponseMessageHash = SHA256( - JSON.stringify(transferInitiationResponseData), - ).toString(); - - sessionData.clientSignatureInitializationRequestMessage = - initializationRequestMessage.clientSignature; - - sessionData.serverSignatureInitializationResponseMessage = - transferInitiationResponseData.serverSignature; - - sessionData.fabricAssetSize = "1"; - - this.sessions.set(sessionData.id, sessionData); - } - - private async sendTransferCommenceRequestMessage( - sessionID: string, - odapServerApiClient: OdapApi, - ): Promise { - const fnTag = `${this.className}#sendTransferCommenceMessage()`; - - const sessionData = this.sessions.get(sessionID); - - if ( - sessionData == undefined || - sessionData.step == undefined || - sessionData.assetProfile == undefined || - sessionData.originatorPubkey == undefined || - sessionData.beneficiaryPubkey == undefined || - sessionData.lastSequenceNumber == undefined || - sessionData.sourceGatewayPubkey == undefined || - sessionData.recipientGatewayPubkey == undefined || - sessionData.sourceGatewayDltSystem == undefined || - sessionData.recipientGatewayDltSystem == undefined || - sessionData.initializationRequestMessageHash == undefined - ) { - throw new Error(`${fnTag}, session data is not correctly initialized`); - } - - await this.storeOdapLog( - { - phase: "p2", - step: sessionData.step.toString(), - type: "init", - operation: "commence", - nodes: `${this.pubKey}->${sessionData.recipientGatewayPubkey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - const hashAssetProfile = SHA256( - JSON.stringify(sessionData.assetProfile), - ).toString(); - - const transferCommenceRequestMessage: TransferCommenceV1Request = { - messageType: OdapMessageType.TransferCommenceRequest, - originatorPubkey: sessionData.originatorPubkey, - beneficiaryPubkey: sessionData.beneficiaryPubkey, - senderDltSystem: sessionData.sourceGatewayDltSystem, - recipientDltSystem: sessionData.recipientGatewayDltSystem, - sessionID: sessionID, - clientIdentityPubkey: sessionData.sourceGatewayPubkey, - serverIdentityPubkey: sessionData.recipientGatewayPubkey, - hashAssetProfile: hashAssetProfile, - hashPrevMessage: sessionData.initializationRequestMessageHash, - // clientTransferNumber - clientSignature: "", - sequenceNumber: sessionData.lastSequenceNumber, - }; - - const messageSignature = this.bufArray2HexStr( - this.sign(JSON.stringify(transferCommenceRequestMessage)), - ); - - this.log.info( - `${fnTag}, created TransferCommenceRequest message signature with value: ${messageSignature}`, - ); - - transferCommenceRequestMessage.clientSignature = messageSignature; - - this.log.info( - `${fnTag}, TransferCommenceRequest message sent, time: ${Date.now()}`, - ); - - const transferCommenceResponse = await odapServerApiClient.phase2TransferCommenceV1( - transferCommenceRequestMessage, - ); - - this.log.info( - `${fnTag}, TransferCommenceResponse message received, time: ${Date.now()}`, - ); - if (transferCommenceResponse.status != 200) { - await this.Revert(sessionID); - throw new Error(`${fnTag}, TransferCommenceResponse message failed`); + sessionData.isBesuAssetCreated = true; } - - const transferCommenceResponseData: TransferCommenceV1Response = - transferCommenceResponse.data; - - if ( - transferCommenceResponseData.messageType != - OdapMessageType.TransferCommenceResponse - ) { - throw new Error( - `${fnTag}, wrong message type for TransferCommenceResponse`, - ); - } - - const sentMessageHash = SHA256( - JSON.stringify(transferCommenceRequestMessage), - ).toString(); - - if ( - transferCommenceResponseData.sequenceNumber != - transferCommenceRequestMessage.sequenceNumber - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse sequence number incorrect`, - ); - } - - if (sentMessageHash != transferCommenceResponseData.hashCommenceRequest) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, TransferCommenceResponse previous message hash does not match the one that was sent`, - ); - } - - if ( - transferCommenceRequestMessage.serverIdentityPubkey != - transferCommenceResponseData.serverIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, TransferCommenceResponse serverIdentity public key does not match the one that was sent`, - ); - } - - if ( - transferCommenceRequestMessage.clientIdentityPubkey != - transferCommenceResponseData.clientIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, TransferCommenceResponse clientIdentity public key does not match the one that was sent`, - ); - } - - const transferCommenceResponseDataSignature = - transferCommenceResponseData.serverSignature; - - const sourceServerSignature = new Uint8Array( - Buffer.from(transferCommenceResponseDataSignature, "hex"), - ); - - const sourceServerPubkey = new Uint8Array( - Buffer.from(sessionData.recipientGatewayPubkey, "hex"), - ); - - transferCommenceResponseData.serverSignature = ""; - - if ( - !this.verifySignature( - JSON.stringify(transferCommenceResponseData), - sourceServerSignature, - sourceServerPubkey, - ) - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, TransferCommenceResponse message signature verification failed`, - ); - } - - transferCommenceResponseData.serverSignature = transferCommenceResponseDataSignature; - - sessionData.step++; - - sessionData.transferCommenceMessageRequestHash = sentMessageHash; - - sessionData.transferCommenceMessageResponseHash = SHA256( - JSON.stringify(transferCommenceResponseData), - ).toString(); - - sessionData.clientSignatureTransferCommenceRequestMessage = - transferCommenceRequestMessage.clientSignature; - - sessionData.serverSignatureTransferCommenceResponseMessage = - transferCommenceResponseData.serverSignature; - - this.sessions.set(sessionID, sessionData); - } - - private async sendLockEvidenceRequestMessage( - sessionID: string, - odapServerApiClient: OdapApi, - ) { - const fnTag = `${this.className}#sendLockEvidenceRequestMessage()`; - - const sessionData = this.sessions.get(sessionID); - - if ( - sessionData == undefined || - sessionData.step == undefined || - sessionData.lastSequenceNumber == undefined || - sessionData.sourceGatewayPubkey == undefined || - sessionData.recipientGatewayPubkey == undefined || - sessionData.transferCommenceMessageResponseHash == undefined - ) { - throw new Error(`${fnTag}, session data is not correctly initialized`); - } - - await this.storeOdapLog( - { - phase: "p2", - step: sessionData.step.toString(), - type: "init", - operation: "lock", - nodes: `${this.pubKey}->${sessionData.recipientGatewayPubkey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - const fabricLockAssetProof = await this.lockFabricAsset(sessionID); - - this.log.info(`${fnTag}, proof of the asset lock: ${fabricLockAssetProof}`); - - const lockEvidenceRequestMessage: LockEvidenceV1Request = { - sessionID: sessionID, - messageType: OdapMessageType.LockEvidenceRequest, - clientIdentityPubkey: sessionData.sourceGatewayPubkey, - serverIdentityPubkey: sessionData.recipientGatewayPubkey, - lockEvidenceClaim: fabricLockAssetProof, - // lock claim format - lockEvidenceExpiration: new Date() - .setDate(new Date().getDate() + 1) - .toString(), // a day from now - hashCommenceAckRequest: sessionData.transferCommenceMessageResponseHash, - clientSignature: "", - sequenceNumber: sessionData.lastSequenceNumber, - }; - - const messageSignature = this.bufArray2HexStr( - this.sign(JSON.stringify(lockEvidenceRequestMessage)), - ); - - this.log.info( - `${fnTag}, created LockEvidenceRequest message signature with value: ${messageSignature}`, - ); - - lockEvidenceRequestMessage.clientSignature = messageSignature; - - this.log.info( - `${fnTag}, LockEvidenceRequest message sent, time: ${Date.now()}`, - ); - - const lockEvidenceResponseMesssage = await odapServerApiClient.phase2LockEvidenceV1( - lockEvidenceRequestMessage, - ); - - this.log.info( - `${fnTag}, LockEvidenceRequest message received, time: ${Date.now()}`, - ); - - if (lockEvidenceResponseMesssage.status != 200) { - await this.Revert(sessionID); - throw new Error(`${fnTag}, LockEvidenceResponse message failed`); - } - - const lockEvidenceResponseMesssageData: LockEvidenceV1Response = - lockEvidenceResponseMesssage.data; - - if ( - lockEvidenceResponseMesssageData.messageType != - OdapMessageType.LockEvidenceResponse - ) { - throw new Error(`${fnTag}, wrong message type for LockEvidenceResponse`); - } - - const sentMessageHash = SHA256( - JSON.stringify(lockEvidenceRequestMessage), - ).toString(); - - if ( - lockEvidenceResponseMesssageData.sequenceNumber != - lockEvidenceRequestMessage.sequenceNumber - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse sequence number incorrect`, - ); - } - - if ( - sentMessageHash != - lockEvidenceResponseMesssageData.hashLockEvidenceRequest - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, LockEvidenceResponse previous message hash does not match the one that was sent`, - ); - } - - if ( - lockEvidenceRequestMessage.serverIdentityPubkey != - lockEvidenceResponseMesssageData.serverIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, LockEvidenceResponse serverIdentity public key does not match the one that was sent`, - ); - } - - if ( - lockEvidenceRequestMessage.clientIdentityPubkey != - lockEvidenceResponseMesssageData.clientIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, LockEvidenceResponse clientIdentity public key does not match the one that was sent`, - ); - } - - const lockEvidenceResponseMesssageDataSignature = - lockEvidenceResponseMesssageData.serverSignature; - - const sourceServerSignature = new Uint8Array( - Buffer.from(lockEvidenceResponseMesssageDataSignature, "hex"), - ); - - const sourceServerPubkey = new Uint8Array( - Buffer.from(sessionData.recipientGatewayPubkey, "hex"), - ); - - lockEvidenceResponseMesssageData.serverSignature = ""; - - if ( - !this.verifySignature( - JSON.stringify(lockEvidenceResponseMesssageData), - sourceServerSignature, - sourceServerPubkey, - ) - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, LockEvidenceResponse message signature verification failed`, - ); - } - - lockEvidenceResponseMesssageData.serverSignature = lockEvidenceResponseMesssageDataSignature; - - sessionData.step++; - - sessionData.lockEvidenceRequestMessageHash = sentMessageHash; - - sessionData.lockEvidenceResponseMessageHash = SHA256( - JSON.stringify(lockEvidenceResponseMesssageData), - ).toString(); - - sessionData.clientSignatureLockEvidenceRequestMessage = - lockEvidenceRequestMessage.clientSignature; - - sessionData.serverSignatureLockEvidenceResponseMessage = - lockEvidenceResponseMesssageData.serverSignature; - - sessionData.lockEvidenceClaim = fabricLockAssetProof; - - this.sessions.set(sessionID, sessionData); - } - - private async sendCommitPreparationRequestMessage( - sessionID: string, - odapServerApiClient: OdapApi, - ) { - const fnTag = `${this.className}#sendCommitPreparationRequestMessage()`; - - const sessionData = this.sessions.get(sessionID); - - if ( - sessionData == undefined || - sessionData.step == undefined || - sessionData.lastSequenceNumber == undefined || - sessionData.sourceGatewayPubkey == undefined || - sessionData.recipientGatewayPubkey == undefined || - sessionData.lockEvidenceResponseMessageHash == undefined - ) { - throw new Error(`${fnTag}, session data is not correctly initialized`); - } - - await this.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "init", - operation: "commit-prepare", - nodes: `${this.pubKey}->${sessionData.recipientGatewayPubkey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - const commitPrepareRequestMessage: CommitPreparationV1Request = { - sessionID: sessionID, - messageType: OdapMessageType.CommitPreparationRequest, - clientIdentityPubkey: sessionData.sourceGatewayPubkey, - serverIdentityPubkey: sessionData.recipientGatewayPubkey, - hashLockEvidenceAck: sessionData.lockEvidenceResponseMessageHash, - clientSignature: "", - sequenceNumber: sessionData.lastSequenceNumber, - }; - - const messageSignature = this.bufArray2HexStr( - this.sign(JSON.stringify(commitPrepareRequestMessage)), - ); - - this.log.info( - `${fnTag}, created CommitPreparationRequest message signature with value: ${messageSignature}`, - ); - - commitPrepareRequestMessage.clientSignature = messageSignature; - - this.log.info( - `${fnTag}, CommitPreparationRequest message sent, time: ${Date.now()}`, - ); - - const commitPrepareResponseMessage = await odapServerApiClient.phase3CommitPreparationV1( - commitPrepareRequestMessage, - ); - - this.log.info( - `${fnTag}, CommitPreparationRequest message received, time: ${Date.now()}`, - ); - - if (commitPrepareResponseMessage.status != 200) { - await this.Revert(sessionID); - throw new Error(`${fnTag}, CommitPreparationRequest message failed`); - } - - const commitPrepareResponseMessageData: CommitPreparationV1Response = - commitPrepareResponseMessage.data; - - if ( - commitPrepareResponseMessageData.messageType != - OdapMessageType.CommitPreparationResponse - ) { - throw new Error( - `${fnTag}, wrong message type for CommitPreparationResponse`, - ); - } - - const sentMessageHash = SHA256( - JSON.stringify(commitPrepareRequestMessage), - ).toString(); - - if ( - commitPrepareResponseMessageData.sequenceNumber != - commitPrepareRequestMessage.sequenceNumber - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse sequence number incorrect`, - ); - } - - if (sentMessageHash != commitPrepareResponseMessageData.hashCommitPrep) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitPreparationResponse previous message hash does not match the one that was sent`, - ); - } - - if ( - commitPrepareRequestMessage.serverIdentityPubkey != - commitPrepareResponseMessageData.serverIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitPreparationResponse serverIdentity public key does not match the one that was sent`, - ); - } - - if ( - commitPrepareRequestMessage.clientIdentityPubkey != - commitPrepareResponseMessageData.clientIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitPreparationResponse clientIdentity public key does not match the one that was sent`, - ); - } - - const commitPrepareResponseMessageDataSignature = - commitPrepareResponseMessageData.serverSignature; - - const sourceServerSignature = new Uint8Array( - Buffer.from(commitPrepareResponseMessageDataSignature, "hex"), - ); - - const sourceServerPubkey = new Uint8Array( - Buffer.from(sessionData.recipientGatewayPubkey, "hex"), - ); - - commitPrepareResponseMessageData.serverSignature = ""; - - if ( - !this.verifySignature( - JSON.stringify(commitPrepareResponseMessageData), - sourceServerSignature, - sourceServerPubkey, - ) - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, LockEvidenceResponse message signature verification failed`, - ); - } - - commitPrepareResponseMessageData.serverSignature = commitPrepareResponseMessageDataSignature; - - sessionData.step++; - - sessionData.commitPrepareRequestMessageHash = sentMessageHash; - - sessionData.commitPrepareResponseMessageHash = SHA256( - JSON.stringify(commitPrepareResponseMessageData), - ).toString(); - - sessionData.clientSignatureCommitPreparationRequestMessage = - commitPrepareRequestMessage.clientSignature; - - sessionData.serverSignatureCommitPreparationResponseMessage = - commitPrepareResponseMessageData.serverSignature; - - this.sessions.set(sessionID, sessionData); - } - - private async sendCommitFinalRequestMessage( - sessionID: string, - odapServerApiClient: OdapApi, - ) { - const fnTag = `${this.className}#sendCommitFinalRequestMessage()`; - - const sessionData = this.sessions.get(sessionID); - - if ( - sessionData == undefined || - sessionData.step == undefined || - sessionData.lastSequenceNumber == undefined || - sessionData.sourceGatewayPubkey == undefined || - sessionData.recipientGatewayPubkey == undefined || - sessionData.commitPrepareResponseMessageHash == undefined - ) { - throw new Error(`${fnTag}, session data is not correctly initialized`); - } - - await this.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "init", - operation: "commit-final", - nodes: `${this.pubKey}->${sessionData.recipientGatewayPubkey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - const fabricDeleteAssetProof = await this.deleteFabricAsset(sessionID); - - const commitFinalRequestMessage: CommitFinalV1Request = { - sessionID: sessionID, - messageType: OdapMessageType.CommitFinalRequest, - clientIdentityPubkey: sessionData.sourceGatewayPubkey, - serverIdentityPubkey: sessionData.recipientGatewayPubkey, - commitFinalClaim: fabricDeleteAssetProof, - // commit final claim format - hashCommitPrepareAck: sessionData.commitPrepareResponseMessageHash, - clientSignature: "", - sequenceNumber: sessionData.lastSequenceNumber, - }; - - const messageSignature = this.bufArray2HexStr( - this.sign(JSON.stringify(commitFinalRequestMessage)), - ); - - this.log.info( - `${fnTag}, created CommitFinalRequest message signature with value: ${messageSignature}`, - ); - - commitFinalRequestMessage.clientSignature = messageSignature; - - this.log.info( - `${fnTag}, CommitFinalRequest message sent, time: ${Date.now()}`, - ); - - const commitFinalResponseMessage = await odapServerApiClient.phase3CommitFinalV1( - commitFinalRequestMessage, - ); - - this.log.info( - `${fnTag}, CommitFinalRequest message received, time: ${Date.now()}`, - ); - - if (commitFinalResponseMessage.status != 200) { - await this.Revert(sessionID); - throw new Error(`${fnTag}, CommitFinalRequest message failed`); - } - - const commitFinalResponseMessageData: CommitFinalV1Response = - commitFinalResponseMessage.data; - - if ( - commitFinalResponseMessageData.messageType != - OdapMessageType.CommitFinalResponse - ) { - throw new Error(`${fnTag}, wrong message type for CommitFinalResponse`); - } - - const sentMessageHash = SHA256( - JSON.stringify(commitFinalRequestMessage), - ).toString(); - - if ( - commitFinalResponseMessageData.sequenceNumber != - commitFinalRequestMessage.sequenceNumber - ) { - throw new Error( - `${fnTag}, TransferInitializationResponse sequence number incorrect`, - ); - } - - if (sentMessageHash != commitFinalResponseMessageData.hashCommitFinal) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitFinalResponse previous message hash does not match the one that was sent`, - ); - } - - if ( - commitFinalRequestMessage.serverIdentityPubkey != - commitFinalResponseMessageData.serverIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitFinalResponse serverIdentity public key does not match the one that was sent`, - ); - } - - if ( - commitFinalRequestMessage.clientIdentityPubkey != - commitFinalResponseMessageData.clientIdentityPubkey - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitFinalResponse clientIdentity public key does not match the one that was sent`, - ); - } - - const commitFinalResponseMessageDataSignature = - commitFinalResponseMessageData.serverSignature; - - const sourceServerSignature = new Uint8Array( - Buffer.from(commitFinalResponseMessageDataSignature, "hex"), - ); - - const sourceServerPubkey = new Uint8Array( - Buffer.from(sessionData.recipientGatewayPubkey, "hex"), - ); - - commitFinalResponseMessageData.serverSignature = ""; - - if ( - !this.verifySignature( - JSON.stringify(commitFinalResponseMessageData), - sourceServerSignature, - sourceServerPubkey, - ) - ) { - await this.Revert(sessionID); - throw new Error( - `${fnTag}, CommitFinalResponse message signature verification failed`, - ); - } - - commitFinalResponseMessageData.serverSignature = commitFinalResponseMessageDataSignature; - - sessionData.step++; - - sessionData.commitFinalRequestMessageHash = sentMessageHash; - - sessionData.commitFinalResponseMessageHash = SHA256( - JSON.stringify(commitFinalResponseMessageData), - ).toString(); - - sessionData.clientSignatureCommitFinalRequestMessage = - commitFinalRequestMessage.clientSignature; - - sessionData.serverSignatureCommitFinalResponseMessage = - commitFinalResponseMessageData.serverSignature; - - this.sessions.set(sessionID, sessionData); - } - - private async sendTransferCompleteRequestMessage( - sessionID: string, - odapServerApiClient: OdapApi, - ) { - const fnTag = `${this.className}#sendTransferCompleteRequestMessage()`; - - const sessionData = this.sessions.get(sessionID); - - if ( - sessionData == undefined || - sessionData.step == undefined || - sessionData.lastSequenceNumber == undefined || - sessionData.sourceGatewayPubkey == undefined || - sessionData.recipientGatewayPubkey == undefined || - sessionData.commitFinalResponseMessageHash == undefined || - sessionData.transferCommenceMessageRequestHash == undefined - ) { - throw new Error(`${fnTag}, session data is not correctly initialized`); - } - - await this.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "init", - operation: "transfer-complete", - nodes: `${this.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - const transferCompleteRequestMessage: TransferCompleteV1Request = { - sessionID: sessionID, - messageType: OdapMessageType.TransferCompleteRequest, - clientIdentityPubkey: sessionData.sourceGatewayPubkey, - serverIdentityPubkey: sessionData.recipientGatewayPubkey, - hashCommitFinalAck: sessionData.commitFinalResponseMessageHash, - hashTransferCommence: sessionData.transferCommenceMessageRequestHash, - clientSignature: "", - sequenceNumber: sessionData.lastSequenceNumber, - }; - - const messageSignature = this.bufArray2HexStr( - this.sign(JSON.stringify(transferCompleteRequestMessage)), - ); - - this.log.info( - `${fnTag}, created TransferCompleteRequest message signature with value: ${messageSignature}`, - ); - - transferCompleteRequestMessage.clientSignature = messageSignature; - - this.log.info( - `${fnTag}, TransferCompleteRequest message sent, time: ${Date.now()}`, - ); - - const transferCompleteResponseMessage = await odapServerApiClient.phase3TransferCompleteV1( - transferCompleteRequestMessage, - ); - - this.log.info( - `${fnTag}, TransferCompleteRequest message received, time: ${Date.now()}`, - ); - - if (transferCompleteResponseMessage.status != 200) { - throw new Error(`${fnTag}, TransferCompleteRequest message failed`); - } - - sessionData.step++; - - sessionData.transferCompleteMessageHash = SHA256( - JSON.stringify(transferCompleteRequestMessage), - ).toString(); - - sessionData.clientSignatureCommitFinalRequestMessage = - transferCompleteRequestMessage.clientSignature; - - this.sessions.set(sessionID, sessionData); - } - - private async lockFabricAsset(sessionID: string) { - const fnTag = `${this.className}#lockFabricAsset()`; - - const sessionData = this.sessions.get(sessionID); - - if (sessionData == undefined) { - throw new Error(`${fnTag}, session data is not correctly initialized`); - } - - if (this.fabricApi == undefined) { - //throw new Error(`${fnTag}, connection to Fabric is not defined`); - return ""; - } - - const lockRes = await this.fabricApi.runTransactionV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: this.fabricContractName, - invocationType: FabricContractInvocationType.Send, - methodName: "LockAsset", - params: [this.fabricAssetID], - } as FabricRunTransactionRequest); - - const receiptLockRes = await this.fabricApi.getTransactionReceiptByTxIDV1({ - signingCredential: this.fabricSigningCredential, - channelName: this.fabricChannelName, - contractName: "qscc", - invocationType: FabricContractInvocationType.Call, - methodName: "GetBlockByTxID", - params: [this.fabricChannelName, lockRes.data.transactionId], - } as FabricRunTransactionRequest); - - this.log.warn(receiptLockRes.data); - const fabricLockAssetProof = JSON.stringify(receiptLockRes.data); - - sessionData.isFabricAssetLocked = true; - - return fabricLockAssetProof; + return besuCreateAssetProof; } - private async deleteFabricAsset(sessionID: string) { + public async deleteFabricAsset(sessionID: string) { const fnTag = `${this.className}#deleteFabricAsset()`; const sessionData = this.sessions.get(sessionID); diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-final.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-final.ts new file mode 100644 index 0000000000..cb69119c34 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-final.ts @@ -0,0 +1,215 @@ +import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; +import { SHA256 } from "crypto-js"; +import { LoggerProvider } from "@hyperledger/cactus-common"; +import { + CommitFinalV1Request, + CommitFinalV1Response, +} from "../../generated/openapi/typescript-axios"; + +const log = LoggerProvider.getOrCreate({ + level: "INFO", + label: "server-commit-final-helper", +}); + +export async function sendCommitFinalResponse( + sessionID: string, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#sendCommitFinalResponse()`; + + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.sourceBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.commitFinalRequestMessageHash == undefined + ) { + throw new Error(`${fnTag}, session data is undefined`); + } + + const besuCreateAssetProof = await odap.createBesuAsset(sessionID); + sessionData.commitAcknowledgementClaim = besuCreateAssetProof; + + const commitFinalResponseMessage: CommitFinalV1Response = { + sessionID: sessionID, + messageType: OdapMessageType.CommitFinalResponse, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + commitAcknowledgementClaim: besuCreateAssetProof, + hashCommitFinal: sessionData.commitFinalRequestMessageHash, + serverSignature: "", + sequenceNumber: ++sessionData.lastSequenceNumber, + }; + + commitFinalResponseMessage.serverSignature = odap.bufArray2HexStr( + await odap.sign(JSON.stringify(commitFinalResponseMessage)), + ); + + sessionData.commitFinalResponseMessageHash = SHA256( + JSON.stringify(commitFinalResponseMessage), + ).toString(); + + sessionData.serverSignatureCommitFinalResponseMessage = + commitFinalResponseMessage.serverSignature; + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "ack", + operation: "commit-prepare", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + sessionData.step++; + + odap.sessions.set(sessionID, sessionData); + + // Log init??? + + log.info(`${fnTag}, sending CommitFinalResponse...`); + + const response = await odap + .getOdapAPI(sessionData.sourceBasePath) + .phase3CommitFinalResponseV1(commitFinalResponseMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, CommitFinalResponse message failed`); + } +} + +export async function checkValidCommitFinalRequest( + request: CommitFinalV1Request, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidCommitFinalRequest()`; + + const sessionID = request.sessionID; + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.id == undefined || + sessionData.step == undefined || + sessionData.lastSequenceNumber == undefined + ) { + throw new Error( + `${fnTag}, session Id does not correspond to any open session`, + ); + } + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "exec", + operation: "commit-final", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + if (request.messageType != OdapMessageType.CommitFinalRequest) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, wrong message type for CommitFinalRequest`); + } + + if (request.sequenceNumber != sessionData.lastSequenceNumber + 1) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, CommitFinalRequest sequence number incorrect`); + } + + if (request.commitFinalClaim == undefined) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, claim presented by client is invalid`); + } + + if (sessionData.recipientGatewayPubkey != request.serverIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalRequest serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != request.clientIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalRequest clientIdentity public key does not match the one that was sent`, + ); + } + + if ( + sessionData.commitPrepareResponseMessageHash != request.hashCommitPrepareAck + ) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, previous message hash does not match`); + } + + const sourceClientSignature = new Uint8Array( + Buffer.from(request.clientSignature, "hex"), + ); + + const sourceClientPubkey = new Uint8Array( + Buffer.from(request.clientIdentityPubkey, "hex"), + ); + + const signature = request.clientSignature; + request.clientSignature = ""; + if ( + !odap.verifySignature( + JSON.stringify(request), + sourceClientSignature, + sourceClientPubkey, + ) + ) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitFinalRequest message signature verification failed`, + ); + } + request.clientSignature = signature; + + // We need to check somewhere if this phase is completed within the asset-lock duration. + + storeSessionData(request, odap); + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "done", + operation: "commit-final", + nodes: `${odap.pubKey}}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + log.info(`CommitFinalRequest passed all checks.`); +} + +async function storeSessionData( + request: CommitFinalV1Request, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#()storeSessionData`; + const sessionData = odap.sessions.get(request.sessionID); + + if (sessionData == undefined) { + throw new Error(`${fnTag}, session data is undefined`); + } + + sessionData.commitFinalClaim = request.commitFinalClaim; + + sessionData.commitFinalRequestMessageHash = SHA256( + JSON.stringify(request), + ).toString(); + + sessionData.clientSignatureCommitFinalRequestMessage = + request.clientSignature; + + odap.sessions.set(request.sessionID, sessionData); +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-prepare-helper.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-preparation.ts similarity index 53% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-prepare-helper.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-preparation.ts index 6dc3438a9a..4394e87c88 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/commit-prepare-helper.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/commit-preparation.ts @@ -8,75 +8,49 @@ import { const log = LoggerProvider.getOrCreate({ level: "INFO", - label: "odap-lock-evidence-helper", + label: "server-commit-preparation-helper", }); -export async function commitPrepare( - request: CommitPreparationV1Request, +export async function sendCommitPreparationResponse( + sessionID: string, odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#CommitPrepare()`; - log.info( - `server gateway receives CommitPrepareRequestMessage: ${JSON.stringify( - request, - )}`, - ); - - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData == undefined || sessionData.step == undefined) { - await odap.Revert(request.sessionID); - throw new Error( - `${fnTag}, session Id does not correspond to any open session`, - ); - } - - await odap.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "exec", - operation: "commit-prepare", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - // Calculate the hash here to avoid changing the object and the hash - const commitPrepareRequestMessageHash = SHA256( - JSON.stringify(request), - ).toString(); - - log.info( - `CommitPrepareRequestMessage hash is: ${commitPrepareRequestMessageHash}`, - ); +): Promise { + const fnTag = `${odap.className}#sendCommitPrepareResponse()`; - await checkValidCommitPreparationRequest(request, odap); + const sessionData = odap.sessions.get(sessionID); - await odap.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "done", - operation: "commit-prepare", - nodes: `${odap.pubKey}}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.sourceBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.commitPrepareRequestMessageHash == undefined + ) { + throw new Error(`${fnTag}, session data is undefined`); + } const commitPreparationResponseMessage: CommitPreparationV1Response = { + sessionID: sessionID, messageType: OdapMessageType.CommitPreparationResponse, - clientIdentityPubkey: request.clientIdentityPubkey, - serverIdentityPubkey: request.serverIdentityPubkey, - hashCommitPrep: commitPrepareRequestMessageHash, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + hashCommitPrep: sessionData.commitPrepareRequestMessageHash, serverSignature: "", - sequenceNumber: request.sequenceNumber, + sequenceNumber: ++sessionData.lastSequenceNumber, }; commitPreparationResponseMessage.serverSignature = odap.bufArray2HexStr( await odap.sign(JSON.stringify(commitPreparationResponseMessage)), ); - storeSessionData(request, commitPreparationResponseMessage, odap); + sessionData.commitPrepareResponseMessageHash = SHA256( + JSON.stringify(commitPreparationResponseMessage), + ).toString(); + + sessionData.serverSignatureCommitPreparationResponseMessage = + commitPreparationResponseMessage.serverSignature; await odap.storeOdapLog( { @@ -84,29 +58,87 @@ export async function commitPrepare( step: sessionData.step.toString(), type: "ack", operation: "commit-prepare", - nodes: `${odap.pubKey}->${request.clientIdentityPubkey}`, + nodes: `${odap.pubKey}->${sessionData.sourceGatewayPubkey}`, }, `${sessionData.id}-${sessionData.step.toString()}`, ); - sessionData.step++; + log.info(`${fnTag}, sending CommitPreparationResponse...`); - return commitPreparationResponseMessage; + const response = await odap + .getOdapAPI(sessionData.sourceBasePath) + .phase3CommitPreparationResponseV1(commitPreparationResponseMessage); + + if (response.status != 200) { + throw new Error(`${fnTag}, CommitPreparationResponse message failed`); + } } -async function checkValidCommitPreparationRequest( +export async function checkValidCommitPreparationRequest( request: CommitPreparationV1Request, odap: PluginOdapGateway, ): Promise { - const fnTag = `${odap.className}#checkValidCommitPreparationRequest()`; + const fnTag = `${odap.className}#checkValidCommitPrepareRequest()`; + + const sessionID = request.sessionID; + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.lastSequenceNumber == undefined + ) { + throw new Error( + `${fnTag}, session Id does not correspond to any open session`, + ); + } + + // We need to check somewhere if this phase is completed within the asset-lock duration. if (request.messageType != OdapMessageType.CommitPreparationRequest) { - await odap.Revert(request.sessionID); + await odap.Revert(sessionID); throw new Error( `${fnTag}, wrong message type for CommitPreparationRequest`, ); } + if (request.sequenceNumber != sessionData.lastSequenceNumber + 1) { + throw new Error( + `${fnTag}, CommitPreparationRequest sequence number incorrect`, + ); + } + + if ( + sessionData.lockEvidenceResponseMessageHash != request.hashLockEvidenceAck + ) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, previous message hash does not match`); + } + + if (sessionData.recipientGatewayPubkey != request.serverIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationRequest serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != request.clientIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, CommitPreparationRequest clientIdentity public key does not match the one that was sent`, + ); + } + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "exec", + operation: "commit-prepare", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + const sourceClientSignature = new Uint8Array( Buffer.from(request.clientSignature, "hex"), ); @@ -124,49 +156,46 @@ async function checkValidCommitPreparationRequest( sourceClientPubkey, ) ) { - await odap.Revert(request.sessionID); + await odap.Revert(sessionID); throw new Error( `${fnTag}, CommitPreparationRequest message signature verification failed`, ); } request.clientSignature = signature; - // We need to check somewhere if this phase is completed within the asset-lock duration. + storeSessionData(request, odap); - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData === undefined) { - throw new Error(`${fnTag}, sessionID non exist`); - } + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "done", + operation: "commit-prepare", + nodes: `${odap.pubKey}}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); - if ( - sessionData.lockEvidenceResponseMessageHash != request.hashLockEvidenceAck - ) { - await odap.Revert(request.sessionID); - throw new Error(`${fnTag}, previous message hash does not match`); - } + log.info(`CommitPreparationRequest passed all checks.`); } function storeSessionData( request: CommitPreparationV1Request, - response: CommitPreparationV1Response, odap: PluginOdapGateway, ): void { - const fnTag = `${odap.className}#()storeDataAfterCommitPreparationRequest`; + const fnTag = `${odap.className}#()storeSessionData`; const sessionData = odap.sessions.get(request.sessionID); if (sessionData == undefined) { throw new Error(`${fnTag}, session data is undefined`); } - sessionData.commitPrepareRequestMessageHash = response.hashCommitPrep; - sessionData.commitPrepareResponseMessageHash = SHA256( - JSON.stringify(response), + sessionData.commitPrepareRequestMessageHash = SHA256( + JSON.stringify(request), ).toString(); sessionData.clientSignatureCommitPreparationRequestMessage = request.clientSignature; - sessionData.serverSignatureCommitPreparationResponseMessage = - response.serverSignature; odap.sessions.set(request.sessionID, sessionData); } diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/lock-evidence-helper.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/lock-evidence.ts similarity index 54% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/lock-evidence-helper.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/lock-evidence.ts index b011599a3c..467b4e7140 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/lock-evidence-helper.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/lock-evidence.ts @@ -8,75 +8,50 @@ import { SHA256 } from "crypto-js"; const log = LoggerProvider.getOrCreate({ level: "INFO", - label: "odap-lock-evidence-helper", + label: "server-lock-evidence-helper", }); -export async function lockEvidence( - request: LockEvidenceV1Request, +export async function sendLockEvidenceResponse( + sessionID: string, odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#lockEvidence()`; - log.info( - `server gateway receives LockEvidenceRequestMessage: ${JSON.stringify( - request, - )}`, - ); - - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData == undefined || sessionData.step == undefined) { - throw new Error( - `${fnTag}, session Id does not correspond to any open session`, - ); - } - - await odap.storeOdapLog( - { - phase: "p2", - step: sessionData.step.toString(), - type: "exec", - operation: "lock", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - // Calculate the hash here to avoid changing the object and the hash - const lockEvidenceRequestMessageHash = SHA256( - JSON.stringify(request), - ).toString(); - - log.info( - `LockEvidenceRequestMessage hash is: ${lockEvidenceRequestMessageHash}`, - ); +): Promise { + const fnTag = `${odap.className}#sendLockEvidenceResponse()`; - await checkValidLockEvidenceRequest(request, odap); + const sessionData = odap.sessions.get(sessionID); - await odap.storeOdapLog( - { - phase: "p2", - step: sessionData.step.toString(), - type: "done", - operation: "lock", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.sourceBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.lockEvidenceRequestMessageHash == undefined + ) { + throw new Error(`${fnTag}, session data is undefined`); + } const lockEvidenceResponseMessage: LockEvidenceV1Response = { + sessionID: sessionID, messageType: OdapMessageType.LockEvidenceResponse, - clientIdentityPubkey: request.clientIdentityPubkey, - serverIdentityPubkey: request.serverIdentityPubkey, - hashLockEvidenceRequest: lockEvidenceRequestMessageHash, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + hashLockEvidenceRequest: sessionData.lockEvidenceRequestMessageHash, // server transfer number serverSignature: "", - sequenceNumber: request.sequenceNumber, + sequenceNumber: ++sessionData.lastSequenceNumber, }; lockEvidenceResponseMessage.serverSignature = odap.bufArray2HexStr( await odap.sign(JSON.stringify(lockEvidenceResponseMessage)), ); - storeSessionData(request, lockEvidenceResponseMessage, odap); + sessionData.lockEvidenceResponseMessageHash = SHA256( + JSON.stringify(lockEvidenceResponseMessage), + ).toString(); + + sessionData.serverSignatureLockEvidenceResponseMessage = + lockEvidenceResponseMessage.serverSignature; await odap.storeOdapLog( { @@ -84,26 +59,95 @@ export async function lockEvidence( step: sessionData.step.toString(), type: "ack", operation: "lock", - nodes: `${odap.pubKey}->${request.clientIdentityPubkey}`, + nodes: `${odap.pubKey}->${sessionData.sourceGatewayPubkey}`, }, `${sessionData.id}-${sessionData.step.toString()}`, ); - sessionData.step++; + log.info(`${fnTag}, sending LockEvidenceResponse...`); + + const response = await odap + .getOdapAPI(sessionData.sourceBasePath) + .phase2LockEvidenceResponseV1(lockEvidenceResponseMessage); - return lockEvidenceResponseMessage; + if (response.status != 200) { + throw new Error(`${fnTag}, LockEvidenceResponse message failed`); + } } -async function checkValidLockEvidenceRequest( +export async function checkValidLockEvidenceRequest( request: LockEvidenceV1Request, odap: PluginOdapGateway, ): Promise { const fnTag = `${odap.className}#checkValidLockEvidenceRequest()`; + const sessionID = request.sessionID; + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.lastSequenceNumber == undefined + ) { + throw new Error( + `${fnTag}, session Id does not correspond to any open session`, + ); + } + + await odap.storeOdapLog( + { + phase: "p2", + step: sessionData.step.toString(), + type: "exec", + operation: "lock", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + if (request.messageType != OdapMessageType.LockEvidenceRequest) { + await odap.Revert(sessionID); throw new Error(`${fnTag}, wrong message type for LockEvidenceRequest`); } + if (request.sequenceNumber != sessionData.lastSequenceNumber + 1) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceRequestMessage sequence number incorrect`, + ); + } + + if ( + sessionData.transferCommenceMessageResponseHash != + request.hashCommenceAckRequest + ) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, previous message hash does not match the one that was sent`, + ); + } + + if (sessionData.recipientGatewayPubkey != request.serverIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceRequest serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != request.clientIdentityPubkey) { + await odap.Revert(sessionID); + throw new Error( + `${fnTag}, LockEvidenceRequest clientIdentity public key does not match the one that was sent`, + ); + } + + if ( + request.lockEvidenceClaim == undefined || + new Date() > new Date(request.lockEvidenceExpiration) + ) { + await odap.Revert(sessionID); + throw new Error(`${fnTag}, invalid or expired lock evidence claim`); + } + const sourceClientSignature = new Uint8Array( Buffer.from(request.clientSignature, "hex"), ); @@ -121,38 +165,31 @@ async function checkValidLockEvidenceRequest( sourceClientPubkey, ) ) { - await odap.Revert(request.sessionID); + await odap.Revert(sessionID); throw new Error( `${fnTag}, LockEvidenceRequest message signature verification failed`, ); } request.clientSignature = signature; - if ( - request.lockEvidenceClaim == undefined || - new Date() > new Date(request.lockEvidenceExpiration) - ) { - await odap.Revert(request.sessionID); - throw new Error(`${fnTag}, invalid or expired lock evidence claim`); - } + storeSessionData(request, odap); - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData === undefined) { - throw new Error(`${fnTag}, sessionID non exist`); - } + await odap.storeOdapLog( + { + phase: "p2", + step: sessionData.step.toString(), + type: "done", + operation: "lock", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); - if ( - sessionData.transferCommenceMessageResponseHash != - request.hashCommenceAckRequest - ) { - await odap.Revert(request.sessionID); - throw new Error(`${fnTag}, previous message hash does not match`); - } + log.info(`LockEvidenceRequest passed all checks.`); } function storeSessionData( request: LockEvidenceV1Request, - response: LockEvidenceV1Response, odap: PluginOdapGateway, ): void { const fnTag = `${odap.className}#()storeSessionData`; @@ -162,17 +199,14 @@ function storeSessionData( throw new Error(`${fnTag}, session data is undefined`); } - sessionData.lockEvidenceResponseMessageHash = SHA256( - JSON.stringify(response), - ).toString(); sessionData.lockEvidenceRequestMessageHash = SHA256( JSON.stringify(request), ).toString(); sessionData.clientSignatureLockEvidenceRequestMessage = request.clientSignature; - sessionData.serverSignatureLockEvidenceResponseMessage = - response.serverSignature; + + sessionData.lockEvidenceClaim = request.lockEvidenceClaim; odap.sessions.set(request.sessionID, sessionData); } diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/transfer-commence-helper.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-commence.ts similarity index 53% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/transfer-commence-helper.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-commence.ts index faab4a4f41..856ba326e5 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/transfer-commence-helper.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-commence.ts @@ -1,5 +1,7 @@ import { LoggerProvider } from "@hyperledger/cactus-common"; import { + // Configuration, + // DefaultApi as OdapApi, TransferCommenceV1Request, TransferCommenceV1Response, } from "../../generated/openapi/typescript-axios"; @@ -8,79 +10,50 @@ import { SHA256 } from "crypto-js"; const log = LoggerProvider.getOrCreate({ level: "INFO", - label: "odap-lock-evidence-helper", + label: "server-transfer-commence-helper", }); -export async function transferCommence( - request: TransferCommenceV1Request, +export async function sendTransferCommenceResponse( + sessionID: string, odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#transferCommence()`; - log.info( - `server gateway receives TransferCommenceMessage: ${JSON.stringify( - request, - )}`, - ); - - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData == undefined || sessionData.step == undefined) { - throw new Error( - `${fnTag}, session Id does not correspond to any open session`, - ); - } - - await odap.storeOdapLog( - { - phase: "p2", - step: sessionData.step.toString(), - type: "exec", - operation: "commence", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - // Calculate the hash here to avoid changing the object and the hash - const transferCommenceRequestMessageHash = SHA256( - JSON.stringify(request), - ).toString(); - - log.info( - `TransferCommenceRequest hash is: ${transferCommenceRequestMessageHash}`, - ); +): Promise { + const fnTag = `${odap.className}#sendTransferCommenceResponse()`; - await checkValidtransferCommenceRequest(request, odap); + const sessionData = odap.sessions.get(sessionID); - await odap.storeOdapLog( - { - phase: "p2", - step: sessionData.step.toString(), - type: "done", - operation: "commence", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.sourceBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.sourceGatewayPubkey == undefined || + sessionData.recipientGatewayPubkey == undefined || + sessionData.transferCommenceMessageRequestHash == undefined + ) { + throw new Error(`${fnTag}, session data is undefined`); + } const transferCommenceResponse: TransferCommenceV1Response = { + sessionID: sessionID, messageType: OdapMessageType.TransferCommenceResponse, - clientIdentityPubkey: request.clientIdentityPubkey, - serverIdentityPubkey: request.serverIdentityPubkey, - hashCommenceRequest: transferCommenceRequestMessageHash, + clientIdentityPubkey: sessionData.sourceGatewayPubkey, + serverIdentityPubkey: sessionData.recipientGatewayPubkey, + hashCommenceRequest: sessionData.transferCommenceMessageRequestHash, // serverTransferNumber?? serverSignature: "", - sequenceNumber: request.sequenceNumber, + sequenceNumber: ++sessionData.lastSequenceNumber, }; - const serverSignature = await odap.sign( - JSON.stringify(transferCommenceResponse), - ); - transferCommenceResponse.serverSignature = odap.bufArray2HexStr( - serverSignature, + odap.sign(JSON.stringify(transferCommenceResponse)), ); - await storeSessionData(request, transferCommenceResponse, odap); + sessionData.transferCommenceMessageResponseHash = SHA256( + JSON.stringify(transferCommenceResponse), + ).toString(); + + sessionData.serverSignatureTransferCommenceResponseMessage = + transferCommenceResponse.serverSignature; await odap.storeOdapLog( { @@ -88,26 +61,88 @@ export async function transferCommence( step: sessionData.step.toString(), type: "ack", operation: "commence", - nodes: `${odap.pubKey}->${request.clientIdentityPubkey}`, + nodes: `${odap.pubKey}->${sessionData.sourceGatewayPubkey}`, }, - `${request.sessionID}-${sessionData.step.toString()}`, + `${sessionID}-${sessionData.step.toString()}`, ); - sessionData.step++; + log.info(`${fnTag}, sending TransferCommenceResponse...`); - return transferCommenceResponse; + const response = await odap + .getOdapAPI(sessionData.sourceBasePath) + .phase2TransferCommenceResponseV1(transferCommenceResponse); + + if (response.status != 200) { + throw new Error(`${fnTag}, TransferCommenceResponse message failed`); + } } -async function checkValidtransferCommenceRequest( +export async function checkValidtransferCommenceRequest( request: TransferCommenceV1Request, odap: PluginOdapGateway, ): Promise { const fnTag = `${odap.className}#checkValidtransferCommenceRequest()`; + const sessionID = request.sessionID; + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.lastSequenceNumber == undefined + ) { + throw new Error( + `${fnTag}, session Id does not correspond to any open session`, + ); + } + + await odap.storeOdapLog( + { + phase: "p2", + step: sessionData.step.toString(), + type: "exec", + operation: "commence", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + if (request.messageType != OdapMessageType.TransferCommenceRequest) { throw new Error(`${fnTag}, wrong message type for TransferCommenceRequest`); } + if (request.sequenceNumber != sessionData.lastSequenceNumber + 1) { + throw new Error( + `${fnTag}, TransferCommenceRequest sequence number incorrect`, + ); + } + + if ( + sessionData.initializationResponseMessageHash != request.hashPrevMessage + ) { + throw new Error( + `${fnTag}, TransferCommenceRequest previous message hash does not match the one that was sent`, + ); + } + + if (sessionData.recipientGatewayPubkey != request.serverIdentityPubkey) { + throw new Error( + `${fnTag}, TransferCommenceRequest serverIdentity public key does not match the one that was sent`, + ); + } + + if (sessionData.sourceGatewayPubkey != request.clientIdentityPubkey) { + throw new Error( + `${fnTag}, TransferCommenceRequest clientIdentity public key does not match the one that was sent`, + ); + } + + const assetProfileHash = SHA256( + JSON.stringify(sessionData.assetProfile), + ).toString(); + if (assetProfileHash !== request.hashAssetProfile) { + throw new Error(`${fnTag}, assetProfile hash not match`); + } + const sourceClientSignature = new Uint8Array( Buffer.from(request.clientSignature, "hex"), ); @@ -131,27 +166,24 @@ async function checkValidtransferCommenceRequest( } request.clientSignature = signature; - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData === undefined) { - throw new Error(`${fnTag}, sessionID non exist`); - } + storeSessionData(request, odap); - if (sessionData.initializationRequestMessageHash != request.hashPrevMessage) { - throw new Error(`${fnTag}, previous message hash not match`); - } + await odap.storeOdapLog( + { + phase: "p2", + step: sessionData.step.toString(), + type: "done", + operation: "commence", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); - const assetProfileHash = SHA256( - JSON.stringify(sessionData.assetProfile), - ).toString(); - const isAssetProfileHashMatch = assetProfileHash === request.hashAssetProfile; - if (!isAssetProfileHashMatch) { - throw new Error(`${fnTag}, assetProfile hash not match`); - } + log.info(`TransferCommenceRequest passed all checks.`); } async function storeSessionData( request: TransferCommenceV1Request, - response: TransferCommenceV1Response, odap: PluginOdapGateway, ): Promise { const fnTag = `${odap.className}#()storeSessionData`; @@ -161,17 +193,13 @@ async function storeSessionData( throw new Error(`${fnTag}, session data is undefined`); } - sessionData.transferCommenceMessageRequestHash = response.hashCommenceRequest; - sessionData.transferCommenceMessageResponseHash = SHA256( - JSON.stringify(response), + sessionData.transferCommenceMessageRequestHash = SHA256( + JSON.stringify(request), ).toString(); sessionData.clientSignatureTransferCommenceRequestMessage = request.clientSignature; - sessionData.serverSignatureTransferCommenceResponseMessage = - response.serverSignature; - sessionData.originatorPubkey = request.originatorPubkey; sessionData.beneficiaryPubkey = request.beneficiaryPubkey; diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/transfer-complete-helper.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-complete.ts similarity index 56% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/transfer-complete-helper.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-complete.ts index 3a90ddfd97..ba4b403c4d 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/transfer-complete-helper.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-complete.ts @@ -1,29 +1,26 @@ import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; import { SHA256 } from "crypto-js"; import { LoggerProvider } from "@hyperledger/cactus-common"; -import { - TransferCompleteV1Request, - TransferCompleteV1Response, -} from "../../generated/openapi/typescript-axios"; +import { TransferCompleteV1Request } from "../../generated/openapi/typescript-axios"; const log = LoggerProvider.getOrCreate({ level: "INFO", - label: "odap-transfer-complete-helper", + label: "server-transfer-complete-helper", }); -export async function transferComplete( +export async function checkValidTransferCompleteRequest( request: TransferCompleteV1Request, odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#transferComplete()`; - log.info( - `server gateway receives TransferCommenceMessage: ${JSON.stringify( - request, - )}`, - ); +): Promise { + const fnTag = `${odap.className}#checkValidTransferCompleteRequest()`; - const sessionData = odap.sessions.get(request.sessionID); - if (sessionData === undefined || sessionData.step == undefined) { + const sessionID = request.sessionID; + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.lastSequenceNumber == undefined + ) { throw new Error( `${fnTag}, session Id does not correspond to any open session`, ); @@ -34,47 +31,28 @@ export async function transferComplete( phase: "p3", step: sessionData.step.toString(), type: "exec", - operation: "transfer-complete", + operation: "complete", nodes: `${odap.pubKey}`, }, `${sessionData.id}-${sessionData.step.toString()}`, ); - // Calculate the hash here to avoid changing the object and the hash - const transferCompleteMessageHash = SHA256( - JSON.stringify(request), - ).toString(); - - log.info(`TransferCommenceRequest hash is: ${transferCompleteMessageHash}`); - - await checkValidTransferCompleteRequest(request, odap); - - log.info("Transfer complete."); - - await odap.storeOdapLog( - { - phase: "p3", - step: sessionData.step.toString(), - type: "ack", - operation: "transfer-complete", - nodes: `${odap.pubKey}->${request.clientIdentityPubkey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); - - return { ok: "true" }; -} - -async function checkValidTransferCompleteRequest( - request: TransferCompleteV1Request, - odap: PluginOdapGateway, -): Promise { - const fnTag = `${odap.className}#checkValidTransferCompleteRequest()`; - if (request.messageType != OdapMessageType.TransferCompleteRequest) { throw new Error(`${fnTag}, wrong message type for TransferCompleteRequest`); } + if (request.sequenceNumber != sessionData.lastSequenceNumber + 1) { + throw new Error( + `${fnTag}, TransferCompleteRequest sequence number incorrect`, + ); + } + + if ( + request.hashCommitFinalAck != sessionData.commitFinalResponseMessageHash + ) { + throw new Error(`${fnTag}, previous message hash not match`); + } + const sourceClientSignature = new Uint8Array( Buffer.from(request.clientSignature, "hex"), ); @@ -93,29 +71,43 @@ async function checkValidTransferCompleteRequest( ) ) { throw new Error( - `${fnTag}, TransferCommenceRequest message signature verification failed`, + `${fnTag}, TransferCompleteRequest message signature verification failed`, ); } request.clientSignature = signature; + storeSessionData(request, odap); + + await odap.storeOdapLog( + { + phase: "p3", + step: sessionData.step.toString(), + type: "done", + operation: "complete", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + log.info(`TransferCompleteRequest passed all checks.`); +} + +async function storeSessionData( + request: TransferCompleteV1Request, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#()storeSessionData`; const sessionData = odap.sessions.get(request.sessionID); - if (sessionData === undefined) { - throw new Error(`${fnTag}, sessionID non exist`); + if (sessionData == undefined) { + throw new Error(`${fnTag}, session data is undefined`); } - if ( - sessionData.commitFinalResponseMessageHash != request.hashCommitFinalAck - ) { - throw new Error(`${fnTag}, previous message hash not match`); - } + sessionData.transferCompleteMessageHash = SHA256( + JSON.stringify(request), + ).toString(); - if ( - sessionData.transferCommenceMessageRequestHash != - request.hashTransferCommence - ) { - throw new Error( - `${fnTag}, previous TransferCommenceRequest hash not match`, - ); - } + sessionData.clientSignatureTransferCompleteMessage = request.clientSignature; + + odap.sessions.set(request.sessionID, sessionData); } diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/initiate-transfer-helper.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-initialization.ts similarity index 67% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/initiate-transfer-helper.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-initialization.ts index ae7e8e9701..9806f38fdd 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/common/initiate-transfer-helper.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/gateway/server/transfer-initialization.ts @@ -1,7 +1,7 @@ import { + SessionData, TransferInitializationV1Request, TransferInitializationV1Response, - SessionData, } from "../../generated/openapi/typescript-axios"; import { LoggerProvider } from "@hyperledger/cactus-common"; import { OdapMessageType, PluginOdapGateway } from "../plugin-odap-gateway"; @@ -9,116 +9,106 @@ import { SHA256 } from "crypto-js"; const log = LoggerProvider.getOrCreate({ level: "INFO", - label: "odap-initiate-transfer-helper", + label: "server-transfer-initialization-helper", }); -export async function initiateTransfer( - request: TransferInitializationV1Request, +export async function sendTransferInitializationResponse( + sessionID: string, odap: PluginOdapGateway, -): Promise { - log.info( - `server gateway receives TransferInitializationRequest: ${JSON.stringify( - request, - )}`, - ); +): Promise { + const fnTag = `${odap.className}#sendTransferInitiationResponse()`; - const recvTimestamp: string = Date.now().toString(); + const sessionData = odap.sessions.get(sessionID); + if ( + sessionData == undefined || + sessionData.step == undefined || + sessionData.sourceBasePath == undefined || + sessionData.lastSequenceNumber == undefined || + sessionData.initializationRequestMessageHash == undefined || + sessionData.initializationRequestMessageRcvTimeStamp == undefined || + sessionData.initializationRequestMessageProcessedTimeStamp == undefined + ) { + throw new Error(`${fnTag}, session data is undefined`); + } - log.info( - `TransferInitializationRequest message received at: ${recvTimestamp}`, - ); + const transferInitializationResponse: TransferInitializationV1Response = { + messageType: OdapMessageType.InitializationResponse, + sessionID: sessionID, + initialRequestMessageHash: sessionData.initializationRequestMessageHash, + timeStamp: sessionData.initializationRequestMessageRcvTimeStamp, + processedTimeStamp: + sessionData.initializationRequestMessageProcessedTimeStamp, + serverIdentityPubkey: odap.pubKey, + sequenceNumber: sessionData.lastSequenceNumber, + serverSignature: "", + }; - const sessionID = request.sessionID; - const sessionData: SessionData = {}; + transferInitializationResponse.serverSignature = odap.bufArray2HexStr( + odap.sign(JSON.stringify(transferInitializationResponse)), + ); - sessionData.id = sessionID; - sessionData.step = 0; + sessionData.initializationResponseMessageHash = SHA256( + JSON.stringify(transferInitializationResponse), + ).toString(); - odap.sessions.set(sessionID, sessionData); + sessionData.serverSignatureInitializationResponseMessage = + transferInitializationResponse.serverSignature; await odap.storeOdapLog( { phase: "p1", step: sessionData.step.toString(), - type: "exec", + type: "ack", operation: "validate", - nodes: `${odap.pubKey}`, + nodes: `${odap.pubKey}->${sessionData.sourceGatewayPubkey}`, }, `${sessionData.id}-${sessionData.step.toString()}`, ); - // Calculate the hash here to avoid changing the object and the hash - const initializationRequestMessageHash = SHA256( - JSON.stringify(request), - ).toString(); + sessionData.step++; - log.info( - `TransferInitializationRequest hash is: ${initializationRequestMessageHash}`, - ); + odap.sessions.set(sessionID, sessionData); - await checkValidInitializationRequest(request, odap); + // Log init??? - await odap.storeOdapLog( - { - phase: "p1", - step: sessionData.step.toString(), - type: "done", - operation: "validate", - nodes: `${odap.pubKey}`, - }, - `${sessionData.id}-${sessionData.step.toString()}`, - ); + log.info(`${fnTag}, sending TransferInitializationResponse...`); - const processedTimestamp: string = Date.now().toString(); + const response = await odap + .getOdapAPI(sessionData.sourceBasePath) + .phase1TransferInitiationResponseV1(transferInitializationResponse); - log.info( - `TransferInitializationResponse being built at: ${processedTimestamp}`, - ); + if (response.status != 200) { + throw new Error(`${fnTag}, TransferInitializationResponse message failed`); + } +} - const transferInitializationResponse: TransferInitializationV1Response = { - messageType: OdapMessageType.InitializationResponse, - sessionID: sessionID, - initialRequestMessageHash: initializationRequestMessageHash, - timeStamp: recvTimestamp, - processedTimeStamp: processedTimestamp, - serverIdentityPubkey: odap.pubKey, - sequenceNumber: request.sequenceNumber, - serverSignature: "", - }; +export async function checkValidInitializationRequest( + request: TransferInitializationV1Request, + odap: PluginOdapGateway, +): Promise { + const fnTag = `${odap.className}#checkValidInitializationRequest()`; - transferInitializationResponse.serverSignature = odap.bufArray2HexStr( - await odap.sign(JSON.stringify(transferInitializationResponse)), - ); + const sessionData: SessionData = {}; + const recvTimestamp: string = Date.now().toString(); + const sessionID = request.sessionID; - await storeSessionData( - request, - transferInitializationResponse, - sessionID, - odap, - ); + sessionData.id = sessionID; + sessionData.step = 0; + sessionData.initializationRequestMessageRcvTimeStamp = recvTimestamp; + + odap.sessions.set(sessionID, sessionData); await odap.storeOdapLog( { phase: "p1", step: sessionData.step.toString(), - type: "ack", + type: "exec", operation: "validate", - nodes: `${odap.pubKey}->${request.sourceGatewayPubkey}`, + nodes: `${odap.pubKey}`, }, `${sessionData.id}-${sessionData.step.toString()}`, ); - sessionData.step++; - - return transferInitializationResponse; -} - -function checkValidInitializationRequest( - request: TransferInitializationV1Request, - odap: PluginOdapGateway, -): void { - const fnTag = `${odap.className}#checkValidInitializationRequest()`; - if (request.messageType != OdapMessageType.InitializationRequest) { throw new Error( `${fnTag}, wrong message type for TransferInitializationRequest`, @@ -158,25 +148,39 @@ function checkValidInitializationRequest( if (isDataExpired) { throw new Error(`${fnTag}, asset has expired`); } + + storeSessionData(request, odap); + + await odap.storeOdapLog( + { + phase: "p1", + step: sessionData.step.toString(), + type: "done", + operation: "validate", + nodes: `${odap.pubKey}`, + }, + `${sessionData.id}-${sessionData.step.toString()}`, + ); + + log.info(`TransferInitializationRequest passed all checks.`); } async function storeSessionData( request: TransferInitializationV1Request, - response: TransferInitializationV1Response, - sessionID: string, odap: PluginOdapGateway, ): Promise { const fnTag = `${odap.className}#storeDataAfterInitializationRequest`; - const sessionData = odap.sessions.get(sessionID); + const sessionData = odap.sessions.get(request.sessionID); if (sessionData == undefined) { - await odap.Revert(sessionID); throw new Error( `${fnTag}, reverting transfer because session data is undefined`, ); } sessionData.step = 1; + sessionData.sourceBasePath = request.sourceGatewayPath; + sessionData.lastSequenceNumber = request.sequenceNumber; sessionData.loggingProfile = request.loggingProfile; sessionData.accessControlProfile = request.accessControlProfile; sessionData.applicationProfile = request.applicationProfile; @@ -190,20 +194,10 @@ async function storeSessionData( JSON.stringify(request), ).toString(); - sessionData.initializationResponseMessageHash = SHA256( - JSON.stringify(response), - ).toString(); - - sessionData.initializationRequestMessageRcvTimeStamp = response.timeStamp; - - sessionData.initializationRequestMessageProcessedTimeStamp = - response.processedTimeStamp; - sessionData.clientSignatureInitializationRequestMessage = request.clientSignature; - sessionData.serverSignatureInitializationResponseMessage = - response.serverSignature; + sessionData.initializationRequestMessageProcessedTimeStamp = Date.now().toString(); - odap.sessions.set(sessionID, sessionData); + odap.sessions.set(request.sessionID, sessionData); } diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/generated/openapi/typescript-axios/api.ts index 360cec45b5..cc8d64dcb6 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/generated/openapi/typescript-axios/api.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -100,6 +100,134 @@ export interface AssetProfile { */ ledgerRequirements?: Array; } +/** + * + * @export + * @interface ClientV1Request + */ +export interface ClientV1Request { + /** + * + * @type {string} + * @memberof ClientV1Request + */ + version: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + loggingProfile: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + accessControlProfile: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + assetControlProfile: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + applicationProfile: string; + /** + * + * @type {AssetProfile} + * @memberof ClientV1Request + */ + assetProfile: AssetProfile; + /** + * + * @type {PayloadProfile} + * @memberof ClientV1Request + */ + payloadProfile: PayloadProfile; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + sourceGatewayDltSystem: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + recipientGatewayDltSystem: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + recipientGatewayPubkey: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + originatorPubkey: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + beneficiaryPubkey: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + clientIdentityPubkey: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + serverIdentityPubkey: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + clientDltSystem: string; + /** + * + * @type {string} + * @memberof ClientV1Request + */ + serverDltSystem: string; + /** + * + * @type {ClientV1RequestClientGatewayConfiguration} + * @memberof ClientV1Request + */ + clientGatewayConfiguration: ClientV1RequestClientGatewayConfiguration; + /** + * + * @type {ClientV1RequestClientGatewayConfiguration} + * @memberof ClientV1Request + */ + serverGatewayConfiguration: ClientV1RequestClientGatewayConfiguration; +} +/** + * + * @export + * @interface ClientV1RequestClientGatewayConfiguration + */ +export interface ClientV1RequestClientGatewayConfiguration { + /** + * + * @type {string} + * @memberof ClientV1RequestClientGatewayConfiguration + */ + apiHost: string; +} /** * * @export @@ -173,6 +301,12 @@ export interface CommitFinalV1Request { * @interface CommitFinalV1Response */ export interface CommitFinalV1Response { + /** + * + * @type {string} + * @memberof CommitFinalV1Response + */ + sessionID: string; /** * * @type {string} @@ -289,6 +423,12 @@ export interface CommitPreparationV1Request { * @interface CommitPreparationV1Response */ export interface CommitPreparationV1Response { + /** + * + * @type {string} + * @memberof CommitPreparationV1Response + */ + sessionID: string; /** * * @type {string} @@ -478,6 +618,12 @@ export interface LockEvidenceV1Request { * @interface LockEvidenceV1Response */ export interface LockEvidenceV1Response { + /** + * + * @type {string} + * @memberof LockEvidenceV1Response + */ + sessionID: string; /** * * @type {string} @@ -668,128 +814,6 @@ export interface PayloadProfile { */ capabilities?: string; } -/** - * - * @export - * @interface SendClientV1Request - */ -export interface SendClientV1Request { - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - version: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - loggingProfile: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - accessControlProfile: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - assetControlProfile: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - applicationProfile: string; - /** - * - * @type {AssetProfile} - * @memberof SendClientV1Request - */ - assetProfile: AssetProfile; - /** - * - * @type {PayloadProfile} - * @memberof SendClientV1Request - */ - payloadProfile: PayloadProfile; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - sourceGatewayDltSystem: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - recipientGatewayDltSystem: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - recipientGatewayPubkey: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - originatorPubkey: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - beneficiaryPubkey: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - clientIdentityPubkey: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - serverIdentityPubkey: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - clientDltSystem: string; - /** - * - * @type {string} - * @memberof SendClientV1Request - */ - serverDltSystem: string; - /** - * - * @type {SendClientV1RequestServerGatewayConfiguration} - * @memberof SendClientV1Request - */ - serverGatewayConfiguration: SendClientV1RequestServerGatewayConfiguration; -} -/** - * - * @export - * @interface SendClientV1RequestServerGatewayConfiguration - */ -export interface SendClientV1RequestServerGatewayConfiguration { - /** - * - * @type {string} - * @memberof SendClientV1RequestServerGatewayConfiguration - */ - apiHost: string; -} /** * * @export @@ -850,6 +874,18 @@ export interface SessionData { * @memberof SessionData */ assetProfile?: AssetProfile; + /** + * + * @type {string} + * @memberof SessionData + */ + sourceBasePath?: string; + /** + * + * @type {string} + * @memberof SessionData + */ + recipientBasePath?: string; /** * * @type {string} @@ -1212,6 +1248,12 @@ export interface TransferCommenceV1Request { * @interface TransferCommenceV1Response */ export interface TransferCommenceV1Response { + /** + * + * @type {string} + * @memberof TransferCommenceV1Response + */ + sessionID: string; /** * * @type {string} @@ -1322,19 +1364,6 @@ export interface TransferCompleteV1Request { */ sequenceNumber: number; } -/** - * - * @export - * @interface TransferCompleteV1Response - */ -export interface TransferCompleteV1Response { - /** - * - * @type {string} - * @memberof TransferCompleteV1Response - */ - ok: string; -} /** * * @export @@ -1485,6 +1514,12 @@ export interface TransferInitializationV1Request { * @memberof TransferInitializationV1Request */ sequenceNumber: number; + /** + * + * @type {string} + * @memberof TransferInitializationV1Request + */ + sourceGatewayPath?: string; } /** @@ -1586,14 +1621,47 @@ export enum TransferInitializationV1ResponseOdapPhaseEnum { */ export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { return { + /** + * + * @param {ClientV1Request} [clientV1Request] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + clientRequestV1: async (clientV1Request?: ClientV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/clientrequest`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(clientV1Request, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @param {TransferInitializationV1Request} [transferInitializationV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase1TransferInitiationV1: async (transferInitializationV1Request?: TransferInitializationV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiation`; + phase1TransferInitiationRequestV1: async (transferInitializationV1Request?: TransferInitializationV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationrequest`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1619,14 +1687,47 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, }; }, + /** + * + * @param {TransferInitializationV1Response} [transferInitializationV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase1TransferInitiationResponseV1: async (transferInitializationV1Response?: TransferInitializationV1Response, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationresponse`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(transferInitializationV1Response, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @param {LockEvidenceV1Request} [lockEvidenceV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase2LockEvidenceV1: async (lockEvidenceV1Request?: LockEvidenceV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidence`; + phase2LockEvidenceRequestV1: async (lockEvidenceV1Request?: LockEvidenceV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidencerequest`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1652,14 +1753,47 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, }; }, + /** + * + * @param {LockEvidenceV1Response} [lockEvidenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase2LockEvidenceResponseV1: async (lockEvidenceV1Response?: LockEvidenceV1Response, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidenceresponse`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(lockEvidenceV1Response, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @param {TransferCommenceV1Request} [transferCommenceV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase2TransferCommenceV1: async (transferCommenceV1Request?: TransferCommenceV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommence`; + phase2TransferCommenceRequestV1: async (transferCommenceV1Request?: TransferCommenceV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommencerequest`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1685,14 +1819,47 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, }; }, + /** + * + * @param {TransferCommenceV1Response} [transferCommenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase2TransferCommenceResponseV1: async (transferCommenceV1Response?: TransferCommenceV1Response, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommenceresponse`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(transferCommenceV1Response, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @param {CommitFinalV1Request} [commitFinalV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase3CommitFinalV1: async (commitFinalV1Request?: CommitFinalV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinal`; + phase3CommitFinalRequestV1: async (commitFinalV1Request?: CommitFinalV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalrequest`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1718,14 +1885,47 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, }; }, + /** + * + * @param {CommitFinalV1Response} [commitFinalV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase3CommitFinalResponseV1: async (commitFinalV1Response?: CommitFinalV1Response, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalresponse`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(commitFinalV1Response, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @param {CommitPreparationV1Request} [commitPreparationV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase3CommitPreparationV1: async (commitPreparationV1Request?: CommitPreparationV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparation`; + phase3CommitPreparationRequestV1: async (commitPreparationV1Request?: CommitPreparationV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationrequest`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1753,12 +1953,12 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati }, /** * - * @param {TransferCompleteV1Request} [transferCompleteV1Request] + * @param {CommitPreparationV1Response} [commitPreparationV1Response] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase3TransferCompleteV1: async (transferCompleteV1Request?: TransferCompleteV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercomplete`; + phase3CommitPreparationResponseV1: async (commitPreparationV1Response?: CommitPreparationV1Response, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationresponse`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1766,7 +1966,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; @@ -1777,7 +1977,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(transferCompleteV1Request, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(commitPreparationV1Response, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -1786,12 +1986,12 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati }, /** * - * @param {SendClientV1Request} [sendClientV1Request] + * @param {TransferCompleteV1Request} [transferCompleteV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - sendClientRequestV1: async (sendClientV1Request?: SendClientV1Request, options: any = {}): Promise => { - const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/sendclientrequest`; + phase3TransferCompleteRequestV1: async (transferCompleteV1Request?: TransferCompleteV1Request, options: any = {}): Promise => { + const localVarPath = `/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercompleterequest`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1799,7 +1999,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; @@ -1810,7 +2010,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(sendClientV1Request, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(transferCompleteV1Request, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -1827,14 +2027,34 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati export const DefaultApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration) return { + /** + * + * @param {ClientV1Request} [clientV1Request] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async clientRequestV1(clientV1Request?: ClientV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.clientRequestV1(clientV1Request, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * * @param {TransferInitializationV1Request} [transferInitializationV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async phase1TransferInitiationV1(transferInitializationV1Request?: TransferInitializationV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.phase1TransferInitiationV1(transferInitializationV1Request, options); + async phase1TransferInitiationRequestV1(transferInitializationV1Request?: TransferInitializationV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase1TransferInitiationRequestV1(transferInitializationV1Request, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @param {TransferInitializationV1Response} [transferInitializationV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async phase1TransferInitiationResponseV1(transferInitializationV1Response?: TransferInitializationV1Response, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase1TransferInitiationResponseV1(transferInitializationV1Response, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -1843,8 +2063,18 @@ export const DefaultApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async phase2LockEvidenceV1(lockEvidenceV1Request?: LockEvidenceV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.phase2LockEvidenceV1(lockEvidenceV1Request, options); + async phase2LockEvidenceRequestV1(lockEvidenceV1Request?: LockEvidenceV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase2LockEvidenceRequestV1(lockEvidenceV1Request, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @param {LockEvidenceV1Response} [lockEvidenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async phase2LockEvidenceResponseV1(lockEvidenceV1Response?: LockEvidenceV1Response, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase2LockEvidenceResponseV1(lockEvidenceV1Response, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -1853,8 +2083,18 @@ export const DefaultApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async phase2TransferCommenceV1(transferCommenceV1Request?: TransferCommenceV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.phase2TransferCommenceV1(transferCommenceV1Request, options); + async phase2TransferCommenceRequestV1(transferCommenceV1Request?: TransferCommenceV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase2TransferCommenceRequestV1(transferCommenceV1Request, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @param {TransferCommenceV1Response} [transferCommenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async phase2TransferCommenceResponseV1(transferCommenceV1Response?: TransferCommenceV1Response, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase2TransferCommenceResponseV1(transferCommenceV1Response, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -1863,8 +2103,18 @@ export const DefaultApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async phase3CommitFinalV1(commitFinalV1Request?: CommitFinalV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.phase3CommitFinalV1(commitFinalV1Request, options); + async phase3CommitFinalRequestV1(commitFinalV1Request?: CommitFinalV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase3CommitFinalRequestV1(commitFinalV1Request, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @param {CommitFinalV1Response} [commitFinalV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async phase3CommitFinalResponseV1(commitFinalV1Response?: CommitFinalV1Response, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase3CommitFinalResponseV1(commitFinalV1Response, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -1873,28 +2123,28 @@ export const DefaultApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async phase3CommitPreparationV1(commitPreparationV1Request?: CommitPreparationV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.phase3CommitPreparationV1(commitPreparationV1Request, options); + async phase3CommitPreparationRequestV1(commitPreparationV1Request?: CommitPreparationV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase3CommitPreparationRequestV1(commitPreparationV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** * - * @param {TransferCompleteV1Request} [transferCompleteV1Request] + * @param {CommitPreparationV1Response} [commitPreparationV1Response] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async phase3TransferCompleteV1(transferCompleteV1Request?: TransferCompleteV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.phase3TransferCompleteV1(transferCompleteV1Request, options); + async phase3CommitPreparationResponseV1(commitPreparationV1Response?: CommitPreparationV1Response, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase3CommitPreparationResponseV1(commitPreparationV1Response, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** * - * @param {SendClientV1Request} [sendClientV1Request] + * @param {TransferCompleteV1Request} [transferCompleteV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async sendClientRequestV1(sendClientV1Request?: SendClientV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.sendClientRequestV1(sendClientV1Request, options); + async phase3TransferCompleteRequestV1(transferCompleteV1Request?: TransferCompleteV1Request, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.phase3TransferCompleteRequestV1(transferCompleteV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, } @@ -1907,14 +2157,32 @@ export const DefaultApiFp = function(configuration?: Configuration) { export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = DefaultApiFp(configuration) return { + /** + * + * @param {ClientV1Request} [clientV1Request] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + clientRequestV1(clientV1Request?: ClientV1Request, options?: any): AxiosPromise { + return localVarFp.clientRequestV1(clientV1Request, options).then((request) => request(axios, basePath)); + }, /** * * @param {TransferInitializationV1Request} [transferInitializationV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase1TransferInitiationV1(transferInitializationV1Request?: TransferInitializationV1Request, options?: any): AxiosPromise { - return localVarFp.phase1TransferInitiationV1(transferInitializationV1Request, options).then((request) => request(axios, basePath)); + phase1TransferInitiationRequestV1(transferInitializationV1Request?: TransferInitializationV1Request, options?: any): AxiosPromise { + return localVarFp.phase1TransferInitiationRequestV1(transferInitializationV1Request, options).then((request) => request(axios, basePath)); + }, + /** + * + * @param {TransferInitializationV1Response} [transferInitializationV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase1TransferInitiationResponseV1(transferInitializationV1Response?: TransferInitializationV1Response, options?: any): AxiosPromise { + return localVarFp.phase1TransferInitiationResponseV1(transferInitializationV1Response, options).then((request) => request(axios, basePath)); }, /** * @@ -1922,8 +2190,17 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase2LockEvidenceV1(lockEvidenceV1Request?: LockEvidenceV1Request, options?: any): AxiosPromise { - return localVarFp.phase2LockEvidenceV1(lockEvidenceV1Request, options).then((request) => request(axios, basePath)); + phase2LockEvidenceRequestV1(lockEvidenceV1Request?: LockEvidenceV1Request, options?: any): AxiosPromise { + return localVarFp.phase2LockEvidenceRequestV1(lockEvidenceV1Request, options).then((request) => request(axios, basePath)); + }, + /** + * + * @param {LockEvidenceV1Response} [lockEvidenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase2LockEvidenceResponseV1(lockEvidenceV1Response?: LockEvidenceV1Response, options?: any): AxiosPromise { + return localVarFp.phase2LockEvidenceResponseV1(lockEvidenceV1Response, options).then((request) => request(axios, basePath)); }, /** * @@ -1931,8 +2208,17 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase2TransferCommenceV1(transferCommenceV1Request?: TransferCommenceV1Request, options?: any): AxiosPromise { - return localVarFp.phase2TransferCommenceV1(transferCommenceV1Request, options).then((request) => request(axios, basePath)); + phase2TransferCommenceRequestV1(transferCommenceV1Request?: TransferCommenceV1Request, options?: any): AxiosPromise { + return localVarFp.phase2TransferCommenceRequestV1(transferCommenceV1Request, options).then((request) => request(axios, basePath)); + }, + /** + * + * @param {TransferCommenceV1Response} [transferCommenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase2TransferCommenceResponseV1(transferCommenceV1Response?: TransferCommenceV1Response, options?: any): AxiosPromise { + return localVarFp.phase2TransferCommenceResponseV1(transferCommenceV1Response, options).then((request) => request(axios, basePath)); }, /** * @@ -1940,8 +2226,17 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase3CommitFinalV1(commitFinalV1Request?: CommitFinalV1Request, options?: any): AxiosPromise { - return localVarFp.phase3CommitFinalV1(commitFinalV1Request, options).then((request) => request(axios, basePath)); + phase3CommitFinalRequestV1(commitFinalV1Request?: CommitFinalV1Request, options?: any): AxiosPromise { + return localVarFp.phase3CommitFinalRequestV1(commitFinalV1Request, options).then((request) => request(axios, basePath)); + }, + /** + * + * @param {CommitFinalV1Response} [commitFinalV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + phase3CommitFinalResponseV1(commitFinalV1Response?: CommitFinalV1Response, options?: any): AxiosPromise { + return localVarFp.phase3CommitFinalResponseV1(commitFinalV1Response, options).then((request) => request(axios, basePath)); }, /** * @@ -1949,26 +2244,26 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase3CommitPreparationV1(commitPreparationV1Request?: CommitPreparationV1Request, options?: any): AxiosPromise { - return localVarFp.phase3CommitPreparationV1(commitPreparationV1Request, options).then((request) => request(axios, basePath)); + phase3CommitPreparationRequestV1(commitPreparationV1Request?: CommitPreparationV1Request, options?: any): AxiosPromise { + return localVarFp.phase3CommitPreparationRequestV1(commitPreparationV1Request, options).then((request) => request(axios, basePath)); }, /** * - * @param {TransferCompleteV1Request} [transferCompleteV1Request] + * @param {CommitPreparationV1Response} [commitPreparationV1Response] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - phase3TransferCompleteV1(transferCompleteV1Request?: TransferCompleteV1Request, options?: any): AxiosPromise { - return localVarFp.phase3TransferCompleteV1(transferCompleteV1Request, options).then((request) => request(axios, basePath)); + phase3CommitPreparationResponseV1(commitPreparationV1Response?: CommitPreparationV1Response, options?: any): AxiosPromise { + return localVarFp.phase3CommitPreparationResponseV1(commitPreparationV1Response, options).then((request) => request(axios, basePath)); }, /** * - * @param {SendClientV1Request} [sendClientV1Request] + * @param {TransferCompleteV1Request} [transferCompleteV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - sendClientRequestV1(sendClientV1Request?: SendClientV1Request, options?: any): AxiosPromise { - return localVarFp.sendClientRequestV1(sendClientV1Request, options).then((request) => request(axios, basePath)); + phase3TransferCompleteRequestV1(transferCompleteV1Request?: TransferCompleteV1Request, options?: any): AxiosPromise { + return localVarFp.phase3TransferCompleteRequestV1(transferCompleteV1Request, options).then((request) => request(axios, basePath)); }, }; }; @@ -1980,6 +2275,17 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @extends {BaseAPI} */ export class DefaultApi extends BaseAPI { + /** + * + * @param {ClientV1Request} [clientV1Request] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public clientRequestV1(clientV1Request?: ClientV1Request, options?: any) { + return DefaultApiFp(this.configuration).clientRequestV1(clientV1Request, options).then((request) => request(this.axios, this.basePath)); + } + /** * * @param {TransferInitializationV1Request} [transferInitializationV1Request] @@ -1987,8 +2293,19 @@ export class DefaultApi extends BaseAPI { * @throws {RequiredError} * @memberof DefaultApi */ - public phase1TransferInitiationV1(transferInitializationV1Request?: TransferInitializationV1Request, options?: any) { - return DefaultApiFp(this.configuration).phase1TransferInitiationV1(transferInitializationV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase1TransferInitiationRequestV1(transferInitializationV1Request?: TransferInitializationV1Request, options?: any) { + return DefaultApiFp(this.configuration).phase1TransferInitiationRequestV1(transferInitializationV1Request, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {TransferInitializationV1Response} [transferInitializationV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public phase1TransferInitiationResponseV1(transferInitializationV1Response?: TransferInitializationV1Response, options?: any) { + return DefaultApiFp(this.configuration).phase1TransferInitiationResponseV1(transferInitializationV1Response, options).then((request) => request(this.axios, this.basePath)); } /** @@ -1998,8 +2315,19 @@ export class DefaultApi extends BaseAPI { * @throws {RequiredError} * @memberof DefaultApi */ - public phase2LockEvidenceV1(lockEvidenceV1Request?: LockEvidenceV1Request, options?: any) { - return DefaultApiFp(this.configuration).phase2LockEvidenceV1(lockEvidenceV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase2LockEvidenceRequestV1(lockEvidenceV1Request?: LockEvidenceV1Request, options?: any) { + return DefaultApiFp(this.configuration).phase2LockEvidenceRequestV1(lockEvidenceV1Request, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {LockEvidenceV1Response} [lockEvidenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public phase2LockEvidenceResponseV1(lockEvidenceV1Response?: LockEvidenceV1Response, options?: any) { + return DefaultApiFp(this.configuration).phase2LockEvidenceResponseV1(lockEvidenceV1Response, options).then((request) => request(this.axios, this.basePath)); } /** @@ -2009,8 +2337,19 @@ export class DefaultApi extends BaseAPI { * @throws {RequiredError} * @memberof DefaultApi */ - public phase2TransferCommenceV1(transferCommenceV1Request?: TransferCommenceV1Request, options?: any) { - return DefaultApiFp(this.configuration).phase2TransferCommenceV1(transferCommenceV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase2TransferCommenceRequestV1(transferCommenceV1Request?: TransferCommenceV1Request, options?: any) { + return DefaultApiFp(this.configuration).phase2TransferCommenceRequestV1(transferCommenceV1Request, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {TransferCommenceV1Response} [transferCommenceV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public phase2TransferCommenceResponseV1(transferCommenceV1Response?: TransferCommenceV1Response, options?: any) { + return DefaultApiFp(this.configuration).phase2TransferCommenceResponseV1(transferCommenceV1Response, options).then((request) => request(this.axios, this.basePath)); } /** @@ -2020,8 +2359,19 @@ export class DefaultApi extends BaseAPI { * @throws {RequiredError} * @memberof DefaultApi */ - public phase3CommitFinalV1(commitFinalV1Request?: CommitFinalV1Request, options?: any) { - return DefaultApiFp(this.configuration).phase3CommitFinalV1(commitFinalV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase3CommitFinalRequestV1(commitFinalV1Request?: CommitFinalV1Request, options?: any) { + return DefaultApiFp(this.configuration).phase3CommitFinalRequestV1(commitFinalV1Request, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {CommitFinalV1Response} [commitFinalV1Response] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public phase3CommitFinalResponseV1(commitFinalV1Response?: CommitFinalV1Response, options?: any) { + return DefaultApiFp(this.configuration).phase3CommitFinalResponseV1(commitFinalV1Response, options).then((request) => request(this.axios, this.basePath)); } /** @@ -2031,30 +2381,30 @@ export class DefaultApi extends BaseAPI { * @throws {RequiredError} * @memberof DefaultApi */ - public phase3CommitPreparationV1(commitPreparationV1Request?: CommitPreparationV1Request, options?: any) { - return DefaultApiFp(this.configuration).phase3CommitPreparationV1(commitPreparationV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase3CommitPreparationRequestV1(commitPreparationV1Request?: CommitPreparationV1Request, options?: any) { + return DefaultApiFp(this.configuration).phase3CommitPreparationRequestV1(commitPreparationV1Request, options).then((request) => request(this.axios, this.basePath)); } /** * - * @param {TransferCompleteV1Request} [transferCompleteV1Request] + * @param {CommitPreparationV1Response} [commitPreparationV1Response] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public phase3TransferCompleteV1(transferCompleteV1Request?: TransferCompleteV1Request, options?: any) { - return DefaultApiFp(this.configuration).phase3TransferCompleteV1(transferCompleteV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase3CommitPreparationResponseV1(commitPreparationV1Response?: CommitPreparationV1Response, options?: any) { + return DefaultApiFp(this.configuration).phase3CommitPreparationResponseV1(commitPreparationV1Response, options).then((request) => request(this.axios, this.basePath)); } /** * - * @param {SendClientV1Request} [sendClientV1Request] + * @param {TransferCompleteV1Request} [transferCompleteV1Request] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public sendClientRequestV1(sendClientV1Request?: SendClientV1Request, options?: any) { - return DefaultApiFp(this.configuration).sendClientRequestV1(sendClientV1Request, options).then((request) => request(this.axios, this.basePath)); + public phase3TransferCompleteRequestV1(transferCompleteV1Request?: TransferCompleteV1Request, options?: any) { + return DefaultApiFp(this.configuration).phase3TransferCompleteRequestV1(transferCompleteV1Request, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/client-request-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/client-request-endpoint.ts new file mode 100644 index 0000000000..aad76588fa --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/client-request-endpoint.ts @@ -0,0 +1,99 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; + +import OAS from "../../../json/openapi.json"; + +export interface IClientRequestEndpointOptions { + logLevel?: LogLevelDesc; + gateway: PluginOdapGateway; +} + +export class ClientRequestEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "ClientRequestEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return ClientRequestEndpointV1.CLASS_NAME; + } + + constructor(public readonly options: IClientRequestEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.gateway, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public getPath(): string { + const apiPath = + OAS.paths["/api/v1/@hyperledger/cactus-plugin-odap-hemres/clientrequest"]; + return apiPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths["/api/v1/@hyperledger/cactus-plugin-odap-hemres/clientrequest"]; + return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/clientrequest" + ].post.operationId; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public async handleRequest(req: Request, res: Response): Promise { + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + await this.options.gateway.runOdap(req.body); + res.status(200).json("OK"); + } catch (ex) { + this.log.error(`Crash while serving ${reqTag}`, ex); + res.status(500).json({ + message: "Internal Server Error", + error: ex?.stack || ex?.message, + }); + } + } +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/commit-final-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/commit-final-response-endpoint.ts similarity index 77% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/commit-final-endpoint.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/commit-final-response-endpoint.ts index bb7c296d06..0df0da6223 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/commit-final-endpoint.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/commit-final-response-endpoint.ts @@ -15,25 +15,25 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { CommitFinalV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; -export interface ICommitFinalEndpointOptions { +import OAS from "../../../json/openapi.json"; + +export interface ICommitFinalResponseEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class CommitFinalEndpointV1 implements IWebServiceEndpoint { - public static readonly CLASS_NAME = "CommitFinalEndpointV1"; +export class CommitFinalResponseEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "CommitFinalResponseEndpointV1"; private readonly log: Logger; public get className(): string { - return CommitFinalEndpointV1.CLASS_NAME; + return CommitFinalResponseEndpointV1.CLASS_NAME; } - constructor(public readonly options: ICommitFinalEndpointOptions) { + constructor(public readonly options: ICommitFinalResponseEndpointOptions) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -46,7 +46,7 @@ export class CommitFinalEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinal" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.path; } @@ -54,14 +54,14 @@ export class CommitFinalEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinal" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinal" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalresponse" ].post.operationId; } @@ -89,10 +89,9 @@ export class CommitFinalEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: CommitFinalV1Request = req.body; try { - const resBody = await this.options.gateway.commitFinalReceived(reqBody); - res.json(resBody); + await this.options.gateway.onCommitFinalResponseReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/commite-prepare-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/commite-prepare-response-endpoint.ts similarity index 76% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/commite-prepare-endpoint.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/commite-prepare-response-endpoint.ts index 91b842ea60..74764c0fbd 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/commite-prepare-endpoint.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/commite-prepare-response-endpoint.ts @@ -15,25 +15,28 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { CommitPreparationV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; -export interface ICommitPrepareEndpointOptions { +import OAS from "../../../json/openapi.json"; + +export interface ICommitPreparationResponseEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class CommitPrepareEndpointV1 implements IWebServiceEndpoint { - public static readonly CLASS_NAME = "CommitPrepareEndpointV1"; +export class CommitPreparationResponseEndpointV1 + implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "CommitPrepareResponseEndpointV1"; private readonly log: Logger; public get className(): string { - return CommitPrepareEndpointV1.CLASS_NAME; + return CommitPreparationResponseEndpointV1.CLASS_NAME; } - constructor(public readonly options: ICommitPrepareEndpointOptions) { + constructor( + public readonly options: ICommitPreparationResponseEndpointOptions, + ) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -46,7 +49,7 @@ export class CommitPrepareEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparation" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.path; } @@ -54,14 +57,14 @@ export class CommitPrepareEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparation" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparation" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationresponse" ].post.operationId; } @@ -89,10 +92,9 @@ export class CommitPrepareEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: CommitPreparationV1Request = req.body; try { - const resBody = await this.options.gateway.commitPrepareReceived(reqBody); - res.json(resBody); + await this.options.gateway.onCommitPrepareResponseReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/lock-evidence-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/lock-evidence-response-endpoint.ts similarity index 78% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/lock-evidence-endpoint.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/lock-evidence-response-endpoint.ts index b38d536dc9..dbec7bd546 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/lock-evidence-endpoint.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/lock-evidence-response-endpoint.ts @@ -15,25 +15,24 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { LockEvidenceV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; -export interface ILockEvidenceEndpointOptions { +export interface ILockEvidenceResponseEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class LockEvidenceEndpointV1 implements IWebServiceEndpoint { - public static readonly CLASS_NAME = "LockEvidenceEndpointV1"; +export class LockEvidenceResponseEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "LockEvidenceResponseEndpointV1"; private readonly log: Logger; public get className(): string { - return LockEvidenceEndpointV1.CLASS_NAME; + return LockEvidenceResponseEndpointV1.CLASS_NAME; } - constructor(public readonly options: ILockEvidenceEndpointOptions) { + constructor(public readonly options: ILockEvidenceResponseEndpointOptions) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -50,7 +49,7 @@ export class LockEvidenceEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidence" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidenceresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.path; } @@ -58,14 +57,14 @@ export class LockEvidenceEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidence" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidenceresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidence" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidenceresponse" ].post.operationId; } @@ -93,10 +92,9 @@ export class LockEvidenceEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: LockEvidenceV1Request = req.body; try { - const resBody = await this.options.gateway.lockEvidenceReceived(reqBody); - res.json(resBody); + await this.options.gateway.onLockEvidenceResponseReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-commence-response-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-commence-response-endpoint.ts new file mode 100644 index 0000000000..97178a1886 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-commence-response-endpoint.ts @@ -0,0 +1,104 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; + +export interface ITransferCommenceResponseEndpointOptions { + logLevel?: LogLevelDesc; + gateway: PluginOdapGateway; +} + +export class TransferCommenceResponseEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "TransferCommenceResponseEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return TransferCommenceResponseEndpointV1.CLASS_NAME; + } + + constructor( + public readonly options: ITransferCommenceResponseEndpointOptions, + ) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.gateway, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public getPath(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommenceresponse" + ]; + return apiPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommenceresponse" + ]; + return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommenceresponse" + ].post.operationId; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public async handleRequest(req: Request, res: Response): Promise { + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + await this.options.gateway.onTransferCommenceResponseReceived(req.body); + res.status(200).json("OK"); + } catch (ex) { + this.log.error(`Crash while serving ${reqTag}`, ex); + res.status(500).json({ + message: "Internal Server Error", + error: ex?.stack || ex?.message, + }); + } + } +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-initiation-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-initiation-response-endpoint.ts similarity index 75% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-initiation-endpoint.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-initiation-response-endpoint.ts index e2e150592c..a4a3bb8184 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-initiation-endpoint.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/client-side/transfer-initiation-response-endpoint.ts @@ -15,25 +15,27 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { TransferInitializationV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; -export interface ITransferInitiationEndpointOptions { +export interface ITransferInitiationResponseEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class TransferInitiationEndpointV1 implements IWebServiceEndpoint { - public static readonly CLASS_NAME = "TransferInitiationEndpointV1"; +export class TransferInitiationResponseEndpointV1 + implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "TransferInitiationResponseEndpointV1"; private readonly log: Logger; public get className(): string { - return TransferInitiationEndpointV1.CLASS_NAME; + return TransferInitiationResponseEndpointV1.CLASS_NAME; } - constructor(public readonly options: ITransferInitiationEndpointOptions) { + constructor( + public readonly options: ITransferInitiationResponseEndpointOptions, + ) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -46,7 +48,7 @@ export class TransferInitiationEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiation" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.path; } @@ -54,14 +56,14 @@ export class TransferInitiationEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiation" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationresponse" ]; return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiation" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationresponse" ].post.operationId; } @@ -90,12 +92,9 @@ export class TransferInitiationEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: TransferInitializationV1Request = req.body; try { - const resBody = await this.options.gateway.initiateTransferReceived( - reqBody, - ); - res.json(resBody); + await this.options.gateway.onTransferInitiationResponseReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commit-final-request-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commit-final-request-endpoint.ts new file mode 100644 index 0000000000..fbaa92de76 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commit-final-request-endpoint.ts @@ -0,0 +1,102 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; + +export interface ICommitFinalRequestEndpointOptions { + logLevel?: LogLevelDesc; + gateway: PluginOdapGateway; +} + +export class CommitFinalRequestEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "CommitFinalRequestEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return CommitFinalRequestEndpointV1.CLASS_NAME; + } + + constructor(public readonly options: ICommitFinalRequestEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.gateway, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public getPath(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalrequest" + ]; + return apiPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalrequest" + ]; + return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitfinalrequest" + ].post.operationId; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public async handleRequest(req: Request, res: Response): Promise { + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + await this.options.gateway.onCommitFinalRequestReceived(req.body); + res.status(200).json("OK"); + } catch (ex) { + this.log.error(`Crash while serving ${reqTag}`, ex); + res.status(500).json({ + message: "Internal Server Error", + error: ex?.stack || ex?.message, + }); + } + } +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commite-prepare-request-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commite-prepare-request-endpoint.ts new file mode 100644 index 0000000000..5c974b6fc3 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/commite-prepare-request-endpoint.ts @@ -0,0 +1,104 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; + +export interface ICommitPreparationRequestEndpointOptions { + logLevel?: LogLevelDesc; + gateway: PluginOdapGateway; +} + +export class CommitPreparationRequestEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "CommitPreparationRequestEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return CommitPreparationRequestEndpointV1.CLASS_NAME; + } + + constructor( + public readonly options: ICommitPreparationRequestEndpointOptions, + ) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.gateway, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public getPath(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationrequest" + ]; + return apiPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationrequest" + ]; + return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/commitpreparationrequest" + ].post.operationId; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public async handleRequest(req: Request, res: Response): Promise { + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + await this.options.gateway.onCommitPrepareRequestReceived(req.body); + res.status(200).json("OK"); + } catch (ex) { + this.log.error(`Crash while serving ${reqTag}`, ex); + res.status(500).json({ + message: "Internal Server Error", + error: ex?.stack || ex?.message, + }); + } + } +} diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/send-client-request.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/lock-evidence-request-endpoint.ts similarity index 71% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/send-client-request.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/lock-evidence-request-endpoint.ts index a694250f6c..9072abd93c 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/send-client-request.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/lock-evidence-request-endpoint.ts @@ -15,25 +15,24 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { SendClientV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; -export interface ISendClientRequestEndpointOptions { +export interface ILockEvidenceRequestEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class SendClientRequestEndpointV1 implements IWebServiceEndpoint { - public static readonly CLASS_NAME = "SendClientRequestEndpointV1"; +export class LockEvidenceRequestEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "LockEvidenceRequestEndpointV1"; private readonly log: Logger; public get className(): string { - return SendClientRequestEndpointV1.CLASS_NAME; + return LockEvidenceRequestEndpointV1.CLASS_NAME; } - constructor(public readonly options: ISendClientRequestEndpointOptions) { + constructor(public readonly options: ILockEvidenceRequestEndpointOptions) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -50,7 +49,7 @@ export class SendClientRequestEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/sendclientrequest" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidencerequest" ]; return apiPath.post["x-hyperledger-cactus"].http.path; } @@ -58,14 +57,14 @@ export class SendClientRequestEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/sendclientrequest" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidencerequest" ]; return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/sendclientrequest" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/lockevidencerequest" ].post.operationId; } @@ -93,10 +92,9 @@ export class SendClientRequestEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: SendClientV1Request = req.body; try { - const resBody = await this.options.gateway.runOdap(reqBody); - res.json(resBody); + await this.options.gateway.onLockEvidenceRequestReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-commence-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-commence-request-endpoint.ts similarity index 78% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-commence-endpoint.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-commence-request-endpoint.ts index dd4779d2ab..0da58301f2 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-commence-endpoint.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-commence-request-endpoint.ts @@ -15,25 +15,26 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { TransferCommenceV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; -export interface ITransferCommenceEndpointOptions { +export interface ITransferCommenceRequestEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class TransferCommenceEndpointV1 implements IWebServiceEndpoint { +export class TransferCommenceRequestEndpointV1 implements IWebServiceEndpoint { public static readonly CLASS_NAME = "LockEvidencePrepareEndpointV1"; private readonly log: Logger; public get className(): string { - return TransferCommenceEndpointV1.CLASS_NAME; + return TransferCommenceRequestEndpointV1.CLASS_NAME; } - constructor(public readonly options: ITransferCommenceEndpointOptions) { + constructor( + public readonly options: ITransferCommenceRequestEndpointOptions, + ) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -46,7 +47,7 @@ export class TransferCommenceEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommence" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommencerequest" ]; return apiPath.post["x-hyperledger-cactus"].http.path; } @@ -54,14 +55,14 @@ export class TransferCommenceEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommence" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommencerequest" ]; return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommence" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase2/transfercommencerequest" ].post.operationId; } @@ -89,12 +90,9 @@ export class TransferCommenceEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: TransferCommenceV1Request = req.body; try { - const resBody = await this.options.gateway.transferCommenceReceived( - reqBody, - ); - res.json(resBody); + await this.options.gateway.onTransferCommenceRequestReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-complete-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-complete-request-endpoint.ts similarity index 75% rename from packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-complete-endpoint.ts rename to packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-complete-request-endpoint.ts index 2d2c19a6db..ef8ee78711 100644 --- a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/transfer-complete-endpoint.ts +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-complete-request-endpoint.ts @@ -15,25 +15,26 @@ import { import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; -import { PluginOdapGateway } from "../gateway/plugin-odap-gateway"; -import { TransferCompleteV1Request } from "../generated/openapi/typescript-axios"; -import OAS from "../../json/openapi.json"; +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; -export interface ITransferCompleteEndpointOptions { +export interface ITransferCompleteRequestEndpointOptions { logLevel?: LogLevelDesc; gateway: PluginOdapGateway; } -export class TransferCompleteEndpointV1 implements IWebServiceEndpoint { - public static readonly CLASS_NAME = "TransferCompleteEndpointV1"; +export class TransferCompleteRequestEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "TransferCompleteRequestEndpointV1"; private readonly log: Logger; public get className(): string { - return TransferCompleteEndpointV1.CLASS_NAME; + return TransferCompleteRequestEndpointV1.CLASS_NAME; } - constructor(public readonly options: ITransferCompleteEndpointOptions) { + constructor( + public readonly options: ITransferCompleteRequestEndpointOptions, + ) { const fnTag = `${this.className}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); Checks.truthy(options.gateway, `${fnTag} arg options.connector`); @@ -46,7 +47,7 @@ export class TransferCompleteEndpointV1 implements IWebServiceEndpoint { public getPath(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercomplete" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercompleterequest" ]; return apiPath.get["x-hyperledger-cactus"].http.path; } @@ -54,14 +55,14 @@ export class TransferCompleteEndpointV1 implements IWebServiceEndpoint { public getVerbLowerCase(): string { const apiPath = OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercomplete" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercompleterequest" ]; return apiPath.get["x-hyperledger-cactus"].http.verbLowerCase; } public getOperationId(): string { return OAS.paths[ - "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercomplete" + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase3/transfercompleterequest" ].get.operationId; } @@ -89,12 +90,9 @@ export class TransferCompleteEndpointV1 implements IWebServiceEndpoint { public async handleRequest(req: Request, res: Response): Promise { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); - const reqBody: TransferCompleteV1Request = req.body; try { - const resBody = await this.options.gateway.transferCompleteReceived( - reqBody, - ); - res.json(resBody); + await this.options.gateway.onTransferCompleteRequestReceived(req.body); + res.status(200).json("OK"); } catch (ex) { this.log.error(`Crash while serving ${reqTag}`, ex); res.status(500).json({ diff --git a/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-initiation-request-endpoint.ts b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-initiation-request-endpoint.ts new file mode 100644 index 0000000000..435a38014b --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/main/typescript/web-services/server-side/transfer-initiation-request-endpoint.ts @@ -0,0 +1,106 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginOdapGateway } from "../../gateway/plugin-odap-gateway"; +import OAS from "../../../json/openapi.json"; + +export interface ITransferInitiationRequestEndpointOptions { + logLevel?: LogLevelDesc; + gateway: PluginOdapGateway; +} + +export class TransferInitiationRequestEndpointV1 + implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "TransferInitiationRequestEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return TransferInitiationRequestEndpointV1.CLASS_NAME; + } + + constructor( + public readonly options: ITransferInitiationRequestEndpointOptions, + ) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.gateway, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public getPath(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationrequest" + ]; + return apiPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationrequest" + ]; + return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-odap-hemres/phase1/transferinitiationrequest" + ].post.operationId; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + console.log("getting authorized provider"); + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public async handleRequest(req: Request, res: Response): Promise { + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + await this.options.gateway.onTransferInitiationRequestReceived(req.body); + res.status(200).json("OK"); + } catch (ex) { + this.log.error(`Crash while serving ${reqTag}`, ex); + res.status(500).json({ + message: "Internal Server Error", + error: ex?.stack || ex?.message, + }); + } + } +} diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call-with-ledger-connector.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call-with-ledger-connector.test.ts similarity index 97% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call-with-ledger-connector.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call-with-ledger-connector.test.ts index 82b7f186f1..c0401b0ebc 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call-with-ledger-connector.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call-with-ledger-connector.test.ts @@ -11,10 +11,7 @@ import { create } from "ipfs-http-client"; import bodyParser from "body-parser"; import express from "express"; import { DefaultApi as ObjectStoreIpfsApi } from "@hyperledger/cactus-plugin-object-store-ipfs"; -import { - SendClientV1Request, - AssetProfile, -} from "../../../../main/typescript/generated/openapi/typescript-axios"; +import { AssetProfile } from "../../../main/typescript/generated/openapi/typescript-axios"; import { Checks, IListenOptions, @@ -32,8 +29,11 @@ import { BesuTestLedger, } from "@hyperledger/cactus-test-tooling"; import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; -import { DefaultApi as OdapApi } from "../../../../main/typescript/public-api"; -import LockAssetContractJson from "../../../solidity/lock-asset-contract/LockAsset.json"; +import { + ClientV1Request, + DefaultApi as OdapApi, +} from "../../../main/typescript/public-api"; +import LockAssetContractJson from "../../solidity/lock-asset-contract/LockAsset.json"; import { PluginRegistry } from "@hyperledger/cactus-core"; import { Configuration, @@ -43,7 +43,7 @@ import { import { IPluginOdapGatewayConstructorOptions, PluginOdapGateway, -} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +} from "../../../main/typescript/gateway/plugin-odap-gateway"; import { ChainCodeProgrammingLanguage, DefaultEventHandlerStrategy, @@ -213,7 +213,7 @@ test("BEFORE " + testCase, async (t: Test) => { const contractName = "basic-asset-transfer-2"; fabricContractName = contractName; const contractRelPath = - "../../fabric-contracts/lock-asset/chaincode-typescript"; + "../fabric-contracts/lock-asset/chaincode-typescript"; const contractDir = path.join(__dirname, contractRelPath); // ├── package.json @@ -621,7 +621,10 @@ test(testCase, async (t: Test) => { const dummyPubKey = clientOdapGateway.bufArray2HexStr(dummyPubKeyBytes); const expiryDate = new Date("23/25/2060").toString(); const assetProfile: AssetProfile = { expirationDate: expiryDate }; - const odapClientRequest: SendClientV1Request = { + const odapClientRequest: ClientV1Request = { + clientGatewayConfiguration: { + apiHost: apiHost, + }, serverGatewayConfiguration: { apiHost: odapServerGatewayApiHost, }, @@ -645,7 +648,7 @@ test(testCase, async (t: Test) => { serverIdentityPubkey: dummyPubKey, sourceGatewayDltSystem: "dummy", }; - const res = await apiClient.sendClientRequestV1(odapClientRequest); + const res = await apiClient.clientRequestV1(odapClientRequest); t.ok(res); } t.end(); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call.test.ts similarity index 93% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call.test.ts index 08ce3986c4..f780bec207 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/odap-api-call.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap-api-call.test.ts @@ -7,24 +7,25 @@ import { create } from "ipfs-http-client"; import bodyParser from "body-parser"; import express from "express"; import { DefaultApi as ObjectStoreIpfsApi } from "@hyperledger/cactus-plugin-object-store-ipfs"; -import { - SendClientV1Request, - AssetProfile, -} from "../../../../main/typescript/generated/openapi/typescript-axios"; +import { DefaultApi as OdapApi } from "../../../main/typescript/public-api"; + import { IListenOptions, LogLevelDesc, Servers, } from "@hyperledger/cactus-common"; -import { DefaultApi as OdapApi } from "../../../../main/typescript/public-api"; - import { Configuration } from "@hyperledger/cactus-core-api"; + +import { GoIpfsTestContainer } from "@hyperledger/cactus-test-tooling"; import { PluginOdapGateway, IPluginOdapGatewayConstructorOptions, -} from "../../../../main/typescript/gateway/plugin-odap-gateway"; -import { GoIpfsTestContainer } from "@hyperledger/cactus-test-tooling"; +} from "../../../main/typescript/gateway/plugin-odap-gateway"; +import { + AssetProfile, + ClientV1Request, +} from "../../../main/typescript/public-api"; /** * Use this to debug issues with the fabric node SDK @@ -166,7 +167,10 @@ describe(testCase, () => { const expiryDate = new Date(2060, 11, 24).toString(); const assetProfile: AssetProfile = { expirationDate: expiryDate }; - const odapClientRequest: SendClientV1Request = { + const odapClientRequest: ClientV1Request = { + clientGatewayConfiguration: { + apiHost: odapClientGatewayApiHost, + }, serverGatewayConfiguration: { apiHost: odapServerGatewayApiHost, }, @@ -190,7 +194,7 @@ describe(testCase, () => { clientIdentityPubkey: "", serverIdentityPubkey: "", }; - const res = await apiClient.sendClientRequestV1(odapClientRequest); + const res = await apiClient.clientRequestV1(odapClientRequest); expect(res.status).toBe(200); } @@ -200,7 +204,7 @@ describe(testCase, () => { const [sessionId] = clientOdapGateway.sessions.keys(); const clientSessionData = clientOdapGateway.sessions.get(sessionId); - const serverSessionData = clientOdapGateway.sessions.get(sessionId); + const serverSessionData = serverOdapGateway.sessions.get(sessionId); if (clientSessionData == undefined || serverSessionData == undefined) { throw new Error("Test Failed"); @@ -221,7 +225,9 @@ describe(testCase, () => { serverSessionData.applicationProfile, ); - expect(clientSessionData.assetProfile).toBe(serverSessionData.assetProfile); + expect(JSON.stringify(clientSessionData.assetProfile)).toBe( + JSON.stringify(serverSessionData.assetProfile), + ); expect(clientSessionData.originatorPubkey).toBe( serverSessionData.originatorPubkey, @@ -255,14 +261,6 @@ describe(testCase, () => { serverSessionData.initializationResponseMessageHash, ); - expect(clientSessionData.initializationRequestMessageRcvTimeStamp).toBe( - serverSessionData.initializationRequestMessageRcvTimeStamp, - ); - - expect( - clientSessionData.initializationRequestMessageProcessedTimeStamp, - ).toBe(serverSessionData.initializationRequestMessageProcessedTimeStamp); - expect(clientSessionData.clientSignatureInitializationRequestMessage).toBe( serverSessionData.clientSignatureInitializationRequestMessage, ); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-initiation.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-initiation.test.ts deleted file mode 100644 index 4e102225ac..0000000000 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-initiation.test.ts +++ /dev/null @@ -1,228 +0,0 @@ -import { randomInt } from "crypto"; -import { SHA256 } from "crypto-js"; -import { v4 as uuidV4 } from "uuid"; -import { - OdapMessageType, - PluginOdapGateway, -} from "../../../../main/typescript/gateway/plugin-odap-gateway"; -import { - TransferInitializationV1Request, - AssetProfile, -} from "../../../../main/typescript/public-api"; - -test("successful transfer initiation flow", async () => { - const sourceGatewayConstructor = { - name: "plugin-odap-gateway#sourceGateway", - dltIDs: ["DLT2"], - instanceId: uuidV4(), - }; - const recipientGatewayConstructor = { - name: "plugin-odap-gateway#recipientGateway", - dltIDs: ["DLT1"], - instanceId: uuidV4(), - }; - - const pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); - const pluginRecipientGateway = new PluginOdapGateway( - recipientGatewayConstructor, - ); - const expiryDate = new Date(2060, 11, 24).toString(); - const assetProfile: AssetProfile = { expirationDate: expiryDate }; - const sequenceNumber = randomInt(100); - - const initializationRequestMessage: TransferInitializationV1Request = { - messageType: OdapMessageType.InitializationRequest, - sessionID: uuidV4(), - version: "0.0.0", - loggingProfile: "dummyLoggingProfile", - accessControlProfile: "dummyAccessControlProfile", - applicationProfile: "dummyApplicationProfile", - payloadProfile: { - assetProfile: assetProfile, - capabilities: "", - }, - clientSignature: "", - sourceGatewayPubkey: pluginSourceGateway.pubKey, - sourceGatewayDltSystem: "DLT1", - recipientGatewayPubkey: pluginRecipientGateway.pubKey, - recipientGatewayDltSystem: "DLT2", - sequenceNumber: sequenceNumber, - }; - - initializationRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( - await pluginSourceGateway.sign( - JSON.stringify(initializationRequestMessage), - ), - ); - - const messageHash = SHA256( - JSON.stringify(initializationRequestMessage), - ).toString(); - - const response = await pluginRecipientGateway.initiateTransferReceived( - initializationRequestMessage, - ); - - const responseHash = SHA256(JSON.stringify(response)).toString(); - - expect(parseInt(response.sessionID)).not.toBeUndefined(); - - const sessionData = pluginRecipientGateway.sessions.get(response.sessionID); - - expect(sessionData).not.toBeUndefined(); - - expect(sessionData?.loggingProfile).toBe("dummyLoggingProfile"); - expect(sessionData?.accessControlProfile).toBe("dummyAccessControlProfile"); - expect(sessionData?.applicationProfile).toBe("dummyApplicationProfile"); - expect(sessionData?.sourceGatewayPubkey).toBe(pluginSourceGateway.pubKey); - expect(sessionData?.recipientGatewayPubkey).toBe( - pluginRecipientGateway.pubKey, - ); - expect(sessionData?.sourceGatewayDltSystem).toBe("DLT1"); - expect(sessionData?.recipientGatewayDltSystem).toBe("DLT2"); - - expect(sessionData?.initializationRequestMessageHash).toBe(messageHash); - expect(sessionData?.initializationResponseMessageHash).toBe(responseHash); - - expect(sessionData?.clientSignatureInitializationRequestMessage).toBe( - initializationRequestMessage.clientSignature, - ); - expect(sessionData?.serverSignatureInitializationResponseMessage).toBe( - response.serverSignature, - ); - - expect(response.sequenceNumber).toBe(sequenceNumber); - - expect(response.messageType).toBe(OdapMessageType.InitializationResponse); - - expect(response.initialRequestMessageHash).toBe(messageHash); - expect(parseInt(response.processedTimeStamp)).toBeGreaterThan( - parseInt(response.timeStamp), - ); - - const sourceClientSignature = new Uint8Array( - Buffer.from(response.serverSignature, "hex"), - ); - - const sourceClientPubkey = new Uint8Array( - Buffer.from(response.serverIdentityPubkey, "hex"), - ); - - response.serverSignature = ""; - - expect( - pluginSourceGateway.verifySignature( - JSON.stringify(response), - sourceClientSignature, - sourceClientPubkey, - ), - ).toBe(true); -}); - -test("transfer initiation flow fails because of incompatible DLTs", async () => { - const sourceGatewayConstructor = { - name: "plugin-odap-gateway#sourceGateway", - dltIDs: ["DLT1"], - instanceId: uuidV4(), - }; - const recipientGatewayConstructor = { - name: "plugin-odap-gateway#recipientGateway", - dltIDs: ["DLT2"], - instanceId: uuidV4(), - }; - - const pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); - const pluginRecipientGateway = new PluginOdapGateway( - recipientGatewayConstructor, - ); - const expiryDate = new Date(2060, 11, 24).toString(); - const assetProfile: AssetProfile = { expirationDate: expiryDate }; - const sequenceNumber = randomInt(100); - - const initializationRequestMessage: TransferInitializationV1Request = { - messageType: OdapMessageType.InitializationRequest, - sessionID: uuidV4(), - version: "0.0.0", - loggingProfile: "dummy", - accessControlProfile: "dummy", - applicationProfile: "dummy", - payloadProfile: { - assetProfile: assetProfile, - capabilities: "", - }, - clientSignature: "", - sourceGatewayPubkey: pluginSourceGateway.pubKey, - sourceGatewayDltSystem: "DLT1", - recipientGatewayPubkey: pluginRecipientGateway.pubKey, - recipientGatewayDltSystem: "DLT2", - sequenceNumber: sequenceNumber, - }; - - initializationRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( - await pluginSourceGateway.sign( - JSON.stringify(initializationRequestMessage), - ), - ); - - await pluginRecipientGateway - .initiateTransferReceived(initializationRequestMessage) - .then(() => { - throw new Error("Test Failed"); - }) - .catch((ex: Error) => - expect(ex.message).toMatch( - "source gateway dlt system is not supported by this gateway", - ), - ); -}); - -test("transfer initiation flow fails because of asset expired", async () => { - const sourceGatewayConstructor = { - name: "plugin-odap-gateway#sourceGateway", - dltIDs: ["DLT2"], - instanceId: uuidV4(), - }; - const recipientGatewayConstructor = { - name: "plugin-odap-gateway#recipientGateway", - dltIDs: ["DLT1"], - instanceId: uuidV4(), - }; - - const pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); - const pluginRecipientGateway = new PluginOdapGateway( - recipientGatewayConstructor, - ); - const expiryDate = new Date(2020, 11, 24).toString(); - const assetProfile: AssetProfile = { expirationDate: expiryDate }; - const sequenceNumber = randomInt(100); - - const initializationRequestMessage: TransferInitializationV1Request = { - messageType: OdapMessageType.InitializationRequest, - sessionID: uuidV4(), - version: "0.0.0", - loggingProfile: "dummy", - accessControlProfile: "dummy", - applicationProfile: "dummy", - payloadProfile: { - assetProfile: assetProfile, - capabilities: "", - }, - clientSignature: "", - sourceGatewayPubkey: pluginSourceGateway.pubKey, - sourceGatewayDltSystem: "DLT1", - recipientGatewayPubkey: pluginRecipientGateway.pubKey, - recipientGatewayDltSystem: "DLT2", - sequenceNumber: sequenceNumber, - }; - - initializationRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( - pluginSourceGateway.sign(JSON.stringify(initializationRequestMessage)), - ); - - await pluginRecipientGateway - .initiateTransferReceived(initializationRequestMessage) - .then(() => { - throw new Error("Test Failed"); - }) - .catch((ex: Error) => expect(ex.message).toMatch("asset has expired")); -}); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-final.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-final.test.ts new file mode 100644 index 0000000000..7dfb717abb --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-final.test.ts @@ -0,0 +1,141 @@ +import { randomInt } from "crypto"; +import { SHA256 } from "crypto-js"; +import { v4 as uuidV4 } from "uuid"; +import { checkValidCommitFinalResponse } from "../../../../main/typescript/gateway/client/commit-final"; +import { + OdapMessageType, + PluginOdapGateway, +} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +import { + CommitFinalV1Response, + SessionData, +} from "../../../../main/typescript/public-api"; + +const COMMIT_FINAL_REQUEST_MESSAGE_HASH = "dummyCommitFinalRequestMessageHash"; +const COMMIT_ACK_CLAIM = "dummyCommitAckClaim"; + +let sourceGatewayConstructor; +let recipientGatewayConstructor; +let pluginSourceGateway: PluginOdapGateway; +let pluginRecipientGateway: PluginOdapGateway; +let sequenceNumber: number; +let sessionID: string; +let step: number; + +beforeEach(() => { + sourceGatewayConstructor = { + name: "plugin-odap-gateway#sourceGateway", + dltIDs: ["DLT2"], + instanceId: uuidV4(), + }; + recipientGatewayConstructor = { + name: "plugin-odap-gateway#recipientGateway", + dltIDs: ["DLT1"], + instanceId: uuidV4(), + }; + + pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); + pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); + + sequenceNumber = randomInt(100); + sessionID = uuidV4(); + step = 1; + + const sessionData: SessionData = { + id: sessionID, + step: step, + sourceGatewayPubkey: pluginSourceGateway.pubKey, + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + commitFinalRequestMessageHash: COMMIT_FINAL_REQUEST_MESSAGE_HASH, + lastSequenceNumber: sequenceNumber, + }; + + pluginSourceGateway.sessions.set(sessionID, sessionData); +}); + +test("valid commit final response", async () => { + const commitFinalResponse: CommitFinalV1Response = { + messageType: OdapMessageType.CommitFinalResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + commitAcknowledgementClaim: COMMIT_ACK_CLAIM, + hashCommitFinal: COMMIT_FINAL_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + commitFinalResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign(JSON.stringify(commitFinalResponse)), + ); + + const messageHash = SHA256(JSON.stringify(commitFinalResponse)).toString(); + + await checkValidCommitFinalResponse(commitFinalResponse, pluginSourceGateway); + + const retrievedSessionData = pluginSourceGateway.sessions.get(sessionID); + + if (retrievedSessionData == undefined) throw new Error("Test Failed."); + + expect(retrievedSessionData.id).toBe(sessionID); + expect(retrievedSessionData.step).toBe(step + 1); + expect(retrievedSessionData.commitAcknowledgementClaim).toBe( + COMMIT_ACK_CLAIM, + ); + expect(retrievedSessionData.commitFinalRequestMessageHash).toBe( + COMMIT_FINAL_REQUEST_MESSAGE_HASH, + ); + expect(retrievedSessionData.commitFinalResponseMessageHash).toBe(messageHash); +}); + +test("commit final response invalid because of wrong previous message hash", async () => { + const commitFinalResponse: CommitFinalV1Response = { + messageType: OdapMessageType.CommitFinalResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + commitAcknowledgementClaim: COMMIT_ACK_CLAIM, + hashCommitFinal: "wrongMessageHash", + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + commitFinalResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign(JSON.stringify(commitFinalResponse)), + ); + + await checkValidCommitFinalResponse(commitFinalResponse, pluginSourceGateway) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch( + "previous message hash does not match the one that was sent", + ), + ); +}); + +test("commit final response invalid because of wrong signature", async () => { + const commitFinalResponse: CommitFinalV1Response = { + messageType: OdapMessageType.CommitFinalResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + commitAcknowledgementClaim: COMMIT_ACK_CLAIM, + hashCommitFinal: COMMIT_FINAL_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + commitFinalResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign("somethingWrong"), + ); + + await checkValidCommitFinalResponse(commitFinalResponse, pluginSourceGateway) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch("message signature verification failed"), + ); +}); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-preparation.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-preparation.test.ts new file mode 100644 index 0000000000..c73ce6c471 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/commit-preparation.test.ts @@ -0,0 +1,152 @@ +import { randomInt } from "crypto"; +import { SHA256 } from "crypto-js"; +import { v4 as uuidV4 } from "uuid"; +import { checkValidCommitPreparationResponse } from "../../../../main/typescript/gateway/client/commit-preparation"; +import { + OdapMessageType, + PluginOdapGateway, +} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +import { + CommitPreparationV1Response, + SessionData, +} from "../../../../main/typescript/public-api"; + +const COMMIT_PREPARATION_REQUEST_MESSAGE_HASH = + "dummyCommitPreparationRequestMessageHash"; + +let sourceGatewayConstructor; +let recipientGatewayConstructor; +let pluginSourceGateway: PluginOdapGateway; +let pluginRecipientGateway: PluginOdapGateway; +let sequenceNumber: number; +let sessionID: string; +let step: number; + +beforeEach(() => { + sourceGatewayConstructor = { + name: "plugin-odap-gateway#sourceGateway", + dltIDs: ["DLT2"], + instanceId: uuidV4(), + }; + recipientGatewayConstructor = { + name: "plugin-odap-gateway#recipientGateway", + dltIDs: ["DLT1"], + instanceId: uuidV4(), + }; + + pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); + pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); + + sequenceNumber = randomInt(100); + sessionID = uuidV4(); + step = 1; + + const sessionData: SessionData = { + id: sessionID, + step: step, + sourceGatewayPubkey: pluginSourceGateway.pubKey, + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + commitPrepareRequestMessageHash: COMMIT_PREPARATION_REQUEST_MESSAGE_HASH, + lastSequenceNumber: sequenceNumber, + }; + + pluginSourceGateway.sessions.set(sessionID, sessionData); +}); + +test("valid commit preparation response", async () => { + const commitPreparationResponse: CommitPreparationV1Response = { + messageType: OdapMessageType.CommitFinalResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashCommitPrep: COMMIT_PREPARATION_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + commitPreparationResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign( + JSON.stringify(commitPreparationResponse), + ), + ); + + const messageHash = SHA256( + JSON.stringify(commitPreparationResponse), + ).toString(); + + await checkValidCommitPreparationResponse( + commitPreparationResponse, + pluginSourceGateway, + ); + + const retrievedSessionData = pluginSourceGateway.sessions.get(sessionID); + + if (retrievedSessionData == undefined) throw new Error("Test Failed."); + + expect(retrievedSessionData.id).toBe(sessionID); + expect(retrievedSessionData.step).toBe(step + 1); + expect(retrievedSessionData.commitPrepareResponseMessageHash).toBe( + messageHash, + ); + expect( + retrievedSessionData.serverSignatureCommitPreparationResponseMessage, + ).toBe(commitPreparationResponse.serverSignature); +}); + +test("commit preparation response invalid because of wrong previous message hash", async () => { + const commitPreparationResponse: CommitPreparationV1Response = { + messageType: OdapMessageType.CommitFinalResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashCommitPrep: "wrongMessageHash", + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + commitPreparationResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign( + JSON.stringify(commitPreparationResponse), + ), + ); + + await checkValidCommitPreparationResponse( + commitPreparationResponse, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch( + "previous message hash does not match the one that was sent", + ), + ); +}); + +test("commit preparation response invalid because of wrong signature", async () => { + const commitPreparationResponse: CommitPreparationV1Response = { + messageType: OdapMessageType.CommitFinalResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashCommitPrep: COMMIT_PREPARATION_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + commitPreparationResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign("somethingWrong"), + ); + + await checkValidCommitPreparationResponse( + commitPreparationResponse, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch("message signature verification failed"), + ); +}); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/lock-evidence.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/lock-evidence.test.ts new file mode 100644 index 0000000000..5873e3b0e7 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/lock-evidence.test.ts @@ -0,0 +1,146 @@ +import { randomInt } from "crypto"; +import { SHA256 } from "crypto-js"; +import { v4 as uuidV4 } from "uuid"; +import { checkValidLockEvidenceResponse } from "../../../../main/typescript/gateway/client/lock-evidence"; +import { + OdapMessageType, + PluginOdapGateway, +} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +import { + LockEvidenceV1Response, + SessionData, +} from "../../../../main/typescript/public-api"; + +const LOCK_EVIDENCE_REQUEST_MESSAGE_HASH = + "dummyLockEvidenceRequestMessageHash"; + +let sourceGatewayConstructor; +let recipientGatewayConstructor; +let pluginSourceGateway: PluginOdapGateway; +let pluginRecipientGateway: PluginOdapGateway; +let sequenceNumber: number; +let sessionID: string; +let step: number; + +beforeEach(() => { + sourceGatewayConstructor = { + name: "plugin-odap-gateway#sourceGateway", + dltIDs: ["DLT2"], + instanceId: uuidV4(), + }; + recipientGatewayConstructor = { + name: "plugin-odap-gateway#recipientGateway", + dltIDs: ["DLT1"], + instanceId: uuidV4(), + }; + + pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); + pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); + + sequenceNumber = randomInt(100); + sessionID = uuidV4(); + step = 1; + + const sessionData: SessionData = { + id: sessionID, + step: step, + sourceGatewayPubkey: pluginSourceGateway.pubKey, + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + lockEvidenceRequestMessageHash: LOCK_EVIDENCE_REQUEST_MESSAGE_HASH, + lastSequenceNumber: sequenceNumber, + }; + + pluginSourceGateway.sessions.set(sessionID, sessionData); +}); + +test("valid lock evidence response", async () => { + const lockEvidenceResponse: LockEvidenceV1Response = { + messageType: OdapMessageType.LockEvidenceResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashLockEvidenceRequest: LOCK_EVIDENCE_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + lockEvidenceResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign(JSON.stringify(lockEvidenceResponse)), + ); + + const messageHash = SHA256(JSON.stringify(lockEvidenceResponse)).toString(); + + await checkValidLockEvidenceResponse( + lockEvidenceResponse, + pluginSourceGateway, + ); + + const retrievedSessionData = pluginSourceGateway.sessions.get(sessionID); + + if (retrievedSessionData == undefined) throw new Error("Test Failed."); + + expect(retrievedSessionData.id).toBe(sessionID); + expect(retrievedSessionData.step).toBe(step + 1); + expect(retrievedSessionData.lockEvidenceResponseMessageHash).toBe( + messageHash, + ); + expect(retrievedSessionData.serverSignatureLockEvidenceResponseMessage).toBe( + lockEvidenceResponse.serverSignature, + ); +}); + +test("lock evidence response invalid because of wrong previous message hash", async () => { + const lockEvidenceResponse: LockEvidenceV1Response = { + messageType: OdapMessageType.LockEvidenceResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashLockEvidenceRequest: "wrongMessageHash", + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + lockEvidenceResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign(JSON.stringify(lockEvidenceResponse)), + ); + + await checkValidLockEvidenceResponse( + lockEvidenceResponse, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch( + "previous message hash does not match the one that was sent", + ), + ); +}); + +test("lock evidence response invalid because of wrong signature", async () => { + const lockEvidenceResponse: LockEvidenceV1Response = { + messageType: OdapMessageType.LockEvidenceResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashLockEvidenceRequest: LOCK_EVIDENCE_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + lockEvidenceResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign("somethingWrong"), + ); + + await checkValidLockEvidenceResponse( + lockEvidenceResponse, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch("message signature verification failed"), + ); +}); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-commence.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-commence.test.ts new file mode 100644 index 0000000000..275438c381 --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-commence.test.ts @@ -0,0 +1,147 @@ +import { randomInt } from "crypto"; +import { SHA256 } from "crypto-js"; +import { v4 as uuidV4 } from "uuid"; +import { checkValidTransferCommenceResponse } from "../../../../main/typescript/gateway/client/transfer-commence"; +import { + OdapMessageType, + PluginOdapGateway, +} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +import { + SessionData, + TransferCommenceV1Response, +} from "../../../../main/typescript/public-api"; + +const COMMENCE_REQUEST_MESSAGE_HASH = "dummyCommenceRequestMessageHash"; + +let sourceGatewayConstructor; +let recipientGatewayConstructor; +let pluginSourceGateway: PluginOdapGateway; +let pluginRecipientGateway: PluginOdapGateway; +let sequenceNumber: number; +let sessionID: string; +let step: number; + +beforeEach(() => { + sourceGatewayConstructor = { + name: "plugin-odap-gateway#sourceGateway", + dltIDs: ["DLT2"], + instanceId: uuidV4(), + }; + recipientGatewayConstructor = { + name: "plugin-odap-gateway#recipientGateway", + dltIDs: ["DLT1"], + instanceId: uuidV4(), + }; + + pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); + pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); + + sequenceNumber = randomInt(100); + sessionID = uuidV4(); + step = 1; + + const sessionData: SessionData = { + id: sessionID, + step: step, + sourceGatewayPubkey: pluginSourceGateway.pubKey, + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + transferCommenceMessageRequestHash: COMMENCE_REQUEST_MESSAGE_HASH, + lastSequenceNumber: sequenceNumber, + }; + + pluginSourceGateway.sessions.set(sessionID, sessionData); +}); + +test("valid transfer commence response", async () => { + const transferCommenceResponse: TransferCommenceV1Response = { + messageType: OdapMessageType.TransferCommenceResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashCommenceRequest: COMMENCE_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + transferCommenceResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign(JSON.stringify(transferCommenceResponse)), + ); + + const messageHash = SHA256( + JSON.stringify(transferCommenceResponse), + ).toString(); + + await checkValidTransferCommenceResponse( + transferCommenceResponse, + pluginSourceGateway, + ); + + const retrievedSessionData = pluginSourceGateway.sessions.get(sessionID); + + if (retrievedSessionData == undefined) throw new Error("Test Failed."); + + expect(retrievedSessionData.id).toBe(sessionID); + expect(retrievedSessionData.step).toBe(step + 1); + expect(retrievedSessionData.transferCommenceMessageResponseHash).toBe( + messageHash, + ); + expect( + retrievedSessionData.serverSignatureTransferCommenceResponseMessage, + ).toBe(transferCommenceResponse.serverSignature); +}); + +test("transfer commence response invalid because of wrong previous message hash", async () => { + const transferCommenceResponse: TransferCommenceV1Response = { + messageType: OdapMessageType.TransferCommenceResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashCommenceRequest: "wrongMessageHash", + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + transferCommenceResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign(JSON.stringify(transferCommenceResponse)), + ); + + await checkValidTransferCommenceResponse( + transferCommenceResponse, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch( + "previous message hash does not match the one that was sent", + ), + ); +}); + +test("transfer commence response invalid because of wrong signature", async () => { + const transferCommenceResponse: TransferCommenceV1Response = { + messageType: OdapMessageType.TransferCommenceResponse, + sessionID: sessionID, + serverIdentityPubkey: pluginRecipientGateway.pubKey, + clientIdentityPubkey: pluginSourceGateway.pubKey, + hashCommenceRequest: COMMENCE_REQUEST_MESSAGE_HASH, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + transferCommenceResponse.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign("somethingWrong"), + ); + + await checkValidTransferCommenceResponse( + transferCommenceResponse, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch("message signature verification failed"), + ); +}); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-initiation.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-initiation.test.ts new file mode 100644 index 0000000000..59b51b778a --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/client/transfer-initiation.test.ts @@ -0,0 +1,163 @@ +import { randomInt } from "crypto"; +import { SHA256 } from "crypto-js"; +import { v4 as uuidV4 } from "uuid"; +import { checkValidInitializationResponse } from "../../../../main/typescript/gateway/client/transfer-initialization"; +import { + OdapMessageType, + PluginOdapGateway, +} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +import { + TransferInitializationV1Response, + SessionData, +} from "../../../../main/typescript/public-api"; + +const INITIALIZATION_REQUEST_MESSAGE_HASH = + "dummyInitializationRequestMessageHash"; + +let sourceGatewayConstructor; +let recipientGatewayConstructor; +let pluginSourceGateway: PluginOdapGateway; +let pluginRecipientGateway: PluginOdapGateway; +let sequenceNumber: number; +let sessionID: string; +let step: number; + +beforeEach(() => { + sourceGatewayConstructor = { + name: "plugin-odap-gateway#sourceGateway", + dltIDs: ["DLT2"], + instanceId: uuidV4(), + }; + recipientGatewayConstructor = { + name: "plugin-odap-gateway#recipientGateway", + dltIDs: ["DLT1"], + instanceId: uuidV4(), + }; + + pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); + pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); + + sequenceNumber = randomInt(100); + sessionID = uuidV4(); + step = 1; + + const sessionData: SessionData = { + id: sessionID, + step: step, + sourceGatewayPubkey: pluginSourceGateway.pubKey, + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + initializationRequestMessageHash: INITIALIZATION_REQUEST_MESSAGE_HASH, + lastSequenceNumber: sequenceNumber, + }; + + pluginSourceGateway.sessions.set(sessionID, sessionData); +}); + +test("valid transfer initiation response", async () => { + const initializationResponseMessage: TransferInitializationV1Response = { + messageType: OdapMessageType.InitializationResponse, + sessionID: sessionID, + initialRequestMessageHash: INITIALIZATION_REQUEST_MESSAGE_HASH, + timeStamp: Date.now().toString(), + processedTimeStamp: Date.now().toString(), + serverIdentityPubkey: pluginRecipientGateway.pubKey, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + initializationResponseMessage.serverSignature = pluginRecipientGateway.bufArray2HexStr( + await pluginRecipientGateway.sign( + JSON.stringify(initializationResponseMessage), + ), + ); + + const messageHash = SHA256( + JSON.stringify(initializationResponseMessage), + ).toString(); + + await checkValidInitializationResponse( + initializationResponseMessage, + pluginSourceGateway, + ); + + const retrievedSessionData = pluginSourceGateway.sessions.get(sessionID); + + if (retrievedSessionData == undefined) throw new Error("Test Failed."); + + expect(retrievedSessionData.id).toBe(sessionID); + expect(retrievedSessionData.step).toBe(step + 1); + expect(retrievedSessionData.recipientGatewayPubkey).toBe( + pluginRecipientGateway.pubKey, + ); + expect(retrievedSessionData.initializationRequestMessageHash).toBe( + INITIALIZATION_REQUEST_MESSAGE_HASH, + ); + expect(retrievedSessionData.initializationResponseMessageHash).toBe( + messageHash, + ); + expect( + retrievedSessionData.serverSignatureInitializationResponseMessage, + ).not.toBe(""); +}); + +test("transfer initiation response invalid because of wrong previous message hash", async () => { + const initializationResponseMessage: TransferInitializationV1Response = { + messageType: OdapMessageType.InitializationResponse, + sessionID: sessionID, + initialRequestMessageHash: "wrongMessageHash", + timeStamp: Date.now().toString(), + processedTimeStamp: Date.now().toString(), + serverIdentityPubkey: pluginRecipientGateway.pubKey, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + initializationResponseMessage.serverSignature = pluginSourceGateway.bufArray2HexStr( + await pluginSourceGateway.sign( + JSON.stringify(initializationResponseMessage), + ), + ); + + await checkValidInitializationResponse( + initializationResponseMessage, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch( + "previous message hash does not match the one that was sent", + ), + ); +}); + +test("transfer initiation response invalid because it does not match transfer initialization request sessionID", async () => { + const initializationResponseMessage: TransferInitializationV1Response = { + messageType: OdapMessageType.InitializationResponse, + sessionID: uuidV4(), + initialRequestMessageHash: "wrongMessageHash", + timeStamp: Date.now().toString(), + processedTimeStamp: Date.now().toString(), + serverIdentityPubkey: pluginRecipientGateway.pubKey, + serverSignature: "", + sequenceNumber: sequenceNumber, + }; + + initializationResponseMessage.serverSignature = pluginSourceGateway.bufArray2HexStr( + await pluginSourceGateway.sign( + JSON.stringify(initializationResponseMessage), + ), + ); + + await checkValidInitializationResponse( + initializationResponseMessage, + pluginSourceGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch("session data is undefined"), + ); +}); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/commit-final.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/commit-final.test.ts similarity index 73% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/commit-final.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/commit-final.test.ts index 52369fcf23..36ef97e1bc 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/commit-final.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/commit-final.test.ts @@ -10,6 +10,7 @@ import { import { v4 as uuidV4 } from "uuid"; import { SHA256 } from "crypto-js"; import { randomInt } from "crypto"; +import { checkValidCommitFinalRequest } from "../../../../main/typescript/gateway/server/commit-final"; let sourceGatewayConstructor: IPluginOdapGatewayConstructorOptions; let recipientGatewayConstructor: IPluginOdapGatewayConstructorOptions; @@ -39,21 +40,23 @@ beforeEach(() => { "commitPreparationResponseMessageData", ).toString(); + sessionID = uuidV4(); + sequenceNumber = randomInt(100); + sessionData = { + id: sessionID, sourceGatewayPubkey: pluginSourceGateway.pubKey, recipientGatewayPubkey: pluginRecipientGateway.pubKey, commitPrepareResponseMessageHash: dummyCommitPreparationResponseMessageHash, step: 2, + lastSequenceNumber: sequenceNumber, }; - sessionID = uuidV4(); - sequenceNumber = randomInt(100); - pluginSourceGateway.sessions.set(sessionID, sessionData); pluginRecipientGateway.sessions.set(sessionID, sessionData); }); -test("successful commit final flow", async () => { +test("valid commit final request", async () => { const commitFinalRequestMessage: CommitFinalV1Request = { sessionID: sessionID, messageType: OdapMessageType.CommitFinalRequest, @@ -62,7 +65,7 @@ test("successful commit final flow", async () => { clientSignature: "", hashCommitPrepareAck: dummyCommitPreparationResponseMessageHash, commitFinalClaim: "dummyFinalClaim", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitFinalRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( @@ -73,58 +76,25 @@ test("successful commit final flow", async () => { JSON.stringify(commitFinalRequestMessage), ).toString(); - const response = await pluginRecipientGateway.commitFinalReceived( + await checkValidCommitFinalRequest( commitFinalRequestMessage, + pluginRecipientGateway, ); - const responseHash = SHA256(JSON.stringify(response)).toString(); - const sessionInfo = pluginRecipientGateway.sessions.get(sessionID); if (sessionInfo == null) throw new Error("Test Failed"); expect(sessionInfo.commitFinalClaim).toBe("dummyFinalClaim"); - expect(sessionInfo.commitAcknowledgementClaim).toBe( - response.commitAcknowledgementClaim, - ); expect(sessionInfo.commitFinalRequestMessageHash).toBe(requestHash); - expect(sessionInfo.commitFinalResponseMessageHash).toBe(responseHash); expect(sessionInfo.clientSignatureCommitFinalRequestMessage).toBe( commitFinalRequestMessage.clientSignature, ); - expect(sessionInfo.serverSignatureCommitFinalResponseMessage).toBe( - response.serverSignature, - ); - - expect(response.messageType).toBe(OdapMessageType.CommitFinalResponse); - - expect(response.clientIdentityPubkey).toBe(pluginSourceGateway.pubKey); - expect(response.serverIdentityPubkey).toBe(pluginRecipientGateway.pubKey); - expect(response.hashCommitFinal).toBe(requestHash); - expect(response.sequenceNumber).toBe(sequenceNumber); - - const sourceClientSignature = new Uint8Array( - Buffer.from(response.serverSignature, "hex"), - ); - - const sourceClientPubkey = new Uint8Array( - Buffer.from(response.serverIdentityPubkey, "hex"), - ); - - response.serverSignature = ""; - - expect( - pluginSourceGateway.verifySignature( - JSON.stringify(response), - sourceClientSignature, - sourceClientPubkey, - ), - ).toBe(true); }); -test("commit final flow with wrong sessionId", async () => { +test("commit final request with wrong sessionId", async () => { const wrongSessionId = uuidV4(); const commitFinalRequestMessage: CommitFinalV1Request = { @@ -135,15 +105,17 @@ test("commit final flow with wrong sessionId", async () => { clientSignature: "", hashCommitPrepareAck: dummyCommitPreparationResponseMessageHash, commitFinalClaim: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitFinalRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(commitFinalRequestMessage)), ); - await pluginRecipientGateway - .commitFinalReceived(commitFinalRequestMessage) + await checkValidCommitFinalRequest( + commitFinalRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -154,7 +126,7 @@ test("commit final flow with wrong sessionId", async () => { ); }); -test("commit final flow with wrong message type", async () => { +test("commit final request with wrong message type", async () => { const commitFinalRequestMessage: CommitFinalV1Request = { sessionID: sessionID, messageType: OdapMessageType.CommitFinalResponse, @@ -163,15 +135,17 @@ test("commit final flow with wrong message type", async () => { clientSignature: "", hashCommitPrepareAck: dummyCommitPreparationResponseMessageHash, commitFinalClaim: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitFinalRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(commitFinalRequestMessage)), ); - await pluginRecipientGateway - .commitFinalReceived(commitFinalRequestMessage) + await checkValidCommitFinalRequest( + commitFinalRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -180,7 +154,7 @@ test("commit final flow with wrong message type", async () => { ); }); -test("commit final flow with wrong previous message hash", async () => { +test("commit final request with wrong previous message hash", async () => { const commitFinalRequestMessage: CommitFinalV1Request = { sessionID: sessionID, messageType: OdapMessageType.CommitFinalRequest, @@ -189,15 +163,17 @@ test("commit final flow with wrong previous message hash", async () => { clientSignature: "", hashCommitPrepareAck: "dummyCommitPreparationResponseMessageHash", commitFinalClaim: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitFinalRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(commitFinalRequestMessage)), ); - await pluginRecipientGateway - .commitFinalReceived(commitFinalRequestMessage) + await checkValidCommitFinalRequest( + commitFinalRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/commit-preparation.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/commit-preparation.test.ts similarity index 73% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/commit-preparation.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/commit-preparation.test.ts index e0a43b0696..07fae0aee8 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/commit-preparation.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/commit-preparation.test.ts @@ -10,6 +10,7 @@ import { } from "../../../../main/typescript/generated/openapi/typescript-axios/api"; import { v4 as uuidV4 } from "uuid"; import { SHA256 } from "crypto-js"; +import { checkValidCommitPreparationRequest } from "../../../../main/typescript/gateway/server/commit-preparation"; let sourceGatewayConstructor: IPluginOdapGatewayConstructorOptions; let recipientGatewayConstructor: IPluginOdapGatewayConstructorOptions; @@ -39,21 +40,23 @@ beforeEach(() => { "lockEvidenceResponseMessageData", ).toString(); + sessionID = uuidV4(); + sequenceNumber = randomInt(100); + sessionData = { + id: sessionID, sourceGatewayPubkey: pluginSourceGateway.pubKey, recipientGatewayPubkey: pluginRecipientGateway.pubKey, lockEvidenceResponseMessageHash: dummyLockEvidenceResponseMessageHash, step: 2, + lastSequenceNumber: sequenceNumber, }; - sessionID = uuidV4(); - sequenceNumber = randomInt(100); - pluginSourceGateway.sessions.set(sessionID, sessionData); pluginRecipientGateway.sessions.set(sessionID, sessionData); }); -test("successful commit prepare flow", async () => { +test("valid commit prepare request", async () => { const commitPrepareRequestMessage: CommitPreparationV1Request = { sessionID: sessionID, messageType: OdapMessageType.CommitPreparationRequest, @@ -61,7 +64,7 @@ test("successful commit prepare flow", async () => { serverIdentityPubkey: pluginRecipientGateway.pubKey, clientSignature: "", hashLockEvidenceAck: dummyLockEvidenceResponseMessageHash, - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitPrepareRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( @@ -72,53 +75,23 @@ test("successful commit prepare flow", async () => { JSON.stringify(commitPrepareRequestMessage), ).toString(); - const response = await pluginRecipientGateway.commitPrepareReceived( + await checkValidCommitPreparationRequest( commitPrepareRequestMessage, + pluginRecipientGateway, ); - const responseHash = SHA256(JSON.stringify(response)).toString(); - const sessionInfo = pluginRecipientGateway.sessions.get(sessionID); if (sessionInfo == null) throw new Error("Test Failed"); expect(sessionInfo.commitPrepareRequestMessageHash).toBe(requestHash); - expect(sessionInfo.commitPrepareResponseMessageHash).toBe(responseHash); expect(sessionInfo.clientSignatureCommitPreparationRequestMessage).toBe( commitPrepareRequestMessage.clientSignature, ); - expect(sessionInfo.serverSignatureCommitPreparationResponseMessage).toBe( - response.serverSignature, - ); - - expect(response.messageType).toBe(OdapMessageType.CommitPreparationResponse); - - expect(response.clientIdentityPubkey).toBe(pluginSourceGateway.pubKey); - expect(response.serverIdentityPubkey).toBe(pluginRecipientGateway.pubKey); - expect(response.hashCommitPrep).toBe(requestHash); - expect(response.sequenceNumber).toBe(sequenceNumber); - - const sourceClientSignature = new Uint8Array( - Buffer.from(response.serverSignature, "hex"), - ); - - const sourceClientPubkey = new Uint8Array( - Buffer.from(response.serverIdentityPubkey, "hex"), - ); - - response.serverSignature = ""; - - expect( - pluginSourceGateway.verifySignature( - JSON.stringify(response), - sourceClientSignature, - sourceClientPubkey, - ), - ).toBe(true); }); -test("commit prepare flow with wrong sessionId", async () => { +test("commit prepare request with wrong sessionId", async () => { const wrongSessionId = uuidV4(); const commitPrepareRequestMessage: CommitPreparationV1Request = { @@ -128,15 +101,17 @@ test("commit prepare flow with wrong sessionId", async () => { serverIdentityPubkey: pluginRecipientGateway.pubKey, clientSignature: "", hashLockEvidenceAck: dummyLockEvidenceResponseMessageHash, - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitPrepareRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(commitPrepareRequestMessage)), ); - await pluginRecipientGateway - .commitPrepareReceived(commitPrepareRequestMessage) + await checkValidCommitPreparationRequest( + commitPrepareRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -147,7 +122,7 @@ test("commit prepare flow with wrong sessionId", async () => { ); }); -test("commit prepare flow with wrong message type", async () => { +test("commit prepare request with wrong message type", async () => { const commitPrepareRequestMessage: CommitPreparationV1Request = { sessionID: sessionID, messageType: OdapMessageType.CommitFinalResponse, @@ -155,15 +130,17 @@ test("commit prepare flow with wrong message type", async () => { serverIdentityPubkey: pluginRecipientGateway.pubKey, clientSignature: "", hashLockEvidenceAck: dummyLockEvidenceResponseMessageHash, - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitPrepareRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(commitPrepareRequestMessage)), ); - await pluginRecipientGateway - .commitPrepareReceived(commitPrepareRequestMessage) + await checkValidCommitPreparationRequest( + commitPrepareRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -174,7 +151,7 @@ test("commit prepare flow with wrong message type", async () => { ); }); -test("commit prepare flow with wrong previous message hash", async () => { +test("commit prepare request with wrong previous message hash", async () => { const commitPrepareRequestMessage: CommitPreparationV1Request = { sessionID: sessionID, messageType: OdapMessageType.CommitPreparationRequest, @@ -182,15 +159,17 @@ test("commit prepare flow with wrong previous message hash", async () => { serverIdentityPubkey: pluginRecipientGateway.pubKey, clientSignature: "", hashLockEvidenceAck: "wrongLockEvidenceResponseMessageHash", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; commitPrepareRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(commitPrepareRequestMessage)), ); - await pluginRecipientGateway - .commitPrepareReceived(commitPrepareRequestMessage) + await checkValidCommitPreparationRequest( + commitPrepareRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/lock-evidence.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/lock-evidence.test.ts similarity index 77% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/lock-evidence.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/lock-evidence.test.ts index f1af8d6114..44d8743e46 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/lock-evidence.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/lock-evidence.test.ts @@ -10,6 +10,7 @@ import { } from "../../../../main/typescript/generated/openapi/typescript-axios/api"; import { v4 as uuidV4 } from "uuid"; import { SHA256 } from "crypto-js"; +import { checkValidLockEvidenceRequest } from "../../../../main/typescript/gateway/server/lock-evidence"; let sourceGatewayConstructor: IPluginOdapGatewayConstructorOptions; let recipientGatewayConstructor: IPluginOdapGatewayConstructorOptions; @@ -40,23 +41,24 @@ beforeEach(() => { "transferCommenceResponseMessageData", ).toString(); + sessionID = uuidV4(); + sequenceNumber = randomInt(100); + sessionData = { sourceGatewayPubkey: pluginSourceGateway.pubKey, recipientGatewayPubkey: pluginRecipientGateway.pubKey, transferCommenceMessageResponseHash: dummyTransferCommenceResponseMessageHash, step: 2, + lastSequenceNumber: sequenceNumber, }; lockExpiryDate = new Date().setDate(new Date().getDate() + 1).toString(); - sessionID = uuidV4(); - sequenceNumber = randomInt(100); - pluginSourceGateway.sessions.set(sessionID, sessionData); pluginRecipientGateway.sessions.set(sessionID, sessionData); }); -test("successful lock evidence flow", async () => { +test("valid lock evidence request", async () => { const lockEvidenceRequestMessage: LockEvidenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.LockEvidenceRequest, @@ -66,7 +68,7 @@ test("successful lock evidence flow", async () => { hashCommenceAckRequest: dummyTransferCommenceResponseMessageHash, lockEvidenceClaim: lockExpiryDate.toString(), lockEvidenceExpiration: new Date(2060, 11, 24).toString(), - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; lockEvidenceRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( @@ -77,53 +79,24 @@ test("successful lock evidence flow", async () => { JSON.stringify(lockEvidenceRequestMessage), ).toString(); - const response = await pluginRecipientGateway.lockEvidenceReceived( + await checkValidLockEvidenceRequest( lockEvidenceRequestMessage, + pluginRecipientGateway, ); - const responseHash = SHA256(JSON.stringify(response)).toString(); - const sessionInfo = pluginRecipientGateway.sessions.get(sessionID); if (sessionInfo == null) throw new Error("Test Failed"); expect(sessionInfo.lockEvidenceRequestMessageHash).toBe(requestHash); - expect(sessionInfo.lockEvidenceResponseMessageHash).toBe(responseHash); + expect(sessionInfo.lockEvidenceResponseMessageHash).not.toBe(""); expect(sessionInfo.clientSignatureLockEvidenceRequestMessage).toBe( lockEvidenceRequestMessage.clientSignature, ); - expect(sessionInfo.serverSignatureLockEvidenceResponseMessage).toBe( - response.serverSignature, - ); - - expect(response.messageType).toBe(OdapMessageType.LockEvidenceResponse); - - expect(response.clientIdentityPubkey).toBe(pluginSourceGateway.pubKey); - expect(response.serverIdentityPubkey).toBe(pluginRecipientGateway.pubKey); - expect(response.hashLockEvidenceRequest).toBe(requestHash); - expect(response.sequenceNumber).toBe(sequenceNumber); - - const sourceClientSignature = new Uint8Array( - Buffer.from(response.serverSignature, "hex"), - ); - - const sourceClientPubkey = new Uint8Array( - Buffer.from(response.serverIdentityPubkey, "hex"), - ); - - response.serverSignature = ""; - - expect( - pluginSourceGateway.verifySignature( - JSON.stringify(response), - sourceClientSignature, - sourceClientPubkey, - ), - ).toBe(true); }); -test("lock evidence flow with wrong sessionId", async () => { +test("lock evidence request with wrong sessionId", async () => { const wrongSessionId = uuidV4(); const lockEvidenceRequestMessage: LockEvidenceV1Request = { @@ -135,15 +108,17 @@ test("lock evidence flow with wrong sessionId", async () => { hashCommenceAckRequest: dummyTransferCommenceResponseMessageHash, lockEvidenceClaim: lockExpiryDate.toString(), lockEvidenceExpiration: new Date(2060, 11, 24).toString(), - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; lockEvidenceRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(lockEvidenceRequestMessage)), ); - await pluginRecipientGateway - .lockEvidenceReceived(lockEvidenceRequestMessage) + await checkValidLockEvidenceRequest( + lockEvidenceRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -154,7 +129,7 @@ test("lock evidence flow with wrong sessionId", async () => { ); }); -test("lock evidence flow with wrong message type", async () => { +test("lock evidence request with wrong message type", async () => { const lockEvidenceRequestMessage: LockEvidenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.LockEvidenceResponse, @@ -164,15 +139,17 @@ test("lock evidence flow with wrong message type", async () => { hashCommenceAckRequest: dummyTransferCommenceResponseMessageHash, lockEvidenceClaim: lockExpiryDate.toString(), lockEvidenceExpiration: new Date(2060, 11, 24).toString(), - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; lockEvidenceRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(lockEvidenceRequestMessage)), ); - await pluginRecipientGateway - .lockEvidenceReceived(lockEvidenceRequestMessage) + await checkValidLockEvidenceRequest( + lockEvidenceRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -181,7 +158,7 @@ test("lock evidence flow with wrong message type", async () => { ); }); -test("lock evidence flow with wrong previous message hash", async () => { +test("lock evidence request with wrong previous message hash", async () => { const lockEvidenceRequestMessage: LockEvidenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.LockEvidenceRequest, @@ -191,15 +168,17 @@ test("lock evidence flow with wrong previous message hash", async () => { hashCommenceAckRequest: "wrongPrevMessageHash", lockEvidenceClaim: lockExpiryDate.toString(), lockEvidenceExpiration: new Date(2060, 11, 24).toString(), - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; lockEvidenceRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(lockEvidenceRequestMessage)), ); - await pluginRecipientGateway - .lockEvidenceReceived(lockEvidenceRequestMessage) + await checkValidLockEvidenceRequest( + lockEvidenceRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -218,15 +197,17 @@ test("transfer commence flow with invalid claim", async () => { hashCommenceAckRequest: dummyTransferCommenceResponseMessageHash, lockEvidenceClaim: "", lockEvidenceExpiration: new Date(2020, 11, 24).toString(), - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; lockEvidenceRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(lockEvidenceRequestMessage)), ); - await pluginRecipientGateway - .lockEvidenceReceived(lockEvidenceRequestMessage) + await checkValidLockEvidenceRequest( + lockEvidenceRequestMessage, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-commence.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-commence.test.ts similarity index 73% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-commence.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-commence.test.ts index b465dfa106..8e0c453fb6 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-commence.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-commence.test.ts @@ -11,12 +11,13 @@ import { } from "../../../../main/typescript/generated/openapi/typescript-axios/api"; import { v4 as uuidV4 } from "uuid"; import { SHA256 } from "crypto-js"; +import { checkValidtransferCommenceRequest } from "../../../../main/typescript/gateway/server/transfer-commence"; let sourceGatewayConstructor: IPluginOdapGatewayConstructorOptions; let recipientGatewayConstructor: IPluginOdapGatewayConstructorOptions; let pluginSourceGateway: PluginOdapGateway; let pluginRecipientGateway: PluginOdapGateway; -let dummyInitializationRequestMessageHash: string; +let dummyInitializationResponseMessageHash: string; let expiryDate: string; let assetProfile: AssetProfile; let assetProfileHash: string; @@ -39,31 +40,34 @@ beforeEach(() => { pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); - dummyInitializationRequestMessageHash = SHA256( - "initializationRequestMessageData", + dummyInitializationResponseMessageHash = SHA256( + "initializationResponseMessageData", ).toString(); expiryDate = new Date(2060, 11, 24).toString(); assetProfile = { expirationDate: expiryDate }; assetProfileHash = SHA256(JSON.stringify(assetProfile)).toString(); + + sessionID = uuidV4(); + sequenceNumber = randomInt(100); + sessionData = { - initializationRequestMessageHash: dummyInitializationRequestMessageHash, + id: sessionID, + initializationResponseMessageHash: dummyInitializationResponseMessageHash, sourceGatewayPubkey: pluginSourceGateway.pubKey, recipientGatewayPubkey: pluginRecipientGateway.pubKey, sourceGatewayDltSystem: "DLT2", recipientGatewayDltSystem: "DLT1", assetProfile: assetProfile, step: 1, + lastSequenceNumber: sequenceNumber, }; - sessionID = uuidV4(); - sequenceNumber = randomInt(100); - pluginSourceGateway.sessions.set(sessionID, sessionData); pluginRecipientGateway.sessions.set(sessionID, sessionData); }); -test("successful transfer commence flow", async () => { +test("valid transfer commence request", async () => { const transferCommenceRequest: TransferCommenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.TransferCommenceRequest, @@ -71,12 +75,12 @@ test("successful transfer commence flow", async () => { beneficiaryPubkey: "beneficiaryDummyPubKey", clientIdentityPubkey: pluginSourceGateway.pubKey, serverIdentityPubkey: pluginRecipientGateway.pubKey, - hashPrevMessage: dummyInitializationRequestMessageHash, + hashPrevMessage: dummyInitializationResponseMessageHash, hashAssetProfile: assetProfileHash, senderDltSystem: "dummy", recipientDltSystem: "dummy", clientSignature: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCommenceRequest.clientSignature = pluginSourceGateway.bufArray2HexStr( @@ -87,55 +91,27 @@ test("successful transfer commence flow", async () => { JSON.stringify(transferCommenceRequest), ).toString(); - const response = await pluginRecipientGateway.transferCommenceReceived( + await checkValidtransferCommenceRequest( transferCommenceRequest, + pluginRecipientGateway, ); - const responseHash = SHA256(JSON.stringify(response)).toString(); - const sessionInfo = pluginRecipientGateway.sessions.get(sessionID); if (sessionInfo == null) throw new Error("Test Failed"); expect(sessionInfo.transferCommenceMessageRequestHash).toBe(requestHash); - expect(sessionInfo.transferCommenceMessageResponseHash).toBe(responseHash); - expect(sessionInfo.clientSignatureTransferCommenceRequestMessage).toBe( transferCommenceRequest.clientSignature, ); - expect(sessionInfo.serverSignatureTransferCommenceResponseMessage).toBe( - response.serverSignature, + expect(sessionInfo.serverSignatureTransferCommenceResponseMessage).not.toBe( + "", ); - expect(sessionInfo.originatorPubkey).toBe("originatorDummyPubKey"); expect(sessionInfo.beneficiaryPubkey).toBe("beneficiaryDummyPubKey"); - - expect(response.messageType).toBe(OdapMessageType.TransferCommenceResponse); - expect(response.clientIdentityPubkey).toBe(pluginSourceGateway.pubKey); - expect(response.serverIdentityPubkey).toBe(pluginRecipientGateway.pubKey); - expect(response.hashCommenceRequest).toBe(requestHash); - expect(response.sequenceNumber).toBe(sequenceNumber); - - const sourceClientSignature = new Uint8Array( - Buffer.from(response.serverSignature, "hex"), - ); - - const sourceClientPubkey = new Uint8Array( - Buffer.from(response.serverIdentityPubkey, "hex"), - ); - - response.serverSignature = ""; - - expect( - pluginSourceGateway.verifySignature( - JSON.stringify(response), - sourceClientSignature, - sourceClientPubkey, - ), - ).toBe(true); }); -test("transfer commence flow with wrong sessionId", async () => { +test("transfer commence request with wrong sessionId", async () => { const wrongSessionId = uuidV4(); const transferCommenceRequest: TransferCommenceV1Request = { sessionID: wrongSessionId, @@ -144,20 +120,22 @@ test("transfer commence flow with wrong sessionId", async () => { beneficiaryPubkey: "dummyPubKey", clientIdentityPubkey: pluginSourceGateway.pubKey, serverIdentityPubkey: pluginRecipientGateway.pubKey, - hashPrevMessage: dummyInitializationRequestMessageHash, + hashPrevMessage: dummyInitializationResponseMessageHash, hashAssetProfile: assetProfileHash, senderDltSystem: "dummy", recipientDltSystem: "dummy", clientSignature: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCommenceRequest.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(transferCommenceRequest)), ); - await pluginRecipientGateway - .transferCommenceReceived(transferCommenceRequest) + await checkValidtransferCommenceRequest( + transferCommenceRequest, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -168,7 +146,7 @@ test("transfer commence flow with wrong sessionId", async () => { ); }); -test("transfer commence flow with wrong message type", async () => { +test("transfer commence request with wrong message type", async () => { const transferCommenceRequest: TransferCommenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.TransferCommenceResponse, @@ -176,20 +154,22 @@ test("transfer commence flow with wrong message type", async () => { beneficiaryPubkey: "dummyPubKey", clientIdentityPubkey: pluginSourceGateway.pubKey, serverIdentityPubkey: pluginRecipientGateway.pubKey, - hashPrevMessage: dummyInitializationRequestMessageHash, + hashPrevMessage: dummyInitializationResponseMessageHash, hashAssetProfile: assetProfileHash, senderDltSystem: "dummy", recipientDltSystem: "dummy", clientSignature: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCommenceRequest.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(transferCommenceRequest)), ); - await pluginRecipientGateway - .transferCommenceReceived(transferCommenceRequest) + await checkValidtransferCommenceRequest( + transferCommenceRequest, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -200,7 +180,7 @@ test("transfer commence flow with wrong message type", async () => { ); }); -test("transfer commence flow with wrong signature", async () => { +test("transfer commence request with wrong signature", async () => { const transferCommenceRequest: TransferCommenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.TransferCommenceRequest, @@ -208,20 +188,22 @@ test("transfer commence flow with wrong signature", async () => { beneficiaryPubkey: "dummyPubKey", clientIdentityPubkey: pluginSourceGateway.pubKey, serverIdentityPubkey: pluginRecipientGateway.pubKey, - hashPrevMessage: dummyInitializationRequestMessageHash, + hashPrevMessage: dummyInitializationResponseMessageHash, hashAssetProfile: assetProfileHash, senderDltSystem: "dummy", recipientDltSystem: "dummy", clientSignature: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCommenceRequest.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify("wrongData")), ); - await pluginRecipientGateway - .transferCommenceReceived(transferCommenceRequest) + await checkValidtransferCommenceRequest( + transferCommenceRequest, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) @@ -232,7 +214,7 @@ test("transfer commence flow with wrong signature", async () => { ); }); -test("transfer commence flow with wrong previous message hash", async () => { +test("transfer commence request with wrong previous message hash", async () => { const transferCommenceRequest: TransferCommenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.TransferCommenceRequest, @@ -245,24 +227,28 @@ test("transfer commence flow with wrong previous message hash", async () => { senderDltSystem: "dummy", recipientDltSystem: "dummy", clientSignature: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCommenceRequest.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(transferCommenceRequest)), ); - await pluginRecipientGateway - .transferCommenceReceived(transferCommenceRequest) + await checkValidtransferCommenceRequest( + transferCommenceRequest, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) .catch((ex: Error) => - expect(ex.message).toMatch("previous message hash not match"), + expect(ex.message).toMatch( + "previous message hash does not match the one that was sent", + ), ); }); -test("transfer commence flow with wrong asset profile hash", async () => { +test("transfer commence request with wrong asset profile hash", async () => { const transferCommenceRequest: TransferCommenceV1Request = { sessionID: sessionID, messageType: OdapMessageType.TransferCommenceRequest, @@ -270,20 +256,22 @@ test("transfer commence flow with wrong asset profile hash", async () => { beneficiaryPubkey: "dummyPubKey", clientIdentityPubkey: pluginSourceGateway.pubKey, serverIdentityPubkey: pluginRecipientGateway.pubKey, - hashPrevMessage: dummyInitializationRequestMessageHash, + hashPrevMessage: dummyInitializationResponseMessageHash, hashAssetProfile: "wrongAssetProfileHash", senderDltSystem: "dummy", recipientDltSystem: "dummy", clientSignature: "", - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCommenceRequest.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(transferCommenceRequest)), ); - await pluginRecipientGateway - .transferCommenceReceived(transferCommenceRequest) + await checkValidtransferCommenceRequest( + transferCommenceRequest, + pluginRecipientGateway, + ) .then(() => { throw new Error("Test Failed"); }) diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-complete.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-complete.test.ts similarity index 88% rename from packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-complete.test.ts rename to packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-complete.test.ts index b196f81f45..0d3247a4f4 100644 --- a/packages/cactus-plugin-odap-hermes/src/test/typescript/integration/odap/transfer-complete.test.ts +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-complete.test.ts @@ -10,6 +10,7 @@ import { import { v4 as uuidV4 } from "uuid"; import { SHA256 } from "crypto-js"; import { randomInt } from "crypto"; +import { checkValidTransferCompleteRequest } from "../../../../main/typescript/gateway/server/transfer-complete"; let sourceGatewayConstructor: IPluginOdapGatewayConstructorOptions; let recipientGatewayConstructor: IPluginOdapGatewayConstructorOptions; @@ -44,17 +45,19 @@ beforeEach(() => { "transferCommenceResponseMessageData", ).toString(); + sessionID = uuidV4(); + sequenceNumber = randomInt(100); + sessionData = { + id: sessionID, sourceGatewayPubkey: pluginSourceGateway.pubKey, recipientGatewayPubkey: pluginRecipientGateway.pubKey, commitFinalResponseMessageHash: dummyCommitFinalResponseMessageHash, transferCommenceMessageRequestHash: dummyTransferCommenceResponseMessageHash, step: 2, + lastSequenceNumber: sequenceNumber, }; - sessionID = uuidV4(); - sequenceNumber = randomInt(100); - pluginSourceGateway.sessions.set(sessionID, sessionData); pluginRecipientGateway.sessions.set(sessionID, sessionData); }); @@ -68,16 +71,17 @@ test("dummy test for transfer complete flow", async () => { clientSignature: "", hashTransferCommence: dummyTransferCommenceResponseMessageHash, hashCommitFinalAck: dummyCommitFinalResponseMessageHash, - sequenceNumber: sequenceNumber, + sequenceNumber: sequenceNumber + 1, }; transferCompleteRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( pluginSourceGateway.sign(JSON.stringify(transferCompleteRequestMessage)), ); - const response = await pluginRecipientGateway.transferCompleteReceived( + checkValidTransferCompleteRequest( transferCompleteRequestMessage, - ); - - expect(response.ok).toBe("true"); + pluginRecipientGateway, + ).catch(() => { + throw new Error("Test failed"); + }); }); diff --git a/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-initiation.test.ts b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-initiation.test.ts new file mode 100644 index 0000000000..2a7049f8bf --- /dev/null +++ b/packages/cactus-plugin-odap-hermes/src/test/typescript/unit/server/transfer-initiation.test.ts @@ -0,0 +1,180 @@ +import { randomInt } from "crypto"; +import { SHA256 } from "crypto-js"; +import { v4 as uuidV4 } from "uuid"; +import { + OdapMessageType, + PluginOdapGateway, +} from "../../../../main/typescript/gateway/plugin-odap-gateway"; +import { checkValidInitializationRequest } from "../../../../main/typescript/gateway/server/transfer-initialization"; +import { + TransferInitializationV1Request, + AssetProfile, +} from "../../../../main/typescript/public-api"; + +let sourceGatewayConstructor; +let recipientGatewayConstructor; +let pluginSourceGateway: PluginOdapGateway; +let pluginRecipientGateway: PluginOdapGateway; +let expiryDate: string; +let assetProfile: AssetProfile; +let sequenceNumber: number; +let sessionID: string; + +beforeAll(() => { + sourceGatewayConstructor = { + name: "plugin-odap-gateway#sourceGateway", + dltIDs: ["DLT2"], + instanceId: uuidV4(), + }; + recipientGatewayConstructor = { + name: "plugin-odap-gateway#recipientGateway", + dltIDs: ["DLT1"], + instanceId: uuidV4(), + }; + + pluginSourceGateway = new PluginOdapGateway(sourceGatewayConstructor); + pluginRecipientGateway = new PluginOdapGateway(recipientGatewayConstructor); + expiryDate = new Date(2060, 11, 24).toString(); + assetProfile = { expirationDate: expiryDate }; + + sequenceNumber = randomInt(100); + sessionID = uuidV4(); +}); + +test("valid transfer initiation request", async () => { + const initializationRequestMessage: TransferInitializationV1Request = { + messageType: OdapMessageType.InitializationRequest, + sessionID: sessionID, + version: "0.0.0", + loggingProfile: "dummyLoggingProfile", + accessControlProfile: "dummyAccessControlProfile", + applicationProfile: "dummyApplicationProfile", + payloadProfile: { + assetProfile: assetProfile, + capabilities: "", + }, + clientSignature: "", + sourceGatewayPubkey: pluginSourceGateway.pubKey, + sourceGatewayDltSystem: "DLT1", + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + recipientGatewayDltSystem: "DLT2", + sequenceNumber: sequenceNumber, + }; + + initializationRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( + await pluginSourceGateway.sign( + JSON.stringify(initializationRequestMessage), + ), + ); + + const messageHash = SHA256( + JSON.stringify(initializationRequestMessage), + ).toString(); + + await checkValidInitializationRequest( + initializationRequestMessage, + pluginRecipientGateway, + ); + + const sessionData = pluginRecipientGateway.sessions.get(sessionID); + + if (sessionData == undefined) throw new Error("Test failed"); + + expect(sessionData.step).not.toBe(0); + expect(sessionData.lastSequenceNumber).toBe(sequenceNumber); + expect(sessionData.loggingProfile).toBe("dummyLoggingProfile"); + expect(sessionData.accessControlProfile).toBe("dummyAccessControlProfile"); + expect(sessionData.applicationProfile).toBe("dummyApplicationProfile"); + expect(JSON.stringify(sessionData.assetProfile)).toBe( + JSON.stringify(assetProfile), + ); + expect(sessionData.sourceGatewayPubkey).toBe(pluginSourceGateway.pubKey); + expect(sessionData.recipientGatewayPubkey).toBe( + pluginRecipientGateway.pubKey, + ); + expect(sessionData.sourceGatewayDltSystem).toBe("DLT1"); + expect(sessionData.recipientGatewayDltSystem).toBe("DLT2"); + + expect(sessionData.initializationRequestMessageHash).toBe(messageHash); + + expect(sessionData.clientSignatureInitializationRequestMessage).toBe( + initializationRequestMessage.clientSignature, + ); +}); + +test("transfer initiation request invalid because of incompatible DLTs", async () => { + const initializationRequestMessage: TransferInitializationV1Request = { + messageType: OdapMessageType.InitializationRequest, + sessionID: sessionID, + version: "0.0.0", + loggingProfile: "dummy", + accessControlProfile: "dummy", + applicationProfile: "dummy", + payloadProfile: { + assetProfile: assetProfile, + capabilities: "", + }, + clientSignature: "", + sourceGatewayPubkey: pluginSourceGateway.pubKey, + sourceGatewayDltSystem: "DLT2", + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + recipientGatewayDltSystem: "DLT1", + sequenceNumber: sequenceNumber, + }; + + initializationRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( + await pluginSourceGateway.sign( + JSON.stringify(initializationRequestMessage), + ), + ); + + await checkValidInitializationRequest( + initializationRequestMessage, + pluginRecipientGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => + expect(ex.message).toMatch( + "source gateway dlt system is not supported by this gateway", + ), + ); +}); + +test("transfer initiation request invalid because of asset expired", async () => { + expiryDate = new Date(2020, 11, 24).toString(); + assetProfile = { expirationDate: expiryDate }; + + const initializationRequestMessage: TransferInitializationV1Request = { + messageType: OdapMessageType.InitializationRequest, + sessionID: sessionID, + version: "0.0.0", + loggingProfile: "dummy", + accessControlProfile: "dummy", + applicationProfile: "dummy", + payloadProfile: { + assetProfile: assetProfile, + capabilities: "", + }, + clientSignature: "", + sourceGatewayPubkey: pluginSourceGateway.pubKey, + sourceGatewayDltSystem: "DLT1", + recipientGatewayPubkey: pluginRecipientGateway.pubKey, + recipientGatewayDltSystem: "DLT2", + sequenceNumber: sequenceNumber, + }; + + initializationRequestMessage.clientSignature = pluginSourceGateway.bufArray2HexStr( + pluginSourceGateway.sign(JSON.stringify(initializationRequestMessage)), + ); + + await checkValidInitializationRequest( + initializationRequestMessage, + pluginRecipientGateway, + ) + .then(() => { + throw new Error("Test Failed"); + }) + .catch((ex: Error) => expect(ex.message).toMatch("asset has expired")); +});