Skip to content

Commit

Permalink
add Signer & chalange to contract invoke handler
Browse files Browse the repository at this point in the history
  • Loading branch information
volodymyr-basiuk committed Oct 2, 2023
1 parent 3af68b3 commit b156b8c
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 53 deletions.
40 changes: 28 additions & 12 deletions src/iden3comm/handlers/contract-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import {
ContractInvokeRequest
} from '../types/protocol/contract-request';
import { DID } from '@iden3/js-iden3-core';
import { ZKProof } from '@iden3/js-jwz';
import { IZKPVerifier } from '../../storage';

/**
* Interface that allows the processing of the contract request
*
* @public
* @beta
* @interface IContractRequestHandler
*/
export interface IContractRequestHandler {
Expand All @@ -34,24 +33,29 @@ export interface IContractRequestHandler {
* @param {did} did - sender DID
* @param {Uint8Array} request - raw byte message
* @param {ContractInvokeHandlerOptions} opts - handler options
* @returns {Array<string>}` - array of transaction hashes
* @returns {Map<string, ZeroKnowledgeProofResponse>}` - map of transaction hash - ZeroKnowledgeProofResponse
*/
handleContractInvokeRequest(
did: DID,
request: Uint8Array,
opts?: ContractInvokeHandlerOptions
): Promise<Array<string>>;
): Promise<Map<string, ZeroKnowledgeProofResponse>>;
}
/**
*
* Allows to process ContractInvokeRequest protocol message
*
* @public
* @beta
* @class ContractRequestHandler
* @implements implements IContractRequestHandler interface
*/
export class ContractRequestHandler implements IContractRequestHandler {
private readonly _allowedCircuits = [
CircuitId.AtomicQueryMTPV2OnChain,
CircuitId.AtomicQuerySigV2OnChain
];

/**
* Creates an instance of ContractRequestHandler.
* @param {IPackageManager} _packerMgr - package manager to unpack message envelope
Expand Down Expand Up @@ -87,21 +91,31 @@ export class ContractRequestHandler implements IContractRequestHandler {
* @param {did} did - sender DID
* @param {ContractInvokeRequest} request - contract invoke request
* @param {ContractInvokeHandlerOptions} opts - handler options
* @returns {Array<string>}` - array of transaction hashes
* @returns {Map<string, ZeroKnowledgeProofResponse>}` - map of transaction hash - ZeroKnowledgeProofResponse
*/
async handleContractInvokeRequest(
did: DID,
request: Uint8Array,
opts?: ContractInvokeHandlerOptions //eslint-disable-line @typescript-eslint/no-unused-vars
): Promise<Array<string>> {
opts: ContractInvokeHandlerOptions
): Promise<Map<string, ZeroKnowledgeProofResponse>> {
const ciRequest = await this.parseContractInvokeRequest(request);

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

const reqIdProofMap = new Map<number, ZKProof>();
if (!opts.ethSigner) {
throw new Error("Can't sign transaction. Provide Signer in options.");
}

const zkRequests = [];
for (const proofReq of ciRequest.body.scope) {
if (!this._allowedCircuits.includes(proofReq.circuitId as CircuitId)) {
throw new Error(
`Can\'t handle circuit ${proofReq.circuitId}. Only onchain circuits allowed.`

Check failure on line 115 in src/iden3comm/handlers/contract-request.ts

View workflow job for this annotation

GitHub Actions / build (18.16.1)

Unnecessary escape character: \'
);
}

const zkpReq: ZeroKnowledgeProofRequest = {
id: proofReq.id,
circuitId: proofReq.circuitId as CircuitId,
Expand All @@ -114,19 +128,21 @@ export class ContractRequestHandler implements IContractRequestHandler {
zkpReq,
did,
{
skipRevocation: query.skipClaimRevocationCheck ?? false
skipRevocation: query.skipClaimRevocationCheck ?? false,
challenge: opts.challange
}
);

reqIdProofMap.set(proofReq.id, zkpRes as ZKProof);
zkRequests.push(zkpRes);
}

const txData = ciRequest.body.transaction_data;

return this._zkpVerifier.submitZKPResponse(
txData.contract_address,
txData.chain_id,
reqIdProofMap
opts.ethSigner,
zkRequests
);
}
}
6 changes: 5 additions & 1 deletion src/iden3comm/types/protocol/contract-request.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Signer } from 'ethers';
import { ZeroKnowledgeProofRequest } from './auth';

