@0xpolygonid/js-sdk 1.5.1 → 1.6.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 (83) hide show
  1. package/dist/browser/esm/index.js +1685 -468
  2. package/dist/browser/esm/index.js.map +1 -1
  3. package/dist/browser/umd/index.js +1703 -470
  4. package/dist/browser/umd/index.js.map +1 -1
  5. package/dist/node/cjs/circuits/atomic-query-mtp-v2-on-chain.js +1 -1
  6. package/dist/node/cjs/circuits/atomic-query-mtp-v2.js +1 -1
  7. package/dist/node/cjs/circuits/atomic-query-sig-v2-on-chain.js +2 -2
  8. package/dist/node/cjs/circuits/atomic-query-sig-v2.js +11 -14
  9. package/dist/node/cjs/circuits/atomic-query-v3-on-chain.js +320 -0
  10. package/dist/node/cjs/circuits/atomic-query-v3.js +275 -0
  11. package/dist/node/cjs/circuits/common.js +5 -7
  12. package/dist/node/cjs/circuits/comparer.js +57 -2
  13. package/dist/node/cjs/circuits/index.js +4 -0
  14. package/dist/node/cjs/circuits/linked-multi-query.js +128 -0
  15. package/dist/node/cjs/circuits/linked-nullifier.js +57 -0
  16. package/dist/node/cjs/circuits/models.js +25 -1
  17. package/dist/node/cjs/credentials/credential-wallet.js +2 -10
  18. package/dist/node/cjs/credentials/index.js +1 -0
  19. package/dist/node/cjs/credentials/utils.js +23 -0
  20. package/dist/node/cjs/iden3comm/handlers/auth.js +49 -8
  21. package/dist/node/cjs/iden3comm/handlers/contract-request.js +20 -8
  22. package/dist/node/cjs/proof/common.js +104 -1
  23. package/dist/node/cjs/proof/inputs-generator.js +393 -0
  24. package/dist/node/cjs/proof/proof-service.js +105 -372
  25. package/dist/node/cjs/schema-processor/json/parser.js +7 -0
  26. package/dist/node/cjs/schema-processor/json/validator.js +1 -0
  27. package/dist/node/cjs/storage/filters/jsonQuery.js +73 -8
  28. package/dist/node/cjs/utils/did-helper.js +14 -0
  29. package/dist/node/cjs/utils/index.js +2 -0
  30. package/dist/node/cjs/utils/object.js +42 -0
  31. package/dist/node/cjs/verifiable/presentation.js +34 -33
  32. package/dist/node/cjs/verifiable/proof.js +2 -0
  33. package/dist/node/esm/circuits/atomic-query-mtp-v2-on-chain.js +1 -1
  34. package/dist/node/esm/circuits/atomic-query-mtp-v2.js +1 -1
  35. package/dist/node/esm/circuits/atomic-query-sig-v2-on-chain.js +2 -2
  36. package/dist/node/esm/circuits/atomic-query-sig-v2.js +11 -14
  37. package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +315 -0
  38. package/dist/node/esm/circuits/atomic-query-v3.js +270 -0
  39. package/dist/node/esm/circuits/common.js +4 -6
  40. package/dist/node/esm/circuits/comparer.js +55 -1
  41. package/dist/node/esm/circuits/index.js +4 -0
  42. package/dist/node/esm/circuits/linked-multi-query.js +123 -0
  43. package/dist/node/esm/circuits/linked-nullifier.js +52 -0
  44. package/dist/node/esm/circuits/models.js +25 -1
  45. package/dist/node/esm/credentials/credential-wallet.js +2 -10
  46. package/dist/node/esm/credentials/index.js +1 -0
  47. package/dist/node/esm/credentials/utils.js +19 -0
  48. package/dist/node/esm/iden3comm/handlers/auth.js +50 -9
  49. package/dist/node/esm/iden3comm/handlers/contract-request.js +20 -8
  50. package/dist/node/esm/proof/common.js +101 -2
  51. package/dist/node/esm/proof/inputs-generator.js +389 -0
  52. package/dist/node/esm/proof/proof-service.js +111 -377
  53. package/dist/node/esm/schema-processor/json/parser.js +7 -0
  54. package/dist/node/esm/schema-processor/json/validator.js +1 -0
  55. package/dist/node/esm/storage/filters/jsonQuery.js +74 -9
  56. package/dist/node/esm/utils/did-helper.js +10 -0
  57. package/dist/node/esm/utils/index.js +2 -0
  58. package/dist/node/esm/utils/object.js +38 -0
  59. package/dist/node/esm/verifiable/presentation.js +30 -29
  60. package/dist/node/esm/verifiable/proof.js +2 -0
  61. package/dist/types/circuits/atomic-query-mtp-v2.d.ts +13 -13
  62. package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +142 -0
  63. package/dist/types/circuits/atomic-query-v3.d.ts +120 -0
  64. package/dist/types/circuits/common.d.ts +4 -4
  65. package/dist/types/circuits/comparer.d.ts +33 -1
  66. package/dist/types/circuits/index.d.ts +4 -0
  67. package/dist/types/circuits/linked-multi-query.d.ts +38 -0
  68. package/dist/types/circuits/linked-nullifier.d.ts +37 -0
  69. package/dist/types/circuits/models.d.ts +20 -2
  70. package/dist/types/credentials/index.d.ts +1 -0
  71. package/dist/types/credentials/utils.d.ts +12 -0
  72. package/dist/types/iden3comm/types/packer.d.ts +1 -2
  73. package/dist/types/iden3comm/types/protocol/auth.d.ts +1 -0
  74. package/dist/types/proof/common.d.ts +34 -3
  75. package/dist/types/proof/inputs-generator.d.ts +46 -0
  76. package/dist/types/proof/proof-service.d.ts +14 -25
  77. package/dist/types/schema-processor/json/parser.d.ts +1 -0
  78. package/dist/types/storage/filters/jsonQuery.d.ts +1 -1
  79. package/dist/types/utils/did-helper.d.ts +6 -0
  80. package/dist/types/utils/index.d.ts +2 -0
  81. package/dist/types/utils/object.d.ts +12 -0
  82. package/dist/types/verifiable/presentation.d.ts +6 -10
  83. package/package.json +1 -1
