Skip to content

Commit 76e629b

Browse files
test: add zkp e2e test (#194)
Signed-off-by: Allain Magyar <[email protected]> Co-authored-by: Allain Magyar <[email protected]>
1 parent d7c464f commit 76e629b

13 files changed

+856
-779
lines changed

integration-tests/e2e-tests/.eslintrc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
root: true
22
ignorePatterns:
33
- target
4+
- InMemoryStore.ts
45
env:
5-
esnext: true
66
node: true
77
extends:
88
- eslint:recommended
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@anoncred @proof
2+
Feature: Provide proof
3+
The Edge Agent should provide proof to Cloud Agent
4+
5+
Scenario: Edge Agent with a credential should provide proof to Cloud Agent
6+
Given Cloud Agent is connected to Edge Agent
7+
And Edge Agent has 1 anonymous credentials issued by Cloud Agent
8+
When Cloud Agent asks for presentation of AnonCred proof
9+
And Edge Agent sends the present-proof
10+
Then Cloud Agent should see the present-proof is verified

integration-tests/e2e-tests/features/provide_proof.feature

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@proof
1+
@jwt @proof
22
Feature: Provide proof
33
The Edge Agent should provide proof to Cloud Agent
44

integration-tests/e2e-tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"@atala/prism-wallet-sdk": "^5.0.0",
2121
"@cucumber/cucumber": "^10.3.1",
2222
"@cucumber/pretty-formatter": "^1.0.0",
23-
"@hyperledger-labs/open-enterprise-agent-ts-client": "^1.19.1",
23+
"@hyperledger-labs/open-enterprise-agent-ts-client": "^1.31.0",
2424
"@serenity-js/assertions": "^3.16.0",
2525
"@serenity-js/console-reporter": "^3.16.0",
2626
"@serenity-js/core": "^3.16.0",

integration-tests/e2e-tests/src/Utils.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {appendFile, writeFileSync} from "fs"
1+
import { appendFile, writeFileSync } from "fs"
2+
import crypto from "crypto"
23

34
export class Utils {
45
static prepareNotes() {
@@ -8,7 +9,7 @@ export class Utils {
89
static appendToNotes(message: string) {
910
console.info("Adding to notes:", message)
1011
appendFile("notes", message + "\n", (err) => {
11-
if(err) console.error(err)
12+
if (err) console.error(err)
1213
})
1314
}
1415

@@ -30,8 +31,21 @@ export class Utils {
3031
}
3132
retry++
3233
}
33-
let error = Error(`${delegateError.message} afer retrying [${times}] times`)
34+
const error = Error(`${delegateError.message} afer retrying [${times}] times`)
3435
error.stack = delegateError.stack
3536
throw error
3637
}
38+
39+
static generateNonce(length: number): string {
40+
let result = ""
41+
while (result.length < length) {
42+
const byte = crypto.randomBytes(1)[0]
43+
if (byte >= 250) {
44+
continue
45+
}
46+
const randomDigit = byte % 10
47+
result += randomDigit.toString()
48+
}
49+
return result
50+
}
3751
}
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
1-
import { Ability, Discardable, Initialisable, Interaction, Question, QuestionAdapter } from "@serenity-js/core";
2-
import SDK from "@atala/prism-wallet-sdk";
3-
import { Message } from "@atala/prism-wallet-sdk/build/typings/domain";
4-
import axios from "axios";
5-
import { CloudAgentConfiguration } from "../configuration/CloudAgentConfiguration";
6-
import { Utils } from "../Utils";
7-
import { InMemoryStore } from "../configuration/InMemoryStore";
1+
import { Ability, Discardable, Initialisable, Interaction, Question, QuestionAdapter } from "@serenity-js/core"
2+
import SDK from "@atala/prism-wallet-sdk"
3+
import { Message } from "@atala/prism-wallet-sdk/build/typings/domain"
4+
import axios from "axios"
5+
import { CloudAgentConfiguration } from "../configuration/CloudAgentConfiguration"
6+
import { Utils } from "../Utils"
7+
import { InMemoryStore } from "../configuration/InMemoryStore"
88

9-
const { Agent, Apollo, Domain, ListenerKey, } = SDK;
9+
const { Agent, Apollo, Domain, ListenerKey, } = SDK
1010

1111
export class WalletSdk extends Ability implements Initialisable, Discardable {
12-
sdk!: SDK.Agent;
13-
messages: MessageQueue = new MessageQueue();
12+
sdk!: SDK.Agent
13+
messages: MessageQueue = new MessageQueue()
1414

1515
static async withANewInstance(): Promise<Ability> {
1616
const instance: SDK.Agent = await Utils.retry(2, async () => {
17-
return await WalletSdkBuilder.createInstance();
18-
});
19-
return new WalletSdk(instance);
17+
return await WalletSdkBuilder.createInstance()
18+
})
19+
return new WalletSdk(instance)
2020
}
2121

