Rust零知识证明库halo2_gadgets的使用,halo2_gadgets为Halo2提供了丰富的零知识证明电路组件和工具函数

Rust零知识证明库halo2_gadgets的使用

halo2_gadgets是Halo2零知识证明系统的重要组成部分,它提供了丰富的电路组件和工具函数。

安装要求

需要Rust 1.60+版本。

安装方式

在项目目录中运行以下Cargo命令:

cargo add halo2_gadgets

或者在Cargo.toml中添加以下行:

halo2_gadgets = "0.3.1"

许可证

halo2_gadgets采用双重许可:

  • Apache License 2.0
  • MIT license

示例代码

以下是内容中提供的示例代码:

use halo2_proofs::{
    circuit::{Layouter, SimpleFloorPlanner, Value},
    plonk::{Advice, Circuit, Column, ConstraintSystem, Error},
};
use halo2_gadgets::{
    ecc::EccInstructions,
    poseidon::{self as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig},
};
use pasta_curves::{pallas, vesta};

// 定义电路结构
struct MyCircuit {
    input: Value<pallas::Base>,
}

// 实现Circuit trait
impl Circuit<pallas::Base> for MyCircuit {
    type Config = PoseidonConfig<pallas::Base, 3, 2>;
    type FloorPlanner = SimpleFloorPlanner;

    fn without_witnesses(&self) -> Self {
        Self {
            input: Value::unknown(),
        }
    }

    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
        // 配置Poseidon哈希函数
        let state = [
            meta.advice_column(),
            meta.advice_column(),
            meta.advice_column(),
        ];
        let partial_sbox = meta.advice_column();
        let rc_a = [(); 3].map(|_| meta.fixed_column());
        let rc_b = [(); 3].map(|_| meta.fixed_column());

        PoseidonConfig::configure(
            meta,
            state,
            partial_sbox,
            rc_a,
            rc_b,
            poseidon::PoseidonChip::<
                pallas::Base,
                3,
                2,
                poseidon::P128Pow5T3 as poseidon::PoseidonConstants<pallas::Base, 3, 2>,
            >::RATE,
            poseidon::P128Pow5T3::constants(),
        )
    }

    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<pallas::Base>,
    ) -> Result<(), Error> {
        // 实例化Poseidon芯片
        let poseidon = PoseidonChip::construct(config);
        
        // 加载初始状态
        let initial_state = layouter.assign_region(
            || "load initial state",
            |mut region| {
                // 分配输入值
                let input_cell = region.assign_advice(
                    || "input",
                    poseidon.config().state[0],
                    0,
                    || self.input,
                )?;

                Ok([input_cell, input_cell, input_cell])
            },
        )?;

        // 计算Poseidon哈希
        let hasher = poseidon::Hash::<_, _, _, 3, 2, 1>::init(
            poseidon,
            layouter.namespace(|| "Poseidon hash"),
            initial_state,
        )?;
        
        hasher.finalize(layouter.namespace(|| "finalize"))?;

        Ok(())
    }
}

fn main() {
    // 创建电路实例
    let circuit = MyCircuit {
        input: Value::known(pallas::Base::from(42)),
    };
    
    // 这里通常会进行证明生成和验证
    // 为了示例简化,省略这部分代码
    println!("Circuit created successfully!");
}

完整示例demo

以下是一个更完整的示例,展示了如何使用halo2_gadgets创建和验证零知识证明:

use halo2_proofs::{
    circuit::{Layouter, SimpleFloorPlanner, Value},
    dev::MockProver,
    plonk::{Circuit, ConstraintSystem, Error},
};
use halo2_gadgets::{
    poseidon::{self as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig},
};
use pasta_curves::pallas;

// 定义电路结构
struct PoseidonCircuit {
    input: Value<pallas::Base>,
}

// 实现Circuit trait
impl Circuit<pallas::Base> for PoseidonCircuit {
    type Config = PoseidonConfig<pallas::Base, 3, 2>;
    type FloorPlanner = SimpleFloorPlanner;

    fn without_witnesses(&self) -> Self {
        Self {
            input: Value::unknown(),
        }
    }

    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
        // 配置Poseidon哈希函数
        let state = [
            meta.advice_column(),
            meta.advice_column(),
            meta.advice_column(),
        ];
        let partial_sbox = meta.advice_column();
        let rc_a = [(); 3].map(|_| meta.fixed_column());
        let rc_b = [(); 3].map(|_| meta.fixed_column());

