Skip to content

Commit

Permalink
Merge pull request #649 from dusk-network/reconcile
Browse files Browse the repository at this point in the history
reconcile PLONKup paper with implementation
  • Loading branch information
xevisalle authored Mar 4, 2022
2 parents e532089 + 0d83802 commit e752ee2
Show file tree
Hide file tree
Showing 42 changed files with 1,261 additions and 1,247 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Changed

- Change variable names for more consistency with the paper [#631](https://github.com/dusk-network/plonk/issues/631)

## [0.10.0] - 24-02-22

## Changed
Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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


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

Expand Down Expand Up @@ -60,7 +61,6 @@ impl Circuit for TestCircuit {
// Make second constraint a * b = d
let constraint = Constraint::new()
.mult(1)
.output(1)
.public(-self.d)
.a(a)
.b(b);
Expand All @@ -70,7 +70,8 @@ impl Circuit for TestCircuit {
let e = composer.append_witness(self.e);
let scalar_mul_result = composer
.component_mul_generator(e, dusk_jubjub::GENERATOR_EXTENDED);
// Apply the constrain

// Apply the constraint
composer.assert_equal_public_point(scalar_mul_result, self.f);
Ok(())
}
Expand All @@ -89,8 +90,9 @@ impl Circuit for TestCircuit {
let pp = PublicParameters::setup(1 << 12, &mut OsRng).unwrap();
// Initialize the circuit
let mut circuit = TestCircuit::default();
// Compile the circuit
// Compile/preproces the circuit
let (pk, vd) = circuit.compile(&pp).unwrap();

// Prover POV
let proof = {
let mut circuit = TestCircuit {
Expand All @@ -105,6 +107,7 @@ let proof = {
};
circuit.prove(&pp, &pk, b"Test").unwrap()
};

// Verifier POV
let public_inputs: Vec<PublicInputValue> = vec![
BlsScalar::from(25u64).into(),
Expand All @@ -128,9 +131,9 @@ TestCircuit::verify(
This crate includes a variety of features which will briefly be explained below:
- `alloc`: Enables the usage of an allocator and with it the capability of performing `Proof` constructions and
verifications. Without this feature it **IS NOT** possible to prove or verify anything.
Its absence only makes `dusk-plonk` export certain fixed-size data structures such as `Proof` which can be useful in no_std envoirments where we don't have allocators either.
- `std`: Enables `std` usage as well as `rayon` parallelisation in some proving and verifying ops.
It also uses the `std` versions of the elliptic curve deps, which utilises the `parallel` feature
Its absence only makes `dusk-plonk` export certain fixed-size data structures such as `Proof` which can be useful in no_std environments where we don't have allocators either.
- `std`: Enables `std` usage as well as `rayon` parallelization in some proving and verifying ops.
It also uses the `std` versions of the elliptic curve deps, which utilizes the `parallel` feature
from `dusk-bls12-381`. By default, this is the feature that comes enabled with the crate.
- `trace`: Enables the Circuit debugger tooling. This is essentially the capability of using the
`StandardComposer::check_circuit_satisfied` function. The function will output information about each circuit gate until
Expand All @@ -140,8 +143,7 @@ This crate includes a variety of features which will briefly be explained below:
values which make up the circuit that we're constructing.
__The recommended method is to derive the std output, and the std error, and then place them in text file
which can be used to efficiently analyse the gates.__
- `canon`: Enables `canonical` serialisation for particular data structures, which is very useful in integrating
this library within the rest of the Dusk stack - especially for storage purposes.
- `canon`: Enables `canonical` serialization for particular data structures, which is very useful in integrating this library within the rest of the Dusk stack - especially for storage purposes.


## Documentation
Expand Down
2 changes: 1 addition & 1 deletion docs/notes-prove-verify.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SNARK construction,
here we will give the set up
of a PLONK proof and show
which steps need to be satisfied
to utilise the protocol.
to utilize the protocol.

First we will explain the
derivation and simplification
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2021-10-28
nightly-2021-10-28
2 changes: 1 addition & 1 deletion src/bit_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

//! Code taken from zcash repo and generalised as we do not have access to the
//! Code taken from zcash repo and generalized as we do not have access to the
//! limbs
use core::mem;

Expand Down
7 changes: 3 additions & 4 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ impl VerifierData {

/// Trait that should be implemented for any circuit function to provide to it
/// the capabilities of automatically being able to generate, and verify proofs
/// as well as compile the circuit.
/// as well as compile/preprocess the circuit.
/// # Example
///
/// ```
Expand Down Expand Up @@ -173,7 +173,6 @@ impl VerifierData {
/// // Make second constraint a * b = d
/// let constraint = Constraint::new()
/// .mult(1)
/// .output(1)
/// .public(-self.d)
/// .a(a)
/// .b(b);
Expand All @@ -185,7 +184,7 @@ impl VerifierData {
/// composer.component_mul_generator(
/// e, dusk_jubjub::GENERATOR_EXTENDED,
/// );
/// // Apply the constrain
/// // Apply the constraint
/// composer
/// .assert_equal_public_point(scalar_mul_result, self.f);
/// Ok(())
Expand All @@ -203,7 +202,7 @@ impl VerifierData {
/// let pp = PublicParameters::setup(1 << 12, &mut OsRng)?;
/// // Initialize the circuit
/// let mut circuit = TestCircuit::default();
/// // Compile the circuit
/// // Compile/preprocess the circuit
/// let (pk, vd) = circuit.compile(&pp)?;
///
/// // Prover POV
Expand Down
4 changes: 2 additions & 2 deletions src/commitment_scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

//! Ideally we should cleanly abstract away the polynomial commitment scheme
//! We note that PLONK makes use of the linearisation technique
//! We note that PLONK makes use of the linearization technique
//! conceived in SONIC [Mary Maller].
//!
//! This technique implicitly requires the
//! commitment scheme to be homomorphic. `Merkle Tree like` techniques such as
//! FRI are not homomorphic and therefore for PLONK to be usable with all
//! commitment schemes without modification, one would need to remove the
//! lineariser
//! linearizer
mod kzg10;

Expand Down
25 changes: 13 additions & 12 deletions src/commitment_scheme/kzg10/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ impl CommitKey {
Self { powers_of_g }
}

/// Serialises the [`CommitKey`] into a byte slice.
/// Serializes the [`CommitKey`] into a byte slice.
pub fn to_var_bytes(&self) -> Vec<u8> {
self.powers_of_g
.iter()
.flat_map(|item| item.to_bytes().to_vec())
.collect()
}

/// Deserialise a slice of bytes into a [`CommitKey`] struct performing
/// Deserialize a slice of bytes into a [`CommitKey`] struct performing
/// security and consistency checks for each point that the bytes
/// contain.
///
Expand Down Expand Up @@ -173,23 +173,23 @@ impl CommitKey {

/// Computes a single witness for multiple polynomials at the same point, by
/// taking a random linear combination of the individual witnesses.
/// We apply the same optimisation mentioned in when computing each witness;
/// We apply the same optimization mentioned in when computing each witness;
/// removing f(z).
pub(crate) fn compute_aggregate_witness(
&self,
polynomials: &[Polynomial],
point: &BlsScalar,
transcript: &mut Transcript,
) -> Polynomial {
let challenge = transcript.challenge_scalar(b"aggregate_witness");
let powers = util::powers_of(&challenge, polynomials.len() - 1);
let v_challenge = transcript.challenge_scalar(b"v_challenge");
let powers = util::powers_of(&v_challenge, polynomials.len() - 1);

assert_eq!(powers.len(), polynomials.len());

let numerator: Polynomial = polynomials
.iter()
.zip(powers.iter())
.map(|(poly, challenge)| poly * challenge)
.map(|(poly, v_challenge)| poly * v_challenge)
.sum();
numerator.ruffini(*point)
}
Expand Down Expand Up @@ -264,22 +264,23 @@ impl OpeningKey {
let mut total_c = G1Projective::identity();
let mut total_w = G1Projective::identity();

let challenge = transcript.challenge_scalar(b"batch"); // XXX: Verifier can add their own randomness at this point
let powers = util::powers_of(&challenge, proofs.len() - 1);
let u_challenge = transcript.challenge_scalar(b"batch"); // XXX: Verifier can add their own randomness at this point
let powers = util::powers_of(&u_challenge, proofs.len() - 1);
// Instead of multiplying g and gamma_g in each turn, we simply
// accumulate their coefficients and perform a final
// multiplication at the end.
let mut g_multiplier = BlsScalar::zero();

for ((proof, challenge), point) in proofs.iter().zip(powers).zip(points)
for ((proof, u_challenge), point) in
proofs.iter().zip(powers).zip(points)
{
let mut c = G1Projective::from(proof.commitment_to_polynomial.0);
let w = proof.commitment_to_witness.0;
c += w * point;
g_multiplier += challenge * proof.evaluated_point;
g_multiplier += u_challenge * proof.evaluated_point;

total_c += c * challenge;
total_w += w * challenge;
total_c += c * u_challenge;
total_w += w * u_challenge;
}
total_c -= self.g * g_multiplier;

Expand Down
13 changes: 7 additions & 6 deletions src/commitment_scheme/kzg10/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub(crate) mod alloc {
use super::*;
use crate::transcript::TranscriptProtocol;
use crate::util::powers_of;
#[rustfmt::skip]
use ::alloc::vec::Vec;
use dusk_bls12_381::G1Projective;
use merlin::Transcript;
Expand All @@ -47,7 +48,7 @@ pub(crate) mod alloc {
}

impl AggregateProof {
/// Initialises an `AggregatedProof` with the commitment to the witness.
/// Initializes an `AggregatedProof` with the commitment to the witness.
pub(crate) fn with_witness(witness: Commitment) -> AggregateProof {
AggregateProof {
commitment_to_witness: witness,
Expand All @@ -67,9 +68,9 @@ pub(crate) mod alloc {
/// The transcript must have the same view as the transcript that was
/// used to aggregate the witness in the proving stage.
pub(crate) fn flatten(&self, transcript: &mut Transcript) -> Proof {
let challenge = transcript.challenge_scalar(b"aggregate_witness");
let v_challenge = transcript.challenge_scalar(b"v_challenge");
let powers = powers_of(
&challenge,
&v_challenge,
self.commitments_to_polynomials.len() - 1,
);

Expand All @@ -89,15 +90,15 @@ pub(crate) mod alloc {
let flattened_poly_evaluations_iter =
self.evaluated_points.par_iter().zip(powers.par_iter());

// Flattened polynomial commitments using challenge
// Flattened polynomial commitments using challenge `v`
let flattened_poly_commitments: G1Projective =
flattened_poly_commitments_iter
.map(|(poly, challenge)| poly.0 * challenge)
.map(|(poly, v_challenge)| poly.0 * v_challenge)
.sum();
// Flattened evaluation points
let flattened_poly_evaluations: BlsScalar =
flattened_poly_evaluations_iter
.map(|(eval, challenge)| eval * challenge)
.map(|(eval, v_challenge)| eval * v_challenge)
.sum();

Proof {
Expand Down
30 changes: 15 additions & 15 deletions src/commitment_scheme/kzg10/srs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,32 +52,32 @@ impl PublicParameters {
return Err(Error::DegreeIsZero);
}

// Generate the secret scalar beta
let beta = util::random_scalar(&mut rng);
// Generate the secret scalar x
let x = util::random_scalar(&mut rng);

// Compute powers of beta up to and including beta^max_degree
let powers_of_beta = util::powers_of(&beta, max_degree);
// Compute powers of x up to and including x^max_degree
let powers_of_x = util::powers_of(&x, max_degree);

// Powers of G1 that will be used to commit to a specified polynomial
let g = util::random_g1_point(&mut rng);
let powers_of_g: Vec<G1Projective> =
util::slow_multiscalar_mul_single_base(&powers_of_beta, g);
util::slow_multiscalar_mul_single_base(&powers_of_x, g);
assert_eq!(powers_of_g.len(), max_degree + 1);

// Normalise all projective points
let mut normalised_g = vec![G1Affine::identity(); max_degree + 1];
G1Projective::batch_normalize(&powers_of_g, &mut normalised_g);
// Normalize all projective points
let mut normalized_g = vec![G1Affine::identity(); max_degree + 1];
G1Projective::batch_normalize(&powers_of_g, &mut normalized_g);

// Compute beta*G2 element and stored cached elements for verifying
// Compute x_2 = x*h element and stored cached elements for verifying
// multiple proofs.
let h: G2Affine = util::random_g2_point(&mut rng).into();
let beta_h: G2Affine = (h * beta).into();
let x_2: G2Affine = (h * x).into();

Ok(PublicParameters {
commit_key: CommitKey {
powers_of_g: normalised_g,
powers_of_g: normalized_g,
},
opening_key: OpeningKey::new(g.into(), h, beta_h),
opening_key: OpeningKey::new(g.into(), h, x_2),
})
}

Expand Down Expand Up @@ -126,14 +126,14 @@ impl PublicParameters {
}
}

/// Serialises a [`PublicParameters`] struct into a slice of bytes.
/// Serializes a [`PublicParameters`] struct into a slice of bytes.
pub fn to_var_bytes(&self) -> Vec<u8> {
let mut bytes = self.opening_key.to_bytes().to_vec();
bytes.extend(self.commit_key.to_var_bytes().iter());
bytes
}

/// Deserialise a slice of bytes into a Public Parameter struct performing
/// Deserialize a slice of bytes into a Public Parameter struct performing
/// security and consistency checks for each point that the bytes
/// contain.
///
Expand Down Expand Up @@ -206,7 +206,7 @@ mod test {
}

#[test]
fn test_serialise_deserialise_public_parameter() {
fn test_serialize_deserialize_public_parameter() {
let pp = PublicParameters::setup(1 << 7, &mut OsRng).unwrap();

let got_pp = PublicParameters::from_slice(&pp.to_var_bytes()).unwrap();
Expand Down
Loading

0 comments on commit e752ee2

Please sign in to comment.