logo
Expand description

PlonkUp

Build Status Repository Documentation Code Coverage GitHub Issues License

This is a pure Rust implementation of the PlonkUp proving system over BLS12-381. More details on this proving system can be found in this paper.

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

DISCLAIMER: This library is currently unstable and still needs to go through an exhaustive security analysis. Use at your own risk.

Usage

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

Performance

Benchmarks taken on Apple M1 For a circuit-size of 2^16 constraints/gates:

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

For more results, please run cargo bench to get a full report of benchmarks in respect of constraint numbers.

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.

Modules

Tools & traits for PLONK circuits

Ideally we should cleanly abstract away the polynomial commitment scheme We note that PLONK makes use of the linearization technique conceived in SONIC [Mary Maller].

The constraint System module stores the implementation of the PLONK Standard Composer, as well as the circuit tools and abstractions, used by the Composer to generate, build, preprocess circuits.

A collection of all possible errors encountered in PLONK.

This module is a self contained file which explains how PLONK and its protocol components work in our library.

Module containing the plonkup works. Plonkup is the protcol for using precomputed and stored tables of values for specific functions to determine the output of gates within a circuit, without computing them.

Collection of functions needed to use plonk library.

Proving system