2021-06-02 18:41:03 -07:00
|
|
|
use halo2::{
|
2021-06-12 18:40:20 -07:00
|
|
|
circuit::{Cell, Layouter, Region},
|
2021-06-02 18:41:03 -07:00
|
|
|
plonk::{Advice, Column, Error, Permutation},
|
|
|
|
};
|
|
|
|
use pasta_curves::arithmetic::FieldExt;
|
|
|
|
|
2021-06-21 08:16:56 -07:00
|
|
|
pub(crate) mod cond_swap;
|
|
|
|
pub(crate) mod enable_flag;
|
|
|
|
pub(crate) mod lookup_range_check;
|
|
|
|
pub(crate) mod plonk;
|
2021-06-02 18:41:54 -07:00
|
|
|
|
2021-06-21 08:16:56 -07:00
|
|
|
/// A variable representing a field element.
|
2021-06-02 18:41:03 -07:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub struct CellValue<F: FieldExt> {
|
|
|
|
cell: Cell,
|
|
|
|
value: Option<F>,
|
|
|
|
}
|
|
|
|
|
2021-06-21 08:16:56 -07:00
|
|
|
pub trait Var<F: FieldExt>: Copy + Clone + std::fmt::Debug {
|
2021-06-02 18:41:03 -07:00
|
|
|
fn new(cell: Cell, value: Option<F>) -> Self;
|
|
|
|
fn cell(&self) -> Cell;
|
|
|
|
fn value(&self) -> Option<F>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: FieldExt> Var<F> for CellValue<F> {
|
|
|
|
fn new(cell: Cell, value: Option<F>) -> Self {
|
|
|
|
Self { cell, value }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cell(&self) -> Cell {
|
|
|
|
self.cell
|
|
|
|
}
|
|
|
|
|
|
|
|
fn value(&self) -> Option<F> {
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-12 18:40:20 -07:00
|
|
|
pub trait UtilitiesInstructions<F: FieldExt> {
|
2021-06-02 18:41:03 -07:00
|
|
|
type Var: Var<F>;
|
|
|
|
|
|
|
|
fn load_private(
|
|
|
|
&self,
|
|
|
|
mut layouter: impl Layouter<F>,
|
|
|
|
column: Column<Advice>,
|
|
|
|
value: Option<F>,
|
|
|
|
) -> Result<Self::Var, Error> {
|
|
|
|
layouter.assign_region(
|
|
|
|
|| "load private",
|
|
|
|
|mut region| {
|
|
|
|
let cell = region.assign_advice(
|
|
|
|
|| "load private",
|
|
|
|
column,
|
|
|
|
0,
|
|
|
|
|| value.ok_or(Error::SynthesisError),
|
|
|
|
)?;
|
|
|
|
Ok(Var::new(cell, value))
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-07 09:28:32 -07:00
|
|
|
/// Assigns a cell at a specific offset within the given region, constraining it
|
|
|
|
/// to the same value as another cell (which may be in any region).
|
|
|
|
///
|
|
|
|
/// Returns an error if either `column` or `copy` is not within `perm`.
|
2021-06-02 18:41:03 -07:00
|
|
|
pub fn copy<A, AR, F: FieldExt>(
|
|
|
|
region: &mut Region<'_, F>,
|
|
|
|
annotation: A,
|
|
|
|
column: Column<Advice>,
|
2021-06-07 09:28:32 -07:00
|
|
|
offset: usize,
|
2021-06-02 18:41:03 -07:00
|
|
|
copy: &CellValue<F>,
|
|
|
|
perm: &Permutation,
|
|
|
|
) -> Result<CellValue<F>, Error>
|
|
|
|
where
|
|
|
|
A: Fn() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2021-06-07 09:28:32 -07:00
|
|
|
let cell = region.assign_advice(annotation, column, offset, || {
|
2021-06-02 18:41:03 -07:00
|
|
|
copy.value.ok_or(Error::SynthesisError)
|
|
|
|
})?;
|
|
|
|
|
|
|
|
region.constrain_equal(perm, cell, copy.cell)?;
|
|
|
|
|
|
|
|
Ok(CellValue::new(cell, copy.value))
|
|
|
|
}
|