Instalation
On Linux
mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \
echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \
source ~/.bashrc
On MacOs Apple Silicon
mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-aarch64-apple-darwin.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \
echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \
source ~/.zshrc
On MacOs Intel
mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-apple-darwin.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \
echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \
source ~/.zshrc
Generate a proof
Generate a new noir project and prepare it to receive the prover inputs.
nargo new hello_world
cd hello_world
nargo check
Now put the inputs in Prover.toml
and generate the proof.
Prover.toml
x = "1"
y = "2"
nargo prove
The proof is now located at proofs/hello_world.proof
.
Verify the proof
Generate the solidity verifier.
nargo codegen-verifier
The verifier contract is now located at contract/hello_world/plonk_vk.sol
. Deploy it and send it's address as param to the following contract with custom logic.
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface INoirVerifier {
function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool);
}
contract NoirCustomLogic {
INoirVerifier public noirVerifier;
uint public publicInput;
constructor(address noirVeriferAddress) {
noirVerifier = INoirVerifier(noirVeriferAddress);
}
function sendProof(bytes calldata _proof, bytes32[] calldata _publicInputs) public {
// ZK verification
noirVerifier.verify(_proof, _publicInputs);
// Your custom logic
publicInput = uint(_publicInputs[0]);
}
}
Nullifier
Circuit
use dep::std;
fn main(x: Field, y: pub Field) -> pub Field {
assert(x != y);
let hash = std::hash::pedersen_hash([x, y]);
hash
}
nargo prove
nargo codegen-verifier
Solidity
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface INoirVerifier {
function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool);
}
contract NoirCustomLogic {
INoirVerifier public noirVerifier;
uint public publicInput;
mapping(bytes32 => bool) public nullifiers;
constructor(address noirVeriferAddress) {
noirVerifier = INoirVerifier(noirVeriferAddress);
}
function sendProof(bytes calldata _proof, bytes32[] calldata _publicInputs) public {
// ZK verification
noirVerifier.verify(_proof, _publicInputs);
// Your custom logic
require(!nullifiers[_publicInputs[1]], "Proof already nullified");
publicInput = uint(_publicInputs[0]);
nullifiers[_publicInputs[1]] = true;
}
}
Advanced zkDapp Demo
- Metamask compatibility
- Anonimity set merkle tree
- Node.js relayer
- Prover in browser
Github repo here.