mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
Add a Selector type
This currently just wraps a `Column<Fixed>`, but enables us to start writing circuits that can later have their selector usage optimised.
This commit is contained in:
parent
9467a03ae2
commit
bd17c726ac
1 changed files with 82 additions and 2 deletions
|
|
@ -7,8 +7,11 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{lookup, permutation, Error};
|
use super::{lookup, permutation, Error};
|
||||||
use crate::arithmetic::FieldExt;
|
use crate::{
|
||||||
use crate::poly::Rotation;
|
arithmetic::FieldExt,
|
||||||
|
circuit::{Chip, Region},
|
||||||
|
poly::Rotation,
|
||||||
|
};
|
||||||
|
|
||||||
/// A column type
|
/// A column type
|
||||||
pub trait ColumnType: 'static + Sized + std::fmt::Debug {}
|
pub trait ColumnType: 'static + Sized + std::fmt::Debug {}
|
||||||
|
|
@ -127,6 +130,71 @@ impl TryFrom<Column<Any>> for Column<Instance> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A selector, representing a fixed boolean value per row of the circuit.
|
||||||
|
///
|
||||||
|
/// Selectors can be used to conditionally enable (portions of) gates:
|
||||||
|
/// ```
|
||||||
|
/// use halo2::poly::Rotation;
|
||||||
|
/// # use halo2::pasta::Fp;
|
||||||
|
/// # use halo2::plonk::ConstraintSystem;
|
||||||
|
///
|
||||||
|
/// # let mut meta = ConstraintSystem::<Fp>::default();
|
||||||
|
/// let a = meta.advice_column();
|
||||||
|
/// let b = meta.advice_column();
|
||||||
|
/// let s = meta.selector();
|
||||||
|
///
|
||||||
|
/// meta.create_gate("foo", |meta| {
|
||||||
|
/// let a = meta.query_advice(a, Rotation::prev());
|
||||||
|
/// let b = meta.query_advice(b, Rotation::cur());
|
||||||
|
/// let s = meta.query_selector(s, Rotation::cur());
|
||||||
|
///
|
||||||
|
/// // On rows where the selector is enabled, a is constrained to equal b.
|
||||||
|
/// // On rows where the selector is disabled, a and b can take any value.
|
||||||
|
/// s * (a - b)
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Selectors are disabled on all rows by default, and must be explicitly enabled on each
|
||||||
|
/// row when required:
|
||||||
|
/// ```
|
||||||
|
/// use halo2::{circuit::{Chip, Layouter}, plonk::{Advice, Column, Error, Selector}};
|
||||||
|
/// # use ff::Field;
|
||||||
|
/// # use halo2::plonk::Fixed;
|
||||||
|
///
|
||||||
|
/// struct Config {
|
||||||
|
/// a: Column<Advice>,
|
||||||
|
/// b: Column<Advice>,
|
||||||
|
/// s: Selector,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn circuit_logic<C: Chip>(mut layouter: impl Layouter<C>) -> Result<(), Error> {
|
||||||
|
/// let config = layouter.config().clone();
|
||||||
|
/// # let config: Config = todo!();
|
||||||
|
/// layouter.assign_region(|| "bar", |mut region| {
|
||||||
|
/// region.assign_advice(|| "a", config.a, 0, || Ok(C::Field::one()))?;
|
||||||
|
/// region.assign_advice(|| "a", config.b, 1, || Ok(C::Field::one()))?;
|
||||||
|
/// config.s.enable(&mut region, 1)
|
||||||
|
/// })?;
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Selector(Column<Fixed>);
|
||||||
|
|
||||||
|
impl Selector {
|
||||||
|
/// Enable this selector at the given offset within the given region.
|
||||||
|
pub fn enable<C: Chip>(&self, region: &mut Region<C>, offset: usize) -> Result<(), Error> {
|
||||||
|
// TODO: Ensure that the default for a selector's cells is always zero, if we
|
||||||
|
// alter the proving system to change the global default.
|
||||||
|
// TODO: Add Region::enable_selector method to allow the layouter to control the
|
||||||
|
// selector's assignment.
|
||||||
|
// https://github.com/zcash/halo2/issues/116
|
||||||
|
region
|
||||||
|
.assign_fixed(|| "", self.0, offset, || Ok(C::Field::one()))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A permutation.
|
/// A permutation.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Permutation {
|
pub struct Permutation {
|
||||||
|
|
@ -507,6 +575,11 @@ impl<F: Field> ConstraintSystem<F> {
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Query a selector at a relative position.
|
||||||
|
pub fn query_selector(&mut self, selector: Selector, at: Rotation) -> Expression<F> {
|
||||||
|
Expression::Fixed(self.query_fixed_index(selector.0, at))
|
||||||
|
}
|
||||||
|
|
||||||
fn query_fixed_index(&mut self, column: Column<Fixed>, at: Rotation) -> usize {
|
fn query_fixed_index(&mut self, column: Column<Fixed>, at: Rotation) -> usize {
|
||||||
// Return existing query, if it exists
|
// Return existing query, if it exists
|
||||||
for (index, fixed_query) in self.fixed_queries.iter().enumerate() {
|
for (index, fixed_query) in self.fixed_queries.iter().enumerate() {
|
||||||
|
|
@ -642,6 +715,13 @@ impl<F: Field> ConstraintSystem<F> {
|
||||||
self.gates.push((name, poly));
|
self.gates.push((name, poly));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocate a new selector.
|
||||||
|
pub fn selector(&mut self) -> Selector {
|
||||||
|
// TODO: Track selectors separately, and combine selectors where possible.
|
||||||
|
// https://github.com/zcash/halo2/issues/116
|
||||||
|
Selector(self.fixed_column())
|
||||||
|
}
|
||||||
|
|
||||||
/// Allocate a new fixed column
|
/// Allocate a new fixed column
|
||||||
pub fn fixed_column(&mut self) -> Column<Fixed> {
|
pub fn fixed_column(&mut self) -> Column<Fixed> {
|
||||||
let tmp = Column {
|
let tmp = Column {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue