|
| 1 | +//! EIP-2494 Baby Jubjub Curve |
| 2 | +//! |
| 3 | +//! This is an append to the the `ark-ed-on-bn254` crate to use the EIP-2494 defined Baby Jubjub curve parameters. |
| 4 | +//! |
| 5 | +//! - https://eips.ethereum.org/EIPS/eip-2494 |
| 6 | +//! |
| 7 | +//! - Base field: q = 21888242871839275222246405745257275088548364400416034343698204186575808495617 |
| 8 | +//! - Scalar field: r = 2736030358979909402780800718157159386076813972158567259200215660948447373041 |
| 9 | +//! - Order: n = l * cofactor = 21888242871839275222246405745257275088614511777268538073601725287587578984328 |
| 10 | +//! - Cofactor: 8 |
| 11 | +//! - Subgroup order: l = 2736030358979909402780800718157159386076813972158567259200215660948447373041 |
| 12 | +//! - Curve equation: ax² + y² = 1 + d·x²y², where |
| 13 | +//! - a = 168700 |
| 14 | +//! - d = 168696 |
| 15 | +//! - Generator point: |
| 16 | +//! (995203441582195749578291179787384436505546430278305826713579947235728471134, |
| 17 | +//! 5472060717959818805561601436314318772137091100104008585924551046643952123905) |
| 18 | +//! - Base point: |
| 19 | +//! (5299619240641551281634865583518297030282874472190772894086521144482721001553, |
| 20 | +//! 16950150798460657717958625567821834550301663161624707787222815936182638968203) |
| 21 | +
|
| 22 | +use ark_ec::{ |
| 23 | + models::CurveConfig, |
| 24 | + twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig}, |
| 25 | +}; |
| 26 | +use ark_ed_on_bn254::{Fq, Fr}; |
| 27 | +use ark_ff::{Field, MontFp}; |
| 28 | + |
| 29 | +pub type EdwardsAffine = Affine<BabyJubjubConfig>; |
| 30 | +pub type EdwardsProjective = Projective<BabyJubjubConfig>; |
| 31 | + |
| 32 | +#[derive(Clone, Default, PartialEq, Eq)] |
| 33 | +pub struct BabyJubjubConfig; |
| 34 | + |
| 35 | +impl CurveConfig for BabyJubjubConfig { |
| 36 | + type BaseField = Fq; |
| 37 | + type ScalarField = Fr; |
| 38 | + |
| 39 | + // h = 8 |
| 40 | + const COFACTOR: &'static [u64] = &[8]; |
| 41 | + |
| 42 | + // h^(-1) (mod r) |
| 43 | + const COFACTOR_INV: Fr = |
| 44 | + MontFp!("2394026564107420727433200628387514462817212225638746351800188703329891451411"); |
| 45 | +} |
| 46 | + |
| 47 | +// Twisted Edwards form |
| 48 | +// ax^2 + y^2 = 1 + dx^2y^2 |
| 49 | +impl TECurveConfig for BabyJubjubConfig { |
| 50 | + // a = 168700 |
| 51 | + const COEFF_A: Fq = MontFp!("168700"); |
| 52 | + |
| 53 | + #[inline(always)] |
| 54 | + fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { |
| 55 | + elem * <BabyJubjubConfig as TECurveConfig>::COEFF_A |
| 56 | + } |
| 57 | + |
| 58 | + // d = 168696 |
| 59 | + const COEFF_D: Fq = MontFp!("168696"); |
| 60 | + |
| 61 | + // Base point is used as generator to operate in subgroup |
| 62 | + const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(BASE_X, BASE_Y); |
| 63 | + |
| 64 | + type MontCurveConfig = BabyJubjubConfig; |
| 65 | +} |
| 66 | + |
| 67 | +// Montgomery form |
| 68 | +// By^2 = x^3 + A x^2 + x |
| 69 | +impl MontCurveConfig for BabyJubjubConfig { |
| 70 | + // A = 168698 |
| 71 | + const COEFF_A: Fq = MontFp!("168698"); |
| 72 | + // B = 1 |
| 73 | + const COEFF_B: Fq = Fq::ONE; |
| 74 | + |
| 75 | + type TECurveConfig = BabyJubjubConfig; |
| 76 | +} |
| 77 | + |
| 78 | +/// Generator point x-coordinate |
| 79 | +pub const GENERATOR_X: Fq = |
| 80 | + MontFp!("995203441582195749578291179787384436505546430278305826713579947235728471134"); |
| 81 | +/// Generator point y-coordinate |
| 82 | +pub const GENERATOR_Y: Fq = |
| 83 | + MontFp!("5472060717959818805561601436314318772137091100104008585924551046643952123905"); |
| 84 | + |
| 85 | +/// Subgroup order `l` |
| 86 | +pub const SUBGROUP_ORDER: Fr = |
| 87 | + MontFp!("2736030358979909402780800718157159386076813972158567259200215660948447373041"); |
| 88 | + |
| 89 | +// Subgroup generator |
| 90 | +// Generates subgroup l * P = O |
| 91 | + |
| 92 | +/// Base point x-coordinate |
| 93 | +pub const BASE_X: Fq = |
| 94 | + MontFp!("5299619240641551281634865583518297030282874472190772894086521144482721001553"); |
| 95 | +/// Base point y-coordinate |
| 96 | +pub const BASE_Y: Fq = |
| 97 | + MontFp!("16950150798460657717958625567821834550301663161624707787222815936182638968203"); |
| 98 | + |
| 99 | +#[cfg(test)] |
| 100 | +mod tests { |
| 101 | + //! Implementation of the tests presented in the EIP-2494 |
| 102 | +
|
| 103 | + use super::*; |
| 104 | + use ark_ec::CurveGroup; |
| 105 | + use ark_ff::{PrimeField, Zero}; |
| 106 | + |
| 107 | + #[test] |
| 108 | + fn test_addition() { |
| 109 | + let p1 = EdwardsAffine::new_unchecked( |
| 110 | + MontFp!( |
| 111 | + "17777552123799933955779906779655732241715742912184938656739573121738514868268" |
| 112 | + ), |
| 113 | + MontFp!("2626589144620713026669568689430873010625803728049924121243784502389097019475"), |
| 114 | + ); |
| 115 | + |
| 116 | + let p2 = EdwardsAffine::new_unchecked( |
| 117 | + MontFp!( |
| 118 | + "16540640123574156134436876038791482806971768689494387082833631921987005038935" |
| 119 | + ), |
| 120 | + MontFp!( |
| 121 | + "20819045374670962167435360035096875258406992893633759881276124905556507972311" |
| 122 | + ), |
| 123 | + ); |
| 124 | + |
| 125 | + let result = (p1 + p2).into_affine(); |
| 126 | + |
| 127 | + assert_eq!( |
| 128 | + result, |
| 129 | + EdwardsAffine::new_unchecked( |
| 130 | + MontFp!( |
| 131 | + "7916061937171219682591368294088513039687205273691143098332585753343424131937" |
| 132 | + ), |
| 133 | + MontFp!( |
| 134 | + "14035240266687799601661095864649209771790948434046947201833777492504781204499" |
| 135 | + ) |
| 136 | + ) |
| 137 | + ); |
| 138 | + } |
| 139 | + |
| 140 | + #[test] |
| 141 | + fn test_doubling() { |
| 142 | + let p1 = EdwardsAffine::new_unchecked( |
| 143 | + MontFp!( |
| 144 | + "17777552123799933955779906779655732241715742912184938656739573121738514868268" |
| 145 | + ), |
| 146 | + MontFp!("2626589144620713026669568689430873010625803728049924121243784502389097019475"), |
| 147 | + ); |
| 148 | + |
| 149 | + let result = (p1 + p1).into_affine(); |
| 150 | + |
| 151 | + assert_eq!( |
| 152 | + result, |
| 153 | + EdwardsAffine::new_unchecked( |
| 154 | + MontFp!( |
| 155 | + "6890855772600357754907169075114257697580319025794532037257385534741338397365" |
| 156 | + ), |
| 157 | + MontFp!( |
| 158 | + "4338620300185947561074059802482547481416142213883829469920100239455078257889" |
| 159 | + ) |
| 160 | + ) |
| 161 | + ); |
| 162 | + } |
| 163 | + |
| 164 | + #[test] |
| 165 | + fn test_doubling_identity() { |
| 166 | + let identity = EdwardsAffine::new_unchecked(Fq::zero(), Fq::ONE); |
| 167 | + let result = (identity + identity).into_affine(); |
| 168 | + |
| 169 | + assert_eq!(result, identity); |
| 170 | + } |
| 171 | + |
| 172 | + #[test] |
| 173 | + fn test_curve_membership() { |
| 174 | + let valid_point = EdwardsAffine::new_unchecked(Fq::zero(), Fq::ONE); |
| 175 | + assert!(valid_point.is_on_curve()); |
| 176 | + |
| 177 | + let invalid_point = EdwardsAffine::new_unchecked(Fq::ONE, Fq::zero()); |
| 178 | + assert!(!invalid_point.is_on_curve()); |
| 179 | + } |
| 180 | + |
| 181 | + #[test] |
| 182 | + fn test_base_point_choice() { |
| 183 | + let g = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y); |
| 184 | + |
| 185 | + let expected_base_point = EdwardsAffine::new_unchecked(BASE_X, BASE_Y); |
| 186 | + let cofactor = Fr::from_be_bytes_mod_order(&[BabyJubjubConfig::COFACTOR[0] as u8]); |
| 187 | + let calculated_base_point = (g * cofactor).into_affine(); |
| 188 | + |
| 189 | + assert_eq!(calculated_base_point, expected_base_point); |
| 190 | + } |
| 191 | + |
| 192 | + #[test] |
| 193 | + fn test_base_point_order() { |
| 194 | + let base_point = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y); |
| 195 | + |
| 196 | + let result = (base_point * SUBGROUP_ORDER).into_affine(); |
| 197 | + let identity = EdwardsAffine::new_unchecked(Fq::zero(), Fq::ONE); |
| 198 | + |
| 199 | + assert_eq!(result, identity); |
| 200 | + } |
| 201 | +} |
0 commit comments