2021-10-01 13:04:46 -07:00
|
|
|
use std::collections::BTreeMap;
|
|
|
|
|
|
|
|
use group::ff::Field;
|
|
|
|
|
2022-07-05 15:12:01 -07:00
|
|
|
use super::{metadata, CellValue, InstanceValue, Value};
|
2021-10-01 13:04:46 -07:00
|
|
|
use crate::{
|
2022-06-28 08:56:09 -07:00
|
|
|
plonk::{
|
|
|
|
AdviceQuery, Any, Column, ColumnType, Expression, FixedQuery, Gate, InstanceQuery,
|
|
|
|
VirtualCell,
|
|
|
|
},
|
2021-10-01 13:04:46 -07:00
|
|
|
poly::Rotation,
|
|
|
|
};
|
|
|
|
|
2022-06-28 08:56:09 -07:00
|
|
|
pub(crate) struct AnyQuery {
|
|
|
|
/// Query index
|
|
|
|
pub index: usize,
|
|
|
|
/// Column type
|
|
|
|
pub column_type: Any,
|
|
|
|
/// Column index
|
|
|
|
pub column_index: usize,
|
|
|
|
/// Rotation of this query
|
|
|
|
pub rotation: Rotation,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<FixedQuery> for AnyQuery {
|
|
|
|
fn from(query: FixedQuery) -> Self {
|
|
|
|
Self {
|
|
|
|
index: query.index,
|
|
|
|
column_type: Any::Fixed,
|
|
|
|
column_index: query.column_index,
|
|
|
|
rotation: query.rotation,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<AdviceQuery> for AnyQuery {
|
|
|
|
fn from(query: AdviceQuery) -> Self {
|
|
|
|
Self {
|
|
|
|
index: query.index,
|
|
|
|
column_type: Any::Advice,
|
|
|
|
column_index: query.column_index,
|
|
|
|
rotation: query.rotation,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<InstanceQuery> for AnyQuery {
|
|
|
|
fn from(query: InstanceQuery) -> Self {
|
|
|
|
Self {
|
|
|
|
index: query.index,
|
|
|
|
column_type: Any::Instance,
|
|
|
|
column_index: query.column_index,
|
|
|
|
rotation: query.rotation,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-01 13:04:46 -07:00
|
|
|
pub(super) fn format_value<F: Field>(v: F) -> String {
|
|
|
|
if v.is_zero_vartime() {
|
|
|
|
"0".into()
|
2022-11-29 21:05:37 -08:00
|
|
|
} else if v == F::ONE {
|
2021-10-01 13:04:46 -07:00
|
|
|
"1".into()
|
2022-11-29 21:05:37 -08:00
|
|
|
} else if v == -F::ONE {
|
2021-10-01 13:04:46 -07:00
|
|
|
"-1".into()
|
|
|
|
} else {
|
|
|
|
// Format value as hex.
|
|
|
|
let s = format!("{:?}", v);
|
|
|
|
// Remove leading zeroes.
|
|
|
|
let s = s.strip_prefix("0x").unwrap();
|
|
|
|
let s = s.trim_start_matches('0');
|
|
|
|
format!("0x{}", s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 16:12:17 -08:00
|
|
|
pub(super) fn load<'a, F: Field, T: ColumnType, Q: Into<AnyQuery> + Copy>(
|
2022-02-01 18:52:36 -08:00
|
|
|
n: i32,
|
|
|
|
row: i32,
|
|
|
|
queries: &'a [(Column<T>, Rotation)],
|
|
|
|
cells: &'a [Vec<CellValue<F>>],
|
2022-06-28 08:56:09 -07:00
|
|
|
) -> impl Fn(Q) -> Value<F> + 'a {
|
|
|
|
move |query| {
|
|
|
|
let (column, at) = &queries[query.into().index];
|
2022-02-01 18:52:36 -08:00
|
|
|
let resolved_row = (row + at.0) % n;
|
|
|
|
cells[column.index()][resolved_row as usize].into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 16:12:17 -08:00
|
|
|
pub(super) fn load_instance<'a, F: Field, T: ColumnType, Q: Into<AnyQuery> + Copy>(
|
2022-02-01 18:52:36 -08:00
|
|
|
n: i32,
|
|
|
|
row: i32,
|
|
|
|
queries: &'a [(Column<T>, Rotation)],
|
2022-07-05 15:12:01 -07:00
|
|
|
cells: &'a [Vec<InstanceValue<F>>],
|
2022-06-28 08:56:09 -07:00
|
|
|
) -> impl Fn(Q) -> Value<F> + 'a {
|
|
|
|
move |query| {
|
|
|
|
let (column, at) = &queries[query.into().index];
|
2022-02-01 18:52:36 -08:00
|
|
|
let resolved_row = (row + at.0) % n;
|
2022-07-05 15:12:01 -07:00
|
|
|
let cell = &cells[column.index()][resolved_row as usize];
|
|
|
|
Value::Real(cell.value())
|
2022-02-01 18:52:36 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 16:12:17 -08:00
|
|
|
fn cell_value<'a, F: Field, Q: Into<AnyQuery> + Copy>(
|
2021-10-01 13:04:46 -07:00
|
|
|
virtual_cells: &'a [VirtualCell],
|
2022-06-28 08:56:09 -07:00
|
|
|
load: impl Fn(Q) -> Value<F> + 'a,
|
|
|
|
) -> impl Fn(Q) -> BTreeMap<metadata::VirtualCell, String> + 'a {
|
|
|
|
move |query| {
|
|
|
|
let AnyQuery {
|
|
|
|
column_type,
|
|
|
|
column_index,
|
|
|
|
rotation,
|
|
|
|
..
|
|
|
|
} = query.into();
|
2021-10-01 13:04:46 -07:00
|
|
|
virtual_cells
|
|
|
|
.iter()
|
|
|
|
.find(|c| {
|
|
|
|
c.column.column_type() == &column_type
|
|
|
|
&& c.column.index() == column_index
|
|
|
|
&& c.rotation == rotation
|
|
|
|
})
|
|
|
|
// None indicates a selector, which we don't bother showing.
|
|
|
|
.map(|cell| {
|
|
|
|
(
|
|
|
|
cell.clone().into(),
|
2022-06-28 08:56:09 -07:00
|
|
|
match load(query) {
|
2021-10-01 13:04:46 -07:00
|
|
|
Value::Real(v) => format_value(v),
|
|
|
|
Value::Poison => unreachable!(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.into_iter()
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 16:12:17 -08:00
|
|
|
pub(super) fn cell_values<'a, F: Field>(
|
2021-10-01 13:04:46 -07:00
|
|
|
gate: &Gate<F>,
|
|
|
|
poly: &Expression<F>,
|
2022-06-28 08:56:09 -07:00
|
|
|
load_fixed: impl Fn(FixedQuery) -> Value<F> + 'a,
|
|
|
|
load_advice: impl Fn(AdviceQuery) -> Value<F> + 'a,
|
|
|
|
load_instance: impl Fn(InstanceQuery) -> Value<F> + 'a,
|
2021-10-01 13:04:46 -07:00
|
|
|
) -> Vec<(metadata::VirtualCell, String)> {
|
|
|
|
let virtual_cells = gate.queried_cells();
|
|
|
|
let cell_values = poly.evaluate(
|
|
|
|
&|_| BTreeMap::default(),
|
|
|
|
&|_| panic!("virtual selectors are removed during optimization"),
|
2023-02-21 09:37:35 -08:00
|
|
|
#[cfg(feature = "unstable-dynamic-lookups")]
|
|
|
|
&|_| panic!("virtual table tags are removed during optimization"),
|
2022-06-28 08:56:09 -07:00
|
|
|
&cell_value(virtual_cells, load_fixed),
|
|
|
|
&cell_value(virtual_cells, load_advice),
|
|
|
|
&cell_value(virtual_cells, load_instance),
|
2021-10-01 13:04:46 -07:00
|
|
|
&|a| a,
|
|
|
|
&|mut a, mut b| {
|
|
|
|
a.append(&mut b);
|
|
|
|
a
|
|
|
|
},
|
|
|
|
&|mut a, mut b| {
|
|
|
|
a.append(&mut b);
|
|
|
|
a
|
|
|
|
},
|
|
|
|
&|a, _| a,
|
|
|
|
);
|
|
|
|
cell_values.into_iter().collect()
|
|
|
|
}
|