Add permutation check to MockProver

This commit is contained in:
therealyingtong 2020-12-22 13:56:30 +08:00 committed by Jack Grigg
parent 6eebf3994b
commit fb939f17a9
5 changed files with 60 additions and 16 deletions

View file

@ -1,11 +1,10 @@
//! Tools for developing circuits. //! Tools for developing circuits.
use ff::Field; use ff::Field;
use std::collections::HashMap;
use crate::{ use crate::{
arithmetic::{FieldExt, Group}, arithmetic::{FieldExt, Group},
plonk::{Any, Assignment, Circuit, Column, ConstraintSystem, Error}, plonk::{permutation, Any, Assignment, Circuit, Column, ConstraintSystem, Error},
poly::{EvaluationDomain, LagrangeCoeff, Polynomial}, poly::{EvaluationDomain, LagrangeCoeff, Polynomial},
}; };
@ -19,6 +18,12 @@ pub enum VerifyFailure {
Gate { gate_index: usize, row: usize }, Gate { gate_index: usize, row: usize },
/// A lookup input did not exist in its corresponding table. /// A lookup input did not exist in its corresponding table.
Lookup { lookup_index: usize, row: usize }, Lookup { lookup_index: usize, row: usize },
/// A permutation did not preserve the original value of a cell.
Permutation {
perm_index: usize,
column: usize,
row: usize,
},
} }
/// A test /// A test
@ -34,7 +39,7 @@ pub struct MockProver<F: Group> {
// The aux cells in the circuit, arranged as [column][row]. // The aux cells in the circuit, arranged as [column][row].
aux: Vec<Polynomial<F, LagrangeCoeff>>, aux: Vec<Polynomial<F, LagrangeCoeff>>,
permutations: HashMap<usize, Vec<(Cell, Cell)>>, permutations: Vec<permutation::keygen::Assembly>,
} }
impl<F: Field + Group> Assignment<F> for MockProver<F> { impl<F: Field + Group> Assignment<F> for MockProver<F> {
@ -76,11 +81,12 @@ impl<F: Field + Group> Assignment<F> for MockProver<F> {
right_column: usize, right_column: usize,
right_row: usize, right_row: usize,
) -> Result<(), crate::plonk::Error> { ) -> Result<(), crate::plonk::Error> {
self.permutations // Check bounds first
.entry(permutation) if permutation >= self.permutations.len() {
.or_default() return Err(Error::BoundsFailure);
.push((Cell(left_column, left_row), Cell(right_column, right_row))); }
Ok(())
self.permutations[permutation].copy(left_column, left_row, right_column, right_row)
} }
} }
@ -90,6 +96,8 @@ impl<F: FieldExt> MockProver<F> {
circuit: &ConcreteCircuit, circuit: &ConcreteCircuit,
aux: Vec<Polynomial<F, LagrangeCoeff>>, aux: Vec<Polynomial<F, LagrangeCoeff>>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let n = 1 << k;
let mut cs = ConstraintSystem::default(); let mut cs = ConstraintSystem::default();
let config = ConcreteCircuit::configure(&mut cs); let config = ConcreteCircuit::configure(&mut cs);
@ -112,15 +120,20 @@ impl<F: FieldExt> MockProver<F> {
let fixed = vec![domain.empty_lagrange(); cs.num_fixed_columns]; let fixed = vec![domain.empty_lagrange(); cs.num_fixed_columns];
let advice = vec![domain.empty_lagrange(); cs.num_advice_columns]; let advice = vec![domain.empty_lagrange(); cs.num_advice_columns];
let permutations = cs
.permutations
.iter()
.map(|p| permutation::keygen::Assembly::new(n as usize, p))
.collect();
let mut prover = MockProver { let mut prover = MockProver {
n: 1 << k, n,
domain, domain,
cs, cs,
fixed, fixed,
advice, advice,
aux, aux,
permutations: HashMap::default(), permutations,
}; };
circuit.synthesize(&mut prover, config)?; circuit.synthesize(&mut prover, config)?;
@ -192,6 +205,33 @@ impl<F: FieldExt> MockProver<F> {
} }
} }
// Check that permutations preserve the original values of the cells.
for (perm_index, assembly) in self.permutations.iter().enumerate() {
// Original values of columns involved in the permutation
let original = self.cs.permutations[perm_index]
.get_columns()
.iter()
.map(|c| self.advice[c.index()].clone())
.collect::<Vec<_>>();
// Iterate over each column of the permutation
for (column, values) in assembly.mapping.iter().enumerate() {
// Iterate over each row of the column to check that the cell's
// value is preserved by the mapping.
for (row, cell) in values.iter().enumerate() {
let original_cell = original[column][row];
let permuted_cell = original[cell.0][cell.1];
if original_cell != permuted_cell {
return Err(VerifyFailure::Permutation {
perm_index,
column,
row,
});
}
}
}
}
// TODO: Implement the rest of the verification checks. // TODO: Implement the rest of the verification checks.
Ok(()) Ok(())

