Skip to content

Commit

Permalink
feat: add support of submitZKPResponseCrossChain (#254)
Browse files Browse the repository at this point in the history
feat: add support of  submitZKPResponseV2 and prepareTxArgsSubmit
  • Loading branch information
volodymyr-basiuk authored Sep 4, 2024
1 parent 1e72293 commit 94dcfcb
Show file tree
Hide file tree
Showing 20 changed files with 1,979 additions and 371 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@0xpolygonid/js-sdk",
"version": "1.17.8",
"version": "1.18.0",
"description": "SDK to work with Polygon ID",
"main": "dist/node/cjs/index.js",
"module": "dist/node/esm/index.js",
Expand Down
15 changes: 14 additions & 1 deletion src/circuits/atomic-query-mtp-v2-on-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
bigIntArrayToStringArray,
existenceToInt,
getNodeAuxValue,
IStateInfoPubSignals,
StatesInfo,
prepareCircuitArrayValues,
prepareSiblingsStr
} from './common';
Expand Down Expand Up @@ -240,7 +242,7 @@ interface atomicQueryMTPV2OnChainCircuitInputs {
* @class AtomicQueryMTPV2OnChainPubSignals
* @extends {BaseConfig}
*/
export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig {
export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
requestID!: bigint;
userID!: Id;
issuerID!: Id;
Expand Down Expand Up @@ -322,4 +324,15 @@ export class AtomicQueryMTPV2OnChainPubSignals extends BaseConfig {

return this;
}

/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
getStatesInfo(): StatesInfo {
return {
states: [
{ id: this.issuerID, state: this.issuerClaimIdenState },
{ id: this.issuerID, state: this.issuerClaimNonRevState }
],
gists: [{ id: this.userID, root: this.gistRoot }]
};
}
}
17 changes: 15 additions & 2 deletions src/circuits/atomic-query-sig-v2-on-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import {
bigIntArrayToStringArray,
existenceToInt,
getNodeAuxValue,
IStateInfoPubSignals,
prepareCircuitArrayValues,
prepareSiblingsStr
prepareSiblingsStr,
StatesInfo
} from './common';
import { byteDecoder, byteEncoder } from '../utils';

Expand Down Expand Up @@ -312,7 +314,7 @@ export class AtomicQuerySigV2OnChainCircuitInputs {
* @class AtomicQuerySigV2OnChainPubSignals
* @extends {BaseConfig}
*/
export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig {
export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
requestID!: bigint;
userID!: Id;
issuerID!: Id;
Expand Down Expand Up @@ -397,4 +399,15 @@ export class AtomicQuerySigV2OnChainPubSignals extends BaseConfig {

return this;
}

/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
getStatesInfo(): StatesInfo {
return {
states: [
{ id: this.issuerID, state: this.issuerAuthState },
{ id: this.issuerID, state: this.issuerClaimNonRevState }
],
gists: [{ id: this.userID, root: this.gistRoot }]
};
}
}
17 changes: 15 additions & 2 deletions src/circuits/atomic-query-v3-on-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
bigIntArrayToStringArray,
prepareSiblingsStr,
getNodeAuxValue,
prepareCircuitArrayValues
prepareCircuitArrayValues,
IStateInfoPubSignals,
StatesInfo
} from './common';
import { BJJSignatureProof, CircuitError, GISTProof, Query, TreeState, ValueProof } from './models';
import { Hash, Proof, ZERO_HASH } from '@iden3/js-merkletree';
Expand Down Expand Up @@ -420,7 +422,7 @@ interface AtomicQueryV3OnChainCircuitInputs {
* @beta
* AtomicQueryV3OnChainPubSignals public inputs
*/
export class AtomicQueryV3OnChainPubSignals extends BaseConfig {
export class AtomicQueryV3OnChainPubSignals extends BaseConfig implements IStateInfoPubSignals {
requestID!: bigint;
userID!: Id;
issuerID!: Id;
Expand Down Expand Up @@ -515,4 +517,15 @@ export class AtomicQueryV3OnChainPubSignals extends BaseConfig {

return this;
}

/** {@inheritDoc IStateInfoPubSignals.getStatesInfo} */
getStatesInfo(): StatesInfo {
return {
states: [
{ id: this.issuerID, state: this.issuerState },
{ id: this.issuerID, state: this.issuerClaimNonRevState }
],
gists: [{ id: this.userID, root: this.gistRoot }]
};
}
}
33 changes: 33 additions & 0 deletions src/circuits/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Hex } from '@iden3/js-crypto';
import { Hash, ZERO_HASH, Proof, swapEndianness } from '@iden3/js-merkletree';
import { TreeState } from './models';
import { Id } from '@iden3/js-iden3-core';

export const defaultMTLevels = 40; // max MT levels, default value for identity circuits
export const defaultValueArraySize = 64; // max value array size, default value for identity circuits
Expand Down Expand Up @@ -226,3 +227,35 @@ export function getProperties(obj: object): object {
}
return result;
}

/**
* states info from pub signals
*
* @public
* @type StatesInfo
*/
export type StatesInfo = {
states: {
id: Id;
state: Hash;
}[];
gists: {
id: Id;
root: Hash;
}[];
};

/**
* state pub signals
*
* @public
* @interface IStatePubSignals
*/
export interface IStateInfoPubSignals {
/**
* return object with state params
*
* @returns {OnChainStateInfo}
*/
getStatesInfo(): StatesInfo;
}
3 changes: 3 additions & 0 deletions src/iden3comm/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export const PROTOCOL_MESSAGE_TYPE = Object.freeze({
// ContractInvokeRequestMessageType is type for request of contract invoke request
CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE:
`${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-request` as const,
// ContractInvokeResponseMessageType is type for response of contract invoke request
CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE:
`${IDEN3_PROTOCOL}proofs/1.0/contract-invoke-response` as const,
// CredentialOnchainOfferMessageType is type of message with credential onchain offering
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/1.0/onchain-offer` as const,
// ProposalRequestMessageType is type for proposal-request message
Expand Down
124 changes: 105 additions & 19 deletions src/iden3comm/handlers/contract-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { CircuitId } from '../../circuits/models';
import { IProofService } from '../../proof/proof-service';
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
import { BasicMessage, IPackageManager, ZeroKnowledgeProofResponse } from '../types';
import { ContractInvokeRequest } from '../types/protocol/contract-request';
import { ContractInvokeRequest, ContractInvokeResponse } from '../types/protocol/contract-request';
import { DID, ChainIds } from '@iden3/js-iden3-core';
import { IOnChainZKPVerifier } from '../../storage';
import { FunctionSignatures, IOnChainZKPVerifier } from '../../storage';
import { Signer } from 'ethers';
import { processZeroKnowledgeProofRequests } from './common';
import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler';
Expand All @@ -17,15 +17,15 @@ import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handl
*/
export interface IContractRequestHandler {
/**
* unpacks contract invoker request
* unpacks contract invoke request
* @beta
* @param {Uint8Array} request - raw byte message
* @returns `Promise<ContractInvokeRequest>`
*/
parseContractInvokeRequest(request: Uint8Array): Promise<ContractInvokeRequest>;

/**
* handle contract invoker request
* handle contract invoke request
* @beta
* @param {did} did - sender DID
* @param {Uint8Array} request - raw byte message
Expand Down Expand Up @@ -91,9 +91,11 @@ export class ContractRequestHandler
ctx: ContractMessageHandlerOptions
): Promise<BasicMessage | null> {
switch (message.type) {
case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE:
await this.handleContractInvoke(message as ContractInvokeRequest, ctx);
return null;
case PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: {
const ciMessage = message as ContractInvokeRequest;
const txHashResponsesMap = await this.handleContractInvoke(ciMessage, ctx);
return this.createContractInvokeResponse(ciMessage, txHashResponsesMap);
}
default:
return super.handle(message, ctx);
}
Expand All @@ -102,7 +104,7 @@ export class ContractRequestHandler
private async handleContractInvoke(
message: ContractInvokeRequest,
ctx: ContractMessageHandlerOptions
): Promise<Map<string, ZeroKnowledgeProofResponse>> {
): Promise<Map<string, ZeroKnowledgeProofResponse[]>> {
if (message.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
throw new Error('Invalid message type for contract invoke request');
}
Expand All @@ -127,11 +129,31 @@ export class ContractRequestHandler
{ ethSigner, challenge, supportedCircuits: this._supportedCircuits }
);

return this._zkpVerifier.submitZKPResponse(
ethSigner,
message.body.transaction_data,
zkpResponses
);
const methodId = message.body.transaction_data.method_id.replace('0x', '');
switch (methodId) {
case FunctionSignatures.SumbitZKPResponseV2:
return this._zkpVerifier.submitZKPResponseV2(
ethSigner,
message.body.transaction_data,
zkpResponses
);
case FunctionSignatures.SumbitZKPResponseV1: {
const txHashZkpResponseMap = await this._zkpVerifier.submitZKPResponse(
ethSigner,
message.body.transaction_data,
zkpResponses
);
const response = new Map<string, ZeroKnowledgeProofResponse[]>();
for (const [txHash, zkpResponse] of txHashZkpResponseMap) {
response.set(txHash, [zkpResponse]);
}
return response;
}
default:
throw new Error(
`Not supported method id. Only '${FunctionSignatures.SumbitZKPResponseV1} and ${FunctionSignatures.SumbitZKPResponseV2} are supported.'`
);
}
}

/**
Expand All @@ -151,8 +173,45 @@ export class ContractRequestHandler
}

/**
* handle contract invoker request
* creates contract invoke response
* @private
* @beta
* @param {ContractInvokeRequest} request - ContractInvokeRequest
* @param { Map<string, ZeroKnowledgeProofResponse[]>} responses - map tx hash to array of ZeroKnowledgeProofResponses
* @returns `Promise<ContractInvokeResponse>`
*/
private async createContractInvokeResponse(
request: ContractInvokeRequest,
txHashToZkpResponseMap: Map<string, ZeroKnowledgeProofResponse[]>
): Promise<ContractInvokeResponse> {
const contractInvokeResponse: ContractInvokeResponse = {
id: request.id,
thid: request.thid,
type: PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_RESPONSE_MESSAGE_TYPE,
from: request.to,
to: request.from,
body: {
transaction_data: request.body.transaction_data,
reason: request.body.reason,
scope: []
}
};
for (const [txHash, zkpResponses] of txHashToZkpResponseMap) {
for (const zkpResponse of zkpResponses) {
contractInvokeResponse.body.scope.push({
txHash,
...zkpResponse
});
}
}
return contractInvokeResponse;
}

/**
* handle contract invoke request
* supports only 0xb68967e2 method id
* @beta
* @deprecated
* @param {did} did - sender DID
* @param {ContractInvokeRequest} request - contract invoke request
* @param {ContractInvokeHandlerOptions} opts - handler options
Expand All @@ -165,10 +224,37 @@ export class ContractRequestHandler
): Promise<Map<string, ZeroKnowledgeProofResponse>> {
const ciRequest = await this.parseContractInvokeRequest(request);

return this.handleContractInvoke(ciRequest, {
senderDid: did,
ethSigner: opts.ethSigner,
challenge: opts.challenge
});
if (ciRequest.body.transaction_data.method_id !== FunctionSignatures.SumbitZKPResponseV1) {
throw new Error(`please use handle method to work with other method ids`);
}

if (ciRequest.type !== PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE) {
throw new Error('Invalid message type for contract invoke request');
}

const { ethSigner, challenge } = opts;
if (!ethSigner) {
throw new Error("Can't sign transaction. Provide Signer in options.");
}

const { chain_id } = ciRequest.body.transaction_data;
const networkFlag = Object.keys(ChainIds).find((key) => ChainIds[key] === chain_id);

if (!networkFlag) {
throw new Error(`Invalid chain id ${chain_id}`);
}
const verifierDid = ciRequest.from ? DID.parse(ciRequest.from) : undefined;
const zkpResponses = await processZeroKnowledgeProofRequests(
did,
ciRequest?.body?.scope,
verifierDid,
this._proofService,
{ ethSigner, challenge, supportedCircuits: this._supportedCircuits }
);
return this._zkpVerifier.submitZKPResponse(
ethSigner,
ciRequest.body.transaction_data,
zkpResponses
);
}
}
13 changes: 12 additions & 1 deletion src/iden3comm/types/protocol/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,16 @@ export type ZeroKnowledgeProofRequest = {
export type ZeroKnowledgeProofResponse = {
id: number;
circuitId: string;
vp?: object;
vp?: VerifiablePresentation;
} & ZKProof;

/** VerifiablePresentation represents structure of Verifiable Presentation */
export type VerifiablePresentation = {
'@context': string | (string | object)[];
'@type': string;
verifiableCredential: {
'@context': string | string[];
'@type': string | string[];
credentialSubject: JsonDocumentObject;
};
};
Loading

0 comments on commit 94dcfcb

Please sign in to comment.