1use crate::pasta_fp_plonk_verifier_index::CamlPastaFpPlonkVerifierIndex;
2use ark_ff::One;
3use kimchi::{
4 circuits::scalars::{caml::CamlRandomOracles, RandomOracles},
5 proof::ProverProof,
6 prover::caml::{CamlProofWithPublic, CamlProverProof},
7 verifier_index::VerifierIndex,
8};
9use mina_poseidon::{
10 self,
11 constants::PlonkSpongeConstantsKimchi,
12 sponge::{DefaultFqSponge, DefaultFrSponge},
13 FqSponge,
14};
15use paste::paste;
16use poly_commitment::{
17 commitment::{caml::CamlPolyComm, shift_scalar, PolyComm},
18 ipa::OpeningProof,
19 SRS,
20};
21
22#[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
23pub struct CamlOracles<F> {
24 pub o: CamlRandomOracles<F>,
25 pub p_eval: (F, F),
26 pub opening_prechallenges: Vec<F>,
27 pub digest_before_evaluations: F,
28}
29
30macro_rules! impl_oracles {
31 ($CamlF: ty, $F: ty, $CamlG: ty, $G: ty, $index: ty, $curve_params: ty) => {
32 paste! {
33 #[ocaml_gen::func]
34 #[ocaml::func]
35 pub fn [<$F:snake _oracles_create>](
36 lgr_comm: Vec<CamlPolyComm<$CamlG>>,
37 index: $index,
38 proof: CamlProofWithPublic<$CamlG, $CamlF>,
39 ) -> Result<CamlOracles<$CamlF>, ocaml::Error> {
40 let index: VerifierIndex<$G, OpeningProof<$G>> = index.into();
41
42 let lgr_comm: Vec<PolyComm<$G>> = lgr_comm
43 .into_iter()
44 .take(proof.proof.public.len())
45 .map(Into::into)
46 .collect();
47 let lgr_comm_refs: Vec<_> = lgr_comm.iter().collect();
48
49 let p_comm = PolyComm::<$G>::multi_scalar_mul(
50 &lgr_comm_refs,
51 &proof
52 .proof
53 .public
54 .iter()
55 .map(Into::<$F>::into)
56 .map(|s| -s)
57 .collect::<Vec<_>>(),
58 );
59
60 let p_comm = {
61 index
62 .srs()
63 .mask_custom(
64 p_comm.clone(),
65 &p_comm.map(|_| $F::one()),
66 )
67 .unwrap()
68 .commitment
69 };
70
71 let (proof, public_input): (ProverProof<$G, OpeningProof<$G>>, Vec<$F>) = proof.into();
72
73 let oracles_result =
74 proof.oracles::<
75 DefaultFqSponge<$curve_params, PlonkSpongeConstantsKimchi>,
76 DefaultFrSponge<$F, PlonkSpongeConstantsKimchi>,
77 >(&index, &p_comm, Some(&public_input))?;
78
79 let (mut sponge, combined_inner_product, p_eval, digest, oracles) = (
80 oracles_result.fq_sponge,
81 oracles_result.combined_inner_product,
82 oracles_result.public_evals,
83 oracles_result.digest,
84 oracles_result.oracles,
85 );
86
87 sponge.absorb_fr(&[shift_scalar::<$G>(combined_inner_product)]);
88
89 let opening_prechallenges = proof
90 .proof
91 .prechallenges(&mut sponge)
92 .into_iter()
93 .map(|x| x.0.into())
94 .collect();
95
96 Ok(CamlOracles {
97 o: oracles.into(),
98 p_eval: (p_eval[0][0].into(), p_eval[1][0].into()),
99 opening_prechallenges,
100 digest_before_evaluations: digest.into(),
101 })
102 }
103
104 #[ocaml_gen::func]
105 #[ocaml::func]
106 pub fn [<$F:snake _oracles_create_no_public>](
107 lgr_comm: Vec<CamlPolyComm<$CamlG>>,
108 index: $index,
109 proof: CamlProverProof<$CamlG, $CamlF>,
110 ) -> Result<CamlOracles<$CamlF>, ocaml::Error> {
111 let proof = CamlProofWithPublic {
112 proof,
113 public_evals: None,
114 };
115
116 let index: VerifierIndex<$G, OpeningProof<$G>> = index.into();
117
118 let lgr_comm: Vec<PolyComm<$G>> = lgr_comm
119 .into_iter()
120 .take(proof.proof.public.len())
121 .map(Into::into)
122 .collect();
123 let lgr_comm_refs: Vec<_> = lgr_comm.iter().collect();
124
125 let p_comm = PolyComm::<$G>::multi_scalar_mul(
126 &lgr_comm_refs,
127 &proof
128 .proof
129 .public
130 .iter()
131 .map(Into::<$F>::into)
132 .map(|s| -s)
133 .collect::<Vec<_>>(),
134 );
135
136 let p_comm = {
137 index
138 .srs()
139 .mask_custom(
140 p_comm.clone(),
141 &p_comm.map(|_| $F::one()),
142 )
143 .unwrap()
144 .commitment
145 };
146
147 let (proof, public_input): (ProverProof<$G, OpeningProof<$G>>, Vec<$F>) = proof.into();
148
149 let oracles_result =
150 proof.oracles::<
151 DefaultFqSponge<$curve_params, PlonkSpongeConstantsKimchi>,
152 DefaultFrSponge<$F, PlonkSpongeConstantsKimchi>,
153 >(&index, &p_comm, Some(&public_input))?;
154
155 let (mut sponge, combined_inner_product, p_eval, digest, oracles) = (
156 oracles_result.fq_sponge,
157 oracles_result.combined_inner_product,
158 oracles_result.public_evals,
159 oracles_result.digest,
160 oracles_result.oracles,
161 );
162
163 sponge.absorb_fr(&[shift_scalar::<$G>(combined_inner_product)]);
164
165 let opening_prechallenges = proof
166 .proof
167 .prechallenges(&mut sponge)
168 .into_iter()
169 .map(|x| x.0.into())
170 .collect();
171
172 Ok(CamlOracles {
173 o: oracles.into(),
174 p_eval: (p_eval[0][0].into(), p_eval[1][0].into()),
175 opening_prechallenges,
176 digest_before_evaluations: digest.into(),
177 })
178 }
179
180 #[ocaml_gen::func]
181 #[ocaml::func]
182 pub fn [<$F:snake _oracles_dummy>]() -> CamlRandomOracles<$CamlF> {
183 RandomOracles::<$F>::default().into()
184 }
185
186 #[ocaml_gen::func]
187 #[ocaml::func]
188 pub fn [<$F:snake _oracles_deep_copy>](
189 x: CamlRandomOracles<$CamlF>,
190 ) -> CamlRandomOracles<$CamlF> {
191 x
192 }
193 }
194 }
195}
196
197pub mod fp {
198 use super::*;
199 use crate::arkworks::{CamlFp, CamlGVesta};
200 use mina_curves::pasta::{Fp, Vesta, VestaParameters};
201
202 impl_oracles!(
203 CamlFp,
204 Fp,
205 CamlGVesta,
206 Vesta,
207 CamlPastaFpPlonkVerifierIndex,
208 VestaParameters
209 );
210}
211
212pub mod fq {
213 use super::*;
214 use crate::{
215 arkworks::{CamlFq, CamlGPallas},
216 oracles::CamlOracles,
217 pasta_fq_plonk_verifier_index::CamlPastaFqPlonkVerifierIndex,
218 };
219 use mina_curves::pasta::{Fq, Pallas, PallasParameters};
220
221 impl_oracles!(
222 CamlFq,
223 Fq,
224 CamlGPallas,
225 Pallas,
226 CamlPastaFqPlonkVerifierIndex,
227 PallasParameters
228 );
229}