Skip to content

Commit

Permalink
Merge pull request privacy-scaling-explorations#876 from privacy-scal…
Browse files Browse the repository at this point in the history
…ing-explorations/fix/cli
  • Loading branch information
ctrlc03 authored Dec 7, 2023
2 parents 3f8fcda + 1915542 commit b653004
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 220 deletions.
4 changes: 3 additions & 1 deletion cli/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
contractAddresses.json
contractAddresses.old.json
localState.json
contractAddress.old
contractAddress.txt
localState.json
24 changes: 22 additions & 2 deletions cli/ts/commands/genLocalState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { getDefaultSigner, genMaciStateFromContract } from "maci-contracts";
import { promptSensitiveValue, banner, contractExists, logError, logYellow, readContractAddress, info } from "../utils";
import {
promptSensitiveValue,
banner,
contractExists,
logError,
logYellow,
readContractAddress,
info,
logGreen,
success,
} from "../utils";
import { Keypair, PrivKey } from "maci-domainobjs";
import { JsonRpcProvider } from "ethers";
import { writeFileSync } from "fs";
Expand All @@ -8,6 +18,15 @@ import { writeFileSync } from "fs";
* Generate a local MACI state from the smart contracts events
* @param outputPath - the path where to write the state
* @param pollId - the id of the poll
* @param maciContractAddress - the address of the MACI contract
* @param coordinatorPrivateKey - the private key of the MACI coordinator
* @param ethereumProvider - the ethereum provider
* @param endBlock - the end block number
* @param startBlock - the start block number
* @param blockPerBatch - the number of blocks to fetch per batch
* @param transactionHash - the transaction hash
* @param sleep - the sleep time between batches
* @param quiet - whether to log the output
*/
export const genLocalState = async (
outputPath: string,
Expand All @@ -23,7 +42,6 @@ export const genLocalState = async (
quiet = true,
) => {
banner(quiet);

// validation of the maci contract address
if (!readContractAddress("MACI") && !maciContractAddress) logError("MACI contract address is empty");

Expand Down Expand Up @@ -74,4 +92,6 @@ export const genLocalState = async (
// write the state to a file
const serializedState = maciState.toJSON();
writeFileSync(outputPath, JSON.stringify(serializedState, null, 4));

logGreen(quiet, success(`The state has been written to ${outputPath}`));
};
19 changes: 13 additions & 6 deletions cli/ts/commands/genProofs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ export const genProofs = async (
const processDatFile = processWitgen + ".dat";
const tallyDatFile = tallyWitgen + ".dat";
const [ok, path] = doesPathExist([rapidsnark, processWitgen, tallyWitgen, processDatFile, tallyDatFile]);

if (!ok) logError(`Could not find ${path}.`);
}

// check if zkeys were provided
const [ok, path] = doesPathExist([processZkey, tallyZkey]);

if (!ok) logError(`Could not find ${path}.`);

// the vk for the subsidy contract (optional)
Expand All @@ -113,16 +115,19 @@ export const genProofs = async (
if (!subsidyWitgen) logError("Please specify the subsidy witnessgen file location");
const subsidyDatFile = subsidyWitgen + ".dat";
const [ok, path] = doesPathExist([subsidyWitgen, subsidyDatFile]);

if (!ok) logError(`Could not find ${path}.`);
} else {
// we expect to have the wasm file
if (!subsidyWasm) logError("Please specify the subsidy wasm file location");
const [ok, path] = doesPathExist([subsidyWasm]);

if (!ok) logError(`Could not find ${path}.`);
}

// either way we check the subsidy zkey
const [ok, path] = doesPathExist([subsidyZkey]);

if (!ok) logError(`Could not find ${path}.`);

subsidyVk = await extractVk(subsidyZkey);
Expand Down Expand Up @@ -170,12 +175,6 @@ export const genProofs = async (
if (mainRoot === "0")
logError("The message tree has not been merged yet. " + "Please use the mergeMessages subcommmand to do so.");

// build an off-chain representation of the MACI contract using data in the contract storage
let fromBlock = startBlock ? Number(startBlock) : 0;
fromBlock = transactionHash ? (await signer.provider.getTransaction(transactionHash)).blockNumber : 0;

logYellow(quiet, info(`starting to fetch logs from block ${fromBlock}`));

let maciState: MaciState;
if (stateFile) {
const content = JSON.parse(readFileSync(stateFile).toString());
Expand All @@ -188,6 +187,11 @@ export const genProofs = async (
logError(error.message);
}
} else {
// build an off-chain representation of the MACI contract using data in the contract storage
let fromBlock = startBlock ? Number(startBlock) : 0;
fromBlock = transactionHash ? (await signer.provider.getTransaction(transactionHash)).blockNumber : 0;

logYellow(quiet, info(`starting to fetch logs from block ${fromBlock}`));
maciState = await genMaciStateFromContract(
signer.provider,
await maciContract.getAddress(),
Expand Down Expand Up @@ -308,6 +312,7 @@ export const genProofs = async (

// store it
writeFileSync(subsidyFile, JSON.stringify(subsidyFileData, null, 4));
logYellow(quiet, info(`Subsidy file:\n${JSON.stringify(subsidyFileData, null, 4)}\n`));

const susbsidyEndTime = Date.now();

Expand Down Expand Up @@ -406,6 +411,8 @@ export const genProofs = async (

writeFileSync(tallyFile, JSON.stringify(tallyFileData, null, 4));

logYellow(quiet, info(`Tally file:\n${JSON.stringify(tallyFileData, null, 4)}\n`));

// compare the commitments
if ("0x" + newTallyCommitment.toString(16) === tallyFileData.newTallyCommitment) {
logGreen(quiet, success("The tally commitment is correct"));
Expand Down
6 changes: 4 additions & 2 deletions cli/ts/commands/signup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,19 @@ export const signup = async (
// sign up to the MACI contract
const tx = await maciContract.signUp(userMaciPubKey.asContractParam(), sgData, ivcpData, { gasLimit: 1000000 });
const receipt = await tx.wait();

logYellow(quiet, info(`Transaction hash: ${tx.hash}`));

if (receipt.status !== 1) logError("The transaction failed");
const iface = maciContract.interface;

// get state index from the event
if (receipt && receipt.logs) {
stateIndex = iface.parseLog(receipt.logs[0]).args[0];

logGreen(quiet, success(`State index: ${stateIndex.toString()}`));
} else {
logError("Unable to retrieve the transaction receipt");
}
logYellow(quiet, info(`Transaction hash: ${tx.hash}`));
} catch (error: any) {
logError(error.message);
}
Expand Down
2 changes: 0 additions & 2 deletions cli/ts/commands/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ export const verify = async (
if (!existsSync(subsidyFile)) logError(`There is no such file: ${subsidyFile}`);
const subsidyData = JSON.parse(readFileSync(subsidyFile, { encoding: "utf8" }));

logYellow(quiet, info(`subsidy file: ${subsidyData}`));

// check the results commitment
const validResultsCommitment =
subsidyData.newSubsidyCommitment && subsidyData.newSubsidyCommitment.match(/0x[a-fA-F0-9]+/);
Expand Down
62 changes: 42 additions & 20 deletions cli/ts/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env node
import { createCommand } from "commander";
import {
genKeyPair,
Expand Down Expand Up @@ -41,7 +42,8 @@ program
"the initial voice credits proxy contract address",
)
.option("-g", "--signupGatekeeperAddress <signupGatekeeperAddress>", "the signup gatekeeper contract address")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.requiredOption("-s, --stateTreeDepth <stateTreeDepth>", "the state tree depth")
.action(async (cmdOptions) => {
try {
Expand All @@ -60,7 +62,8 @@ program
program
.command("checkVerifyingKeys")
.description("check that the verifying keys in the contract match the local ones")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.option("-x, --maci-contract <maciContract>", "the MACI contract address")
.requiredOption("-s, --state-tree-depth <stateTreeDepth>", "the state tree depth")
.requiredOption("-i, --int-state-tree-depth <intStateTreeDepth>", "the intermediate state tree depth")
Expand Down Expand Up @@ -90,14 +93,16 @@ program
.command("genMaciPubKey")
.description("generate a new MACI public key")
.requiredOption("-sk, --privkey <privkey>", "the private key")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action((cmdObj) => {
genMaciPubKey(cmdObj.privkey, cmdObj.quiet);
});
program
.command("genMaciKeyPair")
.description("generate a new MACI key pair")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action((cmdObj) => {
genKeyPair(cmdObj.quiet);
});
Expand All @@ -108,7 +113,8 @@ program
.option("-x, --contract <contract>", "the MACI contract address")
.option("-o, --poll-id <pollId>", "poll id")
.option("-t, --token-address <tokenAddress>", "the token address")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await airdrop(cmdObj.amount, cmdObj.contract, cmdObj.pollId, cmdObj.tokenAddress, cmdObj.quiet);
Expand All @@ -119,7 +125,8 @@ program
program
.command("deployVkRegistry")
.description("deploy a new verification key registry contract")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await deployVkRegistryContract(cmdObj.quiet);
Expand All @@ -130,7 +137,8 @@ program
program
.command("show")
.description("show the deployed contract addresses")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action((cmdObj) => {
try {
showContracts(cmdObj.quiet);
Expand All @@ -150,7 +158,8 @@ program
.requiredOption("-v, --vote-option-tree-depth <voteOptionTreeDepth>", "the vote option tree depth")
.requiredOption("-pk, --pubkey <coordinatorPubkey>", "the coordinator public key")
.option("-x, --maci-address <maciAddress>", "the MACI contract address")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await deployPoll(
Expand Down Expand Up @@ -180,7 +189,8 @@ program
.requiredOption("-p, --process-messages-zkey <processMessagesZkeyPath>", "the process messages zkey path")
.requiredOption("-t, --tally-votes-zkey <tallyVotesZkeyPath>", "the tally votes zkey path")
.option("-k, --vk-registry <vkRegistry>", "the vk registry contract address")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.option("-ss, --subsidy-zkey <subsidyZkeyPath>", "the subsidy zkey path")
.action(async (cmdObj) => {
try {
Expand Down Expand Up @@ -215,7 +225,8 @@ program
.option("-s, --salt <salt>", "the message salt")
.requiredOption("-o, --poll-id <pollId>", "the poll id")
.requiredOption("-w, --new-vote-weight <newVoteWeight>", "the new vote weight")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await publish(
Expand All @@ -237,7 +248,8 @@ program
program
.command("mergeMessages")
.description("merge the message accumulator queue")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.option("-x, --maci-contract-address <maciContractAddress>", "the MACI contract address")
.requiredOption("-o, --poll-id <pollId>", "the poll id")
.option("-n, --num-queue-ops <numQueueOps>", "the number of queue operations")
Expand All @@ -251,7 +263,8 @@ program
program
.command("mergeSignups")
.description("merge the signups accumulator queue")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.option("-x, --maci-contract-address <maciContractAddress>", "the MACI contract address")
.requiredOption("-o, --poll-id <pollId>", "the poll id")
.option("-n, --num-queue-ops <numQueueOps>", "the number of queue operations")
Expand All @@ -266,7 +279,8 @@ program
.command("timeTravel")
.description("fast-forward the time (only works for local hardhat testing")
.requiredOption("-s, --seconds <seconds>", "the number of seconds to fast-forward")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await timeTravel(cmdObj.seconds, cmdObj.quiet);
Expand All @@ -281,7 +295,8 @@ program
.option("-x, --maci-address <maciAddress>", "the MACI contract address")
.option("-s, --sg-data <sgData>", "the signup gateway data")
.option("-i, --ivcp-data <ivcpData>", "the initial voice credit proxy data")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await signup(cmdObj.pubkey, cmdObj.maciAddress, cmdObj.sgData, cmdObj.ivcpData, cmdObj.quiet);
Expand All @@ -296,7 +311,8 @@ program
.option("-x, --maci-address <maciAddress>", "the MACI contract address")
.requiredOption("-i, --state-index <stateIndex>", "state leaf index")
.requiredOption("-o, --poll-id <pollId>", "poll id")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await topup(cmdObj.amount, cmdObj.stateIndex, cmdObj.pollId, cmdObj.maciAddress, cmdObj.quiet);
Expand All @@ -309,7 +325,8 @@ program
.description("Fund a wallet with Ether")
.requiredOption("-a, --amount <amount>", "the amount of Ether")
.requiredOption("-w, --address <address>", "the address to fund")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await fundWallet(cmdObj.amount, cmdObj.address, cmdObj.quiet);
Expand All @@ -326,7 +343,8 @@ program
.option("-x, --contract <contract>", "the MACI contract address")
.option("-tc, --tally-contract <tallyContract>", "the tally contract address")
.option("-sc, --subsidy-contract <subsidyContract>", "the subsidy contract address")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await verify(
Expand Down Expand Up @@ -357,7 +375,8 @@ program
.requiredOption("-zp, --process-zkey <processZkey>", "the path to the process zkey")
.requiredOption("-zt, --tally-zkey <tallyZkey>", "the path to the tally zkey")
.option("-zs, --subsidy-zkey <subsidyZkey>", "the path to the subsidy zkey")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-p, --rpc-provider <provider>", "the rpc provider URL")
.requiredOption("-f, --output <outputDir>", "the output directory for proofs")
.option("-tx, --transaction-hash <transactionHash>", "transaction hash of MACI contract creation")
.option("-w, --wasm", "whether to use the wasm binaries")
Expand Down Expand Up @@ -411,14 +430,16 @@ program
.option("-bb, --blocks-per-batch <blockPerBatch>", "the blocks per batch")
.option("-tx, --transaction-hash <transactionHash>", "the transaction hash")
.option("-s, --sleep <sleep>", "the sleep time between batches")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.action(async (cmdObj) => {
try {
await genLocalState(
cmdObj.output,
cmdObj.pollId,
cmdObj.contract,
cmdObj.privkey,
cmdObj.provider,
cmdObj.endBlock,
cmdObj.startBlock,
cmdObj.blockPerBatch,
Expand All @@ -434,7 +455,8 @@ program
.command("proveOnChain")
.description("prove the results of a poll on chain")
.requiredOption("-o, --poll-id <pollId>", "the poll id")
.option("-q, --quiet", "whether to print values to the console", false)
.option("-q, --quiet <quiet>", "whether to print values to the console", (value) => value === "true", false)
.option("-r, --rpc-provider <provider>", "the rpc provider URL")
.option("-x, --contract <contract>", "the MACI contract address")
.option("-p, --message-processor-address <messageProcessorAddress>", "the message processor contract address")
.option("-t, --tally-contract <tallyContract>", "the tally contract address")
Expand Down
Loading

0 comments on commit b653004

Please sign in to comment.