26 releases (6 breaking)

0.7.0 Apr 6, 2021
0.7.0-pre.0 Mar 16, 2021
0.6.1 Mar 12, 2021
0.3.6 Dec 17, 2020
0.2.5 Jul 31, 2020

#55 in Algorithms

Download history 4/week @ 2020-12-24 29/week @ 2020-12-31 51/week @ 2021-01-07 26/week @ 2021-01-14 94/week @ 2021-01-21 98/week @ 2021-01-28 103/week @ 2021-02-04 300/week @ 2021-02-11 191/week @ 2021-02-18 68/week @ 2021-02-25 49/week @ 2021-03-04 160/week @ 2021-03-11 90/week @ 2021-03-18 139/week @ 2021-03-25 159/week @ 2021-04-01 44/week @ 2021-04-08

464 downloads per month
Used in 4 crates

MPL-2.0 license

400KB
8K SLoC

PLONK Build Status GitHub issues GitHub

This is a pure Rust implementation of the PLONK proving system over BLS12-381

This code is highly experimental, use at your own risk.

This library contains a modularised implementation of KZG10 as the default polynomial commitment scheme.

Usage

use dusk_plonk::prelude::*
use dusk_plonk::circuit;
use dusk-bls12_381::BlsScalar;
use dusk-jubjub::{GENERATOR, JubJubScalar, JubJubAffine};

// Implement the `Circuit` trait for the circuit you want to construct.
// Implements 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 PI
#[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 StandardComposer) -> Result<(), Error> {
        let a = composer.add_input(self.a);
        let b = composer.add_input(self.b);
        // Make first constraint a + b = c
        composer.poly_gate(
            a,
            b,
            composer.zero_var,
            BlsScalar::zero(),
            BlsScalar::one(),
            BlsScalar::one(),
            BlsScalar::zero(),
            BlsScalar::zero(),
            Some(-self.c),
        );
        // Check that a and b are in range
        composer.range_gate(a, 1 << 6);
        composer.range_gate(b, 1 << 5);
        // Make second constraint a * b = d
        composer.poly_gate(
            a,
            b,
            composer.zero_var,
            BlsScalar::one(),
            BlsScalar::zero(),
            BlsScalar::zero(),
            BlsScalar::one(),
            BlsScalar::zero(),
            Some(-self.d),
        );

        // This adds a PI also constraining `generator` to actually be `dusk_jubjub::GENERATOR`
        let generator = Point::from_public_affine(composer, dusk_jubjub::GENERATOR);
        let e = composer.add_input(self.e.into());
        let scalar_mul_result =
            scalar_mul::variable_base::variable_base_scalar_mul(composer, e, generator);
        // Apply the constrain
        composer.assert_equal_public_point(scalar_mul_result.into(), self.f);
        Ok(())
    }
    fn padded_circuit_size(&self) -> usize {
        1 << 11
    }

// Generate CRS (Or read it from file if already have it).
let pp_p = PublicParameters::setup(1 << 12, &mut rand::thread_rng())?;

// Initialize the circuit (with dummy inputs if you want, doesn't matter).
let mut circuit = TestCircuit::default();

// Compile the circuit. This will produce the Prover and Verifier keys as well
// as the public input positions vector.
// You can now store that to use it later on to generate proofs or verify them.
let (pk_p, vk_p, pi_pos) = circuit.compile(&pp)?;

// 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.gen_proof(&pp, &pk, b"Test")
}?;

// Verifier PoV

// Generate the `PublicInputValue`s vector containing your Circuit Pi's **ordered**.
let public_input_vals: Vec<PublicInputValue> = vec![
    BlsScalar::from(25u64).into(),
    BlsScalar::from(100u64).into(),
    dusk_jubjub::GENERATOR.into(),
    JubJubAffine::from(dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(2u64)).into(),
];

// Verify the proof.
assert!(circuit::verify_proof(&pp, &vk, &proof, &public_input_vals, &pi_pos, b"Test").is_ok());

Documentation

There are two main types of documentation in this repository:

  • Crate documentation. This provides info about all of the functions that the library provides as well as the documentation regarding the data structures that it exports. To check it, please feel free to go to the documentation page

  • Notes. This is a specific subset of documentation which explains the mathematical key concepts of PLONK and how they work with mathematical demonstrations. It can be found inside of the documentation page in the notes sub-section

Performance

Benchmarks taken on Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz For a proof-size of 2^16 constraints/gates:

  • Proving time: 5.46s
  • Verification time: 6.13ms. (This time will not vary depending on the circuit-size.)

Acknowledgements

  • Reference implementation AztecProtocol/Barretenberg
  • FFT Module and KZG10 Module were taken and modified from zexe/zcash and scipr-lab respectively.

Licensing

This code is licensed under Mozilla Public License Version 2.0 (MPL-2.0). Please see LICENSE for further info.

About

Implementation designed by the dusk team.

Contributing

  • If you want to contribute to this repository/project please, check CONTRIBUTING.md
  • If you want to report a bug or request a new feature addition, please open an issue on this repository.

Dependencies

~4.5MB
~92K SLoC