#参数 #zk-snarks #mpc #public #circuit #performing

阶段2

用于创建zk-SNARK公共参数的多方计算库

5个不稳定版本

使用旧的Rust 2015

0.2.2 2018年4月13日
0.2.1 2018年4月8日
0.2.0 2018年4月8日
0.1.0 2018年4月6日
0.0.1 2018年4月4日

#32 in #mpc

MIT/Apache

45KB
877

阶段2 Crates.io

这个库仍在开发中。

文档

安全警告

此库不对常量时间操作、内存访问模式或抵抗侧信道攻击做出任何保证。

许可协议

许可协议为以下之一

任选其一。

贡献

除非你明确表示,否则根据Apache-2.0许可证定义,你有意提交的任何贡献都将按上述方式双重许可,不附加任何额外条款或条件。


lib.rs:

zk-SNARK MPC,变得简单。

创建你的电路

获取 bellmanpairing 包。Bellman提供了一个名为 Circuit 的特质,你必须实现它以进行计算。

以下是一个愚蠢的示例:证明你知道一个域元素的立方根。

extern crate pairing;
extern crate bellman;

use pairing::{Engine, Field};
use bellman::{
    Circuit,
    ConstraintSystem,
    SynthesisError,
};

struct CubeRoot<E: Engine> {
    cube_root: Option<E::Fr>
}

impl<E: Engine> Circuit<E> for CubeRoot<E> {
    fn synthesize<CS: ConstraintSystem<E>>(
        self,
        cs: &mut CS
    ) -> Result<(), SynthesisError>
    {
        // Witness the cube root
        let root = cs.alloc(|| "root", || {
            self.cube_root.ok_or(SynthesisError::AssignmentMissing)
        })?;

        // Witness the square of the cube root
        let square = cs.alloc(|| "square", || {
            self.cube_root
                .ok_or(SynthesisError::AssignmentMissing)
                .map(|mut root| {root.square(); root })
        })?;

        // Enforce that `square` is root^2
        cs.enforce(
            || "squaring",
            |lc| lc + root,
            |lc| lc + root,
            |lc| lc + square 
        );

        // Witness the cube, as a public input
        let cube = cs.alloc_input(|| "cube", || {
            self.cube_root
                .ok_or(SynthesisError::AssignmentMissing)
                .map(|root| {
                    let mut tmp = root;
                    tmp.square();
                    tmp.mul_assign(&root);
                    tmp
                })
        })?;

        // Enforce that `cube` is root^3
        // i.e. that `cube` is `root` * `square`
        cs.enforce(
            || "cubing",
            |lc| lc + root,
            |lc| lc + square,
            |lc| lc + cube
        );

        Ok(())
    }
}

创建一些证明

现在我们已经有了 CubeRoot<E> 实现 Circuit,让我们创建一些参数并生成一些证明。

extern crate rand; 

use pairing::bls12_381::{Bls12, Fr};
use bellman::groth16::{
    generate_random_parameters,
    create_random_proof,
    prepare_verifying_key,
    verify_proof
};
use rand::{OsRng, Rand};

let rng = &mut OsRng::new();

// Create public parameters for our circuit
let params = {
    let circuit = CubeRoot::<Bls12> {
        cube_root: None
    };

    generate_random_parameters::<Bls12, _, _>(
        circuit,
        rng
    ).unwrap()
};

// Prepare the verifying key for verification
let pvk = prepare_verifying_key(&params.vk);

// Let's start making proofs!
for _ in 0..50 {
    // Verifier picks a cube in the field.
    // Let's just make a random one.
    let root = Fr::rand(rng);
    let mut cube = root;
    cube.square();
    cube.mul_assign(&root);

    // Prover gets the cube, figures out the cube
    // root, and makes the proof:
    let proof = create_random_proof(
        CubeRoot::<Bls12> {
            cube_root: Some(root)
        }, &params, rng
    ).unwrap();

    // Verifier checks the proof against the cube
    assert!(verify_proof(&pvk, &proof, &[cube]).unwrap());
}

创建参数

注意在前一个示例中,我们通过调用 generate_random_parameters 创建了我们的zk-SNARK参数。然而,如果你愿意,你可以使用你选择的某些秘密数字调用 generate_parameters,并为自己保留它们。有了这些数字,你可以创建虚假的证明。

为了使他人相信你没有,可以使用多方计算(MPC)。MPC具有这样一个特性,即只有一名参与者诚实,参数才能保证安全。这个包(phase2)就是关于使用这样的MPC安全地创建参数。

让我们首先使用 phase2 为我们的电路创建一些基本参数。

extern crate phase2;

let mut params = phase2::MPCParameters::new(CubeRoot {
    cube_root: None
}).unwrap();

第一次尝试时,它将尝试从当前目录读取类似 phase1radix2m2 的文件。您需要从 Powers of Tau 中获取它。

这些参数不安全使用;可以为他们创建错误的证明。让我们为这些参数添加一些随机性。

// Contribute randomness to the parameters. Remember this hash,
// it's how we know our contribution is in the parameters!
let hash = params.contribute(rng);

这些参数现在安全使用,只要您不是恶意的。这可能不会让其他人信服,所以他们也可以贡献随机性!params 可以序列化并发送到其他地方,他们可以进行相同的事情并将新的参数发送回您。只有一个人需要诚实,最终的参数才能是安全的。

一旦设置好参数,您就可以验证参数

let contributions = params.verify(CubeRoot {
    cube_root: None
}).expect("parameters should be valid!");

// We need to check the `contributions` to see if our `hash`
// is in it (see above, when we first contributed)
assert!(phase2::contains_contribution(&contributions, &hash));

太好了,现在如果您满意,使用 params.params() 获取 Groth16 Parameters,这样您就可以像以前一样与 bellman APIs 交互。

依赖项

~1.5MB
~22K SLoC