Skip to content

Commit 865ffc9

Browse files
authored
Support invitation messages with public DID (#340)
Implement public DID invitations Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com>
1 parent 1b11be2 commit 865ffc9

File tree

41 files changed

+1245
-92
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1245
-92
lines changed

agency_client/src/payload.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ pub enum PayloadKinds {
1313
Cred,
1414
Proof,
1515
ProofRequest,
16+
ConnRequest,
1617
Other(String),
1718
}

agents/node/vcxagent-core/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@
3636
"demo:faber:pg": "node demo/faber.js --postgresql",
3737
"demo:alice:sign": "node demo/alice-signature.js",
3838
"demo:faber:verify": "node demo/faber-verify-signature.js",
39-
"test:integration": "npm run test:integration:update-state && npm run test:integration:signing && npm run test:integration:messaging && npm run test:integration:tails && npm run test:integration:trustping && npm run test:integration:feature-discovery",
39+
"test:integration": "npm run test:integration:update-state && npm run test:integration:signing && npm run test:integration:messaging && npm run test:integration:tails && npm run test:integration:trustping && npm run test:integration:feature-discovery && npm run test:integration:public-invite",
4040
"test:integration:update-state": "jest --forceExit --env=node --runInBand test/update-state-v2.spec.js",
4141
"test:integration:signing": "jest --forceExit --env=node --runInBand test/sign-verify.spec.js",
4242
"test:integration:messaging": "jest --forceExit --env=node --runInBand test/sign-messaging.spec.js",
4343
"test:integration:tails": "jest --forceExit --env=node --runInBand test/distribute-tails.spec.js",
4444
"test:integration:trustping": "jest --forceExit --env=node --runInBand test/trustping.spec.js",
45-
"test:integration:feature-discovery": "jest --forceExit --env=node --runInBand test/feature-discovery.spec.js"
45+
"test:integration:feature-discovery": "jest --forceExit --env=node --runInBand test/feature-discovery.spec.js",
46+
"test:integration:public-invite": "jest --forceExit --env=node --runInBand test/public-invite.spec.js"
4647
},
4748
"dependencies": {
4849
"axios": "^0.21.1",

agents/node/vcxagent-core/src/agent.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const { createServiceProver } = require('./services/service-prover')
66
const { createServiceCredHolder } = require('./services/service-cred-holder')
77
const { createServiceCredIssuer } = require('./services/service-cred-issuer')
88
const { createServiceConnections } = require('./services/service-connections')
9+
const { createServiceAgents } = require('./services/service-agents')
910
const { provisionAgentInAgency } = require('./utils/vcx-workflows')
1011
const {
1112
initThreadpool,
@@ -14,7 +15,7 @@ const {
1415
openMainWallet,
1516
openMainPool,
1617
vcxUpdateWebhookUrl,
17-
shutdownVcx,
18+
shutdownVcx
1819
} = require('@hyperledger/node-vcx-wrapper')
1920
const { createStorageService } = require('./storage/storage-service')
2021
const { waitUntilAgencyIsReady } = require('./common')
@@ -67,13 +68,14 @@ async function createVcxAgent ({ agentName, genesisPath, agencyUrl, seed, usePos
6768
}
6869

6970
function getInstitutionDid () {
70-
return agentProvision.institution_did
71+
return issuerDid
7172
}
7273

7374
const serviceConnections = createServiceConnections({
7475
logger,
7576
saveConnection: storageService.saveConnection,
7677
loadConnection: storageService.loadConnection,
78+
loadAgent: storageService.loadAgent,
7779
listConnectionIds: storageService.listConnectionKeys
7880
})
7981
const serviceLedgerSchema = createServiceLedgerSchema({
@@ -118,6 +120,11 @@ async function createVcxAgent ({ agentName, genesisPath, agencyUrl, seed, usePos
118120
loadProof: storageService.loadProof,
119121
listProofIds: storageService.listProofKeys
120122
})
123+
const serviceAgent = createServiceAgents({
124+
logger,
125+
saveAgent: storageService.saveAgent,
126+
loadAgent: storageService.loadAgent
127+
})
121128

122129
return {
123130
// vcx controls
@@ -140,7 +147,10 @@ async function createVcxAgent ({ agentName, genesisPath, agencyUrl, seed, usePos
140147

141148
// proofs
142149
serviceProver,
143-
serviceVerifier
150+
serviceVerifier,
151+
152+
// agents
153+
serviceAgent
144154
}
145155
}
146156

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const {
2+
Agent
3+
} = require('@hyperledger/node-vcx-wrapper')
4+
5+
module.exports.createServiceAgents = function createServiceAgents ({ logger, saveAgent, loadAgent }) {
6+
async function publicAgentCreate (agentId, institutionDid) {
7+
logger.info(`Creating public agent with id ${agentId} for institution did ${institutionDid}`)
8+
const agent = await Agent.create(agentId, institutionDid)
9+
await saveAgent(agentId, agent)
10+
return agent
11+
}
12+
13+
async function getPublicInvite (agentId, label) {
14+
logger.info(`Public agent with id ${agentId} is creating public invite with label ${label}`)
15+
const agent = await loadAgent(agentId)
16+
return agent.generatePublicInvite(label)
17+
}
18+
19+
async function downloadConnectionRequests (agentId) {
20+
logger.info(`Public agent with id ${agentId} is downloading connection requests`)
21+
const agent = await loadAgent(agentId)
22+
return agent.downloadConnectionRequests()
23+
}
24+
25+
return {
26+
publicAgentCreate,
27+
getPublicInvite,
28+
downloadConnectionRequests
29+
}
30+
}

agents/node/vcxagent-core/src/services/service-connections.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ const { getMessagesForConnection } = require('../utils/messages')
22
const {
33
updateMessages,
44
Connection,
5-
ConnectionStateType
5+
ConnectionStateType,
66
} = require('@hyperledger/node-vcx-wrapper')
77
const { pollFunction } = require('../common')
88

9-
module.exports.createServiceConnections = function createServiceConnections ({ logger, saveConnection, loadConnection, listConnectionIds }) {
9+
module.exports.createServiceConnections = function createServiceConnections ({ logger, saveConnection, loadConnection, loadAgent, listConnectionIds }) {
1010
async function inviterConnectionCreate (connectionId, cbInvitation) {
1111
logger.info(`InviterConnectionSM creating connection ${connectionId}`)
1212
const connection = await Connection.create({ id: connectionId })
@@ -22,6 +22,18 @@ module.exports.createServiceConnections = function createServiceConnections ({ l
2222
return invite
2323
}
2424

25+
async function inviterConnectionCreateFromRequest (connectionId, agentId, request) {
26+
logger.info(`InviterConnectionSM creating connection ${connectionId} from received request ${request} and agent id ${agentId}`)
27+
const agent = await loadAgent(agentId)
28+
const connection = await Connection.createWithConnectionRequest({
29+
id: connectionId,
30+
agent,
31+
request
32+
})
33+
await saveConnection(connectionId, connection)
34+
return connection
35+
}
36+
2537
async function inviterConnectionCreateAndAccept (conenctionId, cbInvitation) {
2638
const invite = await inviterConnectionCreate(conenctionId, cbInvitation)
2739
const connection = await loadConnection(conenctionId)
@@ -162,10 +174,10 @@ module.exports.createServiceConnections = function createServiceConnections ({ l
162174
await connection.sendDiscoveryFeatures()
163175
}
164176

165-
166177
return {
167178
// inviter
168179
inviterConnectionCreate,
180+
inviterConnectionCreateFromRequest,
169181
inviterConnectionCreateAndAccept,
170182

171183
// invitee

agents/node/vcxagent-core/src/storage/storage-service.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const {
77
CredentialDef,
88
Schema,
99
DisclosedProof,
10-
Proof
10+
Proof,
11+
Agent
1112
} = require('@hyperledger/node-vcx-wrapper')
1213

1314
async function createStorageService (agentName) {
@@ -24,6 +25,7 @@ async function createStorageService (agentName) {
2425
const storageDisclosedProof = await createFileStorage(`storage-dislosedProofs/${agentName}`)
2526
const storageCredentialDefinitons = await createFileStorage(`storage-credentialDefinitions/${agentName}`)
2627
const storageSchemas = await createFileStorage(`storage-schemas/${agentName}`)
28+
const storageAgents = await createFileStorage(`storage-agents/${agentName}`)
2729

2830
async function agentProvisionExists () {
2931
return storageAgentProvisions.hasKey('agent-provision')
@@ -128,6 +130,19 @@ async function createStorageService (agentName) {
128130
return Proof.deserialize(serialized)
129131
}
130132

133+
async function saveAgent (name, agent) {
134+
const serialized = await agent.serialize()
135+
await storageAgents.set(name, serialized)
136+
}
137+
138+
async function loadAgent (name) {
139+
const serialized = await storageAgents.get(name)
140+
if (!serialized) {
141+
throw Error(`Agent ${name} was not found.`)
142+
}
143+
return Agent.deserialize(serialized)
144+
}
145+
131146
async function listConnectionKeys () {
132147
return storageConnections.keys()
133148
}
@@ -182,6 +197,9 @@ async function createStorageService (agentName) {
182197
saveProof,
183198
loadProof,
184199

200+
saveAgent,
201+
loadAgent,
202+
185203
listConnectionKeys,
186204
listSchemaKeys,
187205
listCredentialDefinitionKeys,

agents/node/vcxagent-core/src/utils/messages.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { downloadMessages, downloadMessagesV2 } = require('@hyperledger/node-vcx-wrapper')
1+
const { downloadMessages, downloadMessagesV2, downloadAllMessages } = require('@hyperledger/node-vcx-wrapper')
22
const _ = require('lodash')
33

44
async function maybeJoinWithComma (list) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-env jest */
2+
require('jest')
3+
const { createPairedAliceAndFaberViaPublicInvite } = require('./utils/utils')
4+
const { initRustapi } = require('../src/index')
5+
6+
beforeAll(async () => {
7+
jest.setTimeout(1000 * 60 * 4)
8+
await initRustapi(process.env.VCX_LOG_LEVEL || 'vcx=error')
9+
})
10+
11+
describe('test public invite', () => {
12+
it('Establish connection via public invite, exchange messages', async () => {
13+
const { alice, faber } = await createPairedAliceAndFaberViaPublicInvite()
14+
15+
await alice.sendMessage('Hello Faber')
16+
const msgsFaber = await faber.downloadReceivedMessagesV2()
17+
expect(msgsFaber.length).toBe(1)
18+
expect(msgsFaber[0].uid).toBeDefined()
19+
expect(msgsFaber[0].statusCode).toBe('MS-103')
20+
const payloadFaber = JSON.parse(msgsFaber[0].decryptedMsg)
21+
expect(payloadFaber['@id']).toBeDefined()
22+
expect(payloadFaber['@type']).toBeDefined()
23+
expect(payloadFaber.content).toBe('Hello Faber')
24+
25+
await faber.sendMessage('Hello Alice')
26+
const msgsAlice = await alice.downloadReceivedMessagesV2()
27+
expect(msgsAlice.length).toBe(1)
28+
expect(msgsAlice[0].uid).toBeDefined()
29+
expect(msgsAlice[0].statusCode).toBe('MS-103')
30+
const payloadAlice = JSON.parse(msgsAlice[0].decryptedMsg)
31+
expect(payloadAlice['@id']).toBeDefined()
32+
expect(payloadAlice['@type']).toBeDefined()
33+
expect(payloadAlice.content).toBe('Hello Alice')
34+
})
35+
})

agents/node/vcxagent-core/test/utils/alice.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module.exports.createAlice = async function createAlice () {
2020
const vcxAgent = await createVcxAgent(aliceAgentConfig)
2121

2222
async function acceptInvite (invite) {
23-
logger.info('Alice establishing connection with Faber')
23+
logger.info(`Alice establishing connection with Faber using invite ${invite}`)
2424

2525
await vcxAgent.agentInitVcx()
2626

agents/node/vcxagent-core/test/utils/faber.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module.exports.createFaber = async function createFaber () {
88
const agentName = `faber-${Math.floor(new Date() / 1000)}`
99
const connectionId = 'connection-faber-to-alice'
1010
const issuerCredId = 'credential-for-alice'
11+
const agentId = 'faber-public-agent'
1112
let credDefId
1213
const proofId = 'proof-from-alice'
1314
const logger = require('../../demo/logger')('Faber')
@@ -37,6 +38,19 @@ module.exports.createFaber = async function createFaber () {
3738
return invite
3839
}
3940

41+
async function createPublicInvite () {
42+
logger.info('Faber is going to generate public invite')
43+
await vcxAgent.agentInitVcx()
44+
45+
await vcxAgent.serviceAgent.publicAgentCreate(agentId, vcxAgent.getInstitutionDid())
46+
const invite = await vcxAgent.serviceAgent.getPublicInvite(agentId, 'faber-label')
47+
logger.info(`Faber generated public invite:\n${invite}`)
48+
49+
await vcxAgent.agentShutdownVcx()
50+
51+
return invite
52+
}
53+
4054
async function sendConnectionResponse () {
4155
logger.info('Faber is going to generate invite')
4256
await vcxAgent.agentInitVcx()
@@ -137,6 +151,24 @@ module.exports.createFaber = async function createFaber () {
137151
return agencyMessages
138152
}
139153

154+
async function _downloadConnectionRequests () {
155+
logger.info('Faber is going to download connection requests')
156+
const connectionRequests = await vcxAgent.serviceAgent.downloadConnectionRequests(agentId)
157+
logger.info(`Downloaded connection requests: ${connectionRequests}`)
158+
return JSON.parse(connectionRequests)
159+
}
160+
161+
async function createConnectionFromReceivedRequest () {
162+
logger.info('Faber is going to download connection requests')
163+
await vcxAgent.agentInitVcx()
164+
165+
const requests = await _downloadConnectionRequests()
166+
await vcxAgent.serviceConnections.inviterConnectionCreateFromRequest(connectionId, agentId, JSON.stringify(requests[0]))
167+
expect(await vcxAgent.serviceConnections.connectionUpdate(connectionId)).toBe(ConnectionStateType.Responded)
168+
169+
await vcxAgent.agentShutdownVcx()
170+
}
171+
140172
async function updateMessageStatus (uids) {
141173
await vcxAgent.agentInitVcx()
142174
await vcxAgent.serviceConnections.updateMessagesStatus(connectionId, uids)
@@ -184,11 +216,21 @@ module.exports.createFaber = async function createFaber () {
184216
return tailsHash
185217
}
186218

219+
async function sendMessage (message) {
220+
logger.info('Faber is going to send message')
221+
await vcxAgent.agentInitVcx()
222+
await vcxAgent.serviceConnections.sendMessage(connectionId, message)
223+
await vcxAgent.agentShutdownVcx()
224+
}
225+
187226
return {
188227
downloadReceivedMessages,
189228
downloadReceivedMessagesV2,
229+
sendMessage,
190230
verifySignature,
191231
createInvite,
232+
createPublicInvite,
233+
createConnectionFromReceivedRequest,
192234
updateConnection,
193235
sendConnectionResponse,
194236
sendCredentialOffer,

agents/node/vcxagent-core/test/utils/utils.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,14 @@ module.exports.createPairedAliceAndFaber = async function createPairedAliceAndFa
1212
await faber.updateConnection(ConnectionStateType.Finished)
1313
return { alice, faber }
1414
}
15+
16+
module.exports.createPairedAliceAndFaberViaPublicInvite = async function createPairedAliceAndFaberViaPublicInvite () {
17+
const alice = await createAlice()
18+
const faber = await createFaber()
19+
const invite = await faber.createPublicInvite()
20+
await alice.acceptInvite(invite)
21+
await faber.createConnectionFromReceivedRequest()
22+
await alice.updateConnection(ConnectionStateType.Finished)
23+
await faber.updateConnection(ConnectionStateType.Finished)
24+
return { alice, faber }
25+
}

aries_vcx/src/handlers/connection/cloud_agent.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,18 @@ impl CloudAgentInfo {
8484
.map_err(|err| err.into())
8585
}
8686

87+
pub fn reject_message(&self, pairwise_info: &PairwiseInfo, uid: String) -> VcxResult<()> {
88+
trace!("CloudAgentInfo::reject_message >>> uid: {:?}", uid);
89+
90+
let messages_to_reject = vec![UIDsByConn {
91+
pairwise_did: pairwise_info.pw_did.clone(),
92+
uids: vec![uid],
93+
}];
94+
95+
update_messages_status(MessageStatusCode::Rejected, messages_to_reject)
96+
.map_err(|err| err.into())
97+
}
98+
8799
pub fn download_encrypted_messages(&self, msg_uid: Option<Vec<String>>, status_codes: Option<Vec<MessageStatusCode>>, pairwise_info: &PairwiseInfo) -> VcxResult<Vec<Message>> {
88100
trace!("CloudAgentInfo::download_encrypted_messages >>>");
89101
get_connection_messages(&pairwise_info.pw_did, &pairwise_info.pw_vk, &self.agent_did, &self.agent_vk, msg_uid, status_codes)

0 commit comments

Comments
 (0)