From 191554279c97c8220a2b6d50f1a28977581b17b5 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Wed, 6 Dec 2023 13:51:00 +0000 Subject: [PATCH] fix(cli) - Small ui fixes, fix wrong cli flags, improve documentation and ensure the cli walkthorugh is up to date --- cli/.gitignore | 4 +- cli/ts/commands/genLocalState.ts | 24 +- cli/ts/commands/genProofs.ts | 19 +- cli/ts/commands/signup.ts | 6 +- cli/ts/commands/verify.ts | 2 - cli/ts/index.ts | 62 ++- website/versioned_docs/version-v1.x/cli.md | 427 ++++++++++++--------- 7 files changed, 324 insertions(+), 220 deletions(-) diff --git a/cli/.gitignore b/cli/.gitignore index f7f90906d7..f76dab18ee 100644 --- a/cli/.gitignore +++ b/cli/.gitignore @@ -1,3 +1,5 @@ contractAddresses.json contractAddresses.old.json -localState.json \ No newline at end of file +contractAddress.old +contractAddress.txt +localState.json diff --git a/cli/ts/commands/genLocalState.ts b/cli/ts/commands/genLocalState.ts index 3369398114..cf44660935 100644 --- a/cli/ts/commands/genLocalState.ts +++ b/cli/ts/commands/genLocalState.ts @@ -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"; @@ -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, @@ -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"); @@ -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}`)); }; diff --git a/cli/ts/commands/genProofs.ts b/cli/ts/commands/genProofs.ts index 7dc0dc5780..c134bd656b 100644 --- a/cli/ts/commands/genProofs.ts +++ b/cli/ts/commands/genProofs.ts @@ -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) @@ -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); @@ -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()); @@ -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(), @@ -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(); @@ -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")); diff --git a/cli/ts/commands/signup.ts b/cli/ts/commands/signup.ts index 5a23be3720..226071b33b 100644 --- a/cli/ts/commands/signup.ts +++ b/cli/ts/commands/signup.ts @@ -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); } diff --git a/cli/ts/commands/verify.ts b/cli/ts/commands/verify.ts index 60813a4047..8e49ba07c1 100644 --- a/cli/ts/commands/verify.ts +++ b/cli/ts/commands/verify.ts @@ -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]+/); diff --git a/cli/ts/index.ts b/cli/ts/index.ts index 21ea899f06..2aa841eaa4 100644 --- a/cli/ts/index.ts +++ b/cli/ts/index.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { createCommand } from "commander"; import { genKeyPair, @@ -41,7 +42,8 @@ program "the initial voice credits proxy contract address", ) .option("-g", "--signupGatekeeperAddress ", "the signup gatekeeper contract address") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .requiredOption("-s, --stateTreeDepth ", "the state tree depth") .action(async (cmdOptions) => { try { @@ -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 ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .option("-x, --maci-contract ", "the MACI contract address") .requiredOption("-s, --state-tree-depth ", "the state tree depth") .requiredOption("-i, --int-state-tree-depth ", "the intermediate state tree depth") @@ -90,14 +93,16 @@ program .command("genMaciPubKey") .description("generate a new MACI public key") .requiredOption("-sk, --privkey ", "the private key") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-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 ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action((cmdObj) => { genKeyPair(cmdObj.quiet); }); @@ -108,7 +113,8 @@ program .option("-x, --contract ", "the MACI contract address") .option("-o, --poll-id ", "poll id") .option("-t, --token-address ", "the token address") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await airdrop(cmdObj.amount, cmdObj.contract, cmdObj.pollId, cmdObj.tokenAddress, cmdObj.quiet); @@ -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 ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await deployVkRegistryContract(cmdObj.quiet); @@ -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 ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action((cmdObj) => { try { showContracts(cmdObj.quiet); @@ -150,7 +158,8 @@ program .requiredOption("-v, --vote-option-tree-depth ", "the vote option tree depth") .requiredOption("-pk, --pubkey ", "the coordinator public key") .option("-x, --maci-address ", "the MACI contract address") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await deployPoll( @@ -180,7 +189,8 @@ program .requiredOption("-p, --process-messages-zkey ", "the process messages zkey path") .requiredOption("-t, --tally-votes-zkey ", "the tally votes zkey path") .option("-k, --vk-registry ", "the vk registry contract address") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .option("-ss, --subsidy-zkey ", "the subsidy zkey path") .action(async (cmdObj) => { try { @@ -215,7 +225,8 @@ program .option("-s, --salt ", "the message salt") .requiredOption("-o, --poll-id ", "the poll id") .requiredOption("-w, --new-vote-weight ", "the new vote weight") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await publish( @@ -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 ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .option("-x, --maci-contract-address ", "the MACI contract address") .requiredOption("-o, --poll-id ", "the poll id") .option("-n, --num-queue-ops ", "the number of queue operations") @@ -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 ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .option("-x, --maci-contract-address ", "the MACI contract address") .requiredOption("-o, --poll-id ", "the poll id") .option("-n, --num-queue-ops ", "the number of queue operations") @@ -266,7 +279,8 @@ program .command("timeTravel") .description("fast-forward the time (only works for local hardhat testing") .requiredOption("-s, --seconds ", "the number of seconds to fast-forward") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await timeTravel(cmdObj.seconds, cmdObj.quiet); @@ -281,7 +295,8 @@ program .option("-x, --maci-address ", "the MACI contract address") .option("-s, --sg-data ", "the signup gateway data") .option("-i, --ivcp-data ", "the initial voice credit proxy data") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await signup(cmdObj.pubkey, cmdObj.maciAddress, cmdObj.sgData, cmdObj.ivcpData, cmdObj.quiet); @@ -296,7 +311,8 @@ program .option("-x, --maci-address ", "the MACI contract address") .requiredOption("-i, --state-index ", "state leaf index") .requiredOption("-o, --poll-id ", "poll id") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await topup(cmdObj.amount, cmdObj.stateIndex, cmdObj.pollId, cmdObj.maciAddress, cmdObj.quiet); @@ -309,7 +325,8 @@ program .description("Fund a wallet with Ether") .requiredOption("-a, --amount ", "the amount of Ether") .requiredOption("-w, --address
", "the address to fund") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await fundWallet(cmdObj.amount, cmdObj.address, cmdObj.quiet); @@ -326,7 +343,8 @@ program .option("-x, --contract ", "the MACI contract address") .option("-tc, --tally-contract ", "the tally contract address") .option("-sc, --subsidy-contract ", "the subsidy contract address") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await verify( @@ -357,7 +375,8 @@ program .requiredOption("-zp, --process-zkey ", "the path to the process zkey") .requiredOption("-zt, --tally-zkey ", "the path to the tally zkey") .option("-zs, --subsidy-zkey ", "the path to the subsidy zkey") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-p, --rpc-provider ", "the rpc provider URL") .requiredOption("-f, --output ", "the output directory for proofs") .option("-tx, --transaction-hash ", "transaction hash of MACI contract creation") .option("-w, --wasm", "whether to use the wasm binaries") @@ -411,7 +430,8 @@ program .option("-bb, --blocks-per-batch ", "the blocks per batch") .option("-tx, --transaction-hash ", "the transaction hash") .option("-s, --sleep ", "the sleep time between batches") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .action(async (cmdObj) => { try { await genLocalState( @@ -419,6 +439,7 @@ program cmdObj.pollId, cmdObj.contract, cmdObj.privkey, + cmdObj.provider, cmdObj.endBlock, cmdObj.startBlock, cmdObj.blockPerBatch, @@ -434,7 +455,8 @@ program .command("proveOnChain") .description("prove the results of a poll on chain") .requiredOption("-o, --poll-id ", "the poll id") - .option("-q, --quiet", "whether to print values to the console", false) + .option("-q, --quiet ", "whether to print values to the console", (value) => value === "true", false) + .option("-r, --rpc-provider ", "the rpc provider URL") .option("-x, --contract ", "the MACI contract address") .option("-p, --message-processor-address ", "the message processor contract address") .option("-t, --tally-contract ", "the tally contract address") diff --git a/website/versioned_docs/version-v1.x/cli.md b/website/versioned_docs/version-v1.x/cli.md index 0af0221f9d..885b44f018 100644 --- a/website/versioned_docs/version-v1.x/cli.md +++ b/website/versioned_docs/version-v1.x/cli.md @@ -74,8 +74,6 @@ contracts can refer to the same VkRegistry as long as they are all owned (via Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js deployVkRegistry ``` @@ -83,7 +81,7 @@ node build/ts/index.js deployVkRegistry Example output: ``` -VkRegistry: 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 +[✓] VkRegistry deployed at: 0x6b5A4751307F6751E265c194244552A9995B6B3D ``` ### Coordinator: Set verifying keys @@ -98,22 +96,19 @@ TallyVotes_-->_t Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js setVerifyingKeys \ -s 10 -i 1 -m 2 -v 2 -b 1 \ -p ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey \ -t ./zkeys/TallyVotes_10-1-2_test.0.zkey \ - -k 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 ``` Example output: ``` -Generating ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey.vk.json, please wait... -Generating ./zkeys/TallyVotes_10-1-2_test.0.zkey.vk.json, please wait... -Transaction hash: 0x582631c36a4e21e0b65c3f9100c6343408c8683a36ded36fc02a9be07fa079e8 +[i] Setting verifying keys... +[i] Transaction hash: 0x6b5b2959ba5161497d5499a0f9d9c69f773cd5f9b82f80a79253797b066863e3 +[✓] Verifying keys set successfully ``` ### Coordinator: Create MACI instance @@ -121,25 +116,14 @@ Transaction hash: 0x582631c36a4e21e0b65c3f9100c6343408c8683a36ded36fc02a9be07fa0 Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ HARDHAT_CONFIG=./build/hardhat.config.js \ -node build/ts/index.js create -r 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 +node build/ts/index.js create -s 10 ``` Example output: ``` -Deploying InitialVoiceCreditProxy -Deploying Poseidon contracts -Linking Poseidon libraries to MACI -Linking Poseidon libraries to PollFactory -Linking Poseidon libraries to MessageAqFactory -Deploying MACI -Transferring PollFactory ownership to MACI -Transferring MessageAqFactory ownership to PollFactory -Initialising MACI -MACI: 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D +[✓] MACI deployed at: 0xB08CEd0f34940a3E576Cf023b287f9Db2f306a1f ``` ### Coordinator: Deploy poll @@ -147,10 +131,8 @@ MACI: 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ +HARDHAT_CONFIG=./build/hardhat.config.js \ node ./build/index.js deployPoll \ - -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D \ -pk macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 \ -t 30 -g 25 -mv 25 -i 1 -m 2 -b 1 -v 2 ``` @@ -158,10 +140,11 @@ node ./build/index.js deployPoll \ Example output: ``` -Verifier: 0x5E70a420373D6BcB1ca3D08FEeB78a2F80727B29 -Poll ID: 0 -Poll contract: 0x710FA420C3bE4bb0730265d6581BDda11087A901 -PollProcessorAndTallyer contract: 0x62C3204a98bbbd73C8fc3B8bfCDa467CB079dF47 +[i] Poll ID: 0 +[i] Poll contract: 0xB6389Da0285c7B1FC0ba352F5A1D5fb1A492a786 +[i] Message processor contract: 0xE0bF6021e023a197DBb3fABE64efA880E13D3f4b +[i] Tally contract: 0x3f21BC64076e7c9ed8695d053DCCBE6D8d5E6f43 +[i] Subsidy contract: 0xb848ef765E289762e9BE66a38006DDc4D23AeF24 ``` ### User: sign up @@ -169,18 +152,16 @@ PollProcessorAndTallyer contract: 0x62C3204a98bbbd73C8fc3B8bfCDa467CB079dF47 Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ +HARDHAT_CONFIG=./build/hardhat.config.js \ node ./build/index.js signup \ - -p macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 \ - -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D + -p macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 ``` Example output: ``` -Transaction hash: 0xcae04f618a0b45896732632121248c312cbc68584519c1e43932b110da9078bc -State index: 1 +[i] Transaction hash: 0x4c7c9f65187fcf6e243804b75555bda48cbae4c317bb312f1b9f95ac4b7697b1 +[✓] State index: 1 ``` ### User: publish message @@ -188,25 +169,54 @@ State index: 1 Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js publish \ -p macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 \ -sk macisk.2ae4f199bf3925a2407f7c775c9261f351ab861d8e9ecbb84622bdd3f6d41b08 \ - -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D \ -i 1 -v 0 -w 9 -n 1 -o 0 ``` +Example output: + +``` +[i] Transaction hash: 0xa2ab91c821bf7fa73fedcf19a5371a0f0866ae0747d22f82f1685afca0e5db49 +[i] Ephemeral private key: macisk.2631d585e46f059e4909ab35172451542ed7723a1ace120fcf49d68e27f935b0 +``` + +### (Testing only) Coordinator: Time travel + +Example usage: + +```bash +HARDHAT_CONFIG=./build/hardhat.config.js \ +node build/ts/index.js timeTravel -s 1000 +``` + +Example output: + +``` +[✓] Fast-forwarded 1000 seconds +``` + ### Coordinator: merge state tree Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ HARDHAT_CONFIG=./build/hardhat.config.js \ -node build/ts/index.js mergeSignups -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D -o 0 +node build/ts/index.js mergeSignups -o 0 +``` + +Example output: + +``` +[i] Merging state subroots 1 / 1 +[i] Transaction hash: 0xd7e7312f70831ec05bb23f23f506ef37d6ce0c2056c1b72f7bb989653d1c8a42 +[✓] Executed mergeMaciStateAqSubRoots(); gas used: 720061 +[✓] All state subtrees have been merged. +[i] Merging subroots to a main state root... +[i] Transaction hash: 0xb5e98d328b066d91e1b7aa35775fe624be446b540a00bcb4b27a02477636b569 +[✓] Executed mergeStateAq(); gas used: 1004720 ``` ### Coordinator: merge message tree @@ -214,10 +224,21 @@ node build/ts/index.js mergeSignups -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4 Example usage: ```bash -ETH_SK=0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \ -ETH_PROVIDER=http://localhost:8545 \ HARDHAT_CONFIG=./build/hardhat.config.js \ -node build/ts/index.js mergeMessages -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D -o 0 +node build/ts/index.js mergeMessages -o 0 +``` + +Example output: + +``` +[i] Merging message subroots 1 / 1 +[✓] Executed mergeMessageAqSubRoots(); gas used: 602448 +[i] Transaction hash: 0xdf9d11c6b35fcccff82dafa3aa15f760e3f7694a72b07007fbdb359d44df0bea +[✓] All message subtrees have been merged. +[i] Merging subroots to a main message root... +[✓] Executed mergeMessageAq(); gas used: 173346 +[i] Transaction hash: 0x1f18ec08fd14db90a0d1d02d1ed27c0bfd3bc138701e812c4c3382572fc4d151 +[✓] The message tree has been merged. ``` ### Coordinator: generate Maci state offchain @@ -227,23 +248,32 @@ Example usage to generate the state locally from the smart contracts events: ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js genLocalState \ - --poll-id $1 \ + --poll-id 0 \ --output localState.json \ --privkey macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \ - --num-blocks-per-request 50 + --blocks-per-batch 50 +``` + +Example output: + +``` +[i] Fetching logs from 0 till 228 and generating the offline maci state +[✓] The state has been written to localState.json ``` ### Coordinator: generate proofs Example usage: +**C++ witness parameters** + ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js genProofs -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D \ -sk macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \ -o 0 \ -t tally.json \ - -f proofs.json \ + -f proofs \ -r ~/rapidsnark/build/prover \ -wp ./zkeys/ProcessMessages_10-2-1-2_test \ -wt ./zkeys/TallyVotes_10-1-2_test \ @@ -251,25 +281,87 @@ node build/ts/index.js genProofs -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D \ -zt ./zkeys/TallyVotes_10-1-2_test.0.zkey \ ``` +**WASM Parameters** + +```bash +HARDHAT_CONFIG=./build/hardhat.config.js \ +node build/ts/index.js genProofs \ + -sk macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \ + -o 0 \ + -t tally.json \ + -f proofs \ + -zp ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey \ + -zt ./zkeys/TallyVotes_10-1-2_test.0.zkey \ + -tw ./zkeys/TallyVotes_10-1-2_test_js/TallyVotes_10-1-2_test.wasm \ + -pw ./zkeys/ProcessMessages_10-2-1-2_test_js/ProcessMessages_10-2-1-2_test.wasm \ + -w true +``` + +Example output: + +``` +[i] starting to fetch logs from block 0 +[i] Generating proofs of message processing... +[i] Progress: 1 / 1 +[i] gen processMessage proof took 17.322 seconds + +[i] Generating proofs of vote tallying... +[i] Progress: 1 / 1 +[✓] The tally commitment is correct +[i] gen tally proof took 4.951 seconds +``` + ### Coordinator: generate proofs using a local state file Example usage to generate the proofs locally from the local state file created with genLocalState: +**C++ witness parameters** + ```bash - # Intel parameters -node/build.js genProofs \ +HARDHAT_CONFIG=./build/hardhat.config.js \ +node build/ts/index.js genProofs \ --privkey macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \ - --poll-id $1 \ + --poll-id 0 \ --rapidsnark ~/rapidsnark/build/prover \ - --process-witnessgen ./zkeys/ProcessMessages_"$PROCESS_MESSAGES_PARAMS" \ - --tally-witnessgen ./zkeys/TallyVotes_"$TALLY_VOTES_PARAMS" \ - --process-zkey "$ZKEYS_DIR"/ProcessMessages_"$PROCESS_MESSAGES_PARAMS".0.zkey \ - --tally-zkey "$ZKEYS_DIR"/TallyVotes_"$TALLY_VOTES_PARAMS".0.zkey \ + --process-witnessgen ./zkeys/ProcessMessages_10-2-1-2_test \ + --tally-witnessgen ./zkeys/TallyVotes_10-1-2_test \ + --process-zkey /zkeys/ProcessMessages_10-2-1-2_test.0.zkey \ + --tally-zkey ./zkeys/TallyVotes_10-1-2_test.0.zkey \ --tally-file tally.json \ --output proofs/ \ --state-file localState.json ``` +**WASM Params** + +```bash +HARDHAT_CONFIG=./build/hardhat.config.js \ +node build/ts/index.js genProofs \ + --privkey macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \ + --poll-id 0 \ + --process-zkey ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey \ + --tally-zkey ./zkeys/TallyVotes_10-1-2_test.0.zkey \ + --tally-file tally.json \ + --output proofs/ \ + --state-file localState.json \ + -tw ./zkeys/TallyVotes_10-1-2_test_js/TallyVotes_10-1-2_test.wasm \ + -pw ./zkeys/ProcessMessages_10-2-1-2_test_js/ProcessMessages_10-2-1-2_test.wasm \ + -w true +``` + +Example output: + +``` +[i] Generating proofs of message processing... +[i] Progress: 1 / 1 +[i] gen processMessage proof took 17.053 seconds + +[i] Generating proofs of vote tallying... +[i] Progress: 1 / 1 +[✓] The tally commitment is correct +[i] gen tally proof took 4.746 seconds +``` + ### Coordinator: prove on chain Example usage: @@ -277,12 +369,23 @@ Example usage: ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js proveOnChain \ - -x 0x89962fa216d39fCcaaC11e1e462340d80ab6Cf4D \ -o 0 \ - -q 0x62C3204a98bbbd73C8fc3B8bfCDa467CB079dF47 \ -f proofs/ ``` +Example output: + +``` +[i] Submitting proofs of message processing... +[i] Transaction hash: 0xa8acf67d6520ceaf5eef8acbf4cda7f5c2657122e2a72a092b9f4503282d70b9 +[i] Progress: 1 / 1 +[✓] All message processing proofs have been submitted. +[i] Submitting proofs of vote tallying... +[i] Progress: 1 / 1 +[i] Transaction hash: 0x691687ab6fb504919859901f297cdb7d8c4d736756d2d4edf345d721bb82365b +[✓] All vote tallying proofs have been submitted. +``` + ### Anyone: verify tally Example usage: @@ -290,10 +393,16 @@ Example usage: ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js verify \ - -x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ -o 0 \ - -t tally.json \ - -q 0x62C3204a98bbbd73C8fc3B8bfCDa467CB079dF47 + -t tally.json +``` + +Example output: + +``` +[i] on-chain tally commitment: 83601b7979c13506317b58e859950e9e92e1e6d326810d89332cc13909833ec +[✓] The on-chain tally commitment matches. +[i] The on-chain tally matches the off-chain tally. ``` ## Demonstration @@ -331,7 +440,7 @@ node build/ts/index.js deployVkRegistry Output: ```bash -VkRegistry: 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 +[✓] VkRegistry deployed at: 0x7607Cfe2fA0d62F725537e55d83C693Cc3C76EF2 ``` ### Coordinator: Set verifying keys @@ -339,7 +448,6 @@ VkRegistry: 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js setVerifyingKeys \ - --vk_registry 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 \ --state-tree-depth 10 \ --int-state-tree-depth 1 \ --msg-tree-depth 2 \ @@ -352,70 +460,56 @@ node build/ts/index.js setVerifyingKeys \ Output: ```bash -Setting verifying keys... -Transaction hash: 0x16236fe5e124f3d0c33ddf20a37ceba9730a659630258a1e858b3e335e057b8e +[i] Setting verifying keys... +[i] Transaction hash: 0xbd5d06935537fb59903c27b9bdb19a41d422f75e1dfd6eb61f028bf3a7b82c76 +[✓] Verifying keys set successfully ``` ### Coordinator: Create MACI instance ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ -node build/ts/index.js create \ - --vk-registry 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 +node build/ts/index.js create -s 10 ``` Output: ```bash -Deploying InitialVoiceCreditProxy -Deploying Poseidon contracts -Linking Poseidon libraries to MACI -Linking Poseidon libraries to PollFactory -Linking Poseidon libraries to MessageAqFactory -Deploying MACI -Transferring PollFactory ownership to MACI -Transferring MessageAqFactory ownership to PollFactory -Initialising MACI -MACI: 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a +[✓] MACI deployed at: 0xC131D3eeD9D6D410A7bfc200d81b9795f1bb5ed6 ``` ### Coordinator: Deploy poll ```bash +HARDHAT_CONFIG=./build/hardhat.config.js \ node ./build/index.js deployPoll \ - --maci-address 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ - --pubkey macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 \ - --duration 1000 \ - --max-messages 25 \ - --max-vote-options 25 \ - --int-state-tree-depth 1 \ - --msg-tree-depth 2 \ - --msg_batch_depth 1 \ - --vote-option-tree-depth 2 + -pk macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 \ + -t 1000 -g 25 -mv 25 -i 1 -m 2 -b 1 -v 2 ``` Output: ```bash -Verifier: 0x0d8cc4b8d15D4c3eF1d70af0071376fb26B5669b -Poll ID: 0 -Poll contract: 0x08e8f54262de52fe7Dfd0Bc0C9Ea87689d70e985 -PollProcessorAndTallyer contract: 0xEcFcaB0A285d3380E488A39B4BB21e777f8A4EaC +[i] Poll ID: 0 +[i] Poll contract: 0x2c3Adf2852788662148038511aD80962aaf631D7 +[i] Message processor contract: 0xd3C3C6530fE4073292D6EAfdEAdEeAbf1A3DC19B +[i] Tally contract: 0x06c1939F6cBb68D42333F140CAE815cc36D341b0 +[i] Subsidy contract: 0xCB74254716c96B07c812c73A5945e68aa1de4569 ``` ### Alice: sign up ```bash +HARDHAT_CONFIG=./build/hardhat.config.js \ node ./build/index.js signup \ - --pubkey macipk.3e7bb2d7f0a1b7e980f1b6f363d1e3b7a12b9ae354c2cd60a9cfa9fd12917391 \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a + --pubkey macipk.3e7bb2d7f0a1b7e980f1b6f363d1e3b7a12b9ae354c2cd60a9cfa9fd12917391 ``` Output: ```bash -Transaction hash: 0xcdff1e0cd3021cdc3ba2c65cfd74bac3715c32efdd2052c0e8f3a677a81a758b -State index: 1 +[i] Transaction hash: 0x7ab4c2d23686049432d19bb64c8ee4e8776fff134d971dcf27e1f513b4fdb97f +[✓] State index: 1 ``` ### Alice: votes for Party A (option index 0) @@ -425,7 +519,6 @@ HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js publish \ --pubkey macipk.3e7bb2d7f0a1b7e980f1b6f363d1e3b7a12b9ae354c2cd60a9cfa9fd12917391 \ --privkey macisk.fd7aa614ec4a82716ffc219c24fd7e7b52a2b63b5afb17e81c22fe21515539c \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ --state-index 1 \ --vote-option-index 0 \ --new-vote-weight 9 \ @@ -436,8 +529,8 @@ node build/ts/index.js publish \ Output: ```bash -Transaction hash: 0xc0964069834b171bb698ffc61e31e1be456c740ff1967ccad7d8cd8ed362e545 -Ephemeral private key: macisk.1bf4bba7086c213606bb4a775b1ceaa4c2e7119c329748e675375f0d79c900dc +[i] Transaction hash: 0x60936cfb0b25c8618d3cb8d0f5497106d5f6e3776f3212932975442d874eddbd +[i] Ephemeral private key: macisk.103b8c4c98700d06f47522892032fce54bd03cd197cee495ede3802730409910 ``` ### Alice: submits an invalid vote for Party B (option index 1) with different public key @@ -447,7 +540,6 @@ HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js publish \ --pubkey macipk.d5788ea6ccf1ec295df99aaef859031fe7bd359e7e03acb80eb6e8a192f2ce19 \ --privkey macisk.fd7aa614ec4a82716ffc219c24fd7e7b52a2b63b5afb17e81c22fe21515539c \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ --state-index 1 \ --vote-option-index 1 \ --new-vote-weight 9 \ @@ -458,60 +550,60 @@ node build/ts/index.js publish \ Output: ```bash -Transaction hash: 0xc13b97e23b387d8c160e0f8b1bfb33dc0ff4441fe63a37f0fc3ec84a0cfa0600 -Ephemeral private key: macisk.5bc9f217a29c5defad1ca9be3d649add1eca30037589527476e8335b24cf75b +[i] Transaction hash: 0x73f74b13d276cd311ce5421a145debc71e97e48abc8be2f9a0a548b26f7920f9 +[i] Ephemeral private key: macisk.1e490d67477b4c5f08806973fca2bea81e723c60deba6bdeacab56f7a4bd867b ``` -Time Travel +### Coordinator: Time Travel +```bash +HARDHAT_CONFIG=./build/hardhat.config.js \ +node build/ts/index.js timeTravel -s 1000 ``` -node build timeTravel -s 1000 + +Output: + +``` +[✓] Fast-forwarded 1000 seconds ``` ### Coordinator: merge state tree ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ -node build/ts/index.js mergeSignups \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ - --poll-id 0 +node build/ts/index.js mergeSignups --poll-id 0 ``` Output: ```bash -Merging state subroots 1 / 1 -Executed mergeMaciStateAqSubRoots(); gas used: 723525 -Transaction hash: 0x14621b208fdadbf277edf80b393f1a9694099ae9676903e148fa485eecfadd4b - -All state subtrees have been merged. -Merging subroots to a main state root... -Executed mergeStateAq(); gas used: 1015876 -Transaction hash: 0xf2903b1c3c83b87c551a71f29e07762b464691ca58b0c6849b2f9b8f5783011f -The state tree has been merged. +[i] Merging state subroots 1 / 1 +[i] Transaction hash: 0xd01932e8dfad251f9b0d288290ac17f12bc449ea859a6921f63edf6b4b06f4c9 +[✓] Executed mergeMaciStateAqSubRoots(); gas used: 720061 +[✓] All state subtrees have been merged. +[i] Merging subroots to a main state root... +[i] Transaction hash: 0x25f60a9b5a24d11b87c41d8a4f681e3fd895b3bdf78ea86755b9800005662ce6 +[✓] Executed mergeStateAq(); gas used: 1004720 ``` ### Coordinator: merge message tree ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ -node build/ts/index.js mergeMessages \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ - --poll-id 0 +node build/ts/index.js mergeMessages --poll-id 0 ``` Output: ```bash -Merging message subroots 1 / 1 -Executed mergeMaciStateAqSubRoots(); gas used: 604387 -Transaction hash: 0xe0c0306b80febe1f6947b6ccbefabef38d01abce0b7611f49ce1cc7e20f196a5 - -All message subtrees have been merged. -Merging subroots to a main message root... -Executed mergeMessageAq(); gas used: 174376 -Transaction hash: 0x424581f08d5f8e9f4fd63b083f9446cc2bff3b8e4b67ebc834076d6e9c34ec20 -The message tree has been merged. +[i] Merging message subroots 1 / 1 +[✓] Executed mergeMessageAqSubRoots(); gas used: 600520 +[i] Transaction hash: 0xac0e8a01277db1b6282f8fb3763a8a4aeeebb3e12a41dd0dee9fc2804a4c9e81 +[✓] All message subtrees have been merged. +[i] Merging subroots to a main message root... +[✓] Executed mergeMessageAq(); gas used: 173346 +[i] Transaction hash: 0x472f0fd515c7cd2a02c430189e4ee92a6843bd6b19807484ce454cb7dab0e931 +[✓] The message tree has been merged. ``` ### Coordinator: generate proofs @@ -519,31 +611,28 @@ The message tree has been merged. ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js genProofs \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ --privkey macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \ --poll-id 0 \ - --tally-file tally.json \ - --output proofs \ - --rapidsnark ~/rapidsnark/build/prover \ - --process-witnessgen ./zkeys/ProcessMessages_10-2-1-2_test \ - --tally-witnessgen ./zkeys/TallyVotes_10-1-2_test \ --process-zkey ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey \ - --tally-zkey ./zkeys/TallyVotes_10-1-2_test.0.zkey + --tally-zkey ./zkeys/TallyVotes_10-1-2_test.0.zkey \ + --tally-file tally.json \ + --output proofs/ \ + -tw ./zkeys/TallyVotes_10-1-2_test_js/TallyVotes_10-1-2_test.wasm \ + -pw ./zkeys/ProcessMessages_10-2-1-2_test_js/ProcessMessages_10-2-1-2_test.wasm \ + -w true ``` Output: ```bash -fromBlock = 0 -Generating proofs of message processing... - -Progress: 1 / 1 - -Generating proofs of vote tallying... - -Progress: 1 / 1 +[i] Generating proofs of message processing... +[i] Progress: 1 / 1 +[i] gen processMessage proof took 16.644 seconds -OK +[i] Generating proofs of vote tallying... +[i] Progress: 1 / 1 +[✓] The tally commitment is correct +[i] gen tally proof took 4.809 seconds ``` ### Coordinator: prove on chain @@ -551,26 +640,21 @@ OK ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js proveOnChain \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ --poll-id 0 \ - --ppt 0xEcFcaB0A285d3380E488A39B4BB21e777f8A4EaC \ --proof-dir proofs/ ``` Output: ```bash -Submitting proofs of message processing... -Transaction hash: 0x59388e69899612390ef22de235629e9355e14f888bb330b46511cc06d8f2035d -Progress: 1 / 1 -All message processing proofs have been submitted. - -Submitting proofs of vote tallying... -Progress: 1 / 1 -Transaction hash: 0xc90e3bd0618def86b709c995485271f806c60701a3f4246903498f27346b9f5e -All vote tallying proofs have been submitted. - -OK +[i] Submitting proofs of message processing... +[i] Transaction hash: 0x9c3280af80de2436f9a886e4cd94218e01fe35ea3d3e671aad97b5aa5d6108ed +[i] Progress: 1 / 1 +[✓] All message processing proofs have been submitted. +[i] Submitting proofs of vote tallying... +[i] Progress: 1 / 1 +[i] Transaction hash: 0x3e82ae3ad04215d4f357455ab5a610eba082796d2abc698aad91b046d16b9350 +[✓] All vote tallying proofs have been submitted. ``` ### Anyone: verify @@ -578,44 +662,13 @@ OK ```bash HARDHAT_CONFIG=./build/hardhat.config.js \ node build/ts/index.js verify \ - --contract 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \ --poll-id 0 \ - --tally-file tally.json \ - --ppt 0xEcFcaB0A285d3380E488A39B4BB21e777f8A4EaC + --tally-file tally.json ``` Output: ```bash -{ - provider: 'http://localhost:8545', - maci: '0xf204a4Ef082f5c04bB89F7D5E6568B796096735a', - pollId: 0, - newTallyCommitment: '0x29b47e79c10709047ba9788580c2dc8528f003eab42d30670df78a47b121aa6c', - results: { - tally: [ - '9', '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', '0', - '0' - ], - salt: '0x132065c8ad3968008aeb7c114a04de228fa5b3618743ad00f64ad3f773a2e4d2' - }, - totalSpentVoiceCredits: { - spent: '81', - salt: '0x2940f93e085350a04f6ff85e1ebffbc391fc3498f1cb41ab47f8899dc9c6efc6' - }, - perVOSpentVoiceCredits: { - tally: [ - '81', '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', '0', - '0' - ], - salt: '0x2db5c3d6b015f8e2ea1cf7ffed7a44af0db8a8c09a5077415c076b6ebcee0571' - } -} -OK +[i] on-chain tally commitment: 1ed004ac21a5397a512cbe749e7110934a434837f4818265043fd2e2e9cbec91 +[✓] The on-chain tally commitment matches. ```