use crate::prelude::*;
elliptic_curve_model! {
[attributes]
name = Montgomery
coordinates = (u, w)
constants = (A, B)
[functions]
serialize: (P: Point) -> Bytes
u <- P.u * P.w.inv()
Bytes::from(u.serialize())
deserialize: (buffer: Bytes) -> Point
u <- Element::deserialize(buffer)
Point::new(u, Element::from(1))
equal: (P: Point, Q: Point) -> Bool
P.u * Q.w = Q.u * P.w
edwards_y: (P: Point) -> Element
y <- P.u - P.w
z <- P.u + P.w
y * z.inv()
neg: (P: Point) -> Point
Point::new(P.u, P.w)
dbl: (P: Point) -> Point
v1 <- P.u + P.w
v1 <- v1.sqr()
v2 <- P.u - P.w
v2 <- v2.sqr()
u <- v1 * v2
v1 <- v1 - v2
v3 <- (A + 2) * 4.inv() * v1
v3 <- v3 + v2
w <- v1 * v3
Point::new(u, w)
differential_add_and_double: (P: Point, Q: Point, PmQ: Point) -> (Point, Point)
t0 <- P.u + P.w
t1 <- P.u - P.w
t2 <- Q.u + Q.w
t3 <- Q.u - Q.w
t4 <- t0.sqr()
t5 <- t1.sqr()
t6 <- t4 - t5
t7 <- t0 * t3
t8 <- t1 * t2
t9 <- t7 + t8
t10 <- t7 - t8
t11 <- t9.sqr()
t12 <- t10.sqr()
t13 <- (A + 2) * 4.inv() * t6
t14 <- t4 * t5
t15 <- t13 + t5
t16 <- t6 * t15
t17 <- PmQ.u * t12 t18 <- PmQ.w * t11
P <- Point::new(t14, t16)
Q <- Point::new(t18, t17)
(P, Q)
}
impl<__F: FiniteField<BOUND = typenum::U8> + 'static, __C: CurveConstants<__F>> MontgomeryModel<__F, __C>
where
MontgomeryModel<__F, __C>: EllipticCurvePoint,
MontgomeryModel<__F, __C>: ConditionallySelectable,
{
pub fn scalar_mul(self, scalar: impl FiniteFieldElement<<Self as EllipticCurvePoint>::Scalar>) -> Self {
let mut x0 = Self::identity();
let mut x1 = self;
let mut prev_bit = false;
for cur_bit in scalar.bits_le().rev().skip(1) {
let choice = prev_bit ^ cur_bit;
Self::conditional_swap(&mut x0, &mut x1, (choice as u8).into());
(x0, x1) = Self::differential_add_and_double(x0, x1, self);
prev_bit = cur_bit;
}
Self::conditional_swap(&mut x0, &mut x1, (prev_bit as u8).into());
x0
}
}