Use Column<Any> in Permutation::Argument

This commit is contained in:
therealyingtong 2021-02-17 21:13:25 +08:00
parent 0a3933b76a
commit a19dc68dee
12 changed files with 130 additions and 55 deletions

View File

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

View File

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

View File

@ -196,7 +196,7 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
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();

View File

@ -73,7 +73,13 @@ impl<F: FieldExt> FieldChip<F> {
advice: [Column<Advice>; 2],
instance: Column<Instance>,
) -> FieldConfig {
let perm = Permutation::new(meta, &advice);
let perm = Permutation::new(
meta,
&advice
.iter()
.map(|column| (*column).into())
.collect::<Vec<_>>(),
);
let s_mul = meta.fixed_column();
let s_pub = meta.fixed_column();

View File

@ -46,11 +46,11 @@ pub struct Permutation {
impl Permutation {
/// Configures a new permutation for the given columns.
pub fn new<F: FieldExt>(meta: &mut ConstraintSystem<F>, columns: &[Column<Advice>]) -> Self {
pub fn new<F: FieldExt>(meta: &mut ConstraintSystem<F>, columns: &[Column<Any>]) -> Self {
let index = meta.permutation(columns);
Permutation {
index,
mapping: columns.iter().map(|c| (*c).into()).collect(),
mapping: columns.iter().copied().collect(),
}
}
}

View File

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

View File

@ -397,12 +397,12 @@ impl<F: Field> Default for ConstraintSystem<F> {
}
impl<F: Field> ConstraintSystem<F> {
/// Add a permutation argument for some advice columns
pub fn permutation(&mut self, columns: &[Column<Advice>]) -> usize {
/// Add a permutation argument for some columns
pub fn permutation(&mut self, columns: &[Column<Any>]) -> 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()));

View File

@ -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<Column<Advice>>,
columns: Vec<Column<Any>>,
}
impl Argument {
pub(crate) fn new(columns: Vec<Column<Advice>>) -> Self {
pub(crate) fn new(columns: Vec<Column<Any>>) -> Self {
Argument { columns }
}
@ -40,7 +40,7 @@ impl Argument {
std::cmp::max(self.columns.len() + 1, 2)
}
pub(crate) fn get_columns(&self) -> Vec<Column<Advice>> {
pub(crate) fn get_columns(&self) -> Vec<Column<Any>> {
self.columns.clone()
}
}

View File

@ -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<C>,
pkey: &ProvingKey<C>,
advice: &[Polynomial<C::Scalar, LagrangeCoeff>],
fixed: &[Polynomial<C::Scalar, LagrangeCoeff>],
instance: &[Polynomial<C::Scalar, LagrangeCoeff>],
beta: ChallengeBeta<C>,
gamma: ChallengeGamma<C>,
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 *= &omega;
}
});
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<C: CurveAffine> Committed<C> {
p: &'a Argument,
pkey: &'a ProvingKey<C>,
advice_cosets: &'a [Polynomial<C::Scalar, ExtendedLagrangeCoeff>],
fixed_cosets: &'a [Polynomial<C::Scalar, ExtendedLagrangeCoeff>],
instance_cosets: &'a [Polynomial<C::Scalar, ExtendedLagrangeCoeff>],
beta: ChallengeBeta<C>,
gamma: ChallengeGamma<C>,
) -> (
@ -146,7 +161,6 @@ impl<C: CurveAffine> Committed<C> {
impl Iterator<Item = Polynomial<C::Scalar, ExtendedLagrangeCoeff>> + 'a,
) {
let domain = &pk.vk.domain;
let expressions = iter::empty()
// l_0(X) * (1 - z(X)) = 0
.chain(Some(
@ -155,21 +169,29 @@ impl<C: CurveAffine> Committed<C> {
// 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<C: CurveAffine> Committed<C> {
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<C: CurveAffine> Constructed<C> {
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))

View File

@ -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<C: CurveAffine> Evaluated<C> {
vk: &'a plonk::VerifyingKey<C>,
p: &'a Argument,
advice_evals: &'a [C::Scalar],
fixed_evals: &[C::Scalar],
instance_evals: &'a [C::Scalar],
l_0: C::Scalar,
beta: ChallengeBeta<C>,
gamma: ChallengeGamma<C>,
@ -85,23 +88,35 @@ impl<C: CurveAffine> Evaluated<C> {
// - 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 + &current_delta + &*gamma);
right *= &(eval + &current_delta + &*gamma);
current_delta *= &C::Scalar::DELTA;
}

View File

@ -275,9 +275,10 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
// Sample gamma challenge
let gamma = ChallengeGamma::get(transcript);
let permutations: Vec<Vec<permutation::prover::Committed<C>>> = advice
let permutations: Vec<Vec<permutation::prover::Committed<C>>> = instance
.iter()
.map(|advice| -> Result<Vec<_>, Error> {
.zip(advice.iter())
.map(|(instance, advice)| -> Result<Vec<_>, Error> {
// Commit to permutations, if any.
pk.vk
.cs
@ -290,6 +291,8 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
pk,
pkey,
&advice.advice_values,
&pk.fixed_values,
&instance.instance_values,
beta,
gamma,
transcript,
@ -316,14 +319,24 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
let (permutations, permutation_expressions): (Vec<Vec<_>>, 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();

View File

@ -158,6 +158,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|(((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<C>>(
.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<C>>(
beta,
gamma,
&advice_evals,
&fixed_evals_copy,
&fixed_evals_copy_copy,
&instance_evals,
)
})