Skip to content

Commit

Permalink
Merge pull request zcash#287 from zcash/remove-selector-rotations
Browse files Browse the repository at this point in the history
Remove rotations from Selectors
  • Loading branch information
str4d authored Jun 5, 2021
2 parents 8795094 + 0d8b3ba commit d8e4f24
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 23 deletions.
4 changes: 2 additions & 2 deletions examples/simple-example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl<F: FieldExt> FieldChip<F> {
let lhs = meta.query_advice(advice[0], Rotation::cur());
let rhs = meta.query_advice(advice[1], Rotation::cur());
let out = meta.query_advice(advice[0], Rotation::next());
let s_mul = meta.query_selector(s_mul, Rotation::cur());
let s_mul = meta.query_selector(s_mul);

// Finally, we return the polynomial expressions that constrain this gate.
// For our multiplication gate, we only need a single polynomial constraint.
Expand All @@ -127,7 +127,7 @@ impl<F: FieldExt> FieldChip<F> {
// column for exposing numbers as public inputs.
let a = meta.query_advice(advice[1], Rotation::cur());
let p = meta.query_instance(instance, Rotation::cur());
let s = meta.query_selector(s_pub, Rotation::cur());
let s = meta.query_selector(s_pub);

// We simply constrain the advice cell to be equal to the instance cell,
// when the selector is enabled.
Expand Down
6 changes: 3 additions & 3 deletions examples/two-chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl<F: FieldExt> AddChip<F> {
let lhs = meta.query_advice(advice[0], Rotation::cur());
let rhs = meta.query_advice(advice[1], Rotation::cur());
let out = meta.query_advice(advice[0], Rotation::next());
let s_add = meta.query_selector(s_add, Rotation::cur());
let s_add = meta.query_selector(s_add);

vec![s_add * (lhs + rhs + out * -F::one())]
});
Expand Down Expand Up @@ -317,7 +317,7 @@ impl<F: FieldExt> MulChip<F> {
let lhs = meta.query_advice(advice[0], Rotation::cur());
let rhs = meta.query_advice(advice[1], Rotation::cur());
let out = meta.query_advice(advice[0], Rotation::next());
let s_mul = meta.query_selector(s_mul, Rotation::cur());
let s_mul = meta.query_selector(s_mul);

// The polynomial expression returned from `create_gate` will be
// constrained by the proving system to equal zero. Our expression
Expand Down Expand Up @@ -455,7 +455,7 @@ impl<F: FieldExt> FieldChip<F> {
// column for exposing numbers as public inputs.
let a = meta.query_advice(advice[1], Rotation::cur());
let p = meta.query_instance(instance, Rotation::cur());
let s = meta.query_selector(s_pub, Rotation::cur());
let s = meta.query_selector(s_pub);

// We simply constrain the advice cell to be equal to the instance cell,
// when the selector is enabled.
Expand Down
15 changes: 5 additions & 10 deletions src/dev.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Tools for developing circuits.
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt;
use std::iter;

Expand Down Expand Up @@ -416,22 +415,18 @@ impl<F: FieldExt> MockProver<F> {
.flat_map(|(gate_index, gate)| {
gate.queried_selectors()
.iter()
.map(|vc| (Selector(vc.column.try_into().unwrap()), vc.rotation))
// Assume that if a queried selector is enabled, the user wants to use the
// corresponding gate in some way.
//
// TODO: This will trip up on the reverse case, where leaving a selector
// un-enabled keeps a gate enabled. We could alternatively require that
// every selector is explicitly enabled or disabled on every row? But that
// seems messy and confusing.
.filter_map(|(s, rotation)| {
self.enabled_selectors.get(&s).map(|at| (at, rotation))
})
.flat_map(move |(at, rotation)| {
.filter_map(|s| self.enabled_selectors.get(&s))
.flat_map(move |at| {
at.iter().flat_map(move |selector_row| {
// Determine the gate instance's logical row from the selector's
// concrete row and its rotation in the gate.
let gate_row = (*selector_row as i32 + n - rotation.0) % n;
// Selectors are queried with no rotation.
let gate_row = *selector_row as i32;

gate.queried_cells().iter().filter_map(move |cell| {
// Determine where this cell should have been assigned.
Expand Down Expand Up @@ -682,7 +677,7 @@ mod tests {
meta.create_gate("Equality check", |cells| {
let a = cells.query_advice(a, Rotation::prev());
let b = cells.query_advice(b, Rotation::cur());
let q = cells.query_selector(q, Rotation::cur());
let q = cells.query_selector(q);

// If q is enabled, a and b must be assigned to.
vec![q * (a - b)]
Expand Down
17 changes: 9 additions & 8 deletions src/plonk/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl TryFrom<Column<Any>> for Column<Instance> {
/// 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());
/// let s = meta.query_selector(s);
///
/// // 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.
Expand Down Expand Up @@ -520,7 +520,7 @@ pub(crate) struct Gate<F: Field> {
polys: Vec<Expression<F>>,
/// We track queried selectors separately from other cells, so that we can use them to
/// trigger debug checks on gates.
queried_selectors: Vec<VirtualCell>,
queried_selectors: Vec<Selector>,
queried_cells: Vec<VirtualCell>,
}

Expand All @@ -537,7 +537,7 @@ impl<F: Field> Gate<F> {
&self.polys
}

pub(crate) fn queried_selectors(&self) -> &[VirtualCell] {
pub(crate) fn queried_selectors(&self) -> &[Selector] {
&self.queried_selectors
}

Expand Down Expand Up @@ -874,7 +874,7 @@ impl<F: Field> ConstraintSystem<F> {
#[derive(Debug)]
pub struct VirtualCells<'a, F: Field> {
meta: &'a mut ConstraintSystem<F>,
queried_selectors: Vec<VirtualCell>,
queried_selectors: Vec<Selector>,
queried_cells: Vec<VirtualCell>,
}

Expand All @@ -887,10 +887,11 @@ impl<'a, F: Field> VirtualCells<'a, F> {
}
}

/// Query a selector at a relative position.
pub fn query_selector(&mut self, selector: Selector, at: Rotation) -> Expression<F> {
self.queried_selectors.push((selector.0, at).into());
Expression::Fixed(self.meta.query_fixed_index(selector.0, at))
/// Query a selector at the current position.
pub fn query_selector(&mut self, selector: Selector) -> Expression<F> {
// Selectors are always queried at the current row.
self.queried_selectors.push(selector);
Expression::Fixed(self.meta.query_fixed_index(selector.0, Rotation::cur()))
}

/// Query a fixed column at a relative position
Expand Down

0 comments on commit d8e4f24

Please sign in to comment.