2222
constructor(sdk: SDK.Agent) {
23-
super();
24-
this.sdk = sdk;
23+
super()
24+
this.sdk = sdk
2525
}
2626

2727
static credentialOfferStackSize(): QuestionAdapter<number> {
2828
return Question.about("credential offer stack", actor => {
29-
return WalletSdk.as(actor).messages.credentialOfferStack.length;
30-
});
29+
return WalletSdk.as(actor).messages.credentialOfferStack.length
30+
})
3131
}
3232

3333
static issuedCredentialStackSize(): QuestionAdapter<number> {
3434
return Question.about("issued credential stack", actor => {
35-
return WalletSdk.as(actor).messages.issuedCredentialStack.length;
36-
});
35+
return WalletSdk.as(actor).messages.issuedCredentialStack.length
36+
})
3737
}
3838

3939
static proofOfRequestStackSize(): QuestionAdapter<number> {
4040
return Question.about("proof of request stack", actor => {
41-
return WalletSdk.as(actor).messages.proofRequestStack.length;
42-
});
41+
return WalletSdk.as(actor).messages.proofRequestStack.length
42+
})
4343
}
4444

4545
static execute(callback: (sdk: SDK.Agent, messages: {
@@ -52,106 +52,106 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
5252
credentialOfferStack: WalletSdk.as(actor).messages.credentialOfferStack,
5353
issuedCredentialStack: WalletSdk.as(actor).messages.issuedCredentialStack,
5454
proofRequestStack: WalletSdk.as(actor).messages.proofRequestStack
55-
});
56-
});
55+
})
56+
})
5757
}
5858

5959
async discard(): Promise<void> {
60-
await this.sdk.stop();
60+
await this.sdk.stop()
6161
}
6262

6363
async initialise(): Promise<void> {
6464
this.sdk.addListener(
6565
ListenerKey.MESSAGE, (messages: SDK.Domain.Message[]) => {
6666
for (const message of messages) {
67-
this.messages.enqueue(message);
67+
this.messages.enqueue(message)
6868
}
6969
}
70-
);
70+
)
7171

72-
await this.sdk.start();
72+
await this.sdk.start()
7373
}
7474

7575
isInitialised(): boolean {
76-
return this.sdk.state != "stopped";
76+
return this.sdk.state != "stopped"
7777
}
7878
}
7979

8080
class WalletSdkBuilder {
8181
private static async getMediatorDidThroughOob(): Promise<string> {
82-
const response = await axios.get(CloudAgentConfiguration.mediatorOobUrl);
83-
const encodedData = response.data.split("?_oob=")[1];
84-
const oobData = JSON.parse(Buffer.from(encodedData, "base64").toString());
85-
return oobData.from;
82+
const response = await axios.get(CloudAgentConfiguration.mediatorOobUrl)
83+
const encodedData = response.data.split("?_oob=")[1]
84+
const oobData = JSON.parse(Buffer.from(encodedData, "base64").toString())
85+
return oobData.from
8686
}
8787

8888
static async createInstance() {
89-
const apollo = new Apollo();
90-
const store = new InMemoryStore();
91-
const pluto = new SDK.Pluto(store, apollo);
92-
const mediatorDID = Domain.DID.fromString(await WalletSdkBuilder.getMediatorDidThroughOob());
89+
const apollo = new Apollo()
90+
const store = new InMemoryStore()
91+
const pluto = new SDK.Pluto(store, apollo)
92+
const mediatorDID = Domain.DID.fromString(await WalletSdkBuilder.getMediatorDidThroughOob())
9393

94-
return Agent.initialize({ apollo, pluto, mediatorDID });
94+
return Agent.initialize({ apollo, pluto, mediatorDID })
9595
}
9696
}
9797

