@0xpolygonid/js-sdk 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/esm/index.js +1685 -468
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +1706 -473
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/circuits/atomic-query-mtp-v2-on-chain.js +1 -1
- package/dist/node/cjs/circuits/atomic-query-mtp-v2.js +1 -1
- package/dist/node/cjs/circuits/atomic-query-sig-v2-on-chain.js +2 -2
- package/dist/node/cjs/circuits/atomic-query-sig-v2.js +11 -14
- package/dist/node/cjs/circuits/atomic-query-v3-on-chain.js +320 -0
- package/dist/node/cjs/circuits/atomic-query-v3.js +275 -0
- package/dist/node/cjs/circuits/common.js +5 -7
- package/dist/node/cjs/circuits/comparer.js +57 -2
- package/dist/node/cjs/circuits/index.js +4 -0
- package/dist/node/cjs/circuits/linked-multi-query.js +128 -0
- package/dist/node/cjs/circuits/linked-nullifier.js +57 -0
- package/dist/node/cjs/circuits/models.js +25 -1
- package/dist/node/cjs/credentials/credential-wallet.js +2 -10
- package/dist/node/cjs/credentials/index.js +1 -0
- package/dist/node/cjs/credentials/utils.js +23 -0
- package/dist/node/cjs/iden3comm/handlers/auth.js +49 -8
- package/dist/node/cjs/iden3comm/handlers/contract-request.js +20 -8
- package/dist/node/cjs/proof/common.js +104 -1
- package/dist/node/cjs/proof/inputs-generator.js +393 -0
- package/dist/node/cjs/proof/proof-service.js +105 -372
- package/dist/node/cjs/schema-processor/json/parser.js +7 -0
- package/dist/node/cjs/schema-processor/json/validator.js +1 -0
- package/dist/node/cjs/storage/filters/jsonQuery.js +73 -8
- package/dist/node/cjs/utils/did-helper.js +14 -0
- package/dist/node/cjs/utils/index.js +2 -0
- package/dist/node/cjs/utils/object.js +42 -0
- package/dist/node/cjs/verifiable/presentation.js +34 -33
- package/dist/node/cjs/verifiable/proof.js +2 -0
- package/dist/node/esm/circuits/atomic-query-mtp-v2-on-chain.js +1 -1
- package/dist/node/esm/circuits/atomic-query-mtp-v2.js +1 -1
- package/dist/node/esm/circuits/atomic-query-sig-v2-on-chain.js +2 -2
- package/dist/node/esm/circuits/atomic-query-sig-v2.js +11 -14
- package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +315 -0
- package/dist/node/esm/circuits/atomic-query-v3.js +270 -0
- package/dist/node/esm/circuits/common.js +4 -6
- package/dist/node/esm/circuits/comparer.js +55 -1
- package/dist/node/esm/circuits/index.js +4 -0
- package/dist/node/esm/circuits/linked-multi-query.js +123 -0
- package/dist/node/esm/circuits/linked-nullifier.js +52 -0
- package/dist/node/esm/circuits/models.js +25 -1
- package/dist/node/esm/credentials/credential-wallet.js +2 -10
- package/dist/node/esm/credentials/index.js +1 -0
- package/dist/node/esm/credentials/utils.js +19 -0
- package/dist/node/esm/iden3comm/handlers/auth.js +50 -9
- package/dist/node/esm/iden3comm/handlers/contract-request.js +20 -8
- package/dist/node/esm/proof/common.js +101 -2
- package/dist/node/esm/proof/inputs-generator.js +389 -0
- package/dist/node/esm/proof/proof-service.js +111 -377
- package/dist/node/esm/schema-processor/json/parser.js +7 -0
- package/dist/node/esm/schema-processor/json/validator.js +1 -0
- package/dist/node/esm/storage/filters/jsonQuery.js +74 -9
- package/dist/node/esm/utils/did-helper.js +10 -0
- package/dist/node/esm/utils/index.js +2 -0
- package/dist/node/esm/utils/object.js +38 -0
- package/dist/node/esm/verifiable/presentation.js +30 -29
- package/dist/node/esm/verifiable/proof.js +2 -0
- package/dist/types/circuits/atomic-query-mtp-v2.d.ts +13 -13
- package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +142 -0
- package/dist/types/circuits/atomic-query-v3.d.ts +120 -0
- package/dist/types/circuits/common.d.ts +4 -4
- package/dist/types/circuits/comparer.d.ts +33 -1
- package/dist/types/circuits/index.d.ts +4 -0
- package/dist/types/circuits/linked-multi-query.d.ts +38 -0
- package/dist/types/circuits/linked-nullifier.d.ts +37 -0
- package/dist/types/circuits/models.d.ts +20 -2
- package/dist/types/credentials/index.d.ts +1 -0
- package/dist/types/credentials/utils.d.ts +12 -0
- package/dist/types/iden3comm/types/packer.d.ts +1 -2
- package/dist/types/iden3comm/types/protocol/auth.d.ts +1 -0
- package/dist/types/proof/common.d.ts +34 -3
- package/dist/types/proof/inputs-generator.d.ts +46 -0
- package/dist/types/proof/proof-service.d.ts +14 -25
- package/dist/types/schema-processor/json/parser.d.ts +1 -0
- package/dist/types/storage/filters/jsonQuery.d.ts +1 -1
- package/dist/types/utils/did-helper.d.ts +6 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/object.d.ts +12 -0
- package/dist/types/verifiable/presentation.d.ts +6 -10
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ProofService = void 0;
|
|
4
4
|
const js_crypto_1 = require("@iden3/js-crypto");
|
|
5
5
|
const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
6
6
|
const js_merkletree_1 = require("@iden3/js-merkletree");
|
|
@@ -11,6 +11,7 @@ const prover_1 = require("./prover");
|
|
|
11
11
|
const js_jsonld_merklization_1 = require("@iden3/js-jsonld-merklization");
|
|
12
12
|
const schema_processor_1 = require("../schema-processor");
|
|
13
13
|
const encoding_1 = require("../utils/encoding");
|
|
14
|
+
const inputs_generator_1 = require("./inputs-generator");
|
|
14
15
|
/**
|
|
15
16
|
* Proof service is an implementation of IProofService
|
|
16
17
|
* that works with a native groth16 prover
|
|
@@ -33,6 +34,7 @@ class ProofService {
|
|
|
33
34
|
this._stateStorage = _stateStorage;
|
|
34
35
|
this._prover = opts?.prover ?? new prover_1.NativeProver(_circuitStorage);
|
|
35
36
|
this._ldOptions = { ...opts, documentLoader: opts?.documentLoader ?? (0, schema_processor_1.cacheLoader)(opts) };
|
|
37
|
+
this._inputsGenerator = new inputs_generator_1.InputGenerator(_identityWallet, _credentialWallet, _stateStorage);
|
|
36
38
|
}
|
|
37
39
|
/** {@inheritdoc IProofService.verifyProof} */
|
|
38
40
|
async verifyProof(zkp, circuitId) {
|
|
@@ -46,20 +48,61 @@ class ProofService {
|
|
|
46
48
|
challenge: 0n
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
let credentialWithRevStatus = { cred: opts.credential, revStatus: opts.credentialRevocationStatus };
|
|
52
|
+
if (!opts.credential) {
|
|
53
|
+
credentialWithRevStatus = await this.findCredentialByProofQuery(identifier, proofReq.query);
|
|
54
|
+
}
|
|
55
|
+
if (opts.credential && !opts.credentialRevocationStatus && !opts.skipRevocation) {
|
|
56
|
+
const revStatus = await this._credentialWallet.getRevocationStatusFromCredential(opts.credential);
|
|
57
|
+
credentialWithRevStatus = { cred: opts.credential, revStatus };
|
|
58
|
+
}
|
|
59
|
+
if (!credentialWithRevStatus.cred) {
|
|
60
|
+
throw new Error(`credential not found for query ${JSON.stringify(proofReq.query)}`);
|
|
61
|
+
}
|
|
62
|
+
const credentialCoreClaim = await this._identityWallet.getCoreClaimFromCredential(credentialWithRevStatus.cred);
|
|
51
63
|
const { nonce: authProfileNonce, genesisDID } = await this._identityWallet.getGenesisDIDMetadata(identifier);
|
|
52
|
-
const preparedCredential =
|
|
64
|
+
const preparedCredential = {
|
|
65
|
+
credential: credentialWithRevStatus.cred,
|
|
66
|
+
credentialCoreClaim,
|
|
67
|
+
revStatus: credentialWithRevStatus.revStatus
|
|
68
|
+
};
|
|
53
69
|
const subjectDID = js_iden3_core_1.DID.parse(preparedCredential.credential.credentialSubject['id']);
|
|
54
70
|
const { nonce: credentialSubjectProfileNonce, genesisDID: subjectGenesisDID } = await this._identityWallet.getGenesisDIDMetadata(subjectDID);
|
|
55
71
|
if (subjectGenesisDID.string() !== genesisDID.string()) {
|
|
56
72
|
throw new Error('subject and auth profiles are not derived from the same did');
|
|
57
73
|
}
|
|
58
|
-
const
|
|
74
|
+
const propertiesMetadata = (0, common_1.parseCredentialSubject)(proofReq.query.credentialSubject);
|
|
75
|
+
if (!propertiesMetadata.length) {
|
|
76
|
+
throw new Error('no queries in zkp request');
|
|
77
|
+
}
|
|
78
|
+
const mtPosition = preparedCredential.credentialCoreClaim.getMerklizedPosition();
|
|
79
|
+
let mk;
|
|
80
|
+
if (mtPosition !== js_iden3_core_1.MerklizedRootPosition.None) {
|
|
81
|
+
mk = await preparedCredential.credential.merklize(this._ldOptions);
|
|
82
|
+
}
|
|
83
|
+
const context = proofReq.query['context'];
|
|
84
|
+
const groupId = proofReq.query['groupId'];
|
|
85
|
+
const ldContext = await this.loadLdContext(context);
|
|
86
|
+
const credentialType = proofReq.query['type'];
|
|
87
|
+
const queriesMetadata = [];
|
|
88
|
+
const circuitQueries = [];
|
|
89
|
+
for (const propertyMetadata of propertiesMetadata) {
|
|
90
|
+
const queryMetadata = await (0, common_1.parseQueryMetadata)(propertyMetadata, encoding_1.byteDecoder.decode(ldContext), credentialType, this._ldOptions);
|
|
91
|
+
queriesMetadata.push(queryMetadata);
|
|
92
|
+
const circuitQuery = await this.toCircuitsQuery(preparedCredential.credential, queryMetadata, mk);
|
|
93
|
+
circuitQueries.push(circuitQuery);
|
|
94
|
+
}
|
|
95
|
+
const inputs = await this.generateInputs(preparedCredential, genesisDID, proofReq, {
|
|
59
96
|
...opts,
|
|
60
97
|
authProfileNonce,
|
|
61
|
-
credentialSubjectProfileNonce
|
|
62
|
-
|
|
98
|
+
credentialSubjectProfileNonce,
|
|
99
|
+
linkNonce: groupId ? opts.linkNonce : 0n
|
|
100
|
+
}, circuitQueries);
|
|
101
|
+
const sdQueries = queriesMetadata.filter((q) => q.operator === circuits_1.Operators.SD);
|
|
102
|
+
let vp;
|
|
103
|
+
if (sdQueries.length) {
|
|
104
|
+
vp = (0, verifiable_1.createVerifiablePresentation)(context, credentialType, preparedCredential.credential, sdQueries);
|
|
105
|
+
}
|
|
63
106
|
const { proof, pub_signals } = await this._prover.generate(inputs, proofReq.circuitId);
|
|
64
107
|
return {
|
|
65
108
|
id: proofReq.id,
|
|
@@ -71,7 +114,7 @@ class ProofService {
|
|
|
71
114
|
}
|
|
72
115
|
/** {@inheritdoc IProofService.transitState} */
|
|
73
116
|
async transitState(did, oldTreeState, isOldStateGenesis, stateStorage, ethSigner) {
|
|
74
|
-
const authInfo = await this.prepareAuthBJJCredential(did, oldTreeState);
|
|
117
|
+
const authInfo = await this._inputsGenerator.prepareAuthBJJCredential(did, oldTreeState);
|
|
75
118
|
const newTreeModel = await this._identityWallet.getDIDTreeModel(did);
|
|
76
119
|
const claimsRoot = await newTreeModel.claimsTree.root();
|
|
77
120
|
const rootOfRoots = await newTreeModel.rootsTree.root();
|
|
@@ -83,17 +126,17 @@ class ProofService {
|
|
|
83
126
|
rootOfRoots
|
|
84
127
|
};
|
|
85
128
|
const challenge = js_crypto_1.Poseidon.hash([oldTreeState.state.bigInt(), newTreeState.state.bigInt()]);
|
|
86
|
-
const signature = await this._identityWallet.signChallenge(challenge, authInfo.
|
|
129
|
+
const signature = await this._identityWallet.signChallenge(challenge, authInfo.credential);
|
|
87
130
|
const circuitInputs = new circuits_1.StateTransitionInputs();
|
|
88
131
|
circuitInputs.id = js_iden3_core_1.DID.idFromDID(did);
|
|
89
132
|
circuitInputs.signature = signature;
|
|
90
133
|
circuitInputs.isOldStateGenesis = isOldStateGenesis;
|
|
91
|
-
const authClaimIncProofNewState = await this._identityWallet.generateCredentialMtp(did, authInfo.
|
|
134
|
+
const authClaimIncProofNewState = await this._identityWallet.generateCredentialMtp(did, authInfo.credential, newTreeState);
|
|
92
135
|
circuitInputs.newTreeState = authClaimIncProofNewState.treeState;
|
|
93
136
|
circuitInputs.authClaimNewStateIncProof = authClaimIncProofNewState.proof;
|
|
94
137
|
circuitInputs.oldTreeState = oldTreeState;
|
|
95
138
|
circuitInputs.authClaim = {
|
|
96
|
-
claim: authInfo.
|
|
139
|
+
claim: authInfo.coreClaim,
|
|
97
140
|
incProof: authInfo.incProof,
|
|
98
141
|
nonRevProof: authInfo.nonRevProof
|
|
99
142
|
};
|
|
@@ -103,370 +146,65 @@ class ProofService {
|
|
|
103
146
|
await this._identityWallet.updateIdentityState(did, true, newTreeState);
|
|
104
147
|
return txId;
|
|
105
148
|
}
|
|
106
|
-
async
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const nonRevProof = await this._identityWallet.generateNonRevocationMtp(did, authCredential, treeStateInfo);
|
|
115
|
-
const authCoreClaim = authCredential.getCoreClaimFromProof(verifiable_1.ProofType.Iden3SparseMerkleTreeProof);
|
|
116
|
-
if (!authCoreClaim) {
|
|
117
|
-
throw new Error('auth core claim is not defined for auth bjj credential');
|
|
118
|
-
}
|
|
119
|
-
return { authCredential, incProof, nonRevProof, authCoreClaim };
|
|
120
|
-
}
|
|
121
|
-
async generateInputs(preparedCredential, identifier, proofReq, params) {
|
|
122
|
-
let generateInputFn;
|
|
123
|
-
switch (proofReq.circuitId) {
|
|
124
|
-
case circuits_1.CircuitId.AtomicQueryMTPV2:
|
|
125
|
-
generateInputFn = this.generateMTPV2Inputs.bind(this);
|
|
126
|
-
break;
|
|
127
|
-
case circuits_1.CircuitId.AtomicQueryMTPV2OnChain:
|
|
128
|
-
generateInputFn = this.generateMTPV2OnChainInputs.bind(this);
|
|
129
|
-
break;
|
|
130
|
-
case circuits_1.CircuitId.AtomicQuerySigV2:
|
|
131
|
-
generateInputFn = this.generateQuerySigV2Inputs.bind(this);
|
|
132
|
-
break;
|
|
133
|
-
case circuits_1.CircuitId.AtomicQuerySigV2OnChain:
|
|
134
|
-
generateInputFn = this.generateQuerySigV2OnChainInputs.bind(this);
|
|
135
|
-
break;
|
|
136
|
-
default:
|
|
137
|
-
throw new Error(`circuit with id ${proofReq.circuitId} is not supported by issuer`);
|
|
138
|
-
}
|
|
139
|
-
return generateInputFn(preparedCredential, identifier, proofReq, params);
|
|
140
|
-
}
|
|
141
|
-
async generateMTPV2Inputs(preparedCredential, identifier, proofReq, params) {
|
|
142
|
-
const circuitClaimData = await this.newCircuitClaimData(preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
143
|
-
circuitClaimData.nonRevProof = (0, common_1.toClaimNonRevStatus)(preparedCredential.revStatus);
|
|
144
|
-
const circuitInputs = new circuits_1.AtomicQueryMTPV2Inputs();
|
|
145
|
-
circuitInputs.id = js_iden3_core_1.DID.idFromDID(identifier);
|
|
146
|
-
circuitInputs.requestID = BigInt(proofReq.id);
|
|
147
|
-
const { query, vp } = await this.toCircuitsQuery(proofReq.query, preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
148
|
-
circuitInputs.query = query;
|
|
149
|
-
circuitInputs.claim = {
|
|
150
|
-
issuerID: circuitClaimData.issuerId,
|
|
151
|
-
claim: circuitClaimData.claim,
|
|
152
|
-
incProof: { proof: circuitClaimData.proof, treeState: circuitClaimData.treeState },
|
|
153
|
-
nonRevProof: circuitClaimData.nonRevProof
|
|
154
|
-
};
|
|
155
|
-
circuitInputs.currentTimeStamp = (0, js_iden3_core_1.getUnixTimestamp)(new Date());
|
|
156
|
-
circuitInputs.claimSubjectProfileNonce = BigInt(params.credentialSubjectProfileNonce);
|
|
157
|
-
circuitInputs.profileNonce = BigInt(params.authProfileNonce);
|
|
158
|
-
circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
|
|
159
|
-
return { inputs: circuitInputs.inputsMarshal(), vp };
|
|
160
|
-
}
|
|
161
|
-
async generateMTPV2OnChainInputs(preparedCredential, identifier, proofReq, params) {
|
|
162
|
-
const circuitClaimData = await this.newCircuitClaimData(preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
163
|
-
const authPrepared = await this.prepareAuthBJJCredential(identifier);
|
|
164
|
-
const authClaimData = await this.newCircuitClaimData(authPrepared.authCredential, authPrepared.authCoreClaim);
|
|
165
|
-
circuitClaimData.nonRevProof = (0, common_1.toClaimNonRevStatus)(preparedCredential.revStatus);
|
|
166
|
-
const circuitInputs = new circuits_1.AtomicQueryMTPV2OnChainInputs();
|
|
167
|
-
const id = js_iden3_core_1.DID.idFromDID(identifier);
|
|
168
|
-
circuitInputs.id = js_iden3_core_1.DID.idFromDID(identifier);
|
|
169
|
-
circuitInputs.requestID = BigInt(proofReq.id);
|
|
170
|
-
const stateProof = await this._stateStorage.getGISTProof(id.bigInt());
|
|
171
|
-
const gistProof = (0, common_1.toGISTProof)(stateProof);
|
|
172
|
-
circuitInputs.gistProof = gistProof;
|
|
173
|
-
if (authClaimData?.treeState) {
|
|
174
|
-
circuitInputs.treeState = {
|
|
175
|
-
state: authClaimData?.treeState?.state,
|
|
176
|
-
claimsRoot: authClaimData?.treeState?.claimsRoot,
|
|
177
|
-
revocationRoot: authClaimData?.treeState?.revocationRoot,
|
|
178
|
-
rootOfRoots: authClaimData?.treeState?.rootOfRoots
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
circuitInputs.authClaim = authClaimData.claim;
|
|
182
|
-
circuitInputs.authClaimIncMtp = authClaimData.proof;
|
|
183
|
-
circuitInputs.authClaimNonRevMtp = authPrepared.nonRevProof.proof;
|
|
184
|
-
if (!params.challenge) {
|
|
185
|
-
throw new Error('challenge must be provided for onchain circuits');
|
|
186
|
-
}
|
|
187
|
-
const signature = await this._identityWallet.signChallenge(params.challenge, authPrepared.authCredential);
|
|
188
|
-
circuitInputs.signature = signature;
|
|
189
|
-
circuitInputs.challenge = params.challenge;
|
|
190
|
-
const { query, vp } = await this.toCircuitsQuery(proofReq.query, preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
191
|
-
circuitInputs.query = query;
|
|
192
|
-
circuitInputs.claim = {
|
|
193
|
-
issuerID: circuitClaimData.issuerId,
|
|
194
|
-
claim: circuitClaimData.claim,
|
|
195
|
-
incProof: { proof: circuitClaimData.proof, treeState: circuitClaimData.treeState },
|
|
196
|
-
nonRevProof: circuitClaimData.nonRevProof
|
|
197
|
-
};
|
|
198
|
-
circuitInputs.currentTimeStamp = (0, js_iden3_core_1.getUnixTimestamp)(new Date());
|
|
199
|
-
circuitInputs.claimSubjectProfileNonce = BigInt(params.credentialSubjectProfileNonce);
|
|
200
|
-
circuitInputs.profileNonce = BigInt(params.authProfileNonce);
|
|
201
|
-
circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
|
|
202
|
-
return { inputs: circuitInputs.inputsMarshal(), vp };
|
|
203
|
-
}
|
|
204
|
-
async generateQuerySigV2Inputs(preparedCredential, identifier, proofReq, params) {
|
|
205
|
-
const circuitClaimData = await this.newCircuitClaimData(preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
206
|
-
circuitClaimData.nonRevProof = (0, common_1.toClaimNonRevStatus)(preparedCredential.revStatus);
|
|
207
|
-
const circuitInputs = new circuits_1.AtomicQuerySigV2Inputs();
|
|
208
|
-
circuitInputs.id = js_iden3_core_1.DID.idFromDID(identifier);
|
|
209
|
-
circuitInputs.claim = {
|
|
210
|
-
issuerID: circuitClaimData?.issuerId,
|
|
211
|
-
signatureProof: circuitClaimData.signatureProof,
|
|
212
|
-
claim: circuitClaimData.claim,
|
|
213
|
-
nonRevProof: circuitClaimData.nonRevProof
|
|
214
|
-
};
|
|
215
|
-
circuitInputs.requestID = BigInt(proofReq.id);
|
|
216
|
-
circuitInputs.claimSubjectProfileNonce = BigInt(params.credentialSubjectProfileNonce);
|
|
217
|
-
circuitInputs.profileNonce = BigInt(params.authProfileNonce);
|
|
218
|
-
circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
|
|
219
|
-
const { query, vp } = await this.toCircuitsQuery(proofReq.query, preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
220
|
-
circuitInputs.query = query;
|
|
221
|
-
circuitInputs.currentTimeStamp = (0, js_iden3_core_1.getUnixTimestamp)(new Date());
|
|
222
|
-
return { inputs: circuitInputs.inputsMarshal(), vp };
|
|
149
|
+
async generateInputs(preparedCredential, identifier, proofReq, params, circuitQueries) {
|
|
150
|
+
return this._inputsGenerator.generateInputs({
|
|
151
|
+
preparedCredential,
|
|
152
|
+
identifier,
|
|
153
|
+
proofReq,
|
|
154
|
+
params,
|
|
155
|
+
circuitQueries
|
|
156
|
+
});
|
|
223
157
|
}
|
|
224
|
-
async
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const authClaimData = await this.newCircuitClaimData(authPrepared.authCredential, authPrepared.authCoreClaim);
|
|
228
|
-
circuitClaimData.nonRevProof = (0, common_1.toClaimNonRevStatus)(preparedCredential.revStatus);
|
|
229
|
-
const circuitInputs = new circuits_1.AtomicQuerySigV2OnChainInputs();
|
|
230
|
-
const id = js_iden3_core_1.DID.idFromDID(identifier);
|
|
231
|
-
circuitInputs.id = id;
|
|
232
|
-
circuitInputs.claim = {
|
|
233
|
-
issuerID: circuitClaimData.issuerId,
|
|
234
|
-
signatureProof: circuitClaimData.signatureProof,
|
|
235
|
-
claim: circuitClaimData.claim,
|
|
236
|
-
nonRevProof: circuitClaimData.nonRevProof
|
|
237
|
-
};
|
|
238
|
-
circuitInputs.requestID = BigInt(proofReq.id);
|
|
239
|
-
circuitInputs.claimSubjectProfileNonce = BigInt(params.credentialSubjectProfileNonce);
|
|
240
|
-
circuitInputs.profileNonce = BigInt(params.authProfileNonce);
|
|
241
|
-
circuitInputs.skipClaimRevocationCheck = params.skipRevocation;
|
|
242
|
-
const { query, vp } = await this.toCircuitsQuery(proofReq.query, preparedCredential.credential, preparedCredential.credentialCoreClaim);
|
|
243
|
-
circuitInputs.query = query;
|
|
244
|
-
circuitInputs.currentTimeStamp = (0, js_iden3_core_1.getUnixTimestamp)(new Date());
|
|
245
|
-
if (authClaimData.treeState) {
|
|
246
|
-
circuitInputs.treeState = {
|
|
247
|
-
state: authClaimData.treeState?.state,
|
|
248
|
-
claimsRoot: authClaimData.treeState?.claimsRoot,
|
|
249
|
-
revocationRoot: authClaimData.treeState?.revocationRoot,
|
|
250
|
-
rootOfRoots: authClaimData.treeState?.rootOfRoots
|
|
251
|
-
};
|
|
158
|
+
async toCircuitsQuery(credential, queryMetadata, merklizedCredential) {
|
|
159
|
+
if (queryMetadata.merklizedSchema && !merklizedCredential) {
|
|
160
|
+
throw new Error('merklized root position is set to None for merklized schema');
|
|
252
161
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
circuitInputs.gistProof = gistProof;
|
|
256
|
-
circuitInputs.authClaim = authClaimData.claim;
|
|
257
|
-
circuitInputs.authClaimIncMtp = authClaimData.proof;
|
|
258
|
-
circuitInputs.authClaimNonRevMtp = authPrepared.nonRevProof.proof;
|
|
259
|
-
if (!params.challenge) {
|
|
260
|
-
throw new Error('challenge must be provided for onchain circuits');
|
|
261
|
-
}
|
|
262
|
-
const signature = await this._identityWallet.signChallenge(params.challenge, authPrepared.authCredential);
|
|
263
|
-
circuitInputs.signature = signature;
|
|
264
|
-
circuitInputs.challenge = params.challenge;
|
|
265
|
-
return { inputs: circuitInputs.inputsMarshal(), vp };
|
|
266
|
-
}
|
|
267
|
-
// NewCircuitClaimData generates circuits claim structure
|
|
268
|
-
async newCircuitClaimData(credential, coreClaim) {
|
|
269
|
-
const smtProof = credential.getIden3SparseMerkleTreeProof();
|
|
270
|
-
const circuitClaim = new circuits_1.CircuitClaim();
|
|
271
|
-
circuitClaim.claim = coreClaim;
|
|
272
|
-
circuitClaim.issuerId = js_iden3_core_1.DID.idFromDID(js_iden3_core_1.DID.parse(credential.issuer));
|
|
273
|
-
if (smtProof) {
|
|
274
|
-
circuitClaim.proof = smtProof.mtp;
|
|
275
|
-
circuitClaim.treeState = {
|
|
276
|
-
state: smtProof.issuerData.state.value,
|
|
277
|
-
claimsRoot: smtProof.issuerData.state.claimsTreeRoot,
|
|
278
|
-
revocationRoot: smtProof.issuerData.state.revocationTreeRoot,
|
|
279
|
-
rootOfRoots: smtProof.issuerData.state.rootOfRoots
|
|
280
|
-
};
|
|
162
|
+
if (!queryMetadata.merklizedSchema && merklizedCredential) {
|
|
163
|
+
throw new Error('merklized root position is not set to None for non-merklized schema');
|
|
281
164
|
}
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
if (!sigProof.issuerData.credentialStatus) {
|
|
296
|
-
throw new Error("can't check the validity of issuer auth claim: no credential status in proof");
|
|
165
|
+
const query = new circuits_1.Query();
|
|
166
|
+
query.slotIndex = queryMetadata.slotIndex;
|
|
167
|
+
query.operator = queryMetadata.operator;
|
|
168
|
+
query.values = queryMetadata.values;
|
|
169
|
+
if (queryMetadata.merklizedSchema && merklizedCredential) {
|
|
170
|
+
const { proof, value: mtValue } = await merklizedCredential.proof(queryMetadata.path);
|
|
171
|
+
query.valueProof = new circuits_1.ValueProof();
|
|
172
|
+
query.valueProof.mtp = proof;
|
|
173
|
+
query.valueProof.path = queryMetadata.claimPathKey;
|
|
174
|
+
const mtEntry = await mtValue?.mtEntry();
|
|
175
|
+
if (!mtEntry) {
|
|
176
|
+
throw new Error(`can't merklize credential: no merkle tree entry found`);
|
|
297
177
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
};
|
|
303
|
-
const rs = await this._credentialWallet.getRevocationStatus(sigProof.issuerData.credentialStatus, opts);
|
|
304
|
-
if (!rs) {
|
|
305
|
-
throw new Error("can't fetch the credential status of issuer auth claim");
|
|
178
|
+
query.valueProof.value = mtEntry;
|
|
179
|
+
if (!queryMetadata.fieldName) {
|
|
180
|
+
query.values = [mtEntry];
|
|
181
|
+
return query;
|
|
306
182
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
183
|
+
}
|
|
184
|
+
if (queryMetadata.operator === circuits_1.Operators.SD) {
|
|
185
|
+
const [first, ...rest] = queryMetadata.fieldName.split('.');
|
|
186
|
+
let v = credential.credentialSubject[first];
|
|
187
|
+
for (const part of rest) {
|
|
188
|
+
v = v[part];
|
|
310
189
|
}
|
|
311
|
-
if (
|
|
312
|
-
throw new Error(
|
|
190
|
+
if (typeof v === 'undefined') {
|
|
191
|
+
throw new Error(`credential doesn't contain value for field ${queryMetadata.fieldName}`);
|
|
313
192
|
}
|
|
314
|
-
|
|
315
|
-
signature: sigProof.signature,
|
|
316
|
-
issuerAuthIncProof: {
|
|
317
|
-
proof: sigProof.issuerData.mtp,
|
|
318
|
-
treeState: {
|
|
319
|
-
state: sigProof.issuerData.state.value,
|
|
320
|
-
claimsRoot: sigProof.issuerData.state.claimsTreeRoot,
|
|
321
|
-
revocationRoot: sigProof.issuerData.state.revocationTreeRoot,
|
|
322
|
-
rootOfRoots: sigProof.issuerData.state.rootOfRoots
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
issuerAuthClaim: sigProof.issuerData.authCoreClaim,
|
|
326
|
-
issuerAuthNonRevProof
|
|
327
|
-
};
|
|
193
|
+
query.values = await (0, common_1.transformQueryValueToBigInts)(v, queryMetadata.datatype);
|
|
328
194
|
}
|
|
329
|
-
return
|
|
330
|
-
}
|
|
331
|
-
async toCircuitsQuery(query, credential, coreClaim) {
|
|
332
|
-
const mtPosition = coreClaim.getMerklizedPosition();
|
|
333
|
-
return mtPosition === js_iden3_core_1.MerklizedRootPosition.None
|
|
334
|
-
? this.prepareNonMerklizedQuery(query, credential)
|
|
335
|
-
: this.prepareMerklizedQuery(query, credential);
|
|
195
|
+
return query;
|
|
336
196
|
}
|
|
337
|
-
async
|
|
338
|
-
const parsedQuery = await this.parseRequest(query.credentialSubject);
|
|
339
|
-
const ldContext = await this.loadLdContextFromJSONSchema(credential.credentialSchema.id);
|
|
340
|
-
let path = new js_jsonld_merklization_1.Path();
|
|
341
|
-
if (parsedQuery.fieldName) {
|
|
342
|
-
path = await js_jsonld_merklization_1.Path.getContextPathKey(encoding_1.byteDecoder.decode(ldContext), credential.type[1], parsedQuery.fieldName, this._ldOptions);
|
|
343
|
-
}
|
|
344
|
-
path.prepend(['https://www.w3.org/2018/credentials#credentialSubject']);
|
|
345
|
-
const mk = await credential.merklize(this._ldOptions);
|
|
346
|
-
const { proof, value: mtValue } = await mk.proof(path);
|
|
347
|
-
const pathKey = await path.mtEntry();
|
|
348
|
-
parsedQuery.query.valueProof = new circuits_1.ValueProof();
|
|
349
|
-
parsedQuery.query.valueProof.mtp = proof;
|
|
350
|
-
parsedQuery.query.valueProof.path = pathKey;
|
|
351
|
-
parsedQuery.query.valueProof.mtp = proof;
|
|
352
|
-
const mtEntry = await mtValue?.mtEntry();
|
|
353
|
-
if (!mtEntry) {
|
|
354
|
-
throw new Error(`can't merklize credential: no merkle tree entry found`);
|
|
355
|
-
}
|
|
356
|
-
parsedQuery.query.valueProof.value = mtEntry;
|
|
357
|
-
// for merklized credentials slotIndex in query must be equal to zero
|
|
358
|
-
// and not a position of merklization root.
|
|
359
|
-
// it has no influence on check in the off-chain circuits, but it aligns with onchain verification standard
|
|
360
|
-
parsedQuery.query.slotIndex = 0;
|
|
361
|
-
if (!parsedQuery.fieldName) {
|
|
362
|
-
const resultQuery = parsedQuery.query;
|
|
363
|
-
resultQuery.operator = circuits_1.QueryOperators.$eq;
|
|
364
|
-
resultQuery.values = [mtEntry];
|
|
365
|
-
return { query: resultQuery };
|
|
366
|
-
}
|
|
367
|
-
if (parsedQuery.isSelectiveDisclosure) {
|
|
368
|
-
const rawValue = mk.rawValue(path);
|
|
369
|
-
const vp = (0, verifiable_1.createVerifiablePresentation)(query.context ?? '', query.type ?? '', parsedQuery.fieldName, rawValue);
|
|
370
|
-
const resultQuery = parsedQuery.query;
|
|
371
|
-
resultQuery.operator = circuits_1.QueryOperators.$eq;
|
|
372
|
-
resultQuery.values = [mtEntry];
|
|
373
|
-
return { query: resultQuery, vp };
|
|
374
|
-
}
|
|
375
|
-
if (parsedQuery.rawValue === null || parsedQuery.rawValue === undefined) {
|
|
376
|
-
throw new Error('value is not presented in the query');
|
|
377
|
-
}
|
|
378
|
-
const ldType = await mk.jsonLDType(path);
|
|
379
|
-
parsedQuery.query.values = await this.transformQueryValueToBigInts(parsedQuery.rawValue, ldType);
|
|
380
|
-
return { query: parsedQuery.query };
|
|
381
|
-
}
|
|
382
|
-
async prepareNonMerklizedQuery(query, credential) {
|
|
383
|
-
const ldContext = await this.loadLdContextFromJSONSchema(credential.credentialSchema.id);
|
|
384
|
-
if (query.credentialSubject && Object.keys(query.credentialSubject).length > 1) {
|
|
385
|
-
throw new Error('multiple requests are not supported');
|
|
386
|
-
}
|
|
387
|
-
const parsedQuery = await this.parseRequest(query.credentialSubject);
|
|
388
|
-
if (!query.type) {
|
|
389
|
-
throw new Error('query type is not defined');
|
|
390
|
-
}
|
|
391
|
-
parsedQuery.query.slotIndex = await schema_processor_1.Parser.getFieldSlotIndex(parsedQuery.fieldName, query.type, ldContext);
|
|
392
|
-
const { vp, mzValue, dataType } = await (0, verifiable_1.verifiablePresentationFromCred)(credential, query, parsedQuery.fieldName, this._ldOptions);
|
|
393
|
-
if (parsedQuery.isSelectiveDisclosure) {
|
|
394
|
-
const resultQuery = parsedQuery.query;
|
|
395
|
-
resultQuery.operator = circuits_1.QueryOperators.$eq;
|
|
396
|
-
resultQuery.values = [await mzValue.mtEntry()];
|
|
397
|
-
return { query: resultQuery, vp };
|
|
398
|
-
}
|
|
399
|
-
if (parsedQuery.rawValue === null || parsedQuery.rawValue === undefined) {
|
|
400
|
-
throw new Error('value is not presented in the query');
|
|
401
|
-
}
|
|
402
|
-
parsedQuery.query.values = await this.transformQueryValueToBigInts(parsedQuery.rawValue, dataType);
|
|
403
|
-
return { query: parsedQuery.query };
|
|
404
|
-
}
|
|
405
|
-
async loadLdContextFromJSONSchema(jsonSchemaURL) {
|
|
197
|
+
async loadLdContext(context) {
|
|
406
198
|
const loader = (0, js_jsonld_merklization_1.getDocumentLoader)(this._ldOptions);
|
|
407
|
-
let schema;
|
|
408
|
-
try {
|
|
409
|
-
schema = (await loader(jsonSchemaURL)).document;
|
|
410
|
-
}
|
|
411
|
-
catch (e) {
|
|
412
|
-
throw new Error(`can't load credential schema ${jsonSchemaURL}`);
|
|
413
|
-
}
|
|
414
|
-
const jsonSchema = schema;
|
|
415
199
|
let ldSchema;
|
|
416
|
-
let ldContextUrl = '';
|
|
417
200
|
try {
|
|
418
|
-
|
|
419
|
-
if (!ldContextUrl) {
|
|
420
|
-
throw new Error('ldContext is not defined in json schema metadata');
|
|
421
|
-
}
|
|
422
|
-
ldSchema = (await loader(ldContextUrl)).document;
|
|
201
|
+
ldSchema = (await loader(context)).document;
|
|
423
202
|
}
|
|
424
203
|
catch (e) {
|
|
425
|
-
throw new Error(`can't load ld context from url ${
|
|
204
|
+
throw new Error(`can't load ld context from url ${context}`);
|
|
426
205
|
}
|
|
427
206
|
return encoding_1.byteEncoder.encode(JSON.stringify(ldSchema));
|
|
428
207
|
}
|
|
429
|
-
async parseRequest(req) {
|
|
430
|
-
if (!req) {
|
|
431
|
-
const query = new circuits_1.Query();
|
|
432
|
-
query.operator = circuits_1.QueryOperators.$eq;
|
|
433
|
-
return { query, fieldName: '' };
|
|
434
|
-
}
|
|
435
|
-
const entries = Object.entries(req);
|
|
436
|
-
if (entries.length > 1) {
|
|
437
|
-
throw new Error(`multiple requests not supported`);
|
|
438
|
-
}
|
|
439
|
-
const [fieldName, fieldReq] = entries[0];
|
|
440
|
-
const fieldReqEntries = Object.entries(fieldReq);
|
|
441
|
-
if (fieldReqEntries.length > 1) {
|
|
442
|
-
throw new Error(`multiple predicates for one field not supported`);
|
|
443
|
-
}
|
|
444
|
-
const isSelectiveDisclosure = fieldReqEntries.length === 0;
|
|
445
|
-
const query = new circuits_1.Query();
|
|
446
|
-
if (isSelectiveDisclosure) {
|
|
447
|
-
return { query, fieldName, isSelectiveDisclosure };
|
|
448
|
-
}
|
|
449
|
-
let operator = 0;
|
|
450
|
-
const [key, value] = fieldReqEntries[0];
|
|
451
|
-
if (!circuits_1.QueryOperators[key]) {
|
|
452
|
-
throw new Error(`operator is not supported by lib`);
|
|
453
|
-
}
|
|
454
|
-
operator = circuits_1.QueryOperators[key];
|
|
455
|
-
query.operator = operator;
|
|
456
|
-
return { query, fieldName, rawValue: value };
|
|
457
|
-
}
|
|
458
|
-
async transformQueryValueToBigInts(value, ldType) {
|
|
459
|
-
const values = new Array(64).fill(BigInt(0));
|
|
460
|
-
if (Array.isArray(value)) {
|
|
461
|
-
for (let index = 0; index < value.length; index++) {
|
|
462
|
-
values[index] = await js_jsonld_merklization_1.Merklizer.hashValue(ldType, value[index]);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
values[0] = await js_jsonld_merklization_1.Merklizer.hashValue(ldType, value);
|
|
467
|
-
}
|
|
468
|
-
return values;
|
|
469
|
-
}
|
|
470
208
|
/** {@inheritdoc IProofService.generateAuthV2Inputs} */
|
|
471
209
|
async generateAuthV2Inputs(hash, did, circuitId) {
|
|
472
210
|
if (circuitId !== circuits_1.CircuitId.AuthV2) {
|
|
@@ -474,9 +212,12 @@ class ProofService {
|
|
|
474
212
|
}
|
|
475
213
|
const { nonce: authProfileNonce, genesisDID } = await this._identityWallet.getGenesisDIDMetadata(did);
|
|
476
214
|
const challenge = js_iden3_core_1.BytesHelper.bytesToInt(hash.reverse());
|
|
477
|
-
const authPrepared = await this.prepareAuthBJJCredential(genesisDID);
|
|
478
|
-
const authClaimData = await this.newCircuitClaimData(
|
|
479
|
-
|
|
215
|
+
const authPrepared = await this._inputsGenerator.prepareAuthBJJCredential(genesisDID);
|
|
216
|
+
const authClaimData = await this._inputsGenerator.newCircuitClaimData({
|
|
217
|
+
credential: authPrepared.credential,
|
|
218
|
+
credentialCoreClaim: authPrepared.coreClaim
|
|
219
|
+
});
|
|
220
|
+
const signature = await this._identityWallet.signChallenge(challenge, authPrepared.credential);
|
|
480
221
|
const id = js_iden3_core_1.DID.idFromDID(genesisDID);
|
|
481
222
|
const stateProof = await this._stateStorage.getGISTProof(id.bigInt());
|
|
482
223
|
const gistProof = (0, common_1.toGISTProof)(stateProof);
|
|
@@ -512,7 +253,7 @@ class ProofService {
|
|
|
512
253
|
}
|
|
513
254
|
return true;
|
|
514
255
|
}
|
|
515
|
-
async
|
|
256
|
+
async findCredentialByProofQuery(did, query) {
|
|
516
257
|
const credentials = await this._identityWallet.findOwnedCredentialsByDID(did, query);
|
|
517
258
|
if (!credentials.length) {
|
|
518
259
|
throw new Error(`no credentials belong to did or its profiles`);
|
|
@@ -520,17 +261,9 @@ class ProofService {
|
|
|
520
261
|
// For EQ / IN / NIN / LT / GT operations selective if credential satisfies query - we can get any.
|
|
521
262
|
// TODO: choose credential for selective credentials
|
|
522
263
|
const credential = query.skipClaimRevocationCheck
|
|
523
|
-
? credentials[0]
|
|
524
|
-
:
|
|
264
|
+
? { cred: credentials[0], revStatus: undefined }
|
|
265
|
+
: await this._credentialWallet.findNonRevokedCredential(credentials);
|
|
525
266
|
return credential;
|
|
526
267
|
}
|
|
527
268
|
}
|
|
528
269
|
exports.ProofService = ProofService;
|
|
529
|
-
// BJJSignatureFromHexString converts hex to babyjub.Signature
|
|
530
|
-
const bJJSignatureFromHexString = async (sigHex) => {
|
|
531
|
-
const signatureBytes = js_crypto_1.Hex.decodeString(sigHex);
|
|
532
|
-
const compressedSig = Uint8Array.from(signatureBytes).slice(0, 64);
|
|
533
|
-
const bjjSig = js_crypto_1.Signature.newFromCompressed(compressedSig);
|
|
534
|
-
return bjjSig;
|
|
535
|
-
};
|
|
536
|
-
exports.bJJSignatureFromHexString = bJJSignatureFromHexString;
|
|
@@ -152,6 +152,13 @@ class Parser {
|
|
|
152
152
|
const ldCtx = await jsonld.processContext(ldcontext.getInitialContext({}), credential['@context'], opts);
|
|
153
153
|
return Parser.getSerializationAttrFromParsedContext(ldCtx, tp);
|
|
154
154
|
}
|
|
155
|
+
// Get `iden3_serialization` attr definition from context document either using
|
|
156
|
+
// type name like DeliverAddressMultiTestForked or by type id like
|
|
157
|
+
// urn:uuid:ac2ede19-b3b9-454d-b1a9-a7b3d5763100.
|
|
158
|
+
static async getSerializationAttrFromContext(context, opts, tp) {
|
|
159
|
+
const ldCtx = await jsonld.processContext(ldcontext.getInitialContext({}), context, opts);
|
|
160
|
+
return Parser.getSerializationAttrFromParsedContext(ldCtx, tp);
|
|
161
|
+
}
|
|
155
162
|
static async getSerializationAttrFromParsedContext(ldCtx, tp) {
|
|
156
163
|
const termDef = ldCtx.mappings;
|
|
157
164
|
if (!termDef) {
|
|
@@ -48,6 +48,7 @@ class JsonSchemaValidator {
|
|
|
48
48
|
const validate = (schema.$id ? validator.getSchema(schema.$id) : undefined) || validator.compile(schema);
|
|
49
49
|
const valid = validate(data);
|
|
50
50
|
if (!valid) {
|
|
51
|
+
// TODO: extract correct error messages
|
|
51
52
|
throw new Error(validate.errors?.map((e) => e.message).join(', '));
|
|
52
53
|
}
|
|
53
54
|
return true;
|