Skip to content

Commit

Permalink
feat(contract): support qv and non-qv verification keys
Browse files Browse the repository at this point in the history
- [x] Add mode for VkRegistry mappings
- [x] Compatibility fixes
  • Loading branch information
0xmad committed Apr 8, 2024
1 parent 8f7a3f2 commit a0cce8c
Show file tree
Hide file tree
Showing 23 changed files with 177 additions and 54 deletions.
2 changes: 1 addition & 1 deletion cli/tests/e2e/e2e.nonQv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe("e2e tests with non quadratic voting", function test() {
// we deploy the vk registry contract
await deployVkRegistryContract({ signer });
// we set the verifying keys
await setVerifyingKeys({ ...setVerifyingKeysNonQvArgs, signer });
await setVerifyingKeys({ ...setVerifyingKeysNonQvArgs, useQuadraticVoting: false, signer });
});

describe("1 signup, 1 message", () => {
Expand Down
5 changes: 4 additions & 1 deletion cli/ts/commands/checkVerifyingKeys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { extractVk } from "maci-circuits";
import { VkRegistry__factory as VkRegistryFactory } from "maci-contracts";
import { EMode, VkRegistry__factory as VkRegistryFactory } from "maci-contracts";
import { VerifyingKey } from "maci-domainobjs";

import fs from "fs";
Expand Down Expand Up @@ -34,6 +34,7 @@ export const checkVerifyingKeys = async ({
tallyVotesZkeyPath,
vkRegistry,
signer,
useQuadraticVoting = true,
quiet = true,
}: CheckVerifyingKeysArgs): Promise<boolean> => {
banner(quiet);
Expand Down Expand Up @@ -75,12 +76,14 @@ export const checkVerifyingKeys = async ({
messageTreeDepth,
voteOptionTreeDepth,
messageBatchSize,
useQuadraticVoting ? EMode.QV : EMode.NON_QV,
);

const tallyVkOnChain = await vkRegistryContractInstance.getTallyVk(
stateTreeDepth,
intStateTreeDepth,
voteOptionTreeDepth,
useQuadraticVoting ? EMode.QV : EMode.NON_QV,
);

// do the actual validation
Expand Down
9 changes: 9 additions & 0 deletions cli/ts/commands/proveOnChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Verifier__factory as VerifierFactory,
formatProofForVerifierContract,
type IVerifyingKeyStruct,
EMode,
} from "maci-contracts";
import { STATE_TREE_ARITY } from "maci-core";
import { G1Point, G2Point, hashLeftRight } from "maci-crypto";
Expand Down Expand Up @@ -165,6 +166,13 @@ export const proveOnChain = async ({
}

let numberBatchesProcessed = Number(await mpContract.numBatchesProcessed());
const tallyMode = await tallyContract.isQv().then((isQv) => (isQv ? EMode.QV : EMode.NON_QV));
const mpMode = await mpContract.isQv().then((isQv) => (isQv ? EMode.QV : EMode.NON_QV));

if (tallyMode !== mpMode) {
logError("Tally and MessageProcessor modes are not compatible");
}

const messageRootOnChain = await messageAqContract.getMainRoot(Number(treeDepths.messageTreeDepth));

const stateTreeDepth = Number(await maciContract.stateTreeDepth());
Expand All @@ -173,6 +181,7 @@ export const proveOnChain = async ({
treeDepths.messageTreeDepth,
treeDepths.voteOptionTreeDepth,
messageBatchSize,
mpMode,
);

const dd = await pollContract.getDeployTimeAndDuration();
Expand Down
17 changes: 13 additions & 4 deletions cli/ts/commands/setVerifyingKeys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { extractVk } from "maci-circuits";
import { type IVerifyingKeyStruct, VkRegistry__factory as VkRegistryFactory } from "maci-contracts";
import { type IVerifyingKeyStruct, VkRegistry__factory as VkRegistryFactory, EMode } from "maci-contracts";
import { genProcessVkSig, genTallyVkSig } from "maci-core";
import { VerifyingKey } from "maci-domainobjs";

Expand Down Expand Up @@ -33,6 +33,7 @@ export const setVerifyingKeys = async ({
tallyVotesZkeyPath,
vkRegistry,
signer,
useQuadraticVoting = true,
quiet = true,
}: SetVerifyingKeysArgs): Promise<void> => {
banner(quiet);
Expand Down Expand Up @@ -121,16 +122,17 @@ export const setVerifyingKeys = async ({
const messageBatchSize = 5 ** messageBatchDepth;

// check if the process messages vk was already set
const mode = useQuadraticVoting ? EMode.QV : EMode.NON_QV;
const processVkSig = genProcessVkSig(stateTreeDepth, messageTreeDepth, voteOptionTreeDepth, messageBatchSize);

if (await vkRegistryContract.isProcessVkSet(processVkSig)) {
if (await vkRegistryContract.isProcessVkSet(processVkSig, mode)) {
logError("This process verifying key is already set in the contract");
}

// do the same for the tally votes vk
const tallyVkSig = genTallyVkSig(stateTreeDepth, intStateTreeDepth, voteOptionTreeDepth);

if (await vkRegistryContract.isTallyVkSet(tallyVkSig)) {
if (await vkRegistryContract.isTallyVkSet(tallyVkSig, mode)) {
logError("This tally verifying key is already set in the contract");
}

Expand All @@ -144,6 +146,7 @@ export const setVerifyingKeys = async ({
messageTreeDepth,
voteOptionTreeDepth,
messageBatchSize,
mode,
processVk.asContractParam() as IVerifyingKeyStruct,
tallyVk.asContractParam() as IVerifyingKeyStruct,
);
Expand All @@ -162,9 +165,15 @@ export const setVerifyingKeys = async ({
messageTreeDepth,
voteOptionTreeDepth,
messageBatchSize,
mode,
);

const tallyVkOnChain = await vkRegistryContract.getTallyVk(stateTreeDepth, intStateTreeDepth, voteOptionTreeDepth);
const tallyVkOnChain = await vkRegistryContract.getTallyVk(
stateTreeDepth,
intStateTreeDepth,
voteOptionTreeDepth,
mode,
);

if (!compareVks(processVk, processVkOnChain)) {
logError("processVk mismatch");
Expand Down
4 changes: 4 additions & 0 deletions cli/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ program
program
.command("checkVerifyingKeys")
.description("check that the verifying keys in the contract match the local ones")
.option("-uq, --use-quadratic-voting", "whether to use quadratic voting", (value) => value === "true", true)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.option("-vk, --vk-contract <vkContract>", "the VkRegistry contract address")
Expand Down Expand Up @@ -113,6 +114,7 @@ program
tallyVotesZkeyPath: cmdOptions.tallyVotesZkey,
vkRegistry: cmdOptions.vkContract,
quiet: cmdOptions.quiet,
useQuadraticVoting: cmdOptions.useQuadraticVoting,
signer,
});
} catch (error) {
Expand Down Expand Up @@ -239,6 +241,7 @@ program
"-t, --tally-votes-zkey <tallyVotesZkeyPath>",
"the tally votes zkey path (see different options for zkey files to use specific circuits https://maci.pse.dev/docs/trusted-setup, https://maci.pse.dev/docs/testing/#pre-compiled-artifacts-for-testing)",
)
.option("-uq, --use-quadratic-voting", "whether to use quadratic voting", (value) => value === "true", true)
.option("-k, --vk-registry <vkRegistry>", "the vk registry contract address")
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
Expand All @@ -256,6 +259,7 @@ program
tallyVotesZkeyPath: cmdObj.tallyVotesZkey,
vkRegistry: cmdObj.vkRegistry,
quiet: cmdObj.quiet,
useQuadraticVoting: cmdObj.useQuadraticVoting,
signer,
});
} catch (error) {
Expand Down
10 changes: 10 additions & 0 deletions cli/ts/utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ export interface CheckVerifyingKeysArgs {
* Whether to log the output
*/
quiet?: boolean;

/**
* Whether to use quadratic voting or not
*/
useQuadraticVoting?: boolean;
}

/**
Expand Down Expand Up @@ -823,6 +828,11 @@ export interface SetVerifyingKeysArgs {
* Whether to log the output
*/
quiet?: boolean;

/**
* Whether to use quadratic voting or not
*/
useQuadraticVoting?: boolean;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion contracts/contracts/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ contract MACI is IMACI, Params, Utilities, Ownable {
_owner
);

address mp = messageProcessorFactory.deploy(_verifier, _vkRegistry, p, _owner);
address mp = messageProcessorFactory.deploy(_verifier, _vkRegistry, p, _owner, _isQv);
address tally = tallyFactory.deploy(_verifier, _vkRegistry, p, mp, _owner, _isQv);

polls[pollId] = p;
Expand Down
9 changes: 7 additions & 2 deletions contracts/contracts/MessageProcessor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,18 @@ contract MessageProcessor is Ownable, SnarkCommon, Hasher, CommonUtilities, IMes
IPoll public immutable poll;
IVerifier public immutable verifier;
IVkRegistry public immutable vkRegistry;
bool public immutable isQv;

/// @notice Create a new instance
/// @param _verifier The Verifier contract address
/// @param _vkRegistry The VkRegistry contract address
/// @param _poll The Poll contract address
constructor(address _verifier, address _vkRegistry, address _poll) payable {
/// @param _isQv Whether to support QV or not
constructor(address _verifier, address _vkRegistry, address _poll, bool _isQv) payable {
verifier = IVerifier(_verifier);
vkRegistry = IVkRegistry(_vkRegistry);
poll = IPoll(_poll);
isQv = _isQv;
}

/// @notice Update the Poll's currentSbCommitment if the proof is valid.
Expand Down Expand Up @@ -180,11 +183,13 @@ contract MessageProcessor is Ownable, SnarkCommon, Hasher, CommonUtilities, IMes
);

// Get the verifying key from the VkRegistry
IVkRegistry.Mode mode = isQv ? IVkRegistry.Mode.QV : IVkRegistry.Mode.NON_QV;
VerifyingKey memory vk = vkRegistry.getProcessVk(
maci.stateTreeDepth(),
_messageTreeDepth,
_voteOptionTreeDepth,
TREE_ARITY ** _messageTreeSubDepth
TREE_ARITY ** _messageTreeSubDepth,
mode
);

isValid = verifier.verify(_proof, vk, publicInputHash);
Expand Down
5 changes: 3 additions & 2 deletions contracts/contracts/MessageProcessorFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ contract MessageProcessorFactory is Params, DomainObjs, IMessageProcessorFactory
address _verifier,
address _vkRegistry,
address _poll,
address _owner
address _owner,
bool _isQv
) public returns (address messageProcessorAddr) {
// deploy MessageProcessor for this Poll
MessageProcessor messageProcessor = new MessageProcessor(_verifier, _vkRegistry, _poll);
MessageProcessor messageProcessor = new MessageProcessor(_verifier, _vkRegistry, _poll, _isQv);
messageProcessor.transferOwnership(_owner);
messageProcessorAddr = address(messageProcessor);
}
Expand Down
3 changes: 2 additions & 1 deletion contracts/contracts/Tally.sol
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ contract Tally is Ownable, SnarkCommon, CommonUtilities, Hasher {
(IMACI maci, , ) = poll.extContracts();

// Get the verifying key
VerifyingKey memory vk = vkRegistry.getTallyVk(maci.stateTreeDepth(), intStateTreeDepth, voteOptionTreeDepth);
IVkRegistry.Mode mode = isQv ? IVkRegistry.Mode.QV : IVkRegistry.Mode.NON_QV;
VerifyingKey memory vk = vkRegistry.getTallyVk(maci.stateTreeDepth(), intStateTreeDepth, voteOptionTreeDepth, mode);

// Get the public inputs
uint256 publicInputHash = genTallyVotesPublicInputHash(
Expand Down
Loading

0 comments on commit a0cce8c

Please sign in to comment.