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(&params, &circuit).expect("keygen_vk should not fail");
    let pk = keygen_pk(&params, vk, &circuit).expect("keygen_pk should not fail");

    // 创建证明
    let mut rng = OsRng;
    let proof = create_proof(&params, &pk, &[circuit], &[&[2u64.into(), 5u64.into()]], &mut rng)
        .expect("proof generation should not fail");

    // 验证证明
    let public_inputs = vec![2u64.into(), 5u64.into()];
    verify_proof(&params, pk.get_vk(), &proof, &[&public_inputs[..]])
        .expect("proof verification should not fail");

    println!("Proof verified successfully!");
}

关键特性

  1. 派生宏#[halo2_circuit]宏自动为电路结构体生成必要的实现
  2. 字段标记
    • #[instance]标记公开输入
    • #[private]标记私有输入
  3. 简化电路开发:减少样板代码,使开发者更专注于电路逻辑

许可证

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));
    
    // 这里应该添加实际的证明生成和验证逻辑
    // 但为了示例简洁省略了具体实现
}

这个完整示例展示了:

  1. 使用#[derive(Circuit)]自动派生电路实现
  2. 定义公共输入(a,b)和私有输出©
  3. 实现乘法约束(a * b = c)
  4. 完整的Circuit trait实现
  5. 值分配和区域布局

注意在实际使用时,还需要添加证明生成和验证的具体逻辑,这个示例主要展示电路定义和约束部分。

回到顶部