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.
```rust use duskplonk::prelude::* use duskplonk::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
pub struct TestCircuit { a: BlsScalar, b: BlsScalar, c: BlsScalar, d: BlsScalar, e: JubJubScalar, f: JubJubAffine, }
impl Circuit for TestCircuit { const CIRCUITID: [u8; 32] = [0xff; 32]; fn gadget(&mut self, composer: &mut StandardComposer) -> Result<(), Error> { let a = composer.addinput(self.a); let b = composer.addinput(self.b); // Make first constraint a + b = c composer.polygate( a, b, composer.zerovar, BlsScalar::zero(), BlsScalar::one(), BlsScalar::one(), BlsScalar::zero(), BlsScalar::zero(), Some(-self.c), ); // Check that a and b are in range composer.rangegate(a, 1 << 6); composer.rangegate(b, 1 << 5); // Make second constraint a * b = d composer.polygate( 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 ppp = PublicParameters::setup(1 << 12, &mut rand::threadrng())?;
// 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 (pkp, vkp, 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(duskjubjub::GENERATOREXTENDED * JubJubScalar::from(2u64)), };
circuit.gen_proof(&pp, &pk, b"Test")
}?;
// Verifier PoV
// Generate the PublicInputValue
s vector containing your Circuit Pi's ordered.
let publicinputvals: Vec
// Verify the proof. assert!(circuit::verifyproof(&pp, &vk, &proof, &publicinputvals, &pipos, b"Test").is_ok()); ```
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
Benchmarks taken on Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz
For a proof-size of 2^16
constraints/gates:
5.46s
6.13ms
. (This time will not vary depending on the circuit-size.)This code is licensed under Mozilla Public License Version 2.0 (MPL-2.0). Please see LICENSE for further info.
Implementation designed by the dusk team.