Pass Expressions to meta.lookup()

This commit is contained in:
therealyingtong 2021-02-10 19:36:25 +08:00 committed by Sean Bowe
parent 9401ceb68d
commit d8534e1c50
No known key found for this signature in database
GPG key ID: 95684257D8F8B031
7 changed files with 76 additions and 52 deletions

View file

@ -283,8 +283,12 @@ fn main() {
* ... ... ... 0 0 * ... ... ... 0 0
* ] * ]
*/ */
meta.lookup(&[a.into()], &[sl.into()]); let a_ = meta.query_any(a.into(), Rotation::cur());
meta.lookup(&[a.into(), b.into()], &[sl.into(), sl2.into()]); let b_ = meta.query_any(b.into(), Rotation::cur());
let sl_ = meta.query_any(sl.into(), Rotation::cur());
let sl2_ = meta.query_any(sl2.into(), Rotation::cur());
meta.lookup(&[a_.clone()], &[sl_.clone()]);
meta.lookup(&[a_, b_], &[sl_, sl2_]);
meta.create_gate("Combined add-mult", |meta| { meta.create_gate("Combined add-mult", |meta| {
let d = meta.query_advice(d, Rotation::next()); let d = meta.query_advice(d, Rotation::next());

View file

@ -5,8 +5,8 @@ use ff::Field;
use crate::{ use crate::{
arithmetic::{FieldExt, Group}, arithmetic::{FieldExt, Group},
plonk::{ plonk::{
permutation, Advice, Any, Assignment, Circuit, Column, ColumnType, ConstraintSystem, Error, permutation, Advice, Assignment, Circuit, Column, ColumnType, ConstraintSystem, Error,
Fixed, Expression, Fixed,
}, },
poly::Rotation, poly::Rotation,
}; };
@ -143,7 +143,7 @@ pub enum VerifyFailure {
/// ); /// );
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
pub struct MockProver<F: Group> { pub struct MockProver<F: Group + Field> {
n: u32, n: u32,
cs: ConstraintSystem<F>, cs: ConstraintSystem<F>,
@ -316,10 +316,21 @@ impl<F: FieldExt> MockProver<F> {
// Check that all lookups exist in their respective tables. // Check that all lookups exist in their respective tables.
for (lookup_index, lookup) in self.cs.lookups.iter().enumerate() { for (lookup_index, lookup) in self.cs.lookups.iter().enumerate() {
for input_row in 0..n { for input_row in 0..n {
let load = |column: &Column<Any>, row| match column.column_type() { let load = |column: &Expression<F>, row| match column {
Any::Fixed => self.fixed[column.index()][row as usize], Expression::Fixed(index) => {
Any::Advice => self.advice[column.index()][row as usize], let column_index = self.cs.fixed_queries[*index].0.index();
Any::Instance => self.instance[column.index()][row as usize], self.fixed[column_index][row as usize]
}
Expression::Advice(index) => {
let column_index = self.cs.advice_queries[*index].0.index();
self.advice[column_index][row as usize]
}
Expression::Instance(index) => {
let column_index = self.cs.instance_queries[*index].0.index();
self.instance[column_index][row as usize]
}
// TODO: other Expression variants
_ => unreachable!(),
}; };
let inputs: Vec<_> = lookup let inputs: Vec<_> = lookup

View file

@ -467,8 +467,12 @@ fn test_proving() {
* ... ... ... 0 0 * ... ... ... 0 0
* ] * ]
*/ */
meta.lookup(&[a.into()], &[sl.into()]); let a_ = meta.query_any(a.into(), Rotation::cur());
meta.lookup(&[a.into(), b.into()], &[sl.into(), sl2.into()]); let b_ = meta.query_any(b.into(), Rotation::cur());
let sl_ = meta.query_any(sl.into(), Rotation::cur());
let sl2_ = meta.query_any(sl2.into(), Rotation::cur());
meta.lookup(&[a_.clone()], &[sl_.clone()]);
meta.lookup(&[a_, b_], &[sl_, sl2_]);
meta.create_gate("Combined add-mult", |meta| { meta.create_gate("Combined add-mult", |meta| {
let d = meta.query_advice(d, Rotation::next()); let d = meta.query_advice(d, Rotation::next());

View file

@ -15,8 +15,10 @@ pub trait ColumnType: 'static + Sized + std::fmt::Debug {}
/// A column with an index and type /// A column with an index and type
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Column<C: ColumnType> { pub struct Column<C: ColumnType> {
index: usize, /// Index of column
column_type: C, pub index: usize,
/// Type of column
pub column_type: C,
} }
impl<C: ColumnType> Column<C> { impl<C: ColumnType> Column<C> {
@ -362,7 +364,7 @@ pub(crate) struct PointIndex(pub usize);
/// This is a description of the circuit environment, such as the gate, column and /// This is a description of the circuit environment, such as the gate, column and
/// permutation arrangements. /// permutation arrangements.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ConstraintSystem<F> { pub struct ConstraintSystem<F: Field> {
pub(crate) num_fixed_columns: usize, pub(crate) num_fixed_columns: usize,
pub(crate) num_advice_columns: usize, pub(crate) num_advice_columns: usize,
pub(crate) num_instance_columns: usize, pub(crate) num_instance_columns: usize,
@ -377,7 +379,7 @@ pub struct ConstraintSystem<F> {
// Vector of lookup arguments, where each corresponds to a sequence of // Vector of lookup arguments, where each corresponds to a sequence of
// input columns and a sequence of table columns involved in the lookup. // input columns and a sequence of table columns involved in the lookup.
pub(crate) lookups: Vec<lookup::Argument>, pub(crate) lookups: Vec<lookup::Argument<F>>,
} }
/// Represents the minimal parameters that determine a `ConstraintSystem`. /// Represents the minimal parameters that determine a `ConstraintSystem`.
@ -456,19 +458,13 @@ impl<F: Field> ConstraintSystem<F> {
/// columns are not the same. /// columns are not the same.
pub fn lookup( pub fn lookup(
&mut self, &mut self,
input_columns: &[Column<Any>], input_columns: &[Expression<F>],
table_columns: &[Column<Any>], table_columns: &[Expression<F>],
) -> usize { ) -> usize {
assert_eq!(input_columns.len(), table_columns.len()); assert_eq!(input_columns.len(), table_columns.len());
let index = self.lookups.len(); let index = self.lookups.len();
for input in input_columns {
self.query_any_index(*input, Rotation::cur());
}
for table in table_columns {
self.query_any_index(*table, Rotation::cur());
}
self.lookups self.lookups
.push(lookup::Argument::new(input_columns, table_columns)); .push(lookup::Argument::new(input_columns, table_columns));

View file

@ -1,16 +1,17 @@
use super::circuit::{Any, Column}; use super::circuit::Expression;
use ff::Field;
pub(crate) mod prover; pub(crate) mod prover;
pub(crate) mod verifier; pub(crate) mod verifier;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Argument { pub(crate) struct Argument<F: Field> {
pub input_columns: Vec<Column<Any>>, pub input_columns: Vec<Expression<F>>,
pub table_columns: Vec<Column<Any>>, pub table_columns: Vec<Expression<F>>,
} }
impl Argument { impl<F: Field> Argument<F> {
pub fn new(input_columns: &[Column<Any>], table_columns: &[Column<Any>]) -> Self { pub fn new(input_columns: &[Expression<F>], table_columns: &[Expression<F>]) -> Self {
assert_eq!(input_columns.len(), table_columns.len()); assert_eq!(input_columns.len(), table_columns.len());
Argument { Argument {
input_columns: input_columns.to_vec(), input_columns: input_columns.to_vec(),

View file

@ -1,5 +1,5 @@
use super::super::{ use super::super::{
circuit::{Any, Column}, circuit::{Advice, Aux, Column, Expression, Fixed},
ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, ProvingKey, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, ProvingKey,
}; };
use super::Argument; use super::Argument;
@ -57,7 +57,7 @@ pub(in crate::plonk) struct Evaluated<C: CurveAffine> {
constructed: Constructed<C>, constructed: Constructed<C>,
} }
impl Argument { impl<F: FieldExt> Argument<F> {
/// Given a Lookup with input columns [A_0, A_1, ..., A_{m-1}] and table columns /// Given a Lookup with input columns [A_0, A_1, ..., A_{m-1}] and table columns
/// [S_0, S_1, ..., S_{m-1}], this method /// [S_0, S_1, ..., S_{m-1}], this method
/// - constructs A_compressed = \theta^{m-1} A_0 + theta^{m-2} A_1 + ... + \theta A_{m-2} + A_{m-1} /// - constructs A_compressed = \theta^{m-1} A_0 + theta^{m-2} A_1 + ... + \theta A_{m-2} + A_{m-1}
@ -82,20 +82,27 @@ impl Argument {
transcript: &mut T, transcript: &mut T,
) -> Result<Permuted<'a, C>, Error> { ) -> Result<Permuted<'a, C>, Error> {
// Closure to get values of columns and compress them // Closure to get values of columns and compress them
let compress_columns = |columns: &[Column<Any>]| { let compress_columns = |columns: &[Expression<F>]| {
// Values of input columns involved in the lookup // Values of input columns involved in the lookup
let (unpermuted_columns, unpermuted_cosets): (Vec<_>, Vec<_>) = columns let (unpermuted_columns, unpermuted_cosets): (Vec<_>, Vec<_>) = columns
.iter() .iter()
.map(|&column| { .map(|column| {
let (values, cosets) = match column.column_type() { match column {
Any::Advice => (advice_values, advice_cosets), Expression::Advice(index) => {
Any::Fixed => (fixed_values, fixed_cosets), let column_index = pk.vk.cs.advice_queries[*index].0.index();
Any::Instance => (instance_values, instance_cosets), (&advice_values[column_index], &advice_cosets[*index])
}; }
( Expression::Fixed(index) => {
&values[column.index()], let column_index = pk.vk.cs.fixed_queries[*index].0.index();
&cosets[pk.vk.cs.get_any_query_index(column, Rotation::cur())], (&fixed_values[column_index], &fixed_cosets[*index])
) }
Expression::Instance(index) => {
let column_index = pk.vk.cs.instance_queries[*index].0.index();
(&instance_values[column_index], &instance_cosets[*index])
}
// TODO: other Expression variants
_ => unreachable!(),
}
}) })
.unzip(); .unzip();

View file

@ -1,9 +1,9 @@
use std::iter; use std::iter;
use super::super::circuit::{Any, Column}; use super::super::circuit::{Advice, Aux, Column, Expression, Fixed};
use super::Argument; use super::Argument;
use crate::{ use crate::{
arithmetic::CurveAffine, arithmetic::{CurveAffine, FieldExt},
plonk::{ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, VerifyingKey}, plonk::{ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, VerifyingKey},
poly::{multiopen::VerifierQuery, Rotation}, poly::{multiopen::VerifierQuery, Rotation},
transcript::TranscriptRead, transcript::TranscriptRead,
@ -29,7 +29,7 @@ pub struct Evaluated<C: CurveAffine> {
permuted_table_eval: C::Scalar, permuted_table_eval: C::Scalar,
} }
impl Argument { impl<F: FieldExt> Argument<F> {
pub(in crate::plonk) fn read_permuted_commitments<C: CurveAffine, T: TranscriptRead<C>>( pub(in crate::plonk) fn read_permuted_commitments<C: CurveAffine, T: TranscriptRead<C>>(
&self, &self,
transcript: &mut T, transcript: &mut T,
@ -101,7 +101,7 @@ impl<C: CurveAffine> Evaluated<C> {
&'a self, &'a self,
vk: &'a VerifyingKey<C>, vk: &'a VerifyingKey<C>,
l_0: C::Scalar, l_0: C::Scalar,
argument: &'a Argument, argument: &'a Argument<C::Scalar>,
theta: ChallengeTheta<C>, theta: ChallengeTheta<C>,
beta: ChallengeBeta<C>, beta: ChallengeBeta<C>,
gamma: ChallengeGamma<C>, gamma: ChallengeGamma<C>,
@ -116,15 +116,16 @@ impl<C: CurveAffine> Evaluated<C> {
* &(self.permuted_input_eval + &*beta) * &(self.permuted_input_eval + &*beta)
* &(self.permuted_table_eval + &*gamma); * &(self.permuted_table_eval + &*gamma);
let compress_columns = |columns: &[Column<Any>]| { let compress_columns = |columns: &[Expression<C::Scalar>]| {
columns columns
.iter() .iter()
.map(|column| { .map(|column| {
let index = vk.cs.get_any_query_index(*column, Rotation::cur()); match column {
match column.column_type() { Expression::Advice(index) => advice_evals[*index],
Any::Advice => advice_evals[index], Expression::Fixed(index) => fixed_evals[*index],
Any::Fixed => fixed_evals[index], Expression::Instance(index) => instance_evals[*index],
Any::Instance => instance_evals[index], // TODO: other Expression variants
_ => unreachable!(),
} }
}) })
.fold(C::Scalar::zero(), |acc, eval| acc * &*theta + &eval) .fold(C::Scalar::zero(), |acc, eval| acc * &*theta + &eval)