From f706d9aa5689f58e646650d92b188f27e5beb4d8 Mon Sep 17 00:00:00 2001 From: 0xmad <0xmad@users.noreply.github.com> Date: Mon, 12 Feb 2024 16:11:55 -0600 Subject: [PATCH] chore(cli): prepare cli package for web apps - [x] Make signer required - [x] Update types - [x] Added sdk folder for web app commands --- cli/package.json | 10 + .../ceremony-params/ceremonyParams.test.ts | 37 +-- cli/tests/constants.ts | 20 +- cli/tests/e2e/e2e.nonQv.test.ts | 15 +- cli/tests/e2e/e2e.subsidy.test.ts | 123 +++++---- cli/tests/e2e/e2e.test.ts | 244 ++++++++++-------- cli/tests/e2e/keyChange.test.ts | 72 +++--- cli/tests/unit/airdrop.test.ts | 12 +- cli/tests/unit/fundWallet.test.ts | 4 +- cli/tests/unit/timeTravel.test.ts | 2 +- cli/tests/unit/topup.test.ts | 6 +- cli/ts/commands/airdrop.ts | 19 +- cli/ts/commands/checkVerifyingKeys.ts | 15 +- cli/ts/commands/deploy.ts | 15 +- cli/ts/commands/deployPoll.ts | 11 +- cli/ts/commands/deployVkRegistry.ts | 7 +- cli/ts/commands/fundWallet.ts | 5 +- cli/ts/commands/genLocalState.ts | 13 +- cli/ts/commands/genProofs.ts | 35 +-- cli/ts/commands/mergeMessages.ts | 33 +-- cli/ts/commands/mergeSignups.ts | 31 +-- cli/ts/commands/proveOnChain.ts | 83 ++---- cli/ts/commands/publish.ts | 18 +- cli/ts/commands/setVerifyingKeys.ts | 17 +- cli/ts/commands/signup.ts | 11 +- cli/ts/commands/timeTravel.ts | 7 +- cli/ts/commands/topup.ts | 16 +- cli/ts/commands/verify.ts | 32 +-- cli/ts/index.ts | 59 ++++- cli/ts/sdk/index.ts | 3 + cli/ts/utils/interfaces.ts | 162 ++++++------ .../ts/__tests__/integration.test.ts | 21 +- 32 files changed, 605 insertions(+), 553 deletions(-) create mode 100644 cli/ts/sdk/index.ts diff --git a/cli/package.json b/cli/package.json index 2032293ec2..d23b4841e0 100644 --- a/cli/package.json +++ b/cli/package.json @@ -3,6 +3,16 @@ "version": "1.1.2", "description": "CLI utilities for MACI", "main": "build/ts/index.js", + "exports": { + ".": { + "types": "./build/ts/index.d.ts", + "default": "./build/ts/index.js" + }, + "./sdk": { + "types": "./build/ts/sdk/index.d.ts", + "default": "./build/ts/sdk/index.js" + } + }, "bin": { "maci-cli": "./build/ts/index.js" }, diff --git a/cli/tests/ceremony-params/ceremonyParams.test.ts b/cli/tests/ceremony-params/ceremonyParams.test.ts index 66bf8acba4..cf1a48ee00 100644 --- a/cli/tests/ceremony-params/ceremonyParams.test.ts +++ b/cli/tests/ceremony-params/ceremonyParams.test.ts @@ -1,6 +1,9 @@ +import { getDefaultSigner } from "maci-contracts"; import { genRandomSalt } from "maci-crypto"; import { Keypair } from "maci-domainobjs"; +import type { Signer } from "ethers"; + import { deploy, deployPoll, @@ -52,8 +55,9 @@ describe("stress tests", function test() { this.timeout(90000000); let maciAddresses: DeployedContracts; + let signer: Signer; - const verifyingKeysArgs: SetVerifyingKeysArgs = { + const verifyingKeysArgs: Omit = { quiet: true, stateTreeDepth, intStateTreeDepth, @@ -64,11 +68,11 @@ describe("stress tests", function test() { tallyVotesZkeyPath: ceremonyTallyVotesZkeyPath, }; - const ceremonyDeployArgs: DeployArgs = { + const ceremonyDeployArgs: Omit = { stateTreeDepth, }; - const deployPollArgs: DeployPollArgs = { + const deployPollArgs: Omit = { pollDuration, intStateTreeDepth, messageTreeSubDepth: messageBatchDepth, @@ -78,7 +82,7 @@ describe("stress tests", function test() { subsidyEnabled, }; - const genProofsCeremonyArgs: GenProofsArgs = { + const genProofsCeremonyArgs: Omit = { outputDir: testProofsDirPath, tallyFile: testTallyFilePath, tallyZkey: ceremonyTallyVotesZkeyPath, @@ -97,10 +101,12 @@ describe("stress tests", function test() { // before all tests we deploy the vk registry contract and set the verifying keys before(async () => { + signer = await getDefaultSigner(); + // we deploy the vk registry contract - await deployVkRegistryContract({}); + await deployVkRegistryContract({ signer }); // we set the verifying keys - await setVerifyingKeys(verifyingKeysArgs); + await setVerifyingKeys({ ...verifyingKeysArgs, signer }); }); const users = Array(2).fill(new Keypair()); @@ -112,13 +118,13 @@ describe("stress tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(ceremonyDeployArgs); + maciAddresses = await deploy({ ...ceremonyDeployArgs, signer }); // deploy a poll contract - await deployPoll(deployPollArgs); + await deployPoll({ ...deployPollArgs, signer }); }); it("should signup 1 user", async () => { - await signup({ maciPubKey: users[0].pubKey.serialize() }); + await signup({ maciPubKey: users[0].pubKey.serialize(), signer }); }); it("should publish 2 messages", async () => { @@ -137,17 +143,18 @@ describe("stress tests", function test() { salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), pollId: 0n, + signer, }); } }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel({ seconds: pollDuration }); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsCeremonyArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ seconds: pollDuration, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsCeremonyArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); }); }); diff --git a/cli/tests/constants.ts b/cli/tests/constants.ts index 65ab04eff0..d0833a1655 100644 --- a/cli/tests/constants.ts +++ b/cli/tests/constants.ts @@ -78,7 +78,7 @@ export const pollDuration = 90; export const maxMessages = 25; export const maxVoteOptions = 25; -export const setVerifyingKeysArgs: SetVerifyingKeysArgs = { +export const setVerifyingKeysArgs: Omit = { quiet: true, stateTreeDepth: STATE_TREE_DEPTH, intStateTreeDepth: INT_STATE_TREE_DEPTH, @@ -89,7 +89,7 @@ export const setVerifyingKeysArgs: SetVerifyingKeysArgs = { tallyVotesZkeyPath: tallyVotesTestZkeyPath, }; -export const setVerifyingKeysNonQvArgs: SetVerifyingKeysArgs = { +export const setVerifyingKeysNonQvArgs: Omit = { quiet: true, stateTreeDepth: STATE_TREE_DEPTH, intStateTreeDepth: INT_STATE_TREE_DEPTH, @@ -100,7 +100,7 @@ export const setVerifyingKeysNonQvArgs: SetVerifyingKeysArgs = { tallyVotesZkeyPath: tallyVotesTestNonQvZkeyPath, }; -export const checkVerifyingKeysArgs: CheckVerifyingKeysArgs = { +export const checkVerifyingKeysArgs: Omit = { stateTreeDepth: STATE_TREE_DEPTH, intStateTreeDepth: INT_STATE_TREE_DEPTH, messageTreeDepth: MSG_TREE_DEPTH, @@ -110,35 +110,35 @@ export const checkVerifyingKeysArgs: CheckVerifyingKeysArgs = { tallyVotesZkeyPath: tallyVotesTestZkeyPath, }; -export const timeTravelArgs: TimeTravelArgs = { +export const timeTravelArgs: Omit = { seconds: pollDuration, }; -export const mergeMessagesArgs: MergeMessagesArgs = { +export const mergeMessagesArgs: Omit = { pollId: 0n, }; -export const mergeSignupsArgs: MergeSignupsArgs = { +export const mergeSignupsArgs: Omit = { pollId: 0n, }; -export const proveOnChainArgs: ProveOnChainArgs = { +export const proveOnChainArgs: Omit = { pollId: 0n, proofDir: testProofsDirPath, subsidyEnabled: false, }; -export const verifyArgs: VerifyArgs = { +export const verifyArgs: Omit = { pollId: 0n, subsidyEnabled: false, tallyFile: testTallyFilePath, }; -export const deployArgs: DeployArgs = { +export const deployArgs: Omit = { stateTreeDepth: STATE_TREE_DEPTH, }; -export const deployPollArgs: DeployPollArgs = { +export const deployPollArgs: Omit = { pollDuration, intStateTreeDepth: INT_STATE_TREE_DEPTH, messageTreeSubDepth: MSG_BATCH_DEPTH, diff --git a/cli/tests/e2e/e2e.nonQv.test.ts b/cli/tests/e2e/e2e.nonQv.test.ts index f2cbc986d7..36092cbb07 100644 --- a/cli/tests/e2e/e2e.nonQv.test.ts +++ b/cli/tests/e2e/e2e.nonQv.test.ts @@ -1,8 +1,9 @@ -import { Signer } from "ethers"; import { getDefaultSigner } from "maci-contracts"; import { genRandomSalt } from "maci-crypto"; import { Keypair } from "maci-domainobjs"; +import type { Signer } from "ethers"; + import { deploy, deployPoll, @@ -51,8 +52,9 @@ describe("e2e tests", function test() { this.timeout(900000); let maciAddresses: DeployedContracts; + let signer: Signer; - const genProofsArgs: GenProofsArgs = { + const genProofsArgs: Omit = { outputDir: testProofsDirPath, tallyFile: testTallyFilePath, tallyZkey: tallyVotesTestNonQvZkeyPath, @@ -71,15 +73,15 @@ describe("e2e tests", function test() { // before all tests we deploy the vk registry contract and set the verifying keys before(async () => { + signer = await getDefaultSigner(); + // we deploy the vk registry contract - await deployVkRegistryContract({}); + await deployVkRegistryContract({ signer }); // we set the verifying keys - await setVerifyingKeys(setVerifyingKeysNonQvArgs); + await setVerifyingKeys({ ...setVerifyingKeysNonQvArgs, signer }); }); describe("1 signup, 1 message (with signer as argument)", () => { - let signer: Signer; - after(() => { cleanVanilla(); }); @@ -87,7 +89,6 @@ describe("e2e tests", function test() { const user = new Keypair(); before(async () => { - signer = await getDefaultSigner(); // deploy the smart contracts maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract diff --git a/cli/tests/e2e/e2e.subsidy.test.ts b/cli/tests/e2e/e2e.subsidy.test.ts index 8cd5e6a4fc..c9fe82f0d0 100644 --- a/cli/tests/e2e/e2e.subsidy.test.ts +++ b/cli/tests/e2e/e2e.subsidy.test.ts @@ -1,6 +1,9 @@ +import { getDefaultSigner } from "maci-contracts"; import { genRandomSalt } from "maci-crypto"; import { Keypair } from "maci-domainobjs"; +import type { Signer } from "ethers"; + import { checkVerifyingKeys, deploy, @@ -54,11 +57,12 @@ describe("e2e with Subsidy tests", function test() { let maciAddresses: DeployedContracts; let pollAddresses: PollContracts; let vkRegistryContractAddress: string; + let signer: Signer; const subsidyEnabled = true; deployPollArgs.subsidyEnabled = subsidyEnabled; - const genProofsArgs: GenProofsArgs = { + const genProofsArgs: Omit = { outputDir: testProofsDirPath, tallyFile: testTallyFilePath, tallyZkey: tallyVotesTestZkeyPath, @@ -81,10 +85,12 @@ describe("e2e with Subsidy tests", function test() { }; before(async () => { + signer = await getDefaultSigner(); + // we deploy the vk registry contract - vkRegistryContractAddress = await deployVkRegistryContract({}); + vkRegistryContractAddress = await deployVkRegistryContract({ signer }); // we set the verifying keys - await setVerifyingKeys({ ...setVerifyingKeysArgs, subsidyZkeyPath: subsidyTestZkeyPath }); + await setVerifyingKeys({ ...setVerifyingKeysArgs, subsidyZkeyPath: subsidyTestZkeyPath, signer }); }); describe("4 signups, 6 messages", () => { @@ -96,16 +102,16 @@ describe("e2e with Subsidy tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup four users", async () => { // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } }); @@ -119,6 +125,7 @@ describe("e2e with Subsidy tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); await publish({ @@ -130,6 +137,7 @@ describe("e2e with Subsidy tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[1].privKey.serialize(), + signer, }); await publish({ @@ -141,6 +149,7 @@ describe("e2e with Subsidy tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[2].privKey.serialize(), + signer, }); await publish({ @@ -152,6 +161,7 @@ describe("e2e with Subsidy tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); await publish({ @@ -163,6 +173,7 @@ describe("e2e with Subsidy tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); await publish({ @@ -174,16 +185,17 @@ describe("e2e with Subsidy tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); }); @@ -206,16 +218,16 @@ describe("e2e with Subsidy tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup nine users", async () => { // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } }); @@ -230,16 +242,17 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - const tallyData = await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify({ ...verifyArgs, tallyData }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + const tallyData = await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, tallyData, signer }); }); }); @@ -252,15 +265,15 @@ describe("e2e with Subsidy tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup eight users (same pub key)", async () => { for (let i = 0; i < 8; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: user.pubKey.serialize() }); + await signup({ maciPubKey: user.pubKey.serialize(), signer }); } }); @@ -277,17 +290,18 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); } }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - const tallyData = await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify({ ...verifyArgs, tallyData }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + const tallyData = await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, tallyData, signer }); }); }); @@ -310,17 +324,17 @@ describe("e2e with Subsidy tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); }); it("should run the first poll", async () => { // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); // signup // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } // publish await publish({ @@ -333,22 +347,23 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); // time travel - await timeTravel(timeTravelArgs); + await timeTravel({ ...timeTravelArgs, signer }); // generate proofs - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); cleanSubsidy(); }); it("should deploy two more polls", async () => { // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); - secondPollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); + secondPollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should publish messages to the second poll", async () => { @@ -362,6 +377,7 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); await publish({ @@ -374,6 +390,7 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[1].privKey.serialize(), + signer, }); await publish({ @@ -386,6 +403,7 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[2].privKey.serialize(), + signer, }); }); @@ -400,6 +418,7 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); await publish({ @@ -412,6 +431,7 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[4].privKey.serialize(), + signer, }); await publish({ @@ -424,46 +444,53 @@ describe("e2e with Subsidy tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[5].privKey.serialize(), + signer, }); }); it("should complete the second poll", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages({ pollId: 1n }); - await mergeSignups({ pollId: 1n }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ pollId: 1n, signer }); + await mergeSignups({ pollId: 1n, signer }); const tallyData = await genProofs({ ...genProofsArgs, pollId: 1n, + signer, }); await proveOnChain({ ...proveOnChainArgs, pollId: 1n, + signer, }); await verify({ ...verifyArgs, pollId: 1n, tallyData, tallyAddress: pollAddresses.tally, + signer, }); cleanSubsidy(); }); it("should complete the third poll", async () => { - await mergeMessages({ pollId: 2n }); - await mergeSignups({ pollId: 2n }); + await mergeMessages({ pollId: 2n, signer }); + await mergeSignups({ pollId: 2n, signer }); const tallyData = await genProofs({ ...genProofsArgs, pollId: 2n, + signer, }); await proveOnChain({ ...proveOnChainArgs, pollId: 2n, + signer, }); await verify({ ...verifyArgs, pollId: 2n, tallyData, tallyAddress: secondPollAddresses.tally, + signer, }); }); }); @@ -471,13 +498,15 @@ describe("e2e with Subsidy tests", function test() { describe("checkKeys", () => { before(async () => { // deploy maci as we need the address - await deploy(deployArgs); + await deploy({ ...deployArgs, signer }); }); + it("should check if the verifying keys have been set correctly", async () => { await checkVerifyingKeys({ ...checkVerifyingKeysArgs, vkRegistry: vkRegistryContractAddress, subsidyZkeyPath: subsidyTestZkeyPath, + signer, }); }); }); diff --git a/cli/tests/e2e/e2e.test.ts b/cli/tests/e2e/e2e.test.ts index ebca9af533..bc9ca3bd31 100644 --- a/cli/tests/e2e/e2e.test.ts +++ b/cli/tests/e2e/e2e.test.ts @@ -1,10 +1,11 @@ -import { Signer } from "ethers"; import { getDefaultSigner } from "maci-contracts"; import { genRandomSalt } from "maci-crypto"; import { Keypair } from "maci-domainobjs"; import fs from "fs"; +import type { Signer } from "ethers"; + import { airdrop, checkVerifyingKeys, @@ -68,8 +69,9 @@ describe("e2e tests", function test() { let maciAddresses: DeployedContracts; let pollAddresses: PollContracts; + let signer: Signer; - const genProofsArgs: GenProofsArgs = { + const genProofsArgs: Omit = { outputDir: testProofsDirPath, tallyFile: testTallyFilePath, tallyZkey: tallyVotesTestZkeyPath, @@ -88,15 +90,15 @@ describe("e2e tests", function test() { // before all tests we deploy the vk registry contract and set the verifying keys before(async () => { + signer = await getDefaultSigner(); + // we deploy the vk registry contract - await deployVkRegistryContract({}); + await deployVkRegistryContract({ signer }); // we set the verifying keys - await setVerifyingKeys(setVerifyingKeysArgs); + await setVerifyingKeys({ ...setVerifyingKeysArgs, signer }); }); describe("1 signup, 1 message (with signer as argument)", () => { - let signer: Signer; - after(() => { cleanVanilla(); }); @@ -104,7 +106,6 @@ describe("e2e tests", function test() { const user = new Keypair(); before(async () => { - signer = await getDefaultSigner(); // deploy the smart contracts maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract @@ -153,13 +154,13 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup one user", async () => { - await signup({ maciPubKey: user.pubKey.serialize() }); + await signup({ maciPubKey: user.pubKey.serialize(), signer }); }); it("should publish one message", async () => { @@ -173,19 +174,21 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - const tallyFileData = await genProofs(genProofsArgs); - await signup({ maciPubKey: user.pubKey.serialize() }); - await proveOnChain(proveOnChainArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + const tallyFileData = await genProofs({ ...genProofsArgs, signer }); + await signup({ maciPubKey: user.pubKey.serialize(), signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); await verify({ ...verifyArgs, tallyData: tallyFileData, + signer, }); }); }); @@ -199,16 +202,16 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup four users", async () => { // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } }); @@ -223,6 +226,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); await publish({ pubkey: users[1].pubKey.serialize(), @@ -234,6 +238,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[1].privKey.serialize(), + signer, }); await publish({ pubkey: users[2].pubKey.serialize(), @@ -245,6 +250,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[2].privKey.serialize(), + signer, }); await publish({ pubkey: users[3].pubKey.serialize(), @@ -256,6 +262,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); await publish({ pubkey: users[3].pubKey.serialize(), @@ -267,6 +274,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); await publish({ pubkey: users[3].pubKey.serialize(), @@ -278,16 +286,17 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); }); @@ -310,16 +319,16 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup nine users", async () => { // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } }); @@ -334,16 +343,17 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - const tallyFileData = await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify({ ...verifyArgs, tallyData: tallyFileData }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + const tallyFileData = await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, tallyData: tallyFileData, signer }); }); }); @@ -356,15 +366,15 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup eight users (same pub key)", async () => { for (let i = 0; i < 8; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: user.pubKey.serialize() }); + await signup({ maciPubKey: user.pubKey.serialize(), signer }); } }); @@ -381,17 +391,18 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); } }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); }); @@ -404,16 +415,16 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup thirty users", async () => { // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } }); @@ -428,6 +439,7 @@ describe("e2e tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); await publish({ @@ -439,6 +451,7 @@ describe("e2e tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[1].privKey.serialize(), + signer, }); await publish({ @@ -450,6 +463,7 @@ describe("e2e tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[2].privKey.serialize(), + signer, }); await publish({ @@ -461,26 +475,27 @@ describe("e2e tests", function test() { newVoteWeight: 9n, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - const tallyFileData = await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify({ ...verifyArgs, tallyData: tallyFileData }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + const tallyFileData = await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, tallyData: tallyFileData, signer }); }); }); describe("checkKeys", () => { before(async () => { // deploy maci as we need the address - await deploy(deployArgs); + await deploy({ ...deployArgs, signer }); }); it("should check if the verifying keys have been set correctly", async () => { - await checkVerifyingKeys(checkVerifyingKeysArgs); + await checkVerifyingKeys({ ...checkVerifyingKeysArgs, signer }); }); }); @@ -493,11 +508,11 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); // signup - await signup({ maciPubKey: user.pubKey.serialize() }); + await signup({ maciPubKey: user.pubKey.serialize(), signer }); // publish await publish({ pubkey: user.pubKey.serialize(), @@ -509,20 +524,21 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); // time travel - await timeTravel(timeTravelArgs); + await timeTravel({ ...timeTravelArgs, signer }); // generate proofs - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - const tallyFileData = await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify({ ...verifyArgs, tallyData: tallyFileData }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + const tallyFileData = await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, tallyData: tallyFileData, signer }); cleanVanilla(); }); it("should deploy a new poll", async () => { - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should publish a new message", async () => { @@ -536,16 +552,17 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); }); it("should generate proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages({ pollId: 1n }); - await mergeSignups({ pollId: 1n }); - await genProofs({ ...genProofsArgs, pollId: 1n }); - await proveOnChain({ ...proveOnChainArgs, pollId: 1n }); - await verify({ ...verifyArgs, pollId: 1n }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ pollId: 1n, signer }); + await mergeSignups({ pollId: 1n, signer }); + await genProofs({ ...genProofsArgs, pollId: 1n, signer }); + await proveOnChain({ ...proveOnChainArgs, pollId: 1n, signer }); + await verify({ ...verifyArgs, pollId: 1n, signer }); }); }); @@ -568,18 +585,18 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); }); it("should run the first poll", async () => { // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); // signup // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < users.length; i += 1) { // eslint-disable-next-line no-await-in-loop - await signup({ maciPubKey: users[i].pubKey.serialize() }); + await signup({ maciPubKey: users[i].pubKey.serialize(), signer }); } // publish @@ -593,23 +610,24 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); // time travel - await timeTravel(timeTravelArgs); + await timeTravel({ ...timeTravelArgs, signer }); // generate proofs - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); cleanVanilla(); }); it("should deploy two more polls", async () => { // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); - secondPollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); + secondPollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should publish messages to the second poll", async () => { @@ -623,6 +641,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[0].privKey.serialize(), + signer, }); await publish({ @@ -635,6 +654,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[1].privKey.serialize(), + signer, }); await publish({ @@ -647,6 +667,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[2].privKey.serialize(), + signer, }); }); @@ -661,6 +682,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[3].privKey.serialize(), + signer, }); await publish({ @@ -673,6 +695,7 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[4].privKey.serialize(), + signer, }); await publish({ @@ -685,20 +708,22 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: users[5].privKey.serialize(), + signer, }); }); it("should complete the second poll", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages({ pollId: 1n }); - await mergeSignups({ pollId: 1n }); - const tallyData = await genProofs({ ...genProofsArgs, pollId: 1n }); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ pollId: 1n, signer }); + await mergeSignups({ pollId: 1n, signer }); + const tallyData = await genProofs({ ...genProofsArgs, pollId: 1n, signer }); await proveOnChain({ ...proveOnChainArgs, pollId: 1n, maciAddress: maciAddresses.maciAddress, messageProcessorAddress: pollAddresses.messageProcessor, tallyAddress: pollAddresses.tally, + signer, }); await verify({ ...verifyArgs, @@ -706,20 +731,22 @@ describe("e2e tests", function test() { tallyData, maciAddress: maciAddresses.maciAddress, tallyAddress: pollAddresses.tally, + signer, }); cleanVanilla(); }); it("should complete the third poll", async () => { - await mergeMessages({ pollId: 2n }); - await mergeSignups({ pollId: 2n }); - const tallyData = await genProofs({ ...genProofsArgs, pollId: 2n }); + await mergeMessages({ pollId: 2n, signer }); + await mergeSignups({ pollId: 2n, signer }); + const tallyData = await genProofs({ ...genProofsArgs, pollId: 2n, signer }); await proveOnChain({ ...proveOnChainArgs, pollId: 2n, maciAddress: maciAddresses.maciAddress, messageProcessorAddress: secondPollAddresses.messageProcessor, tallyAddress: secondPollAddresses.tally, + signer, }); await verify({ ...verifyArgs, @@ -727,6 +754,7 @@ describe("e2e tests", function test() { tallyData, maciAddress: maciAddresses.maciAddress, tallyAddress: secondPollAddresses.tally, + signer, }); }); }); @@ -746,13 +774,13 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup one user", async () => { - await signup({ maciPubKey: user.pubKey.serialize() }); + await signup({ maciPubKey: user.pubKey.serialize(), signer }); }); it("should publish one message", async () => { @@ -766,26 +794,29 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); await genLocalState({ outputPath: stateOutPath, startBlock: 0, coordinatorPrivateKey: coordinatorPrivKey, blockPerBatch: 50, pollId: 0n, + signer, }); await genProofs({ ...genProofsArgs, stateFile: stateOutPath, + signer, }); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); }); @@ -800,13 +831,13 @@ describe("e2e tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - pollAddresses = await deployPoll(deployPollArgs); + pollAddresses = await deployPoll({ ...deployPollArgs, signer }); }); it("should signup one user", async () => { - stateIndex = BigInt(await signup({ maciPubKey: user.pubKey.serialize() })); + stateIndex = BigInt(await signup({ maciPubKey: user.pubKey.serialize(), signer })); }); it("should airdrop topup tokens to the coordinator user", async () => { @@ -815,6 +846,7 @@ describe("e2e tests", function test() { pollId: 0n, contractAddress: maciAddresses.topupCreditAddress, maciAddress: maciAddresses.maciAddress, + signer, }); }); @@ -824,6 +856,7 @@ describe("e2e tests", function test() { stateIndex: Number(stateIndex!), pollId: 0n, maciAddress: maciAddresses.maciAddress, + signer, }); }); @@ -838,16 +871,17 @@ describe("e2e tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: user.privKey.serialize(), + signer, }); }); it("should generate proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); }); }); diff --git a/cli/tests/e2e/keyChange.test.ts b/cli/tests/e2e/keyChange.test.ts index cda6fb8c09..b9299e4456 100644 --- a/cli/tests/e2e/keyChange.test.ts +++ b/cli/tests/e2e/keyChange.test.ts @@ -1,9 +1,12 @@ import { expect } from "chai"; +import { getDefaultSigner } from "maci-contracts"; import { genRandomSalt } from "maci-crypto"; import { Keypair } from "maci-domainobjs"; import fs from "fs"; +import type { Signer } from "ethers"; + import { DeployedContracts, TallyData } from "../../ts"; import { deploy, @@ -49,10 +52,11 @@ describe("keyChange tests", function test() { this.timeout(900000); let maciAddresses: DeployedContracts; + let signer: Signer; deployPollArgs.pollDuration = 90; - const genProofsArgs: GenProofsArgs = { + const genProofsArgs: Omit = { outputDir: testProofsDirPath, tallyFile: testTallyFilePath, tallyZkey: tallyVotesTestZkeyPath, @@ -71,10 +75,12 @@ describe("keyChange tests", function test() { // before all tests we deploy the vk registry contract and set the verifying keys before(async () => { + signer = await getDefaultSigner(); + // we deploy the vk registry contract - await deployVkRegistryContract({}); + await deployVkRegistryContract({ signer }); // we set the verifying keys - await setVerifyingKeys(setVerifyingKeysArgs); + await setVerifyingKeys({ ...setVerifyingKeysArgs, signer }); }); describe("keyChange and new vote (new vote has same nonce)", () => { @@ -94,10 +100,10 @@ describe("keyChange tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - await deployPoll(deployPollArgs); - stateIndex = BigInt(await signup({ maciPubKey: keypair1.pubKey.serialize() })); + await deployPoll({ ...deployPollArgs, signer }); + stateIndex = BigInt(await signup({ maciPubKey: keypair1.pubKey.serialize(), signer })); await publish({ pubkey: keypair1.pubKey.serialize(), stateIndex, @@ -108,6 +114,7 @@ describe("keyChange tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: keypair1.privKey.serialize(), + signer, }); }); @@ -122,16 +129,17 @@ describe("keyChange tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: keypair1.privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); it("should confirm the tally is correct", () => { @@ -158,10 +166,10 @@ describe("keyChange tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - await deployPoll(deployPollArgs); - stateIndex = BigInt(await signup({ maciPubKey: keypair1.pubKey.serialize() })); + await deployPoll({ ...deployPollArgs, signer }); + stateIndex = BigInt(await signup({ maciPubKey: keypair1.pubKey.serialize(), signer })); await publish({ pubkey: keypair1.pubKey.serialize(), stateIndex, @@ -172,6 +180,7 @@ describe("keyChange tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: keypair1.privKey.serialize(), + signer, }); }); @@ -186,16 +195,17 @@ describe("keyChange tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: keypair1.privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); it("should confirm the tally is correct", () => { @@ -222,10 +232,10 @@ describe("keyChange tests", function test() { before(async () => { // deploy the smart contracts - maciAddresses = await deploy(deployArgs); + maciAddresses = await deploy({ ...deployArgs, signer }); // deploy a poll contract - await deployPoll(deployPollArgs); - stateIndex = BigInt(await signup({ maciPubKey: keypair1.pubKey.serialize() })); + await deployPoll({ ...deployPollArgs, signer }); + stateIndex = BigInt(await signup({ maciPubKey: keypair1.pubKey.serialize(), signer })); await publish({ pubkey: keypair1.pubKey.serialize(), stateIndex, @@ -236,6 +246,7 @@ describe("keyChange tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: keypair1.privKey.serialize(), + signer, }); }); @@ -250,16 +261,17 @@ describe("keyChange tests", function test() { maciContractAddress: maciAddresses.maciAddress, salt: genRandomSalt(), privateKey: keypair1.privKey.serialize(), + signer, }); }); it("should generate zk-SNARK proofs and verify them", async () => { - await timeTravel(timeTravelArgs); - await mergeMessages(mergeMessagesArgs); - await mergeSignups(mergeSignupsArgs); - await genProofs(genProofsArgs); - await proveOnChain(proveOnChainArgs); - await verify(verifyArgs); + await timeTravel({ ...timeTravelArgs, signer }); + await mergeMessages({ ...mergeMessagesArgs, signer }); + await mergeSignups({ ...mergeSignupsArgs, signer }); + await genProofs({ ...genProofsArgs, signer }); + await proveOnChain({ ...proveOnChainArgs, signer }); + await verify({ ...verifyArgs, signer }); }); it("should confirm the tally is correct", () => { diff --git a/cli/tests/unit/airdrop.test.ts b/cli/tests/unit/airdrop.test.ts index 6bdf9d4986..ee55c4ce8e 100644 --- a/cli/tests/unit/airdrop.test.ts +++ b/cli/tests/unit/airdrop.test.ts @@ -1,6 +1,6 @@ import chai, { expect } from "chai"; import chaiAsPromised from "chai-as-promised"; -import { ZeroAddress } from "ethers"; +import { Signer, ZeroAddress } from "ethers"; import { deployTopupCredit, getDefaultSigner } from "maci-contracts"; import { airdrop } from "../../ts"; @@ -8,23 +8,27 @@ import { airdrop } from "../../ts"; chai.use(chaiAsPromised); describe("airdrop", () => { + let signer: Signer; let topupContractAddress: string | undefined; before(async () => { + signer = await getDefaultSigner(); const topupContract = await deployTopupCredit(await getDefaultSigner(), true); topupContractAddress = await topupContract.getAddress(); }); it("should airdrop tokens to the coordinator", async () => { - await expect(airdrop({ amount: 100, contractAddress: topupContractAddress })).to.be.fulfilled; + await expect(airdrop({ amount: 100, contractAddress: topupContractAddress, signer })).to.be.fulfilled; }); it("should throw when the amount is negative", async () => { - await expect(airdrop({ amount: -1, contractAddress: topupContractAddress })).to.be.rejectedWith("Invalid amount"); + await expect(airdrop({ amount: -1, contractAddress: topupContractAddress, signer })).to.be.rejectedWith( + "Invalid amount", + ); }); it("should throw when the ERC20 contract address is invalid", async () => { - await expect(airdrop({ amount: 100, contractAddress: ZeroAddress })).to.be.rejectedWith( + await expect(airdrop({ amount: 100, contractAddress: ZeroAddress, signer })).to.be.rejectedWith( "Invalid ERC20 contract address", ); }); diff --git a/cli/tests/unit/fundWallet.test.ts b/cli/tests/unit/fundWallet.test.ts index e13bced412..c2df39568f 100644 --- a/cli/tests/unit/fundWallet.test.ts +++ b/cli/tests/unit/fundWallet.test.ts @@ -9,8 +9,8 @@ describe("fundWallet", () => { const signer = await getDefaultSigner(); const balanceBefore = await signer.provider?.getBalance(ZeroAddress); - await fundWallet({ amount: 1000000000, address: ZeroAddress }); + await fundWallet({ amount: 1000000000, address: ZeroAddress, signer }); const balanceAfter = await signer.provider?.getBalance(ZeroAddress); - expect(balanceAfter).to.be.gt(balanceBefore!); + expect(Number(balanceAfter)).to.be.gt(Number(balanceBefore!)); }); }); diff --git a/cli/tests/unit/timeTravel.test.ts b/cli/tests/unit/timeTravel.test.ts index 39bd2d4e6f..c65a23c831 100644 --- a/cli/tests/unit/timeTravel.test.ts +++ b/cli/tests/unit/timeTravel.test.ts @@ -8,7 +8,7 @@ describe("timeTravel", () => { const signer = await getDefaultSigner(); const blockNumber = await signer.provider?.getBlock("latest"); - await expect(timeTravel({ seconds: 5 })).to.be.fulfilled; + await expect(timeTravel({ seconds: 5, signer })).to.be.fulfilled; const blockNumberAfter = await signer.provider?.getBlock("latest"); expect(blockNumberAfter!.timestamp).to.be.gt(blockNumber!.timestamp); diff --git a/cli/tests/unit/topup.test.ts b/cli/tests/unit/topup.test.ts index 0b708ded9f..5160081420 100644 --- a/cli/tests/unit/topup.test.ts +++ b/cli/tests/unit/topup.test.ts @@ -39,19 +39,19 @@ describe("topup", () => { }); it("should throw when the state index is invalid", async () => { - await expect(topup({ amount: 100, pollId: 0n, stateIndex: 0, maciAddress })).to.be.rejectedWith( + await expect(topup({ amount: 100, pollId: 0n, stateIndex: 0, maciAddress, signer })).to.be.rejectedWith( "State index must be greater than 0", ); }); it("should throw when the poll ID is invalid", async () => { - await expect(topup({ amount: 100, pollId: -1n, stateIndex: 1, maciAddress })).to.be.rejectedWith( + await expect(topup({ amount: 100, pollId: -1n, stateIndex: 1, maciAddress, signer })).to.be.rejectedWith( "Poll ID must be a positive integer", ); }); it("should throw when the amount is invalid", async () => { - await expect(topup({ amount: 0, pollId: 0n, stateIndex: 1, maciAddress })).to.be.rejectedWith( + await expect(topup({ amount: 0, pollId: 0n, stateIndex: 1, maciAddress, signer })).to.be.rejectedWith( "Topup amount must be greater than 0", ); }); diff --git a/cli/ts/commands/airdrop.ts b/cli/ts/commands/airdrop.ts index aae5cbcd2e..a83062579f 100644 --- a/cli/ts/commands/airdrop.ts +++ b/cli/ts/commands/airdrop.ts @@ -1,5 +1,4 @@ -import { BaseContract } from "ethers"; -import { type MACI, type TopupCredit, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts"; +import { MACI__factory as MACIFactory, TopupCredit__factory as TopupCreditFactory } from "maci-contracts"; import { type AirdropArgs, logError, logGreen, success, readContractAddress, contractExists, banner } from "../utils"; @@ -18,10 +17,7 @@ export const airdrop = async ({ quiet = true, }: AirdropArgs): Promise => { banner(quiet); - - // get the signer - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // get the topup credit address from storage const topupCredit = readContractAddress("TopupCredit", network?.name); @@ -35,14 +31,12 @@ export const airdrop = async ({ const ERC20Address = contractAddress || topupCredit; // check if the contract exists - if (!(await contractExists(ethSigner.provider!, ERC20Address))) { + if (!(await contractExists(signer.provider!, ERC20Address))) { logError("Invalid ERC20 contract address"); } - const tokenAbi = parseArtifact("TopupCredit")[0]; - // create the contract instance - const tokenContract = new BaseContract(ERC20Address, tokenAbi, ethSigner) as TopupCredit; + const tokenContract = TopupCreditFactory.connect(ERC20Address, signer); if (amount < 0) { logError("Invalid amount"); @@ -55,7 +49,7 @@ export const airdrop = async ({ }); await tx.wait(); - logGreen(quiet, success(`Airdropped ${amount} credits to ${await ethSigner.getAddress()}`)); + logGreen(quiet, success(`Airdropped ${amount} credits to ${await signer.getAddress()}`)); } catch (error) { logError((error as Error).message); } @@ -71,8 +65,7 @@ export const airdrop = async ({ logError("Please provide a MACI contract address"); } - const maciAbi = parseArtifact("MACI")[0]; - const maciContract = new BaseContract(maciContractAddress!, maciAbi, ethSigner) as MACI; + const maciContract = MACIFactory.connect(maciContractAddress!, signer); const pollAddr = await maciContract.getPoll(pollId); try { diff --git a/cli/ts/commands/checkVerifyingKeys.ts b/cli/ts/commands/checkVerifyingKeys.ts index c2f581a726..a5eb6feaa4 100644 --- a/cli/ts/commands/checkVerifyingKeys.ts +++ b/cli/ts/commands/checkVerifyingKeys.ts @@ -1,6 +1,5 @@ -import { BaseContract } from "ethers"; import { extractVk } from "maci-circuits"; -import { type VkRegistry, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts"; +import { VkRegistry__factory as VkRegistryFactory } from "maci-contracts"; import { G1Point, G2Point } from "maci-crypto"; import { VerifyingKey } from "maci-domainobjs"; @@ -40,9 +39,7 @@ export const checkVerifyingKeys = async ({ quiet = true, }: CheckVerifyingKeysArgs): Promise => { banner(quiet); - // get the signer - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // ensure we have the contract addresses that we need if (!readContractAddress("VkRegistry", network?.name) && !vkRegistry) { @@ -51,15 +48,11 @@ export const checkVerifyingKeys = async ({ const vkContractAddress = vkRegistry || readContractAddress("VkRegistry", network?.name); - if (!(await contractExists(ethSigner.provider!, vkContractAddress))) { + if (!(await contractExists(signer.provider!, vkContractAddress))) { logError("The VkRegistry contract does not exist"); } - const vkRegistryContractInstance = new BaseContract( - vkContractAddress, - parseArtifact("VkRegistry")[0], - ethSigner, - ) as VkRegistry; + const vkRegistryContractInstance = VkRegistryFactory.connect(vkContractAddress, signer); // we need to ensure that the zkey files exist if (!fs.existsSync(processMessagesZkeyPath)) { diff --git a/cli/ts/commands/deploy.ts b/cli/ts/commands/deploy.ts index 1a134cf6c6..b4f7bdffea 100644 --- a/cli/ts/commands/deploy.ts +++ b/cli/ts/commands/deploy.ts @@ -4,8 +4,6 @@ import { deployVerifier, deployMaci, deployTopupCredit, - getDefaultSigner, - getDefaultNetwork, } from "maci-contracts"; import { @@ -43,8 +41,7 @@ export const deploy = async ({ logError("Please provide either an initialVoiceCreditProxyAddress or initialVoiceCredits, not both"); } - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); const poseidonT3 = poseidonT3Address || readContractAddress("PoseidonT3", network?.name); const poseidonT4 = poseidonT4Address || readContractAddress("PoseidonT4", network?.name); @@ -58,7 +55,7 @@ export const deploy = async ({ if (!initialVoiceCreditsProxyAddress) { const contract = await deployConstantInitialVoiceCreditProxy( initialVoiceCredits || DEFAULT_INITIAL_VOICE_CREDITS, - ethSigner, + signer, true, ); @@ -69,15 +66,15 @@ export const deploy = async ({ let signupGatekeeperContractAddress = signupGatekeeperAddress || readContractAddress("SignUpGatekeeper", network?.name); if (!signupGatekeeperContractAddress) { - const contract = await deployFreeForAllSignUpGatekeeper(ethSigner, true); + const contract = await deployFreeForAllSignUpGatekeeper(signer, true); signupGatekeeperContractAddress = await contract.getAddress(); } // deploy a verifier contract - const verifierContract = await deployVerifier(ethSigner, true); + const verifierContract = await deployVerifier(signer, true); // topup credit - const topUpCredit = await deployTopupCredit(ethSigner, true); + const topUpCredit = await deployTopupCredit(signer, true); const [verifierContractAddress, topUpCreditAddress] = await Promise.all([ verifierContract.getAddress(), @@ -95,7 +92,7 @@ export const deploy = async ({ poseidonT5, poseidonT6, }, - signer: ethSigner, + signer, stateTreeDepth, quiet: true, }); diff --git a/cli/ts/commands/deployPoll.ts b/cli/ts/commands/deployPoll.ts index 7281267877..bb3158b029 100644 --- a/cli/ts/commands/deployPoll.ts +++ b/cli/ts/commands/deployPoll.ts @@ -1,5 +1,4 @@ -import { BaseContract } from "ethers"; -import { type MACI, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts"; +import { MACI__factory as MACIFactory } from "maci-contracts"; import { PubKey } from "maci-domainobjs"; import { @@ -34,8 +33,7 @@ export const deployPoll = async ({ }: DeployPollArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // check if we have a vkRegistry already deployed or passed as arg const vkRegistryContractAddress = readContractAddress("VkRegistry", network?.name); @@ -75,7 +73,7 @@ export const deployPoll = async ({ } // we check that the contract is deployed - if (!(await contractExists(ethSigner.provider!, maci))) { + if (!(await contractExists(signer.provider!, maci))) { logError("MACI contract does not exist"); } @@ -89,8 +87,7 @@ export const deployPoll = async ({ // get the verifier contract const verifierContractAddress = readContractAddress("Verifier", network?.name); - const maciAbi = parseArtifact("MACI")[0]; - const maciContract = new BaseContract(maci, maciAbi, ethSigner) as MACI; + const maciContract = MACIFactory.connect(maci, signer); // deploy the poll let pollAddr = ""; diff --git a/cli/ts/commands/deployVkRegistry.ts b/cli/ts/commands/deployVkRegistry.ts index f2d8d3688f..b0dbd6f77f 100644 --- a/cli/ts/commands/deployVkRegistry.ts +++ b/cli/ts/commands/deployVkRegistry.ts @@ -1,4 +1,4 @@ -import { deployVkRegistry, getDefaultSigner, getDefaultNetwork } from "maci-contracts"; +import { deployVkRegistry } from "maci-contracts"; import fs from "fs"; @@ -25,10 +25,9 @@ export const deployVkRegistryContract = async ({ signer, quiet = true }: DeployV resetContractAddresses(); } - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // deploy and store the address - const vkRegistry = await deployVkRegistry(ethSigner, true); + const vkRegistry = await deployVkRegistry(signer, true); const vkRegistryAddress = await vkRegistry.getAddress(); storeContractAddress("VkRegistry", vkRegistryAddress, network?.name); diff --git a/cli/ts/commands/fundWallet.ts b/cli/ts/commands/fundWallet.ts index c86e901121..e869467d20 100644 --- a/cli/ts/commands/fundWallet.ts +++ b/cli/ts/commands/fundWallet.ts @@ -1,5 +1,3 @@ -import { getDefaultSigner } from "maci-contracts"; - import { info, logError, logYellow, logGreen, success, banner, type FundWalletArgs } from "../utils"; /** @@ -10,11 +8,10 @@ import { info, logError, logYellow, logGreen, success, banner, type FundWalletAr */ export const fundWallet = async ({ amount, address, signer, quiet = true }: FundWalletArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); // fund the wallet by sending Ether to it try { - const tx = await ethSigner.sendTransaction({ + const tx = await signer.sendTransaction({ to: address, value: amount.toString(), }); diff --git a/cli/ts/commands/genLocalState.ts b/cli/ts/commands/genLocalState.ts index b8d09dcd51..6ff7d6fab0 100644 --- a/cli/ts/commands/genLocalState.ts +++ b/cli/ts/commands/genLocalState.ts @@ -1,5 +1,5 @@ import { JsonRpcProvider } from "ethers"; -import { getDefaultSigner, getDefaultNetwork, genMaciStateFromContract } from "maci-contracts"; +import { genMaciStateFromContract } from "maci-contracts"; import { Keypair, PrivKey } from "maci-domainobjs"; import fs from "fs"; @@ -37,8 +37,7 @@ export const genLocalState = async ({ }: GenLocalStateArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // validation of the maci contract address if (!readContractAddress("MACI", network?.name) && !maciContractAddress) { @@ -47,7 +46,7 @@ export const genLocalState = async ({ const maciAddress = maciContractAddress || readContractAddress("MACI", network?.name); - if (!(await contractExists(ethSigner.provider!, maciAddress))) { + if (!(await contractExists(signer.provider!, maciAddress))) { logError("MACI contract does not exist"); } @@ -61,15 +60,15 @@ export const genLocalState = async ({ const coordinatorKeypair = new Keypair(coordinatorMaciPrivKey); // calculate the end block number - const endBlockNumber = endBlock || (await ethSigner.provider!.getBlockNumber()); + const endBlockNumber = endBlock || (await signer.provider!.getBlockNumber()); let fromBlock = startBlock || 0; if (transactionHash) { - const tx = await ethSigner.provider!.getTransaction(transactionHash); + const tx = await signer.provider!.getTransaction(transactionHash); fromBlock = tx?.blockNumber ?? 0; } - const provider = ethereumProvider ? new JsonRpcProvider(ethereumProvider) : ethSigner.provider; + const provider = ethereumProvider ? new JsonRpcProvider(ethereumProvider) : signer.provider; logYellow( quiet, diff --git a/cli/ts/commands/genProofs.ts b/cli/ts/commands/genProofs.ts index c8843b33c4..568dd7e733 100644 --- a/cli/ts/commands/genProofs.ts +++ b/cli/ts/commands/genProofs.ts @@ -1,13 +1,9 @@ -import { BaseContract, type BigNumberish } from "ethers"; import { extractVk, genProof, verifyProof } from "maci-circuits"; import { - type MACI, - type AccQueue, - type Poll, + MACI__factory as MACIFactory, + AccQueue__factory as AccQueueFactory, + Poll__factory as PollFactory, genMaciStateFromContract, - getDefaultSigner, - getDefaultNetwork, - parseArtifact, } from "maci-contracts"; import { type CircuitInputs, type IJsonMaciState, MaciState } from "maci-core"; import { hash3, hashLeftRight, genTreeCommitment } from "maci-crypto"; @@ -16,6 +12,8 @@ import { Keypair, PrivKey } from "maci-domainobjs"; import fs from "fs"; import path from "path"; +import type { BigNumberish } from "ethers"; + import { DEFAULT_ETH_PROVIDER, asHex, @@ -185,8 +183,7 @@ export const genProofs = async ({ const maciPrivKey = PrivKey.deserialize(privateKey); const coordinatorKeypair = new Keypair(maciPrivKey); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // contracts if (!readContractAddress("MACI", network?.name) && !maciAddress) { @@ -194,7 +191,7 @@ export const genProofs = async ({ } const maciContractAddress = maciAddress || readContractAddress("MACI", network?.name); - if (!(await contractExists(ethSigner.provider!, maciContractAddress))) { + if (!(await contractExists(signer.provider!, maciContractAddress))) { logError("MACI contract does not exist"); } @@ -202,21 +199,17 @@ export const genProofs = async ({ logError("Invalid poll id"); } - const maciContract = new BaseContract(maciContractAddress, parseArtifact("MACI")[0], ethSigner) as MACI; - + const maciContract = MACIFactory.connect(maciContractAddress, signer); const pollAddr = await maciContract.polls(pollId); - if (!(await contractExists(ethSigner.provider!, pollAddr))) { + + if (!(await contractExists(signer.provider!, pollAddr))) { logError("Poll contract does not exist"); } - const pollContract = new BaseContract(pollAddr, parseArtifact("Poll")[0], ethSigner) as Poll; + const pollContract = PollFactory.connect(pollAddr, signer); const extContracts = await pollContract.extContracts(); const messageAqContractAddr = extContracts.messageAq; - const messageAqContract = new BaseContract( - messageAqContractAddr, - parseArtifact("AccQueue")[0], - ethSigner, - ) as AccQueue; + const messageAqContract = AccQueueFactory.connect(messageAqContractAddr, signer); // Check that the state and message trees have been merged for at least the first poll if (!(await pollContract.stateAqMerged()) && pollId.toString() === "0") { @@ -249,13 +242,13 @@ export const genProofs = async ({ // build an off-chain representation of the MACI contract using data in the contract storage let fromBlock = startBlock ? Number(startBlock) : 0; if (transactionHash) { - const tx = await ethSigner.provider!.getTransaction(transactionHash); + const tx = await signer.provider!.getTransaction(transactionHash); fromBlock = tx?.blockNumber ?? 0; } logYellow(quiet, info(`starting to fetch logs from block ${fromBlock}`)); maciState = await genMaciStateFromContract( - ethSigner.provider!, + signer.provider!, await maciContract.getAddress(), coordinatorKeypair, pollId, diff --git a/cli/ts/commands/mergeMessages.ts b/cli/ts/commands/mergeMessages.ts index 2f449a2eb8..de129ba655 100644 --- a/cli/ts/commands/mergeMessages.ts +++ b/cli/ts/commands/mergeMessages.ts @@ -1,11 +1,7 @@ -import { BaseContract } from "ethers"; import { - type MACI, - type Poll, - type AccQueue, - getDefaultSigner, - getDefaultNetwork, - parseArtifact, + MACI__factory as MACIFactory, + Poll__factory as PollFactory, + AccQueue__factory as AccQueueFactory, } from "maci-contracts"; import { @@ -34,15 +30,14 @@ export const mergeMessages = async ({ signer, }: MergeMessagesArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // maci contract validation if (!readContractAddress("MACI", network?.name) && !maciContractAddress) { logError("Could not read contracts"); } const maciAddress = maciContractAddress || readContractAddress("MACI", network?.name); - if (!(await contractExists(ethSigner.provider!, maciAddress))) { + if (!(await contractExists(signer.provider!, maciAddress))) { logError("MACI contract does not exist"); } @@ -50,27 +45,23 @@ export const mergeMessages = async ({ logError("Invalid poll id"); } - const maciContractAbi = parseArtifact("MACI")[0]; - const pollContractAbi = parseArtifact("Poll")[0]; - const accQueueContractAbi = parseArtifact("AccQueue")[0]; - - const maciContract = new BaseContract(maciAddress, maciContractAbi, ethSigner) as MACI; - + const maciContract = MACIFactory.connect(maciAddress, signer); const pollAddress = await maciContract.polls(pollId); - if (!(await contractExists(ethSigner.provider!, pollAddress))) { + + if (!(await contractExists(signer.provider!, pollAddress))) { logError("Poll contract does not exist"); } - const pollContract = new BaseContract(pollAddress, pollContractAbi, ethSigner) as Poll; + const pollContract = PollFactory.connect(pollAddress, signer); const extContracts = await pollContract.extContracts(); const messageAqContractAddr = extContracts.messageAq; - const accQueueContract = new BaseContract(messageAqContractAddr, accQueueContractAbi, ethSigner) as AccQueue; + const accQueueContract = AccQueueFactory.connect(messageAqContractAddr, signer); // we need to ensure that the signer is the owner of the poll contract // this is because only the owner can merge the message AQ const pollOwner = await pollContract.owner(); - const signerAddress = await ethSigner.getAddress(); + const signerAddress = await signer.getAddress(); if (pollOwner.toLowerCase() !== signerAddress.toLowerCase()) { logError("The signer is not the owner of this Poll contract"); } @@ -78,7 +69,7 @@ export const mergeMessages = async ({ // check if it's time to merge the message AQ const dd = await pollContract.getDeployTimeAndDuration(); const deadline = Number(dd[0]) + Number(dd[1]); - const now = await currentBlockTimestamp(ethSigner.provider!); + const now = await currentBlockTimestamp(signer.provider!); if (now < deadline) { logError("The voting period is not over yet"); diff --git a/cli/ts/commands/mergeSignups.ts b/cli/ts/commands/mergeSignups.ts index 7e631b5680..7da886fe55 100644 --- a/cli/ts/commands/mergeSignups.ts +++ b/cli/ts/commands/mergeSignups.ts @@ -1,11 +1,7 @@ -import { BaseContract } from "ethers"; import { - type AccQueue, - type MACI, - type Poll, - getDefaultSigner, - getDefaultNetwork, - parseArtifact, + AccQueue__factory as AccQueueFactory, + MACI__factory as MACIFactory, + Poll__factory as PollFactory, } from "maci-contracts"; import { @@ -34,8 +30,7 @@ export const mergeSignups = async ({ quiet = true, }: MergeSignupsArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // maci contract validation if (!readContractAddress("MACI", network?.name) && !maciContractAddress) { @@ -44,7 +39,7 @@ export const mergeSignups = async ({ const maciAddress = maciContractAddress || readContractAddress("MACI", network?.name); - if (!(await contractExists(ethSigner.provider!, maciAddress))) { + if (!(await contractExists(signer.provider!, maciAddress))) { logError("MACI contract does not exist"); } @@ -52,26 +47,20 @@ export const mergeSignups = async ({ logError("Invalid poll id"); } - const [maciContractAbi] = parseArtifact("MACI"); - const [pollContractAbi] = parseArtifact("Poll"); - const [accQueueContractAbi] = parseArtifact("AccQueue"); - - const maciContract = new BaseContract(maciAddress, maciContractAbi, ethSigner) as MACI; - + const maciContract = MACIFactory.connect(maciAddress, signer); const pollAddress = await maciContract.polls(pollId); - if (!(await contractExists(ethSigner.provider!, pollAddress))) { + if (!(await contractExists(signer.provider!, pollAddress))) { logError("Poll contract does not exist"); } - const pollContract = new BaseContract(pollAddress, pollContractAbi, ethSigner) as Poll; - - const accQueueContract = new BaseContract(await maciContract.stateAq(), accQueueContractAbi, ethSigner) as AccQueue; + const pollContract = PollFactory.connect(pollAddress, signer); + const accQueueContract = AccQueueFactory.connect(await maciContract.stateAq(), signer); // check if it's time to merge the message AQ const dd = await pollContract.getDeployTimeAndDuration(); const deadline = Number(dd[0]) + Number(dd[1]); - const now = await currentBlockTimestamp(ethSigner.provider!); + const now = await currentBlockTimestamp(signer.provider!); if (now < deadline) { logError("Voting period is not over"); diff --git a/cli/ts/commands/proveOnChain.ts b/cli/ts/commands/proveOnChain.ts index ef6ec6b686..c244b7714e 100644 --- a/cli/ts/commands/proveOnChain.ts +++ b/cli/ts/commands/proveOnChain.ts @@ -1,19 +1,17 @@ /* eslint-disable no-await-in-loop */ -import { BaseContract, type BigNumberish } from "ethers"; +import { type BigNumberish } from "ethers"; import { - type MACI, - type AccQueue, - type Subsidy, - type Tally, - type MessageProcessor, - type Poll as PollContract, - type VkRegistry, - type Verifier, - type IVerifyingKeyStruct, + MACI__factory as MACIFactory, + AccQueue__factory as AccQueueFactory, + Subsidy__factory as SubsidyFactory, + Tally__factory as TallyFactory, + MessageProcessor__factory as MessageProcessorFactory, + Poll__factory as PollFactory, + VkRegistry__factory as VkRegistryFactory, + Verifier__factory as VerifierFactory, formatProofForVerifierContract, - getDefaultSigner, - parseArtifact, - getDefaultNetwork, + type IVerifyingKeyStruct, + type Subsidy, } from "maci-contracts"; import { STATE_TREE_ARITY } from "maci-core"; import { G1Point, G2Point, hashLeftRight } from "maci-crypto"; @@ -54,8 +52,7 @@ export const proveOnChain = async ({ quiet = true, }: ProveOnChainArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // check existence of contract addresses if (!readContractAddress("MACI", network?.name) && !maciAddress) { @@ -83,84 +80,60 @@ export const proveOnChain = async ({ } // check contracts are deployed on chain - if (!(await contractExists(ethSigner.provider!, maciContractAddress))) { + if (!(await contractExists(signer.provider!, maciContractAddress))) { logError("MACI contract does not exist"); } - if (!(await contractExists(ethSigner.provider!, messageProcessorContractAddress))) { + if (!(await contractExists(signer.provider!, messageProcessorContractAddress))) { logError("MessageProcessor contract does not exist"); } - if (!(await contractExists(ethSigner.provider!, tallyContractAddress))) { + if (!(await contractExists(signer.provider!, tallyContractAddress))) { logError("Tally contract does not exist"); } - if ( - subsidyEnabled && - subsidyContractAddress && - !(await contractExists(ethSigner.provider!, subsidyContractAddress)) - ) { + if (subsidyEnabled && subsidyContractAddress && !(await contractExists(signer.provider!, subsidyContractAddress))) { logError("Subsidy contract does not exist"); } - const maciContract = new BaseContract(maciContractAddress, parseArtifact("MACI")[0], ethSigner) as MACI; - + const maciContract = MACIFactory.connect(maciContractAddress, signer); const pollAddr = await maciContract.polls(pollId); - if (!(await contractExists(ethSigner.provider!, pollAddr))) { + if (!(await contractExists(signer.provider!, pollAddr))) { logError("There is no Poll contract with this poll ID linked to the specified MACI contract."); } - const pollContract = new BaseContract(pollAddr, parseArtifact("Poll")[0], ethSigner) as PollContract; - - const mpContract = new BaseContract( - messageProcessorContractAddress, - parseArtifact("MessageProcessor")[0], - ethSigner, - ) as MessageProcessor; + const pollContract = PollFactory.connect(pollAddr, signer); - const tallyContract = new BaseContract(tallyContractAddress, parseArtifact("Tally")[0], ethSigner) as Tally; + const mpContract = MessageProcessorFactory.connect(messageProcessorContractAddress, signer); + const tallyContract = TallyFactory.connect(tallyContractAddress, signer); let subsidyContract: Subsidy | undefined; if (subsidyEnabled && subsidyContractAddress) { - subsidyContract = new BaseContract(subsidyContractAddress, parseArtifact("Subsidy")[0], ethSigner) as Subsidy; + subsidyContract = SubsidyFactory.connect(subsidyContractAddress, signer); } const messageAqContractAddress = (await pollContract.extContracts()).messageAq; - if (!(await contractExists(ethSigner.provider!, messageAqContractAddress))) { + if (!(await contractExists(signer.provider!, messageAqContractAddress))) { logError("There is no MessageAq contract linked to the specified MACI contract."); } - const messageAqContract = new BaseContract( - messageAqContractAddress, - parseArtifact("AccQueue")[0], - ethSigner, - ) as AccQueue; - + const messageAqContract = AccQueueFactory.connect(messageAqContractAddress, signer); const vkRegistryContractAddress = await tallyContract.vkRegistry(); - if (!(await contractExists(ethSigner.provider!, vkRegistryContractAddress))) { + if (!(await contractExists(signer.provider!, vkRegistryContractAddress))) { logError("There is no VkRegistry contract linked to the specified MACI contract."); } - const vkRegsitryContract = new BaseContract( - vkRegistryContractAddress, - parseArtifact("VkRegistry")[0], - ethSigner, - ) as VkRegistry; - + const vkRegsitryContract = VkRegistryFactory.connect(vkRegistryContractAddress, signer); const verifierContractAddress = await mpContract.verifier(); - if (!(await contractExists(ethSigner.provider!, verifierContractAddress))) { + if (!(await contractExists(signer.provider!, verifierContractAddress))) { logError("There is no Verifier contract linked to the specified MACI contract."); } - const verifierContract = new BaseContract( - verifierContractAddress, - parseArtifact("Verifier")[0], - ethSigner, - ) as Verifier; + const verifierContract = VerifierFactory.connect(verifierContractAddress, signer); const data = { processProofs: [] as Proof[], diff --git a/cli/ts/commands/publish.ts b/cli/ts/commands/publish.ts index 52de88e144..5fe86c4938 100644 --- a/cli/ts/commands/publish.ts +++ b/cli/ts/commands/publish.ts @@ -1,5 +1,4 @@ -import { BaseContract } from "ethers"; -import { type MACI, type Poll, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts"; +import { MACI__factory as MACIFactory, Poll__factory as PollFactory } from "maci-contracts"; import { genRandomSalt } from "maci-crypto"; import { Keypair, PCommand, PrivKey, PubKey } from "maci-domainobjs"; @@ -36,8 +35,7 @@ export const publish = async ({ }: PublishArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // validate that the pub key of the user is valid if (!PubKey.isValidSerializedPubKey(pubkey)) { @@ -53,7 +51,7 @@ export const publish = async ({ const maciAddress = maciContractAddress || readContractAddress("MACI", network?.name); - if (!(await contractExists(ethSigner.provider!, maciAddress))) { + if (!(await contractExists(signer.provider!, maciAddress))) { logError("MACI contract does not exist"); } @@ -90,18 +88,14 @@ export const publish = async ({ logError("Invalid poll id"); } - const maciContractAbi = parseArtifact("MACI")[0]; - const pollContractAbi = parseArtifact("Poll")[0]; - - const maciContract = new BaseContract(maciAddress, maciContractAbi, ethSigner) as MACI; - + const maciContract = MACIFactory.connect(maciAddress, signer); const pollAddress = await maciContract.getPoll(pollId); - if (!(await contractExists(ethSigner.provider!, pollAddress))) { + if (!(await contractExists(signer.provider!, pollAddress))) { logError("Poll contract does not exist"); } - const pollContract = new BaseContract(pollAddress, pollContractAbi, ethSigner) as Poll; + const pollContract = PollFactory.connect(pollAddress, signer); const maxValues = await pollContract.maxValues(); const coordinatorPubKeyResult = await pollContract.coordinatorPubKey(); diff --git a/cli/ts/commands/setVerifyingKeys.ts b/cli/ts/commands/setVerifyingKeys.ts index d76c7a4a8f..93321b3e78 100644 --- a/cli/ts/commands/setVerifyingKeys.ts +++ b/cli/ts/commands/setVerifyingKeys.ts @@ -1,12 +1,5 @@ -import { BaseContract } from "ethers"; import { extractVk } from "maci-circuits"; -import { - type IVerifyingKeyStruct, - type VkRegistry, - getDefaultSigner, - getDefaultNetwork, - parseArtifact, -} from "maci-contracts"; +import { type IVerifyingKeyStruct, VkRegistry__factory as VkRegistryFactory } from "maci-contracts"; import { genProcessVkSig, genSubsidyVkSig, genTallyVkSig } from "maci-core"; import { VerifyingKey } from "maci-domainobjs"; @@ -45,8 +38,7 @@ export const setVerifyingKeys = async ({ }: SetVerifyingKeysArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // we must either have the contract as param or stored to file if (!readContractAddress("VkRegistry", network?.name) && !vkRegistry) { @@ -124,13 +116,12 @@ export const setVerifyingKeys = async ({ } // ensure we have a contract deployed at the provided address - if (!(await contractExists(ethSigner.provider!, vkRegistryAddress))) { + if (!(await contractExists(signer.provider!, vkRegistryAddress))) { logError(`A VkRegistry contract is not deployed at ${vkRegistryAddress}`); } // connect to VkRegistry contract - const vkRegistryAbi = parseArtifact("VkRegistry")[0]; - const vkRegistryContract = new BaseContract(vkRegistryAddress, vkRegistryAbi, ethSigner) as VkRegistry; + const vkRegistryContract = VkRegistryFactory.connect(vkRegistryAddress, signer); const messageBatchSize = 5 ** messageBatchDepth; diff --git a/cli/ts/commands/signup.ts b/cli/ts/commands/signup.ts index 6f1392f103..f7cd4e9632 100644 --- a/cli/ts/commands/signup.ts +++ b/cli/ts/commands/signup.ts @@ -1,5 +1,4 @@ -import { BaseContract } from "ethers"; -import { type MACI, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts"; +import { MACI__factory as MACIFactory } from "maci-contracts"; import { PubKey } from "maci-domainobjs"; import { @@ -31,8 +30,7 @@ export const signup = async ({ }: SignupArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // validate user key if (!PubKey.isValidSerializedPubKey(maciPubKey)) { logError("Invalid MACI public key"); @@ -47,7 +45,7 @@ export const signup = async ({ const maciContractAddress = maciAddress || readContractAddress("MACI", network?.name); - if (!(await contractExists(ethSigner.provider!, maciContractAddress))) { + if (!(await contractExists(signer.provider!, maciContractAddress))) { logError("There is no contract deployed at the specified address"); } @@ -65,8 +63,7 @@ export const signup = async ({ logError("invalid initial voice credit proxy data"); } - const maciContractAbi = parseArtifact("MACI")[0]; - const maciContract = new BaseContract(maciContractAddress, maciContractAbi, ethSigner) as MACI; + const maciContract = MACIFactory.connect(maciContractAddress, signer); let stateIndex = ""; try { diff --git a/cli/ts/commands/timeTravel.ts b/cli/ts/commands/timeTravel.ts index e638464154..d30381a53f 100644 --- a/cli/ts/commands/timeTravel.ts +++ b/cli/ts/commands/timeTravel.ts @@ -1,5 +1,3 @@ -import { getDefaultSigner } from "maci-contracts"; - import type { JsonRpcProvider } from "ethers"; import { banner, logError, logGreen, success, type TimeTravelArgs } from "../utils"; @@ -11,12 +9,11 @@ import { banner, logError, logGreen, success, type TimeTravelArgs } from "../uti */ export const timeTravel = async ({ seconds, signer, quiet = true }: TimeTravelArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); try { // send the instructions to the provider - await (ethSigner.provider as JsonRpcProvider).send("evm_increaseTime", [Number(seconds)]); - await (ethSigner.provider as JsonRpcProvider).send("evm_mine", []); + await (signer.provider as JsonRpcProvider).send("evm_increaseTime", [Number(seconds)]); + await (signer.provider as JsonRpcProvider).send("evm_mine", []); logGreen(quiet, success(`Fast-forwarded ${seconds} seconds`)); } catch (error) { diff --git a/cli/ts/commands/topup.ts b/cli/ts/commands/topup.ts index 7e46b220f8..6d185cc2b7 100644 --- a/cli/ts/commands/topup.ts +++ b/cli/ts/commands/topup.ts @@ -1,5 +1,4 @@ -import { BaseContract } from "ethers"; -import { type MACI, type Poll, getDefaultSigner, getDefaultNetwork, parseArtifact } from "maci-contracts"; +import { MACI__factory as MACIFactory, Poll__factory as PollFactory } from "maci-contracts"; import { type TopupArgs, logError, readContractAddress, contractExists, banner } from "../utils"; @@ -16,8 +15,7 @@ export const topup = async ({ quiet = true, }: TopupArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // ensure we have a valid MACI contract address if (!maciAddress && !readContractAddress(maciAddress!, network?.name)) { @@ -27,7 +25,7 @@ export const topup = async ({ const maciContractAddress = maciAddress || readContractAddress(maciAddress!, network?.name); - if (!(await contractExists(ethSigner.provider!, maciContractAddress))) { + if (!(await contractExists(signer.provider!, maciContractAddress))) { logError("There is no contract deployed at the specified address"); } @@ -44,16 +42,14 @@ export const topup = async ({ logError("Poll ID must be a positive integer"); } - const maciContractAbi = parseArtifact("MACI")[0]; - const maciContract = new BaseContract(maciContractAddress, maciContractAbi, ethSigner) as MACI; - const pollContractAbi = parseArtifact("Poll")[0]; + const maciContract = MACIFactory.connect(maciContractAddress, signer); const pollAddr = await maciContract.getPoll(pollId); - if (!(await contractExists(ethSigner.provider!, pollAddr))) { + if (!(await contractExists(signer.provider!, pollAddr))) { logError("There is no Poll contract with this poll ID linked to the specified MACI contract."); } - const pollContract = new BaseContract(pollAddr, pollContractAbi, ethSigner) as Poll; + const pollContract = PollFactory.connect(pollAddr, signer); try { // submit the topup message on chain diff --git a/cli/ts/commands/verify.ts b/cli/ts/commands/verify.ts index 77716cb736..dea3be5eda 100644 --- a/cli/ts/commands/verify.ts +++ b/cli/ts/commands/verify.ts @@ -1,12 +1,8 @@ -import { BaseContract } from "ethers"; import { - type Tally, - type MACI, - type Subsidy, - type Poll, - getDefaultSigner, - getDefaultNetwork, - parseArtifact, + Tally__factory as TallyFactory, + MACI__factory as MACIFactory, + Subsidy__factory as SubsidyFactory, + Poll__factory as PollFactory, } from "maci-contracts"; import { hash2, hash3, genTreeCommitment } from "maci-crypto"; @@ -45,8 +41,7 @@ export const verify = async ({ quiet = true, }: VerifyArgs): Promise => { banner(quiet); - const ethSigner = signer || (await getDefaultSigner()); - const network = await getDefaultNetwork(); + const network = await signer.provider?.getNetwork(); // ensure we have either tally data or tally file if (!(tallyData || tallyFile)) { @@ -74,7 +69,7 @@ export const verify = async ({ logError("Tally contract address is empty"); } - if (!(await contractExists(ethSigner.provider!, tallyContractAddress))) { + if (!(await contractExists(signer.provider!, tallyContractAddress))) { logError(`Error: there is no Tally contract deployed at ${tallyContractAddress}.`); } @@ -86,7 +81,7 @@ export const verify = async ({ logError("MACI contract address is empty"); } - if (!(await contractExists(ethSigner.provider!, maciContractAddress))) { + if (!(await contractExists(signer.provider!, maciContractAddress))) { logError(`Error: there is no MACI contract deployed at ${maciContractAddress}.`); } @@ -100,22 +95,19 @@ export const verify = async ({ logError("Subsidy contract address is empty"); } - if (!(await contractExists(ethSigner.provider!, subsidyContractAddress))) { + if (!(await contractExists(signer.provider!, subsidyContractAddress))) { logError(`Error: there is no Subsidy contract deployed at ${subsidyContractAddress}.`); } } // get the contract objects - const maciContract = new BaseContract(maciContractAddress, parseArtifact("MACI")[0], ethSigner) as MACI; + const maciContract = MACIFactory.connect(maciContractAddress, signer); const pollAddr = await maciContract.polls(pollId); - const pollContract = new BaseContract(pollAddr, parseArtifact("Poll")[0], ethSigner) as Poll; + const pollContract = PollFactory.connect(pollAddr, signer); + const tallyContract = TallyFactory.connect(tallyContractAddress, signer); - const tallyContract = new BaseContract(tallyContractAddress, parseArtifact("Tally")[0], ethSigner) as Tally; - - const subsidyContract = subsidyEnabled - ? (new BaseContract(subsidyContractAddress, parseArtifact("Subsidy")[0], ethSigner) as Subsidy) - : undefined; + const subsidyContract = subsidyEnabled ? SubsidyFactory.connect(subsidyContractAddress, signer) : undefined; // verification const onChainTallyCommitment = BigInt(await tallyContract.tallyCommitment()); diff --git a/cli/ts/index.ts b/cli/ts/index.ts index efed198bd1..c61fa7f277 100644 --- a/cli/ts/index.ts +++ b/cli/ts/index.ts @@ -5,6 +5,8 @@ import { Command } from "@commander-js/extra-typings"; import fs from "fs"; import path from "path"; +import type { Signer } from "ethers"; + import "./cliInit"; import { genKeyPair, @@ -35,6 +37,9 @@ const { description, version, name } = JSON.parse( ) as { description: string; version: string; name: string }; const program = new Command(); program.name(name).description(description).version(version); + +const getSigner = async (): Promise => import("maci-contracts").then((m) => m.getDefaultSigner()); + // add the commands program .command("create") @@ -54,6 +59,8 @@ program .requiredOption("-s, --stateTreeDepth ", "the state tree depth", parseInt) .action(async (cmdOptions) => { try { + const signer = await getSigner(); + await deploy({ stateTreeDepth: cmdOptions.stateTreeDepth, initialVoiceCredits: cmdOptions.initialVoiceCredits, @@ -64,6 +71,7 @@ program poseidonT5Address: cmdOptions.poseidonT5Address, poseidonT6Address: cmdOptions.poseidonT6Address, quiet: cmdOptions.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -94,6 +102,8 @@ program ) .action(async (cmdOptions) => { try { + const signer = await getSigner(); + await checkVerifyingKeys({ stateTreeDepth: cmdOptions.stateTreeDepth, intStateTreeDepth: cmdOptions.intStateTreeDepth, @@ -105,6 +115,7 @@ program vkRegistry: cmdOptions.vkContract, subsidyZkeyPath: cmdOptions.subsidyZkey, quiet: cmdOptions.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -138,12 +149,15 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await airdrop({ amount: cmdObj.amount, maciAddress: cmdObj.contract, pollId: cmdObj.pollId, contractAddress: cmdObj.tokenAddress, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -156,7 +170,9 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { - await deployVkRegistryContract({ quiet: cmdObj.quiet }); + const signer = await getSigner(); + + await deployVkRegistryContract({ quiet: cmdObj.quiet, signer }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); } @@ -194,6 +210,8 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await deployPoll({ pollDuration: cmdObj.duration, intStateTreeDepth: cmdObj.intStateTreeDepth, @@ -205,6 +223,7 @@ program maciAddress: cmdObj.maciAddress, vkRegistryAddress: cmdObj.vkRegistryAddress, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -235,6 +254,8 @@ program ) .action(async (cmdObj) => { try { + const signer = await getSigner(); + await setVerifyingKeys({ stateTreeDepth: cmdObj.stateTreeDepth, intStateTreeDepth: cmdObj.intStateTreeDepth, @@ -246,6 +267,7 @@ program vkRegistry: cmdObj.vkRegistry, subsidyZkeyPath: cmdObj.subsidyZkey, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -270,6 +292,8 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await publish({ pubkey: cmdObj.pubkey, stateIndex: cmdObj.stateIndex, @@ -281,6 +305,7 @@ program salt: cmdObj.salt, privateKey: cmdObj.privkey, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -296,11 +321,14 @@ program .option("-n, --num-queue-ops ", "the number of queue operations", parseInt) .action(async (cmdObj) => { try { + const signer = await getSigner(); + await mergeMessages({ pollId: cmdObj.pollId, maciContractAddress: cmdObj.maciContractAddress, numQueueOps: cmdObj.numQueueOps?.toString(), quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -316,11 +344,14 @@ program .option("-n, --num-queue-ops ", "the number of queue operations", parseInt) .action(async (cmdObj) => { try { + const signer = await getSigner(); + await mergeSignups({ pollId: cmdObj.pollId, maciContractAddress: cmdObj.maciContractAddress, numQueueOps: cmdObj.numQueueOps?.toString(), quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -334,7 +365,9 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { - await timeTravel({ seconds: cmdObj.seconds, quiet: cmdObj.quiet }); + const signer = await getSigner(); + + await timeTravel({ seconds: cmdObj.seconds, quiet: cmdObj.quiet, signer }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); } @@ -350,12 +383,15 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await signup({ maciPubKey: cmdObj.pubkey, maciAddress: cmdObj.maciAddress, sgDataArg: cmdObj.sgData, ivcpDataArg: cmdObj.ivcpData, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -372,12 +408,15 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await topup({ amount: cmdObj.amount, stateIndex: cmdObj.stateIndex, pollId: cmdObj.pollId, maciAddress: cmdObj.maciAddress, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -392,7 +431,9 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { - await fundWallet({ amount: cmdObj.amount, address: cmdObj.address, quiet: cmdObj.quiet }); + const signer = await getSigner(); + + await fundWallet({ amount: cmdObj.amount, address: cmdObj.address, quiet: cmdObj.quiet, signer }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); } @@ -419,6 +460,8 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await verify({ pollId: cmdObj.pollId, subsidyEnabled: cmdObj.subsidyEnabled, @@ -428,6 +471,7 @@ program subsidyAddress: cmdObj.subsidyContract, subsidyFile: cmdObj.subsidyFile, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -470,6 +514,8 @@ program .option("-uq, --use-quadratic-voting", "whether to use quadratic voting", (value) => value === "true", true) .action(async (cmdObj) => { try { + const signer = await getSigner(); + await genProofs({ outputDir: cmdObj.output, tallyFile: cmdObj.tallyFile, @@ -499,6 +545,7 @@ program tallyAddress: cmdObj.tallyAddress, useQuadraticVoting: cmdObj.useQuadraticVoting, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -520,6 +567,8 @@ program .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await genLocalState({ outputPath: cmdObj.output.toString(), pollId: cmdObj.pollId, @@ -532,6 +581,7 @@ program transactionHash: cmdObj.transactionHash, sleep: cmdObj.sleep, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); @@ -556,6 +606,8 @@ program .requiredOption("-f, --proof-dir ", "the proof output directory from the genProofs subcommand") .action(async (cmdObj) => { try { + const signer = await getSigner(); + await proveOnChain({ pollId: cmdObj.pollId, proofDir: cmdObj.proofDir, @@ -565,6 +617,7 @@ program tallyAddress: cmdObj.tallyContract, subsidyAddress: cmdObj.subsidyContract, quiet: cmdObj.quiet, + signer, }); } catch (error) { program.error((error as Error).message, { exitCode: 1 }); diff --git a/cli/ts/sdk/index.ts b/cli/ts/sdk/index.ts new file mode 100644 index 0000000000..f38a9e5fb5 --- /dev/null +++ b/cli/ts/sdk/index.ts @@ -0,0 +1,3 @@ +export { genKeyPair, genMaciPubKey, publish, signup, verify } from "../commands"; + +export type { DeployedContracts, PollContracts, TallyData, PublishArgs, SignupArgs, VerifyArgs } from "../utils"; diff --git a/cli/ts/utils/interfaces.ts b/cli/ts/utils/interfaces.ts index a2bbc2ad05..5113dfd9f0 100644 --- a/cli/ts/utils/interfaces.ts +++ b/cli/ts/utils/interfaces.ts @@ -168,6 +168,11 @@ export interface AirdropArgs { */ amount: number; + /** + * A signer object + */ + signer: Signer; + /** * The address of the ERC20 contract */ @@ -187,11 +192,6 @@ export interface AirdropArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -233,6 +233,11 @@ export interface CheckVerifyingKeysArgs { */ tallyVotesZkeyPath: string; + /** + * A signer object + */ + signer: Signer; + /** * The address of the VkRegistry contract */ @@ -247,11 +252,6 @@ export interface CheckVerifyingKeysArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -263,6 +263,11 @@ export interface DeployArgs { */ stateTreeDepth: number; + /** + * A signer object + */ + signer: Signer; + /** * The initial voice credits to be minted */ @@ -302,11 +307,6 @@ export interface DeployArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -348,6 +348,11 @@ export interface DeployPollArgs { */ subsidyEnabled: boolean; + /** + * A signer object + */ + signer: Signer; + /** * The MACI contract address */ @@ -362,11 +367,6 @@ export interface DeployPollArgs { * Whether to log the output to the console */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -384,6 +384,11 @@ export interface GenLocalStateArgs { */ pollId: bigint; + /** + * A signer object + */ + signer: Signer; + /** * The address of the MACI contract */ @@ -428,11 +433,6 @@ export interface GenLocalStateArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -464,6 +464,11 @@ export interface GenProofsArgs { */ pollId: bigint; + /** + * A signer object + */ + signer: Signer; + /** * The file to store the subsidy proof */ @@ -569,11 +574,6 @@ export interface GenProofsArgs { */ quiet?: boolean; - /** - * A signer object - */ - signer?: Signer; - /** * Whether to use quadratic voting or not */ @@ -594,6 +594,11 @@ export interface MergeMessagesArgs { */ pollId: bigint; + /** + * A signer object + */ + signer: Signer; + /** * Whether to log the output */ @@ -608,11 +613,6 @@ export interface MergeMessagesArgs { * The number of queue operations to merge */ numQueueOps?: string; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -624,6 +624,11 @@ export interface MergeSignupsArgs { */ pollId: bigint; + /** + * A signer object + */ + signer: Signer; + /** * The address of the MACI contract */ @@ -638,11 +643,6 @@ export interface MergeSignupsArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -664,6 +664,11 @@ export interface ProveOnChainArgs { */ subsidyEnabled: boolean; + /** + * A signer object + */ + signer: Signer; + /** * The address of the MACI contract */ @@ -688,11 +693,6 @@ export interface ProveOnChainArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -729,6 +729,11 @@ export interface PublishArgs { */ newVoteWeight: bigint; + /** + * A signer object + */ + signer: Signer; + /** * The address of the MACI contract */ @@ -748,11 +753,6 @@ export interface PublishArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -794,6 +794,11 @@ export interface SetVerifyingKeysArgs { */ tallyVotesZkeyPath: string; + /** + * A signer object + */ + signer: Signer; + /** * The address of the vkRegistry contract */ @@ -808,11 +813,6 @@ export interface SetVerifyingKeysArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -824,6 +824,11 @@ export interface SignupArgs { */ maciPubKey: string; + /** + * A signer object + */ + signer: Signer; + /** * The address of the MACI contract */ @@ -843,11 +848,6 @@ export interface SignupArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -875,14 +875,14 @@ export interface TopupArgs { maciAddress?: string; /** - * Whether to log the output + * A signer object */ - quiet?: boolean; + signer: Signer; /** - * A signer object + * Whether to log the output */ - signer?: Signer; + quiet?: boolean; } /** @@ -899,6 +899,11 @@ export interface VerifyArgs { */ subsidyEnabled: boolean; + /** + * A signer object + */ + signer: Signer; + /** * The path to the tally file with results, per vote option spent credits, spent voice credits total */ @@ -933,11 +938,6 @@ export interface VerifyArgs { * Whether to log the output */ quiet?: boolean; - - /** - * A signer object - */ - signer?: Signer; } /** @@ -955,14 +955,14 @@ export interface FundWalletArgs { address: string; /** - * Whether to log the output + * A signer object */ - quiet?: boolean; + signer: Signer; /** - * A signer object + * Whether to log the output */ - signer?: Signer; + quiet?: boolean; } /** @@ -975,14 +975,14 @@ export interface TimeTravelArgs { seconds: number; /** - * Whether to log the output + * A signer object */ - quiet?: boolean; + signer: Signer; /** - * A signer object + * Whether to log the output */ - signer?: Signer; + quiet?: boolean; } /** @@ -990,12 +990,12 @@ export interface TimeTravelArgs { */ export interface DeployVkRegistryArgs { /** - * Whether to log the output + * A signer object */ - quiet?: boolean; + signer: Signer; /** - * A signer object + * Whether to log the output */ - signer?: Signer; + quiet?: boolean; } diff --git a/integrationTests/ts/__tests__/integration.test.ts b/integrationTests/ts/__tests__/integration.test.ts index 44ce005fd1..1080391f68 100644 --- a/integrationTests/ts/__tests__/integration.test.ts +++ b/integrationTests/ts/__tests__/integration.test.ts @@ -1,6 +1,7 @@ /* eslint-disable no-await-in-loop */ import chai from "chai"; import chaiAsPromised from "chai-as-promised"; +import { Signer } from "ethers"; import { deploy, deployPoll, @@ -17,6 +18,7 @@ import { DeployedContracts, PollContracts, } from "maci-cli"; +import { getDefaultSigner } from "maci-contracts"; import { MaciState, MaxValues, TreeDepths } from "maci-core"; import { genPubKey, genRandomSalt } from "maci-crypto"; import { Keypair, PCommand, PrivKey, PubKey } from "maci-domainobjs"; @@ -61,12 +63,14 @@ describe("Integration tests", function test() { let contracts: DeployedContracts; let pollContracts: PollContracts; let pollId: bigint; + let signer: Signer; const coordinatorKeypair = new Keypair(); // the code that we run before all tests before(async () => { + signer = await getDefaultSigner(); // 1. deploy Vk Registry - const vkRegistryAddress = await deployVkRegistryContract({}); + const vkRegistryAddress = await deployVkRegistryContract({ signer }); // 2. set verifying keys await setVerifyingKeys({ stateTreeDepth: STATE_TREE_DEPTH, @@ -87,6 +91,7 @@ describe("Integration tests", function test() { __dirname, "../../../cli/zkeys/SubsidyPerBatch_10-1-2_test/SubsidyPerBatch_10-1-2_test.0.zkey", ), + signer, }); }); @@ -96,7 +101,7 @@ describe("Integration tests", function test() { maciState = new MaciState(STATE_TREE_DEPTH); // 3. deploy maci - contracts = await deploy({ stateTreeDepth: STATE_TREE_DEPTH, initialVoiceCredits }); + contracts = await deploy({ stateTreeDepth: STATE_TREE_DEPTH, initialVoiceCredits, signer }); const maxValues: MaxValues = { maxMessages: 25, @@ -113,6 +118,7 @@ describe("Integration tests", function test() { coordinatorPubkey: coordinatorKeypair.pubKey.serialize(), subsidyEnabled: true, maciAddress: contracts.maciAddress, + signer, }); const treeDepths: TreeDepths = { @@ -183,6 +189,7 @@ describe("Integration tests", function test() { maciAddress: contracts.maciAddress, sgDataArg: SG_DATA, ivcpDataArg: ivcpData, + signer, }), ); @@ -218,6 +225,7 @@ describe("Integration tests", function test() { salt, // if it's a key change command, then we pass the old private key otherwise just pass the current privateKey: isKeyChange ? oldKeypair.privKey.serialize() : user.keypair.privKey.serialize(), + signer, }); const encPrivKey = PrivKey.deserialize(encryptionKey); @@ -239,16 +247,16 @@ describe("Integration tests", function test() { } } - await timeTravel({ seconds: duration }); + await timeTravel({ seconds: duration, signer }); // merge messages await expect( - mergeMessages({ pollId, maciContractAddress: contracts.maciAddress }), + mergeMessages({ pollId, maciContractAddress: contracts.maciAddress, signer }), ).to.eventually.not.be.rejectedWith(); // merge signups await expect( - mergeSignups({ pollId, maciContractAddress: contracts.maciAddress }), + mergeSignups({ pollId, maciContractAddress: contracts.maciAddress, signer }), ).to.eventually.not.be.rejectedWith(); // generate proofs @@ -306,6 +314,7 @@ describe("Integration tests", function test() { "../../../cli/zkeys/SubsidyPerBatch_10-1-2_test/SubsidyPerBatch_10-1-2_test_js/SubsidyPerBatch_10-1-2_test.wasm", ), useWasm, + signer, }); expect(tallyData).to.not.eq(undefined); @@ -335,6 +344,7 @@ describe("Integration tests", function test() { messageProcessorAddress: pollContracts.messageProcessor, tallyAddress: pollContracts.tally, subsidyAddress: pollContracts.subsidy, + signer, }), ).to.eventually.not.rejectedWith(); @@ -348,6 +358,7 @@ describe("Integration tests", function test() { tallyAddress: pollContracts.tally, subsidyAddress: pollContracts.subsidy, subsidyFile: subsidyEnabled ? path.resolve(__dirname, "../../../cli/subsidy.json") : undefined, + signer, }), ).to.eventually.not.rejectedWith(); });