@0xpolygonid/js-sdk 1.8.3 → 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.
Files changed (70) hide show
  1. package/dist/browser/esm/index.js +420 -189
  2. package/dist/browser/esm/index.js.map +1 -1
  3. package/dist/browser/umd/index.js +425 -189
  4. package/dist/browser/umd/index.js.map +1 -1
  5. package/dist/node/cjs/circuits/atomic-query-v3-on-chain.js +8 -25
  6. package/dist/node/cjs/circuits/atomic-query-v3.js +6 -5
  7. package/dist/node/cjs/circuits/common.js +1 -1
  8. package/dist/node/cjs/circuits/comparer.js +24 -3
  9. package/dist/node/cjs/circuits/linked-multi-query.js +6 -17
  10. package/dist/node/cjs/circuits/models.js +47 -3
  11. package/dist/node/cjs/iden3comm/handlers/auth.js +14 -55
  12. package/dist/node/cjs/iden3comm/handlers/common.js +85 -0
  13. package/dist/node/cjs/iden3comm/handlers/contract-request.js +6 -25
  14. package/dist/node/cjs/iden3comm/handlers/index.js +2 -0
  15. package/dist/node/cjs/iden3comm/handlers/revocation-status.js +119 -0
  16. package/dist/node/cjs/identity/identity-wallet.js +4 -0
  17. package/dist/node/cjs/proof/common.js +11 -5
  18. package/dist/node/cjs/proof/provers/inputs-generator.js +6 -10
  19. package/dist/node/cjs/proof/verifiers/index.js +1 -0
  20. package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +37 -22
  21. package/dist/node/cjs/proof/verifiers/query-hash.js +40 -0
  22. package/dist/node/cjs/proof/verifiers/query.js +24 -16
  23. package/dist/node/cjs/schema-processor/utils.js +2 -2
  24. package/dist/node/cjs/storage/filters/jsonQuery.js +28 -2
  25. package/dist/node/cjs/verifiable/core-utils.js +3 -3
  26. package/dist/node/cjs/verifiable/credential.js +1 -1
  27. package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +9 -26
  28. package/dist/node/esm/circuits/atomic-query-v3.js +7 -6
  29. package/dist/node/esm/circuits/common.js +1 -1
  30. package/dist/node/esm/circuits/comparer.js +24 -3
  31. package/dist/node/esm/circuits/linked-multi-query.js +7 -18
  32. package/dist/node/esm/circuits/models.js +48 -4
  33. package/dist/node/esm/iden3comm/handlers/auth.js +15 -56
  34. package/dist/node/esm/iden3comm/handlers/common.js +81 -0
  35. package/dist/node/esm/iden3comm/handlers/contract-request.js +7 -26
  36. package/dist/node/esm/iden3comm/handlers/index.js +2 -0
  37. package/dist/node/esm/iden3comm/handlers/revocation-status.js +92 -0
  38. package/dist/node/esm/identity/identity-wallet.js +4 -0
  39. package/dist/node/esm/proof/common.js +12 -6
  40. package/dist/node/esm/proof/provers/inputs-generator.js +7 -11
  41. package/dist/node/esm/proof/verifiers/index.js +1 -0
  42. package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +41 -26
  43. package/dist/node/esm/proof/verifiers/query-hash.js +35 -0
  44. package/dist/node/esm/proof/verifiers/query.js +23 -16
  45. package/dist/node/esm/schema-processor/utils.js +3 -3
  46. package/dist/node/esm/storage/filters/jsonQuery.js +28 -2
  47. package/dist/node/esm/verifiable/core-utils.js +1 -1
  48. package/dist/node/esm/verifiable/credential.js +2 -2
  49. package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +4 -8
  50. package/dist/types/circuits/atomic-query-v3.d.ts +2 -2
  51. package/dist/types/circuits/common.d.ts +1 -1
  52. package/dist/types/circuits/comparer.d.ts +4 -0
  53. package/dist/types/circuits/linked-multi-query.d.ts +0 -1
  54. package/dist/types/circuits/models.d.ts +7 -4
  55. package/dist/types/iden3comm/handlers/auth.d.ts +1 -0
  56. package/dist/types/iden3comm/handlers/common.d.ts +23 -0
  57. package/dist/types/iden3comm/handlers/contract-request.d.ts +1 -1
  58. package/dist/types/iden3comm/handlers/index.d.ts +2 -0
  59. package/dist/types/iden3comm/handlers/revocation-status.d.ts +59 -0
  60. package/dist/types/iden3comm/types/protocol/contract-request.d.ts +1 -0
  61. package/dist/types/identity/identity-wallet.d.ts +13 -1
  62. package/dist/types/proof/verifiers/index.d.ts +1 -0
  63. package/dist/types/proof/verifiers/query-hash.d.ts +3 -0
  64. package/dist/types/proof/verifiers/query.d.ts +1 -0
  65. package/dist/types/schema-processor/utils.d.ts +1 -1
  66. package/dist/types/storage/filters/jsonQuery.d.ts +1 -1
  67. package/dist/types/verifiable/core-utils.d.ts +1 -1
  68. package/dist/types/verifiable/credential.d.ts +1 -1
  69. package/dist/types/verifiable/proof.d.ts +5 -1
  70. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Claim, Id } from '@iden3/js-iden3-core';
