@0xpolygonid/js-sdk 1.8.2 → 1.9.0

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 (54) hide show
  1. package/dist/browser/esm/index.js +240 -124
  2. package/dist/browser/esm/index.js.map +1 -1
  3. package/dist/browser/umd/index.js +243 -124
  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 +5 -3
  12. package/dist/node/cjs/iden3comm/handlers/contract-request.js +3 -11
  13. package/dist/node/cjs/proof/common.js +11 -5
  14. package/dist/node/cjs/proof/provers/inputs-generator.js +6 -10
  15. package/dist/node/cjs/proof/verifiers/index.js +1 -0
  16. package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +37 -22
  17. package/dist/node/cjs/proof/verifiers/query-hash.js +40 -0
  18. package/dist/node/cjs/proof/verifiers/query.js +24 -16
  19. package/dist/node/cjs/schema-processor/utils.js +2 -2
  20. package/dist/node/cjs/storage/filters/jsonQuery.js +28 -2
  21. package/dist/node/cjs/verifiable/core-utils.js +3 -3
  22. package/dist/node/cjs/verifiable/credential.js +1 -1
  23. package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +9 -26
  24. package/dist/node/esm/circuits/atomic-query-v3.js +7 -6
  25. package/dist/node/esm/circuits/common.js +1 -1
  26. package/dist/node/esm/circuits/comparer.js +24 -3
  27. package/dist/node/esm/circuits/linked-multi-query.js +7 -18
  28. package/dist/node/esm/circuits/models.js +48 -4
  29. package/dist/node/esm/iden3comm/handlers/auth.js +5 -3
  30. package/dist/node/esm/iden3comm/handlers/contract-request.js +4 -12
  31. package/dist/node/esm/proof/common.js +12 -6
  32. package/dist/node/esm/proof/provers/inputs-generator.js +7 -11
  33. package/dist/node/esm/proof/verifiers/index.js +1 -0
  34. package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +41 -26
  35. package/dist/node/esm/proof/verifiers/query-hash.js +35 -0
  36. package/dist/node/esm/proof/verifiers/query.js +23 -16
  37. package/dist/node/esm/schema-processor/utils.js +3 -3
  38. package/dist/node/esm/storage/filters/jsonQuery.js +28 -2
  39. package/dist/node/esm/verifiable/core-utils.js +1 -1
  40. package/dist/node/esm/verifiable/credential.js +2 -2
  41. package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +4 -8
  42. package/dist/types/circuits/atomic-query-v3.d.ts +2 -2
  43. package/dist/types/circuits/common.d.ts +1 -1
  44. package/dist/types/circuits/comparer.d.ts +4 -0
  45. package/dist/types/circuits/linked-multi-query.d.ts +0 -1
  46. package/dist/types/circuits/models.d.ts +7 -4
  47. package/dist/types/iden3comm/types/protocol/contract-request.d.ts +1 -0
  48. package/dist/types/proof/verifiers/index.d.ts +1 -0
  49. package/dist/types/proof/verifiers/query-hash.d.ts +3 -0
  50. package/dist/types/proof/verifiers/query.d.ts +1 -0
  51. package/dist/types/schema-processor/utils.d.ts +1 -1
  52. package/dist/types/storage/filters/jsonQuery.d.ts +1 -1
  53. package/dist/types/verifiable/core-utils.d.ts +1 -1
  54. package/package.json +1 -1
@@ -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
@@ -69,6 +69,7 @@ export class AuthHandler {
69
69
  if (message.type !== PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE) {
70
70
  throw new Error('Invalid media type');
71
71
  }
72
+ authRequest.body.scope = authRequest.body.scope || [];
72
73
  return authRequest;
73
74
  }
