diff --git a/src/config/configuration.ts b/src/config/configuration.ts index 659fd51..d925259 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -3,20 +3,36 @@ export interface IConfig { port: number; // comma separated list of API keys (API_KEYS) api_keys: string[]; - // RPC endpoint (RPC) - rpcETH: string; - rpcFLR: string; - rpcSGB: string; + // // RPC endpoint (RPC) + // rpcETH: string; + // rpcFLR: string; + // rpcSGB: string; + getRPCSource: IGetRPCSource; + isTestnet: boolean; +} + +export type EVMTransactionSources = "ETH" | "FLR" | "SGB"; +export type IGetRPCSource = (source: EVMTransactionSources) => string; + +function getRPCSource(source: EVMTransactionSources, config: IConfig): string { + switch (source) { + case "ETH": + return process.env.RPC_ETH || "https://flare-api.flare.network/ext/C/rpc"; + case "FLR": + return process.env.RPC_FLR || "https://flare-api.flare.network/ext/C/rpc"; + case "SGB": + return process.env.RPC_SGB || "https://flare-api.flare.network/ext/C/rpc"; + } } export default () => { const api_keys = process.env.API_KEYS?.split(",") || [""]; + const isTestnet = process.env.TESTNET == "true"; const config: IConfig = { port: parseInt(process.env.PORT || "3000"), api_keys, - rpcFLR: process.env.RPC_FLR || "https://flare-api.flare.network/ext/C/rpc", - rpcETH: process.env.RPC_ETH || "https://flare-api.flare.network/ext/C/rpc", - rpcSGB: process.env.RPC_SGB || "https://flare-api.flare.network/ext/C/rpc", + getRPCSource: (source: EVMTransactionSources) => getRPCSource(source, config), + isTestnet, }; return config; }; diff --git a/src/controller/eth/eth-evm-transaction-verifier.controller.ts b/src/controller/eth/eth-evm-transaction-verifier.controller.ts index f75d2a1..15ea1db 100644 --- a/src/controller/eth/eth-evm-transaction-verifier.controller.ts +++ b/src/controller/eth/eth-evm-transaction-verifier.controller.ts @@ -1,71 +1,12 @@ -/////////////////////////////////////////////////////////////// -// THIS IS GENERATED CODE. DO NOT CHANGE THIS FILE MANUALLY .// -/////////////////////////////////////////////////////////////// - -import { Body, Controller, HttpCode, Post, UseGuards } from "@nestjs/common"; -import { ApiSecurity, ApiTags } from "@nestjs/swagger"; -import { ApiKeyAuthGuard } from "../../auth/apikey.guard"; - +import { ApiTags } from "@nestjs/swagger"; import { ETHEVMTransactionVerifierService } from "../../service/eth/eth-evm-transaction-verifier.service"; -import { AttestationResponseDTO_EVMTransaction_Response, EVMTransaction_RequestNoMic } from "../../dto/EVMTransaction.dto"; -import { EncodedRequest, MicResponse, EncodedRequestResponse } from "../../dto/generic.dto"; -import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../../dto/fdcTransactions.dto"; +import { EVMTransactionVerifierControllerBase } from "../evm-transaction-verifier-base.controller"; +import { Controller } from "@nestjs/common"; -@ApiTags("EVMTransaction") +@ApiTags("EVMTransaction", "ETH") @Controller("eth/EVMTransaction") -@UseGuards(ApiKeyAuthGuard) -@ApiSecurity("X-API-KEY") -export class ETHEVMTransactionVerifierController { - constructor(private readonly verifierService: ETHEVMTransactionVerifierService) {} - - /** - * - * Tries to verify encoded attestation request without checking message integrity code, and if successful it returns response. - * @param verifierBody - * @deprecated - * @returns - */ - @HttpCode(200) - @Post() - async verify(@Body() body: EncodedRequest): Promise { - return this.verifierService.verifyEncodedRequest(body.abiEncodedRequest!); - } - - @HttpCode(200) - @Post("verifyFDC") - async verifyFDC(@Body() body: EncodedRequest): Promise { - return this.verifierService.verifyEncodedRequestFDC(body.abiEncodedRequest!); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful it returns response. - * @param prepareResponseBody - * @returns - */ - @HttpCode(200) - @Post("prepareResponse") - async prepareResponse(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.prepareResponse(body); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful, it returns the correct message integrity code. - * @param body - */ - @HttpCode(200) - @Post("mic") - async mic(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.mic(body); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code. - * If successful, it returns the encoding of the attestation request with the correct message integrity code, which can be directly submitted to the State Connector contract. - * @param body - */ - @HttpCode(200) - @Post("prepareRequest") - async prepareRequest(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.prepareRequest(body); +export class ETHEVMTransactionVerifierController extends EVMTransactionVerifierControllerBase { + constructor(protected readonly verifierService: ETHEVMTransactionVerifierService) { + super(); } } diff --git a/src/controller/evm-transaction-verifier-base.controller.ts b/src/controller/evm-transaction-verifier-base.controller.ts new file mode 100644 index 0000000..fc402ee --- /dev/null +++ b/src/controller/evm-transaction-verifier-base.controller.ts @@ -0,0 +1,70 @@ +import { Body, HttpCode, Post, UseGuards } from "@nestjs/common"; +import { ApiSecurity, ApiTags } from "@nestjs/swagger"; +import { ApiKeyAuthGuard } from "../auth/apikey.guard"; +import { AttestationResponseDTO_EVMTransaction_Response, EVMTransaction_RequestNoMic } from "../dto/EVMTransaction.dto"; +import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../dto/fdcTransactions.dto"; +import { EncodedRequest, EncodedRequestResponse, MicResponse } from "../dto/generic.dto"; +import { EVMTransactionVerifierServiceBase } from "../service/evm-transaction-verification-base.service"; + +@ApiTags("EVMTransaction") +@UseGuards(ApiKeyAuthGuard) +@ApiSecurity("X-API-KEY") +export abstract class EVMTransactionVerifierControllerBase { + protected readonly verifierService: EVMTransactionVerifierServiceBase; + + /** + * + * Tries to verify encoded attestation request without checking message integrity code, and if successful it returns response in json form. + * @param body + * @deprecated + * @returns json of AttestationResponse + */ + @HttpCode(200) + @Post() + async verify(@Body() body: EncodedRequest): Promise { + return this.verifierService.verifyEncodedRequest(body.abiEncodedRequest!); + } + + /** + * Tries to verify encoded attestation request without checking message integrity code, and if successful it returns response in abi encoded form. + * @param body + * @returns abi encoded AttestationResponse + */ + @HttpCode(200) + @Post("verifyFDC") + async verifyFDC(@Body() body: EncodedRequest): Promise { + return this.verifierService.verifyEncodedRequestFDC(body.abiEncodedRequest!); + } + + /** + * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful it returns response. + * @param prepareResponseBody + * @returns + */ + @HttpCode(200) + @Post("prepareResponse") + async prepareResponse(@Body() body: EVMTransaction_RequestNoMic): Promise { + return this.verifierService.prepareResponse(body); + } + + /** + * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful, it returns the correct message integrity code. + * @param body + */ + @HttpCode(200) + @Post("mic") + async mic(@Body() body: EVMTransaction_RequestNoMic): Promise { + return this.verifierService.mic(body); + } + + /** + * Tries to verify attestation request (given in JSON) without checking message integrity code. + * If successful, it returns the encoding of the attestation request with the correct message integrity code, which can be directly submitted to the State Connector contract. + * @param body + */ + @HttpCode(200) + @Post("prepareRequest") + async prepareRequest(@Body() body: EVMTransaction_RequestNoMic): Promise { + return this.verifierService.prepareRequest(body); + } +} diff --git a/src/controller/eth/eth-evm-transaction-verifier.controller.spec.ts b/src/controller/flr/flr-evm-transaction-verifier.controller.spec.ts similarity index 82% rename from src/controller/eth/eth-evm-transaction-verifier.controller.spec.ts rename to src/controller/flr/flr-evm-transaction-verifier.controller.spec.ts index 865c324..c4c0f61 100644 --- a/src/controller/eth/eth-evm-transaction-verifier.controller.spec.ts +++ b/src/controller/flr/flr-evm-transaction-verifier.controller.spec.ts @@ -4,15 +4,15 @@ import { ApiKeyStrategy } from "../../auth/apikey.strategy"; import { AuthModule } from "../../auth/auth.module"; import { AuthService } from "../../auth/auth.service"; import configuration from "../../config/configuration"; -import { ETHEVMTransactionVerifierService } from "../../service/eth/eth-evm-transaction-verifier.service"; -import { ETHEVMTransactionVerifierController } from "./eth-evm-transaction-verifier.controller"; +import { FLREVMTransactionVerifierController } from "./flr-evm-transaction-verifier.controller"; +import { FLREVMTransactionVerifierService } from "../../service/flr/flr-evm-transaction-verifier.service"; const EXAMPLE_ENCODED_REQUEST = - "0x45564d5472616e73616374696f6e000000000000000000000000000000000000455448000000000000000000000000000000000000000000000000000000000087e8d91c3d07630fe2bf9b85c36d85cfe2d03ba5e63ac054c22ccb0110bebd310000000000000000000000000000000000000000000000000000000000000020e1ad057e71ac82cd2eaaee0dc8700a2c1b6cff4f295a7674b9e97a5f8dd9b51c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"; + "0x45564d5472616e73616374696f6e000000000000000000000000000000000000464c520000000000000000000000000000000000000000000000000000000000b046e06fc597c21b0d329ce4c1df55bef28d2fd1f261d6ee35f05f21790e51e60000000000000000000000000000000000000000000000000000000000000020e1ad057e71ac82cd2eaaee0dc8700a2c1b6cff4f295a7674b9e97a5f8dd9b51c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"; const EXAMPLE_REQUEST_NOMIC = { attestationType: "0x45564d5472616e73616374696f6e000000000000000000000000000000000000", - sourceId: "0x4554480000000000000000000000000000000000000000000000000000000000", + sourceId: "0x464c520000000000000000000000000000000000000000000000000000000000", requestBody: { transactionHash: "0xe1ad057e71ac82cd2eaaee0dc8700a2c1b6cff4f295a7674b9e97a5f8dd9b51c", requiredConfirmations: "1", @@ -26,7 +26,7 @@ const EXAMPLE_RESPONSE = { status: "VALID", response: { attestationType: "0x45564d5472616e73616374696f6e000000000000000000000000000000000000", - sourceId: "0x4554480000000000000000000000000000000000000000000000000000000000", + sourceId: "0x464c520000000000000000000000000000000000000000000000000000000000", votingRound: "0", lowestUsedTimestamp: "1696806248", requestBody: { @@ -62,10 +62,10 @@ const EXAMPLE_RESPONSE = { }, }; -const EXPECTED_MIC = "0x87e8d91c3d07630fe2bf9b85c36d85cfe2d03ba5e63ac054c22ccb0110bebd31"; +const EXPECTED_MIC = "0xb046e06fc597c21b0d329ce4c1df55bef28d2fd1f261d6ee35f05f21790e51e6"; -describe("AppController", () => { - let appController: ETHEVMTransactionVerifierController; +describe("AppController for FLR (Must have FLR mainnet RPC configure in .env)", () => { + let appController: FLREVMTransactionVerifierController; beforeEach(async () => { const app: TestingModule = await Test.createTestingModule({ @@ -76,11 +76,11 @@ describe("AppController", () => { }), AuthModule, ], - controllers: [ETHEVMTransactionVerifierController], - providers: [ApiKeyStrategy, AuthService, ETHEVMTransactionVerifierService], + controllers: [FLREVMTransactionVerifierController], + providers: [ApiKeyStrategy, AuthService, FLREVMTransactionVerifierService], }).compile(); - appController = app.get(ETHEVMTransactionVerifierController); + appController = app.get(FLREVMTransactionVerifierController); }); describe("root", () => { @@ -91,15 +91,18 @@ describe("AppController", () => { expect(actualRes.status).toEqual("VALID"); expect(JSON.parse(JSON.stringify(actualRes.response))).toStrictEqual(EXAMPLE_RESPONSE.response); }); + it("should prepare response", async () => { const actualRes = await appController.prepareResponse(EXAMPLE_REQUEST_NOMIC); expect(actualRes.status).toEqual("VALID"); expect(JSON.parse(JSON.stringify(actualRes.response))).toStrictEqual(EXAMPLE_RESPONSE.response); }); + it("should obtain 'mic'", async () => { const actualMic = await appController.mic(EXAMPLE_REQUEST_NOMIC); expect(actualMic.messageIntegrityCode).toStrictEqual(EXPECTED_MIC); }); + it("should prepare request", async () => { const actualRequest = await appController.prepareRequest(EXAMPLE_REQUEST_NOMIC); expect(actualRequest.abiEncodedRequest).toStrictEqual(EXAMPLE_ENCODED_REQUEST); diff --git a/src/controller/flr/flr-evm-transaction-verifier.controller.ts b/src/controller/flr/flr-evm-transaction-verifier.controller.ts index 282b102..643f740 100644 --- a/src/controller/flr/flr-evm-transaction-verifier.controller.ts +++ b/src/controller/flr/flr-evm-transaction-verifier.controller.ts @@ -1,70 +1,12 @@ -/////////////////////////////////////////////////////////////// -// THIS IS GENERATED CODE. DO NOT CHANGE THIS FILE MANUALLY .// -/////////////////////////////////////////////////////////////// - -import { Body, Controller, HttpCode, Post, UseGuards } from "@nestjs/common"; -import { ApiSecurity, ApiTags } from "@nestjs/swagger"; -import { ApiKeyAuthGuard } from "../../auth/apikey.guard"; - +import { Controller } from "@nestjs/common"; +import { ApiTags } from "@nestjs/swagger"; import { FLREVMTransactionVerifierService } from "../../service/flr/flr-evm-transaction-verifier.service"; -import { AttestationResponseDTO_EVMTransaction_Response, EVMTransaction_RequestNoMic } from "../../dto/EVMTransaction.dto"; -import { EncodedRequest, MicResponse, EncodedRequestResponse } from "../../dto/generic.dto"; -import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../../dto/fdcTransactions.dto"; +import { EVMTransactionVerifierControllerBase } from "../evm-transaction-verifier-base.controller"; -@ApiTags("EVMTransaction") +@ApiTags("EVMTransaction", "FLR") @Controller("flr/EVMTransaction") -@UseGuards(ApiKeyAuthGuard) -@ApiSecurity("X-API-KEY") -export class FLREVMTransactionVerifierController { - constructor(private readonly verifierService: FLREVMTransactionVerifierService) {} - - /** - * - * Tries to verify encoded attestation request without checking message integrity code, and if successful it returns response. - * @param verifierBody - * @returns - */ - @HttpCode(200) - @Post() - async verify(@Body() body: EncodedRequest): Promise { - return this.verifierService.verifyEncodedRequest(body.abiEncodedRequest!); - } - - @HttpCode(200) - @Post("verifyFDC") - async verifyFDC(@Body() body: EncodedRequest): Promise { - return this.verifierService.verifyEncodedRequestFDC(body.abiEncodedRequest!); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful it returns response. - * @param prepareResponseBody - * @returns - */ - @HttpCode(200) - @Post("prepareResponse") - async prepareResponse(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.prepareResponse(body); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful, it returns the correct message integrity code. - * @param body - */ - @HttpCode(200) - @Post("mic") - async mic(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.mic(body); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code. - * If successful, it returns the encoding of the attestation request with the correct message integrity code, which can be directly submitted to the State Connector contract. - * @param body - */ - @HttpCode(200) - @Post("prepareRequest") - async prepareRequest(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.prepareRequest(body); +export class FLREVMTransactionVerifierController extends EVMTransactionVerifierControllerBase { + constructor(protected readonly verifierService: FLREVMTransactionVerifierService) { + super(); } } diff --git a/src/controller/sgb/sgb-evm-transaction-verifier.controller.ts b/src/controller/sgb/sgb-evm-transaction-verifier.controller.ts index 7a507c6..7c33199 100644 --- a/src/controller/sgb/sgb-evm-transaction-verifier.controller.ts +++ b/src/controller/sgb/sgb-evm-transaction-verifier.controller.ts @@ -1,70 +1,12 @@ -/////////////////////////////////////////////////////////////// -// THIS IS GENERATED CODE. DO NOT CHANGE THIS FILE MANUALLY .// -/////////////////////////////////////////////////////////////// - -import { Body, Controller, HttpCode, Post, UseGuards } from "@nestjs/common"; -import { ApiSecurity, ApiTags } from "@nestjs/swagger"; -import { ApiKeyAuthGuard } from "../../auth/apikey.guard"; - +import { Controller } from "@nestjs/common"; +import { ApiTags } from "@nestjs/swagger"; +import { EVMTransactionVerifierControllerBase } from "../evm-transaction-verifier-base.controller"; import { SGBEVMTransactionVerifierService } from "../../service/sgb/sgb-evm-transaction-verifier.service"; -import { AttestationResponseDTO_EVMTransaction_Response, EVMTransaction_RequestNoMic } from "../../dto/EVMTransaction.dto"; -import { EncodedRequest, MicResponse, EncodedRequestResponse } from "../../dto/generic.dto"; -import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../../dto/fdcTransactions.dto"; -@ApiTags("EVMTransaction") +@ApiTags("EVMTransaction", "SGB") @Controller("sgb/EVMTransaction") -@UseGuards(ApiKeyAuthGuard) -@ApiSecurity("X-API-KEY") -export class SGBEVMTransactionVerifierController { - constructor(private readonly verifierService: SGBEVMTransactionVerifierService) {} - - /** - * - * Tries to verify encoded attestation request without checking message integrity code, and if successful it returns response. - * @param verifierBody - * @returns - */ - @HttpCode(200) - @Post() - async verify(@Body() body: EncodedRequest): Promise { - return this.verifierService.verifyEncodedRequest(body.abiEncodedRequest!); - } - - @HttpCode(200) - @Post("verifyFDC") - async verifyFDC(@Body() body: EncodedRequest): Promise { - return this.verifierService.verifyEncodedRequestFDC(body.abiEncodedRequest!); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful it returns response. - * @param prepareResponseBody - * @returns - */ - @HttpCode(200) - @Post("prepareResponse") - async prepareResponse(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.prepareResponse(body); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code, and if successful, it returns the correct message integrity code. - * @param body - */ - @HttpCode(200) - @Post("mic") - async mic(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.mic(body); - } - - /** - * Tries to verify attestation request (given in JSON) without checking message integrity code. - * If successful, it returns the encoding of the attestation request with the correct message integrity code, which can be directly submitted to the State Connector contract. - * @param body - */ - @HttpCode(200) - @Post("prepareRequest") - async prepareRequest(@Body() body: EVMTransaction_RequestNoMic): Promise { - return this.verifierService.prepareRequest(body); +export class SGBEVMTransactionVerifierController extends EVMTransactionVerifierControllerBase { + constructor(protected readonly verifierService: SGBEVMTransactionVerifierService) { + super(); } } diff --git a/src/service/eth/eth-evm-transaction-verifier.service.ts b/src/service/eth/eth-evm-transaction-verifier.service.ts index 257d677..552a106 100644 --- a/src/service/eth/eth-evm-transaction-verifier.service.ts +++ b/src/service/eth/eth-evm-transaction-verifier.service.ts @@ -1,132 +1,14 @@ -import { HttpException, HttpStatus, Injectable } from "@nestjs/common"; +import { Injectable } from "@nestjs/common"; +import { EVMTransactionVerifierServiceBase, IVerificationServiceConfig } from "../evm-transaction-verification-base.service"; import { ConfigService } from "@nestjs/config"; -import { JsonRpcProvider, ethers } from "ethers"; -import { readFileSync } from "fs"; import { IConfig } from "../../config/configuration"; -import { - AttestationResponseDTO_EVMTransaction_Response, - EVMTransaction_Request, - EVMTransaction_RequestNoMic, - EVMTransaction_Response, -} from "../../dto/EVMTransaction.dto"; -import { EncodedRequestResponse, MicResponse } from "../../dto/generic.dto"; -import { AttestationDefinitionStore } from "../../external-libs/ts/AttestationDefinitionStore"; -import { AttestationResponseStatus } from "../../external-libs/ts/AttestationResponse"; -import { ExampleData } from "../../external-libs/ts/interfaces"; -import { MIC_SALT, ZERO_BYTES_32, encodeAttestationName } from "../../external-libs/ts/utils"; -import { verifyEVMTransactionRequest } from "../../verification/verification"; -import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../../dto/fdcTransactions.dto"; @Injectable() -export class ETHEVMTransactionVerifierService { - store!: AttestationDefinitionStore; - exampleData!: ExampleData; - - //-$$$ Start of custom code section. Do not change this comment. - - web3Provider!: JsonRpcProvider; - - constructor(private configService: ConfigService) { - this.store = new AttestationDefinitionStore("type-definitions"); - this.exampleData = JSON.parse(readFileSync("src/example-data/EVMTransaction.json", "utf8")); - - this.web3Provider = new ethers.JsonRpcProvider(this.configService.get("rpcETH")); - } - - //-$$$ End of custom code section. Do not change this comment. - - async verifyRequestInternal(request: EVMTransaction_Request | EVMTransaction_RequestNoMic): Promise { - if ( - request.attestationType !== encodeAttestationName("EVMTransaction") || - request.sourceId !== encodeAttestationName((process.env.TESTNET == "true" ? "test" : "") + "ETH") - ) { - throw new HttpException( - { - status: HttpStatus.BAD_REQUEST, - error: `Attestation type and source id combination not supported: (${request.attestationType}, ${ - request.sourceId - }). This source supports attestation type 'EVMTransaction' (${encodeAttestationName("EVMTransaction")}) and source id '${ - (process.env.TESTNET == "true" ? "test" : "") + "ETH" - }' (${encodeAttestationName((process.env.TESTNET == "true" ? "test" : "") + "ETH")}).`, - }, - HttpStatus.BAD_REQUEST, - ); - } - - const fixedRequest = { - ...request, - } as EVMTransaction_Request; - if (!fixedRequest.messageIntegrityCode) { - fixedRequest.messageIntegrityCode = ZERO_BYTES_32; - } - - return this.verifyRequest(fixedRequest); - } - - async verifyRequest(fixedRequest: EVMTransaction_Request): Promise { - //-$$$ Start of custom code section. Do not change this comment. - - const responseDTO = await verifyEVMTransactionRequest(fixedRequest, this.web3Provider); - return responseDTO; - - //-$$$ End of custom code section. Do not change this comment. - } - - public async verifyEncodedRequest(abiEncodedRequest: string): Promise { - const requestJSON = this.store.parseRequest(abiEncodedRequest); - const response = await this.verifyRequestInternal(requestJSON); - return response; - } - - public async verifyEncodedRequestFDC(abiEncodedRequest: string): Promise { - const requestJSON = this.store.parseRequest(abiEncodedRequest); - const response = await this.verifyRequestInternal(requestJSON); - if (response.status !== AttestationResponseStatus.VALID || !response.response) { - return { - status: response.status, - }; - } - const encoded = this.store.encodeResponse(response.response); - return { - status: response.status, - abiEncodedResponse: encoded, +export class ETHEVMTransactionVerifierService extends EVMTransactionVerifierServiceBase { + constructor(protected configService: ConfigService) { + const VerificationServiceConfig: IVerificationServiceConfig = { + rpcSource: "ETH", }; - } - - public async prepareResponse(request: EVMTransaction_RequestNoMic): Promise { - const response = await this.verifyRequestInternal(request); - return response; - } - - public async mic(request: EVMTransaction_RequestNoMic): Promise { - const result = await this.verifyRequestInternal(request); - if (result.status !== AttestationResponseStatus.VALID) { - return new MicResponse({ status: result.status }); - } - const response = result.response; - if (!response) return new MicResponse({ status: result.status }); - return new MicResponse({ - status: AttestationResponseStatus.VALID, - messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT), - }); - } - - public async prepareRequest(request: EVMTransaction_RequestNoMic): Promise { - const result = await this.verifyRequestInternal(request); - if (result.status !== AttestationResponseStatus.VALID) { - return new EncodedRequestResponse({ status: result.status }); - } - const response = result.response; - - if (!response) return new EncodedRequestResponse({ status: result.status }); - const newRequest = { - ...request, - messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT)!, - } as EVMTransaction_Request; - - return new EncodedRequestResponse({ - status: AttestationResponseStatus.VALID, - abiEncodedRequest: this.store.encodeRequest(newRequest), - }); + super(configService, VerificationServiceConfig); } } diff --git a/src/service/evm-transaction-verification-base.service.ts b/src/service/evm-transaction-verification-base.service.ts new file mode 100644 index 0000000..4f0c4f4 --- /dev/null +++ b/src/service/evm-transaction-verification-base.service.ts @@ -0,0 +1,142 @@ +import { HttpException, HttpStatus } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { JsonRpcProvider, ethers } from "ethers"; +import { readFileSync } from "fs"; +import { EVMTransactionSources, IConfig, IGetRPCSource } from "../config/configuration"; +import { + EVMTransaction_RequestNoMic, + EVMTransaction_Request, + EVMTransaction_Response, + AttestationResponseDTO_EVMTransaction_Response, + AttestationResponseStatus, +} from "../dto/EVMTransaction.dto"; +import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../dto/fdcTransactions.dto"; +import { MicResponse, EncodedRequestResponse } from "../dto/generic.dto"; +import { AttestationDefinitionStore } from "../external-libs/ts/AttestationDefinitionStore"; +import { encodeAttestationName, ZERO_BYTES_32, MIC_SALT } from "../external-libs/ts/utils"; +import { verifyEVMTransactionRequest } from "../verification/verification"; + +export interface ExampleData { + requestNoMic: RNM; + request: REQ; + response: RES; + messageIntegrityCode: string; + encodedRequestZeroMic: string; + encodedRequest: string; +} + +export interface IVerificationServiceConfig { + rpcSource: EVMTransactionSources; +} + +export abstract class EVMTransactionVerifierServiceBase { + store: AttestationDefinitionStore; + exampleData: ExampleData; + + web3Provider: JsonRpcProvider; + source: EVMTransactionSources; + isTestnet: boolean; + + constructor( + protected configService: ConfigService, + config: IVerificationServiceConfig, + ) { + this.store = new AttestationDefinitionStore("type-definitions"); + this.exampleData = JSON.parse(readFileSync("src/example-data/EVMTransaction.json", "utf8")); + const rpcConfig = this.configService.getOrThrow("getRPCSource"); + this.source = config.rpcSource; + this.web3Provider = new ethers.JsonRpcProvider(rpcConfig(config.rpcSource)); + this.isTestnet = this.configService.getOrThrow("isTestnet"); + } + + async verifyRequestInternal(request: EVMTransaction_Request | EVMTransaction_RequestNoMic): Promise { + if ( + request.attestationType !== encodeAttestationName("EVMTransaction") || + request.sourceId !== encodeAttestationName((this.isTestnet ? "test" : "") + this.source) + ) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + error: `Attestation type and source id combination not supported: (${request.attestationType}, ${ + request.sourceId + }). This source supports attestation type 'EVMTransaction' (${encodeAttestationName("EVMTransaction")}) and source id '${ + (this.isTestnet ? "test" : "") + this.source + }' (${encodeAttestationName((this.isTestnet ? "test" : "") + this.source)}).`, + }, + HttpStatus.BAD_REQUEST, + ); + } + + const fixedRequest = { + ...request, + } as EVMTransaction_Request; + if (!fixedRequest.messageIntegrityCode) { + fixedRequest.messageIntegrityCode = ZERO_BYTES_32; + } + + return this.verifyRequest(fixedRequest); + } + + async verifyRequest(fixedRequest: EVMTransaction_Request): Promise { + const responseDTO = await verifyEVMTransactionRequest(fixedRequest, this.web3Provider); + return responseDTO; + } + + public async verifyEncodedRequest(abiEncodedRequest: string): Promise { + const requestJSON = this.store.parseRequest(abiEncodedRequest); + const response = await this.verifyRequestInternal(requestJSON); + return response; + } + + public async verifyEncodedRequestFDC(abiEncodedRequest: string): Promise { + const requestJSON = this.store.parseRequest(abiEncodedRequest); + const response = await this.verifyRequestInternal(requestJSON); + if (response.status !== AttestationResponseStatus.VALID || !response.response) { + return { + status: response.status, + }; + } + const encoded = this.store.encodeResponse(response.response); + return { + status: response.status, + abiEncodedResponse: encoded, + }; + } + + public async prepareResponse(request: EVMTransaction_RequestNoMic): Promise { + const response = await this.verifyRequestInternal(request); + return response; + } + + public async mic(request: EVMTransaction_RequestNoMic): Promise { + const result = await this.verifyRequestInternal(request); + if (result.status !== AttestationResponseStatus.VALID) { + return new MicResponse({ status: result.status }); + } + const response = result.response; + if (!response) return new MicResponse({ status: result.status }); + return new MicResponse({ + status: AttestationResponseStatus.VALID, + messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT), + }); + } + + public async prepareRequest(request: EVMTransaction_RequestNoMic): Promise { + const result = await this.verifyRequestInternal(request); + if (result.status !== AttestationResponseStatus.VALID) { + return new EncodedRequestResponse({ status: result.status }); + } + const response = result.response; + + if (!response) return new EncodedRequestResponse({ status: result.status }); + const newRequest = { + ...request, + messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT)!, + } as EVMTransaction_Request; + + return new EncodedRequestResponse({ + status: AttestationResponseStatus.VALID, + abiEncodedRequest: this.store.encodeRequest(newRequest), + }); + } +} diff --git a/src/service/flr/flr-evm-transaction-verifier.service.ts b/src/service/flr/flr-evm-transaction-verifier.service.ts index d51c855..7776056 100644 --- a/src/service/flr/flr-evm-transaction-verifier.service.ts +++ b/src/service/flr/flr-evm-transaction-verifier.service.ts @@ -1,134 +1,14 @@ -import { HttpException, HttpStatus, Injectable } from "@nestjs/common"; +import { Injectable } from "@nestjs/common"; +import { EVMTransactionVerifierServiceBase, IVerificationServiceConfig } from "../evm-transaction-verification-base.service"; import { ConfigService } from "@nestjs/config"; -import { JsonRpcProvider, ethers } from "ethers"; -import { readFileSync } from "fs"; import { IConfig } from "../../config/configuration"; -import { - AttestationResponseDTO_EVMTransaction_Response, - EVMTransaction_Request, - EVMTransaction_RequestNoMic, - EVMTransaction_Response, -} from "../../dto/EVMTransaction.dto"; -import { EncodedRequestResponse, MicResponse } from "../../dto/generic.dto"; -import { AttestationDefinitionStore } from "../../external-libs/ts/AttestationDefinitionStore"; -import { AttestationResponseStatus } from "../../external-libs/ts/AttestationResponse"; -import { ExampleData } from "../../external-libs/ts/interfaces"; -import { MIC_SALT, ZERO_BYTES_32, encodeAttestationName } from "../../external-libs/ts/utils"; -import { verifyEVMTransactionRequest } from "../../verification/verification"; -import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../../dto/fdcTransactions.dto"; @Injectable() -export class FLREVMTransactionVerifierService { - store!: AttestationDefinitionStore; - exampleData!: ExampleData; - - //-$$$ Start of custom code section. Do not change this comment. - - web3Provider!: JsonRpcProvider; - - // Add additional class members here. - // Augment the constructor with additional (injected) parameters, if required. Update the constructor code. - constructor(private configService: ConfigService) { - this.store = new AttestationDefinitionStore("type-definitions"); - this.exampleData = JSON.parse(readFileSync("src/example-data/EVMTransaction.json", "utf8")); - - this.web3Provider = new ethers.JsonRpcProvider(this.configService.get("rpcFLR")); - } - - //-$$$ End of custom code section. Do not change this comment. - - async verifyRequestInternal(request: EVMTransaction_Request | EVMTransaction_RequestNoMic): Promise { - if ( - request.attestationType !== encodeAttestationName("EVMTransaction") || - request.sourceId !== encodeAttestationName((process.env.TESTNET == "true" ? "test" : "") + "FLR") - ) { - throw new HttpException( - { - status: HttpStatus.BAD_REQUEST, - error: `Attestation type and source id combination not supported: (${request.attestationType}, ${ - request.sourceId - }). This source supports attestation type 'EVMTransaction' (${encodeAttestationName("EVMTransaction")}) and source id '${ - (process.env.TESTNET == "true" ? "test" : "") + "FLR" - }' (${encodeAttestationName((process.env.TESTNET == "true" ? "test" : "") + "FLR")}).`, - }, - HttpStatus.BAD_REQUEST, - ); - } - - const fixedRequest = { - ...request, - } as EVMTransaction_Request; - if (!fixedRequest.messageIntegrityCode) { - fixedRequest.messageIntegrityCode = ZERO_BYTES_32; - } - - return this.verifyRequest(fixedRequest); - } - - async verifyRequest(fixedRequest: EVMTransaction_Request): Promise { - //-$$$ Start of custom code section. Do not change this comment. - - const responseDTO = await verifyEVMTransactionRequest(fixedRequest, this.web3Provider); - return responseDTO; - - //-$$$ End of custom code section. Do not change this comment. - } - - public async verifyEncodedRequest(abiEncodedRequest: string): Promise { - const requestJSON = this.store.parseRequest(abiEncodedRequest); - const response = await this.verifyRequestInternal(requestJSON); - return response; - } - - public async prepareResponse(request: EVMTransaction_RequestNoMic): Promise { - const response = await this.verifyRequestInternal(request); - return response; - } - - public async mic(request: EVMTransaction_RequestNoMic): Promise { - const result = await this.verifyRequestInternal(request); - if (result.status !== AttestationResponseStatus.VALID) { - return new MicResponse({ status: result.status }); - } - const response = result.response; - if (!response) return new MicResponse({ status: result.status }); - return new MicResponse({ - status: AttestationResponseStatus.VALID, - messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT), - }); - } - - public async prepareRequest(request: EVMTransaction_RequestNoMic): Promise { - const result = await this.verifyRequestInternal(request); - if (result.status !== AttestationResponseStatus.VALID) { - return new EncodedRequestResponse({ status: result.status }); - } - const response = result.response; - - if (!response) return new EncodedRequestResponse({ status: result.status }); - const newRequest = { - ...request, - messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT)!, - } as EVMTransaction_Request; - - return new EncodedRequestResponse({ - status: AttestationResponseStatus.VALID, - abiEncodedRequest: this.store.encodeRequest(newRequest), - }); - } - - public async verifyEncodedRequestFDC(abiEncodedRequest: string): Promise { - const requestJSON = this.store.parseRequest(abiEncodedRequest); - const response = await this.verifyRequestInternal(requestJSON); - if (response.status !== AttestationResponseStatus.VALID || !response.response) { - return { - status: response.status, - }; - } - const encoded = this.store.encodeResponse(response.response); - return { - status: response.status, - abiEncodedResponse: encoded, +export class FLREVMTransactionVerifierService extends EVMTransactionVerifierServiceBase { + constructor(protected configService: ConfigService) { + const VerificationServiceConfig: IVerificationServiceConfig = { + rpcSource: "FLR", }; + super(configService, VerificationServiceConfig); } } diff --git a/src/service/sgb/sgb-evm-transaction-verifier.service.ts b/src/service/sgb/sgb-evm-transaction-verifier.service.ts index a3ec8c2..695e5d6 100644 --- a/src/service/sgb/sgb-evm-transaction-verifier.service.ts +++ b/src/service/sgb/sgb-evm-transaction-verifier.service.ts @@ -1,134 +1,14 @@ -import { HttpException, HttpStatus, Injectable } from "@nestjs/common"; +import { Injectable } from "@nestjs/common"; +import { EVMTransactionVerifierServiceBase, IVerificationServiceConfig } from "../evm-transaction-verification-base.service"; import { ConfigService } from "@nestjs/config"; -import { JsonRpcProvider, ethers } from "ethers"; -import { readFileSync } from "fs"; import { IConfig } from "../../config/configuration"; -import { - AttestationResponseDTO_EVMTransaction_Response, - EVMTransaction_Request, - EVMTransaction_RequestNoMic, - EVMTransaction_Response, -} from "../../dto/EVMTransaction.dto"; -import { EncodedRequestResponse, MicResponse } from "../../dto/generic.dto"; -import { AttestationDefinitionStore } from "../../external-libs/ts/AttestationDefinitionStore"; -import { AttestationResponseStatus } from "../../external-libs/ts/AttestationResponse"; -import { ExampleData } from "../../external-libs/ts/interfaces"; -import { MIC_SALT, ZERO_BYTES_32, encodeAttestationName } from "../../external-libs/ts/utils"; -import { verifyEVMTransactionRequest } from "../../verification/verification"; -import { AttestationResponseDTO_EVMTransaction_ResponseEncoded } from "../../dto/fdcTransactions.dto"; @Injectable() -export class SGBEVMTransactionVerifierService { - store!: AttestationDefinitionStore; - exampleData!: ExampleData; - - //-$$$ Start of custom code section. Do not change this comment. - - web3Provider!: JsonRpcProvider; - - // Add additional class members here. - // Augment the constructor with additional (injected) parameters, if required. Update the constructor code. - constructor(private configService: ConfigService) { - this.store = new AttestationDefinitionStore("type-definitions"); - this.exampleData = JSON.parse(readFileSync("src/example-data/EVMTransaction.json", "utf8")); - - this.web3Provider = new ethers.JsonRpcProvider(this.configService.get("rpcSGB")); - } - - //-$$$ End of custom code section. Do not change this comment. - - async verifyRequestInternal(request: EVMTransaction_Request | EVMTransaction_RequestNoMic): Promise { - if ( - request.attestationType !== encodeAttestationName("EVMTransaction") || - request.sourceId !== encodeAttestationName((process.env.TESTNET == "true" ? "test" : "") + "SGB") - ) { - throw new HttpException( - { - status: HttpStatus.BAD_REQUEST, - error: `Attestation type and source id combination not supported: (${request.attestationType}, ${ - request.sourceId - }). This source supports attestation type 'EVMTransaction' (${encodeAttestationName("EVMTransaction")}) and source id '${ - (process.env.TESTNET == "true" ? "test" : "") + "SGB" - }' (${encodeAttestationName((process.env.TESTNET == "true" ? "test" : "") + "SGB")}).`, - }, - HttpStatus.BAD_REQUEST, - ); - } - - const fixedRequest = { - ...request, - } as EVMTransaction_Request; - if (!fixedRequest.messageIntegrityCode) { - fixedRequest.messageIntegrityCode = ZERO_BYTES_32; - } - - return this.verifyRequest(fixedRequest); - } - - async verifyRequest(fixedRequest: EVMTransaction_Request): Promise { - //-$$$ Start of custom code section. Do not change this comment. - - const responseDTO = await verifyEVMTransactionRequest(fixedRequest, this.web3Provider); - return responseDTO; - - //-$$$ End of custom code section. Do not change this comment. - } - - public async verifyEncodedRequest(abiEncodedRequest: string): Promise { - const requestJSON = this.store.parseRequest(abiEncodedRequest); - const response = await this.verifyRequestInternal(requestJSON); - return response; - } - - public async prepareResponse(request: EVMTransaction_RequestNoMic): Promise { - const response = await this.verifyRequestInternal(request); - return response; - } - - public async mic(request: EVMTransaction_RequestNoMic): Promise { - const result = await this.verifyRequestInternal(request); - if (result.status !== AttestationResponseStatus.VALID) { - return new MicResponse({ status: result.status }); - } - const response = result.response; - if (!response) return new MicResponse({ status: result.status }); - return new MicResponse({ - status: AttestationResponseStatus.VALID, - messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT), - }); - } - - public async prepareRequest(request: EVMTransaction_RequestNoMic): Promise { - const result = await this.verifyRequestInternal(request); - if (result.status !== AttestationResponseStatus.VALID) { - return new EncodedRequestResponse({ status: result.status }); - } - const response = result.response; - - if (!response) return new EncodedRequestResponse({ status: result.status }); - const newRequest = { - ...request, - messageIntegrityCode: this.store.attestationResponseHash(response, MIC_SALT)!, - } as EVMTransaction_Request; - - return new EncodedRequestResponse({ - status: AttestationResponseStatus.VALID, - abiEncodedRequest: this.store.encodeRequest(newRequest), - }); - } - - public async verifyEncodedRequestFDC(abiEncodedRequest: string): Promise { - const requestJSON = this.store.parseRequest(abiEncodedRequest); - const response = await this.verifyRequestInternal(requestJSON); - if (response.status !== AttestationResponseStatus.VALID || !response.response) { - return { - status: response.status, - }; - } - const encoded = this.store.encodeResponse(response.response); - return { - status: response.status, - abiEncodedResponse: encoded, +export class SGBEVMTransactionVerifierService extends EVMTransactionVerifierServiceBase { + constructor(protected configService: ConfigService) { + const VerificationServiceConfig: IVerificationServiceConfig = { + rpcSource: "SGB", }; + super(configService, VerificationServiceConfig); } } diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index 3885344..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const ZERO_MIC = "0x0000000000000000000000000000000000000000000000000000000000000000"; - -export interface ExampleData { - requestNoMic: RNM; - request: REQ; - response: RES; - messageIntegrityCode: string; - encodedRequestZeroMic: string; - encodedRequest: string; -}