use midnight_curves::{Fq as JubjubBase, JubjubExtended as Jubjub};
use crate::CircuitField;
pub trait MapToWeierstrassParams<BaseField: CircuitField> {
const SVDW_Z: BaseField;
const A: BaseField;
const B: BaseField;
fn g(x: BaseField) -> BaseField {
x * x * x + Self::A * x + Self::B
}
fn c1() -> BaseField {
Self::g(Self::SVDW_Z)
}
fn c2() -> BaseField {
-Self::SVDW_Z * BaseField::TWO_INV
}
fn c3() -> BaseField {
let den =
BaseField::from(3u64) * Self::SVDW_Z * Self::SVDW_Z + BaseField::from(4u64) * Self::A;
let a = -Self::c1() * den;
let sqrt = a
.sqrt()
.expect("This value should be a quadratic residue. Check SVDW_Z parameter.");
if bool::from(sqrt.is_even()) {
sqrt
} else {
-sqrt
}
}
fn c4() -> BaseField {
let four = BaseField::from(4u64);
let det = BaseField::from(3u64) * Self::SVDW_Z * Self::SVDW_Z + four * Self::A;
-four * Self::c1() * (det.invert().unwrap())
}
}
pub trait MapToEdwardsParams<BaseField: CircuitField>: MapToWeierstrassParams<BaseField> {
const MONT_J: BaseField;
const MONT_K: BaseField;
}
impl MapToWeierstrassParams<JubjubBase> for Jubjub {
const SVDW_Z: JubjubBase = JubjubBase::from_raw([
0xfffffffeffffffff,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
const A: JubjubBase = JubjubBase::from_raw([
0xc50d34dcd4c20942,
0x20535e745e639334,
0x976220a0378a2328,
0x739e8acf6e7266e8,
]);
const B: JubjubBase = JubjubBase::from_raw([
0x7120c33b4c6628e1,
0xbbf51483ff8366ac,
0xf4c60001b55614b0,
0x6ae5ca3c3f667667,
]);
}
impl MapToEdwardsParams<JubjubBase> for Jubjub {
const MONT_J: JubjubBase = JubjubBase::from_raw([
0x000000000000a002,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
]);
const MONT_K: JubjubBase = JubjubBase::from_raw([
0xfffffffeffff5ffd,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
}
#[cfg(test)]
mod test {
use ff::{Field, PrimeField};
use super::*;
use crate::ecc::curves::CircuitCurve;
fn test_params<C>()
where
C: CircuitCurve + MapToWeierstrassParams<C::Base>,
{
assert_ne!(C::c1(), C::Base::ZERO);
assert_ne!(C::c4(), C::Base::ZERO);
assert!(bool::from(C::c4().sqrt().is_some()));
assert!(bool::from(C::c1().sqrt().is_some()) | bool::from(C::g(C::c2()).sqrt().is_some()));
assert!(bool::from(C::c3().is_even()));
}
#[test]
fn test_jubjub_params() {
test_params::<Jubjub>()
}
}