Give fixed and advice wires separate types

This commit is contained in:
Sean Bowe 2020-08-23 13:26:04 -06:00
parent 7edffe0197
commit c20f3fdf1a
No known key found for this signature in database
GPG key ID: 95684257D8F8B031
4 changed files with 100 additions and 77 deletions

View file

@ -112,14 +112,14 @@ fn test_proving() {
let params: Params<EqAffine> = Params::new::<DummyHash<Fq>>(K); let params: Params<EqAffine> = Params::new::<DummyHash<Fq>>(K);
struct MyConfig { struct MyConfig {
a: Wire, a: AdviceWire,
b: Wire, b: AdviceWire,
c: Wire, c: AdviceWire,
sa: Wire, sa: FixedWire,
sb: Wire, sb: FixedWire,
sc: Wire, sc: FixedWire,
sm: Wire, sm: FixedWire,
} }
struct MyCircuit<F: Field> { struct MyCircuit<F: Field> {
a: Option<F>, a: Option<F>,
@ -174,36 +174,26 @@ fn test_proving() {
// Similar to the above... // Similar to the above...
let mut row = 0; let mut row = 0;
for _ in 0..10 { for _ in 0..10 {
cs.assign(Variable(config.a, row), || { cs.assign_advice(config.a, row, || self.a.ok_or(Error::SynthesisError))?;
self.a.ok_or(Error::SynthesisError) cs.assign_advice(config.b, row, || self.a.ok_or(Error::SynthesisError))?;
})?;
cs.assign(Variable(config.b, row), || {
self.a.ok_or(Error::SynthesisError)
})?;
let a_squared = self.a.map(|a| a.square()); let a_squared = self.a.map(|a| a.square());
cs.assign(Variable(config.c, row), || { cs.assign_advice(config.c, row, || self.a.ok_or(Error::SynthesisError))?;
self.a.ok_or(Error::SynthesisError)
})?;
// Multiplication gate // Multiplication gate
cs.assign(Variable(config.sa, row), || Ok(Field::zero()))?; cs.assign_fixed(config.sa, row, || Ok(Field::zero()))?;
cs.assign(Variable(config.sb, row), || Ok(Field::zero()))?; cs.assign_fixed(config.sb, row, || Ok(Field::zero()))?;
cs.assign(Variable(config.sc, row), || Ok(Field::one()))?; cs.assign_fixed(config.sc, row, || Ok(Field::one()))?;
cs.assign(Variable(config.sm, row), || Ok(Field::one()))?; cs.assign_fixed(config.sm, row, || Ok(Field::one()))?;
row += 1; row += 1;
cs.assign(Variable(config.a, row), || { cs.assign_advice(config.a, row, || self.a.ok_or(Error::SynthesisError))?;
self.a.ok_or(Error::SynthesisError) cs.assign_advice(config.b, row, || a_squared.ok_or(Error::SynthesisError))?;
})?;
cs.assign(Variable(config.b, row), || {
a_squared.ok_or(Error::SynthesisError)
})?;
let fin = a_squared.and_then(|a_squared| self.a.map(|a| a + a_squared)); let fin = a_squared.and_then(|a_squared| self.a.map(|a| a + a_squared));
cs.assign(Variable(config.c, row), || fin.ok_or(Error::SynthesisError))?; cs.assign_advice(config.c, row, || fin.ok_or(Error::SynthesisError))?;
// Addition gate // Addition gate
cs.assign(Variable(config.sa, row), || Ok(Field::one()))?; cs.assign_fixed(config.sa, row, || Ok(Field::one()))?;
cs.assign(Variable(config.sb, row), || Ok(Field::one()))?; cs.assign_fixed(config.sb, row, || Ok(Field::one()))?;
cs.assign(Variable(config.sc, row), || Ok(Field::one()))?; cs.assign_fixed(config.sc, row, || Ok(Field::one()))?;
cs.assign(Variable(config.sm, row), || Ok(Field::zero()))?; cs.assign_fixed(config.sm, row, || Ok(Field::zero()))?;
row += 1; row += 1;
} }

View file

@ -16,12 +16,16 @@ pub enum Wire {
C, C,
/// D wires /// D wires
D, D,
/// Fixed wires
Fixed(usize),
/// Advice wires
Advice(usize),
} }
/// This represents a wire which has a fixed (permanent) value
#[derive(Copy, Clone, Debug)]
pub struct FixedWire(pub usize);
/// This represents a wire which has a witness-specific value
#[derive(Copy, Clone, Debug)]
pub struct AdviceWire(pub usize);
/// Represents a pointer to a value in the constraint system. /// Represents a pointer to a value in the constraint system.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Variable(pub Wire, pub usize); pub struct Variable(pub Wire, pub usize);
@ -29,9 +33,21 @@ pub struct Variable(pub Wire, pub usize);
/// 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 ConstraintSystem<F: Field> { pub trait ConstraintSystem<F: Field> {
/// Assign a wire value /// Assign an advice wire value (witness)
fn assign(&mut self, var: Variable, to: impl FnOnce() -> Result<F, Error>) fn assign_advice(
-> Result<(), Error>; &mut self,
wire: AdviceWire,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error>;
/// Assign a fixed value
fn assign_fixed(
&mut self,
wire: FixedWire,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error>;
/// Creates a gate. /// Creates a gate.
fn create_gate( fn create_gate(
@ -93,8 +109,10 @@ pub trait Circuit<F: Field> {
/// Low-degree polynomial representing an identity that must hold over the committed wires. /// Low-degree polynomial representing an identity that must hold over the committed wires.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Polynomial<F> { pub enum Polynomial<F> {
/// This is a wire queried at a certain relative location /// This is a fixed wire queried at a certain relative location
Wire(Wire, isize), Fixed(FixedWire, isize),
/// This is an advice (witness) wire queried at a certain relative location
Advice(AdviceWire, isize),
/// This is the sum of two polynomials /// This is the sum of two polynomials
Sum(Box<Polynomial<F>>, Box<Polynomial<F>>), Sum(Box<Polynomial<F>>, Box<Polynomial<F>>),
/// This is the product of two polynomials /// This is the product of two polynomials
@ -106,10 +124,11 @@ pub enum Polynomial<F> {
impl<F: Field> Polynomial<F> { impl<F: Field> Polynomial<F> {
fn degree(&self) -> usize { fn degree(&self) -> usize {
match self { match self {
Polynomial::Wire(_, _) => 1, Polynomial::Fixed(_, _) => 1,
Polynomial::Sum(ref a, ref b) => max(a.degree(), b.degree()), Polynomial::Advice(_, _) => 1,
Polynomial::Product(ref a, ref b) => a.degree() + b.degree(), Polynomial::Sum(a, b) => max(a.degree(), b.degree()),
Polynomial::Scaled(ref poly, _) => poly.degree(), Polynomial::Product(a, b) => a.degree() + b.degree(),
Polynomial::Scaled(poly, _) => poly.degree(),
} }
} }
} }
@ -158,14 +177,14 @@ impl Default for MetaCircuit {
impl MetaCircuit { impl MetaCircuit {
/// Allocate a new fixed wire /// Allocate a new fixed wire
pub fn fixed_wire(&mut self) -> Wire { pub fn fixed_wire(&mut self) -> FixedWire {
let tmp = Wire::Fixed(self.num_fixed_wires); let tmp = FixedWire(self.num_fixed_wires);
self.num_fixed_wires += 1; self.num_fixed_wires += 1;
tmp tmp
} }
/// Allocate a new advice wire /// Allocate a new advice wire
pub fn advice_wire(&mut self) -> Wire { pub fn advice_wire(&mut self) -> AdviceWire {
let tmp = Wire::Advice(self.num_advice_wires); let tmp = AdviceWire(self.num_advice_wires);
self.num_advice_wires += 1; self.num_advice_wires += 1;
tmp tmp
} }

View file

@ -1,5 +1,5 @@
use super::{ use super::{
circuit::{Circuit, ConstraintSystem, MetaCircuit, Variable, Wire}, circuit::{AdviceWire, Circuit, ConstraintSystem, FixedWire, MetaCircuit, Variable, Wire},
hash_point, Error, Proof, SRS, hash_point, Error, Proof, SRS,
}; };
use crate::arithmetic::{ use crate::arithmetic::{
@ -35,22 +35,29 @@ impl<C: CurveAffine> Proof<C> {
} }
impl<F: Field> ConstraintSystem<F> for WitnessCollection<F> { impl<F: Field> ConstraintSystem<F> for WitnessCollection<F> {
fn assign( fn assign_advice(
&mut self, &mut self,
var: Variable, wire: AdviceWire,
row: usize,
to: impl FnOnce() -> Result<F, Error>, to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// We only care about advice wires here. *self
match var.0 { .advice
Wire::Advice(index) => { .get_mut(wire.0)
*self .and_then(|v| v.get_mut(row))
.advice .ok_or(Error::BoundsFailure)? = to()?;
.get_mut(index)
.and_then(|v| v.get_mut(var.1)) Ok(())
.ok_or(Error::BoundsFailure)? = to()?; }
}
_ => {} fn assign_fixed(
} &mut self,
_: FixedWire,
_: usize,
_: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
// We only care about advice wires here
Ok(()) Ok(())
} }

View file

@ -1,5 +1,5 @@
use super::{ use super::{
circuit::{Circuit, ConstraintSystem, MetaCircuit, Variable, Wire}, circuit::{AdviceWire, Circuit, ConstraintSystem, FixedWire, MetaCircuit, Variable, Wire},
domain::EvaluationDomain, domain::EvaluationDomain,
Error, GATE_DEGREE, SRS, Error, GATE_DEGREE, SRS,
}; };
@ -23,24 +23,31 @@ impl<C: CurveAffine> SRS<C> {
} }
impl<F: Field> ConstraintSystem<F> for Assembly<F> { impl<F: Field> ConstraintSystem<F> for Assembly<F> {
fn assign( fn assign_advice(
&mut self, &mut self,
var: Variable, _: AdviceWire,
to: impl FnOnce() -> Result<F, Error>, _: usize,
_: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// We only care about fixed wires here. // We only care about fixed wires here
match var.0 {
Wire::Fixed(index) => {
*self
.fixed
.get_mut(index)
.and_then(|v| v.get_mut(var.1))
.ok_or(Error::BoundsFailure)? = to()?;
}
_ => {}
}
Ok(()) Ok(())
} }
fn assign_fixed(
&mut self,
wire: FixedWire,
row: usize,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
*self
.fixed
.get_mut(wire.0)
.and_then(|v| v.get_mut(row))
.ok_or(Error::BoundsFailure)? = to()?;
Ok(())
}
fn create_gate( fn create_gate(
&mut self, &mut self,
sa: F, sa: F,