View file

@ -14,7 +14,7 @@ use crate::transcript::ChallengeScalar;
mod circuit; mod circuit;
mod keygen; mod keygen;
mod lookup; mod lookup;
mod permutation; pub(crate) mod permutation;
mod vanishing; mod vanishing;
mod prover; mod prover;

View file

@ -104,7 +104,7 @@ where
permutations: cs permutations: cs
.permutations .permutations
.iter() .iter()
.map(|p| permutation::keygen::Assembly::new(params, p)) .map(|p| permutation::keygen::Assembly::new(params.n as usize, p))
.collect(), .collect(),
_marker: std::marker::PhantomData, _marker: std::marker::PhantomData,
}; };

View file

@ -37,6 +37,10 @@ impl Argument {
// - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma) // - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma)
std::cmp::max(self.columns.len() + 1, 2) std::cmp::max(self.columns.len() + 1, 2)
} }
pub(crate) fn get_columns(&self) -> Vec<Column<Advice>> {
self.columns.clone()
}
} }
/// The verifying key for a single permutation argument. /// The verifying key for a single permutation argument.

View file

@ -15,19 +15,19 @@ pub(crate) struct AssemblyHelper<C: CurveAffine> {
} }
pub(crate) struct Assembly { pub(crate) struct Assembly {
mapping: Vec<Vec<(usize, usize)>>, pub(crate) mapping: Vec<Vec<(usize, usize)>>,
aux: Vec<Vec<(usize, usize)>>, aux: Vec<Vec<(usize, usize)>>,
sizes: Vec<Vec<usize>>, sizes: Vec<Vec<usize>>,
} }
impl Assembly { impl Assembly {
pub(crate) fn new<C: CurveAffine>(params: &Params<C>, p: &Argument) -> Self { pub(crate) fn new(n: usize, p: &Argument) -> Self {
// Initialize the copy vector to keep track of copy constraints in all // Initialize the copy vector to keep track of copy constraints in all
// the permutation arguments. // the permutation arguments.
let mut columns = vec![]; let mut columns = vec![];
for i in 0..p.columns.len() { for i in 0..p.columns.len() {
// Computes [(i, 0), (i, 1), ..., (i, n - 1)] // Computes [(i, 0), (i, 1), ..., (i, n - 1)]
columns.push((0..params.n).map(|j| (i, j as usize)).collect()); columns.push((0..n).map(|j| (i, j)).collect());
} }
// Before any equality constraints are applied, every cell in the permutation is // Before any equality constraints are applied, every cell in the permutation is
@ -36,7 +36,7 @@ impl Assembly {
Assembly { Assembly {
mapping: columns.clone(), mapping: columns.clone(),
aux: columns, aux: columns,
sizes: vec![vec![1usize; params.n as usize]; p.columns.len()], sizes: vec![vec![1usize; n]; p.columns.len()],
} }
} }