@@ -4,6 +4,10 @@ export * from './comparer';
4
4
  export * from './atomic-query-mtp-v2';
5
5
  export * from './atomic-query-mtp-v2-on-chain';
6
6
  export * from './atomic-query-sig-v2';
7
+ export * from './atomic-query-v3';
8
+ export * from './atomic-query-v3-on-chain';
7
9
  export * from './atomic-query-sig-v2-on-chain';
8
10
  export * from './auth-v2';
9
11
  export * from './state-transition';
12
+ export * from './linked-nullifier';
13
+ export * from './linked-multi-query';
@@ -0,0 +1,123 @@
1
+ import { byteDecoder, byteEncoder } from '../utils';
2
+ import { BaseConfig, bigIntArrayToStringArray, existenceToInt, getNodeAuxValue, prepareCircuitArrayValues, prepareSiblingsStr } from './common';
3
+ /**
4
+ * LinkedMultiQuery circuit representation
5
+ * Inputs and public signals declaration, marshalling and parsing
6
+ *
7
+ * @beta
8
+ * @class LinkedMultiQueryInputs
9
+ */
10
+ export class LinkedMultiQueryInputs extends BaseConfig {
11
+ // InputsMarshal returns Circom private inputs for linkedMultiQueryInputs.circom
12
+ inputsMarshal() {
13
+ const enabled = [];
14
+ const claimPathNotExists = [];
15
+ const claimPathMtp = [];
16
+ const claimPathMtpNoAux = [];
17
+ const claimPathMtpAuxHi = [];
18
+ const claimPathMtpAuxHv = [];
19
+ const claimPathKey = [];
20
+ const claimPathValue = [];
21
+ const slotIndex = [];
22
+ const operator = [];
23
+ const value = [];
24
+ for (let i = 0; i < this.queryLength; i++) {
25
+ if (!this.query) {
26
+ enabled.push(0);
27
+ claimPathNotExists.push(0);
28
+ claimPathMtp.push([]);
29
+ claimPathMtpNoAux.push('0');
30
+ claimPathMtpAuxHi.push('0');
31
+ claimPathMtpAuxHv.push('0');
32
+ claimPathKey.push('0');
33
+ claimPathValue.push('0');
34
+ slotIndex.push(0);
35
+ operator.push(0);
36
+ const valuesArr = prepareCircuitArrayValues([], this.getValueArrSize());
37
+ value.push(bigIntArrayToStringArray(valuesArr));
38
+ continue;
39
+ }
40
+ enabled.push(1);
41
+ const valueProof = this.query[i].valueProof;
42
+ claimPathNotExists.push(existenceToInt(valueProof.mtp.existence));
43
+ claimPathMtp.push(prepareSiblingsStr(valueProof.mtp, this.getMTLevelsClaim()));
44
+ const nodAuxJSONLD = getNodeAuxValue(valueProof.mtp);
45
+ claimPathMtpNoAux.push(nodAuxJSONLD.noAux);
46
+ claimPathMtpAuxHi.push(nodAuxJSONLD.key.bigInt().toString());
47
+ claimPathMtpAuxHv.push(nodAuxJSONLD.value.bigInt().toString());
48
+ claimPathKey.push(valueProof.path.toString());
49
+ claimPathValue.push(valueProof.value.toString());
50
+ slotIndex.push(this.query[i].slotIndex);
51
+ operator.push(this.query[i].operator);
52
+ const valuesArr = prepareCircuitArrayValues(this.query[i].values, this.getValueArrSize());
53
+ value.push(bigIntArrayToStringArray(valuesArr));
54
+ }
55
+ const s = {
56
+ linkNonce: this.linkNonce.toString(),
57
+ issuerClaim: this.claim.marshalJson(),
58
+ enabled,
59
+ claimSchema: this.claim.getSchemaHash().bigInt().toString(),
60
+ claimPathNotExists,
61
+ claimPathMtp,
62
+ claimPathMtpNoAux,
63
+ claimPathMtpAuxHi,
64
+ claimPathMtpAuxHv,
65
+ claimPathKey,
66
+ claimPathValue,
67
+ slotIndex,
68
+ operator,
69
+ value
70
+ };
71
+ return byteEncoder.encode(JSON.stringify(s));
72
+ }
73
+ }
74
+ // LinkedMultiQueryPubSignals linkedMultiQuery.circom public signals
75
+ /**
76
+ * public signals
77
+ *
78
+ * @beta
79
+ * @class LinkedMultiQueryPubSignals
80
+ */
81
+ export class LinkedMultiQueryPubSignals {
82
+ /**
83
+ * PubSignalsUnmarshal unmarshal linkedMultiQuery.circom public inputs to LinkedMultiQueryPubSignals
84
+ *
85
+ * @beta
86
+ * @param {Uint8Array} data
87
+ * @returns LinkedMultiQueryPubSignals
88
+ */
89
+ pubSignalsUnmarshal(data, queryLength) {
90
+ const len = queryLength * 3 + 2;
91
+ const sVals = JSON.parse(byteDecoder.decode(data));
92
+ if (sVals.length !== len) {
93
+ throw new Error(`invalid number of Output values expected ${len} got ${sVals.length}`);
94
+ }
95
+ let fieldIdx = 0;
96
+ // -- linkID
97
+ this.linkID = BigInt(sVals[fieldIdx]);
98
+ fieldIdx++;
99
+ // -- merklized
100
+ this.merklized = parseInt(sVals[fieldIdx]);
101
+ fieldIdx++;
102
+ // - operatorOutput
103
+ this.operatorOutput = [];
104
+ for (let i = 0; i < queryLength; i++) {
105
+ this.operatorOutput.push(BigInt(sVals[fieldIdx]));
106
+ fieldIdx++;
107
+ }
108
+ // - circuitQueryHash
109
+ this.circuitQueryHash = [];
110
+ for (let i = 0; i < queryLength; i++) {
111
+ this.circuitQueryHash.push(BigInt(sVals[fieldIdx]));
112
+ fieldIdx++;
113
+ }
114
+ // - enabled
115
+ this.enabled = [];
116
+ for (let i = 0; i < queryLength; i++) {
117
+ const enabledNum = parseInt(sVals[fieldIdx]);
118
+ this.enabled.push(enabledNum === 1);
119
+ fieldIdx++;
120
+ }
121
+ return this;
122
+ }
123
+ }
@@ -0,0 +1,52 @@
1
+ import { Id } from '@iden3/js-iden3-core';
2
+ import { byteDecoder, byteEncoder } from '../utils';
3
+ /**
4
+ * LinkedNullifier circuit representation
5
+ * Inputs and public signals declaration, marshalling and parsing
6
+ *
7
+ * @beta
8
+ * @class LinkedNullifierInputs
9
+ */
10
+ export class LinkedNullifierInputs {
11
+ // InputsMarshal returns Circom private inputs for nullifier.circom
12
+ inputsMarshal() {
13
+ const s = {
14
+ linkNonce: this.linkNonce.toString(),
15
+ issuerClaim: this.issuerClaim.marshalJson(),
16
+ userGenesisID: this.id.bigInt().toString(),
17
+ claimSubjectProfileNonce: this.claimSubjectProfileNonce.toString(),
18
+ claimSchema: this.issuerClaim.getSchemaHash().bigInt().toString(),
19
+ verifierID: this.verifierID?.bigInt().toString() ?? '0',
20
+ nullifierSessionID: this.nullifierSessionID.toString()
21
+ };
22
+ return byteEncoder.encode(JSON.stringify(s));
23
+ }
24
+ }
25
+ // LinkedNullifierPubSignals nullifier.circom public signals
26
+ /**
27
+ * public signals
28
+ *
29
+ * @beta
30
+ * @class LinkedNullifierPubSignals
31
+ */
32
+ export class LinkedNullifierPubSignals {
33
+ /**
34
+ * PubSignalsUnmarshal unmarshal nullifier.circom public inputs to LinkedNullifierPubSignals
35
+ *
36
+ * @beta
37
+ * @param {Uint8Array} data
38
+ * @returns LinkedNullifierPubSignals
39
+ */
40
+ pubSignalsUnmarshal(data) {
41
+ const len = 4;
42
+ const sVals = JSON.parse(byteDecoder.decode(data));
43
+ if (sVals.length !== len) {
44
+ throw new Error(`invalid number of Output values expected ${len} got ${sVals.length}`);
45
+ }
46
+ this.nullifier = BigInt(sVals[0]);
47
+ this.linkID = BigInt(sVals[1]);
48
+ this.verifierID = Id.fromBigInt(BigInt(sVals[2]));
49
+ this.nullifierSessionID = BigInt(sVals[3]);
50
+ return this;
51
+ }
52
+ }
@@ -12,7 +12,9 @@ export class Query {
12
12
  *
13
13
  */
14
14
  validate() {
15
- if (this.operator !== QueryOperators.$noop && this.values?.some((v) => typeof v !== 'bigint'))
15
+ if (this.operator !== QueryOperators.$noop &&
16
+ this.operator !== QueryOperators.$sd &&
17
+ this.values?.some((v) => typeof v !== 'bigint'))
16
18
  throw new Error(CircuitError.EmptyQueryValue);
17
19
  }
18
20
  }
