1use crate::vector::{fp::NapiVecVecFp, fq::NapiVecVecFq, NapiFlatVector, NapiVector};
2use ark_ec::AffineRepr;
3use ark_ff::One;
4use core::array;
5use kimchi::{
6 circuits::{
7 lookup::runtime_tables::RuntimeTable,
8 wires::{COLUMNS, PERMUTS},
9 },
10 groupmap::GroupMap,
11 proof::{
12 LookupCommitments, PointEvaluations, ProofEvaluations, ProverCommitments, ProverProof,
13 RecursionChallenge,
14 },
15 prover_index::ProverIndex,
16 verifier::{batch_verify, Context},
17};
18use mina_poseidon::{
19 constants::PlonkSpongeConstantsKimchi,
20 pasta::FULL_ROUNDS,
21 sponge::{DefaultFqSponge, DefaultFrSponge},
22};
23use napi::{
24 bindgen_prelude::{sys, ClassInstance, External, FromNapiValue, Result},
25 Error as NapiError, Status,
26};
27use napi_derive::napi;
28use paste::paste;
29use poly_commitment::commitment::CommitmentCurve; use poly_commitment::{
31 ipa::{OpeningProof, SRS as IPA_SRS},
32 PolyComm, SRS as _,
33};
34
35macro_rules! impl_proof {
36 (
37 $NapiG: ty,
38 $G: ty,
39 $NapiF: ty,
40 $F: ty,
41 $NapiPolyComm: ty,
42 $NapiSrs: ty,
43 $NapiIndex: ty,
44 $NapiVerifierIndex: ty,
45 $NapiVecVec: ty,
46 $field_name: ident,
47 $NapiRuntimeTable: ty,
48 ) => {
49 paste! {
50 #[napi(object, js_name = [<Wasm $field_name:camel PointEvaluations>])]
53 #[derive(Clone)]
54 pub struct [<Napi $field_name:camel PointEvaluations>] {
55 pub zeta: NapiVector<$NapiF>,
56 pub zeta_omega: NapiVector<$NapiF>,
57 }
58
59 type NapiPointEvaluations = [<Napi $field_name:camel PointEvaluations>];
60
61 impl From<&PointEvaluations<Vec<$F>>> for NapiPointEvaluations {
62 fn from(x: &PointEvaluations<Vec<$F>>) -> Self {
63 let zeta: Vec<$NapiF> = x.zeta.iter().cloned().map(Into::into).collect();
64 let zeta_omega: Vec<$NapiF> = x
65 .zeta_omega
66 .iter()
67 .cloned()
68 .map(Into::into)
69 .collect();
70 Self {
71 zeta: zeta.into(),
72 zeta_omega: zeta_omega.into(),
73 }
74 }
75 }
76
77 #[napi(object, js_name = [<Wasm $field_name:camel ProofEvaluationsObject>])]
78 #[derive(Clone)]
79 pub struct [<Napi $field_name:camel ProofEvaluationsObject>] {
80 pub public: Option<NapiPointEvaluations>,
81 pub w: NapiVector<NapiPointEvaluations>,
82 pub z: NapiPointEvaluations,
83 pub s: NapiVector<NapiPointEvaluations>,
84 pub coefficients: NapiVector<NapiPointEvaluations>,
85 pub generic_selector: NapiPointEvaluations,
86 pub poseidon_selector: NapiPointEvaluations,
87 pub complete_add_selector: NapiPointEvaluations,
88 pub mul_selector: NapiPointEvaluations,
89 pub emul_selector: NapiPointEvaluations,
90 pub endomul_scalar_selector: NapiPointEvaluations,
91 pub range_check0_selector: Option<NapiPointEvaluations>,
92 pub range_check1_selector: Option<NapiPointEvaluations>,
93 pub foreign_field_add_selector: Option<NapiPointEvaluations>,
94 pub foreign_field_mul_selector: Option<NapiPointEvaluations>,
95 pub xor_selector: Option<NapiPointEvaluations>,
96 pub rot_selector: Option<NapiPointEvaluations>,
97 pub lookup_aggregation: Option<NapiPointEvaluations>,
98 pub lookup_table: Option<NapiPointEvaluations>,
99 pub lookup_sorted: NapiVector<Option<NapiPointEvaluations>>,
100 pub runtime_lookup_table: Option<NapiPointEvaluations>,
101 pub runtime_lookup_table_selector: Option<NapiPointEvaluations>,
102 pub xor_lookup_selector: Option<NapiPointEvaluations>,
103 pub lookup_gate_lookup_selector: Option<NapiPointEvaluations>,
104 pub range_check_lookup_selector: Option<NapiPointEvaluations>,
105 pub foreign_field_mul_lookup_selector: Option<NapiPointEvaluations>,
106 }
107
108 pub type [<Napi $field_name:camel ProofEvaluations>] = [<Napi $field_name:camel ProofEvaluationsObject>];
110 type NapiProofEvaluations = [<Napi $field_name:camel ProofEvaluations>];
111
112 fn [<point_evals_from_napi_ $field_name:snake>](
114 evals: NapiPointEvaluations,
115 ) -> PointEvaluations<Vec<$F>> {
116 PointEvaluations {
117 zeta: evals.zeta.into_iter().map(Into::into).collect(),
118 zeta_omega: evals.zeta_omega.into_iter().map(Into::into).collect(),
119 }
120 }
121
122 fn [<point_evals_into_napi_ $field_name:snake>](
123 evals: &PointEvaluations<Vec<$F>>,
124 ) -> NapiPointEvaluations {
125 evals.into()
126 }
127
128 fn [<proof_evals_from_napi_object_ $field_name:snake>](
129 x: NapiProofEvaluations,
130 ) -> std::result::Result<ProofEvaluations<PointEvaluations<Vec<$F>>>, NapiError> {
131 fn invalid_len(name: &str, expected: usize, got: usize) -> NapiError {
132 NapiError::new(
133 Status::InvalidArg,
134 format!("{name}: expected length {expected}, got {got}"),
135 )
136 }
137
138 let w_vec: Vec<_> = x
139 .w
140 .into_iter()
141 .map([<point_evals_from_napi_ $field_name:snake>])
142 .collect();
143 let w_len = w_vec.len();
144 let w: [PointEvaluations<Vec<$F>>; COLUMNS] = w_vec
145 .try_into()
146 .map_err(|_| invalid_len("evals.w", COLUMNS, w_len))?;
147
148 let s_expected = PERMUTS - 1;
149 let s_vec: Vec<_> = x
150 .s
151 .into_iter()
152 .map([<point_evals_from_napi_ $field_name:snake>])
153 .collect();
154 let s_len = s_vec.len();
155 let s: [PointEvaluations<Vec<$F>>; PERMUTS - 1] = s_vec
156 .try_into()
157 .map_err(|_| invalid_len("evals.s", s_expected, s_len))?;
158
159 let coeffs_vec: Vec<_> = x
160 .coefficients
161 .into_iter()
162 .map([<point_evals_from_napi_ $field_name:snake>])
163 .collect();
164 let coeffs_len = coeffs_vec.len();
165 let coefficients: [PointEvaluations<Vec<$F>>; COLUMNS] = coeffs_vec
166 .try_into()
167 .map_err(|_| invalid_len("evals.coefficients", COLUMNS, coeffs_len))?;
168
169 let lookup_sorted_vec: Vec<_> = x
170 .lookup_sorted
171 .into_iter()
172 .map(|v| v.map([<point_evals_from_napi_ $field_name:snake>]))
173 .collect();
174 let lookup_sorted_len = lookup_sorted_vec.len();
175 let lookup_sorted: [Option<PointEvaluations<Vec<$F>>>; 5] = lookup_sorted_vec
176 .try_into()
177 .map_err(|_| invalid_len("evals.lookup_sorted", 5, lookup_sorted_len))?;
178
179 Ok(ProofEvaluations {
180 public: x.public.map([<point_evals_from_napi_ $field_name:snake>]),
181 w,
182 z: [<point_evals_from_napi_ $field_name:snake>](x.z),
183 s,
184 coefficients,
185 generic_selector: [<point_evals_from_napi_ $field_name:snake>](x.generic_selector),
186 poseidon_selector: [<point_evals_from_napi_ $field_name:snake>](x.poseidon_selector),
187 complete_add_selector: [<point_evals_from_napi_ $field_name:snake>](x.complete_add_selector),
188 mul_selector: [<point_evals_from_napi_ $field_name:snake>](x.mul_selector),
189 emul_selector: [<point_evals_from_napi_ $field_name:snake>](x.emul_selector),
190 endomul_scalar_selector: [<point_evals_from_napi_ $field_name:snake>](x.endomul_scalar_selector),
191 range_check0_selector: x.range_check0_selector.map([<point_evals_from_napi_ $field_name:snake>]),
192 range_check1_selector: x.range_check1_selector.map([<point_evals_from_napi_ $field_name:snake>]),
193 foreign_field_add_selector: x.foreign_field_add_selector.map([<point_evals_from_napi_ $field_name:snake>]),
194 foreign_field_mul_selector: x.foreign_field_mul_selector.map([<point_evals_from_napi_ $field_name:snake>]),
195 xor_selector: x.xor_selector.map([<point_evals_from_napi_ $field_name:snake>]),
196 rot_selector: x.rot_selector.map([<point_evals_from_napi_ $field_name:snake>]),
197 lookup_aggregation: x.lookup_aggregation.map([<point_evals_from_napi_ $field_name:snake>]),
198 lookup_table: x.lookup_table.map([<point_evals_from_napi_ $field_name:snake>]),
199 lookup_sorted,
200 runtime_lookup_table: x.runtime_lookup_table.map([<point_evals_from_napi_ $field_name:snake>]),
201 runtime_lookup_table_selector: x.runtime_lookup_table_selector.map([<point_evals_from_napi_ $field_name:snake>]),
202 xor_lookup_selector: x.xor_lookup_selector.map([<point_evals_from_napi_ $field_name:snake>]),
203 lookup_gate_lookup_selector: x.lookup_gate_lookup_selector.map([<point_evals_from_napi_ $field_name:snake>]),
204 range_check_lookup_selector: x.range_check_lookup_selector.map([<point_evals_from_napi_ $field_name:snake>]),
205 foreign_field_mul_lookup_selector: x.foreign_field_mul_lookup_selector.map([<point_evals_from_napi_ $field_name:snake>]),
206 })
207 }
208
209 impl From<NapiProofEvaluations> for ProofEvaluations<PointEvaluations<Vec<$F>>> {
210 fn from(x: NapiProofEvaluations) -> Self {
211 [<proof_evals_from_napi_object_ $field_name:snake>](x)
212 .expect("invalid proof evaluations shape")
213 }
214 }
215
216 impl From<ProofEvaluations<PointEvaluations<Vec<$F>>>> for NapiProofEvaluations {
217 fn from(x: ProofEvaluations<PointEvaluations<Vec<$F>>>) -> Self {
218 [<Napi $field_name:camel ProofEvaluationsObject>] {
219 public: x.public.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
220 w: x.w.iter().map([<point_evals_into_napi_ $field_name:snake>]).collect(),
221 z: (&x.z).into(),
222 s: x.s.iter().map([<point_evals_into_napi_ $field_name:snake>]).collect(),
223 coefficients: x.coefficients.iter().map([<point_evals_into_napi_ $field_name:snake>]).collect(),
224 generic_selector: (&x.generic_selector).into(),
225 poseidon_selector: (&x.poseidon_selector).into(),
226 complete_add_selector: (&x.complete_add_selector).into(),
227 mul_selector: (&x.mul_selector).into(),
228 emul_selector: (&x.emul_selector).into(),
229 endomul_scalar_selector: (&x.endomul_scalar_selector).into(),
230 range_check0_selector: x.range_check0_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
231 range_check1_selector: x.range_check1_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
232 foreign_field_add_selector: x.foreign_field_add_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
233 foreign_field_mul_selector: x.foreign_field_mul_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
234 xor_selector: x.xor_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
235 rot_selector: x.rot_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
236 lookup_aggregation: x.lookup_aggregation.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
237 lookup_table: x.lookup_table.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
238 lookup_sorted: x
239 .lookup_sorted
240 .iter()
241 .map(|v| v.as_ref().map([<point_evals_into_napi_ $field_name:snake>]))
242 .collect(),
243 runtime_lookup_table: x.runtime_lookup_table.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
244 runtime_lookup_table_selector: x.runtime_lookup_table_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
245 xor_lookup_selector: x.xor_lookup_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
246 lookup_gate_lookup_selector: x.lookup_gate_lookup_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
247 range_check_lookup_selector: x.range_check_lookup_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
248 foreign_field_mul_lookup_selector: x.foreign_field_mul_lookup_selector.as_ref().map([<point_evals_into_napi_ $field_name:snake>]),
249 }
250 }
251 }
252
253 #[napi(js_name = [<Wasm $field_name:camel LookupCommitments>])]
254 #[derive(Clone)]
255 pub struct [<Napi $field_name:camel LookupCommitments>]
256 {
257 #[napi(skip)]
258 pub sorted: NapiVector<$NapiPolyComm>,
259 #[napi(skip)]
260 pub aggreg: $NapiPolyComm,
261 #[napi(skip)]
262 pub runtime: Option<$NapiPolyComm>,
263 }
264
265 type NapiLookupCommitments = [<Napi $field_name:camel LookupCommitments>];
266
267 #[napi]
268 impl [<Napi $field_name:camel LookupCommitments>] {
269 #[napi(constructor)]
270 pub fn new(
271 sorted: NapiVector<$NapiPolyComm>,
272 aggreg: $NapiPolyComm,
273 runtime: Option<$NapiPolyComm>) -> Self {
274 NapiLookupCommitments { sorted, aggreg, runtime }
275 }
276
277 #[napi(getter)]
278 pub fn sorted(&self) -> NapiVector<$NapiPolyComm> {
279 self.sorted.clone()
280 }
281
282 #[napi(getter)]
283 pub fn aggreg(&self) -> $NapiPolyComm {
284 self.aggreg.clone()
285 }
286
287 #[napi(getter)]
288 pub fn runtime(&self) -> Option<$NapiPolyComm> {
289 self.runtime.clone()
290 }
291
292 #[napi(setter, js_name="set_sorted")]
293 pub fn set_sorted(&mut self, s: NapiVector<$NapiPolyComm>) {
294 self.sorted = s
295 }
296
297 #[napi(setter, js_name="set_aggreg")]
298 pub fn set_aggreg(&mut self, a: $NapiPolyComm) {
299 self.aggreg = a
300 }
301
302 #[napi(setter, js_name="set_runtime")]
303 pub fn set_runtime(&mut self, r: Option<$NapiPolyComm>) {
304 self.runtime = r
305 }
306 }
307
308 impl From<LookupCommitments<$G>> for NapiLookupCommitments {
309 fn from(x: LookupCommitments<$G>) -> Self {
310 NapiLookupCommitments {
311 sorted: x.sorted.into_iter().map(Into::into).collect(),
312 aggreg: x.aggreg.into(),
313 runtime: x.runtime.map(Into::into)
314 }
315 }
316 }
317
318 impl From<NapiLookupCommitments> for LookupCommitments<$G> {
319 fn from(x: NapiLookupCommitments) -> Self {
320 LookupCommitments {
321 sorted: x.sorted.into_iter().map(Into::into).collect(),
322 aggreg: x.aggreg.into(),
323 runtime: x.runtime.map(Into::into)
324 }
325 }
326 }
327
328 impl FromNapiValue for [<Napi $field_name:camel LookupCommitments>] {
329 unsafe fn from_napi_value(
330 env: sys::napi_env,
331 napi_val: sys::napi_value,
332 ) -> Result<Self> {
333 let instance = <ClassInstance<[<Napi $field_name:camel LookupCommitments>]> as FromNapiValue>::from_napi_value(env, napi_val)?;
334 Ok((*instance).clone())
335 }
336 }
337
338 #[napi(js_name = [<Wasm $field_name:camel ProverCommitments>])]
339 #[derive(Clone)]
340 pub struct [<Napi $field_name:camel ProverCommitments>]
341 {
342 #[napi(skip)]
343 pub w_comm: NapiVector<$NapiPolyComm>,
344 #[napi(skip)]
345 pub z_comm: $NapiPolyComm,
346 #[napi(skip)]
347 pub t_comm: $NapiPolyComm,
348 #[napi(skip)]
349 pub lookup: Option<NapiLookupCommitments>,
350 }
351
352 type NapiProverCommitments = [<Napi $field_name:camel ProverCommitments>];
353
354 #[napi]
355 impl [<Napi $field_name:camel ProverCommitments>] {
356 #[napi(constructor)]
357 pub fn new(
358 w_comm: NapiVector<$NapiPolyComm>,
359 z_comm: $NapiPolyComm,
360 t_comm: $NapiPolyComm,
361 lookup: Option<NapiLookupCommitments>
362 ) -> Self {
363 NapiProverCommitments { w_comm, z_comm, t_comm, lookup }
364 }
365
366 #[napi(getter, js_name="w_comm")]
367 pub fn w_comm(&self) -> NapiVector<$NapiPolyComm> {
368 self.w_comm.clone()
369 }
370 #[napi(getter, js_name="z_comm")]
371 pub fn z_comm(&self) -> $NapiPolyComm {
372 self.z_comm.clone()
373 }
374 #[napi(getter, js_name="t_comm")]
375 pub fn t_comm(&self) -> $NapiPolyComm {
376 self.t_comm.clone()
377 }
378
379 #[napi(getter)]
380 pub fn lookup(&self) -> Option<NapiLookupCommitments> {
381 self.lookup.clone()
382 }
383
384 #[napi(setter, js_name="set_w_comm")]
385 pub fn set_w_comm(&mut self, x: NapiVector<$NapiPolyComm>) {
386 self.w_comm = x
387 }
388 #[napi(setter, js_name="set_z_comm")]
389 pub fn set_z_comm(&mut self, x: $NapiPolyComm) {
390 self.z_comm = x
391 }
392 #[napi(setter, js_name="set_t_comm")]
393 pub fn set_t_comm(&mut self, x: $NapiPolyComm) {
394 self.t_comm = x
395 }
396
397 #[napi(setter, js_name="set_lookup")]
398 pub fn set_lookup(&mut self, l: Option<NapiLookupCommitments>) {
399 self.lookup = l
400 }
401 }
402
403 impl From<ProverCommitments<$G>> for NapiProverCommitments {
404 fn from(x: ProverCommitments<$G>) -> Self {
405 NapiProverCommitments {
406 w_comm: x.w_comm.iter().map(Into::into).collect(),
407 z_comm: x.z_comm.into(),
408 t_comm: x.t_comm.into(),
409 lookup: x.lookup.map(Into::into),
410 }
411 }
412 }
413
414 impl From<NapiProverCommitments> for ProverCommitments<$G> {
415 fn from(x: NapiProverCommitments) -> Self {
416 ProverCommitments {
417 w_comm: core::array::from_fn(|i| (&x.w_comm[i]).into()),
418 z_comm: x.z_comm.into(),
419 t_comm: x.t_comm.into(),
420 lookup: x.lookup.map(Into::into),
421 }
422 }
423 }
424
425 impl FromNapiValue for [<Napi $field_name:camel ProverCommitments>] {
426 unsafe fn from_napi_value(
427 env: sys::napi_env,
428 napi_val: sys::napi_value,
429 ) -> Result<Self> {
430 let instance = <ClassInstance<[<Napi $field_name:camel ProverCommitments>]> as FromNapiValue>::from_napi_value(env, napi_val)?;
431 Ok((*instance).clone())
432 }
433 }
434
435 #[napi(js_name = [<Wasm $field_name:camel OpeningProof>] )]
436 #[derive(Clone, Debug)]
437 pub struct [<Napi $field_name:camel OpeningProof>] {
438 #[napi(skip)]
439 pub lr_0: NapiVector<$NapiG>, #[napi(skip)]
441 pub lr_1: NapiVector<$NapiG>, #[napi(skip)]
443 pub delta: $NapiG,
444 pub z1: $NapiF,
445 pub z2: $NapiF,
446 #[napi(skip)]
447 pub sg: $NapiG,
448 }
449
450 type NapiOpeningProof = [<Napi $field_name:camel OpeningProof>];
451
452 #[napi]
453 impl [<Napi $field_name:camel OpeningProof>] {
454 #[napi(constructor)]
455 pub fn new(
456 lr_0: NapiVector<$NapiG>,
457 lr_1: NapiVector<$NapiG>,
458 delta: $NapiG,
459 z1: $NapiF,
460 z2: $NapiF,
461 sg: $NapiG) -> Self {
462 NapiOpeningProof { lr_0, lr_1, delta, z1, z2, sg }
463 }
464
465 #[napi(getter, js_name="lr_0")]
466 pub fn lr_0(&self) -> NapiVector<$NapiG> {
467 self.lr_0.clone()
468 }
469 #[napi(getter, js_name="lr_1")]
470 pub fn lr_1(&self) -> NapiVector<$NapiG> {
471 self.lr_1.clone()
472 }
473 #[napi(getter)]
474 pub fn delta(&self) -> $NapiG {
475 self.delta.clone()
476 }
477 #[napi(getter)]
478 pub fn sg(&self) -> $NapiG {
479 self.sg.clone()
480 }
481
482 #[napi(setter, js_name="set_lr_0")]
483 pub fn set_lr_0(&mut self, lr_0: NapiVector<$NapiG>) {
484 self.lr_0 = lr_0
485 }
486 #[napi(setter, js_name="set_lr_1")]
487 pub fn set_lr_1(&mut self, lr_1: NapiVector<$NapiG>) {
488 self.lr_1 = lr_1
489 }
490 #[napi(setter, js_name="set_delta")]
491 pub fn set_delta(&mut self, delta: $NapiG) {
492 self.delta = delta
493 }
494 #[napi(setter, js_name="set_sg")]
495 pub fn set_sg(&mut self, sg: $NapiG) {
496 self.sg = sg
497 }
498 }
499
500 impl From<NapiOpeningProof> for KimchiOpeningProof {
501 fn from(x: NapiOpeningProof) -> Self {
502 let NapiOpeningProof {lr_0, lr_1, delta, z1, z2, sg} = x;
503 OpeningProof {
504 lr: lr_0.into_iter().zip(lr_1.into_iter()).map(|(x, y)| (x.into(), y.into())).collect(),
505 delta: delta.into(),
506 z1: z1.into(),
507 z2: z2.into(),
508 sg: sg.into(),
509 }
510 }
511 }
512
513 impl From<KimchiOpeningProof> for NapiOpeningProof {
514 fn from(x: KimchiOpeningProof) -> Self {
515 let (lr_0, lr_1): (NapiVector<$NapiG>, NapiVector<$NapiG>) = x
516 .lr
517 .clone()
518 .into_iter()
519 .map(|(x, y)| (x.into(), y.into()))
520 .unzip();
521 NapiOpeningProof {
522 lr_0,
523 lr_1,
524 delta: x.delta.clone().into(),
525 z1: x.z1.into(),
526 z2: x.z2.into(),
527 sg: x.sg.clone().into(),
528 }
529 }
530 }
531
532 impl FromNapiValue for [<Napi $field_name:camel ProverProof>] {
533 unsafe fn from_napi_value(
534 env: sys::napi_env,
535 napi_val: sys::napi_value,
536 ) -> Result<Self> {
537 let instance = <ClassInstance<[<Napi $field_name:camel ProverProof>]> as FromNapiValue>::from_napi_value(env, napi_val)?;
538 Ok((*instance).clone())
539 }
540 }
541
542 #[napi(js_name = [<Wasm $field_name:camel ProverProof>])]
543 #[derive(Clone)]
544 pub struct [<Napi $field_name:camel ProverProof>] {
545 #[napi(skip)]
546 pub commitments: NapiProverCommitments,
547 #[napi(skip)]
548 pub proof: NapiOpeningProof,
549 #[napi(skip)]
551 pub evals: NapiProofEvaluations,
552 #[napi(skip)]
553 pub ft_eval1: $NapiF,
554 #[napi(skip)]
555 pub public: NapiFlatVector<$NapiF>,
556 #[napi(skip)]
557 pub prev_challenges_scalars: $NapiVecVec,
558 #[napi(skip)]
559 pub prev_challenges_comms: NapiVector<$NapiPolyComm>,
560 }
561
562 type NapiProverProof = [<Napi $field_name:camel ProverProof>];
563 type KimchiOpeningProof = OpeningProof<$G, FULL_ROUNDS>;
564 type KimchiProverProof = ProverProof<$G, KimchiOpeningProof, FULL_ROUNDS>;
565 type KimchiProofWithPublic = (KimchiProverProof, Vec<$F>);
566 type KimchiIndex = ProverIndex<FULL_ROUNDS, $G, IPA_SRS<$G>>;
567
568 impl From<&NapiProverProof> for KimchiProofWithPublic {
569 fn from(x: &NapiProverProof) -> Self {
570 let proof = ProverProof {
571 commitments: x.commitments.clone().into(),
572 proof: x.proof.clone().into(),
573 evals: x.evals.clone().into(),
574 prev_challenges: x.prev_challenges_scalars.0
575 .iter().cloned()
576 .zip(x.prev_challenges_comms.clone().into_iter())
577 .map(|(chals, comm)| RecursionChallenge { chals, comm: comm.into() })
578 .collect(),
579 ft_eval1: x.ft_eval1.clone().into()
580 };
581 let public = x.public.clone().into_iter().map(Into::into).collect();
582 (proof, public)
583 }
584 }
585
586 impl From<NapiProverProof> for KimchiProofWithPublic {
587 fn from(x: NapiProverProof) -> Self {
588 let proof = ProverProof {
589 commitments: x.commitments.into(),
590 proof: x.proof.into(),
591 evals: x.evals.into(),
592 prev_challenges:
593 x.prev_challenges_scalars.0
594 .iter()
595 .zip((x.prev_challenges_comms).clone().into_iter())
596 .map(|(chals, comm)| {
597 RecursionChallenge {
598 chals: chals.clone(),
599 comm: comm.into(),
600 }
601 })
602 .collect(),
603 ft_eval1: x.ft_eval1.into()
604 };
605 let public = x.public.into_iter().map(Into::into).collect();
606 (proof, public)
607 }
608 }
609
610 impl From<(&KimchiProverProof, &Vec<$F>)> for NapiProverProof {
613 fn from((proof, public): (&KimchiProverProof, &Vec<$F>)) -> Self {
614 let (scalars, comms): (Vec<Vec<$F>>, Vec<$NapiPolyComm>) = proof
615 .prev_challenges
616 .iter()
617 .map(|RecursionChallenge { chals, comm }| (chals.clone(), comm.clone().into()))
618 .unzip();
619
620 NapiProverProof {
621 commitments: proof.commitments.clone().into(),
622 proof: proof.proof.clone().into(),
623 evals: proof.evals.clone().into(),
624 ft_eval1: proof.ft_eval1.clone().into(),
625 public: public.clone().into_iter().map(Into::into).collect(),
626 prev_challenges_scalars: scalars.into(),
627 prev_challenges_comms: comms.into(), }
629 }
630 }
631
632 impl From<KimchiProofWithPublic> for NapiProverProof {
633 fn from((proof, public): KimchiProofWithPublic) -> Self {
634 let (scalars, comms): (Vec<Vec<$F>>, Vec<$NapiPolyComm>) = proof
635 .prev_challenges
636 .into_iter()
637 .map(|RecursionChallenge { chals, comm }| (chals, comm.into()))
638 .unzip();
639
640 NapiProverProof {
641 commitments: proof.commitments.into(),
642 proof: proof.proof.into(),
643 evals: proof.evals.into(),
644 ft_eval1: proof.ft_eval1.into(),
645 public: public.into_iter().map(Into::into).collect(),
646 prev_challenges_scalars: scalars.into(),
647 prev_challenges_comms: comms.into(),
648 }
649 }
650 }
651
652 impl FromNapiValue for [<Napi $field_name:camel OpeningProof>] {
653 unsafe fn from_napi_value(
654 env: sys::napi_env,
655 napi_val: sys::napi_value,
656 ) -> Result<Self> {
657 let instance = <ClassInstance<[<Napi $field_name:camel OpeningProof>]> as FromNapiValue>::from_napi_value(env, napi_val)?;
658 Ok((*instance).clone())
659 }
660 }
661
662 #[napi]
663 impl [<Napi $field_name:camel ProverProof>] {
664 #[napi(constructor)]
665 pub fn new(
666 commitments: NapiProverCommitments, proof: NapiOpeningProof,
668 evals: NapiProofEvaluations, ft_eval1: $NapiF,
670 public_: NapiFlatVector<$NapiF>,
671 prev_challenges_scalars: $NapiVecVec,
672 prev_challenges_comms: NapiVector<$NapiPolyComm>) -> Self {
673 NapiProverProof {
674 commitments,
675 proof,
676 evals,
677 ft_eval1,
678 public: public_,
679 prev_challenges_scalars,
680 prev_challenges_comms,
681 }
682 }
683
684 #[napi(getter)]
685 pub fn commitments(&self) -> NapiProverCommitments {
686 self.commitments.clone()
687 }
688 #[napi(getter)]
689 pub fn proof(&self) -> NapiOpeningProof {
690 self.proof.clone()
691 }
692 #[napi(getter)]
693 pub fn evals(&self) -> NapiProofEvaluations {
694 self.evals.clone()
695 }
696 #[napi(getter, js_name = "ft_eval1")]
697 pub fn ft_eval1(&self) -> $NapiF {
698 self.ft_eval1.clone()
699 }
700 #[napi(getter, js_name="public_")]
701 pub fn public_(&self) -> NapiFlatVector<$NapiF> {
702 self.public.clone()
703 }
704 #[napi(getter, js_name="prev_challenges_scalars")]
705 pub fn prev_challenges_scalars(&self) -> $NapiVecVec {
706 self.prev_challenges_scalars.clone()
707 }
708 #[napi(getter, js_name="prev_challenges_comms")]
709 pub fn prev_challenges_comms(&self) -> NapiVector<$NapiPolyComm> {
710 self.prev_challenges_comms.clone()
711 }
712
713 #[napi(setter, js_name="set_commitments")]
714 pub fn set_commitments(&mut self, commitments: NapiProverCommitments) {
715 self.commitments = commitments
716 }
717 #[napi(setter, js_name="set_proof")]
718 pub fn set_proof(&mut self, proof: NapiOpeningProof) {
719 self.proof = proof
720 }
721 #[napi(setter, js_name="set_evals")]
722 pub fn set_evals(&mut self, evals: NapiProofEvaluations) {
723 self.evals = evals
724 }
725 #[napi(setter, js_name = "set_ft_eval1")]
726 pub fn set_ft_eval1(&mut self, ft_eval1: $NapiF) {
727 self.ft_eval1 = ft_eval1
728 }
729 #[napi(setter, js_name="set_public_")]
730 pub fn set_public_(&mut self, public_: NapiFlatVector<$NapiF>) {
731 self.public = public_
732 }
733 #[napi(setter, js_name="set_prev_challenges_scalars")]
734 pub fn set_prev_challenges_scalars(&mut self, prev_challenges_scalars: $NapiVecVec) {
735 self.prev_challenges_scalars = prev_challenges_scalars;
736 }
737 #[napi(setter, js_name="set_prev_challenges_comms")]
738 pub fn set_prev_challenges_comms(&mut self, prev_challenges_comms: NapiVector<$NapiPolyComm>) {
739 self.prev_challenges_comms = prev_challenges_comms
740 }
741
742 #[napi]
743 #[allow(deprecated)]
744 pub fn serialize(&self) -> String {
745 let (proof, _public_input) = self.into();
746 let serialized = rmp_serde::to_vec(&proof).unwrap();
747 base64::encode(serialized)
749 }
750 }
751
752 type NapiProofF = NapiProverProof;
754
755 #[napi(js_name = [<"caml_pasta_" $field_name:snake "_plonk_proof_create">])]
756 pub fn [<caml_pasta_ $field_name:snake _plonk_proof_create>](
757 index: &External<$NapiIndex>,
758 witness: $NapiVecVec,
759 runtime_tables: NapiVector<$NapiRuntimeTable>,
760 prev_challenges: NapiFlatVector<$NapiF>,
761 prev_sgs: NapiVector<$NapiG>,
762 ) -> Result<NapiProofF> {
763 let (maybe_proof, public_input) = {
764 index
765 .0
766 .srs
767 .as_ref()
768 .get_lagrange_basis(index.0.as_ref().cs.domain.d1);
769 let prev: Vec<RecursionChallenge<$G>> = {
770 if prev_challenges.is_empty() {
771 Vec::new()
772 } else {
773 let challenges_per_sg = prev_challenges.len() / prev_sgs.len();
774 let d = prev_sgs
775 .into_iter()
776 .map(Into::<$G>::into)
777 .enumerate()
778 .map(|(i, sg)| {
779 let chals = prev_challenges
780 [(i * challenges_per_sg)..(i + 1) * challenges_per_sg]
781 .iter()
782 .cloned()
783 .map(Into::into)
784 .collect();
785 let comm = PolyComm::<$G> { chunks: vec![sg] };
786 RecursionChallenge { chals, comm }
787 })
788 .collect();
789 d
790 }
791 };
792 let rust_runtime_tables: Vec<RuntimeTable<$F>> = runtime_tables.into_iter().map(Into::into).collect();
793
794 let witness: [Vec<_>; COLUMNS] = witness
795 .0
796 .try_into()
797 .expect("the witness should be a column of 15 vectors");
798
799 let index: &KimchiIndex = &index.0.as_ref();
800
801 let public_input = witness[0][0..index.cs.public].to_vec();
802
803 let group_map = GroupMap::<_>::setup();
805 let maybe_proof = ProverProof::create_recursive::<
806 DefaultFqSponge<_, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
807 DefaultFrSponge<_, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
808 _,
809 >(
810 &group_map,
811 witness,
812 &rust_runtime_tables,
813 index,
814 prev,
815 None,
816 &mut rand::rngs::OsRng,
817 );
818 (maybe_proof, public_input)
819 };
820
821 match maybe_proof {
822 Ok(proof) => Ok((proof, public_input).into()),
823 Err(err) => Err(NapiError::new(Status::GenericFailure, err.to_string())),
824 }
825 }
826
827 #[napi(js_name = [<"caml_pasta_" $field_name:snake "_plonk_proof_verify">])]
828 pub fn [<caml_pasta_ $field_name:snake _plonk_proof_verify>](
829 index: $NapiVerifierIndex,
830 proof: NapiProofF,
831 ) -> bool {
832 let group_map = <$G as CommitmentCurve>::Map::setup();
833 let verifier_index = &index.into();
834 let proof_with_public: KimchiProofWithPublic =
835 proof.into();
836 let (proof, public_input) = (&proof_with_public.0, &proof_with_public.1);
837 batch_verify::<
838 FULL_ROUNDS,
839 $G,
840 DefaultFqSponge<_, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
841 DefaultFrSponge<_, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
842 KimchiOpeningProof
843 >(
844 &group_map,
845 &[Context { verifier_index, proof, public_input }]
846 ).is_ok()
847 }
848
849
850 #[napi(js_name = [<"caml_pasta_" $field_name:snake "_plonk_proof_batch_verify">])]
851 pub fn [<caml_pasta_ $field_name:snake _plonk_proof_batch_verify>](
852 indexes: NapiVector<$NapiVerifierIndex>,
853 proofs: NapiVector<NapiProofF>,
854 ) -> bool {
855 let indexes: Vec<_> = indexes.into_iter().map(Into::into).collect();
856 let proofs_native: Vec<KimchiProofWithPublic> =
857 proofs.into_iter().map(Into::into).collect();
858
859 if indexes.len() != proofs_native.len() {
860 return false;
861 }
862
863 let contexts: Vec<_> = indexes
864 .iter()
865 .zip(proofs_native.iter())
866 .map(|(index, proof_with_public)| Context {
867 verifier_index: index,
868 proof: &proof_with_public.0,
869 public_input: &proof_with_public.1,
870 })
871 .collect();
872
873 let group_map = GroupMap::<_>::setup();
874
875 batch_verify::<
876 FULL_ROUNDS,
877 $G,
878 DefaultFqSponge<_, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
879 DefaultFrSponge<_, PlonkSpongeConstantsKimchi, FULL_ROUNDS>,
880 KimchiOpeningProof
881 >(&group_map, &contexts)
882 .is_ok()
883 }
884
885 #[napi(js_name = [<"caml_pasta_" $field_name:snake "_plonk_proof_dummy">])]
886 pub fn [<caml_pasta_ $field_name:snake _plonk_proof_dummy>]() -> NapiProofF {
887 fn comm() -> PolyComm<$G> {
888 let g = $G::generator();
889 PolyComm {
890 chunks: vec![g, g, g],
891 }
892 }
893
894 let prev = RecursionChallenge {
895 chals: vec![$F::one(), $F::one()],
896 comm: comm(),
897 };
898 let prev_challenges = vec![prev.clone(), prev.clone(), prev.clone()];
899
900 let g = $G::generator();
901 let proof = OpeningProof {
902 lr: vec![(g, g), (g, g), (g, g)],
903 z1: $F::one(),
904 z2: $F::one(),
905 delta: g,
906 sg: g,
907 };
908 let eval = || PointEvaluations {
909 zeta: vec![$F::one()],
910 zeta_omega: vec![$F::one()],
911 };
912 let evals = ProofEvaluations {
913 w: core::array::from_fn(|_| eval()),
914 coefficients: core::array::from_fn(|_| eval()),
915 z: eval(),
916 s: core::array::from_fn(|_| eval()),
917 generic_selector: eval(),
918 poseidon_selector: eval(),
919 complete_add_selector: eval(),
920 mul_selector: eval(),
921 emul_selector: eval(),
922 endomul_scalar_selector: eval(),
923 range_check0_selector: None,
924 range_check1_selector: None,
925 foreign_field_add_selector: None,
926 foreign_field_mul_selector: None,
927 xor_selector: None,
928 rot_selector: None,
929 lookup_aggregation: None,
930 lookup_table: None,
931 lookup_sorted: array::from_fn(|_| None),
932 runtime_lookup_table: None,
933 runtime_lookup_table_selector: None,
934 xor_lookup_selector: None,
935 lookup_gate_lookup_selector: None,
936 range_check_lookup_selector: None,
937 foreign_field_mul_lookup_selector: None,
938 public: None,
939 };
940
941 let dlogproof = ProverProof {
942 commitments: ProverCommitments {
943 w_comm: core::array::from_fn(|_| comm()),
944 z_comm: comm(),
945 t_comm: comm(),
946 lookup: None,
947 },
948 proof,
949 evals,
950 ft_eval1: $F::one(),
951 prev_challenges,
952 };
953
954 let public = vec![$F::one(), $F::one()];
955 (dlogproof, public).into()
956 }
957
958 #[napi(js_name = [<"caml_pasta_" $field_name:snake "_plonk_proof_deep_copy">])]
959 pub fn [<caml_pasta_ $field_name:snake "_plonk_proof_deep_copy">](
960 x: NapiProofF
961 ) -> NapiProofF {
962 x.clone()
963 }
964 }
965 };
966}
967
968pub mod fp {
969 use super::*;
970 use crate::{
971 pasta_fp_plonk_index::WasmPastaFpPlonkIndex as NapiPastaFpPlonkIndex,
972 plonk_verifier_index::fp::NapiFpPlonkVerifierIndex,
973 poly_comm::vesta::NapiFpPolyComm,
974 wrappers::{field::NapiPastaFp, group::NapiGVesta, lookups::NapiFpRuntimeTable},
975 };
976 use mina_curves::pasta::{Fp, Vesta};
977
978 impl_proof!(
979 NapiGVesta,
980 Vesta,
981 NapiPastaFp,
982 Fp,
983 NapiFpPolyComm,
984 NapiSrs,
985 NapiPastaFpPlonkIndex,
986 NapiFpPlonkVerifierIndex,
987 NapiVecVecFp,
988 Fp,
989 NapiFpRuntimeTable,
990 );
991}
992
993pub mod fq {
994 use super::*;
995 use crate::{
996 pasta_fq_plonk_index::WasmPastaFqPlonkIndex as NapiPastaFqPlonkIndex,
997 plonk_verifier_index::fq::NapiFqPlonkVerifierIndex,
998 poly_comm::pallas::NapiFqPolyComm,
999 wrappers::{field::NapiPastaFq, group::NapiGPallas, lookups::NapiFqRuntimeTable},
1000 };
1001 use mina_curves::pasta::{Fq, Pallas};
1002
1003 impl_proof!(
1004 NapiGPallas,
1005 Pallas,
1006 NapiPastaFq,
1007 Fq,
1008 NapiFqPolyComm,
1009 NapiSrs,
1010 NapiPastaFqPlonkIndex,
1011 NapiFqPlonkVerifierIndex,
1012 NapiVecVecFq,
1013 Fq,
1014 NapiFqRuntimeTable,
1015 );
1016}