#零知识 #zk-snarks #密码学

无 std plonkup

PLONK ZK-Proof 算法的纯 Rust 实现

1 个不稳定版本

0.9.2 2022年2月8日
0.1.0 2022年6月15日

966数学

MPL-2.0 许可协议

505KB
10K SLoC

PlonkUp

Build Status Repository Documentation Code Coverage GitHub Issues License

这是 BLS12-381 上 PlonkUp 证明系统的纯 Rust 实现。有关此证明系统的更多详细信息,请参阅此 论文

此库包含 KZG10 的模块化实现,作为默认的多项式承诺方案。

免责声明:此库目前不稳定,并且仍需经过彻底的安全分析。请在自己的风险下使用。

用法

use plonkup::prelude::*;
use rand_core::OsRng;

// Implement a circuit that checks:
// 1) a + b = c where C is a PI
// 2) a <= 2^6
// 3) b <= 2^5
// 4) a * b = d where D is a PI
// 5) JubJub::GENERATOR * e(JubJubScalar) = f where F is a Public Input
#[derive(Debug, Default)]
pub struct TestCircuit {
    a: BlsScalar,
    b: BlsScalar,
    c: BlsScalar,
    d: BlsScalar,
    e: JubJubScalar,
    f: JubJubAffine,
}

impl Circuit for TestCircuit {
    const CIRCUIT_ID: [u8; 32] = [0xff; 32];
    fn gadget(
        &mut self,
        composer: &mut TurboComposer,
    ) -> Result<(), Error> {
        let a = composer.append_witness(self.a);
        let b = composer.append_witness(self.b);

        // Make first constraint a + b = c
        let constraint = Constraint::new()
            .left(1)
            .right(1)
            .public(-self.c)
            .a(a)
            .b(b);

        composer.append_gate(constraint);

        // Check that a and b are in range
        composer.component_range(a, 1 << 6);
        composer.component_range(b, 1 << 5);

        // Make second constraint a * b = d
        let constraint = Constraint::new()
            .mult(1)
            .public(-self.d)
            .a(a)
            .b(b);

        composer.append_gate(constraint);

        let e = composer.append_witness(self.e);
        let scalar_mul_result = composer
            .component_mul_generator(e, dusk_jubjub::GENERATOR_EXTENDED);

        // Apply the constraint
        composer.assert_equal_public_point(scalar_mul_result, self.f);
        Ok(())
    }

    fn public_inputs(&self) -> Vec<PublicInputValue> {
        vec![self.c.into(), self.d.into(), self.f.into()]
    }

    fn padded_gates(&self) -> usize {
        1 << 11
    }
}

// Now let's use the Circuit we've just implemented!

let pp = PublicParameters::setup(1 << 12, &mut OsRng).unwrap();
// Initialize the circuit
let mut circuit = TestCircuit::default();
// Compile/preproces the circuit
let (pk, vd) = circuit.compile(&pp).unwrap();

// Prover POV
let proof = {
    let mut circuit = TestCircuit {
        a: BlsScalar::from(20u64),
        b: BlsScalar::from(5u64),
        c: BlsScalar::from(25u64),
        d: BlsScalar::from(100u64),
        e: JubJubScalar::from(2u64),
        f: JubJubAffine::from(
            dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(2u64),
        ),
    };
    circuit.prove(&pp, &pk, b"Test", &mut OsRng).unwrap()
};

// Verifier POV
let public_inputs: Vec<PublicInputValue> = vec![
    BlsScalar::from(25u64).into(),
    BlsScalar::from(100u64).into(),
    JubJubAffine::from(
        dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(2u64),
    )
    .into(),
];
TestCircuit::verify(
    &pp,
    &vd,
    &proof,
    &public_inputs,
    b"Test",
).unwrap();

性能

Apple M1 上进行的基准测试。对于大小为 2^16 的约束/门

  • 证明时间: 17.392s
  • 验证时间: 10.475ms(此时间不会因电路大小而变化。)

有关更多结果,请运行 cargo bench 以获取关于约束数的基准测试的完整报告。

致谢

  • 参考实现 AztecProtocol/Barretenberg
  • FFT 模块和 KZG10 模块分别从 zexe/zcash 和 scipr-lab 中获取并修改。

许可协议

此代码根据 Mozilla 公共许可证版本 2.0 (MPL-2.0) 许可。有关更多信息,请参阅 LICENSE

关于

dusk 团队设计。

贡献

  • 如果您想为此存储库/项目做出贡献,请检查 CONTRIBUTING.md
  • 如果您想报告错误或请求添加新功能,请在此存储库上打开一个问题。

依赖项

~3.5–9.5MB
~89K SLoC