Skip to main content

ZK Query Language

The Atomic Query Signature V2 Circuit and Atomic Query MTP V2 Circuit circuits have been designed as generic circuits to do the ZK verification based on users' claims.

The Query Language sits on top of these circuits to provide a simple way for developers to design customized authentication requirements for someone's credentials. As long as the user holds a credential of a specific type, the Verifier can design a query based on 6 operators, for example:

  • Must be a verified human to vote for a DAO specific proposal - equals (operator 1).
  • Must have been born before 2000-01-01 to access a specific website - less-than (operator 2).
  • Must have a monthly salary greater than $1000 to get a loan - greater-than (operator 3).
  • Must be an admin or a hacker of a DAO to enter a platform - in (operator 4).
  • Must not be a resident of a country in the list of blacklisted countries to operate on an exchange - not-in (operator 5).
  • Must not be a resident of a specific country - not-equal (operator 6).

The Atomic Query Signature V3 Circuit circuit is designed to support more operators:

  • Must have been born before or exactly at 2000-01-01 to access a specific website - less-than-equal (operator 7).
  • Must have a monthly salary greater than or equal $1000 to get a loan - greater-than-equal (operator 8).
  • Must be in range - between (operator 9).
  • Must not be in range - non between (operator 10).
  • Field must or must not exist in the credential - exists (operator 11).

The query is designed by the Verifier and presented to the user via a QR Code (or deep-linking). Starting from the proof generated by the user as a response to the query, the Verifier is easily able to check if the query is satisfied or not.

The Query Language follows the same rules whether the verification is implemented on-chain or off-chain, while the syntax to define these is a bit different. For each of the queries presented above, both the on-chain and off-chain way of designing will now be defined.

note

The entire scripts to set a query are available here: off-chain verification, on-chain verification

Equals - Operator 1

Credential Schema

The ProofOfHumanity Schema encodes whether a user has been verified as a human or not. Here's the JSON-LD Context of the Schema Type.

info

You can create customized schemas, check out this tutorial!

Query

When presented with this query, the user must prove that he/she is a Person.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "ProofOfHumanity",
context:
"https://raw.githubusercontent.com/0xPolygonID/tutorial-examples/main/credential-schema/schemas-examples/proof-of-humanity/proof-of-humanity.jsonld",
credentialSubject: {
isHuman: {
$eq: 1
}
}
}
};

Less-than - Operator 2

Credential Schema

The KYCAgeCredential Schema encodes the date of birth of the credential subject. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she has been born before 2001/01/01.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCAgeCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
birthday: {
$lt: 20010101
}
}
}
};

Greater-than - Operator 3

Credential Schema

The EmployeeData Schema encodes the monthly salary of the credential subject. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that his/her monthly salary is greater than $1000.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "EmployeeData",
context:
"https://raw.githubusercontent.com/0xPolygonID/tutorial-examples/main/credential-schema/schemas-examples/employee-data/employee-data.jsonld",
credentialSubject: {
monthlySalary: {
$gt: 1000
}
}
}
};

In - Operator 4

Credential Schema

The ProofOfDaoRole Schema encodes the role of someone inside a DAO. Each role is identified by a code as described in the Schema Vocab.

Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she is either an Admin or a Hacker of a DAO (which corresponds to values 4 and 5).

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "ProofOfDaoRole",
context:
"https://raw.githubusercontent.com/0xPolygonID/tutorial-examples/main/credential-schema/schemas-examples/proof-of-dao-role/proof-of-dao-role.jsonld",
credentialSubject: {
role: {
$in: [4, 5]
}
}
}
};

Not-in - Operator 5

Credential Schema

The KYCCountryOfResidenceCredential Schema encodes the countryCode of residence of the credential subject according to the ISO Standard. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she is not a resident of the countries 840, 120, 340, 509 identified by the ISO Standard.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context: "https://github.com/iden3/claim-schema-vocab/blob/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
countryCode: {
$nin: [840, 120, 340, 509],
}
}
}
};

Not-equal - Operator 6

Credential Schema

