Skip to content

Commit 245260e

Browse files
feat: add support of submitZKPResponseCrossChain (#254)
feat: add support of submitZKPResponseV2 and prepareTxArgsSubmit
1 parent babd7d3 commit 245260e

18 files changed

+1976
-368
lines changed

src/circuits/atomic-query-mtp-v2-on-chain.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
bigIntArrayToStringArray,
88
existenceToInt,
99
getNodeAuxValue,
10+
IStateInfoPubSignals,
11+
StatesInfo,
1012
prepareCircuitArrayValues,
1113
prepareSiblingsStr
1214
} from './common';
@@ -240,7 +242,7 @@ interface atomicQueryMTPV2OnChainCircuitInputs {
240242
* @class AtomicQueryMTPV2OnChainPubSignals
241243
* @extends {BaseConfig}
242244
*/
243-
export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig {
245+
export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
244246
requestID!: bigint;
245247
userID!: Id;
246248
issuerID!: Id;
@@ -322,4 +324,15 @@ export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig {
322324

323325
return this;
324326
}
327+
328+
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
329+
getStatesInfo(): StatesInfo {
330+
return {
331+
states: [
332+
{ id: this.issuerID, state: this.issuerClaimIdenState },
333+
{ id: this.issuerID, state: this.issuerClaimNonRevState }
334+
],
335+
gists: [{ id: this.userID, root: this.gistRoot }]
336+
};
337+
}
325338
}

src/circuits/atomic-query-sig-v2-on-chain.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import {
77
bigIntArrayToStringArray,
88
existenceToInt,
99
getNodeAuxValue,
10+
IStateInfoPubSignals,
1011
prepareCircuitArrayValues,
11-
prepareSiblingsStr
12+
prepareSiblingsStr,
13+
StatesInfo
1214
} from './common';
1315
import { byteDecoder, byteEncoder } from '../utils';
1416

@@ -312,7 +314,7 @@ export class AtomicQuerySigV2OnChainCircuitInputs {
312314
* @class AtomicQuerySigV2OnChainPubSignals
313315
* @extends {BaseConfig}
314316
*/
315-
export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig {
317+
export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
316318
requestID!: bigint;
317319
userID!: Id;
318320
issuerID!: Id;
@@ -397,4 +399,15 @@ export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig {
397399

398400
return this;
399401
}
402+
403+
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
404+
getStatesInfo(): StatesInfo {
405+
return {
406+
states: [
407+
{ id: this.issuerID, state: this.issuerAuthState },
408+
{ id: this.issuerID, state: this.issuerClaimNonRevState }
409+
],
410+
gists: [{ id: this.userID, root: this.gistRoot }]
411+
};
412+
}
400413
}

src/circuits/atomic-query-v3-on-chain.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import {
44
bigIntArrayToStringArray,
55
prepareSiblingsStr,
66
getNodeAuxValue,
7-
prepareCircuitArrayValues
7+
prepareCircuitArrayValues,
8+
IStateInfoPubSignals,
9+
StatesInfo
810
} from './common';
911
import { BJJSignatureProof, CircuitError, GISTProof, Query, TreeState, ValueProof } from './models';
1012
import { Hash, Proof, ZERO_HASH } from '@iden3/js-merkletree';
@@ -420,7 +422,7 @@ interface AtomicQueryV3OnChainCircuitInputs {
420422
* @beta
421423
* AtomicQueryV3OnChainPubSignals public inputs
422424
*/
423-
export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
425+
export class AtomicQueryV3OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
424426
requestID!: bigint;
425427
userID!: Id;
426428
issuerID!: Id;
@@ -515,4 +517,15 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
515517

516518
return this;
517519
}
520+
521+
/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
522+
getStatesInfo(): StatesInfo {
523+
return {
524+
states: [
525+
{ id: this.issuerID, state: this.issuerState },
526+
{ id: this.issuerID, state: this.issuerClaimNonRevState }
527+
],
528+
gists: [{ id: this.userID, root: this.gistRoot }]
529+
};
530+
}
518531
}

src/circuits/common.ts

+33
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Hex } from '@iden3/js-crypto';
22
import { Hash, ZERO_HASH, Proof, swapEndianness } from '@iden3/js-merkletree';
33
import { TreeState } from './models';
4+
import { Id } from '@iden3/js-iden3-core';
45

