kimchi_stubs/
pasta_fq_plonk_proof.rs

1use crate::{
2    arkworks::{CamlFq, CamlGPallas},
3    field_vector::fq::CamlFqVector,
4    pasta_fq_plonk_index::CamlPastaFqPlonkIndexPtr,
5    pasta_fq_plonk_verifier_index::CamlPastaFqPlonkVerifierIndex,
6    WithLagrangeBasis,
7};
8use ark_ec::AffineRepr;
9use ark_ff::One;
10use core::{array, convert::TryInto};
11use groupmap::GroupMap;
12use kimchi::{
13    circuits::{
14        lookup::runtime_tables::{caml::CamlRuntimeTable, RuntimeTable},
15        polynomial::COLUMNS,
16    },
17    proof::{
18        PointEvaluations, ProofEvaluations, ProverCommitments, ProverProof, RecursionChallenge,
19    },
20    prover::caml::CamlProofWithPublic,
21    prover_index::ProverIndex,
22    verifier::{batch_verify, Context},
23    verifier_index::VerifierIndex,
24};
25use mina_curves::pasta::{Fp, Fq, Pallas, PallasParameters};
26use mina_poseidon::{
27    constants::PlonkSpongeConstantsKimchi,
28    sponge::{DefaultFqSponge, DefaultFrSponge},
29};
30use poly_commitment::{
31    commitment::{CommitmentCurve, PolyComm},
32    ipa::OpeningProof,
33};
34
35#[ocaml_gen::func]
36#[ocaml::func]
37pub fn caml_pasta_fq_plonk_proof_create(
38    index: CamlPastaFqPlonkIndexPtr<'static>,
39    witness: Vec<CamlFqVector>,
40    runtime_tables: Vec<CamlRuntimeTable<CamlFq>>,
41    prev_challenges: Vec<CamlFq>,
42    prev_sgs: Vec<CamlGPallas>,
43) -> Result<CamlProofWithPublic<CamlGPallas, CamlFq>, ocaml::Error> {
44    {
45        index
46            .as_ref()
47            .0
48            .srs
49            .with_lagrange_basis(index.as_ref().0.cs.domain.d1);
50    }
51    let prev = if prev_challenges.is_empty() {
52        Vec::new()
53    } else {
54        let challenges_per_sg = prev_challenges.len() / prev_sgs.len();
55        prev_sgs
56            .into_iter()
57            .map(Into::<Pallas>::into)
58            .enumerate()
59            .map(|(i, sg)| {
60                let chals = prev_challenges[(i * challenges_per_sg)..(i + 1) * challenges_per_sg]
61                    .iter()
62                    .map(Into::<Fq>::into)
63                    .collect();
64                let comm = PolyComm::<Pallas> { chunks: vec![sg] };
65                RecursionChallenge { chals, comm }
66            })
67            .collect()
68    };
69
70    let witness: Vec<Vec<_>> = witness.iter().map(|x| (**x).clone()).collect();
71    let witness: [Vec<_>; COLUMNS] = witness
72        .try_into()
73        .expect("the witness should be a column of 15 vectors");
74    let index: &ProverIndex<Pallas, OpeningProof<Pallas>> = &index.as_ref().0;
75
76    let runtime_tables: Vec<RuntimeTable<Fq>> =
77        runtime_tables.into_iter().map(Into::into).collect();
78
79    // public input
80    let public_input = witness[0][0..index.cs.public].to_vec();
81
82    // NB: This method is designed only to be used by tests. However, since
83    // creating a new reference will cause `drop` to be called on it once we are
84    // done with it. Since `drop` calls `caml_shutdown` internally, we *really,
85    // really* do not want to do this, but we have no other way to get at the
86    // active runtime.
87    // TODO: There's actually a way to get a handle to the runtime as a function
88    // argument. Switch to doing this instead.
89    let runtime = unsafe { ocaml::Runtime::recover_handle() };
90
91    // Release the runtime lock so that other threads can run using it while we
92    // generate the proof.
93    runtime.releasing_runtime(|| {
94        let group_map = GroupMap::<Fp>::setup();
95        let proof = ProverProof::create_recursive::<
96            DefaultFqSponge<PallasParameters, PlonkSpongeConstantsKimchi>,
97            DefaultFrSponge<Fq, PlonkSpongeConstantsKimchi>,
98            _,
99        >(
100            &group_map,
101            witness,
102            &runtime_tables,
103            index,
104            prev,
105            None,
106            &mut rand::rngs::OsRng,
107        )
108        .map_err(|e| ocaml::Error::Error(e.into()))?;
109        Ok((proof, public_input).into())
110    })
111}
112
113#[ocaml_gen::func]
114#[ocaml::func]
115pub fn caml_pasta_fq_plonk_proof_verify(
116    index: CamlPastaFqPlonkVerifierIndex,
117    proof: CamlProofWithPublic<CamlGPallas, CamlFq>,
118) -> bool {
119    let group_map = <Pallas as CommitmentCurve>::Map::setup();
120
121    let (proof, public_input) = proof.into();
122    let verifier_index = index.into();
123    let context = Context {
124        verifier_index: &verifier_index,
125        proof: &proof,
126        public_input: &public_input,
127    };
128
129    batch_verify::<
130        Pallas,
131        DefaultFqSponge<PallasParameters, PlonkSpongeConstantsKimchi>,
132        DefaultFrSponge<Fq, PlonkSpongeConstantsKimchi>,
133        OpeningProof<Pallas>,
134    >(&group_map, &[context])
135    .is_ok()
136}
137
138#[ocaml_gen::func]
139#[ocaml::func]
140pub fn caml_pasta_fq_plonk_proof_batch_verify(
141    indexes: Vec<CamlPastaFqPlonkVerifierIndex>,
142    proofs: Vec<CamlProofWithPublic<CamlGPallas, CamlFq>>,
143) -> bool {
144    let ts: Vec<_> = indexes
145        .into_iter()
146        .zip(proofs.into_iter())
147        .map(|(caml_index, caml_proof)| {
148            let verifier_index: VerifierIndex<Pallas, OpeningProof<Pallas>> = caml_index.into();
149            let (proof, public_input): (ProverProof<Pallas, OpeningProof<Pallas>>, Vec<_>) =
150                caml_proof.into();
151            (verifier_index, proof, public_input)
152        })
153        .collect();
154    let ts_ref: Vec<Context<Pallas, OpeningProof<Pallas>>> = ts
155        .iter()
156        .map(|(verifier_index, proof, public_input)| Context {
157            verifier_index,
158            proof,
159            public_input,
160        })
161        .collect();
162    let group_map = GroupMap::<Fp>::setup();
163
164    batch_verify::<
165        Pallas,
166        DefaultFqSponge<PallasParameters, PlonkSpongeConstantsKimchi>,
167        DefaultFrSponge<Fq, PlonkSpongeConstantsKimchi>,
168        OpeningProof<Pallas>,
169    >(&group_map, &ts_ref)
170    .is_ok()
171}
172
173#[ocaml_gen::func]
174#[ocaml::func]
175pub fn caml_pasta_fq_plonk_proof_dummy() -> CamlProofWithPublic<CamlGPallas, CamlFq> {
176    fn comm() -> PolyComm<Pallas> {
177        let g = Pallas::generator();
178        PolyComm {
179            chunks: vec![g, g, g],
180        }
181    }
182
183    let prev = RecursionChallenge {
184        chals: vec![Fq::one(), Fq::one()],
185        comm: comm(),
186    };
187    let prev_challenges = vec![prev.clone(), prev.clone(), prev];
188
189    let g = Pallas::generator();
190    let proof = OpeningProof {
191        lr: vec![(g, g), (g, g), (g, g)],
192        z1: Fq::one(),
193        z2: Fq::one(),
194        delta: g,
195        sg: g,
196    };
197    let eval = || PointEvaluations {
198        zeta: vec![Fq::one()],
199        zeta_omega: vec![Fq::one()],
200    };
201    let evals = ProofEvaluations {
202        public: Some(eval()),
203        w: core::array::from_fn(|_| eval()),
204        coefficients: core::array::from_fn(|_| eval()),
205        z: eval(),
206        s: core::array::from_fn(|_| eval()),
207        generic_selector: eval(),
208        poseidon_selector: eval(),
209        complete_add_selector: eval(),
210        mul_selector: eval(),
211        emul_selector: eval(),
212        endomul_scalar_selector: eval(),
213        range_check0_selector: None,
214        range_check1_selector: None,
215        foreign_field_add_selector: None,
216        foreign_field_mul_selector: None,
217        xor_selector: None,
218        rot_selector: None,
219        lookup_aggregation: None,
220        lookup_table: None,
221        lookup_sorted: array::from_fn(|_| None),
222        runtime_lookup_table: None,
223        runtime_lookup_table_selector: None,
224        xor_lookup_selector: None,
225        lookup_gate_lookup_selector: None,
226        range_check_lookup_selector: None,
227        foreign_field_mul_lookup_selector: None,
228    };
229
230    let public = vec![Fq::one(), Fq::one()];
231    let dlogproof = ProverProof {
232        commitments: ProverCommitments {
233            w_comm: core::array::from_fn(|_| comm()),
234            z_comm: comm(),
235            t_comm: comm(),
236            lookup: None,
237        },
238        proof,
239        evals,
240        ft_eval1: Fq::one(),
241        prev_challenges,
242    };
243
244    (dlogproof, public).into()
245}
246
247#[ocaml_gen::func]
248#[ocaml::func]
249pub fn caml_pasta_fq_plonk_proof_deep_copy(
250    x: CamlProofWithPublic<CamlGPallas, CamlFq>,
251) -> CamlProofWithPublic<CamlGPallas, CamlFq> {
252    x
253}