diff --git a/.github/workflows/bri-3.yml b/.github/workflows/bri-3.yml index ae33b3122..507b47234 100644 --- a/.github/workflows/bri-3.yml +++ b/.github/workflows/bri-3.yml @@ -46,9 +46,9 @@ jobs: DID_REGISTRY: "0x03d5003bf0e79c5f5223588f347eba39afbc3818" DID_BPI_OPERATOR_PUBLIC_KEY: "0x08872e27BC5d78F1FC4590803369492868A1FCCb" DID_BPI_OPERATOR_PRIVATE_KEY: "2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58" - CCSM_NETWORK: "sepolia" + CCSM_NETWORK: "localhost" INFURA_PROVIDER_API_KEY: "c5f37cd25eca4007a9768f18f492bc6f" - CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS: "" + CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS: "0x1CC96ba639d4fd7624913fde39122270a1aC5c34" SERVICE_URL: "bri-3" BPI_NATS_SERVER_URL: "localhost:4222" BPI_NATS_SERVER_USER: "bpi_operator" diff --git a/examples/bri-3/.env.sample b/examples/bri-3/.env.sample index 2b304f035..4bb6d335e 100644 --- a/examples/bri-3/.env.sample +++ b/examples/bri-3/.env.sample @@ -8,9 +8,9 @@ DATABASE_URL="postgresql://postgres:example@localhost:5432/postgres" # DB connec DID_REGISTRY="0x03d5003bf0e79c5f5223588f347eba39afbc3818" # Sepolia did registry https://sepolia.etherscan.io/address/0x03d5003bf0e79c5f5223588f347eba39afbc3818#code DID_BPI_OPERATOR_PUBLIC_KEY="" # bpi_operator_public_key = public key of the bpi operator that represents the issuer of the JWT token DID_BPI_OPERATOR_PRIVATE_KEY="" # bpi_operator_private_key = private key of the bpi operator that is used to sign the issued JWT token -CCSM_NETWORK="sepolia" # network used to resolve dids and connect to BPI smart contract +CCSM_NETWORK="localhost" # network used to connect to BPI smart contract INFURA_PROVIDER_API_KEY="" # API key of the infura account used to connect to the network -CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS="" # address of the smart contract where CAHs are stored +CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS="" # address of the smart contract where CAHs are stored (0x1CC96ba639d4fd7624913fde39122270a1aC5c34 for local hardhat node) SERVICE_URL="bri-3" # JWT token audience BPI_NATS_SERVER_URL="localhost:4222" # URL of the local NATS server instance used by the BPI BPI_NATS_SERVER_USER="bpi_operator" diff --git a/examples/bri-3/ccsm/contracts/CcsmBpiStateAnchor.sol b/examples/bri-3/ccsm/contracts/CcsmBpiStateAnchor.sol index 6b5f87001..a3f49a36e 100644 --- a/examples/bri-3/ccsm/contracts/CcsmBpiStateAnchor.sol +++ b/examples/bri-3/ccsm/contracts/CcsmBpiStateAnchor.sol @@ -26,8 +26,8 @@ contract CcsmBpiStateAnchor is AccessControl { 'WorkstepInstanceId cannot be empty' ); require( - bytes(_workstepInstanceId).length < 36, - 'WorkstepInstanceId cannot exceed 36 bytes' + bytes(_workstepInstanceId).length < 40, + 'WorkstepInstanceId cannot exceed 40 bytes' ); require(bytes(_anchorHash).length > 0, 'AnchorHash cannot be empty'); require( diff --git a/examples/bri-3/ccsm/hardhat.config.ts b/examples/bri-3/ccsm/hardhat.config.ts index a3bacc505..274cb99ab 100644 --- a/examples/bri-3/ccsm/hardhat.config.ts +++ b/examples/bri-3/ccsm/hardhat.config.ts @@ -2,9 +2,12 @@ import { HardhatUserConfig } from 'hardhat/config'; import '@nomicfoundation/hardhat-toolbox'; const config: HardhatUserConfig = { - solidity: '0.8.24', - defaultNetwork: 'hardhat', + solidity: "0.8.24", + defaultNetwork: "localhost", networks: { + localhost: { + url: "http://127.0.0.1:8545", + }, sepolia: { url: 'https://sepolia.infura.io/v3/' + process.env.INFURA_PROVIDER_API_KEY, diff --git a/examples/bri-3/ccsm/scripts/deploy.ts b/examples/bri-3/ccsm/scripts/deploy.ts index 9972289cc..ae7de1334 100644 --- a/examples/bri-3/ccsm/scripts/deploy.ts +++ b/examples/bri-3/ccsm/scripts/deploy.ts @@ -1,13 +1,21 @@ const hre = require("hardhat"); async function main() { - const [owner, adminAccount] = await hre.ethers.getSigners(); + const [originalOwner] = await hre.ethers.getSigners(); + + const ownerAndAdminPrivateKey = "2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58"; + const ownerAndAdmin = new hre.ethers.Wallet(ownerAndAdminPrivateKey, hre.ethers.provider); + + await originalOwner.sendTransaction({ + to: ownerAndAdmin.address, + value: hre.ethers.parseEther("1.0") + }); const CcsmBpiStateAnchor = await hre.ethers.getContractFactory("CcsmBpiStateAnchor"); - const ccsmBpiStateAnchor = await CcsmBpiStateAnchor.deploy([ - await owner.getAddress(), - await adminAccount.getAddress(), + const ccsmBpiStateAnchor = await CcsmBpiStateAnchor.connect(ownerAndAdmin).deploy([ + ownerAndAdmin.address, + ownerAndAdmin.address, ]); console.log("CcsmBpiStateAnchor deployed to:", await ccsmBpiStateAnchor.getAddress()); diff --git a/examples/bri-3/src/bri/auth/agent/auth.agent.ts b/examples/bri-3/src/bri/auth/agent/auth.agent.ts index f3233904c..24b07f946 100644 --- a/examples/bri-3/src/bri/auth/agent/auth.agent.ts +++ b/examples/bri-3/src/bri/auth/agent/auth.agent.ts @@ -130,7 +130,7 @@ export class AuthAgent { }; const serviceDid = - `did:ethr:${process.env.CCSM_NETWORK}:${process.env.DID_BPI_OPERATOR_PUBLIC_KEY}` as string; + `did:ethr:sepolia:${process.env.DID_BPI_OPERATOR_PUBLIC_KEY}` as string; const privateKey = process.env.DID_BPI_OPERATOR_PRIVATE_KEY as string; const serviceSigner = ES256KSigner(hexToBytes(privateKey)); diff --git a/examples/bri-3/src/bri/ccsm/agents/ccsmStorage.agent.ts b/examples/bri-3/src/bri/ccsm/agents/ccsmStorage.agent.ts index cfb547c25..bffd475b0 100644 --- a/examples/bri-3/src/bri/ccsm/agents/ccsmStorage.agent.ts +++ b/examples/bri-3/src/bri/ccsm/agents/ccsmStorage.agent.ts @@ -4,11 +4,14 @@ import { ICcsmService } from '../services/ccsm.interface'; @Injectable() export class CcsmStorageAgent { constructor( - @Inject('IBlockchainService') + @Inject('ICcsmService') private readonly ccsmService: ICcsmService, ) {} - async storeAnchorHashOnCcsm(anchorHash: string): Promise { - await this.ccsmService.storeAnchorHash('Ccsm', anchorHash); + async storeAnchorHashOnCcsm( + workstepInstanceId: string, + anchorHash: string, + ): Promise { + await this.ccsmService.storeAnchorHash(workstepInstanceId, anchorHash); } } diff --git a/examples/bri-3/src/bri/ccsm/ccsm.module.ts b/examples/bri-3/src/bri/ccsm/ccsm.module.ts index c36c42d68..78603ac1a 100644 --- a/examples/bri-3/src/bri/ccsm/ccsm.module.ts +++ b/examples/bri-3/src/bri/ccsm/ccsm.module.ts @@ -6,10 +6,10 @@ import { EthereumService } from './services/ethereum.service'; providers: [ CcsmStorageAgent, { - provide: 'IBlockchainService', + provide: 'ICcsmService', useClass: EthereumService, }, ], - exports: [CcsmStorageAgent, 'IBlockchainService'], + exports: [CcsmStorageAgent, 'ICcsmService'], }) export class CcsmModule {} diff --git a/examples/bri-3/src/bri/ccsm/services/ethereum.service.ts b/examples/bri-3/src/bri/ccsm/services/ethereum.service.ts index 005eebe7c..3997b8292 100644 --- a/examples/bri-3/src/bri/ccsm/services/ethereum.service.ts +++ b/examples/bri-3/src/bri/ccsm/services/ethereum.service.ts @@ -5,6 +5,7 @@ import { Contract, ethers, InfuraProvider, + JsonRpcProvider, Provider, SigningKey, } from 'ethers'; @@ -18,15 +19,18 @@ export class EthereumService implements ICcsmService { private wallet: BaseWallet; constructor() { - // TOOD: This should be environment agnostic, meanning it can worok both against - // local hardhat node, sepolia and mainnet - this.provider = new InfuraProvider( - process.env.CCSM_NETWORK, - process.env.INFURA_PROVIDER_API_KEY, - ); + const network = process.env.CCSM_NETWORK; - const signingKey = new SigningKey('0x' + internalBpiSubjectEcdsaPrivateKey); + if (network === 'localhost') { + this.provider = new JsonRpcProvider('http://127.0.0.1:8545'); + } else { + this.provider = new InfuraProvider( + network, + process.env.INFURA_PROVIDER_API_KEY, + ); + } + const signingKey = new SigningKey(internalBpiSubjectEcdsaPrivateKey); this.wallet = new BaseWallet(signingKey, this.provider); } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/services/did.service.ts b/examples/bri-3/src/bri/identity/bpiSubjects/services/did.service.ts index 251e45b3f..78586376e 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/services/did.service.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/services/did.service.ts @@ -5,14 +5,18 @@ import { getResolver } from 'ethr-did-resolver'; import 'dotenv/config'; export class DidService { + // TODO: Hardcoded sepolia everywhere for DID resolution + // This should be taken from the CCSM_NETWORK env value and + // the service refactored to connect to locahost as well, + // with previous deployment of a did registry to local node. async createKeypair(): Promise { - const keypair = EthrDID.createKeyPair(process.env.CCSM_NETWORK); + const keypair = EthrDID.createKeyPair('sepolia'); return keypair; } async createProvider(): Promise { const provider = new InfuraProvider( - process.env.CCSM_NETWORK, + 'sepolia', process.env.INFURA_PROVIDER_API_KEY, ); return provider; @@ -22,7 +26,7 @@ export class DidService { const did = new EthrDID({ identifier: process.env.DID_BPI_OPERATOR_PUBLIC_KEY as string, provider, - chainNameOrId: process.env.CCSM_NETWORK, + chainNameOrId: 'sepolia', registry: process.env.DID_REGISTRY, }); return did; @@ -31,10 +35,10 @@ export class DidService { async getDidResolver(provider): Promise { const didResolver = new Resolver({ ...getResolver({ - name: process.env.CCSM_NETWORK, + name: 'sepolia', provider: provider, registry: process.env.DID_REGISTRY, - chainId: process.env.CCSM_NETWORK, + chainId: 'sepolia', }), }); diff --git a/examples/bri-3/src/bri/transactions/agents/transactionStorage.agent.ts b/examples/bri-3/src/bri/transactions/agents/transactionStorage.agent.ts index 7e01fa2f5..c4f7d0e07 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactionStorage.agent.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactionStorage.agent.ts @@ -131,7 +131,9 @@ export class TransactionStorageAgent { return this.mapper.map(newTransactionModel, Transaction); } - async updateTransaction(transaction: Transaction): Promise { + async updateTransactionPayload( + transaction: Transaction, + ): Promise { const updatedTransactionModel = await this.prisma.transaction.update({ where: { id: transaction.id }, data: { @@ -143,15 +145,15 @@ export class TransactionStorageAgent { return this.mapper.map(updatedTransactionModel, Transaction); } - async updateTransactionStatus( - transaction: Transaction, - ): Promise { + async updateTransaction(transaction: Transaction): Promise { const updatedTransaction = await this.prisma.transaction.update({ where: { id: transaction.id, }, data: { status: transaction.status, + workflowInstanceId: transaction.workflowInstanceId, + workstepInstanceId: transaction.workstepInstanceId, }, }); 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 090239a7a..a72e35382 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts @@ -185,15 +185,6 @@ export class TransactionAgent { ): Promise { const txResult = new TransactionResult(); - //Generate and store workflowInstanceId & workstepInstanceId - const workflowInstanceId = v4(); - const workstepInstanceId = v4(); - - tx.updateWorkflowInstanceId(workflowInstanceId); - tx.updateWorkstepInstanceId(workstepInstanceId); - - this.txStorageAgent.updateTransaction(tx); - txResult.merkelizedPayload = this.merkleTreeService.merkelizePayload( JSON.parse(tx.payload), `${process.env.MERKLE_TREE_HASH_ALGH}`, 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 7fccfd58d..61416e5c2 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 @@ -251,7 +251,7 @@ describe('TransactionController', () => { signature: 'signature2', } as UpdateTransactionDto; - transactionStorageAgentMock.updateTransaction.mockRejectedValueOnce( + transactionStorageAgentMock.updateTransactionPayload.mockRejectedValueOnce( undefined, ); // Act and assert @@ -285,11 +285,13 @@ describe('TransactionController', () => { signature: 'signature2', } as UpdateTransactionDto; - transactionStorageAgentMock.updateTransaction.mockResolvedValueOnce({ - ...existingTransaction, - payload: updateRequestDto.payload, - signature: updateRequestDto.signature, - } as Transaction); + transactionStorageAgentMock.updateTransactionPayload.mockResolvedValueOnce( + { + ...existingTransaction, + payload: updateRequestDto.payload, + signature: updateRequestDto.signature, + } as Transaction, + ); // Act const updatedTransaction = await controller.updateTransaction( diff --git a/examples/bri-3/src/bri/transactions/capabilities/updateTransaction/updateTransactionCommand.handler.ts b/examples/bri-3/src/bri/transactions/capabilities/updateTransaction/updateTransactionCommand.handler.ts index 022c86d18..1a2b55bef 100644 --- a/examples/bri-3/src/bri/transactions/capabilities/updateTransaction/updateTransactionCommand.handler.ts +++ b/examples/bri-3/src/bri/transactions/capabilities/updateTransaction/updateTransactionCommand.handler.ts @@ -29,7 +29,7 @@ export class UpdateTransactionCommandHandler command.signature, ); - const updatedTransaction = await this.storageAgent.updateTransaction( + const updatedTransaction = await this.storageAgent.updateTransactionPayload( transactionToUpdate, ); diff --git a/examples/bri-3/src/bri/transactions/models/transaction.ts b/examples/bri-3/src/bri/transactions/models/transaction.ts index dee4d8a15..38a42f6dc 100644 --- a/examples/bri-3/src/bri/transactions/models/transaction.ts +++ b/examples/bri-3/src/bri/transactions/models/transaction.ts @@ -2,6 +2,7 @@ import { TransactionStatus } from './transactionStatus.enum'; import { AutoMap } from '@automapper/classes'; import { BpiSubjectAccount } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; import { InternalServerErrorException } from '@nestjs/common'; +import { v4 } from 'uuid'; export class Transaction { @AutoMap() @@ -67,13 +68,6 @@ export class Transaction { this.status = status; } - public updateWorkflowInstanceId(workflowInstanceId: string): void { - this.workflowInstanceId = workflowInstanceId; - } - - public updateWorkstepInstanceId(workstepInstanceId: string): void { - this.workstepInstanceId = workstepInstanceId; - } public updatePayload(payload: string, signature: string): void { // TODO: Verify signature this.payload = payload; @@ -91,6 +85,8 @@ export class Transaction { } this.status = TransactionStatus.Processing; + this.workflowInstanceId = v4(); + this.workstepInstanceId = v4(); } public updateStatusToInvalid(): void { diff --git a/examples/bri-3/src/bri/vsm/capabilites/executeVsmCycle/executeVsmCycleCommand.handler.ts b/examples/bri-3/src/bri/vsm/capabilites/executeVsmCycle/executeVsmCycleCommand.handler.ts index 18a1aceab..85add4af9 100644 --- a/examples/bri-3/src/bri/vsm/capabilites/executeVsmCycle/executeVsmCycleCommand.handler.ts +++ b/examples/bri-3/src/bri/vsm/capabilites/executeVsmCycle/executeVsmCycleCommand.handler.ts @@ -33,14 +33,14 @@ export class ExecuteVsmCycleCommandHandler // TODO: When do we update the nonce on the BpiAccount? // Whenever a transaction is initiated executionCandidates.forEach(async (tx) => { tx.updateStatusToProcessing(); - await this.txStorageAgent.updateTransactionStatus(tx); + await this.txStorageAgent.updateTransaction(tx); if (!this.txAgent.validateTransactionForExecution(tx)) { this.eventBus.publish( new WorkstepExecutedEvent(tx, 'Validation Error'), ); tx.updateStatusToInvalid(); - await this.txStorageAgent.updateTransactionStatus(tx); + await this.txStorageAgent.updateTransaction(tx); return; } @@ -67,15 +67,17 @@ export class ExecuteVsmCycleCommandHandler stateTreeRoot, ); - //TODO - Implement deploy and store on CCSM - //await this.ccsmStorageAgent.storeAnchorHashOnCcsm(txResult.hash); + await this.ccsmStorageAgent.storeAnchorHashOnCcsm( + tx.workstepInstanceId, + txResult.hash, + ); tx.updateStatusToExecuted(); - this.txStorageAgent.updateTransactionStatus(tx); + this.txStorageAgent.updateTransaction(tx); } catch (error) { this.eventBus.publish(new WorkstepExecutedEvent(tx, error)); tx.updateStatusToAborted(); - this.txStorageAgent.updateTransactionStatus(tx); + this.txStorageAgent.updateTransaction(tx); return; } diff --git a/examples/bri-3/src/bri/vsm/vsm.module.ts b/examples/bri-3/src/bri/vsm/vsm.module.ts index 499ff3fef..c9f738ff1 100644 --- a/examples/bri-3/src/bri/vsm/vsm.module.ts +++ b/examples/bri-3/src/bri/vsm/vsm.module.ts @@ -42,7 +42,7 @@ export const QueryHandlers = []; useClass: NatsMessagingClient, }, { - provide: 'IBlockchainService', + provide: 'ICcsmService', useClass: EthereumService, }, ], diff --git a/examples/bri-3/src/shared/testing/constants.ts b/examples/bri-3/src/shared/testing/constants.ts index 751b9f3b5..f0181f93f 100644 --- a/examples/bri-3/src/shared/testing/constants.ts +++ b/examples/bri-3/src/shared/testing/constants.ts @@ -9,4 +9,4 @@ export const buyerBpiSubjectEcdsaPrivateKey = export const internalBpiSubjectEcdsaPublicKey = '0x08872e27BC5d78F1FC4590803369492868A1FCCb'; export const internalBpiSubjectEcdsaPrivateKey = - '2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58'; + '0x2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58'; diff --git a/examples/bri-3/zeroKnowledgeArtifacts/circuits/workstep2/witness.txt b/examples/bri-3/zeroKnowledgeArtifacts/circuits/workstep2/witness.txt index 06ad5e67e..d66b597e7 100644 Binary files a/examples/bri-3/zeroKnowledgeArtifacts/circuits/workstep2/witness.txt and b/examples/bri-3/zeroKnowledgeArtifacts/circuits/workstep2/witness.txt differ