Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): connection-less issuance and verification #359

Merged
merged 22 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dd0adb4
feat: add ~service decorator
TimoGlastra Jun 25, 2021
1ecaa73
feat: support connection-less issuance
TimoGlastra Jun 26, 2021
6a860d1
test: add connection-less credential exchange test
TimoGlastra Jun 26, 2021
17a46d1
feat: support connection-less verification
TimoGlastra Jul 3, 2021
0e8fc5a
style: eslint warnings
TimoGlastra Jul 3, 2021
ae00e7a
test: add tests for assertConnectionOrServiceDecorator
TimoGlastra Jul 3, 2021
858ed99
docs: update features in readme
TimoGlastra Jul 3, 2021
17031e5
Merge remote-tracking branch 'upstream/main' into feat/conectionless
TimoGlastra Jul 17, 2021
e6820a3
style: eslint warnings
TimoGlastra Jul 17, 2021
1730586
fix: updates after merge
TimoGlastra Jul 17, 2021
38244db
test: only log on error
TimoGlastra Jul 17, 2021
7ff329a
test: add timeout before shutdown of mediator
TimoGlastra Jul 17, 2021
869d4d1
Merge remote-tracking branch 'upstream/main' into feat/conectionless
TimoGlastra Jul 20, 2021
6fc2589
chore(core): update to work with auto-accept proofs
TimoGlastra Jul 20, 2021
b91dcd4
Merge remote-tracking branch 'upstream/main' into feat/conectionless
TimoGlastra Jul 20, 2021
75d9bb9
test(core): add connectionles auto accept proof case
TimoGlastra Jul 20, 2021
a6206b8
test(core): fix tests
TimoGlastra Jul 21, 2021
08c6d69
test(core): longer wait for shutdown
TimoGlastra Jul 21, 2021
330b4f5
fix(core): start with $stop event
TimoGlastra Jul 21, 2021
8d2f1cc
Merge remote-tracking branch 'upstream/main' into feat/conectionless
TimoGlastra Jul 22, 2021
a504079
test: break up e2e test to prevent flakyness
TimoGlastra Jul 22, 2021
707034e
build: tsconfig updates
TimoGlastra Jul 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ Some features are not yet supported, but are on our roadmap. Check [the roadmap]
- ✅ Basic Message Protocol ([RFC 0095](https://github.com/hyperledger/aries-rfcs/blob/master/features/0095-basic-message/README.md))
- ✅ Indy Credentials (with `did:sov` support)
- ✅ HTTP Transport
- ✅ Connection-less Issuance and Verification
- ✅ Mediator Coordination Protocol ([RFC 0211](https://github.com/hyperledger/aries-rfcs/blob/master/features/0211-route-coordination/README.md))
- 🚧 Revocation of Indy Credentials
- 🚧 Electron
- 🚧 WebSocket Transport
- ❌ Browser
- ❌ Connection-less Issuance and Verification
- ❌ Issue Credential V2, Present Proof V2, DID Exchange Protocol, Out-Of-Band
- ❌ W3C Linked Data VCs, BBS+ Signatures

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/agent/AgentMessage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AckDecorated } from '../decorators/ack/AckDecoratorExtension'
import { AttachmentDecorated } from '../decorators/attachment/AttachmentExtension'
import { L10nDecorated } from '../decorators/l10n/L10nDecoratorExtension'
import { ServiceDecorated } from '../decorators/service/ServiceDecoratorExtension'
import { ThreadDecorated } from '../decorators/thread/ThreadDecoratorExtension'
import { TimingDecorated } from '../decorators/timing/TimingDecoratorExtension'
import { TransportDecorated } from '../decorators/transport/TransportDecoratorExtension'
Expand All @@ -16,6 +17,7 @@ const DefaultDecorators = [
TimingDecorated,
AckDecorated,
AttachmentDecorated,
ServiceDecorated,
]

export class AgentMessage extends Compose(BaseMessage, DefaultDecorators) {
Expand Down
15 changes: 10 additions & 5 deletions packages/core/src/agent/Dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@ import { Lifecycle, scoped } from 'tsyringe'
import { AriesFrameworkError } from '../error/AriesFrameworkError'

import { MessageSender } from './MessageSender'
import { TransportService } from './TransportService'
import { isOutboundServiceMessage } from './helpers'

@scoped(Lifecycle.ContainerScoped)
class Dispatcher {
private handlers: Handler[] = []
private messageSender: MessageSender
private transportService: TransportService

public constructor(messageSender: MessageSender, transportService: TransportService) {
public constructor(messageSender: MessageSender) {
this.messageSender = messageSender
this.transportService = transportService
}

public registerHandler(handler: Handler) {
Expand All @@ -34,7 +32,14 @@ class Dispatcher {

const outboundMessage = await handler.handle(messageContext)

if (outboundMessage) {
if (outboundMessage && isOutboundServiceMessage(outboundMessage)) {
await this.messageSender.sendMessageToService({
message: outboundMessage.payload,
service: outboundMessage.service,
senderKey: outboundMessage.senderKey,
returnRoute: true,
})
} else if (outboundMessage) {
await this.messageSender.sendMessage(outboundMessage)
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/agent/EnvelopeService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Logger } from '../logger'
import type { PackedMessage, UnpackedMessageContext } from '../types'
import type { UnpackedMessageContext, WireMessage } from '../types'
import type { AgentMessage } from './AgentMessage'
import type { Verkey } from 'indy-sdk'

Expand Down Expand Up @@ -27,7 +27,7 @@ class EnvelopeService {
this.logger = agentConfig.logger
}

public async packMessage(payload: AgentMessage, keys: EnvelopeKeys): Promise<PackedMessage> {
public async packMessage(payload: AgentMessage, keys: EnvelopeKeys): Promise<WireMessage> {
const { routingKeys, recipientKeys, senderKey: senderVk } = keys
const message = payload.toJSON()

Expand All @@ -50,7 +50,7 @@ class EnvelopeService {
return wireMessage
}

public async unpackMessage(packedMessage: PackedMessage): Promise<UnpackedMessageContext> {
public async unpackMessage(packedMessage: WireMessage): Promise<UnpackedMessageContext> {
return this.wallet.unpack(packedMessage)
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/agent/Handler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { OutboundMessage } from '../types'
import type { OutboundMessage, OutboundServiceMessage } from '../types'
import type { AgentMessage } from './AgentMessage'
import type { InboundMessageContext } from './models/InboundMessageContext'

export interface Handler<T extends typeof AgentMessage = typeof AgentMessage> {
readonly supportedMessages: readonly T[]

handle(messageContext: InboundMessageContext): Promise<OutboundMessage | void>
handle(messageContext: InboundMessageContext): Promise<OutboundMessage | OutboundServiceMessage | void>
}

/**
Expand Down
25 changes: 13 additions & 12 deletions packages/core/src/agent/MessageReceiver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Logger } from '../logger'
import type { UnpackedMessageContext, UnpackedMessage } from '../types'
import type { UnpackedMessageContext, UnpackedMessage, WireMessage } from '../types'
import type { AgentMessage } from './AgentMessage'
import type { TransportSession } from './TransportService'

Expand Down Expand Up @@ -53,13 +53,15 @@ export class MessageReceiver {

this.logger.debug(`Agent ${this.config.label} received message`)

const unpackedMessage = await this.unpackMessage(inboundPackedMessage as Record<string, unknown>)
const senderKey = unpackedMessage.sender_verkey
const unpackedMessage = await this.unpackMessage(inboundPackedMessage as WireMessage)
const senderKey = unpackedMessage.senderVerkey
const recipientKey = unpackedMessage.recipientVerkey

let connection = undefined
if (senderKey && unpackedMessage.recipient_verkey) {
if (senderKey && recipientKey) {
// TODO: only attach if theirKey is present. Otherwise a connection that may not be complete, validated or correct will
// be attached to the message context. See #76
connection = (await this.connectionService.findByVerkey(unpackedMessage.recipient_verkey)) || undefined
connection = (await this.connectionService.findByVerkey(recipientKey)) || undefined

// We check whether the sender key is the same as the key we have stored in the connection
// otherwise everyone could send messages to our key and we would just accept
Expand All @@ -80,26 +82,25 @@ export class MessageReceiver {
const messageContext = new InboundMessageContext(message, {
connection,
senderVerkey: senderKey,
recipientVerkey: unpackedMessage.recipient_verkey,
recipientVerkey: recipientKey,
})

// We want to save a session if there is a chance of returning outbound message via inbound transport.
// That can happen when inbound message has `return_route` set to `all` or `thread`.
// If `return_route` defines just `thread`, we decide later whether to use session according to outbound message `threadId`.
if (connection && message.hasAnyReturnRoute() && session) {
if (senderKey && recipientKey && message.hasAnyReturnRoute() && session) {
const keys = {
// TODO handle the case when senderKey is missing
recipientKeys: senderKey ? [senderKey] : [],
recipientKeys: [senderKey],
routingKeys: [],
senderKey: connection?.verkey || null,
senderKey: recipientKey,
}
session.keys = keys
session.inboundMessage = message
session.connection = connection
this.transportService.saveSession(session)
}

return await this.dispatcher.dispatch(messageContext)
await this.dispatcher.dispatch(messageContext)
}

/**
Expand All @@ -108,7 +109,7 @@ export class MessageReceiver {
*
* @param packedMessage the received, probably packed, message to unpack
*/
private async unpackMessage(packedMessage: Record<string, unknown>): Promise<UnpackedMessageContext> {
private async unpackMessage(packedMessage: WireMessage): Promise<UnpackedMessageContext> {
// If the inbound message has no @type field we assume
// the message is packed and must be unpacked first
if (!this.isUnpackedMessage(packedMessage)) {
Expand Down
Loading