kimchi_stubs/
projective.rs

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