1use crate::{
2 arkworks::{CamlFq, CamlGPallas},
3 pasta_fq_plonk_index::CamlPastaFqPlonkIndexPtr,
4 plonk_verifier_index::{CamlPlonkDomain, CamlPlonkVerificationEvals, CamlPlonkVerifierIndex},
5 srs::fq::CamlFqSrs,
6};
7use ark_ec::AffineRepr;
8use ark_ff::One;
9use ark_poly::{EvaluationDomain, Radix2EvaluationDomain as Domain};
10use core::convert::TryInto;
11use kimchi::{
12 circuits::{
13 constraints::FeatureFlags,
14 lookup::lookups::{LookupFeatures, LookupPatterns},
15 polynomials::permutation::{permutation_vanishing_polynomial, zk_w, Shifts},
16 wires::{COLUMNS, PERMUTS},
17 },
18 linearization::expr_linearization,
19 verifier_index::VerifierIndex,
20};
21use mina_curves::pasta::{Fq, Pallas, Vesta};
22use mina_poseidon::pasta::FULL_ROUNDS;
23use poly_commitment::{
24 commitment::{caml::CamlPolyComm, PolyComm},
25 ipa::{OpeningProof, SRS},
26 lagrange_basis::WithLagrangeBasis,
27 OpenProof, SRS as _,
28};
29use std::{path::Path, sync::Arc};
30
31pub type CamlPastaFqPlonkVerifierIndex =
32 CamlPlonkVerifierIndex<CamlFq, CamlFqSrs, CamlPolyComm<CamlGPallas>>;
33
34type Srs = <OpeningProof<Pallas, FULL_ROUNDS> as OpenProof<Pallas, FULL_ROUNDS>>::SRS;
35
36impl From<VerifierIndex<FULL_ROUNDS, Pallas, Srs>> for CamlPastaFqPlonkVerifierIndex {
37 fn from(vi: VerifierIndex<FULL_ROUNDS, Pallas, Srs>) -> Self {
38 Self {
39 domain: CamlPlonkDomain {
40 log_size_of_group: vi.domain.log_size_of_group as isize,
41 group_gen: CamlFq(vi.domain.group_gen),
42 },
43 max_poly_size: vi.max_poly_size as isize,
44 public: vi.public as isize,
45 prev_challenges: vi.prev_challenges as isize,
46 srs: CamlFqSrs(vi.srs.clone()),
47 evals: CamlPlonkVerificationEvals {
48 sigma_comm: vi.sigma_comm.to_vec().iter().map(Into::into).collect(),
49 coefficients_comm: vi
50 .coefficients_comm
51 .to_vec()
52 .iter()
53 .map(Into::into)
54 .collect(),
55 generic_comm: vi.generic_comm.into(),
56 psm_comm: vi.psm_comm.into(),
57 complete_add_comm: vi.complete_add_comm.into(),
58 mul_comm: vi.mul_comm.into(),
59 emul_comm: vi.emul_comm.into(),
60 endomul_scalar_comm: vi.endomul_scalar_comm.into(),
61
62 xor_comm: vi.xor_comm.map(Into::into),
63 range_check0_comm: vi.range_check0_comm.map(Into::into),
64 range_check1_comm: vi.range_check1_comm.map(Into::into),
65 foreign_field_add_comm: vi.foreign_field_add_comm.map(Into::into),
66 foreign_field_mul_comm: vi.foreign_field_mul_comm.map(Into::into),
67 rot_comm: vi.rot_comm.map(Into::into),
68 },
69 shifts: vi.shift.to_vec().iter().map(Into::into).collect(),
70 lookup_index: vi.lookup_index.map(Into::into),
71 zk_rows: vi.zk_rows as isize,
72 }
73 }
74}
75
76impl From<CamlPastaFqPlonkVerifierIndex> for VerifierIndex<FULL_ROUNDS, Pallas, Srs> {
78 fn from(index: CamlPastaFqPlonkVerifierIndex) -> Self {
79 let evals = index.evals;
80 let shifts = index.shifts;
81
82 let (endo_q, _endo_r) = poly_commitment::ipa::endos::<Vesta>();
83 let domain = Domain::<Fq>::new(1 << index.domain.log_size_of_group).expect("wrong size");
84
85 let coefficients_comm: Vec<PolyComm<Pallas>> =
86 evals.coefficients_comm.iter().map(Into::into).collect();
87 let coefficients_comm: [_; COLUMNS] = coefficients_comm.try_into().expect("wrong size");
88
89 let sigma_comm: Vec<PolyComm<Pallas>> = evals.sigma_comm.iter().map(Into::into).collect();
90 let sigma_comm: [_; PERMUTS] = sigma_comm
91 .try_into()
92 .expect("vector of sigma comm is of wrong size");
93
94 let shifts: Vec<Fq> = shifts.iter().map(Into::into).collect();
95 let shift: [Fq; PERMUTS] = shifts.try_into().expect("wrong size");
96
97 let feature_flags = FeatureFlags {
98 range_check0: evals.range_check0_comm.is_some(),
99 range_check1: evals.range_check1_comm.is_some(),
100 foreign_field_add: evals.foreign_field_add_comm.is_some(),
101 foreign_field_mul: evals.foreign_field_mul_comm.is_some(),
102 rot: evals.rot_comm.is_some(),
103 xor: evals.xor_comm.is_some(),
104 lookup_features: {
105 if let Some(li) = index.lookup_index.as_ref() {
106 li.lookup_info.features
107 } else {
108 LookupFeatures {
109 patterns: LookupPatterns {
110 xor: false,
111 lookup: false,
112 range_check: false,
113 foreign_field_mul: false,
114 },
115 joint_lookup_used: false,
116 uses_runtime_tables: false,
117 }
118 }
119 },
120 };
121
122 let (linearization, powers_of_alpha) = expr_linearization(Some(&feature_flags), true);
124
125 VerifierIndex::<FULL_ROUNDS, Pallas, Srs> {
126 domain,
127 max_poly_size: index.max_poly_size as usize,
128 public: index.public as usize,
129 prev_challenges: index.prev_challenges as usize,
130 powers_of_alpha,
131 srs: { Arc::clone(&index.srs.0) },
132
133 zk_rows: index.zk_rows as u64,
134
135 sigma_comm,
136 coefficients_comm,
137 generic_comm: evals.generic_comm.into(),
138
139 psm_comm: evals.psm_comm.into(),
140
141 complete_add_comm: evals.complete_add_comm.into(),
142 mul_comm: evals.mul_comm.into(),
143 emul_comm: evals.emul_comm.into(),
144 endomul_scalar_comm: evals.endomul_scalar_comm.into(),
145
146 xor_comm: evals.xor_comm.map(Into::into),
147 range_check0_comm: evals.range_check0_comm.map(Into::into),
148 range_check1_comm: evals.range_check1_comm.map(Into::into),
149 foreign_field_add_comm: evals.foreign_field_add_comm.map(Into::into),
150 foreign_field_mul_comm: evals.foreign_field_mul_comm.map(Into::into),
151 rot_comm: evals.rot_comm.map(Into::into),
152
153 shift,
154 permutation_vanishing_polynomial_m: {
155 let res = once_cell::sync::OnceCell::new();
156 res.set(permutation_vanishing_polynomial(
157 domain,
158 index.zk_rows as u64,
159 ))
160 .unwrap();
161 res
162 },
163 w: {
164 let res = once_cell::sync::OnceCell::new();
165 res.set(zk_w(domain, index.zk_rows as u64)).unwrap();
166 res
167 },
168 endo: endo_q,
169
170 lookup_index: index.lookup_index.map(Into::into),
171 linearization,
172 }
173 }
174}
175
176pub fn read_raw(
177 offset: Option<ocaml::Int>,
178 srs: CamlFqSrs,
179 path: String,
180) -> Result<VerifierIndex<FULL_ROUNDS, Pallas, Srs>, ocaml::Error> {
181 let path = Path::new(&path);
182 let (endo_q, _endo_r) = poly_commitment::ipa::endos::<Vesta>();
183 VerifierIndex::<FULL_ROUNDS, Pallas, Srs>::from_file(
184 srs.0,
185 path,
186 offset.map(|x| x as u64),
187 endo_q,
188 )
189 .map_err(|_e| {
190 ocaml::Error::invalid_argument("caml_pasta_fq_plonk_verifier_index_raw_read")
191 .err()
192 .unwrap()
193 })
194}
195
196#[ocaml_gen::func]
201#[ocaml::func]
202pub fn caml_pasta_fq_plonk_verifier_index_read(
203 offset: Option<ocaml::Int>,
204 srs: CamlFqSrs,
205 path: String,
206) -> Result<CamlPastaFqPlonkVerifierIndex, ocaml::Error> {
207 let vi = read_raw(offset, srs, path)?;
208 Ok(vi.into())
209}
210
211#[ocaml_gen::func]
212#[ocaml::func]
213pub fn caml_pasta_fq_plonk_verifier_index_write(
214 append: Option<bool>,
215 index: CamlPastaFqPlonkVerifierIndex,
216 path: String,
217) -> Result<(), ocaml::Error> {
218 let index: VerifierIndex<FULL_ROUNDS, Pallas, Srs> = index.into();
219 let path = Path::new(&path);
220 index.to_file(path, append).map_err(|_e| {
221 ocaml::Error::invalid_argument("caml_pasta_fq_plonk_verifier_index_raw_read")
222 .err()
223 .unwrap()
224 })
225}
226
227#[ocaml_gen::func]
228#[ocaml::func]
229pub fn caml_pasta_fq_plonk_verifier_index_create(
230 index: CamlPastaFqPlonkIndexPtr,
231) -> CamlPastaFqPlonkVerifierIndex {
232 index
233 .as_ref()
234 .0
235 .srs
236 .with_lagrange_basis(index.as_ref().0.cs.domain.d1);
237 let verifier_index = index.as_ref().0.verifier_index();
238 verifier_index.into()
239}
240
241#[ocaml_gen::func]
242#[ocaml::func]
243pub fn caml_pasta_fq_plonk_verifier_index_shifts(log2_size: ocaml::Int) -> Vec<CamlFq> {
244 let domain = Domain::<Fq>::new(1 << log2_size).unwrap();
245 let shifts = Shifts::new(&domain);
246 shifts.shifts().iter().map(Into::into).collect()
247}
248
249#[ocaml_gen::func]
250#[ocaml::func]
251pub fn caml_pasta_fq_plonk_verifier_index_dummy() -> CamlPastaFqPlonkVerifierIndex {
252 fn comm() -> CamlPolyComm<CamlGPallas> {
253 let g: CamlGPallas = Pallas::generator().into();
254 CamlPolyComm {
255 shifted: None,
256 unshifted: vec![g, g, g],
257 }
258 }
259 fn vec_comm(num: usize) -> Vec<CamlPolyComm<CamlGPallas>> {
260 (0..num).map(|_| comm()).collect()
261 }
262
263 CamlPlonkVerifierIndex {
264 domain: CamlPlonkDomain {
265 log_size_of_group: 1,
266 group_gen: Fq::one().into(),
267 },
268 max_poly_size: 0,
269 public: 0,
270 prev_challenges: 0,
271 srs: CamlFqSrs::new(SRS::create(0)),
272 evals: CamlPlonkVerificationEvals {
273 sigma_comm: vec_comm(PERMUTS),
274 coefficients_comm: vec_comm(COLUMNS),
275 generic_comm: comm(),
276 psm_comm: comm(),
277 complete_add_comm: comm(),
278 mul_comm: comm(),
279 endomul_scalar_comm: comm(),
280 emul_comm: comm(),
281 xor_comm: None,
282 range_check0_comm: None,
283 range_check1_comm: None,
284 foreign_field_add_comm: None,
285 foreign_field_mul_comm: None,
286 rot_comm: None,
287 },
288 shifts: (0..PERMUTS - 1).map(|_| Fq::one().into()).collect(),
289 lookup_index: None,
290 zk_rows: 3,
291 }
292}
293
294#[ocaml_gen::func]
295#[ocaml::func]
296pub fn caml_pasta_fq_plonk_verifier_index_deep_copy(
297 x: CamlPastaFqPlonkVerifierIndex,
298) -> CamlPastaFqPlonkVerifierIndex {
299 x
300}