@0xpolygonid/js-sdk 1.17.8 → 1.18.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.
Files changed (36) hide show
  1. package/dist/browser/esm/index.js +976 -64
  2. package/dist/browser/esm/index.js.map +1 -1
  3. package/dist/browser/umd/index.js +976 -63
  4. package/dist/browser/umd/index.js.map +1 -1
  5. package/dist/node/cjs/circuits/atomic-query-mtp-v2-on-chain.js +10 -0
  6. package/dist/node/cjs/circuits/atomic-query-sig-v2-on-chain.js +10 -0
  7. package/dist/node/cjs/circuits/atomic-query-v3-on-chain.js +10 -0
  8. package/dist/node/cjs/iden3comm/constants.js +2 -0
  9. package/dist/node/cjs/iden3comm/handlers/contract-request.js +73 -10
  10. package/dist/node/cjs/storage/blockchain/abi/ZkpVerifier.json +530 -9
  11. package/dist/node/cjs/storage/blockchain/onchain-zkp-verifier.js +293 -42
  12. package/dist/node/cjs/utils/did-helper.js +37 -1
  13. package/dist/node/esm/circuits/atomic-query-mtp-v2-on-chain.js +10 -0
  14. package/dist/node/esm/circuits/atomic-query-sig-v2-on-chain.js +10 -0
  15. package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +10 -0
  16. package/dist/node/esm/iden3comm/constants.js +2 -0
  17. package/dist/node/esm/iden3comm/handlers/contract-request.js +73 -10
  18. package/dist/node/esm/storage/blockchain/abi/ZkpVerifier.json +530 -9
  19. package/dist/node/esm/storage/blockchain/onchain-zkp-verifier.js +293 -42
  20. package/dist/node/esm/utils/did-helper.js +35 -0
  21. package/dist/types/circuits/atomic-query-mtp-v2-on-chain.d.ts +4 -2
  22. package/dist/types/circuits/atomic-query-sig-v2-on-chain.d.ts +4 -2
  23. package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +4 -2
  24. package/dist/types/circuits/common.d.ts +31 -0
  25. package/dist/types/iden3comm/constants.d.ts +1 -0
  26. package/dist/types/iden3comm/handlers/contract-request.d.ts +14 -3
  27. package/dist/types/iden3comm/types/protocol/auth.d.ts +11 -1
  28. package/dist/types/iden3comm/types/protocol/contract-request.d.ts +16 -1
  29. package/dist/types/proof/verifiers/pub-signals-verifier.d.ts +2 -2
  30. package/dist/types/proof/verifiers/query.d.ts +4 -3
  31. package/dist/types/storage/blockchain/onchain-zkp-verifier.d.ts +44 -12
  32. package/dist/types/storage/entities/state.d.ts +44 -0
  33. package/dist/types/storage/interfaces/onchain-zkp-verifier.d.ts +22 -1
  34. package/dist/types/utils/did-helper.d.ts +12 -1
  35. package/dist/types/verifiable/presentation.d.ts +2 -2
  36. package/package.json +1 -1
@@ -3,10 +3,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.OnChainZKPVerifier = void 0;
6
+ exports.OnChainZKPVerifier = exports.FunctionSignatures = void 0;
7
7
  const ethers_1 = require("ethers");
8
8
  const ZkpVerifier_json_1 = __importDefault(require("./abi/ZkpVerifier.json"));
9
9
  const blockchain_1 = require("../../blockchain");
10
+ const js_iden3_core_1 = require("@iden3/js-iden3-core");
11
+ const circuits_1 = require("../../circuits");
12
+ const utils_1 = require("../../utils");
13
+ const js_crypto_1 = require("@iden3/js-crypto");
14
+ const maxGasLimit = 10000000n;
15
+ /**
16
+ * Supported function signature for SubmitZKPResponse
17
+ */
18
+ var FunctionSignatures;
19
+ (function (FunctionSignatures) {
20
+ /**
21
+ * solidity identifier for function signature:
22
+ * function submitZKPResponse(uint64 requestId, uint256[] calldata inputs,
23
+ * uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c) public
24
+ */
25
+ FunctionSignatures["SubmitZKPResponseV1"] = "b68967e2";
26
+ //function submitZKPResponseV2(tuple[](uint64 requestId,bytes zkProof,bytes data),bytes crossChainProof)
27
+ FunctionSignatures["SubmitZKPResponseV2"] = "ade09fcd";
28
+ })(FunctionSignatures = exports.FunctionSignatures || (exports.FunctionSignatures = {}));
10
29
  /**
11
30
  * OnChainZKPVerifier is a class that allows to interact with the OnChainZKPVerifier contract
12
31
  * and submitZKPResponse.
@@ -21,70 +40,302 @@ class OnChainZKPVerifier {
21
40
  * @beta
22
41
  * @param {EthConnectionConfig[]} - array of ETH configs
23
42
  */
