snarkvm_curves/edwards_bls12/
parameters.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::{
17    edwards_bls12::{Fq, Fr},
18    errors::GroupError,
19    templates::twisted_edwards_extended::{Affine, Projective},
20    traits::{AffineCurve, ModelParameters, MontgomeryParameters, TwistedEdwardsParameters},
21};
22use snarkvm_fields::field;
23use snarkvm_utilities::biginteger::BigInteger256;
24
25use std::str::FromStr;
26
27pub type EdwardsAffine = Affine<EdwardsParameters>;
28pub type EdwardsProjective = Projective<EdwardsParameters>;
29
30#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
31pub struct EdwardsParameters;
32
33impl ModelParameters for EdwardsParameters {
34    type BaseField = Fq;
35    type ScalarField = Fr;
36}
37
38impl TwistedEdwardsParameters for EdwardsParameters {
39    type MontgomeryParameters = EdwardsParameters;
40
41    /// Generated randomly
42    const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = (GENERATOR_X, GENERATOR_Y);
43    /// COFACTOR = 4
44    const COFACTOR: &'static [u64] = &[4];
45    /// COFACTOR_INV = 527778859339273151515551558673846658209717731602102048798421311598680340096
46    const COFACTOR_INV: Fr = field!(
47        Fr,
48        BigInteger256([10836190823041854989, 14880086764632731920, 5023208332782666747, 239524813690824359,])
49    );
50    /// EDWARDS_A = -1
51    const EDWARDS_A: Fq =
52        field!(Fq, BigInteger256([0x8cf500000000000e, 0xe75281ef6000000e, 0x49dc37a90b0ba012, 0x55f8b2c6e710ab9,]));
53    /// EDWARDS_D = 3021
54    const EDWARDS_D: Fq =
55        field!(Fq, BigInteger256([0xd047ffffffff5e30, 0xf0a91026ffff57d2, 0x9013f560d102582, 0x9fd242ca7be5700,]));
56
57    /// Multiplication by `a` is just negation.
58    /// Is `a` 1 or -1?
59    #[inline(always)]
60    fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
61        -*elem
62    }
63}
64
65impl MontgomeryParameters for EdwardsParameters {
66    type TwistedEdwardsParameters = EdwardsParameters;
67
68    /// MONTGOMERY_A = 3990301581132929505568273333084066329187552697088022219156688740916631500114
69    ///              = 0x8D26E3FADA9010A26949031ECE3971B93952AD84D4753DDEDB748DA37E8F552
70    const MONTGOMERY_A: Fq = field!(
71        Fq,
72        BigInteger256([
73            13800168384327121454u64,
74            6841573379969807446u64,
75            12529593083398462246u64,
76            853978956621483129u64,
77        ])
78    );
79    /// MONTGOMERY_B = 4454160168295440918680551605697480202188346638066041608778544715000777738925
80    ///              = 0x9D8F71EEC83A44C3A1FBCEC6F5418E5C6154C2682B8AC231C5A3725C8170AAD
81    const MONTGOMERY_B: Fq = field!(
82        Fq,
83        BigInteger256([
84            7239382437352637935u64,
85            14509846070439283655u64,
86            5083066350480839936u64,
87            1265663645916442191u64,
88        ])
89    );
90}
91
92impl FromStr for EdwardsAffine {
93    type Err = GroupError;
94
95    fn from_str(mut s: &str) -> Result<Self, Self::Err> {
96        s = s.trim();
97        if s.is_empty() {
98            return Err(GroupError::ParsingEmptyString);
99        }
100        if s.len() < 3 {
101            return Err(GroupError::InvalidString);
102        }
103        if !(s.starts_with('(') && s.ends_with(')')) {
104            return Err(GroupError::InvalidString);
105        }
106        let mut point = Vec::new();
107        for substr in s.split(['(', ')', ',', ' ']) {
108            if !substr.is_empty() {
109                point.push(Fq::from_str(substr)?);
110            }
111        }
112        if point.len() != 2 {
113            return Err(GroupError::InvalidGroupElement);
114        }
115        let point = EdwardsAffine::new(point[0], point[1], point[0] * point[1]);
116
117        if !point.is_on_curve() { Err(GroupError::InvalidGroupElement) } else { Ok(point) }
118    }
119}
120
121/// GENERATOR_X =
122/// 1540945439182663264862696551825005342995406165131907382295858612069623286213
123const GENERATOR_X: Fq =
124    field!(Fq, BigInteger256([15976313411695170452, 17230178952810798400, 11626259175167078036, 678729006091608048]));
125
126/// GENERATOR_Y =
127/// 8003546896475222703853313610036801932325312921786952001586936882361378122196
128const GENERATOR_Y: Fq =
129    field!(Fq, BigInteger256([926786653590077393, 18147000980977651608, 13077459464847727671, 1231472949076376191]));