diff --git a/src/plonk.rs b/src/plonk.rs index ef6e997..d6d9188 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -45,7 +45,7 @@ pub struct SRS { fixed_commitments: Vec, fixed_polys: Vec<(Vec, Vec)>, - meta: MetaCircuit, + meta: MetaCircuit, } /// This is an object which represents a (Turbo)PLONK proof. @@ -128,7 +128,7 @@ fn test_proving() { impl Circuit for MyCircuit { type Config = MyConfig; - fn configure(meta: &mut MetaCircuit) -> MyConfig { + fn configure(meta: &mut MetaCircuit) -> MyConfig { let a = meta.advice_wire(); let b = meta.advice_wire(); let c = meta.advice_wire(); @@ -138,6 +138,19 @@ fn test_proving() { let sc = meta.fixed_wire(); let sm = meta.fixed_wire(); + meta.create_gate(|meta| { + let a = meta.query_advice(a, 0); + let b = meta.query_advice(b, 0); + let c = meta.query_advice(c, 0); + + let sa = meta.query_fixed(sa, 0); + let sb = meta.query_fixed(sb, 0); + let sc = meta.query_fixed(sc, 0); + let sm = meta.query_fixed(sm, 0); + + a.clone() * sa + b.clone() * sb + a * b * sm + (c * sc * (-F::one())) + }); + MyConfig { a, b, diff --git a/src/plonk/circuit.rs b/src/plonk/circuit.rs index 6f3d165..c04ec7e 100644 --- a/src/plonk/circuit.rs +++ b/src/plonk/circuit.rs @@ -1,5 +1,6 @@ use core::cmp::max; use core::ops::{Add, Mul}; +use std::collections::HashMap; use super::Error; use crate::arithmetic::Field; @@ -19,11 +20,11 @@ pub enum Wire { } /// This represents a wire which has a fixed (permanent) value -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct FixedWire(pub usize); /// This represents a wire which has a witness-specific value -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct AdviceWire(pub usize); /// Represents a pointer to a value in the constraint system. @@ -94,7 +95,7 @@ pub trait Circuit { /// The circuit is given an opportunity to describe the exact gate /// arrangement, wire arrangement, etc. - fn configure(meta: &mut MetaCircuit) -> Self::Config; + fn configure(meta: &mut MetaCircuit) -> Self::Config; /// Given the provided `cs`, synthesize the circuit. The concrete type of /// the caller will be different depending on the context, and they may or @@ -121,6 +122,36 @@ pub enum Polynomial { Scaled(Box>, F), } +impl Polynomial { + fn evaluate( + &self, + fixed_wire: &impl Fn(FixedWire, isize) -> T, + advice_wire: &impl Fn(AdviceWire, isize) -> T, + sum: &impl Fn(T, T) -> T, + product: &impl Fn(T, T) -> T, + scaled: &impl Fn(T, F) -> T, + ) -> T { + match self { + Polynomial::Fixed(a, location) => fixed_wire(*a, *location), + Polynomial::Advice(a, location) => advice_wire(*a, *location), + Polynomial::Sum(a, b) => { + let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); + let b = b.evaluate(fixed_wire, advice_wire, sum, product, scaled); + sum(a, b) + } + Polynomial::Product(a, b) => { + let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); + let b = b.evaluate(fixed_wire, advice_wire, sum, product, scaled); + product(a, b) + } + Polynomial::Scaled(a, f) => { + let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); + scaled(a, *f) + } + } + } +} + impl Polynomial { fn degree(&self) -> usize { match self { @@ -157,25 +188,51 @@ impl Mul for Polynomial { /// This is a description of the circuit environment, such as the gate, wire and /// permutation arrangements. #[derive(Debug, Clone)] -pub struct MetaCircuit { +pub struct MetaCircuit { pub(crate) num_fixed_wires: usize, pub(crate) num_advice_wires: usize, // permutations: Vec>, - // gates: Vec, - // queries: HashSet<(Wire, usize)>, + gates: Vec>, + advice_queries: HashMap<(AdviceWire, isize), usize>, + fixed_queries: HashMap<(FixedWire, isize), usize>, // num_queries: usize, } -impl Default for MetaCircuit { - fn default() -> MetaCircuit { +impl Default for MetaCircuit { + fn default() -> MetaCircuit { MetaCircuit { num_fixed_wires: 0, num_advice_wires: 0, + gates: vec![], + fixed_queries: HashMap::new(), + advice_queries: HashMap::new(), } } } -impl MetaCircuit { +impl MetaCircuit { + /// Query a fixed wire at a relative position + pub fn query_fixed(&mut self, wire: FixedWire, at: isize) -> Polynomial { + let len = self.fixed_queries.len(); + self.fixed_queries.entry((wire, at)).or_insert_with(|| len); + + Polynomial::Fixed(wire, at) + } + + /// Query an advice wire at a relative position + pub fn query_advice(&mut self, wire: AdviceWire, at: isize) -> Polynomial { + let len = self.advice_queries.len(); + self.advice_queries.entry((wire, at)).or_insert_with(|| len); + + Polynomial::Advice(wire, at) + } + + /// Create a new gate + pub fn create_gate(&mut self, f: impl FnOnce(&mut Self) -> Polynomial) { + let poly = f(self); + self.gates.push(poly); + } + /// Allocate a new fixed wire pub fn fixed_wire(&mut self) -> FixedWire { let tmp = FixedWire(self.num_fixed_wires);