24
- constructor(_configs) {
43
+ constructor(_configs, _opts) {
25
44
  this._configs = _configs;
45
+ this._opts = _opts;
46
+ /**
47
+ * supported circuits
48
+ */
49
+ this._supportedCircuits = [
50
+ circuits_1.CircuitId.AtomicQueryMTPV2OnChain,
51
+ circuits_1.CircuitId.AtomicQuerySigV2OnChain,
52
+ circuits_1.CircuitId.AtomicQueryV3OnChain
53
+ ];
26
54
  /**
27
- * solidity identifier for function signature:
28
- * function submitZKPResponse(uint64 requestId, uint256[] calldata inputs,
29
- * uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c) public
55
+ * abi coder to encode/decode structures to solidity bytes
30
56
  */
31
- this._supportedMethodId = 'b68967e2';
57
+ this._abiCoder = new ethers_1.ethers.AbiCoder();
32
58
  }
33
59
  /**
34
- * Submit ZKP Responses to OnChainZKPVerifier contract.
35
- * @beta
36
- * @param {Signer} ethSigner - tx signer
37
- * @param {txData} ContractInvokeTransactionData - transaction data
38
- * @param {ZeroKnowledgeProofResponse[]} zkProofResponses - zkProofResponses
39
- * @returns {Promise<Map<string, ZeroKnowledgeProofResponse>>} - map of transaction hash - ZeroKnowledgeProofResponse
60
+ * {@inheritDoc IOnChainZKPVerifier.prepareTxArgsSubmitV1}
61
+ */
62
+ async prepareTxArgsSubmitV1(txData, zkProofResponse) {
63
+ if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV1) {
64
+ throw new Error(`prepareTxArgsSubmitV1 function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV1}' is supported.`);
65
+ }
66
+ const requestID = zkProofResponse.id;
67
+ const inputs = zkProofResponse.pub_signals;
68
+ const payload = [
69
+ requestID,
70
+ inputs,
71
+ zkProofResponse.proof.pi_a.slice(0, 2),
72
+ [
73
+ [zkProofResponse.proof.pi_b[0][1], zkProofResponse.proof.pi_b[0][0]],
74
+ [zkProofResponse.proof.pi_b[1][1], zkProofResponse.proof.pi_b[1][0]]
75
+ ],
76
+ zkProofResponse.proof.pi_c.slice(0, 2)
77
+ ];
78
+ return payload;
79
+ }
80
+ /**
81
+ * {@inheritDoc IOnChainZKPVerifier.submitZKPResponse}
40
82
  */
