@0xpolygonid/js-sdk 1.29.1 → 1.29.3
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 +8999 -8916
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +9000 -8913
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/iden3comm/handlers/common.js +76 -23
- package/dist/node/cjs/iden3comm/handlers/contract-request.js +15 -7
- package/dist/node/cjs/iden3comm/utils/index.js +0 -1
- package/dist/node/cjs/proof/proof-service.js +0 -1
- package/dist/node/cjs/storage/blockchain/common.js +19 -0
- package/dist/node/cjs/storage/blockchain/onchain-zkp-verifier.js +122 -94
- package/dist/node/cjs/storage/blockchain/state.js +2 -2
- package/dist/node/esm/iden3comm/handlers/common.js +75 -24
- package/dist/node/esm/iden3comm/handlers/contract-request.js +16 -8
- package/dist/node/esm/iden3comm/utils/index.js +0 -1
- package/dist/node/esm/proof/proof-service.js +0 -1
- package/dist/node/esm/storage/blockchain/common.js +14 -0
- package/dist/node/esm/storage/blockchain/onchain-zkp-verifier.js +120 -94
- package/dist/node/esm/storage/blockchain/state.js +1 -1
- package/dist/types/iden3comm/handlers/common.d.ts +32 -5
- package/dist/types/iden3comm/types/protocol/auth.d.ts +3 -3
- package/dist/types/iden3comm/types/protocol/contract-request.d.ts +17 -5
- package/dist/types/iden3comm/utils/index.d.ts +0 -1
- package/dist/types/proof/proof-service.d.ts +3 -3
- package/dist/types/proof/provers/inputs-generator.d.ts +3 -0
- package/dist/types/storage/blockchain/common.d.ts +7 -0
- package/dist/types/storage/blockchain/onchain-zkp-verifier.d.ts +45 -6
- package/dist/types/storage/interfaces/onchain-zkp-verifier.d.ts +9 -4
- package/package.json +1 -1
- package/dist/node/cjs/iden3comm/utils/contract-request.utils.js +0 -74
- package/dist/node/esm/iden3comm/utils/contract-request.utils.js +0 -67
- package/dist/types/iden3comm/utils/contract-request.utils.d.ts +0 -27
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { getRandomBytes } from '@iden3/js-crypto';
|
|
1
|
+
import { getRandomBytes, poseidon } from '@iden3/js-crypto';
|
|
2
2
|
import { AuthMethod } from '../types';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { CircuitId } from '../../circuits';
|
|
3
|
+
import { byteEncoder, mergeObjects } from '../../utils';
|
|
4
|
+
import { getUnixTimestamp } from '@iden3/js-iden3-core';
|
|
6
5
|
import { AcceptJwsAlgorithms, defaultAcceptProfile, MediaType } from '../constants';
|
|
7
|
-
import {
|
|
6
|
+
import { ethers } from 'ethers';
|
|
7
|
+
import { packZkpProof, prepareZkpProof } from '../../storage/blockchain/common';
|
|
8
8
|
/**
|
|
9
9
|
* Groups the ZeroKnowledgeProofRequest objects based on their groupId.
|
|
10
10
|
* Returns a Map where the key is the groupId and the value is an object containing the query and linkNonce.
|
|
@@ -96,9 +96,6 @@ export const processProofAuth = async (to, proofService, opts) => {
|
|
|
96
96
|
if (!opts.acceptProfile) {
|
|
97
97
|
opts.acceptProfile = defaultAcceptProfile;
|
|
98
98
|
}
|
|
99
|
-
if (!opts.skipRevocation) {
|
|
100
|
-
opts.skipRevocation = true;
|
|
101
|
-
}
|
|
102
99
|
switch (opts.acceptProfile.env) {
|
|
103
100
|
case MediaType.ZKPMessage:
|
|
104
101
|
if (!opts.acceptProfile.circuits) {
|
|
@@ -108,17 +105,17 @@ export const processProofAuth = async (to, proofService, opts) => {
|
|
|
108
105
|
if (!opts.supportedCircuits.includes(circuitId)) {
|
|
109
106
|
throw new Error(`Circuit ${circuitId} is not supported`);
|
|
110
107
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
case CircuitId.AuthV2: {
|
|
114
|
-
const preparedZkpProof = prepareZkpProof(zkpRes.proof);
|
|
115
|
-
const zkProofEncoded = packZkpProof(zkpRes.pub_signals, preparedZkpProof.a, preparedZkpProof.b, preparedZkpProof.c);
|
|
116
|
-
return {
|
|
117
|
-
authMethod: AuthMethod.AUTHV2,
|
|
118
|
-
proof: zkProofEncoded
|
|
119
|
-
};
|
|
120
|
-
}
|
|
108
|
+
if (!opts.senderAddress) {
|
|
109
|
+
throw new Error('Sender address is not provided');
|
|
121
110
|
}
|
|
111
|
+
const challengeAuth = calcChallengeAuthV2(opts.senderAddress, opts.zkpResponses);
|
|
112
|
+
const zkpRes = await proofService.generateAuthProof(circuitId, to, { challenge: challengeAuth });
|
|
113
|
+
return {
|
|
114
|
+
authProof: {
|
|
115
|
+
authMethod: AuthMethod.AUTHV2,
|
|
116
|
+
zkp: zkpRes
|
|
117
|
+
}
|
|
118
|
+
};
|
|
122
119
|
}
|
|
123
120
|
throw new Error(`Auth method is not supported`);
|
|
124
121
|
case MediaType.SignedMessage:
|
|
@@ -126,10 +123,11 @@ export const processProofAuth = async (to, proofService, opts) => {
|
|
|
126
123
|
throw new Error('Algorithm not specified');
|
|
127
124
|
}
|
|
128
125
|
if (opts.acceptProfile.alg[0] === AcceptJwsAlgorithms.ES256KR) {
|
|
129
|
-
const ethIdProof = packEthIdentityProof(to);
|
|
130
126
|
return {
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
authProof: {
|
|
128
|
+
authMethod: AuthMethod.ETH_IDENTITY,
|
|
129
|
+
userDid: to
|
|
130
|
+
}
|
|
133
131
|
};
|
|
134
132
|
}
|
|
135
133
|
throw new Error(`Algorithm ${opts.acceptProfile.alg[0]} not supported`);
|
|
@@ -137,6 +135,62 @@ export const processProofAuth = async (to, proofService, opts) => {
|
|
|
137
135
|
throw new Error('Accept env not supported');
|
|
138
136
|
}
|
|
139
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* Processes a ZeroKnowledgeProofResponse object and prepares it for further use.
|
|
140
|
+
* @param zkProof - The ZeroKnowledgeProofResponse object containing the proof data.
|
|
141
|
+
* @returns An object containing the requestId, zkProofEncoded, and metadata.
|
|
142
|
+
*/
|
|
143
|
+
export const processProofResponse = (zkProof) => {
|
|
144
|
+
const requestId = zkProof.id;
|
|
145
|
+
const inputs = zkProof.pub_signals;
|
|
146
|
+
const emptyBytes = '0x';
|
|
147
|
+
if (inputs.length === 0) {
|
|
148
|
+
return { requestId, zkProofEncoded: emptyBytes, metadata: emptyBytes };
|
|
149
|
+
}
|
|
150
|
+
const preparedZkpProof = prepareZkpProof(zkProof.proof);
|
|
151
|
+
const zkProofEncoded = packZkpProof(inputs, preparedZkpProof.a, preparedZkpProof.b, preparedZkpProof.c);
|
|
152
|
+
const metadataArr = [];
|
|
153
|
+
if (zkProof.vp) {
|
|
154
|
+
for (const key in zkProof.vp.verifiableCredential.credentialSubject) {
|
|
155
|
+
if (key === '@type') {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const metadataValue = poseidon.hashBytes(byteEncoder.encode(JSON.stringify(zkProof.vp.verifiableCredential.credentialSubject[key])));
|
|
159
|
+
const bytesValue = byteEncoder.encode(metadataValue.toString());
|
|
160
|
+
metadataArr.push({
|
|
161
|
+
key,
|
|
162
|
+
value: bytesValue
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const metadata = metadataArr.length ? packMetadatas(metadataArr) : emptyBytes;
|
|
167
|
+
return { requestId, zkProofEncoded, metadata };
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Calculates the challenge authentication V2 value.
|
|
171
|
+
* @param senderAddress - The address of the sender.
|
|
172
|
+
* @param zkpResponses - An array of ZeroKnowledgeProofResponse objects.
|
|
173
|
+
* @returns A bigint representing the challenge authentication value.
|
|
174
|
+
*/
|
|
175
|
+
export const calcChallengeAuthV2 = (senderAddress, zkpResponses) => {
|
|
176
|
+
const responses = zkpResponses.map((zkpResponse) => {
|
|
177
|
+
const response = processProofResponse(zkpResponse);
|
|
178
|
+
return {
|
|
179
|
+
requestId: response.requestId,
|
|
180
|
+
proof: response.zkProofEncoded,
|
|
181
|
+
metadata: response.metadata
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
return (BigInt(ethers.keccak256(new ethers.AbiCoder().encode(['address', '(uint256 requestId,bytes proof,bytes metadata)[]'], [senderAddress, responses]))) & BigInt('0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'));
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Packs metadata into a string format suitable for encoding in a transaction.
|
|
188
|
+
* @param metas - An array of objects containing key-value pairs to be packed.
|
|
189
|
+
* @returns A string representing the packed metadata.
|
|
190
|
+
*/
|
|
191
|
+
export const packMetadatas = (metas) => {
|
|
192
|
+
return new ethers.AbiCoder().encode(['tuple(' + 'string key,' + 'bytes value' + ')[]'], [metas]);
|
|
193
|
+
};
|
|
140
194
|
/**
|
|
141
195
|
* Verifies that the expires_time field of a message is not in the past. Throws an error if it is.
|
|
142
196
|
*
|
|
@@ -147,6 +201,3 @@ export const verifyExpiresTime = (message) => {
|
|
|
147
201
|
throw new Error('Message expired');
|
|
148
202
|
}
|
|
149
203
|
};
|
|
150
|
-
export const packEthIdentityProof = (did) => {
|
|
151
|
-
return `0x${bytesToHex(BytesHelper.intToBytes(DID.idFromDID(did).bigInt()))}`;
|
|
152
|
-
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { CircuitId } from '../../circuits/models';
|
|
2
2
|
import { defaultAcceptProfile, PROTOCOL_MESSAGE_TYPE, ProtocolVersion } from '../constants';
|
|
3
|
-
import { DID, ChainIds, getUnixTimestamp } from '@iden3/js-iden3-core';
|
|
3
|
+
import { DID, ChainIds, getUnixTimestamp, BytesHelper } from '@iden3/js-iden3-core';
|
|
4
4
|
import { FunctionSignatures } from '../../storage';
|
|
5
5
|
import { processProofAuth, processZeroKnowledgeProofRequests, verifyExpiresTime } from './common';
|
|
6
6
|
import { AbstractMessageHandler } from './message-handler';
|
|
7
7
|
import { parseAcceptProfile } from '../utils';
|
|
8
|
+
import { hexToBytes } from '../../utils';
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
10
11
|
* Allows to process ContractInvokeRequest protocol message
|
|
@@ -68,7 +69,7 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
68
69
|
const { scope = [] } = message.body;
|
|
69
70
|
const zkpResponses = await processZeroKnowledgeProofRequests(did, scope, verifierDid, this._proofService, {
|
|
70
71
|
ethSigner,
|
|
71
|
-
challenge,
|
|
72
|
+
challenge: challenge ?? BytesHelper.bytesToInt(hexToBytes(await ethSigner.getAddress())),
|
|
72
73
|
supportedCircuits: this._supportedCircuits
|
|
73
74
|
});
|
|
74
75
|
const methodId = message.body.transaction_data.method_id.replace('0x', '');
|
|
@@ -79,6 +80,8 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
79
80
|
for (const [txHash, zkpResponses] of txHashZkpResponsesMap) {
|
|
80
81
|
response.set(txHash, { responses: zkpResponses });
|
|
81
82
|
}
|
|
83
|
+
// set txHash of the first response
|
|
84
|
+
message.body.transaction_data.txHash = txHashZkpResponsesMap.keys().next().value;
|
|
82
85
|
return response;
|
|
83
86
|
}
|
|
84
87
|
case FunctionSignatures.SubmitZKPResponseV1: {
|
|
@@ -87,6 +90,8 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
87
90
|
for (const [txHash, zkpResponse] of txHashZkpResponseMap) {
|
|
88
91
|
response.set(txHash, { responses: [zkpResponse] });
|
|
89
92
|
}
|
|
93
|
+
// set txHash of the first response
|
|
94
|
+
message.body.transaction_data.txHash = txHashZkpResponseMap.keys().next().value;
|
|
90
95
|
return response;
|
|
91
96
|
}
|
|
92
97
|
case FunctionSignatures.SubmitResponse: {
|
|
@@ -100,13 +105,16 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
100
105
|
// Get first supported accept profile and pass it to processProofAuth
|
|
101
106
|
const acceptProfile = this.getFirstSupportedProfile(PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE, message.body.accept);
|
|
102
107
|
const identifier = DID.parse(message.to);
|
|
103
|
-
const
|
|
108
|
+
const { authProof } = await processProofAuth(identifier, this._proofService, {
|
|
104
109
|
supportedCircuits: this._supportedCircuits,
|
|
105
110
|
acceptProfile,
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
senderAddress: await ethSigner.getAddress(),
|
|
112
|
+
zkpResponses: zkpResponses
|
|
108
113
|
});
|
|
109
|
-
return
|
|
114
|
+
// we return txHash because responsesMap could be empty if there are no queries in scope
|
|
115
|
+
const txHashZkpResponsesMap = await this._zkpVerifier.submitResponse(ethSigner, message.body.transaction_data, zkpResponses, authProof);
|
|
116
|
+
message.body.transaction_data.txHash = txHashZkpResponsesMap.keys().next().value;
|
|
117
|
+
return txHashZkpResponsesMap;
|
|
110
118
|
}
|
|
111
119
|
default:
|
|
112
120
|
throw new Error(`Not supported method id. Only '${FunctionSignatures.SubmitZKPResponseV1}, ${FunctionSignatures.SubmitZKPResponseV2} and ${FunctionSignatures.SubmitResponse} are supported.'`);
|
|
@@ -177,8 +185,8 @@ export class ContractRequestHandler extends AbstractMessageHandler {
|
|
|
177
185
|
}
|
|
178
186
|
contractInvokeResponse.body = {
|
|
179
187
|
...contractInvokeResponse.body,
|
|
180
|
-
|
|
181
|
-
|
|
188
|
+
crossChainProof: zkpResponses.crossChainProof,
|
|
189
|
+
authProof: zkpResponses.authProof
|
|
182
190
|
};
|
|
183
191
|
}
|
|
184
192
|
return contractInvokeResponse;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
export const packZkpProof = (inputs, a, b, c) => {
|
|
3
|
+
return new ethers.AbiCoder().encode(['uint256[] inputs', 'uint256[2]', 'uint256[2][2]', 'uint256[2]'], [inputs, a, b, c]);
|
|
4
|
+
};
|
|
5
|
+
export const prepareZkpProof = (proof) => {
|
|
6
|
+
return {
|
|
7
|
+
a: proof.pi_a.slice(0, 2),
|
|
8
|
+
b: [
|
|
9
|
+
[proof.pi_b[0][1], proof.pi_b[0][0]],
|
|
10
|
+
[proof.pi_b[1][1], proof.pi_b[1][0]]
|
|
11
|
+
],
|
|
12
|
+
c: proof.pi_c.slice(0, 2)
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { JsonRpcProvider, Contract, ethers } from 'ethers';
|
|
2
|
+
import { AuthMethod, processProofResponse } from '../../iden3comm';
|
|
2
3
|
import abi from './abi/ZkpVerifier.json';
|
|
3
4
|
//import { UniversalVerifier } from '@iden3/universal-verifier-v2-abi';
|
|
4
5
|
import { IVerifierABI } from '@iden3/universal-verifier-v2-abi';
|
|
5
6
|
import { TransactionService } from '../../blockchain';
|
|
6
|
-
import { chainIDfromDID, DID, Id } from '@iden3/js-iden3-core';
|
|
7
|
+
import { BytesHelper, chainIDfromDID, DID, Id } from '@iden3/js-iden3-core';
|
|
7
8
|
import { AtomicQueryMTPV2OnChainPubSignals, AtomicQuerySigV2OnChainPubSignals, AtomicQueryV3OnChainPubSignals, AuthV2PubSignals, CircuitId } from '../../circuits';
|
|
8
|
-
import { byteEncoder, DIDDocumentSignature, resolveDidDocument } from '../../utils';
|
|
9
|
-
import { poseidon } from '@iden3/js-crypto';
|
|
9
|
+
import { byteEncoder, bytesToHex, DIDDocumentSignature, resolveDidDocument } from '../../utils';
|
|
10
10
|
import { Hash } from '@iden3/js-merkletree';
|
|
11
|
-
import { packZkpProof, prepareZkpProof } from '
|
|
11
|
+
import { packZkpProof, prepareZkpProof } from './common';
|
|
12
12
|
const maxGasLimit = 10000000n;
|
|
13
13
|
/**
|
|
14
14
|
* Supported function signature for SubmitZKPResponse
|
|
@@ -26,6 +26,22 @@ export var FunctionSignatures;
|
|
|
26
26
|
//function submitResponse(tuple(string authMethod,bytes proof),tuple(uint256 requestId,bytes proof,bytes metadata)[],bytes crossChainProof)
|
|
27
27
|
FunctionSignatures["SubmitResponse"] = "06c86a91";
|
|
28
28
|
})(FunctionSignatures || (FunctionSignatures = {}));
|
|
29
|
+
export const toTxDataArgs = function (res) {
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
authMethod: res.authProof.raw.authMethod,
|
|
33
|
+
proof: res.authProof.encoded
|
|
34
|
+
},
|
|
35
|
+
res.proofs.map((p) => {
|
|
36
|
+
return {
|
|
37
|
+
requestId: p.requestId,
|
|
38
|
+
proof: p.encoded,
|
|
39
|
+
metadata: p.metadata
|
|
40
|
+
};
|
|
41
|
+
}),
|
|
42
|
+
res.crossChainProof.encoded
|
|
43
|
+
];
|
|
44
|
+
};
|
|
29
45
|
/**
|
|
30
46
|
* OnChainZKPVerifier is a class that allows to interact with the OnChainZKPVerifier contract
|
|
31
47
|
* and submitZKPResponse.
|
|
@@ -152,7 +168,7 @@ export class OnChainZKPVerifier {
|
|
|
152
168
|
/**
|
|
153
169
|
* {@inheritDoc IOnChainVerifierMultiQuery.submitResponse}
|
|
154
170
|
*/
|
|
155
|
-
async submitResponse(ethSigner, txData,
|
|
171
|
+
async submitResponse(ethSigner, txData, responses, authProof) {
|
|
156
172
|
const chainConfig = this._configs.find((i) => i.chainId == txData.chain_id);
|
|
157
173
|
if (!chainConfig) {
|
|
158
174
|
throw new Error(`config for chain id ${txData.chain_id} was not found`);
|
|
@@ -165,7 +181,7 @@ export class OnChainZKPVerifier {
|
|
|
165
181
|
}
|
|
166
182
|
const provider = new JsonRpcProvider(chainConfig.url, chainConfig.chainId);
|
|
167
183
|
ethSigner = ethSigner.connect(provider);
|
|
168
|
-
const
|
|
184
|
+
const txPreparationResult = await this.prepareTxArgsSubmit(txData, responses, authProof);
|
|
169
185
|
const feeData = await provider.getFeeData();
|
|
170
186
|
const maxFeePerGas = chainConfig.maxFeePerGas
|
|
171
187
|
? BigInt(chainConfig.maxFeePerGas)
|
|
@@ -174,7 +190,7 @@ export class OnChainZKPVerifier {
|
|
|
174
190
|
? BigInt(chainConfig.maxPriorityFeePerGas)
|
|
175
191
|
: feeData.maxPriorityFeePerGas;
|
|
176
192
|
const verifierContract = new Contract(txData.contract_address, IVerifierABI);
|
|
177
|
-
const txRequestData = await verifierContract.submitResponse.populateTransaction(...txDataArgs);
|
|
193
|
+
const txRequestData = await verifierContract.submitResponse.populateTransaction(...txPreparationResult.txDataArgs);
|
|
178
194
|
const request = {
|
|
179
195
|
to: txData.contract_address,
|
|
180
196
|
data: txRequestData.data,
|
|
@@ -193,35 +209,90 @@ export class OnChainZKPVerifier {
|
|
|
193
209
|
const { txnHash } = await transactionService.sendTransactionRequest(ethSigner, request);
|
|
194
210
|
// return multiple responses for all the responses (single and grouped)
|
|
195
211
|
return new Map().set(txnHash, {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
authProof: txPreparationResult.result.authProof.raw,
|
|
213
|
+
crossChainProof: txPreparationResult.result.crossChainProof.raw,
|
|
214
|
+
responses: txPreparationResult.result.proofs.map((m) => m.proof)
|
|
199
215
|
});
|
|
200
216
|
}
|
|
201
|
-
static async prepareTxArgsSubmit(resolverUrl, txData,
|
|
217
|
+
static async prepareTxArgsSubmit(resolverUrl, txData, responses, authProof) {
|
|
202
218
|
if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitResponse) {
|
|
203
219
|
throw new Error(`submit cross chain doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitResponse}' is supported.`);
|
|
204
220
|
}
|
|
205
|
-
const
|
|
206
|
-
const
|
|
221
|
+
const gistUpdatesArr = [];
|
|
222
|
+
const stateUpdatesArr = [];
|
|
207
223
|
const payloadResponses = [];
|
|
224
|
+
const emptyBytes = '0x';
|
|
225
|
+
let encodedAuthProof = '';
|
|
226
|
+
switch (authProof.authMethod) {
|
|
227
|
+
case AuthMethod.AUTHV2: {
|
|
228
|
+
const preparedZkpProof = prepareZkpProof(authProof.zkp.proof);
|
|
229
|
+
encodedAuthProof = packZkpProof(authProof.zkp.pub_signals, preparedZkpProof.a, preparedZkpProof.b, preparedZkpProof.c);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case AuthMethod.ETH_IDENTITY: {
|
|
233
|
+
encodedAuthProof = packEthIdentityProof(authProof.userDid);
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
default:
|
|
237
|
+
throw new Error('auth proof must use method AuthV2 or ethIdentity');
|
|
238
|
+
}
|
|
208
239
|
// Process all the responses
|
|
209
240
|
for (const zkProof of responses) {
|
|
210
|
-
|
|
241
|
+
this.checkSupportedCircuit(zkProof.circuitId);
|
|
242
|
+
const { requestId, zkProofEncoded, metadata } = processProofResponse(zkProof);
|
|
211
243
|
payloadResponses.push({
|
|
212
|
-
|
|
213
|
-
|
|
244
|
+
proof: zkProof,
|
|
245
|
+
requestId: requestId,
|
|
246
|
+
encoded: zkProofEncoded,
|
|
214
247
|
metadata: metadata
|
|
215
248
|
});
|
|
216
249
|
}
|
|
217
|
-
|
|
218
|
-
|
|
250
|
+
// Process all zkProofs and prepare cross chain proofs
|
|
251
|
+
const allZkProofs = responses.map((zkProof) => ({
|
|
252
|
+
circuitId: zkProof.circuitId,
|
|
253
|
+
pub_signals: zkProof.pub_signals
|
|
254
|
+
}));
|
|
255
|
+
if (authProof.authMethod == AuthMethod.AUTHV2) {
|
|
256
|
+
allZkProofs.push({
|
|
257
|
+
circuitId: authProof.zkp.circuitId,
|
|
258
|
+
pub_signals: authProof.zkp.pub_signals
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
for (const zkProof of allZkProofs) {
|
|
262
|
+
const { gistUpdateResolutions, stateUpdateResolutions } = this.getUpdateResolutions(resolverUrl, txData.chain_id, zkProof.circuitId, zkProof.pub_signals);
|
|
263
|
+
if (gistUpdateResolutions.length > 0) {
|
|
264
|
+
gistUpdatesArr.push(...(await Promise.all(gistUpdateResolutions)));
|
|
265
|
+
}
|
|
266
|
+
if (stateUpdateResolutions.length > 0) {
|
|
267
|
+
stateUpdatesArr.push(...(await Promise.all(stateUpdateResolutions)));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const encodedCrossChainProof = gistUpdatesArr.length || stateUpdatesArr.length
|
|
271
|
+
? this.packCrossChainProofs(gistUpdatesArr, stateUpdatesArr)
|
|
272
|
+
: emptyBytes;
|
|
273
|
+
const preparationResult = {
|
|
274
|
+
authProof: { raw: authProof, encoded: encodedAuthProof },
|
|
275
|
+
proofs: payloadResponses,
|
|
276
|
+
crossChainProof: {
|
|
277
|
+
raw: {
|
|
278
|
+
globalStateProofs: gistUpdatesArr || [],
|
|
279
|
+
identityStateProofs: stateUpdatesArr || []
|
|
280
|
+
},
|
|
281
|
+
encoded: encodedCrossChainProof
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
return { result: preparationResult, txDataArgs: toTxDataArgs(preparationResult) };
|
|
219
285
|
}
|
|
220
|
-
async prepareTxArgsSubmit(txData,
|
|
286
|
+
async prepareTxArgsSubmit(txData, responses, authProof) {
|
|
221
287
|
if (!this._opts?.didResolverUrl) {
|
|
222
288
|
throw new Error(`did resolver url required for crosschain verification`);
|
|
223
289
|
}
|
|
224
|
-
return OnChainZKPVerifier.prepareTxArgsSubmit(this._opts.didResolverUrl, txData,
|
|
290
|
+
return OnChainZKPVerifier.prepareTxArgsSubmit(this._opts.didResolverUrl, txData, responses, authProof);
|
|
291
|
+
}
|
|
292
|
+
static checkSupportedCircuit(circuitId) {
|
|
293
|
+
if (!this._supportedCircuits.includes(circuitId)) {
|
|
294
|
+
throw new Error(`Circuit ${circuitId} not supported by OnChainZKPVerifier`);
|
|
295
|
+
}
|
|
225
296
|
}
|
|
226
297
|
static getCrossChainResolvers(source, txDataChainId, type, didResolverUrl) {
|
|
227
298
|
return [
|
|
@@ -246,61 +317,30 @@ export class OnChainZKPVerifier {
|
|
|
246
317
|
if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV2) {
|
|
247
318
|
throw new Error(`submit cross chain doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV2}' is supported.`);
|
|
248
319
|
}
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
const
|
|
320
|
+
const gistUpdatesArr = [];
|
|
321
|
+
const stateUpdatesArr = [];
|
|
322
|
+
const payloadResponses = [];
|
|
252
323
|
const emptyBytes = '0x';
|
|
253
324
|
for (const zkProof of zkProofResponses) {
|
|
254
|
-
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
throw new Error(`Circuit ${zkProof.circuitId} not supported by OnChainZKPVerifier`);
|
|
258
|
-
}
|
|
259
|
-
if (inputs.length === 0) {
|
|
260
|
-
payload.push({
|
|
261
|
-
requestId: requestId,
|
|
262
|
-
zkProof: emptyBytes,
|
|
263
|
-
data: emptyBytes
|
|
264
|
-
});
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
const preparedZkpProof = prepareZkpProof(zkProof.proof);
|
|
268
|
-
const zkProofEncoded = packZkpProof(inputs, preparedZkpProof.a, preparedZkpProof.b, preparedZkpProof.c);
|
|
269
|
-
const stateInfo = this.getOnChainGistRootStatePubSignals(proofCircuitId, inputs);
|
|
270
|
-
const chainId = txData.chain_id;
|
|
271
|
-
const gistUpdateResolutions = this.getCrossChainResolvers(stateInfo.gists, chainId, 'gist', resolverUrl);
|
|
272
|
-
const stateUpdateResolutions = this.getCrossChainResolvers(stateInfo.states, chainId, 'state', resolverUrl);
|
|
273
|
-
if (gistUpdateResolutions.length > 0) {
|
|
274
|
-
gistUpdates.push(...(await Promise.all(gistUpdateResolutions)));
|
|
275
|
-
}
|
|
276
|
-
if (stateUpdateResolutions.length > 0) {
|
|
277
|
-
stateUpdates.push(...(await Promise.all(stateUpdateResolutions)));
|
|
278
|
-
}
|
|
279
|
-
const metadataArr = [];
|
|
280
|
-
if (zkProof.vp) {
|
|
281
|
-
for (const key in zkProof.vp.verifiableCredential.credentialSubject) {
|
|
282
|
-
if (key === '@type') {
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
const metadataValue = poseidon.hashBytes(byteEncoder.encode(JSON.stringify(zkProof.vp.verifiableCredential.credentialSubject[key])));
|
|
286
|
-
const bytesValue = byteEncoder.encode(metadataValue.toString());
|
|
287
|
-
metadataArr.push({
|
|
288
|
-
key,
|
|
289
|
-
value: bytesValue
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const metadata = metadataArr.length ? this.packMetadatas(metadataArr) : emptyBytes;
|
|
294
|
-
payload.push({
|
|
325
|
+
this.checkSupportedCircuit(zkProof.circuitId);
|
|
326
|
+
const { requestId, zkProofEncoded, metadata } = processProofResponse(zkProof);
|
|
327
|
+
payloadResponses.push({
|
|
295
328
|
requestId: requestId,
|
|
296
329
|
zkProof: zkProofEncoded,
|
|
297
330
|
data: metadata
|
|
298
331
|
});
|
|
332
|
+
const { gistUpdateResolutions, stateUpdateResolutions } = this.getUpdateResolutions(resolverUrl, txData.chain_id, zkProof.circuitId, zkProof.pub_signals);
|
|
333
|
+
if (gistUpdateResolutions.length > 0) {
|
|
334
|
+
gistUpdatesArr.push(...(await Promise.all(gistUpdateResolutions)));
|
|
335
|
+
}
|
|
336
|
+
if (stateUpdateResolutions.length > 0) {
|
|
337
|
+
stateUpdatesArr.push(...(await Promise.all(stateUpdateResolutions)));
|
|
338
|
+
}
|
|
299
339
|
}
|
|
300
|
-
const
|
|
301
|
-
? this.packCrossChainProofs(
|
|
340
|
+
const crossChainProofEncoded = gistUpdatesArr.length || stateUpdatesArr.length
|
|
341
|
+
? this.packCrossChainProofs(gistUpdatesArr, stateUpdatesArr)
|
|
302
342
|
: emptyBytes;
|
|
303
|
-
return [
|
|
343
|
+
return [payloadResponses, crossChainProofEncoded];
|
|
304
344
|
}
|
|
305
345
|
async prepareTxArgsSubmitV2(txData, zkProofResponses) {
|
|
306
346
|
if (!this._opts?.didResolverUrl) {
|
|
@@ -308,30 +348,11 @@ export class OnChainZKPVerifier {
|
|
|
308
348
|
}
|
|
309
349
|
return OnChainZKPVerifier.prepareTxArgsSubmitV2(this._opts.didResolverUrl, txData, zkProofResponses);
|
|
310
350
|
}
|
|
311
|
-
static
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
const preparedZkpProof = prepareZkpProof(zkProof.proof);
|
|
318
|
-
const zkProofEncoded = packZkpProof(inputs, preparedZkpProof.a, preparedZkpProof.b, preparedZkpProof.c);
|
|
319
|
-
const metadataArr = [];
|
|
320
|
-
if (zkProof.vp) {
|
|
321
|
-
for (const key in zkProof.vp.verifiableCredential.credentialSubject) {
|
|
322
|
-
if (key === '@type') {
|
|
323
|
-
continue;
|
|
324
|
-
}
|
|
325
|
-
const metadataValue = poseidon.hashBytes(byteEncoder.encode(JSON.stringify(zkProof.vp.verifiableCredential.credentialSubject[key])));
|
|
326
|
-
const bytesValue = byteEncoder.encode(metadataValue.toString());
|
|
327
|
-
metadataArr.push({
|
|
328
|
-
key,
|
|
329
|
-
value: bytesValue
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
const metadata = metadataArr.length ? this.packMetadatas(metadataArr) : '0x';
|
|
334
|
-
return { requestID, zkProofEncoded, metadata };
|
|
351
|
+
static getUpdateResolutions(resolverUrl, chainId, proofCircuitId, inputs) {
|
|
352
|
+
const stateInfo = this.getOnChainGistRootStatePubSignals(proofCircuitId, inputs);
|
|
353
|
+
const gistUpdateResolutions = this.getCrossChainResolvers(stateInfo.gists, chainId, 'gist', resolverUrl);
|
|
354
|
+
const stateUpdateResolutions = this.getCrossChainResolvers(stateInfo.states, chainId, 'state', resolverUrl);
|
|
355
|
+
return { gistUpdateResolutions, stateUpdateResolutions };
|
|
335
356
|
}
|
|
336
357
|
static packCrossChainProofs(gistUpdateArr, stateUpdateArr) {
|
|
337
358
|
const proofs = [];
|
|
@@ -375,9 +396,6 @@ export class OnChainZKPVerifier {
|
|
|
375
396
|
')'
|
|
376
397
|
], [msg]);
|
|
377
398
|
}
|
|
378
|
-
static packMetadatas(metas) {
|
|
379
|
-
return new ethers.AbiCoder().encode(['tuple(' + 'string key,' + 'bytes value' + ')[]'], [metas]);
|
|
380
|
-
}
|
|
381
399
|
static getOnChainGistRootStatePubSignals(onChainCircuitId, inputs) {
|
|
382
400
|
const PubSignals = this._supportedCircuitsPubSignalsMap[onChainCircuitId];
|
|
383
401
|
if (!PubSignals) {
|
|
@@ -436,3 +454,11 @@ OnChainZKPVerifier._supportedCircuitsPubSignalsMap = {
|
|
|
436
454
|
[CircuitId.AtomicQueryV3OnChain]: AtomicQueryV3OnChainPubSignals,
|
|
437
455
|
[CircuitId.AuthV2]: AuthV2PubSignals
|
|
438
456
|
};
|
|
457
|
+
/**
|
|
458
|
+
* Packs an Ethereum identity proof from a Decentralized Identifier (DID).
|
|
459
|
+
* @param did - Decentralized Identifier (DID) to pack.
|
|
460
|
+
* @returns A hexadecimal string representing the packed DID identity proof.
|
|
461
|
+
*/
|
|
462
|
+
export const packEthIdentityProof = (did) => {
|
|
463
|
+
return `0x${bytesToHex(BytesHelper.intToBytes(DID.idFromDID(did).bigInt()))}`;
|
|
464
|
+
};
|
|
@@ -4,7 +4,7 @@ import { byteEncoder } from '../../utils';
|
|
|
4
4
|
import abi from './abi/State.json';
|
|
5
5
|
import { DID, getChainId, Id } from '@iden3/js-iden3-core';
|
|
6
6
|
import { TransactionService } from '../../blockchain';
|
|
7
|
-
import { prepareZkpProof } from '
|
|
7
|
+
import { prepareZkpProof } from './common';
|
|
8
8
|
export /** @type {EthConnectionConfig} - default configuration for EthConnectionConfig */ const defaultEthConnectionConfig = {
|
|
9
9
|
url: 'http://localhost:8545',
|
|
10
10
|
defaultGasLimit: 600000,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AcceptProfile,
|
|
1
|
+
import { AcceptProfile, AuthProof, BasicMessage, JWSPackerParams, ZeroKnowledgeProofRequest, ZeroKnowledgeProofResponse } from '../types';
|
|
2
2
|
import { DID } from '@iden3/js-iden3-core';
|
|
3
3
|
import { IProofService } from '../../proof';
|
|
4
4
|
import { CircuitId } from '../../circuits';
|
|
@@ -32,13 +32,40 @@ export declare const processZeroKnowledgeProofRequests: (to: DID, requests: Zero
|
|
|
32
32
|
export declare const processProofAuth: (to: DID, proofService: IProofService, opts: {
|
|
33
33
|
supportedCircuits: CircuitId[];
|
|
34
34
|
acceptProfile?: AcceptProfile;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}) => Promise<
|
|
35
|
+
senderAddress: string;
|
|
36
|
+
zkpResponses: ZeroKnowledgeProofResponse[];
|
|
37
|
+
}) => Promise<{
|
|
38
|
+
authProof: AuthProof;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Processes a ZeroKnowledgeProofResponse object and prepares it for further use.
|
|
42
|
+
* @param zkProof - The ZeroKnowledgeProofResponse object containing the proof data.
|
|
43
|
+
* @returns An object containing the requestId, zkProofEncoded, and metadata.
|
|
44
|
+
*/
|
|
45
|
+
export declare const processProofResponse: (zkProof: ZeroKnowledgeProofResponse) => {
|
|
46
|
+
requestId: string | number;
|
|
47
|
+
zkProofEncoded: string;
|
|
48
|
+
metadata: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Calculates the challenge authentication V2 value.
|
|
52
|
+
* @param senderAddress - The address of the sender.
|
|
53
|
+
* @param zkpResponses - An array of ZeroKnowledgeProofResponse objects.
|
|
54
|
+
* @returns A bigint representing the challenge authentication value.
|
|
55
|
+
*/
|
|
56
|
+
export declare const calcChallengeAuthV2: (senderAddress: string, zkpResponses: ZeroKnowledgeProofResponse[]) => bigint;
|
|
57
|
+
/**
|
|
58
|
+
* Packs metadata into a string format suitable for encoding in a transaction.
|
|
59
|
+
* @param metas - An array of objects containing key-value pairs to be packed.
|
|
60
|
+
* @returns A string representing the packed metadata.
|
|
61
|
+
*/
|
|
62
|
+
export declare const packMetadatas: (metas: {
|
|
63
|
+
key: string;
|
|
64
|
+
value: Uint8Array;
|
|
65
|
+
}[]) => string;
|
|
38
66
|
/**
|
|
39
67
|
* Verifies that the expires_time field of a message is not in the past. Throws an error if it is.
|
|
40
68
|
*
|
|
41
69
|
* @param message - Basic message to verify.
|
|
42
70
|
*/
|
|
43
71
|
export declare const verifyExpiresTime: (message: BasicMessage) => void;
|
|
44
|
-
export declare const packEthIdentityProof: (did: DID) => string;
|
|
@@ -5,7 +5,7 @@ import { ProofType } from '../../../verifiable';
|
|
|
5
5
|
import { CircuitId } from '../../../circuits';
|
|
6
6
|
import { DIDDocument as DidResolverDidDocument, VerificationMethod as DidResolverVerificationMethod } from 'did-resolver';
|
|
7
7
|
import { RootInfo, StateInfo } from '../../../storage';
|
|
8
|
-
import {
|
|
8
|
+
import { AuthProof, CrossChainProof } from './contract-request';
|
|
9
9
|
/** AuthorizationResponseMessage is struct the represents iden3message authorization response */
|
|
10
10
|
export type AuthorizationResponseMessage = BasicMessage & {
|
|
11
11
|
body: AuthorizationMessageResponseBody;
|
|
@@ -56,8 +56,8 @@ export type ZeroKnowledgeProofQuery = {
|
|
|
56
56
|
};
|
|
57
57
|
export type ZeroKnowledgeInvokeResponse = {
|
|
58
58
|
responses: ZeroKnowledgeProofResponse[];
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
crossChainProof?: CrossChainProof;
|
|
60
|
+
authProof?: AuthProof;
|
|
61
61
|
};
|
|
62
62
|
/** ZeroKnowledgeProofResponse represents structure of zkp response */
|
|
63
63
|
export type ZeroKnowledgeProofResponse = {
|