plonky2/evm/src/stark.rs

229 lines
8.2 KiB
Rust
Raw Normal View History

use plonky2::field::extension::{Extendable, FieldExtension};
use plonky2::field::packed::PackedField;
use plonky2::field::types::Field;
2022-05-04 20:57:07 +02:00
use plonky2::fri::structure::{
FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriOracleInfo,
FriPolynomialInfo,
};
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use crate::config::StarkConfig;
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
use crate::evaluation_frame::StarkEvaluationFrame;
2023-02-13 15:58:26 +01:00
use crate::lookup::Lookup;
2022-05-04 20:57:07 +02:00
2022-09-16 15:18:44 -07:00
const TRACE_ORACLE_INDEX: usize = 0;
2023-02-13 15:58:26 +01:00
const AUXILIARY_ORACLE_INDEX: usize = 1;
2022-09-16 15:18:44 -07:00
const QUOTIENT_ORACLE_INDEX: usize = 2;
2022-05-04 20:57:07 +02:00
/// Represents a STARK system.
pub trait Stark<F: RichField + Extendable<D>, const D: usize>: Sync {
/// The total number of columns in the trace.
const COLUMNS: usize = Self::EvaluationFrameTarget::COLUMNS;
/// This is used to evaluate constraints natively.
type EvaluationFrame<FE, P, const D2: usize>: StarkEvaluationFrame<P>
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>>;
2022-05-04 20:57:07 +02: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,
vars: &Self::EvaluationFrame<FE, P, D2>,
2022-05-04 20:57:07 +02: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,
vars: &Self::EvaluationFrame<F, P, 1>,
2022-05-04 20:57:07 +02: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,
vars: &Self::EvaluationFrame<F::Extension, F::Extension, D>,
2022-05-04 20:57:07 +02: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-05-04 20:57:07 +02:00
/// same order as they are given in `eval_packed_generic`.
2022-05-18 09:22:58 +02:00
fn eval_ext_circuit(
2022-05-04 20:57:07 +02:00
&self,
builder: &mut CircuitBuilder<F, D>,
vars: &Self::EvaluationFrameTarget,
2022-05-04 20:57:07 +02:00
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
);
/// The maximum constraint degree.
fn constraint_degree(&self) -> usize;
/// The maximum constraint degree.
fn quotient_degree_factor(&self) -> usize {
1.max(self.constraint_degree() - 1)
}
2022-09-19 20:54:45 -07:00
fn num_quotient_polys(&self, config: &StarkConfig) -> usize {
self.quotient_degree_factor() * config.num_challenges
}
2022-05-04 20:57:07 +02:00
/// Computes the FRI instance used to prove this Stark.
fn fri_instance(
&self,
zeta: F::Extension,
g: F,
num_ctl_helpers: usize,
num_ctl_zs: Vec<usize>,
2022-05-04 20:57:07 +02:00
config: &StarkConfig,
) -> FriInstanceInfo<F, D> {
2022-09-16 15:18:44 -07:00
let trace_oracle = FriOracleInfo {
num_polys: Self::COLUMNS,
blinding: false,
};
let trace_info = FriPolynomialInfo::from_range(TRACE_ORACLE_INDEX, 0..Self::COLUMNS);
2022-05-04 20:57:07 +02:00
2023-02-13 15:58:26 +01:00
let num_lookup_columns = self.num_lookup_helper_columns(config);
let num_auxiliary_polys = num_lookup_columns + num_ctl_helpers + num_ctl_zs.len();
2023-02-13 15:58:26 +01:00
let auxiliary_oracle = FriOracleInfo {
num_polys: num_auxiliary_polys,
2022-09-16 15:18:44 -07:00
blinding: false,
};
2023-02-13 15:58:26 +01:00
let auxiliary_polys_info =
FriPolynomialInfo::from_range(AUXILIARY_ORACLE_INDEX, 0..num_auxiliary_polys);
2022-05-24 16:24:52 +02:00
let ctl_zs_info = FriPolynomialInfo::from_range(
2023-02-13 15:58:26 +01:00
AUXILIARY_ORACLE_INDEX,
num_lookup_columns + num_ctl_helpers..num_auxiliary_polys,
2022-05-24 16:24:52 +02:00
);
2022-05-04 20:57:07 +02:00
2022-09-19 21:41:24 -07:00
let num_quotient_polys = self.num_quotient_polys(config);
2022-09-16 15:18:44 -07:00
let quotient_oracle = FriOracleInfo {
num_polys: num_quotient_polys,
blinding: false,
};
let quotient_info =
FriPolynomialInfo::from_range(QUOTIENT_ORACLE_INDEX, 0..num_quotient_polys);
2022-05-04 20:57:07 +02:00
let zeta_batch = FriBatchInfo {
point: zeta,
2022-05-24 16:24:52 +02:00
polynomials: [
trace_info.clone(),
2023-02-13 15:58:26 +01:00
auxiliary_polys_info.clone(),
2022-05-24 16:24:52 +02:00
quotient_info,
]
.concat(),
2022-05-04 20:57:07 +02:00
};
2022-06-02 23:55:56 +02:00
let zeta_next_batch = FriBatchInfo {
2022-05-04 20:57:07 +02:00
point: zeta.scalar_mul(g),
2023-02-13 15:58:26 +01:00
polynomials: [trace_info, auxiliary_polys_info].concat(),
2022-05-10 15:08:08 +02:00
};
2023-09-11 14:11:13 -04:00
let ctl_first_batch = FriBatchInfo {
point: F::Extension::ONE,
2022-05-24 16:24:52 +02:00
polynomials: ctl_zs_info,
};
2022-05-04 20:57:07 +02:00
FriInstanceInfo {
2023-02-13 15:58:26 +01:00
oracles: vec![trace_oracle, auxiliary_oracle, quotient_oracle],
2023-09-11 14:11:13 -04:00
batches: vec![zeta_batch, zeta_next_batch, ctl_first_batch],
2022-05-04 20:57:07 +02: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,
num_ctl_helper_polys: usize,
2022-05-24 16:24:52 +02:00
num_ctl_zs: usize,
inner_config: &StarkConfig,
2022-05-04 20:57:07 +02:00
) -> FriInstanceInfoTarget<D> {
2022-09-16 15:18:44 -07:00
let trace_oracle = FriOracleInfo {
num_polys: Self::COLUMNS,
blinding: false,
};
let trace_info = FriPolynomialInfo::from_range(TRACE_ORACLE_INDEX, 0..Self::COLUMNS);
2022-05-04 20:57:07 +02:00
2023-02-13 15:58:26 +01:00
let num_lookup_columns = self.num_lookup_helper_columns(inner_config);
let num_auxiliary_polys = num_lookup_columns + num_ctl_helper_polys + num_ctl_zs;
2023-02-13 15:58:26 +01:00
let auxiliary_oracle = FriOracleInfo {
num_polys: num_auxiliary_polys,
2022-09-16 15:18:44 -07:00
blinding: false,
};
2023-02-13 15:58:26 +01:00
let auxiliary_polys_info =
FriPolynomialInfo::from_range(AUXILIARY_ORACLE_INDEX, 0..num_auxiliary_polys);
2022-05-24 16:24:52 +02:00
let ctl_zs_info = FriPolynomialInfo::from_range(
2023-02-13 15:58:26 +01:00
AUXILIARY_ORACLE_INDEX,
num_lookup_columns + num_ctl_helper_polys
..num_lookup_columns + num_ctl_helper_polys + num_ctl_zs,
2022-05-24 16:24:52 +02:00
);
2022-05-04 20:57:07 +02:00
2022-09-19 21:41:24 -07:00
let num_quotient_polys = self.num_quotient_polys(inner_config);
2022-09-16 15:18:44 -07:00
let quotient_oracle = FriOracleInfo {
num_polys: num_quotient_polys,
blinding: false,
};
let quotient_info =
FriPolynomialInfo::from_range(QUOTIENT_ORACLE_INDEX, 0..num_quotient_polys);
2022-05-04 20:57:07 +02:00
let zeta_batch = FriBatchInfoTarget {
point: zeta,
polynomials: [
trace_info.clone(),
2023-02-13 15:58:26 +01:00
auxiliary_polys_info.clone(),
2022-05-04 20:57:07 +02:00
quotient_info,
]
.concat(),
};
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,
2023-02-13 15:58:26 +01:00
polynomials: [trace_info, auxiliary_polys_info].concat(),
2022-05-24 16:24:52 +02:00
};
2023-09-11 14:11:13 -04:00
let ctl_first_batch = FriBatchInfoTarget {
point: builder.one_extension(),
2022-05-24 16:24:52 +02:00
polynomials: ctl_zs_info,
2022-05-04 20:57:07 +02:00
};
FriInstanceInfoTarget {
2023-02-13 15:58:26 +01:00
oracles: vec![trace_oracle, auxiliary_oracle, quotient_oracle],
2023-09-11 14:11:13 -04:00
batches: vec![zeta_batch, zeta_next_batch, ctl_first_batch],
2022-05-04 20:57:07 +02:00
}
}
fn lookups(&self) -> Vec<Lookup<F>> {
2022-05-04 20:57:07 +02:00
vec![]
}
2023-02-13 15:58:26 +01: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-05-04 20:57:07 +02:00
}
2023-02-13 15:58:26 +01:00
fn uses_lookups(&self) -> bool {
!self.lookups().is_empty()
2022-05-04 20:57:07 +02:00
}
}