41
83
  async submitZKPResponse(ethSigner, txData, zkProofResponses) {
42
84
  const chainConfig = this._configs.find((i) => i.chainId == txData.chain_id);
43
85
  if (!chainConfig) {
44
86
  throw new Error(`config for chain id ${txData.chain_id} was not found`);
45
87
  }
46
- if (txData.method_id.replace('0x', '') !== this._supportedMethodId) {
47
- throw new Error(`submit doesn't implement requested method id. Only '0x${this._supportedMethodId}' is supported.`);
88
+ if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV1) {
89
+ throw new Error(`submitZKPResponse function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV1}' is supported.`);
48
90
  }
49
91
  const provider = new ethers_1.JsonRpcProvider(chainConfig.url, chainConfig.chainId);
50
- const verifierContract = new ethers_1.Contract(txData.contract_address, ZkpVerifier_json_1.default, provider);
51
92
  ethSigner = ethSigner.connect(provider);
52
- const contract = verifierContract.connect(ethSigner);
53
93
  const response = new Map();
54
- for (const zkProof of zkProofResponses) {
55
- const requestID = zkProof.id;
56
- const inputs = zkProof.pub_signals;
57
- const payload = [
58
- requestID,
59
- inputs,
60
- zkProof.proof.pi_a.slice(0, 2),
61
- [
62
- [zkProof.proof.pi_b[0][1], zkProof.proof.pi_b[0][0]],
63
- [zkProof.proof.pi_b[1][1], zkProof.proof.pi_b[1][0]]
64
- ],
65
- zkProof.proof.pi_c.slice(0, 2)
66
- ];
67
- const feeData = await provider.getFeeData();
68
- const maxFeePerGas = chainConfig.maxFeePerGas
69
- ? BigInt(chainConfig.maxFeePerGas)
70
- : feeData.maxFeePerGas;
71
- const maxPriorityFeePerGas = chainConfig.maxPriorityFeePerGas
72
- ? BigInt(chainConfig.maxPriorityFeePerGas)
73
- : feeData.maxPriorityFeePerGas;
74
- const gasLimit = await contract.submitZKPResponse.estimateGas(...payload);
75
- const txData = await contract.submitZKPResponse.populateTransaction(...payload);
94
+ const feeData = await provider.getFeeData();
95
+ const maxFeePerGas = chainConfig.maxFeePerGas
96
+ ? BigInt(chainConfig.maxFeePerGas)
97
+ : feeData.maxFeePerGas;
98
+ const maxPriorityFeePerGas = chainConfig.maxPriorityFeePerGas
99
+ ? BigInt(chainConfig.maxPriorityFeePerGas)
100
+ : feeData.maxPriorityFeePerGas;
101
+ const verifierContract = new ethers_1.Contract(txData.contract_address, ZkpVerifier_json_1.default);
102
+ for (const zkProofResponse of zkProofResponses) {
103
+ const txArgs = await this.prepareTxArgsSubmitV1(txData, zkProofResponse);
104
+ const payload = await verifierContract.submitZKPResponse.populateTransaction(...txArgs);
76
105
  const request = {
77
- to: txData.to,
78
- data: txData.data,
79
- gasLimit,
106
+ to: txData.contract_address,
107
+ data: payload.data,
80
108
  maxFeePerGas,
81
109
  maxPriorityFeePerGas
82
110
  };
111
+ let gasLimit;
112
+ try {
113
+ gasLimit = await ethSigner.estimateGas(request);
114
+ }
115
+ catch (e) {
116
+ gasLimit = maxGasLimit;
117
+ }
118
+ request.gasLimit = gasLimit;
83
119
  const transactionService = new blockchain_1.TransactionService(provider);
84
120
  const { txnHash } = await transactionService.sendTransactionRequest(ethSigner, request);
85
- response.set(txnHash, zkProof);
121
+ response.set(txnHash, zkProofResponse);
86
122
  }
87
123
  return response;
88
124
  }
125
+ /**
126
+ * {@inheritDoc IOnChainZKPVerifier.submitZKPResponseV2}
127
+ */
128
+ async submitZKPResponseV2(ethSigner, txData, zkProofResponses) {
129
+ const chainConfig = this._configs.find((i) => i.chainId == txData.chain_id);
130
+ if (!chainConfig) {
131
+ throw new Error(`config for chain id ${txData.chain_id} was not found`);
132
+ }
133
+ if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV2) {
134
+ throw new Error(`submitZKPResponseV2 function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV2}' is supported.`);
135
+ }
136
+ if (!this._opts?.didResolverUrl) {
137
+ throw new Error(`did resolver url required for crosschain verification`);
138
+ }
139
+ const provider = new ethers_1.JsonRpcProvider(chainConfig.url, chainConfig.chainId);
140
+ ethSigner = ethSigner.connect(provider);
141
+ const txDataArgs = await this.prepareTxArgsSubmitV2(txData, zkProofResponses);
142
+ const feeData = await provider.getFeeData();
143
+ const maxFeePerGas = chainConfig.maxFeePerGas
144
+ ? BigInt(chainConfig.maxFeePerGas)
145
+ : feeData.maxFeePerGas;
146
+ const maxPriorityFeePerGas = chainConfig.maxPriorityFeePerGas
147
+ ? BigInt(chainConfig.maxPriorityFeePerGas)
148
+ : feeData.maxPriorityFeePerGas;
149
+ const verifierContract = new ethers_1.Contract(txData.contract_address, ZkpVerifier_json_1.default);
150
+ const txRequestData = await verifierContract.submitZKPResponseV2.populateTransaction(...txDataArgs);
151
+ const request = {
152
+ to: txData.contract_address,
153
+ data: txRequestData.data,
154
+ maxFeePerGas,
155
+ maxPriorityFeePerGas
156
+ };
157
+ let gasLimit;
158
+ try {
159
+ gasLimit = await ethSigner.estimateGas(request);
160
+ }
161
+ catch (e) {
162
+ gasLimit = maxGasLimit;
163
+ }
164
+ request.gasLimit = gasLimit;
165
+ const transactionService = new blockchain_1.TransactionService(provider);
166
+ const { txnHash } = await transactionService.sendTransactionRequest(ethSigner, request);
167
+ return new Map().set(txnHash, zkProofResponses);
168
+ }
169
+ async prepareTxArgsSubmitV2(txData, zkProofResponses) {
170
+ if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV2) {
171
+ throw new Error(`submit cross chain doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV2}' is supported.`);
172
+ }
173
+ if (!this._opts?.didResolverUrl) {
174
+ throw new Error(`did resolver url required for crosschain verification`);
175
+ }
176
+ const gistUpdateArr = [];
177
+ const stateUpdateArr = [];
178
+ const payload = [];
179
+ // Resolved gists and states to avoid duplicate requests
180
+ const gistUpdateResolutionsPending = [];
181
+ const stateUpdateResolutionsPending = [];
182
+ for (const zkProof of zkProofResponses) {
183
+ const requestID = zkProof.id;
184
+ const inputs = zkProof.pub_signals;
185
+ if (!this._supportedCircuits.includes(zkProof.circuitId)) {
186
+ throw new Error(`Circuit ${zkProof.circuitId} not supported by OnChainZKPVerifier`);
187
+ }
188
+ const zkProofEncoded = this.packZkpProof(inputs, zkProof.proof.pi_a.slice(0, 2), [
189
+ [zkProof.proof.pi_b[0][1], zkProof.proof.pi_b[0][0]],
190
+ [zkProof.proof.pi_b[1][1], zkProof.proof.pi_b[1][0]]
191
+ ], zkProof.proof.pi_c.slice(0, 2));
192
+ const stateInfo = this.getOnChainGistRootStatePubSignals(zkProof.circuitId, zkProof.pub_signals);
193
+ const gistUpdateResolutions = [];
194
+ for (const gist of stateInfo.gists) {
195
+ const gistResolutionPending = gistUpdateResolutionsPending.find((g) => g == JSON.stringify(gist));
196
+ if (gistResolutionPending) {
197
+ continue;
198
+ }
199
+ gistUpdateResolutionsPending.push(JSON.stringify(gist));
200
+ gistUpdateResolutions.push(this.resolveDidDocumentEip712MessageAndSignature(js_iden3_core_1.DID.parseFromId(gist.id), this._opts.didResolverUrl, { gist: gist.root }));
201
+ }
202
+ const stateUpdateResolutions = [];
203
+ for (const state of stateInfo.states) {
204
+ const stateResolutionPending = stateUpdateResolutionsPending.find((s) => s == JSON.stringify(state));
205
+ if (stateResolutionPending) {
206
+ continue;
207
+ }
208
+ stateUpdateResolutionsPending.push(JSON.stringify(state));
209
+ stateUpdateResolutions.push(this.resolveDidDocumentEip712MessageAndSignature(js_iden3_core_1.DID.parseFromId(state.id), this._opts.didResolverUrl, {
210
+ state: state.state
211
+ }));
212
+ }
213
+ if (gistUpdateResolutions.length > 0) {
214
+ gistUpdateArr.push(...(await Promise.all(gistUpdateResolutions)));
215
+ }
216
+ if (stateUpdateResolutions.length > 0) {
217
+ stateUpdateArr.push(...(await Promise.all(stateUpdateResolutions)));
218
+ }
219
+ const metadataArr = [];
220
+ if (zkProof.vp) {
221
+ for (const key in zkProof.vp.verifiableCredential.credentialSubject) {
222
+ if (key === '@type') {
223
+ continue;
224
+ }
225
+ const metadataValue = js_crypto_1.poseidon.hashBytes(utils_1.byteEncoder.encode(JSON.stringify(zkProof.vp.verifiableCredential.credentialSubject[key])));
226
+ const bytesValue = utils_1.byteEncoder.encode(metadataValue.toString());
227
+ metadataArr.push({
228
+ key,
229
+ value: bytesValue
230
+ });
231
+ }
232
+ }
233
+ const metadata = this.packMetadatas(metadataArr);
234
+ payload.push({
235
+ requestId: requestID,
236
+ zkProof: zkProofEncoded,
237
+ data: metadata
238
+ });
239
+ }
240
+ const crossChainProofs = this.packCrossChainProofs(gistUpdateArr, stateUpdateArr);
241
+ return [payload, crossChainProofs];
242
+ }
243
+ packZkpProof(inputs, a, b, c) {
244
+ return this._abiCoder.encode(['uint256[] inputs', 'uint256[2]', 'uint256[2][2]', 'uint256[2]'], [inputs, a, b, c]);
245
+ }
246
+ packCrossChainProofs(gistUpdateArr, stateUpdateArr) {
247
+ const proofs = [];
248
+ for (const globalStateUpdate of gistUpdateArr) {
249
+ proofs.push({
250
+ proofType: 'globalStateProof',
251
+ proof: this.packGlobalStateMsg(globalStateUpdate)
252
+ });
253
+ }
254
+ for (const stateUpdate of stateUpdateArr) {
255
+ proofs.push({
256
+ proofType: 'stateProof',
257
+ proof: this.packIdentityStateMsg(stateUpdate)
258
+ });
259
+ }
260
+ return this._abiCoder.encode(['tuple(' + 'string proofType,' + 'bytes proof' + ')[]'], [proofs]);
261
+ }
262
+ packGlobalStateMsg(msg) {
263
+ return this._abiCoder.encode([
264
+ 'tuple(' +
265
+ 'tuple(' +
266
+ 'uint256 timestamp,' +
267
+ 'bytes2 idType,' +
268
+ 'uint256 root,' +
269
+ 'uint256 replacedAtTimestamp' +
270
+ ') globalStateMsg,' +
271
+ 'bytes signature,' +
272
+ ')'
273
+ ], [msg]);
274
+ }
275
+ packIdentityStateMsg(msg) {
276
+ return this._abiCoder.encode([
277
+ 'tuple(' +
278
+ 'tuple(' +
279
+ 'uint256 timestamp,' +
280
+ 'uint256 id,' +
281
+ 'uint256 state,' +
282
+ 'uint256 replacedAtTimestamp' +
283
+ ') idStateMsg,' +
284
+ 'bytes signature,' +
285
+ ')'
286
+ ], [msg]);
287
+ }
288
+ packMetadatas(metas) {
289
+ return this._abiCoder.encode(['tuple(' + 'string key,' + 'bytes value' + ')[]'], [metas]);
290
+ }
291
+ getOnChainGistRootStatePubSignals(onChainCircuitId, inputs) {
292
+ let atomicQueryPubSignals;
293
+ switch (onChainCircuitId) {
294
+ case circuits_1.CircuitId.AtomicQueryMTPV2OnChain:
295
+ atomicQueryPubSignals = new circuits_1.AtomicQueryMTPV2OnChainPubSignals();
296
+ break;
297
+ case circuits_1.CircuitId.AtomicQuerySigV2OnChain:
298
+ atomicQueryPubSignals = new circuits_1.AtomicQuerySigV2OnChainPubSignals();
299
+ break;
300
+ case circuits_1.CircuitId.AtomicQueryV3OnChain:
301
+ atomicQueryPubSignals = new circuits_1.AtomicQueryV3OnChainPubSignals();
302
+ break;
303
+ }
304
+ const encodedInputs = utils_1.byteEncoder.encode(JSON.stringify(inputs));
305
+ atomicQueryPubSignals.pubSignalsUnmarshal(encodedInputs);
306
+ return atomicQueryPubSignals.getStatesInfo();
307
+ }
308
+ async resolveDidDocumentEip712MessageAndSignature(did, resolverUrl, opts) {
309
+ const didDoc = await (0, utils_1.resolveDidDocument)(did, resolverUrl, {
310
+ ...opts,
311
+ signature: utils_1.DIDDocumentSignature.EthereumEip712Signature2021
312
+ });
313
+ if (!didDoc.didResolutionMetadata.proof?.length) {
314
+ throw new Error('No proof found in resolved DID document');
315
+ }
316
+ const message = didDoc.didResolutionMetadata.proof[0].eip712.message;
317
+ const signature = didDoc.didResolutionMetadata.proof[0].proofValue;
318
+ const isGistRequest = opts?.gist && !opts.state;
319
+ if (isGistRequest) {
320
+ return {
321
+ globalStateMsg: {
322
+ timestamp: message.timestamp,
323
+ idType: message.idType,
324
+ root: message.root,
325
+ replacedAtTimestamp: message.replacedAtTimestamp
326
+ },
327
+ signature
328
+ };
329
+ }
330
+ return {
331
+ idStateMsg: {
332
+ timestamp: message.timestamp,
333
+ id: message.id,
334
+ state: message.state,
335
+ replacedAtTimestamp: message.replacedAtTimestamp
336
+ },
337
+ signature
338
+ };
339
+ }
89
340
  }
