2022-05-06 14:55:54 +02:00
|
|
|
use plonky2::field::extension_field::{Extendable, FieldExtension};
|
2022-05-05 22:21:09 +02:00
|
|
|
use plonky2::field::field_types::Field;
|
|
|
|
|
use plonky2::field::packed_field::PackedField;
|
|
|
|
|
use plonky2::field::polynomial::PolynomialValues;
|
|
|
|
|
use plonky2::hash::hash_types::RichField;
|
|
|
|
|
use plonky2::iop::challenger::Challenger;
|
|
|
|
|
use plonky2::plonk::config::GenericConfig;
|
|
|
|
|
use plonky2::plonk::plonk_common::reduce_with_powers;
|
2022-05-06 14:55:54 +02:00
|
|
|
use plonky2::util::reducing::ReducingFactor;
|
2022-05-05 22:21:09 +02:00
|
|
|
|
2022-05-06 17:35:25 +02:00
|
|
|
use crate::all_stark::Table;
|
2022-05-05 22:21:09 +02:00
|
|
|
use crate::config::StarkConfig;
|
2022-05-06 14:55:54 +02:00
|
|
|
use crate::constraint_consumer::ConstraintConsumer;
|
|
|
|
|
use crate::permutation::PermutationChallenge;
|
|
|
|
|
use crate::stark::Stark;
|
|
|
|
|
use crate::vars::StarkEvaluationVars;
|
2022-05-05 22:21:09 +02:00
|
|
|
|
2022-05-06 17:22:30 +02:00
|
|
|
pub struct CrossTableLookup {
|
|
|
|
|
pub looking_table: Table,
|
|
|
|
|
pub looking_columns: Vec<usize>,
|
2022-05-10 07:45:42 +02:00
|
|
|
pub looked_table: Table,
|
2022-05-06 17:22:30 +02:00
|
|
|
pub looked_columns: Vec<usize>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CrossTableLookup {
|
|
|
|
|
pub fn new(
|
|
|
|
|
looking_table: Table,
|
|
|
|
|
looking_columns: Vec<usize>,
|
2022-05-10 07:45:42 +02:00
|
|
|
looked_table: Table,
|
2022-05-06 17:22:30 +02:00
|
|
|
looked_columns: Vec<usize>,
|
|
|
|
|
) -> Self {
|
|
|
|
|
assert_eq!(looking_columns.len(), looked_columns.len());
|
|
|
|
|
Self {
|
|
|
|
|
looking_table,
|
|
|
|
|
looking_columns,
|
|
|
|
|
looked_table,
|
|
|
|
|
looked_columns,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-05 22:21:09 +02:00
|
|
|
/// Lookup data for one table.
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct LookupData<F: Field> {
|
2022-05-11 14:35:33 +02:00
|
|
|
pub beta: F,
|
|
|
|
|
pub gamma: F,
|
|
|
|
|
pub zs_columns: Vec<(PolynomialValues<F>, Vec<usize>)>,
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-11 14:35:33 +02:00
|
|
|
impl<F: Field> LookupData<F> {
|
|
|
|
|
pub fn new(beta: F, gamma: F) -> Self {
|
2022-05-05 22:21:09 +02:00
|
|
|
Self {
|
2022-05-11 14:35:33 +02:00
|
|
|
beta,
|
|
|
|
|
gamma,
|
|
|
|
|
zs_columns: vec![],
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-10 15:08:08 +02:00
|
|
|
pub fn len(&self) -> usize {
|
2022-05-11 14:35:33 +02:00
|
|
|
self.zs_columns.len()
|
2022-05-10 15:08:08 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-05 22:21:09 +02:00
|
|
|
pub fn is_empty(&self) -> bool {
|
2022-05-11 14:35:33 +02:00
|
|
|
self.zs_columns.is_empty()
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn z_polys(&self) -> Vec<PolynomialValues<F>> {
|
2022-05-11 14:35:33 +02:00
|
|
|
self.zs_columns.iter().map(|(p, _)| p.clone()).collect()
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn cross_table_lookup_zs<F: RichField, C: GenericConfig<D, F = F>, const D: usize>(
|
|
|
|
|
config: &StarkConfig,
|
|
|
|
|
trace_poly_values: &[Vec<PolynomialValues<F>>],
|
2022-05-06 17:22:30 +02:00
|
|
|
cross_table_lookups: &[CrossTableLookup],
|
2022-05-05 22:21:09 +02:00
|
|
|
challenger: &mut Challenger<F, C::Hasher>,
|
|
|
|
|
) -> Vec<LookupData<F>> {
|
2022-05-11 14:35:33 +02:00
|
|
|
let beta = challenger.get_challenge();
|
|
|
|
|
let gamma = challenger.get_challenge();
|
2022-05-05 22:21:09 +02:00
|
|
|
cross_table_lookups.iter().fold(
|
2022-05-11 14:35:33 +02:00
|
|
|
vec![LookupData::new(beta, gamma); trace_poly_values.len()],
|
2022-05-05 22:21:09 +02:00
|
|
|
|mut acc, cross_table_lookup| {
|
|
|
|
|
let CrossTableLookup {
|
|
|
|
|
looking_table,
|
|
|
|
|
looking_columns,
|
|
|
|
|
looked_table,
|
|
|
|
|
looked_columns,
|
|
|
|
|
} = cross_table_lookup;
|
|
|
|
|
|
|
|
|
|
for _ in 0..config.num_challenges {
|
|
|
|
|
let z_looking = partial_products(
|
|
|
|
|
&trace_poly_values[*looking_table as usize],
|
2022-05-06 16:59:25 +02:00
|
|
|
looking_columns,
|
2022-05-05 22:21:09 +02:00
|
|
|
beta,
|
|
|
|
|
gamma,
|
|
|
|
|
);
|
|
|
|
|
let z_looked = partial_products(
|
|
|
|
|
&trace_poly_values[*looked_table as usize],
|
2022-05-06 16:59:25 +02:00
|
|
|
looked_columns,
|
2022-05-05 22:21:09 +02:00
|
|
|
beta,
|
|
|
|
|
gamma,
|
|
|
|
|
);
|
|
|
|
|
|
2022-05-11 14:35:33 +02:00
|
|
|
acc[*looking_table as usize]
|
|
|
|
|
.zs_columns
|
|
|
|
|
.push((z_looking, looking_columns.clone()));
|
|
|
|
|
acc[*looked_table as usize]
|
|
|
|
|
.zs_columns
|
|
|
|
|
.push((z_looked, looked_columns.clone()));
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
acc
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn partial_products<F: Field>(
|
|
|
|
|
trace: &[PolynomialValues<F>],
|
|
|
|
|
columns: &[usize],
|
|
|
|
|
beta: F,
|
|
|
|
|
gamma: F,
|
|
|
|
|
) -> PolynomialValues<F> {
|
|
|
|
|
let mut partial_prod = F::ONE;
|
|
|
|
|
let mut res = Vec::new();
|
|
|
|
|
for i in 0..trace[0].len() {
|
|
|
|
|
partial_prod *=
|
2022-05-06 16:59:25 +02:00
|
|
|
gamma + reduce_with_powers(columns.iter().map(|&j| &trace[j].values[i]), beta);
|
2022-05-05 22:21:09 +02:00
|
|
|
res.push(partial_prod);
|
|
|
|
|
}
|
|
|
|
|
res.into()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct CTLCheckVars<F, FE, P, const D2: usize>
|
|
|
|
|
where
|
|
|
|
|
F: Field,
|
|
|
|
|
FE: FieldExtension<D2, BaseField = F>,
|
|
|
|
|
P: PackedField<Scalar = FE>,
|
|
|
|
|
{
|
2022-05-06 14:55:54 +02:00
|
|
|
pub(crate) local_z: P,
|
|
|
|
|
pub(crate) next_z: P,
|
|
|
|
|
pub(crate) challenges: PermutationChallenge<F>,
|
|
|
|
|
pub(crate) columns: Vec<usize>,
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-06 14:55:54 +02:00
|
|
|
pub(crate) fn eval_cross_table_lookup_checks<F, FE, P, C, S, const D: usize, const D2: usize>(
|
2022-05-05 22:21:09 +02:00
|
|
|
vars: StarkEvaluationVars<FE, P>,
|
2022-05-06 14:55:54 +02:00
|
|
|
lookup_data: &[CTLCheckVars<F, FE, P, D2>],
|
2022-05-05 22:21:09 +02:00
|
|
|
consumer: &mut ConstraintConsumer<P>,
|
|
|
|
|
) where
|
|
|
|
|
F: RichField + Extendable<D>,
|
|
|
|
|
FE: FieldExtension<D2, BaseField = F>,
|
|
|
|
|
P: PackedField<Scalar = FE>,
|
|
|
|
|
C: GenericConfig<D, F = F>,
|
|
|
|
|
S: Stark<F, D>,
|
|
|
|
|
{
|
2022-05-06 14:55:54 +02:00
|
|
|
for lookup_datum in lookup_data {
|
|
|
|
|
let CTLCheckVars {
|
|
|
|
|
local_z,
|
|
|
|
|
next_z,
|
|
|
|
|
challenges,
|
|
|
|
|
columns,
|
|
|
|
|
} = lookup_datum;
|
|
|
|
|
let mut factor = ReducingFactor::new(challenges.beta);
|
|
|
|
|
let mut combine = |v: &[P]| -> P {
|
|
|
|
|
factor.reduce_ext(columns.iter().map(|&i| v[i])) + FE::from_basefield(challenges.gamma)
|
|
|
|
|
};
|
2022-05-05 22:21:09 +02:00
|
|
|
|
2022-05-06 14:55:54 +02:00
|
|
|
// Check value of `Z(1)`
|
|
|
|
|
consumer.constraint_first_row(*local_z - combine(vars.local_values));
|
|
|
|
|
// Check `Z(gw) = combination * Z(w)`
|
|
|
|
|
consumer.constraint_transition(*next_z - *local_z * combine(vars.next_values));
|
2022-05-05 22:21:09 +02:00
|
|
|
}
|
|
|
|
|
}
|