@0xpolygonid/js-sdk 1.17.8 → 1.18.1
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 +976 -64
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +976 -63
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/circuits/atomic-query-mtp-v2-on-chain.js +10 -0
- package/dist/node/cjs/circuits/atomic-query-sig-v2-on-chain.js +10 -0
- package/dist/node/cjs/circuits/atomic-query-v3-on-chain.js +10 -0
- package/dist/node/cjs/iden3comm/constants.js +2 -0
- package/dist/node/cjs/iden3comm/handlers/contract-request.js +73 -10
- package/dist/node/cjs/storage/blockchain/abi/ZkpVerifier.json +530 -9
- package/dist/node/cjs/storage/blockchain/onchain-zkp-verifier.js +293 -42
- package/dist/node/cjs/utils/did-helper.js +37 -1
- package/dist/node/esm/circuits/atomic-query-mtp-v2-on-chain.js +10 -0
- package/dist/node/esm/circuits/atomic-query-sig-v2-on-chain.js +10 -0
- package/dist/node/esm/circuits/atomic-query-v3-on-chain.js +10 -0
- package/dist/node/esm/iden3comm/constants.js +2 -0
- package/dist/node/esm/iden3comm/handlers/contract-request.js +73 -10
- package/dist/node/esm/storage/blockchain/abi/ZkpVerifier.json +530 -9
- package/dist/node/esm/storage/blockchain/onchain-zkp-verifier.js +293 -42
- package/dist/node/esm/utils/did-helper.js +35 -0
- package/dist/types/circuits/atomic-query-mtp-v2-on-chain.d.ts +4 -2
- package/dist/types/circuits/atomic-query-sig-v2-on-chain.d.ts +4 -2
- package/dist/types/circuits/atomic-query-v3-on-chain.d.ts +4 -2
- package/dist/types/circuits/common.d.ts +31 -0
- package/dist/types/iden3comm/constants.d.ts +1 -0
- package/dist/types/iden3comm/handlers/contract-request.d.ts +14 -3
- package/dist/types/iden3comm/types/protocol/auth.d.ts +11 -1
- package/dist/types/iden3comm/types/protocol/contract-request.d.ts +16 -1
- package/dist/types/proof/verifiers/pub-signals-verifier.d.ts +2 -2
- package/dist/types/proof/verifiers/query.d.ts +4 -3
- package/dist/types/storage/blockchain/onchain-zkp-verifier.d.ts +44 -12
- package/dist/types/storage/entities/state.d.ts +44 -0
- package/dist/types/storage/interfaces/onchain-zkp-verifier.d.ts +22 -1
- package/dist/types/utils/did-helper.d.ts +12 -1
- package/dist/types/verifiable/presentation.d.ts +2 -2
- package/package.json +1 -1
|
@@ -3,10 +3,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.OnChainZKPVerifier = void 0;
|
|
6
|
+
exports.OnChainZKPVerifier = exports.FunctionSignatures = void 0;
|
|
7
7
|
const ethers_1 = require("ethers");
|
|
8
8
|
const ZkpVerifier_json_1 = __importDefault(require("./abi/ZkpVerifier.json"));
|
|
9
9
|
const blockchain_1 = require("../../blockchain");
|
|
10
|
+
const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
11
|
+
const circuits_1 = require("../../circuits");
|
|
12
|
+
const utils_1 = require("../../utils");
|
|
13
|
+
const js_crypto_1 = require("@iden3/js-crypto");
|
|
14
|
+
const maxGasLimit = 10000000n;
|
|
15
|
+
/**
|
|
16
|
+
* Supported function signature for SubmitZKPResponse
|
|
17
|
+
*/
|
|
18
|
+
var FunctionSignatures;
|
|
19
|
+
(function (FunctionSignatures) {
|
|
20
|
+
/**
|
|
21
|
+
* solidity identifier for function signature:
|
|
22
|
+
* function submitZKPResponse(uint64 requestId, uint256[] calldata inputs,
|
|
23
|
+
* uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c) public
|
|
24
|
+
*/
|
|
25
|
+
FunctionSignatures["SubmitZKPResponseV1"] = "b68967e2";
|
|
26
|
+
//function submitZKPResponseV2(tuple[](uint64 requestId,bytes zkProof,bytes data),bytes crossChainProof)
|
|
27
|
+
FunctionSignatures["SubmitZKPResponseV2"] = "ade09fcd";
|
|
28
|
+
})(FunctionSignatures = exports.FunctionSignatures || (exports.FunctionSignatures = {}));
|
|
10
29
|
/**
|
|
11
30
|
* OnChainZKPVerifier is a class that allows to interact with the OnChainZKPVerifier contract
|
|
12
31
|
* and submitZKPResponse.
|
|
@@ -21,70 +40,302 @@ class OnChainZKPVerifier {
|
|
|
21
40
|
* @beta
|
|
22
41
|
* @param {EthConnectionConfig[]} - array of ETH configs
|
|
23
42
|
*/
|
|
24
|
-
constructor(_configs) {
|
|
43
|
+
constructor(_configs, _opts) {
|
|
25
44
|
this._configs = _configs;
|
|
45
|
+
this._opts = _opts;
|
|
46
|
+
/**
|
|
47
|
+
* supported circuits
|
|
48
|
+
*/
|
|
49
|
+
this._supportedCircuits = [
|
|
50
|
+
circuits_1.CircuitId.AtomicQueryMTPV2OnChain,
|
|
51
|
+
circuits_1.CircuitId.AtomicQuerySigV2OnChain,
|
|
52
|
+
circuits_1.CircuitId.AtomicQueryV3OnChain
|
|
53
|
+
];
|
|
26
54
|
/**
|
|
27
|
-
*
|
|
28
|
-
* function submitZKPResponse(uint64 requestId, uint256[] calldata inputs,
|
|
29
|
-
* uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c) public
|
|
55
|
+
* abi coder to encode/decode structures to solidity bytes
|
|
30
56
|
*/
|
|
31
|
-
this.
|
|
57
|
+
this._abiCoder = new ethers_1.ethers.AbiCoder();
|
|
32
58
|
}
|
|
33
59
|
/**
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
* {@inheritDoc IOnChainZKPVerifier.prepareTxArgsSubmitV1}
|
|
61
|
+
*/
|
|
62
|
+
async prepareTxArgsSubmitV1(txData, zkProofResponse) {
|
|
63
|
+
if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV1) {
|
|
64
|
+
throw new Error(`prepareTxArgsSubmitV1 function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV1}' is supported.`);
|
|
65
|
+
}
|
|
66
|
+
const requestID = zkProofResponse.id;
|
|
67
|
+
const inputs = zkProofResponse.pub_signals;
|
|
68
|
+
const payload = [
|
|
69
|
+
requestID,
|
|
70
|
+
inputs,
|
|
71
|
+
zkProofResponse.proof.pi_a.slice(0, 2),
|
|
72
|
+
[
|
|
73
|
+
[zkProofResponse.proof.pi_b[0][1], zkProofResponse.proof.pi_b[0][0]],
|
|
74
|
+
[zkProofResponse.proof.pi_b[1][1], zkProofResponse.proof.pi_b[1][0]]
|
|
75
|
+
],
|
|
76
|
+
zkProofResponse.proof.pi_c.slice(0, 2)
|
|
77
|
+
];
|
|
78
|
+
return payload;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* {@inheritDoc IOnChainZKPVerifier.submitZKPResponse}
|
|
40
82
|
*/
|
|
41
83
|
async submitZKPResponse(ethSigner, txData, zkProofResponses) {
|
|
42
84
|
const chainConfig = this._configs.find((i) => i.chainId == txData.chain_id);
|
|
43
85
|
if (!chainConfig) {
|
|
44
86
|
throw new Error(`config for chain id ${txData.chain_id} was not found`);
|
|
45
87
|
}
|
|
46
|
-
if (txData.method_id.replace('0x', '') !==
|
|
47
|
-
throw new Error(`
|
|
88
|
+
if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV1) {
|
|
89
|
+
throw new Error(`submitZKPResponse function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV1}' is supported.`);
|
|
48
90
|
}
|
|
49
91
|
const provider = new ethers_1.JsonRpcProvider(chainConfig.url, chainConfig.chainId);
|
|
50
|
-
const verifierContract = new ethers_1.Contract(txData.contract_address, ZkpVerifier_json_1.default, provider);
|
|
51
92
|
ethSigner = ethSigner.connect(provider);
|
|
52
|
-
const contract = verifierContract.connect(ethSigner);
|
|
53
93
|
const response = new Map();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
zkProof.proof.pi_c.slice(0, 2)
|
|
66
|
-
];
|
|
67
|
-
const feeData = await provider.getFeeData();
|
|
68
|
-
const maxFeePerGas = chainConfig.maxFeePerGas
|
|
69
|
-
? BigInt(chainConfig.maxFeePerGas)
|
|
70
|
-
: feeData.maxFeePerGas;
|
|
71
|
-
const maxPriorityFeePerGas = chainConfig.maxPriorityFeePerGas
|
|
72
|
-
? BigInt(chainConfig.maxPriorityFeePerGas)
|
|
73
|
-
: feeData.maxPriorityFeePerGas;
|
|
74
|
-
const gasLimit = await contract.submitZKPResponse.estimateGas(...payload);
|
|
75
|
-
const txData = await contract.submitZKPResponse.populateTransaction(...payload);
|
|
94
|
+
const feeData = await provider.getFeeData();
|
|
95
|
+
const maxFeePerGas = chainConfig.maxFeePerGas
|
|
96
|
+
? BigInt(chainConfig.maxFeePerGas)
|
|
97
|
+
: feeData.maxFeePerGas;
|
|
98
|
+
const maxPriorityFeePerGas = chainConfig.maxPriorityFeePerGas
|
|
99
|
+
? BigInt(chainConfig.maxPriorityFeePerGas)
|
|
100
|
+
: feeData.maxPriorityFeePerGas;
|
|
101
|
+
const verifierContract = new ethers_1.Contract(txData.contract_address, ZkpVerifier_json_1.default);
|
|
102
|
+
for (const zkProofResponse of zkProofResponses) {
|
|
103
|
+
const txArgs = await this.prepareTxArgsSubmitV1(txData, zkProofResponse);
|
|
104
|
+
const payload = await verifierContract.submitZKPResponse.populateTransaction(...txArgs);
|
|
76
105
|
const request = {
|
|
77
|
-
to: txData.
|
|
78
|
-
data:
|
|
79
|
-
gasLimit,
|
|
106
|
+
to: txData.contract_address,
|
|
107
|
+
data: payload.data,
|
|
80
108
|
maxFeePerGas,
|
|
81
109
|
maxPriorityFeePerGas
|
|
82
110
|
};
|
|
111
|
+
let gasLimit;
|
|
112
|
+
try {
|
|
113
|
+
gasLimit = await ethSigner.estimateGas(request);
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
gasLimit = maxGasLimit;
|
|
117
|
+
}
|
|
118
|
+
request.gasLimit = gasLimit;
|
|
83
119
|
const transactionService = new blockchain_1.TransactionService(provider);
|
|
84
120
|
const { txnHash } = await transactionService.sendTransactionRequest(ethSigner, request);
|
|
85
|
-
response.set(txnHash,
|
|
121
|
+
response.set(txnHash, zkProofResponse);
|
|
86
122
|
}
|
|
87
123
|
return response;
|
|
88
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* {@inheritDoc IOnChainZKPVerifier.submitZKPResponseV2}
|
|
127
|
+
*/
|
|
128
|
+
async submitZKPResponseV2(ethSigner, txData, zkProofResponses) {
|
|
129
|
+
const chainConfig = this._configs.find((i) => i.chainId == txData.chain_id);
|
|
130
|
+
if (!chainConfig) {
|
|
131
|
+
throw new Error(`config for chain id ${txData.chain_id} was not found`);
|
|
132
|
+
}
|
|
133
|
+
if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV2) {
|
|
134
|
+
throw new Error(`submitZKPResponseV2 function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV2}' is supported.`);
|
|
135
|
+
}
|
|
136
|
+
if (!this._opts?.didResolverUrl) {
|
|
137
|
+
throw new Error(`did resolver url required for crosschain verification`);
|
|
138
|
+
}
|
|
139
|
+
const provider = new ethers_1.JsonRpcProvider(chainConfig.url, chainConfig.chainId);
|
|
140
|
+
ethSigner = ethSigner.connect(provider);
|
|
141
|
+
const txDataArgs = await this.prepareTxArgsSubmitV2(txData, zkProofResponses);
|
|
142
|
+
const feeData = await provider.getFeeData();
|
|
143
|
+
const maxFeePerGas = chainConfig.maxFeePerGas
|
|
144
|
+
? BigInt(chainConfig.maxFeePerGas)
|
|
145
|
+
: feeData.maxFeePerGas;
|
|
146
|
+
const maxPriorityFeePerGas = chainConfig.maxPriorityFeePerGas
|
|
147
|
+
? BigInt(chainConfig.maxPriorityFeePerGas)
|
|
148
|
+
: feeData.maxPriorityFeePerGas;
|
|
149
|
+
const verifierContract = new ethers_1.Contract(txData.contract_address, ZkpVerifier_json_1.default);
|
|
150
|
+
const txRequestData = await verifierContract.submitZKPResponseV2.populateTransaction(...txDataArgs);
|
|
151
|
+
const request = {
|
|
152
|
+
to: txData.contract_address,
|
|
153
|
+
data: txRequestData.data,
|
|
154
|
+
maxFeePerGas,
|
|
155
|
+
maxPriorityFeePerGas
|
|
156
|
+
};
|
|
157
|
+
let gasLimit;
|
|
158
|
+
try {
|
|
159
|
+
gasLimit = await ethSigner.estimateGas(request);
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
gasLimit = maxGasLimit;
|
|
163
|
+
}
|
|
164
|
+
request.gasLimit = gasLimit;
|
|
165
|
+
const transactionService = new blockchain_1.TransactionService(provider);
|
|
166
|
+
const { txnHash } = await transactionService.sendTransactionRequest(ethSigner, request);
|
|
167
|
+
return new Map().set(txnHash, zkProofResponses);
|
|
168
|
+
}
|
|
169
|
+
async prepareTxArgsSubmitV2(txData, zkProofResponses) {
|
|
170
|
+
if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV2) {
|
|
171
|
+
throw new Error(`submit cross chain doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV2}' is supported.`);
|
|
172
|
+
}
|
|
173
|
+
if (!this._opts?.didResolverUrl) {
|
|
174
|
+
throw new Error(`did resolver url required for crosschain verification`);
|
|
175
|
+
}
|
|
176
|
+
const gistUpdateArr = [];
|
|
177
|
+
const stateUpdateArr = [];
|
|
178
|
+
const payload = [];
|
|
179
|
+
// Resolved gists and states to avoid duplicate requests
|
|
180
|
+
const gistUpdateResolutionsPending = [];
|
|
181
|
+
const stateUpdateResolutionsPending = [];
|
|
182
|
+
for (const zkProof of zkProofResponses) {
|
|
183
|
+
const requestID = zkProof.id;
|
|
184
|
+
const inputs = zkProof.pub_signals;
|
|
185
|
+
if (!this._supportedCircuits.includes(zkProof.circuitId)) {
|
|
186
|
+
throw new Error(`Circuit ${zkProof.circuitId} not supported by OnChainZKPVerifier`);
|
|
187
|
+
}
|
|
188
|
+
const zkProofEncoded = this.packZkpProof(inputs, zkProof.proof.pi_a.slice(0, 2), [
|
|
189
|
+
[zkProof.proof.pi_b[0][1], zkProof.proof.pi_b[0][0]],
|
|
190
|
+
[zkProof.proof.pi_b[1][1], zkProof.proof.pi_b[1][0]]
|
|
191
|
+
], zkProof.proof.pi_c.slice(0, 2));
|
|
192
|
+
const stateInfo = this.getOnChainGistRootStatePubSignals(zkProof.circuitId, zkProof.pub_signals);
|
|
193
|
+
const gistUpdateResolutions = [];
|
|
194
|
+
for (const gist of stateInfo.gists) {
|
|
195
|
+
const gistResolutionPending = gistUpdateResolutionsPending.find((g) => g == JSON.stringify(gist));
|
|
196
|
+
if (gistResolutionPending) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
gistUpdateResolutionsPending.push(JSON.stringify(gist));
|
|
200
|
+
gistUpdateResolutions.push(this.resolveDidDocumentEip712MessageAndSignature(js_iden3_core_1.DID.parseFromId(gist.id), this._opts.didResolverUrl, { gist: gist.root }));
|
|
201
|
+
}
|
|
202
|
+
const stateUpdateResolutions = [];
|
|
203
|
+
for (const state of stateInfo.states) {
|
|
204
|
+
const stateResolutionPending = stateUpdateResolutionsPending.find((s) => s == JSON.stringify(state));
|
|
205
|
+
if (stateResolutionPending) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
stateUpdateResolutionsPending.push(JSON.stringify(state));
|
|
209
|
+
stateUpdateResolutions.push(this.resolveDidDocumentEip712MessageAndSignature(js_iden3_core_1.DID.parseFromId(state.id), this._opts.didResolverUrl, {
|
|
210
|
+
state: state.state
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
if (gistUpdateResolutions.length > 0) {
|
|
214
|
+
gistUpdateArr.push(...(await Promise.all(gistUpdateResolutions)));
|
|
215
|
+
}
|
|
216
|
+
if (stateUpdateResolutions.length > 0) {
|
|
217
|
+
stateUpdateArr.push(...(await Promise.all(stateUpdateResolutions)));
|
|
218
|
+
}
|
|
219
|
+
const metadataArr = [];
|
|
220
|
+
if (zkProof.vp) {
|
|
221
|
+
for (const key in zkProof.vp.verifiableCredential.credentialSubject) {
|
|
222
|
+
if (key === '@type') {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const metadataValue = js_crypto_1.poseidon.hashBytes(utils_1.byteEncoder.encode(JSON.stringify(zkProof.vp.verifiableCredential.credentialSubject[key])));
|
|
226
|
+
const bytesValue = utils_1.byteEncoder.encode(metadataValue.toString());
|
|
227
|
+
metadataArr.push({
|
|
228
|
+
key,
|
|
229
|
+
value: bytesValue
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const metadata = this.packMetadatas(metadataArr);
|
|
234
|
+
payload.push({
|
|
235
|
+
requestId: requestID,
|
|
236
|
+
zkProof: zkProofEncoded,
|
|
237
|
+
data: metadata
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const crossChainProofs = this.packCrossChainProofs(gistUpdateArr, stateUpdateArr);
|
|
241
|
+
return [payload, crossChainProofs];
|
|
242
|
+
}
|
|
243
|
+
packZkpProof(inputs, a, b, c) {
|
|
244
|
+
return this._abiCoder.encode(['uint256[] inputs', 'uint256[2]', 'uint256[2][2]', 'uint256[2]'], [inputs, a, b, c]);
|
|
245
|
+
}
|
|
246
|
+
packCrossChainProofs(gistUpdateArr, stateUpdateArr) {
|
|
247
|
+
const proofs = [];
|
|
248
|
+
for (const globalStateUpdate of gistUpdateArr) {
|
|
249
|
+
proofs.push({
|
|
250
|
+
proofType: 'globalStateProof',
|
|
251
|
+
proof: this.packGlobalStateMsg(globalStateUpdate)
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
for (const stateUpdate of stateUpdateArr) {
|
|
255
|
+
proofs.push({
|
|
256
|
+
proofType: 'stateProof',
|
|
257
|
+
proof: this.packIdentityStateMsg(stateUpdate)
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return this._abiCoder.encode(['tuple(' + 'string proofType,' + 'bytes proof' + ')[]'], [proofs]);
|
|
261
|
+
}
|
|
262
|
+
packGlobalStateMsg(msg) {
|
|
263
|
+
return this._abiCoder.encode([
|
|
264
|
+
'tuple(' +
|
|
265
|
+
'tuple(' +
|
|
266
|
+
'uint256 timestamp,' +
|
|
267
|
+
'bytes2 idType,' +
|
|
268
|
+
'uint256 root,' +
|
|
269
|
+
'uint256 replacedAtTimestamp' +
|
|
270
|
+
') globalStateMsg,' +
|
|
271
|
+
'bytes signature,' +
|
|
272
|
+
')'
|
|
273
|
+
], [msg]);
|
|
274
|
+
}
|
|
275
|
+
packIdentityStateMsg(msg) {
|
|
276
|
+
return this._abiCoder.encode([
|
|
277
|
+
'tuple(' +
|
|
278
|
+
'tuple(' +
|
|
279
|
+
'uint256 timestamp,' +
|
|
280
|
+
'uint256 id,' +
|
|
281
|
+
'uint256 state,' +
|
|
282
|
+
'uint256 replacedAtTimestamp' +
|
|
283
|
+
') idStateMsg,' +
|
|
284
|
+
'bytes signature,' +
|
|
285
|
+
')'
|
|
286
|
+
], [msg]);
|
|
287
|
+
}
|
|
288
|
+
packMetadatas(metas) {
|
|
289
|
+
return this._abiCoder.encode(['tuple(' + 'string key,' + 'bytes value' + ')[]'], [metas]);
|
|
290
|
+
}
|
|
291
|
+
getOnChainGistRootStatePubSignals(onChainCircuitId, inputs) {
|
|
292
|
+
let atomicQueryPubSignals;
|
|
293
|
+
switch (onChainCircuitId) {
|
|
294
|
+
case circuits_1.CircuitId.AtomicQueryMTPV2OnChain:
|
|
295
|
+
atomicQueryPubSignals = new circuits_1.AtomicQueryMTPV2OnChainPubSignals();
|
|
296
|
+
break;
|
|
297
|
+
case circuits_1.CircuitId.AtomicQuerySigV2OnChain:
|
|
298
|
+
atomicQueryPubSignals = new circuits_1.AtomicQuerySigV2OnChainPubSignals();
|
|
299
|
+
break;
|
|
300
|
+
case circuits_1.CircuitId.AtomicQueryV3OnChain:
|
|
301
|
+
atomicQueryPubSignals = new circuits_1.AtomicQueryV3OnChainPubSignals();
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
const encodedInputs = utils_1.byteEncoder.encode(JSON.stringify(inputs));
|
|
305
|
+
atomicQueryPubSignals.pubSignalsUnmarshal(encodedInputs);
|
|
306
|
+
return atomicQueryPubSignals.getStatesInfo();
|
|
307
|
+
}
|
|
308
|
+
async resolveDidDocumentEip712MessageAndSignature(did, resolverUrl, opts) {
|
|
309
|
+
const didDoc = await (0, utils_1.resolveDidDocument)(did, resolverUrl, {
|
|
310
|
+
...opts,
|
|
311
|
+
signature: utils_1.DIDDocumentSignature.EthereumEip712Signature2021
|
|
312
|
+
});
|
|
313
|
+
if (!didDoc.didResolutionMetadata.proof?.length) {
|
|
314
|
+
throw new Error('No proof found in resolved DID document');
|
|
315
|
+
}
|
|
316
|
+
const message = didDoc.didResolutionMetadata.proof[0].eip712.message;
|
|
317
|
+
const signature = didDoc.didResolutionMetadata.proof[0].proofValue;
|
|
318
|
+
const isGistRequest = opts?.gist && !opts.state;
|
|
319
|
+
if (isGistRequest) {
|
|
320
|
+
return {
|
|
321
|
+
globalStateMsg: {
|
|
322
|
+
timestamp: message.timestamp,
|
|
323
|
+
idType: message.idType,
|
|
324
|
+
root: message.root,
|
|
325
|
+
replacedAtTimestamp: message.replacedAtTimestamp
|
|
326
|
+
},
|
|
327
|
+
signature
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
idStateMsg: {
|
|
332
|
+
timestamp: message.timestamp,
|
|
333
|
+
id: message.id,
|
|
334
|
+
state: message.state,
|
|
335
|
+
replacedAtTimestamp: message.replacedAtTimestamp
|
|
336
|
+
},
|
|
337
|
+
signature
|
|
338
|
+
};
|
|
339
|
+
}
|
|
89
340
|
}
|
|
90
341
|
exports.OnChainZKPVerifier = OnChainZKPVerifier;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildDIDFromEthPubKey = exports.resolveDIDDocumentAuth = exports.validateDIDDocumentAuth = exports.buildVerifierId = exports.isEthereumIdentity = exports.isGenesisState = void 0;
|
|
3
|
+
exports.buildDIDFromEthPubKey = exports.resolveDidDocument = exports.resolveDIDDocumentAuth = exports.validateDIDDocumentAuth = exports.buildVerifierId = exports.isEthereumIdentity = exports.isGenesisState = exports.DIDDocumentSignature = 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");
|
|
7
7
|
const js_sha3_1 = require("js-sha3");
|
|
8
8
|
const encoding_1 = require("./encoding");
|
|
9
|
+
/**
|
|
10
|
+
* Supported DID Document Signatures
|
|
11
|
+
*/
|
|
12
|
+
var DIDDocumentSignature;
|
|
13
|
+
(function (DIDDocumentSignature) {
|
|
14
|
+
DIDDocumentSignature["EthereumEip712Signature2021"] = "EthereumEip712Signature2021";
|
|
15
|
+
})(DIDDocumentSignature = exports.DIDDocumentSignature || (exports.DIDDocumentSignature = {}));
|
|
9
16
|
/**
|
|
10
17
|
* Checks if state is genesis state
|
|
11
18
|
*
|
|
@@ -74,6 +81,35 @@ const resolveDIDDocumentAuth = async (did, resolveURL, state) => {
|
|
|
74
81
|
return didResolutionRes.didDocument?.verificationMethod?.find((i) => i.type === 'Iden3StateInfo2023');
|
|
75
82
|
};
|
|
76
83
|
exports.resolveDIDDocumentAuth = resolveDIDDocumentAuth;
|
|
84
|
+
function emptyStateDID(did) {
|
|
85
|
+
const id = js_iden3_core_1.DID.idFromDID(did);
|
|
86
|
+
const didType = (0, js_iden3_core_1.buildDIDType)(js_iden3_core_1.DID.methodFromId(id), js_iden3_core_1.DID.blockchainFromId(id), js_iden3_core_1.DID.networkIdFromId(id));
|
|
87
|
+
const identifier = js_iden3_core_1.Id.idGenesisFromIdenState(didType, 0n);
|
|
88
|
+
const emptyDID = js_iden3_core_1.DID.parseFromId(identifier);
|
|
89
|
+
return emptyDID;
|
|
90
|
+
}
|
|
91
|
+
const resolveDidDocument = async (did, resolverUrl, opts) => {
|
|
92
|
+
let didString = did.string().replace(/:/g, '%3A');
|
|
93
|
+
// for gist resolve we have to `hide` user did (look into resolver implementation)
|
|
94
|
+
const isGistRequest = opts?.gist && !opts.state;
|
|
95
|
+
if (isGistRequest) {
|
|
96
|
+
didString = emptyStateDID(did).string();
|
|
97
|
+
}
|
|
98
|
+
let url = `${resolverUrl}/1.0/identifiers/${didString}`;
|
|
99
|
+
if (opts?.signature) {
|
|
100
|
+
url += `?signature=${opts.signature}`;
|
|
101
|
+
}
|
|
102
|
+
if (opts?.state) {
|
|
103
|
+
url += `${url.includes('?') ? '&' : '?'}state=${opts.state.hex()}`;
|
|
104
|
+
}
|
|
105
|
+
if (opts?.gist) {
|
|
106
|
+
url += `${url.includes('?') ? '&' : '?'}gist=${opts.gist.hex()}`;
|
|
107
|
+
}
|
|
108
|
+
const resp = await fetch(url);
|
|
109
|
+
const data = await resp.json();
|
|
110
|
+
return data;
|
|
111
|
+
};
|
|
112
|
+
exports.resolveDidDocument = resolveDidDocument;
|
|
77
113
|
const buildDIDFromEthPubKey = (didType, pubKeyEth) => {
|
|
78
114
|
// Use Keccak-256 hash function to get public key hash
|
|
79
115
|
const hashOfPublicKey = (0, js_sha3_1.keccak256)((0, encoding_1.hexToBytes)(pubKeyEth));
|
|
@@ -177,4 +177,14 @@ export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig {
|
|
|
177
177
|
fieldIdx++;
|
|
178
178
|
return this;
|
|
179
179
|
}
|
|
180
|
+
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
|
|
181
|
+
getStatesInfo() {
|
|
182
|
+
return {
|
|
183
|
+
states: [
|
|
184
|
+
{ id: this.issuerID, state: this.issuerClaimIdenState },
|
|
185
|
+
{ id: this.issuerID, state: this.issuerClaimNonRevState }
|
|
186
|
+
],
|
|
187
|
+
gists: [{ id: this.userID, root: this.gistRoot }]
|
|
188
|
+
};
|
|
189
|
+
}
|
|
180
190
|
}
|
|
@@ -226,4 +226,14 @@ export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig {
|
|
|
226
226
|
fieldIdx++;
|
|
227
227
|
return this;
|
|
228
228
|
}
|
|
229
|
+
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
|
|
230
|
+
getStatesInfo() {
|
|
231
|
+
return {
|
|
232
|
+
states: [
|
|
233
|
+
{ id: this.issuerID, state: this.issuerAuthState },
|
|
234
|
+
{ id: this.issuerID, state: this.issuerClaimNonRevState }
|
|
235
|
+
],
|
|
236
|
+
gists: [{ id: this.userID, root: this.gistRoot }]
|
|
237
|
+
};
|
|
238
|
+
}
|
|
229
239
|
}
|
|
@@ -303,4 +303,14 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
|
|
|
303
303
|
this.isBJJAuthEnabled = parseInt(sVals[fieldIdx]);
|
|
304
304
|
return this;
|
|
305
305
|
}
|
|
306
|
+
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
|
|
307
|
+
getStatesInfo() {
|
|
308
|
+
return {
|
|
309
|
+
states: [
|
|
310
|
+
{ id: this.issuerID, state: this.issuerState },
|
|
311
|
+
{ id: this.issuerID, state: this.issuerClaimNonRevState }
|
|
312
|
+
],
|
|
313
|
+
gists: [{ id: this.userID, root: this.gistRoot }]
|
|
314
|
+
};
|
|
315
|
+
}
|
|
306
316
|
}
|
|
@@ -31,6 +31,8 @@ export const PROTOCOL_MESSAGE_TYPE = Object.freeze({
|
|
|
31
31
|
REVOCATION_STATUS_RESPONSE_MESSAGE_TYPE: `${IDEN3_PROTOCOL}revocation/1.0/status`,
|
|
32
32
|
// ContractInvokeRequestMessageType is type for request of contract invoke request
|
|
33
33
|
CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: `${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-request`,
|
|
34
|
+
// ContractInvokeResponseMessageType is type for response of contract invoke request
|
|
35
|
+
CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE: `${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-response`,
|
|
34
36
|
// CredentialOnchainOfferMessageType is type of message with credential onchain offering
|
|
35
37
|
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/1.0/onchain-offer`,
|
|
36
38
|
// ProposalRequestMessageType is type for proposal-request message
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CircuitId } from '../../circuits/models';
|
|
2
2
|
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
|
|
3
3
|
import { DID, ChainIds } from '@iden3/js-iden3-core';
|
|
4
|
+
import { FunctionSignatures } from '../../storage';
|
|
4
5
|
import { processZeroKnowledgeProofRequests } from './common';
|
|
5
6
|
import { AbstractMessageHandler } from './message-handler';
|
|
6
7
|
/**
|
|
@@ -33,9 +34,11 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
33
34
|
}
|
|
34
35
|
async handle(message, ctx) {
|
|
35
36
|
switch (message.type) {
|
|
36
|
-
case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE:
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: {
|
|
38
|
+
const ciMessage = message;
|
|
39
|
+
const txHashResponsesMap = await this.handleContractInvoke(ciMessage, ctx);
|
|
40
|
+
return this.createContractInvokeResponse(ciMessage, txHashResponsesMap);
|
|
41
|
+
}
|
|
39
42
|
default:
|
|
40
43
|
return super.handle(message, ctx);
|
|
41
44
|
}
|
|
@@ -55,7 +58,21 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
55
58
|
}
|
|
56
59
|
const verifierDid = message.from ? DID.parse(message.from) : undefined;
|
|
57
60
|
const zkpResponses = await processZeroKnowledgeProofRequests(did, message?.body?.scope, verifierDid, this._proofService, { ethSigner, challenge, supportedCircuits: this._supportedCircuits });
|
|
58
|
-
|
|
61
|
+
const methodId = message.body.transaction_data.method_id.replace('0x', '');
|
|
62
|
+
switch (methodId) {
|
|
63
|
+
case FunctionSignatures.SubmitZKPResponseV2:
|
|
64
|
+
return this._zkpVerifier.submitZKPResponseV2(ethSigner, message.body.transaction_data, zkpResponses);
|
|
65
|
+
case FunctionSignatures.SubmitZKPResponseV1: {
|
|
66
|
+
const txHashZkpResponseMap = await this._zkpVerifier.submitZKPResponse(ethSigner, message.body.transaction_data, zkpResponses);
|
|
67
|
+
const response = new Map();
|
|
68
|
+
for (const [txHash, zkpResponse] of txHashZkpResponseMap) {
|
|
69
|
+
response.set(txHash, [zkpResponse]);
|
|
70
|
+
}
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
73
|
+
default:
|
|
74
|
+
throw new Error(`Not supported method id. Only '${FunctionSignatures.SubmitZKPResponseV1} and ${FunctionSignatures.SubmitZKPResponseV2} are supported.'`);
|
|
75
|
+
}
|
|
59
76
|
}
|
|
60
77
|
/**
|
|
61
78
|
* unpacks contract-invoke request
|
|
@@ -73,8 +90,41 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
73
90
|
return ciRequest;
|
|
74
91
|
}
|
|
75
92
|
/**
|
|
76
|
-
*
|
|
93
|
+
* creates contract invoke response
|
|
94
|
+
* @private
|
|
95
|
+
* @beta
|
|
96
|
+
* @param {ContractInvokeRequest} request - ContractInvokeRequest
|
|
97
|
+
* @param { Map<string, ZeroKnowledgeProofResponse[]>} responses - map tx hash to array of ZeroKnowledgeProofResponses
|
|
98
|
+
* @returns `Promise<ContractInvokeResponse>`
|
|
99
|
+
*/
|
|
100
|
+
async createContractInvokeResponse(request, txHashToZkpResponseMap) {
|
|
101
|
+
const contractInvokeResponse = {
|
|
102
|
+
id: request.id,
|
|
103
|
+
thid: request.thid,
|
|
104
|
+
type: PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE,
|
|
105
|
+
from: request.to,
|
|
106
|
+
to: request.from,
|
|
107
|
+
body: {
|
|
108
|
+
transaction_data: request.body.transaction_data,
|
|
109
|
+
reason: request.body.reason,
|
|
110
|
+
scope: []
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
for (const [txHash, zkpResponses] of txHashToZkpResponseMap) {
|
|
114
|
+
for (const zkpResponse of zkpResponses) {
|
|
115
|
+
contractInvokeResponse.body.scope.push({
|
|
116
|
+
txHash,
|
|
117
|
+
...zkpResponse
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return contractInvokeResponse;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* handle contract invoke request
|
|
125
|
+
* supports only 0xb68967e2 method id
|
|
77
126
|
* @beta
|
|
127
|
+
* @deprecated
|
|
78
128
|
* @param {did} did - sender DID
|
|
79
129
|
* @param {ContractInvokeRequest} request - contract invoke request
|
|
80
130
|
* @param {ContractInvokeHandlerOptions} opts - handler options
|
|
@@ -82,10 +132,23 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
82
132
|
*/
|
|
83
133
|
async handleContractInvokeRequest(did, request, opts) {
|
|
84
134
|
const ciRequest = await this.parseContractInvokeRequest(request);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
135
|
+
if (ciRequest.body.transaction_data.method_id !== FunctionSignatures.SubmitZKPResponseV1) {
|
|
136
|
+
throw new Error(`please use handle method to work with other method ids`);
|
|
137
|
+
}
|
|
138
|
+
if (ciRequest.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
|
|
139
|
+
throw new Error('Invalid message type for contract invoke request');
|
|
140
|
+
}
|
|
141
|
+
const { ethSigner, challenge } = opts;
|
|
142
|
+
if (!ethSigner) {
|
|
143
|
+
throw new Error("Can't sign transaction. Provide Signer in options.");
|
|
144
|
+
}
|
|
145
|
+
const { chain_id } = ciRequest.body.transaction_data;
|
|
146
|
+
const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
|
|
147
|
+
if (!networkFlag) {
|
|
148
|
+
throw new Error(`Invalid chain id ${chain_id}`);
|
|
149
|
+
}
|
|
150
|
+
const verifierDid = ciRequest.from ? DID.parse(ciRequest.from) : undefined;
|
|
151
|
+
const zkpResponses = await processZeroKnowledgeProofRequests(did, ciRequest?.body?.scope, verifierDid, this._proofService, { ethSigner, challenge, supportedCircuits: this._supportedCircuits });
|
|
152
|
+
return this._zkpVerifier.submitZKPResponse(ethSigner, ciRequest.body.transaction_data, zkpResponses);
|
|
90
153
|
}
|
|
91
154
|
}
|