@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
@@ -2,3 +2,5 @@ export * from './auth';
2
2
  export * from './fetch';
3
3
  export * from './contract-request';
4
4
  export * from './refresh';
5
+ export * from './revocation-status';
6
+ export * from './common';
@@ -0,0 +1,92 @@
1
+ import { PROTOCOL_MESSAGE_TYPE } from '../constants';
2
+ import { MediaType } from '../constants';
3
+ import { DID } from '@iden3/js-iden3-core';
4
+ import * as uuid from 'uuid';
5
+ import { byteEncoder } from '../../utils';
6
+ import { proving } from '@iden3/js-jwz';
7
+ /**
8
+ *
9
+ * Allows to process RevocationStatusRequest protocol message
10
+ *
11
+
12
+ * @class RevocationStatusHandler
13
+ * @implements implements IRevocationStatusHandler interface
14
+ */
15
+ export class RevocationStatusHandler {
16
+ /**
17
+ * Creates an instance of RevocationStatusHandler.
18
+ * @param {IPackageManager} _packerMgr - package manager to unpack message envelope
19
+ * @param {IIdentityWallet} _identityWallet - identity wallet
20
+ *
21
+ */
22
+ constructor(_packerMgr, _identityWallet) {
23
+ this._packerMgr = _packerMgr;
24
+ this._identityWallet = _identityWallet;
25
+ }
26
+ /**
27
+ * @inheritdoc IRevocationStatusHandler#parseRevocationStatusRequest
28
+ */
29
+ async parseRevocationStatusRequest(request) {
30
+ const { unpackedMessage: message } = await this._packerMgr.unpack(request);
31
+ const ciRequest = message;
32
+ if (message.type !== PROTOCOL_MESSAGE_TYPE.REVOCATION_STATUS_REQUEST_MESSAGE_TYPE) {
33
+ throw new Error('Invalid media type');
34
+ }
35
+ return ciRequest;
36
+ }
37
+ /**
38
+ * @inheritdoc IRevocationStatusHandler#handleRevocationStatusRequest
39
+ */
40
+ async handleRevocationStatusRequest(did, request, opts) {
41
+ if (!opts) {
42
+ opts = {
43
+ mediaType: MediaType.PlainMessage
44
+ };
45
+ }
46
+ if (opts.mediaType === MediaType.SignedMessage && !opts.packerOptions) {
47
+ throw new Error(`jws packer options are required for ${MediaType.SignedMessage}`);
48
+ }
49
+ const rsRequest = await this.parseRevocationStatusRequest(request);
50
+ if (!rsRequest.to) {
51
+ throw new Error(`failed request. empty 'to' field`);
52
+ }
53
+ if (!rsRequest.from) {
54
+ throw new Error(`failed request. empty 'from' field`);
55
+ }
56
+ if (!rsRequest.body?.revocation_nonce) {
57
+ throw new Error(`failed request. empty 'revocation_nonce' field`);
58
+ }
59
+ const issuerDID = DID.parse(rsRequest.to);
60
+ const mtpWithTreeState = await this._identityWallet.generateNonRevocationMtpWithNonce(issuerDID, BigInt(rsRequest.body.revocation_nonce), opts?.treeState);
61
+ const treeState = mtpWithTreeState.treeState;
62
+ const revStatus = {
63
+ issuer: {
64
+ state: treeState?.state.string(),
65
+ claimsTreeRoot: treeState.claimsRoot.string(),
66
+ revocationTreeRoot: treeState.revocationRoot.string(),
67
+ rootOfRoots: treeState.rootOfRoots.string()
68
+ },
69
+ mtp: mtpWithTreeState.proof
70
+ };
71
+ const packerOpts = opts.mediaType === MediaType.SignedMessage
72
+ ? opts.packerOptions
73
+ : {
74
+ provingMethodAlg: proving.provingMethodGroth16AuthV2Instance.methodAlg
75
+ };
76
+ const senderDID = DID.parse(rsRequest.to);
77
+ const guid = uuid.v4();
78
+ const response = {
79
+ id: guid,
80
+ typ: MediaType.PlainMessage,
81
+ type: PROTOCOL_MESSAGE_TYPE.REVOCATION_STATUS_RESPONSE_MESSAGE_TYPE,
82
+ thid: rsRequest.thid ?? guid,
83
+ body: revStatus,
84
+ from: did.string(),
85
+ to: rsRequest.from
86
+ };
87
+ return this._packerMgr.pack(opts.mediaType, byteEncoder.encode(JSON.stringify(response)), {
88
+ senderDID,
89
+ ...packerOpts
90
+ });
91
+ }
92
+ }
@@ -227,6 +227,10 @@ export class IdentityWallet {
227
227
  async generateNonRevocationMtp(did, credential, treeState) {
228
228
  const coreClaim = await this.getCoreClaimFromCredential(credential);
229
229
  const revNonce = coreClaim.getRevocationNonce();
230
+ return this.generateNonRevocationMtpWithNonce(did, revNonce, treeState);
231
+ }
232
+ /** {@inheritDoc IIdentityWallet.generateNonRevocationMtpWithNonce} */
233
+ async generateNonRevocationMtpWithNonce(did, revNonce, treeState) {
230
234
  const treesModel = await this.getDIDTreeModel(did);
231
235
  const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), MerkleTreeType.Revocations);
