Add `Region::constrain_constant` API

This is the non-assigning subset of `Region::assign_advice_from_constant`.
This commit is contained in:
Jack Grigg 2021-07-20 17:19:47 +01:00 committed by therealyingtong
parent 4c5a830e5c
commit 629c13eae8
4 changed files with 50 additions and 22 deletions

View File

@ -225,6 +225,16 @@ impl<'r, F: Field> Region<'r, F> {
})
}
/// 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())
}
/// Constrains two cells to have the same value.
///
/// Returns an error if either of the cells are in columns where equality

View File

@ -215,28 +215,8 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F>
offset: usize,
constant: Assigned<F>,
) -> Result<Cell, Error> {
if self.layouter.constants.is_empty() {
return Err(Error::NotEnoughColumnsForConstants);
}
let advice = self.assign_advice(annotation, column, offset, &mut || Ok(constant))?;
// For the simple layouter, just assign the fixed constants inside the region
// using the first constants column. self.next_constant_row is updated by this
// function call.
let fixed = self.assign_fixed(
annotation,
self.layouter.constants[0],
// Convert the absolute row into a relative offset within this region, but
// always at an offset that is not before this region (taking advantage of the
// fact that for this single-pass layouter, regions are always layed out in
// increasing row order).
self.next_constant_row
.saturating_sub(*self.layouter.regions[*self.region_index]),
&mut || Ok(constant),
)?;
self.constrain_equal(advice, fixed)?;
self.constrain_constant(advice, constant)?;
Ok(advice)
}
@ -291,6 +271,29 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F>
})
}
fn constrain_constant(&mut self, cell: Cell, constant: Assigned<F>) -> Result<(), Error> {
if self.layouter.constants.is_empty() {
return Err(Error::NotEnoughColumnsForConstants);
}
// For the simple layouter, just assign the fixed constants inside the region
// using the first constants column. self.next_constant_row is updated by this
// function call.
let fixed = self.assign_fixed(
&|| "constant".into(),
self.layouter.constants[0],
// Convert the absolute row into a relative offset within this region, but
// always at an offset that is not before this region (taking advantage of the
// fact that for this single-pass layouter, regions are always layed out in
// increasing row order).
self.next_constant_row
.saturating_sub(*self.layouter.regions[*self.region_index]),
&mut || Ok(constant),
)?;
self.constrain_equal(cell, fixed)
}
fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error> {
self.layouter.cs.copy(
left.column,

View File

@ -348,7 +348,7 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F> for V1Region<'r
constant: Assigned<F>,
) -> Result<Cell, Error> {
let advice = self.assign_advice(annotation, column, offset, &mut || Ok(constant))?;
self.plan.constants.push((constant, advice));
self.constrain_constant(advice, constant)?;
Ok(advice)
}
@ -398,6 +398,11 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F> for V1Region<'r
})
}
fn constrain_constant(&mut self, cell: Cell, constant: Assigned<F>) -> Result<(), Error> {
self.plan.constants.push((constant, cell));
Ok(())
}
fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error> {
self.plan.cs.copy(
left.column,

View File

@ -94,6 +94,11 @@ pub trait RegionLayouter<F: Field>: fmt::Debug {
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
) -> Result<Cell, Error>;
/// Constrains a cell to have a constant value.
///
/// Returns an error if the cell is in a column where equality has not been enabled.
fn constrain_constant(&mut self, cell: Cell, constant: Assigned<F>) -> Result<(), Error>;
/// Constraint two cells to have the same value.
///
/// Returns an error if either of the cells is not within the given permutation.
@ -215,6 +220,11 @@ impl<F: Field> RegionLayouter<F> for RegionShape {
})
}
fn constrain_constant(&mut self, _cell: Cell, _constant: Assigned<F>) -> Result<(), Error> {
// Global constants don't affect the region shape.
Ok(())
}
fn constrain_equal(&mut self, _left: Cell, _right: Cell) -> Result<(), Error> {
// Equality constraints don't affect the region shape.
Ok(())