Merge pull request #199 from zcash/upstream-perm-struct

Upstream Permutation struct into plonk::circuit
This commit is contained in:
str4d 2021-02-26 04:24:00 +13:00 committed by GitHub
commit 87362e22d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 152 additions and 147 deletions

View file

@ -20,7 +20,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
// Initialize the polynomial commitment parameters // Initialize the polynomial commitment parameters
let params: Params<EqAffine> = Params::new(k); let params: Params<EqAffine> = Params::new(k);
#[derive(Copy, Clone)] #[derive(Clone)]
struct PLONKConfig { struct PLONKConfig {
a: Column<Advice>, a: Column<Advice>,
b: Column<Advice>, b: Column<Advice>,
@ -31,7 +31,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
sc: Column<Fixed>, sc: Column<Fixed>,
sm: Column<Fixed>, sm: Column<Fixed>,
perm: usize, perm: Permutation,
} }
trait StandardCS<FF: FieldExt> { trait StandardCS<FF: FieldExt> {
@ -156,21 +156,13 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
)) ))
} }
fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> { fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> {
let left_column = match left.0 { self.cs.copy(
x if x == self.config.a => 0, &self.config.perm,
x if x == self.config.b => 1, left.0.into(),
x if x == self.config.c => 2, left.1,
_ => unreachable!(), right.0.into(),
}; right.1,
let right_column = match right.0 { )
x if x == self.config.a => 0,
x if x == self.config.b => 1,
x if x == self.config.c => 2,
_ => unreachable!(),
};
self.cs
.copy(self.config.perm, left_column, left.1, right_column, right.1)
} }
} }

View file

@ -2,7 +2,7 @@ use halo2::{
arithmetic::FieldExt, arithmetic::FieldExt,
dev::circuit_layout, dev::circuit_layout,
pasta::Fp, pasta::Fp,
plonk::{Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed}, plonk::{Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed, Permutation},
poly::Rotation, poly::Rotation,
}; };
use plotters::prelude::*; use plotters::prelude::*;
@ -30,8 +30,8 @@ fn main() {
sl: Column<Fixed>, sl: Column<Fixed>,
sl2: Column<Fixed>, sl2: Column<Fixed>,
perm: usize, perm: Permutation,
perm2: usize, perm2: Permutation,
} }
trait StandardCS<FF: FieldExt> { trait StandardCS<FF: FieldExt> {
@ -195,26 +195,18 @@ fn main() {
)) ))
} }
fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> { fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> {
let left_column = match left.0 {
x if x == self.config.a => 0,
x if x == self.config.b => 1,
x if x == self.config.c => 2,
_ => unreachable!(),
};
let right_column = match right.0 {
x if x == self.config.a => 0,
x if x == self.config.b => 1,
x if x == self.config.c => 2,
_ => unreachable!(),
};
self.cs
.copy(self.config.perm, left_column, left.1, right_column, right.1)?;
self.cs.copy( self.cs.copy(
self.config.perm2, &self.config.perm,
left_column, left.0.into(),
left.1, left.1,
right_column, right.0.into(),
right.1,
)?;
self.cs.copy(
&self.config.perm2,
left.0.into(),
left.1,
right.0.into(),
right.1, right.1,
) )
} }

View file

@ -17,7 +17,7 @@ use std::marker::PhantomData;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct Variable(Column<Advice>, usize); pub struct Variable(Column<Advice>, usize);
#[derive(Copy, Clone)] #[derive(Clone)]
struct PLONKConfig { struct PLONKConfig {
a: Column<Advice>, a: Column<Advice>,
b: Column<Advice>, b: Column<Advice>,
@ -29,7 +29,7 @@ struct PLONKConfig {
sm: Column<Fixed>, sm: Column<Fixed>,
sp: Column<Fixed>, sp: Column<Fixed>,
perm: usize, perm: Permutation,
} }
trait StandardCS<FF: FieldExt> { trait StandardCS<FF: FieldExt> {
@ -157,21 +157,13 @@ impl<'a, FF: FieldExt, CS: Assignment<FF>> StandardCS<FF> for StandardPLONK<'a,
)) ))
} }
fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> { fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> {
let left_column = match left.0 { self.cs.copy(
x if x == self.config.a => 0, &self.config.perm,
x if x == self.config.b => 1, left.0.into(),
x if x == self.config.c => 2, left.1,
_ => unreachable!(), right.0.into(),
}; right.1,
let right_column = match right.0 { )
x if x == self.config.a => 0,
x if x == self.config.b => 1,
x if x == self.config.c => 2,
_ => unreachable!(),
};
self.cs
.copy(self.config.perm, left_column, left.1, right_column, right.1)
} }
fn public_input<F>(&mut self, f: F) -> Result<Variable, Error> fn public_input<F>(&mut self, f: F) -> Result<Variable, Error>
where where

