mirror of https://github.com/zcash/halo2.git
Use Column<Any> in Permutation::Argument
This commit is contained in:
parent
0a3933b76a
commit
a19dc68dee
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 *= ω
|
||||
}
|
||||
});
|
||||
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))
|
||||
|
|
|
@ -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 + ¤t_delta + &*gamma);
|
||||
right *= &(eval + ¤t_delta + &*gamma);
|
||||
current_delta *= &C::Scalar::DELTA;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue