diff --git a/package-lock.json b/package-lock.json index af04649..abcf83b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@iden3/js-iden3-auth", - "version": "1.1.1", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@iden3/js-iden3-auth", - "version": "1.1.1", + "version": "1.2.0", "license": "AGPL-3.0", "dependencies": { "@0xpolygonid/js-sdk": "../js-sdk", diff --git a/package.json b/package.json index c576a59..7456687 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@iden3/js-iden3-auth", - "version": "1.1.1", + "version": "1.2.0", "description": "iden3-auth implementation in JavaScript", "main": "dist/cjs/index.js", "source": "./src/index.ts", diff --git a/src/circuits/linkedMultiQuery.ts b/src/circuits/linkedMultiQuery.ts index 7cf9028..604d73f 100644 --- a/src/circuits/linkedMultiQuery.ts +++ b/src/circuits/linkedMultiQuery.ts @@ -8,10 +8,14 @@ import { LinkedMultiQueryPubSignals, byteEncoder, cacheLoader, - createSchemaHash, - parseQueriesMetadata + parseQueriesMetadata, + calculateQueryHashV3, + LinkedMultiQueryInputs, + QueryMetadata, + caclulateCoreSchemaHash, + Operators, + fieldValueFromVerifiablePresentation } from '@0xpolygonid/js-sdk'; -import { poseidon } from '@iden3/js-crypto'; /** * Verifies the linked multi-query circuit. @@ -30,7 +34,7 @@ export class LinkedMultiQueryVerifier implements PubSignalsVerifier { return Promise.resolve(); } - async verifyQuery(query: Query, schemaLoader?: DocumentLoader): Promise<BaseConfig> { + async verifyQuery(query: Query, schemaLoader?: DocumentLoader, verifiablePresentation?: JSON): Promise<BaseConfig> { let schema: JSONObject; const ldOpts = { documentLoader: schemaLoader ?? cacheLoader() }; try { @@ -41,8 +45,9 @@ export class LinkedMultiQueryVerifier implements PubSignalsVerifier { const ldContextJSON = JSON.stringify(schema); const credentialSubject = query.credentialSubject as JSONObject; const schemaId: string = await Path.getTypeIDFromContext(ldContextJSON, query.type, ldOpts); - const schemaHash = createSchemaHash(byteEncoder.encode(schemaId)); + // const schemaHash = createSchemaHash(byteEncoder.encode(schemaId)); + const schemaHash = caclulateCoreSchemaHash(byteEncoder.encode(schemaId)); const queriesMetadata = await parseQueriesMetadata( query.type, ldContextJSON, @@ -50,25 +55,58 @@ export class LinkedMultiQueryVerifier implements PubSignalsVerifier { ldOpts ); - const queryHashes = queriesMetadata.map((queryMeta) => { - const valueHash = poseidon.spongeHashX(queryMeta.values, 6); - return poseidon.hash([ - schemaHash.bigInt(), - BigInt(queryMeta.slotIndex), - BigInt(queryMeta.operator), - BigInt(queryMeta.claimPathKey), - queryMeta.merklizedSchema ? 0n : 1n, - valueHash - ]); - }); + const request: { queryHash: bigint; queryMeta: QueryMetadata }[] = []; + const merklized = queriesMetadata[0]?.merklizedSchema ? 1 : 0; + for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) { + const queryMeta = queriesMetadata[i]; + const values = queryMeta?.values ?? []; + const valArrSize = values.length; - const circuitQueryHashes = this.pubSignals.circuitQueryHash - .filter((i) => i !== 0n) - .sort(this.bigIntCompare); - queryHashes.sort(this.bigIntCompare); - // if (!queryHashes.every((queryHash, i) => queryHash === circuitQueryHashes[i])) { - // throw new Error('query hashes do not match'); - // } + const queryHash = calculateQueryHashV3( + values, + schemaHash, + queryMeta?.slotIndex ?? 0, + queryMeta?.operator ?? 0, + queryMeta?.claimPathKey.toString() ?? 0, + valArrSize, + merklized, + 0, + 0, + 0 + ); + request.push({ queryHash, queryMeta }); + } + + const queryHashCompare = (a: { queryHash: bigint }, b: { queryHash: bigint }): number => { + if (a.queryHash < b.queryHash) return -1; + if (a.queryHash > b.queryHash) return 1; + return 0; + }; + + const pubSignalsMeta = this.pubSignals.circuitQueryHash.map((queryHash, index) => ({ + queryHash, + operatorOutput: this.pubSignals.operatorOutput[index] + })); + + pubSignalsMeta.sort(queryHashCompare); + request.sort(queryHashCompare); + + for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) { + if (request[i].queryHash != pubSignalsMeta[i].queryHash) { + throw new Error('query hashes do not match'); + } + + if (request[i].queryMeta?.operator === Operators.SD) { + const disclosedValue = await fieldValueFromVerifiablePresentation( + request[i].queryMeta.fieldName, + verifiablePresentation, + ldOpts.documentLoader + ); + if (disclosedValue != pubSignalsMeta[i].operatorOutput) { + throw new Error('disclosed value is not in the proof outputs'); + } + } + } return this.pubSignals as unknown as BaseConfig; }