Skip to main content

kimchi_stubs/
projective.rs

1use ark_ec::{AdditiveGroup, AffineRepr, CurveGroup, PrimeGroup};
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                // Windowed-NAF variable-base scalar multiplication: fewer point
57                // additions than the default bit-by-bit double-and-add
58                // ([mul_bigint]). Window 4 was fastest in a sweep over the Pasta
59                // curves (~25% faster than mul_bigint, bit-identical result).
60                let ctx = ark_ec::scalar_mul::wnaf::WnafContext::new(4);
61                ctx.mul(x.as_ref().0, &y.0).into()
62            }
63
64            #[ocaml_gen::func]
65            #[ocaml::func]
66            pub fn [<caml_ $name:snake _random>]() -> $GroupProjective {
67                let rng = &mut rand::rngs::OsRng;
68                let proj: $Projective = UniformRand::rand(rng);
69                proj.into()
70            }
71
72            #[ocaml_gen::func]
73            #[ocaml::func]
74            pub fn [<caml_ $name:snake _rng>](i: ocaml::Int) -> $GroupProjective {
75                // We only care about entropy here, so we force a conversion i32
76                // -> u32.
77                let i: u64 = (i as u32).into();
78                let mut rng: StdRng = rand::SeedableRng::seed_from_u64(i);
79                let proj: $Projective = UniformRand::rand(&mut rng);
80                proj.into()
81            }
82
83            #[ocaml_gen::func]
84            #[ocaml::func]
85            pub extern "C" fn [<caml_ $name:snake _endo_base>]() -> $CamlBaseField {
86                let (endo_q, _endo_r) = poly_commitment::ipa::endos::<GAffine>();
87                endo_q.into()
88            }
89
90            #[ocaml_gen::func]
91            #[ocaml::func]
92            pub extern "C" fn [<caml_ $name:snake _endo_scalar>]() -> $CamlScalarField {
93                let (_endo_q, endo_r) = poly_commitment::ipa::endos::<GAffine>();
94                endo_r.into()
95            }
96
97            #[ocaml_gen::func]
98            #[ocaml::func]
99            pub fn [<caml_ $name:snake _to_affine>](x: ocaml::Pointer<$GroupProjective>) -> $CamlG {
100                x.as_ref().into_affine().into()
101            }
102
103            #[ocaml_gen::func]
104            #[ocaml::func]
105            pub fn [<caml_ $name:snake _of_affine>](x: $CamlG) -> $GroupProjective {
106                Into::<GAffine>::into(x).into_group().into()
107            }
108
109            #[ocaml_gen::func]
110            #[ocaml::func]
111            pub fn [<caml_ $name:snake _of_affine_coordinates>](x: $CamlBaseField, y: $CamlBaseField) -> $GroupProjective {
112                let res = $Projective::new_unchecked(x.into(), y.into(), <$BaseField as ark_ff::One>::one());
113                res.into()
114            }
115
116            #[ocaml_gen::func]
117            #[ocaml::func]
118            pub fn [<caml_ $name:snake _affine_deep_copy>](x: $CamlG) -> $CamlG {
119                x
120            }
121        }
122    }
123}
124
125pub mod pallas {
126    use super::*;
127    use crate::arkworks::{CamlFp, CamlFq, CamlGPallas, CamlGroupProjectivePallas};
128    use mina_curves::pasta::{curves::pallas::ProjectivePallas, Fp, Pallas as GAffine};
129
130    impl_projective!(
131        pallas,
132        CamlGroupProjectivePallas,
133        CamlGPallas,
134        CamlFq,
135        Fp,
136        CamlFp,
137        ProjectivePallas
138    );
139}
140
141pub mod vesta {
142    use super::*;
143    use crate::arkworks::{CamlFp, CamlFq, CamlGVesta, CamlGroupProjectiveVesta};
144    use mina_curves::pasta::{curves::vesta::ProjectiveVesta, Fq, Vesta as GAffine};
145
146    impl_projective!(
147        vesta,
148        CamlGroupProjectiveVesta,
149        CamlGVesta,
150        CamlFp,
151        Fq,
152        CamlFq,
153        ProjectiveVesta
154    );
155}