plonky2/src/gates/gate.rs

91 lines
2.6 KiB
Rust
Raw Normal View History

2021-02-09 21:25:21 -08:00
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use crate::circuit_data::CircuitConfig;
2021-03-25 15:20:14 -07:00
use crate::constraint_polynomial::{ConstraintPolynomial, EvaluationVars};
2021-02-09 21:25:21 -08:00
use crate::field::field::Field;
2021-03-01 13:40:05 -08:00
use crate::generator::WitnessGenerator;
2021-02-26 13:18:41 -08:00
use num::ToPrimitive;
2021-02-09 21:25:21 -08:00
/// A custom gate.
// TODO: Remove CircuitConfig params? Could just use fields within each struct.
2021-02-24 12:25:13 -08:00
pub trait Gate<F: Field>: 'static {
2021-02-09 21:25:21 -08:00
fn id(&self) -> String;
/// A set of expressions which must evaluate to zero.
fn constraints(&self, config: CircuitConfig) -> Vec<ConstraintPolynomial<F>>;
2021-03-25 15:20:14 -07:00
// fn eval_constraints(&self, config: CircuitConfig, vars: EvaluationVars<F>) -> Vec<F> {
// self.constraints(config)
// .into_iter()
// .map(|c| c.evaluate(vars))
// .collect()
// }
2021-02-09 21:25:21 -08:00
fn generators(
&self,
config: CircuitConfig,
gate_index: usize,
2021-03-25 15:20:14 -07:00
// TODO: Switch to slices?
2021-02-09 21:25:21 -08:00
local_constants: Vec<F>,
next_constants: Vec<F>,
2021-03-01 13:40:05 -08:00
) -> Vec<Box<dyn WitnessGenerator<F>>>;
2021-02-09 21:25:21 -08:00
/// The number of constants used by this gate.
fn num_constants(&self, config: CircuitConfig) -> usize {
self.constraints(config)
.into_iter()
.map(|c| c.max_constant_index().map_or(0, |i| i + 1))
.max()
.unwrap_or(0)
}
/// The minimum number of wires required to use this gate.
fn min_wires(&self, config: CircuitConfig) -> usize {
self.constraints(config)
.into_iter()
.map(|c| c.max_wire_input_index().map_or(0, |i| i + 1))
.max()
.unwrap_or(0)
}
/// The maximum degree among this gate's constraint polynomials.
fn degree(&self, config: CircuitConfig) -> usize {
self.constraints(config)
.into_iter()
2021-02-26 13:18:41 -08:00
.map(|c| c.degree().to_usize().expect("degree too large"))
2021-02-09 21:25:21 -08:00
.max()
.unwrap_or(0)
}
}
/// A wrapper around an `Rc<Gate>` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs.
#[derive(Clone)]
2021-02-24 12:25:13 -08:00
pub struct GateRef<F: Field>(pub(crate) Rc<dyn Gate<F>>);
2021-02-09 21:25:21 -08:00
impl<F: Field> GateRef<F> {
2021-02-24 12:25:13 -08:00
pub fn new<G: Gate<F>>(gate: G) -> GateRef<F> {
2021-02-09 21:25:21 -08:00
GateRef(Rc::new(gate))
}
}
impl<F: Field> PartialEq for GateRef<F> {
fn eq(&self, other: &Self) -> bool {
self.0.id() == other.0.id()
}
}
impl<F: Field> Hash for GateRef<F> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.id().hash(state)
}
}
impl<F: Field> Eq for GateRef<F> {}
/// A gate along with any constants used to configure it.
pub struct GateInstance<F: Field> {
pub gate_type: GateRef<F>,
pub constants: Vec<F>,
}