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