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 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 let runtime = unsafe { ocaml::Runtime::recover_handle() };
94
95 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}