diff --git a/src/plonk/circuit.rs b/src/plonk/circuit.rs index 5330a1b..5758804 100644 --- a/src/plonk/circuit.rs +++ b/src/plonk/circuit.rs @@ -18,6 +18,17 @@ pub struct AdviceWire(pub usize); #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct AuxWire(pub usize); +/// An enum over all wire types, to be used in permutations +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum Wire { + /// Fixed wire + Fixed(FixedWire), + /// Advice wire + Advice(AdviceWire), + /// Auxiliary wire + Aux(AuxWire), +} + /// This trait allows a [`Circuit`] to direct some backend to assign a witness /// for a constraint system. pub trait Assignment { @@ -176,7 +187,7 @@ pub struct ConstraintSystem { // enforced between advice wire values in A, B and C, and another // permutation between wires (B, C, D) which allows the same with D instead // of A. - pub(crate) permutations: Vec>, + pub(crate) permutations: Vec>, } impl Default for ConstraintSystem { @@ -200,7 +211,7 @@ impl Default for ConstraintSystem { impl ConstraintSystem { /// Add a permutation argument for some advice wires - pub fn permutation(&mut self, wires: &[AdviceWire]) -> usize { + pub fn permutation(&mut self, wires: &[Wire]) -> usize { let index = self.permutations.len(); if index == 0 { let at = Rotation(-1); @@ -209,7 +220,11 @@ impl ConstraintSystem { } let wires = wires .iter() - .map(|&wire| (wire, self.query_advice_index(wire, 0))) + .map(|&wire| match wire { + Wire::Advice(wire) => (Wire::Advice(wire), self.query_advice_index(wire, 0)), + Wire::Aux(wire) => (Wire::Aux(wire), self.query_aux_index(wire, 0)), + Wire::Fixed(wire) => (Wire::Fixed(wire), self.query_fixed_index(wire, 0)), + }) .collect(); self.permutations.push(wires); diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 999a82f..eb6fd08 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -1,5 +1,5 @@ use super::{ - circuit::{AdviceWire, Assignment, Circuit, ConstraintSystem, FixedWire}, + circuit::{AdviceWire, Assignment, Circuit, ConstraintSystem, FixedWire, Wire}, hash_point, Error, Proof, SRS, }; use crate::arithmetic::{ @@ -182,15 +182,34 @@ impl Proof { // Iterate over each wire of the permutation for (&(wire, _), permuted_wire_values) in wires.iter().zip(permuted_values.iter()) { - parallelize(&mut modified_advice, |modified_advice, start| { - for ((modified_advice, advice_value), permuted_advice_value) in modified_advice - .iter_mut() - .zip(witness.advice[wire.0][start..].iter()) - .zip(permuted_wire_values[start..].iter()) - { - *modified_advice *= &(x_0 * permuted_advice_value + &x_1 + advice_value); + match wire { + Wire::Advice(wire) => { + parallelize(&mut modified_advice, |modified_advice, start| { + for ((modified_advice, advice_value), permuted_advice_value) in + modified_advice + .iter_mut() + .zip(witness.advice[wire.0][start..].iter()) + .zip(permuted_wire_values[start..].iter()) + { + *modified_advice *= + &(x_0 * permuted_advice_value + &x_1 + advice_value); + } + }); } - }); + Wire::Aux(wire) => { + parallelize(&mut modified_advice, |modified_aux, start| { + for ((modified_aux, aux_value), permuted_aux_value) in modified_aux + .iter_mut() + .zip(aux_lagrange_polys[wire.0][start..].iter()) + .zip(permuted_wire_values[start..].iter()) + { + *modified_aux *= &(x_0 * permuted_aux_value + &x_1 + aux_value); + } + }); + } + // TODO: implement for fixed wires + _ => unreachable!(), + } } permutation_modified_advice.push(modified_advice); @@ -214,17 +233,38 @@ impl Proof { let mut deltaomega = C::Scalar::one(); for &(wire, _) in wires.iter() { let omega = domain.get_omega(); - parallelize(&mut modified_advice, |modified_advice, start| { - 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[wire.0][start..].iter()) - { - // Multiply by p_j(\omega^i) + \delta^j \omega^i \beta - *modified_advice *= &(deltaomega * &x_0 + &x_1 + advice_value); - deltaomega *= ω + match wire { + Wire::Advice(wire) => { + parallelize(&mut modified_advice, |modified_advice, start| { + 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[wire.0][start..].iter()) + { + // Multiply by p_j(\omega^i) + \delta^j \omega^i \beta + *modified_advice *= &(deltaomega * &x_0 + &x_1 + advice_value); + deltaomega *= ω + } + }); } - }); + Wire::Aux(wire) => { + parallelize(&mut modified_advice, |modified_advice, start| { + let mut deltaomega = + deltaomega * &omega.pow_vartime(&[start as u64, 0, 0, 0]); + for (modified_advice, advice_value) in modified_advice + .iter_mut() + .zip(aux_lagrange_polys[wire.0][start..].iter()) + { + // Multiply by p_j(\omega^i) + \delta^j \omega^i \beta + *modified_advice *= &(deltaomega * &x_0 + &x_1 + advice_value); + deltaomega *= ω + } + }); + } + // TODO: implement for fixed wires + _ => unreachable!(), + } deltaomega *= &C::Scalar::DELTA; }