View file

@ -4,9 +4,11 @@ use std::marker::PhantomData;
use halo2::{ use halo2::{
arithmetic::FieldExt, arithmetic::FieldExt,
circuit::{layouter::SingleChip, Cell, Chip, Layouter, Permutation}, circuit::{layouter::SingleChip, Cell, Chip, Layouter},
dev::VerifyFailure, dev::VerifyFailure,
plonk::{Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}, plonk::{
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Permutation,
},
poly::Rotation, poly::Rotation,
}; };

View file

@ -4,7 +4,7 @@ use std::{fmt, marker::PhantomData};
use crate::{ use crate::{
arithmetic::FieldExt, arithmetic::FieldExt,
plonk::{Advice, Any, Column, ConstraintSystem, Error, Fixed}, plonk::{Advice, Any, Column, Error, Fixed, Permutation},
}; };
pub mod layouter; pub mod layouter;
@ -73,24 +73,6 @@ pub struct Cell {
column: Column<Any>, column: Column<Any>,
} }
/// A permutation configured by a chip.
#[derive(Clone, Debug)]
pub struct Permutation {
index: usize,
mapping: Vec<Column<Any>>,
}
impl Permutation {
/// Configures a new permutation for the given columns.
pub fn new<F: FieldExt>(meta: &mut ConstraintSystem<F>, columns: &[Column<Any>]) -> Self {
let index = meta.permutation(columns);
Permutation {
index,
mapping: columns.iter().copied().collect(),
}
}
}
/// A region of the circuit in which a [`Chip`] can assign cells. /// A region of the circuit in which a [`Chip`] can assign cells.
/// ///
/// Inside a region, the chip may freely use relative offsets; the [`Layouter`] will /// Inside a region, the chip may freely use relative offsets; the [`Layouter`] will

View file

