@zkpassport/sdk 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/cjs/index.d.ts +29 -2
- package/dist/cjs/index.js +416 -86
- package/dist/esm/index.d.ts +29 -2
- package/dist/esm/index.js +416 -86
- package/package.json +3 -3
- package/src/index.ts +504 -92
package/dist/esm/index.js
CHANGED
|
@@ -70,6 +70,7 @@ export class ZKPassport {
|
|
|
70
70
|
this.topicToService = {};
|
|
71
71
|
this.topicToProofs = {};
|
|
72
72
|
this.topicToExpectedProofCount = {};
|
|
73
|
+
this.topicToFailedProofCount = {};
|
|
73
74
|
this.topicToResults = {};
|
|
74
75
|
this.onRequestReceivedCallbacks = {};
|
|
75
76
|
this.onGeneratingProofCallbacks = {};
|
|
@@ -94,14 +95,19 @@ export class ZKPassport {
|
|
|
94
95
|
// Clear the results straight away to avoid concurrency issues
|
|
95
96
|
delete this.topicToResults[topic];
|
|
96
97
|
// Verify the proofs and extract the unique identifier (aka nullifier) and the verification result
|
|
97
|
-
const { uniqueIdentifier, verified } = await this.verify(topic, this.topicToProofs[topic], result);
|
|
98
|
+
const { uniqueIdentifier, verified, queryResultErrors } = await this.verify(topic, this.topicToProofs[topic], result);
|
|
99
|
+
const hasFailedProofs = this.topicToFailedProofCount[topic] > 0;
|
|
98
100
|
await Promise.all(this.onResultCallbacks[topic].map((callback) => callback({
|
|
99
|
-
|
|
100
|
-
verified
|
|
101
|
+
// If there are failed proofs, we don't return the unique identifier
|
|
102
|
+
// and we set the verified result to false
|
|
103
|
+
uniqueIdentifier: hasFailedProofs ? undefined : uniqueIdentifier,
|
|
104
|
+
verified: hasFailedProofs ? false : verified,
|
|
101
105
|
result,
|
|
106
|
+
queryResultErrors,
|
|
102
107
|
})));
|
|
103
|
-
// Clear the expected proof count
|
|
108
|
+
// Clear the expected proof count and failed proof count
|
|
104
109
|
delete this.topicToExpectedProofCount[topic];
|
|
110
|
+
delete this.topicToFailedProofCount[topic];
|
|
105
111
|
}
|
|
106
112
|
setExpectedProofCount(topic) {
|
|
107
113
|
const fields = Object.keys(this.topicToConfig[topic]).filter((key) => hasRequestedAccessToField(this.topicToConfig[topic], key));
|
|
@@ -135,13 +141,23 @@ export class ZKPassport {
|
|
|
135
141
|
}
|
|
136
142
|
break;
|
|
137
143
|
case "in":
|
|
138
|
-
if (field === "nationality" &&
|
|
139
|
-
neededCircuits.
|
|
144
|
+
if (field === "nationality" &&
|
|
145
|
+
!neededCircuits.includes("inclusion_check_nationality")) {
|
|
146
|
+
neededCircuits.push("inclusion_check_nationality");
|
|
147
|
+
}
|
|
148
|
+
else if (field === "issuing_country" &&
|
|
149
|
+
!neededCircuits.includes("inclusion_check_issuing_country")) {
|
|
150
|
+
neededCircuits.push("inclusion_check_issuing_country");
|
|
140
151
|
}
|
|
141
152
|
break;
|
|
142
153
|
case "out":
|
|
143
|
-
if (field === "nationality" &&
|
|
144
|
-
neededCircuits.
|
|
154
|
+
if (field === "nationality" &&
|
|
155
|
+
!neededCircuits.includes("exclusion_check_nationality")) {
|
|
156
|
+
neededCircuits.push("exclusion_check_nationality");
|
|
157
|
+
}
|
|
158
|
+
else if (field === "issuing_country" &&
|
|
159
|
+
!neededCircuits.includes("exclusion_check_issuing_country")) {
|
|
160
|
+
neededCircuits.push("exclusion_check_issuing_country");
|
|
145
161
|
}
|
|
146
162
|
break;
|
|
147
163
|
}
|
|
@@ -152,6 +168,7 @@ export class ZKPassport {
|
|
|
152
168
|
// Each separate needed circuit adds 1 disclosure proof
|
|
153
169
|
this.topicToExpectedProofCount[topic] =
|
|
154
170
|
neededCircuits.length === 0 ? 4 : 3 + neededCircuits.length;
|
|
171
|
+
this.topicToFailedProofCount[topic] = 0;
|
|
155
172
|
}
|
|
156
173
|
/**
|
|
157
174
|
* @notice Handle an encrypted message.
|
|
@@ -207,6 +224,7 @@ export class ZKPassport {
|
|
|
207
224
|
// This means the user has an ID that is not supported yet
|
|
208
225
|
// So we won't receive any proofs and we can handle the result now
|
|
209
226
|
this.topicToExpectedProofCount[topic] = 0;
|
|
227
|
+
this.topicToFailedProofCount[topic] += this.topicToExpectedProofCount[topic];
|
|
210
228
|
if (this.topicToResults[topic]) {
|
|
211
229
|
await this.handleResult(topic);
|
|
212
230
|
}
|
|
@@ -215,6 +233,7 @@ export class ZKPassport {
|
|
|
215
233
|
// This means one of the disclosure proofs failed to be generated
|
|
216
234
|
// So we need to remove one from the expected proof count
|
|
217
235
|
this.topicToExpectedProofCount[topic] -= 1;
|
|
236
|
+
this.topicToFailedProofCount[topic] += 1;
|
|
218
237
|
// If the expected proof count is now equal to the number of proofs received
|
|
219
238
|
// and the results were received, we can handle the result now
|
|
220
239
|
if (this.topicToResults[topic] &&
|
|
@@ -271,9 +290,6 @@ export class ZKPassport {
|
|
|
271
290
|
};
|
|
272
291
|
return this.getZkPassportRequest(topic);
|
|
273
292
|
},
|
|
274
|
-
/*checkAML: (country?: CountryName | Alpha2Code | Alpha3Code) => {
|
|
275
|
-
return this.getZkPassportRequest(topic)
|
|
276
|
-
},*/
|
|
277
293
|
done: () => {
|
|
278
294
|
const base64Config = Buffer.from(JSON.stringify(this.topicToConfig[topic])).toString("base64");
|
|
279
295
|
const base64Service = Buffer.from(JSON.stringify(this.topicToService[topic])).toString("base64");
|
|
@@ -384,6 +400,23 @@ export class ZKPassport {
|
|
|
384
400
|
const defaultDateValue = new Date(1111, 10, 11);
|
|
385
401
|
const currentTime = new Date();
|
|
386
402
|
const today = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, 0, 0, 0);
|
|
403
|
+
const queryResultErrors = {
|
|
404
|
+
sig_check_dsc: {},
|
|
405
|
+
sig_check_id_data: {},
|
|
406
|
+
data_check_integrity: {},
|
|
407
|
+
disclose: {},
|
|
408
|
+
age: {},
|
|
409
|
+
birthdate: {},
|
|
410
|
+
expiry_date: {},
|
|
411
|
+
document_type: {},
|
|
412
|
+
issuing_country: {},
|
|
413
|
+
gender: {},
|
|
414
|
+
nationality: {},
|
|
415
|
+
firstname: {},
|
|
416
|
+
lastname: {},
|
|
417
|
+
fullname: {},
|
|
418
|
+
document_number: {},
|
|
419
|
+
};
|
|
387
420
|
// Since the order is important for the commitments, we need to sort the proofs
|
|
388
421
|
// by their expected order: root signature check -> ID signature check -> integrity check -> disclosure
|
|
389
422
|
const sortedProofs = proofs.sort((a, b) => {
|
|
@@ -395,8 +428,10 @@ export class ZKPassport {
|
|
|
395
428
|
"compare_age",
|
|
396
429
|
"compare_birthdate",
|
|
397
430
|
"compare_expiry",
|
|
398
|
-
"
|
|
399
|
-
"
|
|
431
|
+
"exclusion_check_nationality",
|
|
432
|
+
"inclusion_check_nationality",
|
|
433
|
+
"exclusion_check_issuing_country",
|
|
434
|
+
"inclusion_check_issuing_country",
|
|
400
435
|
];
|
|
401
436
|
const getIndex = (proof) => {
|
|
402
437
|
const name = proof.name || "";
|
|
@@ -412,7 +447,11 @@ export class ZKPassport {
|
|
|
412
447
|
if (merkleRoot !== expectedMerkleRoot) {
|
|
413
448
|
console.warn("The ID was signed by an unrecognized root certificate");
|
|
414
449
|
isCorrect = false;
|
|
415
|
-
|
|
450
|
+
queryResultErrors.sig_check_dsc.certificate = {
|
|
451
|
+
expected: `Certificate registry root: ${expectedMerkleRoot.toString()}`,
|
|
452
|
+
received: `Certificate registry root: ${merkleRoot.toString()}`,
|
|
453
|
+
message: "The ID was signed by an unrecognized root certificate",
|
|
454
|
+
};
|
|
416
455
|
}
|
|
417
456
|
}
|
|
418
457
|
else if (proof.name?.startsWith("sig_check_id_data")) {
|
|
@@ -420,7 +459,11 @@ export class ZKPassport {
|
|
|
420
459
|
if (commitmentIn !== commitmentOut) {
|
|
421
460
|
console.warn("Failed to check the link between the certificate signature and ID signature");
|
|
422
461
|
isCorrect = false;
|
|
423
|
-
|
|
462
|
+
queryResultErrors.sig_check_id_data.commitment = {
|
|
463
|
+
expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
|
|
464
|
+
received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
|
|
465
|
+
message: "Failed to check the link between the certificate signature and ID signature",
|
|
466
|
+
};
|
|
424
467
|
}
|
|
425
468
|
commitmentOut = getCommitmentOutFromIDDataProof(proofData);
|
|
426
469
|
}
|
|
@@ -429,7 +472,11 @@ export class ZKPassport {
|
|
|
429
472
|
if (commitmentIn !== commitmentOut) {
|
|
430
473
|
console.warn("Failed to check the link between the ID signature and the data signed");
|
|
431
474
|
isCorrect = false;
|
|
432
|
-
|
|
475
|
+
queryResultErrors.data_check_integrity.commitment = {
|
|
476
|
+
expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
|
|
477
|
+
received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
|
|
478
|
+
message: "Failed to check the link between the ID signature and the data signed",
|
|
479
|
+
};
|
|
433
480
|
}
|
|
434
481
|
commitmentOut = getCommitmentOutFromIntegrityProof(proofData);
|
|
435
482
|
const currentDate = getCurrentDateFromIntegrityProof(proofData);
|
|
@@ -440,7 +487,11 @@ export class ZKPassport {
|
|
|
440
487
|
if (todayToCurrentDate >= actualDifference) {
|
|
441
488
|
console.warn(`The date used to check the validity of the ID is older than ${this.topicToLocalConfig[topic]?.validity} days. You can ask the user to rescan their ID or ask them to disclose their expiry date`);
|
|
442
489
|
isCorrect = false;
|
|
443
|
-
|
|
490
|
+
queryResultErrors.data_check_integrity.date = {
|
|
491
|
+
expected: `Difference: ${this.topicToLocalConfig[topic]?.validity} days`,
|
|
492
|
+
received: `Difference: ${Math.round(todayToCurrentDate / 86400000)} days`,
|
|
493
|
+
message: "The date used to check the validity of the ID is older than the validity period",
|
|
494
|
+
};
|
|
444
495
|
}
|
|
445
496
|
}
|
|
446
497
|
else if (proof.name === "disclose_bytes") {
|
|
@@ -448,7 +499,11 @@ export class ZKPassport {
|
|
|
448
499
|
if (commitmentIn !== commitmentOut) {
|
|
449
500
|
console.warn("Failed to check the link between the validity of the ID and the data to disclose");
|
|
450
501
|
isCorrect = false;
|
|
451
|
-
|
|
502
|
+
queryResultErrors.disclose.commitment = {
|
|
503
|
+
expected: `Commitment: ${commitmentOut?.toString() || "undefined"}`,
|
|
504
|
+
received: `Commitment: ${commitmentIn?.toString() || "undefined"}`,
|
|
505
|
+
message: "Failed to check the link between the validity of the ID and the data to disclose",
|
|
506
|
+
};
|
|
452
507
|
}
|
|
453
508
|
// We can't be certain that the disclosed data is for a passport or an ID card
|
|
454
509
|
// so we need to check both (unless the document type is revealed)
|
|
@@ -461,12 +516,20 @@ export class ZKPassport {
|
|
|
461
516
|
queryResult.document_type.eq.expected !== disclosedDataPassport.documentType) {
|
|
462
517
|
console.warn("Document type does not match the expected document type");
|
|
463
518
|
isCorrect = false;
|
|
464
|
-
|
|
519
|
+
queryResultErrors.document_type.eq = {
|
|
520
|
+
expected: `${queryResult.document_type.eq.expected}`,
|
|
521
|
+
received: `${disclosedDataPassport.documentType ?? disclosedDataIDCard.documentType}`,
|
|
522
|
+
message: "Document type does not match the expected document type",
|
|
523
|
+
};
|
|
465
524
|
}
|
|
466
525
|
if (queryResult.document_type.disclose?.result !== disclosedDataIDCard.documentType) {
|
|
467
526
|
console.warn("Document type does not match the disclosed document type in query result");
|
|
468
527
|
isCorrect = false;
|
|
469
|
-
|
|
528
|
+
queryResultErrors.document_type.disclose = {
|
|
529
|
+
expected: `${queryResult.document_type.disclose?.result}`,
|
|
530
|
+
received: `${disclosedDataIDCard.documentType ?? disclosedDataPassport.documentType}`,
|
|
531
|
+
message: "Document type does not match the disclosed document type in query result",
|
|
532
|
+
};
|
|
470
533
|
}
|
|
471
534
|
}
|
|
472
535
|
if (queryResult.birthdate) {
|
|
@@ -478,14 +541,22 @@ export class ZKPassport {
|
|
|
478
541
|
queryResult.birthdate.eq.expected.getTime() !== birthdateIDCard.getTime()) {
|
|
479
542
|
console.warn("Birthdate does not match the expected birthdate");
|
|
480
543
|
isCorrect = false;
|
|
481
|
-
|
|
544
|
+
queryResultErrors.birthdate.eq = {
|
|
545
|
+
expected: `${queryResult.birthdate.eq.expected.toISOString()}`,
|
|
546
|
+
received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
|
|
547
|
+
message: "Birthdate does not match the expected birthdate",
|
|
548
|
+
};
|
|
482
549
|
}
|
|
483
550
|
if (queryResult.birthdate.disclose &&
|
|
484
551
|
queryResult.birthdate.disclose.result.getTime() !== birthdatePassport.getTime() &&
|
|
485
552
|
queryResult.birthdate.disclose.result.getTime() !== birthdateIDCard.getTime()) {
|
|
486
553
|
console.warn("Birthdate does not match the disclosed birthdate in query result");
|
|
487
554
|
isCorrect = false;
|
|
488
|
-
|
|
555
|
+
queryResultErrors.birthdate.disclose = {
|
|
556
|
+
expected: `${queryResult.birthdate.disclose.result.toISOString()}`,
|
|
557
|
+
received: `${birthdatePassport?.toISOString() ?? birthdateIDCard?.toISOString()}`,
|
|
558
|
+
message: "Birthdate does not match the disclosed birthdate in query result",
|
|
559
|
+
};
|
|
489
560
|
}
|
|
490
561
|
}
|
|
491
562
|
if (queryResult.expiry_date) {
|
|
@@ -497,14 +568,22 @@ export class ZKPassport {
|
|
|
497
568
|
queryResult.expiry_date.eq.expected.getTime() !== expiryDateIDCard.getTime()) {
|
|
498
569
|
console.warn("Expiry date does not match the expected expiry date");
|
|
499
570
|
isCorrect = false;
|
|
500
|
-
|
|
571
|
+
queryResultErrors.expiry_date.eq = {
|
|
572
|
+
expected: `${queryResult.expiry_date.eq.expected.toISOString()}`,
|
|
573
|
+
received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
|
|
574
|
+
message: "Expiry date does not match the expected expiry date",
|
|
575
|
+
};
|
|
501
576
|
}
|
|
502
577
|
if (queryResult.expiry_date.disclose &&
|
|
503
578
|
queryResult.expiry_date.disclose.result.getTime() !== expiryDatePassport.getTime() &&
|
|
504
579
|
queryResult.expiry_date.disclose.result.getTime() !== expiryDateIDCard.getTime()) {
|
|
505
580
|
console.warn("Expiry date does not match the disclosed expiry date in query result");
|
|
506
581
|
isCorrect = false;
|
|
507
|
-
|
|
582
|
+
queryResultErrors.expiry_date.disclose = {
|
|
583
|
+
expected: `${queryResult.expiry_date.disclose.result.toISOString()}`,
|
|
584
|
+
received: `${expiryDatePassport?.toISOString() ?? expiryDateIDCard?.toISOString()}`,
|
|
585
|
+
message: "Expiry date does not match the disclosed expiry date in query result",
|
|
586
|
+
};
|
|
508
587
|
}
|
|
509
588
|
}
|
|
510
589
|
if (queryResult.nationality) {
|
|
@@ -516,14 +595,22 @@ export class ZKPassport {
|
|
|
516
595
|
queryResult.nationality.eq.expected !== nationalityIDCard) {
|
|
517
596
|
console.warn("Nationality does not match the expected nationality");
|
|
518
597
|
isCorrect = false;
|
|
519
|
-
|
|
598
|
+
queryResultErrors.nationality.eq = {
|
|
599
|
+
expected: `${queryResult.nationality.eq.expected}`,
|
|
600
|
+
received: `${nationalityPassport ?? nationalityIDCard}`,
|
|
601
|
+
message: "Nationality does not match the expected nationality",
|
|
602
|
+
};
|
|
520
603
|
}
|
|
521
604
|
if (queryResult.nationality.disclose &&
|
|
522
605
|
queryResult.nationality.disclose.result !== nationalityPassport &&
|
|
523
606
|
queryResult.nationality.disclose.result !== nationalityIDCard) {
|
|
524
607
|
console.warn("Nationality does not match the disclosed nationality in query result");
|
|
525
608
|
isCorrect = false;
|
|
526
|
-
|
|
609
|
+
queryResultErrors.nationality.disclose = {
|
|
610
|
+
expected: `${queryResult.nationality.disclose.result}`,
|
|
611
|
+
received: `${nationalityPassport ?? nationalityIDCard}`,
|
|
612
|
+
message: "Nationality does not match the disclosed nationality in query result",
|
|
613
|
+
};
|
|
527
614
|
}
|
|
528
615
|
}
|
|
529
616
|
if (queryResult.document_number) {
|
|
@@ -535,14 +622,22 @@ export class ZKPassport {
|
|
|
535
622
|
queryResult.document_number.eq.expected !== documentNumberIDCard) {
|
|
536
623
|
console.warn("Document number does not match the expected document number");
|
|
537
624
|
isCorrect = false;
|
|
538
|
-
|
|
625
|
+
queryResultErrors.document_number.eq = {
|
|
626
|
+
expected: `${queryResult.document_number.eq.expected}`,
|
|
627
|
+
received: `${documentNumberPassport ?? documentNumberIDCard}`,
|
|
628
|
+
message: "Document number does not match the expected document number",
|
|
629
|
+
};
|
|
539
630
|
}
|
|
540
631
|
if (queryResult.document_number.disclose &&
|
|
541
632
|
queryResult.document_number.disclose.result !== documentNumberPassport &&
|
|
542
633
|
queryResult.document_number.disclose.result !== documentNumberIDCard) {
|
|
543
634
|
console.warn("Document number does not match the disclosed document number in query result");
|
|
544
635
|
isCorrect = false;
|
|
545
|
-
|
|
636
|
+
queryResultErrors.document_number.disclose = {
|
|
637
|
+
expected: `${queryResult.document_number.disclose.result}`,
|
|
638
|
+
received: `${documentNumberPassport ?? documentNumberIDCard}`,
|
|
639
|
+
message: "Document number does not match the disclosed document number in query result",
|
|
640
|
+
};
|
|
546
641
|
}
|
|
547
642
|
}
|
|
548
643
|
if (queryResult.gender) {
|
|
@@ -554,14 +649,22 @@ export class ZKPassport {
|
|
|
554
649
|
queryResult.gender.eq.expected !== genderIDCard) {
|
|
555
650
|
console.warn("Gender does not match the expected gender");
|
|
556
651
|
isCorrect = false;
|
|
557
|
-
|
|
652
|
+
queryResultErrors.gender.eq = {
|
|
653
|
+
expected: `${queryResult.gender.eq.expected}`,
|
|
654
|
+
received: `${genderPassport ?? genderIDCard}`,
|
|
655
|
+
message: "Gender does not match the expected gender",
|
|
656
|
+
};
|
|
558
657
|
}
|
|
559
658
|
if (queryResult.gender.disclose &&
|
|
560
659
|
queryResult.gender.disclose.result !== genderPassport &&
|
|
561
660
|
queryResult.gender.disclose.result !== genderIDCard) {
|
|
562
661
|
console.warn("Gender does not match the disclosed gender in query result");
|
|
563
662
|
isCorrect = false;
|
|
564
|
-
|
|
663
|
+
queryResultErrors.gender.disclose = {
|
|
664
|
+
expected: `${queryResult.gender.disclose.result}`,
|
|
665
|
+
received: `${genderPassport ?? genderIDCard}`,
|
|
666
|
+
message: "Gender does not match the disclosed gender in query result",
|
|
667
|
+
};
|
|
565
668
|
}
|
|
566
669
|
}
|
|
567
670
|
if (queryResult.issuing_country) {
|
|
@@ -573,14 +676,22 @@ export class ZKPassport {
|
|
|
573
676
|
queryResult.issuing_country.eq.expected !== issuingCountryIDCard) {
|
|
574
677
|
console.warn("Issuing country does not match the expected issuing country");
|
|
575
678
|
isCorrect = false;
|
|
576
|
-
|
|
679
|
+
queryResultErrors.issuing_country.eq = {
|
|
680
|
+
expected: `${queryResult.issuing_country.eq.expected}`,
|
|
681
|
+
received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
|
|
682
|
+
message: "Issuing country does not match the expected issuing country",
|
|
683
|
+
};
|
|
577
684
|
}
|
|
578
685
|
if (queryResult.issuing_country.disclose &&
|
|
579
686
|
queryResult.issuing_country.disclose.result !== issuingCountryPassport &&
|
|
580
687
|
queryResult.issuing_country.disclose.result !== issuingCountryIDCard) {
|
|
581
688
|
console.warn("Issuing country does not match the disclosed issuing country in query result");
|
|
582
689
|
isCorrect = false;
|
|
583
|
-
|
|
690
|
+
queryResultErrors.issuing_country.disclose = {
|
|
691
|
+
expected: `${queryResult.issuing_country.disclose.result}`,
|
|
692
|
+
received: `${issuingCountryPassport ?? issuingCountryIDCard}`,
|
|
693
|
+
message: "Issuing country does not match the disclosed issuing country in query result",
|
|
694
|
+
};
|
|
584
695
|
}
|
|
585
696
|
}
|
|
586
697
|
if (queryResult.fullname) {
|
|
@@ -594,7 +705,11 @@ export class ZKPassport {
|
|
|
594
705
|
fullnameIDCard.toLowerCase()) {
|
|
595
706
|
console.warn("Fullname does not match the expected fullname");
|
|
596
707
|
isCorrect = false;
|
|
597
|
-
|
|
708
|
+
queryResultErrors.fullname.eq = {
|
|
709
|
+
expected: `${queryResult.fullname.eq.expected}`,
|
|
710
|
+
received: `${fullnamePassport ?? fullnameIDCard}`,
|
|
711
|
+
message: "Fullname does not match the expected fullname",
|
|
712
|
+
};
|
|
598
713
|
}
|
|
599
714
|
if (queryResult.fullname.disclose &&
|
|
600
715
|
formatName(queryResult.fullname.disclose.result).toLowerCase() !==
|
|
@@ -603,7 +718,11 @@ export class ZKPassport {
|
|
|
603
718
|
fullnameIDCard.toLowerCase()) {
|
|
604
719
|
console.warn("Fullname does not match the disclosed fullname in query result");
|
|
605
720
|
isCorrect = false;
|
|
606
|
-
|
|
721
|
+
queryResultErrors.fullname.disclose = {
|
|
722
|
+
expected: `${queryResult.fullname.disclose.result}`,
|
|
723
|
+
received: `${fullnamePassport ?? fullnameIDCard}`,
|
|
724
|
+
message: "Fullname does not match the disclosed fullname in query result",
|
|
725
|
+
};
|
|
607
726
|
}
|
|
608
727
|
}
|
|
609
728
|
if (queryResult.firstname) {
|
|
@@ -622,7 +741,11 @@ export class ZKPassport {
|
|
|
622
741
|
firstnameIDCard.toLowerCase()) {
|
|
623
742
|
console.warn("Firstname does not match the expected firstname");
|
|
624
743
|
isCorrect = false;
|
|
625
|
-
|
|
744
|
+
queryResultErrors.firstname.eq = {
|
|
745
|
+
expected: `${queryResult.firstname.eq.expected}`,
|
|
746
|
+
received: `${firstnamePassport ?? firstnameIDCard}`,
|
|
747
|
+
message: "Firstname does not match the expected firstname",
|
|
748
|
+
};
|
|
626
749
|
}
|
|
627
750
|
if (queryResult.firstname.disclose &&
|
|
628
751
|
formatName(queryResult.firstname.disclose.result).toLowerCase() !==
|
|
@@ -631,7 +754,11 @@ export class ZKPassport {
|
|
|
631
754
|
firstnameIDCard.toLowerCase()) {
|
|
632
755
|
console.warn("Firstname does not match the disclosed firstname in query result");
|
|
633
756
|
isCorrect = false;
|
|
634
|
-
|
|
757
|
+
queryResultErrors.firstname.disclose = {
|
|
758
|
+
expected: `${queryResult.firstname.disclose.result}`,
|
|
759
|
+
received: `${firstnamePassport ?? firstnameIDCard}`,
|
|
760
|
+
message: "Firstname does not match the disclosed firstname in query result",
|
|
761
|
+
};
|
|
635
762
|
}
|
|
636
763
|
}
|
|
637
764
|
if (queryResult.lastname) {
|
|
@@ -650,7 +777,11 @@ export class ZKPassport {
|
|
|
650
777
|
lastnameIDCard.toLowerCase()) {
|
|
651
778
|
console.warn("Lastname does not match the expected lastname");
|
|
652
779
|
isCorrect = false;
|
|
653
|
-
|
|
780
|
+
queryResultErrors.lastname.eq = {
|
|
781
|
+
expected: `${queryResult.lastname.eq.expected}`,
|
|
782
|
+
received: `${lastnamePassport ?? lastnameIDCard}`,
|
|
783
|
+
message: "Lastname does not match the expected lastname",
|
|
784
|
+
};
|
|
654
785
|
}
|
|
655
786
|
if (queryResult.lastname.disclose &&
|
|
656
787
|
formatName(queryResult.lastname.disclose.result).toLowerCase() !==
|
|
@@ -659,7 +790,11 @@ export class ZKPassport {
|
|
|
659
790
|
lastnameIDCard.toLowerCase()) {
|
|
660
791
|
console.warn("Lastname does not match the disclosed lastname in query result");
|
|
661
792
|
isCorrect = false;
|
|
662
|
-
|
|
793
|
+
queryResultErrors.lastname.disclose = {
|
|
794
|
+
expected: `${queryResult.lastname.disclose.result}`,
|
|
795
|
+
received: `${lastnamePassport ?? lastnameIDCard}`,
|
|
796
|
+
message: "Lastname does not match the disclosed lastname in query result",
|
|
797
|
+
};
|
|
663
798
|
}
|
|
664
799
|
}
|
|
665
800
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
@@ -669,7 +804,11 @@ export class ZKPassport {
|
|
|
669
804
|
if (commitmentIn !== commitmentOut) {
|
|
670
805
|
console.warn("Failed to check the link between the validity of the ID and the age derived from it");
|
|
671
806
|
isCorrect = false;
|
|
672
|
-
|
|
807
|
+
queryResultErrors.age.commitment = {
|
|
808
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
809
|
+
received: `Commitment: ${commitmentIn}`,
|
|
810
|
+
message: "Failed to check the link between the validity of the ID and the age derived from it",
|
|
811
|
+
};
|
|
673
812
|
}
|
|
674
813
|
const minAge = getMinAgeFromProof(proofData);
|
|
675
814
|
const maxAge = getMaxAgeFromProof(proofData);
|
|
@@ -679,14 +818,22 @@ export class ZKPassport {
|
|
|
679
818
|
minAge < queryResult.age.gte.expected) {
|
|
680
819
|
console.warn("Age is not greater than or equal to the expected age");
|
|
681
820
|
isCorrect = false;
|
|
682
|
-
|
|
821
|
+
queryResultErrors.age.gte = {
|
|
822
|
+
expected: queryResult.age.gte.expected,
|
|
823
|
+
received: minAge,
|
|
824
|
+
message: "Age is not greater than or equal to the expected age",
|
|
825
|
+
};
|
|
683
826
|
}
|
|
684
827
|
if (queryResult.age.lt &&
|
|
685
828
|
queryResult.age.lt.result &&
|
|
686
829
|
maxAge >= queryResult.age.lt.expected) {
|
|
687
830
|
console.warn("Age is not less than the expected age");
|
|
688
831
|
isCorrect = false;
|
|
689
|
-
|
|
832
|
+
queryResultErrors.age.lt = {
|
|
833
|
+
expected: queryResult.age.lt.expected,
|
|
834
|
+
received: maxAge,
|
|
835
|
+
message: "Age is not less than the expected age",
|
|
836
|
+
};
|
|
690
837
|
}
|
|
691
838
|
if (queryResult.age.range) {
|
|
692
839
|
if (queryResult.age.range.result &&
|
|
@@ -694,38 +841,60 @@ export class ZKPassport {
|
|
|
694
841
|
maxAge >= queryResult.age.range.expected[1])) {
|
|
695
842
|
console.warn("Age is not in the expected range");
|
|
696
843
|
isCorrect = false;
|
|
697
|
-
|
|
844
|
+
queryResultErrors.age.range = {
|
|
845
|
+
expected: queryResult.age.range.expected,
|
|
846
|
+
received: [minAge, maxAge],
|
|
847
|
+
message: "Age is not in the expected range",
|
|
848
|
+
};
|
|
698
849
|
}
|
|
699
850
|
}
|
|
700
851
|
if (!queryResult.age.lt && !queryResult.age.range && maxAge != 0) {
|
|
701
852
|
console.warn("Maximum age should be equal to 0");
|
|
702
853
|
isCorrect = false;
|
|
703
|
-
|
|
854
|
+
queryResultErrors.age.disclose = {
|
|
855
|
+
expected: 0,
|
|
856
|
+
received: maxAge,
|
|
857
|
+
message: "Maximum age should be equal to 0",
|
|
858
|
+
};
|
|
704
859
|
}
|
|
705
860
|
if (!queryResult.age.gte && !queryResult.age.range && minAge != 0) {
|
|
706
861
|
console.warn("Minimum age should be equal to 0");
|
|
707
862
|
isCorrect = false;
|
|
708
|
-
|
|
863
|
+
queryResultErrors.age.disclose = {
|
|
864
|
+
expected: 0,
|
|
865
|
+
received: minAge,
|
|
866
|
+
message: "Minimum age should be equal to 0",
|
|
867
|
+
};
|
|
709
868
|
}
|
|
710
869
|
if (queryResult.age.disclose &&
|
|
711
870
|
(queryResult.age.disclose.result !== minAge ||
|
|
712
871
|
queryResult.age.disclose.result !== maxAge)) {
|
|
713
872
|
console.warn("Age does not match the disclosed age in query result");
|
|
714
873
|
isCorrect = false;
|
|
715
|
-
|
|
874
|
+
queryResultErrors.age.disclose = {
|
|
875
|
+
expected: `${minAge}`,
|
|
876
|
+
received: `${queryResult.age.disclose.result}`,
|
|
877
|
+
message: "Age does not match the disclosed age in query result",
|
|
878
|
+
};
|
|
716
879
|
}
|
|
717
880
|
}
|
|
718
881
|
else {
|
|
719
882
|
console.warn("Age is not set in the query result");
|
|
720
883
|
isCorrect = false;
|
|
721
|
-
|
|
884
|
+
queryResultErrors.age.disclose = {
|
|
885
|
+
message: "Age is not set in the query result",
|
|
886
|
+
};
|
|
722
887
|
}
|
|
723
888
|
const currentDate = getCurrentDateFromAgeProof(proofData);
|
|
724
889
|
if (currentDate.getTime() !== today.getTime() &&
|
|
725
890
|
currentDate.getTime() !== today.getTime() - 86400000) {
|
|
726
891
|
console.warn("Current date in the proof is too old");
|
|
727
892
|
isCorrect = false;
|
|
728
|
-
|
|
893
|
+
queryResultErrors.age.disclose = {
|
|
894
|
+
expected: `${today.toISOString()}`,
|
|
895
|
+
received: `${currentDate.toISOString()}`,
|
|
896
|
+
message: "Current date in the proof is too old",
|
|
897
|
+
};
|
|
729
898
|
}
|
|
730
899
|
uniqueIdentifier = getCommitmentInFromDisclosureProof(proofData).toString(10);
|
|
731
900
|
}
|
|
@@ -734,7 +903,11 @@ export class ZKPassport {
|
|
|
734
903
|
if (commitmentIn !== commitmentOut) {
|
|
735
904
|
console.warn("Failed to check the link between the validity of the ID and the birthdate derived from it");
|
|
736
905
|
isCorrect = false;
|
|
737
|
-
|
|
906
|
+
queryResultErrors.birthdate.commitment = {
|
|
907
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
908
|
+
received: `Commitment: ${commitmentIn}`,
|
|
909
|
+
message: "Failed to check the link between the validity of the ID and the birthdate derived from it",
|
|
910
|
+
};
|
|
738
911
|
}
|
|
739
912
|
const minDate = getMinDateFromProof(proofData);
|
|
740
913
|
const maxDate = getMaxDateFromProof(proofData);
|
|
@@ -744,14 +917,22 @@ export class ZKPassport {
|
|
|
744
917
|
minDate < queryResult.birthdate.gte.expected) {
|
|
745
918
|
console.warn("Birthdate is not greater than or equal to the expected birthdate");
|
|
746
919
|
isCorrect = false;
|
|
747
|
-
|
|
920
|
+
queryResultErrors.birthdate.gte = {
|
|
921
|
+
expected: queryResult.birthdate.gte.expected,
|
|
922
|
+
received: minDate,
|
|
923
|
+
message: "Birthdate is not greater than or equal to the expected birthdate",
|
|
924
|
+
};
|
|
748
925
|
}
|
|
749
926
|
if (queryResult.birthdate.lte &&
|
|
750
927
|
queryResult.birthdate.lte.result &&
|
|
751
928
|
maxDate > queryResult.birthdate.lte.expected) {
|
|
752
929
|
console.warn("Birthdate is not less than the expected birthdate");
|
|
753
930
|
isCorrect = false;
|
|
754
|
-
|
|
931
|
+
queryResultErrors.birthdate.lte = {
|
|
932
|
+
expected: queryResult.birthdate.lte.expected,
|
|
933
|
+
received: maxDate,
|
|
934
|
+
message: "Birthdate is not less than the expected birthdate",
|
|
935
|
+
};
|
|
755
936
|
}
|
|
756
937
|
if (queryResult.birthdate.range) {
|
|
757
938
|
if (queryResult.birthdate.range.result &&
|
|
@@ -759,7 +940,11 @@ export class ZKPassport {
|
|
|
759
940
|
maxDate > queryResult.birthdate.range.expected[1])) {
|
|
760
941
|
console.warn("Birthdate is not in the expected range");
|
|
761
942
|
isCorrect = false;
|
|
762
|
-
|
|
943
|
+
queryResultErrors.birthdate.range = {
|
|
944
|
+
expected: queryResult.birthdate.range.expected,
|
|
945
|
+
received: [minDate, maxDate],
|
|
946
|
+
message: "Birthdate is not in the expected range",
|
|
947
|
+
};
|
|
763
948
|
}
|
|
764
949
|
}
|
|
765
950
|
if (!queryResult.birthdate.lte &&
|
|
@@ -767,20 +952,30 @@ export class ZKPassport {
|
|
|
767
952
|
maxDate.getTime() != defaultDateValue.getTime()) {
|
|
768
953
|
console.warn("Maximum birthdate should be equal to default date value");
|
|
769
954
|
isCorrect = false;
|
|
770
|
-
|
|
955
|
+
queryResultErrors.birthdate.disclose = {
|
|
956
|
+
expected: `${defaultDateValue.toISOString()}`,
|
|
957
|
+
received: `${maxDate.toISOString()}`,
|
|
958
|
+
message: "Maximum birthdate should be equal to default date value",
|
|
959
|
+
};
|
|
771
960
|
}
|
|
772
961
|
if (!queryResult.birthdate.gte &&
|
|
773
962
|
!queryResult.birthdate.range &&
|
|
774
963
|
minDate.getTime() != defaultDateValue.getTime()) {
|
|
775
964
|
console.warn("Minimum birthdate should be equal to default date value");
|
|
776
965
|
isCorrect = false;
|
|
777
|
-
|
|
966
|
+
queryResultErrors.birthdate.disclose = {
|
|
967
|
+
expected: `${defaultDateValue.toISOString()}`,
|
|
968
|
+
received: `${minDate.toISOString()}`,
|
|
969
|
+
message: "Minimum birthdate should be equal to default date value",
|
|
970
|
+
};
|
|
778
971
|
}
|
|
779
972
|
}
|
|
780
973
|
else {
|
|
781
974
|
console.warn("Birthdate is not set in the query result");
|
|
782
975
|
isCorrect = false;
|
|
783
|
-
|
|
976
|
+
queryResultErrors.birthdate.disclose = {
|
|
977
|
+
message: "Birthdate is not set in the query result",
|
|
978
|
+
};
|
|
784
979
|
}
|
|
785
980
|
uniqueIdentifier = getCommitmentInFromDisclosureProof(proofData).toString(10);
|
|
786
981
|
}
|
|
@@ -789,7 +984,11 @@ export class ZKPassport {
|
|
|
789
984
|
if (commitmentIn !== commitmentOut) {
|
|
790
985
|
console.warn("Failed to check the link between the validity of the ID and its expiry date");
|
|
791
986
|
isCorrect = false;
|
|
792
|
-
|
|
987
|
+
queryResultErrors.expiry_date.commitment = {
|
|
988
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
989
|
+
received: `Commitment: ${commitmentIn}`,
|
|
990
|
+
message: "Failed to check the link between the validity of the ID and its expiry date",
|
|
991
|
+
};
|
|
793
992
|
}
|
|
794
993
|
const minDate = getMinDateFromProof(proofData);
|
|
795
994
|
const maxDate = getMaxDateFromProof(proofData);
|
|
@@ -799,14 +998,22 @@ export class ZKPassport {
|
|
|
799
998
|
minDate < queryResult.expiry_date.gte.expected) {
|
|
800
999
|
console.warn("Expiry date is not greater than or equal to the expected expiry date");
|
|
801
1000
|
isCorrect = false;
|
|
802
|
-
|
|
1001
|
+
queryResultErrors.expiry_date.gte = {
|
|
1002
|
+
expected: queryResult.expiry_date.gte.expected,
|
|
1003
|
+
received: minDate,
|
|
1004
|
+
message: "Expiry date is not greater than or equal to the expected expiry date",
|
|
1005
|
+
};
|
|
803
1006
|
}
|
|
804
1007
|
if (queryResult.expiry_date.lte &&
|
|
805
1008
|
queryResult.expiry_date.lte.result &&
|
|
806
1009
|
maxDate > queryResult.expiry_date.lte.expected) {
|
|
807
1010
|
console.warn("Expiry date is not less than the expected expiry date");
|
|
808
1011
|
isCorrect = false;
|
|
809
|
-
|
|
1012
|
+
queryResultErrors.expiry_date.lte = {
|
|
1013
|
+
expected: queryResult.expiry_date.lte.expected,
|
|
1014
|
+
received: maxDate,
|
|
1015
|
+
message: "Expiry date is not less than the expected expiry date",
|
|
1016
|
+
};
|
|
810
1017
|
}
|
|
811
1018
|
if (queryResult.expiry_date.range) {
|
|
812
1019
|
if (queryResult.expiry_date.range.result &&
|
|
@@ -814,7 +1021,11 @@ export class ZKPassport {
|
|
|
814
1021
|
maxDate > queryResult.expiry_date.range.expected[1])) {
|
|
815
1022
|
console.warn("Expiry date is not in the expected range");
|
|
816
1023
|
isCorrect = false;
|
|
817
|
-
|
|
1024
|
+
queryResultErrors.expiry_date.range = {
|
|
1025
|
+
expected: queryResult.expiry_date.range.expected,
|
|
1026
|
+
received: [minDate, maxDate],
|
|
1027
|
+
message: "Expiry date is not in the expected range",
|
|
1028
|
+
};
|
|
818
1029
|
}
|
|
819
1030
|
}
|
|
820
1031
|
if (!queryResult.expiry_date.lte &&
|
|
@@ -822,44 +1033,64 @@ export class ZKPassport {
|
|
|
822
1033
|
maxDate.getTime() != defaultDateValue.getTime()) {
|
|
823
1034
|
console.warn("Maximum expiry date should be equal to default date value");
|
|
824
1035
|
isCorrect = false;
|
|
825
|
-
|
|
1036
|
+
queryResultErrors.expiry_date.disclose = {
|
|
1037
|
+
expected: `${defaultDateValue.toISOString()}`,
|
|
1038
|
+
received: `${maxDate.toISOString()}`,
|
|
1039
|
+
message: "Maximum expiry date should be equal to default date value",
|
|
1040
|
+
};
|
|
826
1041
|
}
|
|
827
1042
|
if (!queryResult.expiry_date.gte &&
|
|
828
1043
|
!queryResult.expiry_date.range &&
|
|
829
1044
|
minDate.getTime() != defaultDateValue.getTime()) {
|
|
830
1045
|
console.warn("Minimum expiry date should be equal to default date value");
|
|
831
1046
|
isCorrect = false;
|
|
832
|
-
|
|
1047
|
+
queryResultErrors.expiry_date.disclose = {
|
|
1048
|
+
expected: `${defaultDateValue.toISOString()}`,
|
|
1049
|
+
received: `${minDate.toISOString()}`,
|
|
1050
|
+
message: "Minimum expiry date should be equal to default date value",
|
|
1051
|
+
};
|
|
833
1052
|
}
|
|
834
1053
|
}
|
|
835
1054
|
else {
|
|
836
1055
|
console.warn("Expiry date is not set in the query result");
|
|
837
1056
|
isCorrect = false;
|
|
838
|
-
|
|
1057
|
+
queryResultErrors.expiry_date.disclose = {
|
|
1058
|
+
message: "Expiry date is not set in the query result",
|
|
1059
|
+
};
|
|
839
1060
|
}
|
|
840
1061
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
841
1062
|
}
|
|
842
|
-
else if (proof.name === "
|
|
1063
|
+
else if (proof.name === "exclusion_check_nationality") {
|
|
843
1064
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
844
1065
|
if (commitmentIn !== commitmentOut) {
|
|
845
|
-
console.warn("Failed to check the link between the validity of the ID and the
|
|
1066
|
+
console.warn("Failed to check the link between the validity of the ID and the nationality exclusion check");
|
|
846
1067
|
isCorrect = false;
|
|
847
|
-
|
|
1068
|
+
queryResultErrors.nationality.commitment = {
|
|
1069
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1070
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1071
|
+
message: "Failed to check the link between the validity of the ID and the nationality exclusion check",
|
|
1072
|
+
};
|
|
848
1073
|
}
|
|
849
1074
|
const countryList = getCountryListFromExclusionProof(proofData);
|
|
850
1075
|
if (queryResult.nationality &&
|
|
851
1076
|
queryResult.nationality.out &&
|
|
852
1077
|
queryResult.nationality.out.result) {
|
|
853
1078
|
if (!queryResult.nationality.out.expected?.every((country) => countryList.includes(country))) {
|
|
854
|
-
console.warn("
|
|
1079
|
+
console.warn("Nationality exclusion list does not match the one from the query results");
|
|
855
1080
|
isCorrect = false;
|
|
856
|
-
|
|
1081
|
+
queryResultErrors.nationality.out = {
|
|
1082
|
+
expected: queryResult.nationality.out.expected,
|
|
1083
|
+
received: countryList,
|
|
1084
|
+
message: "Nationality exclusion list does not match the one from the query results",
|
|
1085
|
+
};
|
|
857
1086
|
}
|
|
858
1087
|
}
|
|
859
1088
|
else if (!queryResult.nationality || !queryResult.nationality.out) {
|
|
860
1089
|
console.warn("Nationality exclusion is not set in the query result");
|
|
861
1090
|
isCorrect = false;
|
|
862
|
-
|
|
1091
|
+
queryResultErrors.nationality.out = {
|
|
1092
|
+
message: "Nationality exclusion is not set in the query result",
|
|
1093
|
+
};
|
|
863
1094
|
}
|
|
864
1095
|
// Check the countryList is in ascending order
|
|
865
1096
|
// If the prover doesn't use a sorted list then the proof cannot be trusted
|
|
@@ -868,37 +1099,129 @@ export class ZKPassport {
|
|
|
868
1099
|
if (countryList[i] < countryList[i - 1]) {
|
|
869
1100
|
console.warn("The nationality exclusion list has not been sorted, and thus the proof cannot be trusted");
|
|
870
1101
|
isCorrect = false;
|
|
871
|
-
|
|
1102
|
+
queryResultErrors.nationality.out = {
|
|
1103
|
+
message: "The nationality exclusion list has not been sorted, and thus the proof cannot be trusted",
|
|
1104
|
+
};
|
|
872
1105
|
}
|
|
873
1106
|
}
|
|
874
1107
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
875
1108
|
}
|
|
876
|
-
else if (proof.name === "
|
|
1109
|
+
else if (proof.name === "exclusion_check_issuing_country") {
|
|
877
1110
|
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
878
1111
|
if (commitmentIn !== commitmentOut) {
|
|
879
|
-
console.warn("Failed to check the link between the validity of the ID and the country
|
|
1112
|
+
console.warn("Failed to check the link between the validity of the ID and the issuing country exclusion check");
|
|
880
1113
|
isCorrect = false;
|
|
881
|
-
|
|
1114
|
+
queryResultErrors.nationality.commitment = {
|
|
1115
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1116
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1117
|
+
message: "Failed to check the link between the validity of the ID and the issuing country exclusion check",
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
const countryList = getCountryListFromExclusionProof(proofData);
|
|
1121
|
+
if (queryResult.issuing_country &&
|
|
1122
|
+
queryResult.issuing_country.out &&
|
|
1123
|
+
queryResult.issuing_country.out.result) {
|
|
1124
|
+
if (!queryResult.issuing_country.out.expected?.every((country) => countryList.includes(country))) {
|
|
1125
|
+
console.warn("Issuing country exclusion list does not match the one from the query results");
|
|
1126
|
+
isCorrect = false;
|
|
1127
|
+
queryResultErrors.issuing_country.out = {
|
|
1128
|
+
expected: queryResult.issuing_country.out.expected,
|
|
1129
|
+
received: countryList,
|
|
1130
|
+
message: "Issuing country exclusion list does not match the one from the query results",
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
else if (!queryResult.issuing_country || !queryResult.issuing_country.out) {
|
|
1135
|
+
console.warn("Issuing country exclusion is not set in the query result");
|
|
1136
|
+
isCorrect = false;
|
|
1137
|
+
queryResultErrors.issuing_country.out = {
|
|
1138
|
+
message: "Issuing country exclusion is not set in the query result",
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
// Check the countryList is in ascending order
|
|
1142
|
+
// If the prover doesn't use a sorted list then the proof cannot be trusted
|
|
1143
|
+
// as it is requirement in the circuit for the exclusion check to work
|
|
1144
|
+
for (let i = 1; i < countryList.length; i++) {
|
|
1145
|
+
if (countryList[i] < countryList[i - 1]) {
|
|
1146
|
+
console.warn("The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted");
|
|
1147
|
+
isCorrect = false;
|
|
1148
|
+
queryResultErrors.issuing_country.out = {
|
|
1149
|
+
message: "The issuing country exclusion list has not been sorted, and thus the proof cannot be trusted",
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1154
|
+
}
|
|
1155
|
+
else if (proof.name === "inclusion_check_nationality") {
|
|
1156
|
+
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
1157
|
+
if (commitmentIn !== commitmentOut) {
|
|
1158
|
+
console.warn("Failed to check the link between the validity of the ID and the nationality inclusion check");
|
|
1159
|
+
isCorrect = false;
|
|
1160
|
+
queryResultErrors.nationality.commitment = {
|
|
1161
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1162
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1163
|
+
message: "Failed to check the link between the validity of the ID and the nationality inclusion check",
|
|
1164
|
+
};
|
|
882
1165
|
}
|
|
883
1166
|
const countryList = getCountryListFromInclusionProof(proofData);
|
|
884
1167
|
if (queryResult.nationality &&
|
|
885
1168
|
queryResult.nationality.in &&
|
|
886
1169
|
queryResult.nationality.in.result) {
|
|
887
1170
|
if (!queryResult.nationality.in.expected?.every((country) => countryList.includes(country))) {
|
|
888
|
-
console.warn("
|
|
1171
|
+
console.warn("Nationality inclusion list does not match the one from the query results");
|
|
889
1172
|
isCorrect = false;
|
|
890
|
-
|
|
1173
|
+
queryResultErrors.nationality.in = {
|
|
1174
|
+
expected: queryResult.nationality.in.expected,
|
|
1175
|
+
received: countryList,
|
|
1176
|
+
message: "Nationality inclusion list does not match the one from the query results",
|
|
1177
|
+
};
|
|
891
1178
|
}
|
|
892
1179
|
}
|
|
893
1180
|
else if (!queryResult.nationality || !queryResult.nationality.in) {
|
|
894
1181
|
console.warn("Nationality inclusion is not set in the query result");
|
|
895
1182
|
isCorrect = false;
|
|
896
|
-
|
|
1183
|
+
queryResultErrors.nationality.in = {
|
|
1184
|
+
message: "Nationality inclusion is not set in the query result",
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
1188
|
+
}
|
|
1189
|
+
else if (proof.name === "inclusion_check_issuing_country") {
|
|
1190
|
+
commitmentIn = getCommitmentInFromDisclosureProof(proofData);
|
|
1191
|
+
if (commitmentIn !== commitmentOut) {
|
|
1192
|
+
console.warn("Failed to check the link between the validity of the ID and the issuing country inclusion check");
|
|
1193
|
+
isCorrect = false;
|
|
1194
|
+
queryResultErrors.nationality.commitment = {
|
|
1195
|
+
expected: `Commitment: ${commitmentOut}`,
|
|
1196
|
+
received: `Commitment: ${commitmentIn}`,
|
|
1197
|
+
message: "Failed to check the link between the validity of the ID and the issuing country inclusion check",
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
const countryList = getCountryListFromInclusionProof(proofData);
|
|
1201
|
+
if (queryResult.issuing_country &&
|
|
1202
|
+
queryResult.issuing_country.in &&
|
|
1203
|
+
queryResult.issuing_country.in.result) {
|
|
1204
|
+
if (!queryResult.issuing_country.in.expected?.every((country) => countryList.includes(country))) {
|
|
1205
|
+
console.warn("Issuing country inclusion list does not match the one from the query results");
|
|
1206
|
+
isCorrect = false;
|
|
1207
|
+
queryResultErrors.issuing_country.in = {
|
|
1208
|
+
expected: queryResult.issuing_country.in.expected,
|
|
1209
|
+
received: countryList,
|
|
1210
|
+
message: "Issuing country inclusion list does not match the one from the query results",
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
else if (!queryResult.issuing_country || !queryResult.issuing_country.in) {
|
|
1215
|
+
console.warn("Issuing country inclusion is not set in the query result");
|
|
1216
|
+
isCorrect = false;
|
|
1217
|
+
queryResultErrors.issuing_country.in = {
|
|
1218
|
+
message: "Issuing country inclusion is not set in the query result",
|
|
1219
|
+
};
|
|
897
1220
|
}
|
|
898
1221
|
uniqueIdentifier = getNullifierFromDisclosureProof(proofData).toString(10);
|
|
899
1222
|
}
|
|
900
1223
|
}
|
|
901
|
-
return { isCorrect, uniqueIdentifier };
|
|
1224
|
+
return { isCorrect, uniqueIdentifier, queryResultErrors };
|
|
902
1225
|
}
|
|
903
1226
|
/**
|
|
904
1227
|
* @notice Verify the proofs received from the mobile app.
|
|
@@ -913,12 +1236,6 @@ export class ZKPassport {
|
|
|
913
1236
|
// There is a minimum of 4 subproofs to make a complete proof
|
|
914
1237
|
if (!proofs || proofs.length < 4) {
|
|
915
1238
|
proofsToVerify = this.topicToProofs[requestId];
|
|
916
|
-
if (!proofsToVerify || proofsToVerify.length < 4) {
|
|
917
|
-
// It may happen that a request returns a result without proofs
|
|
918
|
-
// Meaning the ID is not supported yet by ZKPassport circuits,
|
|
919
|
-
// so the results has to be trusted and cannot be independently verified
|
|
920
|
-
return { uniqueIdentifier: undefined, verified: false };
|
|
921
|
-
}
|
|
922
1239
|
}
|
|
923
1240
|
const { BarretenbergVerifier } = await import("@aztec/bb.js");
|
|
924
1241
|
const verifier = new BarretenbergVerifier();
|
|
@@ -927,13 +1244,15 @@ export class ZKPassport {
|
|
|
927
1244
|
}*/
|
|
928
1245
|
let verified = true;
|
|
929
1246
|
let uniqueIdentifier;
|
|
1247
|
+
let queryResultErrors;
|
|
930
1248
|
if (queryResult) {
|
|
931
|
-
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
|
|
1249
|
+
const { isCorrect, uniqueIdentifier: uniqueIdentifierFromPublicInputs, queryResultErrors: queryResultErrorsFromPublicInputs, } = await this.checkPublicInputs(proofsToVerify, queryResult, requestId);
|
|
932
1250
|
uniqueIdentifier = uniqueIdentifierFromPublicInputs;
|
|
933
1251
|
verified = isCorrect;
|
|
1252
|
+
queryResultErrors = isCorrect ? undefined : queryResultErrorsFromPublicInputs;
|
|
934
1253
|
}
|
|
935
1254
|
// Only proceed with the proof verification if the public inputs are correct
|
|
936
|
-
if (verified) {
|
|
1255
|
+
if (verified && queryResult) {
|
|
937
1256
|
for (const proof of proofsToVerify) {
|
|
938
1257
|
const proofData = getProofData(proof.proof, true);
|
|
939
1258
|
const hostedPackagedCircuit = await getHostedPackagedCircuitByName(proof.version, proof.name);
|
|
@@ -953,7 +1272,7 @@ export class ZKPassport {
|
|
|
953
1272
|
}
|
|
954
1273
|
}
|
|
955
1274
|
this.topicToProofs[requestId] = [];
|
|
956
|
-
return { uniqueIdentifier, verified };
|
|
1275
|
+
return { uniqueIdentifier, verified, queryResultErrors };
|
|
957
1276
|
}
|
|
958
1277
|
/**
|
|
959
1278
|
* @notice Returns the URL of the request.
|
|
@@ -971,14 +1290,17 @@ export class ZKPassport {
|
|
|
971
1290
|
* @param requestId The request ID.
|
|
972
1291
|
*/
|
|
973
1292
|
cancelRequest(requestId) {
|
|
974
|
-
this.topicToWebSocketClient[requestId]
|
|
975
|
-
|
|
1293
|
+
if (this.topicToWebSocketClient[requestId]) {
|
|
1294
|
+
this.topicToWebSocketClient[requestId].close();
|
|
1295
|
+
delete this.topicToWebSocketClient[requestId];
|
|
1296
|
+
}
|
|
976
1297
|
delete this.topicToKeyPair[requestId];
|
|
977
1298
|
delete this.topicToConfig[requestId];
|
|
978
1299
|
delete this.topicToLocalConfig[requestId];
|
|
979
1300
|
delete this.topicToSharedSecret[requestId];
|
|
980
1301
|
delete this.topicToProofs[requestId];
|
|
981
1302
|
delete this.topicToExpectedProofCount[requestId];
|
|
1303
|
+
delete this.topicToFailedProofCount[requestId];
|
|
982
1304
|
delete this.topicToResults[requestId];
|
|
983
1305
|
this.onRequestReceivedCallbacks[requestId] = [];
|
|
984
1306
|
this.onGeneratingProofCallbacks[requestId] = [];
|
|
@@ -987,4 +1309,12 @@ export class ZKPassport {
|
|
|
987
1309
|
this.onRejectCallbacks[requestId] = [];
|
|
988
1310
|
this.onErrorCallbacks[requestId] = [];
|
|
989
1311
|
}
|
|
1312
|
+
/**
|
|
1313
|
+
* @notice Clears all requests.
|
|
1314
|
+
*/
|
|
1315
|
+
clearAllRequests() {
|
|
1316
|
+
for (const requestId in this.topicToWebSocketClient) {
|
|
1317
|
+
this.cancelRequest(requestId);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
990
1320
|
}
|