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