diff --git a/packages/core/src/modules/routing/services/MediationRecipientService.ts b/packages/core/src/modules/routing/services/MediationRecipientService.ts index 3b65a2f7c8..94f4cbfa09 100644 --- a/packages/core/src/modules/routing/services/MediationRecipientService.ts +++ b/packages/core/src/modules/routing/services/MediationRecipientService.ts @@ -28,6 +28,7 @@ import { injectable } from '../../../plugins' import { JsonTransformer } from '../../../utils' import { ConnectionService } from '../../connections/services/ConnectionService' import { Key } from '../../dids' +import { didKeyToVerkey } from '../../dids/helpers' import { ProblemReportError } from '../../problem-reports' import { RoutingEventTypes } from '../RoutingEvents' import { RoutingProblemReportReason } from '../error' @@ -112,7 +113,10 @@ export class MediationRecipientService { // Update record mediationRecord.endpoint = messageContext.message.endpoint - mediationRecord.routingKeys = messageContext.message.routingKeys + + // According to RFC 0211 keys should be a did key, but base58 encoded verkey was used before + // RFC was accepted. This converts the key to a public key base58 if it is a did key. + mediationRecord.routingKeys = messageContext.message.routingKeys.map(didKeyToVerkey) return await this.updateState(mediationRecord, MediationState.Granted) } diff --git a/packages/core/src/modules/routing/services/MediatorService.ts b/packages/core/src/modules/routing/services/MediatorService.ts index 403d3424d8..68d7446f08 100644 --- a/packages/core/src/modules/routing/services/MediatorService.ts +++ b/packages/core/src/modules/routing/services/MediatorService.ts @@ -10,6 +10,7 @@ import { AriesFrameworkError } from '../../../error' import { inject, injectable } from '../../../plugins' import { JsonTransformer } from '../../../utils/JsonTransformer' import { Wallet } from '../../../wallet/Wallet' +import { didKeyToVerkey } from '../../dids/helpers' import { RoutingEventTypes } from '../RoutingEvents' import { KeylistUpdateAction, @@ -118,13 +119,18 @@ export class MediatorService { recipientKey: update.recipientKey, result: KeylistUpdateResult.NoChange, }) + + // According to RFC 0211 key should be a did key, but base58 encoded verkey was used before + // RFC was accepted. This converts the key to a public key base58 if it is a did key. + const publicKeyBase58 = didKeyToVerkey(update.recipientKey) + if (update.action === KeylistUpdateAction.add) { - mediationRecord.addRecipientKey(update.recipientKey) + mediationRecord.addRecipientKey(publicKeyBase58) updated.result = KeylistUpdateResult.Success keylist.push(updated) } else if (update.action === KeylistUpdateAction.remove) { - const success = mediationRecord.removeRecipientKey(update.recipientKey) + const success = mediationRecord.removeRecipientKey(publicKeyBase58) updated.result = success ? KeylistUpdateResult.Success : KeylistUpdateResult.NoChange keylist.push(updated) } diff --git a/packages/core/src/modules/routing/services/__tests__/MediationRecipientService.test.ts b/packages/core/src/modules/routing/services/__tests__/MediationRecipientService.test.ts index fe059d7b02..73748ce2d7 100644 --- a/packages/core/src/modules/routing/services/__tests__/MediationRecipientService.test.ts +++ b/packages/core/src/modules/routing/services/__tests__/MediationRecipientService.test.ts @@ -14,7 +14,13 @@ import { ConnectionRepository } from '../../../connections/repository/Connection import { ConnectionService } from '../../../connections/services/ConnectionService' import { Key } from '../../../dids' import { DidRepository } from '../../../dids/repository/DidRepository' -import { DeliveryRequestMessage, MessageDeliveryMessage, MessagesReceivedMessage, StatusMessage } from '../../messages' +import { + DeliveryRequestMessage, + MediationGrantMessage, + MessageDeliveryMessage, + MessagesReceivedMessage, + StatusMessage, +} from '../../messages' import { MediationRole, MediationState } from '../../models' import { MediationRecord } from '../../repository/MediationRecord' import { MediationRepository } from '../../repository/MediationRepository' @@ -93,6 +99,38 @@ describe('MediationRecipientService', () => { ) }) + describe('processMediationGrant', () => { + test('should process base58 encoded routing keys', async () => { + mediationRecord.state = MediationState.Requested + const mediationGrant = new MediationGrantMessage({ + endpoint: 'http://agent.com:8080', + routingKeys: ['79CXkde3j8TNuMXxPdV7nLUrT2g7JAEjH5TreyVY7GEZ'], + threadId: 'threadId', + }) + + const messageContext = new InboundMessageContext(mediationGrant, { connection: mockConnection }) + + await mediationRecipientService.processMediationGrant(messageContext) + + expect(mediationRecord.routingKeys).toEqual(['79CXkde3j8TNuMXxPdV7nLUrT2g7JAEjH5TreyVY7GEZ']) + }) + + test('should process did:key encoded routing keys', async () => { + mediationRecord.state = MediationState.Requested + const mediationGrant = new MediationGrantMessage({ + endpoint: 'http://agent.com:8080', + routingKeys: ['did:key:z6MkmjY8GnV5i9YTDtPETC2uUAW6ejw3nk5mXF5yci5ab7th'], + threadId: 'threadId', + }) + + const messageContext = new InboundMessageContext(mediationGrant, { connection: mockConnection }) + + await mediationRecipientService.processMediationGrant(messageContext) + + expect(mediationRecord.routingKeys).toEqual(['8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K']) + }) + }) + describe('createStatusRequest', () => { it('creates a status request message', async () => { const statusRequestMessage = await mediationRecipientService.createStatusRequest(mediationRecord, { diff --git a/packages/core/src/modules/routing/services/__tests__/MediatorService.test.ts b/packages/core/src/modules/routing/services/__tests__/MediatorService.test.ts new file mode 100644 index 0000000000..bd3d315294 --- /dev/null +++ b/packages/core/src/modules/routing/services/__tests__/MediatorService.test.ts @@ -0,0 +1,103 @@ +import { getAgentConfig, getMockConnection, mockFunction } from '../../../../../tests/helpers' +import { EventEmitter } from '../../../../agent/EventEmitter' +import { InboundMessageContext } from '../../../../agent/models/InboundMessageContext' +import { IndyWallet } from '../../../../wallet/IndyWallet' +import { DidExchangeState } from '../../../connections' +import { KeylistUpdateAction, KeylistUpdateMessage } from '../../messages' +import { MediationRole, MediationState } from '../../models' +import { MediationRecord } from '../../repository' +import { MediationRepository } from '../../repository/MediationRepository' +import { MediatorRoutingRepository } from '../../repository/MediatorRoutingRepository' +import { MediatorService } from '../MediatorService' + +const agentConfig = getAgentConfig('MediatorService') + +jest.mock('../../repository/MediationRepository') +const MediationRepositoryMock = MediationRepository as jest.Mock + +jest.mock('../../repository/MediatorRoutingRepository') +const MediatorRoutingRepositoryMock = MediatorRoutingRepository as jest.Mock + +jest.mock('../../../../wallet/IndyWallet') +const WalletMock = IndyWallet as jest.Mock + +const mediationRepository = new MediationRepositoryMock() +const mediatorRoutingRepository = new MediatorRoutingRepositoryMock() + +const wallet = new WalletMock() + +const mediatorService = new MediatorService( + mediationRepository, + mediatorRoutingRepository, + agentConfig, + wallet, + new EventEmitter(agentConfig) +) + +const mockConnection = getMockConnection({ + state: DidExchangeState.Completed, +}) + +describe('MediatorService', () => { + describe('processKeylistUpdateRequest', () => { + test('processes base58 encoded recipient keys', async () => { + const mediationRecord = new MediationRecord({ + connectionId: 'connectionId', + role: MediationRole.Mediator, + state: MediationState.Granted, + threadId: 'threadId', + recipientKeys: ['8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K'], + }) + + mockFunction(mediationRepository.getByConnectionId).mockResolvedValue(mediationRecord) + + const keyListUpdate = new KeylistUpdateMessage({ + updates: [ + { + action: KeylistUpdateAction.add, + recipientKey: '79CXkde3j8TNuMXxPdV7nLUrT2g7JAEjH5TreyVY7GEZ', + }, + { + action: KeylistUpdateAction.remove, + recipientKey: '8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K', + }, + ], + }) + + const messageContext = new InboundMessageContext(keyListUpdate, { connection: mockConnection }) + await mediatorService.processKeylistUpdateRequest(messageContext) + + expect(mediationRecord.recipientKeys).toEqual(['79CXkde3j8TNuMXxPdV7nLUrT2g7JAEjH5TreyVY7GEZ']) + }) + + test('processes did:key encoded recipient keys', async () => { + const mediationRecord = new MediationRecord({ + connectionId: 'connectionId', + role: MediationRole.Mediator, + state: MediationState.Granted, + threadId: 'threadId', + recipientKeys: ['8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K'], + }) + + mockFunction(mediationRepository.getByConnectionId).mockResolvedValue(mediationRecord) + + const keyListUpdate = new KeylistUpdateMessage({ + updates: [ + { + action: KeylistUpdateAction.add, + recipientKey: 'did:key:z6MkkbTaLstV4fwr1rNf5CSxdS2rGbwxi3V5y6NnVFTZ2V1w', + }, + { + action: KeylistUpdateAction.remove, + recipientKey: 'did:key:z6MkmjY8GnV5i9YTDtPETC2uUAW6ejw3nk5mXF5yci5ab7th', + }, + ], + }) + + const messageContext = new InboundMessageContext(keyListUpdate, { connection: mockConnection }) + await mediatorService.processKeylistUpdateRequest(messageContext) + + expect(mediationRecord.recipientKeys).toEqual(['79CXkde3j8TNuMXxPdV7nLUrT2g7JAEjH5TreyVY7GEZ']) + }) + }) +})