@ -5,8 +5,8 @@ use std::collections::{HashMap, HashSet};
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use super::{Cell, Chip, Layouter, Permutation, Region, RegionIndex, RegionStart}; use super::{Cell, Chip, Layouter, Region, RegionIndex, RegionStart};
use crate::plonk::{Advice, Any, Assignment, Column, Error, Fixed}; use crate::plonk::{Advice, Any, Assignment, Column, Error, Fixed, Permutation};
/// Helper trait for implementing a custom [`Layouter`]. /// Helper trait for implementing a custom [`Layouter`].
/// ///
@ -320,22 +320,11 @@ impl<'r, 'a, C: Chip, CS: Assignment<C::Field> + 'a> RegionLayouter<C>
left: Cell, left: Cell,
right: Cell, right: Cell,
) -> Result<(), Error> { ) -> Result<(), Error> {
let left_column = permutation
.mapping
.iter()
.position(|c| c == &left.column)
.ok_or(Error::SynthesisError)?;
let right_column = permutation
.mapping
.iter()
.position(|c| c == &right.column)
.ok_or(Error::SynthesisError)?;
self.layouter.cs.copy( self.layouter.cs.copy(
permutation.index, permutation,
left_column, left.column,
*self.layouter.regions[*left.region_index] + left.row_offset, *self.layouter.regions[*left.region_index] + left.row_offset,
right_column, right.column,
*self.layouter.regions[*right.region_index] + right.row_offset, *self.layouter.regions[*right.region_index] + right.row_offset,
)?; )?;

View file

@ -5,8 +5,8 @@ use ff::Field;
use crate::{ use crate::{
arithmetic::{FieldExt, Group}, arithmetic::{FieldExt, Group},
plonk::{ plonk::{
permutation, Advice, Assignment, Circuit, Column, ColumnType, ConstraintSystem, Error, permutation, Advice, Any, Assignment, Circuit, Column, ColumnType, ConstraintSystem, Error,
Expression, Fixed, Expression, Fixed, Permutation,
}, },
poly::Rotation, poly::Rotation,
}; };
@ -211,18 +211,34 @@ impl<F: Field + Group> Assignment<F> for MockProver<F> {
fn copy( fn copy(
&mut self, &mut self,
permutation: usize, permutation: &Permutation,
left_column: usize, left_column: Column<Any>,
left_row: usize, left_row: usize,
right_column: usize, right_column: Column<Any>,
right_row: usize, right_row: usize,
) -> Result<(), crate::plonk::Error> { ) -> Result<(), crate::plonk::Error> {
// Check bounds first // Check bounds first
if permutation >= self.permutations.len() { if permutation.index() >= self.permutations.len() {
return Err(Error::BoundsFailure); return Err(Error::BoundsFailure);
} }
self.permutations[permutation].copy(left_column, left_row, right_column, right_row) let left_column_index = permutation
.mapping()
.iter()
.position(|c| c == &left_column)
.ok_or(Error::SynthesisError)?;
let right_column_index = permutation
.mapping()
.iter()
.position(|c| c == &right_column)
.ok_or(Error::SynthesisError)?;
self.permutations[permutation.index()].copy(
left_column_index,
left_row,
right_column_index,
right_row,
)
} }
fn push_namespace<NR, N>(&mut self, _: N) fn push_namespace<NR, N>(&mut self, _: N)

View file

@ -1,7 +1,9 @@
use ff::Field; use ff::Field;
use tabbycat::{AttrList, Edge, GraphBuilder, GraphType, Identity, StmtList}; use tabbycat::{AttrList, Edge, GraphBuilder, GraphType, Identity, StmtList};
use crate::plonk::{Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed}; use crate::plonk::{
Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed, Permutation,
};
pub mod layout; pub mod layout;
@ -118,10 +120,10 @@ impl<F: Field> Assignment<F> for Graph {
fn copy( fn copy(
&mut self, &mut self,
_: &Permutation,
_: Column<Any>,
_: usize, _: usize,
_: usize, _: Column<Any>,
_: usize,
_: usize,
_: usize, _: usize,
) -> Result<(), crate::plonk::Error> { ) -> Result<(), crate::plonk::Error> {
// Do nothing; we don't care about permutations in this context. // Do nothing; we don't care about permutations in this context.

View file

@ -6,7 +6,9 @@ use plotters::{
use std::cmp; use std::cmp;
use std::collections::HashSet; use std::collections::HashSet;
use crate::plonk::{Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed}; use crate::plonk::{
Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Error, Fixed, Permutation,
};
/// Renders the circuit layout on the given drawing area. /// Renders the circuit layout on the given drawing area.
/// ///
@ -251,10 +253,10 @@ impl<F: Field> Assignment<F> for Layout {
fn copy( fn copy(
&mut self, &mut self,
_: &Permutation,
_: Column<Any>,
_: usize, _: usize,
_: usize, _: Column<Any>,
_: usize,
_: usize,
_: usize, _: usize,
) -> Result<(), crate::plonk::Error> { ) -> Result<(), crate::plonk::Error> {
// Do nothing; we don't care about permutations in this context. // Do nothing; we don't care about permutations in this context.

View file

@ -210,7 +210,7 @@ fn test_proving() {
// Initialize the polynomial commitment parameters // Initialize the polynomial commitment parameters
let params: Params<EqAffine> = Params::new(K); let params: Params<EqAffine> = Params::new(K);
#[derive(Copy, Clone)] #[derive(Clone)]
struct PLONKConfig { struct PLONKConfig {
a: Column<Advice>, a: Column<Advice>,
b: Column<Advice>, b: Column<Advice>,
@ -226,8 +226,8 @@ fn test_proving() {
sl: Column<Fixed>, sl: Column<Fixed>,
sl2: Column<Fixed>, sl2: Column<Fixed>,
perm: usize, perm: Permutation,
perm2: usize, perm2: Permutation,
} }
trait StandardCS<FF: FieldExt> { trait StandardCS<FF: FieldExt> {
@ -380,26 +380,18 @@ fn test_proving() {
)) ))
} }
fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> { fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> {
let left_column = match left.0 {
x if x == self.config.a => 0,
x if x == self.config.b => 1,
x if x == self.config.c => 2,
_ => unreachable!(),
};
let right_column = match right.0 {
x if x == self.config.a => 0,
x if x == self.config.b => 1,
x if x == self.config.c => 2,
_ => unreachable!(),
};
self.cs
.copy(self.config.perm, left_column, left.1, right_column, right.1)?;
self.cs.copy( self.cs.copy(
self.config.perm2, &self.config.perm,
left_column, left.0.into(),
left.1, left.1,
right_column, right.0.into(),
right.1,
)?;
self.cs.copy(
&self.config.perm2,
left.0.into(),
left.1,
right.0.into(),
right.1, right.1,
) )
} }

View file

@ -7,6 +7,7 @@ use std::{
}; };
use super::{lookup, permutation, Error}; use super::{lookup, permutation, Error};
use crate::arithmetic::FieldExt;
use crate::poly::Rotation; use crate::poly::Rotation;
/// A column type /// A column type
@ -126,6 +127,30 @@ impl TryFrom<Column<Any>> for Column<Instance> {
} }
} }
/// A permutation.
#[derive(Clone, Debug)]
pub struct Permutation {
index: usize,
mapping: Vec<Column<Any>>,
}
impl Permutation {
/// Configures a new permutation for the given columns.
pub fn new<F: FieldExt>(meta: &mut ConstraintSystem<F>, columns: &[Column<Any>]) -> Self {
meta.permutation(columns)
}
/// Returns index of permutation
pub fn index(&self) -> usize {
self.index
}
/// Returns mapping of permutation
pub fn mapping(&self) -> &[Column<Any>] {
&self.mapping
}
}
/// This trait allows a [`Circuit`] to direct some backend to assign a witness /// This trait allows a [`Circuit`] to direct some backend to assign a witness
/// for a constraint system. /// for a constraint system.
pub trait Assignment<F: Field> { pub trait Assignment<F: Field> {
@ -176,13 +201,13 @@ pub trait Assignment<F: Field> {
A: FnOnce() -> AR, A: FnOnce() -> AR,
AR: Into<String>; AR: Into<String>;
/// Assign two advice columns to have the same value /// Assign two cells to have the same value
fn copy( fn copy(
&mut self, &mut self,
permutation: usize, permutation: &Permutation,
left_column: usize, left_column: Column<Any>,
left_row: usize, left_row: usize,
right_column: usize, right_column: Column<Any>,
right_row: usize, right_row: usize,
) -> Result<(), Error>; ) -> Result<(), Error>;
@ -448,8 +473,8 @@ impl<F: Field> ConstraintSystem<F> {
} }
} }
/// Add a permutation argument for some advice columns /// Add a permutation argument for some columns
pub fn permutation(&mut self, columns: &[Column<Any>]) -> usize { pub fn permutation(&mut self, columns: &[Column<Any>]) -> Permutation {
let index = self.permutations.len(); let index = self.permutations.len();
for column in columns { for column in columns {
@ -458,7 +483,10 @@ impl<F: Field> ConstraintSystem<F> {
self.permutations self.permutations
.push(permutation::Argument::new(columns.to_vec())); .push(permutation::Argument::new(columns.to_vec()));
index Permutation {
index,
mapping: columns.to_vec(),
}
} }
/// Add a lookup argument for some input expressions and table expressions. /// Add a lookup argument for some input expressions and table expressions.

View file

@ -2,8 +2,8 @@ use ff::Field;
use group::Curve; use group::Curve;
use super::{ use super::{
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed}, circuit::{Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Fixed},
permutation, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey, permutation, Error, LagrangeCoeff, Permutation, Polynomial, ProvingKey, VerifyingKey,
}; };
use crate::arithmetic::CurveAffine; use crate::arithmetic::CurveAffine;
use crate::poly::{ use crate::poly::{
@ -116,18 +116,34 @@ impl<F: Field> Assignment<F> for Assembly<F> {
fn copy( fn copy(
&mut self, &mut self,
permutation: usize, permutation: &Permutation,
left_column: usize, left_column: Column<Any>,
left_row: usize, left_row: usize,
right_column: usize, right_column: Column<Any>,
right_row: usize, right_row: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Check bounds first // Check bounds first
if permutation >= self.permutations.len() { if permutation.index() >= self.permutations.len() {
return Err(Error::BoundsFailure); return Err(Error::BoundsFailure);
} }
self.permutations[permutation].copy(left_column, left_row, right_column, right_row) let left_column_index = permutation
.mapping()
.iter()
.position(|c| c == &left_column)
.ok_or(Error::SynthesisError)?;
let right_column_index = permutation
.mapping()
.iter()
.position(|c| c == &right_column)
.ok_or(Error::SynthesisError)?;
self.permutations[permutation.index()].copy(
left_column_index,
left_row,
right_column_index,
right_row,
)
} }
fn push_namespace<NR, N>(&mut self, _: N) fn push_namespace<NR, N>(&mut self, _: N)

View file

@ -3,9 +3,9 @@ use group::Curve;
use std::iter; use std::iter;
use super::{ use super::{
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed}, circuit::{Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Fixed},
lookup, permutation, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, lookup, permutation, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX,
ChallengeY, Error, ProvingKey, ChallengeY, Error, Permutation, ProvingKey,
}; };
use crate::arithmetic::{eval_polynomial, CurveAffine, FieldExt}; use crate::arithmetic::{eval_polynomial, CurveAffine, FieldExt};
use crate::poly::{ use crate::poly::{
@ -159,10 +159,10 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
fn copy( fn copy(
&mut self, &mut self,
_: &Permutation,
_: Column<Any>,
_: usize, _: usize,
_: usize, _: Column<Any>,
_: usize,
_: usize,
_: usize, _: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
// We only care about advice columns here // We only care about advice columns here