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