2020-12-14 16:36:58 -08:00
|
|
|
//! Traits and structs for implementing circuit components.
|
|
|
|
|
2022-09-09 10:43:43 -07:00
|
|
|
use std::{fmt, marker::PhantomData};
|
2020-12-14 16:36:58 -08:00
|
|
|
|
2021-06-20 16:10:16 -07:00
|
|
|
use ff::Field;
|
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
use crate::{
|
|
|
|
arithmetic::FieldExt,
|
2021-07-27 07:46:37 -07:00
|
|
|
plonk::{Advice, Any, Assigned, Column, Error, Fixed, Instance, Selector, TableColumn},
|
2020-12-14 16:36:58 -08:00
|
|
|
};
|
|
|
|
|
2022-06-07 16:13:42 -07:00
|
|
|
mod value;
|
|
|
|
pub use value::Value;
|
|
|
|
|
2021-06-21 11:10:59 -07:00
|
|
|
pub mod floor_planner;
|
|
|
|
pub use floor_planner::single_pass::SimpleFloorPlanner;
|
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
pub mod layouter;
|
|
|
|
|
|
|
|
/// A chip implements a set of instructions that can be used by gadgets.
|
|
|
|
///
|
2021-04-19 06:25:32 -07:00
|
|
|
/// The chip stores state that is required at circuit synthesis time in
|
|
|
|
/// [`Chip::Config`], which can be fetched via [`Chip::config`].
|
|
|
|
///
|
|
|
|
/// The chip also loads any fixed configuration needed at synthesis time
|
2021-04-25 17:53:43 -07:00
|
|
|
/// using its own implementation of `load`, and stores it in [`Chip::Loaded`].
|
|
|
|
/// This can be accessed via [`Chip::loaded`].
|
2021-04-19 06:25:32 -07:00
|
|
|
pub trait Chip<F: FieldExt>: Sized {
|
2020-12-14 16:36:58 -08:00
|
|
|
/// A type that holds the configuration for this chip, and any other state it may need
|
2021-02-24 07:16:55 -08:00
|
|
|
/// during circuit synthesis, that can be derived during [`Circuit::configure`].
|
|
|
|
///
|
|
|
|
/// [`Circuit::configure`]: crate::plonk::Circuit::configure
|
2021-04-27 19:47:26 -07:00
|
|
|
type Config: fmt::Debug + Clone;
|
2020-12-14 16:36:58 -08:00
|
|
|
|
2021-02-24 07:16:55 -08:00
|
|
|
/// A type that holds any general chip state that needs to be loaded at the start of
|
|
|
|
/// [`Circuit::synthesize`]. This might simply be `()` for some chips.
|
|
|
|
///
|
|
|
|
/// [`Circuit::synthesize`]: crate::plonk::Circuit::synthesize
|
2021-04-27 19:47:26 -07:00
|
|
|
type Loaded: fmt::Debug + Clone;
|
2021-04-19 06:25:32 -07:00
|
|
|
|
|
|
|
/// The chip holds its own configuration.
|
|
|
|
fn config(&self) -> &Self::Config;
|
|
|
|
|
|
|
|
/// Provides access to general chip state loaded at the beginning of circuit
|
|
|
|
/// synthesis.
|
2021-02-24 07:16:55 -08:00
|
|
|
///
|
2021-04-21 15:58:44 -07:00
|
|
|
/// Panics if called before `Chip::load`.
|
2021-04-19 06:25:32 -07:00
|
|
|
fn loaded(&self) -> &Self::Loaded;
|
2020-12-14 16:36:58 -08:00
|
|
|
}
|
|
|
|
|
2021-02-20 05:19:06 -08:00
|
|
|
/// Index of a region in a layouter
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub struct RegionIndex(usize);
|
|
|
|
|
|
|
|
impl From<usize> for RegionIndex {
|
|
|
|
fn from(idx: usize) -> RegionIndex {
|
|
|
|
RegionIndex(idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::ops::Deref for RegionIndex {
|
|
|
|
type Target = usize;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Starting row of a region in a layouter
|
2021-06-08 03:03:29 -07:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
2021-02-20 05:19:06 -08:00
|
|
|
pub struct RegionStart(usize);
|
|
|
|
|
|
|
|
impl From<usize> for RegionStart {
|
|
|
|
fn from(idx: usize) -> RegionStart {
|
|
|
|
RegionStart(idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::ops::Deref for RegionStart {
|
|
|
|
type Target = usize;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
/// A pointer to a cell within a circuit.
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub struct Cell {
|
|
|
|
/// Identifies the region in which this cell resides.
|
2021-02-20 05:19:06 -08:00
|
|
|
region_index: RegionIndex,
|
2021-01-05 17:16:30 -08:00
|
|
|
/// The relative offset of this cell within its region.
|
2020-12-14 16:36:58 -08:00
|
|
|
row_offset: usize,
|
2021-01-05 17:16:30 -08:00
|
|
|
/// The column of this cell.
|
2020-12-14 16:36:58 -08:00
|
|
|
column: Column<Any>,
|
|
|
|
}
|
|
|
|
|
2021-10-11 07:00:40 -07:00
|
|
|
/// An assigned cell.
|
2021-11-27 06:41:27 -08:00
|
|
|
#[derive(Clone, Debug)]
|
2021-11-29 14:37:38 -08:00
|
|
|
pub struct AssignedCell<V, F: Field> {
|
2022-06-07 16:15:35 -07:00
|
|
|
value: Value<V>,
|
2021-10-11 07:00:40 -07:00
|
|
|
cell: Cell,
|
|
|
|
_marker: PhantomData<F>,
|
|
|
|
}
|
|
|
|
|
2021-11-29 14:37:38 -08:00
|
|
|
impl<V, F: Field> AssignedCell<V, F> {
|
2021-10-11 07:00:40 -07:00
|
|
|
/// Returns the value of the [`AssignedCell`].
|
2022-06-07 16:15:35 -07:00
|
|
|
pub fn value(&self) -> Value<&V> {
|
2021-11-29 14:37:38 -08:00
|
|
|
self.value.as_ref()
|
2021-10-11 07:00:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the cell.
|
|
|
|
pub fn cell(&self) -> Cell {
|
|
|
|
self.cell
|
|
|
|
}
|
2021-11-29 14:37:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<V, F: Field> AssignedCell<V, F>
|
|
|
|
where
|
|
|
|
for<'v> Assigned<F>: From<&'v V>,
|
|
|
|
{
|
|
|
|
/// Returns the field element value of the [`AssignedCell`].
|
2022-06-07 16:15:35 -07:00
|
|
|
pub fn value_field(&self) -> Value<Assigned<F>> {
|
|
|
|
self.value.to_field()
|
2021-11-29 14:37:38 -08:00
|
|
|
}
|
|
|
|
}
|
2021-10-11 07:00:40 -07:00
|
|
|
|
2021-12-07 19:27:40 -08:00
|
|
|
impl<F: Field> AssignedCell<Assigned<F>, F> {
|
|
|
|
/// Evaluates this assigned cell's value directly, performing an unbatched inversion
|
|
|
|
/// if necessary.
|
|
|
|
///
|
|
|
|
/// If the denominator is zero, the returned cell's value is zero.
|
|
|
|
pub fn evaluate(self) -> AssignedCell<F, F> {
|
|
|
|
AssignedCell {
|
2022-06-07 16:15:35 -07:00
|
|
|
value: self.value.evaluate(),
|
2021-12-07 19:27:40 -08:00
|
|
|
cell: self.cell,
|
|
|
|
_marker: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-29 14:37:38 -08:00
|
|
|
impl<V: Clone, F: Field> AssignedCell<V, F>
|
|
|
|
where
|
|
|
|
for<'v> Assigned<F>: From<&'v V>,
|
|
|
|
{
|
2021-10-11 07:00:40 -07:00
|
|
|
/// Copies the value to a given advice cell and constrains them to be equal.
|
|
|
|
///
|
|
|
|
/// Returns an error if either this cell or the given cell are in columns
|
|
|
|
/// where equality has not been enabled.
|
|
|
|
pub fn copy_advice<A, AR>(
|
|
|
|
&self,
|
|
|
|
annotation: A,
|
|
|
|
region: &mut Region<'_, F>,
|
|
|
|
column: Column<Advice>,
|
|
|
|
offset: usize,
|
|
|
|
) -> Result<Self, Error>
|
|
|
|
where
|
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2022-06-07 16:15:35 -07:00
|
|
|
let assigned_cell =
|
|
|
|
region.assign_advice(annotation, column, offset, || self.value.clone())?;
|
2021-11-27 06:41:27 -08:00
|
|
|
region.constrain_equal(assigned_cell.cell(), self.cell())?;
|
2021-10-11 07:00:40 -07:00
|
|
|
|
2021-11-27 06:41:27 -08:00
|
|
|
Ok(assigned_cell)
|
2021-10-11 07:00:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
/// A region of the circuit in which a [`Chip`] can assign cells.
|
|
|
|
///
|
|
|
|
/// Inside a region, the chip may freely use relative offsets; the [`Layouter`] will
|
|
|
|
/// treat these assignments as a single "region" within the circuit.
|
|
|
|
///
|
|
|
|
/// The [`Layouter`] is allowed to optimise between regions as it sees fit. Chips must use
|
|
|
|
/// [`Region::constrain_equal`] to copy in variables assigned in other regions.
|
|
|
|
///
|
|
|
|
/// TODO: It would be great if we could constrain the columns in these types to be
|
|
|
|
/// "logical" columns that are guaranteed to correspond to the chip (and have come from
|
|
|
|
/// `Chip::Config`).
|
|
|
|
#[derive(Debug)]
|
2021-06-20 16:10:16 -07:00
|
|
|
pub struct Region<'r, F: Field> {
|
2021-04-19 06:25:32 -07:00
|
|
|
region: &'r mut dyn layouter::RegionLayouter<F>,
|
2020-12-14 16:36:58 -08:00
|
|
|
}
|
|
|
|
|
2021-06-20 16:10:16 -07:00
|
|
|
impl<'r, F: Field> From<&'r mut dyn layouter::RegionLayouter<F>> for Region<'r, F> {
|
2021-04-19 06:25:32 -07:00
|
|
|
fn from(region: &'r mut dyn layouter::RegionLayouter<F>) -> Self {
|
2020-12-14 16:36:58 -08:00
|
|
|
Region { region }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-20 16:10:16 -07:00
|
|
|
impl<'r, F: Field> Region<'r, F> {
|
2021-05-27 04:43:32 -07:00
|
|
|
/// Enables a selector at the given offset.
|
|
|
|
pub(crate) fn enable_selector<A, AR>(
|
|
|
|
&mut self,
|
|
|
|
annotation: A,
|
|
|
|
selector: &Selector,
|
|
|
|
offset: usize,
|
|
|
|
) -> Result<(), Error>
|
|
|
|
where
|
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
|
|
|
self.region
|
|
|
|
.enable_selector(&|| annotation().into(), selector, offset)
|
|
|
|
}
|
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
/// Assign an advice column value (witness).
|
|
|
|
///
|
|
|
|
/// Even though `to` has `FnMut` bounds, it is guaranteed to be called at most once.
|
2021-06-11 09:41:27 -07:00
|
|
|
pub fn assign_advice<'v, V, VR, A, AR>(
|
2020-12-14 16:36:58 -08:00
|
|
|
&'v mut self,
|
2021-01-22 08:57:38 -08:00
|
|
|
annotation: A,
|
2020-12-14 16:36:58 -08:00
|
|
|
column: Column<Advice>,
|
|
|
|
offset: usize,
|
2021-01-22 08:57:38 -08:00
|
|
|
mut to: V,
|
2021-11-27 06:41:27 -08:00
|
|
|
) -> Result<AssignedCell<VR, F>, Error>
|
2021-01-22 08:57:38 -08:00
|
|
|
where
|
2022-06-07 16:15:35 -07:00
|
|
|
V: FnMut() -> Value<VR> + 'v,
|
2021-11-29 14:37:38 -08:00
|
|
|
for<'vr> Assigned<F>: From<&'vr VR>,
|
2021-01-22 08:57:38 -08:00
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2022-06-07 16:15:35 -07:00
|
|
|
let mut value = Value::unknown();
|
2021-11-27 06:41:27 -08:00
|
|
|
let cell =
|
|
|
|
self.region
|
|
|
|
.assign_advice(&|| annotation().into(), column, offset, &mut || {
|
2022-06-07 16:15:35 -07:00
|
|
|
let v = to();
|
|
|
|
let value_f = v.to_field();
|
|
|
|
value = v;
|
|
|
|
value_f
|
2021-11-27 06:41:27 -08:00
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(AssignedCell {
|
|
|
|
value,
|
|
|
|
cell,
|
|
|
|
_marker: PhantomData,
|
|
|
|
})
|
2020-12-14 16:36:58 -08:00
|
|
|
}
|
|
|
|
|
2021-07-20 08:01:38 -07:00
|
|
|
/// Assigns a constant value to the column `advice` at `offset` within this region.
|
|
|
|
///
|
|
|
|
/// The constant value will be assigned to a cell within one of the fixed columns
|
|
|
|
/// configured via `ConstraintSystem::enable_constant`.
|
|
|
|
///
|
|
|
|
/// Returns the advice cell.
|
2021-07-20 16:11:42 -07:00
|
|
|
pub fn assign_advice_from_constant<VR, A, AR>(
|
2021-07-20 08:01:38 -07:00
|
|
|
&mut self,
|
|
|
|
annotation: A,
|
|
|
|
column: Column<Advice>,
|
|
|
|
offset: usize,
|
|
|
|
constant: VR,
|
2021-11-27 06:41:27 -08:00
|
|
|
) -> Result<AssignedCell<VR, F>, Error>
|
2021-07-20 08:01:38 -07:00
|
|
|
where
|
2021-11-29 14:37:38 -08:00
|
|
|
for<'vr> Assigned<F>: From<&'vr VR>,
|
2021-07-20 08:01:38 -07:00
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2021-11-27 06:41:27 -08:00
|
|
|
let cell = self.region.assign_advice_from_constant(
|
2021-07-20 08:01:38 -07:00
|
|
|
&|| annotation().into(),
|
|
|
|
column,
|
|
|
|
offset,
|
2021-11-29 14:37:38 -08:00
|
|
|
(&constant).into(),
|
2021-11-27 06:41:27 -08:00
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(AssignedCell {
|
2022-06-07 16:15:35 -07:00
|
|
|
value: Value::known(constant),
|
2021-11-27 06:41:27 -08:00
|
|
|
cell,
|
|
|
|
_marker: PhantomData,
|
|
|
|
})
|
2021-07-20 08:01:38 -07:00
|
|
|
}
|
|
|
|
|
2021-07-08 13:44:01 -07:00
|
|
|
/// Assign the value of the instance column's cell at absolute location
|
2021-07-10 07:20:34 -07:00
|
|
|
/// `row` to the column `advice` at `offset` within this region.
|
|
|
|
///
|
|
|
|
/// Returns the advice cell, and its value if known.
|
2021-07-09 08:00:35 -07:00
|
|
|
pub fn assign_advice_from_instance<A, AR>(
|
|
|
|
&mut self,
|
2021-07-08 13:44:01 -07:00
|
|
|
annotation: A,
|
|
|
|
instance: Column<Instance>,
|
|
|
|
row: usize,
|
|
|
|
advice: Column<Advice>,
|
|
|
|
offset: usize,
|
2021-11-27 06:41:27 -08:00
|
|
|
) -> Result<AssignedCell<F, F>, Error>
|
2021-07-08 13:44:01 -07:00
|
|
|
where
|
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2021-11-27 06:41:27 -08:00
|
|
|
let (cell, value) = self.region.assign_advice_from_instance(
|
2021-07-08 13:44:01 -07:00
|
|
|
&|| annotation().into(),
|
|
|
|
instance,
|
|
|
|
row,
|
|
|
|
advice,
|
|
|
|
offset,
|
2021-11-27 06:41:27 -08:00
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(AssignedCell {
|
|
|
|
value,
|
|
|
|
cell,
|
|
|
|
_marker: PhantomData,
|
|
|
|
})
|
2021-07-08 13:44:01 -07:00
|
|
|
}
|
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
/// Assign a fixed value.
|
|
|
|
///
|
|
|
|
/// Even though `to` has `FnMut` bounds, it is guaranteed to be called at most once.
|
2021-06-11 09:41:27 -07:00
|
|
|
pub fn assign_fixed<'v, V, VR, A, AR>(
|
2020-12-14 16:36:58 -08:00
|
|
|
&'v mut self,
|
2021-01-22 08:57:38 -08:00
|
|
|
annotation: A,
|
2020-12-14 16:36:58 -08:00
|
|
|
column: Column<Fixed>,
|
|
|
|
offset: usize,
|
2021-01-22 08:57:38 -08:00
|
|
|
mut to: V,
|
2021-11-27 06:41:27 -08:00
|
|
|
) -> Result<AssignedCell<VR, F>, Error>
|
2021-01-22 08:57:38 -08:00
|
|
|
where
|
2022-06-07 16:15:35 -07:00
|
|
|
V: FnMut() -> Value<VR> + 'v,
|
2021-11-29 14:37:38 -08:00
|
|
|
for<'vr> Assigned<F>: From<&'vr VR>,
|
2021-01-22 08:57:38 -08:00
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2022-06-07 16:15:35 -07:00
|
|
|
let mut value = Value::unknown();
|
2021-11-27 06:41:27 -08:00
|
|
|
let cell =
|
|
|
|
self.region
|
|
|
|
.assign_fixed(&|| annotation().into(), column, offset, &mut || {
|
2022-06-07 16:15:35 -07:00
|
|
|
let v = to();
|
|
|
|
let value_f = v.to_field();
|
|
|
|
value = v;
|
|
|
|
value_f
|
2021-11-27 06:41:27 -08:00
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(AssignedCell {
|
|
|
|
value,
|
|
|
|
cell,
|
|
|
|
_marker: PhantomData,
|
|
|
|
})
|
2020-12-14 16:36:58 -08:00
|
|
|
}
|
|
|
|
|
2021-07-20 09:19:47 -07:00
|
|
|
/// Constrains a cell to have a constant value.
|
|
|
|
///
|
|
|
|
/// Returns an error if the cell is in a column where equality has not been enabled.
|
|
|
|
pub fn constrain_constant<VR>(&mut self, cell: Cell, constant: VR) -> Result<(), Error>
|
|
|
|
where
|
|
|
|
VR: Into<Assigned<F>>,
|
|
|
|
{
|
|
|
|
self.region.constrain_constant(cell, constant.into())
|
|
|
|
}
|
|
|
|
|
2021-07-10 07:20:34 -07:00
|
|
|
/// Constrains two cells to have the same value.
|
2020-12-14 16:36:58 -08:00
|
|
|
///
|
2021-07-09 08:14:52 -07:00
|
|
|
/// Returns an error if either of the cells are in columns where equality
|
|
|
|
/// has not been enabled.
|
2021-07-02 15:20:36 -07:00
|
|
|
pub fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error> {
|
|
|
|
self.region.constrain_equal(left, right)
|
2020-12-14 16:36:58 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-26 17:34:51 -07:00
|
|
|
/// A lookup table in the circuit.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Table<'r, F: Field> {
|
|
|
|
table: &'r mut dyn layouter::TableLayouter<F>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r, F: Field> From<&'r mut dyn layouter::TableLayouter<F>> for Table<'r, F> {
|
|
|
|
fn from(table: &'r mut dyn layouter::TableLayouter<F>) -> Self {
|
|
|
|
Table { table }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r, F: Field> Table<'r, F> {
|
2021-07-27 09:48:13 -07:00
|
|
|
/// Assigns a fixed value to a table cell.
|
|
|
|
///
|
|
|
|
/// Returns an error if the table cell has already been assigned to.
|
2021-07-26 17:34:51 -07:00
|
|
|
///
|
|
|
|
/// Even though `to` has `FnMut` bounds, it is guaranteed to be called at most once.
|
2021-07-27 09:48:13 -07:00
|
|
|
pub fn assign_cell<'v, V, VR, A, AR>(
|
2021-07-26 17:34:51 -07:00
|
|
|
&'v mut self,
|
|
|
|
annotation: A,
|
2021-07-27 07:46:37 -07:00
|
|
|
column: TableColumn,
|
2021-07-26 17:34:51 -07:00
|
|
|
offset: usize,
|
|
|
|
mut to: V,
|
|
|
|
) -> Result<(), Error>
|
|
|
|
where
|
2022-06-07 16:15:35 -07:00
|
|
|
V: FnMut() -> Value<VR> + 'v,
|
2021-07-26 17:34:51 -07:00
|
|
|
VR: Into<Assigned<F>>,
|
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
|
|
|
self.table
|
2021-07-27 09:48:13 -07:00
|
|
|
.assign_cell(&|| annotation().into(), column, offset, &mut || {
|
2022-06-07 16:15:35 -07:00
|
|
|
to().into_field()
|
2021-07-26 17:34:51 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 06:25:32 -07:00
|
|
|
/// A layout strategy within a circuit. The layouter is chip-agnostic and applies its
|
|
|
|
/// strategy to the context and config it is given.
|
2020-12-14 16:36:58 -08:00
|
|
|
///
|
|
|
|
/// This abstracts over the circuit assignments, handling row indices etc.
|
|
|
|
///
|
2021-06-20 16:10:16 -07:00
|
|
|
pub trait Layouter<F: Field> {
|
2021-01-22 10:36:42 -08:00
|
|
|
/// Represents the type of the "root" of this layouter, so that nested namespaces
|
|
|
|
/// can minimize indirection.
|
2021-04-19 06:25:32 -07:00
|
|
|
type Root: Layouter<F>;
|
2021-02-24 07:16:55 -08:00
|
|
|
|
2020-12-14 16:36:58 -08:00
|
|
|
/// Assign a region of gates to an absolute row number.
|
|
|
|
///
|
|
|
|
/// Inside the closure, the chip may freely use relative offsets; the `Layouter` will
|
|
|
|
/// treat these assignments as a single "region" within the circuit. Outside this
|
|
|
|
/// closure, the `Layouter` is allowed to optimise as it sees fit.
|
|
|
|
///
|
|
|
|
/// ```ignore
|
2021-01-22 08:43:36 -08:00
|
|
|
/// fn assign_region(&mut self, || "region name", |region| {
|
2021-04-25 17:53:43 -07:00
|
|
|
/// let config = chip.config();
|
2021-04-19 06:25:32 -07:00
|
|
|
/// region.assign_advice(config.a, offset, || { Some(value)});
|
2020-12-14 16:36:58 -08:00
|
|
|
/// });
|
|
|
|
/// ```
|
2021-01-28 16:52:55 -08:00
|
|
|
fn assign_region<A, AR, N, NR>(&mut self, name: N, assignment: A) -> Result<AR, Error>
|
2021-01-22 08:43:36 -08:00
|
|
|
where
|
2021-04-19 06:25:32 -07:00
|
|
|
A: FnMut(Region<'_, F>) -> Result<AR, Error>,
|
2021-01-22 08:43:36 -08:00
|
|
|
N: Fn() -> NR,
|
|
|
|
NR: Into<String>;
|
2021-01-22 10:36:42 -08:00
|
|
|
|
2021-07-26 17:34:51 -07:00
|
|
|
/// Assign a table region to an absolute row number.
|
|
|
|
///
|
|
|
|
/// ```ignore
|
|
|
|
/// fn assign_table(&mut self, || "table name", |table| {
|
|
|
|
/// let config = chip.config();
|
|
|
|
/// table.assign_fixed(config.a, offset, || { Some(value)});
|
|
|
|
/// });
|
|
|
|
/// ```
|
|
|
|
fn assign_table<A, N, NR>(&mut self, name: N, assignment: A) -> Result<(), Error>
|
|
|
|
where
|
|
|
|
A: FnMut(Table<'_, F>) -> Result<(), Error>,
|
|
|
|
N: Fn() -> NR,
|
|
|
|
NR: Into<String>;
|
|
|
|
|
2021-07-10 07:20:34 -07:00
|
|
|
/// Constrains a [`Cell`] to equal an instance column's row value at an
|
|
|
|
/// absolute position.
|
2021-07-08 13:44:01 -07:00
|
|
|
fn constrain_instance(
|
|
|
|
&mut self,
|
|
|
|
cell: Cell,
|
|
|
|
column: Column<Instance>,
|
|
|
|
row: usize,
|
|
|
|
) -> Result<(), Error>;
|
|
|
|
|
2021-01-22 10:36:42 -08:00
|
|
|
/// Gets the "root" of this assignment, bypassing the namespacing.
|
|
|
|
///
|
|
|
|
/// Not intended for downstream consumption; use [`Layouter::namespace`] instead.
|
|
|
|
fn get_root(&mut self) -> &mut Self::Root;
|
|
|
|
|
|
|
|
/// Creates a new (sub)namespace and enters into it.
|
|
|
|
///
|
|
|
|
/// Not intended for downstream consumption; use [`Layouter::namespace`] instead.
|
|
|
|
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.
|
|
|
|
fn pop_namespace(&mut self, gadget_name: Option<String>);
|
|
|
|
|
|
|
|
/// Enters into a namespace.
|
2021-04-19 06:25:32 -07:00
|
|
|
fn namespace<NR, N>(&mut self, name_fn: N) -> NamespacedLayouter<'_, F, Self::Root>
|
2021-01-22 10:36:42 -08:00
|
|
|
where
|
|
|
|
NR: Into<String>,
|
|
|
|
N: FnOnce() -> NR,
|
|
|
|
{
|
|
|
|
self.get_root().push_namespace(name_fn);
|
|
|
|
|
|
|
|
NamespacedLayouter(self.get_root(), PhantomData)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This is a "namespaced" layouter which borrows a `Layouter` (pushing a namespace
|
|
|
|
/// context) and, when dropped, pops out of the namespace context.
|
|
|
|
#[derive(Debug)]
|
2021-06-20 16:10:16 -07:00
|
|
|
pub struct NamespacedLayouter<'a, F: Field, L: Layouter<F> + 'a>(&'a mut L, PhantomData<F>);
|
2021-01-22 10:36:42 -08:00
|
|
|
|
2021-06-20 16:10:16 -07:00
|
|
|
impl<'a, F: Field, L: Layouter<F> + 'a> Layouter<F> for NamespacedLayouter<'a, F, L> {
|
2021-01-22 10:36:42 -08:00
|
|
|
type Root = L::Root;
|
|
|
|
|
2021-01-28 16:52:55 -08:00
|
|
|
fn assign_region<A, AR, N, NR>(&mut self, name: N, assignment: A) -> Result<AR, Error>
|
2021-01-22 10:36:42 -08:00
|
|
|
where
|
2021-04-19 06:25:32 -07:00
|
|
|
A: FnMut(Region<'_, F>) -> Result<AR, Error>,
|
2021-01-22 10:36:42 -08:00
|
|
|
N: Fn() -> NR,
|
|
|
|
NR: Into<String>,
|
|
|
|
{
|
|
|
|
self.0.assign_region(name, assignment)
|
|
|
|
}
|
|
|
|
|
2021-07-26 17:34:51 -07:00
|
|
|
fn assign_table<A, N, NR>(&mut self, name: N, assignment: A) -> Result<(), Error>
|
|
|
|
where
|
|
|
|
A: FnMut(Table<'_, F>) -> Result<(), Error>,
|
|
|
|
N: Fn() -> NR,
|
|
|
|
NR: Into<String>,
|
|
|
|
{
|
|
|
|
self.0.assign_table(name, assignment)
|
|
|
|
}
|
|
|
|
|
2021-07-08 13:44:01 -07:00
|
|
|
fn constrain_instance(
|
|
|
|
&mut self,
|
|
|
|
cell: Cell,
|
|
|
|
column: Column<Instance>,
|
|
|
|
row: usize,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
self.0.constrain_instance(cell, column, row)
|
|
|
|
}
|
|
|
|
|
2021-01-22 10:36:42 -08:00
|
|
|
fn get_root(&mut self) -> &mut Self::Root {
|
|
|
|
self.0.get_root()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn push_namespace<NR, N>(&mut self, _name_fn: N)
|
|
|
|
where
|
|
|
|
NR: Into<String>,
|
|
|
|
N: FnOnce() -> NR,
|
|
|
|
{
|
|
|
|
panic!("Only the root's push_namespace should be called");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pop_namespace(&mut self, _gadget_name: Option<String>) {
|
|
|
|
panic!("Only the root's pop_namespace should be called");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-20 16:10:16 -07:00
|
|
|
impl<'a, F: Field, L: Layouter<F> + 'a> Drop for NamespacedLayouter<'a, F, L> {
|
2021-01-22 10:36:42 -08:00
|
|
|
fn drop(&mut self) {
|
|
|
|
let gadget_name = {
|
|
|
|
#[cfg(feature = "gadget-traces")]
|
|
|
|
{
|
|
|
|
let mut gadget_name = None;
|
|
|
|
let mut is_second_frame = false;
|
|
|
|
backtrace::trace(|frame| {
|
|
|
|
if is_second_frame {
|
|
|
|
// Resolve this instruction pointer to a symbol name.
|
|
|
|
backtrace::resolve_frame(frame, |symbol| {
|
|
|
|
gadget_name = symbol.name().map(|name| format!("{:#}", name));
|
|
|
|
});
|
|
|
|
|
|
|
|
// We are done!
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
// We want the next frame.
|
|
|
|
is_second_frame = true;
|
|
|
|
true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
gadget_name
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "gadget-traces"))]
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
self.get_root().pop_namespace(gadget_name);
|
|
|
|
}
|
2020-12-14 16:36:58 -08:00
|
|
|
}
|