Circom Compilation Pipeline
Verify a Circom/SnarkJS circuit verifier already deployed on chain
A circuit verifier is verified on Circuitscan by submitting its original source code along with all the compilation options. On Circuitscan’s servers, the source is compiled into its R1CS, the appropriate PTAU file is downloaded, the final ZKey is verified on Groth16 verifiers with a second-phase trusted setup, and finally the Solidity verifier source is compared against what is retrieved for the contract address from the block explorer.
Small differences in the Solidity sources are allowed:
The errant hardhatc/console.sol include on PLONK verifiers may be omitted
Contract name
pragma solidityversion differencesComment differences
Whitespace differences
Usage: circuitscan verify:circom [options] <mainCircomFile> <chainId> <verifierContractAddress>
Verify verifier contracts by their circom sources. Can also specify chain by name.
Options:
-p, --protocol <protocol> Specify the protocol: groth16 (default), fflonk, plonk (overrides circomkit.json if available)
-k, --proving-key <provingKey> Specify the proving key filename or url (optional, for Groth16 trusted setups). Must be https hosted if >6 MB
-t, --ptau <ptauSize> Force a specific Powers of Tau size (8-28 or url to download specific file)
-v, --circom-version <circomVersion> Specify the Circom version (e.g. "v2.1.8")
-s, --snarkjs-version <snarkjsVersion> Specify the SnarkJS version (e.g. "0.7.3")
-i, --instance <memorySize> Specify the memory (GB) of compiler instance: 4, 8, 16, 32, 64, 128, 256, 384, 512 (default: 4 for smallest circuits)
-r, --resume <requestId> In case of errors during compilation, reattach to a job and attempt a new verification. Overrides all other options.
-c, --config <configUrl> Specify a different configuration file (default: https://circuitscan.org/cli.json)
-a, --api-key <apiKey> Specify your API Key as a command line argument
-h, --help display help for command
Verification Checklist
Locate the Circom source file with the main component
(e.g.
circuit/multiplier.circom)If the verifier uses Groth16, locate the proving key (final zkey) and, if necessary, upload it to a server where it can be accessed using an HTTPS URL.
(e.g.
https://example.com/multiplier.zkey)Specifying this is not necessary for Plonk or Fflonk verifiers.
Ensure the verifier contract has been verified on Sourcify or Etherscan
Determine the Circom and SnarkJS versions that were used to compile the circuit and generate the verifier contract
Select an instance size by estimating the amount of memory needed
(see the build output of other circuits on Circuitscan for examples)
You are now ready to invoke the Circuitscan CLI:
circuitscan verify:circom \ circuit/multiplier.circom \ sepolia \ 0x9999999999999999999999999999999999999999 \ -k https:/example.com/multiplier.zkey \ -v v2.1.9 \ -s 0.7.4 \ -i 64
Compile a Circom circuit and deploy its circuit verifier on chain
Alternatively, the CLI can be used to compile and deploy the circuit verifier directly from source, ensuring that the verification happens smoothly.
Note
The DEPLOYER_PRIVATE_KEY environment variable and chainId argument must be set to use the deploy command unless the -b or --browser-wallet argument is used.
Usage: circuitscan deploy:circom [options] <mainCircomFile> [chainId]
Deploy verifier contract by their circom sources. Can also specify chain by name.
Options:
-p, --protocol <protocol> Specify the protocol: groth16 (default), fflonk, plonk (overrides circomkit.json if available)
-k, --proving-key <provingKey> Specify the proving key filename or url (optional, for Groth16 trusted setups). Must be https hosted if >6 MB
-t, --ptau <ptauSize> Force a specific Powers of Tau size (8-28 or url to download specific file)
-v, --circom-version <circomVersion> Specify the Circom version (e.g. "v2.1.8")
-s, --snarkjs-version <snarkjsVersion> Specify the SnarkJS version (e.g. "0.7.3")
-i, --instance <memorySize> Specify the memory (GB) of compiler instance: 4, 8, 16, 32, 64, 128, 256, 384, 512 (default: 4 for smallest circuits)
-r, --resume <requestId> In case of errors during compilation, reattach to a job and attempt a new deploy. Overrides all other options.
-c, --config <configUrl> Specify a different configuration file (default: https://circuitscan.org/cli.json)
-a, --api-key <apiKey> Specify your API Key as a command line argument
-b, --browser-wallet Send transaction in browser instead of by passing private key env var (overrides chainId argument)
-h, --help display help for command
Deployment Checklist
Locate the Circom source file with the main component
(e.g.
circuit/multiplier.circom)If the verifier uses Groth16, locate the proving key (final zkey) and, if necessary, upload it to a server where it can be accessed using an HTTPS URL.
(e.g.
https://example.com/multiplier.zkey)If this is omitted for Groth16 verifiers, a random entropy value will be used.
Specifying this is not necessary for Plonk or Fflonk verifiers.
Select the Circom and SnarkJS versions to use to compile the circuit and generate the verifier contract
Select an instance size by estimating the amount of memory needed
(see the build output of other circuits on Circuitscan for examples)
You are now ready to invoke the Circuitscan CLI.
The
-boption is recommended for ease-of-use.circuitscan deploy:circom \ circuit/multiplier.circom \ -b \ -v v2.1.9 \ -s 0.7.4 \ -i 16
Verify a Circom Groth16 multi-verifier already deployed on chain
Circuitscan also supports combining multiple Groth16 verifiers into one verification contract.
This is inspired by Semaphore V4 and is supported using the snarkjs-groth16-multi-verifier NPM package.
All of the individual verifiers must be verified already on Circuitscan, then you must craft a JSON file containing all of the verifiers in order of their inclusion.
Usage: circuitscan verify:circom-multi [options] <jsonFile>
Verify a Groth16 multi-verifier using a JSON specification. See docs website for details.
Options:
-c, --config <configUrl> Specify a different configuration file (default: https://circuitscan.org/cli.json)
-h, --help display help for command
The following example JSON describes Semaphore V4 deployed on Sepolia:
{
"verifiers": [
{ "chainId": 17000, "address": "0xf24a641276ca49e9984124ddf52df4b0d40e63a3" },
{ "chainId": 17000, "address": "0x467d5a506f0dcfbffaa403656ed1cc1477d657eb" },
{ "chainId": 17000, "address": "0x3e950933555243561f28da3c6a0a515639fe7026" },
{ "chainId": 17000, "address": "0xc174d9b265bf99c5aef393c44a18c9703bef1fa1" },
{ "chainId": 17000, "address": "0x7e5e5cbf5533a22ba58b1c7d7a0ad015c2278eac" },
{ "chainId": 17000, "address": "0x8a8817162b13f1856b6ba4d52abade5428b262f0" },
{ "chainId": 17000, "address": "0xebc1535fe0816c8ee6dbd2474b0ad51934bbe030" },
{ "chainId": 17000, "address": "0xa9bced3e075025dd3751c6cef5e349fbb0278acb" },
{ "chainId": 17000, "address": "0x39374372f3ca97b800e47f747c2fb26440609d13" },
{ "chainId": 17000, "address": "0xfdcfd9f5fc0be0e5f93710bd3d53b6a32fe1f580" },
{ "chainId": 17000, "address": "0x7902dadca10ddda38b768b68a6082f152081d5b3" },
{ "chainId": 17000, "address": "0x56e23ddc0ab53aea6447e8f08eafa9607f483f53" },
{ "chainId": 17000, "address": "0x94e1698410614dab6fd34a14ed06d6b6b2cdefd1" },
{ "chainId": 17000, "address": "0xfc05984d8aa48f4c334ee5eac92f408becf4a867" },
{ "chainId": 17000, "address": "0x9e0f76dd17518b1b4cbae2472bf3d549e469034c" },
{ "chainId": 17000, "address": "0x1fef2d460156d914bf5fb1569d9678979cd42a82" },
{ "chainId": 17000, "address": "0x26f56a11ac9bd2f4a243b03e8875f5b797b07af8" },
{ "chainId": 17000, "address": "0x72feeb885599c74fe041c582c3da3e14214cf106" },
{ "chainId": 17000, "address": "0x3c2ca19e80428f7e19808859483a08cf07476722" },
{ "chainId": 17000, "address": "0x445e9b1b1f0feafad68608d1def398bad3e69018" },
{ "chainId": 17000, "address": "0x3df122cdfcced4b07990f38a2e2cc992a942af31" },
{ "chainId": 17000, "address": "0xdccf1079fa92acd45ab3e30637aa84c4e36ea21e" },
{ "chainId": 17000, "address": "0x5dccc38aa2752ac3e09ead06d51285736b3c1096" },
{ "chainId": 17000, "address": "0xce3f1fd94ab9760b24cf06bf128b86b8926f7b74" },
{ "chainId": 17000, "address": "0xb75859fe64e04bdabe93eed006f925a1089694f1" },
{ "chainId": 17000, "address": "0xad8ff16a45f41151415a0680d0a26fd856402bce" },
{ "chainId": 17000, "address": "0xa23905de7bafac05d3e7028c6d87538445da8b43" },
{ "chainId": 17000, "address": "0xe0b9a7bd7e0746791874d7535afb9271b03e259e" },
{ "chainId": 17000, "address": "0x990f37c12e2138aaefc05089b50459c870739825" },
{ "chainId": 17000, "address": "0xbd0feed838293123b27d329dca5e1610698afd4c" },
{ "chainId": 17000, "address": "0xe516cc1ce72ae1124c277b92755bdceebe745f75" },
{ "chainId": 17000, "address": "0x25cd28fca2474604e2bc1bbc835071de739b6bcf" }
],
"offset": 1,
"deployed": {
"chainId": 11155111,
"address": "0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043"
},
"modifier": "semaphorev4"
}
verifiers
Required An array of at least two verifiers already verified on Circuitscan
offset
Required The starting index of the first verifier for the new argument added to the the contract’s verifyProof() function
deployed
Required The address and chain of the deployed multi-verifier contract
modifier
Optional To account for greater variation in deployed multi-verifiers, Circuitscan supports additional modifications to the Solidity source code.
Available modifiers: semaphorev4
Submit new modifiers as PRs to this directory: circuitscan/server/modifiers
Command Line Arguments
-p, --protocol
Specify the protocol of the verifier. If ommitted, groth16 is used.
Allowed values:
groth16(Default)fflonkplonk
This value will be retrieved from circomkit.json if it exists in the current directory or a parent directory.
-k, --proving-key
Specify the final ZKey proving key for groth16 verifiers.
For proving keys under 6 MB, you may pass the filename and it will be uploaded as part of your request but this is not recommended since it does not reveal how each contribution was made.
“Without attestations, you can just replace all the contributions with your own, fully knowing the toxic waste, allowing you to create fake proofs”
Therefore, it is recommended to use a final ZKey HTTPS URL from the PSE P0tion DefinitelySetup website to display verified Groth16 Trusted Setup status on the circuit verifier details page.
If you deploy a groth16 circuit verifier using this CLI but do not specify a proving key, Circuitscan will generate a second-phase setup with a random 32 bytes of entropy. Although this value is discarded and is theoretically secure, P0tion provides greater assurance of security because it does not rely on trusting Circuitscan’s infrastructure.
-t, --ptau
If omitted, Circuitscan will use the smallest Powers of Tau file from the Polygon zkEVM/hermez ceremony that fits the circuit based on the number of constraints.
If passing a number between 8 and 28, the specific Ptau file from the hermez ceremony will be downloaded.
Otherwise, pass an https url for the Ptau file you would like to use.
Another commonly used Ptau ceremony is the PSE P0tion PPoT Trusted Setup Ceremony. Pass one of these urls if using P0tion for the second-phase trusted setup.
-v, --circom-version
Pass the version of the Circom compiler to use.
Allowed values:
v2.2.3v2.2.2v2.2.1v2.2.0v2.1.9v2.1.8(Default)v2.1.7v2.1.6v2.1.5v2.1.4v2.1.3v2.1.2v2.1.1v2.1.0v2.0.9v2.0.8
-s, --snarkjs-version
Pass the version of SnarkJS to use.
Allowed values:
0.7.60.7.50.7.4(Default)0.7.30.7.20.7.10.7.00.6.11
-i, --instance
Compilations are performed on a cloud machine with the specified number of GB of memory.
Please use the smallest value necessary to compile your circuits. Abuse of large instances will result in your account being banned.
Allowed values: 4, 8, 16, 32, 64, 128, 256, 384, 512, 768, 1536
If ommitted, the smallest instance size is used: 4 GB.
-r, --resume
Some circuits take a long time to compile and it may not be feasible to have your local machine connected and waiting for the entire duration.
By taking note of the request ID output at the start of a deploy or verify command, you can close out of the process at any time before compilation completes and restart the process later.
In addition to helping with long running jobs or spotty internet connections, this allows verifying the same circuit verifier it accross multiple deployments without waiting for another compilation.
This argument may also be used to re-use a compilation output if the wrong chain/contract address is passed without waiting to compile again.
Request IDs are stored in ~/.circuitscan-history for easy recovery from errors.
-c, --config
This argument is only used when connecting your CLI to a different (e.g. self-hosted) instance of Circuitscan.
There is no reason to use this argument when verifying or deploying circuits to circuitscan.org.
-a, --api-key
Overrides API key settings from either the CIRCUITSCAN_API_KEY environment variable, or the ~/.circuitscan JSON user configuration.
-b, --browser-wallet
For the deploy:circom command, this argument may be used instead of specifying the DEPLOYER_PRIVATE_KEY environment variable.
A link will be provided after the circuit compiles where you will be able to connect your wallet and deploy the verifier contract.
After your contract is deployed, the verification process will continue in your terminal.
This is a recommended option for desktop use of the Circuitscan CLI. If using in a CI/CD environment, the environment variable provides headless operation.
Additional Configuration
A few more circuit configuration options are available if passed using a circomkit.json file.
The CLI will search parent directories for this file. If found, the CLI will consider that directory as the environment root, searching for dependencies from that directory.
Learn more about Circomkit…
optimization
Set the Circom compiler optimization level. (Default: 2)
include
Specify an array of strings denoting other directories to search for included files.
If your circuit’s dependencies are not found by the CLI, create a circomkit.json file in the directory that contains your node_modules directory.
echo '{"include":["node_modules"]}' >> circomkit.json
prime
Specify a prime value other than the default bn128.
Other primes require specifying a PTAU file that matches that prime.
protocol
The protocol may also be specified here instead of by CLI argument.
cWitness
Specify true to output C witness generator circom --c
wasmWitness
Specify false to skip outputting WASM witness generator circom --wasm (output by default)
Verification Errors
invalid_diff
The generated Solidity verifier contract does not match the source code retrieved from the block explorer
Find the generated source at https://circuitscan-artifacts.s3.us-west-2.amazonaws.com/build/<build-name-adjective-animal>/verifier.sol
contract_not_verified
The contract at this address on the specified is not verified on Sourcify/Blockscout/Etherscan.
Please submit the source to Sourcify.dev
invalid_finalZkey
The final zkey/proving key you specified does not match the r1cs/ptau.