1use crate::wasm_vector::WasmVector;
2use ark_ff::{One, Zero};
3use kimchi::{
4 circuits::scalars::RandomOracles, proof::ProverProof,
5 verifier_index::VerifierIndex as DlogVerifierIndex,
6};
7use mina_poseidon::{
8 self,
9 constants::PlonkSpongeConstantsKimchi,
10 sponge::{DefaultFqSponge, DefaultFrSponge},
11 FqSponge,
12};
13use paste::paste;
14use poly_commitment::{
15 commitment::{shift_scalar, PolyComm},
16 ipa::OpeningProof,
17 SRS,
18};
19use wasm_bindgen::prelude::*;
20
21macro_rules! impl_oracles {
30 ($WasmF: ty,
31 $F: ty,
32 $WasmG: ty,
33 $G: ty,
34 $WasmPolyComm: ty,
35 $WasmProverProof: ty,
36 $index: ty,
37 $curve_params: ty,
38 $field_name: ident) => {
39
40 paste! {
41 use wasm_types::FlatVector as WasmFlatVector;
42 use mina_poseidon::sponge::ScalarChallenge;
43
44 #[wasm_bindgen]
45 #[derive(Clone, Copy)]
46 pub struct [<Wasm $field_name:camel RandomOracles>] {
47 pub joint_combiner_chal: Option<$WasmF>,
48 pub joint_combiner: Option<$WasmF>,
49 pub beta: $WasmF,
50 pub gamma: $WasmF,
51 pub alpha_chal: $WasmF,
52 pub alpha: $WasmF,
53 pub zeta: $WasmF,
54 pub v: $WasmF,
55 pub u: $WasmF,
56 pub zeta_chal: $WasmF,
57 pub v_chal: $WasmF,
58 pub u_chal: $WasmF,
59 }
60 type WasmRandomOracles = [<Wasm $field_name:camel RandomOracles>];
61
62 #[wasm_bindgen]
63 impl [<Wasm $field_name:camel RandomOracles>] {
64 #[allow(clippy::too_many_arguments)]
65 #[wasm_bindgen(constructor)]
66 pub fn new(
67 joint_combiner_chal: Option<$WasmF>,
68 joint_combiner: Option<$WasmF>,
69 beta: $WasmF,
70 gamma: $WasmF,
71 alpha_chal: $WasmF,
72 alpha: $WasmF,
73 zeta: $WasmF,
74 v: $WasmF,
75 u: $WasmF,
76 zeta_chal: $WasmF,
77 v_chal: $WasmF,
78 u_chal: $WasmF) -> Self {
79 Self {
80 joint_combiner_chal,
81 joint_combiner,
82 beta,
83 gamma,
84 alpha_chal,
85 alpha,
86 zeta,
87 v,
88 u,
89 zeta_chal,
90 v_chal,
91 u_chal,
92 }
93 }
94 }
95
96 impl From<RandomOracles<$F>> for WasmRandomOracles
97 {
98 fn from(ro: RandomOracles<$F>) -> Self {
99 Self {
100 joint_combiner_chal: ro.joint_combiner.as_ref().map(|x| x.0.0.into()),
101 joint_combiner: ro.joint_combiner.as_ref().map(|x| x.1.into()),
102 beta: ro.beta.into(),
103 gamma: ro.gamma.into(),
104 alpha_chal: ro.alpha_chal.0.into(),
105 alpha: ro.alpha.into(),
106 zeta: ro.zeta.into(),
107 v: ro.v.into(),
108 u: ro.u.into(),
109 zeta_chal: ro.zeta_chal.0.into(),
110 v_chal: ro.v_chal.0.into(),
111 u_chal: ro.u_chal.0.into(),
112 }
113 }
114 }
115
116 impl From<WasmRandomOracles> for RandomOracles<$F>
117 {
118 fn from(ro: WasmRandomOracles) -> Self {
119 Self {
120 joint_combiner: ro.joint_combiner_chal.and_then(|x| {
121 ro.joint_combiner.map(|y| (ScalarChallenge(x.into()), y.into()))
122 }),
123 beta: ro.beta.into(),
124 gamma: ro.gamma.into(),
125 alpha_chal: ScalarChallenge(ro.alpha_chal.into()),
126 alpha: ro.alpha.into(),
127 zeta: ro.zeta.into(),
128 v: ro.v.into(),
129 u: ro.u.into(),
130 zeta_chal: ScalarChallenge(ro.zeta_chal.into()),
131 v_chal: ScalarChallenge(ro.v_chal.into()),
132 u_chal: ScalarChallenge(ro.u_chal.into()),
133 }
134 }
135 }
136
137 #[wasm_bindgen]
138 #[derive(Clone)]
139 pub struct [<Wasm $field_name:camel Oracles>] {
140 pub o: [<Wasm $field_name:camel RandomOracles>],
141 pub p_eval0: $WasmF,
142 pub p_eval1: $WasmF,
143 #[wasm_bindgen(skip)]
144 pub opening_prechallenges: WasmFlatVector<$WasmF>,
145 pub digest_before_evaluations: $WasmF,
146 }
147
148 #[wasm_bindgen]
149 impl [<Wasm $field_name:camel Oracles>] {
150 #[wasm_bindgen(constructor)]
151 pub fn new(
152 o: WasmRandomOracles,
153 p_eval0: $WasmF,
154 p_eval1: $WasmF,
155 opening_prechallenges: WasmFlatVector<$WasmF>,
156 digest_before_evaluations: $WasmF) -> Self {
157 Self {o, p_eval0, p_eval1, opening_prechallenges, digest_before_evaluations}
158 }
159
160 #[wasm_bindgen(getter)]
161 pub fn opening_prechallenges(&self) -> WasmFlatVector<$WasmF> {
162 self.opening_prechallenges.clone()
163 }
164
165 #[wasm_bindgen(setter)]
166 pub fn set_opening_prechallenges(&mut self, x: WasmFlatVector<$WasmF>) {
167 self.opening_prechallenges = x;
168 }
169 }
170
171 #[wasm_bindgen]
172 pub fn [<$F:snake _oracles_create>](
173 lgr_comm: WasmVector<$WasmPolyComm>, index: $index, proof: $WasmProverProof, ) -> Result<[<Wasm $field_name:camel Oracles>], JsError> {
177 let result = crate::rayon::run_in_pool(|| {
179 let index: DlogVerifierIndex<$G, OpeningProof<$G>> = index.into();
180
181 let lgr_comm: Vec<PolyComm<$G>> = lgr_comm
182 .into_iter()
183 .take(proof.public.len())
184 .map(Into::into)
185 .collect();
186 let lgr_comm_refs: Vec<_> = lgr_comm.iter().collect();
187
188 let p_comm = PolyComm::<$G>::multi_scalar_mul(
189 &lgr_comm_refs,
190 &proof
191 .public
192 .iter()
193 .map(|a| a.clone().into())
194 .map(|s: $F| -s)
195 .collect::<Vec<_>>(),
196 );
197 let p_comm = {
198 index
199 .srs()
200 .mask_custom(
201 p_comm.clone(),
202 &p_comm.map(|_| $F::one()),
203 )
204 .unwrap()
205 .commitment
206 };
207
208 let (proof, public_input): (ProverProof<$G, OpeningProof<$G>>, Vec<$F>) = proof.into();
209
210 let oracles_result =
211 proof.oracles::<
212 DefaultFqSponge<$curve_params, PlonkSpongeConstantsKimchi>,
213 DefaultFrSponge<$F, PlonkSpongeConstantsKimchi>
214 >(&index, &p_comm, Some(&public_input));
215 let oracles_result = match oracles_result {
216 Err(e) => {
217 return Err(format!("oracles_create: {}", e));
218 }
219 Ok(cs) => cs,
220 };
221
222 let (mut sponge, combined_inner_product, p_eval, digest, oracles) = (
223 oracles_result.fq_sponge,
224 oracles_result.combined_inner_product,
225 oracles_result.public_evals,
226 oracles_result.digest,
227 oracles_result.oracles,
228 );
229
230 sponge.absorb_fr(&[shift_scalar::<$G>(combined_inner_product)]);
231
232 let opening_prechallenges = proof
233 .proof
234 .prechallenges(&mut sponge)
235 .into_iter()
236 .map(|x| x.0.into())
237 .collect();
238
239 Ok((oracles, p_eval, opening_prechallenges, digest))
240 });
241
242 match result {
243 Ok((oracles, p_eval, opening_prechallenges, digest)) => Ok([<Wasm $field_name:camel Oracles>] {
244 o: oracles.into(),
245 p_eval0: p_eval[0][0].into(),
246 p_eval1: p_eval[1][0].into(),
247 opening_prechallenges,
248 digest_before_evaluations: digest.into()
249 }),
250 Err(err) => Err(JsError::new(&err))
251 }
252 }
253
254 #[wasm_bindgen]
255 pub fn [<$F:snake _oracles_dummy>]() -> [<Wasm $field_name:camel Oracles>] {
256 [<Wasm $field_name:camel Oracles>] {
257 o: RandomOracles::<$F>::default().into(),
258 p_eval0: $F::zero().into(),
259 p_eval1: $F::zero().into(),
260 opening_prechallenges: vec![].into(),
261 digest_before_evaluations: $F::zero().into(),
262 }
263 }
264
265 #[wasm_bindgen]
266 pub fn [<$F:snake _oracles_deep_copy>](
267 x: $WasmProverProof,
268 ) -> $WasmProverProof {
269 x
270 }
271 }
272 }
273}
274
275pub mod fp {
280 use super::*;
281 use crate::{
282 plonk_proof::fp::WasmFpProverProof as WasmProverProof,
283 plonk_verifier_index::fp::WasmFpPlonkVerifierIndex as WasmPlonkVerifierIndex,
284 poly_comm::vesta::WasmFpPolyComm as WasmPolyComm,
285 };
286 use arkworks::WasmPastaFp;
287 use mina_curves::pasta::{Fp, Vesta as GAffine, VestaParameters};
288
289 impl_oracles!(
290 WasmPastaFp,
291 Fp,
292 WasmGVesta,
293 GAffine,
294 WasmPolyComm,
295 WasmProverProof,
296 WasmPlonkVerifierIndex,
297 VestaParameters,
298 Fp
299 );
300}
301
302pub mod fq {
303 use super::*;
304 use crate::{
305 plonk_proof::fq::WasmFqProverProof as WasmProverProof,
306 plonk_verifier_index::fq::WasmFqPlonkVerifierIndex as WasmPlonkVerifierIndex,
307 poly_comm::pallas::WasmFqPolyComm as WasmPolyComm,
308 };
309 use arkworks::WasmPastaFq;
310 use mina_curves::pasta::{Fq, Pallas as GAffine, PallasParameters};
311
312 impl_oracles!(
313 WasmPastaFq,
314 Fq,
315 WasmGPallas,
316 GAffine,
317 WasmPolyComm,
318 WasmProverProof,
319 WasmPlonkVerifierIndex,
320 PallasParameters,
321 Fq
322 );
323}