@@ -35,6 +37,26 @@ export var CircuitId;
35
37
  CircuitId["AtomicQuerySigV2"] = "credentialAtomicQuerySigV2";
36
38
  // AtomicQuerySigOnChain is a type for credentialAtomicQuerySigOnChain.circom
37
39
  CircuitId["AtomicQuerySigV2OnChain"] = "credentialAtomicQuerySigV2OnChain";
40
+ /**
41
+ * @beta
42
+ */
43
+ // AtomicQueryV3CircuitID is a type for credentialAtomicQueryV3.circom
44
+ CircuitId["AtomicQueryV3"] = "credentialAtomicQueryV3-beta.0";
45
+ /**
46
+ * @beta
47
+ */
48
+ // AtomicQueryV3OnChainCircuitID is a type for credentialAtomicQueryV3OnChain.circom
49
+ CircuitId["AtomicQueryV3OnChain"] = "credentialAtomicQueryV3OnChain-beta.0";
50
+ /**
51
+ * @beta
52
+ */
53
+ // LinkedNullifier is a type for linkedNullifier.circom
54
+ CircuitId["LinkedNullifier"] = "linkedNullifier-beta.0";
55
+ /**
56
+ * @beta
57
+ */
58
+ // LinkedMultiQuery is a type for linkedMultiQuery.circom
59
+ CircuitId["LinkedMultiQuery10"] = "linkedMultiQuery10-beta.0";
38
60
  })(CircuitId || (CircuitId = {}));
