Skip to content

Commit

Permalink
feat: add present proof v2 (#979)
Browse files Browse the repository at this point in the history
Signed-off-by: Mike Richardson <mike.richardson@ontario.ca>

Co-authored-by: NB Prasad Katkar <prasad@northernblock.io>
Co-authored-by: Karim Stekelenburg <karim@animo.id>
  • Loading branch information
3 people authored and TimoGlastra committed Aug 26, 2022
1 parent a79bdb6 commit f2e61d8
Show file tree
Hide file tree
Showing 128 changed files with 9,937 additions and 3,476 deletions.
14 changes: 10 additions & 4 deletions demo/src/Alice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,17 @@ export class Alice extends BaseAgent {
}

public async acceptProofRequest(proofRecord: ProofRecord) {
const retrievedCredentials = await this.agent.proofs.getRequestedCredentialsForProofRequest(proofRecord.id, {
filterByPresentationPreview: true,
const requestedCredentials = await this.agent.proofs.autoSelectCredentialsForProofRequest({
proofRecordId: proofRecord.id,
config: {
filterByPresentationPreview: true,
},
})

await this.agent.proofs.acceptRequest({
proofRecordId: proofRecord.id,
proofFormats: requestedCredentials.proofFormats,
})
const requestedCredentials = this.agent.proofs.autoSelectCredentialsForProofRequest(retrievedCredentials)
await this.agent.proofs.acceptRequest(proofRecord.id, requestedCredentials)
console.log(greenText('\nProof request accepted!\n'))
}

Expand Down
22 changes: 19 additions & 3 deletions demo/src/Faber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import type { ConnectionRecord } from '@aries-framework/core'
import type { CredDef, Schema } from 'indy-sdk'
import type BottomBar from 'inquirer/lib/ui/bottom-bar'

import { V1CredentialPreview, AttributeFilter, ProofAttributeInfo, utils } from '@aries-framework/core'
import {
AttributeFilter,
ProofAttributeInfo,
ProofProtocolVersion,
utils,
V1CredentialPreview,
} from '@aries-framework/core'
import { ui } from 'inquirer'

import { BaseAgent } from './BaseAgent'
Expand Down Expand Up @@ -137,8 +143,18 @@ export class Faber extends BaseAgent {
const connectionRecord = await this.getConnectionRecord()
const proofAttribute = await this.newProofAttribute()
await this.printProofFlow(greenText('\nRequesting proof...\n', false))
await this.agent.proofs.requestProof(connectionRecord.id, {
requestedAttributes: proofAttribute,

await this.agent.proofs.requestProof({
protocolVersion: ProofProtocolVersion.V1,
connectionId: connectionRecord.id,
proofFormats: {
indy: {
name: 'proof-request',
version: '1.0',
nonce: '1298236324864',
requestedAttributes: proofAttribute,
},
},
})
this.ui.updateBottomBar(
`\nProof request sent!\n\nGo to the Alice agent to accept the proof request\n\n${Color.Reset}`
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/agent/AgentConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DID_COMM_TRANSPORT_QUEUE } from '../constants'
import { AriesFrameworkError } from '../error'
import { ConsoleLogger, LogLevel } from '../logger'
import { AutoAcceptCredential } from '../modules/credentials/models/CredentialAutoAcceptType'
import { AutoAcceptProof } from '../modules/proofs/ProofAutoAcceptType'
import { AutoAcceptProof } from '../modules/proofs/models/ProofAutoAcceptType'
import { DidCommMimeType } from '../types'

export class AgentConfig {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/agent/BaseAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export abstract class BaseAgent {
// We set the modules in the constructor because that allows to set them as read-only
this.connections = this.dependencyManager.resolve(ConnectionsApi)
this.credentials = this.dependencyManager.resolve(CredentialsApi) as CredentialsApi
this.proofs = this.dependencyManager.resolve(ProofsApi)
this.proofs = this.dependencyManager.resolve(ProofsApi) as ProofsApi
this.mediator = this.dependencyManager.resolve(MediatorApi)
this.mediationRecipient = this.dependencyManager.resolve(RecipientApi)
this.basicMessages = this.dependencyManager.resolve(BasicMessagesApi)
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/agent/__tests__/Agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import { CredentialRepository } from '../../modules/credentials'
import { CredentialsApi } from '../../modules/credentials/CredentialsApi'
import { IndyLedgerService } from '../../modules/ledger'
import { LedgerApi } from '../../modules/ledger/LedgerApi'
import { ProofRepository, ProofService } from '../../modules/proofs'
import { ProofRepository } from '../../modules/proofs'
import { ProofsApi } from '../../modules/proofs/ProofsApi'
import { V1ProofService } from '../../modules/proofs/protocol/v1'
import { V2ProofService } from '../../modules/proofs/protocol/v2'
import {
MediatorApi,
RecipientApi,
Expand Down Expand Up @@ -115,8 +117,9 @@ describe('Agent', () => {
expect(container.resolve(ConnectionRepository)).toBeInstanceOf(ConnectionRepository)
expect(container.resolve(TrustPingService)).toBeInstanceOf(TrustPingService)

expect(container.resolve(V1ProofService)).toBeInstanceOf(V1ProofService)
expect(container.resolve(V2ProofService)).toBeInstanceOf(V2ProofService)
expect(container.resolve(ProofsApi)).toBeInstanceOf(ProofsApi)
expect(container.resolve(ProofService)).toBeInstanceOf(ProofService)
expect(container.resolve(ProofRepository)).toBeInstanceOf(ProofRepository)

expect(container.resolve(CredentialsApi)).toBeInstanceOf(CredentialsApi)
Expand Down Expand Up @@ -157,8 +160,9 @@ describe('Agent', () => {
expect(container.resolve(ConnectionRepository)).toBe(container.resolve(ConnectionRepository))
expect(container.resolve(TrustPingService)).toBe(container.resolve(TrustPingService))

expect(container.resolve(V1ProofService)).toBe(container.resolve(V1ProofService))
expect(container.resolve(V2ProofService)).toBe(container.resolve(V2ProofService))
expect(container.resolve(ProofsApi)).toBe(container.resolve(ProofsApi))
expect(container.resolve(ProofService)).toBe(container.resolve(ProofService))
expect(container.resolve(ProofRepository)).toBe(container.resolve(ProofRepository))

expect(container.resolve(CredentialsApi)).toBe(container.resolve(CredentialsApi))
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/decorators/ack/AckDecorator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { JsonTransformer } from '../../utils/JsonTransformer'
import { MessageValidator } from '../../utils/MessageValidator'
import { Compose } from '../../utils/mixins'

import { AckValues } from './AckDecorator'
import { AckDecorated } from './AckDecoratorExtension'

describe('Decorators | AckDecoratorExtension', () => {
Expand All @@ -15,7 +16,7 @@ describe('Decorators | AckDecoratorExtension', () => {

test('transforms AckDecorator class to JSON', () => {
const message = new TestMessage()
message.setPleaseAck()
message.setPleaseAck([AckValues.Receipt])
expect(message.toJSON()).toEqual({
'@id': undefined,
'@type': undefined,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import type { AgentContext } from '../../../agent'
import type { EventEmitter } from '../../../agent/EventEmitter'
import type { CredentialRepository } from '../repository'
import type { CredentialFormat } from './CredentialFormat'
import type {
FormatCreateProposalOptions,
Expand All @@ -23,14 +21,6 @@ import { Attachment, AttachmentData } from '../../../decorators/attachment/Attac
import { JsonEncoder } from '../../../utils/JsonEncoder'

export abstract class CredentialFormatService<CF extends CredentialFormat = CredentialFormat> {
protected credentialRepository: CredentialRepository
protected eventEmitter: EventEmitter

public constructor(credentialRepository: CredentialRepository, eventEmitter: EventEmitter) {
this.credentialRepository = credentialRepository
this.eventEmitter = eventEmitter
}

abstract readonly formatKey: CF['formatKey']
abstract readonly credentialRecordType: CF['credentialRecordType']

Expand Down Expand Up @@ -86,7 +76,6 @@ export abstract class CredentialFormatService<CF extends CredentialFormat = Cred
*
* @param data The data to include in the attach object
* @param id the attach id from the formats component of the message
* @returns attachment to the credential proposal
*/
protected getFormatData(data: unknown, id: string): Attachment {
const attachment = new Attachment({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import type {
import type { IndyCredentialFormat } from './IndyCredentialFormat'
import type * as Indy from 'indy-sdk'

import { EventEmitter } from '../../../../agent/EventEmitter'
import { InjectionSymbols } from '../../../../constants'
import { AriesFrameworkError } from '../../../../error'
import { Logger } from '../../../../logger'
Expand All @@ -38,7 +37,6 @@ import { CredentialProblemReportError, CredentialProblemReportReason } from '../
import { CredentialFormatSpec } from '../../models/CredentialFormatSpec'
import { CredentialPreviewAttribute } from '../../models/CredentialPreviewAttribute'
import { CredentialMetadataKeys } from '../../repository/CredentialMetadataTypes'
import { CredentialRepository } from '../../repository/CredentialRepository'
import { CredentialFormatService } from '../CredentialFormatService'

import { IndyCredentialUtils } from './IndyCredentialUtils'
Expand All @@ -59,16 +57,14 @@ export class IndyCredentialFormatService extends CredentialFormatService<IndyCre
private logger: Logger

public constructor(
credentialRepository: CredentialRepository,
eventEmitter: EventEmitter,
indyIssuerService: IndyIssuerService,
indyLedgerService: IndyLedgerService,
indyHolderService: IndyHolderService,
connectionService: ConnectionService,
didResolver: DidResolverService,
@inject(InjectionSymbols.Logger) logger: Logger
) {
super(credentialRepository, eventEmitter)
super()
this.indyIssuerService = indyIssuerService
this.indyLedgerService = indyLedgerService
this.indyHolderService = indyHolderService
Expand Down Expand Up @@ -130,14 +126,10 @@ export class IndyCredentialFormatService extends CredentialFormatService<IndyCre
}

public async processProposal(agentContext: AgentContext, { attachment }: FormatProcessOptions): Promise<void> {
const credProposalJson = attachment.getDataAsJson()
const proposalJson = attachment.getDataAsJson()

if (!credProposalJson) {
throw new AriesFrameworkError('Missing indy credential proposal data payload')
}

const credProposal = JsonTransformer.fromJSON(credProposalJson, IndyCredPropose)
MessageValidator.validateSync(credProposal)
// fromJSON also validates
JsonTransformer.fromJSON(proposalJson, IndyCredPropose)
}

public async acceptProposal(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AgentContext } from '../../../agent'
import type { RequestedCredentials } from '../../proofs'
import type { RequestedCredentials } from '../../proofs/formats/indy/models/RequestedCredentials'
import type * as Indy from 'indy-sdk'

import { AgentDependencies } from '../../../agent/AgentDependencies'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { AgentContext } from '../../../agent'
import type { IndyRevocationInterval } from '../../credentials'
import type { RequestedCredentials } from '../../proofs'
import type { RequestedCredentials } from '../../proofs/formats/indy/models/RequestedCredentials'
import type { default as Indy } from 'indy-sdk'

import { AgentDependencies } from '../../../agent/AgentDependencies'
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/modules/proofs/ProofEvents.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BaseEvent } from '../../agent/Events'
import type { ProofState } from './ProofState'
import type { ProofState } from './models/ProofState'
import type { ProofRecord } from './repository'

export enum ProofEventTypes {
Expand Down
42 changes: 25 additions & 17 deletions packages/core/src/modules/proofs/ProofResponseCoordinator.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import type { AgentContext } from '../../agent/context'
import type { AgentContext } from '../../agent/context/AgentContext'
import type { ProofRecord } from './repository'

import { injectable } from '../../plugins'

import { AutoAcceptProof } from './ProofAutoAcceptType'
import { ProofsModuleConfig } from './ProofsModuleConfig'
import { ProofService } from './ProofService'
import { AutoAcceptProof } from './models/ProofAutoAcceptType'

/**
* This class handles all the automation with all the messages in the present proof protocol
* Every function returns `true` if it should automate the flow and `false` if not
*/
@injectable()
export class ProofResponseCoordinator {
private proofsModuleConfig: ProofsModuleConfig
private proofService: ProofService

public constructor(proofsModuleConfig: ProofsModuleConfig) {
this.proofsModuleConfig = proofsModuleConfig
public constructor(proofService: ProofService) {
this.proofService = proofService
}

/**
* Returns the proof auto accept config based on priority:
* - The record config takes first priority
Expand All @@ -36,12 +37,17 @@ export class ProofResponseCoordinator {
public shouldAutoRespondToProposal(agentContext: AgentContext, proofRecord: ProofRecord) {
const autoAccept = ProofResponseCoordinator.composeAutoAccept(
proofRecord.autoAcceptProof,
this.proofsModuleConfig.autoAcceptProofs
agentContext.config.autoAcceptProofs
)

if (autoAccept === AutoAcceptProof.Always) {
return true
}

if (autoAccept === AutoAcceptProof.ContentApproved) {
return this.proofService.shouldAutoRespondToProposal(agentContext, proofRecord)
}

return false
}

Expand All @@ -51,16 +57,17 @@ export class ProofResponseCoordinator {
public shouldAutoRespondToRequest(agentContext: AgentContext, proofRecord: ProofRecord) {
const autoAccept = ProofResponseCoordinator.composeAutoAccept(
proofRecord.autoAcceptProof,
this.proofsModuleConfig.autoAcceptProofs
agentContext.config.autoAcceptProofs
)

if (
autoAccept === AutoAcceptProof.Always ||
(autoAccept === AutoAcceptProof.ContentApproved && proofRecord.proposalMessage)
) {
if (autoAccept === AutoAcceptProof.Always) {
return true
}

if (autoAccept === AutoAcceptProof.ContentApproved) {
return this.proofService.shouldAutoRespondToRequest(agentContext, proofRecord)
}

return false
}

Expand All @@ -70,16 +77,17 @@ export class ProofResponseCoordinator {
public shouldAutoRespondToPresentation(agentContext: AgentContext, proofRecord: ProofRecord) {
const autoAccept = ProofResponseCoordinator.composeAutoAccept(
proofRecord.autoAcceptProof,
this.proofsModuleConfig.autoAcceptProofs
agentContext.config.autoAcceptProofs
)

if (
autoAccept === AutoAcceptProof.Always ||
(autoAccept === AutoAcceptProof.ContentApproved && proofRecord.requestMessage)
) {
if (autoAccept === AutoAcceptProof.Always) {
return true
}

if (autoAccept === AutoAcceptProof.ContentApproved) {
return this.proofService.shouldAutoRespondToPresentation(agentContext, proofRecord)
}

return false
}
}
Loading

0 comments on commit f2e61d8

Please sign in to comment.