90
341
  exports.OnChainZKPVerifier = OnChainZKPVerifier;
@@ -1,11 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildDIDFromEthPubKey = exports.resolveDIDDocumentAuth = exports.validateDIDDocumentAuth = exports.buildVerifierId = exports.isEthereumIdentity = exports.isGenesisState = void 0;
3
+ exports.buildDIDFromEthPubKey = exports.resolveDidDocument = exports.resolveDIDDocumentAuth = exports.validateDIDDocumentAuth = exports.buildVerifierId = exports.isEthereumIdentity = exports.isGenesisState = exports.DIDDocumentSignature = void 0;
4
4
  const js_crypto_1 = require("@iden3/js-crypto");
5
5
  const js_iden3_core_1 = require("@iden3/js-iden3-core");
6
6
  const js_merkletree_1 = require("@iden3/js-merkletree");
7
7
  const js_sha3_1 = require("js-sha3");
8
8
  const encoding_1 = require("./encoding");
9
+ /**
10
+ * Supported DID Document Signatures
11
+ */
12
+ var DIDDocumentSignature;
13
+ (function (DIDDocumentSignature) {
14
+ DIDDocumentSignature["EthereumEip712Signature2021"] = "EthereumEip712Signature2021";
15
+ })(DIDDocumentSignature = exports.DIDDocumentSignature || (exports.DIDDocumentSignature = {}));
9
16
  /**
10
17
  * Checks if state is genesis state
11
18
  *
@@ -74,6 +81,35 @@ const resolveDIDDocumentAuth = async (did, resolveURL, state) => {
74
81
  return didResolutionRes.didDocument?.verificationMethod?.find((i) => i.type === 'Iden3StateInfo2023');
75
82
  };
76
83
  exports.resolveDIDDocumentAuth = resolveDIDDocumentAuth;
84
+ function emptyStateDID(did) {
85
+ const id = js_iden3_core_1.DID.idFromDID(did);
86
+ const didType = (0, js_iden3_core_1.buildDIDType)(js_iden3_core_1.DID.methodFromId(id), js_iden3_core_1.DID.blockchainFromId(id), js_iden3_core_1.DID.networkIdFromId(id));
87
+ const identifier = js_iden3_core_1.Id.idGenesisFromIdenState(didType, 0n);
88
+ const emptyDID = js_iden3_core_1.DID.parseFromId(identifier);
89
+ return emptyDID;
90
+ }
91
+ const resolveDidDocument = async (did, resolverUrl, opts) => {
92
+ let didString = did.string().replace(/:/g, '%3A');
93
+ // for gist resolve we have to `hide` user did (look into resolver implementation)
94
+ const isGistRequest = opts?.gist && !opts.state;
95
+ if (isGistRequest) {
96
+ didString = emptyStateDID(did).string();
97
+ }
98
+ let url = `${resolverUrl}/1.0/identifiers/${didString}`;
99
+ if (opts?.signature) {
100
+ url += `?signature=${opts.signature}`;
101
+ }
102
+ if (opts?.state) {
103
+ url += `${url.includes('?') ? '&' : '?'}state=${opts.state.hex()}`;
104
+ }
105
+ if (opts?.gist) {
106
+ url += `${url.includes('?') ? '&' : '?'}gist=${opts.gist.hex()}`;
107
+ }
108
+ const resp = await fetch(url);
109
+ const data = await resp.json();
110
+ return data;
111
+ };
112
+ exports.resolveDidDocument = resolveDidDocument;
77
113
  const buildDIDFromEthPubKey = (didType, pubKeyEth) => {
78
114
  // Use Keccak-256 hash function to get public key hash
79
115
  const hashOfPublicKey = (0, js_sha3_1.keccak256)((0, encoding_1.hexToBytes)(pubKeyEth));
@@ -177,4 +177,14 @@ export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig {
177
177
  fieldIdx++;
178
178
  return this;
179
179
  }
180
+ /** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
181
+ getStatesInfo() {
182
+ return {
183
+ states: [
184
+ { id: this.issuerID, state: this.issuerClaimIdenState },
185
+ { id: this.issuerID, state: this.issuerClaimNonRevState }
186
+ ],
187
+ gists: [{ id: this.userID, root: this.gistRoot }]
188
+ };
189
+ }
180
190
  }
@@ -226,4 +226,14 @@ export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig {
226
226
  fieldIdx++;
227
227
  return this;
228
228
  }
229
+ /** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
230
+ getStatesInfo() {
231
+ return {
232
+ states: [
233
+ { id: this.issuerID, state: this.issuerAuthState },
234
+ { id: this.issuerID, state: this.issuerClaimNonRevState }
235
+ ],
236
+ gists: [{ id: this.userID, root: this.gistRoot }]
237
+ };
238
+ }
229
239
  }
@@ -303,4 +303,14 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
303
303
  this.isBJJAuthEnabled = parseInt(sVals[fieldIdx]);
304
304
  return this;
305
305
  }
306
+ /** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
307
+ getStatesInfo() {
308
+ return {
309
+ states: [
310
+ { id: this.issuerID, state: this.issuerState },
311
+ { id: this.issuerID, state: this.issuerClaimNonRevState }
312
+ ],
313
+ gists: [{ id: this.userID, root: this.gistRoot }]
314
+ };
315
+ }
306
316
  }
@@ -31,6 +31,8 @@ export const PROTOCOL_MESSAGE_TYPE = Object.freeze({
31
31
  REVOCATION_STATUS_RESPONSE_MESSAGE_TYPE: `${IDEN3_PROTOCOL}revocation/1.0/status`,
32
32
  // ContractInvokeRequestMessageType is type for request of contract invoke request
33
33
  CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: `${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-request`,
34
+ // ContractInvokeResponseMessageType is type for response of contract invoke request
35
+ CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE: `${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-response`,
34
36
  // CredentialOnchainOfferMessageType is type of message with credential onchain offering
35
37
  CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/1.0/onchain-offer`,
36
38
  // ProposalRequestMessageType is type for proposal-request message
@@ -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 { FunctionSignatures } from '../../storage';
4
5
  import { processZeroKnowledgeProofRequests } from './common';
5
6
  import { AbstractMessageHandler } from './message-handler';
6
7
  /**
@@ -33,9 +34,11 @@ export class ContractRequestHandler extends AbstractMessageHandler {
33
34
  }
34
35
  async handle(message, ctx) {
35
36
  switch (message.type) {
36
- case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE:
37
- await this.handleContractInvoke(message, ctx);
38
- return null;
37
+ case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: {
38
+ const ciMessage = message;
39
+ const txHashResponsesMap = await this.handleContractInvoke(ciMessage, ctx);
40
+ return this.createContractInvokeResponse(ciMessage, txHashResponsesMap);
41
+ }
39
42
  default:
40
43
  return super.handle(message, ctx);
41
44
  }
@@ -55,7 +58,21 @@ export class ContractRequestHandler extends AbstractMessageHandler {
55
58
  }
56
59
  const verifierDid = message.from ? DID.parse(message.from) : undefined;
57
60
  const zkpResponses = await processZeroKnowledgeProofRequests(did, message?.body?.scope, verifierDid, this._proofService, { ethSigner, challenge, supportedCircuits: this._supportedCircuits });
58
- return this._zkpVerifier.submitZKPResponse(ethSigner, message.body.transaction_data, zkpResponses);
61
+ const methodId = message.body.transaction_data.method_id.replace('0x', '');
62
+ switch (methodId) {
63
+ case FunctionSignatures.SubmitZKPResponseV2:
64
+ return this._zkpVerifier.submitZKPResponseV2(ethSigner, message.body.transaction_data, zkpResponses);
65
+ case FunctionSignatures.SubmitZKPResponseV1: {
66
+ const txHashZkpResponseMap = await this._zkpVerifier.submitZKPResponse(ethSigner, message.body.transaction_data, zkpResponses);
67
+ const response = new Map();
68
+ for (const [txHash, zkpResponse] of txHashZkpResponseMap) {
69
+ response.set(txHash, [zkpResponse]);
70
+ }
71
+ return response;
72
+ }
73
+ default:
74
+ throw new Error(`Not supported method id. Only '${FunctionSignatures.SubmitZKPResponseV1} and ${FunctionSignatures.SubmitZKPResponseV2} are supported.'`);
75
+ }
59
76
  }
60
77
  /**
61
78
  * unpacks contract-invoke request
@@ -73,8 +90,41 @@ export class ContractRequestHandler extends AbstractMessageHandler {
73
90
  return ciRequest;
74
91
  }
75
92
  /**
76
- * handle contract invoker request
93
+ * creates contract invoke response
94
+ * @private
95
+ * @beta
96
+ * @param {ContractInvokeRequest} request - ContractInvokeRequest
97
+ * @param { Map<string, ZeroKnowledgeProofResponse[]>} responses - map tx hash to array of ZeroKnowledgeProofResponses
98
+ * @returns `Promise<ContractInvokeResponse>`
99
+ */
100
+ async createContractInvokeResponse(request, txHashToZkpResponseMap) {
101
+ const contractInvokeResponse = {
102
+ id: request.id,
103
+ thid: request.thid,
104
+ type: PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE,
105
+ from: request.to,
106
+ to: request.from,
107
+ body: {
108
+ transaction_data: request.body.transaction_data,
109
+ reason: request.body.reason,
110
+ scope: []
111
+ }
112
+ };
113
+ for (const [txHash, zkpResponses] of txHashToZkpResponseMap) {
114
+ for (const zkpResponse of zkpResponses) {
115
+ contractInvokeResponse.body.scope.push({
116
+ txHash,
117
+ ...zkpResponse
118
+ });
119
+ }
120
+ }
121
+ return contractInvokeResponse;
122
+ }
123
+ /**
124
+ * handle contract invoke request
125
+ * supports only 0xb68967e2 method id
77
126
  * @beta
127
+ * @deprecated
78
128
  * @param {did} did - sender DID
79
129
  * @param {ContractInvokeRequest} request - contract invoke request
80
130
  * @param {ContractInvokeHandlerOptions} opts - handler options
@@ -82,10 +132,23 @@ export class ContractRequestHandler extends AbstractMessageHandler {
82
132
  */
