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