        PoseidonConfig::configure(
            meta,
            state,
            partial_sbox,
            rc_a,
            rc_b,
            poseidon::PoseidonChip::<
                pallas::Base,
                3,
                2,
                poseidon::P128Pow5T3 as poseidon::PoseidonConstants<pallas::Base, 3, 2>,
            >::RATE,
            poseidon::P128Pow5T3::constants(),
        )
    }

    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<pallas::Base>,
    ) -> Result<(), Error> {
        // 实例化Poseidon芯片
        let poseidon = PoseidonChip::construct(config);
        
        // 加载初始状态
        let initial_state = layouter.assign_region(
            || "load initial state",
            |mut region| {
                // 分配输入值
                let input_cell = region.assign_advice(
                    || "input",
                    poseidon.config().state[0],
                    0,
                    || self.input,
                )?;

                Ok([input_cell, input_cell, input_cell])
            },
        )?;

        // 计算Poseidon哈希
        let hasher = poseidon::Hash::<_, _, _, 3, 2, 1>::init(
            poseidon,
            layouter.namespace(|| "Poseidon hash"),
            initial_state,
        )?;
        
        hasher.finalize(layouter.namespace(|| "finalize"))?;

        Ok(())
    }
}

fn main() {
    // 创建电路实例
    let circuit = PoseidonCircuit {
        input: Value::known(pallas::Base::from(42)),
    };
    
    // 创建MockProver进行验证
    let prover = MockProver::run(17, &circuit, vec![]).unwrap();
    
    // 验证电路约束
    assert_eq!(prover.verify(), Ok(()));
    
    println!("Circuit verified successfully!");
}

主要功能

halo2_gadgets提供了以下主要组件:

  1. 椭圆曲线运算(EccInstructions)
  2. Poseidon哈希函数
  3. 范围检查
  4. 其他加密原语

文档资源

  • Halo 2 Book
  • Crate文档

1 回复

Rust零知识证明库halo2_gadgets使用指南

概述

halo2_gadgets是Halo2零知识证明系统的一个扩展库,提供了丰富的预构建电路组件和实用工具函数。它为开发者提供了构建复杂零知识证明电路所需的基本构建块,简化了开发过程。

主要功能

  1. 提供常见密码学原语的电路实现
  2. 包含各种基础电路组件
  3. 提供实用工具函数
  4. 支持多种哈希函数和签名方案的电路实现

安装

在Cargo.toml中添加依赖:

[dependencies]
halo2_proofs = "0.3"
halo2_gadgets = { version = "0.3", features = ["full"] }

核心组件和使用示例

SHA-256哈希电路

use halo2_gadgets::sha256::{Sha256, BlockWord, Sha256Config};
use halo2_proofs::{
    circuit::{Layouter, SimpleFloorPlanner, Value},
    plonk::{Circuit, ConstraintSystem, Error},
};
use halo2curves::pasta::Fp;

// 定义一个简单的电路结构体
struct MyCircuit;

impl Circuit<Fp> for MyCircuit {
    type Config = Sha256Config;
    type FloorPlanner = SimpleFloorPlanner;

    // 创建一个没有见证值的电路实例
    fn without_witnesses(&self) -> Self {
        Self
    }

    // 配置电路约束
    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
        Sha256::configure(meta)
    }

    // 合成电路逻辑
    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<Fp>,
    ) -> Result<(), Error> {
        // 对16个32位字(初始全为0)进行SHA-256哈希计算
        Sha256::digest(
            config,
            layouter.namespace(|| "SHA-256"),
            [BlockWord::from(Value::known(0u32)); 16],
        )?;
        Ok(())
    }
}

椭圆曲线操作

use halo2_gadgets::ecc::{
    EccConfig, FixedPoints, NonIdentityPoint, ScalarFixed,
};
use halo2_proofs::{
    circuit::{Layouter, SimpleFloorPlanner, Value},
    plonk::{Circuit, ConstraintSystem, Error},
};
use halo2curves::pasta::{pallas, Fp};

// 椭圆曲线操作电路
struct MyCircuit;

impl Circuit<Fp> for MyCircuit {
    type Config = EccConfig;
    type FloorPlanner = SimpleFloorPlanner;

    fn without_witnesses(&self) -> Self {
        Self
    }

    // 配置椭圆曲线电路
    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
        EccConfig::configure(meta, FixedPoints::Pallas)
    }

    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<Fp>,
    ) -> Result<(), Error> {
        // 定义标量值为2
        let scalar = ScalarFixed::new(
            layouter.namespace(|| "scalar"),
            config,
            Value::known(pallas::Scalar::from(2u64)),
        )?;

        // 定义生成元点
        let point = NonIdentityPoint::new(
            layouter.namespace(|| "point"),
            config,
            Value::known(pallas::Point::generator()),
        )?;

        // 计算标量乘法: point * 2
        let _result = point.mul(
            layouter.namespace(|| "scalar multiplication"),
            config,
            &scalar,
        )?;

        Ok(())
    }
}

范围证明

use halo2_gadgets::{
    range::RangeConfig,
    utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig},
};
use halo2_proofs::{
    circuit::{Layouter, SimpleFloorPlanner, Value},
    plonk::{Circuit, ConstraintSystem, Error},
};
use halo2curves::pasta::Fp;

// 范围证明电路
struct MyCircuit {
    value: Value<u64>,
}

impl Circuit<Fp> for MyCircuit {
    type Config = RangeConfig<Fp, 10>;
    type FloorPlanner = SimpleFloorPlanner;

