From d9d20bfe369be6db057050a8f7a3b8f0fb319a33 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 12 Jan 2021 08:01:50 -0700 Subject: [PATCH 1/7] Break out domain creation logic into separate method. --- src/plonk/keygen.rs | 76 +++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index 94a020a..fa1b1c0 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -10,6 +10,51 @@ use crate::poly::{ EvaluationDomain, LagrangeCoeff, Polynomial, Rotation, }; +pub(crate) fn create_domain( + params: &Params, +) -> ( + EvaluationDomain, + ConstraintSystem, + ConcreteCircuit::Config, +) +where + C: CurveAffine, + ConcreteCircuit: Circuit, +{ + let mut cs = ConstraintSystem::default(); + let config = ConcreteCircuit::configure(&mut cs); + + // The permutation argument will serve alongside the gates, so must be + // accounted for. + let mut degree = cs + .permutations + .iter() + .map(|p| p.required_degree()) + .max() + .unwrap_or(1); + + // The lookup argument also serves alongside the gates and must be accounted + // for. + degree = std::cmp::max( + degree, + cs.lookups + .iter() + .map(|l| l.required_degree()) + .max() + .unwrap_or(1), + ); + + // Account for each gate to ensure our quotient polynomial is the + // correct degree and that our extended domain is the right size. + for poly in cs.gates.iter() { + degree = std::cmp::max(degree, poly.degree()); + } + + let domain = EvaluationDomain::new(degree as u32, params.k); + + (domain, cs, config) +} + /// Generate a `ProvingKey` from an instance of `Circuit`. pub fn keygen( params: &Params, @@ -68,36 +113,7 @@ where } } - let mut cs = ConstraintSystem::default(); - let config = ConcreteCircuit::configure(&mut cs); - - // The permutation argument will serve alongside the gates, so must be - // accounted for. - let mut degree = cs - .permutations - .iter() - .map(|p| p.required_degree()) - .max() - .unwrap_or(1); - - // The lookup argument also serves alongside the gates and must be accounted - // for. - degree = std::cmp::max( - degree, - cs.lookups - .iter() - .map(|l| l.required_degree()) - .max() - .unwrap_or(1), - ); - - // Account for each gate to ensure our quotient polynomial is the - // correct degree and that our extended domain is the right size. - for poly in cs.gates.iter() { - degree = std::cmp::max(degree, poly.degree()); - } - - let domain = EvaluationDomain::new(degree as u32, params.k); + let (domain, cs, config) = create_domain::(params); let mut assembly: Assembly = Assembly { fixed: vec![domain.empty_lagrange(); cs.num_fixed_columns], From a0d7998785e519e1fc29e21026c3f95dead72988 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 12 Jan 2021 08:22:35 -0700 Subject: [PATCH 2/7] Add implementations of read/write to CurveAffine and FieldExt. --- src/arithmetic/curves.rs | 19 +++++++++++++++++++ src/arithmetic/fields.rs | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index 6210031..fa6512c 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -8,6 +8,8 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use super::{FieldExt, Group}; +use std::io::{self, Read, Write}; + /// This trait is a common interface for dealing with elements of an elliptic /// curve group in the "projective" form, where that arithmetic is usually more /// efficient. @@ -153,10 +155,27 @@ pub trait CurveAffine: /// endian representation. fn from_bytes(bytes: &[u8; 32]) -> CtOption; + /// Reads a compressed element from the buffer and attempts to parse it + /// using `from_bytes`. + fn read(reader: &mut R) -> io::Result { + let mut compressed = [0u8; 32]; + reader.read_exact(&mut compressed[..])?; + Option::from(Self::from_bytes(&compressed)).ok_or(io::Error::new( + io::ErrorKind::Other, + "invalid point encoding in proof", + )) + } + /// Obtains the compressed, 32-byte little endian representation of this /// element. fn to_bytes(&self) -> [u8; 32]; + /// Writes an element in compressed form to the buffer. + fn write(&self, writer: &mut W) -> io::Result<()> { + let compressed = self.to_bytes(); + writer.write_all(&compressed[..]) + } + /// Attempts to obtain a group element from its uncompressed 64-byte little /// endian representation. fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption; diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index 6a35cc0..3d0dfcb 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -10,6 +10,8 @@ use subtle::{Choice, ConstantTimeEq, CtOption}; use super::Group; +use std::io::{self, Read, Write}; + const_assert!(size_of::() >= 4); /// This trait is a common interface for dealing with elements of a finite @@ -77,10 +79,27 @@ pub trait FieldExt: /// representation. fn to_bytes(&self) -> [u8; 32]; + /// Writes this element in its normalized, little endian form into a buffer. + fn write(&self, writer: &mut W) -> io::Result<()> { + let compressed = self.to_bytes(); + writer.write_all(&compressed[..]) + } + /// Attempts to obtain a field element from its normalized, little endian /// byte representation. fn from_bytes(bytes: &[u8; 32]) -> CtOption; + /// Reads a normalized, little endian represented field element from a + /// buffer. + fn read(reader: &mut R) -> io::Result { + let mut compressed = [0u8; 32]; + reader.read_exact(&mut compressed[..])?; + Option::from(Self::from_bytes(&compressed)).ok_or(io::Error::new( + io::ErrorKind::Other, + "invalid point encoding in proof", + )) + } + /// Obtains a field element that is congruent to the provided little endian /// byte representation of an integer. fn from_bytes_wide(bytes: &[u8; 64]) -> Self; From ba591c3b39d26fbae3f98430896e845f33baf3ad Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 12 Jan 2021 08:28:35 -0700 Subject: [PATCH 3/7] Add serialization support for PLONK verifying keys. --- src/plonk.rs | 52 +++++++++++++++++++++++++++++++++++++--- src/plonk/permutation.rs | 21 ++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/plonk.rs b/src/plonk.rs index bc81918..d2bf6c7 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -6,7 +6,9 @@ //! [plonk]: https://eprint.iacr.org/2019/953 use crate::arithmetic::CurveAffine; -use crate::poly::{Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}; +use crate::poly::{ + commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, +}; use crate::transcript::ChallengeScalar; mod circuit; @@ -23,6 +25,8 @@ pub use keygen::*; pub use prover::*; pub use verifier::*; +use std::io; + /// This is a verifying key which allows for the verification of proofs for a /// particular circuit. #[derive(Debug)] @@ -33,6 +37,45 @@ pub struct VerifyingKey { cs: ConstraintSystem, } +impl VerifyingKey { + /// Writes a verifying key to a buffer. + pub fn write(&self, writer: &mut W) -> io::Result<()> { + for commitment in &self.fixed_commitments { + writer.write_all(&commitment.to_bytes())?; + } + for permutation in &self.permutations { + permutation.write(writer)?; + } + + Ok(()) + } + + /// Reads a verification key from a buffer. + pub fn read>( + reader: &mut R, + params: &Params, + ) -> io::Result { + let (domain, cs, _) = keygen::create_domain::(params); + + let mut fixed_commitments = Vec::with_capacity(cs.num_fixed_columns); + for _ in 0..cs.num_fixed_columns { + fixed_commitments.push(C::read(reader)?); + } + + let mut permutations = Vec::with_capacity(cs.permutations.len()); + for argument in &cs.permutations { + permutations.push(permutation::VerifyingKey::read(reader, argument)?); + } + + Ok(VerifyingKey { + domain, + fixed_commitments, + permutations, + cs, + }) + } +} + /// This is a proving key which allows for the creation of proofs for a /// particular circuit. #[derive(Debug)] @@ -487,8 +530,11 @@ fn test_proving() { let msm = guard.clone().use_challenges(); assert!(msm.clone().eval()); let mut transcript = DummyHashRead::init(&proof[..], Fq::one()); - let guard = - verify_proof(¶ms, pk.get_vk(), msm, pubinput_slice, &mut transcript).unwrap(); + let mut vk_buffer = vec![]; + pk.get_vk().write(&mut vk_buffer).unwrap(); + let vk = VerifyingKey::::read::<_, MyCircuit>(&mut &vk_buffer[..], ¶ms) + .unwrap(); + let guard = verify_proof(¶ms, &vk, msm, pubinput_slice, &mut transcript).unwrap(); { let msm = guard.clone().use_challenges(); assert!(msm.eval()); diff --git a/src/plonk/permutation.rs b/src/plonk/permutation.rs index 8073f2f..affb0bf 100644 --- a/src/plonk/permutation.rs +++ b/src/plonk/permutation.rs @@ -10,6 +10,8 @@ pub(crate) mod keygen; mod prover; mod verifier; +use std::io; + /// A permutation argument. #[derive(Debug, Clone)] pub(crate) struct Argument { @@ -49,6 +51,25 @@ pub(crate) struct VerifyingKey { commitments: Vec, } +impl VerifyingKey { + pub(crate) fn write(&self, writer: &mut W) -> io::Result<()> { + for commitment in &self.commitments { + commitment.write(writer)?; + } + + Ok(()) + } + + pub(crate) fn read(reader: &mut R, argument: &Argument) -> io::Result { + let mut commitments = Vec::with_capacity(argument.columns.len()); + for _ in 0..argument.columns.len() { + commitments.push(C::read(reader)?); + } + + Ok(VerifyingKey { commitments }) + } +} + /// The proving key for a single permutation argument. #[derive(Debug)] pub(crate) struct ProvingKey { From b9737ada939f8bdf0990d005677b4ca85983c003 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 13 Jan 2021 17:39:10 +0800 Subject: [PATCH 4/7] Add serialization support for polycommit Params. --- src/poly/commitment.rs | 57 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 11e9d9e..ca5adc9 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -20,6 +20,8 @@ pub use msm::MSM; pub use prover::create_proof; pub use verifier::{verify_proof, Accumulator, Guard}; +use std::io; + /// These are the public parameters for the polynomial commitment scheme. #[derive(Debug)] pub struct Params { @@ -188,6 +190,55 @@ impl Params { pub fn get_g(&self) -> Vec { self.g.clone() } + + /// Writes params to a buffer. + pub fn write(&self, writer: &mut W) -> io::Result<()> { + writer.write_all(&self.k.to_le_bytes())?; + writer.write_all(&self.n.to_le_bytes())?; + for g_element in &self.g { + writer.write_all(&g_element.to_bytes())?; + } + for g_lagrange_element in &self.g_lagrange { + writer.write_all(&g_lagrange_element.to_bytes())?; + } + writer.write(&self.h.to_bytes())?; + writer.write(&self.u.to_bytes())?; + + Ok(()) + } + + /// Reads params from a buffer. + pub fn read(reader: &mut R) -> io::Result { + let mut k = [0u8; 4]; + reader.read_exact(&mut k[..])?; + let k = u32::from_le_bytes(k); + + let mut n = [0u8; 8]; + reader.read_exact(&mut n[..])?; + let n = u64::from_le_bytes(n); + + let mut g = Vec::with_capacity(n as usize); + for _ in 0..n { + g.push(C::read(reader)?); + } + + let mut g_lagrange = Vec::with_capacity(n as usize); + for _ in 0..n { + g_lagrange.push(C::read(reader)?); + } + + let h = C::read(reader)?; + let u = C::read(reader)?; + + Ok(Params { + k, + n, + g, + g_lagrange, + h, + u, + }) + } } /// Wrapper type around a blinding factor. @@ -292,13 +343,17 @@ fn test_opening_proof() { commitment::{Blind, Params}, EvaluationDomain, }; - use crate::arithmetic::{eval_polynomial, Curve, FieldExt}; + use crate::arithmetic::{eval_polynomial, FieldExt}; use crate::pasta::{EpAffine, Fq}; use crate::transcript::{ ChallengeScalar, DummyHashRead, DummyHashWrite, Transcript, TranscriptRead, TranscriptWrite, }; let params = Params::::new(K); + let mut params_buffer = vec![]; + params.write(&mut params_buffer).unwrap(); + let params: Params = Params::read::<_>(&mut ¶ms_buffer[..]).unwrap(); + let domain = EvaluationDomain::new(1, K); let mut px = domain.empty_coeff(); From 58479fbcc395da64246f1602674a364d4765917b Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 14 Jan 2021 01:23:01 +0800 Subject: [PATCH 5/7] Refactor keygen to generate pk from vk. --- benches/plonk.rs | 3 +- examples/performance_model.rs | 3 +- src/plonk.rs | 3 +- src/plonk/keygen.rs | 184 ++++++++++++++++++++------------ src/plonk/permutation/keygen.rs | 48 ++++++--- 5 files changed, 152 insertions(+), 89 deletions(-) diff --git a/benches/plonk.rs b/benches/plonk.rs index 2d59b2b..06f6317 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -226,7 +226,8 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) { let empty_circuit: MyCircuit = MyCircuit { a: None, k }; // Initialize the proving key - let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail"); + let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); let prover_name = name.to_string() + "-prover"; let verifier_name = name.to_string() + "-verifier"; diff --git a/examples/performance_model.rs b/examples/performance_model.rs index a23a4fb..15be99b 100644 --- a/examples/performance_model.rs +++ b/examples/performance_model.rs @@ -257,7 +257,8 @@ fn main() { let empty_circuit: MyCircuit = MyCircuit { a: None, k }; // Initialize the proving key - let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail"); + let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); println!("[Keygen] {}", recorder); recorder.clear(); diff --git a/src/plonk.rs b/src/plonk.rs index d2bf6c7..3a35fe4 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -485,7 +485,8 @@ fn test_proving() { }; // Initialize the proving key - let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail"); + let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); let mut pubinputs = pk.get_vk().get_domain().empty_lagrange(); pubinputs[0] = aux; diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index fa1b1c0..835acd7 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -2,12 +2,12 @@ use ff::Field; use super::{ circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed}, - permutation, Error, ProvingKey, VerifyingKey, + permutation, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey, }; use crate::arithmetic::{Curve, CurveAffine}; use crate::poly::{ commitment::{Blind, Params}, - EvaluationDomain, LagrangeCoeff, Polynomial, Rotation, + EvaluationDomain, Rotation, }; pub(crate) fn create_domain( @@ -55,64 +55,66 @@ where (domain, cs, config) } -/// Generate a `ProvingKey` from an instance of `Circuit`. -pub fn keygen( +/// Assembly to be used in circuit synthesis. +#[derive(Clone, Debug)] +pub struct Assembly { + fixed: Vec>, + permutations: Vec, + _marker: std::marker::PhantomData, +} + +impl Assignment for Assembly { + fn assign_advice( + &mut self, + _: Column, + _: usize, + _: impl FnOnce() -> Result, + ) -> Result<(), Error> { + // We only care about fixed columns here + Ok(()) + } + + fn assign_fixed( + &mut self, + column: Column, + row: usize, + to: impl FnOnce() -> Result, + ) -> Result<(), Error> { + *self + .fixed + .get_mut(column.index()) + .and_then(|v| v.get_mut(row)) + .ok_or(Error::BoundsFailure)? = to()?; + + Ok(()) + } + + fn copy( + &mut self, + permutation: usize, + left_column: usize, + left_row: usize, + right_column: usize, + right_row: usize, + ) -> Result<(), Error> { + // Check bounds first + if permutation >= self.permutations.len() { + return Err(Error::BoundsFailure); + } + + self.permutations[permutation].copy(left_column, left_row, right_column, right_row) + } +} + +/// Generate a `VerifyingKey` from an instance of `Circuit`. +pub fn keygen_vk( params: &Params, circuit: &ConcreteCircuit, -) -> Result, Error> +) -> Result, Error> where C: CurveAffine, ConcreteCircuit: Circuit, { - struct Assembly { - fixed: Vec>, - permutations: Vec, - _marker: std::marker::PhantomData, - } - - impl Assignment for Assembly { - fn assign_advice( - &mut self, - _: Column, - _: usize, - _: impl FnOnce() -> Result, - ) -> Result<(), Error> { - // We only care about fixed columns here - Ok(()) - } - - fn assign_fixed( - &mut self, - column: Column, - row: usize, - to: impl FnOnce() -> Result, - ) -> Result<(), Error> { - *self - .fixed - .get_mut(column.index()) - .and_then(|v| v.get_mut(row)) - .ok_or(Error::BoundsFailure)? = to()?; - - Ok(()) - } - - fn copy( - &mut self, - permutation: usize, - left_column: usize, - left_row: usize, - right_column: usize, - right_row: usize, - ) -> Result<(), Error> { - // Check bounds first - if permutation >= self.permutations.len() { - return Err(Error::BoundsFailure); - } - - self.permutations[permutation].copy(left_column, left_row, right_column, right_row) - } - } - let (domain, cs, config) = create_domain::(params); let mut assembly: Assembly = Assembly { @@ -130,12 +132,12 @@ where let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain); - let (permutation_pks, permutation_vks) = cs + let permutation_vks = cs .permutations .iter() - .zip(assembly.permutations.into_iter()) - .map(|(p, assembly)| assembly.build_keys(params, &domain, &permutation_helper, p)) - .unzip(); + .zip(assembly.clone().permutations.into_iter()) + .map(|(p, assembly)| assembly.build_vk(params, &domain, &permutation_helper, p)) + .collect(); let fixed_commitments = assembly .fixed @@ -143,35 +145,77 @@ where .map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine()) .collect(); + Ok(VerifyingKey { + domain, + fixed_commitments, + permutations: permutation_vks, + cs, + }) +} + +/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`. +pub fn keygen_pk( + params: &Params, + vk: VerifyingKey, + circuit: &ConcreteCircuit, +) -> Result, Error> +where + C: CurveAffine, + ConcreteCircuit: Circuit, +{ + let mut cs = ConstraintSystem::default(); + let config = ConcreteCircuit::configure(&mut cs); + + let mut assembly: Assembly = Assembly { + fixed: vec![vk.domain.empty_lagrange(); vk.cs.num_fixed_columns], + permutations: vk + .cs + .permutations + .iter() + .map(|p| permutation::keygen::Assembly::new(params.n as usize, p)) + .collect(), + _marker: std::marker::PhantomData, + }; + + // Synthesize the circuit to obtain SRS + circuit.synthesize(&mut assembly, config)?; + let fixed_polys: Vec<_> = assembly .fixed .iter() - .map(|poly| domain.lagrange_to_coeff(poly.clone())) + .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) .collect(); - let fixed_cosets = cs + let fixed_cosets = vk + .cs .fixed_queries .iter() .map(|&(column, at)| { let poly = fixed_polys[column.index()].clone(); - domain.coeff_to_extended(poly, at) + vk.domain.coeff_to_extended(poly, at) }) .collect(); + let permutation_helper = + permutation::keygen::Assembly::build_helper(params, &vk.cs, &vk.domain); + + let permutation_pks = vk + .cs + .permutations + .iter() + .zip(assembly.permutations.into_iter()) + .map(|(p, assembly)| assembly.build_pk(&vk.domain, &permutation_helper, p)) + .collect(); + // Compute l_0(X) // TODO: this can be done more efficiently - let mut l0 = domain.empty_lagrange(); + let mut l0 = vk.domain.empty_lagrange(); l0[0] = C::Scalar::one(); - let l0 = domain.lagrange_to_coeff(l0); - let l0 = domain.coeff_to_extended(l0, Rotation::cur()); + let l0 = vk.domain.lagrange_to_coeff(l0); + let l0 = vk.domain.coeff_to_extended(l0, Rotation::cur()); Ok(ProvingKey { - vk: VerifyingKey { - domain, - fixed_commitments, - permutations: permutation_vks, - cs, - }, + vk, l0, fixed_values: assembly.fixed, fixed_polys, diff --git a/src/plonk/permutation/keygen.rs b/src/plonk/permutation/keygen.rs index 017bf15..d527725 100644 --- a/src/plonk/permutation/keygen.rs +++ b/src/plonk/permutation/keygen.rs @@ -14,7 +14,7 @@ pub(crate) struct AssemblyHelper { deltaomega: Vec>, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub(crate) struct Assembly { pub(crate) mapping: Vec>, aux: Vec>, @@ -132,19 +132,15 @@ impl Assembly { AssemblyHelper { deltaomega } } - pub(crate) fn build_keys( + pub(crate) fn build_vk( self, params: &Params, domain: &EvaluationDomain, helper: &AssemblyHelper, p: &Argument, - ) -> (ProvingKey, VerifyingKey) { - // Compute permutation polynomials, convert to coset form and - // pre-compute commitments for the SRS. + ) -> VerifyingKey { + // Pre-compute commitments for the SRS. let mut commitments = vec![]; - let mut permutations = vec![]; - let mut polys = vec![]; - let mut cosets = vec![]; for i in 0..p.columns.len() { // Computes the permutation polynomial based on the permutation // description in the assembly. @@ -160,19 +156,39 @@ impl Assembly { .commit_lagrange(&permutation_poly, Blind::default()) .to_affine(), ); + } + VerifyingKey { commitments } + } + + pub(crate) fn build_pk( + self, + domain: &EvaluationDomain, + helper: &AssemblyHelper, + p: &Argument, + ) -> ProvingKey { + // Compute permutation polynomials, convert to coset form. + let mut permutations = vec![]; + let mut polys = vec![]; + let mut cosets = vec![]; + for i in 0..p.columns.len() { + // Computes the permutation polynomial based on the permutation + // description in the assembly. + let mut permutation_poly = domain.empty_lagrange(); + for (j, p) in permutation_poly.iter_mut().enumerate() { + let (permuted_i, permuted_j) = self.mapping[i][j]; + *p = helper.deltaomega[permuted_i][permuted_j]; + } + // Store permutation polynomial and precompute its coset evaluation permutations.push(permutation_poly.clone()); let poly = domain.lagrange_to_coeff(permutation_poly); polys.push(poly.clone()); cosets.push(domain.coeff_to_extended(poly, Rotation::cur())); } - ( - ProvingKey { - permutations, - polys, - cosets, - }, - VerifyingKey { commitments }, - ) + ProvingKey { + permutations, + polys, + cosets, + } } } From e0f9fe1dcf398789212d88374f0faf7fec6365bc Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 22 Jan 2021 07:40:25 +0800 Subject: [PATCH 6/7] Clippy fixes + address review comments Co-authored-by: Jack Grigg --- src/arithmetic/curves.rs | 6 ++---- src/arithmetic/fields.rs | 6 ++---- src/plonk.rs | 16 ++++++++-------- src/plonk/keygen.rs | 2 +- src/plonk/permutation.rs | 8 +++----- src/poly/commitment.rs | 15 ++++----------- 6 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index fa6512c..50bc2d9 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -160,10 +160,8 @@ pub trait CurveAffine: fn read(reader: &mut R) -> io::Result { let mut compressed = [0u8; 32]; reader.read_exact(&mut compressed[..])?; - Option::from(Self::from_bytes(&compressed)).ok_or(io::Error::new( - io::ErrorKind::Other, - "invalid point encoding in proof", - )) + Option::from(Self::from_bytes(&compressed)) + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof")) } /// Obtains the compressed, 32-byte little endian representation of this diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index 3d0dfcb..10f3102 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -94,10 +94,8 @@ pub trait FieldExt: fn read(reader: &mut R) -> io::Result { let mut compressed = [0u8; 32]; reader.read_exact(&mut compressed[..])?; - Option::from(Self::from_bytes(&compressed)).ok_or(io::Error::new( - io::ErrorKind::Other, - "invalid point encoding in proof", - )) + Option::from(Self::from_bytes(&compressed)) + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof")) } /// Obtains a field element that is congruent to the provided little endian diff --git a/src/plonk.rs b/src/plonk.rs index 3a35fe4..284e9cf 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -57,15 +57,15 @@ impl VerifyingKey { ) -> io::Result { let (domain, cs, _) = keygen::create_domain::(params); - let mut fixed_commitments = Vec::with_capacity(cs.num_fixed_columns); - for _ in 0..cs.num_fixed_columns { - fixed_commitments.push(C::read(reader)?); - } + let fixed_commitments: Vec<_> = (0..cs.num_fixed_columns) + .map(|_| C::read(reader)) + .collect::>()?; - let mut permutations = Vec::with_capacity(cs.permutations.len()); - for argument in &cs.permutations { - permutations.push(permutation::VerifyingKey::read(reader, argument)?); - } + let permutations: Vec<_> = cs + .permutations + .iter() + .map(|argument| permutation::VerifyingKey::read(reader, argument)) + .collect::>()?; Ok(VerifyingKey { domain, diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index 835acd7..8128934 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -135,7 +135,7 @@ where let permutation_vks = cs .permutations .iter() - .zip(assembly.clone().permutations.into_iter()) + .zip(assembly.permutations.into_iter()) .map(|(p, assembly)| assembly.build_vk(params, &domain, &permutation_helper, p)) .collect(); diff --git a/src/plonk/permutation.rs b/src/plonk/permutation.rs index affb0bf..86cf917 100644 --- a/src/plonk/permutation.rs +++ b/src/plonk/permutation.rs @@ -61,11 +61,9 @@ impl VerifyingKey { } pub(crate) fn read(reader: &mut R, argument: &Argument) -> io::Result { - let mut commitments = Vec::with_capacity(argument.columns.len()); - for _ in 0..argument.columns.len() { - commitments.push(C::read(reader)?); - } - + let commitments = (0..argument.columns.len()) + .map(|_| C::read(reader)) + .collect::, _>>()?; Ok(VerifyingKey { commitments }) } } diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index ca5adc9..55517d3 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -201,8 +201,8 @@ impl Params { for g_lagrange_element in &self.g_lagrange { writer.write_all(&g_lagrange_element.to_bytes())?; } - writer.write(&self.h.to_bytes())?; - writer.write(&self.u.to_bytes())?; + writer.write_all(&self.h.to_bytes())?; + writer.write_all(&self.u.to_bytes())?; Ok(()) } @@ -217,15 +217,8 @@ impl Params { reader.read_exact(&mut n[..])?; let n = u64::from_le_bytes(n); - let mut g = Vec::with_capacity(n as usize); - for _ in 0..n { - g.push(C::read(reader)?); - } - - let mut g_lagrange = Vec::with_capacity(n as usize); - for _ in 0..n { - g_lagrange.push(C::read(reader)?); - } + let g: Vec<_> = (0..n).map(|_| C::read(reader)).collect::>()?; + let g_lagrange: Vec<_> = (0..n).map(|_| C::read(reader)).collect::>()?; let h = C::read(reader)?; let u = C::read(reader)?; From ffdd739f859b89ea412ef4ad844f332baea8410b Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 22 Jan 2021 12:31:27 +0800 Subject: [PATCH 7/7] Only write k in Params; calculate n when reading Co-authored-by: Jack Grigg Co-authored-by: Daira Hopwood --- src/plonk/keygen.rs | 6 +++--- src/plonk/permutation/keygen.rs | 4 ++-- src/poly/commitment.rs | 5 +---- src/poly/commitment/prover.rs | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index 8128934..8c99b7a 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -56,7 +56,7 @@ where } /// Assembly to be used in circuit synthesis. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Assembly { fixed: Vec>, permutations: Vec, @@ -127,7 +127,7 @@ where _marker: std::marker::PhantomData, }; - // Synthesize the circuit to obtain SRS + // Synthesize the circuit to obtain URS circuit.synthesize(&mut assembly, config)?; let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain); @@ -177,7 +177,7 @@ where _marker: std::marker::PhantomData, }; - // Synthesize the circuit to obtain SRS + // Synthesize the circuit to obtain URS circuit.synthesize(&mut assembly, config)?; let fixed_polys: Vec<_> = assembly diff --git a/src/plonk/permutation/keygen.rs b/src/plonk/permutation/keygen.rs index d527725..072f6c5 100644 --- a/src/plonk/permutation/keygen.rs +++ b/src/plonk/permutation/keygen.rs @@ -14,7 +14,7 @@ pub(crate) struct AssemblyHelper { deltaomega: Vec>, } -#[derive(Clone, Debug)] +#[derive(Debug)] pub(crate) struct Assembly { pub(crate) mapping: Vec>, aux: Vec>, @@ -139,7 +139,7 @@ impl Assembly { helper: &AssemblyHelper, p: &Argument, ) -> VerifyingKey { - // Pre-compute commitments for the SRS. + // Pre-compute commitments for the URS. let mut commitments = vec![]; for i in 0..p.columns.len() { // Computes the permutation polynomial based on the permutation diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 55517d3..f4098a8 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -194,7 +194,6 @@ impl Params { /// Writes params to a buffer. pub fn write(&self, writer: &mut W) -> io::Result<()> { writer.write_all(&self.k.to_le_bytes())?; - writer.write_all(&self.n.to_le_bytes())?; for g_element in &self.g { writer.write_all(&g_element.to_bytes())?; } @@ -213,9 +212,7 @@ impl Params { reader.read_exact(&mut k[..])?; let k = u32::from_le_bytes(k); - let mut n = [0u8; 8]; - reader.read_exact(&mut n[..])?; - let n = u64::from_le_bytes(n); + let n: u64 = 1 << k; let g: Vec<_> = (0..n).map(|_| C::read(reader)).collect::>()?; let g_lagrange: Vec<_> = (0..n).map(|_| C::read(reader)).collect::>()?; diff --git a/src/poly/commitment/prover.rs b/src/poly/commitment/prover.rs index 3f51865..4710821 100644 --- a/src/poly/commitment/prover.rs +++ b/src/poly/commitment/prover.rs @@ -20,7 +20,7 @@ use std::io; /// **Important:** This function assumes that the provided `transcript` has /// already seen the common inputs: the polynomial commitment P, the claimed /// opening v, and the point x. It's probably also nice for the transcript -/// to have seen the elliptic curve description and the SRS, if you want to +/// to have seen the elliptic curve description and the URS, if you want to /// be rigorous. pub fn create_proof>( params: &Params, @@ -82,7 +82,7 @@ pub fn create_proof>( } } - // Initialize the vector `G` from the SRS. We'll be progressively collapsing + // Initialize the vector `G` from the URS. We'll be progressively collapsing // this vector into smaller and smaller vectors until it is of length 1. let mut g = params.g.clone();