Skip to content

Commit db7879d

Browse files
committed
refactor: implement our own TE config
Previously defining the cofactor was done on `AffineCurve`: this let us set it to 1 since decaf377 provides a prime-order group. However, the cofactor is now moved to the curve configuration via the trait `CurveConfig`. This means we can no longer use the upstream `ark_ed_on_bls12_377` curve configuration type: we need to define our own and implement the required traits, and then use that to define `EdwardsAffine`, `EdwardsProjective`, and `EdwardsVar` (R1CS) instead of the upstream provided definitions of those types.
1 parent d762be0 commit db7879d

12 files changed

+111
-47
lines changed

src/constants.rs

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ pub static B_T: Lazy<Fq> = Lazy::new(|| {
5454
});
5555
pub static B_Z: Lazy<Fq> = Lazy::new(|| ark_ff::MontFp!("1"));
5656

57+
// Canonical basepoint affine coordinates
58+
pub const GENERATOR_X: Fq =
59+
ark_ff::MontFp!("4959445789346820725352484487855828915252512307947624787834978378872129235627");
60+
pub const GENERATOR_Y: Fq =
61+
ark_ff::MontFp!("6060471950081851567114691557659790004756535011754163002297540472747064943288");
62+
5763
// Modulus of basefield
5864
pub static R: Lazy<Fr> = Lazy::new(|| {
5965
ark_ff::MontFp!("2111115437357092606062206234695386632838870926408408195193685246394721360383")

src/element.rs

+62-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,75 @@
1-
use ark_ec::{AffineRepr, CurveGroup, Group, ScalarMul, VariableBaseMSM};
2-
use ark_ed_on_bls12_377::{EdwardsAffine, EdwardsConfig, EdwardsProjective};
1+
use ark_ec::{
2+
twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig},
3+
AffineRepr, CurveConfig, CurveGroup, Group, ScalarMul, VariableBaseMSM,
4+
};
5+
use ark_ed_on_bls12_377::EdwardsConfig;
6+
use ark_ff::MontFp;
37
use ark_serialize::Valid;
48

5-
use crate::{Fq, Fr};
9+
use crate::{
10+
constants::{GENERATOR_X, GENERATOR_Y},
11+
Fq, Fr,
12+
};
613

714
pub mod affine;
815
pub mod projective;
916

1017
pub use affine::AffineElement;
1118
pub use projective::Element;
1219

20+
#[derive(Clone, Default, PartialEq, Eq)]
21+
pub struct Decaf377EdwardsConfig;
22+
23+
// These types should not be exported. They are similar to `EdwardsAffine` and
24+
// `EdwardsProjective` from the `ark_ed_on_bls12_377` crate, except using our own
25+
// `Decaf377Config` that has the cofactor set to 1. Consumers of this
26+
// library should use the `AffineElement` and `Element` (projective)
27+
// types.
28+
pub(crate) type EdwardsAffine = Affine<Decaf377EdwardsConfig>;
29+
pub(crate) type EdwardsProjective = Projective<Decaf377EdwardsConfig>;
30+
31+
impl CurveConfig for Decaf377EdwardsConfig {
32+
type BaseField = Fq;
33+
type ScalarField = Fr;
34+
35+
const COFACTOR: &'static [u64] = &[1];
36+
37+
const COFACTOR_INV: Fr = MontFp!("1");
38+
}
39+
40+
impl TECurveConfig for Decaf377EdwardsConfig {
41+
/// COEFF_A = -1
42+
const COEFF_A: Fq = <EdwardsConfig as ark_ec::twisted_edwards::TECurveConfig>::COEFF_A;
43+
44+
/// COEFF_D = 3021
45+
const COEFF_D: Fq = <EdwardsConfig as ark_ec::twisted_edwards::TECurveConfig>::COEFF_D;
46+
47+
const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y);
48+
49+
type MontCurveConfig = EdwardsConfig;
50+
51+
/// Multiplication by `a` is just negation.
52+
#[inline(always)]
53+
fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
54+
-elem
55+
}
56+
57+
fn is_in_correct_subgroup_assuming_on_curve(_: &Affine<Self>) -> bool {
58+
true
59+
}
60+
}
61+
62+
impl MontCurveConfig for Decaf377EdwardsConfig {
63+
const COEFF_A: Fq = <EdwardsConfig as ark_ec::twisted_edwards::MontCurveConfig>::COEFF_A;
64+
65+
const COEFF_B: Fq = <EdwardsConfig as ark_ec::twisted_edwards::MontCurveConfig>::COEFF_B;
66+
67+
type TECurveConfig = Decaf377EdwardsConfig;
68+
}
69+
1370
impl Valid for Element {
1471
fn check(&self) -> Result<(), ark_serialize::SerializationError> {
15-
todo!()
72+
Ok(())
1673
}
1774
}
1875

