Skip to content

Query Language

The Atomic Query Signature and Atomic Query MTP Circuits have been designed as generic circuits to do ZK verification based on user's claims.

The Query language sits on top of these circuits to provide a way for developers to design customised requirements based on someone's claims.

Platforms can implement queries for user authentication/verification in a flexible way using the Query Language operators, for example:

  • Must be an admin inside PolygonDAO to vote for a specific proposal - equals
  • Must have been born before 2000-01-01 to access an adult content website - less-than
  • Must have a monthly salary greater than $1000 to get a loan - greater-than
  • Must have one game item across a list of items to enter a tournament - ìn
  • Must not be resident of one country inside a list of countries to operate on an exchange - not-in

Starting from the proof generated by the user, the verifier is easily able to check if the query is satisfied or not. The verifier doesn't get access to any user's data.

As long as the user has been issued a claim that contain certain information, the verifier can design a specific query related to the claim based on these 5 operators.

The data structure of the claim described below is simplified. More details about the actual claim strucutre can be found here

Equals

Claim

PolygonDAOMember {
  "role": "5" // 5 corresponds to Dao Admin. Each role has a code associated
} 

Query

const proofRequest: protocol.ZKPRequest = {
   id: 1,
   circuit_id: 'credentialAtomicQuerySig',
   rules: {
     query: {
       allowedIssuers: ['11A4eeoCN7Xdy5FZSd3BDxUS9yeA7FGGCCmpKPNhNP'], // ID of the trusted issuer
       schema: {
         type: 'PolygonDAOMember',
         url: 'https://schema.polygonid.com/jsonld/dao.json-ld',
       },
       req: {
         role: {
           $eq: 5, // the role must be 5 = Group Admin
         },
       },
     },
   },
 };

Less-than

Claim

AgeCredential {
  "birthDay": "19701230" //yymmdd
} 

Query

const proofRequest: protocol.ZKPRequest = {
   id: 1,
   circuit_id: 'credentialAtomicQuerySig',
   rules: {
     query: {
       allowedIssuers: ['113T3p9mwkNbRwsREgBwdjMdNJehAW5p6HcJSBpPjQ', '111DLXZwaj5Ag4hBneVgfb8FAy5EiyxjSkayVpqKj'], // ID of the trusted issuers
       schema: {
         type: 'AgeCredential',
         url: 'https://schema.polygonid.com/jsonld/kyc.json-ld',
       },
       req: {
         birthDay: {
           $lt: 20000101, // birthDay field less then 2000/01/01
         },
       },
     },
   },
 };

Greater-than

Claim

EmployeeData {
  "monthlySalary": "1650", //denominated in $$
  "employedSince": "20151230"
} 

Query

const proofRequest: protocol.ZKPRequest = {
   id: 1,
   circuit_id: 'credentialAtomicQuerySig',
   rules: {
     query: {
       allowedIssuers: ['*'],
       schema: {
         type: 'EmployeeData',
         url: 'https://schema.com/...employeedata',
       },
       req: {
         monthlySalary: {
           $gt: 1000, // monthlySalary must be over $1000
         },
       },
     },
   },
 };

Schema type yet to be defined

In

Claim

UserGameItems {
  "item": "52", // 52 identifies a specific in-game item
}

Query

const proofRequest: protocol.ZKPRequest = {
   id: 1,
   circuit_id: 'credentialAtomicQuerySig',
   rules: {
     query: {
       allowedIssuers: ['*'],
       schema: {
         type: 'UserGameItems',
         url: 'https://schema.com/...usergameitems',
       },
       req: {
         item: {
           $in: [47, 52, 112, 145], // accept users that have an item included in the list
         },
       },
     },
   },
 };

Schema type yet to be defined

Not-in

Claim

CountryOfResidenceCredential {
  "countryCode": "840"
} 

Query

const proofRequest: protocol.ZKPRequest = {
   id: 1,
   circuit_id: 'credentialAtomicQuerySig',
   rules: {
     query: {
       allowedIssuers: ['11BL1tHEwMR1tuCERfnaYbw4m5QPf45PKfFKZTL2Ep'], // ID of the trusted issuer
       schema: {
         type: 'CountryOfResidenceCredential',
         url: 'https://schema.polygonid.com/jsonld/kyc.json-ld',
       },
       req: {
         countryCode: {
           $nin: [840, 120, 340, 509], // accepted any country not in the list 
         },
       },
     },
   },
 };

To add a operator-based query inside a proof request is not mandatory. For instance, a platform can just ask the user to have an AgeCredential claim as a way to identity unique humans without any requirements on the date of birth. In that case the veriifer should simply not fill the req field inside the proofRequest