/** ContractInvokeRequest represents structure of contract invoke request object */
Expand Down Expand Up @@ -25,4 +26,7 @@ export type ContractInvokeTransactionData = {
};

/** ContractInvokeHandlerOptions represents contract invoke handler options */
export type ContractInvokeHandlerOptions = object;
export type ContractInvokeHandlerOptions = {
ethSigner: Signer;
challange?: bigint;
};
36 changes: 19 additions & 17 deletions src/storage/blockchain/zkp-verifier.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import abi from './zkp-verifier-abi.json';
import { ethers } from 'ethers';
import { ethers, Signer } from 'ethers';
import { EthConnectionConfig } from './state';
import { ZKProof } from '@iden3/js-jwz';
import { IZKPVerifier } from '../interfaces/zkp-verifier';
import { ZeroKnowledgeProofResponse } from '../../iden3comm';

/**
* ZKPVerifier is a class that allows to interact with the ZKPVerifier contract
Expand All @@ -28,27 +28,29 @@ export class ZKPVerifier implements IZKPVerifier {
* @public
* @param {string} address - ZKPVerifier contract address
* @param {number} chain_id - chain id
* @param {Map<number, ZKProof>} requestIdProofs - request id - proof data map
* @returns {Promise<Array<string>>} - array of transaction hashes
* @param {Signer} ethSigner - tx signer
* @param {ZeroKnowledgeProofResponse[]} zkProofResponses - zkProofResponses
* @returns {Promise<Map<string, ZeroKnowledgeProofResponse>>} - map of transaction hash - ZeroKnowledgeProofResponse
*/
public async submitZKPResponse(
address: string,
chain_id: number,
requestIdProofs: Map<number, ZKProof>
): Promise<Array<string>> {
ethSigner: Signer,
zkProofResponses: ZeroKnowledgeProofResponse[]
): Promise<Map<string, ZeroKnowledgeProofResponse>> {
this.config.chainId = chain_id;

const provider = new ethers.providers.JsonRpcProvider(this.config);
const contract: ethers.Contract = new ethers.Contract(address, abi, provider);
const verifierContract: ethers.Contract = new ethers.Contract(address, abi, provider);
const contract = verifierContract.connect(ethSigner);

const txHashes = [];
for (const requestProof of requestIdProofs) {
const requestID = requestProof[0];
const proofData = requestProof[1];
const inputs = proofData.pub_signals;
const a = proofData.proof.pi_a;
const b = proofData.proof.pi_b;
const c = proofData.proof.pi_c;
const response = new Map<string, ZeroKnowledgeProofResponse>();
for (const zkProof of zkProofResponses) {
const requestID = zkProof.id;
const inputs = zkProof.pub_signals;
const a = zkProof.proof.pi_a;
const b = zkProof.proof.pi_b;
const c = zkProof.proof.pi_c;
const tx = await contract.submitZKPResponse([requestID, inputs, a, b, c]);
const txnReceipt = await tx.wait();
const status: number = txnReceipt.status;
Expand All @@ -57,9 +59,9 @@ export class ZKPVerifier implements IZKPVerifier {
if (status === 0) {
throw new Error(`transaction: ${txnHash} failed to mined`);
}
txHashes.push(txnHash);
response.set(txnHash, zkProof);
}

return txHashes;
return response;
}
}
13 changes: 8 additions & 5 deletions src/storage/interfaces/zkp-verifier.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ZKProof } from '@iden3/js-jwz';
import { Signer } from 'ethers';
import { ZeroKnowledgeProofResponse } from '../../iden3comm';

