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.
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.
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.
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>", // replace with your contract address
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/0xPolygonID/tutorial-examples/main/credential-schema/schemas-examples/proof-of-humanity/proof-of-humanity.jsonld",
"credentialSubject": {
"isHuman": {
"$eq": 1
}
},
"type": "ProofOfHumanity"
}
}
]
}
}
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.
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"birthday": {
"$lt": 20010101
}
},
"type": "KYCAgeCredential"
}
}
]
}
}
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.
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code**
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/0xPolygonID/tutorial-examples/main/credential-schema/schemas-examples/employee-data/employee-data.jsonld",
"credentialSubject": {
"monthlySalary": {
"$gt": 1000
}
},
"type": "EmployeeData"
}
}
]
}
}
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).
- off-chain
- on-chain
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],
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"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]
}
},
"type": "ProofOfDaoRole"
}
}
]
}
}
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.
- off-chain
- on-chain
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],
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"countryCode": {
"$nin": [840, 120, 340, 509]
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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.
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"countryCode": {
"$ne": 840
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"birthday": {
"$lte": 20010101
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"birthday": {
"$gte": 20010101
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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
- off-chain
- on-chain
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],
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"birthday": {
"$between": [19960101, 20010101]
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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
- off-chain
- on-chain
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],
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"birthday": {
"$nonbetween": [19960101, 20010101]
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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
.
- off-chain
- on-chain
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,
},
},
},
};
Please, check out our Onchain verification tutorial to build a query to learn more how to set zk request for onchain
Corresponding QR Code
{
"id": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"typ": "application/iden3comm-plain-json",
"type": "https://iden3-communication.io/proofs/1.0/contract-invoke-request",
"thid": "7f38a193-0918-4a48-9fac-36adfdb8b542",
"body": {
"reason": "airdrop participation",
"transaction_data": {
"contract address": "<add your contract address here>",
"method_id": "b68967e2",
"chain_id": 80002,
"network": "polygon-amoy"
},
"scope": [
{
"id": 1,
"circuitId": "credentialAtomicQuerySigV2OnChain",
"query": {
"allowedIssuers": ["*"],
"context": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld",
"credentialSubject": {
"countryCode": {
"$exists": true
}
},
"type": "KYCCountryOfResidenceCredential"
}
}
]
}
}
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]
}
}
}
}
]
}
}
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 *
.