2022-11-04 16:04:10 -07:00
|
|
|
use alloc::vec;
|
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
|
2022-06-27 07:18:21 -07:00
|
|
|
use plonky2::field::extension::{Extendable, FieldExtension};
|
2022-06-27 15:07:52 -07:00
|
|
|
use plonky2::field::packed::PackedField;
|
2024-02-06 12:57:40 -05:00
|
|
|
use plonky2::field::types::Field;
|
2022-02-08 18:16:33 +01:00
|
|
|
use plonky2::fri::structure::{
|
|
|
|
|
FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriOracleInfo,
|
|
|
|
|
FriPolynomialInfo,
|
|
|
|
|
};
|
2022-01-26 00:09:29 -08:00
|
|
|
use plonky2::hash::hash_types::RichField;
|
2022-02-08 18:16:33 +01:00
|
|
|
use plonky2::iop::ext_target::ExtensionTarget;
|
2022-01-26 00:09:29 -08:00
|
|
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
|
|
|
|
|
2022-02-16 01:33:59 -08:00
|
|
|
use crate::config::StarkConfig;
|
2022-01-26 00:09:29 -08:00
|
|
|
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
2023-10-24 08:20:00 +08:00
|
|
|
use crate::evaluation_frame::StarkEvaluationFrame;
|
2024-02-06 12:57:40 -05:00
|
|
|
use crate::lookup::Lookup;
|
|
|
|
|
|
|
|
|
|
const TRACE_ORACLE_INDEX: usize = 0;
|
|
|
|
|
const AUXILIARY_ORACLE_INDEX: usize = 1;
|
|
|
|
|
const QUOTIENT_ORACLE_INDEX: usize = 2;
|
2022-01-26 00:09:29 -08:00
|
|
|
|
|
|
|
|
/// Represents a STARK system.
|
2022-02-14 10:23:26 +01:00
|
|
|
pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
|
2022-01-26 00:09:29 -08:00
|
|
|
/// The total number of columns in the trace.
|
2023-10-24 08:20:00 +08:00
|
|
|
const COLUMNS: usize = Self::EvaluationFrameTarget::COLUMNS;
|
|
|
|
|
const PUBLIC_INPUTS: usize = Self::EvaluationFrameTarget::PUBLIC_INPUTS;
|
|
|
|
|
|
|
|
|
|
/// This is used to evaluate constraints natively.
|
|
|
|
|
type EvaluationFrame<FE, P, const D2: usize>: StarkEvaluationFrame<P, FE>
|
|
|
|
|
where
|
|
|
|
|
FE: FieldExtension<D2, BaseField = F>,
|
|
|
|
|
P: PackedField<Scalar = FE>;
|
|
|
|
|
|
|
|
|
|
/// The `Target` version of `Self::EvaluationFrame`, used to evaluate constraints recursively.
|
|
|
|
|
type EvaluationFrameTarget: StarkEvaluationFrame<ExtensionTarget<D>, ExtensionTarget<D>>;
|
2022-01-26 00:09:29 -08:00
|
|
|
|
|
|
|
|
/// Evaluate constraints at a vector of points.
|
|
|
|
|
///
|
|
|
|
|
/// The points are elements of a field `FE`, a degree `D2` extension of `F`. This lets us
|
|
|
|
|
/// evaluate constraints over a larger domain if desired. This can also be called with `FE = F`
|
|
|
|
|
/// and `D2 = 1`, in which case we are using the trivial extension, i.e. just evaluating
|
|
|
|
|
/// constraints over `F`.
|
|
|
|
|
fn eval_packed_generic<FE, P, const D2: usize>(
|
|
|
|
|
&self,
|
2023-10-24 08:20:00 +08:00
|
|
|
vars: &Self::EvaluationFrame<FE, P, D2>,
|
2022-01-26 00:09:29 -08:00
|
|
|
yield_constr: &mut ConstraintConsumer<P>,
|
|
|
|
|
) where
|
|
|
|
|
FE: FieldExtension<D2, BaseField = F>,
|
|
|
|
|
P: PackedField<Scalar = FE>;
|
|
|
|
|
|
|
|
|
|
/// Evaluate constraints at a vector of points from the base field `F`.
|
|
|
|
|
fn eval_packed_base<P: PackedField<Scalar = F>>(
|
|
|
|
|
&self,
|
2023-10-24 08:20:00 +08:00
|
|
|
vars: &Self::EvaluationFrame<F, P, 1>,
|
2022-01-26 00:09:29 -08:00
|
|
|
yield_constr: &mut ConstraintConsumer<P>,
|
|
|
|
|
) {
|
|
|
|
|
self.eval_packed_generic(vars, yield_constr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Evaluate constraints at a single point from the degree `D` extension field.
|
|
|
|
|
fn eval_ext(
|
|
|
|
|
&self,
|
2023-10-24 08:20:00 +08:00
|
|
|
vars: &Self::EvaluationFrame<F::Extension, F::Extension, D>,
|
2022-01-26 00:09:29 -08:00
|
|
|
yield_constr: &mut ConstraintConsumer<F::Extension>,
|
|
|
|
|
) {
|
|
|
|
|
self.eval_packed_generic(vars, yield_constr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Evaluate constraints at a vector of points from the degree `D` extension field. This is like
|
|
|
|
|
/// `eval_ext`, except in the context of a recursive circuit.
|
2023-12-08 10:17:07 +00:00
|
|
|
/// Note: constraints must be added through`yield_constr.constraint(builder, constraint)` in the
|
2022-04-29 15:39:54 +02:00
|
|
|
/// same order as they are given in `eval_packed_generic`.
|
2022-05-17 11:04:35 +02:00
|
|
|
fn eval_ext_circuit(
|
2022-01-26 00:09:29 -08:00
|
|
|
&self,
|
|
|
|
|
builder: &mut CircuitBuilder<F, D>,
|
2023-10-24 08:20:00 +08:00
|
|
|
vars: &Self::EvaluationFrameTarget,
|
2022-01-26 00:09:29 -08:00
|
|
|
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
|
|
|
|
|
);
|
2022-01-27 12:58:56 +01:00
|
|
|
|
2022-02-04 15:56:59 +01:00
|
|
|
/// The maximum constraint degree.
|
2022-02-04 17:04:07 +01:00
|
|
|
fn constraint_degree(&self) -> usize;
|
2022-02-04 15:56:59 +01:00
|
|
|
|
2022-02-04 20:24:58 +01:00
|
|
|
/// The maximum constraint degree.
|
|
|
|
|
fn quotient_degree_factor(&self) -> usize {
|
|
|
|
|
1.max(self.constraint_degree() - 1)
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 21:41:24 -07:00
|
|
|
fn num_quotient_polys(&self, config: &StarkConfig) -> usize {
|
|
|
|
|
self.quotient_degree_factor() * config.num_challenges
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-27 13:27:06 +01:00
|
|
|
/// Computes the FRI instance used to prove this Stark.
|
2022-01-27 12:58:56 +01:00
|
|
|
fn fri_instance(
|
2022-02-04 17:04:07 +01:00
|
|
|
&self,
|
2022-01-27 12:58:56 +01:00
|
|
|
zeta: F::Extension,
|
2022-02-08 18:16:33 +01:00
|
|
|
g: F,
|
2022-02-16 01:33:59 -08:00
|
|
|
config: &StarkConfig,
|
2022-01-27 12:58:56 +01:00
|
|
|
) -> FriInstanceInfo<F, D> {
|
2024-02-06 12:57:40 -05:00
|
|
|
let trace_oracle = FriOracleInfo {
|
2022-09-16 15:18:44 -07:00
|
|
|
num_polys: Self::COLUMNS,
|
|
|
|
|
blinding: false,
|
2022-02-16 01:33:59 -08:00
|
|
|
};
|
2024-02-06 12:57:40 -05:00
|
|
|
let trace_info = FriPolynomialInfo::from_range(TRACE_ORACLE_INDEX, 0..Self::COLUMNS);
|
|
|
|
|
|
|
|
|
|
let num_lookup_columns = self.num_lookup_helper_columns(config);
|
|
|
|
|
let num_auxiliary_polys = num_lookup_columns;
|
|
|
|
|
let auxiliary_oracle = FriOracleInfo {
|
|
|
|
|
num_polys: num_auxiliary_polys,
|
|
|
|
|
blinding: false,
|
|
|
|
|
};
|
|
|
|
|
let auxiliary_polys_info =
|
|
|
|
|
FriPolynomialInfo::from_range(AUXILIARY_ORACLE_INDEX, 0..num_auxiliary_polys);
|
2022-02-16 01:33:59 -08:00
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
let num_quotient_polys = self.num_quotient_polys(config);
|
|
|
|
|
let quotient_oracle = FriOracleInfo {
|
2022-09-16 15:18:44 -07:00
|
|
|
num_polys: num_quotient_polys,
|
|
|
|
|
blinding: false,
|
2024-02-06 12:57:40 -05:00
|
|
|
};
|
|
|
|
|
let quotient_info =
|
|
|
|
|
FriPolynomialInfo::from_range(QUOTIENT_ORACLE_INDEX, 0..num_quotient_polys);
|
2022-02-16 01:33:59 -08:00
|
|
|
|
2022-01-27 12:58:56 +01:00
|
|
|
let zeta_batch = FriBatchInfo {
|
|
|
|
|
point: zeta,
|
2022-02-16 01:33:59 -08:00
|
|
|
polynomials: [
|
|
|
|
|
trace_info.clone(),
|
2024-02-06 12:57:40 -05:00
|
|
|
auxiliary_polys_info.clone(),
|
2022-02-16 01:33:59 -08:00
|
|
|
quotient_info,
|
|
|
|
|
]
|
|
|
|
|
.concat(),
|
2022-01-27 12:58:56 +01:00
|
|
|
};
|
2022-06-02 23:55:56 +02:00
|
|
|
let zeta_next_batch = FriBatchInfo {
|
2022-02-08 18:16:33 +01:00
|
|
|
point: zeta.scalar_mul(g),
|
2024-02-06 12:57:40 -05:00
|
|
|
polynomials: [trace_info, auxiliary_polys_info].concat(),
|
2022-01-27 12:58:56 +01:00
|
|
|
};
|
2022-09-16 15:18:44 -07:00
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
FriInstanceInfo {
|
|
|
|
|
oracles: vec![trace_oracle, auxiliary_oracle, quotient_oracle],
|
|
|
|
|
batches: vec![zeta_batch, zeta_next_batch],
|
|
|
|
|
}
|
2022-01-27 12:58:56 +01:00
|
|
|
}
|
2022-02-08 18:16:33 +01:00
|
|
|
|
|
|
|
|
/// Computes the FRI instance used to prove this Stark.
|
|
|
|
|
fn fri_instance_target(
|
|
|
|
|
&self,
|
|
|
|
|
builder: &mut CircuitBuilder<F, D>,
|
|
|
|
|
zeta: ExtensionTarget<D>,
|
|
|
|
|
g: F,
|
2022-02-16 01:33:59 -08:00
|
|
|
config: &StarkConfig,
|
2022-02-08 18:16:33 +01:00
|
|
|
) -> FriInstanceInfoTarget<D> {
|
2024-02-06 12:57:40 -05:00
|
|
|
let trace_oracle = FriOracleInfo {
|
2022-09-16 15:18:44 -07:00
|
|
|
num_polys: Self::COLUMNS,
|
|
|
|
|
blinding: false,
|
2022-02-16 01:33:59 -08:00
|
|
|
};
|
2024-02-06 12:57:40 -05:00
|
|
|
let trace_info = FriPolynomialInfo::from_range(TRACE_ORACLE_INDEX, 0..Self::COLUMNS);
|
2022-02-16 01:33:59 -08:00
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
let num_lookup_columns = self.num_lookup_helper_columns(config);
|
|
|
|
|
let num_auxiliary_polys = num_lookup_columns;
|
|
|
|
|
let auxiliary_oracle = FriOracleInfo {
|
|
|
|
|
num_polys: num_auxiliary_polys,
|
|
|
|
|
blinding: false,
|
|
|
|
|
};
|
|
|
|
|
let auxiliary_polys_info =
|
|
|
|
|
FriPolynomialInfo::from_range(AUXILIARY_ORACLE_INDEX, 0..num_auxiliary_polys);
|
|
|
|
|
|
|
|
|
|
let num_quotient_polys = self.num_quotient_polys(config);
|
|
|
|
|
let quotient_oracle = FriOracleInfo {
|
2022-09-16 15:18:44 -07:00
|
|
|
num_polys: num_quotient_polys,
|
|
|
|
|
blinding: false,
|
2024-02-06 12:57:40 -05:00
|
|
|
};
|
|
|
|
|
let quotient_info =
|
|
|
|
|
FriPolynomialInfo::from_range(QUOTIENT_ORACLE_INDEX, 0..num_quotient_polys);
|
2022-02-16 01:33:59 -08:00
|
|
|
|
2022-02-08 18:16:33 +01:00
|
|
|
let zeta_batch = FriBatchInfoTarget {
|
|
|
|
|
point: zeta,
|
2022-02-16 01:33:59 -08:00
|
|
|
polynomials: [
|
|
|
|
|
trace_info.clone(),
|
2024-02-06 12:57:40 -05:00
|
|
|
auxiliary_polys_info.clone(),
|
2022-02-16 01:33:59 -08:00
|
|
|
quotient_info,
|
|
|
|
|
]
|
|
|
|
|
.concat(),
|
2022-02-08 18:16:33 +01:00
|
|
|
};
|
2022-06-02 23:55:56 +02:00
|
|
|
let zeta_next = builder.mul_const_extension(g, zeta);
|
|
|
|
|
let zeta_next_batch = FriBatchInfoTarget {
|
|
|
|
|
point: zeta_next,
|
2024-02-06 12:57:40 -05:00
|
|
|
polynomials: [trace_info, auxiliary_polys_info].concat(),
|
2022-02-08 18:16:33 +01:00
|
|
|
};
|
2022-09-16 15:18:44 -07:00
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
FriInstanceInfoTarget {
|
|
|
|
|
oracles: vec![trace_oracle, auxiliary_oracle, quotient_oracle],
|
|
|
|
|
batches: vec![zeta_batch, zeta_next_batch],
|
|
|
|
|
}
|
2022-02-08 18:16:33 +01:00
|
|
|
}
|
2022-02-16 01:33:59 -08:00
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
fn lookups(&self) -> Vec<Lookup<F>> {
|
2022-02-16 01:33:59 -08:00
|
|
|
vec![]
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
fn num_lookup_helper_columns(&self, config: &StarkConfig) -> usize {
|
|
|
|
|
self.lookups()
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|lookup| lookup.num_helper_columns(self.constraint_degree()))
|
|
|
|
|
.sum::<usize>()
|
|
|
|
|
* config.num_challenges
|
2022-02-16 01:33:59 -08:00
|
|
|
}
|
|
|
|
|
|
2024-02-06 12:57:40 -05:00
|
|
|
fn uses_lookups(&self) -> bool {
|
|
|
|
|
!self.lookups().is_empty()
|
2022-02-16 01:33:59 -08:00
|
|
|
}
|
2022-01-26 00:09:29 -08:00
|
|
|
}
|