1use crate::{
23 circuits::{
24 domains::{Domain, EvaluationDomains},
25 expr::{
26 CacheId, ColumnEnvironment, ColumnEvaluations, ConstantExpr, ConstantTerm, Constants,
27 Expr, ExprError, FormattedOutput,
28 },
29 gate::{CurrOrNext, GateType},
30 lookup::{index::LookupSelectors, lookups::LookupPattern},
31 wires::COLUMNS,
32 },
33 proof::{PointEvaluations, ProofEvaluations},
34};
35use ark_ff::FftField;
36use ark_poly::{Evaluations, Radix2EvaluationDomain as D};
37use serde::{Deserialize, Serialize};
38use std::collections::HashMap;
39
40#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
42pub enum BerkeleyChallengeTerm {
43 Alpha,
45 Beta,
47 Gamma,
49 JointCombiner,
51}
52
53impl core::fmt::Display for BerkeleyChallengeTerm {
54 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55 use BerkeleyChallengeTerm::*;
56 let str = match self {
57 Alpha => "alpha".to_string(),
58 Beta => "beta".to_string(),
59 Gamma => "gamma".to_string(),
60 JointCombiner => "joint_combiner".to_string(),
61 };
62 write!(f, "{}", str)
63 }
64}
65
66impl<'a> super::expr::AlphaChallengeTerm<'a> for BerkeleyChallengeTerm {
67 const ALPHA: Self = Self::Alpha;
68}
69
70pub struct BerkeleyChallenges<F> {
71 pub alpha: F,
73 pub beta: F,
75 pub gamma: F,
77 pub joint_combiner: F,
80}
81
82impl<F: ark_ff::Field> core::ops::Index<BerkeleyChallengeTerm> for BerkeleyChallenges<F> {
83 type Output = F;
84
85 fn index(&self, challenge_term: BerkeleyChallengeTerm) -> &Self::Output {
86 match challenge_term {
87 BerkeleyChallengeTerm::Alpha => &self.alpha,
88 BerkeleyChallengeTerm::Beta => &self.beta,
89 BerkeleyChallengeTerm::Gamma => &self.gamma,
90 BerkeleyChallengeTerm::JointCombiner => &self.joint_combiner,
91 }
92 }
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
105pub enum Column {
106 Witness(usize),
107 Z,
108 LookupSorted(usize),
109 LookupAggreg,
110 LookupTable,
111 LookupKindIndex(LookupPattern),
112 LookupRuntimeSelector,
113 LookupRuntimeTable,
114 Index(GateType),
115 Coefficient(usize),
116 Permutation(usize),
117}
118
119impl FormattedOutput for Column {
120 fn is_alpha(&self) -> bool {
121 unimplemented!()
123 }
124
125 fn ocaml(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
126 unimplemented!()
128 }
129
130 fn latex(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
131 match self {
132 Column::Witness(i) => format!("w_{{{i}}}"),
133 Column::Z => "Z".to_string(),
134 Column::LookupSorted(i) => format!("s_{{{i}}}"),
135 Column::LookupAggreg => "a".to_string(),
136 Column::LookupTable => "t".to_string(),
137 Column::LookupKindIndex(i) => format!("k_{{{i:?}}}"),
138 Column::LookupRuntimeSelector => "rts".to_string(),
139 Column::LookupRuntimeTable => "rt".to_string(),
140 Column::Index(gate) => {
141 format!("{gate:?}")
142 }
143 Column::Coefficient(i) => format!("c_{{{i}}}"),
144 Column::Permutation(i) => format!("sigma_{{{i}}}"),
145 }
146 }
147
148 fn text(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
149 match self {
150 Column::Witness(i) => format!("w[{i}]"),
151 Column::Z => "Z".to_string(),
152 Column::LookupSorted(i) => format!("s[{i}]"),
153 Column::LookupAggreg => "a".to_string(),
154 Column::LookupTable => "t".to_string(),
155 Column::LookupKindIndex(i) => format!("k[{i:?}]"),
156 Column::LookupRuntimeSelector => "rts".to_string(),
157 Column::LookupRuntimeTable => "rt".to_string(),
158 Column::Index(gate) => {
159 format!("{gate:?}")
160 }
161 Column::Coefficient(i) => format!("c[{i}]"),
162 Column::Permutation(i) => format!("sigma_[{i}]"),
163 }
164 }
165}
166
167impl<F: Copy> ColumnEvaluations<F> for ProofEvaluations<PointEvaluations<F>> {
168 type Column = Column;
169 fn evaluate(&self, col: Self::Column) -> Result<PointEvaluations<F>, ExprError<Self::Column>> {
170 use Column::*;
171 match col {
172 Witness(i) => Ok(self.w[i]),
173 Z => Ok(self.z),
174 LookupSorted(i) => self.lookup_sorted[i].ok_or(ExprError::MissingIndexEvaluation(col)),
175 LookupAggreg => self
176 .lookup_aggregation
177 .ok_or(ExprError::MissingIndexEvaluation(col)),
178 LookupTable => self
179 .lookup_table
180 .ok_or(ExprError::MissingIndexEvaluation(col)),
181 LookupRuntimeTable => self
182 .runtime_lookup_table
183 .ok_or(ExprError::MissingIndexEvaluation(col)),
184 Index(GateType::Poseidon) => Ok(self.poseidon_selector),
185 Index(GateType::Generic) => Ok(self.generic_selector),
186 Index(GateType::CompleteAdd) => Ok(self.complete_add_selector),
187 Index(GateType::VarBaseMul) => Ok(self.mul_selector),
188 Index(GateType::EndoMul) => Ok(self.emul_selector),
189 Index(GateType::EndoMulScalar) => Ok(self.endomul_scalar_selector),
190 Index(GateType::RangeCheck0) => self
191 .range_check0_selector
192 .ok_or(ExprError::MissingIndexEvaluation(col)),
193 Index(GateType::RangeCheck1) => self
194 .range_check1_selector
195 .ok_or(ExprError::MissingIndexEvaluation(col)),
196 Index(GateType::ForeignFieldAdd) => self
197 .foreign_field_add_selector
198 .ok_or(ExprError::MissingIndexEvaluation(col)),
199 Index(GateType::ForeignFieldMul) => self
200 .foreign_field_mul_selector
201 .ok_or(ExprError::MissingIndexEvaluation(col)),
202 Index(GateType::Xor16) => self
203 .xor_selector
204 .ok_or(ExprError::MissingIndexEvaluation(col)),
205 Index(GateType::Rot64) => self
206 .rot_selector
207 .ok_or(ExprError::MissingIndexEvaluation(col)),
208 Permutation(i) => Ok(self.s[i]),
209 Coefficient(i) => Ok(self.coefficients[i]),
210 LookupKindIndex(LookupPattern::Xor) => self
211 .xor_lookup_selector
212 .ok_or(ExprError::MissingIndexEvaluation(col)),
213 LookupKindIndex(LookupPattern::Lookup) => self
214 .lookup_gate_lookup_selector
215 .ok_or(ExprError::MissingIndexEvaluation(col)),
216 LookupKindIndex(LookupPattern::RangeCheck) => self
217 .range_check_lookup_selector
218 .ok_or(ExprError::MissingIndexEvaluation(col)),
219 LookupKindIndex(LookupPattern::ForeignFieldMul) => self
220 .foreign_field_mul_lookup_selector
221 .ok_or(ExprError::MissingIndexEvaluation(col)),
222 LookupRuntimeSelector => self
223 .runtime_lookup_table_selector
224 .ok_or(ExprError::MissingIndexEvaluation(col)),
225 Index(_) => Err(ExprError::MissingIndexEvaluation(col)),
226 }
227 }
228}
229
230impl<'a, F: FftField> ColumnEnvironment<'a, F, BerkeleyChallengeTerm, BerkeleyChallenges<F>>
231 for Environment<'a, F>
232{
233 type Column = Column;
234
235 fn get_column(&self, col: &Self::Column) -> Option<&'a Evaluations<F, D<F>>> {
236 use Column::*;
237 let lookup = self.lookup.as_ref();
238 match col {
239 Witness(i) => Some(&self.witness[*i]),
240 Coefficient(i) => Some(&self.coefficient[*i]),
241 Z => Some(self.z),
242 LookupKindIndex(i) => lookup.and_then(|l| l.selectors[*i].as_ref()),
243 LookupSorted(i) => lookup.map(|l| &l.sorted[*i]),
244 LookupAggreg => lookup.map(|l| l.aggreg),
245 LookupTable => lookup.map(|l| l.table),
246 LookupRuntimeSelector => lookup.and_then(|l| l.runtime_selector),
247 LookupRuntimeTable => lookup.and_then(|l| l.runtime_table),
248 Index(t) => match self.index.get(t) {
249 None => None,
250 Some(e) => Some(e),
251 },
252 Permutation(_) => None,
253 }
254 }
255
256 fn get_domain(&self, d: Domain) -> D<F> {
257 match d {
258 Domain::D1 => self.domain.d1,
259 Domain::D2 => self.domain.d2,
260 Domain::D4 => self.domain.d4,
261 Domain::D8 => self.domain.d8,
262 }
263 }
264
265 fn column_domain(&self, col: &Self::Column) -> Domain {
266 match *col {
267 Self::Column::Index(GateType::Generic) => Domain::D4,
268 Self::Column::Index(GateType::CompleteAdd) => Domain::D4,
269 _ => Domain::D8,
270 }
271 }
272
273 fn get_constants(&self) -> &Constants<F> {
274 &self.constants
275 }
276
277 fn get_challenges(&self) -> &BerkeleyChallenges<F> {
278 &self.challenges
279 }
280
281 fn vanishes_on_zero_knowledge_and_previous_rows(&self) -> &'a Evaluations<F, D<F>> {
282 self.vanishes_on_zero_knowledge_and_previous_rows
283 }
284
285 fn l0_1(&self) -> F {
286 self.l0_1
287 }
288}
289
290pub struct LookupEnvironment<'a, F: FftField> {
294 pub sorted: &'a Vec<Evaluations<F, D<F>>>,
296 pub aggreg: &'a Evaluations<F, D<F>>,
298 pub selectors: &'a LookupSelectors<Evaluations<F, D<F>>>,
300 pub table: &'a Evaluations<F, D<F>>,
302 pub runtime_selector: Option<&'a Evaluations<F, D<F>>>,
304 pub runtime_table: Option<&'a Evaluations<F, D<F>>>,
306}
307
308pub struct Environment<'a, F: FftField> {
313 pub witness: &'a [Evaluations<F, D<F>>; COLUMNS],
315 pub coefficient: &'a [Evaluations<F, D<F>>; COLUMNS],
317 pub vanishes_on_zero_knowledge_and_previous_rows: &'a Evaluations<F, D<F>>,
319 pub z: &'a Evaluations<F, D<F>>,
321 pub index: HashMap<GateType, &'a Evaluations<F, D<F>>>,
323 pub l0_1: F,
326 pub constants: Constants<F>,
328 pub challenges: BerkeleyChallenges<F>,
330 pub domain: EvaluationDomains<F>,
332 pub lookup: Option<LookupEnvironment<'a, F>>,
334}
335
336pub type E<F> = Expr<ConstantExpr<F, BerkeleyChallengeTerm>, Column>;
342
343pub fn constant<F>(x: F) -> E<F> {
345 ConstantTerm::Literal(x).into()
346}
347
348pub fn witness<F>(i: usize, row: CurrOrNext) -> E<F> {
350 E::<F>::cell(Column::Witness(i), row)
351}
352
353pub fn witness_curr<F>(i: usize) -> E<F> {
355 witness(i, CurrOrNext::Curr)
356}
357
358pub fn witness_next<F>(i: usize) -> E<F> {
360 witness(i, CurrOrNext::Next)
361}
362
363pub fn index<F>(g: GateType) -> E<F> {
365 E::<F>::cell(Column::Index(g), CurrOrNext::Curr)
366}
367
368pub fn coeff<F>(i: usize) -> E<F> {
369 E::<F>::cell(Column::Coefficient(i), CurrOrNext::Curr)
370}