39
61
  /**
40
62
  * Claim structure for circuit inputs
@@ -68,7 +90,9 @@ export var CircuitError;
68
90
  CircuitError["EmptyId"] = "empty Id";
69
91
  CircuitError["EmptyChallenge"] = "empty challenge";
70
92
  CircuitError["EmptyGISTProof"] = "empty GIST merkle tree proof";
93
+ CircuitError["EmptyTreeState"] = "empty tree state";
71
94
  CircuitError["EmptyRequestID"] = "empty request ID";
95
+ CircuitError["InvalidProofType"] = "invalid proof type";
72
96
  })(CircuitError || (CircuitError = {}));
73
97
  /**
74
98
  * ValueProof represents a Merkle Proof for a value stored as MT
@@ -4,6 +4,7 @@ import * as uuid from 'uuid';
4
4
  import { CredentialStatusResolverRegistry } from './status/resolver';
5
5
  import { IssuerResolver } from './status/sparse-merkle-tree';
6
6
  import { AgentResolver } from './status/agent-revocation';
7
+ import { getUserDIDFromCredential } from './utils';
7
8
  // ErrAllClaimsRevoked all claims are revoked.
8
9
  const ErrAllClaimsRevoked = 'all claims are revoked';
9
10
  /**
@@ -99,16 +100,7 @@ export class CredentialWallet {
99
100
  ? mtpProof.issuerData.state
100
101
  : sigProof?.issuerData.state;
101
102
  const issuerDID = DID.parse(cred.issuer);
102
- let userDID;
103
- if (!cred.credentialSubject.id) {
104
- userDID = issuerDID;
105
- }
106
- else {
107
- if (typeof cred.credentialSubject.id !== 'string') {
108
- throw new Error('credential status `id` is not a string');
109
- }
110
- userDID = DID.parse(cred.credentialSubject.id);
111
- }
103
+ const userDID = getUserDIDFromCredential(issuerDID, cred);
112
104
  const opts = {
113
105
  issuerGenesisState: stateInfo,
114
106
  issuerDID,
@@ -6,3 +6,4 @@ export * from './status/agent-revocation';
6
6
  export * from './status/utils';
7
7
  export * from './credential-wallet';
8
8
  export * from './rhs';
9
+ export * from './utils';
@@ -0,0 +1,19 @@
1
+ import { DID } from '@iden3/js-iden3-core';
2
+ /**
3
+ * Retrieves the user DID from a given credential.
4
+ * If the credential does not have a credentialSubject.id property, the issuer DID is returned.
5
+ * If the credentialSubject.id is not a string, an error is thrown.
6
+ * @param issuerDID The DID of the issuer.
7
+ * @param credential The credential object.
8
+ * @returns The user DID parsed from the credential.
9
+ * @throws Error if the credentialSubject.id is not a string.
10
+ */
11
+ export const getUserDIDFromCredential = (issuerDID, credential) => {
12
+ if (!credential.credentialSubject.id) {
13
+ return issuerDID;
14
+ }
15
+ if (typeof credential.credentialSubject.id !== 'string') {
16
+ throw new Error('credential subject `id` is not a string');
17
+ }
18
+ return DID.parse(credential.credentialSubject.id);
19
+ };
@@ -3,7 +3,8 @@ 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 } from '../../utils';
6
+ import { byteDecoder, byteEncoder, mergeObjects } from '../../utils';
7
+ import { getRandomBytes } from '@iden3/js-crypto';
7
8
  /**
8
9
  *
9
10
  * Allows to process AuthorizationRequest protocol message and produce JWZ response.
@@ -79,15 +80,55 @@ export class AuthHandler {
79
80
  from: did.string(),
80
81
  to: authRequest.from
81
82
  };
82
- for (const proofReq of authRequest.body.scope) {
83
- const zkpReq = {
84
- id: proofReq.id,
85
- circuitId: proofReq.circuitId,
86
- query: proofReq.query
87
- };
83
+ const requestScope = authRequest.body.scope;
84
+ const combinedQueries = requestScope.reduce((acc, proofReq) => {
85
+ const groupId = proofReq.query.groupId;
86
+ if (!groupId) {
87
+ return acc;
88
+ }
89
+ const existedData = acc.get(groupId);
90
+ if (!existedData) {
91
+ const seed = getRandomBytes(12);
92
+ const dataView = new DataView(seed.buffer);
93
+ const linkNonce = dataView.getUint32(0);
94
+ acc.set(groupId, { query: proofReq.query, linkNonce });
95
+ return acc;
96
+ }
97
+ const credentialSubject = mergeObjects(existedData.query.credentialSubject, proofReq.query.credentialSubject);
98
+ acc.set(groupId, {
99
+ ...existedData,
100
+ query: {
101
+ skipClaimRevocationCheck: existedData.query.skipClaimRevocationCheck || proofReq.query.skipClaimRevocationCheck,
102
+ ...existedData.query,
103
+ credentialSubject
104
+ }
105
+ });
106
+ return acc;
107
+ }, new Map());
108
+ const groupedCredentialsCache = new Map();
109
+ for (const proofReq of requestScope) {
88
110
  const query = proofReq.query;
89
- const zkpRes = await this._proofService.generateProof(zkpReq, did, {
90
- skipRevocation: query.skipClaimRevocationCheck ?? false
111
+ const groupId = query.groupId;
112
+ const combinedQueryData = combinedQueries.get(groupId);
113
+ if (groupId) {
114
+ if (!combinedQueryData) {
115
+ throw new Error(`Invalid group id ${query.groupId}`);
116
+ }
117
+ const combinedQuery = combinedQueryData.query;
118
+ if (!groupedCredentialsCache.has(groupId)) {
119
+ const credWithRevStatus = await this._proofService.findCredentialByProofQuery(did, combinedQueryData.query);
120
+ if (!credWithRevStatus.cred) {
121
+ throw new Error(`Credential not found for query ${JSON.stringify(combinedQuery)}`);
122
+ }
123
+ groupedCredentialsCache.set(groupId, credWithRevStatus);
124
+ }
125
+ }
126
+ const credWithRevStatus = groupedCredentialsCache.get(groupId);
127
+ const zkpRes = await this._proofService.generateProof(proofReq, did, {
128
+ skipRevocation: Boolean(query.skipClaimRevocationCheck),
129
+ credential: credWithRevStatus?.cred,
130
+ credentialRevocationStatus: credWithRevStatus?.revStatus,
131
+ linkNonce: combinedQueryData?.linkNonce ? BigInt(combinedQueryData.linkNonce) : undefined
91
132
  });
92
133
  authResponse.body.scope.push(zkpRes);
93
134
  }
@@ -1,5 +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
5
  /**
4
6
  *
5
7
  * Allows to process ContractInvokeRequest protocol message
@@ -23,7 +25,8 @@ export class ContractRequestHandler {
23
25
  this._zkpVerifier = _zkpVerifier;
24
26
  this._allowedCircuits = [
25
27
  CircuitId.AtomicQueryMTPV2OnChain,
26
- CircuitId.AtomicQuerySigV2OnChain
28
+ CircuitId.AtomicQuerySigV2OnChain,
29
+ CircuitId.AtomicQueryV3OnChain
27
30
  ];
28
31
  }
29
32
  /**
@@ -57,19 +60,28 @@ export class ContractRequestHandler {
57
60
  throw new Error("Can't sign transaction. Provide Signer in options.");
58
61
  }
59
62
  const zkRequests = [];
63
+ const { contract_address, chain_id } = ciRequest.body.transaction_data;
64
+ const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
65
+ if (!networkFlag) {
66
+ throw new Error(`Invalid chain id ${chain_id}`);
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);
60
76
  for (const proofReq of ciRequest.body.scope) {
61
77
  if (!this._allowedCircuits.includes(proofReq.circuitId)) {
62
78
  throw new Error(`Can't handle circuit ${proofReq.circuitId}. Only onchain circuits are allowed.`);
63
79
  }
64
- const zkpReq = {
65
- id: proofReq.id,
66
- circuitId: proofReq.circuitId,
67
- query: proofReq.query
68
- };
69
80
  const query = proofReq.query;
70
- const zkpRes = await this._proofService.generateProof(zkpReq, did, {
81
+ const zkpRes = await this._proofService.generateProof(proofReq, did, {
71
82
  skipRevocation: query.skipClaimRevocationCheck ?? false,
72
- challenge: opts.challenge
83
+ challenge: opts.challenge,
84
+ verifierDid
73
85
  });
74
86
  zkRequests.push(zkpRes);
75
87
  }
@@ -1,5 +1,10 @@
1
- import { Hash, Proof } from '@iden3/js-merkletree';
2
- import { buildTreeState } from '../circuits';
1
+ import { Hash, Proof, ZERO_HASH } from '@iden3/js-merkletree';
2
+ import { buildTreeState, isValidOperation, QueryOperators } from '../circuits';
3
+ import { buildFieldPath } from '../verifiable';
4
+ import { Merklizer, Path } from '@iden3/js-jsonld-merklization';
5
+ import { Parser } from '../schema-processor/json';
6
+ import { byteEncoder } from '../utils';
7
+ import { poseidon } from '@iden3/js-crypto';
3
8
  /**
4
9
  * converts verifiable RevocationStatus model to circuits structure
5
10
  *
@@ -7,6 +12,18 @@ import { buildTreeState } from '../circuits';
7
12
  * @returns {ClaimNonRevStatus}
8
13
  */
