Repository: dalek-cryptography/curve25519-dalek (language: rust)

Issue:
`const fn` support (e.g. for constructors)
[From `scalar.rs`](https://github.com/dalek-cryptography/curve25519-dalek/blob/7d53206/src/scalar.rs#L229-L230):

> XXX This is pub(crate) so we can write literal constants.  If const fns were stable, we could
> make the Scalar constructors const fns and use those instead.

This now possible after the MSRV bump.

I wouldn't consider it a release blocker though. Functions can always be made `const fn` later.




Discussion / hints:
Offhand the only constructor `Scalar` that seems immediately applicable for a `const fn` constructor is `Scalar::from_bits`.

All of the others use `reduce` which creates a backend-specific `UnpackedScalar`. We can't make the SIMD backends `const fn` (yet, see https://github.com/rust-lang/miri/issues/1912).

With a simpler canonicalization check that does a simple conditional subtract (#384), `Scalar::from_canonical_bytes` could almost be made `const fn`, but since we made it return `CtOption` that alone makes `const fn` support no longer possible.

Fix patch:
diff --git a/src/edwards.rs b/src/edwards.rs
index 2706c4313..664dfe779 100644
--- a/src/edwards.rs
+++ b/src/edwards.rs
@@ -176,12 +176,12 @@ impl Debug for CompressedEdwardsY {
 
 impl CompressedEdwardsY {
     /// View this `CompressedEdwardsY` as an array of bytes.
-    pub fn as_bytes(&self) -> &[u8; 32] {
+    pub const fn as_bytes(&self) -> &[u8; 32] {
         &self.0
     }
 
     /// Copy this `CompressedEdwardsY` to an array of bytes.
-    pub fn to_bytes(&self) -> [u8; 32] {
+    pub const fn to_bytes(&self) -> [u8; 32] {
         self.0
     }
 
@@ -481,7 +481,7 @@ impl EdwardsPoint {
     /// coordinates to projective coordinates.
     ///
     /// Free.
-    pub(crate) fn as_projective(&self) -> ProjectivePoint {
+    pub(crate) const fn as_projective(&self) -> ProjectivePoint {
         ProjectivePoint {
             X: self.X,
             Y: self.Y,
diff --git a/src/montgomery.rs b/src/montgomery.rs
index 09653c08f..a1143d0d6 100644
--- a/src/montgomery.rs
+++ b/src/montgomery.rs
@@ -119,12 +119,12 @@ impl Zeroize for MontgomeryPoint {
 
 impl MontgomeryPoint {
     /// View this `MontgomeryPoint` as an array of bytes.
-    pub fn as_bytes(&self) -> &[u8; 32] {
+    pub const fn as_bytes(&self) -> &[u8; 32] {
         &self.0
     }
 
     /// Convert this `MontgomeryPoint` to an array of bytes.
-    pub fn to_bytes(&self) -> [u8; 32] {
+    pub const fn to_bytes(&self) -> [u8; 32] {
         self.0
     }
 
diff --git a/src/ristretto.rs b/src/ristretto.rs
index cbca349ac..3df176609 100644
--- a/src/ristretto.rs
+++ b/src/ristretto.rs
@@ -231,12 +231,12 @@ impl ConstantTimeEq for CompressedRistretto {
 
 impl CompressedRistretto {
     /// Copy the bytes of this `CompressedRistretto`.
-    pub fn to_bytes(&self) -> [u8; 32] {
+    pub const fn to_bytes(&self) -> [u8; 32] {
         self.0
     }
 
     /// View this `CompressedRistretto` as an array of bytes.
-    pub fn as_bytes(&self) -> &[u8; 32] {
+    pub const fn as_bytes(&self) -> &[u8; 32] {
         &self.0
     }
 
diff --git a/src/scalar.rs b/src/scalar.rs
index d5266cce8..0f27b0c5b 100644
--- a/src/scalar.rs
+++ b/src/scalar.rs
@@ -226,8 +226,9 @@ pub struct Scalar {
     ///
     /// This ensures that there is room for a carry bit when computing a NAF representation.
     //
-    // XXX This is pub(crate) so we can write literal constants.  If const fns were stable, we could
-    //     make the Scalar constructors const fns and use those instead.
+    // XXX This is pub(crate) so we can write literal constants.
+    //     Alternatively we could make the Scalar constructors `const fn`s and use those instead.
+    //     See dalek-cryptography/curve25519-dalek#493
     pub(crate) bytes: [u8; 32],
 }
 
@@ -688,7 +689,7 @@ impl Scalar {
     ///
     /// assert!(s.to_bytes() == [0u8; 32]);
     /// ```
-    pub fn to_bytes(&self) -> [u8; 32] {
+    pub const fn to_bytes(&self) -> [u8; 32] {
         self.bytes
     }
 
@@ -703,7 +704,7 @@ impl Scalar {
     ///
     /// assert!(s.as_bytes() == &[0u8; 32]);
     /// ```
-    pub fn as_bytes(&self) -> &[u8; 32] {
+    pub const fn as_bytes(&self) -> &[u8; 32] {
         &self.bytes
     }
 


Test patch: