From 42eaf24f5da2c66e71a48a2924900cbbd87f31f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= <34384633+tdelabro@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:21:15 +0100 Subject: [PATCH] No std crypto (#736) * all good so far * add feature serde for crypto in ensure-no_std * add feature alloc for math in ensure-no_std * math/polynomial behind alloc + remove thiserror * crypto unflag kzg * refacto(math): remove all the feature = std flags, replace by alloc * refacto(math): make ftt module no_std * clippy * uncomment licence field * fix math --no-default-features compilation + clippy * fix: FFTEError add From impl for metal and cuda errors * fix Cargo.toml + add clippy and test runs for no_std in CI --------- Co-authored-by: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> --- .github/workflows/ci.yaml | 12 +++- Cargo.toml | 10 +-- crypto/Cargo.toml | 14 +++-- crypto/src/commitments/kzg.rs | 10 +-- crypto/src/fiat_shamir/default_transcript.rs | 3 + crypto/src/hash/hash_to_field.rs | 2 + crypto/src/hash/poseidon/mod.rs | 1 + crypto/src/hash/sha3/mod.rs | 4 ++ crypto/src/lib.rs | 6 ++ .../src/merkle_tree/backends/field_element.rs | 4 +- .../backends/field_element_vector.rs | 3 +- crypto/src/merkle_tree/merkle.rs | 26 +++++++- crypto/src/merkle_tree/proof.rs | 25 +++++--- crypto/src/merkle_tree/test_merkle.rs | 2 +- crypto/src/merkle_tree/traits.rs | 1 + crypto/src/merkle_tree/utils.rs | 3 + ensure-no_std/Cargo.toml | 5 +- ensure-no_std/src/main.rs | 5 ++ math/Cargo.toml | 14 ++--- .../curves/bls12_381/compression.rs | 27 ++++---- .../curves/bls12_381/field_extension.rs | 14 +++-- .../short_weierstrass/curves/bls12_381/mod.rs | 2 +- .../curves/bls12_381/pairing.rs | 22 +++---- .../curves/bls12_381/twist.rs | 4 +- .../elliptic_curve/short_weierstrass/point.rs | 30 ++++----- math/src/fft/cpu/bit_reversing.rs | 3 +- math/src/fft/cpu/fft.rs | 7 ++- math/src/fft/cpu/mod.rs | 2 + math/src/fft/cpu/ops.rs | 2 +- math/src/fft/cpu/roots_of_unity.rs | 2 + math/src/fft/errors.rs | 63 ++++++++++++++++--- math/src/fft/mod.rs | 3 +- math/src/fft/polynomial.rs | 9 ++- math/src/fft/test_helpers.rs | 6 +- math/src/field/element.rs | 26 +++++--- math/src/field/extensions/cubic.rs | 14 +++-- math/src/field/extensions/quadratic.rs | 12 ++-- .../src/field/fields/fft_friendly/babybear.rs | 4 +- .../fft_friendly/stark_252_prime_field.rs | 4 +- .../fields/fft_friendly/u64_goldilocks.rs | 4 +- math/src/field/fields/mersenne31/field.rs | 11 ++-- .../fields/montgomery_backed_prime_fields.rs | 38 +++++------ .../fields/p448_goldilocks_prime_field.rs | 8 +-- math/src/field/fields/u64_goldilocks_field.rs | 8 +-- math/src/field/fields/u64_prime_field.rs | 29 ++++----- math/src/field/fields/winterfell.rs | 6 ++ math/src/field/test_fields/u32_test_field.rs | 8 +-- math/src/field/test_fields/u64_test_field.rs | 4 +- math/src/field/traits.rs | 10 +-- math/src/helpers.rs | 8 ++- math/src/lib.rs | 7 ++- math/src/msm/mod.rs | 1 + math/src/msm/naive.rs | 16 ++++- math/src/msm/pippenger.rs | 3 + math/src/polynomial.rs | 24 +++++-- math/src/traits.rs | 12 ++-- math/src/unsigned_integer/element.rs | 16 ++--- provers/cairo/Cargo.toml | 4 +- provers/stark/Cargo.toml | 4 +- 59 files changed, 399 insertions(+), 228 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 26f04e593..787959e8d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -79,8 +79,11 @@ jobs: - name: Run clippy run: make clippy - - name: Run clippy math no std - run: cargo clippy --package lambdaworks-math --no-default-features -- -D warnings + - name: Run clippy math and crypto no std + run: cargo clippy --package lambdaworks-math --package lambdaworks-crypto --no-default-features -- -D warnings + + - name: Run clippy math no std + alloc + run: cargo clippy --package lambdaworks-math --no-default-features --features=alloc,lambdaworks-serde-string,lambdaworks-serde-binary -- -D warnings test: name: Test (Ubuntu) @@ -112,8 +115,11 @@ jobs: tool: cargo-nextest,cargo-llvm-cov - name: Run tests with no std - run: cargo test --package lambdaworks-math --no-default-features + run: cargo test --package lambdaworks-math --package lambdaworks-crypto --no-default-features + - name: Run tests for math with no std + alloc + run: cargo test --package lambdaworks-math --no-default-features --features=alloc,lambdaworks-serde-string,lambdaworks-serde-binary + - name: Run tests and generate code coverage run: make coverage diff --git a/Cargo.toml b/Cargo.toml index 8ae4e92f7..350a9e506 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,11 +11,11 @@ repository = "https://github.com/lambdaclass/lambdaworks" [workspace.dependencies] iai-callgrind = "0.3.1" -lambdaworks-crypto = { path = "./crypto", version = "0.4.0" } -lambdaworks-gpu = { path = "./gpu", version = "0.4.0" } -lambdaworks-math = { path = "./math", version = "0.4.0" } -stark-platinum-prover = { path = "./provers/stark", version = "0.4.0" } -cairo-platinum-prover = { path = "./provers/cairo", version = "0.4.0" } +lambdaworks-crypto = { path = "./crypto", default-features = false } +lambdaworks-gpu = { path = "./gpu" } +lambdaworks-math = { path = "./math", default-features = false } +stark-platinum-prover = { path = "./provers/stark" } +cairo-platinum-prover = { path = "./provers/cairo" } [patch.crates-io] winter-air = { git = "https://github.com/lambdaclass/winterfell-for-lambdaworks.git", branch = "derive-clone-v6.4"} diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index adb02143a..b7c86f597 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -8,11 +8,12 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lambdaworks-math.workspace = true -sha3 = "0.10" -sha2 = "0.10" -thiserror = "1.0.38" -serde = { version = "1.0", features = ["derive"] } +lambdaworks-math = { workspace = true, features = ["alloc"] } +sha3 = { version = "0.10", default-features = false } +sha2 = { version = "0.10", default-features = false } + +# Optional +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true } rayon = { version = "1.8.0", optional = true } [dev-dependencies] @@ -21,6 +22,9 @@ iai-callgrind.workspace = true rand = "0.8.5" [features] +default = ["std"] +std = ["lambdaworks-math/std", "sha2/std", "sha3/std", "serde?/std"] +serde = ["dep:serde"] test_fiat_shamir = [] parallel = ["dep:rayon"] diff --git a/crypto/src/commitments/kzg.rs b/crypto/src/commitments/kzg.rs index fb33cb0ff..4fea7ed29 100644 --- a/crypto/src/commitments/kzg.rs +++ b/crypto/src/commitments/kzg.rs @@ -1,6 +1,6 @@ -use crate::errors::SrsFromFileError; - use super::traits::IsCommitmentScheme; +use alloc::{borrow::ToOwned, vec::Vec}; +use core::{marker::PhantomData, mem}; use lambdaworks_math::{ cyclic_group::IsGroup, elliptic_curve::traits::IsPairing, @@ -11,7 +11,6 @@ use lambdaworks_math::{ traits::{Deserializable, Serializable}, unsigned_integer::element::UnsignedInteger, }; -use std::{marker::PhantomData, mem}; #[derive(PartialEq, Clone, Debug)] pub struct StructuredReferenceString { @@ -32,12 +31,13 @@ where } } +#[cfg(feature = "std")] impl StructuredReferenceString where G1Point: IsGroup + Deserializable, G2Point: IsGroup + Deserializable, { - pub fn from_file(file_path: &str) -> Result { + pub fn from_file(file_path: &str) -> Result { let bytes = std::fs::read(file_path)?; Ok(Self::deserialize(&bytes)?) } @@ -252,6 +252,7 @@ impl>, P #[cfg(test)] mod tests { + use alloc::vec::Vec; use lambdaworks_math::{ cyclic_group::IsGroup, elliptic_curve::{ @@ -413,6 +414,7 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn load_srs_from_file() { type TestSrsType = StructuredReferenceString< ShortWeierstrassProjectivePoint, diff --git a/crypto/src/fiat_shamir/default_transcript.rs b/crypto/src/fiat_shamir/default_transcript.rs index f192a708e..4279ea901 100644 --- a/crypto/src/fiat_shamir/default_transcript.rs +++ b/crypto/src/fiat_shamir/default_transcript.rs @@ -1,4 +1,5 @@ use super::transcript::Transcript; +use alloc::borrow::ToOwned; use sha3::{Digest, Keccak256}; pub struct DefaultTranscript { @@ -35,6 +36,8 @@ impl DefaultTranscript { #[cfg(test)] mod tests { + use alloc::vec::Vec; + use super::*; #[test] diff --git a/crypto/src/hash/hash_to_field.rs b/crypto/src/hash/hash_to_field.rs index d452155e8..e0e898406 100644 --- a/crypto/src/hash/hash_to_field.rs +++ b/crypto/src/hash/hash_to_field.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use lambdaworks_math::{ field::{ element::FieldElement, @@ -67,6 +68,7 @@ fn build_two_to_the_nth> + Clone, const N: usize #[cfg(test)] mod tests { + use alloc::vec::Vec; use lambdaworks_math::{ field::{ element::FieldElement, diff --git a/crypto/src/hash/poseidon/mod.rs b/crypto/src/hash/poseidon/mod.rs index 5954a142f..7d61de5a3 100644 --- a/crypto/src/hash/poseidon/mod.rs +++ b/crypto/src/hash/poseidon/mod.rs @@ -1,3 +1,4 @@ +use alloc::{borrow::ToOwned, vec::Vec}; use lambdaworks_math::field::element::FieldElement as FE; pub mod parameters; diff --git a/crypto/src/hash/sha3/mod.rs b/crypto/src/hash/sha3/mod.rs index 580e63178..ee42b8991 100644 --- a/crypto/src/hash/sha3/mod.rs +++ b/crypto/src/hash/sha3/mod.rs @@ -1,3 +1,7 @@ +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; use sha3::{Digest, Sha3_256}; pub struct Sha3Hasher; diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index a3de18107..7e750015d 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -1,4 +1,10 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +extern crate alloc; + pub mod commitments; +#[cfg(feature = "std")] pub mod errors; pub mod fiat_shamir; pub mod hash; diff --git a/crypto/src/merkle_tree/backends/field_element.rs b/crypto/src/merkle_tree/backends/field_element.rs index 11171f218..cebc9646d 100644 --- a/crypto/src/merkle_tree/backends/field_element.rs +++ b/crypto/src/merkle_tree/backends/field_element.rs @@ -1,6 +1,7 @@ use crate::hash::poseidon::Poseidon; use crate::merkle_tree::traits::IsMerkleTreeBackend; +use core::marker::PhantomData; use lambdaworks_math::{ field::{element::FieldElement, traits::IsField}, traits::Serializable, @@ -9,7 +10,7 @@ use sha3::{ digest::{generic_array::GenericArray, OutputSizeUser}, Digest, }; -use std::marker::PhantomData; + #[derive(Clone)] pub struct FieldElementBackend { phantom1: PhantomData, @@ -76,6 +77,7 @@ where #[cfg(test)] mod tests { + use alloc::vec::Vec; use lambdaworks_math::field::{ element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, }; diff --git a/crypto/src/merkle_tree/backends/field_element_vector.rs b/crypto/src/merkle_tree/backends/field_element_vector.rs index 509c56752..5ea42caa4 100644 --- a/crypto/src/merkle_tree/backends/field_element_vector.rs +++ b/crypto/src/merkle_tree/backends/field_element_vector.rs @@ -1,7 +1,8 @@ -use std::marker::PhantomData; +use core::marker::PhantomData; use crate::hash::poseidon::Poseidon; use crate::merkle_tree::traits::IsMerkleTreeBackend; +use alloc::vec::Vec; use lambdaworks_math::{ field::{element::FieldElement, traits::IsField}, traits::Serializable, diff --git a/crypto/src/merkle_tree/merkle.rs b/crypto/src/merkle_tree/merkle.rs index a7ff33244..c56c8ebe6 100644 --- a/crypto/src/merkle_tree/merkle.rs +++ b/crypto/src/merkle_tree/merkle.rs @@ -1,6 +1,25 @@ +use core::fmt::Display; + +use alloc::vec::Vec; + use super::{proof::Proof, traits::IsMerkleTreeBackend, utils::*}; -#[derive(Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug)] +pub enum Error { + OutOfBounds, +} + +impl Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Accessed node was out of bound") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +#[derive(Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MerkleTree { pub root: B::Node, nodes: Vec, @@ -46,14 +65,14 @@ where Some(Proof { merkle_path }) } - fn build_merkle_path(&self, pos: usize) -> Result, std::io::Error> { + fn build_merkle_path(&self, pos: usize) -> Result, Error> { let mut merkle_path = Vec::new(); let mut pos = pos; while pos != ROOT { let Some(node) = self.nodes.get(sibling_index(pos)) else { // out of bounds, exit returning the current merkle_path - return Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)); + return Err(Error::OutOfBounds); }; merkle_path.push(node.clone()); @@ -66,6 +85,7 @@ where #[cfg(test)] mod tests { + use super::*; use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; use crate::merkle_tree::{merkle::MerkleTree, test_merkle::TestBackend}; diff --git a/crypto/src/merkle_tree/proof.rs b/crypto/src/merkle_tree/proof.rs index 21c1b9c74..788ce9d4e 100644 --- a/crypto/src/merkle_tree/proof.rs +++ b/crypto/src/merkle_tree/proof.rs @@ -1,7 +1,7 @@ -use lambdaworks_math::{ - errors::DeserializationError, - traits::{Deserializable, Serializable}, -}; +use alloc::vec::Vec; +#[cfg(feature = "alloc")] +use lambdaworks_math::traits::Serializable; +use lambdaworks_math::{errors::DeserializationError, traits::Deserializable}; use super::traits::IsMerkleTreeBackend; @@ -10,7 +10,8 @@ use super::traits::IsMerkleTreeBackend; /// `merkle_path` field, in such a way that, if the merkle tree is of height `n`, the /// `i`-th element of `merkle_path` is the sibling node in the `n - 1 - i`-th check /// when verifying. -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Proof { pub merkle_path: Vec, } @@ -36,6 +37,7 @@ impl Proof { } } +#[cfg(feature = "alloc")] impl Serializable for Proof where T: Serializable + PartialEq + Eq, @@ -67,11 +69,12 @@ where #[cfg(test)] mod tests { + #[cfg(feature = "alloc")] use super::Proof; - use lambdaworks_math::{ - field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, - traits::{Deserializable, Serializable}, - }; + use alloc::vec::Vec; + use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; + #[cfg(feature = "alloc")] + use lambdaworks_math::traits::{Deserializable, Serializable}; use crate::merkle_tree::{merkle::MerkleTree, test_merkle::TestBackend}; @@ -81,6 +84,7 @@ mod tests { pub type Ecgfp5 = U64PrimeField<0xFFFF_FFFF_0000_0001_u64>; pub type Ecgfp5FE = FieldElement; pub type TestMerkleTreeEcgfp = MerkleTree>; + #[cfg(feature = "alloc")] pub type TestProofEcgfp5 = Proof; const MODULUS: u64 = 13; @@ -88,6 +92,7 @@ mod tests { type FE = FieldElement; #[test] + #[cfg(feature = "alloc")] fn serialize_proof_and_deserialize_using_be_it_get_a_consistent_proof() { let merkle_path = [Ecgfp5FE::new(2), Ecgfp5FE::new(1), Ecgfp5FE::new(1)].to_vec(); let original_proof = TestProofEcgfp5 { merkle_path }; @@ -100,6 +105,7 @@ mod tests { } #[test] + #[cfg(feature = "alloc")] fn serialize_proof_and_deserialize_using_le_it_get_a_consistent_proof() { let merkle_path = [Ecgfp5FE::new(2), Ecgfp5FE::new(1), Ecgfp5FE::new(1)].to_vec(); let original_proof = TestProofEcgfp5 { merkle_path }; @@ -123,6 +129,7 @@ mod tests { } #[test] + #[cfg(feature = "alloc")] fn merkle_proof_verifies_after_serialization_and_deserialization() { let values: Vec = (1..6).map(Ecgfp5FE::new).collect(); let merkle_tree = TestMerkleTreeEcgfp::build(&values); diff --git a/crypto/src/merkle_tree/test_merkle.rs b/crypto/src/merkle_tree/test_merkle.rs index 4fc8e2cdc..746ff6a83 100644 --- a/crypto/src/merkle_tree/test_merkle.rs +++ b/crypto/src/merkle_tree/test_merkle.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use core::marker::PhantomData; use lambdaworks_math::field::{element::FieldElement, traits::IsField}; diff --git a/crypto/src/merkle_tree/traits.rs b/crypto/src/merkle_tree/traits.rs index dce3e253b..38b6bf143 100644 --- a/crypto/src/merkle_tree/traits.rs +++ b/crypto/src/merkle_tree/traits.rs @@ -1,3 +1,4 @@ +use alloc::vec::Vec; #[cfg(feature = "parallel")] use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; diff --git a/crypto/src/merkle_tree/utils.rs b/crypto/src/merkle_tree/utils.rs index ab76176bb..a93df7df8 100644 --- a/crypto/src/merkle_tree/utils.rs +++ b/crypto/src/merkle_tree/utils.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + use super::traits::IsMerkleTreeBackend; pub fn sibling_index(node_index: usize) -> usize { @@ -59,6 +61,7 @@ pub fn right_child_index(parent_index: usize) -> usize { #[cfg(test)] mod tests { + use alloc::vec::Vec; use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; use crate::merkle_tree::{test_merkle::TestBackend, traits::IsMerkleTreeBackend}; diff --git a/ensure-no_std/Cargo.toml b/ensure-no_std/Cargo.toml index 2818628b0..492686ab4 100644 --- a/ensure-no_std/Cargo.toml +++ b/ensure-no_std/Cargo.toml @@ -5,7 +5,10 @@ edition = "2021" [dependencies] -lambdaworks-math = { path = "../math", default-features = false } +lambdaworks-math = { path = "../math", default-features = false, features = ["alloc", "lambdaworks-serde-binary", "lambdaworks-serde-string"] } +lambdaworks-crypto = { path = "../crypto", default-features = false, features = ["serde"] } + +wee_alloc = "0.4.5" [profile.dev] panic = "abort" diff --git a/ensure-no_std/src/main.rs b/ensure-no_std/src/main.rs index dad5877d0..2b547cda4 100644 --- a/ensure-no_std/src/main.rs +++ b/ensure-no_std/src/main.rs @@ -14,5 +14,10 @@ fn panic(_info: &PanicInfo) -> ! { loop {} } +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +#[allow(unused_imports)] +use lambdaworks_crypto; #[allow(unused_imports)] use lambdaworks_math; diff --git a/math/Cargo.toml b/math/Cargo.toml index 287ebd72c..24d041398 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -8,9 +8,8 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -thiserror = { version = "1.0", optional = true } -serde = { version = "1.0", features = ["derive"], optional = true } -serde_json = { version = "1.0", optional = true } +serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } +serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true } proptest = { version = "1.1.0", optional = true } winter-math = { package = "winter-math", version = "0.6.4", default-features = false, optional = true } miden-core = { package = "miden-core" , version = "0.7", default-features = false, optional = true } @@ -37,11 +36,12 @@ proptest = "1.1.0" pprof = { version = "0.13.0", features = ["criterion","flamegraph"] } [features] -rayon = ["dep:rayon"] default = ["rayon", "std"] -std = ["dep:thiserror"] -lambdaworks-serde-binary = ["dep:serde", "std"] -lambdaworks-serde-string = ["dep:serde", "dep:serde_json", "std"] +std = ["alloc", "serde?/std", "serde_json?/std"] +alloc = [] +rayon = ["dep:rayon"] +lambdaworks-serde-binary = ["dep:serde", "alloc"] +lambdaworks-serde-string = ["dep:serde", "dep:serde_json", "alloc"] proptest = ["dep:proptest"] winter_compatibility = ["winter-math", "miden-core"] diff --git a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/compression.rs b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/compression.rs index effa080bc..058496f76 100644 --- a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/compression.rs +++ b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/compression.rs @@ -5,10 +5,8 @@ use crate::{ }, field::element::FieldElement, }; -#[cfg(feature = "std")] -use std::{cmp::Ordering, ops::Neg}; +use core::cmp::Ordering; -#[cfg(feature = "std")] use crate::{ cyclic_group::IsGroup, elliptic_curve::traits::FromAffine, errors::ByteConversionError, traits::ByteConversion, @@ -17,7 +15,6 @@ use crate::{ pub type G1Point = ShortWeierstrassProjectivePoint; pub type BLS12381FieldElement = FieldElement; -#[cfg(feature = "std")] pub fn decompress_g1_point(input_bytes: &mut [u8; 48]) -> Result { let first_byte = input_bytes.first().unwrap(); // We get the 3 most significant bits @@ -68,11 +65,11 @@ pub fn decompress_g1_point(input_bytes: &mut [u8; 48]) -> Result Vec { +#[cfg(feature = "alloc")] +pub fn compress_g1_point(point: &G1Point) -> alloc::vec::Vec { if *point == G1Point::neutral_element() { // point is at infinity - let mut x_bytes = vec![0_u8; 48]; + let mut x_bytes = alloc::vec![0_u8; 48]; x_bytes[0] |= 1 << 7; x_bytes[0] |= 1 << 6; x_bytes @@ -87,7 +84,7 @@ pub fn compress_g1_point(point: &G1Point) -> Vec { // Set first bit to to 1 indicate this is compressed element. x_bytes[0] |= 1 << 7; - let y_neg = y.neg(); + let y_neg = core::ops::Neg::neg(y); if y_neg.representative() < y.representative() { x_bytes[0] |= 1 << 5; } @@ -101,9 +98,9 @@ mod tests { use crate::elliptic_curve::short_weierstrass::curves::bls12_381::curve::BLS12381Curve; use crate::elliptic_curve::traits::{FromAffine, IsEllipticCurve}; - #[cfg(feature = "std")] - use super::{compress_g1_point, decompress_g1_point}; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] + use super::compress_g1_point; + use super::decompress_g1_point; use crate::{ cyclic_group::IsGroup, traits::ByteConversion, unsigned_integer::element::UnsignedInteger, }; @@ -121,7 +118,7 @@ mod tests { assert!(!false_point2.is_in_subgroup()); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_g1_compress_generator() { let g = BLS12381Curve::generator(); @@ -137,7 +134,7 @@ mod tests { assert_eq!(*g_x, compressed_g_x); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_g1_compress_point_at_inf() { let inf = G1Point::neutral_element(); @@ -147,7 +144,7 @@ mod tests { assert_eq!(*first_byte >> 6, 3_u8); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_compress_decompress_generator() { let g = BLS12381Curve::generator(); @@ -159,7 +156,7 @@ mod tests { assert_eq!(g, decompressed_g); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_compress_decompress_2g() { let g = BLS12381Curve::generator(); diff --git a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/field_extension.rs b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/field_extension.rs index 4d57d18cd..b97f51218 100644 --- a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/field_extension.rs +++ b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/field_extension.rs @@ -143,22 +143,24 @@ impl IsSubFieldOf for BLS12381PrimeField { [FieldElement::from_raw(a), FieldElement::zero()] } - #[cfg(feature = "std")] - fn to_subfield_vec(b: ::BaseType) -> Vec { + #[cfg(feature = "alloc")] + fn to_subfield_vec( + b: ::BaseType, + ) -> alloc::vec::Vec { b.into_iter().map(|x| x.to_raw()).collect() } } impl ByteConversion for FieldElement { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { let mut byte_slice = ByteConversion::to_bytes_be(&self.value()[0]); byte_slice.extend(ByteConversion::to_bytes_be(&self.value()[1])); byte_slice } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { let mut byte_slice = ByteConversion::to_bytes_le(&self.value()[0]); byte_slice.extend(ByteConversion::to_bytes_le(&self.value()[1])); byte_slice diff --git a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/mod.rs b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/mod.rs index c77622122..0ce0e6803 100644 --- a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/mod.rs +++ b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/mod.rs @@ -5,5 +5,5 @@ pub mod field_extension; pub mod sqrt; pub mod twist; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub mod pairing; diff --git a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/pairing.rs b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/pairing.rs index 0e2afa809..1d6d37f80 100644 --- a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/pairing.rs +++ b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/pairing.rs @@ -1,19 +1,17 @@ +use super::curve::MILLER_LOOP_CONSTANT; use super::{ - curve::{BLS12381Curve, MILLER_LOOP_CONSTANT}, + curve::BLS12381Curve, field_extension::{BLS12381PrimeField, Degree12ExtensionField, Degree2ExtensionField}, twist::BLS12381TwistCurve, }; +use crate::{cyclic_group::IsGroup, elliptic_curve::traits::IsPairing, errors::PairingError}; + use crate::{ - cyclic_group::IsGroup, - elliptic_curve::{ - short_weierstrass::{ - curves::bls12_381::field_extension::{Degree6ExtensionField, LevelTwoResidue}, - point::ShortWeierstrassProjectivePoint, - traits::IsShortWeierstrass, - }, - traits::IsPairing, + elliptic_curve::short_weierstrass::{ + curves::bls12_381::field_extension::{Degree6ExtensionField, LevelTwoResidue}, + point::ShortWeierstrassProjectivePoint, + traits::IsShortWeierstrass, }, - errors::PairingError, field::{element::FieldElement, extensions::cubic::HasCubicNonResidue}, unsigned_integer::element::{UnsignedInteger, U256}, }; @@ -23,6 +21,7 @@ pub const SUBGROUP_ORDER: U256 = #[derive(Clone)] pub struct BLS12381AtePairing; + impl IsPairing for BLS12381AtePairing { type G1Point = ShortWeierstrassProjectivePoint; type G2Point = ShortWeierstrassProjectivePoint; @@ -101,6 +100,7 @@ fn double_accumulate_line( ]), ]); } + fn add_accumulate_line( t: &mut ShortWeierstrassProjectivePoint, q: &ShortWeierstrassProjectivePoint, @@ -163,7 +163,7 @@ fn miller( let mut r = q.clone(); let mut f = FieldElement::::one(); let mut miller_loop_constant = MILLER_LOOP_CONSTANT; - let mut miller_loop_constant_bits: Vec = vec![]; + let mut miller_loop_constant_bits: alloc::vec::Vec = alloc::vec![]; while miller_loop_constant > 0 { miller_loop_constant_bits.insert(0, (miller_loop_constant & 1) == 1); diff --git a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/twist.rs b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/twist.rs index 8853f0c10..2a27516b0 100644 --- a/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/twist.rs +++ b/math/src/elliptic_curve/short_weierstrass/curves/bls12_381/twist.rs @@ -97,7 +97,7 @@ mod tests { type Level0FE = FieldElement; type Level1FE = FieldElement; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] use crate::elliptic_curve::short_weierstrass::point::{ Endianness, PointFormat, ShortWeierstrassProjectivePoint, }; @@ -112,7 +112,7 @@ mod tests { ); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn serialize_deserialize_generator() { let g = BLS12381TwistCurve::generator(); diff --git a/math/src/elliptic_curve/short_weierstrass/point.rs b/math/src/elliptic_curve/short_weierstrass/point.rs index d4adf0f92..4671f863f 100644 --- a/math/src/elliptic_curve/short_weierstrass/point.rs +++ b/math/src/elliptic_curve/short_weierstrass/point.rs @@ -11,8 +11,10 @@ use crate::{ use super::traits::IsShortWeierstrass; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use crate::traits::Serializable; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; #[derive(Clone, Debug)] pub struct ShortWeierstrassProjectivePoint(pub ProjectivePoint); @@ -231,7 +233,7 @@ where FieldElement: ByteConversion, { /// Serialize the points in the given format - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn serialize(&self, point_format: PointFormat, endianness: Endianness) -> Vec { // TODO: Add more compact serialization formats // Uncompressed affine / Compressed @@ -340,7 +342,7 @@ where } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Serializable for ShortWeierstrassProjectivePoint where E: IsShortWeierstrass, @@ -369,24 +371,24 @@ mod tests { use super::*; use crate::elliptic_curve::short_weierstrass::curves::bls12_381::curve::BLS12381Curve; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] use crate::{ elliptic_curve::short_weierstrass::curves::bls12_381::field_extension::BLS12381PrimeField, field::element::FieldElement, }; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::upper_case_acronyms)] type FEE = FieldElement; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn point() -> ShortWeierstrassProjectivePoint { let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); BLS12381Curve::create_point_from_affine(x, y).unwrap() } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_be_projective() { let expected_point = point(); @@ -400,7 +402,7 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_be_uncompressed() { let expected_point = point(); @@ -413,7 +415,7 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_le_projective() { let expected_point = point(); @@ -427,7 +429,7 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_le_uncompressed() { let expected_point = point(); @@ -442,7 +444,7 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_le_and_be_does_not_work_projective() { let bytes = point().serialize(PointFormat::Projective, Endianness::LittleEndian); @@ -459,7 +461,7 @@ mod tests { ); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_le_and_be_does_not_work_uncompressed() { let bytes = point().serialize(PointFormat::Uncompressed, Endianness::LittleEndian); @@ -476,7 +478,7 @@ mod tests { ); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_be_and_le_does_not_work_projective() { let bytes = point().serialize(PointFormat::Projective, Endianness::BigEndian); @@ -493,7 +495,7 @@ mod tests { ); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_be_and_le_does_not_work_uncompressed() { let bytes = point().serialize(PointFormat::Uncompressed, Endianness::BigEndian); diff --git a/math/src/fft/cpu/bit_reversing.rs b/math/src/fft/cpu/bit_reversing.rs index 68eb73427..f225dd5e0 100644 --- a/math/src/fft/cpu/bit_reversing.rs +++ b/math/src/fft/cpu/bit_reversing.rs @@ -17,9 +17,10 @@ pub fn reverse_index(i: usize, size: u64) -> usize { } } -#[cfg(test)] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; + use alloc::vec::Vec; // TODO: proptest would be better. #[test] diff --git a/math/src/fft/cpu/fft.rs b/math/src/fft/cpu/fft.rs index e2910f8cd..8e8e82b87 100644 --- a/math/src/fft/cpu/fft.rs +++ b/math/src/fft/cpu/fft.rs @@ -177,12 +177,13 @@ where } } -#[cfg(test)] +#[cfg(all(test, feature = "alloc"))] mod tests { use crate::fft::cpu::bit_reversing::in_place_bit_reverse_permute; use crate::fft::cpu::roots_of_unity::get_twiddles; use crate::fft::test_helpers::naive_matrix_dft_test; use crate::field::{test_fields::u64_test_field::U64TestField, traits::RootsConfig}; + use alloc::format; use proptest::{collection, prelude::*}; use super::*; @@ -201,12 +202,12 @@ mod tests { } } prop_compose! { - fn field_vec(max_exp: u8)(vec in (1..max_exp).prop_flat_map(|i| collection::vec(field_element(), 1 << i))) -> Vec { + fn field_vec(max_exp: u8)(vec in (1..max_exp).prop_flat_map(|i| collection::vec(field_element(), 1 << i))) -> alloc::vec::Vec { vec } } prop_compose! { - fn field_vec_r4(max_exp: u8)(vec in (1..max_exp).prop_flat_map(|i| collection::vec(field_element(), 1 << (2 * i)))) -> Vec { + fn field_vec_r4(max_exp: u8)(vec in (1..max_exp).prop_flat_map(|i| collection::vec(field_element(), 1 << (2 * i)))) -> alloc::vec::Vec { vec } } diff --git a/math/src/fft/cpu/mod.rs b/math/src/fft/cpu/mod.rs index 92484abe0..8f296f412 100644 --- a/math/src/fft/cpu/mod.rs +++ b/math/src/fft/cpu/mod.rs @@ -1,4 +1,6 @@ pub mod bit_reversing; pub mod fft; +#[cfg(feature = "alloc")] pub mod ops; +#[cfg(feature = "alloc")] pub mod roots_of_unity; diff --git a/math/src/fft/cpu/ops.rs b/math/src/fft/cpu/ops.rs index f4bdffd7a..da887cb70 100644 --- a/math/src/fft/cpu/ops.rs +++ b/math/src/fft/cpu/ops.rs @@ -13,7 +13,7 @@ use super::{bit_reversing::in_place_bit_reverse_permute, fft::in_place_nr_2radix pub fn fft, E: IsField>( input: &[FieldElement], twiddles: &[FieldElement], -) -> Result>, FFTError> { +) -> Result>, FFTError> { if !input.len().is_power_of_two() { return Err(FFTError::InputError(input.len())); } diff --git a/math/src/fft/cpu/roots_of_unity.rs b/math/src/fft/cpu/roots_of_unity.rs index 43456860e..29c2d8e58 100644 --- a/math/src/fft/cpu/roots_of_unity.rs +++ b/math/src/fft/cpu/roots_of_unity.rs @@ -2,6 +2,7 @@ use crate::field::{ element::FieldElement, traits::{IsFFTField, RootsConfig}, }; +use alloc::vec::Vec; use crate::fft::errors::FFTError; @@ -82,6 +83,7 @@ mod tests { }, field::{test_fields::u64_test_field::U64TestField, traits::RootsConfig}, }; + use alloc::format; use proptest::prelude::*; type F = U64TestField; diff --git a/math/src/fft/errors.rs b/math/src/fft/errors.rs index b599e4eac..4bbec91c2 100644 --- a/math/src/fft/errors.rs +++ b/math/src/fft/errors.rs @@ -1,5 +1,6 @@ +use core::fmt::Display; + use crate::field::errors::FieldError; -use thiserror::Error; #[cfg(feature = "metal")] use lambdaworks_gpu::metal::abstractions::errors::MetalError; @@ -7,20 +8,64 @@ use lambdaworks_gpu::metal::abstractions::errors::MetalError; #[cfg(feature = "cuda")] use lambdaworks_gpu::cuda::abstractions::errors::CudaError; -#[derive(Debug, Error)] +#[derive(Debug)] pub enum FFTError { - #[error("Could not calculate root of unity")] RootOfUnityError(u64), - #[error("Input length is {0}, which is not a power of two")] InputError(usize), - #[error("Order should be less than or equal to 63, but is {0}")] OrderError(u64), #[cfg(feature = "metal")] - #[error("A Metal related error has ocurred")] - MetalError(#[from] MetalError), + MetalError(MetalError), #[cfg(feature = "cuda")] - #[error("A CUDA related error has ocurred")] - CudaError(#[from] CudaError), + CudaError(CudaError), +} + +impl Display for FFTError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + FFTError::RootOfUnityError(_) => write!(f, "Could not calculate root of unity"), + FFTError::InputError(v) => { + write!(f, "Input length is {v}, which is not a power of two") + } + FFTError::OrderError(v) => { + write!(f, "Order should be less than or equal to 63, but is {v}") + } + #[cfg(feature = "metal")] + FFTError::MetalError(_) => { + write!(f, "A Metal related error has ocurred") + } + #[cfg(feature = "cuda")] + FFTError::CudaError(_) => { + write!(f, "A CUDA related error has ocurred") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FFTError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + #[cfg(feature = "metal")] + FFTError::MetalError(e) => Some(e), + #[cfg(feature = "cuda")] + FFTError::CudaError(_) => Some(e), + _ => None, + } + } +} + +#[cfg(feature = "metal")] +impl From for FFTError { + fn from(error: MetalError) -> Self { + Self::MetalError(error) + } +} + +#[cfg(feature = "cuda")] +impl From for FFTError { + fn from(error: CudaError) -> Self { + Self::CudaError(error) + } } impl From for FFTError { diff --git a/math/src/fft/mod.rs b/math/src/fft/mod.rs index f204adf98..51080aaef 100644 --- a/math/src/fft/mod.rs +++ b/math/src/fft/mod.rs @@ -1,7 +1,8 @@ pub mod cpu; pub mod errors; pub mod gpu; +#[cfg(feature = "alloc")] pub mod polynomial; -#[cfg(test)] +#[cfg(all(test, feature = "alloc"))] pub(crate) mod test_helpers; diff --git a/math/src/fft/polynomial.rs b/math/src/fft/polynomial.rs index 481e32692..a27811d31 100644 --- a/math/src/fft/polynomial.rs +++ b/math/src/fft/polynomial.rs @@ -8,6 +8,7 @@ use crate::{ }, polynomial::Polynomial, }; +use alloc::{vec, vec::Vec}; #[cfg(feature = "cuda")] use crate::fft::gpu::cuda::polynomial::{evaluate_fft_cuda, interpolate_fft_cuda}; @@ -27,7 +28,7 @@ impl Polynomial> { domain_size: Option, ) -> Result>, FFTError> { let domain_size = domain_size.unwrap_or(0); - let len = std::cmp::max(poly.coeff_len(), domain_size).next_power_of_two() * blowup_factor; + let len = core::cmp::max(poly.coeff_len(), domain_size).next_power_of_two() * blowup_factor; if poly.coefficients().is_empty() { return Ok(vec![FieldElement::zero(); len]); @@ -44,7 +45,7 @@ impl Polynomial> { } else { println!( "GPU evaluation failed for field {}. Program will fallback to CPU.", - std::any::type_name::() + core::any::type_name::() ); evaluate_fft_cpu::(&coeffs) } @@ -93,7 +94,7 @@ impl Polynomial> { } else { println!( "GPU interpolation failed for field {}. Program will fallback to CPU.", - std::any::type_name::() + core::any::type_name::() ); interpolate_fft_cpu::(fft_evals) } @@ -177,6 +178,8 @@ mod tests { #[cfg(all(not(feature = "metal"), not(feature = "cuda")))] use crate::field::traits::IsField; + use alloc::format; + use crate::field::{ test_fields::u64_test_field::{U64TestField, U64TestFieldExtension}, traits::RootsConfig, diff --git a/math/src/fft/test_helpers.rs b/math/src/fft/test_helpers.rs index 0c177a1da..272bdaa99 100644 --- a/math/src/fft/test_helpers.rs +++ b/math/src/fft/test_helpers.rs @@ -5,6 +5,7 @@ use crate::{ traits::{IsFFTField, RootsConfig}, }, }; +use alloc::vec::Vec; /// Calculates the (non-unitary) Discrete Fourier Transform of `input` via the DFT matrix. pub fn naive_matrix_dft_test(input: &[FieldElement]) -> Vec> { @@ -32,10 +33,11 @@ pub fn naive_matrix_dft_test(input: &[FieldElement]) -> Vec; diff --git a/math/src/field/element.rs b/math/src/field/element.rs index 400719507..890cc373c 100644 --- a/math/src/field/element.rs +++ b/math/src/field/element.rs @@ -41,7 +41,7 @@ pub struct FieldElement { value: F::BaseType, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl FieldElement { // Source: https://en.wikipedia.org/wiki/Modular_multiplicative_inverse#Multiple_inverses pub fn inplace_batch_inverse(numbers: &mut [Self]) -> Result<(), FieldError> { @@ -49,7 +49,7 @@ impl FieldElement { return Ok(()); } let count = numbers.len(); - let mut prod_prefix = Vec::with_capacity(count); + let mut prod_prefix = alloc::vec::Vec::with_capacity(count); prod_prefix.push(numbers[0].clone()); for i in 1..count { prod_prefix.push(&prod_prefix[i - 1] * &numbers[i]); @@ -65,7 +65,7 @@ impl FieldElement { } #[inline(always)] - pub fn to_subfield_vec(self) -> Vec> + pub fn to_subfield_vec(self) -> alloc::vec::Vec> where S: IsSubFieldOf, { @@ -557,7 +557,7 @@ where where M: MapAccess<'de>, { - let mut value: Option> = None; + let mut value: Option> = None; while let Some(key) = map.next_key()? { match key { Field::Value => { @@ -577,7 +577,7 @@ where where S: SeqAccess<'de>, { - let mut value: Option> = None; + let mut value: Option> = None; while let Some(val) = seq.next_element()? { if value.is_some() { return Err(de::Error::duplicate_field("value")); @@ -696,9 +696,11 @@ mod tests { use crate::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField; use crate::field::fields::u64_prime_field::U64PrimeField; use crate::field::test_fields::u64_test_field::U64TestField; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] use crate::unsigned_integer::element::UnsignedInteger; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] + use alloc::vec::Vec; + #[cfg(feature = "alloc")] use proptest::collection; use proptest::{prelude::*, prop_compose, proptest, strategy::Strategy}; @@ -727,9 +729,11 @@ mod tests { ); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_display_montgomery_field() { + use alloc::format; + let zero_field_element = FieldElement::::from(0); assert_eq!(format!("{}", zero_field_element), "0x0"); @@ -849,16 +853,18 @@ mod tests { } prop_compose! { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn field_vec(max_exp: u8)(vec in collection::vec(field_element(), 0..1 << max_exp)) -> Vec> { vec } } proptest! { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_inplace_batch_inverse_returns_inverses(vec in field_vec(10)) { + use alloc::format; + let input: Vec<_> = vec.into_iter().filter(|x| x != &FieldElement::::zero()).collect(); let mut inverses = input.clone(); FieldElement::inplace_batch_inverse(&mut inverses).unwrap(); diff --git a/math/src/field/extensions/cubic.rs b/math/src/field/extensions/cubic.rs index 7443b48a7..d05e1fa9d 100644 --- a/math/src/field/extensions/cubic.rs +++ b/math/src/field/extensions/cubic.rs @@ -30,13 +30,13 @@ impl ByteConversion for [FieldElement; 3] where F: IsField, { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { unimplemented!() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { unimplemented!() } @@ -203,8 +203,10 @@ where ] } - #[cfg(feature = "std")] - fn to_subfield_vec(b: as IsField>::BaseType) -> Vec { + #[cfg(feature = "alloc")] + fn to_subfield_vec( + b: as IsField>::BaseType, + ) -> alloc::vec::Vec { b.into_iter().map(|x| x.to_raw()).collect() } } diff --git a/math/src/field/extensions/quadratic.rs b/math/src/field/extensions/quadratic.rs index 6cd3fd46f..77ab87a0d 100644 --- a/math/src/field/extensions/quadratic.rs +++ b/math/src/field/extensions/quadratic.rs @@ -43,13 +43,13 @@ impl ByteConversion for [FieldElement; 2] where F: IsField, { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { unimplemented!() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { unimplemented!() } @@ -194,10 +194,10 @@ where [FieldElement::from_raw(a), FieldElement::zero()] } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_subfield_vec( b: as IsField>::BaseType, - ) -> Vec { + ) -> alloc::vec::Vec { b.into_iter().map(|x| x.to_raw()).collect() } } diff --git a/math/src/field/fields/fft_friendly/babybear.rs b/math/src/field/fields/fft_friendly/babybear.rs index a516e8523..d294aff38 100644 --- a/math/src/field/fields/fft_friendly/babybear.rs +++ b/math/src/field/fields/fft_friendly/babybear.rs @@ -56,7 +56,7 @@ mod tests { use crate::{field::element::FieldElement, traits::ByteConversion}; #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_le() { let element = FieldElement::::from_hex_unchecked("0123456701234567"); @@ -66,7 +66,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_be() { let element = FieldElement::::from_hex_unchecked("0123456701234567"); diff --git a/math/src/field/fields/fft_friendly/stark_252_prime_field.rs b/math/src/field/fields/fft_friendly/stark_252_prime_field.rs index 737a21014..999c1afae 100644 --- a/math/src/field/fields/fft_friendly/stark_252_prime_field.rs +++ b/math/src/field/fields/fft_friendly/stark_252_prime_field.rs @@ -102,7 +102,7 @@ mod test_stark_252_bytes_ops { use crate::{field::element::FieldElement, traits::ByteConversion}; #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_le() { let element = FieldElement::::from_hex_unchecked( "\ @@ -118,7 +118,7 @@ mod test_stark_252_bytes_ops { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_be() { let element = FieldElement::::from_hex_unchecked( "\ diff --git a/math/src/field/fields/fft_friendly/u64_goldilocks.rs b/math/src/field/fields/fft_friendly/u64_goldilocks.rs index 7b35e4405..ca2cec138 100644 --- a/math/src/field/fields/fft_friendly/u64_goldilocks.rs +++ b/math/src/field/fields/fft_friendly/u64_goldilocks.rs @@ -49,7 +49,7 @@ mod test_u64_goldilocks_bytes_ops { use crate::{field::element::FieldElement, traits::ByteConversion}; #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_le() { let element = FieldElement::::from_hex_unchecked( "\ @@ -62,7 +62,7 @@ mod test_u64_goldilocks_bytes_ops { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_be() { let element = FieldElement::::from_hex_unchecked( "\ diff --git a/math/src/field/fields/mersenne31/field.rs b/math/src/field/fields/mersenne31/field.rs index 5454cd681..0d85ba146 100644 --- a/math/src/field/fields/mersenne31/field.rs +++ b/math/src/field/fields/mersenne31/field.rs @@ -181,21 +181,20 @@ impl IsPrimeField for Mersenne31Field { } impl FieldElement { - #[cfg(feature = "std")] - pub fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + pub fn to_bytes_le(&self) -> alloc::vec::Vec { self.representative().to_le_bytes().to_vec() } - #[cfg(feature = "std")] - pub fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + pub fn to_bytes_be(&self) -> alloc::vec::Vec { self.representative().to_be_bytes().to_vec() } } impl Display for FieldElement { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:x}", self.representative())?; - Ok(()) + write!(f, "{:x}", self.representative()) } } diff --git a/math/src/field/fields/montgomery_backed_prime_fields.rs b/math/src/field/fields/montgomery_backed_prime_fields.rs index e2e0f66a4..475b4d9c6 100644 --- a/math/src/field/fields/montgomery_backed_prime_fields.rs +++ b/math/src/field/fields/montgomery_backed_prime_fields.rs @@ -1,7 +1,9 @@ use crate::field::element::FieldElement; use crate::field::errors::FieldError; use crate::field::traits::IsPrimeField; -use crate::traits::{ByteConversion, Serializable}; +use crate::traits::ByteConversion; +#[cfg(feature = "alloc")] +use crate::traits::Serializable; use crate::{ field::traits::IsField, unsigned_integer::element::UnsignedInteger, unsigned_integer::montgomery::MontgomeryAlgorithms, @@ -326,8 +328,8 @@ impl ByteConversion where M: IsModulus> + Clone + Debug, { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { MontgomeryAlgorithms::cios( self.value(), &UnsignedInteger::from_u64(1), @@ -337,8 +339,8 @@ where .to_bytes_be() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { MontgomeryAlgorithms::cios( self.value(), &UnsignedInteger::from_u64(1), @@ -359,13 +361,13 @@ where } } +#[cfg(feature = "alloc")] impl Serializable for FieldElement> where M: IsModulus> + Clone + Debug, { - #[cfg(feature = "std")] - fn serialize(&self) -> Vec { + fn serialize(&self) -> alloc::vec::Vec { self.value().to_bytes_be() } } @@ -379,7 +381,7 @@ mod tests_u384_prime_fields { }; use crate::field::traits::IsField; use crate::field::traits::IsPrimeField; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] use crate::traits::ByteConversion; use crate::unsigned_integer::element::U384; use crate::unsigned_integer::element::{UnsignedInteger, U256}; @@ -715,7 +717,7 @@ mod tests_u384_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_bytes_from_bytes_be_is_the_identity() { let x = U384FP2Element::new(UnsignedInteger::from_hex_unchecked( "5f103b0bd4397d4df560eb559f38353f80eeb6", @@ -724,7 +726,7 @@ mod tests_u384_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_bytes_to_bytes_be_is_the_identity_for_one() { let bytes = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -737,7 +739,7 @@ mod tests_u384_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_bytes_from_bytes_le_is_the_identity() { let x = U384FP2Element::new(UnsignedInteger::from_hex_unchecked( "5f103b0bd4397d4df560eb559f38353f80eeb6", @@ -746,7 +748,7 @@ mod tests_u384_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_bytes_to_bytes_le_is_the_identity_for_one() { let bytes = [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -766,7 +768,7 @@ mod tests_u256_prime_fields { use crate::field::fields::montgomery_backed_prime_fields::{IsModulus, U256PrimeField}; use crate::field::traits::IsField; use crate::field::traits::IsPrimeField; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] use crate::traits::ByteConversion; use crate::unsigned_integer::element::U256; use crate::unsigned_integer::element::{UnsignedInteger, U64}; @@ -1051,7 +1053,7 @@ mod tests_u256_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_bytes_from_bytes_be_is_the_identity() { let x = FP2Element::new(UnsignedInteger::from_hex_unchecked( "5f103b0bd4397d4df560eb559f38353f80eeb6", @@ -1060,7 +1062,7 @@ mod tests_u256_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_bytes_to_bytes_be_is_the_identity_for_one() { let bytes = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1073,7 +1075,7 @@ mod tests_u256_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_bytes_from_bytes_le_is_the_identity() { let x = FP2Element::new(UnsignedInteger::from_hex_unchecked( "5f103b0bd4397d4df560eb559f38353f80eeb6", @@ -1082,7 +1084,7 @@ mod tests_u256_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_bytes_to_bytes_le_is_the_identity_for_one() { let bytes = [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1095,7 +1097,7 @@ mod tests_u256_prime_fields { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn creating_a_field_element_from_its_representative_returns_the_same_element_1() { let change = U256::from_u64(1); let f1 = U256FP1Element::new(U256ModulusP1::MODULUS + change); diff --git a/math/src/field/fields/p448_goldilocks_prime_field.rs b/math/src/field/fields/p448_goldilocks_prime_field.rs index 5e927386c..9f67fd1d2 100644 --- a/math/src/field/fields/p448_goldilocks_prime_field.rs +++ b/math/src/field/fields/p448_goldilocks_prime_field.rs @@ -23,13 +23,13 @@ pub struct U56x8 { #[cfg(feature = "lambdaworks-serde-binary")] impl ByteConversion for U56x8 { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { unimplemented!() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { unimplemented!() } diff --git a/math/src/field/fields/u64_goldilocks_field.rs b/math/src/field/fields/u64_goldilocks_field.rs index bfbd7802c..5c1a29d3c 100644 --- a/math/src/field/fields/u64_goldilocks_field.rs +++ b/math/src/field/fields/u64_goldilocks_field.rs @@ -24,13 +24,13 @@ impl Goldilocks64Field { #[cfg(feature = "lambdaworks-serde-binary")] impl ByteConversion for u64 { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { unimplemented!() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { unimplemented!() } diff --git a/math/src/field/fields/u64_prime_field.rs b/math/src/field/fields/u64_prime_field.rs index b300464bd..764263b54 100644 --- a/math/src/field/fields/u64_prime_field.rs +++ b/math/src/field/fields/u64_prime_field.rs @@ -1,14 +1,13 @@ use crate::cyclic_group::IsGroup; -#[cfg(feature = "std")] use crate::errors::ByteConversionError::{FromBEBytesError, FromLEBytesError}; use crate::errors::CreationError; -#[cfg(feature = "std")] use crate::errors::DeserializationError; use crate::field::element::FieldElement; use crate::field::errors::FieldError; use crate::field::traits::{IsFFTField, IsField, IsPrimeField}; -#[cfg(feature = "std")] -use crate::traits::{ByteConversion, Deserializable, Serializable}; +#[cfg(feature = "alloc")] +use crate::traits::Serializable; +use crate::traits::{ByteConversion, Deserializable}; /// Type representing prime fields over unsigned 64-bit integers. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -124,15 +123,14 @@ impl IsGroup for U64FieldElement { } } -#[cfg(feature = "std")] impl ByteConversion for U64FieldElement { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { u64::to_be_bytes(*self.value()).into() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { u64::to_le_bytes(*self.value()).into() } @@ -147,14 +145,13 @@ impl ByteConversion for U64FieldElement { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Serializable for FieldElement> { - fn serialize(&self) -> Vec { + fn serialize(&self) -> alloc::vec::Vec { self.to_bytes_be() } } -#[cfg(feature = "std")] impl Deserializable for FieldElement> { fn deserialize(bytes: &[u8]) -> Result where @@ -347,28 +344,28 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_bytes_from_bytes_be_is_the_identity() { let x = FE::new(12345); assert_eq!(FE::from_bytes_be(&x.to_bytes_be()).unwrap(), x); } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_bytes_to_bytes_be_is_the_identity_for_one() { let bytes = [0, 0, 0, 0, 0, 0, 0, 1]; assert_eq!(FE::from_bytes_be(&bytes).unwrap().to_bytes_be(), bytes); } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_bytes_from_bytes_le_is_the_identity() { let x = FE::new(12345); assert_eq!(FE::from_bytes_le(&x.to_bytes_le()).unwrap(), x); } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_bytes_to_bytes_le_is_the_identity_for_one() { let bytes = [1, 0, 0, 0, 0, 0, 0, 0]; assert_eq!(FE::from_bytes_le(&bytes).unwrap().to_bytes_le(), bytes); diff --git a/math/src/field/fields/winterfell.rs b/math/src/field/fields/winterfell.rs index 5a2bd89e1..6b5c47f5f 100644 --- a/math/src/field/fields/winterfell.rs +++ b/math/src/field/fields/winterfell.rs @@ -91,6 +91,7 @@ impl IsField for Felt { } } +#[cfg(feature = "alloc")] impl Serializable for FieldElement { fn serialize(&self) -> Vec { Felt::elements_as_bytes(&[*self.value()]).to_vec() @@ -98,10 +99,12 @@ impl Serializable for FieldElement { } impl ByteConversion for Felt { + #[cfg(feature = "alloc")] fn to_bytes_be(&self) -> Vec { Felt::elements_as_bytes(&[*self]).to_vec() } + #[cfg(feature = "alloc")] fn to_bytes_le(&self) -> Vec { Felt::elements_as_bytes(&[*self]).to_vec() } @@ -132,6 +135,7 @@ impl ByteConversion for Felt { pub type QuadFelt = QuadExtension; impl ByteConversion for QuadFelt { + #[cfg(feature = "alloc")] fn to_bytes_be(&self) -> Vec { let [b0, b1] = self.to_base_elements(); let mut bytes = b0.to_bytes_be(); @@ -139,6 +143,7 @@ impl ByteConversion for QuadFelt { bytes } + #[cfg(feature = "alloc")] fn to_bytes_le(&self) -> Vec { let [b0, b1] = self.to_base_elements(); let mut bytes = b0.to_bytes_le(); @@ -161,6 +166,7 @@ impl ByteConversion for QuadFelt { } } +#[cfg(feature = "alloc")] impl Serializable for FieldElement { fn serialize(&self) -> Vec { let [b0, b1] = self.value().to_base_elements(); diff --git a/math/src/field/test_fields/u32_test_field.rs b/math/src/field/test_fields/u32_test_field.rs index 40de22bcd..723f2501c 100644 --- a/math/src/field/test_fields/u32_test_field.rs +++ b/math/src/field/test_fields/u32_test_field.rs @@ -13,13 +13,13 @@ pub struct U32Field; #[cfg(feature = "lambdaworks-serde-binary")] impl ByteConversion for u32 { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { unimplemented!() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { unimplemented!() } diff --git a/math/src/field/test_fields/u64_test_field.rs b/math/src/field/test_fields/u64_test_field.rs index f3cbc0dbe..afb7f104d 100644 --- a/math/src/field/test_fields/u64_test_field.rs +++ b/math/src/field/test_fields/u64_test_field.rs @@ -134,7 +134,7 @@ mod tests_u64_test_field { ); } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[test] fn test_to_subfield_vec() { let a = FieldElement::::from(&[ @@ -142,7 +142,7 @@ mod tests_u64_test_field { FieldElement::from(3), ]); let b = a.to_subfield_vec::(); - assert_eq!(b, vec![FieldElement::from(1), FieldElement::from(3)]); + assert_eq!(b, alloc::vec![FieldElement::from(1), FieldElement::from(3)]); } #[cfg(feature = "std")] diff --git a/math/src/field/traits.rs b/math/src/field/traits.rs index 9896259b4..b84a3ff81 100644 --- a/math/src/field/traits.rs +++ b/math/src/field/traits.rs @@ -21,8 +21,8 @@ pub trait IsSubFieldOf: IsField { fn div(a: &Self::BaseType, b: &F::BaseType) -> F::BaseType; fn sub(a: &Self::BaseType, b: &F::BaseType) -> F::BaseType; fn embed(a: Self::BaseType) -> F::BaseType; - #[cfg(feature = "std")] - fn to_subfield_vec(b: F::BaseType) -> Vec; + #[cfg(feature = "alloc")] + fn to_subfield_vec(b: F::BaseType) -> alloc::vec::Vec; } impl IsSubFieldOf for F @@ -54,9 +54,9 @@ where a } - #[cfg(feature = "std")] - fn to_subfield_vec(b: F::BaseType) -> Vec { - vec![b] + #[cfg(feature = "alloc")] + fn to_subfield_vec(b: F::BaseType) -> alloc::vec::Vec { + alloc::vec![b] } } diff --git a/math/src/helpers.rs b/math/src/helpers.rs index d9d92192c..f50888d64 100644 --- a/math/src/helpers.rs +++ b/math/src/helpers.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use crate::field::{element::FieldElement, traits::IsFFTField}; pub fn next_power_of_two(n: u64) -> u64 { @@ -9,8 +9,10 @@ pub fn next_power_of_two(n: u64) -> u64 { } } -#[cfg(feature = "std")] -pub fn resize_to_next_power_of_two(trace_colums: &mut [Vec>]) { +#[cfg(feature = "alloc")] +pub fn resize_to_next_power_of_two( + trace_colums: &mut [alloc::vec::Vec>], +) { trace_colums.iter_mut().for_each(|col| { // TODO: Remove this unwrap. This may panic if the usize cant be // casted into a u64. diff --git a/math/src/lib.rs b/math/src/lib.rs index a75ac7a8f..56c6e598e 100644 --- a/math/src/lib.rs +++ b/math/src/lib.rs @@ -1,5 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "alloc")] +extern crate alloc; + pub mod cyclic_group; pub mod elliptic_curve; pub mod errors; @@ -11,9 +14,7 @@ pub mod unsigned_integer; pub mod gpu; // These modules don't work in no-std mode -#[cfg(feature = "std")] pub mod fft; -#[cfg(feature = "std")] pub mod msm; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub mod polynomial; diff --git a/math/src/msm/mod.rs b/math/src/msm/mod.rs index 9e098e4c0..a4980728d 100644 --- a/math/src/msm/mod.rs +++ b/math/src/msm/mod.rs @@ -1,2 +1,3 @@ pub mod naive; +#[cfg(feature = "alloc")] pub mod pippenger; diff --git a/math/src/msm/naive.rs b/math/src/msm/naive.rs index c2cb013ab..fec773073 100644 --- a/math/src/msm/naive.rs +++ b/math/src/msm/naive.rs @@ -1,12 +1,24 @@ +use core::fmt::Display; + use crate::cyclic_group::IsGroup; use crate::unsigned_integer::traits::IsUnsignedInteger; -#[derive(Debug, thiserror::Error)] +#[derive(Debug)] pub enum MSMError { - #[error("`cs` and `points` must be of the same length to compute `msm`. Got: {0} and {1}")] LengthMismatch(usize, usize), } +impl Display for MSMError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + MSMError::LengthMismatch(cs, points) => write!(f, "`cs` and `points` must be of the same length to compute `msm`. Got: {cs} and {points}"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for MSMError {} + /// This function computes the multiscalar multiplication (MSM). /// /// Assume a group G of order r is given. diff --git a/math/src/msm/pippenger.rs b/math/src/msm/pippenger.rs index 8d484c11f..75aa59c79 100644 --- a/math/src/msm/pippenger.rs +++ b/math/src/msm/pippenger.rs @@ -2,6 +2,8 @@ use crate::{cyclic_group::IsGroup, unsigned_integer::element::UnsignedInteger}; use super::naive::MSMError; +use alloc::vec; + /// This function computes the multiscalar multiplication (MSM). /// /// Assume a group G of order r is given. @@ -168,6 +170,7 @@ mod tests { }, unsigned_integer::element::UnsignedInteger, }; + use alloc::{format, vec::Vec}; use proptest::{collection, prelude::*, prop_assert_eq, prop_compose, proptest}; const _CASES: u32 = 20; diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index cee58d339..058c61466 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -1,6 +1,7 @@ use super::field::element::FieldElement; use crate::field::traits::{IsField, IsSubFieldOf}; -use std::ops; +use alloc::{borrow::ToOwned, vec, vec::Vec}; +use core::{fmt::Display, ops}; /// Represents the polynomial c_0 + c_1 * X + c_2 * X^2 + ... + c_n * X^n /// as a vector of coefficients `[c_0, c_1, ... , c_n]` @@ -779,16 +780,26 @@ where } } -use thiserror::Error; - -#[derive(Debug, Error)] +#[derive(Debug)] pub enum InterpolateError { - #[error("xs and ys must be the same length. Got: {0} != {1}")] UnequalLengths(usize, usize), - #[error("xs values should be unique.")] NonUniqueXs, } +impl Display for InterpolateError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + InterpolateError::UnequalLengths(x, y) => { + write!(f, "xs and ys must be the same length. Got: {x} != {y}") + } + InterpolateError::NonUniqueXs => write!(f, "xs values should be unique."), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InterpolateError {} + #[cfg(test)] mod tests { use crate::field::fields::u64_prime_field::U64PrimeField; @@ -1079,6 +1090,7 @@ mod tests { assert_eq!(p1, &p1_expected); } + use alloc::format; use proptest::prelude::*; proptest! { #[test] diff --git a/math/src/traits.rs b/math/src/traits.rs index b5ece2d19..5aa0e0da7 100644 --- a/math/src/traits.rs +++ b/math/src/traits.rs @@ -9,12 +9,12 @@ use crate::errors::ByteConversionError; /// little-endian order. pub trait ByteConversion { /// Returns the byte representation of the element in big-endian order.} - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec; + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec; /// Returns the byte representation of the element in little-endian order. - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec; + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec; /// Returns the element from its byte representation in big-endian order. fn from_bytes_be(bytes: &[u8]) -> Result @@ -29,10 +29,10 @@ pub trait ByteConversion { /// Serialize function without args /// Used for serialization when formatting options are not relevant +#[cfg(feature = "alloc")] pub trait Serializable { /// Default serialize without args - #[cfg(feature = "std")] - fn serialize(&self) -> Vec; + fn serialize(&self) -> alloc::vec::Vec; } /// Deserialize function without args diff --git a/math/src/unsigned_integer/element.rs b/math/src/unsigned_integer/element.rs index e65e0ae86..11efa94d1 100644 --- a/math/src/unsigned_integer/element.rs +++ b/math/src/unsigned_integer/element.rs @@ -888,16 +888,16 @@ impl UnsignedInteger { impl IsUnsignedInteger for UnsignedInteger {} impl ByteConversion for UnsignedInteger { - #[cfg(feature = "std")] - fn to_bytes_be(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_be(&self) -> alloc::vec::Vec { self.limbs .iter() .flat_map(|limb| limb.to_be_bytes()) .collect() } - #[cfg(feature = "std")] - fn to_bytes_le(&self) -> Vec { + #[cfg(feature = "alloc")] + fn to_bytes_le(&self) -> alloc::vec::Vec { self.limbs .iter() .rev() @@ -1864,7 +1864,7 @@ mod tests_u384 { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_be_bytes_works() { let number = U384::from_u64(1); let expected_bytes = [ @@ -1876,7 +1876,7 @@ mod tests_u384 { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_le_bytes_works() { let number = U384::from_u64(1); let expected_bytes = [ @@ -2846,7 +2846,7 @@ mod tests_u256 { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_be_bytes_works() { let number = U256::from_u64(1); let expected_bytes = [ @@ -2858,7 +2858,7 @@ mod tests_u256 { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_le_bytes_works() { let number = U256::from_u64(1); let expected_bytes = [ diff --git a/provers/cairo/Cargo.toml b/provers/cairo/Cargo.toml index f9fcdb58e..60f220736 100644 --- a/provers/cairo/Cargo.toml +++ b/provers/cairo/Cargo.toml @@ -16,8 +16,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] rand = "0.8.5" -lambdaworks-math = { workspace = true , features = ["lambdaworks-serde-binary"] } -lambdaworks-crypto = { workspace = true } +lambdaworks-math = { workspace = true, default-features = true, features = ["lambdaworks-serde-binary"] } +lambdaworks-crypto = { workspace = true, default-features = true } stark-platinum-prover = { workspace = true, features = ["wasm"] } thiserror = "1.0.38" log = "0.4.17" diff --git a/provers/stark/Cargo.toml b/provers/stark/Cargo.toml index 033e1a9c9..2c181a729 100644 --- a/provers/stark/Cargo.toml +++ b/provers/stark/Cargo.toml @@ -9,8 +9,8 @@ license.workspace = true crate-type = ["cdylib", "rlib"] [dependencies] -lambdaworks-math = { workspace = true , features = ["lambdaworks-serde-binary"] } -lambdaworks-crypto.workspace = true +lambdaworks-math = { workspace = true , features = ["std", "lambdaworks-serde-binary"] } +lambdaworks-crypto = { workspace = true, features = ["std", "serde"] } miden-core = { git="https://github.com/lambdaclass/miden-vm", optional=true} rand = "0.8.5"