1use ark_ec::{AffineRepr, CurveGroup, Group};
2use ark_ff::UniformRand;
3use paste::paste;
4use rand::rngs::StdRng;
5
6use wasm_bindgen::prelude::*;
7
8macro_rules! impl_projective {
9 ($name: ident,
10 $GroupProjective: ty,
11 $CamlG: ty,
12 $CamlScalarField: ty,
13 $BaseField: ty,
14 $CamlBaseField: ty,
15 $Projective: ty) => {
16
17 paste! {
18 #[wasm_bindgen]
19 pub fn [<caml_ $name:snake _one>]() -> $GroupProjective {
20 $Projective::generator().into()
21 }
22
23 #[wasm_bindgen]
24 pub fn [<caml_ $name:snake _add>](
25 x: &$GroupProjective,
26 y: &$GroupProjective,
27 ) -> $GroupProjective {
28 x.as_ref() + y.as_ref()
29 }
30
31 #[wasm_bindgen]
32 pub fn [<caml_ $name:snake _sub>](
33 x: &$GroupProjective,
34 y: &$GroupProjective,
35 ) -> $GroupProjective {
36 x.as_ref() - y.as_ref()
37 }
38
39 #[wasm_bindgen]
40 pub fn [<caml_ $name:snake _negate>](
41 x: &$GroupProjective,
42 ) -> $GroupProjective {
43 -(*x.as_ref())
44 }
45
46 #[wasm_bindgen]
47 pub fn [<caml_ $name:snake _double>](
48 x: &$GroupProjective,
49 ) -> $GroupProjective {
50 x.as_ref().double().into()
51 }
52
53 #[wasm_bindgen]
54 pub fn [<caml_ $name:snake _scale>](
55 x: &$GroupProjective,
56 y: $CamlScalarField,
57 ) -> $GroupProjective {
58 let y: ark_ff::BigInteger256 = y.0.into();
59 x.as_ref().mul_bigint(&y).into()
60 }
61
62 #[wasm_bindgen]
63 pub fn [<caml_ $name:snake _random>]() -> $GroupProjective {
64 let rng = &mut rand::rngs::OsRng;
65 let proj: $Projective = UniformRand::rand(rng);
66 proj.into()
67 }
68
69 #[wasm_bindgen]
70 pub fn [<caml_ $name:snake _rng>](i: u32) -> $GroupProjective {
71 let i: u64 = (i as u32).into();
73 let mut rng: StdRng = rand::SeedableRng::seed_from_u64(i);
74 let proj: $Projective = UniformRand::rand(&mut rng);
75 proj.into()
76 }
77
78 #[allow(improper_ctypes_definitions)]
81 #[wasm_bindgen]
82 pub extern "C" fn [<caml_ $name:snake _endo_base>]() -> $CamlBaseField {
83 let (endo_q, _endo_r) = poly_commitment::ipa::endos::<GAffine>();
84 endo_q.into()
85 }
86
87 #[allow(improper_ctypes_definitions)]
90 #[wasm_bindgen]
91 pub extern "C" fn [<caml_ $name:snake _endo_scalar>]() -> $CamlScalarField {
92 let (_endo_q, endo_r) = poly_commitment::ipa::endos::<GAffine>();
93 endo_r.into()
94 }
95
96 #[wasm_bindgen]
97 pub fn [<caml_ $name:snake _to_affine>](
98 x: &$GroupProjective
99 ) -> $CamlG {
100 x.as_ref().into_affine().into()
101 }
102
103 #[wasm_bindgen]
104 pub fn [<caml_ $name:snake _of_affine>](x: $CamlG) -> $GroupProjective {
105 Into::<GAffine>::into(x).into_group().into()
106 }
107
108 #[wasm_bindgen]
109 pub fn [<caml_ $name:snake _of_affine_coordinates>](x: $CamlBaseField, y: $CamlBaseField) -> $GroupProjective {
110 let res = $Projective::new_unchecked(x.into(), y.into(), <$BaseField as ark_ff::One>::one());
111 res.into()
112 }
113
114 #[wasm_bindgen]
115 pub fn [<caml_ $name:snake _affine_deep_copy>](x: $CamlG) -> $CamlG {
116 x
117 }
118 }
119 }
120}
121
122pub mod pallas {
123 use super::*;
124 use arkworks::{WasmGPallas, WasmPallasGProjective, WasmPastaFp, WasmPastaFq};
125 use mina_curves::pasta::{Fp, Pallas as GAffine, ProjectivePallas};
126
127 impl_projective!(
128 pallas,
129 WasmPallasGProjective,
130 WasmGPallas,
131 WasmPastaFq,
132 Fp,
133 WasmPastaFp,
134 ProjectivePallas
135 );
136}
137
138pub mod vesta {
139 use super::*;
140 use arkworks::{WasmGVesta, WasmPastaFp, WasmPastaFq, WasmVestaGProjective};
141 use mina_curves::pasta::{Fq, ProjectiveVesta, Vesta as GAffine};
142
143 impl_projective!(
144 vesta,
145 WasmVestaGProjective,
146 WasmGVesta,
147 WasmPastaFp,
148 Fq,
149 WasmPastaFq,
150 ProjectiveVesta
151 );
152}