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提供了以下主要组件:
- 椭圆曲线运算(EccInstructions)
- Poseidon哈希函数
- 范围检查
- 其他加密原语
文档资源
- Halo 2 Book
- Crate文档
1 回复
Rust零知识证明库halo2_gadgets使用指南
概述
halo2_gadgets是Halo2零知识证明系统的一个扩展库,提供了丰富的预构建电路组件和实用工具函数。它为开发者提供了构建复杂零知识证明电路所需的基本构建块,简化了开发过程。
主要功能
- 提供常见密码学原语的电路实现
- 包含各种基础电路组件
- 提供实用工具函数
- 支持多种哈希函数和签名方案的电路实现
安装
在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(())
}
最佳实践
- 模块化设计:将复杂电路分解为多个小电路,使用halo2_gadgets提供的组件组合
- 合理配置查找表:对于频繁使用的操作,配置查找表提高效率
- 资源管理:注意电路规模和约束数量,优化布局
- 测试验证:使用halo2_proofs的mock prover验证电路正确性
注意事项
- halo2_gadgets仍在活跃开发中,API可能会有变化
- 使用前应充分理解零知识证明和电路约束系统的基本概念
- 性能优化需要针对具体应用场景进行调整
- 生产环境使用前应进行充分的安全审计
通过halo2_gadgets,开发者可以快速构建复杂的零知识证明应用,而无需从零开始实现基础密码学原语。