83
133
  async handleContractInvokeRequest(did, request, opts) {
84
134
  const ciRequest = await this.parseContractInvokeRequest(request);
85
- return this.handleContractInvoke(ciRequest, {
86
- senderDid: did,
87
- ethSigner: opts.ethSigner,
88
- challenge: opts.challenge
89
- });
135
+ if (ciRequest.body.transaction_data.method_id !== FunctionSignatures.SubmitZKPResponseV1) {
136
+ throw new Error(`please use handle method to work with other method ids`);
137
+ }
138
+ if (ciRequest.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
139
+ throw new Error('Invalid message type for contract invoke request');
140
+ }
141
+ const { ethSigner, challenge } = opts;
142
+ if (!ethSigner) {
143
+ throw new Error("Can't sign transaction. Provide Signer in options.");
144
+ }
145
+ const { chain_id } = ciRequest.body.transaction_data;
146
+ const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
147
+ if (!networkFlag) {
148
+ throw new Error(`Invalid chain id ${chain_id}`);
149
+ }
150
+ const verifierDid = ciRequest.from ? DID.parse(ciRequest.from) : undefined;
151
+ const zkpResponses = await processZeroKnowledgeProofRequests(did, ciRequest?.body?.scope, verifierDid, this._proofService, { ethSigner, challenge, supportedCircuits: this._supportedCircuits });
152
+ return this._zkpVerifier.submitZKPResponse(ethSigner, ciRequest.body.transaction_data, zkpResponses);
90
153
  }
91
154
  }