A hardhat template repository for developing noir (zk) circuits.
Click the Use this template button at the top of this repository to create a new repository from this template.
You'll need:
- Noir (nargo CLI - Installation steps can be found here).
- Node Package Manager (npm, yarn, pnpm, etc. - whatever suits - so long as you can run
hardhaton your CLI).
Once you've cloned the repo, run:
# using yarn - or use npm or pnpm
yarn installto install all necessary packages.
I made this repository as I was having trouble getting a hardhat project to work with noir - so I thought I'd make a template repository to help others get started. The connectivity circuit example within this template is an example of how to write a very basic circuit, compile and test it using BarretenbergWasm from within hardhat, and have the ability to turn it into a contract that can be tested as part of a hardhat project.
Most of this repository contains boilerplate code that can be removed (contents of circuits/, deploy/, contracts/ and test/ primarily).
If you want to create a new circuit (zk program), from the circuits/ directory, run:
nargo new <circuit_name>where <circuit_name> is the name of your circuit.
So, say we run nargo new myCircuit, we should now have the following files at circuits/myCircuit/:
.
├── src
│ └── main.nr # the main circuit file
└── Nargo.toml # the .toml specification for that noir circuitYou can then write your circuit in src/main.nr - and once you're done, you can compile it using:
nargo checkThis will add 2 new files, Prover.toml and Verifier.toml to your circuits/myCircuit/ directory, like so:
.
├── src
│ └── main.nr # the main circuit file
├── Nargo.toml # the .toml specification for that noir circuit
├── Prover.toml # where the inputs to generate a proof for your circuit go
└── Verifier.toml # where the output of a proof goes to be used in a verificationAs the default Prover.toml and Verifier.toml files are empty, you'll need to add some example inputs to get them working. The default main.nr circuit generated by nargo new just accepts 2 inputs, x and y, and ensures that x != y. If this condition is met - it outputs a verification proof, and if it's not met - nargo will throw an error. You can try this by setting the contents of Prover.toml like so:
x = "1"
y = "2"
and then to generate a proof - run:
nargo prove pThis will generate a proof target directory for your circuit, as well as output a proof to Verifier.toml - which you can then use to verify your proof using:
nargo verify pIf all goes well, the CLI won't output anything. If it output something - something has gone wrong.
This is a very simple example of a proof - but this should be enough to demonstrate the general proof/verification process. To read more on noir's commands - check out the nargo CLI docs.
Once you've got this circuit created - you can use this templates returnCircuitTestingAPI() util to get a testing API for your circuit in hardhat, like so:
const { barretenberg, pedersen, boardCircuit, acir, prover, verifier } =
await returnCircuitTestingAPI("myCircuit");And you're ready to test this circuit in hardhat. See the test/connectivity.test.ts file for an example of how to use both this function and these variables in hardhat, evaluating the simple circuits/connectivity/src/main.nr circuit included in this template.
It's more efficient to evaluate your proofs firstly using wasm/ts tests first - but once you've done that it's time to turn your circuit into a contract.
You can use this repo's create-circuit-contract hardhat task to this for you, and rename it to a more specific contract name (e.g. myCircuitVerifier.sol) to allow for nicer deployment scripts. To use this task with our above example (our myCircuit circuit), you'd run:
npx hardhat create-circuit-contract --circuit myCircuit
This will generate your Circuit contract file for you using nargo - but move it into your contracts/ directory and rename it to be your circuit name + Verifier.sol (e.g. MyCircuitVerifier.sol), as well as rename the actual contract from TurboVerifier (nargo default) to MyCircuitVerifier.
Alternatively - you can just use nargo to generate a plonk_vk.sol contract instead (using our example myCircuit from above):
cd circuits/myCircuit
nargo codegen-verifier
This will create a plonk_vk.sol file at circuits/myCircuit/contracts/ which you can then use in your hardhat project.
Any issues or features you'd like, hit me up, otherwise, happy hacking :)