@0xpolygonid/js-sdk 1.8.3 → 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.
- package/dist/browser/esm/index.js +234 -121
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +237 -121
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/circuits/atomic-query-v3-on-chain.js +8 -25
- package/dist/node/cjs/circuits/atomic-query-v3.js +6 -5
- package/dist/node/cjs/circuits/common.js +1 -1
- package/dist/node/cjs/circuits/comparer.js +24 -3
- package/dist/node/cjs/circuits/linked-multi-query.js +6 -17
- package/dist/node/cjs/circuits/models.js +47 -3
- package/dist/node/cjs/iden3comm/handlers/contract-request.js +2 -11
- package/dist/node/cjs/proof/common.js +11 -5
- package/dist/node/cjs/proof/provers/inputs-generator.js +6 -10
- package/dist/node/cjs/proof/verifiers/index.js +1 -0
- package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +37 -22
- package/dist/node/cjs/proof/verifiers/query-hash.js +40 -0
- package/dist/node/cjs/proof/verifiers/query.js +24 -16
- package/dist/node/cjs/schema-processor/utils.js +2 -2
- package/dist/node/cjs/storage/filters/jsonQuery.js +28 -2
- package/dist/node/cjs/verifiable/core-utils.js +3 -3
- package/dist/node/cjs/verifiable/credential.js +1 -1
- package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +9 -26
- package/dist/node/esm/circuits/atomic-query-v3.js +7 -6
- package/dist/node/esm/circuits/common.js +1 -1
- package/dist/node/esm/circuits/comparer.js +24 -3
- package/dist/node/esm/circuits/linked-multi-query.js +7 -18
- package/dist/node/esm/circuits/models.js +48 -4
- package/dist/node/esm/iden3comm/handlers/contract-request.js +3 -12
- package/dist/node/esm/proof/common.js +12 -6
- package/dist/node/esm/proof/provers/inputs-generator.js +7 -11
- package/dist/node/esm/proof/verifiers/index.js +1 -0
- package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +41 -26
- package/dist/node/esm/proof/verifiers/query-hash.js +35 -0
- package/dist/node/esm/proof/verifiers/query.js +23 -16
- package/dist/node/esm/schema-processor/utils.js +3 -3
- package/dist/node/esm/storage/filters/jsonQuery.js +28 -2
- package/dist/node/esm/verifiable/core-utils.js +1 -1
- package/dist/node/esm/verifiable/credential.js +2 -2
- package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +4 -8
- package/dist/types/circuits/atomic-query-v3.d.ts +2 -2
- package/dist/types/circuits/common.d.ts +1 -1
- package/dist/types/circuits/comparer.d.ts +4 -0
- package/dist/types/circuits/linked-multi-query.d.ts +0 -1
- package/dist/types/circuits/models.d.ts +7 -4
- package/dist/types/iden3comm/types/protocol/contract-request.d.ts +1 -0
- package/dist/types/proof/verifiers/index.d.ts +1 -0
- package/dist/types/proof/verifiers/query-hash.d.ts +3 -0
- package/dist/types/proof/verifiers/query.d.ts +1 -0
- package/dist/types/schema-processor/utils.d.ts +1 -1
- package/dist/types/storage/filters/jsonQuery.d.ts +1 -1
- package/dist/types/verifiable/core-utils.d.ts +1 -1
- package/package.json +1 -1
|
@@ -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.
|
|
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.
|
|
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.
|
|
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
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CircuitId } from '../../circuits/models';
|
|
2
2
|
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
|
|
3
|
-
import { DID, ChainIds
|
|
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
|
|
@@ -61,19 +60,11 @@ export class ContractRequestHandler {
|
|
|
61
60
|
throw new Error("Can't sign transaction. Provide Signer in options.");
|
|
62
61
|
}
|
|
63
62
|
const zkRequests = [];
|
|
64
|
-
const {
|
|
63
|
+
const { chain_id } = ciRequest.body.transaction_data;
|
|
65
64
|
const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
|
|
66
65
|
if (!networkFlag) {
|
|
67
66
|
throw new Error(`Invalid chain id ${chain_id}`);
|
|
68
67
|
}
|
|
69
|
-
const [blockchain, networkId] = networkFlag.split(':');
|
|
70
|
-
const verifierId = buildVerifierId(contract_address, {
|
|
71
|
-
blockchain,
|
|
72
|
-
networkId,
|
|
73
|
-
// DidMethod.Iden3 is used based on discussions: all onchain issuers have iden3 did method by default. This can be changed in the release of v3 circuit.
|
|
74
|
-
method: DidMethod.Iden3
|
|
75
|
-
});
|
|
76
|
-
const verifierDid = DID.parseFromId(verifierId);
|
|
77
68
|
for (const proofReq of ciRequest.body.scope) {
|
|
78
69
|
if (!this._allowedCircuits.includes(proofReq.circuitId)) {
|
|
79
70
|
throw new Error(`Can't handle circuit ${proofReq.circuitId}. Only onchain circuits are allowed.`);
|
|
@@ -82,7 +73,7 @@ export class ContractRequestHandler {
|
|
|
82
73
|
const zkpRes = await this._proofService.generateProof(proofReq, did, {
|
|
83
74
|
skipRevocation: query.skipClaimRevocationCheck ?? false,
|
|
84
75
|
challenge: opts.challenge,
|
|
85
|
-
verifierDid
|
|
76
|
+
verifierDid: ciRequest.from ? DID.parse(ciRequest.from) : undefined
|
|
86
77
|
});
|
|
87
78
|
zkRequests.push(zkpRes);
|
|
88
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:
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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,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 {
|
|
5
|
-
import {
|
|
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(
|
|
204
|
-
const schemaHash =
|
|
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
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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 {
|
|
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 =
|
|
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.
|
|
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.${
|
|
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 '${
|
|
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 '${
|
|
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 '${
|
|
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
|
-
|
|
183
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
138
|
-
nullifierSessionID: bigint;
|
|
139
|
-
authEnabled: number;
|
|
135
|
+
isBJJAuthEnabled: number;
|
|
140
136
|
pubSignalsUnmarshal(data: Uint8Array): AtomicQueryV3OnChainPubSignals;
|
|
141
137
|
}
|
|
142
138
|
export {};
|