use std::ops::Range;
use halo2_middleware::circuit::Any;
use halo2_middleware::ff::Field;
use crate::circuit::Value;
use crate::plonk::{
permutation, Advice, AssignError, Assigned, Assignment, Challenge, Column, Error, Fixed,
Instance, Selector,
};
#[derive(Debug)]
pub(crate) struct Assembly<F: Field> {
pub(crate) k: u32,
pub(crate) fixed: Vec<Vec<Assigned<F>>>,
pub(crate) permutation: permutation::Assembly,
pub(crate) selectors: Vec<Vec<bool>>,
pub(crate) usable_rows: Range<usize>,
pub(crate) _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,
{
}
fn exit_region(&mut self) {
}
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));
}
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>,
{
Ok(())
}
fn assign_fixed<V, VR, A, AR>(
&mut self,
desc: 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));
}
let value = match to().into_field().assign() {
Ok(v) => v,
Err(_) => {
return Err(Error::AssignError(AssignError::WitnessMissing {
func: "assign_fixed".to_string(),
desc: desc().into(),
}))
}
};
*self
.fixed
.get_mut(column.index())
.and_then(|v| v.get_mut(row))
.ok_or(Error::BoundsFailure)? = value;
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 = match to.assign() {
Ok(v) => v,
Err(_) => {
return Err(Error::AssignError(AssignError::WitnessMissing {
func: "fill_from_row".to_string(),
desc: "".to_string(),
}))
}
};
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>,
{
}
fn push_namespace<NR, N>(&mut self, _: N)
where
NR: Into<String>,
N: FnOnce() -> NR,
{
}
fn pop_namespace(&mut self, _: Option<String>) {
}
}