Rust零知识证明库bellman的使用,bellman提供高效zk-SNARKs证明系统实现与密码学工具
Rust零知识证明库bellman的使用,bellman提供高效zk-SNARKs证明系统实现与密码学工具
bellman
是一个用于构建zk-SNARK电路的Rust库。它提供了电路特性和基本结构,以及布尔值和数字抽象等基本gadget实现。
bellman
使用 ff
和 group
crate来在标量字段类型上通用地构建电路,该标量字段类型用作电路的"字"。模标量字段质数的算术运算是高效的,而其他操作(如布尔逻辑)则使用这些字来实现。
当前状态
目前 bellman
捆绑了Groth16证明系统的实现。未来这将被移到一个单独的crate中,而 bellman
将包含任何使实现证明系统更容易的工具。
许可证
根据以下任一许可证授权:
- Apache License, Version 2.0
- MIT license
示例代码
以下是一个使用bellman创建简单zk-SNARK电路的完整示例:
use bellman::{
gadgets::{
boolean::{AllocatedBit, Boolean},
multipack,
sha256::sha256,
},
groth16, Circuit, ConstraintSystem, SynthesisError,
};
use bls12_381::{Bls12, Scalar};
use ff::PrimeField;
use rand::rngs::OsRng;
use sha2::{Digest, Sha256};
// 定义一个简单的电路用于SHA256哈希计算
struct MyCircuit {
// 电路输入,None表示不知道输入值
input: Option<Vec<u8>>,
}
// 为电路实现Circuit trait
impl<Scalar: PrimeField> Circuit<Scalar> for MyCircuit {
fn synthesize<CS: ConstraintSystem<Scalar>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
// 将输入转换为布尔值位
let bit_values = if let Some(input) = self.input {
input
.into_iter()
.flat_map(|byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8))
.collect::<Vec<bool>>()
} else {
vec![false; 256]
};
// 为每个位分配电路变量
let preimage_bits = bit_values
.into_iter()
.enumerate()
.map(|(i, b)| {
AllocatedBit::alloc(cs.namespace(|| format!("preimage bit {}", i)), Some(b))
})
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(Boolean::from)
.collect::<Vec<_>>();
// 计算SHA256哈希
let hash = sha256(cs.namespace(|| "sha256"), &preimage_bits)?;
// 将哈希位打包到标量中
multipack::pack_into_inputs(cs.namespace(|| "pack hash"), &hash)
}
}
fn main() {
// 创建随机参数
let rng = &mut OsRng;
// 生成CRS (Common Reference String)
let params = {
let c = MyCircuit { input: None };
groth16::generate_random_parameters::<Bls12, _, _>(c, rng).unwrap()
};
// 准备验证密钥
let pvk = groth16::prepare_verifying_key(¶ms.vk);
// 创建证明
let input = b"hello world";
let c = MyCircuit {
input: Some(input.to_vec()),
};
let proof = groth16::create_random_proof(c, ¶ms, rng).unwrap();
// 计算预期哈希
let hash = Sha256::digest(input);
let mut hash_bits = Vec::new();
for byte in hash.iter() {
for i in 0..8 {
hash_bits.push((byte >> i) & 1u8 == 1u8);
}
}
let inputs = multipack::bytes_to_b bits(&hash);
let inputs = multipack::compute_multipacking::<Scalar>(&inputs);
// 验证证明
assert!(groth16::verify_proof(&pvk, &proof, &inputs).is_ok());
println!("Proof verified successfully!");
}
这个示例演示了如何使用bellman:
- 定义了一个简单的电路来计算SHA256哈希
- 生成证明参数
- 创建证明
- 验证证明
电路将输入位转换为布尔值,计算SHA256哈希,并将结果打包为标量值用于验证。
1 回复
以下是基于您提供的内容整理的完整示例demo,首先展示内容中的示例,然后提供完整实现:
内容中的示例代码
1. 定义电路示例
use bellman::{
Circuit,
ConstraintSystem,
SynthesisError,
};
use pairing::{Engine, Field};
struct MyCircuit<E: Engine> {
a: Option<E::Fr>,
b: Option<E::Fr>,
}
impl<E: Engine> Circuit<E> for MyCircuit<E> {
fn synthesize<CS: ConstraintSystem<E>>(
self,
cs: &mut CS
) -> Result<(), SynthesisError> {
let a_var = cs.alloc(|| "a", || {
self.a.ok_or(SynthesisError::AssignmentMissing)
})?;
let b_var = cs.alloc(|| "b", || {
self.b.ok_or(SynthesisError::AssignmentMissing)
})?;
let ab_var = cs.alloc(|| "a*b", || {
let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;
a.mul_assign(&b);
Ok(a)
})?;
cs.enforce(
|| "a*b = ab",
|lc| lc + a_var,
|lc| lc + b_var,
|lc| lc + ab_var
);
Ok(())
}
}
2. 生成和验证证明示例
use bellman::groth16::{
generate_random_parameters,
create_random_proof,
prepare_verifying_key,
verify_proof,
};
use pairing::bls12_381::{Bls12, Fr};
use rand::thread_rng;
fn main() {
let rng = &mut thread_rng();
let circuit = MyCircuit::<Bls12> {
a: Some(Fr::from_str("3").unwrap()),
b: Some(Fr::from_str("5").unwrap()),
};
let params = generate_random_parameters::<Bls12, _, _>(
circuit.clone(),
rng
).unwrap();
let pvk = prepare_verifying_key(¶ms.vk);
let proof = create_random_proof(circuit, ¶ms, rng).unwrap();
let result = verify_proof(&pvk, &proof, &[]).unwrap();
assert!(result);
println!("Proof verified successfully!");
}
完整示例demo
use bellman::{
Circuit,
ConstraintSystem,
SynthesisError,
groth16::{
generate_random_parameters,
create_random_proof,
prepare_verifying_key,
verify_proof,
}
};
use pairing::{
Engine,
bls12_381::{Bls12, Fr},
Field
};
use rand::thread_rng;
use std::str::FromStr;
// 定义电路结构
struct MultiplicationCircuit<E: Engine> {
// 输入值a
a: Option<E::Fr>,
// 输入值b
b: Option<E::Fr>,
}
// 为电路实现Circuit trait
impl<E: Engine> Circuit<E> for MultiplicationCircuit<E> {
fn synthesize<CS: ConstraintSystem<E>>(
self,
cs: &mut CS
) -> Result<(), SynthesisError> {
// 分配输入a
let a_var = cs.alloc(|| "a", || {
self.a.ok_or(SynthesisError::AssignmentMissing)
})?;
// 分配输入b
let b_var = cs.alloc(|| "b", || {
self.b.ok_or(SynthesisError::AssignmentMissing)
})?;
// 计算a*b并分配结果
let ab_var = cs.alloc(|| "a*b", || {
let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;
a.mul_assign(&b);
Ok(a)
})?;
// 添加约束:a * b = ab
cs.enforce(
|| "a*b = ab constraint",
|lc| lc + a_var,
|lc| lc + b_var,
|lc| lc + ab_var
);
Ok(())
}
}
fn main() {
// 初始化随机数生成器
let rng = &mut thread_rng();
// 创建电路实例
let circuit = MultiplicationCircuit::<Bls12> {
a: Some(Fr::from_str("3").unwrap()),
b: Some(Fr::from_str("5").unwrap()),
};
// 1. 生成CRS (公共参考字符串)
println!("Generating parameters...");
let params = generate_random_parameters::<Bls12, _, _>(circuit.clone(), rng)
.expect("Failed to generate parameters");
// 2. 准备验证密钥
let pvk = prepare_verifying_key(¶ms.vk);
// 3. 创建证明
println!("Creating proof...");
let proof = create_random_proof(circuit, ¶ms, rng)
.expect("Failed to create proof");
// 4. 验证证明
println!("Verifying proof...");
let result = verify_proof(&pvk, &proof, &[])
.expect("Failed to verify proof");
assert!(result, "Proof verification failed");
println!("Proof verified successfully!");
// 5. 测试错误案例
println!("Testing with invalid inputs...");
let invalid_circuit = MultiplicationCircuit::<Bls12> {
a: Some(Fr::from_str("4").unwrap()), // 错误的a值
b: Some(Fr::from_str("5").unwrap()),
};
let invalid_proof = create_random_proof(invalid_circuit, ¶ms, rng)
.expect("Failed to create invalid proof");
let invalid_result = verify_proof(&pvk, &invalid_proof, &[])
.expect("Failed to verify invalid proof");
assert!(!invalid_result, "Invalid proof should not verify");
println!("Invalid proof correctly rejected");
}
这个完整示例演示了:
- 定义一个简单的乘法电路
- 生成zk-SNARK参数
- 创建和验证证明
- 包含错误案例测试
使用步骤:
- 将代码保存为main.rs
- 在Cargo.toml中添加bellman和pairing依赖
- 运行程序将输出证明生成和验证过程
注意:实际使用时需要根据具体需求设计更复杂的电路和约束条件。