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 let public_input = witness[0][0..index.cs.public].to_vec();
81
82 let runtime = unsafe { ocaml::Runtime::recover_handle() };
90
91 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}