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    if std::env::var("KIMCHI_PROVER_DUMP_ARGUMENTS").is_ok() {
83        kimchi::bench::bench_arguments_dump_into_file(&index.cs, &witness, &runtime_tables, &prev);
84    }
85
86    // NB: This method is designed only to be used by tests. However, since
87    // creating a new reference will cause `drop` to be called on it once we are
88    // done with it. Since `drop` calls `caml_shutdown` internally, we *really,
89    // really* do not want to do this, but we have no other way to get at the
90    // active runtime.
91    // TODO: There's actually a way to get a handle to the runtime as a function
92    // argument. Switch to doing this instead.
93    let runtime = unsafe { ocaml::Runtime::recover_handle() };
94
95    // Release the runtime lock so that other threads can run using it while we
96    // generate the proof.
97    runtime.releasing_runtime(|| {
98        let group_map = GroupMap::<Fp>::setup();
99        let proof = ProverProof::create_recursive::<
100            DefaultFqSponge<PallasParameters, PlonkSpongeConstantsKimchi>,
101            DefaultFrSponge<Fq, PlonkSpongeConstantsKimchi>,
102            _,
103        >(
104            &group_map,
105            witness,
106            &runtime_tables,
107            index,
108            prev,
109            None,
110            &mut rand::rngs::OsRng,
111        )
112        .map_err(|e| ocaml::Error::Error(e.into()))?;
113        Ok((proof, public_input).into())
114    })
115}
116
117#[ocaml_gen::func]
118#[ocaml::func]
119pub fn caml_pasta_fq_plonk_proof_verify(
120    index: CamlPastaFqPlonkVerifierIndex,
121    proof: CamlProofWithPublic<CamlGPallas, CamlFq>,
122) -> bool {
123    let group_map = <Pallas as CommitmentCurve>::Map::setup();
124
125    let (proof, public_input) = proof.into();
126    let verifier_index = index.into();
127    let context = Context {
128        verifier_index: &verifier_index,
129        proof: &proof,
130        public_input: &public_input,
131    };
132
133    batch_verify::<
134        Pallas,
135        DefaultFqSponge<PallasParameters, PlonkSpongeConstantsKimchi>,
136        DefaultFrSponge<Fq, PlonkSpongeConstantsKimchi>,
137        OpeningProof<Pallas>,
138    >(&group_map, &[context])
139    .is_ok()
140}
141
142#[ocaml_gen::func]
143#[ocaml::func]
144pub fn caml_pasta_fq_plonk_proof_batch_verify(
145    indexes: Vec<CamlPastaFqPlonkVerifierIndex>,
146    proofs: Vec<CamlProofWithPublic<CamlGPallas, CamlFq>>,
147) -> bool {
148    let ts: Vec<_> = indexes
149        .into_iter()
150        .zip(proofs.into_iter())
151        .map(|(caml_index, caml_proof)| {
152            let verifier_index: VerifierIndex<Pallas, OpeningProof<Pallas>> = caml_index.into();
153            let (proof, public_input): (ProverProof<Pallas, OpeningProof<Pallas>>, Vec<_>) =
154                caml_proof.into();
155            (verifier_index, proof, public_input)
156        })
157        .collect();
158    let ts_ref: Vec<Context<Pallas, OpeningProof<Pallas>>> = ts
159        .iter()
160        .map(|(verifier_index, proof, public_input)| Context {
161            verifier_index,
162            proof,
163            public_input,
164        })
165        .collect();
166    let group_map = GroupMap::<Fp>::setup();
167
168    batch_verify::<
169        Pallas,
170        DefaultFqSponge<PallasParameters, PlonkSpongeConstantsKimchi>,
171        DefaultFrSponge<Fq, PlonkSpongeConstantsKimchi>,
172        OpeningProof<Pallas>,
173    >(&group_map, &ts_ref)
174    .is_ok()
175}
176
177#[ocaml_gen::func]
178#[ocaml::func]
179pub fn caml_pasta_fq_plonk_proof_dummy() -> CamlProofWithPublic<CamlGPallas, CamlFq> {
180    fn comm() -> PolyComm<Pallas> {
181        let g = Pallas::generator();
182        PolyComm {
183            chunks: vec![g, g, g],
184        }
185    }
186
187    let prev = RecursionChallenge {
188        chals: vec![Fq::one(), Fq::one()],
189        comm: comm(),
190    };
191    let prev_challenges = vec![prev.clone(), prev.clone(), prev];
192
193    let g = Pallas::generator();
194    let proof = OpeningProof {
195        lr: vec![(g, g), (g, g), (g, g)],
196        z1: Fq::one(),
197        z2: Fq::one(),
198        delta: g,
199        sg: g,
200    };
201    let eval = || PointEvaluations {
202        zeta: vec![Fq::one()],
203        zeta_omega: vec![Fq::one()],
204    };
205    let evals = ProofEvaluations {
206        public: Some(eval()),
207        w: core::array::from_fn(|_| eval()),
208        coefficients: core::array::from_fn(|_| eval()),
209        z: eval(),
210        s: core::array::from_fn(|_| eval()),
211        generic_selector: eval(),
212        poseidon_selector: eval(),
213        complete_add_selector: eval(),
214        mul_selector: eval(),
215        emul_selector: eval(),
216        endomul_scalar_selector: eval(),
217        range_check0_selector: None,
218        range_check1_selector: None,
219        foreign_field_add_selector: None,
220        foreign_field_mul_selector: None,
221        xor_selector: None,
222        rot_selector: None,
223        lookup_aggregation: None,
224        lookup_table: None,
225        lookup_sorted: array::from_fn(|_| None),
226        runtime_lookup_table: None,
227        runtime_lookup_table_selector: None,
228        xor_lookup_selector: None,
229        lookup_gate_lookup_selector: None,
230        range_check_lookup_selector: None,
231        foreign_field_mul_lookup_selector: None,
232    };
233
234    let public = vec![Fq::one(), Fq::one()];
235    let dlogproof = ProverProof {
236        commitments: ProverCommitments {
237            w_comm: core::array::from_fn(|_| comm()),
238            z_comm: comm(),
239            t_comm: comm(),
240            lookup: None,
241        },
242        proof,
243        evals,
244        ft_eval1: Fq::one(),
245        prev_challenges,
246    };
247
248    (dlogproof, public).into()
249}
250
251#[ocaml_gen::func]
252#[ocaml::func]
253pub fn caml_pasta_fq_plonk_proof_deep_copy(
254    x: CamlProofWithPublic<CamlGPallas, CamlFq>,
255) -> CamlProofWithPublic<CamlGPallas, CamlFq> {
256    x
257}