mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-04 20:03:40 +00:00
Implement simplified backend selection (#428)
As proposed in #414, this commit changes the backend selection approach, introspecting `target_pointer_width` to select `u32_backend` vs `u64_backend` (or `fiat_u32_backend`/`fiat_u64_backend` if the `fiat_backend` feature is enabled). This helps eliminate the use of non-additive features, and also the rather confusing errors that happen if multiple backends are selected (i.e. thousands of lines of rustc errors). The selection logic checks if `target_pointer_width = "64"` and uses the 64-bit backend, or falls back to the 32-bit backend otherwise. This means the crate will always have a valid backend regardless of the pointer width, although there may be odd edge cases for exotic platforms which would optimally use the 64-bit backend but have a non-"64" target pointer width for whatever reason. We can handle those cases as they come up.
This commit is contained in:
parent
977eb0d3b7
commit
081f632d91
8 changed files with 159 additions and 147 deletions
35
.github/workflows/rust.yml
vendored
35
.github/workflows/rust.yml
vendored
|
|
@ -10,21 +10,24 @@ env:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
test-u32:
|
||||
name: Test u32 backend
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo test --no-default-features --features "std u32_backend"
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# 32-bit target
|
||||
- target: i686-unknown-linux-gnu
|
||||
deps: sudo apt update && sudo apt install gcc-multilib
|
||||
|
||||
test-u64:
|
||||
name: Test u64 backend
|
||||
runs-on: ubuntu-latest
|
||||
# 64-bit target
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo test --no-default-features --features "std u64_backend"
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: rustup target add ${{ matrix.target }}
|
||||
- run: ${{ matrix.deps }}
|
||||
- run: cargo test --target ${{ matrix.target }}
|
||||
- run: cargo test --target ${{ matrix.target }} --features fiat_backend
|
||||
|
||||
build-simd:
|
||||
name: Build simd backend (nightly)
|
||||
|
|
@ -54,7 +57,9 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo test --lib --no-default-features --features "alloc u32_backend"
|
||||
- run: rustup target add i686-unknown-linux-gnu
|
||||
- run: sudo apt update && sudo apt install gcc-multilib
|
||||
- run: cargo test --lib --no-default-features --features alloc --target i686-unknown-linux-gnu
|
||||
|
||||
nightly:
|
||||
name: Test nightly compiler
|
||||
|
|
@ -72,11 +77,11 @@ jobs:
|
|||
# First run `cargo +nightly -Z minimal-verisons check` in order to get a
|
||||
# Cargo.lock with the oldest possible deps
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cargo -Z minimal-versions check --no-default-features --features "fiat_u64_backend serde"
|
||||
- run: cargo -Z minimal-versions check --no-default-features --features fiat_backend,serde
|
||||
# Now check that `cargo build` works with respect to the oldest possible
|
||||
# deps and the stated MSRV
|
||||
- uses: dtolnay/rust-toolchain@1.56.1
|
||||
- run: cargo build --no-default-features --features "fiat_u64_backend serde"
|
||||
- run: cargo build --no-default-features --features fiat_backend,serde
|
||||
|
||||
bench:
|
||||
name: Check that benchmarks compile
|
||||
|
|
|
|||
18
Cargo.toml
18
Cargo.toml
|
|
@ -43,6 +43,7 @@ name = "dalek_benchmarks"
|
|||
harness = false
|
||||
|
||||
[dependencies]
|
||||
cfg-if = "1"
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
digest = { version = "0.10", default-features = false }
|
||||
subtle = { version = "^2.2.1", default-features = false }
|
||||
|
|
@ -55,20 +56,11 @@ fiat-crypto = { version = "0.1.6", optional = true}
|
|||
|
||||
[features]
|
||||
nightly = ["subtle/nightly"]
|
||||
default = ["std", "u64_backend"]
|
||||
default = ["std"]
|
||||
std = ["alloc", "subtle/std", "rand_core/std"]
|
||||
alloc = ["zeroize/alloc"]
|
||||
|
||||
# The u32 backend uses u32s with u64 products.
|
||||
u32_backend = []
|
||||
# The u64 backend uses u64s with u128 products.
|
||||
u64_backend = []
|
||||
# fiat-u64 backend (with formally-verified field arith) uses u64s with u128 products.
|
||||
fiat_u64_backend = ["fiat-crypto"]
|
||||
# fiat-u32 backend (with formally-verified field arith) uses u32s with u64 products.
|
||||
fiat_u32_backend = ["fiat-crypto"]
|
||||
# fiat-crypto backend with formally-verified field arithmetic
|
||||
fiat_backend = ["fiat-crypto"]
|
||||
# The SIMD backend uses parallel formulas, using either AVX2 or AVX512-IFMA.
|
||||
simd_backend = ["nightly", "u64_backend", "packed_simd"]
|
||||
# DEPRECATED: this is now an alias for `simd_backend` and may be removed
|
||||
# in some future release.
|
||||
avx2_backend = ["simd_backend"]
|
||||
simd_backend = ["nightly", "packed_simd"]
|
||||
|
|
|
|||
49
README.md
49
README.md
|
|
@ -82,9 +82,13 @@ version, and in terms of non-breaking changes it includes:
|
|||
### 4.x (current alpha)
|
||||
|
||||
The `4.x` series has an API largely unchanged from `3.x`, with a breaking change
|
||||
to update the `rand` dependency crates. It also requires including a new trait,
|
||||
`use curve25519_dalek::traits::BasepointTable`, whenever using `EdwardsBasepointTable`
|
||||
or `RistrettoBasepointTable`.
|
||||
to update the `rand` dependency crates.
|
||||
|
||||
It also requires including a new trait,
|
||||
`use curve25519_dalek::traits::BasepointTable`, whenever using
|
||||
`EdwardsBasepointTable` or `RistrettoBasepointTable`.
|
||||
|
||||
Backend selection has also been updated to be more automatic. See below.
|
||||
|
||||
# Backends and Features
|
||||
|
||||
|
|
@ -98,24 +102,26 @@ Curve arithmetic is implemented using one of the following backends:
|
|||
* a `u64` backend using serial formulas and `u128` products;
|
||||
* an `avx2` backend using [parallel formulas][parallel_doc] and `avx2` instructions (sets speed records);
|
||||
* an `ifma` backend using [parallel formulas][parallel_doc] and `ifma` instructions (sets speed records);
|
||||
|
||||
By default the `u64` backend is selected. To select a specific backend, use:
|
||||
```sh
|
||||
cargo build --no-default-features --features "std u32_backend"
|
||||
cargo build --no-default-features --features "std u64_backend"
|
||||
# Requires nightly, RUSTFLAGS="-C target_feature=+avx2" to use avx2
|
||||
cargo build --no-default-features --features "std simd_backend"
|
||||
# Requires nightly, RUSTFLAGS="-C target_feature=+avx512ifma" to use ifma
|
||||
cargo build --no-default-features --features "std simd_backend"
|
||||
```
|
||||
Crates using `curve25519-dalek` can either select a backend on behalf of their
|
||||
users, or expose feature flags that control the `curve25519-dalek` backend.
|
||||
* a `fiat` backend using formally verified field arithmetic from [fiat-crypto];
|
||||
|
||||
The `std` feature is enabled by default, but it can be disabled for no-`std`
|
||||
builds using `--no-default-features`. Note that this requires explicitly
|
||||
selecting an arithmetic backend using one of the `_backend` features.
|
||||
If no backend is selected, compilation will fail.
|
||||
|
||||
## Backend selection
|
||||
|
||||
Backend selection is done automatically. E.g., if you're compiling on a
|
||||
64-bit machine, then the `u64` backend is automatically chosen. And
|
||||
if the `fiat_backend` feature is set, then the fiat `u64` backend is
|
||||
chosen.
|
||||
|
||||
If you need a `u32` backend on a `u64` machine, then simple
|
||||
cross-compiling will work on an x86-64 Linux machine:
|
||||
|
||||
* `sudo apt install gcc-multilib` (or whatever package manager you use)
|
||||
* `rustup target add i686-unknown-linux-gnu`
|
||||
* `cargo build --target i686-unknown-linux-gnu`
|
||||
|
||||
# Minimum Supported Rust Version
|
||||
|
||||
|
|
@ -166,11 +172,10 @@ compiled with appropriate `target_feature`s, so this cannot occur.
|
|||
Benchmarks are run using [`criterion.rs`][criterion]:
|
||||
|
||||
```sh
|
||||
cargo bench --no-default-features --features "std u32_backend"
|
||||
cargo bench --no-default-features --features "std u64_backend"
|
||||
cargo bench --no-default-features
|
||||
# Uses avx2 or ifma only if compiled for an appropriate target.
|
||||
export RUSTFLAGS="-C target_cpu=native"
|
||||
cargo bench --no-default-features --features "std simd_backend"
|
||||
cargo +nightly bench --no-default-features --features simd_backend
|
||||
```
|
||||
|
||||
Performance is a secondary goal behind correctness, safety, and
|
||||
|
|
@ -227,10 +232,9 @@ optimised batch inversion was contributed by Sean Bowe and Daira Hopwood.
|
|||
|
||||
The `no_std` and `zeroize` support was contributed by Tony Arcieri.
|
||||
|
||||
The formally verified backends, `fiat_u32_backend` and `fiat_u64_backend`, which
|
||||
integrate with the Rust generated by the
|
||||
[Fiat Crypto project](https://github.com/mit-plv/fiat-crypto) were contributed
|
||||
by François Garillot.
|
||||
The formally verified `fiat_backend` integrates Rust code generated by the
|
||||
[Fiat Crypto project](https://github.com/mit-plv/fiat-crypto) and was
|
||||
contributed by François Garillot.
|
||||
|
||||
Thanks also to Ashley Hauck, Lucas Salibian, Manish Goregaokar, Jack Grigg,
|
||||
Pratyush Mishra, Michael Rosenberg, and countless others for their
|
||||
|
|
@ -244,3 +248,4 @@ contributions.
|
|||
[criterion]: https://github.com/japaric/criterion.rs
|
||||
[parallel_doc]: https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/avx2/index.html
|
||||
[subtle_doc]: https://doc.dalek.rs/subtle/
|
||||
[fiat-crypto]: https://github.com/mit-plv/fiat-crypto
|
||||
|
|
|
|||
|
|
@ -34,18 +34,6 @@
|
|||
//! The [`vector`] backend is selected by the `simd_backend` cargo
|
||||
//! feature; it uses the [`serial`] backend for non-vectorized operations.
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "u32_backend",
|
||||
feature = "u64_backend",
|
||||
feature = "fiat_u32_backend",
|
||||
feature = "fiat_u64_backend",
|
||||
feature = "simd_backend",
|
||||
)))]
|
||||
compile_error!(
|
||||
"no curve25519-dalek backend cargo feature enabled! \
|
||||
please enable one of: u32_backend, u64_backend, fiat_u32_backend, fiat_u64_backend, simd_backend"
|
||||
);
|
||||
|
||||
pub mod serial;
|
||||
|
||||
#[cfg(any(
|
||||
|
|
|
|||
|
|
@ -19,32 +19,24 @@
|
|||
//!
|
||||
//! When the vector backend is enabled, the field and scalar
|
||||
//! implementations are still used for non-vectorized operations.
|
||||
//!
|
||||
//! Note: at this time the `u32` and `u64` backends cannot be built
|
||||
//! together.
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "u32_backend",
|
||||
feature = "u64_backend",
|
||||
feature = "fiat_u32_backend",
|
||||
feature = "fiat_u64_backend"
|
||||
)))]
|
||||
compile_error!(
|
||||
"no curve25519-dalek backend cargo feature enabled! \
|
||||
please enable one of: u32_backend, u64_backend, fiat_u32_backend, fiat_u64_backend"
|
||||
);
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
#[cfg(feature = "u32_backend")]
|
||||
pub mod u32;
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fiat_backend")] {
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub mod fiat_u32;
|
||||
|
||||
#[cfg(feature = "u64_backend")]
|
||||
pub mod u64;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub mod fiat_u64;
|
||||
} else {
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub mod u32;
|
||||
|
||||
#[cfg(feature = "fiat_u32_backend")]
|
||||
pub mod fiat_u32;
|
||||
|
||||
#[cfg(feature = "fiat_u64_backend")]
|
||||
pub mod fiat_u64;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub mod u64;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod curve_models;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,20 +28,27 @@
|
|||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use crate::edwards::CompressedEdwardsY;
|
||||
use crate::montgomery::MontgomeryPoint;
|
||||
use crate::ristretto::CompressedRistretto;
|
||||
use crate::ristretto::RistrettoPoint;
|
||||
use crate::scalar::Scalar;
|
||||
|
||||
#[cfg(feature = "fiat_u32_backend")]
|
||||
pub use crate::backend::serial::fiat_u32::constants::*;
|
||||
#[cfg(feature = "fiat_u64_backend")]
|
||||
pub use crate::backend::serial::fiat_u64::constants::*;
|
||||
#[cfg(feature = "u32_backend")]
|
||||
pub use crate::backend::serial::u32::constants::*;
|
||||
#[cfg(feature = "u64_backend")]
|
||||
pub use crate::backend::serial::u64::constants::*;
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fiat_backend")] {
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub use crate::backend::serial::fiat_u32::constants::*;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub use crate::backend::serial::fiat_u64::constants::*;
|
||||
} else {
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub use crate::backend::serial::u32::constants::*;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub use crate::backend::serial::u64::constants::*;
|
||||
}
|
||||
}
|
||||
|
||||
/// The Ed25519 basepoint, in `CompressedEdwardsY` format.
|
||||
///
|
||||
|
|
@ -142,7 +149,7 @@ mod test {
|
|||
|
||||
/// Test that d = -121665/121666
|
||||
#[test]
|
||||
#[cfg(feature = "u32_backend")]
|
||||
#[cfg(all(not(target_pointer_width = "64"), not(feature = "fiat_backend")))]
|
||||
fn test_d_vs_ratio() {
|
||||
use crate::backend::serial::u32::field::FieldElement2625;
|
||||
let a = -&FieldElement2625([121665, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
|
@ -155,7 +162,7 @@ mod test {
|
|||
|
||||
/// Test that d = -121665/121666
|
||||
#[test]
|
||||
#[cfg(feature = "u64_backend")]
|
||||
#[cfg(all(target_pointer_width = "64", not(feature = "fiat_backend")))]
|
||||
fn test_d_vs_ratio() {
|
||||
use crate::backend::serial::u64::field::FieldElement51;
|
||||
let a = -&FieldElement51([121665, 0, 0, 0, 0]);
|
||||
|
|
|
|||
78
src/field.rs
78
src/field.rs
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallyNegatable;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
|
@ -33,40 +35,52 @@ use subtle::ConstantTimeEq;
|
|||
use crate::backend;
|
||||
use crate::constants;
|
||||
|
||||
#[cfg(feature = "fiat_u32_backend")]
|
||||
pub use backend::serial::fiat_u32::field::*;
|
||||
#[cfg(feature = "fiat_u64_backend")]
|
||||
pub use backend::serial::fiat_u64::field::*;
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
/// Using formally-verified field arithmetic from fiat-crypto
|
||||
#[cfg(feature = "fiat_u32_backend")]
|
||||
pub type FieldElement = backend::serial::fiat_u32::field::FieldElement2625;
|
||||
#[cfg(feature = "fiat_u64_backend")]
|
||||
pub type FieldElement = backend::serial::fiat_u64::field::FieldElement51;
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fiat_backend")] {
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub use backend::serial::fiat_u32::field::*;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub use backend::serial::fiat_u64::field::*;
|
||||
|
||||
#[cfg(feature = "u64_backend")]
|
||||
pub use crate::backend::serial::u64::field::*;
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
#[cfg(feature = "u64_backend")]
|
||||
pub type FieldElement = backend::serial::u64::field::FieldElement51;
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
///
|
||||
/// Using formally-verified field arithmetic from fiat-crypto.
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub type FieldElement = backend::serial::fiat_u32::field::FieldElement2625;
|
||||
|
||||
#[cfg(feature = "u32_backend")]
|
||||
pub use backend::serial::u32::field::*;
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
#[cfg(feature = "u32_backend")]
|
||||
pub type FieldElement = backend::serial::u32::field::FieldElement2625;
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
///
|
||||
/// Using formally-verified field arithmetic from fiat-crypto.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type FieldElement = backend::serial::fiat_u64::field::FieldElement51;
|
||||
} else if #[cfg(target_pointer_width = "64")] {
|
||||
pub use crate::backend::serial::u64::field::*;
|
||||
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
pub type FieldElement = backend::serial::u64::field::FieldElement51;
|
||||
} else {
|
||||
pub use backend::serial::u32::field::*;
|
||||
|
||||
/// A `FieldElement` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||
/// implementations.
|
||||
pub type FieldElement = backend::serial::u32::field::FieldElement2625;
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FieldElement {}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ use core::ops::{Sub, SubAssign};
|
|||
#[allow(unused_imports)]
|
||||
use crate::prelude::*;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use digest::generic_array::typenum::U64;
|
||||
|
|
@ -164,28 +166,35 @@ use zeroize::Zeroize;
|
|||
use crate::backend;
|
||||
use crate::constants;
|
||||
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
#[cfg(feature = "fiat_u32_backend")]
|
||||
type UnpackedScalar = backend::serial::fiat_u32::scalar::Scalar29;
|
||||
#[cfg(feature = "fiat_u64_backend")]
|
||||
type UnpackedScalar = backend::serial::fiat_u64::scalar::Scalar52;
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fiat_backend")] {
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
type UnpackedScalar = backend::serial::fiat_u32::scalar::Scalar29;
|
||||
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
#[cfg(feature = "u64_backend")]
|
||||
type UnpackedScalar = backend::serial::u64::scalar::Scalar52;
|
||||
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
#[cfg(feature = "u32_backend")]
|
||||
type UnpackedScalar = backend::serial::u32::scalar::Scalar29;
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
type UnpackedScalar = backend::serial::fiat_u64::scalar::Scalar52;
|
||||
} else if #[cfg(target_pointer_width = "64")] {
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
type UnpackedScalar = backend::serial::u64::scalar::Scalar52;
|
||||
} else {
|
||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||
///
|
||||
/// This is a type alias for one of the scalar types in the `backend`
|
||||
/// module.
|
||||
type UnpackedScalar = backend::serial::u32::scalar::Scalar29;
|
||||
}
|
||||
}
|
||||
|
||||
/// The `Scalar` struct holds an integer \\(s < 2\^{255} \\) which
|
||||
/// represents an element of \\(\mathbb Z / \ell\\).
|
||||
|
|
|
|||
Loading…
Reference in a new issue