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