Skip to content

Commit

Permalink
feat: use gatekeeper per poll (#1961)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrlc03 authored Dec 18, 2024
1 parent 20092d1 commit 8e1ab15
Show file tree
Hide file tree
Showing 23 changed files with 480 additions and 40 deletions.
38 changes: 30 additions & 8 deletions packages/cli/ts/commands/deployPoll.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MACI__factory as MACIFactory, EMode } from "maci-contracts";
import { MACI__factory as MACIFactory, EMode, deployFreeForAllSignUpGatekeeper } from "maci-contracts";
import { PubKey } from "maci-domainobjs";

import {
Expand Down Expand Up @@ -26,6 +26,7 @@ export const deployPoll = async ({
coordinatorPubkey,
maciAddress,
vkRegistryAddress,
gatekeeperAddress,
signer,
quiet = true,
useQuadraticVoting = false,
Expand All @@ -49,6 +50,18 @@ export const deployPoll = async ({

const maci = maciAddress || maciContractAddress;

const maciContract = MACIFactory.connect(maci, signer);
const pollId = await maciContract.nextPollId();

// check if we have a signupGatekeeper already deployed or passed as arg
let signupGatekeeperContractAddress =
gatekeeperAddress || (await readContractAddress(`SignUpGatekeeper-${pollId.toString()}`, network?.name));

if (!signupGatekeeperContractAddress) {
const contract = await deployFreeForAllSignUpGatekeeper(signer, true);
signupGatekeeperContractAddress = await contract.getAddress();
}

// required arg -> poll duration
if (pollDuration <= 0) {
logError("Duration cannot be <= 0");
Expand Down Expand Up @@ -83,8 +96,6 @@ export const deployPoll = async ({
// get the verifier contract
const verifierContractAddress = await readContractAddress("Verifier", network?.name);

const maciContract = MACIFactory.connect(maci, signer);

// deploy the poll
let pollAddr = "";
let messageProcessorContractAddress = "";
Expand All @@ -103,6 +114,7 @@ export const deployPoll = async ({
verifierContractAddress,
vkRegistry,
useQuadraticVoting ? EMode.QV : EMode.NON_QV,
signupGatekeeperContractAddress,
{ gasLimit: 10000000 },
);

Expand Down Expand Up @@ -130,8 +142,8 @@ export const deployPoll = async ({
}

// eslint-disable-next-line no-underscore-dangle
const pollId = log.args._pollId;
const pollContracts = await maciContract.getPoll(pollId);
const eventPollId = log.args._pollId;
const pollContracts = await maciContract.getPoll(eventPollId);
pollAddr = pollContracts.poll;
messageProcessorContractAddress = pollContracts.messageProcessor;
tallyContractAddress = pollContracts.tally;
Expand All @@ -142,9 +154,18 @@ export const deployPoll = async ({
logGreen(quiet, info(`Tally contract: ${tallyContractAddress}`));

// store the address
await storeContractAddress(`MessageProcessor-${pollId.toString()}`, messageProcessorContractAddress, network?.name);
await storeContractAddress(`Tally-${pollId.toString()}`, tallyContractAddress, network?.name);
await storeContractAddress(`Poll-${pollId.toString()}`, pollAddr, network?.name);
await storeContractAddress(
`SignUpGatekeeper-${eventPollId.toString()}`,
signupGatekeeperContractAddress,
network?.name,
);
await storeContractAddress(
`MessageProcessor-${eventPollId.toString()}`,
messageProcessorContractAddress,
network?.name,
);
await storeContractAddress(`Tally-${eventPollId.toString()}`, tallyContractAddress, network?.name);
await storeContractAddress(`Poll-${eventPollId.toString()}`, pollAddr, network?.name);
} catch (error) {
logError((error as Error).message);
}
Expand All @@ -154,5 +175,6 @@ export const deployPoll = async ({
messageProcessor: messageProcessorContractAddress,
tally: tallyContractAddress,
poll: pollAddr,
signupGatekeeper: signupGatekeeperContractAddress,
};
};
6 changes: 5 additions & 1 deletion packages/cli/ts/commands/joinPoll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import fs from "fs";

import type { IJoinPollArgs, IJoinedUserArgs, IParsePollJoinEventsArgs, IJoinPollData } from "../utils";

import { contractExists, logError, logYellow, info, logGreen, success, BLOCKS_STEP } from "../utils";
import { contractExists, logError, logYellow, info, logGreen, success, BLOCKS_STEP, DEFAULT_SG_DATA } from "../utils";
import { banner } from "../utils/banner";

/**
Expand Down Expand Up @@ -195,6 +195,7 @@ export const joinPoll = async ({
rapidsnark,
pollWitgen,
pollWasm,
sgDataArg,
quiet = true,
}: IJoinPollArgs): Promise<IJoinPollData> => {
banner(quiet);
Expand Down Expand Up @@ -332,6 +333,8 @@ export const joinPoll = async ({
let pollStateIndex = "";
let receipt: ContractTransactionReceipt | null = null;

const sgData = sgDataArg || DEFAULT_SG_DATA;

try {
// generate the proof for this batch
const proof = await generateAndVerifyProof(
Expand All @@ -351,6 +354,7 @@ export const joinPoll = async ({
loadedCreditBalance!,
currentStateRootIndex,
proof,
sgData,
);
receipt = await tx.wait();
logYellow(quiet, info(`Transaction hash: ${receipt!.hash}`));
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ program
.description("join the poll")
.requiredOption("-sk, --priv-key <privKey>", "the private key")
.option("-i, --state-index <stateIndex>", "the user's state index", BigInt)
.requiredOption("-s, --sg-data <sgData>", "the signup gateway data")
.requiredOption("-esk, --poll-priv-key <pollPrivKey>", "the user ephemeral private key for the poll")
.option(
"-nv, --new-voice-credit-balance <newVoiceCreditBalance>",
Expand Down Expand Up @@ -265,6 +266,7 @@ program
useWasm: cmdObj.wasm,
rapidsnark: cmdObj.rapidsnark,
pollWitgen: cmdObj.pollWitnessgen,
sgDataArg: cmdObj.sgData,
});
} catch (error) {
program.error((error as Error).message, { exitCode: 1 });
Expand Down
11 changes: 11 additions & 0 deletions packages/cli/ts/utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface PollContracts {
poll: string;
messageProcessor: string;
tally: string;
signupGatekeeper: string;
}

/**
Expand Down Expand Up @@ -318,6 +319,11 @@ export interface DeployPollArgs {
* Whether to use quadratic voting or not
*/
useQuadraticVoting?: boolean;

/**
* The address of the gatekeeper contract
*/
gatekeeperAddress?: string;
}

/**
Expand Down Expand Up @@ -447,6 +453,11 @@ export interface IJoinPollArgs {
* Poll private key for the poll
*/
pollPrivKey: string;

/**
* The signup gatekeeper data
*/
sgDataArg?: string;
}

/**
Expand Down
7 changes: 5 additions & 2 deletions packages/contracts/contracts/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { IMessageProcessorFactory } from "./interfaces/IMPFactory.sol";
import { ITallyFactory } from "./interfaces/ITallyFactory.sol";
import { IVerifier } from "./interfaces/IVerifier.sol";
import { IVkRegistry } from "./interfaces/IVkRegistry.sol";
import { ISignUpGatekeeper } from "./interfaces/ISignUpGatekeeper.sol";
import { InitialVoiceCreditProxy } from "./initialVoiceCreditProxy/InitialVoiceCreditProxy.sol";
import { SignUpGatekeeper } from "./gatekeepers/SignUpGatekeeper.sol";
import { IMACI } from "./interfaces/IMACI.sol";
Expand Down Expand Up @@ -187,7 +188,8 @@ contract MACI is IMACI, DomainObjs, Params, Utilities {
PubKey memory _coordinatorPubKey,
address _verifier,
address _vkRegistry,
Mode _mode
Mode _mode,
address _gatekeeper
) public virtual {
// cache the poll to a local variable so we can increment it
uint256 pollId = nextPollId;
Expand All @@ -208,7 +210,8 @@ contract MACI is IMACI, DomainObjs, Params, Utilities {
ExtContracts memory extContracts = ExtContracts({
maci: IMACI(address(this)),
verifier: IVerifier(_verifier),
vkRegistry: IVkRegistry(_vkRegistry)
vkRegistry: IVkRegistry(_vkRegistry),
gatekeeper: ISignUpGatekeeper(_gatekeeper)
});

address p = pollFactory.deploy(
Expand Down
18 changes: 11 additions & 7 deletions packages/contracts/contracts/Poll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SnarkCommon } from "./crypto/SnarkCommon.sol";
import { LazyIMTData, InternalLazyIMT } from "./trees/LazyIMT.sol";
import { IMACI } from "./interfaces/IMACI.sol";
import { IPoll } from "./interfaces/IPoll.sol";
import { ISignUpGatekeeper } from "./interfaces/ISignUpGatekeeper.sol";
import { Utilities } from "./utilities/Utilities.sol";
import { CurveBabyJubJub } from "./crypto/BabyJubJub.sol";

Expand Down Expand Up @@ -284,28 +285,31 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll {
PubKey calldata _pubKey,
uint256 _newVoiceCreditBalance,
uint256 _stateRootIndex,
uint256[8] calldata _proof
uint256[8] calldata _proof,
bytes memory _signUpGatekeeperData
) public virtual isWithinVotingDeadline {
// Whether the user has already joined
if (pollNullifier[_nullifier]) {
revert UserAlreadyJoined();
}

// Set nullifier for user's private key
pollNullifier[_nullifier] = true;

// Verify user's proof
if (!verifyPollProof(_nullifier, _newVoiceCreditBalance, _stateRootIndex, _pubKey, _proof)) {
revert InvalidPollProof();
}

// Check if the user is eligible to join the poll
extContracts.gatekeeper.register(msg.sender, _signUpGatekeeperData);

// Store user in the pollStateTree
uint256 timestamp = block.timestamp;
uint256 stateLeaf = hashStateLeaf(StateLeaf(_pubKey, _newVoiceCreditBalance, timestamp));
uint256 stateLeaf = hashStateLeaf(StateLeaf(_pubKey, _newVoiceCreditBalance, block.timestamp));
InternalLazyIMT._insert(pollStateTree, stateLeaf);

// Set nullifier for user's private key
pollNullifier[_nullifier] = true;

uint256 pollStateIndex = pollStateTree.numberOfLeaves - 1;
emit PollJoined(_pubKey.x, _pubKey.y, _newVoiceCreditBalance, timestamp, _nullifier, pollStateIndex);
emit PollJoined(_pubKey.x, _pubKey.y, _newVoiceCreditBalance, block.timestamp, _nullifier, pollStateIndex);
}

/// @notice Verify the proof for Poll
Expand Down
3 changes: 2 additions & 1 deletion packages/contracts/contracts/interfaces/IPoll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ interface IPoll {
DomainObjs.PubKey calldata _pubKey,
uint256 _newVoiceCreditBalance,
uint256 _stateRootIndex,
uint256[8] calldata _proof
uint256[8] calldata _proof,
bytes memory _signUpGatekeeperData
) external;

/// @notice The number of messages which have been processed and the number of signups
Expand Down
11 changes: 11 additions & 0 deletions packages/contracts/contracts/interfaces/ISignUpGatekeeper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

/// @title ISignUpGatekeeper
/// @notice SignUpGatekeeper interface
interface ISignUpGatekeeper {
/// @notice Register a user
/// @param _user User address
/// @param _data Data to register
function register(address _user, bytes memory _data) external;
}
2 changes: 2 additions & 0 deletions packages/contracts/contracts/utilities/Params.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.20;
import { IMACI } from "../interfaces/IMACI.sol";
import { IVerifier } from "../interfaces/IVerifier.sol";
import { IVkRegistry } from "../interfaces/IVkRegistry.sol";
import { ISignUpGatekeeper } from "../interfaces/ISignUpGatekeeper.sol";

/// @title Params
/// @notice This contracts contains a number of structures
Expand All @@ -24,5 +25,6 @@ contract Params {
IMACI maci;
IVerifier verifier;
IVkRegistry vkRegistry;
ISignUpGatekeeper gatekeeper;
}
}
33 changes: 22 additions & 11 deletions packages/contracts/deploy-config-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.9a59264310d95cfd8eb7083aebeba221b5c26e77427f12b7c0f50bc1cc35e621",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"scroll_sepolia": {
Expand Down Expand Up @@ -133,7 +134,8 @@
"Poll": {
"pollDuration": 10800,
"coordinatorPubkey": "macipk.0a1ce79a43fa676ee3d2882c79d9164a24d4a22bb6190e3d8fa25d97bffc069a",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"optimism": {
Expand Down Expand Up @@ -202,7 +204,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.9a59264310d95cfd8eb7083aebeba221b5c26e77427f12b7c0f50bc1cc35e621",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"arbitrum_sepolia": {
Expand Down Expand Up @@ -271,7 +274,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.9a59264310d95cfd8eb7083aebeba221b5c26e77427f12b7c0f50bc1cc35e621",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"localhost": {
Expand Down Expand Up @@ -340,7 +344,8 @@
"Poll": {
"pollDuration": 30,
"coordinatorPubkey": "macipk.29add77d27341c4cdfc2fb623175ecfd6527a286e3e7ded785d9fd7afbbdf399",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"base_sepolia": {
Expand Down Expand Up @@ -409,7 +414,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.9a59264310d95cfd8eb7083aebeba221b5c26e77427f12b7c0f50bc1cc35e621",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"optimism_sepolia": {
Expand Down Expand Up @@ -483,7 +489,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.9a59264310d95cfd8eb7083aebeba221b5c26e77427f12b7c0f50bc1cc35e621",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"gnosis_chiado": {
Expand Down Expand Up @@ -557,7 +564,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.0a1ce79a43fa676ee3d2882c79d9164a24d4a22bb6190e3d8fa25d97bffc069a",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"gnosis": {
Expand Down Expand Up @@ -631,7 +639,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.0a1ce79a43fa676ee3d2882c79d9164a24d4a22bb6190e3d8fa25d97bffc069a",
"useQuadraticVoting": false
"useQuadraticVoting": false,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"polygon_amoy": {
Expand Down Expand Up @@ -705,7 +714,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.0a1ce79a43fa676ee3d2882c79d9164a24d4a22bb6190e3d8fa25d97bffc069a",
"useQuadraticVoting": true
"useQuadraticVoting": true,
"gatekeeper": "FreeForAllGatekeeper"
}
},
"polygon": {
Expand Down Expand Up @@ -779,7 +789,8 @@
"Poll": {
"pollDuration": 3600,
"coordinatorPubkey": "macipk.0a1ce79a43fa676ee3d2882c79d9164a24d4a22bb6190e3d8fa25d97bffc069a",
"useQuadraticVoting": true
"useQuadraticVoting": true,
"gatekeeper": "FreeForAllGatekeeper"
}
}
}
Loading

0 comments on commit 8e1ab15

Please sign in to comment.