name: zk-circuits
description: 使用 Circom 和 Noir 语言进行零知识电路开发。支持约束优化、ZK友好型密码学原语、证明生成(Groth16、PLONK)以及默克尔树实现。
allowed-tools: Read, Grep, Write, Bash, Edit, Glob, WebFetch
ZK 电路开发技能
使用 Circom 和 Noir 进行零知识电路开发,用于隐私保护应用和 zkRollups。
能力
- Circom 电路:编写 Circom 模板和组件
- Noir 程序:开发 Noir ZK 应用
- 约束优化:最小化电路约束
- ZK 原语:使用 Poseidon、MiMC 和 Pedersen 哈希
- 证明系统:生成 Groth16 和 PLONK 证明
- 信号设计:设计高效的电路输入/输出
- 默克尔树:实现成员资格和非成员资格证明
- 见证生成:创建高效的见证计算器
Circom 开发
安装
# 安装 Circom
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
git clone https://github.com/iden3/circom.git
cd circom
cargo build --release
cargo install --path circom
# 安装 snarkjs
npm install -g snarkjs
# 验证
circom --version
snarkjs --version
基础电路
pragma circom 2.1.6;
// 简单加法电路
template Addition() {
// 公共输入
signal input a;
signal input b;
// 输出(默认为公共)
signal output c;
// 约束
c <== a + b;
}
component main = Addition();
乘法器电路
pragma circom 2.1.6;
template Multiplier(n) {
signal input in[n];
signal output out;
signal intermediate[n];
intermediate[0] <== in[0];
for (var i = 1; i < n; i++) {
intermediate[i] <== intermediate[i-1] * in[i];
}
out <== intermediate[n-1];
}
component main {public [in]} = Multiplier(3);
哈希电路(Poseidon)
pragma circom 2.1.6;
include "circomlib/circuits/poseidon.circom";
template HashPreimage() {
signal input preimage;
signal input hash;
component hasher = Poseidon(1);
hasher.inputs[0] <== preimage;
// 验证哈希
hash === hasher.out;
}
component main {public [hash]} = HashPreimage();
默克尔树成员资格证明
pragma circom 2.1.6;
include "circomlib/circuits/poseidon.circom";
include "circomlib/circuits/mux1.circom";
template MerkleProof(levels) {
signal input leaf;
signal input root;
signal input pathElements[levels];
signal input pathIndices[levels];
component hashers[levels];
component mux[levels];
signal levelHashes[levels + 1];
levelHashes[0] <== leaf;
for (var i = 0; i < levels; i++) {
hashers[i] = Poseidon(2);
mux[i] = Mux1();
mux[i].c[0] <== levelHashes[i];
mux[i].c[1] <== pathElements[i];
mux[i].s <== pathIndices[i];
hashers[i].inputs[0] <== mux[i].out;
hashers[i].inputs[1] <== levelHashes[i] + pathElements[i] - mux[i].out;
levelHashes[i + 1] <== hashers[i].out;
}
root === levelHashes[levels];
}
component main {public [root]} = MerkleProof(20);
Circom 构建流程
# 编译电路
circom circuit.circom --r1cs --wasm --sym -o build
# 生成见证
node build/circuit_js/generate_witness.js build/circuit_js/circuit.wasm input.json witness.wtns
# Powers of Tau 仪式(一次性)
snarkjs powersoftau new bn128 14 pot14_0000.ptau
snarkjs powersoftau contribute pot14_0000.ptau pot14_0001.ptau
snarkjs powersoftau prepare phase2 pot14_0001.ptau pot14_final.ptau
# 生成证明密钥(Groth16)
snarkjs groth16 setup build/circuit.r1cs pot14_final.ptau circuit_0000.zkey
snarkjs zkey contribute circuit_0000.zkey circuit_final.zkey
# 导出验证密钥
snarkjs zkey export verificationkey circuit_final.zkey verification_key.json
# 生成证明
snarkjs groth16 prove circuit_final.zkey witness.wtns proof.json public.json
# 验证证明
snarkjs groth16 verify verification_key.json public.json proof.json
# 生成 Solidity 验证器
snarkjs zkey export solidityverifier circuit_final.zkey Verifier.sol
Noir 开发
安装
# 安装 Noir(Nargo)
curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash
noirup
# 验证
nargo --version
基础 Noir 程序
// src/main.nr
fn main(x: Field, y: pub Field) {
assert(x != y);
}
哈希验证
use dep::std::hash::pedersen_hash;
fn main(preimage: Field, hash: pub Field) {
let computed_hash = pedersen_hash([preimage]);
assert(computed_hash == hash);
}
Noir 中的默克尔证明
use dep::std::hash::poseidon;
use dep::std::merkle::compute_merkle_root;
fn main(
leaf: Field,
index: Field,
hash_path: [Field; 20],
root: pub Field
) {
let computed_root = compute_merkle_root(leaf, index, hash_path);
assert(computed_root == root);
}
Noir 构建流程
# 创建项目
nargo new my_circuit
cd my_circuit
# 编辑 src/main.nr
# 编辑 Prover.toml 输入
# 编译
nargo compile
# 生成见证
nargo execute
# 生成证明
nargo prove
# 验证证明
nargo verify
优化技术
约束减少
// 不好:创建额外约束
template Bad() {
signal input a;
signal output b;
b <== a * a * a * a; // 多个中间约束
}
// 好:单一约束
template Good() {
signal input a;
signal output b;
signal a2;
a2 <== a * a;
b <== a2 * a2; // 更少约束
}
域算术
// 高效使用域算术
template FieldOps() {
signal input a;
signal input b;
signal output c;
// 加法是免费的(无约束)
signal sum;
sum <== a + b;
// 乘法增加约束
c <== a * b;
}
查找表
// 使用查找表进行范围检查
template RangeCheck(n) {
signal input in;
component bits = Num2Bits(n);
bits.in <== in;
// 隐式约束 in < 2^n
}
ZK 友好型原语
| 原语 |
约束数 |
使用场景 |
| Poseidon |
~300/哈希 |
通用哈希 |
| MiMC |
~700/哈希 |
默克尔树 |
| Pedersen |
~1000/哈希 |
承诺 |
| ECDSA |
~10000/签名 |
签名 |
| EdDSA |
~3000/签名 |
签名 |
流程集成
| 流程 |
目的 |
zk-circuit-development.js |
电路开发 |
zk-snark-application.js |
ZK 应用构建 |
zk-rollup-development.js |
Rollup 电路 |
privacy-token-implementation.js |
隐私协议 |
最佳实践
- 最小化约束以提高证明效率
- 使用 ZK 友好型哈希函数
- 审计电路的完备性
- 使用边界情况测试
- 尽可能使用形式化验证
- 清晰地记录信号流
另请参阅
skills/crypto-primitives/SKILL.md - 密码学原语
agents/zk-cryptographer/AGENT.md - ZK 专家智能体
- Circom 文档
- Noir 文档