Skip to content

Commit

Permalink
Implement public-facing ops traits on all combos of &T/T
Browse files Browse the repository at this point in the history
The public-facing types with arithmetic operations are:

- `Scalar`s
- `ExtendedPoint`s
- `RistrettoPoint`s

For these types we define operators with all combinations of borrowed and
non-borrowed inputs, to avoid forcing API consumers to write extra ampersands.
Since all of the operations involved with these types are expensive relative to
the cost of an unnecessary copy, this isn't a big deal.

The `MontgomeryPoint` struct isn't included in the above because it's only
useful for scalar multiplication.

This commit is based on work by @UnlawfulMonad.
  • Loading branch information
hdevalence committed Jan 24, 2018
1 parent ed7345f commit 52d600d
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 1 deletion.
5 changes: 5 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ extern crate serde;
#[cfg(feature = "yolocrypto")]
extern crate stdsimd;

// Macros come first!
#[path="src/macros.rs"]
#[macro_use]
mod macros;

// Public modules

#[path="src/scalar.rs"]
Expand Down
23 changes: 22 additions & 1 deletion src/edwards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,25 +378,33 @@ impl<'a, 'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint {
}
}

define_add_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint, Output = ExtendedPoint);

impl<'b> AddAssign<&'b ExtendedPoint> for ExtendedPoint {
fn add_assign(&mut self, _rhs: &'b ExtendedPoint) {
*self = (self as &ExtendedPoint) + _rhs;
}
}

define_add_assign_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint);

impl<'a, 'b> Sub<&'b ExtendedPoint> for &'a ExtendedPoint {
type Output = ExtendedPoint;
fn sub(self, other: &'b ExtendedPoint) -> ExtendedPoint {
(self - &other.to_projective_niels()).to_extended()
}
}

define_sub_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint, Output = ExtendedPoint);

impl<'b> SubAssign<&'b ExtendedPoint> for ExtendedPoint {
fn sub_assign(&mut self, _rhs: &'b ExtendedPoint) {
*self = (self as &ExtendedPoint) - _rhs;
}
}

define_sub_assign_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint);

// ------------------------------------------------------------------------
// Negation
// ------------------------------------------------------------------------
Expand All @@ -414,6 +422,14 @@ impl<'a> Neg for &'a ExtendedPoint {
}
}

impl Neg for ExtendedPoint {
type Output = ExtendedPoint;

fn neg(self) -> ExtendedPoint {
-&self
}
}

// ------------------------------------------------------------------------
// Scalar multiplication
// ------------------------------------------------------------------------
Expand All @@ -425,6 +441,11 @@ impl<'b> MulAssign<&'b Scalar> for ExtendedPoint {
}
}

define_mul_assign_variants!(LHS = ExtendedPoint, RHS = Scalar);

define_mul_variants!(LHS = ExtendedPoint, RHS = Scalar, Output = ExtendedPoint);
define_mul_variants!(LHS = Scalar, RHS = ExtendedPoint, Output = ExtendedPoint);

impl<'a, 'b> Mul<&'b Scalar> for &'a ExtendedPoint {
type Output = ExtendedPoint;
/// Scalar multiplication: compute `scalar * self`.
Expand Down Expand Up @@ -478,7 +499,7 @@ impl<'a, 'b> Mul<&'b ExtendedPoint> for &'a Scalar {
/// For scalar multiplication of a basepoint,
/// `EdwardsBasepointTable` is approximately 4x faster.
fn mul(self, point: &'b ExtendedPoint) -> ExtendedPoint {
point * &self
point * self
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_cbor;

// Internal macros. Must come first!
#[macro_use]
pub(crate) mod macros;

//------------------------------------------------------------------------
// curve25519-dalek public modules
//------------------------------------------------------------------------
Expand Down
123 changes: 123 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// -*- mode: rust; -*-
//
// This file is part of curve25519-dalek.
// Copyright (c) 2016-2017 Isis Lovecruft, Henry de Valence
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <[email protected]>
// - Henry de Valence <[email protected]>

//! Internal macros.
/// Define borrow and non-borrow variants of `Add`.
macro_rules! define_add_variants {
(LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
impl<'b> Add<&'b $rhs> for $lhs {
type Output = $out;
fn add(self, rhs: &'b $rhs) -> $out {
&self + rhs
}
}

impl<'a> Add<$rhs> for &'a $lhs {
type Output = $out;
fn add(self, rhs: $rhs) -> $out {
self + &rhs
}
}

impl Add<$rhs> for $lhs {
type Output = $out;
fn add(self, rhs: $rhs) -> $out {
&self + &rhs
}
}
}
}

/// Define non-borrow variants of `AddAssign`.
macro_rules! define_add_assign_variants {
(LHS = $lhs:ty, RHS = $rhs:ty) => {
impl AddAssign<$rhs> for $lhs {
fn add_assign(&mut self, rhs: $rhs) {
*self += &rhs;
}
}
}
}

/// Define borrow and non-borrow variants of `Sub`.
macro_rules! define_sub_variants {
(LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
impl<'b> Sub<&'b $rhs> for $lhs {
type Output = $out;
fn sub(self, rhs: &'b $rhs) -> $out {
&self - rhs
}
}

impl<'a> Sub<$rhs> for &'a $lhs {
type Output = $out;
fn sub(self, rhs: $rhs) -> $out {
self - &rhs
}
}

impl Sub<$rhs> for $lhs {
type Output = $out;
fn sub(self, rhs: $rhs) -> $out {
&self - &rhs
}
}
}
}

/// Define non-borrow variants of `SubAssign`.
macro_rules! define_sub_assign_variants {
(LHS = $lhs:ty, RHS = $rhs:ty) => {
impl SubAssign<$rhs> for $lhs {
fn sub_assign(&mut self, rhs: $rhs) {
*self -= &rhs;
}
}
}
}

/// Define borrow and non-borrow variants of `Mul`.
macro_rules! define_mul_variants {
(LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
impl<'b> Mul<&'b $rhs> for $lhs {
type Output = $out;
fn mul(self, rhs: &'b $rhs) -> $out {
&self * rhs
}
}

impl<'a> Mul<$rhs> for &'a $lhs {
type Output = $out;
fn mul(self, rhs: $rhs) -> $out {
self * &rhs
}
}

impl Mul<$rhs> for $lhs {
type Output = $out;
fn mul(self, rhs: $rhs) -> $out {
&self * &rhs
}
}
}
}

/// Define non-borrow variants of `MulAssign`.
macro_rules! define_mul_assign_variants {
(LHS = $lhs:ty, RHS = $rhs:ty) => {
impl MulAssign<$rhs> for $lhs {
fn mul_assign(&mut self, rhs: $rhs) {
*self *= &rhs;
}
}
}
}

22 changes: 22 additions & 0 deletions src/ristretto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,12 +925,16 @@ impl<'a, 'b> Add<&'b RistrettoPoint> for &'a RistrettoPoint {
}
}

define_add_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint);

impl<'b> AddAssign<&'b RistrettoPoint> for RistrettoPoint {
fn add_assign(&mut self, _rhs: &RistrettoPoint) {
*self = (self as &RistrettoPoint) + _rhs;
}
}

define_add_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint);

impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint {
type Output = RistrettoPoint;

Expand All @@ -939,12 +943,16 @@ impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint {
}
}

define_sub_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint);

impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint {
fn sub_assign(&mut self, _rhs: &RistrettoPoint) {
*self = (self as &RistrettoPoint) - _rhs;
}
}

define_sub_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint);

impl<'a> Neg for &'a RistrettoPoint {
type Output = RistrettoPoint;

Expand All @@ -953,6 +961,14 @@ impl<'a> Neg for &'a RistrettoPoint {
}
}

impl Neg for RistrettoPoint {
type Output = RistrettoPoint;

fn neg(self) -> RistrettoPoint {
-&self
}
}

impl<'b> MulAssign<&'b Scalar> for RistrettoPoint {
fn mul_assign(&mut self, scalar: &'b Scalar) {
let result = (self as &RistrettoPoint) * scalar;
Expand All @@ -977,6 +993,12 @@ impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar {
}
}

define_mul_assign_variants!(LHS = RistrettoPoint, RHS = Scalar);

define_mul_variants!(LHS = RistrettoPoint, RHS = Scalar, Output = RistrettoPoint);
define_mul_variants!(LHS = Scalar, RHS = RistrettoPoint, Output = RistrettoPoint);


/// Given a vector of (possibly secret) scalars and a vector of
/// (possibly secret) points, compute `c_1 P_1 + ... + c_n P_n`.
///
Expand Down
19 changes: 19 additions & 0 deletions src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,46 +186,65 @@ impl<'b> MulAssign<&'b Scalar> for Scalar {
}
}

define_mul_assign_variants!(LHS = Scalar, RHS = Scalar);

impl<'a, 'b> Mul<&'b Scalar> for &'a Scalar {
type Output = Scalar;
fn mul(self, _rhs: &'b Scalar) -> Scalar {
UnpackedScalar::mul(&self.unpack(), &_rhs.unpack()).pack()
}
}

define_mul_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar);

impl<'b> AddAssign<&'b Scalar> for Scalar {
fn add_assign(&mut self, _rhs: &'b Scalar) {
*self = UnpackedScalar::add(&self.unpack(), &_rhs.unpack()).pack();
}
}

define_add_assign_variants!(LHS = Scalar, RHS = Scalar);

impl<'a, 'b> Add<&'b Scalar> for &'a Scalar {
type Output = Scalar;
fn add(self, _rhs: &'b Scalar) -> Scalar {
UnpackedScalar::add(&self.unpack(), &_rhs.unpack()).pack()
}
}

define_add_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar);

impl<'b> SubAssign<&'b Scalar> for Scalar {
fn sub_assign(&mut self, _rhs: &'b Scalar) {
*self = UnpackedScalar::sub(&self.unpack(), &_rhs.unpack()).pack();
}
}

define_sub_assign_variants!(LHS = Scalar, RHS = Scalar);

impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar {
type Output = Scalar;
fn sub(self, _rhs: &'b Scalar) -> Scalar {
UnpackedScalar::sub(&self.unpack(), &_rhs.unpack()).pack()
}
}

define_sub_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar);

impl<'a> Neg for &'a Scalar {
type Output = Scalar;
fn neg(self) -> Scalar {
&Scalar::zero() - self
}
}

impl<'a> Neg for Scalar {
type Output = Scalar;
fn neg(self) -> Scalar {
-&self
}
}

impl ConditionallyAssignable for Scalar {
/// Conditionally assign another Scalar to this one.
///
Expand Down

0 comments on commit 52d600d

Please sign in to comment.