diff --git a/package-lock.json b/package-lock.json index c4bf0a2d..a3eb782f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@0xpolygonid/js-sdk", - "version": "1.9.1", + "version": "1.9.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@0xpolygonid/js-sdk", - "version": "1.9.1", + "version": "1.9.2", "license": "AGPL-3.0", "dependencies": { "ajv": "8.12.0", diff --git a/package.json b/package.json index 933bb8c2..23c713aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xpolygonid/js-sdk", - "version": "1.9.1", + "version": "1.9.2", "description": "SDK to work with Polygon ID", "main": "dist/node/cjs/index.js", "module": "dist/node/esm/index.js", diff --git a/src/proof/common.ts b/src/proof/common.ts index 658017dc..1fbaa11b 100644 --- a/src/proof/common.ts +++ b/src/proof/common.ts @@ -207,15 +207,17 @@ export const parseQueryMetadata = async ( } } - if (propertyQuery.operatorValue) { + if (propertyQuery.operatorValue !== undefined) { if (!isValidOperation(query.datatype, propertyQuery.operator)) { throw new Error( `operator ${propertyQuery.operator} is not supported for datatype ${query.datatype}` ); } - const datatype = propertyQuery.operator === Operators.EXISTS ? XSDNS.Boolean : query.datatype; - query.values = await transformQueryValueToBigInts(propertyQuery.operatorValue, datatype); + query.values = + propertyQuery.operator === Operators.EXISTS + ? transformExistsValue(propertyQuery.operatorValue) + : await transformQueryValueToBigInts(propertyQuery.operatorValue, query.datatype); } return query; }; @@ -247,3 +249,10 @@ export const transformQueryValueToBigInts = async ( } return values; }; + +const transformExistsValue = (value: unknown): bigint[] => { + if (typeof value == 'boolean') { + return [BigInt(value)]; + } + throw new Error('exists operator value must be true or false'); +}; diff --git a/src/proof/proof-service.ts b/src/proof/proof-service.ts index 02ab2e88..618feeb1 100644 --- a/src/proof/proof-service.ts +++ b/src/proof/proof-service.ts @@ -449,11 +449,7 @@ export class ProofService implements IProofService { query.valueProof.mtp = proof; query.valueProof.path = queryMetadata.claimPathKey; - const mtEntry = await mtValue?.mtEntry(); - if (!mtEntry) { - throw new Error(`can't merklize credential: no merkle tree entry found`); - } - + const mtEntry = (await mtValue?.mtEntry()) ?? 0n; query.valueProof.value = mtEntry; if (!queryMetadata.fieldName) { query.values = [mtEntry]; diff --git a/src/storage/filters/jsonQuery.ts b/src/storage/filters/jsonQuery.ts index 439c70c9..7dc35fc3 100644 --- a/src/storage/filters/jsonQuery.ts +++ b/src/storage/filters/jsonQuery.ts @@ -243,7 +243,7 @@ export class FilterQuery implements IFilterQuery { const credentialPathValue = resolvePath(credential, this.path); if ( (credentialPathValue === null || credentialPathValue === undefined) && - this.operatorFunc !== existsComparator + this.operatorFunc !== comparatorOptions.$exists ) { return false; } diff --git a/tests/proofs/sig.test.ts b/tests/proofs/sig.test.ts index c542a661..4345da73 100644 --- a/tests/proofs/sig.test.ts +++ b/tests/proofs/sig.test.ts @@ -520,4 +520,149 @@ describe('sig proofs', () => { } }); }); + + it('sigv3-ipfs-non-exists', async () => { + const req = { + id: '0d8e91e5-5686-49b5-85e3-2b35538c6a03', + typ: 'application/iden3comm-plain-json', + type: 'https://iden3-communication.io/authorization/1.0/request', + thid: '0d8e91e5-5686-49b5-85e3-2b35538c6a03', + body: { + callbackUrl: 'https://verifier-v2.polygonid.me/api/callback?sessionId=25269', + reason: 'test flow', + scope: [ + { + circuitId: 'credentialAtomicQueryV3-beta.1', + id: 1711115116, + query: { + allowedIssuers: ['*'], + context: 'ipfs://QmcvoKLc742CyVH2Cnw6X95b4c8VdABqNPvTyAHEeaK1aP', + type: 'types123', + credentialSubject: { + bol: { + $exists: false + } + } + } + } + ] + }, + from: 'did:polygonid:polygon:mumbai:2qLPqvayNQz9TA2r5VPxUugoF18teGU583zJ859wfy' + }; + + const claimReq: CredentialRequest = { + credentialSchema: 'ipfs://QmTRpn65HN3j6Y5ZC5WDU1orXnWPWMpoPr2qpep8eMCX6e', + type: 'types123', + credentialSubject: { + id: userDID.string(), + double: 1.2, + int: 1, + string: 'test' + }, + expiration: 2793526400, + revocationOpts: { + type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof, + id: rhsUrl + } + }; + const issuerCred = await idWallet.issueCredential(issuerDID, claimReq, { + ipfsNodeURL + }); + + await credWallet.save(issuerCred); + + const creds = await credWallet.findByQuery(req.body.scope[0].query); + + expect(creds.length).to.not.equal(0); + + const { proof, vp, circuitId, pub_signals } = await proofService.generateProof( + req.body.scope[0], + userDID + ); + expect(proof).not.to.be.undefined; + expect(vp).to.be.undefined; + + const isValid = await proofService.verifyProof( + { + proof, + pub_signals + }, + circuitId as CircuitId + ); + + expect(isValid).to.be.true; + }); + + it('sigv3-ipfs-exists', async () => { + const req = { + id: '0d8e91e5-5686-49b5-85e3-2b35538c6a03', + typ: 'application/iden3comm-plain-json', + type: 'https://iden3-communication.io/authorization/1.0/request', + thid: '0d8e91e5-5686-49b5-85e3-2b35538c6a03', + body: { + callbackUrl: 'https://verifier-v2.polygonid.me/api/callback?sessionId=25269', + reason: 'test flow', + scope: [ + { + circuitId: 'credentialAtomicQueryV3-beta.1', + id: 1711115116, + query: { + allowedIssuers: ['*'], + context: 'ipfs://QmcvoKLc742CyVH2Cnw6X95b4c8VdABqNPvTyAHEeaK1aP', + type: 'types123', + credentialSubject: { + bol: { + $exists: true + } + } + } + } + ] + }, + from: 'did:polygonid:polygon:mumbai:2qLPqvayNQz9TA2r5VPxUugoF18teGU583zJ859wfy' + }; + + const claimReq: CredentialRequest = { + credentialSchema: 'ipfs://QmTRpn65HN3j6Y5ZC5WDU1orXnWPWMpoPr2qpep8eMCX6e', + type: 'types123', + credentialSubject: { + id: userDID.string(), + double: 1.2, + int: 1, + bol: true, + string: 'test' + }, + expiration: 2793526400, + revocationOpts: { + type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof, + id: rhsUrl + } + }; + const issuerCred = await idWallet.issueCredential(issuerDID, claimReq, { + ipfsNodeURL + }); + + await credWallet.save(issuerCred); + + const creds = await credWallet.findByQuery(req.body.scope[0].query); + + expect(creds.length).to.not.equal(0); + + const { proof, vp, circuitId, pub_signals } = await proofService.generateProof( + req.body.scope[0], + userDID + ); + expect(proof).not.to.be.undefined; + expect(vp).to.be.undefined; + + const isValid = await proofService.verifyProof( + { + proof, + pub_signals + }, + circuitId as CircuitId + ); + + expect(isValid).to.be.true; + }); });