kimchi_stubs/
pasta_fq_plonk_verifier_index.rs

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
73// TODO: This should really be a TryFrom or TryInto
74impl 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        // TODO dummy_lookup_value ?
120        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//
194// OCaml methods
195//
196
197#[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}