Rust零知识证明库halo2derive的使用:基于Halo2的派生宏和电路构建工具
Rust零知识证明库halo2derive的使用:基于Halo2的派生宏和电路构建工具
安装
在项目目录中运行以下Cargo命令:
cargo add halo2derive
或者在Cargo.toml中添加以下行:
halo2derive = "0.2.0"
使用示例
halo2derive是一个基于Halo2的派生宏和电路构建工具,它简化了零知识证明电路的开发过程。下面是一个完整的使用示例:
use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner},
plonk::{Advice, Circuit, Column, ConstraintSystem, Error},
};
use halo2derive::halo2_circuit;
// 定义一个简单的电路结构体
#[halo2_circuit]
struct MyCircuit {
#[instance] // 标记为公开输入
public_input: u64,
#[private] // 标记为私有输入
private_input: u64,
// 不标记的字段会被视为电路内部状态
result: u64,
}
// 为电路实现Circuit trait
impl<F: Field> Circuit<F> for MyCircuit {
type Config = MyConfig;
type FloorPlanner = SimpleFloorPlanner;
fn without_witnesses(&self) -> Self {
Self {
public_input: 0,
private_input: 0,
result: 0,
}
}
fn configure(meta: &mut ConstraintSystem<F>) -> MyConfig {
let a = meta.advice_column();
let b = meta.advice_column();
let c = meta.advice_column();
let instance = meta.instance_column();
meta.enable_equality(a);
meta.enable_equality(b);
meta.enable_equality(c);
meta.enable_equality(instance);
MyConfig { a, b, c, instance }
}
fn synthesize(
&self,
config: MyConfig,
mut layouter: impl Layouter<F>,
) -> Result<(), Error> {
layouter.assign_region(
|| "assign values",
|mut region| {
// 分配公开输入
region.assign_advice(
|| "public input",
config.a,
0,
|| Value::known(F::from(self.public_input)),
)?;
// 分配私有输入
region.assign_advice(
|| "private input",
config.b,
0,
|| Value::known(F::from(self.private_input)),
)?;
// 计算并分配结果
let result_cell = region.assign_advice(
|| "result",
config.c,
0,
|| Value::known(F::from(self.public_input + self.private_input)),
)?;
// 将结果公开
region.constrain_instance(result_cell.cell(), config.instance, 0)
},
)
}
}
// 电路配置
#[derive(Clone, Debug)]
struct MyConfig {
a: Column<Advice>,
b: Column<Advice>,
c: Column<Advice>,
instance: Column<Instance>,
}
完整示例demo
以下是一个更完整的示例,展示了如何使用halo2derive构建和验证一个简单的零知识证明电路:
use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value},
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance},
poly::commitment::ParamsProver,
};
use halo2derive::halo2_circuit;
use pasta_curves::pallas;
use rand::rngs::OsRng;
// 定义电路结构体
#[halo2_circuit]
struct SimpleCircuit {
#[instance] // 公开输入
x: u64,
#[private] // 私有输入
y: u64,
// 计算结果
sum: u64,
}
// 实现Circuit trait
impl<F: ff::PrimeField> Circuit<F> for SimpleCircuit {
type Config = CircuitConfig;
type FloorPlanner = SimpleFloorPlanner;
fn without_witnesses(&self) -> Self {
Self {
x: 0,
y: 0,
sum: 0,
}
}
fn configure(meta: &mut ConstraintSystem<F>) -> CircuitConfig {
let col_a = meta.advice_column();
let col_b = meta.advice_column();
let col_c = meta.advice_column();
let instance = meta.instance_column();
meta.enable_equality(col_a);
meta.enable_equality(col_b);
meta.enable_equality(col_c);
meta.enable_equality(instance);
CircuitConfig {
col_a,
col_b,
col_c,
instance,
}
}
fn synthesize(
&self,
config: CircuitConfig,
mut layouter: impl Layouter<F>,
) -> Result<(), Error> {
layouter.assign_region(
|| "assign values",
|mut region| {
// 分配公开输入x
region.assign_advice(
|| "x",
config.col_a,
0,
|| Value::known(F::from(self.x)),
)?;
// 分配私有输入y
region.assign_advice(
|| "y",
config.col_b,
0,
|| Value::known(F::from(self.y)),
)?;
// 计算x + y并分配结果
let sum_cell = region.assign_advice(
|| "x + y",
config.col_c,
0,
|| Value::known(F::from(self.x + self.y)),
)?;
// 将结果约束到公开列
region.constrain_instance(sum_cell.cell(), config.instance, 0)
},
)
}
}
// 电路配置
#[derive(Clone, Debug)]
struct CircuitConfig {
col_a: Column<Advice>,
col_b: Column<Advice>,
col_c: Column<Advice>,
instance: Column<Instance>,
}
// 示例使用
fn main() {
// 准备电路实例
let circuit = SimpleCircuit {
x: 2, // 公开输入
y: 3, // 私有输入
sum: 5, // 计算结果(x+y)
};
// 生成证明参数
let k = 4;
let params = halo2_proofs::poly::commitment::Params::new(k);
// 生成验证密钥和证明密钥
let vk = keygen_vk(¶ms, &circuit).expect("keygen_vk should not fail");
let pk = keygen_pk(¶ms, vk, &circuit).expect("keygen_pk should not fail");
// 创建证明
let mut rng = OsRng;
let proof = create_proof(¶ms, &pk, &[circuit], &[&[2u64.into(), 5u64.into()]], &mut rng)
.expect("proof generation should not fail");
// 验证证明
let public_inputs = vec![2u64.into(), 5u64.into()];
verify_proof(¶ms, pk.get_vk(), &proof, &[&public_inputs[..]])
.expect("proof verification should not fail");
println!("Proof verified successfully!");
}
关键特性
- 派生宏:
#[halo2_circuit]
宏自动为电路结构体生成必要的实现 - 字段标记:
#[instance]
标记公开输入#[private]
标记私有输入
- 简化电路开发:减少样板代码,使开发者更专注于电路逻辑
许可证
halo2derive采用MIT或Apache-2.0双许可证。
1 回复
以下是基于您提供的内容整理的完整示例demo,首先展示内容中的示例,然后给出一个完整的电路实现示例:
内容中的基础电路定义示例
use halo2_derive::Circuit;
#[derive(Circuit)]
struct MyCircuit {
// 公共输入
#[public]
x: Value<Fp>,
// 私有输入
#[private]
y: Value<Fp>,
// 电路输出
#[public]
out: Value<Fp>,
}
impl MyCircuit {
fn configure(meta: &mut ConstraintSystem<Fp>) -> Self {
let x = meta.advice_column();
let y = meta.advice_column();
let out = meta.advice_column();
meta.create_gate("my_gate", |meta| {
let x = meta.query_advice(x, Rotation::cur());
let y = meta.query_advice(y, Rotation::cur());
let out = meta.query_advice(out, Rotation::cur());
vec![x * y - out]
});
MyCircuit { x, y, out }
}
}
完整示例demo:实现一个完整的乘法验证电路
use halo2_proofs::{
arithmetic::FieldExt,
circuit::{Layouter, SimpleFloorPlanner, Value},
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance},
poly::Rotation,
};
use halo2_derive::Circuit;
use pairing::bn256::Fr as Fp;
// 定义电路结构
#[derive(Circuit)]
struct MultiplierCircuit {
// 公共输入a
#[public]
a: Value<Fp>,
// 公共输入b
#[public]
b: Value<Fp>,
// 私有输出
#[private]
c: Value<Fp>,
}
impl MultiplierCircuit {
// 构造函数
fn new(a: Fp, b: Fp) -> Self {
Self {
a: Value::known(a),
b: Value::known(b),
c: Value::known(a * b),
}
}
}
// 实现Circuit trait
impl Circuit<Fp> for MultiplierCircuit {
type Config = (Column<Advice>, Column<Advice>, Column<Advice>);
type FloorPlanner = SimpleFloorPlanner;
fn without_witnesses(&self) -> Self {
Self {
a: Value::unknown(),
b: Value::unknown(),
c: Value::unknown(),
}
}
fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
// 定义三列advice列
let a = meta.advice_column();
let b = meta.advice_column();
let c = meta.advice_column();
// 定义乘法约束
meta.create_gate("multiplication", |meta| {
let a = meta.query_advice(a, Rotation::cur());
let b = meta.query_advice(b, Rotation::cur());
let c = meta.query_advice(c, Rotation::cur());
// 约束a * b = c
vec![a * b - c]
});
(a, b, c)
}
fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<Fp>,
) -> Result<(), Error> {
layouter.assign_region(
|| "assign values",
|mut region| {
// 分配a值
region.assign_advice(
|| "a",
config.0,
0,
|| self.a,
)?;
// 分配b值
region.assign_advice(
|| "b",
config.1,
0,
|| self.b,
)?;
// 分配c值
region.assign_advice(
|| "c",
config.2,
0,
|| self.c,
)?;
Ok(())
},
)
}
}
// 使用示例
fn main() {
// 创建电路实例
let circuit = MultiplierCircuit::new(Fp::from(2), Fp::from(3));
// 这里应该添加实际的证明生成和验证逻辑
// 但为了示例简洁省略了具体实现
}
这个完整示例展示了:
- 使用
#[derive(Circuit)]
自动派生电路实现 - 定义公共输入(a,b)和私有输出©
- 实现乘法约束(a * b = c)
- 完整的Circuit trait实现
- 值分配和区域布局
注意在实际使用时,还需要添加证明生成和验证的具体逻辑,这个示例主要展示电路定义和约束部分。