@0xpolygonid/js-sdk 1.9.0 → 1.9.1
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 +188 -70
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +189 -69
- 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/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/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();
|
|
@@ -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
|
}
|