9898
/**
9999
* Helper class for message queueing processor
100100
*/
101101
class MessageQueue {
102-
private processingId: NodeJS.Timeout | null = null;
103-
private queue: Message[] = [];
102+
private processingId: NodeJS.Timeout | null = null
103+
private queue: Message[] = []
104104

105-
credentialOfferStack: Message[] = [];
106-
proofRequestStack: Message[] = [];
107-
issuedCredentialStack: Message[] = [];
108-
receivedMessages: string[] = [];
105+
credentialOfferStack: Message[] = []
106+
proofRequestStack: Message[] = []
107+
issuedCredentialStack: Message[] = []
108+
receivedMessages: string[] = []
109109

110110
enqueue(message: Message) {
111-
this.queue.push(message);
111+
this.queue.push(message)
112112

113113
// auto start processing messages
114114
if (!this.processingId) {
115-
this.processMessages();
115+
this.processMessages()
116116
}
117117
}
118118

119119
dequeue(): Message {
120-
return this.queue.shift()!;
120+
return this.queue.shift()!
121121
}
122122

123123
// Check if the queue is empty
124124
isEmpty(): boolean {
125-
return this.queue.length === 0;
125+
return this.queue.length === 0
126126
}
127127

128128
// Get the number of messages in the queue
129129
size(): number {
130-
return this.queue.length;
130+
return this.queue.length
131131
}
132132

133133
processMessages() {
134134
this.processingId = setInterval(() => {
135135
if (!this.isEmpty()) {
136-
const message: Message = this.dequeue();
136+
const message: Message = this.dequeue()
137137
// checks if sdk already received message
138138
if (this.receivedMessages.includes(message.id)) {
139-
return;
139+
return
140140
}
141141

142-
this.receivedMessages.push(message.id);
142+
this.receivedMessages.push(message.id)
143143

144144
if (message.piuri.includes("/offer-credential")) {
145-
this.credentialOfferStack.push(message);
145+
this.credentialOfferStack.push(message)
146146
} else if (message.piuri.includes("/present-proof")) {
147-
this.proofRequestStack.push(message);
147+
this.proofRequestStack.push(message)
148148
} else if (message.piuri.includes("/issue-credential")) {
149-
this.issuedCredentialStack.push(message);
149+
this.issuedCredentialStack.push(message)
150150
}
151151
} else {
152-
clearInterval(this.processingId!);
153-
this.processingId = null;
152+
clearInterval(this.processingId!)
153+
this.processingId = null
154154
}
155-
}, 50);
155+
}, 50)
156156
}
157157
}

integration-tests/e2e-tests/src/configuration/CloudAgentConfiguration.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
CreateManagedDidRequestDocumentTemplate,
44
CredentialDefinitionInput,
55
CredentialSchemaInput,
6-
ManagedDIDKeyTemplate
6+
ManagedDIDKeyTemplate,
7+
Purpose
78
} from "@hyperledger-labs/open-enterprise-agent-ts-client"
89
import {Utils} from "../Utils"
910
import {randomUUID} from "crypto"
@@ -70,7 +71,7 @@ export class CloudAgentConfiguration {
7071

7172
const publicKey = new ManagedDIDKeyTemplate()
7273
publicKey.id = "key-1"
73-
publicKey.purpose = "assertionMethod"
74+
publicKey.purpose = Purpose.AssertionMethod
7475

7576
creationData.documentTemplate.publicKeys = [publicKey]
7677
creationData.documentTemplate.services = []
@@ -176,7 +177,7 @@ export class CloudAgentConfiguration {
176177
name: "Automation Anoncred",
177178
version: "1.0",
178179
issuerId : this.publishedDid,
179-
attrNames: ["name", "age"]
180+
attrNames: ["name", "age", "gender"]
180181
}
181182

182183
const credentialSchemaInput: CredentialSchemaInput = {
@@ -201,7 +202,7 @@ export class CloudAgentConfiguration {
201202
version: "1.0.0",
202203
tag: "automation-test",
203204
author: this.publishedDid,
204-
schemaId: `${this.agentUrl}schema-registry/schemas/${newSchemaGuid}/schema`,
205+
schemaId: `${this.agentUrl}/schema-registry/schemas/${newSchemaGuid}/schema`,
205206
signatureType: "CL",
206207
supportRevocation: false,
207208
description: "Test Automation Auto-Generated TS"

0 commit comments

Comments
 (0)