2
- import { BaseConfig, bigIntArrayToStringArray, prepareSiblingsStr, existenceToInt, getNodeAuxValue, prepareCircuitArrayValues } from './common';
2
+ import { BaseConfig, bigIntArrayToStringArray, prepareSiblingsStr, getNodeAuxValue, prepareCircuitArrayValues } from './common';
3
3
  import { CircuitError, ValueProof } from './models';
4
4
  import { Hash, Proof, ZERO_HASH } from '@iden3/js-merkletree';
5
5
  import { byteDecoder, byteEncoder } from '../utils';
@@ -23,13 +23,14 @@ export class AtomicQueryV3OnChainInputs extends BaseConfig {
23
23
  if (!this.query.values) {
24
24
  throw new Error(CircuitError.EmptyQueryValue);
25
25
  }
26
+ this.query.validateValueArraySize(this.getValueArrSize());
26
27
  if (!this.proofType) {
27
28
  throw new Error(CircuitError.InvalidProofType);
28
29
  }
29
30
  if (!this.challenge) {
30
31
  throw new Error(CircuitError.EmptyChallenge);
31
32
  }
32
- if (this.authEnabled === 1) {
33
+ if (this.isBJJAuthEnabled === 1) {
33
34
  if (!this.authClaimIncMtp) {
34
35
  throw new Error(CircuitError.EmptyAuthClaimProof);
35
36
  }
@@ -145,7 +146,7 @@ export class AtomicQueryV3OnChainInputs extends BaseConfig {
145
146
  isRevocationChecked: 1
146
147
  };
147
148
  s.challenge = this.challenge?.toString();
148
- if (this.authEnabled === 1) {
149
+ if (this.isBJJAuthEnabled === 1) {
149
150
  s.authClaim = this.authClaim?.marshalJson();
150
151
  s.userClaimsTreeRoot = this.treeState.claimsRoot?.bigInt().toString();
151
152
  s.userRevTreeRoot = this.treeState.revocationRoot?.bigInt().toString();
@@ -220,18 +221,18 @@ export class AtomicQueryV3OnChainInputs extends BaseConfig {
220
221
  s.issuerClaimNonRevMtpAuxHi = nodeAuxNonRev.key.bigInt().toString();
221
222
  s.issuerClaimNonRevMtpAuxHv = nodeAuxNonRev.value.bigInt().toString();
222
223
  s.issuerClaimNonRevMtpNoAux = nodeAuxNonRev.noAux;
223
- s.claimPathNotExists = existenceToInt(valueProof.mtp.existence);
224
224
  const nodAuxJSONLD = getNodeAuxValue(valueProof.mtp);
225
225
  s.claimPathMtpNoAux = nodAuxJSONLD.noAux;
226
226
  s.claimPathMtpAuxHi = nodAuxJSONLD.key.bigInt().toString();
227
227
  s.claimPathMtpAuxHv = nodAuxJSONLD.value.bigInt().toString();
228
228
  s.claimPathKey = valueProof.path.toString();
229
+ s.valueArraySize = this.query.values.length;
229
230
  const values = prepareCircuitArrayValues(this.query.values, this.getValueArrSize());
230
231
  s.value = bigIntArrayToStringArray(values);
231
232
  s.linkNonce = this.linkNonce.toString();
232
233
  s.verifierID = this.verifierID?.bigInt().toString() ?? '0';
233
234
  s.nullifierSessionID = this.nullifierSessionID.toString();
234
- s.authEnabled = this.authEnabled.toString();
235
+ s.isBJJAuthEnabled = this.isBJJAuthEnabled.toString();
235
236
  return byteEncoder.encode(JSON.stringify(s));
236
237
  }
237
238
  }
@@ -243,7 +244,6 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
243
244
  // PubSignalsUnmarshal unmarshal credentialAtomicQueryV3.circom public signals
244
245
  pubSignalsUnmarshal(data) {
245
246
  // expected order:
246
- // merklized
247
247
  // userID
248
248
  // circuitQueryHash
249
249
  // issuerState
@@ -255,17 +255,11 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
255
255
  // challenge
256
256
  // gistRoot
257
257
  // issuerID
258
- // isRevocationChecked
259
258
  // issuerClaimNonRevState
260
259
  // timestamp
261
- // verifierID
262
- // nullifierSessionID
263
- // authEnabled
260
+ // isBJJAuthEnabled
264
261
  const sVals = JSON.parse(byteDecoder.decode(data));
265
262
  let fieldIdx = 0;
266
- // -- merklized
267
- this.merklized = parseInt(sVals[fieldIdx]);
268
- fieldIdx++;
269
263
  // - userID
270
264
  this.userID = Id.fromBigInt(BigInt(sVals[fieldIdx]));
271
265
  fieldIdx++;
@@ -299,25 +293,14 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
299
293
  // - issuerID
300
294
  this.issuerID = Id.fromBigInt(BigInt(sVals[fieldIdx]));
301
295
  fieldIdx++;
302
- // - isRevocationChecked
303
- this.isRevocationChecked = parseInt(sVals[fieldIdx]);
304
- fieldIdx++;
305
296
  // - issuerClaimNonRevState
306
297
  this.issuerClaimNonRevState = Hash.fromString(sVals[fieldIdx]);
307
298
  fieldIdx++;
308
299
  // - timestamp
309
300
  this.timestamp = parseInt(sVals[fieldIdx]);
310
301
  fieldIdx++;
311
- // - verifierID
312
- if (sVals[fieldIdx] !== '0') {
313
- this.verifierID = Id.fromBigInt(BigInt(sVals[fieldIdx]));
314
- }
315
- fieldIdx++;
316
- // - nullifierSessionID
317
- this.nullifierSessionID = BigInt(sVals[fieldIdx]);
318
- fieldIdx++;
319
- // - authEnabled
320
- this.authEnabled = parseInt(sVals[fieldIdx]);
302
+ // - isBJJAuthEnabled
303
+ this.isBJJAuthEnabled = parseInt(sVals[fieldIdx]);
321
304
  return this;
322
305
  }
323
306
  }
@@ -1,5 +1,5 @@
1
1
  import { Claim, Id, SchemaHash } from '@iden3/js-iden3-core';
2
- import { BaseConfig, bigIntArrayToStringArray, prepareSiblingsStr, existenceToInt, getNodeAuxValue, prepareCircuitArrayValues } from './common';
2
+ import { BaseConfig, bigIntArrayToStringArray, prepareSiblingsStr, getNodeAuxValue, prepareCircuitArrayValues } from './common';
3
3
  import { CircuitError, ValueProof } from './models';
4
4
  import { Hash, Proof, ZERO_HASH } from '@iden3/js-merkletree';
5
5
  import { byteDecoder, byteEncoder } from '../utils';
@@ -23,6 +23,7 @@ export class AtomicQueryV3Inputs extends BaseConfig {
23
23
  if (!this.query.values) {
24
24
  throw new Error(CircuitError.EmptyQueryValue);
25
25
  }
26
+ this.query.validateValueArraySize(this.getValueArrSize());
26
27
  if (!this.proofType) {
27
28
  throw new Error(CircuitError.InvalidProofType);
28
29
  }
@@ -152,12 +153,12 @@ export class AtomicQueryV3Inputs extends BaseConfig {
152
153
  s.issuerClaimNonRevMtpAuxHi = nodeAuxNonRev.key.bigInt().toString();
153
154
  s.issuerClaimNonRevMtpAuxHv = nodeAuxNonRev.value.bigInt().toString();
154
155
  s.issuerClaimNonRevMtpNoAux = nodeAuxNonRev.noAux;
155
- s.claimPathNotExists = existenceToInt(valueProof.mtp.existence);
156
156
  const nodAuxJSONLD = getNodeAuxValue(valueProof.mtp);
157
157
  s.claimPathMtpNoAux = nodAuxJSONLD.noAux;
158
158
  s.claimPathMtpAuxHi = nodAuxJSONLD.key.bigInt().toString();
159
159
  s.claimPathMtpAuxHv = nodAuxJSONLD.value.bigInt().toString();
160
160
  s.claimPathKey = valueProof.path.toString();
161
+ s.valueArraySize = this.query.values.length;
161
162
  const values = prepareCircuitArrayValues(this.query.values, this.getValueArrSize());
162
163
  s.value = bigIntArrayToStringArray(values);
163
164
  s.linkNonce = this.linkNonce.toString();
@@ -191,11 +192,11 @@ export class AtomicQueryV3PubSignals extends BaseConfig {
191
192
  // issuerClaimNonRevState
192
193
  // timestamp
193
194
  // claimSchema
194
- // claimPathNotExists
195
195
  // claimPathKey
196
196
  // slotIndex
197
197
  // operator
198
198
  // value
199
+ // valueArraySize
199
200
  // verifierID
200
201
  // nullifierSessionID
201
202
  // 19 is a number of fields in AtomicQueryV3PubSignals before values, values is last element in the proof and
@@ -246,9 +247,6 @@ export class AtomicQueryV3PubSignals extends BaseConfig {
246
247
  // - claimSchema
247
248
  this.claimSchema = SchemaHash.newSchemaHashFromInt(BigInt(sVals[fieldIdx]));
248
249
  fieldIdx++;
249
- // - ClaimPathNotExists
250
- this.claimPathNotExists = parseInt(sVals[fieldIdx]);
251
- fieldIdx++;
252
250
  // - ClaimPathKey
253
251
  this.claimPathKey = BigInt(sVals[fieldIdx]);
254
252
  fieldIdx++;
@@ -263,6 +261,9 @@ export class AtomicQueryV3PubSignals extends BaseConfig {
263
261
  this.value.push(BigInt(sVals[fieldIdx]));
264
262
  fieldIdx++;
265
263
  }
264
+ // - valueArraySize
265
+ this.valueArraySize = parseInt(sVals[fieldIdx]);
266
+ fieldIdx++;
266
267
  // - verifierID
267
268
  if (sVals[fieldIdx] !== '0') {
268
269
  this.verifierID = Id.fromBigInt(BigInt(sVals[fieldIdx]));
@@ -42,7 +42,7 @@ export class BaseConfig {
42
42
  * @returns number
43
43
  */
44
44
  getValueArrSize() {
45
- return this.valueArraySize ? this.valueArraySize : defaultValueArraySize;
45
+ return this.maxValueArraySize ? this.maxValueArraySize : defaultValueArraySize;
46
46
  }
47
47
  /**
48
48
  * getMTLevelOnChain return level on chain for given circuit
@@ -30,6 +30,8 @@ export var Operators;
30
30
  Operators[Operators["LTE"] = 7] = "LTE";
31
31
  Operators[Operators["GTE"] = 8] = "GTE";
32
32
  Operators[Operators["BETWEEN"] = 9] = "BETWEEN";
33
+ Operators[Operators["NONBETWEEN"] = 10] = "NONBETWEEN";
34
+ Operators[Operators["EXISTS"] = 11] = "EXISTS";
33
35
  Operators[Operators["SD"] = 16] = "SD";
34
36
  Operators[Operators["NULLIFY"] = 17] = "NULLIFY";
35
37
  })(Operators || (Operators = {}));
@@ -45,12 +47,17 @@ export const QueryOperators = {
45
47
  $lte: Operators.LTE,
46
48
  $gte: Operators.GTE,
47
49
  $between: Operators.BETWEEN,
50
+ $nonbetween: Operators.NONBETWEEN,
51
+ $exists: Operators.EXISTS,
48
52
  $sd: Operators.SD,
49
53
  $nullify: Operators.NULLIFY
50
54
  };
51
55
  const allOperations = Object.values(QueryOperators);
52
56
  export const availableTypesOperators = new Map([
53
- [XSDNS.Boolean, [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$sd]],
57
+ [
58
+ XSDNS.Boolean,
59
+ [QueryOperators.$eq, QueryOperators.$ne, QueryOperators.$sd, QueryOperators.$exists]
60
+ ],
54
61
  [XSDNS.Integer, allOperations],
55
62
  [XSDNS.NonNegativeInteger, allOperations],
56
63
  [XSDNS.PositiveInteger, allOperations],
@@ -61,7 +68,8 @@ export const availableTypesOperators = new Map([
61
68
  QueryOperators.$ne,
62
69
  QueryOperators.$in,
63
70
  QueryOperators.$nin,
64
- QueryOperators.$sd
71
+ QueryOperators.$sd,
72
+ QueryOperators.$exists
65
73
  ]
66
74
  ],
67
75
  [
@@ -71,7 +79,8 @@ export const availableTypesOperators = new Map([
71
79
  QueryOperators.$ne,
72
80
  QueryOperators.$in,
73
81
  QueryOperators.$nin,
74
- QueryOperators.$sd
82
+ QueryOperators.$sd,
83
+ QueryOperators.$exists
75
84
  ]
76
85
  ],
77
86
  [XSDNS.DateTime, allOperations]
@@ -162,6 +171,16 @@ export class Vector {
162
171
  return this.y.includes(this.x);
163
172
  case Operators.NIN:
164
173
  return !this.y.includes(this.x);
174
+ case Operators.BETWEEN:
175
+ if (this.y.length !== 2) {
176
+ return false;
177
+ }
178
+ return this.x >= this.y[0] && this.x <= this.y[1];
179
+ case Operators.NONBETWEEN:
180
+ if (this.y.length !== 2) {
181
+ return false;
182
+ }
183
+ return this.x < this.y[0] || this.x > this.y[1];
165
184
  default:
166
185
  throw new Error('unknown compare type for vector');
167
186
  }
@@ -187,6 +206,8 @@ export const factoryComparer = (x, y, operator) => {
187
206
  return new Scalar(x, y[0]);
188
207
  case Operators.IN:
189
208
  case Operators.NIN:
209
+ case Operators.BETWEEN:
210
+ case Operators.NONBETWEEN:
190
211
  return new Vector(x, y);
191
212
  default:
192
213
  throw new Error('unknown compare type');
@@ -1,6 +1,6 @@
1
1
  import { Proof } from '@iden3/js-merkletree';
2
2
  import { byteDecoder, byteEncoder } from '../utils';
3
- import { BaseConfig, bigIntArrayToStringArray, existenceToInt, getNodeAuxValue, prepareCircuitArrayValues, prepareSiblingsStr } from './common';
3
+ import { BaseConfig, bigIntArrayToStringArray, getNodeAuxValue, prepareCircuitArrayValues, prepareSiblingsStr } from './common';
4
4
  import { ValueProof } from './models';
5
5
  /**
6
6
  * LinkedMultiQuery circuit representation
@@ -12,8 +12,6 @@ import { ValueProof } from './models';
12
12
  export class LinkedMultiQueryInputs extends BaseConfig {
13
13
  // InputsMarshal returns Circom private inputs for linkedMultiQueryInputs.circom
14
14
  inputsMarshal() {
15
- const enabled = [];
16
- const claimPathNotExists = [];
17
15
  const claimPathMtp = [];
18
16
  const claimPathMtpNoAux = [];
19
17
  const claimPathMtpAuxHi = [];
@@ -23,10 +21,9 @@ export class LinkedMultiQueryInputs extends BaseConfig {
23
21
  const slotIndex = [];
24
22
  const operator = [];
25
23
  const value = [];
24
+ const valueArraySize = [];
26
25
  for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) {
27
26
  if (!this.query[i]) {
28
- enabled.push(0);
29
- claimPathNotExists.push(0);
30
27
  claimPathMtp.push(new Array(this.getMTLevelsClaim()).fill('0'));
31
28
  claimPathMtpNoAux.push('0');
32
29
  claimPathMtpAuxHi.push('0');
@@ -37,9 +34,9 @@ export class LinkedMultiQueryInputs extends BaseConfig {
37
34
  operator.push(0);
38
35
  const valuesArr = prepareCircuitArrayValues([], this.getValueArrSize());
39
36
  value.push(bigIntArrayToStringArray(valuesArr));
37
+ valueArraySize.push(0);
40
38
  continue;
41
39
  }
42
- enabled.push(1);
43
40
  let valueProof = this.query[i].valueProof;
44
41
  if (!valueProof) {
45
42
  valueProof = new ValueProof();
@@ -47,7 +44,6 @@ export class LinkedMultiQueryInputs extends BaseConfig {
47
44
  valueProof.value = 0n;
48
45
  valueProof.mtp = new Proof();
49
46
  }
50
- claimPathNotExists.push(existenceToInt(valueProof.mtp.existence));
51
47
  claimPathMtp.push(prepareSiblingsStr(valueProof.mtp, this.getMTLevelsClaim()));
52
48
  const nodAuxJSONLD = getNodeAuxValue(valueProof.mtp);
53
49
  claimPathMtpNoAux.push(nodAuxJSONLD.noAux);
@@ -57,15 +53,14 @@ export class LinkedMultiQueryInputs extends BaseConfig {
57
53
  claimPathValue.push(valueProof.value.toString());
58
54
  slotIndex.push(this.query[i].slotIndex);
59
55
  operator.push(this.query[i].operator);
56
+ valueArraySize.push(this.query[i].values.length);
60
57
  const valuesArr = prepareCircuitArrayValues(this.query[i].values, this.getValueArrSize());
61
58
  value.push(bigIntArrayToStringArray(valuesArr));
62
59
  }
63
60
  const s = {
64
61
  linkNonce: this.linkNonce.toString(),
65
62
  issuerClaim: this.claim.marshalJson(),
66
- enabled,
67
63
  claimSchema: this.claim.getSchemaHash().bigInt().toString(),
68
- claimPathNotExists,
69
64
  claimPathMtp,
70
65
  claimPathMtpNoAux,
71
66
  claimPathMtpAuxHi,
@@ -74,7 +69,8 @@ export class LinkedMultiQueryInputs extends BaseConfig {
74
69
  claimPathValue,
75
70
  slotIndex,
76
71
  operator,
77
- value
72
+ value,
73
+ valueArraySize
78
74
  };
79
75
  return byteEncoder.encode(JSON.stringify(s));
80
76
  }
@@ -96,7 +92,7 @@ export class LinkedMultiQueryPubSignals {
96
92
  * @returns LinkedMultiQueryPubSignals
97
93
  */
98
94
  pubSignalsUnmarshal(data) {
99
- const len = 32;
95
+ const len = 22;
100
96
  const queryLength = LinkedMultiQueryInputs.queryCount;
101
97
  const sVals = JSON.parse(byteDecoder.decode(data));
102
98
  if (sVals.length !== len) {
@@ -121,13 +117,6 @@ export class LinkedMultiQueryPubSignals {
121
117
  this.circuitQueryHash.push(BigInt(sVals[fieldIdx]));
122
118
  fieldIdx++;
123
119
  }
124
- // - enabled
125
- this.enabled = [];
126
- for (let i = 0; i < queryLength; i++) {
127
- const enabledNum = parseInt(sVals[fieldIdx]);
128
- this.enabled.push(enabledNum === 1);
129
- fieldIdx++;
130
- }
131
120
  return this;
132
121
  }
133
122
  }
@@ -1,5 +1,5 @@
1
1
  import { Proof } from '@iden3/js-merkletree';
2
- import { QueryOperators } from './comparer';
2
+ import { Operators, QueryOperators } from './comparer';
3
3
  /**
4
4
  * Query represents basic request to claim slot verification
5
5
  *
@@ -17,6 +17,48 @@ export class Query {
17
17
  this.values?.some((v) => typeof v !== 'bigint'))
18
18
  throw new Error(CircuitError.EmptyQueryValue);
19
19
  }
20
+ validateValueArraySize(maxArrSize) {
21
+ switch (this.values.length) {
22
+ case 0: {
23
+ const zeroArrSizeOps = [Operators.NOOP, Operators.SD, Operators.NULLIFY];
24
+ if (!zeroArrSizeOps.includes(this.operator)) {
25
+ throw new Error(CircuitError.InvalidValuesArrSize);
26
+ }
27
+ return;
28
+ }
29
+ case 1: {
30
+ const oneArrSizeOps = [
31
+ Operators.EQ,
32
+ Operators.LT,
33
+ Operators.GT,
34
+ Operators.NE,
35
+ Operators.LTE,
36
+ Operators.GTE,
37
+ Operators.EXISTS
38
+ ];
39
+ if (!oneArrSizeOps.includes(this.operator)) {
40
+ throw new Error(CircuitError.InvalidValuesArrSize);
41
+ }
42
+ return;
43
+ }
44
+ case 2: {
45
+ const twoArrSizeOps = [Operators.BETWEEN, Operators.NONBETWEEN];
46
+ if (!twoArrSizeOps.includes(this.operator)) {
47
+ throw new Error(CircuitError.InvalidValuesArrSize);
48
+ }
49
+ return;
50
+ }
51
+ default: {
52
+ const maxArrSizeOps = [Operators.IN, Operators.NIN];
53
+ if (!maxArrSizeOps.includes(this.operator)) {
54
+ throw new Error(CircuitError.InvalidOperationType);
55
+ }
56
+ if (!this.values.length || this.values.length > maxArrSize) {
57
+ throw new Error(CircuitError.InvalidValuesArrSize);
58
+ }
59
+ }
60
+ }
61
+ }
20
62
  }
21
63
  /**
22
64
  * CircuitID is alias for circuit identifier
@@ -41,17 +83,17 @@ export var CircuitId;
41
83
  * @beta
42
84
  */
43
85
  // AtomicQueryV3CircuitID is a type for credentialAtomicQueryV3.circom
44
- CircuitId["AtomicQueryV3"] = "credentialAtomicQueryV3-beta.0";
86
+ CircuitId["AtomicQueryV3"] = "credentialAtomicQueryV3-beta.1";
45
87
  /**
46
88
  * @beta
47
89
  */
48
90
  // AtomicQueryV3OnChainCircuitID is a type for credentialAtomicQueryV3OnChain.circom
49
- CircuitId["AtomicQueryV3OnChain"] = "credentialAtomicQueryV3OnChain-beta.0";
91
+ CircuitId["AtomicQueryV3OnChain"] = "credentialAtomicQueryV3OnChain-beta.1";
50
92
  /**
51
93
  * @beta
52
94
  */
53
95
  // LinkedMultiQuery is a type for linkedMultiQuery.circom
54
- CircuitId["LinkedMultiQuery10"] = "linkedMultiQuery10-beta.0";
96
+ CircuitId["LinkedMultiQuery10"] = "linkedMultiQuery10-beta.1";
55
97
  })(CircuitId || (CircuitId = {}));
56
98
  /**
57
99
  * Claim structure for circuit inputs
@@ -88,6 +130,8 @@ export var CircuitError;
88
130
  CircuitError["EmptyTreeState"] = "empty tree state";
89
131
  CircuitError["EmptyRequestID"] = "empty request ID";
90
132
  CircuitError["InvalidProofType"] = "invalid proof type";
133
+ CircuitError["InvalidValuesArrSize"] = "invalid query Values array size";
134
+ CircuitError["InvalidOperationType"] = "invalid operation type";
91
135
  })(CircuitError || (CircuitError = {}));
92
136
  /**
93
137
  * ValueProof represents a Merkle Proof for a value stored as MT
@@ -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, mergeObjects } from '../../utils';
7
- import { getRandomBytes } from '@iden3/js-crypto';
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,7 +1,7 @@
1
1
  import { CircuitId } from '../../circuits/models';
2
2
  import { PROTOCOL_MESSAGE_TYPE } from '../constants';
3
- import { DID, ChainIds, DidMethod } from '@iden3/js-iden3-core';
4
- import { buildVerifierId } from '../../utils';
3
+ import { DID, ChainIds } from '@iden3/js-iden3-core';
4
+ import { processZeroKnowledgeProofRequests } from './common';
5
5
  /**
6
6
  *
7
7
  * Allows to process ContractInvokeRequest protocol message
@@ -23,7 +23,7 @@ export class ContractRequestHandler {
23
23
  this._packerMgr = _packerMgr;
24
24
  this._proofService = _proofService;
25
25
  this._zkpVerifier = _zkpVerifier;
26
- this._allowedCircuits = [
26
+ this._supportedCircuits = [
27
27
  CircuitId.AtomicQueryMTPV2OnChain,
28
28
  CircuitId.AtomicQuerySigV2OnChain,
29
29
  CircuitId.AtomicQueryV3OnChain
@@ -60,32 +60,13 @@ export class ContractRequestHandler {
60
60
  if (!opts.ethSigner) {
61
61
  throw new Error("Can't sign transaction. Provide Signer in options.");
62
62
  }
63
- const zkRequests = [];
64
- const { contract_address, chain_id } = ciRequest.body.transaction_data;
63
+ const { chain_id } = ciRequest.body.transaction_data;
65
64
  const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
66
65
  if (!networkFlag) {
67
66
  throw new Error(`Invalid chain id ${chain_id}`);
68
67
  }
69
- const [blockchain, networkId] = networkFlag.split(':');
70
- const verifierId = buildVerifierId(contract_address, {
71
- blockchain,
72
- networkId,
73
- // DidMethod.Iden3 is used based on discussions: all onchain issuers have iden3 did method by default. This can be changed in the release of v3 circuit.
74
- method: DidMethod.Iden3
75
- });
76
- const verifierDid = DID.parseFromId(verifierId);
77
- for (const proofReq of ciRequest.body.scope) {
78
- if (!this._allowedCircuits.includes(proofReq.circuitId)) {
79
- throw new Error(`Can't handle circuit ${proofReq.circuitId}. Only onchain circuits are allowed.`);
80
- }
81
- const query = proofReq.query;
82
- const zkpRes = await this._proofService.generateProof(proofReq, did, {
83
- skipRevocation: query.skipClaimRevocationCheck ?? false,
84
- challenge: opts.challenge,
85
- verifierDid
86
- });
87
- zkRequests.push(zkpRes);
88
- }
89
- 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);
90
71
  }
91
72
  }