2个版本

使用旧Rust 2015

0.0.2 2018年10月26日
0.0.1 2018年10月26日

#8 in #groth16

GPL-3.0-or-later

160KB
3.5K SLoC

零知识SNARK

此库尚未准备用于生产。

该crate提供创建和使用零知识证明的功能。实现基于groth16

用法

该算法的主要功能是setupproveverify函数,这些函数位于groth16模块中。可以从.zk文件生成中间表示,这些文件是用表示算术电路的领域特定语言(DSL)编写的。

语言

表示算术电路的语言相当基本,以类似lisp的风格编写,使用括号内前缀记法。以下是一个计算二次多项式的电路的示例程序:y = ax^2 + bx + c

(in x a b c)
(out y)
(verify x y)

(program
    (= t1
        (* x a))
    (= t2
        (* x (+ t1 b)))
    (= y
        (* 1 (+ t2 c))))

顺序必须始终遵循inoutverify然后是program。目前括号是'粘性的',这意味着它们之间不能有任何空白字符和内部标记。关键字如下:

  • in位于电路输入线列表之前,不包括常数单位线。
  • out位于电路输出线列表之前。
  • verify位于验证者将通过在验证过程中提供它们作为输入来检查的线列表之前。
  • program位于构成整个算术电路的乘法子电路列表之前。乘法子电路模拟一个扇入为二的单个乘法门,其中两个输入可以是任意数量的电路输入和先前内部线的线性组合。它们使用以下关键字。
  • = 是赋值运算符,它接受两个参数。第一个参数是要赋值的变量,代表乘法门的输出线。第二个参数是要赋值的表达式,代表输入线的线性组合。
  • * 是乘法运算符,它既用于乘法门,也用于表示乘法门输入的线性组合中的常数缩放。它只接受两个参数;当用于乘法门时,顺序无关紧要,但对于常数缩放,常数必须是第一个参数。
  • + 是加法运算符,如前所述,它可以有任意数量的参数。每个参数可以是变量,也可以是缩放变量(即它可以是像 x 这样的形式,或者,例如,像 (* 5 x) 这样的形式)。

示例

例如,考虑简单的算术表达式 x = 4ab + c + 6。我们想验证 xb 这两条线。程序文件可能看起来像以下这样

(in a b c)
(out x)
(verify b x)

(program
    (= temp
        (* a b))
    (= x
        (* 1 (+ (* 4 temp) c 6))))

假设证明者想证明他们知道 ac 的值,使得当验证者输入 b = 2x = 34 时,电路是满足的。以下代码是设置、证明和验证过程的示例。

extern crate zksnark;

use zksnark::groth16;
use zksnark::groth16::{Proof, SigmaG1, SigmaG2, QAP};
use zksnark::groth16::circuit::{ASTParser, TryParse};
use zksnark::groth16::fr::FrLocal;
use zksnark::groth16::coefficient_poly::CoefficientPoly;

// x = 4ab + c + 6
let code = &*::std::fs::read_to_string("test_programs/simple.zk").unwrap();
let qap: QAP<CoefficientPoly<FrLocal>> =
    ASTParser::try_parse(code)
        .unwrap()
        .into();

// The assignments are the inputs to the circuit in the order they
// appear in the file
let assignments = &[
    3.into(), // a
    2.into(), // b
    4.into(), // c
];
let weights = groth16::weights(code, assignments).unwrap();

let (sigmag1, sigmag2) = groth16::setup(&qap);

let proof = groth16::prove(&qap, (&sigmag1, &sigmag2), &weights);

assert!(groth16::verify(
    &qap,
    (sigmag1, sigmag2),
    &vec![FrLocal::from(2), FrLocal::from(34)],
    proof
));

依赖项

~4MB
~28K SLoC