pasta_curves-source/src/plonk/circuit.rs

143 lines
4 KiB
Rust
Raw Normal View History

2020-08-22 21:09:47 +00:00
use core::cmp::max;
use core::ops::{Add, Mul};
2020-08-22 20:15:39 +00:00
2020-08-22 21:09:47 +00:00
use super::Error;
2020-08-22 20:15:39 +00:00
use crate::arithmetic::Field;
/// This represents a PLONK wire, which could be a fixed (selector) wire or an
/// advice wire.
2020-08-22 21:09:47 +00:00
#[derive(Clone, Debug)]
2020-08-22 20:15:39 +00:00
pub enum Wire {
/// A wires
A(usize),
/// B wires
B(usize),
/// C wires
C(usize),
/// D wires
D(usize),
}
/// This trait allows a [`Circuit`] to direct some backend to assign a witness
/// for a constraint system.
pub trait ConstraintSystem<F: Field> {
/// Creates a gate.
fn create_gate(
&mut self,
sa: F,
sb: F,
sc: F,
sd: F,
sm: F,
f: impl Fn() -> Result<(F, F, F, F), Error>,
) -> Result<(Wire, Wire, Wire, Wire), Error>;
/// a * b - c = 0
fn multiply(
&mut self,
f: impl Fn() -> Result<(F, F, F), Error>,
) -> Result<(Wire, Wire, Wire, Wire), Error> {
self.create_gate(F::zero(), F::zero(), F::one(), F::zero(), F::one(), || {
let (a, b, c) = f()?;
Ok((a, b, c, F::zero()))
})
}
/// a + b - c = 0
fn add(
&mut self,
f: impl Fn() -> Result<(F, F, F), Error>,
) -> Result<(Wire, Wire, Wire, Wire), Error> {
self.create_gate(F::one(), F::one(), F::one(), F::zero(), F::zero(), || {
let (a, b, c) = f()?;
Ok((a, b, c, F::zero()))
})
}
// fn copy(&mut self, left: Wire, right: Wire);
}
/// This is a trait that circuits provide implementations for so that the
/// backend prover can ask the circuit to synthesize using some given
/// [`ConstraintSystem`] implementation.
pub trait Circuit<F: Field> {
2020-08-22 21:09:47 +00:00
/// This is a configuration object that stores things like wires.
type Config;
/// The circuit is given an opportunity to describe the exact gate
/// arrangement, wire arrangement, etc.
fn configure(meta: &mut MetaCircuit) -> Self::Config;
2020-08-22 20:15:39 +00:00
/// Given the provided `cs`, synthesize the circuit. The concrete type of
/// the caller will be different depending on the context, and they may or
/// may not expect to have a witness present.
2020-08-22 21:09:47 +00:00
fn synthesize(
&self,
cs: &mut impl ConstraintSystem<F>,
config: Self::Config,
) -> Result<(), Error>;
}
/// Low-degree polynomial representing an identity that must hold over the committed wires.
#[derive(Clone, Debug)]
pub enum Polynomial<F> {
/// This is a wire queried at a certain relative location
Wire(Wire, isize),
/// This is the sum of two polynomials
Sum(Box<Polynomial<F>>, Box<Polynomial<F>>),
/// This is the product of two polynomials
Product(Box<Polynomial<F>>, Box<Polynomial<F>>),
/// This is a scaled polynomial
Scaled(Box<Polynomial<F>>, F),
}
impl<F: Field> Polynomial<F> {
fn degree(&self) -> usize {
match self {
Polynomial::Wire(_, _) => 1,
Polynomial::Sum(ref a, ref b) => max(a.degree(), b.degree()),
Polynomial::Product(ref a, ref b) => a.degree() + b.degree(),
Polynomial::Scaled(ref poly, _) => poly.degree(),
}
}
}
impl<F> Add for Polynomial<F> {
type Output = Polynomial<F>;
fn add(self, rhs: Polynomial<F>) -> Polynomial<F> {
Polynomial::Sum(Box::new(self), Box::new(rhs))
}
}
impl<F> Mul for Polynomial<F> {
type Output = Polynomial<F>;
fn mul(self, rhs: Polynomial<F>) -> Polynomial<F> {
Polynomial::Product(Box::new(self), Box::new(rhs))
}
}
impl<F> Mul<F> for Polynomial<F> {
type Output = Polynomial<F>;
fn mul(self, rhs: F) -> Polynomial<F> {
Polynomial::Scaled(Box::new(self), rhs)
}
}
/// This is a description of the circuit environment, such as the gate, wire and
/// permutation arrangements.
#[derive(Debug, Clone)]
pub struct MetaCircuit {
// num_fixed_wires: usize,
// num_advice_wires: usize,
// permutations: Vec<Vec<Wire>>,
// gates: Vec<Polynomial>,
// queries: HashSet<(Wire, usize)>,
// num_queries: usize,
}
impl Default for MetaCircuit {
fn default() -> MetaCircuit {
MetaCircuit {}
}
2020-08-22 20:15:39 +00:00
}