diff --git a/patches/@credo-ts+core+0.5.3+005+commenting validationPresentation to avoid abandoned issue.patch b/patches/@credo-ts+core+0.5.3+005+commenting validationPresentation to avoid abandoned issue.patch new file mode 100644 index 00000000..90cb11dd --- /dev/null +++ b/patches/@credo-ts+core+0.5.3+005+commenting validationPresentation to avoid abandoned issue.patch @@ -0,0 +1,14 @@ +diff --git a/node_modules/@credo-ts/core/build/modules/proofs/formats/dif-presentation-exchange/DifPresentationExchangeProofFormatService.js b/node_modules/@credo-ts/core/build/modules/proofs/formats/dif-presentation-exchange/DifPresentationExchangeProofFormatService.js +index 006d870..da56801 100644 +--- a/node_modules/@credo-ts/core/build/modules/proofs/formats/dif-presentation-exchange/DifPresentationExchangeProofFormatService.js ++++ b/node_modules/@credo-ts/core/build/modules/proofs/formats/dif-presentation-exchange/DifPresentationExchangeProofFormatService.js +@@ -170,7 +170,8 @@ class DifPresentationExchangeProofFormatService { + try { + ps.validatePresentationDefinition(request.presentation_definition); + ps.validatePresentationSubmission(jsonPresentation.presentation_submission); +- ps.validatePresentation(request.presentation_definition, parsedPresentation); ++ // FIXME: Commenting validatePresentation() for now due to intermittent abandoned issue ++ //ps.validatePresentation(request.presentation_definition, parsedPresentation); + let verificationResult; + // FIXME: for some reason it won't accept the input if it doesn't know + // whether it's a JWT or JSON-LD VP even though the input is the same. diff --git a/patches/@credo-ts+core+0.5.3+003+credential-record-debug-patch.patch b/patches/@credo-ts+core+0.5.3+006+w3c-issuance-without-holder-did-negotiaton.patch similarity index 68% rename from patches/@credo-ts+core+0.5.3+003+credential-record-debug-patch.patch rename to patches/@credo-ts+core+0.5.3+006+w3c-issuance-without-holder-did-negotiaton.patch index 129474c4..dcf25eaf 100644 --- a/patches/@credo-ts+core+0.5.3+003+credential-record-debug-patch.patch +++ b/patches/@credo-ts+core+0.5.3+006+w3c-issuance-without-holder-did-negotiaton.patch @@ -1,12 +1,12 @@ diff --git a/node_modules/@credo-ts/core/build/modules/credentials/protocol/v2/V2CredentialProtocol.js b/node_modules/@credo-ts/core/build/modules/credentials/protocol/v2/V2CredentialProtocol.js -index fb1fb9d..260fe21 100644 +index fb1fb9d..b519694 100644 --- a/node_modules/@credo-ts/core/build/modules/credentials/protocol/v2/V2CredentialProtocol.js +++ b/node_modules/@credo-ts/core/build/modules/credentials/protocol/v2/V2CredentialProtocol.js -@@ -444,6 +444,7 @@ class V2CredentialProtocol extends BaseCredentialProtocol_1.BaseCredentialProtoc +@@ -97,7 +97,6 @@ class V2CredentialProtocol extends BaseCredentialProtocol_1.BaseCredentialProtoc let credentialRecord = await this.findByProperties(messageContext.agentContext, { - threadId: requestMessage.threadId, + threadId: proposalMessage.threadId, role: models_1.CredentialRole.Issuer, -+ connectionId: connection?.id +- connectionId: connection === null || connection === void 0 ? void 0 : connection.id, }); - const formatServices = this.getFormatServicesFromMessage(requestMessage.formats); + const formatServices = this.getFormatServicesFromMessage(proposalMessage.formats); if (formatServices.length === 0) { diff --git a/patches/@credo-ts+tenants+0.5.3+001+cache-tenant-record-patch.patch b/patches/@credo-ts+tenants+0.5.3+001+cache-tenant-record-patch.patch new file mode 100644 index 00000000..75e379e8 --- /dev/null +++ b/patches/@credo-ts+tenants+0.5.3+001+cache-tenant-record-patch.patch @@ -0,0 +1,56 @@ +diff --git a/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.d.ts b/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.d.ts +index 91bb8f4..b4dae61 100644 +--- a/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.d.ts ++++ b/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.d.ts +@@ -1,5 +1,5 @@ + import type { TenantRecord } from '../repository'; +-import type { AgentContextProvider, UpdateAssistantUpdateOptions } from '@credo-ts/core'; ++import type { AgentContextProvider, UpdateAssistantUpdateOptions , CacheModule, InMemoryLruCache } from '@credo-ts/core'; + import { AgentContext, EventEmitter, Logger } from '@credo-ts/core'; + import { TenantRecordService } from '../services'; + import { TenantSessionCoordinator } from './TenantSessionCoordinator'; +@@ -9,7 +9,9 @@ export declare class TenantAgentContextProvider implements AgentContextProvider + private eventEmitter; + private logger; + private tenantSessionCoordinator; +- constructor(tenantRecordService: TenantRecordService, rootAgentContext: AgentContext, eventEmitter: EventEmitter, tenantSessionCoordinator: TenantSessionCoordinator, logger: Logger); ++ private cacheModule; ++ private inMemoryLruCache; ++ constructor(tenantRecordService: TenantRecordService, rootAgentContext: AgentContext, eventEmitter: EventEmitter, tenantSessionCoordinator: TenantSessionCoordinator, logger: Logger, cache: InMemoryLruCache); + getAgentContextForContextCorrelationId(contextCorrelationId: string): Promise; + getContextForInboundMessage(inboundMessage: unknown, options?: { + contextCorrelationId?: string; +diff --git a/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.js b/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.js +index d491d4e..d60ec79 100644 +--- a/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.js ++++ b/node_modules/@credo-ts/tenants/build/context/TenantAgentContextProvider.js +@@ -24,16 +24,28 @@ let TenantAgentContextProvider = class TenantAgentContextProvider { + this.eventEmitter = eventEmitter; + this.tenantSessionCoordinator = tenantSessionCoordinator; + this.logger = logger; ++ this.cache = new core_1.CacheModule({ ++ cache: new core_1.InMemoryLruCache({ limit: 100 }), ++ }); + // Start listener for newly created routing keys, so we can register a mapping for each new key for the tenant + this.listenForRoutingKeyCreatedEvents(); + } + async getAgentContextForContextCorrelationId(contextCorrelationId) { ++ this.logger.debug('debug ========= Inside getAgentContextForContextCorrelationId') + // It could be that the root agent context is requested, in that case we return the root agent context + if (contextCorrelationId === this.rootAgentContext.contextCorrelationId) { + return this.rootAgentContext; + } + // TODO: maybe we can look at not having to retrieve the tenant record if there's already a context available. +- const tenantRecord = await this.tenantRecordService.getTenantById(this.rootAgentContext, contextCorrelationId); ++ this.logger.debug('debug ========= Get tenantRecord from cache') ++ let tenantRecord = await this.cache.config.cache.get(this.rootAgentContext, `contextCorrelationId-${contextCorrelationId}`) ++ if(!tenantRecord) { ++ // TODO: maybe we can look at not having to retrieve the tenant record if there's already a context available. ++ this.logger.debug('debug ========= TenantRecord not found in cache') ++ tenantRecord = await this.tenantRecordService.getTenantById(this.rootAgentContext, contextCorrelationId) ++ await this.cache.config.cache.set(this.rootAgentContext,`contextCorrelationId-${contextCorrelationId}`,tenantRecord) ++ this.logger.debug(`debug ========= Cached tenant agent context for tenant '${contextCorrelationId}'`) ++ } + const shouldUpdate = !(0, core_1.isStorageUpToDate)(tenantRecord.storageVersion); + // If the tenant storage is not up to date, and autoUpdate is disabled we throw an error + if (shouldUpdate && !this.rootAgentContext.config.autoUpdateStorageOnStartup) { diff --git a/samples/cliConfig.json b/samples/cliConfig.json index eea039ff..7d2a40e1 100644 --- a/samples/cliConfig.json +++ b/samples/cliConfig.json @@ -19,7 +19,7 @@ "indyNamespace": "indicio:demonet" }, { - "genesisTransactions": "http://test.bcovrin.vonx.io/genesis", + "genesisTransactions": "https://raw.githubusercontent.com/bcgov/von-network/main/BCovrin/genesis_test", "indyNamespace": "bcovrin:testnet" } ], diff --git a/taskdef/credo-ecs-taskdef.json b/scripts/taskdef/credo-ecs-taskdef.json similarity index 78% rename from taskdef/credo-ecs-taskdef.json rename to scripts/taskdef/credo-ecs-taskdef.json index 5f1a6816..d05cf562 100644 --- a/taskdef/credo-ecs-taskdef.json +++ b/scripts/taskdef/credo-ecs-taskdef.json @@ -1,20 +1,20 @@ { - "family": "DEV_AGENT_SPINUP_TASKDEF", + "family": "${FAMILY}", "containerDefinitions": [ { - "name": "e7cc1515-a197-4580-9e63-dda70c9c7f08-Platform-admin-service-ODg2YmE4ZDU3", + "name": "Platform-admin", "image": "%REPOSITORY_URI%:CREDO_v_%BUILD_NUMBER%", "cpu": 154, "memory": 307, "portMappings": [ { - "containerPort": 8004, - "hostPort": 8004, + "containerPort": 8001, + "hostPort": 8001, "protocol": "tcp" }, { - "containerPort": 9004, - "hostPort": 9004, + "containerPort": 9001, + "hostPort": 9001, "protocol": "tcp" } ], @@ -59,7 +59,7 @@ { "name": "config", "host": { - "sourcePath": "/home/ec2-user/config/e7cc1515-a197-4580-9e63-dda70c9c7f08_Platform-admin.json" + "sourcePath": "${SourcePath}" } } ] diff --git a/taskdef/credo-fargate-taskdef.json b/scripts/taskdef/credo-fargate-taskdef.json similarity index 89% rename from taskdef/credo-fargate-taskdef.json rename to scripts/taskdef/credo-fargate-taskdef.json index 1e91fe3d..bf3a4a59 100644 --- a/taskdef/credo-fargate-taskdef.json +++ b/scripts/taskdef/credo-fargate-taskdef.json @@ -1,5 +1,5 @@ { - "family": "QA-AFJ-TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "Platform-admin", @@ -21,7 +21,7 @@ "command": [ "--auto-accept-connections", "--config", - "/config/c15f48c9-1d0e-46b6-8915-b7689e255a22_Platform-admin.json" + "/config/${CONFIG_FILE}" ], "environment": [ { @@ -47,7 +47,7 @@ "logConfiguration": { "logDriver": "awslogs", "options": { - "awslogs-group": "/ecs/QA-AFJ-TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-create-group": "true", "awslogs-region": "ap-south-1", "awslogs-stream-prefix": "ecs" @@ -62,8 +62,8 @@ "requiresCompatibilities": [ "FARGATE" ], - "cpu": "2048", - "memory": "4096", + "cpu": "1024", + "memory": "2048", "volumes": [ { "name": "config", diff --git a/src/controllers/credentials/CredentialController.ts b/src/controllers/credentials/CredentialController.ts index f7068dfa..c1eccc05 100644 --- a/src/controllers/credentials/CredentialController.ts +++ b/src/controllers/credentials/CredentialController.ts @@ -1,7 +1,19 @@ import type { RestAgentModules } from '../../cliAgent' -import type { CredentialExchangeRecordProps, CredentialProtocolVersionType, Routing } from '@credo-ts/core' +import type { + CredentialExchangeRecordProps, + CredentialProtocolVersionType, + PeerDidNumAlgo2CreateOptions, + Routing, +} from '@credo-ts/core' -import { CredentialState, Agent, W3cCredentialService, Key, KeyType, CredentialRole } from '@credo-ts/core' +import { + CredentialState, + Agent, + W3cCredentialService, + CredentialRole, + createPeerDidDocumentFromServices, + PeerDidNumAlgo, +} from '@credo-ts/core' import { injectable } from 'tsyringe' import ErrorHandlingService from '../../errorHandlingService' @@ -165,21 +177,35 @@ export class CredentialController extends Controller { @Post('/create-offer-oob') public async createOfferOob(@Body() outOfBandOption: CreateOfferOobOptions) { try { + let invitationDid: string | undefined let routing: Routing const linkSecretIds = await this.agent.modules.anoncreds.getLinkSecretIds() if (linkSecretIds.length === 0) { await this.agent.modules.anoncreds.createLinkSecret() } - if (outOfBandOption?.recipientKey) { - routing = { - endpoints: this.agent.config.endpoints, - routingKeys: [], - recipientKey: Key.fromPublicKeyBase58(outOfBandOption.recipientKey, KeyType.Ed25519), - mediatorId: undefined, - } + + if (outOfBandOption?.invitationDid) { + invitationDid = outOfBandOption?.invitationDid } else { routing = await this.agent.mediationRecipient.getRouting({}) + const didDocument = createPeerDidDocumentFromServices([ + { + id: 'didcomm', + recipientKeys: [routing.recipientKey], + routingKeys: routing.routingKeys, + serviceEndpoint: routing.endpoints[0], + }, + ]) + const did = await this.agent.dids.create({ + didDocument, + method: 'peer', + options: { + numAlgo: PeerDidNumAlgo.MultipleInceptionKeyWithoutDoc, + }, + }) + invitationDid = did.didState.did } + const offerOob = await this.agent.credentials.createOffer({ protocolVersion: outOfBandOption.protocolVersion as CredentialProtocolVersionType<[]>, credentialFormats: outOfBandOption.credentialFormats, @@ -193,7 +219,7 @@ export class CredentialController extends Controller { messages: [credentialMessage], autoAcceptConnection: true, imageUrl: outOfBandOption?.imageUrl, - routing, + invitationDid, }) return { invitationUrl: outOfBandRecord.outOfBandInvitation.toUrl({ @@ -203,7 +229,7 @@ export class CredentialController extends Controller { useDidSovPrefixWhereAllowed: this.agent.config.useDidSovPrefixWhereAllowed, }), outOfBandRecord: outOfBandRecord.toJSON(), - recipientKey: outOfBandOption?.recipientKey ? {} : { recipientKey: routing.recipientKey.publicKeyBase58 }, + invitationDid: outOfBandOption?.invitationDid ? '' : invitationDid, } } catch (error) { throw ErrorHandlingService.handle(error) diff --git a/src/controllers/proofs/ProofController.ts b/src/controllers/proofs/ProofController.ts index 46d259fc..903acba9 100644 --- a/src/controllers/proofs/ProofController.ts +++ b/src/controllers/proofs/ProofController.ts @@ -1,11 +1,12 @@ import type { AcceptProofRequestOptions, + PeerDidNumAlgo2CreateOptions, ProofExchangeRecordProps, ProofsProtocolVersionType, Routing, } from '@credo-ts/core' -import { Agent, Key, KeyType } from '@credo-ts/core' +import { Agent, PeerDidNumAlgo, createPeerDidDocumentFromServices } from '@credo-ts/core' import { injectable } from 'tsyringe' import ErrorHandlingService from '../../errorHandlingService' @@ -148,16 +149,30 @@ export class ProofController extends Controller { public async createRequest(@Body() createRequestOptions: CreateProofRequestOobOptions) { try { let routing: Routing - if (createRequestOptions?.recipientKey) { - routing = { - endpoints: this.agent.config.endpoints, - routingKeys: [], - recipientKey: Key.fromPublicKeyBase58(createRequestOptions.recipientKey, KeyType.Ed25519), - mediatorId: undefined, - } + let invitationDid: string | undefined + + if (createRequestOptions?.invitationDid) { + invitationDid = createRequestOptions?.invitationDid } else { routing = await this.agent.mediationRecipient.getRouting({}) + const didDocument = createPeerDidDocumentFromServices([ + { + id: 'didcomm', + recipientKeys: [routing.recipientKey], + routingKeys: routing.routingKeys, + serviceEndpoint: routing.endpoints[0], + }, + ]) + const did = await this.agent.dids.create({ + didDocument, + method: 'peer', + options: { + numAlgo: PeerDidNumAlgo.MultipleInceptionKeyWithoutDoc, + }, + }) + invitationDid = did.didState.did } + const proof = await this.agent.proofs.createRequest({ protocolVersion: createRequestOptions.protocolVersion as ProofsProtocolVersionType<[]>, proofFormats: createRequestOptions.proofFormats, @@ -173,7 +188,7 @@ export class ProofController extends Controller { messages: [proofMessage], autoAcceptConnection: true, imageUrl: createRequestOptions?.imageUrl, - routing, + invitationDid, }) return { @@ -184,7 +199,7 @@ export class ProofController extends Controller { useDidSovPrefixWhereAllowed: this.agent.config.useDidSovPrefixWhereAllowed, }), outOfBandRecord: outOfBandRecord.toJSON(), - recipientKey: createRequestOptions?.recipientKey ? {} : { recipientKey: routing.recipientKey.publicKeyBase58 }, + invitationDid: createRequestOptions?.invitationDid ? '' : invitationDid, } } catch (error) { throw ErrorHandlingService.handle(error) diff --git a/src/events/ReuseConnectionEvents.ts b/src/events/ReuseConnectionEvents.ts index 2bebbc19..c4ee435f 100644 --- a/src/events/ReuseConnectionEvents.ts +++ b/src/events/ReuseConnectionEvents.ts @@ -9,7 +9,7 @@ import { sendWebhookEvent } from './WebhookEvent' export const reuseConnectionEvents = async (agent: Agent, config: ServerConfig) => { agent.events.on(OutOfBandEventTypes.HandshakeReused, async (event: HandshakeReusedEvent) => { const body = { - connectionRecord: event.payload.connectionRecord.toJSON(), + ...event.payload.connectionRecord.toJSON(), outOfBandRecord: event.payload.outOfBandRecord.toJSON(), reuseThreadId: event.payload.reuseThreadId, ...event.metadata,