    fn without_witnesses(&self) -> Self {
        Self {
            value: Value::unknown(),
        }
    }

    // 配置范围检查电路
    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
        let lookup_config = LookupRangeCheckConfig::configure(meta);
        RangeConfig::configure(meta, lookup_config)
    }

    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<Fp>,
    ) -> Result<(), Error> {
        // 加载查找表
        config.load_lookup_table(&mut layouter)?;

        // 执行范围检查(10位)
        let value = config.range_check(
            layouter.namespace(|| "Range check"),
            self.value,
            10,
        )?;

        Ok(())
    }
}

实用工具函数

布尔值检查

use halo2_gadgets::utilities::bool_check;
use halo2_proofs::{
    circuit::{Layouter, Value},
    plonk::Error,
};
use halo2curves::pasta::Fp;

// 检查一个值是否为布尔值(0或1)
fn check_boolean(
    layouter: &mut impl Layouter<Fp>,
    value: Value<Fp>,
) -> Result<(), Error> {
    bool_check(layouter.namespace(|| "bool check"), value)
}

数值分解

use halo2_gadgets::utilities::decompose_running_sum;
use halo2_proofs::{
    circuit::{Layouter, Value},
    plonk::{Assigned, Error},
};
use halo2curves::pasta::Fp;

// 将数值分解为指定位数的二进制表示
fn decompose_value(
    layouter: &mut impl Layouter<Fp>,
    value: Value<u64>,
    num_bits: usize,
) -> Result<Vec<Assigned<Fp>>, Error> {
    decompose_running_sum(
        layouter.namespace(|| "decompose"),
        value.map(|v| Fp::from(v)),
        num_bits,
    )
}

完整示例demo

下面是一个完整的示例,展示如何使用halo2_gadgets构建一个简单的电路,证明你知道某个值的SHA-256哈希:

use halo2_gadgets::sha256::{Sha256, BlockWord, Sha256Config};
use halo2_proofs::{
    circuit::{Layouter, SimpleFloorPlanner, Value},
    dev::MockProver,
    plonk::{Circuit, ConstraintSystem, Error},
};
use halo2curves::pasta::Fp;
use sha2::{Digest, Sha256 as NativeSha256};

// 定义电路结构体
struct Sha256Circuit {
    // 输入数据(16个32位字)
    input: [Value<u32>; 16],
    // 期望的哈希结果(256位)
    expected_hash: Value<[u8; 32]>,
}

impl Circuit<Fp> for Sha256Circuit {
    type Config = Sha256Config;
    type FloorPlanner = SimpleFloorPlanner;

    fn without_witnesses(&self) -> Self {
        Self {
            input: [Value::unknown(); 16],
            expected_hash: Value::unknown(),
        }
    }

    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
        Sha256::configure(meta)
    }

    fn synthesize(
        &self,
        config: Self::Config,
        mut layouter: impl Layouter<Fp>,
    ) -> Result<(), Error> {
        // 将输入数据转换为BlockWord格式
        let input_words = self.input.map(|v| BlockWord::from(v));
        
        // 计算SHA-256哈希
        let computed_hash = Sha256::digest(
            config,
            layouter.namespace(|| "SHA-256"),
            input_words,
        )?;

        // 验证计算出的哈希是否与预期匹配
        if let (Value::known(computed), Value::known(expected)) = 
            (computed_hash.value(), self.expected_hash) 
        {
            assert_eq!(computed, expected);
        }

        Ok(())
    }
}

fn main() -> Result<(), Error> {
    // 准备测试数据
    let data = b"hello halo2";
    let mut hasher = NativeSha256::new();
    hasher.update(data);
    let result = hasher.finalize();
    
    // 将输入数据填充为16个32位字(实际实现中需要完整处理填充规则)
    let mut input = [0u32; 16];
    input[0] = u32::from_be_bytes([data[0], data[1], data[2], data[3]]);
    
    // 创建电路实例
    let circuit = Sha256Circuit {
        input: input.map(|v| Value::known(v)),
        expected_hash: Value::known(result.into()),
    };
    
    // 使用MockProver验证电路
    let prover = MockProver::run(20, &circuit, vec![])?;
    prover.assert_satisfied();
    
    println!("Circuit verified successfully!");
    Ok(())
}

最佳实践

  1. 模块化设计:将复杂电路分解为多个小电路,使用halo2_gadgets提供的组件组合
  2. 合理配置查找表:对于频繁使用的操作,配置查找表提高效率
  3. 资源管理:注意电路规模和约束数量,优化布局
  4. 测试验证:使用halo2_proofs的mock prover验证电路正确性

注意事项

  1. halo2_gadgets仍在活跃开发中,API可能会有变化
  2. 使用前应充分理解零知识证明和电路约束系统的基本概念
  3. 性能优化需要针对具体应用场景进行调整
  4. 生产环境使用前应进行充分的安全审计

通过halo2_gadgets,开发者可以快速构建复杂的零知识证明应用,而无需从零开始实现基础密码学原语。

回到顶部