@0xpolygonid/js-sdk 1.9.0 → 1.9.2
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/dist/browser/esm/index.js +201 -78
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +202 -77
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/iden3comm/handlers/auth.js +14 -55
- package/dist/node/cjs/iden3comm/handlers/common.js +85 -0
- package/dist/node/cjs/iden3comm/handlers/contract-request.js +5 -15
- package/dist/node/cjs/iden3comm/handlers/index.js +2 -0
- package/dist/node/cjs/iden3comm/handlers/revocation-status.js +119 -0
- package/dist/node/cjs/identity/identity-wallet.js +4 -0
- package/dist/node/cjs/proof/common.js +11 -3
- package/dist/node/cjs/proof/proof-service.js +1 -4
- package/dist/node/cjs/storage/filters/jsonQuery.js +1 -1
- package/dist/node/esm/iden3comm/handlers/auth.js +15 -56
- package/dist/node/esm/iden3comm/handlers/common.js +81 -0
- package/dist/node/esm/iden3comm/handlers/contract-request.js +5 -15
- package/dist/node/esm/iden3comm/handlers/index.js +2 -0
- package/dist/node/esm/iden3comm/handlers/revocation-status.js +92 -0
- package/dist/node/esm/identity/identity-wallet.js +4 -0
- package/dist/node/esm/proof/common.js +12 -4
- package/dist/node/esm/proof/proof-service.js +1 -4
- package/dist/node/esm/storage/filters/jsonQuery.js +1 -1
- package/dist/types/iden3comm/handlers/auth.d.ts +1 -0
- package/dist/types/iden3comm/handlers/common.d.ts +23 -0
- package/dist/types/iden3comm/handlers/contract-request.d.ts +1 -1
- package/dist/types/iden3comm/handlers/index.d.ts +2 -0
- package/dist/types/iden3comm/handlers/revocation-status.d.ts +59 -0
- package/dist/types/identity/identity-wallet.d.ts +13 -1
- package/dist/types/verifiable/credential.d.ts +1 -1
- package/dist/types/verifiable/proof.d.ts +5 -1
- package/package.json +1 -1
|
@@ -30,7 +30,8 @@ const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
|
30
30
|
const js_jwz_1 = require("@iden3/js-jwz");
|
|
31
31
|
const uuid = __importStar(require("uuid"));
|
|
32
32
|
const utils_1 = require("../../utils");
|
|
33
|
-
const
|
|
33
|
+
const common_1 = require("./common");
|
|
34
|
+
const circuits_1 = require("../../circuits");
|
|
34
35
|
/**
|
|
35
36
|
* createAuthorizationRequest is a function to create protocol authorization request
|
|
36
37
|
* @param {string} reason - reason to request proof
|
|
@@ -87,6 +88,12 @@ class AuthHandler {
|
|
|
87
88
|
constructor(_packerMgr, _proofService) {
|
|
88
89
|
this._packerMgr = _packerMgr;
|
|
89
90
|
this._proofService = _proofService;
|
|
91
|
+
this._supportedCircuits = [
|
|
92
|
+
circuits_1.CircuitId.AtomicQueryV3,
|
|
93
|
+
circuits_1.CircuitId.AtomicQuerySigV2,
|
|
94
|
+
circuits_1.CircuitId.AtomicQueryMTPV2,
|
|
95
|
+
circuits_1.CircuitId.LinkedMultiQuery10
|
|
96
|
+
];
|
|
90
97
|
}
|
|
91
98
|
/**
|
|
92
99
|
* @inheritdoc IAuthHandler#parseAuthorizationRequest
|
|
@@ -121,6 +128,11 @@ class AuthHandler {
|
|
|
121
128
|
did = js_iden3_core_1.DID.parse(authRequest.to);
|
|
122
129
|
}
|
|
123
130
|
const guid = uuid.v4();
|
|
131
|
+
if (!authRequest.from) {
|
|
132
|
+
throw new Error('auth request should contain from field');
|
|
133
|
+
}
|
|
134
|
+
const from = js_iden3_core_1.DID.parse(authRequest.from);
|
|
135
|
+
const responseScope = await (0, common_1.processZeroKnowledgeProofRequests)(did, authRequest?.body.scope, from, this._proofService, { ...opts, supportedCircuits: this._supportedCircuits });
|
|
124
136
|
const authResponse = {
|
|
125
137
|
id: guid,
|
|
126
138
|
typ: opts.mediaType,
|
|
@@ -128,64 +140,11 @@ class AuthHandler {
|
|
|
128
140
|
thid: authRequest.thid ?? guid,
|
|
129
141
|
body: {
|
|
130
142
|
message: authRequest?.body?.message,
|
|
131
|
-
scope:
|
|
143
|
+
scope: responseScope
|
|
132
144
|
},
|
|
133
145
|
from: did.string(),
|
|
134
146
|
to: authRequest.from
|
|
135
147
|
};
|
|
136
|
-
const requestScope = authRequest.body.scope;
|
|
137
|
-
const combinedQueries = requestScope.reduce((acc, proofReq) => {
|
|
138
|
-
const groupId = proofReq.query.groupId;
|
|
139
|
-
if (!groupId) {
|
|
140
|
-
return acc;
|
|
141
|
-
}
|
|
142
|
-
const existedData = acc.get(groupId);
|
|
143
|
-
if (!existedData) {
|
|
144
|
-
const seed = (0, js_crypto_1.getRandomBytes)(12);
|
|
145
|
-
const dataView = new DataView(seed.buffer);
|
|
146
|
-
const linkNonce = dataView.getUint32(0);
|
|
147
|
-
acc.set(groupId, { query: proofReq.query, linkNonce });
|
|
148
|
-
return acc;
|
|
149
|
-
}
|
|
150
|
-
const credentialSubject = (0, utils_1.mergeObjects)(existedData.query.credentialSubject, proofReq.query.credentialSubject);
|
|
151
|
-
acc.set(groupId, {
|
|
152
|
-
...existedData,
|
|
153
|
-
query: {
|
|
154
|
-
skipClaimRevocationCheck: existedData.query.skipClaimRevocationCheck || proofReq.query.skipClaimRevocationCheck,
|
|
155
|
-
...existedData.query,
|
|
156
|
-
credentialSubject
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
return acc;
|
|
160
|
-
}, new Map());
|
|
161
|
-
const groupedCredentialsCache = new Map();
|
|
162
|
-
for (const proofReq of requestScope) {
|
|
163
|
-
const query = proofReq.query;
|
|
164
|
-
const groupId = query.groupId;
|
|
165
|
-
const combinedQueryData = combinedQueries.get(groupId);
|
|
166
|
-
if (groupId) {
|
|
167
|
-
if (!combinedQueryData) {
|
|
168
|
-
throw new Error(`Invalid group id ${query.groupId}`);
|
|
169
|
-
}
|
|
170
|
-
const combinedQuery = combinedQueryData.query;
|
|
171
|
-
if (!groupedCredentialsCache.has(groupId)) {
|
|
172
|
-
const credWithRevStatus = await this._proofService.findCredentialByProofQuery(did, combinedQueryData.query);
|
|
173
|
-
if (!credWithRevStatus.cred) {
|
|
174
|
-
throw new Error(`Credential not found for query ${JSON.stringify(combinedQuery)}`);
|
|
175
|
-
}
|
|
176
|
-
groupedCredentialsCache.set(groupId, credWithRevStatus);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
const credWithRevStatus = groupedCredentialsCache.get(groupId);
|
|
180
|
-
const zkpRes = await this._proofService.generateProof(proofReq, did, {
|
|
181
|
-
verifierDid: js_iden3_core_1.DID.parse(authRequest.from),
|
|
182
|
-
skipRevocation: Boolean(query.skipClaimRevocationCheck),
|
|
183
|
-
credential: credWithRevStatus?.cred,
|
|
184
|
-
credentialRevocationStatus: credWithRevStatus?.revStatus,
|
|
185
|
-
linkNonce: combinedQueryData?.linkNonce ? BigInt(combinedQueryData.linkNonce) : undefined
|
|
186
|
-
});
|
|
187
|
-
authResponse.body.scope.push(zkpRes);
|
|
188
|
-
}
|
|
189
148
|
const msgBytes = utils_1.byteEncoder.encode(JSON.stringify(authResponse));
|
|
190
149
|
const packerOpts = opts.mediaType === constants_1.MediaType.SignedMessage
|
|
191
150
|
? opts.packerOptions
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processZeroKnowledgeProofRequests = void 0;
|
|
4
|
+
const js_crypto_1 = require("@iden3/js-crypto");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
|
+
/**
|
|
7
|
+
* Groups the ZeroKnowledgeProofRequest objects based on their groupId.
|
|
8
|
+
* Returns a Map where the key is the groupId and the value is an object containing the query and linkNonce.
|
|
9
|
+
*
|
|
10
|
+
* @param requestScope - An array of ZeroKnowledgeProofRequest objects.
|
|
11
|
+
* @returns A Map<number, { query: JSONObject; linkNonce: number }> representing the grouped queries.
|
|
12
|
+
*/
|
|
13
|
+
const getGroupedQueries = (requestScope) => requestScope.reduce((acc, proofReq) => {
|
|
14
|
+
const groupId = proofReq.query.groupId;
|
|
15
|
+
if (!groupId) {
|
|
16
|
+
return acc;
|
|
17
|
+
}
|
|
18
|
+
const existedData = acc.get(groupId);
|
|
19
|
+
if (!existedData) {
|
|
20
|
+
const seed = (0, js_crypto_1.getRandomBytes)(12);
|
|
21
|
+
const dataView = new DataView(seed.buffer);
|
|
22
|
+
const linkNonce = dataView.getUint32(0);
|
|
23
|
+
acc.set(groupId, { query: proofReq.query, linkNonce });
|
|
24
|
+
return acc;
|
|
25
|
+
}
|
|
26
|
+
const credentialSubject = (0, utils_1.mergeObjects)(existedData.query.credentialSubject, proofReq.query.credentialSubject);
|
|
27
|
+
acc.set(groupId, {
|
|
28
|
+
...existedData,
|
|
29
|
+
query: {
|
|
30
|
+
skipClaimRevocationCheck: existedData.query.skipClaimRevocationCheck || proofReq.query.skipClaimRevocationCheck,
|
|
31
|
+
...existedData.query,
|
|
32
|
+
credentialSubject
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return acc;
|
|
36
|
+
}, new Map());
|
|
37
|
+
/**
|
|
38
|
+
* Processes zero knowledge proof requests.
|
|
39
|
+
*
|
|
40
|
+
* @param senderIdentifier - The identifier of the sender.
|
|
41
|
+
* @param requests - An array of zero knowledge proof requests.
|
|
42
|
+
* @param from - The identifier of the sender.
|
|
43
|
+
* @param proofService - The proof service.
|
|
44
|
+
* @param opts - Additional options for processing the requests.
|
|
45
|
+
* @returns A promise that resolves to an array of zero knowledge proof responses.
|
|
46
|
+
*/
|
|
47
|
+
const processZeroKnowledgeProofRequests = async (senderIdentifier, requests, from, proofService, opts) => {
|
|
48
|
+
const requestScope = requests ?? [];
|
|
49
|
+
const combinedQueries = getGroupedQueries(requestScope);
|
|
50
|
+
const groupedCredentialsCache = new Map();
|
|
51
|
+
const zkpResponses = [];
|
|
52
|
+
for (const proofReq of requestScope) {
|
|
53
|
+
if (!opts.supportedCircuits.includes(proofReq.circuitId)) {
|
|
54
|
+
throw new Error(`Circuit ${proofReq.circuitId} is not allowed`);
|
|
55
|
+
}
|
|
56
|
+
const query = proofReq.query;
|
|
57
|
+
const groupId = query.groupId;
|
|
58
|
+
const combinedQueryData = combinedQueries.get(groupId);
|
|
59
|
+
if (groupId) {
|
|
60
|
+
if (!combinedQueryData) {
|
|
61
|
+
throw new Error(`Invalid group id ${query.groupId}`);
|
|
62
|
+
}
|
|
63
|
+
const combinedQuery = combinedQueryData.query;
|
|
64
|
+
if (!groupedCredentialsCache.has(groupId)) {
|
|
65
|
+
const credWithRevStatus = await proofService.findCredentialByProofQuery(senderIdentifier, combinedQueryData.query);
|
|
66
|
+
if (!credWithRevStatus.cred) {
|
|
67
|
+
throw new Error(`Credential not found for query ${JSON.stringify(combinedQuery)}`);
|
|
68
|
+
}
|
|
69
|
+
groupedCredentialsCache.set(groupId, credWithRevStatus);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const credWithRevStatus = groupedCredentialsCache.get(groupId);
|
|
73
|
+
const zkpRes = await proofService.generateProof(proofReq, senderIdentifier, {
|
|
74
|
+
verifierDid: from,
|
|
75
|
+
challenge: opts.challenge,
|
|
76
|
+
skipRevocation: Boolean(query.skipClaimRevocationCheck),
|
|
77
|
+
credential: credWithRevStatus?.cred,
|
|
78
|
+
credentialRevocationStatus: credWithRevStatus?.revStatus,
|
|
79
|
+
linkNonce: combinedQueryData?.linkNonce ? BigInt(combinedQueryData.linkNonce) : undefined
|
|
80
|
+
});
|
|
81
|
+
zkpResponses.push(zkpRes);
|
|
82
|
+
}
|
|
83
|
+
return zkpResponses;
|
|
84
|
+
};
|
|
85
|
+
exports.processZeroKnowledgeProofRequests = processZeroKnowledgeProofRequests;
|
|
@@ -4,6 +4,7 @@ exports.ContractRequestHandler = void 0;
|
|
|
4
4
|
const models_1 = require("../../circuits/models");
|
|
5
5
|
const constants_1 = require("../constants");
|
|
6
6
|
const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
7
|
+
const common_1 = require("./common");
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
9
10
|
* Allows to process ContractInvokeRequest protocol message
|
|
@@ -25,7 +26,7 @@ class ContractRequestHandler {
|
|
|
25
26
|
this._packerMgr = _packerMgr;
|
|
26
27
|
this._proofService = _proofService;
|
|
27
28
|
this._zkpVerifier = _zkpVerifier;
|
|
28
|
-
this.
|
|
29
|
+
this._supportedCircuits = [
|
|
29
30
|
models_1.CircuitId.AtomicQueryMTPV2OnChain,
|
|
30
31
|
models_1.CircuitId.AtomicQuerySigV2OnChain,
|
|
31
32
|
models_1.CircuitId.AtomicQueryV3OnChain
|
|
@@ -62,25 +63,14 @@ class ContractRequestHandler {
|
|
|
62
63
|
if (!opts.ethSigner) {
|
|
63
64
|
throw new Error("Can't sign transaction. Provide Signer in options.");
|
|
64
65
|
}
|
|
65
|
-
const zkRequests = [];
|
|
66
66
|
const { chain_id } = ciRequest.body.transaction_data;
|
|
67
67
|
const networkFlag = Object.keys(js_iden3_core_1.ChainIds).find((key) => js_iden3_core_1.ChainIds[key] === chain_id);
|
|
68
68
|
if (!networkFlag) {
|
|
69
69
|
throw new Error(`Invalid chain id ${chain_id}`);
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
const query = proofReq.query;
|
|
76
|
-
const zkpRes = await this._proofService.generateProof(proofReq, did, {
|
|
77
|
-
skipRevocation: query.skipClaimRevocationCheck ?? false,
|
|
78
|
-
challenge: opts.challenge,
|
|
79
|
-
verifierDid: ciRequest.from ? js_iden3_core_1.DID.parse(ciRequest.from) : undefined
|
|
80
|
-
});
|
|
81
|
-
zkRequests.push(zkpRes);
|
|
82
|
-
}
|
|
83
|
-
return this._zkpVerifier.submitZKPResponse(opts.ethSigner, ciRequest.body.transaction_data, zkRequests);
|
|
71
|
+
const verifierDid = ciRequest.from ? js_iden3_core_1.DID.parse(ciRequest.from) : undefined;
|
|
72
|
+
const zkpResponses = await (0, common_1.processZeroKnowledgeProofRequests)(did, ciRequest?.body?.scope, verifierDid, this._proofService, { ...opts, supportedCircuits: this._supportedCircuits });
|
|
73
|
+
return this._zkpVerifier.submitZKPResponse(opts.ethSigner, ciRequest.body.transaction_data, zkpResponses);
|
|
84
74
|
}
|
|
85
75
|
}
|
|
86
76
|
exports.ContractRequestHandler = ContractRequestHandler;
|
|
@@ -18,3 +18,5 @@ __exportStar(require("./auth"), exports);
|
|
|
18
18
|
__exportStar(require("./fetch"), exports);
|
|
19
19
|
__exportStar(require("./contract-request"), exports);
|
|
20
20
|
__exportStar(require("./refresh"), exports);
|
|
21
|
+
__exportStar(require("./revocation-status"), exports);
|
|
22
|
+
__exportStar(require("./common"), exports);
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.RevocationStatusHandler = void 0;
|
|
27
|
+
const constants_1 = require("../constants");
|
|
28
|
+
const constants_2 = require("../constants");
|
|
29
|
+
const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
30
|
+
const uuid = __importStar(require("uuid"));
|
|
31
|
+
const utils_1 = require("../../utils");
|
|
32
|
+
const js_jwz_1 = require("@iden3/js-jwz");
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* Allows to process RevocationStatusRequest protocol message
|
|
36
|
+
*
|
|
37
|
+
|
|
38
|
+
* @class RevocationStatusHandler
|
|
39
|
+
* @implements implements IRevocationStatusHandler interface
|
|
40
|
+
*/
|
|
41
|
+
class RevocationStatusHandler {
|
|
42
|
+
/**
|
|
43
|
+
* Creates an instance of RevocationStatusHandler.
|
|
44
|
+
* @param {IPackageManager} _packerMgr - package manager to unpack message envelope
|
|
45
|
+
* @param {IIdentityWallet} _identityWallet - identity wallet
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
constructor(_packerMgr, _identityWallet) {
|
|
49
|
+
this._packerMgr = _packerMgr;
|
|
50
|
+
this._identityWallet = _identityWallet;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* @inheritdoc IRevocationStatusHandler#parseRevocationStatusRequest
|
|
54
|
+
*/
|
|
55
|
+
async parseRevocationStatusRequest(request) {
|
|
56
|
+
const { unpackedMessage: message } = await this._packerMgr.unpack(request);
|
|
57
|
+
const ciRequest = message;
|
|
58
|
+
if (message.type !== constants_1.PROTOCOL_MESSAGE_TYPE.REVOCATION_STATUS_REQUEST_MESSAGE_TYPE) {
|
|
59
|
+
throw new Error('Invalid media type');
|
|
60
|
+
}
|
|
61
|
+
return ciRequest;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* @inheritdoc IRevocationStatusHandler#handleRevocationStatusRequest
|
|
65
|
+
*/
|
|
66
|
+
async handleRevocationStatusRequest(did, request, opts) {
|
|
67
|
+
if (!opts) {
|
|
68
|
+
opts = {
|
|
69
|
+
mediaType: constants_2.MediaType.PlainMessage
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (opts.mediaType === constants_2.MediaType.SignedMessage && !opts.packerOptions) {
|
|
73
|
+
throw new Error(`jws packer options are required for ${constants_2.MediaType.SignedMessage}`);
|
|
74
|
+
}
|
|
75
|
+
const rsRequest = await this.parseRevocationStatusRequest(request);
|
|
76
|
+
if (!rsRequest.to) {
|
|
77
|
+
throw new Error(`failed request. empty 'to' field`);
|
|
78
|
+
}
|
|
79
|
+
if (!rsRequest.from) {
|
|
80
|
+
throw new Error(`failed request. empty 'from' field`);
|
|
81
|
+
}
|
|
82
|
+
if (!rsRequest.body?.revocation_nonce) {
|
|
83
|
+
throw new Error(`failed request. empty 'revocation_nonce' field`);
|
|
84
|
+
}
|
|
85
|
+
const issuerDID = js_iden3_core_1.DID.parse(rsRequest.to);
|
|
86
|
+
const mtpWithTreeState = await this._identityWallet.generateNonRevocationMtpWithNonce(issuerDID, BigInt(rsRequest.body.revocation_nonce), opts?.treeState);
|
|
87
|
+
const treeState = mtpWithTreeState.treeState;
|
|
88
|
+
const revStatus = {
|
|
89
|
+
issuer: {
|
|
90
|
+
state: treeState?.state.string(),
|
|
91
|
+
claimsTreeRoot: treeState.claimsRoot.string(),
|
|
92
|
+
revocationTreeRoot: treeState.revocationRoot.string(),
|
|
93
|
+
rootOfRoots: treeState.rootOfRoots.string()
|
|
94
|
+
},
|
|
95
|
+
mtp: mtpWithTreeState.proof
|
|
96
|
+
};
|
|
97
|
+
const packerOpts = opts.mediaType === constants_2.MediaType.SignedMessage
|
|
98
|
+
? opts.packerOptions
|
|
99
|
+
: {
|
|
100
|
+
provingMethodAlg: js_jwz_1.proving.provingMethodGroth16AuthV2Instance.methodAlg
|
|
101
|
+
};
|
|
102
|
+
const senderDID = js_iden3_core_1.DID.parse(rsRequest.to);
|
|
103
|
+
const guid = uuid.v4();
|
|
104
|
+
const response = {
|
|
105
|
+
id: guid,
|
|
106
|
+
typ: constants_2.MediaType.PlainMessage,
|
|
107
|
+
type: constants_1.PROTOCOL_MESSAGE_TYPE.REVOCATION_STATUS_RESPONSE_MESSAGE_TYPE,
|
|
108
|
+
thid: rsRequest.thid ?? guid,
|
|
109
|
+
body: revStatus,
|
|
110
|
+
from: did.string(),
|
|
111
|
+
to: rsRequest.from
|
|
112
|
+
};
|
|
113
|
+
return this._packerMgr.pack(opts.mediaType, utils_1.byteEncoder.encode(JSON.stringify(response)), {
|
|
114
|
+
senderDID,
|
|
115
|
+
...packerOpts
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.RevocationStatusHandler = RevocationStatusHandler;
|
|
@@ -253,6 +253,10 @@ class IdentityWallet {
|
|
|
253
253
|
async generateNonRevocationMtp(did, credential, treeState) {
|
|
254
254
|
const coreClaim = await this.getCoreClaimFromCredential(credential);
|
|
255
255
|
const revNonce = coreClaim.getRevocationNonce();
|
|
256
|
+
return this.generateNonRevocationMtpWithNonce(did, revNonce, treeState);
|
|
257
|
+
}
|
|
258
|
+
/** {@inheritDoc IIdentityWallet.generateNonRevocationMtpWithNonce} */
|
|
259
|
+
async generateNonRevocationMtpWithNonce(did, revNonce, treeState) {
|
|
256
260
|
const treesModel = await this.getDIDTreeModel(did);
|
|
257
261
|
const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), storage_1.MerkleTreeType.Revocations);
|
|
258
262
|
const claimsRoot = await treesModel.claimsTree.root();
|
|
@@ -125,12 +125,14 @@ const parseQueryMetadata = async (propertyQuery, ldContextJSON, credentialType,
|
|
|
125
125
|
throw new Error(`field does not exist in the schema ${e.message}`);
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
if (propertyQuery.operatorValue) {
|
|
128
|
+
if (propertyQuery.operatorValue !== undefined) {
|
|
129
129
|
if (!(0, circuits_1.isValidOperation)(query.datatype, propertyQuery.operator)) {
|
|
130
130
|
throw new Error(`operator ${propertyQuery.operator} is not supported for datatype ${query.datatype}`);
|
|
131
131
|
}
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
query.values =
|
|
133
|
+
propertyQuery.operator === circuits_1.Operators.EXISTS
|
|
134
|
+
? transformExistsValue(propertyQuery.operatorValue)
|
|
135
|
+
: await (0, exports.transformQueryValueToBigInts)(propertyQuery.operatorValue, query.datatype);
|
|
134
136
|
}
|
|
135
137
|
return query;
|
|
136
138
|
};
|
|
@@ -153,3 +155,9 @@ const transformQueryValueToBigInts = async (value, ldType) => {
|
|
|
153
155
|
return values;
|
|
154
156
|
};
|
|
155
157
|
exports.transformQueryValueToBigInts = transformQueryValueToBigInts;
|
|
158
|
+
const transformExistsValue = (value) => {
|
|
159
|
+
if (typeof value == 'boolean') {
|
|
160
|
+
return [BigInt(value)];
|
|
161
|
+
}
|
|
162
|
+
throw new Error('exists operator value must be true or false');
|
|
163
|
+
};
|
|
@@ -191,10 +191,7 @@ class ProofService {
|
|
|
191
191
|
query.valueProof = new circuits_1.ValueProof();
|
|
192
192
|
query.valueProof.mtp = proof;
|
|
193
193
|
query.valueProof.path = queryMetadata.claimPathKey;
|
|
194
|
-
const mtEntry = await mtValue?.mtEntry();
|
|
195
|
-
if (!mtEntry) {
|
|
196
|
-
throw new Error(`can't merklize credential: no merkle tree entry found`);
|
|
197
|
-
}
|
|
194
|
+
const mtEntry = (await mtValue?.mtEntry()) ?? 0n;
|
|
198
195
|
query.valueProof.value = mtEntry;
|
|
199
196
|
if (!queryMetadata.fieldName) {
|
|
200
197
|
query.values = [mtEntry];
|
|
@@ -166,7 +166,7 @@ class FilterQuery {
|
|
|
166
166
|
}
|
|
167
167
|
const credentialPathValue = (0, exports.resolvePath)(credential, this.path);
|
|
168
168
|
if ((credentialPathValue === null || credentialPathValue === undefined) &&
|
|
169
|
-
this.operatorFunc !==
|
|
169
|
+
this.operatorFunc !== exports.comparatorOptions.$exists) {
|
|
170
170
|
return false;
|
|
171
171
|
}
|
|
172
172
|
if (this.isReverseParams) {
|
|
@@ -3,8 +3,9 @@ import { PROTOCOL_MESSAGE_TYPE } from '../constants';
|
|
|
3
3
|
import { DID } from '@iden3/js-iden3-core';
|
|
4
4
|
import { proving } from '@iden3/js-jwz';
|
|
5
5
|
import * as uuid from 'uuid';
|
|
6
|
-
import { byteDecoder, byteEncoder
|
|
7
|
-
import {
|
|
6
|
+
import { byteDecoder, byteEncoder } from '../../utils';
|
|
7
|
+
import { processZeroKnowledgeProofRequests } from './common';
|
|
8
|
+
import { CircuitId } from '../../circuits';
|
|
8
9
|
/**
|
|
9
10
|
* createAuthorizationRequest is a function to create protocol authorization request
|
|
10
11
|
* @param {string} reason - reason to request proof
|
|
@@ -59,6 +60,12 @@ export class AuthHandler {
|
|
|
59
60
|
constructor(_packerMgr, _proofService) {
|
|
60
61
|
this._packerMgr = _packerMgr;
|
|
61
62
|
this._proofService = _proofService;
|
|
63
|
+
this._supportedCircuits = [
|
|
64
|
+
CircuitId.AtomicQueryV3,
|
|
65
|
+
CircuitId.AtomicQuerySigV2,
|
|
66
|
+
CircuitId.AtomicQueryMTPV2,
|
|
67
|
+
CircuitId.LinkedMultiQuery10
|
|
68
|
+
];
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* @inheritdoc IAuthHandler#parseAuthorizationRequest
|
|
@@ -93,6 +100,11 @@ export class AuthHandler {
|
|
|
93
100
|
did = DID.parse(authRequest.to);
|
|
94
101
|
}
|
|
95
102
|
const guid = uuid.v4();
|
|
103
|
+
if (!authRequest.from) {
|
|
104
|
+
throw new Error('auth request should contain from field');
|
|
105
|
+
}
|
|
106
|
+
const from = DID.parse(authRequest.from);
|
|
107
|
+
const responseScope = await processZeroKnowledgeProofRequests(did, authRequest?.body.scope, from, this._proofService, { ...opts, supportedCircuits: this._supportedCircuits });
|
|
96
108
|
const authResponse = {
|
|
97
109
|
id: guid,
|
|
98
110
|
typ: opts.mediaType,
|
|
@@ -100,64 +112,11 @@ export class AuthHandler {
|
|
|
100
112
|
thid: authRequest.thid ?? guid,
|
|
101
113
|
body: {
|
|
102
114
|
message: authRequest?.body?.message,
|
|
103
|
-
scope:
|
|
115
|
+
scope: responseScope
|
|
104
116
|
},
|
|
105
117
|
from: did.string(),
|
|
106
118
|
to: authRequest.from
|
|
107
119
|
};
|
|
108
|
-
const requestScope = authRequest.body.scope;
|
|
109
|
-
const combinedQueries = requestScope.reduce((acc, proofReq) => {
|
|
110
|
-
const groupId = proofReq.query.groupId;
|
|
111
|
-
if (!groupId) {
|
|
112
|
-
return acc;
|
|
113
|
-
}
|
|
114
|
-
const existedData = acc.get(groupId);
|
|
115
|
-
if (!existedData) {
|
|
116
|
-
const seed = getRandomBytes(12);
|
|
117
|
-
const dataView = new DataView(seed.buffer);
|
|
118
|
-
const linkNonce = dataView.getUint32(0);
|
|
119
|
-
acc.set(groupId, { query: proofReq.query, linkNonce });
|
|
120
|
-
return acc;
|
|
121
|
-
}
|
|
122
|
-
const credentialSubject = mergeObjects(existedData.query.credentialSubject, proofReq.query.credentialSubject);
|
|
123
|
-
acc.set(groupId, {
|
|
124
|
-
...existedData,
|
|
125
|
-
query: {
|
|
126
|
-
skipClaimRevocationCheck: existedData.query.skipClaimRevocationCheck || proofReq.query.skipClaimRevocationCheck,
|
|
127
|
-
...existedData.query,
|
|
128
|
-
credentialSubject
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
return acc;
|
|
132
|
-
}, new Map());
|
|
133
|
-
const groupedCredentialsCache = new Map();
|
|
134
|
-
for (const proofReq of requestScope) {
|
|
135
|
-
const query = proofReq.query;
|
|
136
|
-
const groupId = query.groupId;
|
|
137
|
-
const combinedQueryData = combinedQueries.get(groupId);
|
|
138
|
-
if (groupId) {
|
|
139
|
-
if (!combinedQueryData) {
|
|
140
|
-
throw new Error(`Invalid group id ${query.groupId}`);
|
|
141
|
-
}
|
|
142
|
-
const combinedQuery = combinedQueryData.query;
|
|
143
|
-
if (!groupedCredentialsCache.has(groupId)) {
|
|
144
|
-
const credWithRevStatus = await this._proofService.findCredentialByProofQuery(did, combinedQueryData.query);
|
|
145
|
-
if (!credWithRevStatus.cred) {
|
|
146
|
-
throw new Error(`Credential not found for query ${JSON.stringify(combinedQuery)}`);
|
|
147
|
-
}
|
|
148
|
-
groupedCredentialsCache.set(groupId, credWithRevStatus);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
const credWithRevStatus = groupedCredentialsCache.get(groupId);
|
|
152
|
-
const zkpRes = await this._proofService.generateProof(proofReq, did, {
|
|
153
|
-
verifierDid: DID.parse(authRequest.from),
|
|
154
|
-
skipRevocation: Boolean(query.skipClaimRevocationCheck),
|
|
155
|
-
credential: credWithRevStatus?.cred,
|
|
156
|
-
credentialRevocationStatus: credWithRevStatus?.revStatus,
|
|
157
|
-
linkNonce: combinedQueryData?.linkNonce ? BigInt(combinedQueryData.linkNonce) : undefined
|
|
158
|
-
});
|
|
159
|
-
authResponse.body.scope.push(zkpRes);
|
|
160
|
-
}
|
|
161
120
|
const msgBytes = byteEncoder.encode(JSON.stringify(authResponse));
|
|
162
121
|
const packerOpts = opts.mediaType === MediaType.SignedMessage
|
|
163
122
|
? opts.packerOptions
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { getRandomBytes } from '@iden3/js-crypto';
|
|
2
|
+
import { mergeObjects } from '../../utils';
|
|
3
|
+
/**
|
|
4
|
+
* Groups the ZeroKnowledgeProofRequest objects based on their groupId.
|
|
5
|
+
* Returns a Map where the key is the groupId and the value is an object containing the query and linkNonce.
|
|
6
|
+
*
|
|
7
|
+
* @param requestScope - An array of ZeroKnowledgeProofRequest objects.
|
|
8
|
+
* @returns A Map<number, { query: JSONObject; linkNonce: number }> representing the grouped queries.
|
|
9
|
+
*/
|
|
10
|
+
const getGroupedQueries = (requestScope) => requestScope.reduce((acc, proofReq) => {
|
|
11
|
+
const groupId = proofReq.query.groupId;
|
|
12
|
+
if (!groupId) {
|
|
13
|
+
return acc;
|
|
14
|
+
}
|
|
15
|
+
const existedData = acc.get(groupId);
|
|
16
|
+
if (!existedData) {
|
|
17
|
+
const seed = getRandomBytes(12);
|
|
18
|
+
const dataView = new DataView(seed.buffer);
|
|
19
|
+
const linkNonce = dataView.getUint32(0);
|
|
20
|
+
acc.set(groupId, { query: proofReq.query, linkNonce });
|
|
21
|
+
return acc;
|
|
22
|
+
}
|
|
23
|
+
const credentialSubject = mergeObjects(existedData.query.credentialSubject, proofReq.query.credentialSubject);
|
|
24
|
+
acc.set(groupId, {
|
|
25
|
+
...existedData,
|
|
26
|
+
query: {
|
|
27
|
+
skipClaimRevocationCheck: existedData.query.skipClaimRevocationCheck || proofReq.query.skipClaimRevocationCheck,
|
|
28
|
+
...existedData.query,
|
|
29
|
+
credentialSubject
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return acc;
|
|
33
|
+
}, new Map());
|
|
34
|
+
/**
|
|
35
|
+
* Processes zero knowledge proof requests.
|
|
36
|
+
*
|
|
37
|
+
* @param senderIdentifier - The identifier of the sender.
|
|
38
|
+
* @param requests - An array of zero knowledge proof requests.
|
|
39
|
+
* @param from - The identifier of the sender.
|
|
40
|
+
* @param proofService - The proof service.
|
|
41
|
+
* @param opts - Additional options for processing the requests.
|
|
42
|
+
* @returns A promise that resolves to an array of zero knowledge proof responses.
|
|
43
|
+
*/
|
|
44
|
+
export const processZeroKnowledgeProofRequests = async (senderIdentifier, requests, from, proofService, opts) => {
|
|
45
|
+
const requestScope = requests ?? [];
|
|
46
|
+
const combinedQueries = getGroupedQueries(requestScope);
|
|
47
|
+
const groupedCredentialsCache = new Map();
|
|
48
|
+
const zkpResponses = [];
|
|
49
|
+
for (const proofReq of requestScope) {
|
|
50
|
+
if (!opts.supportedCircuits.includes(proofReq.circuitId)) {
|
|
51
|
+
throw new Error(`Circuit ${proofReq.circuitId} is not allowed`);
|
|
52
|
+
}
|
|
53
|
+
const query = proofReq.query;
|
|
54
|
+
const groupId = query.groupId;
|
|
55
|
+
const combinedQueryData = combinedQueries.get(groupId);
|
|
56
|
+
if (groupId) {
|
|
57
|
+
if (!combinedQueryData) {
|
|
58
|
+
throw new Error(`Invalid group id ${query.groupId}`);
|
|
59
|
+
}
|
|
60
|
+
const combinedQuery = combinedQueryData.query;
|
|
61
|
+
if (!groupedCredentialsCache.has(groupId)) {
|
|
62
|
+
const credWithRevStatus = await proofService.findCredentialByProofQuery(senderIdentifier, combinedQueryData.query);
|
|
63
|
+
if (!credWithRevStatus.cred) {
|
|
64
|
+
throw new Error(`Credential not found for query ${JSON.stringify(combinedQuery)}`);
|
|
65
|
+
}
|
|
66
|
+
groupedCredentialsCache.set(groupId, credWithRevStatus);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const credWithRevStatus = groupedCredentialsCache.get(groupId);
|
|
70
|
+
const zkpRes = await proofService.generateProof(proofReq, senderIdentifier, {
|
|
71
|
+
verifierDid: from,
|
|
72
|
+
challenge: opts.challenge,
|
|
73
|
+
skipRevocation: Boolean(query.skipClaimRevocationCheck),
|
|
74
|
+
credential: credWithRevStatus?.cred,
|
|
75
|
+
credentialRevocationStatus: credWithRevStatus?.revStatus,
|
|
76
|
+
linkNonce: combinedQueryData?.linkNonce ? BigInt(combinedQueryData.linkNonce) : undefined
|
|
77
|
+
});
|
|
78
|
+
zkpResponses.push(zkpRes);
|
|
79
|
+
}
|
|
80
|
+
return zkpResponses;
|
|
81
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CircuitId } from '../../circuits/models';
|
|
2
2
|
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
|
|
3
3
|
import { DID, ChainIds } from '@iden3/js-iden3-core';
|
|
4
|
+
import { processZeroKnowledgeProofRequests } from './common';
|
|
4
5
|
/**
|
|
5
6
|
*
|
|
6
7
|
* Allows to process ContractInvokeRequest protocol message
|
|
@@ -22,7 +23,7 @@ export class ContractRequestHandler {
|
|
|
22
23
|
this._packerMgr = _packerMgr;
|
|
23
24
|
this._proofService = _proofService;
|
|
24
25
|
this._zkpVerifier = _zkpVerifier;
|
|
25
|
-
this.
|
|
26
|
+
this._supportedCircuits = [
|
|
26
27
|
CircuitId.AtomicQueryMTPV2OnChain,
|
|
27
28
|
CircuitId.AtomicQuerySigV2OnChain,
|
|
28
29
|
CircuitId.AtomicQueryV3OnChain
|
|
@@ -59,24 +60,13 @@ export class ContractRequestHandler {
|
|
|
59
60
|
if (!opts.ethSigner) {
|
|
60
61
|
throw new Error("Can't sign transaction. Provide Signer in options.");
|
|
61
62
|
}
|
|
62
|
-
const zkRequests = [];
|
|
63
63
|
const { chain_id } = ciRequest.body.transaction_data;
|
|
64
64
|
const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
|
|
65
65
|
if (!networkFlag) {
|
|
66
66
|
throw new Error(`Invalid chain id ${chain_id}`);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
const query = proofReq.query;
|
|
73
|
-
const zkpRes = await this._proofService.generateProof(proofReq, did, {
|
|
74
|
-
skipRevocation: query.skipClaimRevocationCheck ?? false,
|
|
75
|
-
challenge: opts.challenge,
|
|
76
|
-
verifierDid: ciRequest.from ? DID.parse(ciRequest.from) : undefined
|
|
77
|
-
});
|
|
78
|
-
zkRequests.push(zkpRes);
|
|
79
|
-
}
|
|
80
|
-
return this._zkpVerifier.submitZKPResponse(opts.ethSigner, ciRequest.body.transaction_data, zkRequests);
|
|
68
|
+
const verifierDid = ciRequest.from ? DID.parse(ciRequest.from) : undefined;
|
|
69
|
+
const zkpResponses = await processZeroKnowledgeProofRequests(did, ciRequest?.body?.scope, verifierDid, this._proofService, { ...opts, supportedCircuits: this._supportedCircuits });
|
|
70
|
+
return this._zkpVerifier.submitZKPResponse(opts.ethSigner, ciRequest.body.transaction_data, zkpResponses);
|
|
81
71
|
}
|
|
82
72
|
}
|