74
75
  /**
@@ -180,7 +181,8 @@ export class AuthHandler {
180
181
  throw new Error(`sender of the request is not a target of response - expected ${request.from}, given ${response.to}`);
181
182
  }
182
183
  this.verifyAuthRequest(request);
183
- const requestScope = request.body.scope;
184
+ const requestScope = request.body.scope || [];
185
+ const responseScope = response.body.scope || [];
184
186
  if (!response.from) {
185
187
  throw new Error(`proof response doesn't contain from field`);
186
188
  }
@@ -188,7 +190,7 @@ export class AuthHandler {
188
190
  // group requests by query group id
189
191
  for (const proofRequest of requestScope) {
190
192
  const groupId = proofRequest.query.groupId;
191
- const proofResp = response.body.scope.find((resp) => resp.id === proofRequest.id);
193
+ const proofResp = responseScope.find((resp) => resp.id === proofRequest.id);
192
194
  if (!proofResp) {
193
195
  throw new Error(`proof is not given for requestId ${proofRequest.id}`);
194
196
  }
@@ -224,7 +226,7 @@ export class AuthHandler {
224
226
  }
225
227
  verifyAuthRequest(request) {
226
228
  const groupIdValidationMap = {};
227
- const requestScope = request.body.scope;
229
+ const requestScope = request.body.scope || [];
228
230
  for (const proofRequest of requestScope) {
229
231
  const groupId = proofRequest.query.groupId;
230
232
  if (groupId) {
@@ -1,7 +1,6 @@
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';
5
4
  /**
6
5
  *
7
6
  * Allows to process ContractInvokeRequest protocol message
@@ -41,6 +40,7 @@ export class ContractRequestHandler {
41
40
  if (message.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
42
41
  throw new Error('Invalid media type');
43
42
  }
43
+ ciRequest.body.scope = ciRequest.body.scope || [];
44
44
  return ciRequest;
45
45
  }
46
46
  /**
@@ -60,19 +60,11 @@ export class ContractRequestHandler {
60
60
  throw new Error("Can't sign transaction. Provide Signer in options.");
61
61
  }
62
62
  const zkRequests = [];
63
- const { contract_address, chain_id } = ciRequest.body.transaction_data;
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
- const [blockchain, networkId] = networkFlag.split(':');
69
- const verifierId = buildVerifierId(contract_address, {
70
- blockchain,
71
- networkId,
72
- // 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.
73
- method: DidMethod.Iden3
74
- });
75
- const verifierDid = DID.parseFromId(verifierId);
76
68
  for (const proofReq of ciRequest.body.scope) {
77
69
  if (!this._allowedCircuits.includes(proofReq.circuitId)) {
78
70
  throw new Error(`Can't handle circuit ${proofReq.circuitId}. Only onchain circuits are allowed.`);
@@ -81,7 +73,7 @@ export class ContractRequestHandler {
81
73
  const zkpRes = await this._proofService.generateProof(proofReq, did, {
82
74
  skipRevocation: query.skipClaimRevocationCheck ?? false,
83
75
  challenge: opts.challenge,
84
- verifierDid
76
+ verifierDid: ciRequest.from ? DID.parse(ciRequest.from) : undefined
85
77
  });
86
78
  zkRequests.push(zkpRes);
87
79
  }
@@ -1,5 +1,5 @@
1
1
  import { Hash, Proof, ZERO_HASH } from '@iden3/js-merkletree';
2
- import { buildTreeState, isValidOperation, QueryOperators } from '../circuits';
2
+ import { buildTreeState, isValidOperation, Operators, QueryOperators, XSDNS } from '../circuits';
3
3
  import { buildFieldPath, getSerializationAttrFromContext, getFieldSlotIndex } from '../verifiable';
4
4
  import { Merklizer, Path } from '@iden3/js-jsonld-merklization';
5
5
  import { byteEncoder } from '../utils';
@@ -84,16 +84,21 @@ export const parseCredentialSubject = (credentialSubject) => {
84
84
  return queries;
85
85
  };
86
86
  export const parseQueryMetadata = async (propertyQuery, ldContextJSON, credentialType, options) => {
87
- const datatype = await Path.newTypeFromContext(ldContextJSON, `${credentialType}.${propertyQuery.fieldName}`, options);
88
87
  const query = {
89
88
  ...propertyQuery,
90
89
  slotIndex: 0,
91
90
  merklizedSchema: false,
92
- datatype: datatype,
91
+ datatype: '',
93
92
  claimPathKey: BigInt(0),
94
93
  values: [],
95
94
  path: new Path()
96
95
  };
96
+ if (!propertyQuery.fieldName && propertyQuery.operator !== Operators.NOOP) {
97
+ throw new Error('query must have a field name if operator is not $noop');
98
+ }
99
+ if (propertyQuery.fieldName) {
100
+ query.datatype = await Path.newTypeFromContext(ldContextJSON, `${credentialType}.${propertyQuery.fieldName}`, options);
101
+ }
97
102
  const serAttr = await getSerializationAttrFromContext(JSON.parse(ldContextJSON), options, credentialType);
98
103
  if (!serAttr) {
99
104
  query.merklizedSchema = true;
@@ -115,9 +120,10 @@ export const parseQueryMetadata = async (propertyQuery, ldContextJSON, credentia
115
120
  }
116
121
  }
117
122
  if (propertyQuery.operatorValue) {
118
- if (!isValidOperation(datatype, propertyQuery.operator)) {
119
- throw new Error(`operator ${propertyQuery.operator} is not supported for datatype ${datatype}`);
123
+ if (!isValidOperation(query.datatype, propertyQuery.operator)) {
124
+ throw new Error(`operator ${propertyQuery.operator} is not supported for datatype ${query.datatype}`);
120
125
  }
126
+ const datatype = propertyQuery.operator === Operators.EXISTS ? XSDNS.Boolean : query.datatype;
121
127
  query.values = await transformQueryValueToBigInts(propertyQuery.operatorValue, datatype);
122
128
  }
123
129
  return query;
@@ -127,7 +133,7 @@ export const parseQueriesMetadata = async (credentialType, ldContextJSON, creden
127
133
  return Promise.all(queriesMetadata.map((m) => parseQueryMetadata(m, ldContextJSON, credentialType, options)));
128
134
  };
129
135
  export const transformQueryValueToBigInts = async (value, ldType) => {
130
- const values = new Array(64).fill(BigInt(0));
136
+ const values = [];
131
137
  if (Array.isArray(value)) {
132
138
  for (let index = 0; index < value.length; index++) {
133
139
  values[index] = await Merklizer.hashValue(ldType, value[index]);
@@ -1,6 +1,6 @@
1
1
  import { DID, Id, getUnixTimestamp } from '@iden3/js-iden3-core';
2
2
  import { ProofType } from '../../verifiable';
3
- import { AtomicQueryMTPV2Inputs, AtomicQueryMTPV2OnChainInputs, AtomicQuerySigV2Inputs, AtomicQuerySigV2OnChainInputs, AtomicQueryV3Inputs, AtomicQueryV3OnChainInputs, CircuitClaim, CircuitId, defaultValueArraySize, LinkedMultiQueryInputs, Operators, QueryOperators } from '../../circuits';
3
+ import { AtomicQueryMTPV2Inputs, AtomicQueryMTPV2OnChainInputs, AtomicQuerySigV2Inputs, AtomicQuerySigV2OnChainInputs, AtomicQueryV3Inputs, AtomicQueryV3OnChainInputs, CircuitClaim, CircuitId, LinkedMultiQueryInputs, Operators, QueryOperators, ValueProof } from '../../circuits';
4
4
  import { toClaimNonRevStatus, toGISTProof } from '../common';
5
5
  import { getUserDIDFromCredential } from '../../credentials';
6
6
  const allOperations = Object.values(QueryOperators);
@@ -202,10 +202,8 @@ export class InputGenerator {
202
202
  circuitInputs.profileNonce = BigInt(params.authProfileNonce);
203
203
  circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
204
204
  const query = circuitQueries[0];
205
- query.values =
206
- query.operator === Operators.SD || query.operator === Operators.NOOP
207
- ? new Array(defaultValueArraySize).fill(0)
208
- : query.values;
205
+ query.values = [Operators.SD, Operators.NOOP].includes(query.operator) ? [] : query.values;
206
+ query.valueProof = query.operator === Operators.NOOP ? new ValueProof() : query.valueProof;
209
207
  circuitInputs.query = query;
210
208
  circuitInputs.currentTimeStamp = getUnixTimestamp(new Date());
211
209
  circuitInputs.proofType = proofType;
@@ -253,10 +251,8 @@ export class InputGenerator {
253
251
  circuitInputs.profileNonce = BigInt(params.authProfileNonce);
254
252
  circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
255
253
  const query = circuitQueries[0];
256
- query.values =
257
- query.operator === Operators.SD || query.operator === Operators.NOOP
258
- ? new Array(defaultValueArraySize).fill(0)
259
- : query.values;
254
+ query.values = [Operators.SD, Operators.NOOP].includes(query.operator) ? [] : query.values;
255
+ query.valueProof = query.operator === Operators.NOOP ? new ValueProof() : query.valueProof;
260
256
  circuitInputs.query = query;
261
257
  circuitInputs.currentTimeStamp = getUnixTimestamp(new Date());
262
258
  circuitInputs.proofType = proofType;
@@ -272,7 +268,7 @@ export class InputGenerator {
272
268
  catch {
273
269
  isEthIdentity = false;
274
270
  }
275
- circuitInputs.authEnabled = isEthIdentity ? 0 : 1;
271
+ circuitInputs.isBJJAuthEnabled = isEthIdentity ? 0 : 1;
276
272
  circuitInputs.challenge = BigInt(params.challenge ?? 0);
277
273
  const { nonce: authProfileNonce, genesisDID } = await this._identityWallet.getGenesisDIDMetadata(identifier);
278
274
  const id = DID.idFromDID(genesisDID);
@@ -280,7 +276,7 @@ export class InputGenerator {
280
276
  const gistProof = toGISTProof(stateProof);
281
277
  circuitInputs.gistProof = gistProof;
282
278
  // auth inputs
283
- if (circuitInputs.authEnabled === 1) {
279
+ if (circuitInputs.isBJJAuthEnabled === 1) {
284
280
  const authPrepared = await this.prepareAuthBJJCredential(genesisDID);
285
281
  const authClaimData = await this.newCircuitClaimData({
286
282
  credential: authPrepared.credential,
@@ -1,2 +1,3 @@
1
1
  export * from './pub-signals-verifier';
2
2
  export * from './query';
3
+ export * from './query-hash';
@@ -1,17 +1,18 @@
1
- import { poseidon } from '@iden3/js-crypto';
2
1
  import { DID, getDateFromUnixTimestamp } from '@iden3/js-iden3-core';
3
2
  import { Path } from '@iden3/js-jsonld-merklization';
4
- import { bigIntCompare, byteEncoder, isGenesisState } from '../../utils';
5
- import { caclulateCoreSchemaHash, ProofType } from '../../verifiable';
3
+ import { byteEncoder, isGenesisState } from '../../utils';
4
+ import { calculateCoreSchemaHash, ProofType } from '../../verifiable';
6
5
  import { AtomicQueryMTPV2PubSignals } from '../../circuits/atomic-query-mtp-v2';
7
6
  import { AtomicQuerySigV2PubSignals } from '../../circuits/atomic-query-sig-v2';
8
7
  import { AtomicQueryV3PubSignals } from '../../circuits/atomic-query-v3';
9
8
  import { AuthV2PubSignals } from '../../circuits/auth-v2';
10
9
  import { BaseConfig } from '../../circuits/common';
11
- import { LinkedMultiQueryPubSignals } from '../../circuits/linked-multi-query';
10
+ import { LinkedMultiQueryPubSignals, LinkedMultiQueryInputs } from '../../circuits/linked-multi-query';
12
11
  import { CircuitId } from '../../circuits/models';
13
- import { checkQueryRequest } from './query';
12
+ import { checkQueryRequest, fieldValueFromVerifiablePresentation } from './query';
14
13
  import { parseQueriesMetadata } from '../common';
14
+ import { Operators } from '../../circuits';
15
+ import { calculateQueryHashV3 } from './query-hash';
15
16
  export const userStateError = new Error(`user state is not valid`);
16
17
  const zeroInt = 0n;
17
18
  const defaultProofVerifyOpts = 1 * 60 * 60 * 1000; // 1 hour
@@ -109,7 +110,6 @@ export class PubSignalsVerifier {
109
110
  timestamp: v3PubSignals.timestamp,
110
111
  merklized: v3PubSignals.merklized,
111
112
  claimPathKey: v3PubSignals.claimPathKey,
112
- claimPathNotExists: v3PubSignals.claimPathNotExists,
113
113
  valueArraySize: v3PubSignals.getValueArrSize(),
114
114
  isRevocationChecked: v3PubSignals.isRevocationChecked
115
115
  };
@@ -186,7 +186,7 @@ export class PubSignalsVerifier {
186
186
  this.verifyIdOwnership(sender, challenge);
187
187
  return new BaseConfig();
188
188
  };
189
- this.linkedMultiQuery10Verify = async ({ query, pubSignals }) => {
189
+ this.linkedMultiQuery10Verify = async ({ query, verifiablePresentation, pubSignals }) => {
190
190
  let multiQueryPubSignals = new LinkedMultiQueryPubSignals();
191
191
  multiQueryPubSignals = multiQueryPubSignals.pubSignalsUnmarshal(byteEncoder.encode(JSON.stringify(pubSignals)));
192
192
  // verify query
@@ -200,26 +200,41 @@ export class PubSignalsVerifier {
200
200
  }
201
201
  const ldContextJSON = JSON.stringify(schema);
202
202
  const credentialSubject = query.credentialSubject;
203
- const schemaId = await Path.getTypeIDFromContext(JSON.stringify(schema), query.type || '', ldOpts);
204
- const schemaHash = caclulateCoreSchemaHash(byteEncoder.encode(schemaId));
203
+ const schemaId = await Path.getTypeIDFromContext(ldContextJSON, query.type || '', ldOpts);
204
+ const schemaHash = calculateCoreSchemaHash(byteEncoder.encode(schemaId));
205
205
  const queriesMetadata = await parseQueriesMetadata(query.type || '', ldContextJSON, credentialSubject, ldOpts);
206
- const queryHashes = queriesMetadata.map((queryMeta) => {
207
- const valueHash = poseidon.spongeHashX(queryMeta.values, 6);
208
- return poseidon.hash([
209
- schemaHash.bigInt(),
210
- BigInt(queryMeta.slotIndex),
211
- BigInt(queryMeta.operator),
212
- BigInt(queryMeta.claimPathKey),
213
- queryMeta.merklizedSchema ? 0n : 1n,
214
- valueHash
215
- ]);
216
- });
217
- const circuitQueryHashes = multiQueryPubSignals.circuitQueryHash
218
- .filter((i) => i !== 0n)
219
- .sort(bigIntCompare);
220
- queryHashes.sort(bigIntCompare);
221
- if (!queryHashes.every((queryHash, i) => queryHash === circuitQueryHashes[i])) {
222
- throw new Error('query hashes do not match');
206
+ const request = [];
207
+ const merklized = queriesMetadata[0]?.merklizedSchema ? 1 : 0;
208
+ for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) {
209
+ const queryMeta = queriesMetadata[i];
210
+ const values = queryMeta?.values ?? [];
211
+ const valArrSize = values.length;
212
+ const queryHash = calculateQueryHashV3(values, schemaHash, queryMeta?.slotIndex ?? 0, queryMeta?.operator ?? 0, queryMeta?.claimPathKey.toString() ?? 0, valArrSize, merklized, 0, 0, 0);
213
+ request.push({ queryHash, queryMeta });
214
+ }
215
+ const queryHashCompare = (a, b) => {
216
+ if (a.queryHash < b.queryHash)
217
+ return -1;
218
+ if (a.queryHash > b.queryHash)
219
+ return 1;
220
+ return 0;
221
+ };
222
+ const pubSignalsMeta = multiQueryPubSignals.circuitQueryHash.map((queryHash, index) => ({
223
+ queryHash,
224
+ operatorOutput: multiQueryPubSignals.operatorOutput[index]
225
+ }));
226
+ pubSignalsMeta.sort(queryHashCompare);
227
+ request.sort(queryHashCompare);
228
+ for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) {
229
+ if (request[i].queryHash != pubSignalsMeta[i].queryHash) {
230
+ throw new Error('query hashes do not match');
231
+ }
232
+ if (request[i].queryMeta?.operator === Operators.SD) {
233
+ const disclosedValue = await fieldValueFromVerifiablePresentation(request[i].queryMeta.fieldName, verifiablePresentation, this._documentLoader);
234
+ if (disclosedValue != pubSignalsMeta[i].operatorOutput) {
235
+ throw new Error('disclosed value is not in the proof outputs');
236
+ }
237
+ }
223
238
  }
224
239
  return multiQueryPubSignals;
225
240
  };
@@ -0,0 +1,35 @@
1
+ import { poseidon } from '@iden3/js-crypto';
2
+ import { defaultValueArraySize, prepareCircuitArrayValues } from '../../circuits';
3
+ export function calculateQueryHashV2(values, schema, slotIndex, operator, claimPathKey, claimPathNotExists) {
4
+ const expValue = prepareCircuitArrayValues(values, 64);
5
+ const valueHash = poseidon.spongeHashX(expValue, 6);
6
+ return poseidon.hash([
7
+ schema.bigInt(),
8
+ BigInt(slotIndex),
9
+ BigInt(operator),
10
+ BigInt(claimPathKey),
11
+ BigInt(claimPathNotExists),
12
+ valueHash
13
+ ]);
14
+ }
15
+ export function calculateQueryHashV3(values, schema, slotIndex, operator, claimPathKey, valueArraySize, merklized, isRevocationChecked, verifierID, nullifierSessionID) {
16
+ const expValue = prepareCircuitArrayValues(values, defaultValueArraySize);
17
+ const valueHash = poseidon.spongeHashX(expValue, 6);
18
+ const firstPartQueryHash = poseidon.hash([
19
+ schema.bigInt(),
20
+ BigInt(slotIndex),
21
+ BigInt(operator),
22
+ BigInt(claimPathKey),
23
+ BigInt(merklized),
24
+ valueHash
25
+ ]);
26
+ const queryHash = poseidon.hash([
27
+ firstPartQueryHash,
28
+ BigInt(valueArraySize),
29
+ BigInt(isRevocationChecked),
30
+ BigInt(verifierID),
31
+ BigInt(nullifierSessionID),
32
+ 0n
33
+ ]);
34
+ return queryHash;
35
+ }
@@ -2,7 +2,7 @@ import { DID, getDateFromUnixTimestamp } from '@iden3/js-iden3-core';
2
2
  import { getDocumentLoader, Merklizer, Path } from '@iden3/js-jsonld-merklization';
3
3
  import { byteEncoder } from '../../utils';
4
4
  import { Operators } from '../../circuits/comparer';
5
- import { caclulateCoreSchemaHash, VerifiableConstants } from '../../verifiable';
5
+ import { calculateCoreSchemaHash, VerifiableConstants } from '../../verifiable';
6
6
  import { parseQueriesMetadata } from '../common';
7
7
  import { circuitValidator } from '../provers';
8
8
  const defaultProofGenerationDelayOpts = 24 * 60 * 60 * 1000; // 24 hours
@@ -29,7 +29,7 @@ export async function checkQueryRequest(query, outputs, circuitId, schemaLoader,
29
29
  const schemaId = await Path.getTypeIDFromContext(JSON.stringify(schema), query.type, {
30
30
  documentLoader: schemaLoader
31
31
  });
32
- const schemaHash = caclulateCoreSchemaHash(byteEncoder.encode(schemaId));
32
+ const schemaHash = calculateCoreSchemaHash(byteEncoder.encode(schemaId));
33
33
  if (schemaHash.bigInt() !== outputs.schemaHash.bigInt()) {
34
34
  throw new Error(`schema that was used is not equal to requested in query`);
35
35
  }
@@ -47,7 +47,8 @@ export async function checkQueryRequest(query, outputs, circuitId, schemaLoader,
47
47
  if (notSupportedOpIndx > -1) {
48
48
  throw new Error(`circuit ${circuitId} not support ${queriesMetadata[notSupportedOpIndx].operator} operator`);
49
49
  }
50
- queriesMetadata.forEach(async (metadata) => {
50
+ for (let i = 0; i < queriesMetadata.length; i++) {
51
+ const metadata = queriesMetadata[i];
51
52
  if (!query.type) {
52
53
  throw new Error(`proof query type is undefined`);
53
54
  }
@@ -100,7 +101,7 @@ export async function checkQueryRequest(query, outputs, circuitId, schemaLoader,
100
101
  if (timeDiff > acceptedProofGenerationDelay) {
101
102
  throw new Error('generated proof is outdated');
102
103
  }
103
- });
104
+ }
104
105
  return;
105
106
  }
106
107
  async function validateEmptyCredentialSubject(cq, outputs) {
@@ -129,14 +130,14 @@ async function validateOperators(cq, outputs) {
129
130
  }
130
131
  for (let index = 0; index < outputs.value.length; index++) {
131
132
  if (outputs.value[index] !== cq.values[index]) {
133
+ if (outputs.value[index] === 0n && cq.values[index] === undefined) {
134
+ continue;
135
+ }
132
136
  throw new Error(`comparison value that was used is not equal to requested in query`);
133
137
  }
134
138
  }
135
139
  }
136
140
  async function validateDisclosure(cq, outputs, verifiablePresentation, ldLoader) {
137
- if (!verifiablePresentation) {
138
- throw new Error(`verifiablePresentation is required for selective disclosure request`);
139
- }
140
141
  if (outputs.operator !== Operators.EQ) {
141
142
  throw new Error(`operator for selective disclosure must be $eq`);
142
143
  }
@@ -145,6 +146,15 @@ async function validateDisclosure(cq, outputs, verifiablePresentation, ldLoader)
145
146
  throw new Error(`selective disclosure not available for array of values`);
146
147
  }
147
148
  }
149
+ const bi = await fieldValueFromVerifiablePresentation(cq.fieldName, verifiablePresentation, ldLoader);
150
+ if (bi !== outputs.value[0]) {
151
+ throw new Error(`value that was used is not equal to requested in query`);
152
+ }
153
+ }
154
+ export const fieldValueFromVerifiablePresentation = async (fieldName, verifiablePresentation, ldLoader) => {
155
+ if (!verifiablePresentation) {
156
+ throw new Error(`verifiablePresentation is required for selective disclosure request`);
157
+ }
148
158
  let mz;
149
159
  const strVerifiablePresentation = JSON.stringify(verifiablePresentation);
150
160
  try {
@@ -157,13 +167,13 @@ async function validateDisclosure(cq, outputs, verifiablePresentation, ldLoader)
157
167
  }
158
168
  let merklizedPath;
159
169
  try {
160
- const p = `verifiableCredential.credentialSubject.${cq.fieldName}`;
170
+ const p = `verifiableCredential.credentialSubject.${fieldName}`;
161
171
  merklizedPath = await Path.fromDocument(null, strVerifiablePresentation, p, {
162
172
  documentLoader: ldLoader
163
173
  });
164
174
  }
165
175
  catch (e) {
166
- throw new Error(`can't build path to '${cq.fieldName}' key`);
176
+ throw new Error(`can't build path to '${fieldName}' key`);
167
177
  }
168
178
  let proof;
169
179
  let value;
@@ -171,16 +181,13 @@ async function validateDisclosure(cq, outputs, verifiablePresentation, ldLoader)
171
181
  ({ proof, value } = await mz.proof(merklizedPath));
172
182
  }
173
183
  catch (e) {
174
- throw new Error(`can't get value by path '${cq.fieldName}'`);
184
+ throw new Error(`can't get value by path '${fieldName}'`);
175
185
  }
176
186
  if (!value) {
177
- throw new Error(`can't get merkle value for field '${cq.fieldName}'`);
187
+ throw new Error(`can't get merkle value for field '${fieldName}'`);
178
188
  }
179
189
  if (!proof.existence) {
180
190
  throw new Error(`path [${merklizedPath.parts}] doesn't exist in verifiablePresentation document`);
181
191
  }
182
- const bi = await value.mtEntry();
183
- if (bi !== outputs.value[0]) {
184
- throw new Error(`value that was used is not equal to requested in query`);
185
- }
186
- }
192
+ return await value.mtEntry();
193
+ };
@@ -1,5 +1,5 @@
1
1
  import { BytesHelper, checkBigIntInField } from '@iden3/js-iden3-core';
2
- import { caclulateCoreSchemaHash, fillCoreClaimSlot } from '../verifiable';
2
+ import { calculateCoreSchemaHash, fillCoreClaimSlot } from '../verifiable';
3
3
  /**
4
4
  * SwapEndianness swaps the endianness of the value encoded in buf. If buf is
5
5
  * Big-Endian, the result will be Little-Endian and vice-versa.
@@ -48,14 +48,14 @@ export function checkDataInField(data) {
48
48
  }
49
49
  /**
50
50
  *
51
- * @deprecated The method should not be used. Use caclulateCoreSchemaHash from verifiable.
51
+ * @deprecated The method should not be used. Use calculateCoreSchemaHash from verifiable.
52
52
  * Calculates schema hash
53
53
  *
54
54
  * @param {Uint8Array} schemaId
55
55
  * @returns {*} {SchemaHash}
56
56
  */
57
57
  export const createSchemaHash = (schemaId) => {
58
- return caclulateCoreSchemaHash(schemaId);
58
+ return calculateCoreSchemaHash(schemaId);
59
59
  };
60
60
  /**
61
61
  *