openzeppelin_crypto/curve/te/instance/
baby_jubjub.rs

1//! [Baby Jubjub Elliptic Curve] parameters.
2//!
3//! [Baby Jubjub Elliptic Curve]: <https://eips.ethereum.org/EIPS/eip-2494>
4
5use crate::{
6    arithmetic::uint::U256,
7    curve::{
8        te::{Affine, MontCurveConfig, TECurveConfig},
9        CurveConfig,
10    },
11    field::fp::{Fp256, FpParams, LIMBS_256},
12    fp_from_num, from_num,
13};
14
15const G_GENERATOR_X: Fq = fp_from_num!("995203441582195749578291179787384436505546430278305826713579947235728471134");
16
17const G_GENERATOR_Y: Fq = fp_from_num!("5472060717959818805561601436314318772137091100104008585924551046643952123905");
18
19/// Base Field for [`BabyJubjubConfig`].
20pub type Fq = Fp256<BabyJubjubFqParam>;
21/// Base Field parameters for [`BabyJubjubConfig`].
22pub struct BabyJubjubFqParam;
23
24impl FpParams<LIMBS_256> for BabyJubjubFqParam {
25    const GENERATOR: Fp256<Self> = fp_from_num!("2");
26    const MODULUS: U256 = from_num!("21888242871839275222246405745257275088548364400416034343698204186575808495617");
27}
28
29/// Scalar Field for [`BabyJubjubConfig`].
30pub type Fr = Fp256<BabyJubjubFrParam>;
31/// Scalar Field parameters for [`BabyJubjubConfig`].
32pub struct BabyJubjubFrParam;
33
34impl FpParams<LIMBS_256> for BabyJubjubFrParam {
35    const GENERATOR: Fp256<Self> = fp_from_num!("2");
36    const MODULUS: U256 = from_num!("2736030358979909402780800718157159386076813972158567259200215660948447373041");
37}
38
39/// Baby Jubjub's Curve Details.
40#[derive(Clone, Default, PartialEq, Eq)]
41pub struct BabyJubjubConfig;
42
43impl CurveConfig for BabyJubjubConfig {
44    type BaseField = Fq;
45    type ScalarField = Fr;
46
47    const COFACTOR: &'static [u64] = &[8];
48    const COFACTOR_INV: Fr = fp_from_num!("2394026564107420727433200628387514462817212225638746351800188703329891451411");
49}
50
51impl TECurveConfig for BabyJubjubConfig {
52    type MontCurveConfig = Self;
53
54    const COEFF_A: Self::BaseField = fp_from_num!("168700");
55    const COEFF_D: Self::BaseField = fp_from_num!("168696");
56    const GENERATOR: Affine<Self> =
57        Affine::new_unchecked(G_GENERATOR_X, G_GENERATOR_Y);
58}
59
60impl MontCurveConfig for BabyJubjubConfig {
61    type TECurveConfig = Self;
62
63    const COEFF_A: Self::BaseField = fp_from_num!("168698");
64    const COEFF_B: Self::BaseField = fp_from_num!("1");
65}
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use crate::curve::{AffineRepr, CurveGroup, PrimeGroup};
70
71    // ---- Test cases from EIP-2494 (https://eips.ethereum.org/EIPS/eip-2494). ----
72
73    #[test]
74    fn test_addition() {
75        // Test 1: Addition of two different points
76        let x1 = fp_from_num!("17777552123799933955779906779655732241715742912184938656739573121738514868268");
77        let y1 = fp_from_num!("2626589144620713026669568689430873010625803728049924121243784502389097019475");
78        let p1 = Affine::<BabyJubjubConfig>::new_unchecked(x1, y1);
79
80        let x2 = fp_from_num!("16540640123574156134436876038791482806971768689494387082833631921987005038935");
81        let y2 = fp_from_num!("20819045374670962167435360035096875258406992893633759881276124905556507972311");
82        let p2 = Affine::<BabyJubjubConfig>::new_unchecked(x2, y2);
83
84        let expected_x = fp_from_num!("7916061937171219682591368294088513039687205273691143098332585753343424131937");
85        let expected_y = fp_from_num!("14035240266687799601661095864649209771790948434046947201833777492504781204499");
86        let expected =
87            Affine::<BabyJubjubConfig>::new_unchecked(expected_x, expected_y);
88
89        let result = (p1 + p2).into_affine();
90        assert_eq!(result, expected);
91    }
92
93    #[test]
94    fn test_doubling() {
95        // Test 2: Point doubling
96        let x1 = fp_from_num!("17777552123799933955779906779655732241715742912184938656739573121738514868268");
97        let y1 = fp_from_num!("2626589144620713026669568689430873010625803728049924121243784502389097019475");
98        let p1 = Affine::<BabyJubjubConfig>::new_unchecked(x1, y1);
99
100        let expected_x = fp_from_num!("6890855772600357754907169075114257697580319025794532037257385534741338397365");
101        let expected_y = fp_from_num!("4338620300185947561074059802482547481416142213883829469920100239455078257889");
102        let expected =
103            Affine::<BabyJubjubConfig>::new_unchecked(expected_x, expected_y);
104
105        let result = (p1 + p1).into_affine();
106        assert_eq!(result, expected);
107    }
108
109    #[test]
110    fn test_identity_doubling() {
111        // Test 3: Doubling the identity element
112        let x1 = fp_from_num!("0");
113        let y1 = fp_from_num!("1");
114        let identity = Affine::<BabyJubjubConfig>::new_unchecked(x1, y1);
115
116        let result = (identity + identity).into_affine();
117        assert_eq!(result, identity);
118    }
119    #[test]
120    fn test_curve_membership() {
121        // Test 4: Curve membership
122        // Point (0,1) is a point on Baby Jubjub
123        let x1 = fp_from_num!("0");
124        let y1 = fp_from_num!("1");
125        let p1 = Affine::<BabyJubjubConfig>::new_unchecked(x1, y1);
126        assert!(p1.is_on_curve());
127
128        // Point (1,0) is not a point on Baby Jubjub
129        let x2 = fp_from_num!("1");
130        let y2 = fp_from_num!("0");
131        let p2 = Affine::<BabyJubjubConfig>::new_unchecked(x2, y2);
132        assert!(!p2.is_on_curve());
133    }
134
135    #[test]
136    #[allow(clippy::similar_names)]
137    fn test_base_point_choice() {
138        // Test 5: Base point choice
139        // Check that the base point B = 8 * G
140        let gx = fp_from_num!("995203441582195749578291179787384436505546430278305826713579947235728471134");
141        let gy = fp_from_num!("5472060717959818805561601436314318772137091100104008585924551046643952123905");
142        let g = Affine::<BabyJubjubConfig>::new_unchecked(gx, gy);
143
144        let expected_bx = fp_from_num!("5299619240641551281634865583518297030282874472190772894086521144482721001553");
145        let expected_by = fp_from_num!("16950150798460657717958625567821834550301663161624707787222815936182638968203");
146        let expected_b =
147            Affine::<BabyJubjubConfig>::new_unchecked(expected_bx, expected_by);
148
149        // Multiply by 8
150        let b = g.into_group().mul_bigint(8u64).into_affine();
151        assert_eq!(b, expected_b);
152    }
153
154    #[test]
155    fn test_base_point_order() {
156        // Test 6: Base point order
157        let bx = fp_from_num!("5299619240641551281634865583518297030282874472190772894086521144482721001553");
158        let by = fp_from_num!("16950150798460657717958625567821834550301663161624707787222815936182638968203");
159        let b = Affine::<BabyJubjubConfig>::new_unchecked(bx, by);
160
161        // Create scalar l
162        let l = fp_from_num!("2736030358979909402780800718157159386076813972158567259200215660948447373041");
163
164        // B * l should equal identity (0, 1)
165        let result = (b.into_group() * l).into_affine();
166
167        let identity_x = fp_from_num!("0");
168        let identity_y = fp_from_num!("1");
169        let identity =
170            Affine::<BabyJubjubConfig>::new_unchecked(identity_x, identity_y);
171
172        assert_eq!(result, identity);
173    }
174}