232
236
  const claimsRoot = await treesModel.claimsTree.root();
@@ -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
  *
@@ -66,6 +66,19 @@ const lessThanOrEqual = (a, b) => {
66
66
  }
67
67
  return a <= b;
68
68
  };
69
+ // a - field value
70
+ // b - true / false (exists operator values)
71
+ const existsComparator = (a, b) => {
72
+ if (truthyValues.includes(b) && typeof a !== 'undefined') {
73
+ // if exists val is true , a field val exists
74
+ return true;
75
+ }
76
+ // if exists val is false , a field val doesn't exist
77
+ if (falsyValues.includes(b) && (a === undefined || (Array.isArray(a) && !a.length))) {
78
+ return true;
79
+ }
80
+ return false;
81
+ };
69
82
  const inOperator = (a, b) => {
70
83
  if (Array.isArray(a) && Array.isArray(b)) {
71
84
  return a.every((val) => b.includes(val));
@@ -78,9 +91,19 @@ const inOperator = (a, b) => {
78
91
  }
79
92
  return false;
80
93
  };
94
+ const betweenOperator = (a, b) => {
95
+ if (!Array.isArray(b) || b.length !== 2) {
96
+ throw new Error('$between/$nonbetween operator value should be 2 elements array');
97
+ }
98
+ if (Array.isArray(a)) {
99
+ return a.every((val) => val >= b[0] && val <= b[1]);
100
+ }
101
+ return a >= b[0] && a <= b[1];
102
+ };
81
103
  export const comparatorOptions = {
82
104
  $noop: () => true,
83
105
  $sd: () => true,
106
+ $exists: (a, b) => existsComparator(a, b),
84
107
  $eq: (a, b) => equalsComparator(a, b),
85
108
  $in: (a, b) => inOperator(a, b),
86
109
  $nin: (a, b) => !inOperator(a, b),
@@ -88,7 +111,9 @@ export const comparatorOptions = {
88
111
  $lt: (a, b) => !greaterThan(a, b),
89
112
  $ne: (a, b) => !equalsComparator(a, b),
90
113
  $gte: (a, b) => greaterThanOrEqual(a, b),
91
- $lte: (a, b) => lessThanOrEqual(a, b)
114
+ $lte: (a, b) => lessThanOrEqual(a, b),
115
+ $between: (a, b) => betweenOperator(a, b),
116
+ $nonbetween: (a, b) => !betweenOperator(a, b)
92
117
  };
93
118
  /**
94
119
  * credential search path resolver
@@ -136,7 +161,8 @@ export class FilterQuery {
136
161
  throw new Error(SearchError.NotDefinedComparator);
137
162
  }
138
163
  const credentialPathValue = resolvePath(credential, this.path);
139
- if (credentialPathValue === null || credentialPathValue === undefined) {
164
+ if ((credentialPathValue === null || credentialPathValue === undefined) &&
165
+ this.operatorFunc !== existsComparator) {
140
166
  return false;
141
167
  }
142
168
  if (this.isReverseParams) {
@@ -194,7 +194,7 @@ export const parseCoreClaimSlots = async (ldCtx, mz, credentialType) => {
194
194
  * @param {Uint8Array} schemaId
195
195
  * @returns {*} {SchemaHash}
196
196
  */
197
- export const caclulateCoreSchemaHash = (schemaId) => {
197
+ export const calculateCoreSchemaHash = (schemaId) => {
198
198
  const sHash = Hex.decodeString(keccak256(schemaId));
199
199
  return new SchemaHash(sHash.slice(sHash.length - 16, sHash.length));
200
200
  };
@@ -7,7 +7,7 @@ import { PublicKey, poseidon } from '@iden3/js-crypto';
7
7
  import { getUserDIDFromCredential } from '../credentials/utils';
8
8
  import { byteEncoder, validateDIDDocumentAuth } from '../utils';
9
9
  import { MerklizedRootPosition, ProofType, SubjectPosition } from './constants';
10
- import { caclulateCoreSchemaHash, findCredentialType, parseCoreClaimSlots } from './core-utils';
10
+ import { calculateCoreSchemaHash, findCredentialType, parseCoreClaimSlots } from './core-utils';
11
11
  import * as jsonld from 'jsonld/lib';
12
12
  import * as ldcontext from 'jsonld/lib/context';
13
13
  /**
@@ -119,7 +119,7 @@ export class W3CCredential {
119
119
  if (!nonMerklized && opts.merklizedRootPosition === MerklizedRootPosition.None) {
120
120
  opts.merklizedRootPosition = MerklizedRootPosition.Index;
121
121
  }
122
- const schemaHash = caclulateCoreSchemaHash(byteEncoder.encode(credentialType));
122
+ const schemaHash = calculateCoreSchemaHash(byteEncoder.encode(credentialType));
123
123
  const claim = Claim.newClaim(schemaHash, ClaimOptions.withIndexDataBytes(slots.indexA, slots.indexB), ClaimOptions.withValueDataBytes(slots.valueA, slots.valueB), ClaimOptions.withRevocationNonce(BigInt(opts.revNonce)), ClaimOptions.withVersion(opts.version));
124
124
  if (opts.updatable) {
125
125
  claim.setFlagUpdatable(opts.updatable);
@@ -32,7 +32,7 @@ export declare class AtomicQueryV3OnChainInputs extends BaseConfig {
32
32
  linkNonce: bigint;
33
33
  verifierID?: Id;
34
34
  nullifierSessionID: bigint;
35
- authEnabled: number;
35
+ isBJJAuthEnabled: number;
36
36
  validate(): void;
37
37
  fillMTPProofsWithZero(s: Partial<AtomicQueryV3OnChainCircuitInputs>): void;
38
38
  fillSigProofWithZero(s: Partial<AtomicQueryV3OnChainCircuitInputs>): void;
@@ -73,7 +73,6 @@ interface AtomicQueryV3OnChainCircuitInputs {
73
73
  issuerAuthRootsTreeRoot: string;
74
74
  issuerAuthState: string;
75
75
  isRevocationChecked: number;
76
- claimPathNotExists: number;
77
76
  claimPathMtp: string[];
78
77
  claimPathMtpNoAux: string;
79
78
  claimPathMtpAuxHi: string;
@@ -84,6 +83,7 @@ interface AtomicQueryV3OnChainCircuitInputs {
84
83
  slotIndex: number;
85
84
  timestamp: number;
86
85
  value: string[];
86
+ valueArraySize: number;
87
87
  issuerClaimMtp: string[];
88
88
  issuerClaimClaimsTreeRoot: string;
89
89
  issuerClaimRevTreeRoot: string;
@@ -112,7 +112,7 @@ interface AtomicQueryV3OnChainCircuitInputs {
112
112
  linkNonce: string;
113
113
  verifierID: string;
114
114
  nullifierSessionID: string;
115
- authEnabled: string;
115
+ isBJJAuthEnabled: string;
116
116
  }
117
117
  /**
118
118
  * @beta
@@ -125,8 +125,6 @@ export declare class AtomicQueryV3OnChainPubSignals extends BaseConfig {
125
125
  issuerState: Hash;
126
126
  issuerClaimNonRevState: Hash;
127
127
  timestamp: number;
128
- merklized: number;
129
- isRevocationChecked: number;
130
128
  circuitQueryHash: bigint;
131
129
  challenge: bigint;
132
130
  gistRoot: Hash;
@@ -134,9 +132,7 @@ export declare class AtomicQueryV3OnChainPubSignals extends BaseConfig {
134
132
  linkID: bigint;
135
133
  nullifier: bigint;
136
134
  operatorOutput: bigint;
137
- verifierID: Id;
138
- nullifierSessionID: bigint;
139
- authEnabled: number;
135
+ isBJJAuthEnabled: number;
140
136
  pubSignalsUnmarshal(data: Uint8Array): AtomicQueryV3OnChainPubSignals;
141
137
  }
142
138
  export {};
@@ -69,7 +69,6 @@ interface AtomicQueryV3CircuitInputs {
69
69
  issuerAuthRootsTreeRoot: string;
70
70
  issuerAuthState: string;
71
71
  isRevocationChecked: number;
72
- claimPathNotExists: number;
73
72
  claimPathMtp: string[];
74
73
  claimPathMtpNoAux: string;
75
74
  claimPathMtpAuxHi: string;
@@ -80,6 +79,7 @@ interface AtomicQueryV3CircuitInputs {
80
79
  slotIndex: number;
81
80
  timestamp: number;
82
81
  value: string[];
82
+ valueArraySize: number;
83
83
  issuerClaimMtp: string[];
84
84
  issuerClaimClaimsTreeRoot: string;
85
85
  issuerClaimRevTreeRoot: string;
@@ -104,10 +104,10 @@ export declare class AtomicQueryV3PubSignals extends BaseConfig {
104
104
  slotIndex: number;
105
105
  operator: number;
106
106
  value: bigint[];
107
+ valueArraySize: number;
107
108
  timestamp: number;
108
109
  merklized: number;
109
110
  claimPathKey: bigint;
110
- claimPathNotExists: number;
111
111
  isRevocationChecked: number;
112
112
  proofType: number;
113
113
  linkID: bigint;