#parameters #zk-snarks #mpc #public #circuit #performing

阶段21

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

15个版本 (8个破坏性更新)

0.11.0 2020年11月1日
0.9.0 2020年10月1日
0.7.0 2020年6月29日
0.4.0 2020年3月23日
0.3.0 2019年5月20日

#34 in #mpc

每月38次下载

MIT/Apache

91KB
1.5K SLoC

phase21 Crates.io

这是对优秀的phase2库的分支。

此库仍在开发中。

文档

安全警告

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

许可

许可协议为以下之一

任选其一。

贡献

除非你明确表示,否则任何提交以包含在作品中的贡献,如Apache-2.0许可证中定义的,均将双许可如上,没有任何附加条款或条件。


lib.rs:

zk-SNARK MPC,简单易用。

创建你的电路

获取bellperson包。Bellman提供了一个名为Circuit的trait,你必须实现它来处理你的计算。

这里有一个愚蠢的例子:证明你知道一个域元素的立方根。

use ff::Field;
use bellperson::{
    Circuit,
    ConstraintSystem,
    SynthesisError,
    bls::Engine,
};

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(())
    }
}

创建一些证明

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

use bellperson::bls::{Bls12, Fr};
use bellperson::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具有这样的性质:只有一位参与者需要诚实,参数才能安全。这个crate(phase21)就是关于使用这样的MPC安全地创建参数。

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

let mut params = phase21::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!(phase21::contains_contribution(&contributions, &hash));

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

依赖关系

~3.5–6MB
~121K SLoC