9
14
  export const toClaimNonRevStatus = (s) => {
15
+ if (!s) {
16
+ const hash = poseidon.hash(new Array(3).fill(0n));
17
+ return {
18
+ proof: new Proof(),
19
+ treeState: {
20
+ state: Hash.fromBigInt(hash),
21
+ claimsRoot: ZERO_HASH,
22
+ revocationRoot: ZERO_HASH,
23
+ rootOfRoots: ZERO_HASH
24
+ }
25
+ };
26
+ }
10
27
  return {
11
28
  proof: s.mtp,
12
29
  treeState: buildTreeState(s.issuer.state, s.issuer.claimsTreeRoot, s.issuer.revocationTreeRoot, s.issuer.rootOfRoots)
@@ -40,3 +57,85 @@ export const toGISTProof = (smtProof) => {
40
57
  proof
41
58
  };
42
59
  };
60
+ export const parseCredentialSubject = (credentialSubject) => {
61
+ // credentialSubject is empty
62
+ if (!credentialSubject) {
63
+ return [{ operator: QueryOperators.$eq, fieldName: '' }];
64
+ }
65
+ const queries = [];
66
+ const entries = Object.entries(credentialSubject);
67
+ if (!entries.length) {
68
+ throw new Error(`query must have at least 1 predicate`);
69
+ }
70
+ for (const [fieldName, fieldReq] of entries) {
71
+ const fieldReqEntries = Object.entries(fieldReq);
72
+ const isSelectiveDisclosure = fieldReqEntries.length === 0;
73
+ if (isSelectiveDisclosure) {
74
+ queries.push({ operator: QueryOperators.$sd, fieldName: fieldName });
75
+ continue;
76
+ }
77
+ for (const [operatorName, operatorValue] of fieldReqEntries) {
78
+ if (!QueryOperators[operatorName]) {
79
+ throw new Error(`operator is not supported by lib`);
80
+ }
81
+ const operator = QueryOperators[operatorName];
82
+ queries.push({ operator, fieldName, operatorValue });
83
+ }
84
+ }
85
+ return queries;
86
+ };
87
+ export const parseQueryMetadata = async (propertyQuery, ldContextJSON, credentialType, options) => {
88
+ const datatype = await Path.newTypeFromContext(ldContextJSON, `${credentialType}.${propertyQuery.fieldName}`, options);
89
+ const query = {
90
+ ...propertyQuery,
91
+ slotIndex: 0,
92
+ merklizedSchema: false,
93
+ datatype: datatype,
94
+ claimPathKey: BigInt(0),
95
+ values: [],
96
+ path: new Path()
97
+ };
98
+ const serAttr = await Parser.getSerializationAttrFromContext(JSON.parse(ldContextJSON), options, credentialType);
99
+ if (!serAttr) {
100
+ query.merklizedSchema = true;
101
+ }
102
+ // for merklized credentials slotIndex in query must be equal to zero
103
+ // and not a position of merklization root.
104
+ // it has no influence on check in the off-chain circuits, but it aligns with onchain verification standard
105
+ if (!query.merklizedSchema) {
106
+ query.slotIndex = await Parser.getFieldSlotIndex(propertyQuery.fieldName, credentialType, byteEncoder.encode(ldContextJSON));
107
+ }
108
+ else {
109
+ try {
110
+ const path = await buildFieldPath(ldContextJSON, credentialType, propertyQuery.fieldName, options);
111
+ query.claimPathKey = await path.mtEntry();
112
+ query.path = path;
113
+ }
114
+ catch (e) {
115
+ throw new Error(`field does not exist in the schema ${e.message}`);
116
+ }
117
+ }
118
+ if (propertyQuery.operatorValue) {
119
+ if (!isValidOperation(datatype, propertyQuery.operator)) {
120
+ throw new Error(`operator ${propertyQuery.operator} is not supported for datatype ${datatype}`);
121
+ }
122
+ query.values = await transformQueryValueToBigInts(propertyQuery.operatorValue, datatype);
123
+ }
124
+ return query;
125
+ };
126
+ export const parseQueriesMetadata = async (credentialType, ldContextJSON, credentialSubject, options) => {
127
+ const queriesMetadata = parseCredentialSubject(credentialSubject);
128
+ return Promise.all(queriesMetadata.map((m) => parseQueryMetadata(m, ldContextJSON, credentialType, options)));
129
+ };
130
+ export const transformQueryValueToBigInts = async (value, ldType) => {
131
+ const values = new Array(64).fill(BigInt(0));
132
+ if (Array.isArray(value)) {
133
+ for (let index = 0; index < value.length; index++) {
134
+ values[index] = await Merklizer.hashValue(ldType, value[index]);
135
+ }
136
+ }
137
+ else {
138
+ values[0] = await Merklizer.hashValue(ldType, value);
139
+ }
140
+ return values;
141
+ };