mirror of https://github.com/zcash/halo2.git
162 lines
4.1 KiB
Rust
162 lines
4.1 KiB
Rust
use std::ops::Range;
|
|
|
|
use halo2_middleware::ff::Field;
|
|
|
|
use crate::circuit::Value;
|
|
use crate::plonk::{permutation, Assigned, Assignment, Challenge, Column, Error, Selector};
|
|
use halo2_middleware::circuit::{Advice, Any, Fixed, Instance};
|
|
|
|
/// Assembly to be used in circuit synthesis.
|
|
#[derive(Debug)]
|
|
pub struct Assembly<F: Field> {
|
|
pub k: u32,
|
|
pub fixed: Vec<Vec<Assigned<F>>>,
|
|
pub permutation: permutation::Assembly,
|
|
pub selectors: Vec<Vec<bool>>,
|
|
// A range of available rows for assignment and copies.
|
|
pub usable_rows: Range<usize>,
|
|
pub _marker: std::marker::PhantomData<F>,
|
|
}
|
|
|
|
impl<F: Field> Assignment<F> for Assembly<F> {
|
|
fn enter_region<NR, N>(&mut self, _: N)
|
|
where
|
|
NR: Into<String>,
|
|
N: FnOnce() -> NR,
|
|
{
|
|
// Do nothing; we don't care about regions in this context.
|
|
}
|
|
|
|
fn exit_region(&mut self) {
|
|
// Do nothing; we don't care about regions in this context.
|
|
}
|
|
|
|
fn enable_selector<A, AR>(&mut self, _: A, selector: &Selector, row: usize) -> Result<(), Error>
|
|
where
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>,
|
|
{
|
|
if !self.usable_rows.contains(&row) {
|
|
return Err(Error::not_enough_rows_available(self.k));
|
|
}
|
|
|
|
self.selectors[selector.0][row] = true;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn query_instance(&self, _: Column<Instance>, row: usize) -> Result<Value<F>, Error> {
|
|
if !self.usable_rows.contains(&row) {
|
|
return Err(Error::not_enough_rows_available(self.k));
|
|
}
|
|
|
|
// There is no instance in this context.
|
|
Ok(Value::unknown())
|
|
}
|
|
|
|
fn assign_advice<V, VR, A, AR>(
|
|
&mut self,
|
|
_: A,
|
|
_: Column<Advice>,
|
|
_: usize,
|
|
_: V,
|
|
) -> Result<(), Error>
|
|
where
|
|
V: FnOnce() -> Value<VR>,
|
|
VR: Into<Assigned<F>>,
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>,
|
|
{
|
|
// We only care about fixed columns here
|
|
Ok(())
|
|
}
|
|
|
|
fn assign_fixed<V, VR, A, AR>(
|
|
&mut self,
|
|
_: 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>,
|
|
{
|
|
if !self.usable_rows.contains(&row) {
|
|
return Err(Error::not_enough_rows_available(self.k));
|
|
}
|
|
|
|
*self
|
|
.fixed
|
|
.get_mut(column.index())
|
|
.and_then(|v| v.get_mut(row))
|
|
.ok_or(Error::BoundsFailure)? = to().into_field().assign()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn copy(
|
|
&mut self,
|
|
left_column: Column<Any>,
|
|
left_row: usize,
|
|
right_column: Column<Any>,
|
|
right_row: usize,
|
|
) -> Result<(), Error> {
|
|
if !self.usable_rows.contains(&left_row) || !self.usable_rows.contains(&right_row) {
|
|
return Err(Error::not_enough_rows_available(self.k));
|
|
}
|
|
|
|
self.permutation
|
|
.copy(left_column, left_row, right_column, right_row)
|
|
}
|
|
|
|
fn fill_from_row(
|
|
&mut self,
|
|
column: Column<Fixed>,
|
|
from_row: usize,
|
|
to: Value<Assigned<F>>,
|
|
) -> Result<(), Error> {
|
|
if !self.usable_rows.contains(&from_row) {
|
|
return Err(Error::not_enough_rows_available(self.k));
|
|
}
|
|
|
|
let col = self
|
|
.fixed
|
|
.get_mut(column.index())
|
|
.ok_or(Error::BoundsFailure)?;
|
|
|
|
let filler = to.assign()?;
|
|
for row in self.usable_rows.clone().skip(from_row) {
|
|
col[row] = filler;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_challenge(&self, _: Challenge) -> Value<F> {
|
|
Value::unknown()
|
|
}
|
|
|
|
fn annotate_column<A, AR>(&mut self, _annotation: A, _column: Column<Any>)
|
|
where
|
|
A: FnOnce() -> AR,
|
|
AR: Into<String>,
|
|
{
|
|
// Do nothing
|
|
}
|
|
|
|
fn push_namespace<NR, N>(&mut self, _: N)
|
|
where
|
|
NR: Into<String>,
|
|
N: FnOnce() -> NR,
|
|
{
|
|
// Do nothing; we don't care about namespaces in this context.
|
|
}
|
|
|
|
fn pop_namespace(&mut self, _: Option<String>) {
|
|
// Do nothing; we don't care about namespaces in this context.
|
|
}
|
|
}
|