kimchi_stubs/
pasta_fp_plonk_verifier_index.rs

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
77// TODO: This should really be a TryFrom or TryInto
78impl 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        // TODO dummy_lookup_value ?
124        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//
198// OCaml methods
199//
200
201#[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}