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