@@ -84,7 +141,7 @@ impl CurveGroup for Element {
84141

85142
impl Valid for AffineElement {
86143
fn check(&self) -> Result<(), ark_serialize::SerializationError> {
87-
todo!()
144+
Ok(())
88145
}
89146
}
90147

src/element/affine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::hash::Hash;
22

3-
use ark_ed_on_bls12_377::EdwardsAffine;
3+
use crate::element::EdwardsAffine;
44
use ark_std::fmt::{Display, Formatter, Result as FmtResult};
55
use ark_std::Zero;
66

src/element/projective.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use std::borrow::Borrow;
22
use std::hash::Hash;
33

4-
use ark_ed_on_bls12_377::EdwardsProjective;
54
use ark_ff::Zero;
65
use ark_std::fmt::{Display, Formatter, Result as FmtResult};
76

87
use zeroize::Zeroize;
98

10-
use crate::{Fq, Fr};
9+
use crate::{EdwardsProjective, Fq, Fr};
1110

1211
#[derive(Copy, Clone)]
1312
pub struct Element {

src/elligator.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![allow(non_snake_case)]
22
use ark_ec::twisted_edwards::TECurveConfig;
3-
use ark_ed_on_bls12_377::{EdwardsConfig, EdwardsProjective};
43
use ark_ff::Field;
54

5+
use crate::element::{Decaf377EdwardsConfig, EdwardsProjective};
6+
67
use crate::{
78
constants::{ONE, TWO, ZETA},
89
Element, Fq, OnCurve, Sign, SqrtRatioZeta,
@@ -12,8 +13,8 @@ impl Element {
1213
/// Elligator 2 map to decaf377 point
1314
fn elligator_map(r_0: &Fq) -> Element {
1415
// Ref: `Decaf_1_1_Point.elligator` (optimized) in `ristretto.sage`
15-
let A = EdwardsConfig::COEFF_A;
16-
let D = EdwardsConfig::COEFF_D;
16+
let A = Decaf377EdwardsConfig::COEFF_A;
17+
let D = Decaf377EdwardsConfig::COEFF_D;
1718

1819
let r = *ZETA * r_0.square();
1920

@@ -44,8 +45,8 @@ impl Element {
4445

4546
// Convert point to extended projective (X : Y : Z : T)
4647
let E = *TWO * s;
47-
let F = *ONE + EdwardsConfig::COEFF_A * s.square();
48-
let G = *ONE - EdwardsConfig::COEFF_A * s.square();
48+
let F = *ONE + Decaf377EdwardsConfig::COEFF_A * s.square();
49+
let G = *ONE - Decaf377EdwardsConfig::COEFF_A * s.square();
4950
let H = t;
5051
let result = Element {
5152
inner: EdwardsProjective::new(E * H, F * G, E * G, F * H),
@@ -86,7 +87,7 @@ impl Element {
8687

8788
#[cfg(test)]
8889
mod tests {
89-
use ark_ed_on_bls12_377::EdwardsAffine;
90+
use crate::element::EdwardsAffine;
9091

9192
use super::*;
9293

src/encoding.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
use std::convert::{TryFrom, TryInto};
44

55
use ark_ec::twisted_edwards::TECurveConfig;
6-
use ark_ed_on_bls12_377::{EdwardsConfig, EdwardsProjective};
76
use ark_ff::{Field, One};
87
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
98

10-
use crate::{constants::TWO, Element, EncodingError, Fq, OnCurve, Sign, SqrtRatioZeta};
9+
use crate::{
10+
constants::TWO, element::Decaf377EdwardsConfig, EdwardsProjective, Element, EncodingError, Fq,
11+
OnCurve, Sign, SqrtRatioZeta,
12+
};
1113

1214
#[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)]
1315
pub struct Encoding(pub [u8; 32]);
@@ -35,7 +37,7 @@ impl Encoding {
3537

3638
// This isn't a constant, only because traits don't have const methods
3739
// yet and multiplication is only implemented as part of the Mul trait.
38-
let D4: Fq = EdwardsConfig::COEFF_D * Fq::from(4u32);
40+
let D4: Fq = Decaf377EdwardsConfig::COEFF_D * Fq::from(4u32);
3941

4042
// 1/2. Reject unless s is canonically encoded and nonnegative.
4143
let s =
@@ -90,7 +92,7 @@ impl Element {
9092
pub fn vartime_compress_to_field(&self) -> Fq {
9193
// This isn't a constant, only because traits don't have const methods
9294
// yet and subtraction is only implemented as part of the Sub trait.
93-
let A_MINUS_D = EdwardsConfig::COEFF_A - EdwardsConfig::COEFF_D;
95+
let A_MINUS_D = Decaf377EdwardsConfig::COEFF_A - Decaf377EdwardsConfig::COEFF_D;
9496
let p = &self.inner;
9597

9698
// 1.

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ pub mod rand;
1414
pub mod serialize;
1515
mod sign;
1616

17-
use ark_ed_on_bls12_377::EdwardsProjective;
1817
pub use constants::ZETA;
1918
pub use element::{AffineElement, Element};
19+
pub(crate) use element::{Decaf377EdwardsConfig, EdwardsProjective};
2020
pub use encoding::Encoding;
2121
pub use error::EncodingError;
2222
pub use field_ext::FieldExt;

src/ops/affine.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
22

33
use ark_ec::twisted_edwards::Projective;
4-
use ark_ed_on_bls12_377::EdwardsConfig;
54

6-
use crate::{element::AffineElement, Element, Fr};
5+
use crate::{element::AffineElement, Decaf377EdwardsConfig, Element, Fr};
76

87
impl<'a, 'b> Add<&'b AffineElement> for &'a AffineElement {
98
type Output = AffineElement;
@@ -102,7 +101,7 @@ impl Neg for AffineElement {
102101

103102
impl<'b> MulAssign<&'b Fr> for AffineElement {
104103
fn mul_assign(&mut self, point: &'b Fr) {
105-
let mut p: Projective<EdwardsConfig> = self.inner.into();
104+
let mut p: Projective<Decaf377EdwardsConfig> = self.inner.into();
106105
p *= *point;
107106
*self = AffineElement { inner: p.into() }
108107
}
@@ -118,7 +117,7 @@ impl<'a, 'b> Mul<&'b Fr> for &'a AffineElement {
118117
type Output = AffineElement;
119118

120119
fn mul(self, point: &'b Fr) -> AffineElement {
121-
let mut p: Projective<EdwardsConfig> = self.inner.into();
120+
let mut p: Projective<Decaf377EdwardsConfig> = self.inner.into();
122121
p *= *point;
123122
AffineElement { inner: p.into() }
124123
}

src/ops/projective.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl Neg for Element {
105105

106106
impl<'b> MulAssign<&'b Fr> for Element {
107107
// Scalar multiplication is performed through the implementation
108-
// of `MulAssign` on `EdwardsProjective` which is a type alias for
108+
// of `MulAssign` on `ProjectiveDecaf377` which is a type alias for
109109
// `Group<EdwardsConfig>`.
110110
fn mul_assign(&mut self, point: &'b Fr) {
111111
let mut p = self.inner;

src/r1cs/element.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@
22
use std::borrow::Borrow;
33

44
use ark_ec::AffineRepr;
5-
use ark_ed_on_bls12_377::{
6-
constraints::{EdwardsVar, FqVar},
7-
EdwardsAffine,
8-
};
5+
use ark_ed_on_bls12_377::constraints::FqVar;
96
use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, prelude::*, R1CSVar};
107
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
118

12-
use crate::r1cs::inner::ElementVar as InnerElementVar;
139
use crate::r1cs::lazy::LazyElementVar;
10+
use crate::{element::EdwardsAffine, r1cs::inner::ElementVar as InnerElementVar};
1411
use crate::{AffineElement, Element, Fq};
1512

13+
use super::inner::Decaf377EdwardsVar;
14+
1615
#[derive(Clone, Debug)]
1716
/// Represents the R1CS equivalent of a `decaf377::Element`
1817
///
@@ -115,7 +114,7 @@ impl CondSelectGadget<Fq> for ElementVar {
115114
let y = cond.select(&true_element.inner.y, &false_element.inner.y)?;
116115

117116
let new_element = InnerElementVar {
118-
inner: EdwardsVar::new(x, y),
117+
inner: Decaf377EdwardsVar::new(x, y),
119118
};
120119
Ok(Self {
121120
inner: LazyElementVar::new_from_element(new_element),

src/r1cs/inner.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,27 @@ use std::borrow::Borrow;
33
use std::ops::{Add, AddAssign, Sub, SubAssign};
44

55
use ark_ec::{twisted_edwards::TECurveConfig, AffineRepr};
6-
use ark_ed_on_bls12_377::{
7-
constraints::{EdwardsVar, FqVar},
8-
EdwardsAffine, EdwardsConfig,
9-
};
6+
use ark_ed_on_bls12_377::constraints::FqVar;
107
use ark_r1cs_std::{
118
alloc::AllocVar, eq::EqGadget, groups::curves::twisted_edwards::AffineVar, prelude::*, R1CSVar,
129
};
1310
use ark_relations::ns;
1411
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
1512

13+
use crate::element::EdwardsAffine;
14+
use crate::Decaf377EdwardsConfig;
1615
use crate::{constants::ZETA, r1cs::fqvar_ext::FqVarExtension, AffineElement, Element, Fq};
1716

17+
pub(crate) type Decaf377EdwardsVar = AffineVar<Decaf377EdwardsConfig, FqVar>;
18+
1819
#[derive(Clone, Debug)]
1920
/// Represents the R1CS equivalent of a `decaf377::Element`
2021
///
2122
/// Generally the suffix -`Var` will indicate that the type or variable
2223
/// represents in R1CS.
2324
pub struct ElementVar {
2425
/// Inner type is an alias for `AffineVar<EdwardsConfig, FqVar>`
25-
pub(crate) inner: EdwardsVar,
26+
pub(crate) inner: Decaf377EdwardsVar,
2627
}
2728

2829
impl ElementVar {
@@ -38,8 +39,10 @@ impl ElementVar {
3839
let Z_var = FqVar::one();
3940
let T_var = X_var * Y_var;
4041

41-
let A_MINUS_D_VAR =
42-
FqVar::new_constant(self.cs(), EdwardsConfig::COEFF_A - EdwardsConfig::COEFF_D)?;
42+
let A_MINUS_D_VAR = FqVar::new_constant(
43+
self.cs(),
44+
Decaf377EdwardsConfig::COEFF_A - Decaf377EdwardsConfig::COEFF_D,
45+
)?;
4346

4447
// 1.
4548
let u_1_var = (X_var.clone() + T_var.clone()) * (X_var.clone() - T_var.clone());
@@ -62,7 +65,7 @@ impl ElementVar {
6265

6366
/// R1CS equivalent of `Encoding::vartime_decompress`
6467
pub fn decompress_from_field(s_var: FqVar) -> Result<ElementVar, SynthesisError> {
65-
let D4: Fq = EdwardsConfig::COEFF_D * Fq::from(4u32);
68+
let D4: Fq = Decaf377EdwardsConfig::COEFF_D * Fq::from(4u32);
6669
let D4_VAR = FqVar::constant(D4);
6770

6871
// 1. We do not check if canonically encoded here since we know FqVar is already
@@ -107,8 +110,8 @@ impl ElementVar {
107110
pub(crate) fn elligator_map(r_0_var: &FqVar) -> Result<ElementVar, SynthesisError> {
108111
let cs = r_0_var.cs();
109112

110-
let A_VAR = FqVar::new_constant(cs.clone(), EdwardsConfig::COEFF_A)?;
111-
let D_VAR = FqVar::new_constant(cs.clone(), EdwardsConfig::COEFF_D)?;
113+
let A_VAR = FqVar::new_constant(cs.clone(), Decaf377EdwardsConfig::COEFF_A)?;
114+
let D_VAR = FqVar::new_constant(cs.clone(), Decaf377EdwardsConfig::COEFF_D)?;
112115
let ZETA_VAR = FqVar::new_constant(cs, *ZETA)?;
113116

114117
let r_var = ZETA_VAR * r_0_var.square()?;
@@ -219,7 +222,7 @@ impl CondSelectGadget<Fq> for ElementVar {
219222
let y = cond.select(&true_value.inner.y, &false_value.inner.y)?;
220223

221224
Ok(ElementVar {
222-
inner: EdwardsVar::new(x, y),
225+
inner: Decaf377EdwardsVar::new(x, y),
223226
})
224227
}
225228
}
@@ -244,7 +247,7 @@ impl AllocVar<Element, Fq> for ElementVar {
244247
// where they check that the point is in the right subgroup prior to witnessing.
245248
match mode {
246249
AllocationMode::Constant => Ok(Self {
247-
inner: EdwardsVar::new_variable_omit_prime_order_check(
250+
inner: Decaf377EdwardsVar::new_variable_omit_prime_order_check(
248251
cs,
249252
|| Ok(group_projective_point.inner),
250253
mode,
@@ -254,7 +257,6 @@ impl AllocVar<Element, Fq> for ElementVar {
254257
unreachable!()
255258
}
256259
AllocationMode::Witness => {
257-
//let ge: EdwardsAffine = group_projective_point.inner.into();
258260
let P_var = AffineVar::new_variable_omit_prime_order_check(
259261
ns!(cs, "P_affine"),
260262
|| Ok(group_projective_point.inner),
@@ -410,13 +412,13 @@ impl<'a> GroupOpsBounds<'a, Element, ElementVar> for ElementVar {}
410412
impl CurveVar<Element, Fq> for ElementVar {
411413
fn zero() -> Self {
412414
Self {
413-
inner: AffineVar::<EdwardsConfig, FqVar>::zero(),
415+
inner: AffineVar::<Decaf377EdwardsConfig, FqVar>::zero(),
414416
}
415417
}
416418

417419
fn constant(other: Element) -> Self {
418420
Self {
419-
inner: AffineVar::<EdwardsConfig, FqVar>::constant(other.inner),
421+
inner: AffineVar::<Decaf377EdwardsConfig, FqVar>::constant(other.inner),
420422
}
421423
}
422424

0 commit comments

Comments
 (0)