The KYCCountryOfResidenceCredential Schema encodes the countryCode of residence of the credential subject according to the ISO Standard. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she is not a resident of the country 840 identified by the ISO Standard.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
countryCode: {
$ne: 840
}
}
}
};
info

Operators 7-11 are supported only by V3 circuit

Less-than-equal - Operator 7

Credential Schema

The KYCCountryOfResidenceCredential Schema encodes the countryCode of residence of the credential subject according to the ISO Standard. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she has been born before or including 2001/01/01

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
birthday: {
$lte: 20010101
}
}
}
};

Greater-than-equal - Operator 8

Credential Schema

The KYCCountryOfResidenceCredential Schema encodes the countryCode of residence of the credential subject according to the ISO Standard. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she has been born after or including 2001/01/01

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
birthday: {
$gte: 20010101
}
}
}
};

Between - Operator 9

Credential Schema

The KYCCountryOfResidenceCredential Schema encodes the countryCode of residence of the credential subject according to the ISO Standard. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she has been born before 2001/01/01, but after 1996/01/01

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
birthday: {
$between: [19960101, 20010101]
}
}
}
};

Non-between - Operator 10

Credential Schema

The KYCCountryOfResidenceCredential Schema encodes the countryCode of residence of the credential subject according to the ISO Standard. Here's the JSON-LD Context of the Schema Type.

Query

When presented with this query, the user must prove that he/she has been born not after 1996/01/01 and and not till 2001/01/01

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
birthday: {
$nonbetween: [19960101, 20010101]
}
}
}
};

Exists - Operator 11

Credential Schema

Credential schema can have optional fields, so W3C Verifiable Credential can / can not have a specific field.

Query

When presented with this query, the user must prove that document field exists / does not exists in the credential. Possible values for $exists operator are true and false.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
countryCode: {
$exists: true
}
}
}
};

Proof of credential issuance ($noop)

By not including the credentialSubject in the query, a verifier requests proof of the presence of a credential in the user's wallet without requiring any condition to be met or revealing any specific detail about the credential.

Query

In the example below, the verifier doesn't include credential subject.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld"
}
};

Selective Disclosure

Selective Disclosure is a feature that enables requests for specific data from the ID Holder. Using a similar approach to the ZK language equal operation, the Verifier sends a verification request for a piece of the Holder's identity. As seen below, the way to make this request is by sending an empty object as a value.

Query

In the example below, the verifier requests the Holder's country code.

const proofRequest: protocol.ZKPRequest = {
id: 1,
circuitId: "credentialAtomicQuerySigV2",
query: {
allowedIssuers: ["*"],
type: "KYCCountryOfResidenceCredential",
context:
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
credentialSubject: {
countryCode: {}
}
}
};

Multi query

In the example below, the verifier requests two different proof queries in the single authorization request. Queries can be created for different credentials.

{
"id": "f8aee09d-f592-4fcc-8d2a-8938aa26676c",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/authorization/1.0/request",
"thid": "f8aee09d-f592-4fcc-8d2a-8938aa26676c",
"from": "did:polygonid:polygon:amoy:2qFroxB5kwgCxgVrNGUM6EW3khJgCdHHnKTr3VnTcp",
"body": {
"callbackUrl": "https://test.com/callback",
"reason": "age verification",
"message": "test message",
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v101.json-ld",
"type": "KYCEmployee",
"credentialSubject": {
"position": {
"$eq": "developer"
}
}
}
},
{
"id": 2,
"circuitId": "credentialAtomicQuerySigV2",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v101.json-ld",
"type": "KYCCountryOfResidenceCredential",
"credentialSubject": {
"countryCode": {
"$in": [980, 340]
}
}
}
}
]
}
}
"Allowed Issuers"

When we use * in the "allowed issuers" segment (allowedIssuers: ['*']), we mean that we accept any entity that might have provided the credential. Even though this seems to be convenient for testing purposes, it may also be considered risky. Applying due diligence by actually choosing trusted specific issuers should be the best approach. Only in rare cases, a verifier would accept any issuer, so we advise not to use *.