Skip to content

Commit

Permalink
feat: optimize deployment and tally event
Browse files Browse the repository at this point in the history
- [x] Update integration and cli docs
- [x] Add poseidon contract addresses as cli arguments
- [x] Add BallotsTallied(address) event for Tally contract
- [x] Reuse already deployed poseidon contracts
- [x] Use network to distingish contracts for different deployments
  • Loading branch information
0xmad committed Jan 23, 2024
1 parent c6e7fee commit 185b407
Show file tree
Hide file tree
Showing 39 changed files with 394 additions and 197 deletions.
3 changes: 2 additions & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"max-line-length": ["warn", 120],
"quotes": ["error", "double"],
"func-visibility": ["error", { "ignoreConstructors": true }],
"state-visibility": "error"
"state-visibility": "error",
"immutable-vars-naming": ["warn", { "immutablesAsConstants": false }]
}
}
24 changes: 16 additions & 8 deletions cli/tests/unit/topup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ describe("topup", () => {
const signupGatekepper = await deployFreeForAllSignUpGatekeeper(signer, true);
const topupCredit = await deployTopupCredit(signer, true);
const initialVoiceCreditProxyAddress = await deployConstantInitialVoiceCreditProxy(100, signer, true);
const maciContracts = await deployMaci(
await signupGatekepper.getAddress(),
await initialVoiceCreditProxyAddress.getAddress(),
await topupCredit.getAddress(),
const [signUpTokenGatekeeperContractAddress, initialVoiceCreditBalanceAddress, topupCreditContractAddress] =
await Promise.all([
signupGatekepper.getAddress(),
initialVoiceCreditProxyAddress.getAddress(),
topupCredit.getAddress(),
]);

const { maciContract } = await deployMaci({
signUpTokenGatekeeperContractAddress,
initialVoiceCreditBalanceAddress,
topupCreditContractAddress,
signer,
10,
true,
);
maciAddress = await maciContracts.maciContract.getAddress();
stateTreeDepth: 10,
quiet: true,
});

maciAddress = await maciContract.getAddress();
});

