From a19dc68deeb60b2edd38af214b64a9f598a31a14 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 17 Feb 2021 21:13:25 +0800 Subject: [PATCH] Use Column in Permutation::Argument --- benches/plonk.rs | 2 +- examples/circuit-layout.rs | 4 +- examples/performance_model.rs | 2 +- examples/simple-example.rs | 8 ++- src/circuit.rs | 4 +- src/plonk.rs | 4 +- src/plonk/circuit.rs | 6 +-- src/plonk/permutation.rs | 8 +-- src/plonk/permutation/prover.rs | 82 +++++++++++++++++++++---------- src/plonk/permutation/verifier.rs | 29 ++++++++--- src/plonk/prover.rs | 21 ++++++-- src/plonk/verifier.rs | 15 +++++- 12 files changed, 130 insertions(+), 55 deletions(-) diff --git a/benches/plonk.rs b/benches/plonk.rs index 3df2e852..7e264fff 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -182,7 +182,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) { let b = meta.advice_column(); let c = meta.advice_column(); - let perm = meta.permutation(&[a, b, c]); + let perm = meta.permutation(&[a.into(), b.into(), c.into()]); let sm = meta.fixed_column(); let sa = meta.fixed_column(); diff --git a/examples/circuit-layout.rs b/examples/circuit-layout.rs index a603deff..045e50e3 100644 --- a/examples/circuit-layout.rs +++ b/examples/circuit-layout.rs @@ -257,8 +257,8 @@ fn main() { let d = meta.advice_column(); let p = meta.instance_column(); - let perm = meta.permutation(&[a, b, c]); - let perm2 = meta.permutation(&[a, b, c]); + let perm = meta.permutation(&[a.into(), b.into(), c.into()]); + let perm2 = meta.permutation(&[a.into(), b.into(), c.into()]); let sm = meta.fixed_column(); let sa = meta.fixed_column(); diff --git a/examples/performance_model.rs b/examples/performance_model.rs index b89ad295..5f03efb6 100644 --- a/examples/performance_model.rs +++ b/examples/performance_model.rs @@ -196,7 +196,7 @@ impl Circuit for MyCircuit { let c = meta.advice_column(); let p = meta.instance_column(); - let perm = meta.permutation(&[a, b, c]); + let perm = meta.permutation(&[a.into(), b.into(), c.into()]); let sm = meta.fixed_column(); let sa = meta.fixed_column(); diff --git a/examples/simple-example.rs b/examples/simple-example.rs index 56d53df9..0acc59b9 100644 --- a/examples/simple-example.rs +++ b/examples/simple-example.rs @@ -73,7 +73,13 @@ impl FieldChip { advice: [Column; 2], instance: Column, ) -> FieldConfig { - let perm = Permutation::new(meta, &advice); + let perm = Permutation::new( + meta, + &advice + .iter() + .map(|column| (*column).into()) + .collect::>(), + ); let s_mul = meta.fixed_column(); let s_pub = meta.fixed_column(); diff --git a/src/circuit.rs b/src/circuit.rs index e9ad2995..8658ad0a 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -46,11 +46,11 @@ pub struct Permutation { impl Permutation { /// Configures a new permutation for the given columns. - pub fn new(meta: &mut ConstraintSystem, columns: &[Column]) -> Self { + pub fn new(meta: &mut ConstraintSystem, columns: &[Column]) -> Self { let index = meta.permutation(columns); Permutation { index, - mapping: columns.iter().map(|c| (*c).into()).collect(), + mapping: columns.iter().copied().collect(), } } } diff --git a/src/plonk.rs b/src/plonk.rs index bffe2ae6..598d683e 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -396,8 +396,8 @@ fn test_proving() { let d = meta.advice_column(); let p = meta.instance_column(); - let perm = meta.permutation(&[a, b, c]); - let perm2 = meta.permutation(&[a, b, c]); + let perm = meta.permutation(&[a.into(), b.into(), c.into()]); + let perm2 = meta.permutation(&[a.into(), b.into(), c.into()]); let sm = meta.fixed_column(); let sa = meta.fixed_column(); diff --git a/src/plonk/circuit.rs b/src/plonk/circuit.rs index ff925b2f..e8dfcfcc 100644 --- a/src/plonk/circuit.rs +++ b/src/plonk/circuit.rs @@ -397,12 +397,12 @@ impl Default for ConstraintSystem { } impl ConstraintSystem { - /// Add a permutation argument for some advice columns - pub fn permutation(&mut self, columns: &[Column]) -> usize { + /// Add a permutation argument for some columns + pub fn permutation(&mut self, columns: &[Column]) -> usize { let index = self.permutations.len(); for column in columns { - self.query_advice_index(*column, Rotation::cur()); + self.query_any_index(*column, Rotation::cur()); } self.permutations .push(permutation::Argument::new(columns.to_vec())); diff --git a/src/plonk/permutation.rs b/src/plonk/permutation.rs index 89f178dd..dffa01c5 100644 --- a/src/plonk/permutation.rs +++ b/src/plonk/permutation.rs @@ -1,6 +1,6 @@ //! Implementation of a PLONK permutation argument. -use super::circuit::{Advice, Column}; +use super::circuit::{Any, Column}; use crate::{ arithmetic::CurveAffine, poly::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, @@ -16,11 +16,11 @@ use std::io; #[derive(Debug, Clone)] pub(crate) struct Argument { /// A sequence of columns involved in the argument. - columns: Vec>, + columns: Vec>, } impl Argument { - pub(crate) fn new(columns: Vec>) -> Self { + pub(crate) fn new(columns: Vec>) -> Self { Argument { columns } } @@ -40,7 +40,7 @@ impl Argument { std::cmp::max(self.columns.len() + 1, 2) } - pub(crate) fn get_columns(&self) -> Vec> { + pub(crate) fn get_columns(&self) -> Vec> { self.columns.clone() } } diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index 843e4324..b0a3f300 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -1,6 +1,7 @@ use ff::Field; use std::iter; +use super::super::circuit::Any; use super::{Argument, ProvingKey}; use crate::{ arithmetic::{eval_polynomial, parallelize, BatchInvert, Curve, CurveAffine, FieldExt}, @@ -36,6 +37,8 @@ impl Argument { pk: &plonk::ProvingKey, pkey: &ProvingKey, advice: &[Polynomial], + fixed: &[Polynomial], + instance: &[Polynomial], beta: ChallengeBeta, gamma: ChallengeGamma, transcript: &mut T, @@ -47,53 +50,63 @@ impl Argument { // (p_j(\omega^i) + \delta^j \omega^i \beta + \gamma) / // (p_j(\omega^i) + \beta s_j(\omega^i) + \gamma) // - // where p_j(X) is the jth advice column in this permutation, + // where p_j(X) is the jth column in this permutation, // and i is the ith row of the column. - let mut modified_advice = vec![C::Scalar::one(); params.n as usize]; + let mut modified_values = vec![C::Scalar::one(); params.n as usize]; // Iterate over each column of the permutation for (&column, permuted_column_values) in self.columns.iter().zip(pkey.permutations.iter()) { - parallelize(&mut modified_advice, |modified_advice, start| { - for ((modified_advice, advice_value), permuted_advice_value) in modified_advice + let values = match column.column_type() { + Any::Advice => advice, + Any::Fixed => fixed, + Any::Instance => instance, + }; + parallelize(&mut modified_values, |modified_values, start| { + for ((modified_values, value), permuted_value) in modified_values .iter_mut() - .zip(advice[column.index()][start..].iter()) + .zip(values[column.index()][start..].iter()) .zip(permuted_column_values[start..].iter()) { - *modified_advice *= &(*beta * permuted_advice_value + &*gamma + advice_value); + *modified_values *= &(*beta * permuted_value + &*gamma + value); } }); } // Invert to obtain the denominator for the permutation product polynomial - modified_advice.batch_invert(); + modified_values.batch_invert(); // Iterate over each column again, this time finishing the computation // of the entire fraction by computing the numerators let mut deltaomega = C::Scalar::one(); for &column in self.columns.iter() { let omega = domain.get_omega(); - parallelize(&mut modified_advice, |modified_advice, start| { + let values = match column.column_type() { + Any::Advice => advice, + Any::Fixed => fixed, + Any::Instance => instance, + }; + parallelize(&mut modified_values, |modified_values, start| { let mut deltaomega = deltaomega * &omega.pow_vartime(&[start as u64, 0, 0, 0]); - for (modified_advice, advice_value) in modified_advice + for (modified_values, value) in modified_values .iter_mut() - .zip(advice[column.index()][start..].iter()) + .zip(values[column.index()][start..].iter()) { // Multiply by p_j(\omega^i) + \delta^j \omega^i \beta - *modified_advice *= &(deltaomega * &*beta + &*gamma + advice_value); + *modified_values *= &(deltaomega * &*beta + &*gamma + value); deltaomega *= ω } }); deltaomega *= &C::Scalar::DELTA; } - // The modified_advice vector is a vector of products of fractions + // The modified_values vector is a vector of products of fractions // of the form // // (p_j(\omega^i) + \delta^j \omega^i \beta + \gamma) / // (p_j(\omega^i) + \beta s_j(\omega^i) + \gamma) // - // where i is the index into modified_advice, for the jth column in + // where i is the index into modified_values, for the jth column in // the permutation // Compute the evaluations of the permutation product polynomial @@ -102,7 +115,7 @@ impl Argument { for row in 1..(params.n as usize) { let mut tmp = z[row - 1]; - tmp *= &modified_advice[row]; + tmp *= &modified_values[row]; z.push(tmp); } let z = domain.lagrange_from_vec(z); @@ -139,6 +152,8 @@ impl Committed { p: &'a Argument, pkey: &'a ProvingKey, advice_cosets: &'a [Polynomial], + fixed_cosets: &'a [Polynomial], + instance_cosets: &'a [Polynomial], beta: ChallengeBeta, gamma: ChallengeGamma, ) -> ( @@ -146,7 +161,6 @@ impl Committed { impl Iterator> + 'a, ) { let domain = &pk.vk.domain; - let expressions = iter::empty() // l_0(X) * (1 - z(X)) = 0 .chain(Some( @@ -155,21 +169,29 @@ impl Committed { // z(X) \prod (p(X) + \beta s_i(X) + \gamma) - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma) .chain(Some({ let mut left = self.permutation_product_coset.clone(); - for (advice, permutation) in p + for (values, permutation) in p .columns .iter() - .map(|&column| { - &advice_cosets[pk.vk.cs.get_advice_query_index(column, Rotation::cur())] + .map(|&column| match column.column_type() { + Any::Advice => { + &advice_cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())] + } + Any::Fixed => { + &fixed_cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())] + } + Any::Instance => { + &instance_cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())] + } }) .zip(pkey.cosets.iter()) { parallelize(&mut left, |left, start| { - for ((left, advice), permutation) in left + for ((left, value), permutation) in left .iter_mut() - .zip(advice[start..].iter()) + .zip(values[start..].iter()) .zip(permutation[start..].iter()) { - *left *= &(*advice + &(*beta * permutation) + &*gamma); + *left *= &(*value + &(*beta * permutation) + &*gamma); } }); } @@ -177,14 +199,22 @@ impl Committed { let mut right = self.permutation_product_coset_inv.clone(); let mut current_delta = *beta * &C::Scalar::ZETA; let step = domain.get_extended_omega(); - for advice in p.columns.iter().map(|&column| { - &advice_cosets[pk.vk.cs.get_advice_query_index(column, Rotation::cur())] + for values in p.columns.iter().map(|&column| match column.column_type() { + Any::Advice => { + &advice_cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())] + } + Any::Fixed => { + &fixed_cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())] + } + Any::Instance => { + &instance_cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())] + } }) { parallelize(&mut right, move |right, start| { let mut beta_term = current_delta * &step.pow_vartime(&[start as u64, 0, 0, 0]); - for (right, advice) in right.iter_mut().zip(advice[start..].iter()) { - *right *= &(*advice + &beta_term + &*gamma); + for (right, value) in right.iter_mut().zip(values[start..].iter()) { + *right *= &(*value + &beta_term + &*gamma); beta_term *= &step; } }); @@ -240,7 +270,7 @@ impl Constructed { let permutation_evals = pkey.evaluate(x); - // Hash each advice evaluation + // Hash permutation product evals for eval in iter::empty() .chain(Some(&permutation_product_eval)) .chain(Some(&permutation_product_inv_eval)) diff --git a/src/plonk/permutation/verifier.rs b/src/plonk/permutation/verifier.rs index 9f865e7b..74471aec 100644 --- a/src/plonk/permutation/verifier.rs +++ b/src/plonk/permutation/verifier.rs @@ -1,6 +1,7 @@ use ff::Field; use std::iter; +use super::super::circuit::Any; use super::{Argument, VerifyingKey}; use crate::{ arithmetic::{CurveAffine, FieldExt}, @@ -71,6 +72,8 @@ impl Evaluated { vk: &'a plonk::VerifyingKey, p: &'a Argument, advice_evals: &'a [C::Scalar], + fixed_evals: &[C::Scalar], + instance_evals: &'a [C::Scalar], l_0: C::Scalar, beta: ChallengeBeta, gamma: ChallengeGamma, @@ -85,23 +88,35 @@ impl Evaluated { // - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma) .chain(Some({ let mut left = self.permutation_product_eval; - for (advice_eval, permutation_eval) in p + for (eval, permutation_eval) in p .columns .iter() - .map(|&column| { - advice_evals[vk.cs.get_advice_query_index(column, Rotation::cur())] + .map(|&column| match column.column_type() { + Any::Advice => { + advice_evals[vk.cs.get_any_query_index(column, Rotation::cur())] + } + Any::Fixed => { + fixed_evals[vk.cs.get_any_query_index(column, Rotation::cur())] + } + Any::Instance => { + instance_evals[vk.cs.get_any_query_index(column, Rotation::cur())] + } }) .zip(self.permutation_evals.iter()) { - left *= &(advice_eval + &(*beta * permutation_eval) + &*gamma); + left *= &(eval + &(*beta * permutation_eval) + &*gamma); } let mut right = self.permutation_product_inv_eval; let mut current_delta = *beta * &*x; - for advice_eval in p.columns.iter().map(|&column| { - advice_evals[vk.cs.get_advice_query_index(column, Rotation::cur())] + for eval in p.columns.iter().map(|&column| match column.column_type() { + Any::Advice => advice_evals[vk.cs.get_any_query_index(column, Rotation::cur())], + Any::Fixed => fixed_evals[vk.cs.get_any_query_index(column, Rotation::cur())], + Any::Instance => { + instance_evals[vk.cs.get_any_query_index(column, Rotation::cur())] + } }) { - right *= &(advice_eval + ¤t_delta + &*gamma); + right *= &(eval + ¤t_delta + &*gamma); current_delta *= &C::Scalar::DELTA; } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 525bdf53..038b12d5 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -275,9 +275,10 @@ pub fn create_proof, ConcreteCircuit: Circ // Sample gamma challenge let gamma = ChallengeGamma::get(transcript); - let permutations: Vec>> = advice + let permutations: Vec>> = instance .iter() - .map(|advice| -> Result, Error> { + .zip(advice.iter()) + .map(|(instance, advice)| -> Result, Error> { // Commit to permutations, if any. pk.vk .cs @@ -290,6 +291,8 @@ pub fn create_proof, ConcreteCircuit: Circ pk, pkey, &advice.advice_values, + &pk.fixed_values, + &instance.instance_values, beta, gamma, transcript, @@ -316,14 +319,24 @@ pub fn create_proof, ConcreteCircuit: Circ let (permutations, permutation_expressions): (Vec>, Vec>) = permutations .into_iter() .zip(advice.iter()) - .map(|(permutations, advice)| { + .zip(instance.iter()) + .map(|((permutations, advice), instance)| { // Evaluate the h(X) polynomial's constraint system expressions for the permutation constraints, if any. let tmp: Vec<_> = permutations .into_iter() .zip(pk.vk.cs.permutations.iter()) .zip(pk.permutations.iter()) .map(|((p, argument), pkey)| { - p.construct(pk, argument, pkey, &advice.advice_cosets, beta, gamma) + p.construct( + pk, + argument, + pkey, + &advice.advice_cosets, + &pk.fixed_cosets, + &instance.instance_cosets, + beta, + gamma, + ) }) .collect(); diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 283141f3..6d1f7219 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -158,6 +158,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead>( |(((advice_evals, instance_evals), permutations), lookups)| { let fixed_evals = fixed_evals.clone(); let fixed_evals_copy = fixed_evals.clone(); + let fixed_evals_copy_copy = fixed_evals.clone(); std::iter::empty() // Evaluate the circuit using the custom gates provided @@ -176,7 +177,17 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead>( .iter() .zip(vk.cs.permutations.iter()) .flat_map(move |(p, argument)| { - p.expressions(vk, argument, &advice_evals, l_0, beta, gamma, x) + p.expressions( + vk, + argument, + &advice_evals, + &fixed_evals_copy, + &instance_evals, + l_0, + beta, + gamma, + x, + ) }) .into_iter(), ) @@ -193,7 +204,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead>( beta, gamma, &advice_evals, - &fixed_evals_copy, + &fixed_evals_copy_copy, &instance_evals, ) })