mirror of https://github.com/zcash/halo2.git
201 lines
7.2 KiB
Rust
201 lines
7.2 KiB
Rust
use crate::circuit::{layouter::SyncDeps, Layouter, Value};
|
|
use crate::plonk::{Assigned, Error};
|
|
use halo2_middleware::circuit::{Advice, Any, Fixed, Instance};
|
|
use halo2_middleware::ff::Field;
|
|
|
|
pub mod compress_selectors;
|
|
pub mod constraint_system;
|
|
pub mod expression;
|
|
|
|
pub use constraint_system::*;
|
|
pub use expression::*;
|
|
|
|
// TODO: Bring ColumnType, Advice, Fixed, Instance and Any here, where Advice has a sealed phase
|
|
// Keep a slim copy of those types in middleware.
|
|
// https://github.com/privacy-scaling-explorations/halo2/issues/295
|
|
|
|
/// This trait allows a [`Circuit`] to direct some backend to assign a witness
|
|
/// for a constraint system.
|
|
pub trait Assignment<F: Field> {
|
|
/// Creates a new region and enters into it.
|
|
///
|
|
/// Panics if we are currently in a region (if `exit_region` was not called).
|
|
///
|
|
/// Not intended for downstream consumption; use [`Layouter::assign_region`] instead.
|
|
///
|
|
/// [`Layouter::assign_region`]: crate::circuit::Layouter#method.assign_region
|
|
fn enter_region<NR, N>(&mut self, name_fn: N)
|
|
where
|
|
NR: Into<String>,
|
|
N: FnOnce() -> NR;
|
|
|
|
/// Allows the developer to include an annotation for an specific column within a `Region`.
|
|
///
|
|
/// This is usually useful for debugging circuit failures.
|
|
fn annotate_column<A, AR>(&mut self, annotation: A, column: Column<Any>)
|
|
where
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>;
|
|
|
|
/// Exits the current region.
|
|
///
|
|
/// Panics if we are not currently in a region (if `enter_region` was not called).
|
|
///
|
|
/// Not intended for downstream consumption; use [`Layouter::assign_region`] instead.
|
|
///
|
|
/// [`Layouter::assign_region`]: crate::circuit::Layouter#method.assign_region
|
|
fn exit_region(&mut self);
|
|
|
|
/// Enables a selector at the given row.
|
|
fn enable_selector<A, AR>(
|
|
&mut self,
|
|
annotation: A,
|
|
selector: &Selector,
|
|
row: usize,
|
|
) -> Result<(), Error>
|
|
where
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>;
|
|
|
|
/// Queries the cell of an instance column at a particular absolute row.
|
|
///
|
|
/// Returns the cell's value, if known.
|
|
fn query_instance(&self, column: Column<Instance>, row: usize) -> Result<Value<F>, Error>;
|
|
|
|
/// Assign an advice column value (witness)
|
|
fn assign_advice<V, VR, A, AR>(
|
|
&mut self,
|
|
annotation: A,
|
|
column: Column<Advice>,
|
|
row: usize,
|
|
to: V,
|
|
) -> Result<(), Error>
|
|
where
|
|
V: FnOnce() -> Value<VR>,
|
|
VR: Into<Assigned<F>>,
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>;
|
|
|
|
/// Assign a fixed value
|
|
fn assign_fixed<V, VR, A, AR>(
|
|
&mut self,
|
|
annotation: A,
|
|
column: Column<Fixed>,
|
|
row: usize,
|
|
to: V,
|
|
) -> Result<(), Error>
|
|
where
|
|
V: FnOnce() -> Value<VR>,
|
|
VR: Into<Assigned<F>>,
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>;
|
|
|
|
/// Assign two cells to have the same value
|
|
fn copy(
|
|
&mut self,
|
|
left_column: Column<Any>,
|
|
left_row: usize,
|
|
right_column: Column<Any>,
|
|
right_row: usize,
|
|
) -> Result<(), Error>;
|
|
|
|
/// Fills a fixed `column` starting from the given `row` with value `to`.
|
|
fn fill_from_row(
|
|
&mut self,
|
|
column: Column<Fixed>,
|
|
row: usize,
|
|
to: Value<Assigned<F>>,
|
|
) -> Result<(), Error>;
|
|
|
|
/// Queries the value of the given challenge.
|
|
///
|
|
/// Returns `Value::unknown()` if the current synthesis phase is before the challenge can be queried.
|
|
fn get_challenge(&self, challenge: Challenge) -> Value<F>;
|
|
|
|
/// Creates a new (sub)namespace and enters into it.
|
|
///
|
|
/// Not intended for downstream consumption; use [`Layouter::namespace`] instead.
|
|
///
|
|
/// [`Layouter::namespace`]: crate::circuit::Layouter#method.namespace
|
|
fn push_namespace<NR, N>(&mut self, name_fn: N)
|
|
where
|
|
NR: Into<String>,
|
|
N: FnOnce() -> NR;
|
|
|
|
/// Exits out of the existing namespace.
|
|
///
|
|
/// Not intended for downstream consumption; use [`Layouter::namespace`] instead.
|
|
///
|
|
/// [`Layouter::namespace`]: crate::circuit::Layouter#method.namespace
|
|
fn pop_namespace(&mut self, gadget_name: Option<String>);
|
|
}
|
|
|
|
/// A floor planning strategy for a circuit.
|
|
///
|
|
/// The floor planner is chip-agnostic and applies its strategy to the circuit it is used
|
|
/// within.
|
|
pub trait FloorPlanner {
|
|
/// Given the provided `cs`, synthesize the given circuit.
|
|
///
|
|
/// `constants` is the list of fixed columns that the layouter may use to assign
|
|
/// global constant values. These columns will all have been equality-enabled.
|
|
///
|
|
/// Internally, a floor planner will perform the following operations:
|
|
/// - Instantiate a [`Layouter`] for this floor planner.
|
|
/// - Perform any necessary setup or measurement tasks, which may involve one or more
|
|
/// calls to `Circuit::default().synthesize(config, &mut layouter)`.
|
|
/// - Call `circuit.synthesize(config, &mut layouter)` exactly once.
|
|
fn synthesize<F: Field, CS: Assignment<F> + SyncDeps, C: Circuit<F>>(
|
|
cs: &mut CS,
|
|
circuit: &C,
|
|
config: C::Config,
|
|
constants: Vec<Column<Fixed>>,
|
|
) -> Result<(), Error>;
|
|
}
|
|
|
|
/// 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> {
|
|
/// This is a configuration object that stores things like columns.
|
|
type Config: Clone;
|
|
/// The floor planner used for this circuit. This is an associated type of the
|
|
/// `Circuit` trait because its behaviour is circuit-critical.
|
|
type FloorPlanner: FloorPlanner;
|
|
/// Optional circuit configuration parameters. Requires the `circuit-params` feature.
|
|
#[cfg(feature = "circuit-params")]
|
|
type Params: Default;
|
|
|
|
/// Returns a copy of this circuit with no witness values (i.e. all witnesses set to
|
|
/// `None`). For most circuits, this will be equal to `Self::default()`.
|
|
fn without_witnesses(&self) -> Self;
|
|
|
|
/// Returns a reference to the parameters that should be used to configure the circuit.
|
|
/// Requires the `circuit-params` feature.
|
|
#[cfg(feature = "circuit-params")]
|
|
fn params(&self) -> Self::Params {
|
|
Self::Params::default()
|
|
}
|
|
|
|
/// The circuit is given an opportunity to describe the exact gate
|
|
/// arrangement, column arrangement, etc. Takes a runtime parameter. The default
|
|
/// implementation calls `configure` ignoring the `_params` argument in order to easily support
|
|
/// circuits that don't use configuration parameters.
|
|
#[cfg(feature = "circuit-params")]
|
|
fn configure_with_params(
|
|
meta: &mut ConstraintSystem<F>,
|
|
_params: Self::Params,
|
|
) -> Self::Config {
|
|
Self::configure(meta)
|
|
}
|
|
|
|
/// The circuit is given an opportunity to describe the exact gate
|
|
/// arrangement, column arrangement, etc.
|
|
fn configure(meta: &mut ConstraintSystem<F>) -> 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
|
|
/// may not expect to have a witness present.
|
|
fn synthesize(&self, config: Self::Config, layouter: impl Layouter<F>) -> Result<(), Error>;
|
|
}
|