Skip to content

Commit

Permalink
refactor: verifying keys sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrlc03 committed Jan 29, 2025
1 parent 8b7ce16 commit ade2511
Show file tree
Hide file tree
Showing 9 changed files with 341 additions and 22 deletions.
41 changes: 21 additions & 20 deletions packages/cli/ts/commands/checkVerifyingKeys.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { extractVk } from "maci-circuits";
import { EMode, VkRegistry__factory as VkRegistryFactory } from "maci-contracts";
import { VerifyingKey } from "maci-domainobjs";
import { EMode } from "maci-contracts";
import { extractAllVks, compareVks, getAllOnChainVks } from "maci-sdk";

import fs from "fs";

import {
CheckVerifyingKeysArgs,
banner,
compareVks,
contractExists,
info,
logError,
Expand Down Expand Up @@ -52,8 +50,6 @@ export const checkVerifyingKeys = async ({
logError("The VkRegistry contract does not exist");
}

const vkRegistryContractInstance = VkRegistryFactory.connect(vkContractAddress, signer);

// we need to ensure that the zkey files exist
const isProcessMessagesZkeyPathExists = fs.existsSync(processMessagesZkeyPath);

Expand All @@ -68,38 +64,43 @@ export const checkVerifyingKeys = async ({
}

// extract the verification keys from the zkey files
const processVk = VerifyingKey.fromObj(await extractVk(processMessagesZkeyPath));
const tallyVk = VerifyingKey.fromObj(await extractVk(tallyVotesZkeyPath));
const pollJoiningVk = VerifyingKey.fromObj(await extractVk(pollJoiningZkeyPath));
const pollJoinedVk = VerifyingKey.fromObj(await extractVk(pollJoinedZkeyPath));
const { pollJoiningVk, pollJoinedVk, processVk, tallyVk } = await extractAllVks({
processMessagesZkeyPath,
tallyVotesZkeyPath,
pollJoiningZkeyPath,
pollJoinedZkeyPath,
});

try {
logYellow(quiet, info("Retrieving verifying keys from the contract..."));
// retrieve the verifying keys from the contract

const mode = useQuadraticVoting ? EMode.QV : EMode.NON_QV;

const [pollJoiningVkOnChain, pollJoinedVkOnChain, processVkOnChain, tallyVkOnChain] = await Promise.all([
vkRegistryContractInstance.getPollJoiningVk(stateTreeDepth, voteOptionTreeDepth),
vkRegistryContractInstance.getPollJoinedVk(stateTreeDepth, voteOptionTreeDepth),
vkRegistryContractInstance.getProcessVk(stateTreeDepth, voteOptionTreeDepth, messageBatchSize, mode),
vkRegistryContractInstance.getTallyVk(stateTreeDepth, intStateTreeDepth, voteOptionTreeDepth, mode),
]);
const { pollJoiningVkOnChain, pollJoinedVkOnChain, processVkOnChain, tallyVkOnChain } = await getAllOnChainVks({
vkRegistryAddress: vkContractAddress,
signer,
stateTreeDepth,
voteOptionTreeDepth,
messageBatchSize,
intStateTreeDepth,
mode,
});

// do the actual validation
if (!compareVks(pollJoiningVk, pollJoiningVkOnChain)) {
if (!compareVks(pollJoiningVk!, pollJoiningVkOnChain)) {
logError("Poll verifying keys do not match");
}

if (!compareVks(pollJoinedVk, pollJoinedVkOnChain)) {
if (!compareVks(pollJoinedVk!, pollJoinedVkOnChain)) {
logError("Poll verifying keys do not match");
}

if (!compareVks(processVk, processVkOnChain)) {
if (!compareVks(processVk!, processVkOnChain)) {
logError("Process verifying keys do not match");
}

if (!compareVks(tallyVk, tallyVkOnChain)) {
if (!compareVks(tallyVk!, tallyVkOnChain)) {
logError("Tally verifying keys do not match");
}
} catch (error) {
Expand Down
4 changes: 3 additions & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
"ethers": "^6.13.4",
"maci-contracts": "^2.5.0",
"maci-crypto": "^2.5.0",
"maci-domainobjs": "^2.5.0"
"maci-domainobjs": "^2.5.0",
"snarkjs": "^0.7.5"
},
"devDependencies": {
"@types/chai": "^4.3.9",
"@types/chai-as-promised": "^7.1.8",
"@types/mocha": "^10.0.8",
"@types/node": "^22.9.0",
"@types/snarkjs": "^0.7.9",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.2",
"mocha": "^10.7.3",
Expand Down
12 changes: 11 additions & 1 deletion packages/sdk/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { getPoll, getPollParams } from "./poll";
export { verify } from "./verify";
export { generateTallyCommitments } from "./tallyCommitments";
export { isUserRegistered, isJoinedUser, signup } from "./user";
export { getAllOnChainVks, compareVks, extractAllVks, extractVk } from "./verifyingKeys";

export {
linkPoseidonLibraries,
Expand All @@ -14,4 +15,13 @@ export {

export * from "maci-contracts/typechain-types";

export type { TallyData, VerifyArgs, IGetPollArgs, IGetPollData, IIsRegisteredUser, IIsJoinedUser } from "./utils";
export type {
TallyData,
VerifyArgs,
IGetPollArgs,
IGetPollData,
IIsRegisteredUser,
IIsJoinedUser,
IExtractAllVksArgs,
IMaciVks,
} from "./utils";
5 changes: 5 additions & 0 deletions packages/sdk/ts/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ export type {
IParsePollJoinEventsArgs,
IIsRegisteredUser,
IIsJoinedUser,
IMaciVerifyingKeys,
GetAllVksArgs,
ICircuitParams,
IExtractAllVksArgs,
IMaciVks,
} from "./interfaces";
export { verifyPerVOSpentVoiceCredits, verifyTallyResults } from "./verifiers";
export { BLOCKS_STEP } from "./constants";
Expand Down
124 changes: 124 additions & 0 deletions packages/sdk/ts/utils/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { EMode } from "maci-contracts";
import { MACI, Poll } from "maci-contracts/typechain-types";
import { PubKey } from "maci-domainobjs";

import type { Provider, Signer } from "ethers";
import type { IVkContractParams, VerifyingKey } from "maci-domainobjs";

/**
* Interface for the tally file data.
Expand Down Expand Up @@ -469,3 +471,125 @@ export interface IIsJoinedUser {
*/
voiceCredits?: string;
}

/**
* Arguments for the getAllVks function
*/
export interface GetAllVksArgs {
/**
* The address of the VkRegistry contract
*/
vkRegistryAddress: string;
/**
* The signer to use for the contract calls
*/
signer: Signer;
/**
* The depth of the state tree
*/
stateTreeDepth: number;
/**
* The depth of the vote option tree
*/
voteOptionTreeDepth: number;
/**
* The batch size for the process messages
*/
messageBatchSize: number;
/**
* The depth of the ballot tree
*/
intStateTreeDepth: number;
/**
* The mode to use for the contract calls
*/
mode: EMode;
}

/**
* MACI's verifying keys
*/
export interface IMaciVerifyingKeys {
/**
* The verifying key for the poll joining circuit
*/
pollJoiningVkOnChain: IVkContractParams;
/**
* The verifying key for the poll joined circuit
*/
pollJoinedVkOnChain: IVkContractParams;
/**
* The verifying key for the process messages circuit
*/
processVkOnChain: IVkContractParams;
/**
* The verifying key for the tally votes circuit
*/
tallyVkOnChain: IVkContractParams;
}

/**
* Circuit parameters
*/
export interface ICircuitParams {
/**
* The state tree depth
*/
stateTreeDepth: number;
/**
* The intermediate state tree depth (ballot tree)
*/
intStateTreeDepth: number;
/**
* The vote option tree depth
*/
voteOptionTreeDepth: number;
/**
* The message batch size
*/
messageBatchSize: number;
}

/**
* Maci verifying keys
*/
export interface IMaciVks {
/**
* The poll joining verifying key
*/
pollJoiningVk?: VerifyingKey;
/**
* The poll joined verifying key
*/
pollJoinedVk?: VerifyingKey;
/**
* The message processing verifying key
*/
processVk?: VerifyingKey;
/**
* The tally verifying key
*/
tallyVk?: VerifyingKey;
}

/**
* Arguments for the extractAllVks function
*/
export interface IExtractAllVksArgs {
/**
* The path to the poll joining zkey
*/
pollJoiningZkeyPath?: string;
/**
* The path to the poll joined zkey
*/
pollJoinedZkeyPath?: string;
/**
* The path to the process messages zkey
*/
processMessagesZkeyPath?: string;
/**
* The path to the tally votes zkey
*/
tallyVotesZkeyPath?: string;
}
23 changes: 23 additions & 0 deletions packages/sdk/ts/utils/params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ICircuitParams } from "./interfaces";

/**
* Validate the circuit parameters
* @param params - The circuit parameters
*/
export const validateParams = ({
stateTreeDepth,
intStateTreeDepth,
voteOptionTreeDepth,
messageBatchSize,
}: ICircuitParams): boolean => {
// validate args
if (stateTreeDepth < 1 || intStateTreeDepth < 1 || voteOptionTreeDepth < 1 || messageBatchSize < 1) {
throw new Error("Invalid depth or batch size parameters");
}

if (stateTreeDepth < intStateTreeDepth) {
throw new Error("Invalid state tree depth or intermediate state tree depth");
}

return true;
};
35 changes: 35 additions & 0 deletions packages/sdk/ts/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import os from "os";

declare global {
interface ITerminatable {
terminate: () => Promise<unknown>;
}

// eslint-disable-next-line vars-on-top, no-var, camelcase
var curve_bn128: ITerminatable | undefined;

// eslint-disable-next-line vars-on-top, no-var, camelcase
var curve_bls12381: ITerminatable | undefined;
}

/**
* Check if we are running on an arm chip
* @returns whether we are running on an arm chip
*/
export const isArm = (): boolean => os.arch().includes("arm");

/*
* https://github.com/iden3/snarkjs/issues/152
* Need to cleanup the threads to avoid stalling
*/
export const cleanThreads = async (): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!globalThis) {
return;
}

const curves = ["curve_bn128", "curve_bls12381"];
await Promise.all(
curves.map((curve) => globalThis[curve as "curve_bn128" | "curve_bls12381"]?.terminate()).filter(Boolean),
);
};
Loading

0 comments on commit ade2511

Please sign in to comment.