halo2_proofs/plonk/permutation/
keygen.rsuse ff::Field;
use group::Curve;
use super::{Argument, ProvingKey, VerifyingKey};
use crate::{
arithmetic::{CurveAffine, FieldExt},
plonk::{Any, Column, Error},
poly::{
commitment::{Blind, Params},
EvaluationDomain,
},
};
#[derive(Debug)]
pub(crate) struct Assembly {
columns: Vec<Column<Any>>,
pub(crate) mapping: Vec<Vec<(usize, usize)>>,
aux: Vec<Vec<(usize, usize)>>,
sizes: Vec<Vec<usize>>,
}
impl Assembly {
pub(crate) fn new(n: usize, p: &Argument) -> Self {
let mut columns = vec![];
for i in 0..p.columns.len() {
columns.push((0..n).map(|j| (i, j)).collect());
}
Assembly {
columns: p.columns.clone(),
mapping: columns.clone(),
aux: columns,
sizes: vec![vec![1usize; n]; p.columns.len()],
}
}
pub(crate) fn copy(
&mut self,
left_column: Column<Any>,
left_row: usize,
right_column: Column<Any>,
right_row: usize,
) -> Result<(), Error> {
let left_column = self
.columns
.iter()
.position(|c| c == &left_column)
.ok_or(Error::ColumnNotInPermutation(left_column))?;
let right_column = self
.columns
.iter()
.position(|c| c == &right_column)
.ok_or(Error::ColumnNotInPermutation(right_column))?;
if left_row >= self.mapping[left_column].len()
|| right_row >= self.mapping[right_column].len()
{
return Err(Error::BoundsFailure);
}
let mut left_cycle = self.aux[left_column][left_row];
let mut right_cycle = self.aux[right_column][right_row];
if left_cycle == right_cycle {
return Ok(());
}
if self.sizes[left_cycle.0][left_cycle.1] < self.sizes[right_cycle.0][right_cycle.1] {
std::mem::swap(&mut left_cycle, &mut right_cycle);
}
self.sizes[left_cycle.0][left_cycle.1] += self.sizes[right_cycle.0][right_cycle.1];
let mut i = right_cycle;
loop {
self.aux[i.0][i.1] = left_cycle;
i = self.mapping[i.0][i.1];
if i == right_cycle {
break;
}
}
let tmp = self.mapping[left_column][left_row];
self.mapping[left_column][left_row] = self.mapping[right_column][right_row];
self.mapping[right_column][right_row] = tmp;
Ok(())
}
pub(crate) fn build_vk<C: CurveAffine>(
self,
params: &Params<C>,
domain: &EvaluationDomain<C::Scalar>,
p: &Argument,
) -> VerifyingKey<C> {
let mut omega_powers = Vec::with_capacity(params.n as usize);
{
let mut cur = C::Scalar::one();
for _ in 0..params.n {
omega_powers.push(cur);
cur *= &domain.get_omega();
}
}
let mut deltaomega = Vec::with_capacity(p.columns.len());
{
let mut cur = C::Scalar::one();
for _ in 0..p.columns.len() {
let mut omega_powers = omega_powers.clone();
for o in &mut omega_powers {
*o *= &cur;
}
deltaomega.push(omega_powers);
cur *= &C::Scalar::DELTA;
}
}
let mut commitments = vec![];
for i in 0..p.columns.len() {
let mut permutation_poly = domain.empty_lagrange();
for (j, p) in permutation_poly.iter_mut().enumerate() {
let (permuted_i, permuted_j) = self.mapping[i][j];
*p = deltaomega[permuted_i][permuted_j];
}
commitments.push(
params
.commit_lagrange(&permutation_poly, Blind::default())
.to_affine(),
);
}
VerifyingKey { commitments }
}
pub(crate) fn build_pk<C: CurveAffine>(
self,
params: &Params<C>,
domain: &EvaluationDomain<C::Scalar>,
p: &Argument,
) -> ProvingKey<C> {
let mut omega_powers = Vec::with_capacity(params.n as usize);
{
let mut cur = C::Scalar::one();
for _ in 0..params.n {
omega_powers.push(cur);
cur *= &domain.get_omega();
}
}
let mut deltaomega = Vec::with_capacity(p.columns.len());
{
let mut cur = C::Scalar::one();
for _ in 0..p.columns.len() {
let mut omega_powers = omega_powers.clone();
for o in &mut omega_powers {
*o *= &cur;
}
deltaomega.push(omega_powers);
cur *= &C::Scalar::DELTA;
}
}
let mut permutations = vec![];
let mut polys = vec![];
let mut cosets = vec![];
for i in 0..p.columns.len() {
let mut permutation_poly = domain.empty_lagrange();
for (j, p) in permutation_poly.iter_mut().enumerate() {
let (permuted_i, permuted_j) = self.mapping[i][j];
*p = deltaomega[permuted_i][permuted_j];
}
permutations.push(permutation_poly.clone());
let poly = domain.lagrange_to_coeff(permutation_poly);
polys.push(poly.clone());
cosets.push(domain.coeff_to_extended(poly));
}
ProvingKey {
permutations,
polys,
cosets,
}
}
}