Skip to main content

kimchi_stubs/
oracles.rs

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: (Vec<F>, Vec<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.inner().into())
96                    .collect();
97
98                let [pe0, pe1] = p_eval;
99                Ok(CamlOracles {
100                    o: oracles.into(),
101                    p_eval: (
102                        pe0.into_iter().map(Into::into).collect(),
103                        pe1.into_iter().map(Into::into).collect(),
104                    ),
105                    opening_prechallenges,
106                    digest_before_evaluations: digest.into(),
107                })
108            }
109
110            #[ocaml_gen::func]
111            #[ocaml::func]
112            pub fn [<$F:snake _oracles_create_no_public>](
113                lgr_comm: Vec<CamlPolyComm<$CamlG>>,
114                index: $index,
115                proof: CamlProverProof<$CamlG, $CamlF>,
116            ) -> Result<CamlOracles<$CamlF>, ocaml::Error> {
117                let proof = CamlProofWithPublic {
118                    proof,
119                    public_evals: None,
120                };
121
122                let index: VerifierIndex<FULL_ROUNDS, $G, <OpeningProof<$G,FULL_ROUNDS> as poly_commitment::OpenProof<$G, FULL_ROUNDS>>::SRS> = index.into();
123
124                let lgr_comm: Vec<PolyComm<$G>> = lgr_comm
125                    .into_iter()
126                    .take(proof.proof.public.len())
127                    .map(Into::into)
128                    .collect();
129                let lgr_comm_refs: Vec<_> = lgr_comm.iter().collect();
130
131                let p_comm = PolyComm::<$G>::multi_scalar_mul(
132                    &lgr_comm_refs,
133                    &proof
134                        .proof
135                        .public
136                        .iter()
137                        .map(Into::<$F>::into)
138                        .map(|s| -s)
139                        .collect::<Vec<_>>(),
140                );
141
142                let p_comm = {
143                    index
144                        .srs()
145                        .mask_custom(
146                            p_comm.clone(),
147                            &p_comm.map(|_| $F::one()),
148                        )
149                        .unwrap()
150                        .commitment
151                };
152
153                let (proof, public_input): (ProverProof<$G, OpeningProof<$G, FULL_ROUNDS>, FULL_ROUNDS>, Vec<$F>) = proof.into();
154
155                let oracles_result =
156                    proof.oracles::<
157                        DefaultFqSponge<$curve_params, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
158                        DefaultFrSponge<$F, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
159                        _,
160                    >(&index, &p_comm, Some(&public_input))?;
161
162                let (mut sponge, combined_inner_product, p_eval, digest, oracles) = (
163                    oracles_result.fq_sponge,
164                    oracles_result.combined_inner_product,
165                    oracles_result.public_evals,
166                    oracles_result.digest,
167                    oracles_result.oracles,
168                );
169
170                sponge.absorb_fr(&[shift_scalar::<$G>(combined_inner_product)]);
171
172                let opening_prechallenges = proof
173                    .proof
174                    .prechallenges(&mut sponge)
175                    .into_iter()
176                    .map(|x| x.inner().into())
177                    .collect();
178
179                let [pe0, pe1] = p_eval;
180                Ok(CamlOracles {
181                    o: oracles.into(),
182                    p_eval: (
183                        pe0.into_iter().map(Into::into).collect(),
184                        pe1.into_iter().map(Into::into).collect(),
185                    ),
186                    opening_prechallenges,
187                    digest_before_evaluations: digest.into(),
188                })
189            }
190
191            #[ocaml_gen::func]
192            #[ocaml::func]
193            pub fn [<$F:snake _oracles_dummy>]() -> CamlRandomOracles<$CamlF> {
194                RandomOracles::<$F>::default().into()
195            }
196
197            #[ocaml_gen::func]
198            #[ocaml::func]
199            pub fn [<$F:snake _oracles_deep_copy>](
200                x: CamlRandomOracles<$CamlF>,
201            ) -> CamlRandomOracles<$CamlF> {
202                x
203            }
204        }
205    }
206}
207
208pub mod fp {
209    use super::*;
210    use crate::arkworks::{CamlFp, CamlGVesta};
211    use mina_curves::pasta::{Fp, Vesta, VestaParameters};
212
213    impl_oracles!(
214        CamlFp,
215        Fp,
216        CamlGVesta,
217        Vesta,
218        CamlPastaFpPlonkVerifierIndex,
219        VestaParameters
220    );
221}
222
223pub mod fq {
224    use super::*;
225    use crate::{
226        arkworks::{CamlFq, CamlGPallas},
227        oracles::CamlOracles,
228        pasta_fq_plonk_verifier_index::CamlPastaFqPlonkVerifierIndex,
229    };
230    use mina_curves::pasta::{Fq, Pallas, PallasParameters};
231
232    impl_oracles!(
233        CamlFq,
234        Fq,
235        CamlGPallas,
236        Pallas,
237        CamlPastaFqPlonkVerifierIndex,
238        PallasParameters
239    );
240}