it("should throw when the state index is invalid", async () => {
Expand Down
14 changes: 9 additions & 5 deletions cli/ts/commands/airdrop.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BaseContract } from "ethers";
import { type MACI, type TopupCredit, getDefaultSigner, parseArtifact } from "maci-contracts";
import { type MACI, type TopupCredit, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts";

import { type AirdropArgs, logError, logGreen, success, readContractAddress, contractExists, banner } from "../utils";

Expand All @@ -18,8 +18,12 @@ export const airdrop = async ({
}: AirdropArgs): Promise<void> => {
banner(quiet);

// get the signer
const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

// get the topup credit address from storage
const topupCredit = readContractAddress("TopupCredit");
const topupCredit = readContractAddress("TopupCredit", network?.name);

// we want to ensure that we have either the address stored
// or that it was passed as a paramter
Expand All @@ -29,8 +33,6 @@ export const airdrop = async ({

const ERC20Address = contractAddress || topupCredit;

// get the signer
const signer = await getDefaultSigner();
// check if the contract exists
if (!(await contractExists(signer.provider!, ERC20Address))) {
logError("Invalid ERC20 contract address");
Expand Down Expand Up @@ -60,7 +62,9 @@ export const airdrop = async ({
// if there is a poll id provided, we can pre-approve all of the tokens
// so there is no need to do it afterwards
if (pollId !== undefined) {
const maciContractAddress = readContractAddress("MACI") ? readContractAddress("MACI") : maciAddress;
const maciContractAddress = readContractAddress("MACI", network?.name)
? readContractAddress("MACI", network?.name)
: maciAddress;

if (!maciAddress) {
logError("Please provide a MACI contract address");
Expand Down
8 changes: 5 additions & 3 deletions cli/ts/commands/checkVerifyingKeys.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BaseContract } from "ethers";
import { extractVk } from "maci-circuits";
import { type VkRegistry, getDefaultSigner, parseArtifact } from "maci-contracts";
import { type VkRegistry, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts";
import { G1Point, G2Point } from "maci-crypto";
import { VerifyingKey } from "maci-domainobjs";

Expand Down Expand Up @@ -41,12 +41,14 @@ export const checkVerifyingKeys = async ({
banner(quiet);
// get the signer
const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

// ensure we have the contract addresses that we need
if (!readContractAddress("VkRegistry") && !vkRegistry) {
if (!readContractAddress("VkRegistry", network?.name) && !vkRegistry) {
logError("Please provide a VkRegistry contract address");
}
const vkContractAddress = vkRegistry || readContractAddress("VkRegistry");

const vkContractAddress = vkRegistry || readContractAddress("VkRegistry", network?.name);

if (!(await contractExists(signer.provider!, vkContractAddress))) {
logError("The VkRegistry contract does not exist");
Expand Down
61 changes: 39 additions & 22 deletions cli/ts/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
deployMaci,
deployTopupCredit,
getDefaultSigner,
getDefaultNetwork,
} from "maci-contracts";

import {
Expand All @@ -29,6 +30,10 @@ export const deploy = async ({
initialVoiceCredits,
initialVoiceCreditsProxyAddress,
signupGatekeeperAddress,
poseidonT3Address,
poseidonT4Address,
poseidonT5Address,
poseidonT6Address,
quiet = true,
}: DeployArgs): Promise<DeployedContracts> => {
banner(quiet);
Expand All @@ -38,6 +43,12 @@ export const deploy = async ({
}

const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

const poseidonT3 = poseidonT3Address || readContractAddress("PoseidonT3", network?.name);
const poseidonT4 = poseidonT4Address || readContractAddress("PoseidonT4", network?.name);
const poseidonT5 = poseidonT5Address || readContractAddress("PoseidonT5", network?.name);
const poseidonT6 = poseidonT6Address || readContractAddress("PoseidonT6", network?.name);

// if we did not deploy it before, then deploy it now
let initialVoiceCreditProxyContractAddress: string | undefined;
Expand All @@ -53,7 +64,7 @@ export const deploy = async ({
}

// check if we have a signupGatekeeper already deployed or passed as arg
let signupGatekeeperContractAddress = readContractAddress("SignUpGatekeeper");
let signupGatekeeperContractAddress = readContractAddress("SignUpGatekeeper", network?.name);
if (!signupGatekeeperContractAddress && !signupGatekeeperAddress) {
const contract = await deployFreeForAllSignUpGatekeeper(signer, true);
signupGatekeeperContractAddress = await contract.getAddress();
Expand All @@ -71,14 +82,20 @@ export const deploy = async ({
]);

// deploy MACI, stateAq, PollFactory and poseidon
const { maciContract, stateAqContract, pollFactoryContract, poseidonAddrs } = await deployMaci(
signupGatekeeperContractAddress,
initialVoiceCreditProxyContractAddress!,
topUpCreditAddress,
const { maciContract, stateAqContract, pollFactoryContract, poseidonAddrs } = await deployMaci({
signUpTokenGatekeeperContractAddress: signupGatekeeperContractAddress,
initialVoiceCreditBalanceAddress: initialVoiceCreditProxyContractAddress!,
topupCreditContractAddress: topUpCreditAddress,
poseidonAddresses: {
poseidonT3,
poseidonT4,
poseidonT5,
poseidonT6,
},
signer,
stateTreeDepth,
true,
);
quiet: true,
});

const [maciContractAddress, stateAqContractAddress, pollFactoryContractAddress] = await Promise.all([
maciContract.getAddress(),
Expand All @@ -87,17 +104,17 @@ export const deploy = async ({
]);

// save to the JSON File
storeContractAddress("InitialVoiceCreditProxy", initialVoiceCreditProxyContractAddress!);
storeContractAddress("SignUpGatekeeper", signupGatekeeperContractAddress);
storeContractAddress("Verifier", verifierContractAddress);
storeContractAddress("MACI", maciContractAddress);
storeContractAddress("StateAq", stateAqContractAddress);
storeContractAddress("PollFactory", pollFactoryContractAddress);
storeContractAddress("TopupCredit", topUpCreditAddress);
storeContractAddress("PoseidonT3", poseidonAddrs[0]);
storeContractAddress("PoseidonT4", poseidonAddrs[1]);
storeContractAddress("PoseidonT5", poseidonAddrs[2]);
storeContractAddress("PoseidonT6", poseidonAddrs[3]);
storeContractAddress("InitialVoiceCreditProxy", initialVoiceCreditProxyContractAddress!, network?.name);
storeContractAddress("SignUpGatekeeper", signupGatekeeperContractAddress, network?.name);
storeContractAddress("Verifier", verifierContractAddress, network?.name);
storeContractAddress("MACI", maciContractAddress, network?.name);
storeContractAddress("StateAq", stateAqContractAddress, network?.name);
storeContractAddress("PollFactory", pollFactoryContractAddress, network?.name);
storeContractAddress("TopupCredit", topUpCreditAddress, network?.name);
storeContractAddress("PoseidonT3", poseidonAddrs.poseidonT3, network?.name);
storeContractAddress("PoseidonT4", poseidonAddrs.poseidonT4, network?.name);
storeContractAddress("PoseidonT5", poseidonAddrs.poseidonT5, network?.name);
storeContractAddress("PoseidonT6", poseidonAddrs.poseidonT6, network?.name);

logGreen(quiet, success(`MACI deployed at: ${maciContractAddress}`));

Expand All @@ -108,10 +125,10 @@ export const deploy = async ({
pollFactoryAddress: pollFactoryContractAddress,
verifierAddress: verifierContractAddress,
topupCreditAddress: topUpCreditAddress,
poseidonT3Address: poseidonAddrs[0],
poseidonT4Address: poseidonAddrs[1],
poseidonT5Address: poseidonAddrs[2],
poseidonT6Address: poseidonAddrs[3],
poseidonT3Address: poseidonAddrs.poseidonT3,
poseidonT4Address: poseidonAddrs.poseidonT4,
poseidonT5Address: poseidonAddrs.poseidonT5,
poseidonT6Address: poseidonAddrs.poseidonT6,
signUpGatekeeperAddress: signupGatekeeperContractAddress,
initialVoiceCreditProxyAddress: initialVoiceCreditProxyContractAddress!,
};
Expand Down
21 changes: 11 additions & 10 deletions cli/ts/commands/deployPoll.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BaseContract } from "ethers";
import { type MACI, getDefaultSigner, parseArtifact } from "maci-contracts";
import { type MACI, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts";
import { PubKey } from "maci-domainobjs";

import {
Expand Down Expand Up @@ -35,15 +35,18 @@ export const deployPoll = async ({
}: DeployPollArgs): Promise<PollContracts> => {
banner(quiet);

const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

// check if we have a vkRegistry already deployed or passed as arg
const vkRegistryContractAddress = readContractAddress("VkRegistry");
const vkRegistryContractAddress = readContractAddress("VkRegistry", network?.name);
if (!vkRegistryContractAddress && !vkRegistryAddress) {
logError("Please provide a VkRegistry contract address");
}

const vkRegistry = vkRegistryAddress || vkRegistryContractAddress;

const maciContractAddress = readContractAddress("MACI");
const maciContractAddress = readContractAddress("MACI", network?.name);
if (!maciContractAddress && !maciAddress) {
logError("Please provide a MACI contract address");
}
Expand Down Expand Up @@ -80,8 +83,6 @@ export const deployPoll = async ({
logError("Vote option tree depth cannot be <= 0");
}

const signer = await getDefaultSigner();

// we check that the contract is deployed
if (!(await contractExists(signer.provider!, maci))) {
logError("MACI contract does not exist");
Expand All @@ -95,7 +96,7 @@ export const deployPoll = async ({
const unserializedKey = PubKey.deserialize(coordinatorPubkey);

// get the verifier contract
const verifierContractAddress = readContractAddress("Verifier");
const verifierContractAddress = readContractAddress("Verifier", network?.name);

const maciAbi = parseArtifact("MACI")[0];
const maciContract = new BaseContract(maci, maciAbi, signer) as MACI;
Expand Down Expand Up @@ -169,12 +170,12 @@ export const deployPoll = async ({
logGreen(quiet, info(`Tally contract: ${tallyContractAddress}`));
if (subsidyEnabled && subsidyContractAddress) {
logGreen(quiet, info(`Subsidy contract: ${subsidyContractAddress}`));
storeContractAddress(`Subsidy-${pollId.toString()}`, subsidyContractAddress);
storeContractAddress(`Subsidy-${pollId.toString()}`, subsidyContractAddress, network?.name);
}
// store the addresss
storeContractAddress(`MessageProcessor-${pollId.toString()}`, messageProcessorContractAddress);
storeContractAddress(`Tally-${pollId.toString()}`, tallyContractAddress);
storeContractAddress(`Poll-${pollId.toString()}`, pollAddr);
storeContractAddress(`MessageProcessor-${pollId.toString()}`, messageProcessorContractAddress, network?.name);
storeContractAddress(`Tally-${pollId.toString()}`, tallyContractAddress, network?.name);
storeContractAddress(`Poll-${pollId.toString()}`, pollAddr, network?.name);
} catch (error) {
logError((error as Error).message);
}
Expand Down
8 changes: 5 additions & 3 deletions cli/ts/commands/deployVkRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deployVkRegistry, getDefaultSigner } from "maci-contracts";
import { deployVkRegistry, getDefaultSigner, getDefaultNetwork } from "maci-contracts";

import fs from "fs";

Expand All @@ -24,10 +24,12 @@ export const deployVkRegistryContract = async (quiet = true): Promise<string> =>
resetContractAddresses();
}

const signer = await getDefaultSigner();
const network = await getDefaultNetwork();
// deploy and store the address
const vkRegistry = await deployVkRegistry(await getDefaultSigner(), true);
const vkRegistry = await deployVkRegistry(signer, true);
const vkRegistryAddress = await vkRegistry.getAddress();
storeContractAddress("VkRegistry", vkRegistryAddress);
storeContractAddress("VkRegistry", vkRegistryAddress, network?.name);

logGreen(quiet, success(`VkRegistry deployed at: ${vkRegistryAddress}`));
return vkRegistryAddress;
Expand Down
11 changes: 7 additions & 4 deletions cli/ts/commands/genLocalState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { JsonRpcProvider } from "ethers";
import { getDefaultSigner, genMaciStateFromContract } from "maci-contracts";
import { getDefaultSigner, getDefaultNetwork, genMaciStateFromContract } from "maci-contracts";
import { Keypair, PrivKey } from "maci-domainobjs";

import fs from "fs";
Expand Down Expand Up @@ -35,14 +35,17 @@ export const genLocalState = async ({
quiet = true,
}: GenLocalStateArgs): Promise<void> => {
banner(quiet);

const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

// validation of the maci contract address
if (!readContractAddress("MACI") && !maciContractAddress) {
if (!readContractAddress("MACI", network?.name) && !maciContractAddress) {
logError("MACI contract address is empty");
}

const maciAddress = maciContractAddress || readContractAddress("MACI");
const maciAddress = maciContractAddress || readContractAddress("MACI", network?.name);

const signer = await getDefaultSigner();
if (!(await contractExists(signer.provider!, maciAddress))) {
logError("MACI contract does not exist");
}
Expand Down
7 changes: 5 additions & 2 deletions cli/ts/commands/genProofs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
type Poll,
genMaciStateFromContract,
getDefaultSigner,
getDefaultNetwork,
parseArtifact,
} from "maci-contracts";
import { type CircuitInputs, type IJsonMaciState, MaciState } from "maci-core";
Expand Down Expand Up @@ -182,11 +183,13 @@ export const genProofs = async ({
const coordinatorKeypair = new Keypair(maciPrivKey);

const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

// contracts
if (!readContractAddress("MACI") && !maciAddress) {
if (!readContractAddress("MACI", network?.name) && !maciAddress) {
logError("MACI contract address is empty");
}
const maciContractAddress = maciAddress || readContractAddress("MACI");
const maciContractAddress = maciAddress || readContractAddress("MACI", network?.name);

if (!(await contractExists(signer.provider!, maciContractAddress))) {
logError("MACI contract does not exist");
Expand Down
14 changes: 11 additions & 3 deletions cli/ts/commands/mergeMessages.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { BaseContract } from "ethers";
import { type MACI, type Poll, type AccQueue, getDefaultSigner, parseArtifact } from "maci-contracts";
import {
type MACI,
type Poll,
type AccQueue,
getDefaultSigner,
getDefaultNetwork,
parseArtifact,
} from "maci-contracts";

import {
DEFAULT_SR_QUEUE_OPS,
Expand Down Expand Up @@ -27,12 +34,13 @@ export const mergeMessages = async ({
}: MergeMessagesArgs): Promise<void> => {
banner(quiet);
const signer = await getDefaultSigner();
const network = await getDefaultNetwork();

// maci contract validation
if (!readContractAddress("MACI") && !maciContractAddress) {
if (!readContractAddress("MACI", network?.name) && !maciContractAddress) {
logError("Could not read contracts");
}
const maciAddress = maciContractAddress || readContractAddress("MACI");
const maciAddress = maciContractAddress || readContractAddress("MACI", network?.name);
if (!(await contractExists(signer.provider!, maciAddress))) {
logError("MACI contract does not exist");
}
Expand Down
Loading

0 comments on commit 185b407

Please sign in to comment.