Introduce Column struct and ColumnType trait

This commit is contained in:
therealyingtong 2020-11-06 11:25:50 +08:00
parent 2034179d82
commit 075988ae4e
5 changed files with 175 additions and 74 deletions

View file

@ -114,28 +114,29 @@ fn test_proving() {
use crate::arithmetic::{Curve, EqAffine, Field, Fp, Fq};
use crate::poly::commitment::{Blind, Params};
use crate::transcript::DummyHash;
use circuit::{Advice, Column, Fixed};
use std::marker::PhantomData;
const K: u32 = 5;
/// This represents an advice column at a certain row in the ConstraintSystem
#[derive(Copy, Clone, Debug)]
pub struct Variable(AdviceColumn, usize);
pub struct Variable(Column<Advice>, usize);
// Initialize the polynomial commitment parameters
let params: Params<EqAffine> = Params::new::<DummyHash<Fq>>(K);
struct PLONKConfig {
a: AdviceColumn,
b: AdviceColumn,
c: AdviceColumn,
d: AdviceColumn,
e: AdviceColumn,
a: Column<Advice>,
b: Column<Advice>,
c: Column<Advice>,
d: Column<Advice>,
e: Column<Advice>,
sa: FixedColumn,
sb: FixedColumn,
sc: FixedColumn,
sm: FixedColumn,
sp: FixedColumn,
sa: Column<Fixed>,
sb: Column<Fixed>,
sc: Column<Fixed>,
sm: Column<Fixed>,
sp: Column<Fixed>,
perm: usize,
perm2: usize,

View file

@ -4,19 +4,99 @@ use std::collections::BTreeMap;
use super::Error;
use crate::arithmetic::Field;
use crate::poly::Rotation;
/// This represents a column which has a fixed (permanent) value
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct FixedColumn(pub usize);
/// This represents a column which has a witness-specific value
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct AdviceColumn(pub usize);
/// A column type
pub trait ColumnType: 'static + Sized {}
/// This represents a column which has an externally assigned value
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct AuxColumn(pub usize);
/// A column with an index and type
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Column<C: ColumnType> {
pub(crate) index: usize,
pub(crate) column_type: C,
}
/// An advice column
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Advice;
/// A fixed column
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Fixed;
/// An auxiliary column
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Aux;
/// An enum over the Advice, Fixed, Aux structs
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Any {
/// An Advice variant
Advice,
/// A Fixed variant
Fixed,
/// An Auxiliary variant
Aux,
}
impl ColumnType for Advice {}
impl ColumnType for Fixed {}
impl ColumnType for Aux {}
impl ColumnType for Any {}
impl From<Column<Advice>> for Column<Any> {
fn from(advice: Column<Advice>) -> Column<Any> {
Column {
index: advice.index,
column_type: Any::Advice,
}
}
}
impl From<Column<Fixed>> for Column<Any> {
fn from(advice: Column<Fixed>) -> Column<Any> {
Column {
index: advice.index,
column_type: Any::Fixed,
}
}
}
impl From<Column<Aux>> for Column<Any> {
fn from(advice: Column<Aux>) -> Column<Any> {
Column {
index: advice.index,
column_type: Any::Aux,
}
}
}
impl From<Column<Any>> for Column<Advice> {
fn from(any: Column<Any>) -> Column<Advice> {
Column {
index: any.index,
column_type: Advice,
}
}
}
impl From<Column<Any>> for Column<Fixed> {
fn from(any: Column<Any>) -> Column<Fixed> {
Column {
index: any.index,
column_type: Fixed,
}
}
}
impl From<Column<Any>> for Column<Aux> {
fn from(any: Column<Any>) -> Column<Aux> {
Column {
index: any.index,
column_type: Aux,
}
}
}
/// This trait allows a [`Circuit`] to direct some backend to assign a witness
/// for a constraint system.
@ -24,7 +104,7 @@ pub trait Assignment<F: Field> {
/// Assign an advice column value (witness)
fn assign_advice(
&mut self,
column: AdviceColumn,
column: Column<Advice>,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error>;
@ -32,7 +112,7 @@ pub trait Assignment<F: Field> {
/// Assign a fixed value
fn assign_fixed(
&mut self,
column: FixedColumn,
column: Column<Fixed>,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error>;
@ -197,16 +277,16 @@ pub struct ConstraintSystem<F> {
pub(crate) num_advice_columns: usize,
pub(crate) num_aux_columns: usize,
pub(crate) gates: Vec<Expression<F>>,
pub(crate) advice_queries: Vec<(AdviceColumn, Rotation)>,
pub(crate) aux_queries: Vec<(AuxColumn, Rotation)>,
pub(crate) fixed_queries: Vec<(FixedColumn, Rotation)>,
pub(crate) advice_queries: Vec<(Column<Advice>, Rotation)>,
pub(crate) aux_queries: Vec<(Column<Aux>, Rotation)>,
pub(crate) fixed_queries: Vec<(Column<Fixed>, Rotation)>,
// Mapping from a witness vector rotation to the index in the point vector.
pub(crate) rotations: BTreeMap<Rotation, PointIndex>,
// Vector of permutation arguments, where each corresponds to a set of columns
// that are involved in a permutation argument.
pub(crate) permutations: Vec<Vec<AdviceColumn>>,
pub(crate) permutations: Vec<Vec<Column<Advice>>>,
}
impl<F: Field> Default for ConstraintSystem<F> {
@ -230,7 +310,7 @@ 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: &[AdviceColumn]) -> usize {
pub fn permutation(&mut self, columns: &[Column<Advice>]) -> usize {
let index = self.permutations.len();
if self.permutations.is_empty() {
let at = Rotation(-1);
@ -246,7 +326,7 @@ impl<F: Field> ConstraintSystem<F> {
index
}
fn query_fixed_index(&mut self, column: FixedColumn, at: i32) -> usize {
fn query_fixed_index(&mut self, column: Column<Fixed>, at: i32) -> usize {
let at = Rotation(at);
{
let len = self.rotations.len();
@ -268,22 +348,11 @@ impl<F: Field> ConstraintSystem<F> {
}
/// Query a fixed column at a relative position
pub fn query_fixed(&mut self, column: FixedColumn, at: i32) -> Expression<F> {
pub fn query_fixed(&mut self, column: Column<Fixed>, at: i32) -> Expression<F> {
Expression::Fixed(self.query_fixed_index(column, at))
}
pub(crate) fn get_advice_query_index(&self, column: AdviceColumn, at: i32) -> usize {
let at = Rotation(at);
for (index, advice_query) in self.advice_queries.iter().enumerate() {
if advice_query == &(column, at) {
return index;
}
}
panic!("get_advice_query_index called for non-existant query");
}
pub(crate) fn query_advice_index(&mut self, column: AdviceColumn, at: i32) -> usize {
pub(crate) fn query_advice_index(&mut self, column: Column<Advice>, at: i32) -> usize {
let at = Rotation(at);
{
let len = self.rotations.len();
@ -305,11 +374,11 @@ impl<F: Field> ConstraintSystem<F> {
}
/// Query an advice column at a relative position
pub fn query_advice(&mut self, column: AdviceColumn, at: i32) -> Expression<F> {
pub fn query_advice(&mut self, column: Column<Advice>, at: i32) -> Expression<F> {
Expression::Advice(self.query_advice_index(column, at))
}
fn query_aux_index(&mut self, column: AuxColumn, at: i32) -> usize {
fn query_aux_index(&mut self, column: Column<Aux>, at: i32) -> usize {
let at = Rotation(at);
{
let len = self.rotations.len();
@ -331,10 +400,32 @@ impl<F: Field> ConstraintSystem<F> {
}
/// Query an auxiliary column at a relative position
pub fn query_aux(&mut self, column: AuxColumn, at: i32) -> Expression<F> {
pub fn query_aux(&mut self, column: Column<Aux>, at: i32) -> Expression<F> {
Expression::Aux(self.query_aux_index(column, at))
}
pub(crate) fn get_advice_query_index(&self, column: Column<Advice>, at: i32) -> usize {
let at = Rotation(at);
for (index, advice_query) in self.advice_queries.iter().enumerate() {
if advice_query == &(column, at) {
return index;
}
}
panic!("get_advice_query_index called for non-existant query");
}
pub(crate) fn get_fixed_query_index(&self, column: Column<Fixed>, at: i32) -> usize {
let at = Rotation(at);
for (index, fixed_query) in self.fixed_queries.iter().enumerate() {
if fixed_query == &(column, at) {
return index;
}
}
panic!("get_fixed_query_index called for non-existent query");
}
/// Create a new gate
pub fn create_gate(&mut self, f: impl FnOnce(&mut Self) -> Expression<F>) {
let poly = f(self);
@ -342,22 +433,31 @@ impl<F: Field> ConstraintSystem<F> {
}
/// Allocate a new fixed column
pub fn fixed_column(&mut self) -> FixedColumn {
let tmp = FixedColumn(self.num_fixed_columns);
pub fn fixed_column(&mut self) -> Column<Fixed> {
let tmp = Column {
index: self.num_fixed_columns,
column_type: Fixed,
};
self.num_fixed_columns += 1;
tmp
}
/// Allocate a new advice column
pub fn advice_column(&mut self) -> AdviceColumn {
let tmp = AdviceColumn(self.num_advice_columns);
pub fn advice_column(&mut self) -> Column<Advice> {
let tmp = Column {
index: self.num_advice_columns,
column_type: Advice,
};
self.num_advice_columns += 1;
tmp
}
/// Allocate a new auxiliary column
pub fn aux_column(&mut self) -> AuxColumn {
let tmp = AuxColumn(self.num_aux_columns);
pub fn aux_column(&mut self) -> Column<Aux> {
let tmp = Column {
index: self.num_aux_columns,
column_type: Aux,
};
self.num_aux_columns += 1;
tmp
}

View file

@ -1,5 +1,5 @@
use super::{
circuit::{AdviceColumn, Assignment, Circuit, ConstraintSystem, FixedColumn},
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
Error, ProvingKey, VerifyingKey,
};
use crate::arithmetic::{Curve, CurveAffine, Field};
@ -28,7 +28,7 @@ where
impl<F: Field> Assignment<F> for Assembly<F> {
fn assign_advice(
&mut self,
_: AdviceColumn,
_: Column<Advice>,
_: usize,
_: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
@ -38,13 +38,13 @@ where
fn assign_fixed(
&mut self,
column: FixedColumn,
column: Column<Fixed>,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
*self
.fixed
.get_mut(column.0)
.get_mut(column.index)
.and_then(|v| v.get_mut(row))
.ok_or(Error::BoundsFailure)? = to()?;
@ -230,7 +230,7 @@ where
.fixed_queries
.iter()
.map(|&(column, at)| {
let poly = fixed_polys[column.0].clone();
let poly = fixed_polys[column.index].clone();
domain.coeff_to_extended(poly, at)
})
.collect();

View file

@ -1,5 +1,5 @@
use super::{
circuit::{AdviceColumn, Assignment, Circuit, ConstraintSystem, FixedColumn},
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
hash_point, Error, Proof, ProvingKey,
};
use crate::arithmetic::{
@ -39,13 +39,13 @@ impl<C: CurveAffine> Proof<C> {
impl<F: Field> Assignment<F> for WitnessCollection<F> {
fn assign_advice(
&mut self,
column: AdviceColumn,
column: Column<Advice>,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
*self
.advice
.get_mut(column.0)
.get_mut(column.index)
.and_then(|v| v.get_mut(row))
.ok_or(Error::BoundsFailure)? = to()?;
@ -54,7 +54,7 @@ impl<C: CurveAffine> Proof<C> {
fn assign_fixed(
&mut self,
_: FixedColumn,
_: Column<Fixed>,
_: usize,
_: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
@ -120,7 +120,7 @@ impl<C: CurveAffine> Proof<C> {
.aux_queries
.iter()
.map(|&(column, at)| {
let poly = aux_polys[column.0].clone();
let poly = aux_polys[column.index].clone();
domain.coeff_to_extended(poly, at)
})
.collect();
@ -157,7 +157,7 @@ impl<C: CurveAffine> Proof<C> {
.advice_queries
.iter()
.map(|&(column, at)| {
let poly = advice_polys[column.0].clone();
let poly = advice_polys[column.index].clone();
domain.coeff_to_extended(poly, at)
})
.collect();
@ -192,7 +192,7 @@ impl<C: CurveAffine> Proof<C> {
parallelize(&mut modified_advice, |modified_advice, start| {
for ((modified_advice, advice_value), permuted_advice_value) in modified_advice
.iter_mut()
.zip(witness.advice[column.0][start..].iter())
.zip(witness.advice[column.index][start..].iter())
.zip(permuted_column_values[start..].iter())
{
*modified_advice *= &(x_0 * permuted_advice_value + &x_1 + advice_value);
@ -226,7 +226,7 @@ impl<C: CurveAffine> Proof<C> {
let mut deltaomega = deltaomega * &omega.pow_vartime(&[start as u64, 0, 0, 0]);
for (modified_advice, advice_value) in modified_advice
.iter_mut()
.zip(witness.advice[column.0][start..].iter())
.zip(witness.advice[column.index][start..].iter())
{
// Multiply by p_j(\omega^i) + \delta^j \omega^i \beta
*modified_advice *= &(deltaomega * &x_0 + &x_1 + advice_value);
@ -395,7 +395,7 @@ impl<C: CurveAffine> Proof<C> {
.advice_queries
.iter()
.map(|&(column, at)| {
eval_polynomial(&advice_polys[column.0], domain.rotate_omega(x_3, at))
eval_polynomial(&advice_polys[column.index], domain.rotate_omega(x_3, at))
})
.collect();
@ -403,7 +403,7 @@ impl<C: CurveAffine> Proof<C> {
.aux_queries
.iter()
.map(|&(column, at)| {
eval_polynomial(&aux_polys[column.0], domain.rotate_omega(x_3, at))
eval_polynomial(&aux_polys[column.index], domain.rotate_omega(x_3, at))
})
.collect();
@ -411,7 +411,7 @@ impl<C: CurveAffine> Proof<C> {
.fixed_queries
.iter()
.map(|&(column, at)| {
eval_polynomial(&pk.fixed_polys[column.0], domain.rotate_omega(x_3, at))
eval_polynomial(&pk.fixed_polys[column.index], domain.rotate_omega(x_3, at))
})
.collect();
@ -469,8 +469,8 @@ impl<C: CurveAffine> Proof<C> {
instances.push(ProverQuery {
point,
poly: &advice_polys[column.0],
blind: advice_blinds[column.0],
poly: &advice_polys[column.index],
blind: advice_blinds[column.index],
eval: advice_evals[query_index],
});
}
@ -480,7 +480,7 @@ impl<C: CurveAffine> Proof<C> {
instances.push(ProverQuery {
point,
poly: &aux_polys[column.0],
poly: &aux_polys[column.index],
blind: Blind::default(),
eval: aux_evals[query_index],
});
@ -491,7 +491,7 @@ impl<C: CurveAffine> Proof<C> {
instances.push(ProverQuery {
point,
poly: &pk.fixed_polys[column.0],
poly: &pk.fixed_polys[column.index],
blind: Blind::default(),
eval: fixed_evals[query_index],
});

View file

@ -93,7 +93,7 @@ impl<'a, C: CurveAffine> Proof<C> {
let point = vk.domain.rotate_omega(x_3, at);
queries.push(VerifierQuery {
point,
commitment: &self.advice_commitments[column.0],
commitment: &self.advice_commitments[column.index],
eval: self.advice_evals[query_index],
});
}
@ -102,7 +102,7 @@ impl<'a, C: CurveAffine> Proof<C> {
let point = vk.domain.rotate_omega(x_3, at);
queries.push(VerifierQuery {
point,
commitment: &aux_commitments[column.0],
commitment: &aux_commitments[column.index],
eval: self.aux_evals[query_index],
});
}
@ -111,7 +111,7 @@ impl<'a, C: CurveAffine> Proof<C> {
let point = vk.domain.rotate_omega(x_3, at);
queries.push(VerifierQuery {
point,
commitment: &vk.fixed_commitments[column.0],
commitment: &vk.fixed_commitments[column.index],
eval: self.fixed_evals[query_index],
});
}