/**
* Interface that defines methods for ZKP verifier
Expand All @@ -12,12 +13,14 @@ export interface IZKPVerifier {
* @public
* @param {string} address - ZKPVerifier contract address
* @param {number} chain_id - chain id
* @param {Map<number, ZKProof>} requestIdProofs - request id - proof data map
* @returns {Promise<Array<string>>} - array of transaction hashes
* @param {Signer} ethSigner - tx signer
* @param {ZeroKnowledgeProofResponse[]} zkProofResponses - zkProofResponses
* @returns {Promise<Map<string, ZeroKnowledgeProofResponse>>} - map of transaction hash - ZeroKnowledgeProofResponse
*/
submitZKPResponse(
address: string,
chain_id: number,
requestIdProofs: Map<number, ZKProof>
): Promise<Array<string>>;
ethSigner: Signer,
zkProofResponses: ZeroKnowledgeProofResponse[]
): Promise<Map<string, ZeroKnowledgeProofResponse>>;
}
55 changes: 37 additions & 18 deletions tests/handlers/contract-request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
CredentialStorage,
FSCircuitStorage,
IdentityWallet,
byteEncoder
byteEncoder,
EthStateStorage
} from '../../src';
import { BjjProvider, KMS, KmsKeyType } from '../../src/kms';
import { InMemoryPrivateKeyStore } from '../../src/kms/store';
Expand All @@ -21,6 +22,7 @@ import path from 'path';
import { CircuitData } from '../../src/storage/entities/circuitData';
import {
AuthDataPrepareFunc,
ContractInvokeHandlerOptions,
ContractInvokeRequest,
ContractInvokeRequestBody,
ContractInvokeTransactionData,
Expand All @@ -34,17 +36,19 @@ import {
VerificationHandlerFunc,
VerificationParams,
ZeroKnowledgeProofRequest,
ZeroKnowledgeProofResponse,
ZKPPacker
} from '../../src/iden3comm';
import { proving, ZKProof } from '@iden3/js-jwz';
import { proving } from '@iden3/js-jwz';
import * as uuid from 'uuid';
import { MediaType, PROTOCOL_MESSAGE_TYPE } from '../../src/iden3comm/constants';
import { Blockchain, DidMethod, NetworkId } from '@iden3/js-iden3-core';
import { expect } from 'chai';
import { CredentialStatusResolverRegistry } from '../../src/credentials';
import { RHSResolver } from '../../src/credentials';
import { ethers, Signer } from 'ethers';

describe('contact-request', () => {
describe.only('contact-request', () => {
let idWallet: IdentityWallet;
let credWallet: CredentialWallet;

Expand All @@ -54,6 +58,7 @@ describe('contact-request', () => {
let packageMgr: IPackageManager;
const rhsUrl = process.env.RHS_URL as string;
const ipfsNodeURL = process.env.IPFS_URL as string;
const walletKey = process.env.WALLET_KEY as string;

const seedPhraseIssuer: Uint8Array = byteEncoder.encode('seedseedseedseedseedseedseedseed');
const seedPhrase: Uint8Array = byteEncoder.encode('seedseedseedseedseedseedseeduser');
Expand Down Expand Up @@ -90,12 +95,16 @@ describe('contact-request', () => {
};

const mockZKPVerifier: IZKPVerifier = {
submitZKPResponse: async (
address: string,
chain_id: number,
requestIdProofs: Map<number, ZKProof>) => {
return ['txhash1'];
},
submitZKPResponse: async (
address: string,
chain_id: number,
signer: Signer,
zkProofResponses: ZeroKnowledgeProofResponse[]
) => {
const response = new Map<string, ZeroKnowledgeProofResponse>();
response.set('txhash1', zkProofResponses[0]);
return response;
}
};

const getPackageMgr = async (
Expand Down Expand Up @@ -226,7 +235,7 @@ describe('contact-request', () => {

const proofReq: ZeroKnowledgeProofRequest = {
id: 1,
circuitId: CircuitId.AtomicQuerySigV2,
circuitId: CircuitId.AtomicQuerySigV2OnChain,
optional: false,
query: {
allowedIssuers: ['*'],
Expand All @@ -242,9 +251,9 @@ describe('contact-request', () => {
};

const transactionData: ContractInvokeTransactionData = {
contract_address: 'test_address',
method_id: '123',
chain_id: 80001
contract_address: 'test_address',
method_id: '123',
chain_id: 80001
};

const ciRequestBody: ContractInvokeRequestBody = {
Expand All @@ -262,12 +271,22 @@ describe('contact-request', () => {
body: ciRequestBody
};

const ethSigner = new ethers.Wallet(
walletKey,
(dataStorage.states as EthStateStorage).provider
);

const options: ContractInvokeHandlerOptions = {
ethSigner,
challange: BigInt(112312)
};
const msgBytes = byteEncoder.encode(JSON.stringify(ciRequest));
const ciResponse = await contractRequest.handleContractInvokeRequest(userDID, msgBytes);
const ciResponse = await contractRequest.handleContractInvokeRequest(
userDID,
msgBytes,
options
);

expect(ciResponse.length).to.be.equal(1);
expect(ciResponse[0]).to.be.equal('txhash1');
expect(ciResponse.has('txhash1')).to.be.true;
});


});

0 comments on commit b156b8c

Please sign in to comment.