diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts index 8565f199f..48f2b7870 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts @@ -1,35 +1,36 @@ -import { AuthAgent } from '../../auth/agent/auth.agent'; -import { BpiSubjectAccount as BpiSubjectAccountPrismaModel } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; -import { WorkflowStorageAgent } from '../../workgroup/workflows/agents/workflowsStorage.agent'; -import { WorkstepStorageAgent } from '../../workgroup/worksteps/agents/workstepsStorage.agent'; -import { Transaction } from '../models/transaction'; -import { TransactionStatus } from '../models/transactionStatus.enum'; -import { TransactionStorageAgent } from './transactionStorage.agent'; -import { TransactionAgent } from './transactions.agent'; -import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; +import { classes } from '@automapper/classes'; +import { AutomapperModule } from '@automapper/nestjs'; +import { NotFoundException } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; import { + BpiAccount, BpiSubject, BpiSubjectAccount, + PrismaClient, + PublicKeyType, Workflow, Workgroup, Workstep, - BpiAccount, - PrismaClient, - PublicKeyType, } from '../../../../__mocks__/@prisma/client'; -import { Test, TestingModule } from '@nestjs/testing'; -import { SnarkjsCircuitService } from '../../zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service'; +import { AuthModule } from '../../../bri/auth/auth.module'; +import { LoggingModule } from '../../../shared/logging/logging.module'; import { PrismaMapper } from '../../../shared/prisma/prisma.mapper'; import { PrismaService } from '../../../shared/prisma/prisma.service'; +import { AuthAgent } from '../../auth/agent/auth.agent'; +import { BpiSubjectAccount as BpiSubjectAccountPrismaModel } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; import { BpiSubjectStorageAgent } from '../../identity/bpiSubjects/agents/bpiSubjectsStorage.agent'; -import { LoggingModule } from '../../../shared/logging/logging.module'; -import { NotFoundException } from '@nestjs/common'; -import { NOT_FOUND_ERR_MESSAGE as WORKSTEP_NOT_FOUND_ERR_MESSAGE } from '../../workgroup/worksteps/api/err.messages'; +import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; +import { WorkflowStorageAgent } from '../../workgroup/workflows/agents/workflowsStorage.agent'; import { NOT_FOUND_ERR_MESSAGE as WORKFLOW_NOT_FOUND_ERR_MESSAGE } from '../../workgroup/workflows/api/err.messages'; -import { AuthModule } from '../../../bri/auth/auth.module'; -import { AutomapperModule } from '@automapper/nestjs'; -import { classes } from '@automapper/classes'; -import { uuid } from 'uuidv4'; +import { WorkstepStorageAgent } from '../../workgroup/worksteps/agents/workstepsStorage.agent'; +import { NOT_FOUND_ERR_MESSAGE as WORKSTEP_NOT_FOUND_ERR_MESSAGE } from '../../workgroup/worksteps/api/err.messages'; +import { CircuitInputsParserService } from '../../zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service'; +import { SnarkjsCircuitService } from '../../zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service'; +import { ZeroKnowledgeProofModule } from '../../zeroKnowledgeProof/zeroKnowledgeProof.module'; +import { Transaction } from '../models/transaction'; +import { TransactionStatus } from '../models/transactionStatus.enum'; +import { TransactionAgent } from './transactions.agent'; +import { TransactionStorageAgent } from './transactionStorage.agent'; let agent: TransactionAgent; let authAgent: AuthAgent; @@ -66,6 +67,7 @@ beforeEach(async () => { provide: 'ICircuitService', useClass: SnarkjsCircuitService, }, + CircuitInputsParserService, ], }) .overrideProvider(PrismaService) diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts index f70efccc9..e5bd34a54 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts @@ -7,21 +7,25 @@ import { import { Transaction } from '../models/transaction'; import { TransactionStatus } from '../models/transactionStatus.enum'; +import MerkleTree from 'merkletreejs'; +import { Witness } from 'src/bri/zeroKnowledgeProof/models/witness'; import { AuthAgent } from '../../auth/agent/auth.agent'; import { BpiSubjectAccount } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; +import { PublicKeyType } from '../../identity/bpiSubjects/models/publicKey'; import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; import { WorkflowStorageAgent } from '../../workgroup/workflows/agents/workflowsStorage.agent'; import { WorkstepStorageAgent } from '../../workgroup/worksteps/agents/workstepsStorage.agent'; import { Workstep } from '../../workgroup/worksteps/models/workstep'; +import { CircuitInputsParserService } from '../../zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service'; import { ICircuitService } from '../../zeroKnowledgeProof/services/circuit/circuitService.interface'; +import { computeEddsaSigPublicInputs } from '../../zeroKnowledgeProof/services/circuit/snarkjs/utils/computePublicInputs'; import { DELETE_WRONG_STATUS_ERR_MESSAGE, NOT_FOUND_ERR_MESSAGE, UPDATE_WRONG_STATUS_ERR_MESSAGE, } from '../api/err.messages'; -import { TransactionStorageAgent } from './transactionStorage.agent'; import { TransactionResult } from '../models/transactionResult'; -import { PublicKeyType } from '../../identity/bpiSubjects/models/publicKey'; +import { TransactionStorageAgent } from './transactionStorage.agent'; @Injectable() export class TransactionAgent { @@ -33,6 +37,7 @@ export class TransactionAgent { private merkleTreeService: MerkleTreeService, @Inject('ICircuitService') private readonly circuitService: ICircuitService, + private circuitInputsParserService: CircuitInputsParserService, ) {} public throwIfCreateTransactionInputInvalid() { @@ -179,14 +184,12 @@ export class TransactionAgent { ): Promise { const txResult = new TransactionResult(); - const merkelizedPayload = this.merkleTreeService.merkelizePayload( + txResult.merkelizedPayload = this.merkleTreeService.merkelizePayload( JSON.parse(tx.payload), `${process.env.MERKLE_TREE_HASH_ALGH}`, ); - txResult.merkelizedPayload = merkelizedPayload; const { - snakeCaseWorkstepName, circuitProvingKeyPath, circuitVerificatioKeyPath, circuitPath, @@ -195,8 +198,10 @@ export class TransactionAgent { } = this.constructCircuitPathsFromWorkstepName(workstep.name); txResult.witness = await this.circuitService.createWitness( - { tx, merkelizedPayload }, - snakeCaseWorkstepName, + await this.prepareCircuitInputs( + tx, + workstep.circuitInputsTranslationSchema, + ), circuitPath, circuitProvingKeyPath, circuitVerificatioKeyPath, @@ -204,17 +209,9 @@ export class TransactionAgent { circuitWitnessFilePath, ); - const hashFn = this.merkleTreeService.createHashFunction( - `${process.env.MERKLE_TREE_HASH_ALGH}`, - ); - - const merkelizedInvoiceRoot = merkelizedPayload.getRoot().toString('hex'); - const witnessHash = hashFn(JSON.stringify(txResult.witness)).toString( - 'hex', - ); - - txResult.hash = hashFn(`${merkelizedInvoiceRoot}${witnessHash}`).toString( - 'hex', + txResult.hash = this.constructTxHash( + txResult.merkelizedPayload, + txResult.witness, ); return txResult; @@ -225,7 +222,6 @@ export class TransactionAgent { // Format is: /_. // Will be ditched completely as part of milestone 5. private constructCircuitPathsFromWorkstepName(name: string): { - snakeCaseWorkstepName: string; circuitProvingKeyPath: string; circuitVerificatioKeyPath: string; circuitPath: string; @@ -270,7 +266,6 @@ export class TransactionAgent { snakeCaseWorkstepName + '/witness.txt'; return { - snakeCaseWorkstepName, circuitProvingKeyPath, circuitVerificatioKeyPath, circuitPath, @@ -279,10 +274,7 @@ export class TransactionAgent { }; } - // TODO: #744 ChatGPT generated only for the purposes of temporary convention - // to connect worksteps with circuits on the file system. private convertStringToSnakeCase(name: string): string { - // Remove any leading or trailing spaces name = name.trim(); // Replace spaces, hyphens, and underscores with a single underscore @@ -299,4 +291,86 @@ export class TransactionAgent { return name; } + + private async prepareCircuitInputs( + tx: Transaction, + circuitInputsTranslationSchema: string, + ): Promise { + const payloadAsCircuitInputs = await this.preparePayloadAsCircuitInputs( + tx.payload, + circuitInputsTranslationSchema, + ); + + return Object.assign( + payloadAsCircuitInputs, + await computeEddsaSigPublicInputs(tx), + ); + } + + private async preparePayloadAsCircuitInputs( + txPayload: string, + workstepTranslationSchema: string, + ): Promise { + const mapping: CircuitInputsMapping = JSON.parse(workstepTranslationSchema); + + if (!mapping) { + throw new Error(`Broken mapping`); + } + + const parsedInputs = + this.circuitInputsParserService.applyMappingToJSONPayload( + txPayload, + mapping, + ); + if (!parsedInputs) { + throw new Error(`Failed to parse inputs`); + } + + return parsedInputs; + } + + private constructTxHash( + merkelizedPayload: MerkleTree, + witness: Witness, + ): string { + const hashFn = this.merkleTreeService.createHashFunction( + `${process.env.MERKLE_TREE_HASH_ALGH}`, + ); + + const merkelizedInvoiceRoot = merkelizedPayload.getRoot().toString('hex'); + const witnessHash = hashFn(JSON.stringify(witness)).toString('hex'); + + return hashFn(`${merkelizedInvoiceRoot}${witnessHash}`).toString('hex'); + } } +// TODO: Example input preparation for other workstep circuits from the example use-case, to be used +// to properly setup dynamic mappings and to delete afterwards +// private async workstep2(inputs: { +// tx: Transaction; +// merkelizedPayload: MerkleTree; +// }): Promise { +// //1. Eddsa signature + +// const payload = JSON.parse(inputs.tx.payload); + +// const preparedInputs = { +// invoiceStatus: payload.status, +// }; + +// return preparedInputs; +// } + +// private async workstep3(inputs: { +// tx: Transaction; +// merkelizedPayload: MerkleTree; +// }): Promise { +// //1. Eddsa signature + +// const payload = JSON.parse(inputs.tx.payload); + +// const preparedInputs = { +// invoiceStatus: payload.status, +// }; + +// return preparedInputs; +// } diff --git a/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts b/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts index 01da6b495..8c48782bc 100644 --- a/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts +++ b/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts @@ -6,17 +6,24 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DeepMockProxy, mockDeep } from 'jest-mock-extended'; import { validate as uuidValidate, version as uuidVersion } from 'uuid'; import { uuid } from 'uuidv4'; +import { LoggingModule } from '../../../shared/logging/logging.module'; import { AuthAgent } from '../../auth/agent/auth.agent'; import { BpiSubjectAccountAgent } from '../../identity/bpiSubjectAccounts/agents/bpiSubjectAccounts.agent'; import { BpiSubjectAccountStorageAgent } from '../../identity/bpiSubjectAccounts/agents/bpiSubjectAccountsStorage.agent'; import { BpiSubjectAccount } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; import { BpiSubjectStorageAgent } from '../../identity/bpiSubjects/agents/bpiSubjectsStorage.agent'; import { BpiSubject } from '../../identity/bpiSubjects/models/bpiSubject'; +import { + PublicKey, + PublicKeyType, +} from '../../identity/bpiSubjects/models/publicKey'; +import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; import { WorkflowStorageAgent } from '../../workgroup/workflows/agents/workflowsStorage.agent'; import { WorkstepStorageAgent } from '../../workgroup/worksteps/agents/workstepsStorage.agent'; +import { CircuitInputsParserService } from '../../zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service'; import { SnarkjsCircuitService } from '../../zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service'; -import { TransactionStorageAgent } from '../agents/transactionStorage.agent'; import { TransactionAgent } from '../agents/transactions.agent'; +import { TransactionStorageAgent } from '../agents/transactionStorage.agent'; import { CreateTransactionCommandHandler } from '../capabilities/createTransaction/createTransactionCommand.handler'; import { DeleteTransactionCommandHandler } from '../capabilities/deleteTransaction/deleteTransactionCommand.handler'; import { GetTransactionByIdQueryHandler } from '../capabilities/getTransactionById/getTransactionByIdQuery.handler'; @@ -28,11 +35,6 @@ import { CreateTransactionDto } from './dtos/request/createTransaction.dto'; import { UpdateTransactionDto } from './dtos/request/updateTransaction.dto'; import { NOT_FOUND_ERR_MESSAGE } from './err.messages'; import { TransactionController } from './transactions.controller'; -import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; -import { - PublicKey, - PublicKeyType, -} from '../../identity/bpiSubjects/models/publicKey'; describe('TransactionController', () => { let controller: TransactionController; @@ -84,6 +86,7 @@ describe('TransactionController', () => { AutomapperModule.forRoot({ strategyInitializer: classes(), }), + LoggingModule, ], controllers: [TransactionController], providers: [ @@ -105,6 +108,7 @@ describe('TransactionController', () => { provide: 'ICircuitService', useClass: SnarkjsCircuitService, }, + CircuitInputsParserService, ], }) .overrideProvider(TransactionStorageAgent) diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.spec.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.spec.ts index de452a9af..0490323c6 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.spec.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.spec.ts @@ -388,4 +388,66 @@ describe('CircuitInputsParserService', () => { // Assert expect(circuitInputs).toStrictEqual({ dascircuitinput: [387, 388, 389] }); }); + + it('Should generate a single circuit input param based on a object string property of an object array at root level', () => { + // Arrange + const payload = `{ + "supplierInvoiceIDs": [ + { "id": "INV123", "price" : 222 }, + { "id": "INV124", "price" : 223 }, + { "id": "INV125", "price" : 224 } + ] + }`; + + const schema = { + mapping: [ + { + circuitInput: 'dascircuitinput', + description: 'desc', + payloadJsonPath: 'supplierInvoiceIDs', + dataType: 'array', + arrayType: 'object', + arrayItemFieldName: 'id', + arrayItemFieldType: 'string', + } as CircuitInputMapping, + ], + } as CircuitInputsMapping; + + // Act + const circuitInputs = cips.applyMappingToJSONPayload(payload, schema); + + // Assert + expect(circuitInputs).toStrictEqual({ dascircuitinput: [387, 388, 389] }); + }); + + it('Should generate a single circuit input param based on a object integer property of an object array at root level', () => { + // Arrange + const payload = `{ + "supplierInvoiceIDs": [ + { "id": "1", "price" : 222 }, + { "id": "2", "price" : 223 }, + { "id": "3", "price" : 224 } + ] + }`; + + const schema = { + mapping: [ + { + circuitInput: 'dascircuitinput', + description: 'desc', + payloadJsonPath: 'supplierInvoiceIDs', + dataType: 'array', + arrayType: 'object', + arrayItemFieldName: 'price', + arrayItemFieldType: 'integer', + } as CircuitInputMapping, + ], + } as CircuitInputsMapping; + + // Act + const circuitInputs = cips.applyMappingToJSONPayload(payload, schema); + + // Assert + expect(circuitInputs).toStrictEqual({ dascircuitinput: [222, 223, 224] }); + }); }); diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts index 63da30b5f..f226d4da0 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts @@ -94,7 +94,24 @@ export class CircuitInputsParserService { } if (mapping.arrayType === 'object') { - // TODO + if (mapping.arrayItemFieldName && mapping.arrayItemFieldType) { + result[mapping.circuitInput] = value + ? value.map((item) => { + const fieldValue = item[mapping.arrayItemFieldName!]; + if (mapping.arrayItemFieldType === 'integer') { + return parseInt(fieldValue, 10); + } else if (mapping.arrayItemFieldType === 'string') { + return this.calculateStringCharCodeSum(fieldValue); + } + return fieldValue; + }) + : mapping.defaultValue; + } else { + this.logger.logError( + `Missing arrayItemFieldName or arrayItemFieldType for object array mapping ${mapping.circuitInput}`, + ); + return null; + } } break; default: diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputsMapping.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputsMapping.ts index ec0e1a510..1d9a50e35 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputsMapping.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputsMapping.ts @@ -9,4 +9,6 @@ type CircuitInputMapping = { dataType: string; defaultValue?: any; arrayType?: string; + arrayItemFieldName?: string; + arrayItemFieldType?: string; }; diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitService.interface.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitService.interface.ts index 6eb3b4446..b202280f4 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitService.interface.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitService.interface.ts @@ -1,14 +1,15 @@ import { Witness } from '../../models/witness'; +import { Transaction } from '../../../transactions/models/transaction'; export interface ICircuitService { createWitness( - inputs: object, - circuitName: string, + circuitInputs: object, pathToCircuit: string, pathToProvingKey: string, pathToVerificationKey: string, pathToWitnessCalculator?: string, pathToWitnessFile?: string, ): Promise; + verifyProofUsingWitness(witness: Witness): Promise; } diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.spec.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.spec.ts index d0fe6a374..21d41aad6 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.spec.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.spec.ts @@ -18,17 +18,12 @@ import { } from '../../../../identity/bpiSubjects/models/publicKey'; jest.setTimeout(20000); +//NOTE: Skiping out the workstep1 as it requires compiled artifacts to run. describe.skip('SnarkjsService', () => { const snarkjs = new SnarkjsCircuitService(); - let inputs: any; + let tx: Transaction; let witness: Witness; - //REMOVE THIS TEST: Empty test - it('this is empty test', () => { - expect('test').toBe('test'); - }); - - //NOTE: Commenting out the workstep1 as it requires compiled artifacts to run. RUN THIS. beforeAll(async () => { const eddsa = await circomlib.buildEddsa(); const babyJub = await circomlib.buildBabyjub(); @@ -112,7 +107,7 @@ describe.skip('SnarkjsService', () => { const packedSignature = eddsa.packSignature(eddsaSignature); const signature = Buffer.from(packedSignature).toString('hex'); - const tx: Transaction = new Transaction( + tx = new Transaction( '123', 12, '123', @@ -123,8 +118,6 @@ describe.skip('SnarkjsService', () => { signature, TransactionStatus.Initialized, ); - - inputs = { tx }; }); it('creates witness for workstep1', async () => { @@ -141,8 +134,7 @@ describe.skip('SnarkjsService', () => { './zeroKnowledgeArtifacts/circuits/workstep1/witness.txt'; witness = await snarkjs.createWitness( - inputs, - circuitName, + 'TODO: circuitInputs' as unknown as object, pathToCircuit, pathToProvingKey, pathToVerificationKey, diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.ts index 549c6f3be..951acfd31 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service.ts @@ -2,10 +2,7 @@ import { Injectable, BadRequestException } from '@nestjs/common'; import { Witness } from '../../../models/witness'; import { Proof } from '../../../models/proof'; import { ICircuitService } from '../circuitService.interface'; -import { computeEddsaSigPublicInputs } from './utils/computePublicInputs'; import * as snarkjs from 'snarkjs'; -import { Transaction } from '../../../../transactions/models/transaction'; -import MerkleTree from 'merkletreejs'; import * as fs from 'fs'; @Injectable() @@ -21,11 +18,7 @@ export class SnarkjsCircuitService implements ICircuitService { } public async createWitness( - inputs: { - tx: Transaction; - merkelizedPayload: MerkleTree; - }, - circuitName: string, + circuitInputs: object, pathToCircuit: string, pathToProvingKey: string, pathToVerificationKey: string, @@ -34,10 +27,8 @@ export class SnarkjsCircuitService implements ICircuitService { ): Promise { this.witness = new Witness(); - const preparedInputs = await this.prepareInputs(inputs, circuitName); - const { proof, publicInputs } = await this.executeCircuit( - preparedInputs, + circuitInputs, pathToCircuit, pathToProvingKey, pathToWitnessCalculator, @@ -100,97 +91,4 @@ export class SnarkjsCircuitService implements ICircuitService { return { proof: newProof, publicInputs }; } - - private async prepareInputs( - inputs: { - tx: Transaction; - merkelizedPayload: MerkleTree; - }, - circuitName: string, - ): Promise { - return await this[circuitName](inputs); - } - - // TODO: Mil5 - How to parametrize this for different use-cases? - private async workstep1(inputs: { - tx: Transaction; - merkelizedPayload: MerkleTree; - }): Promise { - //1. Ecdsa signature - const { message, A, R8, S } = await computeEddsaSigPublicInputs(inputs.tx); - - //2. Items - const payload = JSON.parse(inputs.tx.payload); - - const itemPrices: number[] = []; - const itemAmount: number[] = []; - - payload.items.forEach((item: object) => { - itemPrices.push(item['price']); - itemAmount.push(item['amount']); - }); - - const preparedInputs = { - invoiceStatus: this.calculateStringCharCodeSum(payload.status), - invoiceAmount: payload.amount, - itemPrices, - itemAmount, - message, - A, - R8, - S, - }; - - return preparedInputs; - } - - private async workstep2(inputs: { - tx: Transaction; - merkelizedPayload: MerkleTree; - }): Promise { - //1. Eddsa signature - const { message, A, R8, S } = await computeEddsaSigPublicInputs(inputs.tx); - - const payload = JSON.parse(inputs.tx.payload); - - const preparedInputs = { - invoiceStatus: payload.status, - message, - A, - R8, - S, - }; - - return preparedInputs; - } - - private async workstep3(inputs: { - tx: Transaction; - merkelizedPayload: MerkleTree; - }): Promise { - //1. Eddsa signature - const { message, A, R8, S } = await computeEddsaSigPublicInputs(inputs.tx); - - const payload = JSON.parse(inputs.tx.payload); - - const preparedInputs = { - invoiceStatus: payload.status, - message, - A, - R8, - S, - }; - - return preparedInputs; - } - - private calculateStringCharCodeSum(status: string): number { - let sum = 0; - - for (let i = 0; i < status.length; i++) { - sum += status.charCodeAt(i); - } - - return sum; - } } diff --git a/examples/bri-3/test/sriUseCase.e2e-spec.ts b/examples/bri-3/test/sriUseCase.e2e-spec.ts index a97e01505..c7cb13c84 100644 --- a/examples/bri-3/test/sriUseCase.e2e-spec.ts +++ b/examples/bri-3/test/sriUseCase.e2e-spec.ts @@ -141,8 +141,40 @@ describe('SRI use-case end-to-end test', () => { }); it('Add a circuit input translation schema to a workstep', async () => { - const schema = - '{"mapping": [{"circuitInput": "input1", "description": "desc1", "payloadJsonPath": "path1", "dataType": "string"}]}'; + const schema = `{ + "mapping": [ + { + "circuitInput": "invoiceStatus", + "description": "Invoice status", + "payloadJsonPath": "status", + "dataType": "string" + }, + { + "circuitInput": "invoiceAmount", + "description": "Total gross amount of the invoice", + "payloadJsonPath": "amount", + "dataType": "integer" + }, + { + "circuitInput": "itemPrices", + "description": "Invoice item prices", + "payloadJsonPath": "items", + "dataType": "array", + "arrayType": "object", + "arrayItemFieldName": "price", + "arrayItemFieldType": "integer" + }, + { + "circuitInput": "itemAmount", + "description": "Invoice item amounts", + "payloadJsonPath": "items", + "dataType": "array", + "arrayType": "object", + "arrayItemFieldName": "amount", + "arrayItemFieldType": "integer" + } + ] + }`; await addCircuitInputsSchema(createdWorkstepId, schema); });