56
export const defaultMTLevels = 40; // max MT levels, default value for identity circuits
67
export const defaultValueArraySize = 64; // max value array size, default value for identity circuits
@@ -226,3 +227,35 @@ export function getProperties(obj: object): object {
226227
}
227228
return result;
228229
}
230+
231+
/**
232+
* states info from pub signals
233+
*
234+
* @public
235+
* @type StatesInfo
236+
*/
237+
export type StatesInfo = {
238+
states: {
239+
id: Id;
240+
state: Hash;
241+
}[];
242+
gists: {
243+
id: Id;
244+
root: Hash;
245+
}[];
246+
};
247+
248+
/**
249+
* state pub signals
250+
*
251+
* @public
252+
* @interface IStatePubSignals
253+
*/
254+
export interface IStateInfoPubSignals {
255+
/**
256+
* return object with state params
257+
*
258+
* @returns {OnChainStateInfo}
259+
*/
260+
getStatesInfo(): StatesInfo;
261+
}

src/iden3comm/constants.ts

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ export const PROTOCOL_MESSAGE_TYPE = Object.freeze({
3636
// ContractInvokeRequestMessageType is type for request of contract invoke request
3737
CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE:
3838
`${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-request` as const,
39+
// ContractInvokeResponseMessageType is type for response of contract invoke request
40+
CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE:
41+
`${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-response` as const,
3942
// CredentialOnchainOfferMessageType is type of message with credential onchain offering
4043
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/1.0/onchain-offer` as const,
4144
// ProposalRequestMessageType is type for proposal-request message

src/iden3comm/handlers/contract-request.ts

+105-19
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { CircuitId } from '../../circuits/models';
22
import { IProofService } from '../../proof/proof-service';
33
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
44
import { BasicMessage, IPackageManager, ZeroKnowledgeProofResponse } from '../types';
5-
import { ContractInvokeRequest } from '../types/protocol/contract-request';
5+
import { ContractInvokeRequest, ContractInvokeResponse } from '../types/protocol/contract-request';
66
import { DID, ChainIds } from '@iden3/js-iden3-core';
7-
import { IOnChainZKPVerifier } from '../../storage';
7+
import { FunctionSignatures, IOnChainZKPVerifier } from '../../storage';
88
import { Signer } from 'ethers';
99
import { processZeroKnowledgeProofRequests } from './common';
1010
import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler';
@@ -17,15 +17,15 @@ import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handl
1717
*/
1818
export interface IContractRequestHandler {
1919
/**
20-
* unpacks contract invoker request
20+
* unpacks contract invoke request
2121
* @beta
2222
* @param {Uint8Array} request - raw byte message
2323
* @returns `Promise<ContractInvokeRequest>`
2424
*/
2525
parseContractInvokeRequest(request: Uint8Array): Promise<ContractInvokeRequest>;
2626

2727
/**
28-
* handle contract invoker request
28+
* handle contract invoke request
2929
* @beta
3030
* @param {did} did - sender DID
3131
* @param {Uint8Array} request - raw byte message
@@ -91,9 +91,11 @@ export class ContractRequestHandler
9191
ctx: ContractMessageHandlerOptions
9292
): Promise<BasicMessage | null> {
9393
switch (message.type) {
94-
case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE:
95-
await this.handleContractInvoke(message as ContractInvokeRequest, ctx);
96-
return null;
94+
case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: {
95+
const ciMessage = message as ContractInvokeRequest;
96+
const txHashResponsesMap = await this.handleContractInvoke(ciMessage, ctx);
97+
return this.createContractInvokeResponse(ciMessage, txHashResponsesMap);
98+
}
9799
default:
98100
return super.handle(message, ctx);
99101
}
@@ -102,7 +104,7 @@ export class ContractRequestHandler
102104
private async handleContractInvoke(
103105
message: ContractInvokeRequest,
104106
ctx: ContractMessageHandlerOptions
105-
): Promise<Map<string, ZeroKnowledgeProofResponse>> {
107+
): Promise<Map<string, ZeroKnowledgeProofResponse[]>> {
106108
if (message.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
107109
throw new Error('Invalid message type for contract invoke request');
108110
}
@@ -127,11 +129,31 @@ export class ContractRequestHandler
127129
{ ethSigner, challenge, supportedCircuits: this._supportedCircuits }
128130
);
129131

130-
return this._zkpVerifier.submitZKPResponse(
131-
ethSigner,
132-
message.body.transaction_data,
133-
zkpResponses
134-
);
132+
const methodId = message.body.transaction_data.method_id.replace('0x', '');
133+
switch (methodId) {
134+
case FunctionSignatures.SumbitZKPResponseV2:
135+
return this._zkpVerifier.submitZKPResponseV2(
136+
ethSigner,
137+
message.body.transaction_data,
138+
zkpResponses
139+
);
140+
case FunctionSignatures.SumbitZKPResponseV1: {
141+
const txHashZkpResponseMap = await this._zkpVerifier.submitZKPResponse(
142+
ethSigner,
143+
message.body.transaction_data,
144+
zkpResponses
145+
);
146+
const response = new Map<string, ZeroKnowledgeProofResponse[]>();
147+
for (const [txHash, zkpResponse] of txHashZkpResponseMap) {
148+
response.set(txHash, [zkpResponse]);
149+
}
150+
return response;
151+
}
152+
default:
153+
throw new Error(
154+
`Not supported method id. Only '${FunctionSignatures.SumbitZKPResponseV1} and ${FunctionSignatures.SumbitZKPResponseV2} are supported.'`
155+
);
156+
}
135157
}
136158

137159
/**
@@ -151,8 +173,45 @@ export class ContractRequestHandler
151173
}
152174

153175
/**
154-
* handle contract invoker request
176+
* creates contract invoke response
177+
* @private
178+
* @beta
179+
* @param {ContractInvokeRequest} request - ContractInvokeRequest
180+
* @param { Map<string, ZeroKnowledgeProofResponse[]>} responses - map tx hash to array of ZeroKnowledgeProofResponses
181+
* @returns `Promise<ContractInvokeResponse>`
182+
*/
183+
private async createContractInvokeResponse(
184+
request: ContractInvokeRequest,
185+
txHashToZkpResponseMap: Map<string, ZeroKnowledgeProofResponse[]>
186+
): Promise<ContractInvokeResponse> {
187+
const contractInvokeResponse: ContractInvokeResponse = {
188+
id: request.id,
189+
thid: request.thid,
190+
type: PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE,
191+
from: request.to,
192+
to: request.from,
193+
body: {
194+
transaction_data: request.body.transaction_data,
195+
reason: request.body.reason,
196+
scope: []
197+
}
198+
};
199+
for (const [txHash, zkpResponses] of txHashToZkpResponseMap) {
200+
for (const zkpResponse of zkpResponses) {
201+
contractInvokeResponse.body.scope.push({
202+
txHash,
203+
...zkpResponse
204+
});
205+
}
206+
}
207+
return contractInvokeResponse;
208+
}
209+
210+
/**
211+
* handle contract invoke request
212+
* supports only 0xb68967e2 method id
155213
* @beta
214+
* @deprecated
156215
* @param {did} did - sender DID
157216
* @param {ContractInvokeRequest} request - contract invoke request
158217
* @param {ContractInvokeHandlerOptions} opts - handler options
@@ -165,10 +224,37 @@ export class ContractRequestHandler
165224
): Promise<Map<string, ZeroKnowledgeProofResponse>> {
166225
const ciRequest = await this.parseContractInvokeRequest(request);
167226

168-
return this.handleContractInvoke(ciRequest, {
169-
senderDid: did,
170-
ethSigner: opts.ethSigner,
171-
challenge: opts.challenge
172-
});
227+
if (ciRequest.body.transaction_data.method_id !== FunctionSignatures.SumbitZKPResponseV1) {
228+
throw new Error(`please use handle method to work with other method ids`);
229+
}
230+
231+
if (ciRequest.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
232+
throw new Error('Invalid message type for contract invoke request');
233+
}
234+
235+
const { ethSigner, challenge } = opts;
236+
if (!ethSigner) {
237+
throw new Error("Can't sign transaction. Provide Signer in options.");
238+
}
239+
240+
const { chain_id } = ciRequest.body.transaction_data;
241+
const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);
242+
243+
if (!networkFlag) {
244+
throw new Error(`Invalid chain id ${chain_id}`);
245+
}
246+
const verifierDid = ciRequest.from ? DID.parse(ciRequest.from) : undefined;
247+
const zkpResponses = await processZeroKnowledgeProofRequests(
248+
did,
249+
ciRequest?.body?.scope,
250+
verifierDid,
251+
this._proofService,
252+
{ ethSigner, challenge, supportedCircuits: this._supportedCircuits }
253+
);
254+
return this._zkpVerifier.submitZKPResponse(
255+
ethSigner,
256+
ciRequest.body.transaction_data,
257+
zkpResponses
258+
);
173259
}
174260
}

src/iden3comm/types/protocol/auth.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,16 @@ export type ZeroKnowledgeProofRequest = {
4949
export type ZeroKnowledgeProofResponse = {
5050
id: number;
5151
circuitId: string;
52-
vp?: object;
52+
vp?: VerifiablePresentation;
5353
} & ZKProof;
54+
55+
/** VerifiablePresentation represents structure of Verifiable Presentation */
56+
export type VerifiablePresentation = {
57+
'@context': string | (string | object)[];
58+
'@type': string;
59+
verifiableCredential: {
60+
'@context': string | string[];
61+
'@type': string | string[];
62+
credentialSubject: JsonDocumentObject;
63+
};
64+
};

src/iden3comm/types/protocol/contract-request.ts

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PROTOCOL_MESSAGE_TYPE } from '../../constants';
22
import { BasicMessage } from '../packer';
3-
import { ZeroKnowledgeProofRequest } from './auth';
3+
import { ZeroKnowledgeProofRequest, ZeroKnowledgeProofResponse } from './auth';
44

55
/** ContractInvokeRequest represents structure of contract invoke request object */
66
export type ContractInvokeRequest = BasicMessage & {
@@ -15,6 +15,24 @@ export type ContractInvokeRequestBody = {
1515
scope: Array<ZeroKnowledgeProofRequest>;
1616
};
1717

18+
/** ContractInvokeResponse represents structure of contract invoke response object */
19+
export type ContractInvokeResponse = BasicMessage & {
20+
body: ContractInvokeResponseBody;
21+
type: typeof PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE;
22+
};
23+
24+
/** ContractInvokeResponseBody represents structure of contract invoke response body object */
25+
export type ContractInvokeResponseBody = {
26+
scope: Array<OnChainZeroKnowledgeProofResponse>;
27+
transaction_data: ContractInvokeTransactionData;
28+
reason: string;
29+
};
30+
31+
/** OnChainZeroKnowledgeProofResponse represents structure of onchain zero knowledge proof response */
32+
export type OnChainZeroKnowledgeProofResponse = ZeroKnowledgeProofResponse & {
33+
txHash: string;
34+
};
35+
1836
/** ContractInvokeTransactionData represents structure of contract invoke transaction data object */
1937
export type ContractInvokeTransactionData = {
2038
contract_address: string;

0 commit comments

Comments
 (0)