Skip to content

Commit

Permalink
No std crypto (#736)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
tdelabro and MauroToscano authored Jan 4, 2024
1 parent 802012d commit 42eaf24
Show file tree
Hide file tree
Showing 59 changed files with 399 additions and 228 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"}
Expand Down
14 changes: 9 additions & 5 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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"]

Expand Down
10 changes: 6 additions & 4 deletions crypto/src/commitments/kzg.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<G1Point, G2Point> {
Expand All @@ -32,12 +31,13 @@ where
}
}

#[cfg(feature = "std")]
impl<G1Point, G2Point> StructuredReferenceString<G1Point, G2Point>
where
G1Point: IsGroup + Deserializable,
G2Point: IsGroup + Deserializable,
{
pub fn from_file(file_path: &str) -> Result<Self, SrsFromFileError> {
pub fn from_file(file_path: &str) -> Result<Self, crate::errors::SrsFromFileError> {
let bytes = std::fs::read(file_path)?;
Ok(Self::deserialize(&bytes)?)
}
Expand Down Expand Up @@ -252,6 +252,7 @@ impl<const N: usize, F: IsPrimeField<RepresentativeType = UnsignedInteger<N>>, P

#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use lambdaworks_math::{
cyclic_group::IsGroup,
elliptic_curve::{
Expand Down Expand Up @@ -413,6 +414,7 @@ mod tests {
}

#[test]
#[cfg(feature = "std")]
fn load_srs_from_file() {
type TestSrsType = StructuredReferenceString<
ShortWeierstrassProjectivePoint<BLS12381Curve>,
Expand Down
3 changes: 3 additions & 0 deletions crypto/src/fiat_shamir/default_transcript.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::transcript::Transcript;
use alloc::borrow::ToOwned;
use sha3::{Digest, Keccak256};

pub struct DefaultTranscript {
Expand Down Expand Up @@ -35,6 +36,8 @@ impl DefaultTranscript {

#[cfg(test)]
mod tests {
use alloc::vec::Vec;

use super::*;

#[test]
Expand Down
2 changes: 2 additions & 0 deletions crypto/src/hash/hash_to_field.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::{string::String, vec::Vec};
use lambdaworks_math::{
field::{
element::FieldElement,
Expand Down Expand Up @@ -67,6 +68,7 @@ fn build_two_to_the_nth<M: IsModulus<UnsignedInteger<N>> + Clone, const N: usize

#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use lambdaworks_math::{
field::{
element::FieldElement,
Expand Down
1 change: 1 addition & 0 deletions crypto/src/hash/poseidon/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::{borrow::ToOwned, vec::Vec};
use lambdaworks_math::field::element::FieldElement as FE;

pub mod parameters;
Expand Down
4 changes: 4 additions & 0 deletions crypto/src/hash/sha3/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use alloc::{
string::{String, ToString},
vec::Vec,
};
use sha3::{Digest, Sha3_256};

pub struct Sha3Hasher;
Expand Down
6 changes: 6 additions & 0 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
4 changes: 3 additions & 1 deletion crypto/src/merkle_tree/backends/field_element.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -9,7 +10,7 @@ use sha3::{
digest::{generic_array::GenericArray, OutputSizeUser},
Digest,
};
use std::marker::PhantomData;

#[derive(Clone)]
pub struct FieldElementBackend<F, D: Digest, const NUM_BYTES: usize> {
phantom1: PhantomData<F>,
Expand Down Expand Up @@ -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,
};
Expand Down
3 changes: 2 additions & 1 deletion crypto/src/merkle_tree/backends/field_element_vector.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
26 changes: 23 additions & 3 deletions crypto/src/merkle_tree/merkle.rs
Original file line number Diff line number Diff line change
@@ -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<B: IsMerkleTreeBackend> {
pub root: B::Node,
nodes: Vec<B::Node>,
Expand Down Expand Up @@ -46,14 +65,14 @@ where
Some(Proof { merkle_path })
}

fn build_merkle_path(&self, pos: usize) -> Result<Vec<B::Node>, std::io::Error> {
fn build_merkle_path(&self, pos: usize) -> Result<Vec<B::Node>, 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());

Expand All @@ -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};
Expand Down
25 changes: 16 additions & 9 deletions crypto/src/merkle_tree/proof.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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<T: PartialEq + Eq> {
pub merkle_path: Vec<T>,
}
Expand All @@ -36,6 +37,7 @@ impl<T: PartialEq + Eq> Proof<T> {
}
}

#[cfg(feature = "alloc")]
impl<T> Serializable for Proof<T>
where
T: Serializable + PartialEq + Eq,
Expand Down Expand Up @@ -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};

Expand All @@ -81,13 +84,15 @@ mod tests {
pub type Ecgfp5 = U64PrimeField<0xFFFF_FFFF_0000_0001_u64>;
pub type Ecgfp5FE = FieldElement<Ecgfp5>;
pub type TestMerkleTreeEcgfp = MerkleTree<TestBackend<Ecgfp5>>;
#[cfg(feature = "alloc")]
pub type TestProofEcgfp5 = Proof<Ecgfp5FE>;

const MODULUS: u64 = 13;
type U64PF = U64PrimeField<MODULUS>;
type FE = FieldElement<U64PF>;

#[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 };
Expand All @@ -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 };
Expand All @@ -123,6 +129,7 @@ mod tests {
}

#[test]
#[cfg(feature = "alloc")]
fn merkle_proof_verifies_after_serialization_and_deserialization() {
let values: Vec<Ecgfp5FE> = (1..6).map(Ecgfp5FE::new).collect();
let merkle_tree = TestMerkleTreeEcgfp::build(&values);
Expand Down
2 changes: 1 addition & 1 deletion crypto/src/merkle_tree/test_merkle.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::marker::PhantomData;
use core::marker::PhantomData;

use lambdaworks_math::field::{element::FieldElement, traits::IsField};

Expand Down
1 change: 1 addition & 0 deletions crypto/src/merkle_tree/traits.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
#[cfg(feature = "parallel")]
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};

Expand Down
3 changes: 3 additions & 0 deletions crypto/src/merkle_tree/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::vec::Vec;

use super::traits::IsMerkleTreeBackend;

pub fn sibling_index(node_index: usize) -> usize {
Expand Down Expand Up @@ -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};
Expand Down
5 changes: 4 additions & 1 deletion ensure-no_std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
5 changes: 5 additions & 0 deletions ensure-no_std/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Loading

0 comments on commit 42eaf24

Please sign in to comment.