1use crate::{
4 alphas::Alphas,
5 circuits::{
6 berkeley_columns::{BerkeleyChallengeTerm, Column},
7 constraints::{ColumnEvaluations, ConstraintSystem},
8 expr::{Linearization, PolishToken},
9 },
10 curve::KimchiCurve,
11 linearization::expr_linearization,
12 verifier_index::VerifierIndex,
13};
14use ark_ff::PrimeField;
15use mina_poseidon::FqSponge;
16use poly_commitment::{OpenProof, SRS as _};
17use serde::{de::DeserializeOwned, Deserialize, Serialize};
18use serde_with::serde_as;
19use std::sync::Arc;
20
21#[serde_as]
23#[derive(Serialize, Deserialize, Debug, Clone)]
24pub struct ProverIndex<G: KimchiCurve, OpeningProof: OpenProof<G>> {
26 #[serde(bound = "ConstraintSystem<G::ScalarField>: Serialize + DeserializeOwned")]
28 pub cs: ConstraintSystem<G::ScalarField>,
29
30 #[serde(skip)]
32 pub linearization:
33 Linearization<Vec<PolishToken<G::ScalarField, Column, BerkeleyChallengeTerm>>, Column>,
34
35 #[serde(skip)]
37 pub powers_of_alpha: Alphas<G::ScalarField>,
38
39 #[serde(skip)]
41 #[serde(bound(deserialize = "OpeningProof::SRS: Default"))]
42 pub srs: Arc<OpeningProof::SRS>,
43
44 pub max_poly_size: usize,
46
47 #[serde(bound = "ColumnEvaluations<G::ScalarField>: Serialize + DeserializeOwned")]
48 pub column_evaluations: ColumnEvaluations<G::ScalarField>,
49
50 #[serde(skip)]
52 pub verifier_index: Option<VerifierIndex<G, OpeningProof>>,
53
54 #[serde_as(as = "Option<o1_utils::serialization::SerdeAs>")]
56 pub verifier_index_digest: Option<G::BaseField>,
57}
58impl<G: KimchiCurve, OpeningProof: OpenProof<G>> ProverIndex<G, OpeningProof>
61where
62 G::BaseField: PrimeField,
63{
64 pub fn create(
66 mut cs: ConstraintSystem<G::ScalarField>,
67 endo_q: G::ScalarField,
68 srs: Arc<OpeningProof::SRS>,
69 ) -> Self {
70 let max_poly_size = srs.max_poly_size();
71 cs.endo = endo_q;
72
73 let (linearization, powers_of_alpha) = expr_linearization(Some(&cs.feature_flags), true);
75
76 let evaluated_column_coefficients = cs.evaluated_column_coefficients();
77
78 let column_evaluations = cs.column_evaluations(&evaluated_column_coefficients);
79
80 ProverIndex {
81 cs,
82 linearization,
83 powers_of_alpha,
84 srs,
85 max_poly_size,
86 column_evaluations,
87 verifier_index: None,
88 verifier_index_digest: None,
89 }
90 }
91
92 pub fn compute_verifier_index_digest<
95 EFqSponge: Clone + FqSponge<G::BaseField, G, G::ScalarField>,
96 >(
97 &mut self,
98 ) -> G::BaseField
99 where
100 VerifierIndex<G, OpeningProof>: Clone,
101 {
102 if let Some(verifier_index_digest) = self.verifier_index_digest {
103 return verifier_index_digest;
104 }
105
106 if self.verifier_index.is_none() {
107 self.verifier_index = Some(self.verifier_index());
108 }
109
110 let verifier_index_digest = self.verifier_index_digest::<EFqSponge>();
111 self.verifier_index_digest = Some(verifier_index_digest);
112 verifier_index_digest
113 }
114
115 pub fn verifier_index_digest<EFqSponge: Clone + FqSponge<G::BaseField, G, G::ScalarField>>(
117 &self,
118 ) -> G::BaseField
119 where
120 VerifierIndex<G, OpeningProof>: Clone,
121 {
122 if let Some(verifier_index_digest) = self.verifier_index_digest {
123 return verifier_index_digest;
124 }
125
126 match &self.verifier_index {
127 None => {
128 let verifier_index = self.verifier_index();
129 verifier_index.digest::<EFqSponge>()
130 }
131 Some(verifier_index) => verifier_index.digest::<EFqSponge>(),
132 }
133 }
134}
135
136pub mod testing {
137 use super::*;
138 use crate::{
139 circuits::{
140 gate::CircuitGate,
141 lookup::{runtime_tables::RuntimeTableCfg, tables::LookupTable},
142 },
143 precomputed_srs,
144 };
145 use ark_ff::PrimeField;
146 use ark_poly::{EvaluationDomain, Radix2EvaluationDomain as D};
147 use poly_commitment::{
148 ipa::{OpeningProof, SRS},
149 OpenProof,
150 };
151
152 #[allow(clippy::too_many_arguments)]
153 pub fn new_index_for_test_with_lookups_and_custom_srs<
154 G: KimchiCurve,
155 OpeningProof: OpenProof<G>,
156 F: FnMut(D<G::ScalarField>, usize) -> OpeningProof::SRS,
157 >(
158 gates: Vec<CircuitGate<G::ScalarField>>,
159 public: usize,
160 prev_challenges: usize,
161 lookup_tables: Vec<LookupTable<G::ScalarField>>,
162 runtime_tables: Option<Vec<RuntimeTableCfg<G::ScalarField>>>,
163 disable_gates_checks: bool,
164 override_srs_size: Option<usize>,
165 mut get_srs: F,
166 ) -> ProverIndex<G, OpeningProof>
167 where
168 G::BaseField: PrimeField,
169 G::ScalarField: PrimeField,
170 {
171 let cs = ConstraintSystem::<G::ScalarField>::create(gates)
173 .lookup(lookup_tables)
174 .runtime(runtime_tables)
175 .public(public)
176 .prev_challenges(prev_challenges)
177 .disable_gates_checks(disable_gates_checks)
178 .max_poly_size(override_srs_size)
179 .build()
180 .unwrap();
181
182 let srs_size = override_srs_size.unwrap_or_else(|| cs.domain.d1.size());
183 let srs = get_srs(cs.domain.d1, srs_size);
184 let srs = Arc::new(srs);
185
186 let &endo_q = G::other_curve_endo();
187 ProverIndex::create(cs, endo_q, srs)
188 }
189
190 pub fn new_index_for_test_with_lookups<G: KimchiCurve>(
196 gates: Vec<CircuitGate<G::ScalarField>>,
197 public: usize,
198 prev_challenges: usize,
199 lookup_tables: Vec<LookupTable<G::ScalarField>>,
200 runtime_tables: Option<Vec<RuntimeTableCfg<G::ScalarField>>>,
201 disable_gates_checks: bool,
202 override_srs_size: Option<usize>,
203 ) -> ProverIndex<G, OpeningProof<G>>
204 where
205 G::BaseField: PrimeField,
206 G::ScalarField: PrimeField,
207 {
208 new_index_for_test_with_lookups_and_custom_srs(
209 gates,
210 public,
211 prev_challenges,
212 lookup_tables,
213 runtime_tables,
214 disable_gates_checks,
215 override_srs_size,
216 |d1: D<G::ScalarField>, size: usize| {
217 let log2_size = size.ilog2();
218 let srs = if log2_size <= precomputed_srs::SERIALIZED_SRS_SIZE {
219 precomputed_srs::get_srs_test()
221 } else {
222 SRS::<G>::create(size)
224 };
225
226 srs.get_lagrange_basis(d1);
227 srs
228 },
229 )
230 }
231
232 pub fn new_index_for_test<G: KimchiCurve>(
233 gates: Vec<CircuitGate<G::ScalarField>>,
234 public: usize,
235 ) -> ProverIndex<G, OpeningProof<G>>
236 where
237 G::BaseField: PrimeField,
238 G::ScalarField: PrimeField,
239 {
240 new_index_for_test_with_lookups::<G>(gates, public, 0, vec![], None, false, None)
241 }
242}